aboutsummaryrefslogtreecommitdiff
path: root/nomsu.lua
diff options
context:
space:
mode:
Diffstat (limited to 'nomsu.lua')
-rw-r--r--nomsu.lua210
1 files changed, 103 insertions, 107 deletions
diff --git a/nomsu.lua b/nomsu.lua
index c103777..159b25f 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -126,15 +126,13 @@ do
end
return _accum_0
end)(), " ")
- local line_no = 1
- while (ctx.line_starts[line_no + 1] or math.huge) < start do
- line_no = line_no + 1
- end
local src = ctx.source_code:sub(start, stop - 1)
return {
+ start = start,
+ stop = stop,
type = "FunctionCall",
src = src,
- line_no = tostring(ctx.filename) .. ":" .. tostring(line_no),
+ get_line_no = ctx.get_line_no,
value = value,
stub = stub
}
@@ -149,6 +147,7 @@ do
stop = stop,
value = value,
src = ctx.source_code:sub(start, stop - 1),
+ get_line_no = ctx.get_line_no,
type = key
}
end
@@ -168,15 +167,26 @@ do
local nomsu = peg_tidier:match(io.open("nomsu.peg"):read("*a"))
nomsu = re.compile(nomsu, defs)
parse = function(source_code, filename)
- local old_ctx = ctx
- ctx = {
+ local _ctx = {
source_code = source_code,
filename = filename,
indent_stack = {
0
}
}
- ctx.line_starts = re.compile("lines <- {| line ('\n' line)* |} line <- {} [^\n]*"):match(source_code)
+ _ctx.line_starts = re.compile("lines <- {| line ('\n' line)* |} line <- {} [^\n]*"):match(source_code)
+ _ctx.get_line_no = function(self)
+ if not (self._line_no) then
+ local line_no = 1
+ while (_ctx.line_starts[line_no + 1] or math.huge) < self.start do
+ line_no = line_no + 1
+ end
+ self._line_no = tostring(_ctx.filename) .. ":" .. tostring(line_no)
+ end
+ return self._line_no
+ end
+ local old_ctx = ctx
+ ctx = _ctx
local tree = nomsu:match(source_code)
ctx = old_ctx
return tree
@@ -206,8 +216,6 @@ do
signature = self:get_stubs(signature)
end
self:assert(type(fn) == 'function', "Bad fn: " .. tostring(repr(fn)))
- local canonical_args = nil
- local canonical_escaped_args = nil
local aliases = { }
self.__class.def_number = self.__class.def_number + 1
local def = {
@@ -221,6 +229,7 @@ do
local where_defs_go = (getmetatable(self.defs) or { }).__newindex or self.defs
for sig_i = 1, #signature do
local stub, arg_names, escaped_args = unpack(signature[sig_i])
+ local arg_positions = { }
self:assert(stub, "NO STUB FOUND: " .. tostring(repr(signature)))
if self.debug then
self:writeln(tostring(colored.bright("DEFINING RULE:")) .. " " .. tostring(colored.underscore(colored.magenta(repr(stub)))) .. " " .. tostring(colored.bright("WITH ARGS")) .. " " .. tostring(colored.dim(repr(arg_names))))
@@ -232,22 +241,34 @@ do
end
end
end
- if canonical_args then
- self:assert(equivalent(set(arg_names), canonical_args), "Mismatched args")
- else
- canonical_args = set(arg_names)
- end
- if canonical_escaped_args then
- self:assert(equivalent(escaped_args, canonical_escaped_args), "Mismatched escaped args")
- else
- canonical_escaped_args = escaped_args
+ if sig_i == 1 then
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for i = 1, #arg_names do
+ _accum_0[_len_0] = i
+ _len_0 = _len_0 + 1
+ end
+ arg_positions = _accum_0
+ end
+ def.args = arg_names
def.escaped_args = escaped_args
+ else
+ self:assert(equivalent(set(def.args), set(arg_names)), "Mismatched args")
+ self:assert(equivalent(def.escaped_args, escaped_args), "Mismatched escaped args")
+ for j, a in ipairs(arg_names) do
+ for i, c_a in ipairs(def.args) do
+ if a == c_a then
+ arg_positions[j] = i
+ end
+ end
+ end
end
insert(def.aliases, stub)
local stub_def = setmetatable({
stub = stub,
arg_names = arg_names,
- escaped_args = escaped_args
+ arg_positions = arg_positions
}, {
__index = def
})
@@ -361,27 +382,30 @@ do
if not (def.is_macro) then
self:assert_permission(stub)
end
- local fn, arg_names
- fn, arg_names = def.fn, def.arg_names
+ local fn, arg_positions
+ fn, arg_positions = def.fn, def.arg_positions
local args
do
- local _tbl_0 = { }
- for i, name in ipairs(arg_names) do
- _tbl_0[name] = select(i, ...)
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #arg_positions do
+ local p = arg_positions[_index_0]
+ _accum_0[_len_0] = select(p, ...)
+ _len_0 = _len_0 + 1
end
- args = _tbl_0
+ args = _accum_0
end
if self.debug then
self:write(tostring(colored.bright("CALLING")) .. " " .. tostring(colored.magenta(colored.underscore(stub))) .. " ")
self:writeln(tostring(colored.bright("WITH ARGS:")))
- for name, value in pairs(args) do
- self:writeln(" " .. tostring(colored.bright("* " .. tostring(name))) .. " = " .. tostring(colored.dim(repr(value))))
+ for i, value in ipairs(args) do
+ self:writeln(" " .. tostring(colored.bright("* " .. tostring(def.args[i]))) .. " = " .. tostring(colored.dim(repr(value))))
end
end
local old_defs
old_defs, self.defs = self.defs, def.defs
local rets = {
- fn(self, args)
+ fn(self, unpack(args))
}
self.defs = old_defs
remove(self.callstack)
@@ -407,7 +431,7 @@ do
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
end
insert(self.callstack, "#macro")
- local ret = self:call(tree.stub, tree.line_no, unpack(args))
+ local ret = self:call(tree.stub, tree:get_line_no(), unpack(args))
remove(self.callstack)
return ret
end,
@@ -495,6 +519,7 @@ do
return false
end,
parse = function(self, str, filename)
+ self:assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename)))
if self.debug then
self:writeln(tostring(colored.bright("PARSING:")) .. "\n" .. tostring(colored.yellow(str)))
end
@@ -507,10 +532,7 @@ do
end
return tree
end,
- run = function(self, src, filename, vars, max_operations, output_file)
- if vars == nil then
- vars = { }
- end
+ run = function(self, src, filename, max_operations, output_file)
if max_operations == nil then
max_operations = nil
end
@@ -518,7 +540,7 @@ do
output_file = nil
end
if src == "" then
- return nil, "", vars
+ return nil, ""
end
if max_operations then
local timeout
@@ -534,21 +556,18 @@ do
local lua = self:tree_to_lua(tree, filename)
local lua_code = lua.statements or (lua.expr .. ";")
lua_code = "-- File: " .. tostring(filename) .. "\n" .. lua_code
- local ret = self:run_lua(lua_code, vars)
+ local ret = self:run_lua(lua_code)
if max_operations then
debug.sethook()
end
if output_file then
output_file:write(lua_code)
end
- return ret, lua_code, vars
+ return ret, lua_code
end,
- run_file = function(self, filename, vars)
- if vars == nil then
- vars = { }
- end
+ run_file = function(self, filename)
if filename:match(".*%.lua") then
- return dofile(filename)(self, vars)
+ return dofile(filename)(self)
end
if filename:match(".*%.nom") then
if not self.skip_precompiled then
@@ -556,7 +575,7 @@ do
if file then
local lua_code = file:read("*a")
file:close()
- return self:run_lua(lua_code, vars)
+ return self:run_lua(lua_code)
end
end
local file = file or io.open(filename)
@@ -570,23 +589,20 @@ do
return self:error("Invalid filetype for " .. tostring(filename))
end
end,
- require_file = function(self, filename, vars)
- if vars == nil then
- vars = { }
- end
+ require_file = function(self, filename)
local loaded = self.defs["#loaded_files"]
if not loaded[filename] then
- loaded[filename] = self:run_file(filename, vars) or true
+ loaded[filename] = self:run_file(filename) or true
end
return loaded[filename]
end,
- run_lua = function(self, lua_code, vars)
- if vars == nil then
- vars = { }
- end
- local load_lua_fn, err = load(([[return function(nomsu, vars)
+ run_lua = function(self, lua_code)
+ local load_lua_fn, err = load(([[return function(nomsu)
%s
end]]):format(lua_code))
+ if self.debug then
+ self:writeln(tostring(colored.bright("RUNNING LUA:")) .. "\n" .. tostring(colored.blue(colored.bright(lua_code))))
+ end
if not load_lua_fn then
local n = 1
local fn
@@ -598,15 +614,15 @@ end]]):format(lua_code))
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err))
end
local run_lua_fn = load_lua_fn()
- local ok, ret = pcall(run_lua_fn, self, vars)
+ local ok, ret = pcall(run_lua_fn, self)
if not ok then
self:errorln(debug.traceback())
self:error(ret)
end
return ret
end,
- tree_to_value = function(self, tree, vars, filename)
- local code = "return (function(nomsu, vars)\nreturn " .. tostring(self:tree_to_lua(tree, filename).expr) .. ";\nend);"
+ tree_to_value = function(self, tree, filename)
+ local code = "return (function(nomsu)\nreturn " .. tostring(self:tree_to_lua(tree, filename).expr) .. ";\nend);"
code = "-- Tree to value: " .. tostring(filename) .. "\n" .. code
if self.debug then
self:writeln(tostring(colored.bright("RUNNING LUA TO GET VALUE:")) .. "\n" .. tostring(colored.blue(colored.bright(code))))
@@ -615,7 +631,7 @@ end]]):format(lua_code))
if not lua_thunk then
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(colored.red(err)))
end
- return (lua_thunk())(self, vars or { })
+ return (lua_thunk())(self)
end,
tree_to_nomsu = function(self, tree, force_inline)
if force_inline == nil then
@@ -841,7 +857,7 @@ end]]):format(lua_code))
}
elseif "Nomsu" == _exp_0 then
return {
- expr = "nomsu:parse(" .. tostring(repr(tree.value.src)) .. ", " .. tostring(repr(tree.line_no)) .. ").value[1]"
+ expr = "nomsu:parse(" .. tostring(repr(tree.value.src)) .. ", " .. tostring(repr(tree:get_line_no())) .. ").value[1]"
}
elseif "Block" == _exp_0 then
local lua_bits = { }
@@ -891,7 +907,7 @@ end]]):format(lua_code))
end
local args = {
repr(tree.stub),
- repr(tree.line_no)
+ repr(tree:get_line_no())
}
local arg_names, escaped_args
if def then
@@ -922,7 +938,7 @@ end]]):format(lua_code))
break
end
if escaped_args[arg_names[arg_num]] then
- insert(args, "nomsu:parse(" .. tostring(repr(arg.src)) .. ", " .. tostring(repr(tree.line_no)) .. ").value[1]")
+ insert(args, "nomsu:parse(" .. tostring(repr(arg.src)) .. ", " .. tostring(repr(tree:get_line_no())) .. ").value[1]")
else
local lua = self:tree_to_lua(arg, filename)
if lua.statements then
@@ -1039,15 +1055,9 @@ end]]):format(lua_code))
expr = repr(tree.value)
}
elseif "Var" == _exp_0 then
- if tree.value:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
- return {
- expr = "vars." .. tostring(tree.value)
- }
- else
- return {
- expr = "vars[" .. tostring(repr(tree.value)) .. "]"
- }
- end
+ return {
+ expr = ("_" .. self:var_to_lua_identifier(tree.value))
+ }
else
return self:error("Unknown/unimplemented thingy: " .. tostring(tree.type))
end
@@ -1256,13 +1266,15 @@ end]]):format(lua_code))
msg = ''
end
if not condition then
- return self:error(msg)
+ return self:error("Assertion failed: " .. msg)
end
end,
error = function(self, msg)
local error_msg = colored.red("ERROR!")
- if msg then
+ if msg and #msg > 0 then
error_msg = error_msg .. ("\n" .. (colored.bright(colored.yellow(colored.onred(msg)))))
+ else
+ error_msg = error_msg .. "\n<no message>"
end
error_msg = error_msg .. "\nCallstack:"
local maxlen = max((function()
@@ -1301,20 +1313,6 @@ end]]):format(lua_code))
self.callstack = { }
return error(error_msg, 3)
end,
- typecheck = function(self, vars, varname, desired_type)
- local x = vars[varname]
- local x_type = type(x)
- if x_type == desired_type then
- return x
- end
- if x_type == 'table' then
- x_type = x.type or x_type
- if x_type == desired_type then
- return x
- end
- end
- return self:error("Invalid type for %" .. tostring(varname) .. ". Expected " .. tostring(desired_type) .. ", but got " .. tostring(x_type) .. ":\n" .. tostring(repr(x)))
- end,
source_code = function(self, level)
if level == nil then
level = 0
@@ -1340,51 +1338,51 @@ end]]):format(lua_code))
end
return concat(concat_parts)
end
- self:defmacro("do %block", function(self, vars)
+ self:defmacro("do %block", function(self, _block)
local make_line
make_line = function(lua)
return lua.expr and (lua.expr .. ";") or lua.statements
end
- if vars.block.type == "Block" then
- return self:tree_to_lua(vars.block)
+ if _block.type == "Block" then
+ return self:tree_to_lua(_block)
else
return {
- expr = tostring(self:tree_to_lua(vars.block)) .. "(nomsu, vars)"
+ expr = tostring(self:tree_to_lua(_block)) .. "(nomsu)"
}
end
end)
- self:defmacro("immediately %block", function(self, vars)
- local lua = self:tree_to_lua(vars.block)
+ self:defmacro("immediately %block", function(self, _block)
+ local lua = self:tree_to_lua(_block)
local lua_code = lua.statements or (lua.expr .. ";")
lua_code = "-- Immediately:\n" .. lua_code
- self:run_lua(lua_code, vars)
+ self:run_lua(lua_code)
return {
statements = lua_code
}
end)
- self:defmacro("lua> %code", function(self, vars)
- local lua = nomsu_string_as_lua(self, vars.code)
+ self:defmacro("lua> %code", function(self, _code)
+ local lua = nomsu_string_as_lua(self, _code)
return {
statements = lua
}
end)
- self:defmacro("=lua %code", function(self, vars)
- local lua = nomsu_string_as_lua(self, vars.code)
+ self:defmacro("=lua %code", function(self, _code)
+ local lua = nomsu_string_as_lua(self, _code)
return {
expr = lua
}
end)
- self:defmacro("__src__ %level", function(self, vars)
+ self:defmacro("__src__ %level", function(self, _level)
return {
- expr = repr(self:source_code(self:tree_to_value(vars.level)))
+ expr = repr(self:source_code(self:tree_to_value(_level)))
}
end)
- self:def("run file %filename", function(self, vars)
- return self:run_file(vars.filename, vars)
+ self:def("run file %filename", function(self, _filename)
+ return self:run_file(_filename)
end)
- return self:defmacro("require %filename", function(self, vars)
- local filename = self:tree_to_value(vars.filename)
- self:require_file(filename, vars)
+ return self:defmacro("require %filename", function(self, _filename)
+ local filename = self:tree_to_value(_filename)
+ self:require_file(filename)
return {
statements = "nomsu:require_file(" .. tostring(repr(filename)) .. ");"
}
@@ -1513,8 +1511,7 @@ if arg then
else
input = io.open(args.input):read("*a")
end
- local vars = { }
- local retval, code = c:run(input, args.input, vars)
+ local retval, code = c:run(input, args.input)
if args.output then
compiled_output:write(code)
end
@@ -1524,7 +1521,6 @@ if arg then
end
end
if args.flags["-i"] then
- local vars = { }
c:run('require "lib/core.nom"', "stdin")
while true do
local buff = ""
@@ -1540,7 +1536,7 @@ if arg then
break
end
local ok, ret = pcall(function()
- return c:run(buff, "stdin", vars)
+ return c:run(buff, "stdin")
end)
if ok and ret ~= nil then
print("= " .. repr(ret))