From 1de29826a82cc858cf6d9df9ead86655304251a4 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 12 Apr 2018 18:01:51 -0700 Subject: [PATCH] Incremental progress towards working. --- core/metaprogramming.nom | 2 +- lua_obj.moon | 18 +++++++++++---- nomsu.lua | 49 ++++++++++++++++++++++++++-------------- nomsu.moon | 42 +++++++++++++++++++++------------- 4 files changed, 73 insertions(+), 38 deletions(-) diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 5d6b59c..24201b0 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -26,7 +26,7 @@ immediately: end local body_lua = nomsu:tree_to_lua(\%lua):as_statements(); body_lua:declare_locals(args); - lua:append("\\n ", body_lua, "\\nend);") + lua:append(")\\n ", body_lua, "\\nend);") return lua; end); diff --git a/lua_obj.moon b/lua_obj.moon index 1565fcb..ef5dc7e 100644 --- a/lua_obj.moon +++ b/lua_obj.moon @@ -56,7 +56,8 @@ class Lua declare_locals: (skip={})=> if next(skip) == 1 skip = {[s]:true for s in *skip} - @prepend "local #{concat @free_vars, ", "};\n" + if #@free_vars > 0 + @prepend "local #{concat @free_vars, ", "};\n" for var in *@free_vars do skip[var] = true for bit in *@bits if type(bit) == Lua @@ -66,7 +67,9 @@ class Lua buff = {} for b in *@bits buff[#buff+1] = tostring(b) - return concat(buff, "") + ret = concat(buff, "") + assert(not ret\match(".*table: 0x.*")) + return ret __len: => len = 0 @@ -96,7 +99,6 @@ class Lua lua_filename:lua_chunkname, lua_file:lua_str lua_to_nomsu: {}, nomsu_to_lua: {} } - metadata, lua_offset = {}, 1 lua_offset = 1 walk = (lua)-> if type(lua) == 'string' @@ -106,7 +108,7 @@ class Lua for b in *lua.bits walk b lua_stop = lua_offset - nomsu_src, lua_src = lua.souce, Location(lua_chunkname, lua_str, lua_start, lua_stop) + nomsu_src, lua_src = lua.source, Location(lua_chunkname, lua_str, lua_start, lua_stop) metadata.lua_to_nomsu[lua_src] = nomsu_src metadata.nomsu_to_lua[nomsu_src] = lua_src walk self @@ -119,6 +121,14 @@ class LuaValue extends Lua new: (@source, ...)=> @bits = {...} + __tostring: => + buff = {} + for b in *@bits + buff[#buff+1] = tostring(b) + ret = concat(buff, "") + assert(not ret\match(".*table: 0x.*")) + return ret + as_statements: => bits = {unpack @bits} bits[#bits+1] = ";" diff --git a/nomsu.lua b/nomsu.lua index 2bd41b8..36d8e6b 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -916,8 +916,8 @@ do elseif "FunctionCall" == _exp_0 then insert(self.compilestack, tree) local stub = self:tree_to_stub(tree) - local fn = rawget(self.environment.ACTIONS, stub) - local metadata = self.action_metadata[fn] + local action = rawget(self.environment.ACTIONS, stub) + local metadata = self.action_metadata[action] if metadata and metadata.compile_time then local args do @@ -948,7 +948,7 @@ do end args = new_args end - local lua = fn(unpack(args)) + local lua = action(unpack(args)) remove(self.compilestack) return lua elseif not metadata and self.__class.math_patt:match(stub) then @@ -1419,9 +1419,7 @@ do end) self:define_compile_action("!! code location !!", get_line_no(), function() local tree = nomsu.compilestack[#nomsu.compilestack - 1] - return LuaValue(tree.source, { - repr(tostring(tree.source)) - }) + return LuaValue(tree.source, repr(tostring(tree.source))) end) self:define_action("run file %filename", get_line_no(), function(_filename) return nomsu:run_file(_filename) @@ -1430,9 +1428,7 @@ do local tree = nomsu.compilestack[#nomsu.compilestack - 1] local filename = nomsu:tree_to_value(_filename) nomsu:use_file(filename) - return LuaValue(tree.source, { - "nomsu:use_file(" .. tostring(repr(filename)) .. ")" - }) + return LuaValue(tree.source, "nomsu:use_file(" .. tostring(repr(filename)) .. ")") end) end } @@ -1510,6 +1506,9 @@ do self.environment[k] = v end self.environment.Tuple = Tuple + self.environment.Lua = Lua + self.environment.LuaValue = LuaValue + self.environment.Location = Location self.environment.ACTIONS = setmetatable({ }, { __index = function(self, key) return error("Attempt to run undefined action: " .. tostring(key), 0) @@ -1597,21 +1596,37 @@ if arg and debug_getinfo(2).func ~= require then return line_table end }) - debug.getinfo = function(...) - local info = debug_getinfo(...) + debug.getinfo = function(thread, f, what) + if what == nil then + f, what, thread = thread, f, nil + end + if type(f) == 'number' then + f = f + 1 + end + local info + if thread == nil then + info = debug_getinfo(f, what) + else + info = debug_getinfo(thread, f, what) + end if not info or not info.func then return info end - if info.source and info.source:sub(1, 1) ~= "@" and LINE_STARTS[info.source] then - do - local metadata = nomsu.action_metadata[info.func] - if metadata then - info.name = metadata.aliases[1] - end + do + local metadata = nomsu.action_metadata[info.func] + if metadata then + info.name = metadata.aliases[1] end + end + local is_nomsu, nomsu_line = pcall(lua_line_to_nomsu_line, info.short_src, info.linedefined) + if is_nomsu then if info.source:sub(1, 1) == "@" then error("Not-yet-loaded source: " .. tostring(info.source)) end + info.linedefined = nomsu_line + info.currentline = lua_line_to_nomsu_line(info.short_src, info.currentline) + info.short_src = metadata.source.text_name + info.source = metadata.source.text else if info.short_src and info.short_src:match("^.*%.moon$") then local line_table = moonscript_line_tables[info.short_src] diff --git a/nomsu.moon b/nomsu.moon index e736128..e75ba04 100755 --- a/nomsu.moon +++ b/nomsu.moon @@ -34,6 +34,7 @@ debug_getinfo = debug.getinfo -- Do a pass on all actions to enforce parameters-are-nouns heuristic -- Maybe do some sort of lazy definitions of actions that defer until they're used in code -- Add a ((%x foo %y) where {x:"asdf", y:"fdsa"}) compile-time action for substitution +-- Allow plain text backslash like: "\n" in longstrings without requiring "\\n" FILE_CACHE = setmetatable {}, { __index: (filename)=> @@ -215,6 +216,9 @@ class NomsuCompiler } for k,v in pairs(Types) do @environment[k] = v @environment.Tuple = Tuple + @environment.Lua = Lua + @environment.LuaValue = LuaValue + @environment.Location = Location @environment.ACTIONS = setmetatable({}, {__index:(key)=> error("Attempt to run undefined action: #{key}", 0) }) @@ -677,16 +681,16 @@ class NomsuCompiler insert @compilestack, tree stub = @tree_to_stub tree - fn = rawget(@environment.ACTIONS, stub) + action = rawget(@environment.ACTIONS, stub) - metadata = @action_metadata[fn] + metadata = @action_metadata[action] if metadata and metadata.compile_time args = [arg for arg in *tree.value when arg.type != "Word"] -- Force all compile-time actions to take a tree location if metadata and metadata.arg_orders new_args = [args[p] for p in *metadata.arg_orders[stub]] args = new_args - lua = fn(unpack(args)) + lua = action(unpack(args)) remove @compilestack return lua elseif not metadata and @@math_patt\match(stub) @@ -1005,13 +1009,13 @@ class NomsuCompiler lua = nomsu\tree_to_lua(_block)\as_statements! lua\declare_locals! nomsu\run_lua(lua) - return Lua _block.source, "if IMMEDIATE then\n", lua, "\nend" + return Lua(_block.source, "if IMMEDIATE then\n", lua, "\nend") @define_compile_action "lua> %code", get_line_no!, (_code)-> if _code.type != "Text" return LuaValue(_code.source, "nomsu:run_lua(",nomsu\tree_to_lua(_code),")") - lua = Lua _code.source + lua = Lua(_code.source) for bit in *_code.value if type(bit) == "string" lua\append bit @@ -1041,7 +1045,7 @@ class NomsuCompiler @define_compile_action "!! code location !!", get_line_no!, -> tree = nomsu.compilestack[#nomsu.compilestack-1] - return LuaValue(tree.source, {repr(tostring(tree.source))}) + return LuaValue(tree.source, repr(tostring(tree.source))) @define_action "run file %filename", get_line_no!, (_filename)-> return nomsu\run_file(_filename) @@ -1050,7 +1054,7 @@ class NomsuCompiler tree = nomsu.compilestack[#nomsu.compilestack-1] filename = nomsu\tree_to_value(_filename) nomsu\use_file(filename) - return LuaValue(tree.source, {"nomsu:use_file(#{repr filename})"}) + return LuaValue(tree.source, "nomsu:use_file(#{repr filename})") -- 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 @@ -1081,17 +1085,23 @@ if arg and debug_getinfo(2).func != require return line_table } - debug.getinfo = (...)-> - info = debug_getinfo(...) + debug.getinfo = (thread,f,what)-> + if what == nil + f,what,thread = thread,f,nil + if type(f) == 'number' then f += 1 -- Account for this wrapper function + info = if thread == nil + debug_getinfo(f,what) + else debug_getinfo(thread,f,what) if not info or not info.func then return info - if info.source and info.source\sub(1,1) != "@" and LINE_STARTS[info.source] - if metadata = nomsu.action_metadata[info.func] - info.name = metadata.aliases[1] + if metadata = nomsu.action_metadata[info.func] + info.name = metadata.aliases[1] + is_nomsu, nomsu_line = pcall(lua_line_to_nomsu_line, info.short_src, info.linedefined) + if is_nomsu if info.source\sub(1,1) == "@" then error("Not-yet-loaded source: #{info.source}") - --info.linedefined = lua_line_to_nomsu_line(info.short_src, info.linedefined) - --info.currentline = lua_line_to_nomsu_line(info.short_src, info.currentline) - --info.short_src = metadata.source.text_name - --info.source = metadata.source.text + info.linedefined = nomsu_line + info.currentline = lua_line_to_nomsu_line(info.short_src, info.currentline) + info.short_src = metadata.source.text_name + info.source = metadata.source.text else if info.short_src and info.short_src\match("^.*%.moon$") line_table = moonscript_line_tables[info.short_src]