aboutsummaryrefslogtreecommitdiff
path: root/core/metaprogramming.nom
diff options
context:
space:
mode:
Diffstat (limited to 'core/metaprogramming.nom')
-rw-r--r--core/metaprogramming.nom197
1 files changed, 85 insertions, 112 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index b104987..be7450a 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -3,7 +3,9 @@
This File contains actions for making actions and compile-time actions and some helper
functions to make that easier.
-lua> "NOMSU_CORE_VERSION = 9"
+lua> "\
+ ..NOMSU_CORE_VERSION = 10
+ NOMSU_LIB_VERSION = 7"
lua> "\
..do
local mangle_index = 0
@@ -15,17 +17,18 @@ lua> "\
end
end
end
- COMPILE_ACTIONS["define mangler"] = function(nomsu, tree)
+ compile.action["define mangler"] = function(compile, tree)
return LuaCode(tree.source, "local mangle = mangler()")
end"
lua> "\
- ..COMPILE_ACTIONS["1 ->"] = function(nomsu, tree, \%args, \%body)
- local lua = LuaCode.Value(tree.source, "(function(")
+ ..compile.action["1 ->"] = function(compile, tree, \%args, \%body)
+ local lua = LuaCode(tree.source, "(function(")
if SyntaxTree:is_instance(\%args) and \%args.type == "Action" then \%args = \%args:get_args() end
- local lua_args = table.map(\%args, function(a) return SyntaxTree:is_instance(a) and nomsu:compile(a):text() or a end)
+ local lua_args = table.map(\%args, function(a) return SyntaxTree:is_instance(a) and compile(a):text() or a end)
lua:concat_append(lua_args, ", ")
- local body_lua = SyntaxTree:is_instance(\%body) and nomsu:compile(\%body):as_statements("return ") or \%body
+ local body_lua = SyntaxTree:is_instance(\%body) and compile(\%body) or \%body
+ if SyntaxTree:is_instance(\%body) and \%body.type ~= "Block" then body_lua:prepend("return ") end
body_lua:remove_free_vars(lua_args)
body_lua:declare_locals()
lua:append(")\\n ", body_lua, "\\nend)")
@@ -33,10 +36,10 @@ lua> "\
end"
lua> "\
- ..COMPILE_ACTIONS["what 1 compiles to"] = function(nomsu, tree, \%action)
- local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", \%action.stub:as_lua(), "](")
- local lua_args = table.map(\%action:get_args(), function(a) return nomsu:compile(a) end)
- table.insert(lua_args, 1, "nomsu")
+ ..compile.action["what 1 compiles to"] = function(compile, tree, \%action)
+ local lua = LuaCode(tree.source, "compile.action[", \%action.stub:as_lua(), "](")
+ local lua_args = table.map(\%action:get_args(), function(a) return compile(a) end)
+ table.insert(lua_args, 1, "compile")
table.insert(lua_args, 2, "tree")
lua:concat_append(lua_args, ", ")
lua:append(")")
@@ -46,10 +49,10 @@ lua> "\
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test:
- (five) compiles to (Lua value "5")
+ (five) compiles to "5"
test:
assume ((five) == 5) or barf "Compile to expression failed."
- (loc x) compiles to (Lua "local x = 99;")
+ (loc x) compiles to "local x = 99;"
test:
lua> "do"
loc x
@@ -63,9 +66,12 @@ test:
asdf
assume (%tmp is (nil)) or barf "compile to is leaking variables"
lua> "\
- ..COMPILE_ACTIONS["1 compiles to"] = function(nomsu, tree, \%action, \%body)
- local \%args = List{\(\%nomsu), \(\%tree), unpack(\%action:get_args())}
- local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%action.stub:as_lua(),
+ ..compile.action["1 compiles to"] = function(compile, tree, \%action, \%body)
+ local \%args = List{\(\%compile), \(\%tree), unpack(\%action:get_args())}
+ if \%body.type == "Text" then
+ \%body = SyntaxTree{source=\%body.source, type="Action", "Lua", \%body}
+ end
+ local lua = LuaCode(tree.source, "compile.action[", \%action.stub:as_lua(),
"] = ", \(what (%args -> %body) compiles to))
return lua
end"
@@ -75,16 +81,16 @@ lua> "\
(%actions all compile to %body) compiles to:
lua> "\
..if \%actions.type ~= "List" then
- nomsu:compile_error(\%actions, "This should be a list of actions.")
+ compile_error(\%actions, "This should be a list of actions.")
end
local lua = LuaCode(tree.source, \(what (%actions.1 compiles to %body) compiles to))
- local \%args = List{\(\%nomsu), \(\%tree), unpack(\%actions[1]:get_args())}
+ local \%args = List{\(\%compile), \(\%tree), unpack(\%actions[1]:get_args())}
for i=2,#\%actions do
local alias = \%actions[i]
- local \%alias_args = List{\(\%nomsu), \(\%tree), unpack(alias:get_args())}
- lua:append("\\nCOMPILE_ACTIONS[", alias.stub:as_lua(), "] = ")
+ local \%alias_args = List{\(\%compile), \(\%tree), unpack(alias:get_args())}
+ lua:append("\\ncompile.action[", alias.stub:as_lua(), "] = ")
if \%alias_args == \%args then
- lua:append("COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "]")
+ lua:append("compile.action[", \%actions[1].stub:as_lua(), "]")
else
lua:append(\(what (%alias_args -> \(what %actions.1 compiles to)) compiles to))
end
@@ -95,17 +101,17 @@ lua> "\
(call %fn with %args) compiles to:
lua> "\
- ..local lua = LuaCode.Value(tree.source, nomsu:compile(\%fn), "(")
+ ..local lua = LuaCode(tree.source, compile(\%fn), "(")
if \%args.type == 'List' then
- lua:concat_append(table.map(\%args, function(a) return nomsu:compile(a) end), ", ")
+ lua:concat_append(table.map(\%args, function(a) return compile(a) end), ", ")
else
- lua:append('unpack(', nomsu:compile(\%args), ')')
+ lua:append('unpack(', compile(\%args), ')')
end
lua:append(")")
return lua"
test:
- (foo %x) means (return "outer")
+ (foo %x) means "outer"
with local [(foo %)'s meaning]:
(foo %x) means:
%y = (%x + 1)
@@ -162,7 +168,7 @@ test:
test:
assume (((say %)'s meaning) == (=lua "say"))
-(%action's meaning) compiles to (Lua value (%action.stub as lua id))
+(%action's meaning) compiles to (Lua (%action.stub as lua id))
test:
(swap %x and %y) parses as (..)
@@ -183,10 +189,10 @@ test:
lua> "\
..local replacements = {}
if \%actions.type ~= "List" then
- nomsu:compile_error(\%actions, "This should be a list.")
+ compile_error(\%actions, "This should be a list.")
end
for i,arg in ipairs(\%actions[1]:get_args()) do
- replacements[arg[1]] = nomsu:compile(arg):text()
+ replacements[arg[1]] = compile(arg):text()
end
local function make_tree(t)
if SyntaxTree:is_instance(t) and t.type == "Var" then
@@ -227,27 +233,17 @@ test:
[%action parses as %body] all parse as ([%action] all parse as %body)
-# TODO: add check for .is_value
-(%tree as lua expr) compiles to (..)
- Lua value "nomsu:compile(\(=lua "nomsu:compile(\%tree, nil, true)"), nil, true)"
+(%tree as lua expr) compiles to "\
+ ..compile(\(=lua "compile(\%tree, nil, true)"), nil, true)"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(%tree as lua) compiles to (Lua value "nomsu:compile(\(%tree as lua expr))")
-(%tree as lua statements) compiles to (..)
- Lua value "nomsu:compile(\(%tree as lua expr)):as_statements()"
-
-(%tree as lua return) compiles to (..)
- Lua value "nomsu:compile(\(%tree as lua expr)):as_statements('return ')"
-
-test:
- assume ("\(\(foo \%x) as nomsu)" == "foo %x") or barf "\
- ..action source code failed."
-(%tree as nomsu) compiles to (..)
- Lua value "nomsu:tree_to_nomsu(\(%tree as lua expr))"
+(%tree as lua) compiles to "compile(\(%tree as lua expr))"
+(%tree as lua statements) compiles to "\
+ ..compile(\(%tree as lua expr)):as_statements()"
-(%tree as inline nomsu) compiles to (..)
- Lua value "nomsu:tree_to_inline_nomsu(\(%tree as lua expr), true)"
+(%tree as lua return) compiles to "\
+ ..compile(\(%tree as lua expr)):as_statements('return ')"
externally [%var as lua identifier, %var as lua id] all mean:
lua> "\
@@ -256,7 +252,7 @@ externally [%var as lua identifier, %var as lua id] all mean:
elseif SyntaxTree:is_instance(\%var) then
local lua = \(%var as lua expr)
if not lua:text():match("^[_a-zA-Z][_a-zA-Z0-9]*$") then
- nomsu:compile_error(\%var, "This is not a valid Lua identifier.")
+ compile_error(\%var, "This is not a valid Lua identifier.")
end
return lua
else error("Unknown type: "..tostring(\%var))
@@ -264,15 +260,14 @@ externally [%var as lua identifier, %var as lua id] all mean:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(% is syntax tree) compiles to (Lua value "SyntaxTree:is_instance(\(% as lua expr))")
-(% is %kind syntax tree) compiles to (..)
- Lua value "SyntaxTree:is_instance(\(% as lua expr), \(%kind as lua expr))"
+(% is syntax tree) compiles to "SyntaxTree:is_instance(\(% as lua expr))"
+externally (% is %kind syntax tree) means (..)
+ =lua "SyntaxTree:is_instance(\%) and \%.type == \%kind"
-(%tree with %t -> %replacement) compiles to (..)
- Lua value "\
- ..\(%tree as lua expr):map(function(\(%t as lua expr))
- \(%replacement as lua return)
- end)"
+(%tree with %t -> %replacement) compiles to "\
+ ..\(%tree as lua expr):map(function(\(%t as lua expr))
+ \(%replacement as lua return)
+ end)"
externally (%tree with vars %replacements) means (..)
=lua "\
@@ -282,22 +277,20 @@ externally (%tree with vars %replacements) means (..)
end
end)"
-(tree %tree with vars %replacements) compiles to (..)
- Lua value "\
- ..\(=lua "(\%tree):as_lua()"):map(function(t)
- if t.type == "Var" then
- return \(%replacements as lua expr)[t[1]]
- end
- end)"
+(tree %tree with vars %replacements) compiles to "\
+ ..\(=lua "(\%tree):as_lua()"):map(function(t)
+ if t.type == "Var" then
+ return \(%replacements as lua expr)[t[1]]
+ end
+ end)"
-(%tree has subtree %match_tree) compiles to (..)
- Lua value "\
- ..(function()
- local match_tree = \(%match_tree as lua expr)
- for subtree in coroutine.wrap(function() \(%tree as lua expr):map(coroutine.yield) end) do
- if subtree == match_tree then return true end
- end
- end)()"
+(%tree has subtree %match_tree) compiles to "\
+ ..(function()
+ local match_tree = \(%match_tree as lua expr)
+ for subtree in coroutine.wrap(function() \(%tree as lua expr):map(coroutine.yield) end) do
+ if subtree == match_tree then return true end
+ end
+ end)()"
externally (match %tree with %patt) means:
lua> "\
@@ -339,7 +332,7 @@ test:
..one
"two""
..== "\"one\\n\\\"two\\\"\""
-(quote %s) compiles to (Lua value "tostring(\(%s as lua expr)):as_lua()")
+(quote %s) compiles to (Lua "tostring(\(%s as lua expr)):as_lua()")
test:
assume (lua type of {}) == "table"
@@ -368,63 +361,43 @@ externally (type of %) means:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test:
- assume ((parse "foo %") == \(foo \%))
- %a = (parse "\\1")
- %b = \(\(1))
- assume ((parse "\\1") == \(\(1)))
-(parse %text) compiles to (Lua value "nomsu:parse(\(%text as lua expr))")
-(parse %text from %filename) compiles to (..)
- Lua value "\
- ..nomsu:parse(NomsuCode(Source(\(%filename as lua expr), 1, #\(%text as lua expr)), \(..)
- %text as lua expr
- ..))"
-
-test:
assume ((run "return (2 + 99)") == 101)
external %passed = (no)
run "external %passed = (yes)"
assume %passed
-(run %nomsu_code) compiles to (..)
- Lua value "\
- ..nomsu:run(NomsuCode(\(=lua "tostring(\(%nomsu_code.source)):as_lua()"), \(..)
- %nomsu_code as lua expr
- ..))"
+ assume (run \(return \(\(5) + \(5)))) == 10
+(run %nomsu_code) compiles to "\
+ ..run_1_in(\(%nomsu_code as lua expr), _ENV)"
-test:
- assume ((\(\(5) + \(5)) as value) == 10) or barf "%tree as value failed."
-[run tree %tree, %tree as value] all compile to (..)
- Lua value "nomsu:run(\(%tree as lua expr))"
-
-[compile %block, compiled %block, %block compiled] all compile to (..)
- Lua value "nomsu:compile(\(%block as lua))"
+[compile %block, compiled %block, %block compiled] all compile to "\
+ ..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.
-(return) compiles to (Lua "do return; end")
-(return %return_value) compiles to (..)
- Lua "do return \(%return_value as lua expr) end"
+(return) compiles to "do return; end"
+(return %return_value) compiles to "do return \(%return_value as lua expr) end"
# Literals
-(yes) compiles to (Lua value "true")
-(no) compiles to (Lua value "false")
-[nothing, nil, null] all compile to (Lua value "nil")
-(Nomsu syntax version) compiles to (Lua value "NOMSU_SYNTAX_VERSION")
-(Nomsu compiler version) compiles to (Lua value "NOMSU_COMPILER_VERSION")
-(core version) compiles to (Lua value "NOMSU_CORE_VERSION")
-(lib version) compiles to (Lua value "NOMSU_LIB_VERSION")
-(command line args) compiles to (Lua value "arg")
+(yes) compiles to "true"
+(no) compiles to "false"
+[nothing, nil, null] all compile to "nil"
+(Nomsu syntax version) compiles to "NOMSU_SYNTAX_VERSION"
+(Nomsu compiler version) compiles to "NOMSU_COMPILER_VERSION"
+(core version) compiles to "NOMSU_CORE_VERSION"
+(lib version) compiles to "NOMSU_LIB_VERSION"
+(command line args) compiles to "command_line_args"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(with local compile actions %body) compiles to (..)
- Lua "\
- ..do
- local nomsu = nomsu:fork()
- local COMPILE_ACTIONS = nomsu.environment.COMPILE_ACTIONS
- \(%body as lua statements)
- end"
+(with local compile actions %body) compiles to "\
+ ..do
+ --local compile = _1_forked(compile)
+ local old_action = compile.action
+ compile.action = _1_forked(old_action)
+ \(%body as lua statements)
+ compile.action = old_action
+ end"
externally (Nomsu version) means:
- use "lib/version.nom"
return "\
..\(Nomsu syntax version).\(core version).\(Nomsu compiler version).\(lib version)"