diff options
Diffstat (limited to 'lib/core/metaprogramming.nom')
| -rw-r--r-- | lib/core/metaprogramming.nom | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/lib/core/metaprogramming.nom b/lib/core/metaprogramming.nom index 76ccf4a..bfcc0bf 100644 --- a/lib/core/metaprogramming.nom +++ b/lib/core/metaprogramming.nom @@ -16,13 +16,16 @@ lua> (" end end end - COMPILE_RULES["define mangler"] = function(\(nomsu environment)) + COMPILE_RULES["define mangler"] = function(\(nomsu environment), _tree) return LuaCode("local mangle = mangler()") end + COMPILE_RULES["this tree"] = function(\(nomsu environment), _tree) + return LuaCode("_tree") + end ") lua> (" - COMPILE_RULES["1 ->"] = function(\(nomsu environment), \$args, \$body) + COMPILE_RULES["1 ->"] = function(\(nomsu environment), _tree, \$args, \$body) if \$args and not \$body then \$args, \$body = {}, \$args end local body_lua = SyntaxTree:is_instance(\$body) and \(nomsu environment):compile(\$body) or \$body if SyntaxTree:is_instance(\$body) and \$body.type ~= "Block" then body_lua:prepend("return ") end @@ -41,7 +44,7 @@ lua> (" elseif not arg_lua:is_lua_id() then at_1_fail(SyntaxTree:is_instance(arg) and arg or nil, "Compile error: This does not compile to a Lua identifier, so it ".. - "can't be used as a function argument.".. + "can't be used as a function argument. ".. "Hint: This should probably be a Nomsu variable instead (like $x).") end lua:add(i > 1 and ", " or "", arg_lua) @@ -84,13 +87,29 @@ test: fail "compile to is leaking variables" lua> (" - COMPILE_RULES["1 compiles to"] = function(\(nomsu environment), \$action, \$body) - local \$args = List{"\(nomsu environment)", unpack(\$action:get_args())} + COMPILE_RULES["1 compiles to"] = function(\(nomsu environment), \(this tree), \$action, \$body) + local \$args = List{"\(nomsu environment)", "\(this tree)"} if \$body.type == "Text" then \$body = SyntaxTree{source=\$body.source, type="Action", "Lua", \$body} end - return LuaCode("COMPILE_RULES[", \$action:get_stub():as_lua(), - "] = ", \(\($args -> $body) as lua)) + if not (\$action.type == "Action" or (\$action.type == "EscapedNomsu" and \$action[1]\ + ...type == "Action")) then + at_1_fail(\$action.source, "Compile error: ".. + "This is neither an action nor an escaped action. ".. + "Hint: This should probably be an action like:\\n" + .."(foo $x) compiles to \\"(\\\\($x as lua) + 1)\\"") + end + if \$action.type == "EscapedNomsu" then + for _,a in ipairs(\$action[1]) do + if a.type == "EscapedNomsu" then \$args:add(a[1]) end + end + return LuaCode("COMPILE_RULES[", \($action as lua), ":get_stub()] = ", + \(\($args -> $body) as lua)) + else + for _,a in ipairs(\$action:get_args()) do \$args:add(a) end + return LuaCode("COMPILE_RULES[", \$action:get_stub():as_lua(), + "] = ", \(\($args -> $body) as lua)) + end end ") @@ -102,19 +121,19 @@ lua> (" at_1_fail(\$actions, "Compile error: This should be a list of actions.") end local lua = \(\($actions.1 compiles to $body) as lua) - local \$args = List{"\(nomsu environment)", unpack(\$actions[1]:get_args())} - local \$compiled_args = List{"\(nomsu environment)"}; - for i=2,#\$args do \$compiled_args[i] = \(nomsu environment):compile(\$args[i]) end + local \$args = List{"\(nomsu environment)", "\(this tree)", unpack(\$actions[1]:get_args())} + local \$compiled_args = List{"\(nomsu environment)", "\(this tree)"}; + for i=3,#\$args do \$compiled_args[i] = \(nomsu environment):compile(\$args[i]) end for i=2,#\$actions do local alias = \$actions[i] - local \$alias_args = List{"\(nomsu environment)", unpack(alias:get_args())} + local \$alias_args = List{"\(nomsu environment)", "\(this tree)", unpack(alias:get_args())} lua:add("\\nCOMPILE_RULES[", alias:get_stub():as_lua(), "] = ") if \$alias_args == \$args then lua:add("COMPILE_RULES[", \$actions[1]:get_stub():as_lua(), "]") else lua:add("function(") - local \$compiled_alias_args = List{"\(nomsu environment)"}; - for i=2,#\$alias_args do \$compiled_alias_args[i] = \(nomsu environment):compile(\$alias_args[i]) end + local \$compiled_alias_args = List{"\(nomsu environment)", "\(this tree)"}; + for i=3,#\$alias_args do \$compiled_alias_args[i] = \(nomsu environment):compile(\$alias_args[i]) end lua:concat_add(\$compiled_alias_args, ", ") lua:add(") return COMPILE_RULES[", \$actions[1]:get_stub():as_lua(), "](") lua:concat_add(\$compiled_args, ", ") @@ -152,7 +171,7 @@ test: lua:add(\$action:get_stub():as_lua_id()) lua:add_free_vars({\$action:get_stub():as_lua_id()}) else - at_1_fail(\$action, "Compile error: Expected an action or method call here") + at_1_fail(\$action, "Compile error: This is not an action or method call.") end lua:add(" = ", \(\($action -> $body) as lua), ";") return lua @@ -415,6 +434,7 @@ external: lua> (" local lua_type = \(lua type of $) if lua_type == 'string' then return 'Text' + elseif lua_type == 'nil' then return 'nil' elseif lua_type == 'table' or lua_type == 'userdata' then local mt = getmetatable(\$) if mt and mt.__type then return mt.__type end @@ -428,6 +448,17 @@ external: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: + assume ("Action" tree with "foo" ("Var" tree with "x")) == \(foo \$x) + +external: + ($type tree with (*extra arguments*)) means + SyntaxTree (=lua "{type=\$type, ...}") + ($type tree from $source) means + SyntaxTree (=lua "{type=\$type, source=\$source}") + ($type tree from $source with (*extra arguments*)) means + SyntaxTree (=lua "{type=\$type, source=\$source, ...}") + +test: (foo) means: return 100 200 300 assume (select 2 (foo)) == 200 |
