From 79d4bd5125de7ff220fbf8a8a5493d437ed16963 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 18 Sep 2018 19:48:58 -0700 Subject: [PATCH] Got rid of repr() use and replaced with :as_lua() or :as_nomsu() in as many places as possible. --- code_obj.lua | 20 ++++----- code_obj.moon | 15 ++++--- containers.lua | 90 ++++++++++++++++++++++++++++++++++++++-- containers.moon | 30 ++++++++++++-- core/collections.nom | 2 + core/metaprogramming.nom | 24 ++++++----- lib/object.nom | 10 ++++- nomsu.lua | 8 ++-- nomsu.moon | 6 ++- nomsu_compiler.lua | 39 ++++++++++------- nomsu_compiler.moon | 37 ++++++++++------- parser.lua | 2 - parser.moon | 1 - string2.lua | 18 ++++++++ string2.moon | 14 +++++++ syntax_tree.lua | 58 +++++++++++++++++++++++--- syntax_tree.moon | 23 ++++++++-- 17 files changed, 312 insertions(+), 85 deletions(-) diff --git a/code_obj.lua b/code_obj.lua index d51d63f..5be92e6 100644 --- a/code_obj.lua +++ b/code_obj.lua @@ -3,8 +3,6 @@ do local _obj_0 = table insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat end -local repr -repr = require('utils').repr local unpack = unpack or table.unpack local LuaCode, NomsuCode, Source do @@ -13,8 +11,8 @@ do __tostring = function(self) return "@" .. tostring(self.filename) .. "[" .. tostring(self.start) .. tostring(self.stop and ':' .. self.stop or '') .. "]" end, - __repr = function(self) - return "Source(" .. tostring(repr(self.filename)) .. ", " .. tostring(self.start) .. tostring(self.stop and ', ' .. self.stop or '') .. ")" + as_lua = function(self) + return "Source(" .. tostring(self.filename:as_lua()) .. ", " .. tostring(self.start) .. tostring(self.stop and ', ' .. self.stop or '') .. ")" end, __eq = function(self, other) return getmetatable(self) == getmetatable(other) and self.filename == other.filename and self.start == other.start and self.stop == other.stop @@ -108,16 +106,16 @@ do end return self.__str end, - __repr = function(self) + as_lua = function(self) return tostring(self.__class.__name) .. "(" .. tostring(concat({ - repr(tostring(self.source)), + tostring(self.source):as_lua(), unpack((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = self.bits for _index_0 = 1, #_list_0 do local b = _list_0[_index_0] - _accum_0[_len_0] = repr(b) + _accum_0[_len_0] = b:as_lua() _len_0 = _len_0 + 1 end return _accum_0 @@ -158,7 +156,7 @@ do b.dirty = error end if type(b) ~= 'string' and not (type(b) == 'table' and b.is_code) then - b = repr(b) + b = b:as_lua() end bits[#bits + 1] = b _continue_0 = true @@ -236,7 +234,7 @@ do b.dirty = error end if type(b) ~= 'string' and not (type(b) == 'table' and b.is_code) then - b = repr(b) + b = b:as_lua() end bits[i] = b end @@ -276,7 +274,7 @@ do local _parent_0 = Code local _base_0 = { __tostring = Code.__tostring, - __repr = Code.__repr, + as_lua = Code.as_lua, __len = Code.__len, add_free_vars = function(self, vars) if not (#vars > 0) then @@ -469,7 +467,7 @@ do local _parent_0 = Code local _base_0 = { __tostring = Code.__tostring, - __repr = Code.__repr, + as_lua = Code.as_lua, __len = Code.__len } _base_0.__index = _base_0 diff --git a/code_obj.moon b/code_obj.moon index bd53c5b..4e70784 100644 --- a/code_obj.moon +++ b/code_obj.moon @@ -2,7 +2,6 @@ -- build up generated code, while keeping track of where it came from, and managing -- indentation levels. {:insert, :remove, :concat} = table -{:repr} = require 'utils' unpack or= table.unpack local LuaCode, NomsuCode, Source @@ -19,7 +18,7 @@ class Source __tostring: => "@#{@filename}[#{@start}#{@stop and ':'..@stop or ''}]" - __repr: => "Source(#{repr @filename}, #{@start}#{@stop and ', '..@stop or ''})" + as_lua: => "Source(#{@filename\as_lua!}, #{@start}#{@stop and ', '..@stop or ''})" __eq: (other)=> getmetatable(@) == getmetatable(other) and @filename == other.filename and @start == other.start and @stop == other.stop @@ -67,8 +66,8 @@ class Code @__str = concat(buff, "") return @__str - __repr: => - "#{@__class.__name}(#{concat {repr(tostring(@source)), unpack([repr(b) for b in *@bits])}, ", "})" + as_lua: => + "#{@__class.__name}(#{concat {tostring(@source)\as_lua!, unpack([b\as_lua! for b in *@bits])}, ", "})" __len: => #tostring(@) @@ -93,7 +92,7 @@ class Code if b == '' then continue b.dirty = error if b.is_code if type(b) != 'string' and not (type(b) == 'table' and b.is_code) - b = repr(b) + b = b\as_lua! bits[#bits+1] = b @dirty! @@ -148,7 +147,7 @@ class Code b = select(i, ...) b.dirty = error if b.is_code if type(b) != 'string' and not (type(b) == 'table' and b.is_code) - b = repr(b) + b = b\as_lua! bits[i] = b @dirty! @@ -158,7 +157,7 @@ class Code class LuaCode extends Code __tostring: Code.__tostring - __repr: Code.__repr + as_lua: Code.as_lua __len: Code.__len new: (...)=> super ... @@ -253,7 +252,7 @@ class LuaCode extends Code class NomsuCode extends Code __tostring: Code.__tostring - __repr: Code.__repr + as_lua: Code.as_lua __len: Code.__len Code.__base.append_1 = assert Code.__base.append diff --git a/containers.lua b/containers.lua index 1b3fd94..a7819ec 100644 --- a/containers.lua +++ b/containers.lua @@ -3,14 +3,50 @@ do local _obj_0 = table insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat end -local repr, stringify, equivalent, nth_to_last, size +local equivalent, nth_to_last, size do local _obj_0 = require('utils') - repr, stringify, equivalent, nth_to_last, size = _obj_0.repr, _obj_0.stringify, _obj_0.equivalent, _obj_0.nth_to_last, _obj_0.size + equivalent, nth_to_last, size = _obj_0.equivalent, _obj_0.nth_to_last, _obj_0.size end local lpeg = require('lpeg') local re = require('re') local List, Dict +local as_nomsu +as_nomsu = function(self) + if type(self) == 'number' then + return tostring(self) + end + do + local mt = getmetatable(self) + if mt then + do + local _as_nomsu = mt.as_nomsu + if _as_nomsu then + return _as_nomsu(self) + end + end + end + end + return error("Not supported: " .. tostring(self)) +end +local as_lua +as_lua = function(self) + if type(self) == 'number' then + return tostring(self) + end + do + local mt = getmetatable(self) + if mt then + do + local _as_lua = mt.as_lua + if _as_lua then + return _as_lua(self) + end + end + end + end + return error("Not supported: " .. tostring(self)) +end local _list_mt = { __eq = equivalent, __tostring = function(self) @@ -19,12 +55,36 @@ local _list_mt = { local _len_0 = 1 for _index_0 = 1, #self do local b = self[_index_0] - _accum_0[_len_0] = repr(b) + _accum_0[_len_0] = tostring(b) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") .. "]" end, + as_nomsu = function(self) + return "[" .. concat((function() + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #self do + local b = self[_index_0] + _accum_0[_len_0] = as_nomsu(b) + _len_0 = _len_0 + 1 + end + return _accum_0 + end)(), ", ") .. "]" + end, + as_lua = function(self) + return "_List{" .. concat((function() + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #self do + local b = self[_index_0] + _accum_0[_len_0] = as_lua(b) + _len_0 = _len_0 + 1 + end + return _accum_0 + end)(), ", ") .. "}" + end, __lt = function(self, other) assert(type(self) == 'table' and type(other) == 'table', "Incompatible types for comparison") for i = 1, math.max(#self, #other) do @@ -162,7 +222,29 @@ local _dict_mt = { local _accum_0 = { } local _len_0 = 1 for k, v in pairs(self) do - _accum_0[_len_0] = tostring(repr(k)) .. ": " .. tostring(repr(v)) + _accum_0[_len_0] = tostring(tostring(k)) .. ": " .. tostring(tostring(v)) + _len_0 = _len_0 + 1 + end + return _accum_0 + end)(), ", ") .. "}" + end, + as_nomsu = function(self) + return "{" .. concat((function() + local _accum_0 = { } + local _len_0 = 1 + for k, v in pairs(self) do + _accum_0[_len_0] = tostring(as_nomsu(k)) .. ": " .. tostring(as_nomsu(v)) + _len_0 = _len_0 + 1 + end + return _accum_0 + end)(), ", ") .. "}" + end, + as_lua = function(self) + return "_Dict{" .. concat((function() + local _accum_0 = { } + local _len_0 = 1 + for k, v in pairs(self) do + _accum_0[_len_0] = "[ " .. tostring(as_lua(k)) .. "]= " .. tostring(as_lua(v)) _len_0 = _len_0 + 1 end return _accum_0 diff --git a/containers.moon b/containers.moon index eaf007a..70a9f70 100644 --- a/containers.moon +++ b/containers.moon @@ -1,19 +1,39 @@ -- This file contains container classes, i.e. Lists, Dicts, and Sets {:insert,:remove,:concat} = table -{:repr, :stringify, :equivalent, :nth_to_last, :size} = require 'utils' +{:equivalent, :nth_to_last, :size} = require 'utils' lpeg = require 'lpeg' re = require 're' local List, Dict +as_nomsu = => + if type(@) == 'number' + return tostring(@) + if mt = getmetatable(@) + if _as_nomsu = mt.as_nomsu + return _as_nomsu(@) + error("Not supported: #{@}") + +as_lua = => + if type(@) == 'number' + return tostring(@) + if mt = getmetatable(@) + if _as_lua = mt.as_lua + return _as_lua(@) + error("Not supported: #{@}") + -- List and Dict classes to provide basic equality/tostring functionality for the tables -- used in Nomsu. This way, they retain a notion of whether they were originally lists or dicts. _list_mt = __eq:equivalent -- Could consider adding a __newindex to enforce list-ness, but would hurt performance __tostring: => - "["..concat([repr(b) for b in *@], ", ").."]" + "["..concat([tostring(b) for b in *@], ", ").."]" + as_nomsu: => + "["..concat([as_nomsu(b) for b in *@], ", ").."]" + as_lua: => + "_List{"..concat([as_lua(b) for b in *@], ", ").."}" __lt: (other)=> assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison" for i=1,math.max(#@, #other) @@ -74,7 +94,11 @@ _dict_mt = __eq:equivalent __len:size __tostring: => - "{"..concat(["#{repr(k)}: #{repr(v)}" for k,v in pairs @], ", ").."}" + "{"..concat(["#{tostring(k)}: #{tostring(v)}" for k,v in pairs @], ", ").."}" + as_nomsu: => + "{"..concat(["#{as_nomsu(k)}: #{as_nomsu(v)}" for k,v in pairs @], ", ").."}" + as_lua: => + "_Dict{"..concat(["[ #{as_lua(k)}]= #{as_lua(v)}" for k,v in pairs @], ", ").."}" __ipairs: => walk_items, {table:@, key:nil}, 0 __band: (other)=> Dict{k,v for k,v in pairs(@) when other[k] != nil} diff --git a/core/collections.nom b/core/collections.nom index 8dbc79d..3877d31 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -149,6 +149,8 @@ test: assume ("\%t" == "XXX") compile [set %dict 's metatable to %metatable] to (..) Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));" +compile [%'s metatable, %' metatable] to (..) + Lua value "getmetatable(\(% as lua expr))" test: assume (({} with fallback % -> (% + 1)).10 == 11) diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index c50f783..51831ec 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -34,7 +34,7 @@ lua> "\ lua> "\ ..COMPILE_ACTIONS["compile as 1"] = function(nomsu, tree, \%action) - local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", repr(\%action.stub), "](") + local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", \%action.stub:as_lua(), "](") local lua_args = table.map(\%action:get_args(), function(a) return nomsu:compile(a) end) table.insert(lua_args, 1, "nomsu") table.insert(lua_args, 2, "tree") @@ -66,19 +66,19 @@ lua> "\ ..COMPILE_ACTIONS["compile 1 to 2"] = function(nomsu, tree, \%actions, \%body) local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(\ ..a)) end))} - local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", repr(\%actions[1].stub), + local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "] = ", \(compile as (%args -> %body))) for i=2,#\%actions do local alias = \%actions[i] local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return tostring(nomsu:compile(\ ..a)) end))} - lua:append("\\nCOMPILE_ACTIONS[", repr(alias.stub), "] = ") + lua:append("\\nCOMPILE_ACTIONS[", alias.stub:as_lua(), "] = ") if utils.equivalent(\%args, \%alias_args) then - lua:append("COMPILE_ACTIONS[", repr(\%actions[1].stub), "]") + lua:append("COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "]") else lua:append("function(") lua:concat_append(\%alias_args, ", ") - lua:append(")\\n return COMPILE_ACTIONS[", repr(\%actions[1].stub), "](") + lua:append(")\\n return COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "](") lua:concat_append(\%args, ", ") lua:append(")\\nend") end @@ -173,7 +173,7 @@ compile [parse %actions as %body] to (..) if replacements[t[1]] then return replacements[t[1]] else - return t.type.."{mangle("..repr(t[1]).."), source="..repr(tostring(t.source)).."}" + return t.type.."{mangle("..t[1]:as_lua().."), source="..tostring(t.source):as_lua().."}" end elseif AST.is_syntax_tree(t) then local ret = {} @@ -183,7 +183,7 @@ compile [parse %actions as %body] to (..) ret[#ret+1] = make_tree(t[i]) i = i + 1 elseif k == "source" then - ret[#ret+1] = k.."= "..repr(tostring(v)) + ret[#ret+1] = k.."= "..tostring(v):as_lua() elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then ret[#ret+1] = k.."= "..make_tree(v) else @@ -191,8 +191,10 @@ compile [parse %actions as %body] to (..) end end return t.type.."{"..table.concat(ret, ", ").."}" + elseif type(t) == 'number' then + return tostring(t) else - return repr(t) + return t:as_lua() end end local \%new_body = LuaCode(\%body.source, @@ -257,7 +259,7 @@ action [%tree with vars %replacements] (..) compile [tree %tree with vars %replacements] to (..) Lua value "\ - ..\(=lua "repr(\%tree)"):map(function(t) + ..\(=lua "(\%tree):as_lua()"):map(function(t) if t.type == "Var" then return \(%replacements as lua expr)[t[1]] end @@ -312,7 +314,7 @@ test: ..one "two"" ..== "\"one\\n\\\"two\\\"\"" -compile [quote %s] to (Lua value "repr(\(%s as lua expr))") +compile [quote %s] to (Lua value "tostring(\(%s as lua expr)):as_lua()") test: assume ((type of {}) == "table") or barf "type of failed." @@ -340,7 +342,7 @@ test: compile [run %nomsu_code] to (..) Lua value "\ ..nomsu:run(NomsuCode(\(..) - =lua "repr(tostring(\(%nomsu_code.source)))" + =lua "tostring(\(%nomsu_code.source)):as_lua()" .., \(%nomsu_code as lua expr)))" test: diff --git a/lib/object.nom b/lib/object.nom index b49b8f2..600ecf6 100644 --- a/lib/object.nom +++ b/lib/object.nom @@ -46,7 +46,7 @@ compile [my action %actions %body] to: lua> "\ ..local fn_name = \%actions[1].stub:as_lua_id() local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end) - table.insert(\%args, \(\%me as lua id)) + table.insert(\%args, 1, \(\%me as lua id)) local lua = LuaCode(tree.source, "class.", fn_name, " = ", \(..) compile as (%args -> %body) ..) @@ -54,7 +54,7 @@ compile [my action %actions %body] to: local alias = \%actions[i] local alias_name = alias.stub:as_lua_id() local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end) - table.insert(\%alias_args, \(\%me as lua id)) + table.insert(\%alias_args, 1, \(\%me as lua id)) lua:append("\\nclass.", alias_name, " = ") if utils.equivalent(\%args, \%alias_args) then lua:append("class.", fn_name) @@ -110,3 +110,9 @@ compile [object %classname extends %parent %class_body] to: parse [object %classname %class_body] as (..) object %classname extends (nil) %class_body + +parse [%obj is a %class] as (..) + all of [..] + (type of %obj) == "table" + %obj's metatable + (%obj's metatable).__index == %class diff --git a/nomsu.lua b/nomsu.lua index 3d78dd1..fa6a6ce 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -91,8 +91,6 @@ do local _obj_0 = require("code_obj") NomsuCode, LuaCode, Source = _obj_0.NomsuCode, _obj_0.LuaCode, _obj_0.Source end -local repr -repr = require("utils").repr if not arg or debug.getinfo(2).func == require then return NomsuCompiler end @@ -324,7 +322,11 @@ say "\ local ret ok, ret = xpcall(nomsu.run, err_hand, nomsu, buff, Source(pseudo_filename, 1, #buff)) if ok and ret ~= nil then - print("= " .. repr(ret)) + if type(ret) == 'number' then + print("= " .. tostring(ret)) + else + print("= " .. tostring(ret:as_nomsu())) + end elseif not ok then Errhand.print_error(ret) end diff --git a/nomsu.moon b/nomsu.moon index 382a5b5..1ab9637 100755 --- a/nomsu.moon +++ b/nomsu.moon @@ -48,7 +48,6 @@ Files = require "files" Errhand = require "error_handling" NomsuCompiler = require "nomsu_compiler" {:NomsuCode, :LuaCode, :Source} = require "code_obj" -{:repr} = require "utils" -- If this file was reached via require(), then just return the Nomsu compiler if not arg or debug.getinfo(2).func == require @@ -222,7 +221,10 @@ say "\ Errhand.print_error error_message ok, ret = xpcall(nomsu.run, err_hand, nomsu, buff, Source(pseudo_filename, 1, #buff)) if ok and ret != nil - print "= "..repr(ret) + if type(ret) == 'number' + print "= #{ret}" + else + print "= #{ret\as_nomsu!}" elseif not ok Errhand.print_error ret diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua index 2e286b7..89d247a 100644 --- a/nomsu_compiler.lua +++ b/nomsu_compiler.lua @@ -4,8 +4,8 @@ R, P, S = lpeg.R, lpeg.P, lpeg.S local re = require('re') local utils = require('utils') local Files = require('files') -local repr, stringify, equivalent -repr, stringify, equivalent = utils.repr, utils.stringify, utils.equivalent +local stringify, equivalent +stringify, equivalent = utils.stringify, utils.equivalent local List, Dict, Text do local _obj_0 = require('containers') @@ -193,7 +193,6 @@ do ipairs = ipairs, _List = List, _Dict = Dict, - repr = repr, stringify = stringify, utils = utils, lpeg = lpeg, @@ -385,7 +384,7 @@ do add_lua_string_bits = function(self, val_or_stmt, code) local cls_str = val_or_stmt == "value" and "LuaCode.Value(" or "LuaCode(" if code.type ~= "Text" then - return LuaCode.Value(code.source, cls_str, repr(tostring(code.source)), ", ", self:compile(code), ")") + return LuaCode.Value(code.source, cls_str, tostring(code.source):as_lua(), ", ", self:compile(code), ")") end local add_bit_lua add_bit_lua = function(lua, bit_lua) @@ -395,11 +394,11 @@ do end local operate_on_text operate_on_text = function(text) - local lua = LuaCode.Value(text.source, cls_str, repr(tostring(text.source))) + local lua = LuaCode.Value(text.source, cls_str, tostring(text.source):as_lua()) for _index_0 = 1, #text do local bit = text[_index_0] if type(bit) == "string" then - add_bit_lua(lua, repr(bit)) + add_bit_lua(lua, bit:as_lua()) elseif bit.type == "Text" then add_bit_lua(lua, operate_on_text(bit)) else @@ -480,13 +479,13 @@ do end return _accum_0 end)(), "\n") - return LuaCode(tree.source, "TESTS[" .. tostring(repr(tostring(tree.source))) .. "] = ", repr(test_str)) + return LuaCode(tree.source, "TESTS[" .. tostring(tostring(tree.source):as_lua()) .. "] = ", test_str:as_lua()) end, ["is jit"] = function(self, tree, code) return LuaCode.Value(tree.source, jit and "true" or "false") end, ["Lua version"] = function(self, tree, code) - return LuaCode.Value(tree.source, repr(_VERSION)) + return LuaCode.Value(tree.source, _VERSION:as_lua()) end, __parent = setmetatable({ }, { __index = function(self, key) @@ -744,9 +743,9 @@ do if tok.type == "Block" then self:compile_error(tok, "Can't compile action (" .. tostring(stub) .. ") with a Block as an argument.", "Maybe there should be a compile-time action with that name that isn't being found?") elseif tok.type == "Action" then - self:compile_error(tok, "Can't use this as an argument to (" .. tostring(stub) .. "), since it's not an expression, it produces: " .. tostring(repr(arg_lua)), "Check the implementation of (" .. tostring(tok.stub) .. ") to see if it is actually meant to produce an expression.") + self:compile_error(tok, "Can't use this as an argument to (" .. tostring(stub) .. "), since it's not an expression, it produces: " .. tostring(tostring(arg_lua)), "Check the implementation of (" .. tostring(tok.stub) .. ") to see if it is actually meant to produce an expression.") else - self:compile_error(tok, "Can't use this as an argument to (" .. tostring(stub) .. "), since it's not an expression, it produces: " .. tostring(repr(arg_lua))) + self:compile_error(tok, "Can't use this as an argument to (" .. tostring(stub) .. "), since it's not an expression, it produces: " .. tostring(tostring(arg_lua))) end end insert(args, arg_lua) @@ -762,6 +761,16 @@ do elseif "EscapedNomsu" == _exp_0 then local lua = LuaCode.Value(tree.source, tree[1].type, "{") local needs_comma, i = false, 1 + local as_lua + as_lua = function(x) + if type(x) == 'number' then + return tostring(x) + elseif AST.is_syntax_tree(x) then + return self:compile(x, compile_actions) + else + return x:as_lua() + end + end for k, v in pairs(AST.is_syntax_tree(tree[1], "EscapedNomsu") and tree or tree[1]) do if needs_comma then lua:append(", ") @@ -773,12 +782,12 @@ do elseif type(k) == 'string' and match(k, "[_a-zA-Z][_a-zA-Z0-9]*") then lua:append(k, "= ") else - lua:append("[", (AST.is_syntax_tree(k) and self:compile(k, compile_actions) or repr(k)), "]= ") + lua:append("[", as_lua(k), "]= ") end if k == "source" then - lua:append(repr(tostring(v))) + lua:append(tostring(v):as_lua()) else - lua:append(AST.is_syntax_tree(v) and self:compile(v, compile_actions) or repr(v)) + lua:append(as_lua(v)) end end lua:append("}") @@ -849,7 +858,7 @@ do if #lua.bits > 0 then lua:append("..") end - lua:append(repr(string_buffer)) + lua:append(string_buffer:as_lua()) string_buffer = "" end local bit_lua = self:compile(bit, compile_actions) @@ -875,7 +884,7 @@ do if #lua.bits > 0 then lua:append("..") end - lua:append(repr(string_buffer)) + lua:append(string_buffer:as_lua()) end if #lua.bits > 1 then lua:parenthesize() diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon index 19d4049..0718bca 100644 --- a/nomsu_compiler.moon +++ b/nomsu_compiler.moon @@ -14,7 +14,7 @@ lpeg = require 'lpeg' re = require 're' utils = require 'utils' Files = require 'files' -{:repr, :stringify, :equivalent} = utils +{:stringify, :equivalent} = utils {:List, :Dict, :Text} = require 'containers' export colors, colored colors = require 'consolecolors' @@ -104,7 +104,7 @@ with NomsuCompiler -- Nomsu types: _List:List, _Dict:Dict, -- Utilities and misc. - repr:repr, stringify:stringify, utils:utils, lpeg:lpeg, re:re, Files:Files, + stringify:stringify, utils:utils, lpeg:lpeg, re:re, Files:Files, :AST, TESTS: Dict{}, globals: Dict{} :LuaCode, :NomsuCode, :Source nomsu:NomsuCompiler @@ -202,16 +202,16 @@ with NomsuCompiler add_lua_string_bits = (val_or_stmt, code)=> cls_str = val_or_stmt == "value" and "LuaCode.Value(" or "LuaCode(" if code.type != "Text" - return LuaCode.Value(code.source, cls_str, repr(tostring(code.source)), ", ", @compile(code), ")") + return LuaCode.Value(code.source, cls_str, tostring(code.source)\as_lua!, ", ", @compile(code), ")") add_bit_lua = (lua, bit_lua)-> bit_leading_len = #(bit_lua\match("^[^\n]*")) lua\append(lua\trailing_line_len! + bit_leading_len > MAX_LINE and ",\n " or ", ") lua\append(bit_lua) operate_on_text = (text)-> - lua = LuaCode.Value(text.source, cls_str, repr(tostring(text.source))) + lua = LuaCode.Value(text.source, cls_str, tostring(text.source)\as_lua!) for bit in *text if type(bit) == "string" - add_bit_lua(lua, repr(bit)) + add_bit_lua(lua, bit\as_lua!) elseif bit.type == "Text" add_bit_lua(lua, operate_on_text(bit)) else @@ -270,13 +270,13 @@ with NomsuCompiler ["tests"]: (tree)=> LuaCode.Value(tree.source, "TESTS") ["test 1"]: (tree, body)=> test_str = table.concat [tostring(@tree_to_nomsu(line)) for line in *body], "\n" - LuaCode tree.source, "TESTS[#{repr(tostring(tree.source))}] = ", repr(test_str) + LuaCode tree.source, "TESTS[#{tostring(tree.source)\as_lua!}] = ", test_str\as_lua! ["is jit"]: (tree, code)=> return LuaCode.Value(tree.source, jit and "true" or "false") ["Lua version"]: (tree, code)=> - return LuaCode.Value(tree.source, repr(_VERSION)) + return LuaCode.Value(tree.source, _VERSION\as_lua!) __parent: setmetatable({}, { __index: (key)=> @@ -439,11 +439,11 @@ with NomsuCompiler elseif tok.type == "Action" @compile_error tok, - "Can't use this as an argument to (#{stub}), since it's not an expression, it produces: #{repr arg_lua}", + "Can't use this as an argument to (#{stub}), since it's not an expression, it produces: #{tostring(arg_lua)}", "Check the implementation of (#{tok.stub}) to see if it is actually meant to produce an expression." else @compile_error tok, - "Can't use this as an argument to (#{stub}), since it's not an expression, it produces: #{repr arg_lua}" + "Can't use this as an argument to (#{stub}), since it's not an expression, it produces: #{tostring(arg_lua)}" insert args, arg_lua lua\concat_append args, ", " lua\append ")" @@ -452,6 +452,13 @@ with NomsuCompiler when "EscapedNomsu" lua = LuaCode.Value tree.source, tree[1].type, "{" needs_comma, i = false, 1 + as_lua = (x)-> + if type(x) == 'number' + tostring(x) + elseif AST.is_syntax_tree(x) + @compile(x, compile_actions) + else x\as_lua! + for k,v in pairs(AST.is_syntax_tree(tree[1], "EscapedNomsu") and tree or tree[1]) if needs_comma then lua\append ", " else needs_comma = true @@ -460,11 +467,11 @@ with NomsuCompiler elseif type(k) == 'string' and match(k,"[_a-zA-Z][_a-zA-Z0-9]*") lua\append(k, "= ") else - lua\append("[", (AST.is_syntax_tree(k) and @compile(k, compile_actions) or repr(k)), "]= ") + lua\append("[", as_lua(k), "]= ") if k == "source" - lua\append repr(tostring(v)) + lua\append tostring(v)\as_lua! else - lua\append(AST.is_syntax_tree(v) and @compile(v, compile_actions) or repr(v)) + lua\append as_lua(v) lua\append "}" return lua @@ -499,9 +506,9 @@ with NomsuCompiler if type(bit) == "string" string_buffer ..= bit continue - if string_buffer ~= "" + if string_buffer != "" if #lua.bits > 0 then lua\append ".." - lua\append repr(string_buffer) + lua\append string_buffer\as_lua! string_buffer = "" bit_lua = @compile(bit, compile_actions) unless bit_lua.is_value @@ -516,7 +523,7 @@ with NomsuCompiler if string_buffer ~= "" or #lua.bits == 0 if #lua.bits > 0 then lua\append ".." - lua\append repr(string_buffer) + lua\append string_buffer\as_lua! if #lua.bits > 1 lua\parenthesize! diff --git a/parser.lua b/parser.lua index 0694e3e..5eee8ca 100644 --- a/parser.lua +++ b/parser.lua @@ -3,8 +3,6 @@ local re = require('re') lpeg.setmaxstack(20000) local P, R, S, C, Cmt, Carg, Cc P, R, S, C, Cmt, Carg, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cmt, lpeg.Carg, lpeg.Cc -local repr -repr = require('utils').repr local DEFS do local _with_0 = { } diff --git a/parser.moon b/parser.moon index 9a2e2ff..78e6291 100644 --- a/parser.moon +++ b/parser.moon @@ -3,7 +3,6 @@ lpeg = require 'lpeg' re = require 're' lpeg.setmaxstack 20000 {:P,:R,:S,:C,:Cmt,:Carg,:Cc} = lpeg -{:repr} = require 'utils' DEFS = with {} -- Newline supports either windows-style CR+LF or unix-style LF diff --git a/string2.lua b/string2.lua index 5995de2..2cdfefc 100644 --- a/string2.lua +++ b/string2.lua @@ -119,6 +119,24 @@ local string2 = { end return table.concat(lines, "\n") end, + as_lua = function(self) + local escaped = gsub(self, "\\", "\\\\") + escaped = gsub(escaped, "\n", "\\n") + escaped = gsub(escaped, '"', '\\"') + escaped = gsub(escaped, "[^ %g]", function(c) + return format("\\%03d", byte(c, 1)) + end) + return '"' .. escaped .. '"' + end, + as_nomsu = function(self) + local escaped = gsub(self, "\\", "\\\\") + escaped = gsub(escaped, "\n", "\\n") + escaped = gsub(escaped, '"', '\\"') + escaped = gsub(escaped, "[^ %g]", function(c) + return format("\\%03d", byte(c, 1)) + end) + return '"' .. escaped .. '"' + end, as_lua_id = function(str) local orig = str str = gsub(str, "^ *$", "%1 ") diff --git a/string2.moon b/string2.moon index 2259272..662cd0d 100644 --- a/string2.moon +++ b/string2.moon @@ -45,6 +45,20 @@ string2 = { lines[#lines+1] = line return table.concat(lines, "\n") + as_lua: => + escaped = gsub(@, "\\", "\\\\") + escaped = gsub(escaped, "\n", "\\n") + escaped = gsub(escaped, '"', '\\"') + escaped = gsub(escaped, "[^ %g]", (c)-> format("\\%03d", byte(c, 1))) + return '"'..escaped..'"' + + as_nomsu: => + escaped = gsub(@, "\\", "\\\\") + escaped = gsub(escaped, "\n", "\\n") + escaped = gsub(escaped, '"', '\\"') + escaped = gsub(escaped, "[^ %g]", (c)-> format("\\%03d", byte(c, 1))) + return '"'..escaped..'"' + -- Convert an arbitrary text into a valid Lua identifier. This function is injective, -- but not idempotent. In logic terms: (x != y) => (as_lua_id(x) != as_lua_id(y)), -- but not (as_lua_id(a) == b) => (as_lua_id(b) == b). diff --git a/syntax_tree.lua b/syntax_tree.lua index 72b510e..afdb631 100644 --- a/syntax_tree.lua +++ b/syntax_tree.lua @@ -1,5 +1,3 @@ -local repr -repr = require('utils').repr local insert, remove, concat do local _obj_0 = table @@ -15,6 +13,24 @@ AST.is_syntax_tree = function(n, t) end return type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n) and (t == nil or n.type == t) end +local as_lua +as_lua = function(self) + if type(self) == 'number' then + return tostring(self) + end + do + local mt = getmetatable(self) + if mt then + do + local _as_lua = mt.as_lua + if _as_lua then + return _as_lua(self) + end + end + end + end + return error("Not supported: " .. tostring(self)) +end local types = { "Number", "Var", @@ -42,10 +58,42 @@ for _index_0 = 1, #types do return getmetatable(x) == self end cls.__tostring = function(self) - return tostring(self.type) .. tostring(repr(self, (function() end))) + local bits + do + local _accum_0 = { } + local _len_0 = 1 + for _index_1 = 1, #self do + local b = self[_index_1] + _accum_0[_len_0] = tostring(b) + _len_0 = _len_0 + 1 + end + bits = _accum_0 + end + for k, v in pairs(self) do + if not (bits[k]) then + table.insert(bits, "[ " .. tostring(tostring(k)) .. "]=" .. tostring(tostring(v))) + end + end + return tostring(self.type) .. "{" .. tostring(table.concat(bits, ", ")) .. "}" end - cls.__repr = function(self) - return tostring(self.type) .. tostring(repr(self, (function() end))) + cls.as_lua = function(self) + local bits + do + local _accum_0 = { } + local _len_0 = 1 + for _index_1 = 1, #self do + local b = self[_index_1] + _accum_0[_len_0] = as_lua(b) + _len_0 = _len_0 + 1 + end + bits = _accum_0 + end + for k, v in pairs(self) do + if not (bits[k]) then + table.insert(bits, "[ " .. tostring(as_lua(k)) .. "]=" .. tostring(as_lua(v))) + end + end + return tostring(self.type) .. "{" .. tostring(table.concat(bits, ", ")) .. "}" end cls.source_code_for_tree = setmetatable({ }, { __index = function(self, t) diff --git a/syntax_tree.moon b/syntax_tree.moon index 305a1ee..d2f5d37 100644 --- a/syntax_tree.moon +++ b/syntax_tree.moon @@ -1,6 +1,5 @@ -- This file contains the datastructures used to represent parsed Nomsu syntax trees, -- as well as the logic for converting them to Lua code. -{:repr} = require 'utils' {:insert, :remove, :concat} = table {:Source} = require "code_obj" unpack or= table.unpack @@ -9,6 +8,14 @@ AST = {} AST.is_syntax_tree = (n, t=nil)-> type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n) and (t == nil or n.type == t) +as_lua = => + if type(@) == 'number' + return tostring(@) + if mt = getmetatable(@) + if _as_lua = mt.as_lua + return _as_lua(@) + error("Not supported: #{@}") + types = {"Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry", "IndexChain", "Action", "FileChunks", "Error", "Comment"} for name in *types @@ -19,8 +26,18 @@ for name in *types .__name = name .type = name .is_instance = (x)=> getmetatable(x) == @ - .__tostring = => "#{@type}#{repr @, (->)}" - .__repr = => "#{@type}#{repr @, (->)}" + .__tostring = => + bits = [tostring(b) for b in *@] + for k,v in pairs(@) + unless bits[k] + table.insert(bits, "[ #{tostring(k)}]=#{tostring(v)}") + return "#{@type}{#{table.concat(bits, ", ")}}" + .as_lua = => + bits = [as_lua(b) for b in *@] + for k,v in pairs(@) + unless bits[k] + table.insert(bits, "[ #{as_lua(k)}]=#{as_lua(v)}") + return "#{@type}{#{table.concat(bits, ", ")}}" .source_code_for_tree = setmetatable({}, {__index:(t)=> s = t.source Files = require 'files'