aboutsummaryrefslogtreecommitdiff
path: root/lib/metaprogramming.nom
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-01-08 18:53:57 -0800
committerBruce Hill <bitbucket@bruce-hill.com>2018-01-08 18:53:57 -0800
commitf97ab858edae5495f8ebfef46656e86150665888 (patch)
treeed47620eba2365192ba54950647d6307223cac29 /lib/metaprogramming.nom
parent568a44ef191e1f4072d379700e3b6f599150a92b (diff)
Modernized the codebase a bit to include "immediately:" for immediately
running code before further parsing takes place. That means that in the default case, whole files can be run at once, which makes all but the weirdest edge cases make a lot more sense and operate smoothly.
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.*)");