aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2018-09-26 12:45:08 -0700
committerBruce Hill <bruce@bruce-hill.com>2018-09-26 12:45:19 -0700
commit692fae5416ce1f2702b599ffb27b2e3d2235eba7 (patch)
tree12ae256ef5606251bc013935390fdef7e737d79d
parent28d0792e69bbb9c467c616eb3dc89a60085c35f2 (diff)
Incremental fixes and more nomnom ports.
-rw-r--r--containers.lua16
-rw-r--r--containers.moon5
-rw-r--r--core/math.nom26
-rw-r--r--core/metaprogramming.nom11
-rw-r--r--nomnom/code_obj.nom28
-rw-r--r--nomnom/compile.nom48
-rw-r--r--string2.lua69
-rw-r--r--string2.moon19
-rwxr-xr-xtools/find_action.nom11
9 files changed, 139 insertions, 94 deletions
diff --git a/containers.lua b/containers.lua
index d31c786..682932f 100644
--- a/containers.lua
+++ b/containers.lua
@@ -192,6 +192,22 @@ local _list_mt = {
end
end
return nil
+ end,
+ slice_1_to_2 = function(self, start, stop)
+ local n = #self
+ if n < 0 then
+ start = (n + 1 - start)
+ end
+ if n < 0 then
+ stop = (n + 1 - stop)
+ end
+ local _accum_0 = { }
+ local _len_0 = 1
+ for i = start, stop do
+ _accum_0[_len_0] = self[i]
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
end
},
__newindex = function(self, k, v)
diff --git a/containers.moon b/containers.moon
index 039a4ea..8a7d7fa 100644
--- a/containers.moon
+++ b/containers.moon
@@ -76,6 +76,11 @@ _list_mt =
if x == item
return i
return nil
+ slice_1_to_2: (start, stop)=>
+ n = #@
+ start = (n+1-start) if n < 0
+ stop = (n+1-stop) if n < 0
+ return [@[i] for i=start,stop]
-- TODO: remove this safety check to get better performance?
__newindex: (k,v)=>
assert type(k) == 'number', "List indices must be numbers"
diff --git a/core/math.nom b/core/math.nom
index d6ddbce..5daa2d8 100644
--- a/core/math.nom
+++ b/core/math.nom
@@ -89,6 +89,32 @@ compile [sum of %items, sum %items] to:
%clauses = ((% as lua expr) for % in %items)
return (Lua value "(\(%clauses::joined with " + "))")
+parse [if all of %items %body, if all of %items then %body] as (..)
+ if (all of %items) %body
+parse [unless all of %items %body, unless all of %items then %body] as (..)
+ if (not (all of %items)) %body
+parse [if any of %items %body, if any of %items then %body] as (..)
+ if (any of %items) %body
+parse [unless any of %items %body, unless any of %items then %body] as (..)
+ if (not (any of %items)) %body
+parse [if none of %items %body, if none of %items then %body] as (..)
+ if (not (any of %items)) %body
+parse [unless none of %items %body, unless none of %items then %body] as (..)
+ if (any of %items) %body
+
+parse [if all of %items %body else %else, if all of %items then %body else %else] as (..)
+ if (all of %items) %body else %else
+parse [unless all of %items %body else %else, unless all of %items then %body else %else] as (..)
+ if (not (all of %items)) %body else %else
+parse [if any of %items %body else %else, if any of %items then %body else %else] as (..)
+ if (any of %items) %body else %else
+parse [unless any of %items %body else %else, unless any of %items then %body else %else] as (..)
+ if (not (any of %items)) %body else %else
+parse [if none of %items %body else %else, if none of %items then %body else %else] as (..)
+ if (not (any of %items)) %body else %else
+parse [unless none of %items %body else %else, unless none of %items then %body else %else] as (..)
+ if (any of %items) %body else %else
+
compile [product of %items, product %items] to:
unless (%items.type is "List"):
return (Lua value "utils.product(\(%items as lua expr))")
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 1503905..8b75ccd 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -184,14 +184,14 @@ compile [parse %actions as %body] to (..)
i = i + 1
elseif k == "source" then
ret[#ret+1] = k.."= "..tostring(v):as_lua()
- elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then
+ elseif lua_type_of_1(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then
ret[#ret+1] = k.."= "..make_tree(v)
else
ret[#ret+1] = "["..make_tree(k).."]= "..make_tree(v)
end
end
return t.type.."{"..table.concat(ret, ", ").."}"
- elseif type(t) == 'number' then
+ elseif lua_type_of_1(t) == 'number' then
return tostring(t)
else
return t:as_lua()
@@ -231,12 +231,12 @@ compile [%tree as inline nomsu] to (..)
action [%var as lua identifier, %var as lua id] (..)
lua> "\
- ..if type(\%var) == 'string' then return \%var:as_lua_id()
+ ..if lua_type_of_1(\%var) == 'string' then return \%var:as_lua_id()
elseif AST.is_syntax_tree(\%var, 'Var') then return \%var[1]:as_lua_id()
elseif AST.is_syntax_tree(\%var) then
local lua = \(%var as lua expr)
if not tostring(lua):match("^[_a-zA-Z][_a-zA-Z0-9]*$") then
- \(compile error at %var "This is not a valid Lua identifier.")
+ compile_error_at_1_2(\%var, "This is not a valid Lua identifier.")
end
return lua
else error("Unknown type: "..tostring(\%var))
@@ -328,9 +328,6 @@ test:
assume ("" is text)
assume ("" isn't a "Dict")
-%dict_mt = (=lua "getmetatable(\{})")
-%list_mt = (=lua "getmetatable(\[])")
-
action [% is text] (=lua "\(lua type of %) == 'string'")
action [% is not text, % isn't text] (=lua "\(lua type of %) ~= 'string'")
action [type of %]:
diff --git a/nomnom/code_obj.nom b/nomnom/code_obj.nom
index 4df312e..057748f 100644
--- a/nomnom/code_obj.nom
+++ b/nomnom/code_obj.nom
@@ -163,18 +163,20 @@ object (Lua Code) extends (Code):
%statements::add %suffix
return %statements
- action [Lua Code from %tree] (..)
- Lua Code {source:%tree.source, bits:[], is_value:(no), free_vars:[]}
- action [Lua Code from %tree %bits] (..)
- Lua Code {source:%tree.source, bits:%bits, is_value:(no), free_vars:[]}
-
- action [Lua Value from %tree] (..)
- Lua Code {source:%tree.source, bits:[], is_value:(yes), free_vars:[]}
- action [Lua Value from %tree %bits] (..)
- Lua Code {source:%tree.source, bits:%bits, is_value:(yes), free_vars:[]}
+ action [Lua Code from %source {%bits:[]}]:
+ if (%bits is text): %bits = [%bits]
+ if (%source is a "Syntax Tree"): %source = %source.source
+ return (..)
+ Lua Code {source:%source, bits:%bits, is_value:(no), free_vars:[]}
+ action [Lua Value from %tree {%bits:[]}]:
+ if (%bits is text): %bits = [%bits]
+ if (%source is a "Syntax Tree"): %source = %source.source
+ return (..)
+ Lua Code {source:%source, bits:%bits, is_value:(yes), free_vars:[]}
object (Nomsu Code) extends (Code):
- action [Nomsu Code from %tree] (..)
- Nomsu Code {source:%tree.source, bits:[]}
- action [Nomsu Code from %tree %bits] (..)
- Nomsu Code {source:%tree.source, bits:%bits}
+ action [Nomsu Code from %source {%bits:[]}]:
+ if (%bits is text): %bits = [%bits]
+ if (%source is a "Syntax Tree"): %source = %source.source
+ return (..)
+ Nomsu Code {source:%source, bits:%bits}
diff --git a/nomnom/compile.nom b/nomnom/compile.nom
index ec48f05..ff3b71f 100644
--- a/nomnom/compile.nom
+++ b/nomnom/compile.nom
@@ -4,17 +4,17 @@ use "nomnom/code_obj.nom"
action [compile %tree using %compile_actions]:
assume (%tree is a "Syntax Tree")
- if (..)
- all of [..]
- %tree.version, action (Nomsu version)
- %tree.version != (Nomsu version)
- action (1 upgraded from 2 to 3)
- ..: %tree = (upgrade %tree from %tree.version to (Nomsu version))
+ if all of [..]
+ %tree.version, action (Nomsu version)
+ %tree.version != (Nomsu version)
+ action (1 upgraded from 2 to 3)
+ ..then: %tree = (upgrade %tree from %tree.version to (Nomsu version))
if %tree.type is:
"Action":
%stub = %tree.stub
%compile_action = %compile_actions.%stub
- if %compile_action:
+ # Don't apply compiler actions to methods
+ if (%compile_action and (not %tree.target)):
%args = [%tree, %compile_actions]
for % in (%tree::get args): %args::add %
%result = (call %compile_action with %args)
@@ -32,7 +32,7 @@ action [compile %tree using %compile_actions]:
return (compile %result using %compile_actions)
return %result
- %lua = (new Lua Value from %tree)
+ %lua = (Lua Value from %tree)
if %tree.target: # Method call
%target_lua = (compile %tree.target using %compile_actions)
if (("\%target_lua"::matches "^%(.*%)$") or ("\%target_lua"::matches "^[_a-zA-Z][_a-zA-Z0-9]*$")):
@@ -49,15 +49,15 @@ action [compile %tree using %compile_actions]:
%values = (..)
(compile %line using %compile_actions) for %line in %tok
..unless (%line.type == "Comment")
- if (all of (%.is_value for % in %values)):
+ if all of (%.is_value for % in %values):
if ((size of %values) == 1):
%arg_lua = %values.1
..else:
- %arg_lua = (new Lua Value from %tok ["("])
+ %arg_lua = (Lua Value from %tok ["("])
%arg_lua::add %values joined with " and nil or "
%arg_lua::add ")"
..else:
- %arg_lua = (new Lua Value from %tok ["((function()"])
+ %arg_lua = (Lua Value from %tok ["((function()"])
for %v in %values at %i:
if %v.is_value:
%v = (%v::as statements ("return " if (%i == (size of %values) else "")))
@@ -83,10 +83,10 @@ action [compile %tree using %compile_actions]:
return %lua
"EscapedNomsu":
- return (new Lua Value from %tree ((%tree.1)::as nomsu))
+ return (Lua Value from %tree ((%tree.1)::as nomsu))
"Block":
- %lua = (new Lua Code from %tree)
+ %lua = (Lua Code from %tree)
%lua::add (..)
((compile %line using %compile_actions)::as statements)
..for %line in %tree
@@ -94,7 +94,7 @@ action [compile %tree using %compile_actions]:
return %lua
"Text":
- %lua = (new Lua Code from %tree)
+ %lua = (Lua Code from %tree)
%lua_bits = []
%string_buffer = ""
for % in %tree:
@@ -109,7 +109,7 @@ action [compile %tree using %compile_actions]:
compile error at %bit "\
..Can't use this as a string interpolation value, since it doesn't have a value."
if (%bit.type != "Text"):
- %bit_lua = (new Lua Value from %bit ["tostring(",%bit_lua,")"])
+ %bit_lua = (Lua Value from %bit ["tostring(",%bit_lua,")"])
%lua_bits::add %bit_lua
if ((%string_buffer != "") or ((size of %lua_bits) == 0)):
@@ -121,13 +121,13 @@ action [compile %tree using %compile_actions]:
return %lua
"List":
- %lua = (new Lua Value from %tree ["_List{"])
+ %lua = (Lua Value from %tree ["List{"])
%lua::add ((compile % using %compile_actions) for % in %tree) joined with ", " or ",\n "
%lua::add "}"
return %lua
"Dict":
- %lua = (new Lua Value from %tree ["_Dict{"])
+ %lua = (Lua Value from %tree ["Dict{"])
%lua::add ((compile % using %compile_actions) for % in %tree) joined with ", " or ",\n "
%lua::add "}"
return %lua
@@ -140,21 +140,21 @@ action [compile %tree using %compile_actions]:
..Can't use this as a dict key, since it's not an expression."
%value_lua = (..)
(compile %value using %compile_actions) if %value
- ..else (new Lua Value from %key ["true"]))
+ ..else (Lua Value from %key ["true"]))
unless %value_lua.is_value:
compile error at %tree.2 "\
..Can't use this as a dict value, since it's not an expression."
%key_str = ("\%key_lua"::matching "^[\"']([a-zA-Z_][a-zA-Z0-9_]*)['\"]$")
if:
%key_str:
- return (new Lua Code from %tree [%key_str, "=", %value_lua])
+ return (Lua Code from %tree [%key_str, "=", %value_lua])
("\%key_lua".1 == "["):
# NOTE: this *must* use a space after the [ to avoid freaking out
Lua's parser if the inner expression is a long string. Lua
parses x[[[y]]] as x("[y]"), not as x["y"]
- return (new Lua Code from %tree ["[ ", %key_lua, "]=", %value_lua])
+ return (Lua Code from %tree ["[ ", %key_lua, "]=", %value_lua])
else:
- return (new Lua Code from %tree ["[", %key_lua, "]=", %value_lua])
+ return (Lua Code from %tree ["[", %key_lua, "]=", %value_lua])
"IndexChain":
%lua = (compile %tree.1 using %compile_actions)
@@ -186,10 +186,10 @@ action [compile %tree using %compile_actions]:
return %lua
"Number":
- return (new Lua Value from %tree ["\(%tree.1)"])
+ return (Lua Value from %tree ["\(%tree.1)"])
"Var":
- return (new Lua Value from %tree [%tree.1::as lua id])
+ return (Lua Value from %tree [%tree.1::as lua id])
"FileChunks":
barf "\
@@ -198,7 +198,7 @@ action [compile %tree using %compile_actions]:
"Comment":
# TODO: implement?
- return (new Lua Code from %tree)
+ return (Lua Code from %tree)
"Error":
barf "Can't compile errors"
diff --git a/string2.lua b/string2.lua
index 2cdfefc..1f15fed 100644
--- a/string2.lua
+++ b/string2.lua
@@ -27,34 +27,39 @@ isplit = function(self, sep)
}, 0
end
local lua_keywords = {
- "and",
- "break",
- "do",
- "else",
- "elseif",
- "end",
- "false",
- "for",
- "function",
- "goto",
- "if",
- "in",
- "local",
- "nil",
- "not",
- "or",
- "repeat",
- "return",
- "then",
- "true",
- "until",
- "while"
+ ["and"] = true,
+ ["break"] = true,
+ ["do"] = true,
+ ["else"] = true,
+ ["elseif"] = true,
+ ["end"] = true,
+ ["false"] = true,
+ ["for"] = true,
+ ["function"] = true,
+ ["goto"] = true,
+ ["if"] = true,
+ ["in"] = true,
+ ["local"] = true,
+ ["nil"] = true,
+ ["not"] = true,
+ ["or"] = true,
+ ["repeat"] = true,
+ ["return"] = true,
+ ["then"] = true,
+ ["true"] = true,
+ ["until"] = true,
+ ["while"] = true
}
+local is_lua_id
+is_lua_id = function(str)
+ return match(str, "^[_a-zA-Z][_a-zA-Z0-9]*$") and not lua_keywords[str]
+end
local string2 = {
isplit = isplit,
uppercase = upper,
lowercase = lower,
reversed = reverse,
+ is_lua_id = is_lua_id,
capitalized = function(self)
return gsub(self, '%l', upper, 1)
end,
@@ -148,27 +153,15 @@ local string2 = {
return format("x%02X", byte(c))
end
end)
- str = gsub(str, "^_*%d", "_%1")
- if match(str, "^_*[abdefgilnortuw][aefhilnoru][acdefiklnoprstu]*$") then
- for _index_0 = 1, #lua_keywords do
- local kw = lua_keywords[_index_0]
- if match(str, ("^_*" .. kw .. "$")) then
- str = "_" .. str
- end
- end
+ if not (is_lua_id(str:match("^_*(.*)$"))) then
+ str = "_" .. str
end
return str
end,
from_lua_id = function(str)
- if match(str, "^_+[abdefgilnortuw][aefhilnoru][acdefiklnoprstu]*$") then
- for _index_0 = 1, #lua_keywords do
- local kw = lua_keywords[_index_0]
- if match(str, ("^_+" .. kw .. "$")) then
- str = str:sub(2, -1)
- end
- end
+ if not (is_lua_id("^_+(.*)$")) then
+ str = str:sub(2, -1)
end
- str = gsub(str, "^_(_*%d.*)", "%1")
str = gsub(str, "_", " ")
str = gsub(str, "x([0-9A-F][0-9A-F])", function(hex)
return char(tonumber(hex, 16))
diff --git a/string2.moon b/string2.moon
index 1b0037f..140c586 100644
--- a/string2.moon
+++ b/string2.moon
@@ -13,14 +13,16 @@ isplit = (sep='%s+')=>
return step, {str:@, pos:1, :sep}, 0
lua_keywords = {
- ["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true, ["elseif"]=true, ["end"]=true,
- ["false"]=true, ["for"]=true, ["function"]=true, ["goto"]=true, ["if"]=true,
- ["in"]=true, ["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true, ["repeat"]=true,
- ["return"]=true, ["then"]=true, ["true"]=true, ["until"]=true, ["while"]=true
+ ["and"]:true, ["break"]:true, ["do"]:true, ["else"]:true, ["elseif"]:true, ["end"]:true,
+ ["false"]:true, ["for"]:true, ["function"]:true, ["goto"]:true, ["if"]:true,
+ ["in"]:true, ["local"]:true, ["nil"]:true, ["not"]:true, ["or"]:true, ["repeat"]:true,
+ ["return"]:true, ["then"]:true, ["true"]:true, ["until"]:true, ["while"]:true
}
+is_lua_id = (str)->
+ match(str, "^[_a-zA-Z][_a-zA-Z0-9]*$") and not lua_keywords[str]
string2 = {
- :isplit, uppercase:upper, lowercase:lower, reversed:reverse
+ :isplit, uppercase:upper, lowercase:lower, reversed:reverse, :is_lua_id
capitalized: => gsub(@, '%l', upper, 1)
byte: byte, bytes: (i, j)=> {byte(@, i or 1, j or -1)}
split: (sep)=> [chunk for i,chunk in isplit(@, sep)]
@@ -79,17 +81,14 @@ string2 = {
if c == ' ' then '_'
else format("x%02X", byte(c))
- unless string2.is_lua_id(str\match("^_*(.*)$"))
+ unless is_lua_id(str\match("^_*(.*)$"))
str = "_"..str
return str
- is_lua_id: (str)->
- match(str, "^[_a-zA-Z][_a-zA-Z0-9]*$") and not lua_keywords[str]
-
-- from_lua_id(as_lua_id(str)) == str, but behavior is unspecified for inputs that
-- did not come from as_lua_id()
from_lua_id: (str)->
- unless string2.is_lua_id("^_+(.*)$")
+ unless is_lua_id("^_+(.*)$")
str = str\sub(2,-1)
str = gsub(str, "_", " ")
str = gsub(str, "x([0-9A-F][0-9A-F])", (hex)-> char(tonumber(hex, 16)))
diff --git a/tools/find_action.nom b/tools/find_action.nom
index e6fe90a..8381855 100755
--- a/tools/find_action.nom
+++ b/tools/find_action.nom
@@ -15,12 +15,19 @@ for %path in %files:
unless (%filename::matches "%.nom$") (do next %filename)
%file = (read file %filename)
%tree = (parse %file from %filename)
+ %results = []
for %t in recursive %tree:
if (%t is "Action" syntax tree):
if (%t.stub is %stub):
%line_num = (line number of %t.source.start in %file)
- say (blue "\%filename:\%line_num:")
- say (yellow (source lines of %t))
+ %results::add {..}
+ line: %line_num
+ text: "\
+ ..\(blue "\%filename:\%line_num:")
+ \(yellow (source lines of %t))"
if (%t is syntax tree):
for %sub in %t: recurse %t on %sub
+ sort %results by % -> %.line
+ for % in %results:
+ say %.text