aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code_obj.lua6
-rw-r--r--code_obj.moon6
-rw-r--r--core/control_flow.nom24
-rw-r--r--core/math.nom8
-rw-r--r--core/metaprogramming.nom40
-rw-r--r--core/operators.nom28
-rw-r--r--core/text.nom6
-rw-r--r--lib/object.nom16
-rw-r--r--nomsu.lua250
-rwxr-xr-xnomsu.moon210
-rw-r--r--nomsu_tree.lua43
-rw-r--r--nomsu_tree.moon20
-rw-r--r--tests/metaprogramming.nom4
13 files changed, 326 insertions, 335 deletions
diff --git a/code_obj.lua b/code_obj.lua
index f0440ca..d84744e 100644
--- a/code_obj.lua
+++ b/code_obj.lua
@@ -106,6 +106,7 @@ do
for i = 1, n do
local b = select(i, ...)
assert(b ~= self, "No recursion please.")
+ assert(not Source:is_instance(b))
bits[#bits + 1] = b
if type(b) == 'string' then
do
@@ -165,6 +166,7 @@ do
self.source = Source(self.source, 1, #tostring(self) + 1)
end
end
+ return assert(self.source)
end,
__base = _base_0,
__name = "Code"
@@ -218,7 +220,7 @@ do
for _index_0 = 1, #vars do
local var = vars[_index_0]
assert(type(var) == 'userdata' and var.type == "Var")
- removals[var] = true
+ removals[var.value] = true
end
local stack = {
self
@@ -227,7 +229,7 @@ do
local lua
lua, stack[#stack] = stack[#stack], nil
for i = #lua.free_vars, 1, -1 do
- if removals[lua.free_vars[i]] then
+ if removals[lua.free_vars[i].value] then
remove(lua.free_vars, i)
end
end
diff --git a/code_obj.moon b/code_obj.moon
index 66b7978..3f9e37a 100644
--- a/code_obj.moon
+++ b/code_obj.moon
@@ -72,6 +72,7 @@ class Code
@source = Source(filename, tonumber(start), tonumber(stop))
else
@source = Source(@source, 1, #tostring(self)+1)
+ assert(@source)
sub: (start,stop)=>
-- TODO: implement this better
@@ -86,6 +87,7 @@ class Code
for i=1,n
b = select(i, ...)
assert(b != self, "No recursion please.")
+ assert(not Source\is_instance(b))
bits[#bits+1] = b
if type(b) == 'string'
if spaces = match(b, "\n([ ]*)[^\n]*$")
@@ -139,13 +141,13 @@ class Lua extends Code
removals = {}
for var in *vars
assert(type(var) == 'userdata' and var.type == "Var")
- removals[var] = true
+ removals[var.value] = true
stack = {self}
while #stack > 0
lua, stack[#stack] = stack[#stack], nil
for i=#lua.free_vars,1,-1
- if removals[lua.free_vars[i]]
+ if removals[lua.free_vars[i].value]
remove lua.free_vars, i
for b in *lua.bits
if type(b) != 'string'
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 6d93e8a..5eabefd 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -188,14 +188,14 @@ immediately
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "do next %") and
- %.3 = %var
+ %.value.3.value = %var.value
..: to %lua write (Lua "\n ::continue_\(%var as lua identifier)::;")
to %lua write "\nend --foreach-loop"
if
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "stop %") and
- %.2 = %var
+ %.value.2.value = %var.value
..
%lua <-
Lua ".."
@@ -219,14 +219,14 @@ immediately
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "do next %") and
- %.3 = %key
+ %.value.3.value = %key.value
..: to %lua write (Lua "\n ::continue_\(%key as lua identifier)::;")
if
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "do next %") and
- %.3 = %value
+ %.value.3.value = %value.value
..: to %lua write (Lua "\n ::continue_\(%value as lua identifier)::;")
to %lua write "\nend --foreach-loop"
@@ -235,14 +235,14 @@ immediately
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "stop %") and
- %.2 = %key
+ %.value.2.value = %key.value
..: to %stop_labels write "\n::stop_\(%key as lua identifier)::;"
if
%body has subtree % where
(%.type = "Action") and
((%'s stub) is "stop %") and
- %.2 = %value
+ %.value.2.value = %value.value
..: to %stop_labels write "\n::stop_\(%value as lua identifier)::;"
if: (length of %stop_labels) > 0
@@ -262,14 +262,14 @@ immediately
%is_first <- (yes)
%seen_else <- (no)
%branches <-
- %body if (%body.type = "Block") else [%body]
+ %body.value if (%body.type = "Block") else [%body]
for %func_call in %branches
assume (%func_call.type is "Action") or barf ".."
Invalid format for 'when' statement. Only '*' blocks are allowed.
with {..}
- %star: %func_call.1
- %condition: %func_call.2
- %action: %func_call.3
+ %star: %func_call.value.1
+ %condition: %func_call.value.2
+ %action: %func_call.value.3
..
assume (%star = "*") or barf ".."
Invalid format for 'when' statement. Lines must begin with '*'
@@ -310,11 +310,11 @@ immediately
%is_first <- (yes)
%seen_else <- (no)
%branches <-
- %body if (%body.type = "Block") else [%body]
+ %body.value if (%body.type = "Block") else [%body]
for %func_call in %branches
assume (%func_call.type is "Action") or barf ".."
Invalid format for 'when' statement. Only '*' blocks are allowed.
- with {%star:%func_call.1, %condition:%func_call.2, %action:%func_call.3}
+ with {%star:%func_call.value.1, %condition:%func_call.value.2, %action:%func_call.value.3}
assume (%star = "*") or barf ".."
Invalid format for 'when' statement. Lines must begin with '*'
assume %condition or barf ".."
diff --git a/core/math.nom b/core/math.nom
index 8d484b4..ed2cdb6 100644
--- a/core/math.nom
+++ b/core/math.nom
@@ -42,7 +42,7 @@ compile [all of %items, all %items] to
unless: (%items' "type") is "List"
return: Lua value "utils.all(\(%items as lua expr))"
%clauses <- []
- for % in %items
+ for % in %items.value
lua> "table.insert(\%clauses, \(% as lua expr));"
return: Lua value "(\(%clauses joined with " and "))"
parse [not all of %items, not all %items] as: not (all of %items)
@@ -50,7 +50,7 @@ compile [any of %items, any %items] to
unless: (%items' "type") is "List"
return: Lua value "utils.any(\(%items as lua expr))"
%clauses <- []
- for % in %items
+ for % in %items.value
lua> "table.insert(\%clauses, \(% as lua expr));"
return: Lua value "(\(%clauses joined with " or "))"
parse [none of %items, none %items] as: not (any of %items)
@@ -58,14 +58,14 @@ compile [sum of %items, sum %items] to
unless: (%items' "type") is "List"
return: Lua value "utils.sum(\(%items as lua expr))"
%clauses <- []
- for % in %items
+ for % in %items.value
lua> "table.insert(\%clauses, \(% as lua expr));"
return: Lua value "(\(%clauses joined with " + "))"
compile [product of %items, product %items] to
unless: (%items' "type") is "List"
return: Lua value "utils.product(\(%items as lua expr))"
%clauses <- []
- for % in %items
+ for % in %items.value
lua> "table.insert(\%clauses, \(% as lua expr));"
return: Lua value "(\(%clauses joined with " * "))"
action [avg of %items, average of %items]
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 6c5221c..76ba731 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -6,9 +6,9 @@
immediately
lua> ".."
nomsu:define_compile_action("compile %actions to %lua", function(tree, \%actions, \%lua)
- local lua = Lua(nil, "nomsu:define_compile_action(")
+ local lua = Lua(tree.source, "nomsu:define_compile_action(")
local stubs = {}
- for i, action in ipairs(\%actions) do
+ for i, action in ipairs(\%actions.value) do
stubs[i] = action:get_stub(true)
end
stubs = repr(stubs)
@@ -19,7 +19,7 @@ immediately
end
lua:append("function(tree")
local args = {}
- for i,tok in ipairs(\%actions[1]) do
+ for i,tok in ipairs(\%actions.value[1].value) do
if tok.type == "Var" then args[#args+1] = tok end
end
for i, arg in ipairs(args) do
@@ -36,9 +36,9 @@ immediately
immediately
compile [action %actions %body] to
lua> ".."
- local lua = Lua(nil, "nomsu:define_action(")
+ local lua = Lua(tree.source, "nomsu:define_action(")
local stubs = {}
- for i, action in ipairs(\%actions) do
+ for i, action in ipairs(\%actions.value) do
stubs[i] = action:get_stub(true)
end
stubs = repr(stubs)
@@ -49,7 +49,7 @@ immediately
end
lua:append("function(")
local args = {}
- for i,tok in ipairs(\%actions[1]) do
+ for i,tok in ipairs(\%actions.value[1].value) do
if tok.type == "Var" then args[#args+1] = tok end
end
for i, arg in ipairs(args) do
@@ -66,9 +66,9 @@ immediately
immediately
compile [parse %shorthand as %longhand] to
lua> ".."
- local lua = Lua(nil, "nomsu:define_compile_action(")
+ local lua = Lua(tree.source, "nomsu:define_compile_action(")
local stubs = {}
- for i, action in ipairs(\%shorthand) do
+ for i, action in ipairs(\%shorthand.value) do
stubs[i] = action:get_stub(true)
end
stubs = repr(stubs)
@@ -79,26 +79,26 @@ immediately
end
lua:append("function(tree")
local replacements = {}
- for i,tok in ipairs(\%shorthand[1]) do
+ for i,tok in ipairs(\%shorthand.value[1].value) do
if tok.type == "Var" then
local lua_var = tostring(nomsu:tree_to_lua(tok))
- replacements[tok] = lua_var
+ replacements[tok.value] = lua_var
lua:append(", ", lua_var)
end
end
local function make_tree(t)
- if replacements[t] then
- return replacements[t]
- elseif type(t) ~= 'table' and type(t) ~= 'userdata' then
+ if type(t) ~= 'table' and type(t) ~= 'userdata' then
return repr(t)
+ elseif t.type == 'Var' and replacements[t.value] then
+ return replacements[t.value]
elseif t.is_multi then
local bits = {}
- for i, entry in ipairs(t) do
+ for i, entry in ipairs(t.value) do
bits[i] = make_tree(entry)
end
- return t.type.."("..table.concat(bits, ", ")..")"
+ return t.type.."(Tuple("..table.concat(bits, ", ").."), "..repr(t.source)..")"
else
- return t.type.."("..make_tree(t.value)..")"
+ return t.type.."("..repr(t.value)..", "..repr(t.source)..")"
end
end
lua:append(")\n local tree = ", make_tree(\%longhand), "\n return nomsu:tree_to_lua(tree)\nend);")
@@ -169,21 +169,21 @@ immediately
# Compiler tools
immediately
compile [run %code] to
- Lua value "nomsu:run(Nomsu(nil, \(%code as lua expr)))"
+ Lua "nomsu:run(Nomsu(\(%code.source as text), \(%code as lua expr)))"
immediately
compile [show lua %block] to
lua> ".."
local \%lua = nomsu:tree_to_lua(\%block);
- return Lua(nil, "print(", repr(tostring(\%lua)), ");");
+ return Lua(tree.source, "print(", repr(tostring(\%lua)), ");");
immediately
compile [say %message] to
lua> ".."
if \%message.type == "Text" then
- return Lua(nil, "print(", \(%message as lua expr), ");");
+ return Lua(tree.source, "print(", \(%message as lua expr), ");");
else
- return Lua(nil, "print(stringify(", \(%message as lua expr), "));");
+ return Lua(tree.source, "print(stringify(", \(%message as lua expr), "));");
end
# Return
diff --git a/core/operators.nom b/core/operators.nom
index 62a3225..7f5c772 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -28,18 +28,18 @@ immediately
local safe = {Text=true, Number=true}
local a_lua, b_lua = \(%a as lua), \(%b as lua)
if safe[\%a.type] or safe[\%b.type] then
- return Lua.Value(nil, "(", a_lua, " == ", b_lua, ")")
+ return Lua.Value(tree.source, "(", a_lua, " == ", b_lua, ")")
else
- return Lua.Value(nil, "utils.equivalent(", a_lua, ", ", b_lua, ")")
+ return Lua.Value(tree.source, "utils.equivalent(", a_lua, ", ", b_lua, ")")
end
compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to
lua> ".."
local safe = {Text=true, Number=true}
local a_lua, b_lua = \(%a as lua), \(%b as lua)
if safe[\%a.type] or safe[\%b.type] then
- return Lua.Value(nil, "(", a_lua, " ~= ", b_lua, ")")
+ return Lua.Value(tree.source, "(", a_lua, " ~= ", b_lua, ")")
else
- return Lua.Value(nil, "(not utils.equivalent(", a_lua, ", ", b_lua, "))")
+ return Lua.Value(tree.source, "(not utils.equivalent(", a_lua, ", ", b_lua, "))")
end
# For strict identity checking, use (%x's id) is (%y's id)
compile [%'s id, id of %] to: Lua value "nomsu.ids[\(% as lua expr)]"
@@ -52,7 +52,7 @@ immediately
lua> "local \%value_lua = \(%value as lua);"
assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
lua> ".."
- local lua = Lua(nil, \%var_lua, ' = ', \%value_lua, ';')
+ local lua = Lua(tree.source, \%var_lua, ' = ', \%value_lua, ';')
if \%var.type == 'Var' then
lua:add_free_vars({\%var})
end
@@ -64,9 +64,9 @@ immediately
assume ((%assignments' "type") is "Dict") or barf ".."
Expected a Dict for the assignments part of '<- %' statement, not \%assignments
lua> ".."
- local lhs, rhs = Lua(), Lua()
- for i, item in ipairs(\%assignments) do
- local \%target, \%value = item[1], item[2]
+ local lhs, rhs = Lua(tree.source), Lua(tree.source)
+ for i, item in ipairs(\%assignments.value) do
+ local \%target, \%value = item.value[1], item.value[2]
local target_lua = \(%target as lua)
if not target_lua.is_value then error("Invalid target for assignment: "..\(%target as text)) end
local value_lua = \(%value as lua)
@@ -81,7 +81,7 @@ immediately
lhs:append(target_lua)
rhs:append(value_lua)
end
- return Lua(nil, lhs, " = ", rhs, ";")
+ return Lua(tree.source, lhs, " = ", rhs, ";")
immediately
compile [external %var <- %value] to
@@ -89,20 +89,20 @@ immediately
assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
%value_lua <- (%value as lua)
assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
- return: Lua "\(%var_lua) = \(%value_lua);"
+ return: Lua "\%var_lua = \%value_lua;"
compile [with external %externs %body] to
%body_lua <- (%body as lua statements)
- lua> "\%body_lua:remove_free_vars(\(%externs));"
+ lua> "\%body_lua:remove_free_vars(\%externs.value);"
return %body_lua
compile [with %assignments %body] to
%lua <- (%body as lua statements)
lua> ".."
- local lhs, rhs = Lua(), Lua()
+ local lhs, rhs = Lua(tree.source), Lua(tree.source)
local vars = {}
- for i, item in ipairs(\%assignments) do
- local \%target, \%value = item[1], item[2]
+ for i, item in ipairs(\%assignments.value) do
+ local \%target, \%value = item.value[1], item.value[2]
if not \%target.type == "Var" then
error("Invalid target for 'with' assignment: "..tostring(\%target))
end
diff --git a/core/text.nom b/core/text.nom
index b7fd2cf..95451ee 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -27,7 +27,7 @@ lua> ".."
};
for name, e in pairs(escapes) do
local lua = "'"..e.."'";
- nomsu:define_compile_action(name, function(tree) return Lua.Value(nil, lua); end);
+ nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.value, lua); end);
end
local colors = {
["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m",
@@ -42,9 +42,9 @@ lua> ".."
for name, c in pairs(colors) do
local color = "'"..c.."'";
local reset = "'"..colors["reset color"].."'";
- nomsu:define_compile_action(name, function(tree) return Lua.Value(nil, color); end);
+ nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.value, color); end);
nomsu:define_compile_action(name.." %", function(\%)
- return Lua.Value(nil, color, "..", \(% as lua), "..", reset);
+ return Lua.Value(tree.value, color, "..", \(% as lua), "..", reset);
end);
end
end
diff --git a/lib/object.nom b/lib/object.nom
index 5c73046..cf0a809 100644
--- a/lib/object.nom
+++ b/lib/object.nom
@@ -16,20 +16,20 @@ compile [as %instance %body] to
end
compile [object %classname %class_body] to
- %class_id <- (=lua "Var(\(%classname as value)):as_lua_id():sub(2,-1)")
+ %class_id <- (=lua "Var.as_lua_id({value=\(%classname as value)}):sub(2,-1)")
if: %class_id is ""
%class_id <- "class"
%methods <-: Lua ""
%__index <- %class_id
%__newindex <- "nil"
- for %line in %class_body
+ for %line in %class_body.value
if: %line.type is "Comment"
do next %line
if: (%line.type is "Action") and ((%line's stub) is "slots %")
%slot_index_clauses <- []
%slot_newindex_clauses <- []
- %slots <- %line.2
- for %slot_index = %slot_var in %slots
+ %slots <- %line.value.2
+ for %slot_index = %slot_var in %slots.value
to %slot_index_clauses add ".."
if key == \(repr %slot_var.value) or key == \(repr (%slot_var as lua expr)) then
return rawget(self, \%slot_index);
@@ -52,15 +52,15 @@ compile [object %classname %class_body] to
do next %line
assume ((%line.type is "Action") and ((%line's stub) is "action % %"))
..or barf "Only action definitions are supported inside 'object % %'"
- %actions <- %line.2
- %body <- %line.3
+ %actions <- %line.value.2
+ %body <- %line.value.3
lua> ".."
do
local stubs = {}
- for i, action in ipairs(\%actions) do
+ for i, action in ipairs(\%actions.value) do
stubs[i] = action:get_stub(true)
end
- local lua = Lua(nil, \%class_id, "[ ", repr(stubs[1]), "] = function(self")
+ local lua = Lua(\(%line.source), \%class_id, "[ ", repr(stubs[1]), "] = function(self")
local args = {}
for i,tok in ipairs(\%actions[1]) do
if tok.type == "Var" then args[#args+1] = tok end
diff --git a/nomsu.lua b/nomsu.lua
index fcc3941..d035611 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -234,12 +234,19 @@ end
setmetatable(NOMSU_DEFS, {
__index = function(self, key)
local make_node
- make_node = function(src, ...)
- local tree = Types[key](...)
- insert(lpeg.userdata.depth_first_sources, {
- src,
- tree
- })
+ make_node = function(start, ...)
+ local args = {
+ ...
+ }
+ local stop = args[#args]
+ local source = lpeg.userdata.source:sub(start, stop)
+ args[#args] = nil
+ local tree
+ if Types[key].is_multi then
+ tree = Types[key](Tuple(unpack(args)), source)
+ else
+ tree = Types[key](args[1], source)
+ end
return tree
end
self[key] = make_node
@@ -253,7 +260,7 @@ do
anon_def <- ({ident} (" "*) ":"
{((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- %2"
captured_def <- ({ident} (" "*) "(" {ident} ")" (" "*) ":"
- {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3) -> %2)"
+ {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3 {}) -> %2)"
ident <- [a-zA-Z_][a-zA-Z0-9_]*
comment <- "--" [^%nl]*
]])
@@ -298,7 +305,9 @@ do
local _len_0 = 1
for _index_1 = 1, #stub_args do
local a = stub_args[_index_1]
- _accum_0[_len_0] = fn_arg_positions[Types.Var(a):as_lua_id()]
+ _accum_0[_len_0] = fn_arg_positions[Types.Var.as_lua_id({
+ value = a
+ })]
_len_0 = _len_0 + 1
end
arg_orders[stub] = _accum_0
@@ -322,7 +331,7 @@ do
""
},
errors = { },
- depth_first_sources = { }
+ source = nomsu_code.source
}
local old_userdata
old_userdata, lpeg.userdata = lpeg.userdata, userdata
@@ -345,25 +354,7 @@ do
end
error(concat(errors, "\n\n"), 0)
end
- local src_map = { }
- local src_i = 1
- local walk_tree
- walk_tree = function(tree, path)
- if tree.is_multi then
- for i, v in ipairs(tree) do
- if Types.is_node(v) then
- walk_tree(v, Tuple(i, path))
- end
- end
- end
- local src, t2 = unpack(userdata.depth_first_sources[src_i])
- src_i = src_i + 1
- assert(t2 == tree)
- src_map[path] = src
- end
- walk_tree(tree, Tuple())
- assert(src_i == #userdata.depth_first_sources + 1)
- return tree, src_map
+ return tree
end,
run = function(self, nomsu_code, compile_fn)
if compile_fn == nil then
@@ -465,10 +456,7 @@ do
end
return run_lua_fn()
end,
- tree_to_lua = function(self, tree, path)
- if path == nil then
- path = Tuple()
- end
+ tree_to_lua = function(self, tree)
local _exp_0 = tree.type
if "Action" == _exp_0 then
local stub = tree:get_stub()
@@ -478,8 +466,9 @@ do
do
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #tree do
- local arg = tree[_index_0]
+ local _list_0 = tree.value
+ for _index_0 = 1, #_list_0 do
+ local arg = _list_0[_index_0]
if type(arg) ~= "string" then
_accum_0[_len_0] = arg
_len_0 = _len_0 + 1
@@ -505,13 +494,13 @@ do
return ret
end
local action = rawget(self.environment.ACTIONS, stub)
- local lua = Lua.Value()
+ local lua = Lua.Value(tree.source)
if not action and math_expression:match(stub) then
- for i, tok in ipairs(tree) do
+ for i, tok in ipairs(tree.value) do
if type(tok) == 'string' then
lua:append(tok)
else
- local tok_lua = self:tree_to_lua(tok, Tuple(i, path))
+ local tok_lua = self:tree_to_lua(tok)
if not (tok_lua.is_value) then
error("non-expression value inside math expression: " .. tostring(colored.yellow(repr(tok))))
end
@@ -520,21 +509,21 @@ do
end
lua:append(tok_lua)
end
- if i < #tree then
+ if i < #tree.value then
lua:append(" ")
end
end
return lua
end
local args = { }
- for i, tok in ipairs(tree) do
+ for i, tok in ipairs(tree.value) do
local _continue_0 = false
repeat
if type(tok) == "string" then
_continue_0 = true
break
end
- local arg_lua = self:tree_to_lua(tok, Tuple(i, path))
+ local arg_lua = self:tree_to_lua(tok)
if not (arg_lua.is_value) then
error("Cannot use:\n" .. tostring(colored.yellow(repr(tok))) .. "\nas an argument to " .. tostring(stub) .. ", since it's not an expression, it produces: " .. tostring(repr(arg_lua)), 0)
end
@@ -578,23 +567,24 @@ do
do
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #t do
- local bit = t[_index_0]
+ local _list_0 = t.value
+ for _index_0 = 1, #_list_0 do
+ local bit = _list_0[_index_0]
_accum_0[_len_0] = make_tree(bit)
_len_0 = _len_0 + 1
end
bits = _accum_0
end
- return t.type .. "(" .. table.concat(bits, ", ") .. ")"
+ return t.type .. "(Tuple(" .. table.concat(bits, ", ") .. "), " .. repr(t.source) .. ")"
else
- return t.type .. "(" .. make_tree(t[1]) .. ")"
+ return t.type .. "(" .. repr(t.value) .. ", " .. repr(t.source) .. ")"
end
end
- return Lua.Value(nil, make_tree(tree[1]))
+ return Lua.Value(tree.source, make_tree(tree.value[1]))
elseif "Block" == _exp_0 then
- local lua = Lua()
- for i, line in ipairs(tree) do
- local line_lua = self:tree_to_lua(line, Tuple(i, path))
+ local lua = Lua(tree.source)
+ for i, line in ipairs(tree.value) do
+ local line_lua = self:tree_to_lua(line)
if i > 1 then
lua:append("\n")
end
@@ -602,9 +592,9 @@ do
end
return lua
elseif "Text" == _exp_0 then
- local lua = Lua.Value()
+ local lua = Lua.Value(tree.source)
local string_buffer = ""
- for i, bit in ipairs(tree) do
+ for i, bit in ipairs(tree.value) do
local _continue_0 = false
repeat
if type(bit) == "string" then
@@ -619,7 +609,7 @@ do
lua:append(repr(string_buffer))
string_buffer = ""
end
- local bit_lua = self:tree_to_lua(bit, Tuple(i, path))
+ local bit_lua = self:tree_to_lua(bit)
if not (bit_lua.is_value) then
error("Cannot use " .. tostring(colored.yellow(repr(bit))) .. " as a string interpolation value, since it's not an expression.", 0)
end
@@ -627,7 +617,7 @@ do
lua:append("..")
end
if bit.type ~= "Text" then
- bit_lua = Lua.Value(nil, "stringify(", bit_lua, ")")
+ bit_lua = Lua.Value(bit.source, "stringify(", bit_lua, ")")
end
lua:append(bit_lua)
_continue_0 = true
@@ -647,10 +637,10 @@ do
end
return lua
elseif "List" == _exp_0 then
- local lua = Lua.Value(nil, "{")
+ local lua = Lua.Value(tree.source, "{")
local line_length = 0
- for i, item in ipairs(tree) do
- local item_lua = self:tree_to_lua(item, Tuple(i, path))
+ for i, item in ipairs(tree.value) do
+ local item_lua = self:tree_to_lua(item)
if not (item_lua.is_value) then
error("Cannot use " .. tostring(colored.yellow(repr(item))) .. " as a list item, since it's not an expression.", 0)
end
@@ -662,7 +652,7 @@ do
else
line_length = line_length + #last_line
end
- if i < #tree then
+ if i < #tree.value then
if line_length >= MAX_LINE then
lua:append(",\n ")
line_length = 0
@@ -675,10 +665,10 @@ do
lua:append("}")
return lua
elseif "Dict" == _exp_0 then
- local lua = Lua.Value(nil, "{")
+ local lua = Lua.Value(tree.source, "{")
local line_length = 0
- for i, entry in ipairs(tree) do
- local entry_lua = self:tree_to_lua(entry, Tuple(i, path))
+ for i, entry in ipairs(tree.value) do
+ local entry_lua = self:tree_to_lua(entry)
lua:append(entry_lua)
local entry_lua_str = tostring(entry_lua)
local last_line = entry_lua_str:match("\n([^\n]*)$")
@@ -687,7 +677,7 @@ do
else
line_length = line_length + #entry_lua_str
end
- if i < #tree then
+ if i < #tree.value then
if line_length >= MAX_LINE then
lua:append(",\n ")
line_length = 0
@@ -700,35 +690,35 @@ do
lua:append("}")
return lua
elseif "DictEntry" == _exp_0 then
- local key, value = tree[1], tree[2]
- local key_lua = self:tree_to_lua(key, Tuple(1, path))
+ local key, value = tree.value[1], tree.value[2]
+ local key_lua = self:tree_to_lua(key)
if not (key_lua.is_value) then
error("Cannot use " .. tostring(colored.yellow(repr(key))) .. " as a dict key, since it's not an expression.", 0)
end
- local value_lua = value and self:tree_to_lua(value, Tuple(2, path)) or Lua.Value(nil, "true")
+ local value_lua = value and self:tree_to_lua(value) or Lua.Value(key.source, "true")
if not (value_lua.is_value) then
error("Cannot use " .. tostring(colored.yellow(repr(value))) .. " as a dict value, since it's not an expression.", 0)
end
local key_str = tostring(key_lua):match([=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
if key_str then
- return Lua(nil, key_str, "=", value_lua)
+ return Lua(tree.source, key_str, "=", value_lua)
elseif tostring(key_lua):sub(1, 1) == "[" then
- return Lua(nil, "[ ", key_lua, "]=", value_lua)
+ return Lua(tree.source, "[ ", key_lua, "]=", value_lua)
else
- return Lua(nil, "[", key_lua, "]=", value_lua)
+ return Lua(tree.source, "[", key_lua, "]=", value_lua)
end
elseif "IndexChain" == _exp_0 then
- local lua = self:tree_to_lua(tree[1], Tuple(1, path))
+ local lua = self:tree_to_lua(tree.value[1])
if not (lua.is_value) then
- error("Cannot index " .. tostring(colored.yellow(repr(tree[1]))) .. ", since it's not an expression.", 0)
+ error("Cannot index " .. tostring(colored.yellow(repr(tree.value[1]))) .. ", since it's not an expression.", 0)
end
local first_char = tostring(lua):sub(1, 1)
if first_char == "{" or first_char == '"' or first_char == "[" then
lua:parenthesize()
end
- for i = 2, #tree do
- local key = tree[i]
- local key_lua = self:tree_to_lua(key, Tuple(i, path))
+ for i = 2, #tree.value do
+ local key = tree.value[i]
+ local key_lua = self:tree_to_lua(key)
if not (key_lua.is_value) then
error("Cannot use " .. tostring(colored.yellow(repr(key))) .. " as an index, since it's not an expression.", 0)
end
@@ -746,11 +736,9 @@ do
end
return lua
elseif "Number" == _exp_0 then
- return Lua.Value(nil, tostring(tree.value))
+ return Lua.Value(tree.source, tostring(tree.value))
elseif "Var" == _exp_0 then
- return Lua.Value(nil, tree:as_lua_id())
- elseif "Comment" == _exp_0 then
- return Lua(nil, "--" .. tree.value:gsub("\n", "\n--") .. "\n")
+ return Lua.Value(tree.source, tree:as_lua_id())
else
return error("Unknown type: " .. tostring(tree.type))
end
@@ -765,8 +753,8 @@ do
local _exp_0 = tree.type
if "Action" == _exp_0 then
if inline then
- local nomsu = Nomsu()
- for i, bit in ipairs(tree) do
+ local nomsu = Nomsu(tree.source)
+ for i, bit in ipairs(tree.value) do
if type(bit) == "string" then
if i > 1 then
nomsu:append(" ")
@@ -788,10 +776,10 @@ do
end
return nomsu
else
- local nomsu = Nomsu()
+ local nomsu = Nomsu(tree.source)
local next_space = ""
local last_colon = nil
- for i, bit in ipairs(tree) do
+ for i, bit in ipairs(tree.value) do
if type(bit) == "string" then
nomsu:append(next_space, bit)
next_space = " "
@@ -825,9 +813,9 @@ do
end
if bit.type ~= "List" and bit.type ~= "Dict" and bit.type ~= "Text" then
if i == 1 then
- arg_nomsu = Nomsu(nil, "(..)\n ", arg_nomsu)
+ arg_nomsu = Nomsu(bit.source, "(..)\n ", arg_nomsu)
else
- arg_nomsu = Nomsu(nil, "\n ", arg_nomsu)
+ arg_nomsu = Nomsu(bit.source, "\n ", arg_nomsu)
end
end
if last_colon == i - 1 and (bit.type == "Action" or bit.type == "Block") then
@@ -846,14 +834,14 @@ do
elseif "EscapedNomsu" == _exp_0 then
local nomsu = self:tree_to_nomsu(tree.value, true)
if nomsu == nil and not inline then
- nomsu = self:tree_to_nomsu(tree[1])
- return nomsu and Nomsu(nil, "\\:\n ", nomsu)
+ nomsu = self:tree_to_nomsu(tree.value[1])
+ return nomsu and Nomsu(tree.source, "\\:\n ", nomsu)
end
- return nomsu and Nomsu(nil, "\\(", nomsu, ")")
+ return nomsu and Nomsu(tree.source, "\\(", nomsu, ")")
elseif "Block" == _exp_0 then
if inline then
- local nomsu = Nomsu()
- for i, line in ipairs(self) do
+ local nomsu = Nomsu(tree.source)
+ for i, line in ipairs(tree.value) do
if i > 1 then
nomsu:append("; ")
end
@@ -865,7 +853,7 @@ do
end
return nomsu
end
- local nomsu = Nomsu()
+ local nomsu = Nomsu(tree.source)
for i, line in ipairs(self) do
line = assert(self:tree_to_nomsu(line, nil, true), "Could not convert line to nomsu")
nomsu:append(line)
@@ -879,9 +867,10 @@ do
return nomsu
elseif "Text" == _exp_0 then
if inline then
- local nomsu = Nomsu(nil, '"')
- for _index_0 = 1, #tree do
- local bit = tree[_index_0]
+ local nomsu = Nomsu(tree.source, '"')
+ local _list_0 = tree.value
+ for _index_0 = 1, #_list_0 do
+ local bit = _list_0[_index_0]
if type(bit) == 'string' then
nomsu:append((bit:gsub("\\", "\\\\"):gsub("\n", "\\n")))
else
@@ -903,7 +892,7 @@ do
if inline_version and #inline_version <= MAX_LINE then
return inline_version
end
- local nomsu = Nomsu(nil, '".."\n ')
+ local nomsu = Nomsu(tree.source, '".."\n ')
for i, bit in ipairs(self) do
if type(bit) == 'string' then
nomsu:append((bit:gsub("\\", "\\\\"):gsub("\n", "\n ")))
@@ -930,8 +919,8 @@ do
end
elseif "List" == _exp_0 then
if inline then
- local nomsu = Nomsu(nil, "[")
- for i, item in ipairs(tree) do
+ local nomsu = Nomsu(tree.source, "[")
+ for i, item in ipairs(tree.value) do
local item_nomsu = self:tree_to_nomsu(item, true)
if not (item_nomsu) then
return nil
@@ -948,10 +937,11 @@ do
if inline_version and #inline_version <= MAX_LINE then
return inline_version
end
- local nomsu = Nomsu(nil, "[..]")
- local line = Nomsu(nil, "\n ")
- for _index_0 = 1, #tree do
- local item = tree[_index_0]
+ local nomsu = Nomsu(tree.source, "[..]")
+ local line = Nomsu(tree.source, "\n ")
+ local _list_0 = tree.value
+ for _index_0 = 1, #_list_0 do
+ local item = _list_0[_index_0]
local item_nomsu = self:tree_to_nomsu(item, true)
if item_nomsu and #line + #", " + #item_nomsu <= MAX_LINE then
if #line.bits > 1 then
@@ -967,7 +957,7 @@ do
end
if #line.bits > 1 then
nomsu:append(line)
- line = Nomsu(nil, "\n ")
+ line = Nomsu(line.source, "\n ")
end
line:append(item_nomsu)
end
@@ -979,8 +969,8 @@ do
end
elseif "Dict" == _exp_0 then
if inline then
- local nomsu = Nomsu(nil, "{")
- for i, entry in ipairs(tree) do
+ local nomsu = Nomsu(tree.source, "{")
+ for i, entry in ipairs(tree.value) do
local entry_nomsu = self:tree_to_nomsu(entry, true)
if not (entry_nomsu) then
return nil
@@ -997,10 +987,11 @@ do
if inline_version then
return inline_version
end
- local nomsu = Nomsu(nil, "{..}")
- local line = Nomsu(nil, "\n ")
- for _index_0 = 1, #tree do
- local entry = tree[_index_0]
+ local nomsu = Nomsu(tree.source, "{..}")
+ local line = Nomsu(tree.source, "\n ")
+ local _list_0 = tree.value
+ for _index_0 = 1, #_list_0 do
+ local entry = _list_0[_index_0]
local entry_nomsu = self:tree_to_nomsu(entry)
if not (entry_nomsu) then
return nil
@@ -1013,7 +1004,7 @@ do
else
if #line.bits > 1 then
nomsu:append(line)
- line = Nomsu(nil, "\n ")
+ line = Nomsu(line.source, "\n ")
end
line:append(entry_nomsu)
end
@@ -1024,7 +1015,7 @@ do
return nomsu
end
elseif "DictEntry" == _exp_0 then
- local key, value = tree[1], tree[2]
+ local key, value = tree.value[1], tree.value[2]
local key_nomsu = self:tree_to_nomsu(key, true)
if not (key_nomsu) then
return nil
@@ -1036,7 +1027,7 @@ do
if value then
value_nomsu = self:tree_to_nomsu(value, true)
else
- value_nomsu = Nomsu(nil, "")
+ value_nomsu = Nomsu(tree.source, "")
end
if inline and not value_nomsu then
return nil
@@ -1050,10 +1041,10 @@ do
return nil
end
end
- return Nomsu(nil, key_nomsu, ":", value_nomsu)
+ return Nomsu(tree.source, key_nomsu, ":", value_nomsu)
elseif "IndexChain" == _exp_0 then
- local nomsu = Nomsu()
- for i, bit in ipairs(tree) do
+ local nomsu = Nomsu(tree.source)
+ for i, bit in ipairs(tree.value) do
if i > 1 then
nomsu:append(".")
end
@@ -1068,14 +1059,14 @@ do
end
return nomsu
elseif "Number" == _exp_0 then
- return Nomsu(nil, tostring(tree.value))
+ return Nomsu(tree.source, tostring(tree.value))
elseif "Var" == _exp_0 then
- return Nomsu(nil, "%", tree.value)
+ return Nomsu(tree.source, "%", tree.value)
elseif "Comment" == _exp_0 then
if inline then
return nil
end
- return Nomsu(nil, "#", tree.value:gsub("\n", "\n "))
+ return Nomsu(tree.source, "#", tree.value:gsub("\n", "\n "))
else
return error("Unknown type: " .. tostring(tree.type))
end
@@ -1084,7 +1075,7 @@ do
if tree.type == 'Text' and #tree == 1 and type(tree[1]) == 'string' then
return tree[1]
end
- local lua = Lua(nil, "return ", self:tree_to_lua(tree), ";")
+ local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";")
return self:run_lua(lua)
end,
walk_tree = function(self, tree, depth)
@@ -1093,8 +1084,9 @@ do
end
coroutine.yield(tree, depth)
if tree.is_multi then
- for _index_0 = 1, #tree do
- local v = tree[_index_0]
+ local _list_0 = tree.value
+ for _index_0 = 1, #_list_0 do
+ local v = _list_0[_index_0]
if Types.is_node(v) then
self:walk_tree(v, depth + 1)
end
@@ -1107,7 +1099,7 @@ do
local lua = nomsu:tree_to_lua(_block):as_statements()
lua:declare_locals()
nomsu:run_lua(lua)
- return Lua(nil, "if IMMEDIATE then\n ", lua, "\nend")
+ return Lua(_block.source, "if IMMEDIATE then\n ", lua, "\nend")
end)
local add_lua_string_bits
add_lua_string_bits = function(lua, code)
@@ -1115,8 +1107,9 @@ do
lua:append(", ", nomsu:tree_to_lua(code))
return
end
- for _index_0 = 1, #code do
- local bit = code[_index_0]
+ local _list_0 = code.value
+ for _index_0 = 1, #_list_0 do
+ local bit = _list_0[_index_0]
lua:append(", ")
if type(bit) == "string" then
lua:append(repr(bit))
@@ -1130,21 +1123,22 @@ do
end
end
self:define_compile_action("Lua %code", function(self, _code)
- local lua = Lua.Value(nil, "Lua(nil")
+ local lua = Lua.Value(_code.source, "Lua(", repr(_code.source))
add_lua_string_bits(lua, _code)
lua:append(")")
return lua
end)
self:define_compile_action("Lua value %code", function(self, _code)
- local lua = Lua.Value(nil, "Lua.Value(nil")
+ local lua = Lua.Value(_code.source, "Lua.Value(", repr(_code.source))
add_lua_string_bits(lua, _code)
lua:append(")")
return lua
end)
local add_lua_bits
add_lua_bits = function(lua, code)
- for _index_0 = 1, #code do
- local bit = code[_index_0]
+ local _list_0 = code.value
+ for _index_0 = 1, #_list_0 do
+ local bit = _list_0[_index_0]
if type(bit) == "string" then
lua:append(bit)
else
@@ -1159,20 +1153,20 @@ do
end
self:define_compile_action("lua> %code", function(self, _code)
if _code.type ~= "Text" then
- return Lua(nil, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ");")
+ return Lua(self.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ");")
end
- return add_lua_bits(Lua(), _code)
+ return add_lua_bits(Lua(self.source), _code)
end)
self:define_compile_action("=lua %code", function(self, _code)
if _code.type ~= "Text" then
- return Lua.Value(nil, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ":as_statements('return '))")
+ return Lua.Value(self.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ":as_statements('return '))")
end
- return add_lua_bits(Lua.Value(), _code)
+ return add_lua_bits(Lua.Value(self.source), _code)
end)
return self:define_compile_action("use %path", function(self, _path)
local path = nomsu:tree_to_value(_path)
nomsu:run_file(path)
- return Lua(nil, "nomsu:run_file(" .. tostring(repr(path)) .. ");")
+ return Lua(_path.source, "nomsu:run_file(" .. tostring(repr(path)) .. ");")
end)
end
}
diff --git a/nomsu.moon b/nomsu.moon
index 8fef96c..cd542b0 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -200,9 +200,14 @@ NOMSU_DEFS = with {}
return true
setmetatable(NOMSU_DEFS, {__index:(key)=>
- make_node = (src, ...)->
- tree = Types[key](...)
- insert lpeg.userdata.depth_first_sources, {src, tree}
+ make_node = (start, ...)->
+ args = {...}
+ stop = args[#args]
+ source = lpeg.userdata.source\sub(start, stop)
+ args[#args] = nil
+ tree = if Types[key].is_multi
+ Types[key](Tuple(unpack(args)), source)
+ else Types[key](args[1], source)
return tree
self[key] = make_node
return make_node
@@ -217,7 +222,7 @@ NOMSU_PATTERN = do
anon_def <- ({ident} (" "*) ":"
{((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- %2"
captured_def <- ({ident} (" "*) "(" {ident} ")" (" "*) ":"
- {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3) -> %2)"
+ {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3 {}) -> %2)"
ident <- [a-zA-Z_][a-zA-Z0-9_]*
comment <- "--" [^%nl]*
]]
@@ -314,7 +319,7 @@ class NomsuCompiler
stub = assert(stub_pattern\match(alias))
stub_args = assert(var_pattern\match(alias))
(is_compile_action and @environment.COMPILE_ACTIONS or @environment.ACTIONS)[stub] = fn
- arg_orders[stub] = [fn_arg_positions[Types.Var(a)\as_lua_id!] for a in *stub_args]
+ arg_orders[stub] = [fn_arg_positions[Types.Var.as_lua_id {value:a}] for a in *stub_args]
@environment.ARG_ORDERS[fn] = arg_orders
define_compile_action: (signature, fn)=>
@@ -329,7 +334,7 @@ class NomsuCompiler
nomsu_code = Nomsu(filename, nomsu_code)
userdata = {
source_code:nomsu_code, indent_stack: {""}, errors: {},
- depth_first_sources: {},
+ source: nomsu_code.source,
}
old_userdata, lpeg.userdata = lpeg.userdata, userdata
@@ -344,21 +349,7 @@ class NomsuCompiler
errors = [userdata.errors[k] for k in *keys]
error(concat(errors, "\n\n"), 0)
- src_map = {}
- src_i = 1
- walk_tree = (tree, path)->
- if tree.is_multi
- for i, v in ipairs tree
- if Types.is_node(v)
- walk_tree(v, Tuple(i, path))
- src, t2 = unpack(userdata.depth_first_sources[src_i])
- src_i += 1
- assert t2 == tree
- src_map[path] = src
- walk_tree tree, Tuple!
- assert src_i == #userdata.depth_first_sources + 1
-
- return tree, src_map
+ return tree
run: (nomsu_code, compile_fn=nil)=>
if #tostring(nomsu_code) == 0 then return nil
@@ -427,13 +418,13 @@ class NomsuCompiler
MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
math_expression = re.compile [[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]
- tree_to_lua: (tree, path=Tuple!)=>
+ tree_to_lua: (tree)=>
switch tree.type
when "Action"
stub = tree\get_stub!
compile_action = @environment.COMPILE_ACTIONS[stub]
if compile_action
- args = [arg for arg in *tree when type(arg) != "string"]
+ args = [arg for arg in *tree.value when type(arg) != "string"]
-- Force all compile-time actions to take a tree location
args = [args[p-1] for p in *@environment.ARG_ORDERS[compile_action][stub]]
-- Force Lua to avoid tail call optimization for debugging purposes
@@ -442,29 +433,29 @@ class NomsuCompiler
if not ret then error("Failed to produce any Lua")
return ret
action = rawget(@environment.ACTIONS, stub)
- lua = Lua.Value!
+ lua = Lua.Value(tree.source)
if not action and math_expression\match(stub)
-- This is a bit of a hack, but this code handles arbitrarily complex
-- math expressions like 2*x + 3^2 without having to define a single
-- action for every possibility.
- for i,tok in ipairs tree
+ for i,tok in ipairs tree.value
if type(tok) == 'string'
lua\append tok
else
- tok_lua = @tree_to_lua(tok, Tuple(i, path))
+ tok_lua = @tree_to_lua(tok)
unless tok_lua.is_value
error("non-expression value inside math expression: #{colored.yellow repr(tok)}")
if tok.type == "Action"
tok_lua\parenthesize!
lua\append tok_lua
- if i < #tree
+ if i < #tree.value
lua\append " "
return lua
args = {}
- for i, tok in ipairs tree
+ for i, tok in ipairs tree.value
if type(tok) == "string" then continue
- arg_lua = @tree_to_lua(tok, Tuple(i, path))
+ arg_lua = @tree_to_lua(tok)
unless arg_lua.is_value
error "Cannot use:\n#{colored.yellow repr(tok)}\nas an argument to #{stub}, since it's not an expression, it produces: #{repr arg_lua}", 0
insert args, arg_lua
@@ -486,25 +477,25 @@ class NomsuCompiler
if type(t) != 'userdata'
return repr(t)
if t.is_multi
- bits = [make_tree(bit) for bit in *t]
- return t.type.."("..table.concat(bits, ", ")..")"
+ bits = [make_tree(bit) for bit in *t.value]
+ return t.type.."(Tuple("..table.concat(bits, ", ").."), "..repr(t.source)..")"
else
- return t.type.."("..make_tree(t[1])..")"
- Lua.Value nil, make_tree(tree[1])
+ return t.type.."("..repr(t.value)..", "..repr(t.source)..")"
+ Lua.Value tree.source, make_tree(tree.value[1])
when "Block"
- lua = Lua!
- for i,line in ipairs tree
- line_lua = @tree_to_lua(line, Tuple(i, path))
+ lua = Lua(tree.source)
+ for i,line in ipairs tree.value
+ line_lua = @tree_to_lua(line)
if i > 1
lua\append "\n"
lua\append line_lua\as_statements!
return lua
when "Text"
- lua = Lua.Value!
+ lua = Lua.Value(tree.source)
string_buffer = ""
- for i, bit in ipairs tree
+ for i, bit in ipairs tree.value
if type(bit) == "string"
string_buffer ..= bit
continue
@@ -512,12 +503,12 @@ class NomsuCompiler
if #lua.bits > 0 then lua\append ".."
lua\append repr(string_buffer)
string_buffer = ""
- bit_lua = @tree_to_lua(bit, Tuple(i, path))
+ bit_lua = @tree_to_lua(bit)
unless bit_lua.is_value
error "Cannot use #{colored.yellow repr(bit)} as a string interpolation value, since it's not an expression.", 0
if #lua.bits > 0 then lua\append ".."
if bit.type != "Text"
- bit_lua = Lua.Value(nil, "stringify(",bit_lua,")")
+ bit_lua = Lua.Value(bit.source, "stringify(",bit_lua,")")
lua\append bit_lua
if string_buffer ~= "" or #lua.bits == 0
@@ -529,10 +520,10 @@ class NomsuCompiler
return lua
when "List"
- lua = Lua.Value nil, "{"
+ lua = Lua.Value tree.source, "{"
line_length = 0
- for i, item in ipairs tree
- item_lua = @tree_to_lua(item, Tuple(i, path))
+ for i, item in ipairs tree.value
+ item_lua = @tree_to_lua(item)
unless item_lua.is_value
error "Cannot use #{colored.yellow repr(item)} as a list item, since it's not an expression.", 0
lua\append item_lua
@@ -542,7 +533,7 @@ class NomsuCompiler
line_length = #last_line
else
line_length += #last_line
- if i < #tree
+ if i < #tree.value
if line_length >= MAX_LINE
lua\append ",\n "
line_length = 0
@@ -553,10 +544,10 @@ class NomsuCompiler
return lua
when "Dict"
- lua = Lua.Value nil, "{"
+ lua = Lua.Value tree.source, "{"
line_length = 0
- for i, entry in ipairs tree
- entry_lua = @tree_to_lua(entry, Tuple(i, path))
+ for i, entry in ipairs tree.value
+ entry_lua = @tree_to_lua(entry)
lua\append entry_lua
entry_lua_str = tostring(entry_lua)
-- TODO: maybe make this more accurate? It's only a heuristic, so eh...
@@ -565,7 +556,7 @@ class NomsuCompiler
line_length = #last_line
else
line_length += #entry_lua_str
- if i < #tree
+ if i < #tree.value
if line_length >= MAX_LINE
lua\append ",\n "
line_length = 0
@@ -576,35 +567,35 @@ class NomsuCompiler
return lua
when "DictEntry"
- key, value = tree[1], tree[2]
- key_lua = @tree_to_lua(key, Tuple(1, path))
+ key, value = tree.value[1], tree.value[2]
+ key_lua = @tree_to_lua(key)
unless key_lua.is_value
error "Cannot use #{colored.yellow repr(key)} as a dict key, since it's not an expression.", 0
- value_lua = value and @tree_to_lua(value, Tuple(2, path)) or Lua.Value(nil, "true")
+ value_lua = value and @tree_to_lua(value) or Lua.Value(key.source, "true")
unless value_lua.is_value
error "Cannot use #{colored.yellow repr(value)} as a dict value, since it's not an expression.", 0
key_str = tostring(key_lua)\match([=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
return if key_str
- Lua nil, key_str,"=",value_lua
+ Lua tree.source, key_str,"=",value_lua
elseif tostring(key_lua)\sub(1,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"]
- Lua nil, "[ ",key_lua,"]=",value_lua
+ Lua tree.source, "[ ",key_lua,"]=",value_lua
else
- Lua nil, "[",key_lua,"]=",value_lua
+ Lua tree.source, "[",key_lua,"]=",value_lua
when "IndexChain"
- lua = @tree_to_lua(tree[1], Tuple(1, path))
+ lua = @tree_to_lua(tree.value[1])
unless lua.is_value
- error "Cannot index #{colored.yellow repr(tree[1])}, since it's not an expression.", 0
+ error "Cannot index #{colored.yellow repr(tree.value[1])}, since it's not an expression.", 0
first_char = tostring(lua)\sub(1,1)
if first_char == "{" or first_char == '"' or first_char == "["
lua\parenthesize!
- for i=2,#tree
- key = tree[i]
- key_lua = @tree_to_lua(key, Tuple(i, path))
+ for i=2,#tree.value
+ key = tree.value[i]
+ key_lua = @tree_to_lua(key)
unless key_lua.is_value
error "Cannot use #{colored.yellow repr(key)} as an index, since it's not an expression.", 0
key_lua_str = tostring(key_lua)
@@ -620,13 +611,10 @@ class NomsuCompiler
return lua
when "Number"
- Lua.Value(nil, tostring(tree.value))
+ Lua.Value(tree.source, tostring(tree.value))
when "Var"
- Lua.Value(nil, tree\as_lua_id!)
-
- when "Comment"
- Lua(nil, "--"..tree.value\gsub("\n","\n--").."\n")
+ Lua.Value(tree.source, tree\as_lua_id!)
else
error("Unknown type: #{tree.type}")
@@ -636,8 +624,8 @@ class NomsuCompiler
switch tree.type
when "Action"
if inline
- nomsu = Nomsu!
- for i,bit in ipairs tree
+ nomsu = Nomsu(tree.source)
+ for i,bit in ipairs tree.value
if type(bit) == "string"
if i > 1
nomsu\append " "
@@ -652,11 +640,11 @@ class NomsuCompiler
nomsu\append arg_nomsu
return nomsu
else
- nomsu = Nomsu!
+ nomsu = Nomsu(tree.source)
next_space = ""
-- TODO: track line length as we go and use 80-that instead of 80 for wrapping
last_colon = nil
- for i,bit in ipairs tree
+ for i,bit in ipairs tree.value
if type(bit) == "string"
nomsu\append next_space, bit
next_space = " "
@@ -683,9 +671,9 @@ class NomsuCompiler
-- These types carry their own indentation
if bit.type != "List" and bit.type != "Dict" and bit.type != "Text"
if i == 1
- arg_nomsu = Nomsu(nil, "(..)\n ", arg_nomsu)
+ arg_nomsu = Nomsu(bit.source, "(..)\n ", arg_nomsu)
else
- arg_nomsu = Nomsu(nil, "\n ", arg_nomsu)
+ arg_nomsu = Nomsu(bit.source, "\n ", arg_nomsu)
if last_colon == i-1 and (bit.type == "Action" or bit.type == "Block")
next_space = ""
@@ -699,21 +687,21 @@ class NomsuCompiler
when "EscapedNomsu"
nomsu = @tree_to_nomsu(tree.value, true)
if nomsu == nil and not inline
- nomsu = @tree_to_nomsu(tree[1])
- return nomsu and Nomsu nil, "\\:\n ", nomsu
- return nomsu and Nomsu nil, "\\(", nomsu, ")"
+ nomsu = @tree_to_nomsu(tree.value[1])
+ return nomsu and Nomsu tree.source, "\\:\n ", nomsu
+ return nomsu and Nomsu tree.source, "\\(", nomsu, ")"
when "Block"
if inline
- nomsu = Nomsu!
- for i,line in ipairs @
+ nomsu = Nomsu(tree.source)
+ for i,line in ipairs tree.value
if i > 1
nomsu\append "; "
line_nomsu = @tree_to_nomsu(line,true)
return nil unless line_nomsu
nomsu\append line_nomsu
return nomsu
- nomsu = Nomsu!
+ nomsu = Nomsu(tree.source)
for i, line in ipairs @
line = assert(@tree_to_nomsu(line, nil, true), "Could not convert line to nomsu")
nomsu\append line
@@ -725,8 +713,8 @@ class NomsuCompiler
when "Text"
if inline
- nomsu = Nomsu(nil, '"')
- for bit in *tree
+ nomsu = Nomsu(tree.source, '"')
+ for bit in *tree.value
if type(bit) == 'string'
-- TODO: unescape better?
nomsu\append (bit\gsub("\\","\\\\")\gsub("\n","\\n"))
@@ -743,7 +731,7 @@ class NomsuCompiler
inline_version = @tree_to_nomsu(tree, true)
if inline_version and #inline_version <= MAX_LINE
return inline_version
- nomsu = Nomsu(nil, '".."\n ')
+ nomsu = Nomsu(tree.source, '".."\n ')
for i, bit in ipairs @
if type(bit) == 'string'
nomsu\append (bit\gsub("\\","\\\\")\gsub("\n","\n "))
@@ -763,8 +751,8 @@ class NomsuCompiler
when "List"
if inline
- nomsu = Nomsu(nil, "[")
- for i, item in ipairs tree
+ nomsu = Nomsu(tree.source, "[")
+ for i, item in ipairs tree.value
item_nomsu = @tree_to_nomsu(item, true)
return nil unless item_nomsu
if i > 1
@@ -776,9 +764,9 @@ class NomsuCompiler
inline_version = @tree_to_nomsu(tree, true)
if inline_version and #inline_version <= MAX_LINE
return inline_version
- nomsu = Nomsu(nil, "[..]")
- line = Nomsu(nil, "\n ")
- for item in *tree
+ nomsu = Nomsu(tree.source, "[..]")
+ line = Nomsu(tree.source, "\n ")
+ for item in *tree.value
item_nomsu = @tree_to_nomsu(item, true)
if item_nomsu and #line + #", " + #item_nomsu <= MAX_LINE
if #line.bits > 1
@@ -790,7 +778,7 @@ class NomsuCompiler
return nil unless item_nomsu
if #line.bits > 1
nomsu\append line
- line = Nomsu(nil, "\n ")
+ line = Nomsu(line.source, "\n ")
line\append item_nomsu
if #line.bits > 1
nomsu\append line
@@ -798,8 +786,8 @@ class NomsuCompiler
when "Dict"
if inline
- nomsu = Nomsu(nil, "{")
- for i, entry in ipairs tree
+ nomsu = Nomsu(tree.source, "{")
+ for i, entry in ipairs tree.value
entry_nomsu = @tree_to_nomsu(entry, true)
return nil unless entry_nomsu
if i > 1
@@ -810,9 +798,9 @@ class NomsuCompiler
else
inline_version = @tree_to_nomsu(tree, true)
if inline_version then return inline_version
- nomsu = Nomsu(nil, "{..}")
- line = Nomsu(nil, "\n ")
- for entry in *tree
+ nomsu = Nomsu(tree.source, "{..}")
+ line = Nomsu(tree.source, "\n ")
+ for entry in *tree.value
entry_nomsu = @tree_to_nomsu(entry)
return nil unless entry_nomsu
if #line + #tostring(entry_nomsu) <= MAX_LINE
@@ -822,31 +810,31 @@ class NomsuCompiler
else
if #line.bits > 1
nomsu\append line
- line = Nomsu(nil, "\n ")
+ line = Nomsu(line.source, "\n ")
line\append entry_nomsu
if #line.bits > 1
nomsu\append line
return nomsu
when "DictEntry"
- key, value = tree[1], tree[2]
+ key, value = tree.value[1], tree.value[2]
key_nomsu = @tree_to_nomsu(key, true)
return nil unless key_nomsu
if key.type == "Action" or key.type == "Block"
key_nomsu\parenthesize!
value_nomsu = if value
@tree_to_nomsu(value, true)
- else Nomsu(nil, "")
+ else Nomsu(tree.source, "")
if inline and not value_nomsu then return nil
if not value_nomsu
return nil if inline
value_nomsu = @tree_to_nomsu(value)
return nil unless value_nomsu
- return Nomsu nil, key_nomsu, ":", value_nomsu
+ return Nomsu tree.source, key_nomsu, ":", value_nomsu
when "IndexChain"
- nomsu = Nomsu!
- for i, bit in ipairs tree
+ nomsu = Nomsu(tree.source)
+ for i, bit in ipairs tree.value
if i > 1
nomsu\append "."
bit_nomsu = @tree_to_nomsu(bit, true)
@@ -857,14 +845,14 @@ class NomsuCompiler
return nomsu
when "Number"
- return Nomsu(nil, tostring(tree.value))
+ return Nomsu(tree.source, tostring(tree.value))
when "Var"
- return Nomsu(nil, "%", tree.value)
+ return Nomsu(tree.source, "%", tree.value)
when "Comment"
return nil if inline
- return Nomsu(nil, "#", tree.value\gsub("\n", "\n "))
+ return Nomsu(tree.source, "#", tree.value\gsub("\n", "\n "))
else
error("Unknown type: #{tree.type}")
@@ -873,13 +861,13 @@ class NomsuCompiler
-- Special case for text literals
if tree.type == 'Text' and #tree == 1 and type(tree[1]) == 'string'
return tree[1]
- lua = Lua(nil, "return ",@tree_to_lua(tree),";")
+ lua = Lua(tree.source, "return ",@tree_to_lua(tree),";")
return @run_lua(lua)
walk_tree: (tree, depth=0)=>
coroutine.yield(tree, depth)
if tree.is_multi
- for v in *tree
+ for v in *tree.value
if Types.is_node(v)
@walk_tree(v, depth+1)
@@ -890,13 +878,13 @@ class NomsuCompiler
lua = nomsu\tree_to_lua(_block)\as_statements!
lua\declare_locals!
nomsu\run_lua(lua)
- return Lua(nil, "if IMMEDIATE then\n ", lua, "\nend")
+ return Lua(_block.source, "if IMMEDIATE then\n ", lua, "\nend")
add_lua_string_bits = (lua, code)->
if code.type != "Text"
lua\append ", ", nomsu\tree_to_lua(code)
return
- for bit in *code
+ for bit in *code.value
lua\append ", "
if type(bit) == "string"
lua\append repr(bit)
@@ -907,19 +895,19 @@ class NomsuCompiler
lua\append bit_lua
@define_compile_action "Lua %code", (_code)=>
- lua = Lua.Value(nil, "Lua(nil")
+ lua = Lua.Value(_code.source, "Lua(", repr(_code.source))
add_lua_string_bits(lua, _code)
lua\append ")"
return lua
@define_compile_action "Lua value %code", (_code)=>
- lua = Lua.Value(nil, "Lua.Value(nil")
+ lua = Lua.Value(_code.source, "Lua.Value(", repr(_code.source))
add_lua_string_bits(lua, _code)
lua\append ")"
return lua
add_lua_bits = (lua, code)->
- for bit in *code
+ for bit in *code.value
if type(bit) == "string"
lua\append bit
else
@@ -931,18 +919,18 @@ class NomsuCompiler
@define_compile_action "lua> %code", (_code)=>
if _code.type != "Text"
- return Lua nil, "nomsu:run_lua(", nomsu\tree_to_lua(_code), ");"
- return add_lua_bits(Lua!, _code)
+ return Lua @source, "nomsu:run_lua(", nomsu\tree_to_lua(_code), ");"
+ return add_lua_bits(Lua(@source), _code)
@define_compile_action "=lua %code", (_code)=>
if _code.type != "Text"
- return Lua.Value nil, "nomsu:run_lua(", nomsu\tree_to_lua(_code), ":as_statements('return '))"
- return add_lua_bits(Lua.Value!, _code)
+ return Lua.Value @source, "nomsu:run_lua(", nomsu\tree_to_lua(_code), ":as_statements('return '))"
+ return add_lua_bits(Lua.Value(@source), _code)
@define_compile_action "use %path", (_path)=>
path = nomsu\tree_to_value(_path)
nomsu\run_file(path)
- return Lua(nil, "nomsu:run_file(#{repr path});")
+ return Lua(_path.source, "nomsu:run_file(#{repr path});")
-- Only run this code if this file was run directly with command line arguments, and not require()'d:
if arg and debug_getinfo(2).func != require
diff --git a/nomsu_tree.lua b/nomsu_tree.lua
index e7a5fce..ccbc34a 100644
--- a/nomsu_tree.lua
+++ b/nomsu_tree.lua
@@ -23,11 +23,12 @@ Tree = function(name, kind, methods)
assert((kind == 'single') or (kind == 'multi'))
local is_multi = (kind == 'multi')
do
- methods.with_value = function(self, value)
- return getmetatable(self)(value)
- end
methods.type = name
methods.name = name
+ methods.__new = function(self, value, source)
+ assert(source)
+ return value, source
+ end
methods.is_multi = is_multi
methods.map = function(self, fn)
if type(fn) == 'table' then
@@ -49,8 +50,9 @@ Tree = function(name, kind, methods)
return tostring(self.name) .. "(" .. tostring(table.concat((function()
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #self do
- local v = self[_index_0]
+ local _list_0 = self.value
+ for _index_0 = 1, #_list_0 do
+ local v = _list_0[_index_0]
_accum_0[_len_0] = repr(v)
_len_0 = _len_0 + 1
end
@@ -68,16 +70,20 @@ Tree = function(name, kind, methods)
do
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #self do
- local v = self[_index_0]
+ local _list_0 = self.value
+ for _index_0 = 1, #_list_0 do
+ local v = _list_0[_index_0]
_accum_0[_len_0] = v._map and v:_map(fn) or v
_len_0 = _len_0 + 1
end
new_vals = _accum_0
end
- local ret = getmetatable(self)(unpack(new_vals))
+ local ret = getmetatable(self)(Tuple(unpack(new_vals)), self.source)
return ret
end
+ methods.__ipairs = function(self)
+ return error()
+ end
else
methods.__tostring = function(self)
return tostring(self.name) .. "(" .. tostring(repr(self.value)) .. ")"
@@ -87,13 +93,10 @@ Tree = function(name, kind, methods)
end
end
end
- if is_multi then
- Types[name] = immutable(nil, methods)
- else
- Types[name] = immutable({
- "value"
- }, methods)
- end
+ Types[name] = immutable({
+ "value",
+ "source"
+ }, methods)
end
Tree("Block", 'multi')
Tree("EscapedNomsu", 'multi')
@@ -124,8 +127,9 @@ Tree("Action", 'multi', {
return concat((function()
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #self do
- local a = self[_index_0]
+ local _list_0 = self.value
+ for _index_0 = 1, #_list_0 do
+ local a = _list_0[_index_0]
_accum_0[_len_0] = type(a) == "string" and a or "%" .. tostring(a.value)
_len_0 = _len_0 + 1
end
@@ -135,8 +139,9 @@ Tree("Action", 'multi', {
return concat((function()
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #self do
- local a = self[_index_0]
+ local _list_0 = self.value
+ for _index_0 = 1, #_list_0 do
+ local a = _list_0[_index_0]
_accum_0[_len_0] = type(a) == "string" and a or "%"
_len_0 = _len_0 + 1
end
diff --git a/nomsu_tree.moon b/nomsu_tree.moon
index e261306..ac82cc0 100644
--- a/nomsu_tree.moon
+++ b/nomsu_tree.moon
@@ -18,9 +18,11 @@ Tree = (name, kind, methods)->
assert((kind == 'single') or (kind == 'multi'))
is_multi = (kind == 'multi')
with methods
- .with_value = (value)=> getmetatable(self)(value)
.type = name
.name = name
+ .__new = (value, source)=>
+ assert source
+ return value, source
.is_multi = is_multi
.map = (fn)=>
if type(fn) == 'table'
@@ -31,22 +33,20 @@ Tree = (name, kind, methods)->
fn = (k)-> _replacements[k]
return @_map(fn)
if is_multi
- .__tostring = => "#{@name}(#{table.concat [repr(v) for v in *@], ', '})"
+ .__tostring = => "#{@name}(#{table.concat [repr(v) for v in *@value], ', '})"
._map = (fn)=>
if ret = fn(@)
return ret
- new_vals = [v._map and v\_map(fn) or v for v in *@]
- ret = getmetatable(self)(unpack(new_vals))
+ new_vals = [v._map and v\_map(fn) or v for v in *@value]
+ ret = getmetatable(self)(Tuple(unpack(new_vals)), @source)
return ret
+ .__ipairs = => error!
else
.__tostring = => "#{@name}(#{repr(@value)})"
._map = (fn)=>
fn(@) or @
- if is_multi
- Types[name] = immutable nil, methods
- else
- Types[name] = immutable {"value"}, methods
+ Types[name] = immutable {"value", "source"}, methods
Tree "Block", 'multi'
Tree "EscapedNomsu", 'multi'
@@ -65,8 +65,8 @@ Tree "Var", 'single',
Tree "Action", 'multi',
get_stub: (include_names=false)=>
if include_names
- concat [type(a) == "string" and a or "%#{a.value}" for a in *@], " "
+ concat [type(a) == "string" and a or "%#{a.value}" for a in *@value], " "
else
- concat [type(a) == "string" and a or "%" for a in *@], " "
+ concat [type(a) == "string" and a or "%" for a in *@value], " "
return Types
diff --git a/tests/metaprogramming.nom b/tests/metaprogramming.nom
index ac27394..9a4c9b2 100644
--- a/tests/metaprogramming.nom
+++ b/tests/metaprogramming.nom
@@ -54,10 +54,10 @@ assume (((\%x as lua identifier) as text) = "_x") or barf "converting to identif
assume ((run "return 99") = 99) or barf "run % failed."
-say "Metaprogramming test passed."
-
%code <-: Lua "global_x = true;"
lua> %code
assume (=lua "global_x") or barf "Running lua from a variable failed."
%code <-: Lua value "global_x"
assume (=lua %code) or barf "Running lua from a variable failed."
+
+say "Metaprogramming test passed."