Incremental progress.
This commit is contained in:
parent
b9827b1745
commit
17a2bded6a
@ -26,7 +26,7 @@ immediately:
|
|||||||
end
|
end
|
||||||
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
|
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
|
||||||
body_lua:declare_locals(args);
|
body_lua:declare_locals(args);
|
||||||
lua:append("\n ", body_lua, "\nend);")
|
lua:append("\\n ", body_lua, "\\nend);")
|
||||||
return lua;
|
return lua;
|
||||||
end);
|
end);
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ immediately:
|
|||||||
end
|
end
|
||||||
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
|
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
|
||||||
body_lua:declare_locals(args);
|
body_lua:declare_locals(args);
|
||||||
lua:append("\n ", body_lua, "\nend);")
|
lua:append("\\n ", body_lua, "\\nend);")
|
||||||
return lua;
|
return lua;
|
||||||
|
|
||||||
# Macro to make nomsu macros:
|
# Macro to make nomsu macros:
|
||||||
@ -76,10 +76,10 @@ immediately:
|
|||||||
local template;
|
local template;
|
||||||
if \%longhand.type == "Block" then
|
if \%longhand.type == "Block" then
|
||||||
local lines = {};
|
local lines = {};
|
||||||
for i, line in ipairs(\%longhand.value) do lines[i] = nomsu:get_source_code(line); end
|
for i, line in ipairs(\%longhand.value) do lines[i] = line.source:get_text(); end
|
||||||
template = repr(table.concat(lines, "\\n"));
|
template = repr(table.concat(lines, "\\n"));
|
||||||
else
|
else
|
||||||
template = repr(nomsu:get_source_code(\%longhand));
|
template = repr(\%longhand.source:get_text());
|
||||||
end
|
end
|
||||||
local replacements = {};
|
local replacements = {};
|
||||||
for i, a in ipairs(args) do replacements[i] = a.."="..a; end
|
for i, a in ipairs(args) do replacements[i] = a.."="..a; end
|
||||||
@ -109,19 +109,16 @@ immediately:
|
|||||||
action [%tree as lua expr]:
|
action [%tree as lua expr]:
|
||||||
lua> ".."
|
lua> ".."
|
||||||
local lua = nomsu:tree_to_lua(\%tree);
|
local lua = nomsu:tree_to_lua(\%tree);
|
||||||
if lua.locals or not lua.expr then
|
if not lua.is_value then
|
||||||
error("Invalid thing to convert to lua expr: "..nomsu:get_source_code(\%tree));
|
error("Invalid thing to convert to lua expr: "..\%tree.source:get_text());
|
||||||
end
|
end
|
||||||
return lua.expr;
|
return lua;
|
||||||
|
|
||||||
action [%tree as lua statements]:
|
action [%tree as lua statements]:
|
||||||
lua> ".."
|
lua> ".."
|
||||||
local lua = nomsu:tree_to_lua(\%tree);
|
local lua = nomsu:tree_to_lua(\%tree):as_statements();
|
||||||
local code = lua.statements or (lua.expr..";");
|
lua:declare_locals();
|
||||||
if lua.locals then
|
return lua;
|
||||||
code = "local "..table.concat(lua.locals, ", ")..";\\n"..code;
|
|
||||||
end
|
|
||||||
return code;
|
|
||||||
|
|
||||||
action [%tree as value]:
|
action [%tree as value]:
|
||||||
=lua "nomsu:tree_to_value(\%tree)"
|
=lua "nomsu:tree_to_value(\%tree)"
|
||||||
@ -130,7 +127,7 @@ immediately:
|
|||||||
=lua "nomsu:tree_to_stub(\%tree)"
|
=lua "nomsu:tree_to_stub(\%tree)"
|
||||||
|
|
||||||
immediately:
|
immediately:
|
||||||
compile [%tree's source code, %tree' source code] to {expr:"nomsu:get_source_code(\(%tree as lua expr))"}
|
compile [%tree's source code, %tree' source code] to {expr:"\(%tree as lua expr).source:get_text()"}
|
||||||
|
|
||||||
compile [repr %obj] to {expr:"repr(\(%obj as lua expr))"}
|
compile [repr %obj] to {expr:"repr(\(%obj as lua expr))"}
|
||||||
compile [type of %obj] to {expr:"type(\(%obj as lua expr))"}
|
compile [type of %obj] to {expr:"type(\(%obj as lua expr))"}
|
||||||
@ -190,7 +187,7 @@ immediately:
|
|||||||
compile [barf] to {statements:"error(nil, 0);"}
|
compile [barf] to {statements:"error(nil, 0);"}
|
||||||
compile [barf %msg] to {statements:"error(\(%msg as lua expr), 0);"}
|
compile [barf %msg] to {statements:"error(\(%msg as lua expr), 0);"}
|
||||||
compile [assume %condition] to:
|
compile [assume %condition] to:
|
||||||
lua> "local \%assumption = 'Assumption failed: '..nomsu:get_source_code(\%condition);"
|
lua> "local \%assumption = 'Assumption failed: '..\%condition.source:get_text();"
|
||||||
return {..}
|
return {..}
|
||||||
statements:".."
|
statements:".."
|
||||||
if not \(%condition as lua expr) then
|
if not \(%condition as lua expr) then
|
||||||
|
24
lua_obj.moon
24
lua_obj.moon
@ -1,10 +1,12 @@
|
|||||||
{:insert, :remove, :concat} = table
|
{:insert, :remove, :concat} = table
|
||||||
immutable = require 'immutable'
|
immutable = require 'immutable'
|
||||||
local Lua, LuaValue, Location
|
local Lua, LuaValue, Location
|
||||||
|
export LINE_STARTS
|
||||||
|
|
||||||
Location = immutable {"text_name","text","start","stop"}, {
|
Location = immutable {"text_name","text","start","stop"}, {
|
||||||
__new: (text_name, text, start, stop)-> text_name, text, start, stop or start
|
name:"Location"
|
||||||
__tostring: "#{text_name}[#{start}:#{stop}]"
|
__new: (text_name, text, start, stop)=> text_name, text, start, stop or start
|
||||||
|
__tostring: => "#{@text_name}[#{@start}:#{@stop}]"
|
||||||
__lt: (other)=>
|
__lt: (other)=>
|
||||||
assert(@text == other.text, "Cannot compare sources from different texts")
|
assert(@text == other.text, "Cannot compare sources from different texts")
|
||||||
return if @start == other.start
|
return if @start == other.start
|
||||||
@ -20,10 +22,10 @@ Location = immutable {"text_name","text","start","stop"}, {
|
|||||||
-- TODO: do a binary search if this is actually slow, which I doubt
|
-- TODO: do a binary search if this is actually slow, which I doubt
|
||||||
line_starts = LINE_STARTS[@text]
|
line_starts = LINE_STARTS[@text]
|
||||||
start_line = 1
|
start_line = 1
|
||||||
while start_line < #line_starts and line_starts[start_line+1] <= @start
|
while (line_starts[start_line+1] or (#src+1)) <= @start
|
||||||
start_line += 1
|
start_line += 1
|
||||||
stop_line = start_line
|
stop_line = start_line
|
||||||
while stop_line < #line_starts and line_starts[stop_line+1] <= @stop
|
while (line_starts[stop_line+1] or (#src+1)) <= @stop
|
||||||
stop_line += 1
|
stop_line += 1
|
||||||
return start_line, stop_line
|
return start_line, stop_line
|
||||||
get_line: => "#{@text_name}:#{@get_line_number}"
|
get_line: => "#{@text_name}:#{@get_line_number}"
|
||||||
@ -38,7 +40,7 @@ class Lua
|
|||||||
is_statement: true
|
is_statement: true
|
||||||
is_value: false
|
is_value: false
|
||||||
|
|
||||||
__new: (@source, ...)=>
|
new: (@source, ...)=>
|
||||||
@bits = {...}
|
@bits = {...}
|
||||||
@free_vars = {}
|
@free_vars = {}
|
||||||
|
|
||||||
@ -63,11 +65,7 @@ class Lua
|
|||||||
__tostring: =>
|
__tostring: =>
|
||||||
buff = {}
|
buff = {}
|
||||||
for b in *@bits
|
for b in *@bits
|
||||||
if type(b) == 'string'
|
buff[#buff+1] = tostring(b)
|
||||||
buff[#buff+1] = b
|
|
||||||
else
|
|
||||||
for sub in *b\render!
|
|
||||||
buff[#buff+1] = sub
|
|
||||||
return concat(buff, "")
|
return concat(buff, "")
|
||||||
|
|
||||||
__len: =>
|
__len: =>
|
||||||
@ -105,7 +103,7 @@ class Lua
|
|||||||
lua_offset += #lua
|
lua_offset += #lua
|
||||||
else
|
else
|
||||||
lua_start = lua_offset
|
lua_start = lua_offset
|
||||||
for b in lua.bits
|
for b in *lua.bits
|
||||||
walk b
|
walk b
|
||||||
lua_stop = lua_offset
|
lua_stop = lua_offset
|
||||||
nomsu_src, lua_src = lua.souce, Location(lua_chunkname, lua_str, lua_start, lua_stop)
|
nomsu_src, lua_src = lua.souce, Location(lua_chunkname, lua_str, lua_start, lua_stop)
|
||||||
@ -118,7 +116,7 @@ class LuaValue extends Lua
|
|||||||
is_statement: false
|
is_statement: false
|
||||||
is_value: true
|
is_value: true
|
||||||
|
|
||||||
__new: (@source, ...)=>
|
new: (@source, ...)=>
|
||||||
@bits = {...}
|
@bits = {...}
|
||||||
|
|
||||||
as_statements: =>
|
as_statements: =>
|
||||||
@ -130,4 +128,4 @@ class LuaValue extends Lua
|
|||||||
@prepend "("
|
@prepend "("
|
||||||
@append ")"
|
@append ")"
|
||||||
|
|
||||||
return {:Lua, :LuaValue}
|
return {:Lua, :LuaValue, :Location}
|
||||||
|
82
nomsu.lua
82
nomsu.lua
@ -27,6 +27,11 @@ do
|
|||||||
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
|
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
|
||||||
end
|
end
|
||||||
local debug_getinfo = debug.getinfo
|
local debug_getinfo = debug.getinfo
|
||||||
|
local Lua, LuaValue, Location
|
||||||
|
do
|
||||||
|
local _obj_0 = require("lua_obj")
|
||||||
|
Lua, LuaValue, Location = _obj_0.Lua, _obj_0.LuaValue, _obj_0.Location
|
||||||
|
end
|
||||||
local FILE_CACHE = setmetatable({ }, {
|
local FILE_CACHE = setmetatable({ }, {
|
||||||
__index = function(self, filename)
|
__index = function(self, filename)
|
||||||
local file = io.open(filename)
|
local file = io.open(filename)
|
||||||
@ -44,7 +49,7 @@ local line_counter = re.compile([[ lines <- {| line (%nl line)* |}
|
|||||||
]], {
|
]], {
|
||||||
nl = P("\r") ^ -1 * P("\n")
|
nl = P("\r") ^ -1 * P("\n")
|
||||||
})
|
})
|
||||||
local LINE_STARTS = setmetatable({ }, {
|
LINE_STARTS = setmetatable({ }, {
|
||||||
__mode = "k",
|
__mode = "k",
|
||||||
__index = function(self, k)
|
__index = function(self, k)
|
||||||
local line_starts = line_counter:match(k)
|
local line_starts = line_counter:match(k)
|
||||||
@ -83,16 +88,7 @@ end
|
|||||||
local Types = { }
|
local Types = { }
|
||||||
local type_tostring
|
local type_tostring
|
||||||
type_tostring = function(self)
|
type_tostring = function(self)
|
||||||
return tostring(self.name) .. "(" .. tostring(concat((function()
|
return tostring(self.name) .. "(" .. tostring(repr(self.value)) .. ")"
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for _index_0 = 1, #self do
|
|
||||||
local x = self[_index_0]
|
|
||||||
_accum_0[_len_0] = repr(x)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
return _accum_0
|
|
||||||
end)(), ", ")) .. ")"
|
|
||||||
end
|
end
|
||||||
local type_with_value
|
local type_with_value
|
||||||
type_with_value = function(self, value)
|
type_with_value = function(self, value)
|
||||||
@ -200,12 +196,12 @@ do
|
|||||||
pos = pos + #lpeg.userdata.source_code:match("[ \t\n\r]*", pos)
|
pos = pos + #lpeg.userdata.source_code:match("[ \t\n\r]*", pos)
|
||||||
end
|
end
|
||||||
local line_no = 1
|
local line_no = 1
|
||||||
local text_loc = Source(lpeg.userdata.filename, src, pos)
|
local text_loc = Location(lpeg.userdata.filename, src, pos)
|
||||||
line_no = text_loc:get_line_number()
|
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 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)
|
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 1)
|
||||||
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 1)
|
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 1)
|
||||||
local pointer = ("-"):rep(pos - LINE_STARTS[line_no]) .. "^"
|
local pointer = ("-"):rep(pos - LINE_STARTS[src][line_no]) .. "^"
|
||||||
err_msg = (err_msg or "Parse error") .. " in " .. tostring(lpeg.userdata.filename) .. " on line " .. tostring(line_no) .. ":\n"
|
err_msg = (err_msg or "Parse error") .. " in " .. tostring(lpeg.userdata.filename) .. " on line " .. tostring(line_no) .. ":\n"
|
||||||
err_msg = err_msg .. "\n" .. tostring(prev_line) .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer) .. "\n" .. tostring(next_line) .. "\n"
|
err_msg = err_msg .. "\n" .. tostring(prev_line) .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer) .. "\n" .. tostring(next_line) .. "\n"
|
||||||
return error(err_msg)
|
return error(err_msg)
|
||||||
@ -219,7 +215,7 @@ setmetatable(NOMSU_DEFS, {
|
|||||||
if type(value) == 'table' then
|
if type(value) == 'table' then
|
||||||
error("Not a tuple: " .. tostring(repr(value)))
|
error("Not a tuple: " .. tostring(repr(value)))
|
||||||
end
|
end
|
||||||
local loc = Source(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
|
local loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
|
||||||
local node = Types[key](value, loc)
|
local node = Types[key](value, loc)
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
@ -360,13 +356,6 @@ do
|
|||||||
end
|
end
|
||||||
return code:gsub("\n", "\n" .. (" "):rep(levels))
|
return code:gsub("\n", "\n" .. (" "):rep(levels))
|
||||||
end,
|
end,
|
||||||
get_source_code = function(self, tree)
|
|
||||||
local metadata = self.tree_metadata[tree]
|
|
||||||
if not (metadata) then
|
|
||||||
return self:tree_to_nomsu(tree)
|
|
||||||
end
|
|
||||||
return self:dedent(metadata.source_code:sub(metadata.start, metadata.stop - 1))
|
|
||||||
end,
|
|
||||||
parse = function(self, nomsu_code, filename)
|
parse = function(self, nomsu_code, filename)
|
||||||
assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename)))
|
assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename)))
|
||||||
local userdata = {
|
local userdata = {
|
||||||
@ -374,8 +363,7 @@ do
|
|||||||
filename = filename,
|
filename = filename,
|
||||||
indent_stack = {
|
indent_stack = {
|
||||||
""
|
""
|
||||||
},
|
}
|
||||||
tree_metadata = self.tree_metadata
|
|
||||||
}
|
}
|
||||||
local old_userdata
|
local old_userdata
|
||||||
old_userdata, lpeg.userdata = lpeg.userdata, userdata
|
old_userdata, lpeg.userdata = lpeg.userdata, userdata
|
||||||
@ -461,12 +449,12 @@ do
|
|||||||
_chunk_counter = _chunk_counter + 1
|
_chunk_counter = _chunk_counter + 1
|
||||||
filename = "<lua chunk #" .. tostring(_chunk_counter) .. ">"
|
filename = "<lua chunk #" .. tostring(_chunk_counter) .. ">"
|
||||||
else
|
else
|
||||||
filename = lua.source.filename .. ".lua"
|
filename = lua.source.text_name .. ".lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(lua) ~= 'string' then
|
if type(lua) ~= 'string' then
|
||||||
local metadata
|
local metadata
|
||||||
lua, metadata = make_offset_table(filename)
|
lua, metadata = lua:make_offset_table(filename)
|
||||||
LUA_METADATA[lua] = metadata
|
LUA_METADATA[lua] = metadata
|
||||||
end
|
end
|
||||||
local run_lua_fn, err = load(lua, filename, "t", self.environment)
|
local run_lua_fn, err = load(lua, filename, "t", self.environment)
|
||||||
@ -487,7 +475,7 @@ do
|
|||||||
return tree.value[1]
|
return tree.value[1]
|
||||||
end
|
end
|
||||||
local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";")
|
local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";")
|
||||||
return self:run_lua(lua, tree.source.filename)
|
return self:run_lua(lua, tree.source.text_name)
|
||||||
end,
|
end,
|
||||||
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
|
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
|
||||||
if indentation == nil then
|
if indentation == nil then
|
||||||
@ -885,7 +873,7 @@ do
|
|||||||
tree_to_lua = function(self, tree)
|
tree_to_lua = function(self, tree)
|
||||||
assert(tree, "No tree provided.")
|
assert(tree, "No tree provided.")
|
||||||
if not Types.is_node(tree) then
|
if not Types.is_node(tree) then
|
||||||
error("Invalid tree: " .. tostring(repr(tree)), 0)
|
error("Invalid tree")
|
||||||
end
|
end
|
||||||
local _exp_0 = tree.type
|
local _exp_0 = tree.type
|
||||||
if "File" == _exp_0 then
|
if "File" == _exp_0 then
|
||||||
@ -894,25 +882,23 @@ do
|
|||||||
end
|
end
|
||||||
local file_lua = Lua(tree.source)
|
local file_lua = Lua(tree.source)
|
||||||
local declared_locals = { }
|
local declared_locals = { }
|
||||||
local _list_1 = tree.value
|
for i, line in ipairs(tree.value) do
|
||||||
for _index_0 = 1, #_list_1 do
|
|
||||||
local line = _list_1[_index_0]
|
|
||||||
local line_lua = self:tree_to_lua(line)
|
local line_lua = self:tree_to_lua(line)
|
||||||
if not line_lua then
|
if not line_lua then
|
||||||
error("No lua produced by " .. tostring(repr(line)), 0)
|
error("No lua produced by " .. tostring(repr(line)), 0)
|
||||||
end
|
end
|
||||||
local lua = lua:as_statements()
|
line_lua = line_lua:as_statements()
|
||||||
if i < #tree.value then
|
if i < #tree.value then
|
||||||
file_lua:append("\n")
|
file_lua:append("\n")
|
||||||
end
|
end
|
||||||
file_lua:append(lua)
|
file_lua:append(line_lua)
|
||||||
end
|
end
|
||||||
file_lua:declare_locals()
|
file_lua:declare_locals()
|
||||||
return file_lua
|
return file_lua
|
||||||
elseif "Comment" == _exp_0 then
|
elseif "Comment" == _exp_0 then
|
||||||
return Lua(tree.source, "--" .. tree.value:gsub("\n", "\n--"))
|
return Lua(tree.source, "--" .. tree.value:gsub("\n", "\n--"))
|
||||||
elseif "Nomsu" == _exp_0 then
|
elseif "Nomsu" == _exp_0 then
|
||||||
return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.filename), ")")
|
return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.text_name), ")")
|
||||||
elseif "Block" == _exp_0 then
|
elseif "Block" == _exp_0 then
|
||||||
local block_lua = Lua(tree.source)
|
local block_lua = Lua(tree.source)
|
||||||
for i, arg in ipairs(tree.value) do
|
for i, arg in ipairs(tree.value) do
|
||||||
@ -947,7 +933,6 @@ do
|
|||||||
end
|
end
|
||||||
args = _accum_0
|
args = _accum_0
|
||||||
end
|
end
|
||||||
table.insert(args, 1, tree.source)
|
|
||||||
if metadata and metadata.arg_orders then
|
if metadata and metadata.arg_orders then
|
||||||
local new_args
|
local new_args
|
||||||
do
|
do
|
||||||
@ -1002,7 +987,7 @@ do
|
|||||||
local line, src = tok.source:get_line(), tok.source:get_text()
|
local line, src = tok.source:get_line(), tok.source:get_text()
|
||||||
error(tostring(line) .. ": Cannot use:\n" .. tostring(colored.yellow(src)) .. "\nas an argument to " .. tostring(stub) .. ", since it's not an expression, it produces: " .. tostring(repr(arg_lua)), 0)
|
error(tostring(line) .. ": Cannot use:\n" .. tostring(colored.yellow(src)) .. "\nas an argument to " .. tostring(stub) .. ", since it's not an expression, it produces: " .. tostring(repr(arg_lua)), 0)
|
||||||
end
|
end
|
||||||
insert(args, lua)
|
insert(args, arg_lua)
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
until true
|
until true
|
||||||
if not _continue_0 then
|
if not _continue_0 then
|
||||||
@ -1402,7 +1387,7 @@ do
|
|||||||
lua:append(bit)
|
lua:append(bit)
|
||||||
else
|
else
|
||||||
local bit_lua = nomsu:tree_to_lua(bit)
|
local bit_lua = nomsu:tree_to_lua(bit)
|
||||||
if not (lua.is_value) then
|
if not (bit_lua.is_value) then
|
||||||
local line, src = bit.source:get_line(), bit.source:get_text()
|
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)
|
error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a string interpolation value, since it's not an expression.", 0)
|
||||||
end
|
end
|
||||||
@ -1434,16 +1419,9 @@ do
|
|||||||
end)
|
end)
|
||||||
self:define_compile_action("!! code location !!", get_line_no(), function()
|
self:define_compile_action("!! code location !!", get_line_no(), function()
|
||||||
local tree = nomsu.compilestack[#nomsu.compilestack - 1]
|
local tree = nomsu.compilestack[#nomsu.compilestack - 1]
|
||||||
local metadata = self.tree_metadata[tree]
|
return LuaValue(tree.source, {
|
||||||
if metadata then
|
repr(tostring(tree.source))
|
||||||
return LuaValue(tree.source, {
|
})
|
||||||
repr(tostring(metadata.filename) .. ":" .. tostring(metadata.start) .. "," .. tostring(metadata.stop))
|
|
||||||
})
|
|
||||||
else
|
|
||||||
return LuaValue(tree.source, {
|
|
||||||
repr("<dynamically generated>")
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
self:define_action("run file %filename", get_line_no(), function(_filename)
|
self:define_action("run file %filename", get_line_no(), function(_filename)
|
||||||
return nomsu:run_file(_filename)
|
return nomsu:run_file(_filename)
|
||||||
@ -1624,20 +1602,16 @@ if arg and debug_getinfo(2).func ~= require then
|
|||||||
if not info or not info.func then
|
if not info or not info.func then
|
||||||
return info
|
return info
|
||||||
end
|
end
|
||||||
if info.source and NOMSU_LINE_TABLES[info.source] then
|
if info.source and info.source:sub(1, 1) ~= "@" and LINE_STARTS[info.source] then
|
||||||
do
|
do
|
||||||
local metadata = nomsu.action_metadata[info.func]
|
local metadata = nomsu.action_metadata[info.func]
|
||||||
if metadata then
|
if metadata then
|
||||||
info.name = metadata.aliases[1]
|
info.name = metadata.aliases[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
info.short_src = NOMSU_SOURCE_FILE[info.source]
|
if info.source:sub(1, 1) == "@" then
|
||||||
lua_line_to_nomsu_line(info.source, info)
|
error("Not-yet-loaded source: " .. tostring(info.source))
|
||||||
info.short_src = metadata.source.text_name
|
end
|
||||||
info.source = metadata.source.text
|
|
||||||
info.linedefined = metadata.source:get_line_number()
|
|
||||||
info.currentline = LUA_LINE_TO_NOMSU_LINE[metadata.source.filename][info.currentline]
|
|
||||||
local name = colored.bright(colored.yellow(metadata.aliases[1]))
|
|
||||||
else
|
else
|
||||||
if info.short_src and info.short_src:match("^.*%.moon$") then
|
if info.short_src and info.short_src:match("^.*%.moon$") then
|
||||||
local line_table = moonscript_line_tables[info.short_src]
|
local line_table = moonscript_line_tables[info.short_src]
|
||||||
|
62
nomsu.moon
62
nomsu.moon
@ -23,6 +23,7 @@ colors = setmetatable({}, {__index:->""})
|
|||||||
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
|
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
|
||||||
{:insert, :remove, :concat} = table
|
{:insert, :remove, :concat} = table
|
||||||
debug_getinfo = debug.getinfo
|
debug_getinfo = debug.getinfo
|
||||||
|
{:Lua, :LuaValue, :Location} = require "lua_obj"
|
||||||
|
|
||||||
-- TODO:
|
-- TODO:
|
||||||
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
|
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
|
||||||
@ -49,6 +50,7 @@ line_counter = re.compile([[
|
|||||||
line <- {} (!%nl .)*
|
line <- {} (!%nl .)*
|
||||||
]], nl:P("\r")^-1 * P("\n"))
|
]], nl:P("\r")^-1 * P("\n"))
|
||||||
-- Mapping from line number -> character offset
|
-- Mapping from line number -> character offset
|
||||||
|
export LINE_STARTS
|
||||||
LINE_STARTS = setmetatable {}, {
|
LINE_STARTS = setmetatable {}, {
|
||||||
__mode:"k"
|
__mode:"k"
|
||||||
__index: (k)=>
|
__index: (k)=>
|
||||||
@ -86,7 +88,7 @@ do
|
|||||||
|
|
||||||
Types = {}
|
Types = {}
|
||||||
type_tostring = =>
|
type_tostring = =>
|
||||||
"#{@name}(#{concat [repr(x) for x in *@], ", "})"
|
"#{@name}(#{repr(@value)})"
|
||||||
type_with_value = (value)=> getmetatable(self)(@source, value)
|
type_with_value = (value)=> getmetatable(self)(@source, value)
|
||||||
Tuple = immutable(nil, {name:"Tuple"})
|
Tuple = immutable(nil, {name:"Tuple"})
|
||||||
for t in *{"File", "Nomsu", "Block", "List", "FunctionCall", "Text", "Dict", "Number", "Word", "Var", "Comment", "IndexChain"}
|
for t in *{"File", "Nomsu", "Block", "List", "FunctionCall", "Text", "Dict", "Number", "Word", "Var", "Comment", "IndexChain"}
|
||||||
@ -146,12 +148,12 @@ NOMSU_DEFS = with {}
|
|||||||
if lpeg.userdata.source_code\sub(pos,pos)\match("[\r\n]")
|
if lpeg.userdata.source_code\sub(pos,pos)\match("[\r\n]")
|
||||||
pos += #lpeg.userdata.source_code\match("[ \t\n\r]*", pos)
|
pos += #lpeg.userdata.source_code\match("[ \t\n\r]*", pos)
|
||||||
line_no = 1
|
line_no = 1
|
||||||
text_loc = Source(lpeg.userdata.filename, src, pos)
|
text_loc = Location(lpeg.userdata.filename, src, pos)
|
||||||
line_no = text_loc\get_line_number!
|
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)
|
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)
|
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-1)
|
||||||
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-1)
|
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-1)
|
||||||
pointer = ("-")\rep(pos-LINE_STARTS[line_no]) .. "^"
|
pointer = ("-")\rep(pos-LINE_STARTS[src][line_no]) .. "^"
|
||||||
err_msg = (err_msg or "Parse error").." in #{lpeg.userdata.filename} on line #{line_no}:\n"
|
err_msg = (err_msg or "Parse error").." in #{lpeg.userdata.filename} on line #{line_no}:\n"
|
||||||
err_msg ..="\n#{prev_line}\n#{err_line}\n#{pointer}\n#{next_line}\n"
|
err_msg ..="\n#{prev_line}\n#{err_line}\n#{pointer}\n#{next_line}\n"
|
||||||
error(err_msg)
|
error(err_msg)
|
||||||
@ -159,7 +161,7 @@ NOMSU_DEFS = with {}
|
|||||||
setmetatable(NOMSU_DEFS, {__index:(key)=>
|
setmetatable(NOMSU_DEFS, {__index:(key)=>
|
||||||
make_node = (start, value, stop)->
|
make_node = (start, value, stop)->
|
||||||
if type(value) == 'table' then error("Not a tuple: #{repr value}")-- = Tuple(value)
|
if type(value) == 'table' then error("Not a tuple: #{repr value}")-- = Tuple(value)
|
||||||
loc = Source(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
|
loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
|
||||||
node = Types[key](value, loc)
|
node = Types[key](value, loc)
|
||||||
return node
|
return node
|
||||||
self[key] = make_node
|
self[key] = make_node
|
||||||
@ -279,19 +281,11 @@ class NomsuCompiler
|
|||||||
indent: (code, levels=1)=>
|
indent: (code, levels=1)=>
|
||||||
return code\gsub("\n","\n"..(" ")\rep(levels))
|
return code\gsub("\n","\n"..(" ")\rep(levels))
|
||||||
|
|
||||||
get_source_code: (tree)=>
|
|
||||||
-- Return the (dedented) source code of a tree, or construct some if the tree was
|
|
||||||
-- dynamically generated.
|
|
||||||
metadata = @tree_metadata[tree]
|
|
||||||
unless metadata
|
|
||||||
return @tree_to_nomsu(tree)
|
|
||||||
return @dedent metadata.source_code\sub(metadata.start, metadata.stop-1)
|
|
||||||
|
|
||||||
parse: (nomsu_code, filename)=>
|
parse: (nomsu_code, filename)=>
|
||||||
assert type(filename) == "string", "Bad filename type: #{type filename}"
|
assert type(filename) == "string", "Bad filename type: #{type filename}"
|
||||||
|
|
||||||
userdata = {
|
userdata = {
|
||||||
source_code:nomsu_code, :filename, indent_stack: {""}, tree_metadata:@tree_metadata,
|
source_code:nomsu_code, :filename, indent_stack: {""}
|
||||||
}
|
}
|
||||||
|
|
||||||
old_userdata, lpeg.userdata = lpeg.userdata, userdata
|
old_userdata, lpeg.userdata = lpeg.userdata, userdata
|
||||||
@ -355,9 +349,9 @@ class NomsuCompiler
|
|||||||
_chunk_counter += 1
|
_chunk_counter += 1
|
||||||
"<lua chunk ##{_chunk_counter}>"
|
"<lua chunk ##{_chunk_counter}>"
|
||||||
else
|
else
|
||||||
lua.source.filename..".lua"
|
lua.source.text_name..".lua"
|
||||||
if type(lua) != 'string'
|
if type(lua) != 'string'
|
||||||
lua, metadata = make_offset_table(filename)
|
lua, metadata = lua\make_offset_table(filename)
|
||||||
LUA_METADATA[lua] = metadata
|
LUA_METADATA[lua] = metadata
|
||||||
|
|
||||||
run_lua_fn, err = load(lua, filename, "t", @environment)
|
run_lua_fn, err = load(lua, filename, "t", @environment)
|
||||||
@ -375,7 +369,7 @@ class NomsuCompiler
|
|||||||
if tree.type == 'Text' and #tree.value == 1 and type(tree.value[1]) == 'string'
|
if tree.type == 'Text' and #tree.value == 1 and type(tree.value[1]) == 'string'
|
||||||
return tree.value[1]
|
return tree.value[1]
|
||||||
lua = Lua(tree.source, "return ",@tree_to_lua(tree),";")
|
lua = Lua(tree.source, "return ",@tree_to_lua(tree),";")
|
||||||
return @run_lua(lua, tree.source.filename)
|
return @run_lua(lua, tree.source.text_name)
|
||||||
|
|
||||||
tree_to_nomsu: (tree, indentation="", max_line=80, expr_type=nil)=>
|
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
|
-- Convert a tree into nomsu code that satisfies the max line requirement or nil
|
||||||
@ -640,22 +634,23 @@ class NomsuCompiler
|
|||||||
-- Return <lua code for value>, <additional lua code>
|
-- Return <lua code for value>, <additional lua code>
|
||||||
assert tree, "No tree provided."
|
assert tree, "No tree provided."
|
||||||
if not Types.is_node(tree)
|
if not Types.is_node(tree)
|
||||||
error("Invalid tree: #{repr(tree)}", 0)
|
--error("Invalid tree: #{repr(tree)}", 0)
|
||||||
|
error("Invalid tree")
|
||||||
switch tree.type
|
switch tree.type
|
||||||
when "File"
|
when "File"
|
||||||
if #tree.value == 1
|
if #tree.value == 1
|
||||||
return @tree_to_lua(tree.value[1])
|
return @tree_to_lua(tree.value[1])
|
||||||
file_lua = Lua(tree.source)
|
file_lua = Lua(tree.source)
|
||||||
declared_locals = {}
|
declared_locals = {}
|
||||||
for line in *tree.value
|
for i, line in ipairs tree.value
|
||||||
line_lua = @tree_to_lua line
|
line_lua = @tree_to_lua line
|
||||||
if not line_lua
|
if not line_lua
|
||||||
error("No lua produced by #{repr line}", 0)
|
error("No lua produced by #{repr line}", 0)
|
||||||
lua = lua\as_statements!
|
line_lua = line_lua\as_statements!
|
||||||
if i < #tree.value
|
if i < #tree.value
|
||||||
file_lua\append "\n"
|
file_lua\append "\n"
|
||||||
|
|
||||||
file_lua\append lua
|
file_lua\append line_lua
|
||||||
file_lua\declare_locals!
|
file_lua\declare_locals!
|
||||||
return file_lua
|
return file_lua
|
||||||
|
|
||||||
@ -664,7 +659,7 @@ class NomsuCompiler
|
|||||||
|
|
||||||
when "Nomsu"
|
when "Nomsu"
|
||||||
--return Lua(tree.source, repr(tree.value))
|
--return Lua(tree.source, repr(tree.value))
|
||||||
return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.filename),")")
|
return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.text_name),")")
|
||||||
|
|
||||||
when "Block"
|
when "Block"
|
||||||
block_lua = Lua(tree.source)
|
block_lua = Lua(tree.source)
|
||||||
@ -688,7 +683,6 @@ class NomsuCompiler
|
|||||||
if metadata and metadata.compile_time
|
if metadata and metadata.compile_time
|
||||||
args = [arg for arg in *tree.value when arg.type != "Word"]
|
args = [arg for arg in *tree.value when arg.type != "Word"]
|
||||||
-- Force all compile-time actions to take a tree location
|
-- Force all compile-time actions to take a tree location
|
||||||
table.insert args, 1, tree.source
|
|
||||||
if metadata and metadata.arg_orders
|
if metadata and metadata.arg_orders
|
||||||
new_args = [args[p] for p in *metadata.arg_orders[stub]]
|
new_args = [args[p] for p in *metadata.arg_orders[stub]]
|
||||||
args = new_args
|
args = new_args
|
||||||
@ -722,7 +716,7 @@ class NomsuCompiler
|
|||||||
unless arg_lua.is_value
|
unless arg_lua.is_value
|
||||||
line, src = tok.source\get_line!, tok.source\get_text!
|
line, src = tok.source\get_line!, tok.source\get_text!
|
||||||
error "#{line}: Cannot use:\n#{colored.yellow src}\nas an argument to #{stub}, since it's not an expression, it produces: #{repr arg_lua}", 0
|
error "#{line}: Cannot use:\n#{colored.yellow src}\nas an argument to #{stub}, since it's not an expression, it produces: #{repr arg_lua}", 0
|
||||||
insert args, lua
|
insert args, arg_lua
|
||||||
|
|
||||||
if metadata and metadata.arg_orders
|
if metadata and metadata.arg_orders
|
||||||
args = [args[p] for p in *metadata.arg_orders[stub]]
|
args = [args[p] for p in *metadata.arg_orders[stub]]
|
||||||
@ -1023,7 +1017,7 @@ class NomsuCompiler
|
|||||||
lua\append bit
|
lua\append bit
|
||||||
else
|
else
|
||||||
bit_lua = nomsu\tree_to_lua bit
|
bit_lua = nomsu\tree_to_lua bit
|
||||||
unless lua.is_value
|
unless bit_lua.is_value
|
||||||
line, src = bit.source\get_line!, bit.source\get_text!
|
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
|
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 bit_lua
|
||||||
@ -1047,11 +1041,7 @@ class NomsuCompiler
|
|||||||
|
|
||||||
@define_compile_action "!! code location !!", get_line_no!, ->
|
@define_compile_action "!! code location !!", get_line_no!, ->
|
||||||
tree = nomsu.compilestack[#nomsu.compilestack-1]
|
tree = nomsu.compilestack[#nomsu.compilestack-1]
|
||||||
metadata = @tree_metadata[tree]
|
return LuaValue(tree.source, {repr(tostring(tree.source))})
|
||||||
if metadata
|
|
||||||
return LuaValue(tree.source, {repr("#{metadata.filename}:#{metadata.start},#{metadata.stop}")})
|
|
||||||
else
|
|
||||||
return LuaValue(tree.source, {repr("<dynamically generated>")})
|
|
||||||
|
|
||||||
@define_action "run file %filename", get_line_no!, (_filename)->
|
@define_action "run file %filename", get_line_no!, (_filename)->
|
||||||
return nomsu\run_file(_filename)
|
return nomsu\run_file(_filename)
|
||||||
@ -1094,16 +1084,14 @@ if arg and debug_getinfo(2).func != require
|
|||||||
debug.getinfo = (...)->
|
debug.getinfo = (...)->
|
||||||
info = debug_getinfo(...)
|
info = debug_getinfo(...)
|
||||||
if not info or not info.func then return info
|
if not info or not info.func then return info
|
||||||
if info.source and NOMSU_LINE_TABLES[info.source]
|
if info.source and info.source\sub(1,1) != "@" and LINE_STARTS[info.source]
|
||||||
if metadata = nomsu.action_metadata[info.func]
|
if metadata = nomsu.action_metadata[info.func]
|
||||||
info.name = metadata.aliases[1]
|
info.name = metadata.aliases[1]
|
||||||
info.short_src = NOMSU_SOURCE_FILE[info.source]
|
if info.source\sub(1,1) == "@" then error("Not-yet-loaded source: #{info.source}")
|
||||||
lua_line_to_nomsu_line(info.source, info)
|
--info.linedefined = lua_line_to_nomsu_line(info.short_src, info.linedefined)
|
||||||
info.short_src = metadata.source.text_name
|
--info.currentline = lua_line_to_nomsu_line(info.short_src, info.currentline)
|
||||||
info.source = metadata.source.text
|
--info.short_src = metadata.source.text_name
|
||||||
info.linedefined = metadata.source\get_line_number!
|
--info.source = metadata.source.text
|
||||||
info.currentline = LUA_LINE_TO_NOMSU_LINE[metadata.source.filename][info.currentline]
|
|
||||||
name = colored.bright(colored.yellow(metadata.aliases[1]))
|
|
||||||
else
|
else
|
||||||
if info.short_src and info.short_src\match("^.*%.moon$")
|
if info.short_src and info.short_src\match("^.*%.moon$")
|
||||||
line_table = moonscript_line_tables[info.short_src]
|
line_table = moonscript_line_tables[info.short_src]
|
||||||
|
Loading…
Reference in New Issue
Block a user