aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-04-13 14:54:35 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-04-13 14:54:47 -0700
commit222d4d07271a3296175d55d09b0bfbbd72613dd8 (patch)
tree53842f83fba8f078db00213b5ea9dc509b5ec424
parentb05a46c78ca40e6838ee49121fdc5d02823ed44b (diff)
More correct and more working.
-rw-r--r--core/metaprogramming.nom62
-rw-r--r--lua_obj.moon40
-rw-r--r--nomsu.lua95
-rwxr-xr-xnomsu.moon85
4 files changed, 177 insertions, 105 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index d7409d2..0c7cada 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -5,14 +5,13 @@
# Compile-time action to make compile-time actions:
immediately:
lua> ".."
- nomsu:define_compile_action("compile %actions to %lua", \(!! code location !!), function(\%actions, \%lua)
- local tree = nomsu.compilestack[#nomsu.compilestack];
+ nomsu:define_compile_action("compile %actions to %lua", \(!! code location !!), function(tree, \%actions, \%lua)
local lua = Lua(tree.source, "nomsu:define_compile_action(");
local stubs = {};
for i, action in ipairs(\%actions.value) do
stubs[i] = nomsu:tree_to_named_stub(action);
end
- lua:append(repr(stubs), ", ", repr(tree.source:get_line()), ", function(");
+ lua:append(repr(stubs), ", ", repr(tree.source:get_line()), ", function(tree");
local args = {};
for i,tok in ipairs(\%actions.value[1].value) do
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
@@ -21,10 +20,10 @@ immediately:
error("Invalid type for 'compile % to %', expected a dict with expr/statements, but got text.", 0);
end
for i, arg in ipairs(args) do
+ lua:append(", ");
lua:append(arg);
- if i < #args then lua:append(", ") end
end
- local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
+ local body_lua = nomsu:tree_to_lua(\%lua):as_statements("return ");
body_lua:declare_locals(args);
lua:append(")\\n ", body_lua, "\\nend);")
return lua;
@@ -34,7 +33,6 @@ immediately:
immediately:
compile [action %actions %body] to:
lua> ".."
- local tree = nomsu.compilestack[#nomsu.compilestack];
local lua = Lua(tree.source, "nomsu:define_action(");
local stubs = {};
for i, action in ipairs(\%actions.value) do
@@ -49,7 +47,7 @@ immediately:
lua:append(arg);
if i < #args then lua:append(", ") end
end
- local body_lua = nomsu:tree_to_lua(\%body):as_statements();
+ local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ");
body_lua:declare_locals(args);
lua:append(")\\n ", body_lua, "\\nend);")
return lua;
@@ -58,20 +56,19 @@ immediately:
immediately:
compile [parse %shorthand as %longhand] to:
lua> ".."
- local tree = nomsu.compilestack[#nomsu.compilestack];
local lua = Lua(tree.source, "nomsu:define_compile_action(");
local stubs = {};
for i, action in ipairs(\%shorthand.value) do
stubs[i] = nomsu:tree_to_named_stub(action);
end
- lua:append(repr(stubs), ", ", repr(tree.source:get_line()), ", function(");
+ lua:append(repr(stubs), ", ", repr(tree.source:get_line()), ", function(tree");
local args = {};
for i,tok in ipairs(\%shorthand.value[1].value) do
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
end
for i, arg in ipairs(args) do
+ lua:append(", ");
lua:append(arg);
- if i < #args then lua:append(", ") end
end
local template;
if \%longhand.type == "Block" then
@@ -127,14 +124,14 @@ immediately:
=lua "nomsu:tree_to_stub(\%tree)"
immediately:
- compile [%tree's source code, %tree' source code] to {expr:"\(%tree as lua expr).source:get_text()"}
+ compile [%tree's source code, %tree' source code] to: LuaValue "\(%tree as lua expr).source:get_text()"
- compile [repr %obj] to {expr:"repr(\(%obj as lua expr))"}
- compile [type of %obj] to {expr:"type(\(%obj as lua expr))"}
+ compile [repr %obj] to: LuaValue "repr(\(%obj as lua expr))"
+ compile [type of %obj] to: LuaValue "type(\(%obj as lua expr))"
immediately:
- compile [nomsu] to {expr:"nomsu"}
- compile [%var as lua identifier] to {expr:"nomsu:var_to_lua_identifier(\(%var as lua expr))"}
+ compile [nomsu] to: LuaValue "nomsu"
+ compile [%var as lua identifier] to: LuaValue "nomsu:var_to_lua_identifier(\(%var as lua expr))"
action [action %names metadata]:
=lua "nomsu.action_metadata[ACTIONS[\%names]]"
@@ -151,9 +148,8 @@ action [help %action]:
# Compiler tools
immediately:
- #local def_metadata = nomsu.tree_metadata[nomsu.compilestack[#nomsu.compilestack]];
- compile [run %code] to {..}
- expr: ".."
+ compile [run %code] to:
+ LuaValue ".."
nomsu:run(\(%code as lua expr), '\
=lua "nomsu:get_line_number(nomsu.compilestack[#nomsu.compilestack])"
..')
@@ -164,44 +160,40 @@ immediately:
compile [show lua %block] to:
lua> ".."
local \%lua = nomsu:tree_to_lua(\%block);
- return {statements = "print("..repr(\%lua.statements or \%lua.expr)..");"};
+ return Lua(\%block.source, "print(", repr(tostring(\%lua)), ");");
immediately:
compile [say %message] to:
lua> ".."
+ local tree = nomsu.compilestack[#nomsu.compilestack];
if \%message.type == "Text" then
- return {statements="print("..\(%message as lua expr)..");"};
+ return Lua(tree.source, "print(", \(%message as lua expr), ");");
else
- return {statements="print(stringify("..\(%message as lua expr).."));"};
+ return Lua(tree.source, "print(stringify(", \(%message as lua expr), "));");
end
# Return
immediately:
#.. Return statement is wrapped in a do..end block because Lua is unhappy if you
put code after a return statement, unless you wrap it in a block.
- compile [return] to {statements:"do return; end"}
- compile [return %return_value] to {statements:"do return \(%return_value as lua expr); end"}
+ compile [return] to: Lua "do return; end"
+ compile [return %return_value] to: Lua "do return \(%return_value as lua expr); end"
# Error functions
immediately:
- compile [barf] to {statements:"error(nil, 0);"}
- compile [barf %msg] to {statements:"error(\(%msg as lua expr), 0);"}
+ compile [barf] to: LuaValue "error(nil, 0);"
+ compile [barf %msg] to: LuaValue "error(\(%msg as lua expr), 0);"
compile [assume %condition] to:
lua> "local \%assumption = 'Assumption failed: '..\%condition.source:get_text();"
- return {..}
- statements:".."
+ return:
+ Lua ".."
if not \(%condition as lua expr) then
error(\(repr %assumption), 0);
end
- compile [assume %condition or barf %msg] to {..}
- statements:".."
- if not \(%condition as lua expr) then
- error(\(%msg as lua expr), 0);
- end
# Literals
immediately:
- compile [yes] to {expr:"true"}
- compile [no] to {expr:"false"}
- compile [nothing, nil, null] to {expr:"nil"}
+ compile [yes] to: LuaValue "true"
+ compile [no] to: LuaValue "false"
+ compile [nothing, nil, null] to: LuaValue "nil"
diff --git a/lua_obj.moon b/lua_obj.moon
index 6cc3e00..1979c94 100644
--- a/lua_obj.moon
+++ b/lua_obj.moon
@@ -3,29 +3,26 @@ immutable = require 'immutable'
local Lua, LuaValue, Location
export LINE_STARTS
-Location = immutable {"text_name","text","start","stop"}, {
+Location = immutable {"filename","start","stop"}, {
name:"Location"
- __new: (text_name, text, start, stop)=>
- assert(type(text_name) == 'string')
- assert(type(text) == 'string')
- assert(type(start) == 'number')
- assert(type(stop or start) == 'number')
- return text_name, text, start, stop or start
- __tostring: => "#{@text_name}[#{@start}:#{@stop}]"
+ __new: (filename, start, stop)=>
+ assert(type(filename) == 'string' and type(start) == 'number' and type(stop) == 'number')
+ return filename, start, stop or start
+ __tostring: => "Location(\"#{@filename}\", #{@start}, #{@stop})"
__lt: (other)=>
- assert(@text == other.text, "Cannot compare sources from different texts")
+ assert(@filename == other.filename, "Cannot compare sources from different files")
return if @start == other.start
@stop < other.stop
else @start < other.start
__le: (other)=>
- assert(@text == other.text, "Cannot compare sources from different texts")
+ assert(@filename == other.filename, "Cannot compare sources from different files")
return if @start == other.start
@stop <= other.stop
else @start <= other.start
- get_text: => @text\sub(@start,@stop)
+ get_text: => FILE_CACHE[@filename]\sub(@start,@stop)
get_line_number: =>
-- TODO: do a binary search if this is actually slow, which I doubt
- line_starts = LINE_STARTS[@text]
+ line_starts = LINE_STARTS[FILE_CACHE[@filename]]
start_line = 1
while (line_starts[start_line+1] or (#src+1)) <= @start
start_line += 1
@@ -33,12 +30,12 @@ Location = immutable {"text_name","text","start","stop"}, {
while (line_starts[stop_line+1] or (#src+1)) <= @stop
stop_line += 1
return start_line, stop_line
- get_line: => "#{@text_name}:#{@get_line_number!}"
+ get_line: => "#{@filename}:#{@get_line_number!}"
get_line_range: =>
start_line, stop_line = @get_line_number!
return if stop_line == start_line
- "#{text_name}:#{start_line}"
- else "#{text_name}:#{start_line}-#{stop_line}"
+ "#{@filename}:#{start_line}"
+ else "#{@filename}:#{start_line}-#{stop_line}"
}
class Lua
@@ -46,6 +43,9 @@ class Lua
is_value: false
new: (@source, ...)=>
+ if type(@source) == 'string'
+ filename,start,stop = @source\match("^(.-)[(%d+):(%d+)]$")
+ @source = Location(filename, tonumber(start), tonumber(stop))
for i=1,select("#",...)
x = select(i,...)
assert(type(x) != 'table' or getmetatable(x))
@@ -109,7 +109,7 @@ class Lua
-- Return a mapping from output (lua) character number to input (nomsu) character number
lua_str = tostring(self)
metadata = {
- nomsu_filename:@source.text_name, nomsu_file:@source.text,
+ nomsu_filename:@source.filename
lua_filename:lua_chunkname, lua_file:lua_str
lua_to_nomsu: {}, nomsu_to_lua: {}
}
@@ -122,7 +122,7 @@ class Lua
for b in *lua.bits
walk b
lua_stop = lua_offset
- nomsu_src, lua_src = lua.source, Location(lua_chunkname, lua_str, lua_start, lua_stop)
+ nomsu_src, lua_src = lua.source, Location(lua_chunkname, lua_start, lua_stop)
metadata.lua_to_nomsu[lua_src] = nomsu_src
metadata.nomsu_to_lua[nomsu_src] = lua_src
walk self
@@ -143,9 +143,9 @@ class LuaValue extends Lua
assert(not ret\match(".*table: 0x.*"))
return ret
- as_statements: =>
- bits = {unpack @bits}
- bits[#bits+1] = ";"
+ as_statements: (prefix="", suffix=";")=>
+ bits = {prefix, unpack @bits}
+ bits[#bits+1] = suffix
return Lua(@source, unpack(bits))
parenthesize: =>
diff --git a/nomsu.lua b/nomsu.lua
index ba1d813..2df72be 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -32,7 +32,7 @@ do
local _obj_0 = require("lua_obj")
Lua, LuaValue, Location = _obj_0.Lua, _obj_0.LuaValue, _obj_0.Location
end
-local FILE_CACHE = setmetatable({ }, {
+FILE_CACHE = setmetatable({ }, {
__index = function(self, filename)
local file = io.open(filename)
if not (file) then
@@ -196,7 +196,7 @@ do
pos = pos + #lpeg.userdata.source_code:match("[ \t\n\r]*", pos)
end
local line_no = 1
- local text_loc = Location(lpeg.userdata.filename, src, pos)
+ local text_loc = Location(lpeg.userdata.filename, pos)
line_no = text_loc:get_line_number()
local prev_line = src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 1)
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 1)
@@ -215,7 +215,7 @@ setmetatable(NOMSU_DEFS, {
if type(value) == 'table' then
error("Not a tuple: " .. tostring(repr(value)))
end
- local loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
+ local loc = Location(lpeg.userdata.filename, start, stop)
local node = Types[key](value, loc)
return node
end
@@ -282,9 +282,6 @@ do
end
arg_positions = _accum_0
end
- if #arg_positions ~= #args then
- error("Mismatch in args between lua function's " .. tostring(repr(fn_arg_positions)) .. " and stub's " .. tostring(repr(args)) .. " for " .. tostring(repr(stub)), 0)
- end
arg_orders[stub] = arg_positions
end
end
@@ -379,7 +376,8 @@ do
local tree = self:parse(nomsu_code, filename)
assert(tree, "Failed to parse: " .. tostring(nomsu_code))
assert(tree.type == "File", "Attempt to run non-file: " .. tostring(tree.type))
- local lua = self:tree_to_lua(tree):as_statements():with_locals_declared()
+ local lua = self:tree_to_lua(tree):as_statements()
+ lua:declare_locals()
lua:prepend("-- File: " .. tostring(filename) .. "\n")
return self:run_lua(lua, filename .. ".lua")
end,
@@ -449,8 +447,9 @@ do
_chunk_counter = _chunk_counter + 1
filename = "<lua chunk #" .. tostring(_chunk_counter) .. ">"
else
- filename = lua.source.text_name .. ".lua"
+ filename = lua.source.filename .. ".lua"
end
+ FILE_CACHE[filename] = tostring(lua)
end
if type(lua) ~= 'string' then
local metadata
@@ -475,7 +474,7 @@ do
return tree.value[1]
end
local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";")
- return self:run_lua(lua, tree.source.text_name)
+ return self:run_lua(lua, tree.source.filename)
end,
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
if indentation == nil then
@@ -896,9 +895,9 @@ do
file_lua:declare_locals()
return file_lua
elseif "Comment" == _exp_0 then
- return Lua(tree.source, "--" .. tree.value:gsub("\n", "\n--"))
+ return Lua(tree.source, "--" .. tree.value:gsub("\n", "\n--") .. "\n")
elseif "Nomsu" == _exp_0 then
- return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.text_name), ")")
+ return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.filename), ")")
elseif "Block" == _exp_0 then
local block_lua = Lua(tree.source)
for i, arg in ipairs(tree.value) do
@@ -941,14 +940,14 @@ do
local _list_1 = metadata.arg_orders[stub]
for _index_0 = 1, #_list_1 do
local p = _list_1[_index_0]
- _accum_0[_len_0] = args[p]
+ _accum_0[_len_0] = args[p - 1]
_len_0 = _len_0 + 1
end
new_args = _accum_0
end
args = new_args
end
- local lua = action(unpack(args))
+ local lua = action(tree, unpack(args))
remove(self.compilestack)
return lua
elseif not metadata and self.__class.math_patt:match(stub) then
@@ -1367,15 +1366,61 @@ do
return "nomsu.moon:" .. tostring(debug_getinfo(2).currentline)
end
local nomsu = self
- self:define_compile_action("immediately %block", get_line_no(), function(_block)
+ self:define_compile_action("immediately %block", get_line_no(), function(self, _block)
local 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(self.source, "if IMMEDIATE then\n", lua, "\nend")
+ end)
+ self:define_compile_action("Lua %code", get_line_no(), function(self, _code)
+ if _code.type ~= "Text" then
+ return LuaValue(self.source, "Lua(", repr(_code.source), ", ", nomsu:tree_to_lua(_code), ")")
+ end
+ local lua = LuaValue(self.source, "Lua(", repr(_code.source))
+ local _list_1 = _code.value
+ for _index_0 = 1, #_list_1 do
+ local bit = _list_1[_index_0]
+ lua:append(", ")
+ if type(bit) == "string" then
+ lua:append(repr(bit))
+ else
+ local bit_lua = nomsu:tree_to_lua(bit)
+ if not (bit_lua.is_value) then
+ local line, src = bit.source:get_line(), bit.source:get_text()
+ error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a string interpolation value, since it's not an expression.", 0)
+ end
+ lua:append(bit_lua)
+ end
+ end
+ lua:append(")")
+ return lua
+ end)
+ self:define_compile_action("LuaValue %code", get_line_no(), function(self, _code)
+ if _code.type ~= "Text" then
+ return LuaValue(self.source, "LuaValue(", repr(_code.source), ", ", nomsu:tree_to_lua(_code), ")")
+ end
+ local lua = LuaValue(self.source, "LuaValue(", repr(_code.source))
+ local _list_1 = _code.value
+ for _index_0 = 1, #_list_1 do
+ local bit = _list_1[_index_0]
+ lua:append(", ")
+ if type(bit) == "string" then
+ lua:append(repr(bit))
+ else
+ local bit_lua = nomsu:tree_to_lua(bit)
+ if not (bit_lua.is_value) then
+ local line, src = bit.source:get_line(), bit.source:get_text()
+ error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a string interpolation value, since it's not an expression.", 0)
+ end
+ lua:append(bit_lua)
+ end
+ end
+ lua:append(")")
+ return lua
end)
- self:define_compile_action("lua> %code", get_line_no(), function(_code)
+ self:define_compile_action("lua> %code", get_line_no(), function(self, _code)
if _code.type ~= "Text" then
- return LuaValue(_code.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ")")
+ return LuaValue(self.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ")")
end
local lua = Lua(_code.source)
local _list_1 = _code.value
@@ -1394,11 +1439,11 @@ do
end
return lua
end)
- self:define_compile_action("=lua %code", get_line_no(), function(_code)
+ self:define_compile_action("=lua %code", get_line_no(), function(self, _code)
if _code.type ~= "Text" then
- return LuaValue(_code.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ")")
+ return LuaValue(self.source, "nomsu:run_lua(", nomsu:tree_to_lua(_code), ")")
end
- local lua = LuaValue(_code.source)
+ local lua = LuaValue(self.source)
local _list_1 = _code.value
for _index_0 = 1, #_list_1 do
local bit = _list_1[_index_0]
@@ -1415,18 +1460,16 @@ do
end
return lua
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)))
+ self:define_compile_action("!! code location !!", get_line_no(), function(self)
+ return LuaValue(self.source, repr(self.source))
end)
self:define_action("run file %filename", get_line_no(), function(_filename)
return nomsu:run_file(_filename)
end)
- return self:define_compile_action("use %filename", get_line_no(), function(_filename)
- local tree = nomsu.compilestack[#nomsu.compilestack - 1]
+ return self:define_compile_action("use %filename", get_line_no(), function(self, _filename)
local filename = nomsu:tree_to_value(_filename)
nomsu:use_file(filename)
- return LuaValue(tree.source, "nomsu:use_file(" .. tostring(repr(filename)) .. ")")
+ return LuaValue(self.source, "nomsu:use_file(" .. tostring(repr(filename)) .. ")")
end)
end
}
diff --git a/nomsu.moon b/nomsu.moon
index 5c24430..e840fb3 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -36,6 +36,7 @@ debug_getinfo = debug.getinfo
-- 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"
+export FILE_CACHE
FILE_CACHE = setmetatable {}, {
__index: (filename)=>
file = io.open(filename)
@@ -149,7 +150,7 @@ NOMSU_DEFS = with {}
if lpeg.userdata.source_code\sub(pos,pos)\match("[\r\n]")
pos += #lpeg.userdata.source_code\match("[ \t\n\r]*", pos)
line_no = 1
- text_loc = Location(lpeg.userdata.filename, src, pos)
+ text_loc = Location(lpeg.userdata.filename, pos)
line_no = text_loc\get_line_number!
prev_line = src\sub(LINE_STARTS[src][line_no-1] or 1, LINE_STARTS[src][line_no]-1)
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-1)
@@ -162,7 +163,7 @@ NOMSU_DEFS = with {}
setmetatable(NOMSU_DEFS, {__index:(key)=>
make_node = (start, value, stop)->
if type(value) == 'table' then error("Not a tuple: #{repr value}")-- = Tuple(value)
- loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
+ loc = Location(lpeg.userdata.filename, start, stop)
node = Types[key](value, loc)
return node
self[key] = make_node
@@ -247,8 +248,8 @@ class NomsuCompiler
unless fn_info.isvararg
arg_positions = [fn_arg_positions[a] for a in *args]
-- TODO: better error checking?
- if #arg_positions != #args
- error("Mismatch in args between lua function's #{repr fn_arg_positions} and stub's #{repr args} for #{repr stub}", 0)
+ --if #arg_positions != #args
+ -- error("Mismatch in args between lua function's #{repr fn_arg_positions} and stub's #{repr args} for #{repr stub}", 0)
arg_orders[stub] = arg_positions
@action_metadata[fn] = {
@@ -304,7 +305,8 @@ class NomsuCompiler
tree = @parse(nomsu_code, filename)
assert tree, "Failed to parse: #{nomsu_code}"
assert tree.type == "File", "Attempt to run non-file: #{tree.type}"
- lua = @tree_to_lua(tree)\as_statements!\with_locals_declared!
+ lua = @tree_to_lua(tree)\as_statements!
+ lua\declare_locals!
lua\prepend "-- File: #{filename}\n"
return @run_lua(lua, filename..".lua")
@@ -353,7 +355,8 @@ class NomsuCompiler
_chunk_counter += 1
"<lua chunk ##{_chunk_counter}>"
else
- lua.source.text_name..".lua"
+ lua.source.filename..".lua"
+ FILE_CACHE[filename] = tostring(lua)
if type(lua) != 'string'
lua, metadata = lua\make_offset_table(filename)
LUA_METADATA[lua] = metadata
@@ -373,7 +376,7 @@ class NomsuCompiler
if tree.type == 'Text' and #tree.value == 1 and type(tree.value[1]) == 'string'
return tree.value[1]
lua = Lua(tree.source, "return ",@tree_to_lua(tree),";")
- return @run_lua(lua, tree.source.text_name)
+ return @run_lua(lua, tree.source.filename)
tree_to_nomsu: (tree, indentation="", max_line=80, expr_type=nil)=>
-- Convert a tree into nomsu code that satisfies the max line requirement or nil
@@ -659,11 +662,11 @@ class NomsuCompiler
return file_lua
when "Comment"
- return Lua(tree.source, "--"..tree.value\gsub("\n","\n--"))
+ return Lua(tree.source, "--"..tree.value\gsub("\n","\n--").."\n")
when "Nomsu"
--return Lua(tree.source, repr(tree.value))
- return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.text_name),")")
+ return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.filename),")")
when "Block"
block_lua = Lua(tree.source)
@@ -688,9 +691,9 @@ class NomsuCompiler
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]]
+ new_args = [args[p-1] for p in *metadata.arg_orders[stub]]
args = new_args
- lua = action(unpack(args))
+ lua = action(tree, unpack(args))
remove @compilestack
return lua
elseif not metadata and @@math_patt\match(stub)
@@ -1005,15 +1008,51 @@ class NomsuCompiler
-- Sets up some core functionality
get_line_no = -> "nomsu.moon:#{debug_getinfo(2).currentline}"
nomsu = self
- @define_compile_action "immediately %block", get_line_no!, (_block)->
+ @define_compile_action "immediately %block", get_line_no!, (_block)=>
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(@source, "if IMMEDIATE then\n", lua, "\nend")
- @define_compile_action "lua> %code", get_line_no!, (_code)->
+ @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),")")
+ return LuaValue(@source, "Lua(", repr(_code.source),", ",nomsu\tree_to_lua(_code),")")
+
+ lua = LuaValue(@source, "Lua(", repr(_code.source))
+ for bit in *_code.value
+ lua\append ", "
+ if type(bit) == "string"
+ lua\append repr(bit)
+ else
+ bit_lua = nomsu\tree_to_lua bit
+ unless bit_lua.is_value
+ line, src = bit.source\get_line!, bit.source\get_text!
+ error "#{line}: Cannot use #{colored.yellow src} as a string interpolation value, since it's not an expression.", 0
+ lua\append bit_lua
+ lua\append ")"
+ return lua
+
+ @define_compile_action "LuaValue %code", get_line_no!, (_code)=>
+ if _code.type != "Text"
+ return LuaValue(@source, "LuaValue(", repr(_code.source),", ",nomsu\tree_to_lua(_code),")")
+
+ lua = LuaValue(@source, "LuaValue(", repr(_code.source))
+ for bit in *_code.value
+ lua\append ", "
+ if type(bit) == "string"
+ lua\append repr(bit)
+ else
+ bit_lua = nomsu\tree_to_lua bit
+ unless bit_lua.is_value
+ line, src = bit.source\get_line!, bit.source\get_text!
+ error "#{line}: Cannot use #{colored.yellow src} as a string interpolation value, since it's not an expression.", 0
+ lua\append bit_lua
+ lua\append ")"
+ return lua
+
+ @define_compile_action "lua> %code", get_line_no!, (_code)=>
+ if _code.type != "Text"
+ return LuaValue(@source, "nomsu:run_lua(",nomsu\tree_to_lua(_code),")")
lua = Lua(_code.source)
for bit in *_code.value
@@ -1027,11 +1066,11 @@ class NomsuCompiler
lua\append bit_lua
return lua
- @define_compile_action "=lua %code", get_line_no!, (_code)->
+ @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),")")
+ return LuaValue(@source, "nomsu:run_lua(",nomsu\tree_to_lua(_code),")")
- lua = LuaValue(_code.source)
+ lua = LuaValue(@source)
for bit in *_code.value
if type(bit) == "string"
lua\append bit
@@ -1043,18 +1082,16 @@ class NomsuCompiler
lua\append bit_lua
return lua
- @define_compile_action "!! code location !!", get_line_no!, ->
- tree = nomsu.compilestack[#nomsu.compilestack-1]
- return LuaValue(tree.source, repr(tostring(tree.source)))
+ @define_compile_action "!! code location !!", get_line_no!, =>
+ return LuaValue(@source, repr(@source))
@define_action "run file %filename", get_line_no!, (_filename)->
return nomsu\run_file(_filename)
- @define_compile_action "use %filename", get_line_no!, (_filename)->
- tree = nomsu.compilestack[#nomsu.compilestack-1]
+ @define_compile_action "use %filename", get_line_no!, (_filename)=>
filename = nomsu\tree_to_value(_filename)
nomsu\use_file(filename)
- return LuaValue(tree.source, "nomsu:use_file(#{repr filename})")
+ return LuaValue(@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