diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-05-16 19:08:16 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-05-16 19:08:59 -0700 |
| commit | ad94ed3653e2b7a9f68855670a32617aa80a637c (patch) | |
| tree | bfde4d9e82635aea25336bfda4bf73e819347a93 /nomsu_tree.lua | |
| parent | 6f6c4377b236902566794c3d06820f3fdd7ec28c (diff) | |
Moved all the tree->lua and tree->nomsu code back into single functions
in nomsu.moon, and cleaned up how Vars are treated, since they are not
atomic.
Diffstat (limited to 'nomsu_tree.lua')
| -rw-r--r-- | nomsu_tree.lua | 726 |
1 files changed, 33 insertions, 693 deletions
diff --git a/nomsu_tree.lua b/nomsu_tree.lua index 4d30f38..f4f10b2 100644 --- a/nomsu_tree.lua +++ b/nomsu_tree.lua @@ -19,6 +19,7 @@ Types.is_node = function(n) end local Tree Tree = function(name, kind, methods) + methods = methods or { } assert((kind == 'single') or (kind == 'multi')) local is_multi = (kind == 'multi') do @@ -28,6 +29,21 @@ Tree = function(name, kind, methods) methods.type = name methods.name = name methods.is_multi = is_multi + methods.map = function(self, fn) + if type(fn) == 'table' then + if not (next(fn)) then + return self + end + if type(next(fn)) == 'string' then + error("SHIT") + end + local _replacements = fn + fn = function(k) + return _replacements[k] + end + end + return self:_map(fn) + end if is_multi then methods.__tostring = function(self) return tostring(self.name) .. "(" .. tostring(table.concat((function() @@ -79,191 +95,32 @@ Tree = function(name, kind, methods) }, methods) end end +Tree("Block", 'multi') +Tree("Text", 'multi') +Tree("List", 'multi') +Tree("Dict", 'multi') +Tree("DictEntry", 'multi') +Tree("IndexChain", 'multi') +Tree("Number", 'single') +Tree("Word", 'single') +Tree("Comment", 'single') Tree("EscapedNomsu", 'single', { - as_lua = function(self, nomsu) - local make_tree - make_tree = function(t) - if type(t) ~= 'userdata' then - return repr(t) - end - if t.is_multi then - local bits - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #t do - local bit = t[_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, ", ") .. ")" - else - return t.type .. "(" .. make_tree(t.value) .. ")" - end - end - return Lua.Value(nil, make_tree(self.value)) - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - local nomsu = self.value:as_nomsu(true) - if nomsu == nil and not inline then - nomsu = self.value:as_nomsu() - return nomsu and Nomsu(nil, "\\:\n ", nomsu) - end - return nomsu and Nomsu(nil, "\\(", nomsu, ")") - end, map = function(self, fn) return fn(self) or self:map(fn) end }) -Tree("Block", 'multi', { - as_lua = function(self, nomsu) - local lua = Lua() - for i, line in ipairs(self) do - local line_lua = line:as_lua(nomsu) - if i > 1 then - lua:append("\n") - end - lua:append(line_lua:as_statements()) - end - return lua - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - if inline then - local nomsu = Nomsu() - for i, line in ipairs(self) do - if i > 1 then - nomsu:append("; ") - end - local line_nomsu = line:as_nomsu(true) - if not (line_nomsu) then - return nil - end - nomsu:append(line_nomsu) - end - return nomsu - end - local nomsu = Nomsu() - for i, line in ipairs(self) do - line = assert(line:as_nomsu(nil, true), "Could not convert line to nomsu") - nomsu:append(line) - if i < #self then - nomsu:append("\n") - if tostring(line):match("\n") then - nomsu:append("\n") - end +Tree("Var", 'single', { + as_lua_id = function(self) + return "_" .. (self.value:gsub("%W", function(c) + if c == "_" then + return "__" + else + return ("_%x"):format(c:byte()) end - end - return nomsu + end)) end }) -local math_expression = re.compile([[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]) Tree("Action", 'multi', { - as_lua = function(self, nomsu) - local stub = self:get_stub() - local compile_action = nomsu.environment.COMPILE_ACTIONS[stub] - if compile_action then - local args - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #self do - local arg = self[_index_0] - if arg.type ~= "Word" then - _accum_0[_len_0] = arg - _len_0 = _len_0 + 1 - end - end - args = _accum_0 - end - do - local _accum_0 = { } - local _len_0 = 1 - local _list_0 = nomsu.environment.ARG_ORDERS[compile_action][stub] - for _index_0 = 1, #_list_0 do - local p = _list_0[_index_0] - _accum_0[_len_0] = args[p - 1] - _len_0 = _len_0 + 1 - end - args = _accum_0 - end - local ret = compile_action(self, unpack(args)) - if not ret then - error("Failed to produce any Lua") - end - return ret - end - local action = rawget(nomsu.environment.ACTIONS, stub) - local lua = Lua.Value() - if not action and math_expression:match(stub) then - for i, tok in ipairs(self) do - if tok.type == "Word" then - lua:append(tok.value) - else - local tok_lua = tok:as_lua(nomsu) - if not (tok_lua.is_value) then - error("non-expression value inside math expression: " .. tostring(colored.yellow(repr(tok)))) - end - if tok.type == "Action" then - tok_lua:parenthesize() - end - lua:append(tok_lua) - end - if i < #self then - lua:append(" ") - end - end - return lua - end - local args = { } - for i, tok in ipairs(self) do - local _continue_0 = false - repeat - if tok.type == "Word" then - _continue_0 = true - break - end - local arg_lua = tok:as_lua(nomsu) - 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 - insert(args, arg_lua) - _continue_0 = true - until true - if not _continue_0 then - break - end - end - if action then - do - local _accum_0 = { } - local _len_0 = 1 - local _list_0 = nomsu.environment.ARG_ORDERS[action][stub] - for _index_0 = 1, #_list_0 do - local p = _list_0[_index_0] - _accum_0[_len_0] = args[p] - _len_0 = _len_0 + 1 - end - args = _accum_0 - end - end - lua:append("ACTIONS[", repr(stub), "](") - for i, arg in ipairs(args) do - lua:append(arg) - if i < #args then - lua:append(", ") - end - end - lua:append(")") - return lua - end, get_stub = function(self, include_names) if include_names == nil then include_names = false @@ -293,523 +150,6 @@ Tree("Action", 'multi', { end end return concat(bits, " ") - end, - as_nomsu = function(self, inline, can_use_colon) - if inline == nil then - inline = false - end - if can_use_colon == nil then - can_use_colon = false - end - if inline then - local nomsu = Nomsu() - for i, bit in ipairs(self) do - if bit.type == "Word" then - if i > 1 then - nomsu:append(" ") - end - nomsu:append(bit.value) - else - local arg_nomsu = bit:as_nomsu(true) - if not (arg_nomsu) then - return nil - end - if not (i == 1) then - nomsu:append(" ") - end - if bit.type == "Action" or bit.type == "Block" then - arg_nomsu:parenthesize() - end - nomsu:append(arg_nomsu) - end - end - return nomsu - else - local nomsu = Nomsu() - local next_space = "" - local last_colon = nil - for i, bit in ipairs(self) do - if bit.type == "Word" then - nomsu:append(next_space, bit.value) - next_space = " " - else - local arg_nomsu - if last_colon == i - 1 and bit.type == "Action" then - arg_nomsu = nil - elseif bit.type == "Block" then - arg_nomsu = nil - else - arg_nomsu = bit:as_nomsu(true) - end - if arg_nomsu and #arg_nomsu < MAX_LINE then - if bit.type == "Action" then - if can_use_colon and i > 1 then - nomsu:append(next_space:match("[^ ]*"), ": ", arg_nomsu) - next_space = "\n.." - last_colon = i - else - nomsu:append(next_space, "(", arg_nomsu, ")") - next_space = " " - end - else - nomsu:append(next_space, arg_nomsu) - next_space = " " - end - else - arg_nomsu = bit:as_nomsu(nil, true) - if not (nomsu) then - return nil - 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) - else - arg_nomsu = Nomsu(nil, "\n ", arg_nomsu) - end - end - if last_colon == i - 1 and (bit.type == "Action" or bit.type == "Block") then - next_space = "" - end - nomsu:append(next_space, arg_nomsu) - next_space = "\n.." - end - if next_space == " " and #(tostring(nomsu):match("[^\n]*$")) > MAX_LINE then - next_space = "\n.." - end - end - end - return nomsu - end - end -}) -Tree("Text", 'multi', { - as_lua = function(self, nomsu) - local lua = Lua.Value() - local string_buffer = "" - for _index_0 = 1, #self do - local _continue_0 = false - repeat - local bit = self[_index_0] - if type(bit) == "string" then - string_buffer = string_buffer .. bit - _continue_0 = true - break - end - if string_buffer ~= "" then - if #lua.bits > 0 then - lua:append("..") - end - lua:append(repr(string_buffer)) - string_buffer = "" - end - local bit_lua = bit:as_lua(nomsu) - 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 - if #lua.bits > 0 then - lua:append("..") - end - if bit.type ~= "Text" then - bit_lua = Lua.Value(nil, "stringify(", bit_lua, ")") - end - lua:append(bit_lua) - _continue_0 = true - until true - if not _continue_0 then - break - end - end - if string_buffer ~= "" or #lua.bits == 0 then - if #lua.bits > 0 then - lua:append("..") - end - lua:append(repr(string_buffer)) - end - if #lua.bits > 1 then - lua:parenthesize() - end - return lua - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - if inline then - local nomsu = Nomsu(nil, '"') - for _index_0 = 1, #self do - local bit = self[_index_0] - if type(bit) == 'string' then - nomsu:append((bit:gsub("\\", "\\\\"):gsub("\n", "\\n"))) - else - local interp_nomsu = bit:as_nomsu(true) - if interp_nomsu then - if bit.type ~= "Word" and bit.type ~= "List" and bit.type ~= "Dict" and bit.type ~= "Text" then - interp_nomsu:parenthesize() - end - nomsu:append("\\", interp_nomsu) - else - return nil - end - end - end - nomsu:append('"') - return nomsu - else - local inline_version = self:as_nomsu(true) - if inline_version and #inline_version <= MAX_LINE then - return inline_version - end - local nomsu = Nomsu(nil, '".."\n ') - for i, bit in ipairs(self) do - if type(bit) == 'string' then - nomsu:append((bit:gsub("\\", "\\\\"):gsub("\n", "\n "))) - else - local interp_nomsu = bit:as_nomsu(true) - if interp_nomsu then - if bit.type ~= "Word" and bit.type ~= "List" and bit.type ~= "Dict" and bit.type ~= "Text" then - interp_nomsu:parenthesize() - end - nomsu:append("\\", interp_nomsu) - else - interp_nomsu = bit:as_nomsu() - if not (interp_nomsu) then - return nil - end - nomsu:append("\\\n ", interp_nomsu) - if i < #self then - nomsu:append("\n ..") - end - end - end - end - return nomsu - end - end -}) -Tree("List", 'multi', { - as_lua = function(self, nomsu) - local lua = Lua.Value(nil, "{") - local line_length = 0 - for i, item in ipairs(self) do - local item_lua = item:as_lua(nomsu) - 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 - lua:append(item_lua) - local item_string = tostring(item_lua) - local last_line = item_string:match("[^\n]*$") - if item_string:match("\n") then - line_length = #last_line - else - line_length = line_length + #last_line - end - if i < #self then - if line_length >= MAX_LINE then - lua:append(",\n ") - line_length = 0 - else - lua:append(", ") - line_length = line_length + 2 - end - end - end - lua:append("}") - return lua - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - if inline then - local nomsu = Nomsu(nil, "[") - for i, item in ipairs(self) do - local item_nomsu = item:as_nomsu(true) - if not (item_nomsu) then - return nil - end - if i > 1 then - nomsu:append(", ") - end - nomsu:append(item_nomsu) - end - nomsu:append("]") - return nomsu - else - local inline_version = self:as_nomsu(true) - 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, #self do - local item = self[_index_0] - local item_nomsu = item:as_nomsu(true) - if item_nomsu and #line + #", " + #item_nomsu <= MAX_LINE then - if #line.bits > 1 then - line:append(", ") - end - line:append(item_nomsu) - else - if not (item_nomsu) then - item_nomsu = item:as_nomsu() - if not (item_nomsu) then - return nil - end - end - if #line.bits > 1 then - nomsu:append(line) - line = Nomsu(nil, "\n ") - end - line:append(item_nomsu) - end - end - if #line.bits > 1 then - nomsu:append(line) - end - return nomsu - end - end -}) -Tree("Dict", 'multi', { - as_lua = function(self, nomsu) - local lua = Lua.Value(nil, "{") - local line_length = 0 - for i, entry in ipairs(self) do - 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 + #entry_lua_str - end - if i < #self then - if line_length >= MAX_LINE then - lua:append(",\n ") - line_length = 0 - else - lua:append(", ") - line_length = line_length + 2 - end - end - end - lua:append("}") - return lua - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - if inline then - local nomsu = Nomsu(nil, "{") - for i, entry in ipairs(self) do - local entry_nomsu = entry:as_nomsu(true) - if not (entry_nomsu) then - return nil - end - if i > 1 then - nomsu:append(", ") - end - nomsu:append(entry_nomsu) - end - nomsu:append("}") - return nomsu - else - local inline_version = self:as_nomsu(true) - if inline_version then - return inline_version - end - local nomsu = Nomsu(nil, "{..}") - local line = Nomsu(nil, "\n ") - for _index_0 = 1, #self do - local entry = self[_index_0] - local entry_nomsu = entry:as_nomsu() - if not (entry_nomsu) then - return nil - end - if #line + #tostring(entry_nomsu) <= MAX_LINE then - if #line.bits > 1 then - line:append(", ") - end - line:append(entry_nomsu) - else - if #line.bits > 1 then - nomsu:append(line) - line = Nomsu(nil, "\n ") - end - line:append(entry_nomsu) - end - end - if #line.bits > 1 then - nomsu:append(line) - end - return nomsu - end - end -}) -Tree("DictEntry", 'multi', { - as_lua = function(self, nomsu) - local key, value = self[1], self[2] - local key_lua = key:as_lua(nomsu) - 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 value:as_lua(nomsu) or Lua.Value(nil, "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) - elseif tostring(key_lua):sub(1, 1) == "[" then - return Lua(nil, "[ ", key_lua, "]=", value_lua) - else - return Lua(nil, "[", key_lua, "]=", value_lua) - end - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = true - end - local key, value = self[1], self[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(nil, "") - 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 - end - return Nomsu(nil, key_nomsu, ":", value_nomsu) - end -}) -Tree("IndexChain", 'multi', { - as_lua = function(self, nomsu) - local lua = self[1]:as_lua(nomsu) - if not (lua.is_value) then - error("Cannot index " .. tostring(colored.yellow(repr(self[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, #self do - local key = self[i] - local key_lua = key:as_lua(nomsu) - 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 - local key_lua_str = tostring(key_lua) - do - local lua_id = key_lua_str:match("^['\"]([a-zA-Z_][a-zA-Z0-9_]*)['\"]$") - if lua_id then - lua:append("." .. tostring(lua_id)) - elseif key_lua_str:sub(1, 1) == '[' then - lua:append("[ ", key_lua, " ]") - else - lua:append("[", key_lua, "]") - end - end - end - return lua - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - local nomsu = Nomsu() - for i, bit in ipairs(self) do - if i > 1 then - nomsu:append(".") - end - local bit_nomsu = bit:as_nomsu(true) - if not (bit_nomsu) then - return nil - end - if bit.type == "Action" or bit.type == "Block" then - bit_nomsu:parenthesize() - end - nomsu:append(bit_nomsu) - end - return nomsu - end -}) -Tree("Number", 'single', { - as_lua = function(self, nomsu) - return Lua.Value(nil, tostring(self.value)) - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - return Nomsu(nil, tostring(self.value)) - end -}) -Tree("Var", 'single', { - as_lua_id = function(v) - return "_" .. (v:gsub("%W", function(c) - if c == "_" then - return "__" - else - return ("_%x"):format(c:byte()) - end - end)) - end, - as_lua = function(self, nomsu) - return Lua.Value(nil, self.as_lua_id(self.value)) - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - return Nomsu(nil, "%", self.value) - end -}) -Tree("Word", 'single', { - as_lua = function(self, nomsu) - return error("Attempt to convert Word to lua") - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - return Nomsu(nil, self.value) - end -}) -Tree("Comment", 'single', { - as_lua = function(self, nomsu) - return Lua(nil, "--" .. self.value:gsub("\n", "\n--") .. "\n") - end, - as_nomsu = function(self, inline) - if inline == nil then - inline = false - end - if inline then - return nil - end - if self.value:match("\n") then - return Nomsu(nil, "#..", self.value:gsub("\n", "\n ")) - else - return Nomsu(nil, "#", self.value) - end end }) return Types |
