aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/metaprogramming.nom128
-rw-r--r--core/operators.nom4
-rw-r--r--nomsu.lua16
-rwxr-xr-xnomsu.moon16
-rw-r--r--nomsu.peg11
-rw-r--r--nomsu_tree.lua239
-rw-r--r--nomsu_tree.moon130
7 files changed, 230 insertions, 314 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 4b7f0bc..0cc3859 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -6,108 +6,116 @@
immediately
lua> ".."
nomsu:define_compile_action("compile %actions to %lua", function(tree, \%actions, \%lua)
- local lua = Lua(tree.source, "nomsu:define_compile_action(");
- local stubs = {};
+ local lua = Lua(tree.source, "nomsu:define_compile_action(")
+ local stubs = {}
for i, action in ipairs(\%actions.value) do
- stubs[i] = action:get_stub(true);
+ stubs[i] = action:get_stub(true)
end
- stubs = repr(stubs);
+ stubs = repr(stubs)
if #stubs > 80 then
- lua:append("\n ",stubs,",\n ");
+ lua:append("\n ",stubs,",\n ")
else
- lua:append(stubs,", ");
+ lua:append(stubs,", ")
end
- lua:append("function(tree");
- local args = {};
+ lua:append("function(tree")
+ local args = {}
for i,tok in ipairs(\%actions.value[1].value) do
- if tok.type == "Var" then args[#args+1] = tok:as_lua(nomsu); end
+ if tok.type == "Var" then args[#args+1] = tok:as_lua(nomsu) end
end
for i, arg in ipairs(args) do
- lua:append(", ");
- lua:append(arg);
+ lua:append(", ", arg)
end
- local body_lua = \%lua:as_lua(nomsu);
- body_lua = body_lua:as_statements("return ");
- body_lua:remove_free_vars(args);
- body_lua:declare_locals();
- lua:append(")\n ", body_lua, "\nend);");
- return lua;
+ local body_lua = \%lua:as_lua(nomsu):as_statements("return ")
+ body_lua:remove_free_vars(args)
+ body_lua:declare_locals()
+ lua:append(")\n ", body_lua, "\nend);")
+ return lua
end);
# Compile-time action to make actions
immediately
compile [action %actions %body] to
lua> ".."
- local lua = Lua(tree.source, "nomsu:define_action(");
- local stubs = {};
+ local lua = Lua(tree.source, "nomsu:define_action(")
+ local stubs = {}
for i, action in ipairs(\%actions.value) do
- stubs[i] = action:get_stub(true);
+ stubs[i] = action:get_stub(true)
end
- stubs = repr(stubs);
+ stubs = repr(stubs)
if #stubs > 80 then
- lua:append("\n ",stubs,",\n ");
+ lua:append("\n ",stubs,",\n ")
else
- lua:append(stubs,", ");
+ lua:append(stubs,", ")
end
- lua:append("function(");
- local args = {};
+ lua:append("function(")
+ local args = {}
for i,tok in ipairs(\%actions.value[1].value) do
- if tok.type == "Var" then args[#args+1] = tok:as_lua(nomsu); end
+ if tok.type == "Var" then args[#args+1] = tok:as_lua(nomsu) end
end
for i, arg in ipairs(args) do
- lua:append(arg);
+ lua:append(arg)
if i < #args then lua:append(", ") end
end
- local body_lua = \%body:as_lua(nomsu);
- body_lua = body_lua:as_statements("return ");
- body_lua:remove_free_vars(args);
- body_lua:declare_locals();
+ local body_lua = \%body:as_lua(nomsu):as_statements("return ")
+ body_lua:remove_free_vars(args)
+ body_lua:declare_locals()
lua:append(")\n ", body_lua, "\nend);")
- return lua;
+ return lua
# Macro to make nomsu macros
immediately
compile [parse %shorthand as %longhand] to
lua> ".."
- local lua = Lua(tree.source, "nomsu:define_compile_action(");
- local stubs = {};
+ local lua = Lua(tree.source, "nomsu:define_compile_action(")
+ local stubs = {}
for i, action in ipairs(\%shorthand.value) do
- stubs[i] = action:get_stub(true);
+ stubs[i] = action:get_stub(true)
end
- stubs = repr(stubs);
+ stubs = repr(stubs)
if #stubs > 80 then
- lua:append("\n ",stubs,",\n ");
+ lua:append("\n ",stubs,",\n ")
else
- lua:append(stubs,", ");
+ lua:append(stubs,", ")
end
- lua:append("function(tree");
- local args = {};
+ lua:append("function(tree")
+ local replacements = {}
for i,tok in ipairs(\%shorthand.value[1].value) do
- if tok.type == "Var" then args[#args+1] = tostring(tok:as_lua(nomsu)); end
+ if tok.type == "Var" then
+ local lua_var = tostring(tok:as_lua(nomsu))
+ replacements[tok.value] = lua_var
+ lua:append(", ", lua_var)
+ end
end
- for i, arg in ipairs(args) do
- lua:append(", ");
- lua:append(arg);
+ local function make_tree(t)
+ if Tuple:is_instance(t) then
+ local bits = {}
+ for i, entry in ipairs(t) do
+ bits[i] = make_tree(entry)
+ end
+ return "Tuple("..table.concat(bits, ", ")..")"
+ elseif type(t) ~= 'table' and type(t) ~= 'userdata' then
+ return repr(t)
+ elseif t.type == "Var" and replacements[t.value] then
+ return replacements[t.value]
+ else
+ return t.type.."("..make_tree(t.value)..")"
+ end
end
- local template = repr(tostring(\%longhand:as_nomsu(true)));
- local replacements = {};
- for i, a in ipairs(args) do replacements[i] = a.."="..a; end
- replacements = "{"..table.concat(replacements, ", ").."}";
lua:append([[)
- local template = nomsu:parse(Nomsu(]]..repr(tree.source)..[[, ]]..template..[[));
- local replacement = nomsu:tree_with_replacements(template, ]]..replacements..[[);
- return replacement:as_lua(nomsu);
- end);]]);
- return lua;
+ local tree = ]], make_tree(\%longhand), [[
+
+ return tree:as_lua(nomsu)
+ end);]])
+ return lua
action [remove action %stub]
lua> ".."
- local fn = ACTIONS[\%stub];
- local stubs = ARG_ORDERS[fn];
+ local fn = ACTIONS[\%stub]
+ local stubs = ARG_ORDERS[fn]
for stub in pairs(stubs) do
- ACTIONS[stub] = nil;
+ ACTIONS[stub] = nil
end
- ARG_ORDERS[fn] = nil;
+ ARG_ORDERS[fn] = nil
immediately
action [%tree as lua]
@@ -115,11 +123,11 @@ immediately
action [%tree as lua expr]
lua> ".."
- local lua = \%tree:as_lua(nomsu);
+ local lua = \%tree:as_lua(nomsu)
if not lua.is_value then
- error("Invalid thing to convert to lua expr: "..\%tree.source:get_text());
+ error("Invalid thing to convert to lua expr: "..\%tree.source:get_text())
end
- return lua;
+ return lua
action [%tree as lua statements]
=lua "\%tree:as_lua(nomsu):as_statements()"
diff --git a/core/operators.nom b/core/operators.nom
index 60fe969..e3b41e1 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -66,7 +66,7 @@ immediately
lua> ".."
local lhs, rhs = Lua(tree.source), Lua(\%assignments.source);
for i, item in ipairs(\%assignments.value) do
- local target, value = item.key, item.value;
+ local target, value = item.value[1], item.value[2];
local target_lua = target:as_lua(nomsu);
if not target_lua.is_value then error("Invalid target for assignment: "..target:get_src()); end
local value_lua = value:as_lua(nomsu);
@@ -102,7 +102,7 @@ immediately
local lhs, rhs = Lua(tree.source), Lua(\%assignments.source);
local vars = {};
for i, item in ipairs(\%assignments.value) do
- local target, value = item.key, item.value;
+ local target, value = item.value[1], item.value[2];
if not target.type == "Var" then
error("Invalid target for 'with' assignment: "..tostring(target.source:get_text()));
end
diff --git a/nomsu.lua b/nomsu.lua
index 0ba3b26..f7b8938 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -149,9 +149,6 @@ do
_with_0.Tuple = function(values)
return Tuple(unpack(values))
end
- _with_0.DictEntry = function(k, v)
- return Types.DictEntry(k, v)
- end
_with_0.nl = P("\r") ^ -1 * P("\n")
_with_0.ws = S(" \t")
_with_0.tonumber = tonumber
@@ -467,24 +464,15 @@ do
if not (Types.is_node(tree)) then
return
end
- local _exp_0 = tree.type
- if "List" == _exp_0 or "Block" == _exp_0 or "Action" == _exp_0 or "Text" == _exp_0 or "IndexChain" == _exp_0 then
+ if Tuple:is_instance(tree.value) then
local _list_0 = tree.value
for _index_0 = 1, #_list_0 do
local v = _list_0[_index_0]
self:walk_tree(v, depth + 1)
end
- elseif "Dict" == _exp_0 then
- local _list_0 = tree.value
- for _index_0 = 1, #_list_0 do
- local e = _list_0[_index_0]
- self:walk_tree(e.key, depth + 1)
- self:walk_tree(e.value, depth + 1)
- end
else
- self:walk_tree(tree.value, depth + 1)
+ return self:walk_tree(v, depth + 1)
end
- return nil
end,
tree_with_replacements = function(self, tree, replacements)
if not (next(replacements)) then
diff --git a/nomsu.moon b/nomsu.moon
index ce0e8d6..db196fc 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -131,7 +131,6 @@ NOMSU_DEFS = with {}
-- Newline supports either windows-style CR+LF or unix-style LF
.Tuple = (values)->
return Tuple(unpack(values))
- .DictEntry = (k,v) -> Types.DictEntry(k,v)
.nl = P("\r")^-1 * P("\n")
.ws = S(" \t")
.tonumber = tonumber
@@ -429,16 +428,11 @@ class NomsuCompiler
walk_tree: (tree, depth=0)=>
coroutine.yield(tree, depth)
return unless Types.is_node(tree)
- switch tree.type
- when "List", "Block", "Action", "Text", "IndexChain"
- for v in *tree.value
- @walk_tree(v, depth+1)
- when "Dict"
- for e in *tree.value
- @walk_tree(e.key, depth+1)
- @walk_tree(e.value, depth+1)
- else @walk_tree(tree.value, depth+1)
- return nil
+ if Tuple\is_instance(tree.value)
+ for v in *tree.value
+ @walk_tree(v, depth+1)
+ else
+ @walk_tree(v, depth+1)
tree_with_replacements: (tree, replacements)=>
return tree unless next(replacements)
diff --git a/nomsu.peg b/nomsu.peg
index 4ebf6c2..e7c8a7f 100644
--- a/nomsu.peg
+++ b/nomsu.peg
@@ -107,7 +107,7 @@ inline_list_item: inline_block / inline_action / inline_expression
inline_dict (Dict):
!('{..}')
- "{" %ws* ({| (inline_dict_item (comma inline_dict_item)*)? |} -> Tuple) %ws*
+ "{" %ws* ({| (inline_dict_entry (comma inline_dict_entry)*)? |} -> Tuple) %ws*
("}"
/ (({} (%ws* comma? (!. / &%nl)->"Failed to find a closing } on the same line")) => error)
/ (({} ([^%nl]*->"Error while parsing dictionary")) => error))
@@ -117,10 +117,11 @@ indented_dict (Dict):
|} -> Tuple)
(dedent / (({} (non_dedent_error -> "Error while parsing dict")) => error))
dict_line:
- ((dict_key %ws* ":" %ws* (action / expression)) -> DictEntry !comma)
- / (inline_dict_item (comma dict_line?)?)
-inline_dict_item:
- ((dict_key %ws* (":" %ws* (inline_block / inline_action / inline_expression)?)?)-> DictEntry)
+ (dict_entry !comma) / (inline_dict_entry (comma dict_line?)?)
+dict_entry(DictEntry):
+ {| dict_key %ws* ":" %ws* (action / expression) |} -> Tuple
+inline_dict_entry(DictEntry):
+ {| dict_key %ws* (":" %ws* (inline_block / inline_action / inline_expression)?) |} -> Tuple
dict_key:
text_word / inline_expression
diff --git a/nomsu_tree.lua b/nomsu_tree.lua
index 1132dac..68475f6 100644
--- a/nomsu_tree.lua
+++ b/nomsu_tree.lua
@@ -14,12 +14,6 @@ do
end
local MAX_LINE = 80
local Types = { }
-Types.DictEntry = immutable({
- "key",
- "value"
-}, {
- name = "DictEntry"
-})
Types.is_node = function(n)
return type(n) == 'userdata' and getmetatable(n) and Types[n.type] == getmetatable(n)
end
@@ -46,6 +40,28 @@ Tree = function(name, methods)
local ret = tostring(self.source:get_text()):gsub("\n" .. ((" "):rep(leading_space)), "\n")
return ret
end
+ methods.map = function(self, fn)
+ do
+ local mapped = fn(self)
+ if mapped then
+ return mapped
+ end
+ end
+ if Tuple:is_instance(self.value) then
+ return self:with_value(Tuple(unpack((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ 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
+ return _accum_0
+ end)())))
+ end
+ return self
+ end
end
Types[name] = immutable({
"value",
@@ -66,9 +82,6 @@ Tree("Nomsu", {
return nomsu and Nomsu(self.source, "\\:\n ", nomsu)
end
return nomsu and Nomsu(self.source, "\\(", nomsu, ")")
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(self.value:map(fn))
end
})
Tree("Block", {
@@ -113,19 +126,6 @@ Tree("Block", {
end
end
return nomsu
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local v = _list_0[_index_0]
- _accum_0[_len_0] = v:map(fn)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)())))
end
})
local math_expression = re.compile([[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]])
@@ -349,19 +349,6 @@ Tree("Action", {
end
return nomsu
end
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local v = _list_0[_index_0]
- _accum_0[_len_0] = v:map(fn)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)())))
end
})
Tree("Text", {
@@ -469,19 +456,6 @@ Tree("Text", {
end
return nomsu
end
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local v = _list_0[_index_0]
- _accum_0[_len_0] = type(v) == 'string' and v or v:map(fn)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)())))
end
})
Tree("List", {
@@ -568,19 +542,6 @@ Tree("List", {
end
return nomsu
end
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local v = _list_0[_index_0]
- _accum_0[_len_0] = v:map(fn)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)())))
end
})
Tree("Dict", {
@@ -588,29 +549,14 @@ Tree("Dict", {
local lua = Lua.Value(self.source, "{")
local line_length = 0
for i, entry in ipairs(self.value) do
- local key_lua = entry.key:as_lua(nomsu)
- if not (key_lua.is_value) then
- local line, src = key.source:get_line(), key.source:get_text()
- error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a dict key, since it's not an expression.", 0)
- end
- local value_lua = entry.value and entry.value:as_lua(nomsu) or Lua.Value(entry.key.source, "true")
- if not (value_lua.is_value) then
- local line, src = value.source:get_line(), value.source:get_text()
- error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " 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
- lua:append(key_str, "=", value_lua)
- elseif tostring(key_lua):sub(1, 1) == "[" then
- lua:append("[ ", key_lua, "]=", value_lua)
- else
- lua:append("[", key_lua, "]=", value_lua)
- end
- local newlines, last_line = ("[" .. tostring(key_lua) .. "=" .. tostring(value_lua)):match("^(.-)([^\n]*)$")
- if #newlines > 0 then
+ local entry_lua = entry:as_lua(nomsu)
+ lua:append(entry_lua)
+ local entry_lua_str = tostring(entry_lua)
+ local last_line = entry_lua_str:match("\n([^\n]*)$")
+ if last_line then
line_length = #last_line
else
- line_length = line_length + #last_line
+ line_length = line_length + #entry_lua_str
end
if i < #self.value then
if line_length >= MAX_LINE then
@@ -632,21 +578,14 @@ Tree("Dict", {
if inline then
local nomsu = Nomsu(self.source, "{")
for i, entry in ipairs(self.value) do
- local key_nomsu = entry.key:as_nomsu(true)
- if not (key_nomsu) then
- return nil
- end
- if entry.key.type == "Action" or entry.key.type == "Block" then
- key_nomsu:parenthesize()
- end
- local value_nomsu = entry.value and entry.value:as_nomsu(true) or Nomsu(entry.key.source, "")
- if not (value_nomsu) then
+ local entry_nomsu = entry:as_nomsu(true)
+ if not (entry_nomsu) then
return nil
end
if i > 1 then
nomsu:append(", ")
end
- nomsu:append(key_nomsu, ":", value_nomsu)
+ nomsu:append(entry_nomsu)
end
nomsu:append("}")
return nomsu
@@ -660,37 +599,21 @@ Tree("Dict", {
local _list_0 = self.value
for _index_0 = 1, #_list_0 do
local entry = _list_0[_index_0]
- local key_nomsu = entry.key:as_nomsu(true)
- if not (key_nomsu) then
+ local entry_nomsu = entry:as_nomsu()
+ if not (entry_nomsu) then
return nil
end
- if entry.key.type == "Action" or entry.key.type == "Block" then
- key_nomsu:parenthesize()
- end
- local value_nomsu = entry.value and entry.value:as_nomsu(true) or Nomsu(entry.key.source, "")
- if value_nomsu and #line + #", " + #key_nomsu + #":" + #value_nomsu <= MAX_LINE then
+ if #line + #tostring(entry_nomsu) <= MAX_LINE then
if #line.bits > 1 then
line:append(", ")
end
- line:append(key_nomsu)
- if entry.value then
- line:append(":", value_nomsu)
- end
+ line:append(entry_nomsu)
else
- if not (value_nomsu) then
- value_nomsu = entry.value:as_nomsu()
- if not (value_nomsu) then
- return nil
- end
- end
if #line.bits > 1 then
nomsu:append(line)
line = Nomsu(bit.source, "\n ")
end
- line:append(key_nomsu)
- if entry.value then
- line:append(":", value_nomsu)
- end
+ line:append(entry_nomsu)
end
end
if #line.bits > 1 then
@@ -698,20 +621,61 @@ Tree("Dict", {
end
return nomsu
end
+ end
+})
+Tree("DictEntry", {
+ as_lua = function(self, nomsu)
+ local key, value = self.value[1], self.value[2]
+ local key_lua = key:as_lua(nomsu)
+ if not (key_lua.is_value) then
+ local line, src = key.source:get_line(), key.source:get_text()
+ error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a dict key, since it's not an expression.", 0)
+ end
+ local value_lua = value and value:as_lua(nomsu) or Lua.Value(key.source, "true")
+ if not (value_lua.is_value) then
+ local line, src = value.source:get_line(), value.source:get_text()
+ error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " 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(key.source, key_str, "=", value_lua)
+ elseif tostring(key_lua):sub(1, 1) == "[" then
+ return Lua(key.source, "[ ", key_lua, "]=", value_lua)
+ else
+ return Lua(key.source, "[", key_lua, "]=", value_lua)
+ end
end,
- map = function(self, fn)
- local DictEntry = Types.DictEntry
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local e = _list_0[_index_0]
- _accum_0[_len_0] = DictEntry(e.key:map(fn), e.value:map(fn))
- _len_0 = _len_0 + 1
+ as_nomsu = function(self, inline)
+ if inline == nil then
+ inline = true
+ end
+ local key, value = self.value[1], self.value[2]
+ local key_nomsu = key:as_nomsu(true)
+ if not (key_nomsu) then
+ return nil
+ end
+ if key.type == "Action" or key.type == "Block" then
+ key_nomsu:parenthesize()
+ end
+ local value_nomsu
+ if value then
+ value_nomsu = value:as_nomsu(true)
+ else
+ value_nomsu = Nomsu(key.source, "")
+ end
+ if inline and not value_nomsu then
+ return nil
+ end
+ if not value_nomsu then
+ if inline then
+ return nil
+ end
+ value_nomsu = value:as_nomsu()
+ if not (value_nomsu) then
+ return nil
end
- return _accum_0
- end)())))
+ end
+ return Nomsu(key.source, key_nomsu, ":", value_nomsu)
end
})
Tree("IndexChain", {
@@ -771,19 +735,6 @@ Tree("IndexChain", {
nomsu:append(bit_nomsu)
end
return nomsu
- end,
- map = function(self, fn)
- return fn(self) or self:with_value(Tuple(unpack((function()
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = self.value
- for _index_0 = 1, #_list_0 do
- local v = _list_0[_index_0]
- _accum_0[_len_0] = v:map(fn)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)())))
end
})
Tree("Number", {
@@ -795,9 +746,6 @@ Tree("Number", {
inline = false
end
return Nomsu(self.source, tostring(self.value))
- end,
- map = function(self, fn)
- return fn(self) or self
end
})
Tree("Var", {
@@ -818,9 +766,6 @@ Tree("Var", {
inline = false
end
return Nomsu(self.source, "%", self.value)
- end,
- map = function(self, fn)
- return fn(self) or self
end
})
Tree("Word", {
@@ -832,9 +777,6 @@ Tree("Word", {
inline = false
end
return Nomsu(self.source, self.value)
- end,
- map = function(self, fn)
- return fn(self) or self
end
})
Tree("Comment", {
@@ -853,9 +795,6 @@ Tree("Comment", {
else
return Nomsu(self.source, "#", self.value)
end
- end,
- map = function(self, fn)
- return fn(self) or self
end
})
return Types
diff --git a/nomsu_tree.moon b/nomsu_tree.moon
index dd3bb28..ae345cc 100644
--- a/nomsu_tree.moon
+++ b/nomsu_tree.moon
@@ -9,7 +9,6 @@ immutable = require 'immutable'
MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
Types = {}
-Types.DictEntry = immutable({"key","value"}, {name:"DictEntry"})
Types.is_node = (n)->
type(n) == 'userdata' and getmetatable(n) and Types[n.type] == getmetatable(n)
@@ -29,6 +28,12 @@ Tree = (name, methods)->
leading_space = 0
ret = tostring(@source\get_text!)\gsub("\n"..((" ")\rep(leading_space)), "\n")
return ret
+ .map = (fn)=>
+ if mapped = fn(self)
+ return mapped
+ if Tuple\is_instance(@value)
+ return @with_value(Tuple(unpack([v.map and v\map(fn) or v for v in *@value])))
+ return self
Types[name] = immutable {"value","source"}, methods
@@ -44,9 +49,6 @@ Tree "Nomsu",
return nomsu and Nomsu(@source, "\\:\n ", nomsu)
return nomsu and Nomsu(@source, "\\(", nomsu, ")")
- map: (fn)=>
- fn(self) or @with_value(@value\map(fn))
-
Tree "Block",
as_lua: (nomsu)=>
lua = Lua(@source)
@@ -77,9 +79,6 @@ Tree "Block",
nomsu\append "\n"
return nomsu
- map: (fn)=>
- fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
-
math_expression = re.compile [[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]
Tree "Action",
as_lua: (nomsu)=>
@@ -203,9 +202,6 @@ Tree "Action",
next_space = "\n.."
return nomsu
- map: (fn)=>
- fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
-
Tree "Text",
as_lua: (nomsu)=>
lua = Lua.Value(@source)
@@ -273,9 +269,6 @@ Tree "Text",
nomsu\append "\n .."
return nomsu
- map: (fn)=>
- fn(self) or @with_value(Tuple(unpack([type(v) == 'string' and v or v\map(fn) for v in *@value])))
-
Tree "List",
as_lua: (nomsu)=>
lua = Lua.Value @source, "{"
@@ -337,39 +330,20 @@ Tree "List",
nomsu\append line
return nomsu
- map: (fn)=>
- fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
-
Tree "Dict",
as_lua: (nomsu)=>
lua = Lua.Value @source, "{"
line_length = 0
for i, entry in ipairs @value
- key_lua = entry.key\as_lua(nomsu)
- unless key_lua.is_value
- line, src = key.source\get_line!, key.source\get_text!
- error "#{line}: Cannot use #{colored.yellow src} as a dict key, since it's not an expression.", 0
- value_lua = entry.value and entry.value\as_lua(nomsu) or Lua.Value(entry.key.source, "true")
- unless value_lua.is_value
- line, src = value.source\get_line!, value.source\get_text!
- error "#{line}: Cannot use #{colored.yellow src} as a dict value, since it's not an expression.", 0
- key_str = tostring(key_lua)\match([=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
- if key_str
- lua\append 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\append "[ ",key_lua,"]=",value_lua
- else
- lua\append "[",key_lua,"]=",value_lua
-
+ entry_lua = entry\as_lua(nomsu)
+ lua\append entry_lua
+ entry_lua_str = tostring(entry_lua)
-- TODO: maybe make this more accurate? It's only a heuristic, so eh...
- newlines, last_line = ("[#{key_lua}=#{value_lua}")\match("^(.-)([^\n]*)$")
- if #newlines > 0
+ last_line = entry_lua_str\match("\n([^\n]*)$")
+ if last_line
line_length = #last_line
else
- line_length += #last_line
+ line_length += #entry_lua_str
if i < #@value
if line_length >= MAX_LINE
lua\append ",\n "
@@ -384,15 +358,11 @@ Tree "Dict",
if inline
nomsu = Nomsu(@source, "{")
for i, entry in ipairs @value
- key_nomsu = entry.key\as_nomsu(true)
- return nil unless key_nomsu
- if entry.key.type == "Action" or entry.key.type == "Block"
- key_nomsu\parenthesize!
- value_nomsu = entry.value and entry.value\as_nomsu(true) or Nomsu(entry.key.source, "")
- return nil unless value_nomsu
+ entry_nomsu = entry\as_nomsu(true)
+ return nil unless entry_nomsu
if i > 1
nomsu\append ", "
- nomsu\append key_nomsu,":",value_nomsu
+ nomsu\append entry_nomsu
nomsu\append "}"
return nomsu
else
@@ -401,32 +371,59 @@ Tree "Dict",
nomsu = Nomsu(@source, "{..}")
line = Nomsu(@source, "\n ")
for entry in *@value
- key_nomsu = entry.key\as_nomsu(true)
- return nil unless key_nomsu
- if entry.key.type == "Action" or entry.key.type == "Block"
- key_nomsu\parenthesize!
- value_nomsu = entry.value and entry.value\as_nomsu(true) or Nomsu(entry.key.source, "")
- if value_nomsu and #line + #", " + #key_nomsu + #":" + #value_nomsu <= MAX_LINE
+ entry_nomsu = entry\as_nomsu!
+ return nil unless entry_nomsu
+ if #line + #tostring(entry_nomsu) <= MAX_LINE
if #line.bits > 1
line\append ", "
- line\append key_nomsu
- if entry.value then line\append ":",value_nomsu
+ line\append entry_nomsu
else
- unless value_nomsu
- value_nomsu = entry.value\as_nomsu!
- return nil unless value_nomsu
if #line.bits > 1
nomsu\append line
line = Nomsu(bit.source, "\n ")
- line\append key_nomsu
- if entry.value then line\append ":",value_nomsu
+ line\append entry_nomsu
if #line.bits > 1
nomsu\append line
return nomsu
- map: (fn)=>
- DictEntry = Types.DictEntry
- fn(self) or @with_value(Tuple(unpack([DictEntry(e.key\map(fn), e.value\map(fn)) for e in *@value])))
+Tree "DictEntry",
+ as_lua: (nomsu)=>
+ key, value = @value[1], @value[2]
+ key_lua = key\as_lua(nomsu)
+ unless key_lua.is_value
+ line, src = key.source\get_line!, key.source\get_text!
+ error "#{line}: Cannot use #{colored.yellow src} as a dict key, since it's not an expression.", 0
+ value_lua = value and value\as_lua(nomsu) or Lua.Value(key.source, "true")
+ unless value_lua.is_value
+ line, src = value.source\get_line!, value.source\get_text!
+ error "#{line}: Cannot use #{colored.yellow src} 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 key.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 key.source, "[ ",key_lua,"]=",value_lua
+ else
+ Lua key.source, "[",key_lua,"]=",value_lua
+
+ as_nomsu: (inline=true)=>
+ key, value = @value[1], @value[2]
+ key_nomsu = key\as_nomsu(true)
+ return nil unless key_nomsu
+ if key.type == "Action" or key.type == "Block"
+ key_nomsu\parenthesize!
+ value_nomsu = if value
+ value\as_nomsu(true)
+ else Nomsu(key.source, "")
+ if inline and not value_nomsu then return nil
+ if not value_nomsu
+ return nil if inline
+ value_nomsu = value\as_nomsu!
+ return nil unless value_nomsu
+ return Nomsu key.source, key_nomsu, ":", value_nomsu
+
Tree "IndexChain",
as_lua: (nomsu)=>
@@ -468,9 +465,6 @@ Tree "IndexChain",
nomsu\append bit_nomsu
return nomsu
- map: (fn)=>
- fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
-
Tree "Number",
as_lua: (nomsu)=>
Lua.Value(@source, tostring(@value))
@@ -478,8 +472,6 @@ Tree "Number",
as_nomsu: (inline=false)=>
return Nomsu(@source, tostring(@value))
- map: (fn)=> fn(self) or self
-
Tree "Var",
as_lua_id: (v)->
"_"..(v\gsub("%W", (c)-> if c == "_" then "__" else ("_%x")\format(c\byte!)))
@@ -490,8 +482,6 @@ Tree "Var",
as_nomsu: (inline=false)=>
return Nomsu(@source, "%", @value)
- map: (fn)=> fn(self) or self
-
Tree "Word",
as_lua: (nomsu)=>
error("Attempt to convert Word to lua")
@@ -499,8 +489,6 @@ Tree "Word",
as_nomsu: (inline=false)=>
return Nomsu(@source, @value)
- map: (fn)=> fn(self) or self
-
Tree "Comment",
as_lua: (nomsu)=>
Lua(@source, "--"..@value\gsub("\n","\n--").."\n")
@@ -512,6 +500,4 @@ Tree "Comment",
else
return Nomsu(@source, "#", @value)
- map: (fn)=> fn(self) or self
-
return Types