aboutsummaryrefslogtreecommitdiff
path: root/lib/metaprogramming.nom
diff options
context:
space:
mode:
Diffstat (limited to 'lib/metaprogramming.nom')
-rw-r--r--lib/metaprogramming.nom196
1 files changed, 102 insertions, 94 deletions
diff --git a/lib/metaprogramming.nom b/lib/metaprogramming.nom
index 325f102..f59ce04 100644
--- a/lib/metaprogramming.nom
+++ b/lib/metaprogramming.nom
@@ -3,74 +3,93 @@
that easier.
# Rule to make rules:
-lua> ".."
- nomsu:defmacro("rule %signature = %body", (function(nomsu, vars)
- nomsu:assert(\%signature.type == "List",
- "Invalid type for rule definition signature. Expected List, but got: "..tostring(\%signature.type));
- nomsu:assert(\%body.type == "Thunk",
- "Invalid type for rule definition body. Expected Thunk, but got: "..tostring(\%body.type));
- local signature = {};
- for i, alias in ipairs(\%signature.value) do
- signature[i] = alias.src;
- end
- local src = nomsu:source_code(0);
- return nil, ([[
- nomsu:def(%s, %s, %s)
- ]]):format(nomsu:repr(signature), nomsu:tree_to_lua(\%body), nomsu:repr(nomsu:dedent(src)));
- end), \(__src__ 1));
-
-# Rule to make lua macros:
-rule [compile \%macro_def to \%body] =:
+immediately:
lua> ".."
- nomsu:assert(\%macro_def.type == "List",
- "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
- nomsu:assert(\%body.type == "Thunk",
- "Invalid type for compile definition body. Expected Thunk, but got: "..tostring(\%body.type));
- local signature = {};
- for i, alias in ipairs(\%macro_def.value) do
- signature[i] = alias.src;
- end
- local thunk = nomsu:tree_to_value(\%body);
- nomsu:defmacro(signature, thunk, ("compile %s\\n..to %s"):format(\%macro_def.src, \%body.src));
+ nomsu:defmacro("rule %signature = %body", (function(nomsu, vars)
+ nomsu:assert(\%signature.type == "List",
+ "Invalid type for rule definition signature. Expected List, but got: "..tostring(\%signature.type));
+ nomsu:assert(\%body.type == "Block",
+ "Invalid type for rule definition body. Expected Block, but got: "..tostring(\%body.type));
+ local signature = {};
+ for i, alias in ipairs(\%signature.value) do
+ signature[i] = alias.src;
+ end
+ local src = nomsu:source_code(0);
+ local body_lua = nomsu:tree_to_lua(\%body);
+ local fn_src = ([[
+ function(nomsu, vars)
+ %s
+ end]]):format(body_lua.statements or ("return "..body_lua.expr..";"));
+ return {statements=([[
+ nomsu:def(%s, %s, %s)
+ ]]):format(nomsu:repr(signature), fn_src, nomsu:repr(nomsu:dedent(src)))};
+ end), \(__src__ 1));
-rule [compile \%macro_def to code \%body] =:
- lua> ".."
- nomsu:assert(\%macro_def.type == "List",
- "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
- nomsu:assert(\%body.type == "Thunk",
- "Invalid type for compile definition body. Expected Thunk, but got: "..tostring(\%body.type));
- local signature = {};
- for i, alias in ipairs(\%macro_def.value) do
- signature[i] = alias.src;
- end
- local thunk = nomsu:tree_to_value(\%body);
- local thunk_wrapper = function(...) return nil, thunk(...); end
- nomsu:defmacro(signature, thunk_wrapper, ("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src));
+# Rules to make lua macros:
+immediately:
+ rule [compile \%macro_def to \%body] =:
+ lua> ".."
+ nomsu:assert(\%macro_def.type == "List",
+ "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
+ nomsu:assert(\%body.type == "Block",
+ "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
+ local signature = {};
+ for i, alias in ipairs(\%macro_def.value) do
+ signature[i] = alias.src;
+ end
+ local body_lua = nomsu:tree_to_lua(\%body);
+ local fn_src = ([[
+ function(nomsu, vars)
+ %s
+ end]]):format(body_lua.statements or ("return "..body_lua.expr..";"));
+ local fn = nomsu:run_lua("return "..fn_src..";");
+ local fn_wrapper = function(...) return {expr=fn(...)}; end;
+ nomsu:defmacro(signature, fn_wrapper, ("compile %s\\n..to %s"):format(\%macro_def.src, \%body.src));
+
+ rule [compile \%macro_def to code \%body] =:
+ lua> ".."
+ nomsu:assert(\%macro_def.type == "List",
+ "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
+ nomsu:assert(\%body.type == "Block",
+ "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
+ local signature = {};
+ for i, alias in ipairs(\%macro_def.value) do
+ signature[i] = alias.src;
+ end
+ local body_lua = nomsu:tree_to_lua(\%body);
+ local fn_src = ([[
+ function(nomsu, vars)
+ %s
+ end]]):format(body_lua.statements or ("return "..body_lua.expr..";"));
+ local fn = nomsu:run_lua("return "..fn_src..";");
+ local fn_wrapper = function(...) return {statements=fn(...)}; end;
+ nomsu:defmacro(signature, fn_wrapper, ("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src));
# Rule to make nomsu macros:
-lua> ".."
- nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, vars)
- nomsu:assert(\%shorthand.type == "List",
- "Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type));
- nomsu:assert(\%longhand.type == "Thunk",
- "Invalid type for parse definition body. Expected Thunk, but got: "..tostring(\%longhand.type));
- local signature = {};
- for i, alias in ipairs(\%shorthand.value) do
- signature[i] = alias.src;
- end
- local template = {};
- for i, line in ipairs(\%longhand.value) do
- template[i] = nomsu:dedent(line.src);
- end
- signature, template = nomsu:repr(signature), nomsu:repr(table.concat(template, "\\n"));
- return nil, ([[
- nomsu:defmacro(%s, (function(nomsu, vars)
- local template = nomsu:parse(%s, %s);
- if #template.value == 1 then template = template.value[1]; end
- local replacement = nomsu:replaced_vars(template, vars);
- return nomsu:tree_to_lua(replacement);
- end), %s)]]):format(signature, template, nomsu:repr(\%shorthand.line_no), nomsu:repr(nomsu:source_code(0)));
- end), \(__src__ 1));
+immediately:
+ lua> ".."
+ nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, vars)
+ nomsu:assert(\%shorthand.type == "List",
+ "Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type));
+ nomsu:assert(\%longhand.type == "Block",
+ "Invalid type for parse definition body. Expected Block, but got: "..tostring(\%longhand.type));
+ local signature = {};
+ for i, alias in ipairs(\%shorthand.value) do
+ signature[i] = alias.src;
+ end
+ local template = {};
+ for i, line in ipairs(\%longhand.value) do
+ template[i] = nomsu:dedent(line.src);
+ end
+ signature, template = nomsu:repr(signature), nomsu:repr(table.concat(template, "\\n"));
+ return {expr=([[
+ nomsu:defmacro(%s, (function(nomsu, vars)
+ local template = nomsu:parse(%s, %s);
+ if #template.value == 1 then template = template.value[1]; end
+ local replacement = nomsu:replaced_vars(template, vars);
+ return nomsu:tree_to_lua(replacement);
+ end), %s)]]):format(signature, template, nomsu:repr(\%shorthand.line_no), nomsu:repr(nomsu:source_code(0)))};
+ end), \(__src__ 1));
rule [remove rule %stub] =:
lua> ".."
@@ -79,40 +98,29 @@ rule [remove rule %stub] =:
nomsu.defs[alias] = false;
end
-rule [%tree as lua] =:
- =lua "nomsu:tree_to_lua(\%tree)"
-rule [%tree as value] =:
- =lua "nomsu:tree_to_value(\%tree, vars)"
-compile [repr %obj] to:
- "nomsu:repr(\(%obj as lua))"
-compile [indented %obj] to:
- "nomsu:indent(\(%obj as lua))"
-compile [dedented %obj] to:
- "nomsu:dedent(\(%obj as lua))"
-compile [type %obj, type of %obj] to:
- "type(\(%obj as lua))"
+immediately:
+ rule [%tree as lua] =:
+ =lua "nomsu:tree_to_lua(\%tree).expr"
+ rule [%tree as lua statements] =:
+ lua> ".."
+ local lua = nomsu:tree_to_lua(\%tree);
+ return lua.statements or (lua.expr..";");
+ rule [%tree as value] =:
+ =lua "nomsu:tree_to_value(\%tree, vars)"
+ compile [repr %obj] to:
+ "nomsu:repr(\(%obj as lua))"
+ compile [indented %obj] to:
+ "nomsu:indent(\(%obj as lua))"
+ compile [dedented %obj] to:
+ "nomsu:dedent(\(%obj as lua))"
+ compile [type %obj, type of %obj] to:
+ "type(\(%obj as lua))"
parse [lua do> %block] as:
lua> "do"
lua> %block
lua> "end"
-rule [%tree as lua statement] =:
- lua do> ".."
- local _,statement = nomsu:tree_to_lua(\%tree);
- return statement;
-rule [%tree as lua statements] =:
- lua do> ".."
- local lua_bits = {};
- nomsu:assert(type(\%tree) == 'table' and \%tree.type == "Thunk",
- "Invalid type. Expected Thunk.");
- for _,bit in ipairs(\%tree.value) do
- local expr, statement = nomsu:tree_to_lua(bit);
- if statement then table.insert(lua_bits, statement); end
- if expr then table.insert(lua_bits, "ret = "..expr..";"); end
- end
- return table.concat(lua_bits, "\\n");
-
compile [nomsu] to: "nomsu"
compile [nomsu's %key] to: "nomsu[\(%key as lua)]"
compile [nomsu %method %args] to: "nomsu[\(%method as lua)](nomsu, unpack(\(%args as lua)))"
@@ -124,7 +132,7 @@ parse [rule %signature] as:
# Get the source code for a function
rule [help %rule] =:
- lua do> ".."
+ lua> ".."
local fn_def = nomsu.defs[nomsu:get_stub(\%rule)]
if not fn_def then
nomsu:writeln("Rule not found: "..nomsu:repr(\%rule));
@@ -135,7 +143,7 @@ rule [help %rule] =:
# Compiler tools
parse [eval %code, run %code] as: nomsu "run" [%code]
rule [source code from tree %tree] =:
- lua do> ".."
+ lua> ".."
local _,_,leading_space = \%tree.src:find("\\n(%s*)%S");
if leading_space then
local chunk1, chunk2 = \%tree.src:match(":%s*([^\\n]*)(\\n.*)");