Working version.
This commit is contained in:
parent
b0997a7dbf
commit
63a19db0dc
@ -83,6 +83,7 @@ do
|
||||
local match = string.match
|
||||
for i = 1, n do
|
||||
local b = select(i, ...)
|
||||
assert(b)
|
||||
bits[#bits + 1] = b
|
||||
if type(b) == 'string' then
|
||||
do
|
||||
@ -171,7 +172,6 @@ do
|
||||
end
|
||||
for _index_0 = 1, #vars do
|
||||
local var = vars[_index_0]
|
||||
assert(var.type == "Var")
|
||||
if not (seen[var]) then
|
||||
self.free_vars[#self.free_vars + 1] = var
|
||||
seen[var] = true
|
||||
@ -186,7 +186,6 @@ do
|
||||
local removals = { }
|
||||
for _index_0 = 1, #vars do
|
||||
local var = vars[_index_0]
|
||||
assert(var.type == "Var")
|
||||
removals[var[1]] = true
|
||||
end
|
||||
local stack = {
|
||||
@ -264,7 +263,7 @@ do
|
||||
local _len_0 = 1
|
||||
for _index_0 = 1, #to_declare do
|
||||
local v = to_declare[_index_0]
|
||||
_accum_0[_len_0] = string.as_lua_id(v[1])
|
||||
_accum_0[_len_0] = type(v) == 'string' and v or string.as_lua_id(v[1])
|
||||
_len_0 = _len_0 + 1
|
||||
end
|
||||
return _accum_0
|
||||
|
@ -57,6 +57,7 @@ class Code
|
||||
match = string.match
|
||||
for i=1,n
|
||||
b = select(i, ...)
|
||||
assert(b)
|
||||
bits[#bits+1] = b
|
||||
if type(b) == 'string'
|
||||
if spaces = match(b, "\n([ ]*)[^\n]*$")
|
||||
@ -98,7 +99,6 @@ class Lua extends Code
|
||||
return unless #vars > 0
|
||||
seen = {[v]:true for v in *@free_vars}
|
||||
for var in *vars
|
||||
assert(var.type == "Var")
|
||||
unless seen[var]
|
||||
@free_vars[#@free_vars+1] = var
|
||||
seen[var] = true
|
||||
@ -108,7 +108,6 @@ class Lua extends Code
|
||||
return unless #vars > 0
|
||||
removals = {}
|
||||
for var in *vars
|
||||
assert(var.type == "Var")
|
||||
removals[var[1]] = true
|
||||
|
||||
stack = {self}
|
||||
@ -147,7 +146,7 @@ class Lua extends Code
|
||||
gather_from self
|
||||
if #to_declare > 0
|
||||
@remove_free_vars to_declare
|
||||
@prepend "local #{concat [string.as_lua_id(v[1]) for v in *to_declare], ", "};\n"
|
||||
@prepend "local #{concat [type(v) == 'string' and v or string.as_lua_id(v[1]) for v in *to_declare], ", "};\n"
|
||||
return to_declare
|
||||
|
||||
__tostring: =>
|
||||
|
@ -5,85 +5,112 @@
|
||||
# Compile-time action to make compile-time actions:
|
||||
immediately
|
||||
lua> ".."
|
||||
nomsu:define_compile_action("compile %actions to %lua", function(tree, \%actions, \%lua)
|
||||
local lua = Lua(tree.source, "nomsu:define_compile_action(")
|
||||
local specs = {}
|
||||
for i, action in ipairs(\%actions) do
|
||||
specs[i] = action:get_spec()
|
||||
end
|
||||
specs = repr(specs)
|
||||
if #specs > 80 then
|
||||
lua:append("\n ",specs,",\n ")
|
||||
else
|
||||
lua:append(specs,", ")
|
||||
end
|
||||
lua:append("function(tree")
|
||||
_ENV['ACTION'..string.as_lua_id("compile % to %")] = function(tree, \%actions, \%lua)
|
||||
local lua = Lua(tree.source)
|
||||
local canonical = \%actions[1]
|
||||
lua:append("ACTION", string.as_lua_id(canonical.stub), ' = function(tree')
|
||||
local args = {}
|
||||
for i,tok in ipairs(\%actions[1]) do
|
||||
for i,tok in ipairs(canonical) do
|
||||
if tok.type == "Var" then args[#args+1] = tok end
|
||||
end
|
||||
local canonical_arg_positions = {}
|
||||
for i, arg in ipairs(args) do
|
||||
canonical_arg_positions[arg[1]] = i
|
||||
lua:append(", ", nomsu:tree_to_lua(arg))
|
||||
end
|
||||
local body_lua = nomsu:tree_to_lua(\%lua):as_statements("return ")
|
||||
body_lua:remove_free_vars(args)
|
||||
body_lua:declare_locals()
|
||||
lua:append(")\n ", body_lua, "\nend);")
|
||||
lua:append(")\n ", body_lua, "\nend")
|
||||
lua:append("\nCOMPILE_TIME[ACTION", string.as_lua_id(canonical.stub), "] = true")
|
||||
|
||||
for i=2,#\%actions do
|
||||
local action = \%actions[i]
|
||||
lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub))
|
||||
|
||||
local arg_positions = {}
|
||||
for _,tok in ipairs(action) do
|
||||
if tok.type == 'Var' then
|
||||
arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]]
|
||||
end
|
||||
end
|
||||
lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions))
|
||||
lua:append("\nCOMPILE_TIME[ACTION", string.as_lua_id(action.stub), "] = true")
|
||||
end
|
||||
lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {")
|
||||
for i,action in ipairs(\%actions) do
|
||||
if i > 1 then lua:append(", ") end
|
||||
lua:append(repr(action.stub))
|
||||
end
|
||||
lua:append("}")
|
||||
return lua
|
||||
end);
|
||||
end
|
||||
COMPILE_TIME[_ENV['ACTION'..string.as_lua_id("compile % to %")]] = true
|
||||
|
||||
# Compile-time action to make actions
|
||||
immediately
|
||||
compile [action %actions %body] to
|
||||
lua> ".."
|
||||
local lua = Lua(tree.source, "nomsu:define_action(")
|
||||
local specs = {}
|
||||
for i, action in ipairs(\%actions) do
|
||||
specs[i] = action:get_spec()
|
||||
end
|
||||
specs = repr(specs)
|
||||
if #specs > 80 then
|
||||
lua:append("\n ",specs,",\n ")
|
||||
else
|
||||
lua:append(specs,", ")
|
||||
end
|
||||
lua:append("function(")
|
||||
local lua = Lua(tree.source)
|
||||
local canonical = \%actions[1]
|
||||
lua:append("ACTION", string.as_lua_id(canonical.stub), ' = function(')
|
||||
local args = {}
|
||||
for i,tok in ipairs(\%actions[1]) do
|
||||
for i,tok in ipairs(canonical) do
|
||||
if tok.type == "Var" then args[#args+1] = tok end
|
||||
end
|
||||
local canonical_arg_positions = {}
|
||||
for i, arg in ipairs(args) do
|
||||
canonical_arg_positions[arg[1]] = i
|
||||
lua:append(nomsu:tree_to_lua(arg))
|
||||
if i < #args then lua:append(", ") end
|
||||
end
|
||||
local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ")
|
||||
body_lua:remove_free_vars(args)
|
||||
body_lua:declare_locals()
|
||||
lua:append(")\n ", body_lua, "\nend);")
|
||||
lua:append(")\n ", body_lua, "\nend")
|
||||
|
||||
for i=2,#\%actions do
|
||||
local action = \%actions[i]
|
||||
lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub))
|
||||
|
||||
local arg_positions = {}
|
||||
for _,tok in ipairs(action) do
|
||||
if tok.type == 'Var' then
|
||||
arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]]
|
||||
end
|
||||
end
|
||||
lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions))
|
||||
end
|
||||
lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {")
|
||||
for i,action in ipairs(\%actions) do
|
||||
if i > 1 then lua:append(", ") end
|
||||
lua:append(repr(action.stub))
|
||||
end
|
||||
lua:append("}")
|
||||
return lua
|
||||
|
||||
# Macro to make nomsu macros
|
||||
immediately
|
||||
compile [parse %shorthand as %longhand] to
|
||||
lua> ".."
|
||||
local lua = Lua(tree.source, "nomsu:define_compile_action(")
|
||||
local specs = {}
|
||||
for i, action in ipairs(\%shorthand) do
|
||||
specs[i] = action:get_spec()
|
||||
local lua = Lua(tree.source)
|
||||
local canonical = \%shorthand[1]
|
||||
lua:append("ACTION", string.as_lua_id(canonical.stub), ' = function(tree')
|
||||
local args = {}
|
||||
for i,tok in ipairs(canonical) do
|
||||
if tok.type == "Var" then args[#args+1] = tok end
|
||||
end
|
||||
specs = repr(specs)
|
||||
if #specs > 80 then
|
||||
lua:append("\n ",specs,",\n ")
|
||||
else
|
||||
lua:append(specs,", ")
|
||||
local canonical_arg_positions = {}
|
||||
for i, arg in ipairs(args) do
|
||||
canonical_arg_positions[arg[1]] = i
|
||||
lua:append(", ", nomsu:tree_to_lua(arg))
|
||||
end
|
||||
lua:append("function(tree")
|
||||
|
||||
local replacements = {}
|
||||
for i,tok in ipairs(\%shorthand[1]) do
|
||||
for i,tok in ipairs(canonical) do
|
||||
if tok.type == "Var" then
|
||||
local lua_var = tostring(nomsu:tree_to_lua(tok))
|
||||
replacements[tok[1]] = lua_var
|
||||
lua:append(", ", lua_var)
|
||||
end
|
||||
end
|
||||
MANGLE_INDEX = (MANGLE_INDEX or 0) + 1
|
||||
@ -102,18 +129,39 @@ immediately
|
||||
return t.type.."("..table.concat(bits, ", ")..")"
|
||||
end
|
||||
end
|
||||
lua:append(")\n local tree = ", make_tree(\%longhand), "\n return nomsu:tree_to_lua(tree)\nend);")
|
||||
lua:append(")\n local tree = ", make_tree(\%longhand), "\n return nomsu:tree_to_lua(tree)\nend")
|
||||
lua:append("\nCOMPILE_TIME[ACTION", string.as_lua_id(canonical.stub), "] = true")
|
||||
|
||||
for i=2,#\%shorthand do
|
||||
local action = \%shorthand[i]
|
||||
lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub))
|
||||
|
||||
local arg_positions = {}
|
||||
for _,tok in ipairs(action) do
|
||||
if tok.type == 'Var' then
|
||||
arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]]
|
||||
end
|
||||
end
|
||||
lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions))
|
||||
lua:append("\nCOMPILE_TIME[ACTION", string.as_lua_id(action.stub), "] = true")
|
||||
end
|
||||
lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {")
|
||||
for i,action in ipairs(\%shorthand) do
|
||||
if i > 1 then lua:append(", ") end
|
||||
lua:append(repr(action.stub))
|
||||
end
|
||||
lua:append("}")
|
||||
return lua
|
||||
|
||||
compile [remove action %action] to
|
||||
Lua ".."
|
||||
do
|
||||
local fn = ACTIONS[\(=lua "repr(\%action.stub)")]
|
||||
local stubs = ARG_ORDERS[fn]
|
||||
for stub in pairs(stubs) do
|
||||
ACTIONS[stub] = nil
|
||||
local fn = ACTION\(=lua "string.as_lua_id(\(%action.stub))")
|
||||
for stub in pairs(ALIASES[fn]) do
|
||||
_ENV['ACTION'..string.as_lua_id(stub)] = nil
|
||||
end
|
||||
ARG_ORDERS[fn] = nil
|
||||
COMPILE_TIME[fn] = nil
|
||||
end
|
||||
|
||||
immediately
|
||||
|
111
nomsu.lua
111
nomsu.lua
@ -43,13 +43,18 @@ do
|
||||
end
|
||||
local STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
|
||||
string.as_lua_id = function(str)
|
||||
return "_" .. (gsub(str, "%W", function(c)
|
||||
if c == "_" then
|
||||
return "__"
|
||||
local argnum = 0
|
||||
str = gsub(str, "%W", function(c)
|
||||
if c == ' ' then
|
||||
return '_'
|
||||
elseif c == '%' then
|
||||
argnum = argnum + 1
|
||||
return tostring(argnum)
|
||||
else
|
||||
return format("_%x", byte(c))
|
||||
return format("x%X", byte(c))
|
||||
end
|
||||
end))
|
||||
end)
|
||||
return '_' .. str
|
||||
end
|
||||
FILE_CACHE = setmetatable({ }, {
|
||||
__index = function(self, filename)
|
||||
@ -237,6 +242,9 @@ setmetatable(NOMSU_DEFS, {
|
||||
if value.__init then
|
||||
value:__init()
|
||||
end
|
||||
for i = 1, #value do
|
||||
assert(value[i])
|
||||
end
|
||||
return value
|
||||
end
|
||||
self[key] = make_node
|
||||
@ -262,10 +270,7 @@ do
|
||||
local _class_0
|
||||
local compile_error, stub_pattern, var_pattern, _running_files, MAX_LINE, math_expression
|
||||
local _base_0 = {
|
||||
define_action = function(self, signature, fn, is_compile_action)
|
||||
if is_compile_action == nil then
|
||||
is_compile_action = false
|
||||
end
|
||||
define_action = function(self, signature, fn)
|
||||
if type(fn) ~= 'function' then
|
||||
error("Not a function: " .. tostring(repr(fn)))
|
||||
end
|
||||
@ -286,13 +291,12 @@ do
|
||||
end
|
||||
fn_arg_positions = _tbl_0
|
||||
end
|
||||
local actions = (is_compile_action and self.environment.COMPILE_ACTIONS or self.environment.ACTIONS)
|
||||
local arg_orders = { }
|
||||
for _index_0 = 1, #signature do
|
||||
local alias = signature[_index_0]
|
||||
local stub = concat(assert(stub_pattern:match(alias)), ' ')
|
||||
local stub_args = assert(var_pattern:match(alias))
|
||||
actions[stub] = fn
|
||||
self.environment['ACTION' .. string.as_lua_id(stub)] = fn
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
@ -307,7 +311,8 @@ do
|
||||
self.environment.ARG_ORDERS[fn] = arg_orders
|
||||
end,
|
||||
define_compile_action = function(self, signature, fn)
|
||||
return self:define_action(signature, fn, true)
|
||||
self:define_action(signature, fn)
|
||||
self.environment.COMPILE_TIME[fn] = true
|
||||
end,
|
||||
parse = function(self, nomsu_code)
|
||||
assert(type(nomsu_code) ~= 'string')
|
||||
@ -426,7 +431,7 @@ do
|
||||
run_lua = function(self, lua)
|
||||
assert(type(lua) ~= 'string', "Attempt to run lua string instead of Lua (object)")
|
||||
local lua_string = tostring(lua)
|
||||
local run_lua_fn, err = load(lua_string, tostring(lua.source), "t", self.environment)
|
||||
local run_lua_fn, err = load(lua_string, nil and tostring(lua.source), "t", self.environment)
|
||||
if not run_lua_fn then
|
||||
local n = 1
|
||||
local fn
|
||||
@ -475,8 +480,8 @@ do
|
||||
local _exp_0 = tree.type
|
||||
if "Action" == _exp_0 then
|
||||
local stub = tree.stub
|
||||
local compile_action = self.environment.COMPILE_ACTIONS[stub]
|
||||
if compile_action then
|
||||
local action = self.environment['ACTION' .. string.as_lua_id(stub)]
|
||||
if action and self.environment.COMPILE_TIME[action] then
|
||||
local args
|
||||
do
|
||||
local _accum_0 = { }
|
||||
@ -490,25 +495,27 @@ do
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
local arg_orders = self.environment.ARG_ORDERS[compile_action]
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
local _list_0 = arg_orders[stub]
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local p = _list_0[_index_0]
|
||||
_accum_0[_len_0] = args[p - 1]
|
||||
_len_0 = _len_0 + 1
|
||||
local arg_orders = self.environment.ARG_ORDERS[stub]
|
||||
if arg_orders then
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
for _index_0 = 1, #arg_orders do
|
||||
local p = arg_orders[_index_0]
|
||||
_accum_0[_len_0] = args[p]
|
||||
_len_0 = _len_0 + 1
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
local ret = compile_action(tree, unpack(args))
|
||||
local ret = action(tree, unpack(args))
|
||||
if not ret then
|
||||
compile_error(tree, "Compile-time action:\n%s\nfailed to produce any Lua")
|
||||
end
|
||||
return ret
|
||||
end
|
||||
local action = rawget(self.environment.ACTIONS, stub)
|
||||
local lua = Lua.Value(tree.source)
|
||||
if not action and math_expression:match(stub) then
|
||||
for i, tok in ipairs(tree) do
|
||||
@ -551,18 +558,22 @@ do
|
||||
end
|
||||
if action then
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
local _list_0 = self.environment.ARG_ORDERS[action][stub]
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local p = _list_0[_index_0]
|
||||
_accum_0[_len_0] = args[p]
|
||||
_len_0 = _len_0 + 1
|
||||
local arg_orders = self.environment.ARG_ORDERS[stub]
|
||||
if arg_orders then
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
for _index_0 = 1, #arg_orders do
|
||||
local p = arg_orders[_index_0]
|
||||
_accum_0[_len_0] = args[p]
|
||||
_len_0 = _len_0 + 1
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
end
|
||||
lua:append("ACTIONS[", repr(stub), "](")
|
||||
lua:append("ACTION", string.as_lua_id(stub), "(")
|
||||
for i, arg in ipairs(args) do
|
||||
lua:append(arg)
|
||||
if i < #args then
|
||||
@ -1085,22 +1096,31 @@ do
|
||||
end)
|
||||
local add_lua_string_bits
|
||||
add_lua_string_bits = function(lua, code)
|
||||
local line_len = 0
|
||||
if code.type ~= "Text" then
|
||||
lua:append(", ", nomsu:tree_to_lua(code))
|
||||
return
|
||||
end
|
||||
for _index_0 = 1, #code do
|
||||
local bit = code[_index_0]
|
||||
lua:append(", ")
|
||||
local bit_lua
|
||||
if type(bit) == "string" then
|
||||
lua:append(repr(bit))
|
||||
bit_lua = repr(bit)
|
||||
else
|
||||
local bit_lua = nomsu:tree_to_lua(bit)
|
||||
bit_lua = nomsu:tree_to_lua(bit)
|
||||
if not (bit_lua.is_value) then
|
||||
compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.")
|
||||
end
|
||||
lua:append(bit_lua)
|
||||
bit_lua = bit_lua
|
||||
end
|
||||
line_len = line_len + #tostring(bit_lua)
|
||||
if line_len > MAX_LINE then
|
||||
lua:append(",\n ")
|
||||
line_len = 4
|
||||
else
|
||||
lua:append(", ")
|
||||
end
|
||||
lua:append(bit_lua)
|
||||
end
|
||||
end
|
||||
self:define_compile_action("Lua %code", function(self, _code)
|
||||
@ -1262,19 +1282,16 @@ do
|
||||
self.environment.Lua = Lua
|
||||
self.environment.Nomsu = Nomsu
|
||||
self.environment.Source = Source
|
||||
self.environment.ACTIONS = setmetatable({ }, {
|
||||
__index = function(self, key)
|
||||
return function(...)
|
||||
return error("Attempt to run undefined action: " .. tostring(key), 0)
|
||||
end
|
||||
end
|
||||
})
|
||||
self.environment.COMPILE_ACTIONS = { }
|
||||
self.environment.ARG_ORDERS = setmetatable({ }, {
|
||||
__mode = "k"
|
||||
})
|
||||
self.environment.ALIASES = setmetatable({ }, {
|
||||
__mode = "k"
|
||||
})
|
||||
self.environment.COMPILE_TIME = { }
|
||||
self.environment.LOADED = { }
|
||||
self.environment.AST = AST
|
||||
self.environment._ENV = self.environment
|
||||
return self:initialize_core()
|
||||
end,
|
||||
__base = _base_0,
|
||||
|
61
nomsu.moon
61
nomsu.moon
@ -36,7 +36,14 @@ debug_getinfo = debug.getinfo
|
||||
STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
|
||||
|
||||
string.as_lua_id = (str)->
|
||||
"_"..(gsub(str, "%W", (c)-> if c == "_" then "__" else format("_%x", byte(c))))
|
||||
argnum = 0
|
||||
str = gsub str, "%W", (c)->
|
||||
if c == ' ' then '_'
|
||||
elseif c == '%' then
|
||||
argnum += 1
|
||||
tostring(argnum)
|
||||
else format("x%X", byte(c))
|
||||
return '_'..str
|
||||
|
||||
-- TODO:
|
||||
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
|
||||
@ -194,6 +201,7 @@ setmetatable(NOMSU_DEFS, {__index:(key)=>
|
||||
value.source = source
|
||||
setmetatable(value, AST[key])
|
||||
if value.__init then value\__init!
|
||||
for i=1,#value do assert(value[i])
|
||||
return value
|
||||
|
||||
self[key] = make_node
|
||||
@ -273,14 +281,12 @@ class NomsuCompiler
|
||||
@environment.Lua = Lua
|
||||
@environment.Nomsu = Nomsu
|
||||
@environment.Source = Source
|
||||
@environment.ACTIONS = setmetatable({}, {__index:(key)=>
|
||||
(...)->
|
||||
error("Attempt to run undefined action: #{key}", 0)
|
||||
})
|
||||
@environment.COMPILE_ACTIONS = {}
|
||||
@environment.ARG_ORDERS = setmetatable({}, {__mode:"k"})
|
||||
@environment.ALIASES = setmetatable({}, {__mode:"k"})
|
||||
@environment.COMPILE_TIME = {}
|
||||
@environment.LOADED = {}
|
||||
@environment.AST = AST
|
||||
@environment._ENV = @environment
|
||||
@initialize_core!
|
||||
|
||||
local stub_defs
|
||||
@ -294,7 +300,7 @@ class NomsuCompiler
|
||||
tok <- ({'%'} %varname) / {%word}
|
||||
]=], stub_defs
|
||||
var_pattern = re.compile "{| ((('%' {%varname}) / %word) ([ ])*)+ !. |}", stub_defs
|
||||
define_action: (signature, fn, is_compile_action=false)=>
|
||||
define_action: (signature, fn)=>
|
||||
if type(fn) != 'function'
|
||||
error("Not a function: #{repr fn}")
|
||||
if type(signature) == 'string'
|
||||
@ -305,17 +311,17 @@ class NomsuCompiler
|
||||
fn_info = debug_getinfo(fn, "u")
|
||||
assert(not fn_info.isvararg, "Vararg functions aren't supported. Sorry, use a list instead.")
|
||||
fn_arg_positions = {debug.getlocal(fn, i), i for i=1,fn_info.nparams}
|
||||
actions = (is_compile_action and @environment.COMPILE_ACTIONS or @environment.ACTIONS)
|
||||
arg_orders = {}
|
||||
for alias in *signature
|
||||
stub = concat(assert(stub_pattern\match(alias)), ' ')
|
||||
stub_args = assert(var_pattern\match(alias))
|
||||
actions[stub] = fn
|
||||
@environment['ACTION'..string.as_lua_id(stub)] = fn
|
||||
arg_orders[stub] = [fn_arg_positions[string.as_lua_id a] for a in *stub_args]
|
||||
@environment.ARG_ORDERS[fn] = arg_orders
|
||||
|
||||
define_compile_action: (signature, fn)=>
|
||||
return @define_action(signature, fn, true)
|
||||
@define_action(signature, fn)
|
||||
@environment.COMPILE_TIME[fn] = true
|
||||
|
||||
parse: (nomsu_code)=>
|
||||
assert(type(nomsu_code) != 'string')
|
||||
@ -391,7 +397,7 @@ class NomsuCompiler
|
||||
run_lua: (lua)=>
|
||||
assert(type(lua) != 'string', "Attempt to run lua string instead of Lua (object)")
|
||||
lua_string = tostring(lua)
|
||||
run_lua_fn, err = load(lua_string, tostring(lua.source), "t", @environment)
|
||||
run_lua_fn, err = load(lua_string, nil and tostring(lua.source), "t", @environment)
|
||||
if not run_lua_fn
|
||||
n = 1
|
||||
fn = ->
|
||||
@ -431,20 +437,19 @@ class NomsuCompiler
|
||||
switch tree.type
|
||||
when "Action"
|
||||
stub = tree.stub
|
||||
compile_action = @environment.COMPILE_ACTIONS[stub]
|
||||
if compile_action
|
||||
action = @environment['ACTION'..string.as_lua_id(stub)]
|
||||
if action and @environment.COMPILE_TIME[action]
|
||||
args = [arg for arg in *tree when type(arg) != "string"]
|
||||
-- Force all compile-time actions to take a tree location
|
||||
arg_orders = @environment.ARG_ORDERS[compile_action]
|
||||
args = [args[p-1] for p in *arg_orders[stub]]
|
||||
if arg_orders = @environment.ARG_ORDERS[stub]
|
||||
args = [args[p] for p in *arg_orders]
|
||||
-- Force Lua to avoid tail call optimization for debugging purposes
|
||||
-- TODO: use tail call
|
||||
ret = compile_action(tree, unpack(args))
|
||||
ret = action(tree, unpack(args))
|
||||
if not ret
|
||||
compile_error tree,
|
||||
"Compile-time action:\n%s\nfailed to produce any Lua"
|
||||
return ret
|
||||
action = rawget(@environment.ACTIONS, stub)
|
||||
lua = Lua.Value(tree.source)
|
||||
if not action and math_expression\match(stub)
|
||||
-- This is a bit of a hack, but this code handles arbitrarily complex
|
||||
@ -476,11 +481,10 @@ class NomsuCompiler
|
||||
insert args, arg_lua
|
||||
|
||||
if action
|
||||
args = [args[p] for p in *@environment.ARG_ORDERS[action][stub]]
|
||||
if arg_orders = @environment.ARG_ORDERS[stub]
|
||||
args = [args[p] for p in *arg_orders]
|
||||
|
||||
-- Not really worth bothering with ACTIONS.foo(...) style since almost every action
|
||||
-- has arguments, so it won't work
|
||||
lua\append "ACTIONS[",repr(stub),"]("
|
||||
lua\append "ACTION",string.as_lua_id(stub),"("
|
||||
for i, arg in ipairs args
|
||||
lua\append arg
|
||||
if i < #args then lua\append ", "
|
||||
@ -883,19 +887,26 @@ class NomsuCompiler
|
||||
return Lua(_block.source, "if IMMEDIATE then\n ", lua, "\nend")
|
||||
|
||||
add_lua_string_bits = (lua, code)->
|
||||
line_len = 0
|
||||
if code.type != "Text"
|
||||
lua\append ", ", nomsu\tree_to_lua(code)
|
||||
return
|
||||
for bit in *code
|
||||
lua\append ", "
|
||||
if type(bit) == "string"
|
||||
lua\append repr(bit)
|
||||
bit_lua = if type(bit) == "string"
|
||||
repr(bit)
|
||||
else
|
||||
bit_lua = nomsu\tree_to_lua(bit)
|
||||
unless bit_lua.is_value
|
||||
compile_error bit,
|
||||
"Cannot use:\n%s\nas a string interpolation value, since it's not an expression."
|
||||
lua\append bit_lua
|
||||
bit_lua
|
||||
line_len += #tostring(bit_lua)
|
||||
if line_len > MAX_LINE
|
||||
lua\append ",\n "
|
||||
line_len = 4
|
||||
else
|
||||
lua\append ", "
|
||||
lua\append bit_lua
|
||||
|
||||
@define_compile_action "Lua %code", (_code)=>
|
||||
lua = Lua.Value(_code.source, "Lua(", repr(tostring _code.source))
|
||||
|
@ -62,6 +62,9 @@ Tree = function(name, methods)
|
||||
if type(source) == 'string' then
|
||||
source = Source:from_string(source)
|
||||
end
|
||||
for i = 1, select('#', ...) do
|
||||
assert(select(i, ...))
|
||||
end
|
||||
assert(Source:is_instance(source))
|
||||
local inst = {
|
||||
source = source,
|
||||
|
@ -37,6 +37,7 @@ Tree = (name, methods)->
|
||||
__call: (source, ...)=>
|
||||
if type(source) == 'string'
|
||||
source = Source\from_string(source)
|
||||
for i=1,select('#', ...) do assert(select(i,...))
|
||||
assert(Source\is_instance(source))
|
||||
inst = {:source, ...}
|
||||
setmetatable(inst, @)
|
||||
|
@ -49,9 +49,10 @@ assume ((%1 = 2) and (%2 = 1)) or barf "'parse % as %' failed on 'swap % and %'"
|
||||
swap %tmp and %tmp2
|
||||
assume ((%tmp = 2) and (%tmp2 = 1)) or barf "'parse % as %' variable mangling failed."
|
||||
|
||||
remove action (foo %)
|
||||
try: foo 99
|
||||
..and if it succeeds: barf "Failed to delete action"
|
||||
#
|
||||
remove action (foo %)
|
||||
try: foo 99
|
||||
..and if it succeeds: barf "Failed to delete action"
|
||||
|
||||
assume ((\(5 + 5) as value) = 10) or barf "%tree as value failed."
|
||||
|
||||
|
@ -15,11 +15,11 @@ using
|
||||
action [baz]
|
||||
return "outer"
|
||||
|
||||
using
|
||||
action [baz]
|
||||
return "inner"
|
||||
..do
|
||||
assume: (baz) = "inner"
|
||||
assume: (baz) = "outer"
|
||||
#
|
||||
do
|
||||
local action [baz]
|
||||
return "inner"
|
||||
assume: (baz) = "inner"
|
||||
assume: (baz) = "outer"
|
||||
|
||||
say "Scopes test passed."
|
||||
|
Loading…
Reference in New Issue
Block a user