diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-08-27 13:38:58 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-08-27 13:39:22 -0700 |
| commit | 930d522fbc3ab57faa926ed85f0d35d661722402 (patch) | |
| tree | 8c91c71728b43b4e1817ed182c39bf991cb4b2a9 /core/metaprogramming.nom | |
| parent | c6a7b0be9ebdddb58a03749705987cb3058060d3 (diff) | |
Bunch of miscellaneous changes. Paved the way a little bit for having
different compiler domains.
Diffstat (limited to 'core/metaprogramming.nom')
| -rw-r--r-- | core/metaprogramming.nom | 116 |
1 files changed, 79 insertions, 37 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 153a0bf..968ed39 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -5,12 +5,12 @@ lua> "NOMSU_CORE_VERSION = 5" lua> ".." - nomsu.COMPILE_ACTIONS["% -> %"] = function(nomsu, tree, \%args, \%body) + COMPILE_ACTIONS["% -> %"] = function(nomsu, tree, \%args, \%body) local lua = LuaCode.Value(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) + local lua_args = table.map(\%args, function(a) return AST.is_syntax_tree(a) and tostring(_ENV: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 + local body_lua = AST.is_syntax_tree(\%body) and _ENV:compile(\%body):as_statements("return ") or \%body body_lua:remove_free_vars(lua_args) body_lua:declare_locals() lua:append(")\\n ", body_lua, "\\nend)") @@ -18,9 +18,9 @@ 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) + COMPILE_ACTIONS["compile as %"] = function(nomsu, tree, \%action) + local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", repr(\%action.stub), "](") + local lua_args = table.map(\%action:get_args(), function(a) return _ENV:compile(a) end) table.insert(lua_args, 1, "nomsu") table.insert(lua_args, 2, "tree") lua:concat_append(lua_args, ", ") @@ -48,22 +48,22 @@ test: asdf assume (%tmp is (nil)) or barf "compile to is leaking variables" 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(\ + COMPILE_ACTIONS["compile % to %"] = function(nomsu, tree, \%actions, \%body) + local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return tostring(_ENV:compile(\ ..a)) end))} - local lua = LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), + local lua = LuaCode(tree.source, "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(\ + local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return tostring(_ENV:compile(\ ..a)) end))} - lua:append("\\nnomsu.COMPILE_ACTIONS[", repr(alias.stub), "] = ") + lua:append("\\nCOMPILE_ACTIONS[", repr(alias.stub), "] = ") if utils.equivalent(\%args, \%alias_args) then - lua:append("nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "]") + lua:append("COMPILE_ACTIONS[", repr(\%actions[1].stub), "]") else lua:append("function(") lua:concat_append(\%alias_args, ", ") - lua:append(")\\n return nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "](") + lua:append(")\\n return COMPILE_ACTIONS[", repr(\%actions[1].stub), "](") lua:concat_append(\%args, ", ") lua:append(")\\nend") end @@ -75,8 +75,8 @@ lua> ".." compile [call %fn with %args] to (..) lua> ".." - local lua = LuaCode.Value(tree.source, nomsu:compile(\%fn), "(") - lua:concat_append(table.map(\%args, function(a) return nomsu:compile(a) end), ", ") + local lua = LuaCode.Value(tree.source, _ENV:compile(\%fn), "(") + lua:concat_append(table.map(\%args, function(a) return _ENV:compile(a) end), ", ") lua:append(")") return lua @@ -95,14 +95,14 @@ test: 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 \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(_ENV: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) + local \%alias_args = table.map(alias:get_args(), function(a) return tostring(_ENV:compile(a)) end) lua:append("\\n", alias_name, " = ") if utils.equivalent(\%args, \%alias_args) then lua:append(fn_name) @@ -151,7 +151,7 @@ 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)) + replacements[arg[1]] = tostring(_ENV:compile(arg)) end local function make_tree(t) if not AST.is_syntax_tree(t) then @@ -168,7 +168,7 @@ compile [parse %actions as %body] to (..) local \%new_body = LuaCode(\%body.source, "__MANGLE_INDEX = (__MANGLE_INDEX or 0) + 1", "\\nlocal tree = ", make_tree(\%body), - "\\nlocal lua = nomsu:compile(tree); return lua") + "\\nlocal lua = _ENV:compile(tree); return lua") local ret = \(compile as (compile %actions to %new_body)) return ret @@ -176,33 +176,33 @@ compile [parse %actions as %body] to (..) action [%tree as lua expr]: lua> ".." - \%tree_lua = nomsu:compile(\%tree) + \%tree_lua = _ENV:compile(\%tree) if not \%tree_lua.is_value then - nomsu:compile_error(\%tree.source, "Could not convert %s to a Lua expression", - nomsu:tree_to_nomsu(\%tree)) + _ENV:compile_error(\%tree.source, "Could not convert %s to a Lua expression", + _ENV:tree_to_nomsu(\%tree)) end return \%tree_lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -compile [%tree as lua] to (Lua value "nomsu:compile(\(%tree as lua expr))") +compile [%tree as lua] to (Lua value "_ENV:compile(\(%tree as lua expr))") compile [%tree as lua statements] to (..) - Lua value "nomsu:compile(\(%tree as lua expr)):as_statements()" + Lua value "_ENV:compile(\(%tree as lua expr)):as_statements()" compile [%tree as lua return] to (..) - Lua value "nomsu:compile(\(%tree as lua expr)):as_statements('return ')" + Lua value "_ENV:compile(\(%tree as lua expr)):as_statements('return ')" compile [remove action %action] to (..) Lua "A\(=lua "string.as_lua_id(\(%action.stub))") = nil" test: - assume ("\(\(foo %x) as nomsu)" == "foo %x") or barf ".." + assume ("\(\(foo \%x) as nomsu)" == "foo %x") or barf ".." action source code failed. compile [%tree as nomsu] to (..) - Lua value "nomsu:tree_to_nomsu(\(%tree as lua expr))" + Lua value "_ENV:tree_to_nomsu(\(%tree as lua expr))" compile [%tree as inline nomsu] to (..) - Lua value "nomsu:tree_to_nomsu(\(%tree as lua expr), true)" + Lua value "_ENV:tree_to_nomsu(\(%tree as lua expr), true)" action [%var as lua identifier, %var as lua id] (..) lua> ".." @@ -231,6 +231,14 @@ action [%tree with vars %replacements] (..) end end) +compile [tree %tree with vars %replacements] to (..) + Lua value ".." + \(=lua "repr(\%tree)"):map(function(t) + if t.type == "Var" then + return \(%replacements as lua expr)[t[1]] + end + end) + compile [%tree has subtree %match_tree] to (..) Lua value ".." (function() @@ -240,6 +248,39 @@ compile [%tree has subtree %match_tree] to (..) end end)() +action [match %tree with %patt]: + lua> ".." + if \%patt.type == "Var" then return dict{[\%patt[1]]=\%tree} end + if \%patt.type == "Action" and \%patt.stub ~= \%tree.stub then return nil end + if #\%patt ~= #\%tree then return nil end + local matches = dict{} + for \%i=1,#\%patt do + if AST.is_syntax_tree(\%tree[\%i]) then + local submatch = \(match %tree.%i with %patt.%i) + if not submatch then return nil end + for k,v in pairs(submatch) do + if matches[k] and matches[k] ~= v then return nil end + matches[k] = v + end + end + end + return matches + +action [%tree with %patt ~> %replacement]: + lua> ".." + return \%tree:map(function(\%t) + local \%vars = \(match %t with %patt) + if not \%vars then return nil end + for \%k,\%v in pairs(\%vars) do + \%vars[\%k] = \(%v with %patt ~> %replacement) + end + return \%replacement:map(function(\%t) + if \%t.type == "Var" then + return \%vars[\%t[1]] + end + end) + end) + compile [declare locals in %code] to (..) Lua value "\(%code as lua expr):declare_locals()" @@ -275,11 +316,12 @@ compile [type of %obj] to (Lua value "type(\(%obj as lua expr))") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: - assume ((parse "foo %") == \(foo %)) -compile [parse %text] to (Lua value "nomsu:parse(\(%text as lua expr))") + assume ((parse "foo %") == \(foo \%)) + assume ((parse "\\1") == \\1) +compile [parse %text] to (Lua value "_ENV:parse(\(%text as lua expr))") compile [parse %text from %filename] to (..) Lua value ".." - nomsu:parse(NomsuCode(Source(\(%filename as lua expr), 1, #\(%text as lua expr)), \(..) + _ENV:parse(NomsuCode(Source(\(%filename as lua expr), 1, #\(%text as lua expr)), \(..) %text as lua expr ..)) @@ -287,19 +329,19 @@ test: assume ((run "return (2 + 99)") == 101) external %passed = (no) run \: - external %passed = (yes) + \(external \%passed = \(yes)) assume %passed compile [run %nomsu_code] to (..) Lua value ".." - nomsu:run(\(%nomsu_code as lua expr), \(..) + _ENV:run(\(%nomsu_code as lua expr), \(..) =lua "repr(tostring(\(%nomsu_code.source)))" ..) test: - assume ((\(5 + 5) as value) == 10) or barf "%tree as value failed." -action [run tree %tree, %tree as value] (lua> "return nomsu:run(\%tree)") + assume ((\(\5 + \5) as value) == 10) or barf "%tree as value failed." +action [run tree %tree, %tree as value] (lua> "return _ENV:run(\%tree)") compile [compile %block, compiled %block, %block compiled] to (..) - Lua value "nomsu:compile(\(%block as lua))" + Lua value "_ENV:compile(\(%block as lua))" # 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. @@ -322,7 +364,7 @@ compile [command line args] to (Lua value "arg") compile [with local compile actions %body] to (..) Lua ".." do - local nomsu = table.fork(nomsu, {COMPILE_ACTIONS=table.fork(nomsu.COMPILE_ACTIONS)}) + local nomsu = table.fork(nomsu, {COMPILE_ACTIONS=table.fork(COMPILE_ACTIONS)}) \(%body as lua statements) end |
