diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/collections.nom | 3 | ||||
| -rw-r--r-- | core/control_flow.nom | 10 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 182 | ||||
| -rw-r--r-- | core/operators.nom | 13 |
4 files changed, 100 insertions, 108 deletions
diff --git a/core/collections.nom b/core/collections.nom index 69a51c7..6ba806a 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -55,6 +55,8 @@ compile [pop from %list, remove last from %list] to compile [remove index %index from %list] to Lua "table.remove(\(%list as lua expr), \(%index as lua expr))" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # List Comprehension parse [%expression for %item in %iterable] as result of @@ -73,6 +75,7 @@ parse [..] add %expression to %comprehension return %comprehension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ parse [%expression for %var in %start to %stop] as %expression for %var in %start to %stop via 1 diff --git a/core/control_flow.nom b/core/control_flow.nom index fccdfca..5a96d3e 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -152,7 +152,7 @@ compile [..] %body has subtree % where (%.type = "Action") and (%.stub is "do next %") and - %.3 = %var + %.(3).1 = %var.1 ..: to %lua write "\n ::continue_\(%var as lua identifier)::" to %lua write "\nend --numeric for-loop" @@ -160,7 +160,7 @@ compile [..] %body has subtree % where (%.type = "Action") and (%.stub is "stop %") and - %.2 = %var + %.(2).1 = %var.1 .. %lua <- Lua ".." @@ -246,7 +246,7 @@ compile [..] %.2.(1) = %value.(1) ..: to %stop_labels write "\n::stop_\(%value as lua identifier)::" - if: (length of %stop_labels) > 0 + if: (length of "\%stop_labels") > 0 %lua <- Lua ".." do -- scope for stopping for % = % loop @@ -300,7 +300,7 @@ compile [when %body] to %is_first <- (no) assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block" - assume ((length of %code) > 0) or barf "Empty body for 'when' block" + assume ((length of "\%code") > 0) or barf "Empty body for 'when' block" to %code write "\nend --when" return %code @@ -346,7 +346,7 @@ compile [when %branch_value = ? %body, when %branch_value is ? %body] to %is_first <- (no) assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block" - assume ((length of %code) > 0) or barf "No body for 'when % = ?' block!" + assume ((length of "\%code") > 0) or barf "No body for 'when % = ?' block!" to %code write "\nend" %code <- Lua ".." diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index d04ced3..a7da3d8 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -2,46 +2,92 @@ This File contains actions for making actions and compile-time actions and some helper functions to make that easier. -# Compile-time action to make compile-time actions: lua> ".." - nomsu.COMPILE_ACTIONS["give % nickname %"] = (function(nomsu, tree, \%action, \%nickname, is_compile_time) - local function arg_to_string(a) return tostring(nomsu:compile(a)) end - local action_args = table.map(\%action:get_args(), arg_to_string) - local nickname_args = table.map(\%nickname:get_args(), arg_to_string) - if utils.equivalent(action_args, nickname_args) then - if is_compile_time then - return LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%nickname.stub), "] = nomsu.COMPILE_ACTIONS[", repr(\%action.stub), "]") + nomsu.COMPILE_ACTIONS["% -> %"] = function(nomsu, tree, \%args, \%body) + local lua = LuaCode(tree.source, "function(") + if AST.is_syntax_tree(\%args, "Action") then \%args = \%args:get_args() end + local lua_args = table.map(\%args, function(a) return AST.is_syntax_tree(a) and tostring(nomsu:compile(a)) or a end) + lua:concat_append(lua_args, ", ") + local body_lua = AST.is_syntax_tree(\%body) and nomsu:compile(\%body):as_statements("return ") or \%body + body_lua:remove_free_vars(lua_args) + body_lua:declare_locals() + lua:append(")\n ", body_lua, "\nend") + return lua + end + +lua> ".." + nomsu.COMPILE_ACTIONS["compile as %"] = function(nomsu, tree, \%action) + local lua = LuaCode.Value(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%action.stub), "](") + local lua_args = table.map(\%action:get_args(), function(a) return nomsu:compile(a) end) + table.insert(lua_args, 1, "nomsu") + table.insert(lua_args, 2, "tree") + lua:concat_append(lua_args, ", ") + lua:append(")") + return lua + end + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +lua> ".." + nomsu.COMPILE_ACTIONS["compile % to %"] = function(nomsu, tree, \%actions, \%body) + local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end))} + local lua = LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), + "] = ", \(compile as: %args -> %body)) + for i=2,#\%actions do + local alias = \%actions[i] + local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end))} + lua:append("\nnomsu.COMPILE_ACTIONS[", repr(alias.stub), "] = ") + if utils.equivalent(\%args, \%alias_args) then + lua:append("nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "]") else - return LuaCode(tree.source, "A", string.as_lua_id(\%nickname.stub), " = A", string.as_lua_id(\%action.stub)) + lua:append("function(") + lua:concat_append(\%alias_args, ", ") + lua:append(")\n return nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "](") + lua:concat_append(\%args, ", ") + lua:append(")\nend") end end - local lua = LuaCode(tree.source) - if is_compile_time then - lua:append("nomsu.COMPILE_ACTIONS[", repr(\%nickname.stub), "] = ") - table.insert(action_args, 1, "nomsu") - table.insert(nickname_args, 1, "nomsu") - table.insert(action_args, 2, "tree") - table.insert(nickname_args, 2, "tree") - else - lua:append("A", string.as_lua_id(\%nickname.stub), " = ") - end - lua:append("(function(") - lua:concat_append(nickname_args, ", ") - if is_compile_time then - lua:append(")\n return nomsu.COMPILE_ACTIONS[", repr(\%action.stub), "](") - else - lua:append(")\n return A", string.as_lua_id(\%action.stub), "(") - end - lua:concat_append(action_args, ", ") - lua:append(")\nend)") - if not is_compile_time then - lua:add_free_vars({"A"..string.as_lua_id(\%nickname.stub)}) + return lua + end + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +compile [local action %actions %body] to + lua> ".." + local fn_name = "A"..string.as_lua_id(\%actions[1].stub) + local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end) + local lua = LuaCode(tree.source, fn_name, " = ", \(compile as: %args -> %body)) + lua:add_free_vars({fn_name}) + for i=2,#\%actions do + local alias = \%actions[i] + local alias_name = "A"..string.as_lua_id(alias.stub) + lua:add_free_vars({alias_name}) + local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end) + lua:append("\n", alias_name, " = ") + if utils.equivalent(\%args, \%alias_args) then + lua:append(fn_name) + else + lua:append("function(") + lua:concat_append(\%alias_args, ", ") + lua:append(")\n return ", fn_name, "(") + lua:concat_append(\%args, ", ") + lua:append(")\nend") + end end return lua - end) - __MANGLE_INDEX = 0 - nomsu.COMPILE_ACTIONS["parse % as %"] = (function(nomsu, tree, \%actions, \%body) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +compile [action %actions %body] to + lua> ".." + local lua = \(compile as: local action %actions %body) + lua:remove_free_vars(table.map(\%actions, function(a) return "A"..string.as_lua_id(a.stub) end)) + return lua + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +compile [parse %actions as %body] to + lua> ".." local replacements = {} for i,arg in ipairs(\%actions[1]:get_args()) do replacements[arg[1]] = tostring(nomsu:compile(arg)) @@ -50,81 +96,25 @@ lua> ".." if not AST.is_syntax_tree(t) then return repr(t) elseif t.type ~= 'Var' then - local args = table.map(t, make_tree) - table.insert(args, 1, repr(tostring(t.source))) + local args = {repr(tostring(t.source)), unpack(table.map(t, make_tree))} return t.type.."("..table.concat(args, ", ")..")" elseif replacements[t[1]] then return replacements[t[1]] else - return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].." \\0").."..('%X'):format(__MANGLE_INDEX))" + return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].." \\0").."..string.format('%X', __MANGLE_INDEX))" end end - local lua = LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "] = (function(nomsu, tree") - lua:add_free_vars({"A"..string.as_lua_id(\%actions[1].stub)}) - for _,arg in ipairs(\%actions[1]:get_args()) do - lua:append(", ", nomsu:compile(arg)) - end - lua:append(")\n __MANGLE_INDEX = __MANGLE_INDEX + 1", - "\n local tree = ", make_tree(\%body), - "\n local lua = nomsu:compile(tree)", - "\n lua:remove_free_vars({") - local vars = table.map(\%actions[1]:get_args(), function(a) - return "Var("..repr(tostring(a.source))..", "..repr(a[1])..")" - end) - lua:concat_append(vars, ", ") - lua:append("})\n return lua\nend)") - - for i=2,#\%actions do - lua:append("\n", nomsu.COMPILE_ACTIONS["give % nickname %"](nomsu, \%actions[i], \%actions[1], \%actions[i], true)) - end - return lua - end) - - nomsu.COMPILE_ACTIONS["local action % %"] = (function(nomsu, tree, \%actions, \%body, is_compile_time) - local lua = LuaCode(tree.source) - if is_compile_time then - lua:append("nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "] = ") - else - lua:append("A", string.as_lua_id(\%actions[1].stub), " = ") - lua:add_free_vars({"A"..string.as_lua_id(\%actions[1].stub)}) - end - lua:append("(function(") - local args = \%actions[1]:get_args() - local lua_args = table.map(args, function(a) return nomsu:compile(a) end) - if is_compile_time then - table.insert(lua_args, 1, "nomsu") - table.insert(lua_args, 2, "tree") - end - lua:concat_append(lua_args, ", ") - local body_lua = nomsu:compile(\%body):as_statements("return ") - body_lua:remove_free_vars(args) - body_lua:declare_locals() - lua:append(")\n ", body_lua, "\nend)") - for i=2,#\%actions do - lua:append("\n", nomsu.COMPILE_ACTIONS["give % nickname %"](nomsu, \%actions[i], \%actions[1], \%actions[i], is_compile_time)) - end - return lua - end) - - -- Compile-time actions are always global, since they affect the state of the compiler - nomsu.COMPILE_ACTIONS["compile % to %"] = (function(nomsu, tree, \%actions, \%body) - local lua = nomsu.COMPILE_ACTIONS["local action % %"](nomsu, tree, \%actions, \%body, true) - return lua - end) - - nomsu.COMPILE_ACTIONS["action % %"] = (function(nomsu, tree, \%actions, \%body) - local lua = nomsu.COMPILE_ACTIONS["local action % %"](nomsu, tree, \%actions, \%body) - lua:remove_free_vars(table.map(\%actions, function(a) return "A"..a.stub:as_lua_id() end)) - return lua - end) + local \%new_body = LuaCode(\%body.source, + "__MANGLE_INDEX = (__MANGLE_INDEX or 0) + 1", + "\nlocal tree = ", make_tree(\%body), + "\nreturn nomsu:compile(tree)") + return \(compile as: compile %actions to %new_body) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compile [remove action %action] to Lua ".." A\(=lua "string.as_lua_id(\(%action.stub))") = nil - ARG_ORDERS[fn] = nil - COMPILE_TIME[fn] = nil action [%tree as nomsu] =lua "nomsu:tree_to_nomsu(\%tree)" diff --git a/core/operators.nom b/core/operators.nom index b4567b1..0756751 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -50,7 +50,7 @@ compile [%var <- %value] to lua> ".." local lua = LuaCode(tree.source, \%var_lua, ' = ', \%value_lua, ';') if \%var.type == 'Var' then - lua:add_free_vars({\%var}) + lua:add_free_vars({tostring(nomsu:compile(\%var))}) end return lua @@ -72,7 +72,7 @@ compile [<- %assignments, assign %assignments] to local value_lua = \(%value as lua) if not value_lua.is_value then error("Invalid value for assignment: "..\(%value as text)) end if \%target.type == "Var" then - lhs:add_free_vars({\%target}) + lhs:add_free_vars({tostring(target_lua)}) end if i > 1 then lhs:append(", ") @@ -94,7 +94,7 @@ compile [external %var <- %value] to compile [with external %externs %body] to %body_lua <- (%body as lua statements) - lua> "\%body_lua:remove_free_vars(\%externs);" + lua> "\%body_lua:remove_free_vars(table.map(\%externs, function(v) return tostring(nomsu:compile(v)) end))" return %body_lua compile [with %assignments %body] to @@ -112,16 +112,15 @@ compile [with %assignments %body] to if not value_lua.is_value then error("Invalid value for assignment: "..tostring(\%value)) end - if \%target.type == "Var" then - lhs:add_free_vars({\%target}) - end if i > 1 then lhs:append(", ") rhs:append(", ") end lhs:append(target_lua) rhs:append(value_lua) - vars[i] = \%target + if \%target.type == "Var" then + vars[i] = tostring(target_lua) + end end \%lua:remove_free_vars(vars) \%lua:prepend("local ", lhs, " = ", rhs, ";\n") |
