aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-01-09 14:59:06 -0800
committerBruce Hill <bitbucket@bruce-hill.com>2018-01-09 14:59:06 -0800
commit421abe1a6f6c04ba55106b9154160ccd45d83610 (patch)
tree84a028fd28708622ee54495c119d4691e6b8b497 /lib
parentf97ab858edae5495f8ebfef46656e86150665888 (diff)
Cleaned up metaprogramming to go "compile to" -> "rule =" -> "parse as".
This speeds things up a bit, and is more intuitive.
Diffstat (limited to 'lib')
-rw-r--r--lib/control_flow.nom557
-rw-r--r--lib/metaprogramming.nom80
2 files changed, 330 insertions, 307 deletions
diff --git a/lib/control_flow.nom b/lib/control_flow.nom
index 5169ac2..922338f 100644
--- a/lib/control_flow.nom
+++ b/lib/control_flow.nom
@@ -3,312 +3,327 @@ require "lib/operators.nom"
require "lib/utils.nom"
# Conditionals
-compile [if %condition %if_body] to code: ".."
- if \(%condition as lua) then
- \(%if_body as lua statements)
- end --end if
-parse [unless %condition %unless_body] as: if (not %condition) %unless_body
-parse [if %x == %y %if_body] as: if (%x == %y) %if_body
-parse [if %x != %y %if_body] as: if (%x != %y) %if_body
-parse [unless %x == %y %if_body] as: if (%x != %y) %if_body
-parse [unless %x != %y %if_body] as: if (%x == %y) %if_body
+immediately:
+ compile [if %condition %if_body] to code: ".."
+ if \(%condition as lua) then
+ \(%if_body as lua statements)
+ end --end if
+ parse [unless %condition %unless_body] as: if (not %condition) %unless_body
+ parse [if %x == %y %if_body] as: if (%x == %y) %if_body
+ parse [if %x != %y %if_body] as: if (%x != %y) %if_body
+ parse [unless %x == %y %if_body] as: if (%x != %y) %if_body
+ parse [unless %x != %y %if_body] as: if (%x == %y) %if_body
-compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to code: ".."
- if \(%condition as lua) then
- \(%if_body as lua statements)
- else
- \(%else_body as lua statements)
- end --end if
-parse [if %x == %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
-parse [if %x != %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
-parse [unless %x == %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
-parse [unless %x != %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
+ compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to code: ".."
+ if \(%condition as lua) then
+ \(%if_body as lua statements)
+ else
+ \(%else_body as lua statements)
+ end --end if
+ parse [if %x == %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
+ parse [if %x != %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
+ parse [unless %x == %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
+ parse [unless %x != %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
# Return
-compile [return] to code: "do return; end"
-compile [return %return_value] to code: "do return \(%return_value as lua); end"
+immediately:
+ compile [return] to code: "do return; end"
+ compile [return %return_value] to code: "do return \(%return_value as lua); end"
# GOTOs
-compile [-> %label] to code: ".."
- ::label_\(nomsu "var_to_lua_identifier" [%label])::;
-compile [go to %label] to code: ".."
- goto label_\(nomsu "var_to_lua_identifier" [%label]);
+immediately:
+ compile [-> %label] to code: ".."
+ ::label_\(nomsu "var_to_lua_identifier" [%label])::;
+ compile [go to %label] to code: ".."
+ goto label_\(nomsu "var_to_lua_identifier" [%label]);
-rule [tree %tree has function call %call] =:
- lua> ".."
- local target = (\%call).stub;
- for subtree,_ in coroutine.wrap(function() nomsu:walk_tree(\%tree); end) do
- if type(subtree) == 'table' and subtree.type == "FunctionCall"
- and subtree.stub == target then
- return true;
+# Helper function
+immediately:
+ rule [tree %tree has function call %call] =:
+ lua> ".."
+ local target = (\%call).stub;
+ for subtree,_ in coroutine.wrap(function() nomsu:walk_tree(\%tree); end) do
+ if type(subtree) == 'table' and subtree.type == "FunctionCall"
+ and subtree.stub == target then
+ return true;
+ end
end
- end
- return false;
+ return false;
# While loops
-compile [do next repeat-loop] to code: "goto continue_repeat;"
-compile [stop repeat-loop] to code: "goto stop_repeat;"
-compile [repeat while %condition %body] to code:
- %continue_labels = (..)
- "\n::continue_repeat::;" if (tree %body has function call \(do next repeat-loop)) else ""
- %code = ".."
- while \(%condition as lua) do
- \(%body as lua statements)\
- ..\%continue_labels
- end --while-loop
- if (tree %body has function call \(stop repeat-loop)):
- return ".."
- do --while-loop label scope
- \%code
- ::stop_repeat::;
- end --while-loop label scope
- return %code
-parse [repeat %body] as: repeat while (true) %body
-parse [repeat until %condition %body] as: repeat while (not %condition) %body
-parse [repeat while %x == %y %body] as: repeat while (%x == %y) %body
-parse [repeat while %x != %y %body] as: repeat while (%x != %y) %body
-parse [repeat until %x == %y %body] as: repeat while (%x != %y) %body
-parse [repeat until %x != %y %body] as: repeat while (%x == %y) %body
+immediately:
+ compile [do next repeat-loop] to code: "goto continue_repeat;"
+ compile [stop repeat-loop] to code: "goto stop_repeat;"
+ compile [repeat while %condition %body] to code:
+ %continue_labels = (..)
+ "\n::continue_repeat::;" if (tree %body has function call \(do next repeat-loop)) else ""
+ %code = ".."
+ while \(%condition as lua) do
+ \(%body as lua statements)\
+ ..\%continue_labels
+ end --while-loop
+ if (tree %body has function call \(stop repeat-loop)):
+ return ".."
+ do --while-loop label scope
+ \%code
+ ::stop_repeat::;
+ end --while-loop label scope
+ return %code
+ parse [repeat %body] as: repeat while (true) %body
+ parse [repeat until %condition %body] as: repeat while (not %condition) %body
+ parse [repeat while %x == %y %body] as: repeat while (%x == %y) %body
+ parse [repeat while %x != %y %body] as: repeat while (%x != %y) %body
+ parse [repeat until %x == %y %body] as: repeat while (%x != %y) %body
+ parse [repeat until %x != %y %body] as: repeat while (%x == %y) %body
# For loop control flow:
-compile [stop for-loop] to code: "goto stop_for;"
-compile [stop %var] to code: ".."
- goto stop_\(nomsu "var_to_lua_identifier" [%var]);
-compile [do next for-loop] to code: "goto continue_for;"
-compile [do next %var] to code: ".."
- goto continue_\(nomsu "var_to_lua_identifier" [%var]);
+immediately:
+ compile [stop for-loop] to code: "goto stop_for;"
+ compile [stop %var] to code: ".."
+ goto stop_\(nomsu "var_to_lua_identifier" [%var]);
+ compile [do next for-loop] to code: "goto continue_for;"
+ compile [do next %var] to code: ".."
+ goto continue_\(nomsu "var_to_lua_identifier" [%var]);
# Numeric range for loops
-compile [..]
- for %var from %start to %stop by %step %body
- for %var from %start to %stop via %step %body
-..to code:
- %continue_labels = ""
- if (tree %body has function call \(do next for-loop)):
- %continue_labels join= "\n::continue_for::;"
- if (tree %body has function call (tree \(do next %) with {""=%var})):
- %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
- # This trashes the loop variables, just like in Python.
- %code = ".."
- for i=\(%start as lua),\(%stop as lua),\(%step as lua) do
- \(%var as lua) = i;
- \(%body as lua statements)\
- ..\%continue_labels
- end --numeric for-loop
- %stop_labels = ""
- if (tree %body has function call \(stop for-loop)):
- %stop_labels join= "\n::stop_for::;"
- if (tree %body has function call (tree \(stop %) with {""=%var})):
- %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
- return (..)
- ".."
- do --for-loop label scope
- \%code\
- ..\%stop_labels
- end --for-loop label scope
- ..if %stop_labels != "" else %code
+immediately:
+ compile [..]
+ for %var from %start to %stop by %step %body
+ for %var from %start to %stop via %step %body
+ ..to code:
+ %continue_labels = ""
+ if (tree %body has function call \(do next for-loop)):
+ %continue_labels join= "\n::continue_for::;"
+ if (tree %body has function call (tree \(do next %) with {""=%var})):
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
+ # This trashes the loop variables, just like in Python.
+ %code = ".."
+ for i=\(%start as lua),\(%stop as lua),\(%step as lua) do
+ \(%var as lua) = i;
+ \(%body as lua statements)\
+ ..\%continue_labels
+ end --numeric for-loop
+ %stop_labels = ""
+ if (tree %body has function call \(stop for-loop)):
+ %stop_labels join= "\n::stop_for::;"
+ if (tree %body has function call (tree \(stop %) with {""=%var})):
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
+ return (..)
+ ".."
+ do --for-loop label scope
+ \%code\
+ ..\%stop_labels
+ end --for-loop label scope
+ ..if %stop_labels != "" else %code
-parse [for %var from %start to %stop %body] as: for %var from %start to %stop via 1 %body
-parse [..]
- for all %start to %stop by %step %body
- for all %start to %stop via %step %body
-..as: for % from %start to %stop via %step %body
-parse [for all %start to %stop %body] as: for all %start to %stop via 1 %body
+immediately:
+ parse [for %var from %start to %stop %body] as: for %var from %start to %stop via 1 %body
+ parse [..]
+ for all %start to %stop by %step %body
+ for all %start to %stop via %step %body
+ ..as: for % from %start to %stop via %step %body
+ parse [for all %start to %stop %body] as: for all %start to %stop via 1 %body
-compile [for %var in %iterable %body] to code:
- %continue_labels = ""
- if (tree %body has function call \(do next for-loop)):
- %continue_labels join= "\n::continue_for::;"
- if (tree %body has function call (tree \(do next %) with {""=%var})):
- %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
- # This trashes the loop variables, just like in Python.
- %code = ".."
- for i,value in ipairs(\(%iterable as lua)) do
- \(%var as lua) = value;
- \(%body as lua statements)\
- ..\%continue_labels
- end --foreach-loop
- %stop_labels = ""
- if (tree %body has function call \(stop for-loop)):
- %stop_labels join= "\n::stop_for::;"
- if (tree %body has function call (tree \(stop %) with {""=%var})):
- %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
- return (..)
- ".."
- do --for-loop label scope
- \%code\%stop_labels
- end --for-loop label scope
- ..if %stop_labels != "" else %code
-parse [for all %iterable %body] as: for % in %iterable %body
+immediately:
+ compile [for %var in %iterable %body] to code:
+ %continue_labels = ""
+ if (tree %body has function call \(do next for-loop)):
+ %continue_labels join= "\n::continue_for::;"
+ if (tree %body has function call (tree \(do next %) with {""=%var})):
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
+ # This trashes the loop variables, just like in Python.
+ %code = ".."
+ for i,value in ipairs(\(%iterable as lua)) do
+ \(%var as lua) = value;
+ \(%body as lua statements)\
+ ..\%continue_labels
+ end --foreach-loop
+ %stop_labels = ""
+ if (tree %body has function call \(stop for-loop)):
+ %stop_labels join= "\n::stop_for::;"
+ if (tree %body has function call (tree \(stop %) with {""=%var})):
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
+ return (..)
+ ".."
+ do --for-loop label scope
+ \%code\%stop_labels
+ end --for-loop label scope
+ ..if %stop_labels != "" else %code
+ parse [for all %iterable %body] as: for % in %iterable %body
# Dict iteration (lua's "pairs()")
-compile [for %key = %value in %iterable %body] to code:
- %continue_labels = ""
- if (tree %body has function call \(do next for-loop)):
- %continue_labels join= "\n::continue_for::;"
- if (tree %body has function call (tree \(do next %x) with {x=%key})):
- %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%key])::;"
- if (tree %body has function call (tree \(do next %) with {""=%value})):
- %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%value])::;"
- # This trashes the loop variables, just like in Python.
- %code = ".."
- for key,value in ipairs(\(%iterable as lua)) do
- \(%key as lua), \(%value as lua) = key, value;
- \(%body as lua statements)\
- ..\%continue_labels
- end --foreach-loop
- %stop_labels = ""
- if (tree %body has function call \(stop for-loop)):
- %stop_labels join= "\n::stop_for::;"
- if (tree %body has function call (tree \(stop %) with {""=%key})):
- %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%key])::;"
- if (tree %body has function call (tree \(stop %) with {""=%value})):
- %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%value])::;"
- return (..)
- ".."
- do --for-loop label scope
- \%code\
- ..\%stop_labels
- end --for-loop label scope
- ..if %stop_labels != "" else %code
+immediately:
+ compile [for %key = %value in %iterable %body] to code:
+ %continue_labels = ""
+ if (tree %body has function call \(do next for-loop)):
+ %continue_labels join= "\n::continue_for::;"
+ if (tree %body has function call (tree \(do next %x) with {x=%key})):
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%key])::;"
+ if (tree %body has function call (tree \(do next %) with {""=%value})):
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%value])::;"
+ # This trashes the loop variables, just like in Python.
+ %code = ".."
+ for key,value in ipairs(\(%iterable as lua)) do
+ \(%key as lua), \(%value as lua) = key, value;
+ \(%body as lua statements)\
+ ..\%continue_labels
+ end --foreach-loop
+ %stop_labels = ""
+ if (tree %body has function call \(stop for-loop)):
+ %stop_labels join= "\n::stop_for::;"
+ if (tree %body has function call (tree \(stop %) with {""=%key})):
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%key])::;"
+ if (tree %body has function call (tree \(stop %) with {""=%value})):
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%value])::;"
+ return (..)
+ ".."
+ do --for-loop label scope
+ \%code\
+ ..\%stop_labels
+ end --for-loop label scope
+ ..if %stop_labels != "" else %code
# Switch statement/multi-branch if
-compile [when %body] to code:
- %result = ""
- %fallthroughs = []
- %first = (yes)
- for %func_call in (%body's "value"):
- assert ((%func_call's "type") == "FunctionCall") ".."
- Invalid format for 'when' statement. Only '*' blocks are allowed.
- %tokens = (%func_call's "value")
- %star = (%tokens -> 1)
- assert (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") ".."
- Invalid format for 'when' statement. Lines must begin with '*'
+immediately:
+ compile [when %body] to code:
+ %result = ""
+ %fallthroughs = []
+ %first = (yes)
+ for %func_call in (%body's "value"):
+ assert ((%func_call's "type") == "FunctionCall") ".."
+ Invalid format for 'when' statement. Only '*' blocks are allowed.
+ %tokens = (%func_call's "value")
+ %star = (%tokens -> 1)
+ assert (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") ".."
+ Invalid format for 'when' statement. Lines must begin with '*'
- %condition = (%tokens -> 2)
- assert %condition ".."
- Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
+ %condition = (%tokens -> 2)
+ assert %condition ".."
+ Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
- %action = (%tokens -> 3)
- if (%action == (nil)):
- lua do> "table.insert(\%fallthroughs, \%condition)"
- do next %func_call
+ %action = (%tokens -> 3)
+ if (%action == (nil)):
+ lua do> "table.insert(\%fallthroughs, \%condition)"
+ do next %func_call
- if (=lua "\%condition.type == 'Word' and \%condition.value == 'else'"):
- %result join= ".."
-
- else
- \(%action as lua statements)
- stop for-loop
- ..else:
- %condition = (%condition as lua)
- for all %fallthroughs:
- %condition join= " or \(% as lua)"
- %result join= ".."
-
- \("if" if %first else "elseif") \%condition then
- \(%action as lua statements)
+ if (=lua "\%condition.type == 'Word' and \%condition.value == 'else'"):
+ %result join= ".."
+
+ else
+ \(%action as lua statements)
+ stop for-loop
+ ..else:
+ %condition = (%condition as lua)
+ for all %fallthroughs:
+ %condition join= " or \(% as lua)"
+ %result join= ".."
+
+ \("if" if %first else "elseif") \%condition then
+ \(%action as lua statements)
- %fallthroughs = []
- %first = (no)
+ %fallthroughs = []
+ %first = (no)
- if (%result != ""):
- %result join= "\nend"
- return %result
+ if (%result != ""):
+ %result join= "\nend"
+ return %result
# Switch statement
-compile [when %branch_value == ? %body] to code:
- %result = ""
- %fallthroughs = []
- %first = (yes)
- for %func_call in (%body's "value"):
- assert ((%func_call's "type") == "FunctionCall") ".."
- Invalid format for 'when' statement. Only '*' blocks are allowed.
- %tokens = (%func_call's "value")
- %star = (%tokens -> 1)
- assert (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") ".."
- Invalid format for 'when' statement. Lines must begin with '*'
+immediately:
+ compile [when %branch_value == ? %body] to code:
+ %result = ""
+ %fallthroughs = []
+ %first = (yes)
+ for %func_call in (%body's "value"):
+ assert ((%func_call's "type") == "FunctionCall") ".."
+ Invalid format for 'when' statement. Only '*' blocks are allowed.
+ %tokens = (%func_call's "value")
+ %star = (%tokens -> 1)
+ assert (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") ".."
+ Invalid format for 'when' statement. Lines must begin with '*'
- %condition = (%tokens -> 2)
- assert %condition ".."
- Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
+ %condition = (%tokens -> 2)
+ assert %condition ".."
+ Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
- %action = (%tokens -> 3)
- if (%action == (nil)):
- lua> "table.insert(\%fallthroughs, \%condition)"
- do next %func_call
+ %action = (%tokens -> 3)
+ if (%action == (nil)):
+ lua> "table.insert(\%fallthroughs, \%condition)"
+ do next %func_call
- if (=lua "\%condition.type == 'Word' and \%condition.value == 'else'"):
- %result join= ".."
-
- else
- \(%action as lua statements)
- stop for-loop
- ..else:
- %condition = "branch_value == (\(%condition as lua))"
- for all %fallthroughs:
- %condition join= " or (branch_value == \(% as lua))"
- %result join= ".."
-
- \("if" if %first else "elseif") \%condition then
- \(%action as lua statements)
+ if (=lua "\%condition.type == 'Word' and \%condition.value == 'else'"):
+ %result join= ".."
+
+ else
+ \(%action as lua statements)
+ stop for-loop
+ ..else:
+ %condition = "branch_value == (\(%condition as lua))"
+ for all %fallthroughs:
+ %condition join= " or (branch_value == \(% as lua))"
+ %result join= ".."
+
+ \("if" if %first else "elseif") \%condition then
+ \(%action as lua statements)
- %fallthroughs = []
- %first = (no)
+ %fallthroughs = []
+ %first = (no)
- if (%result != ""):
- %result = ".."
- do --when == ?
- local branch_value = \(%branch_value as lua);\
- ..\%result
- end
- end --when == ?
- return %result
+ if (%result != ""):
+ %result = ".."
+ do --when == ?
+ local branch_value = \(%branch_value as lua);\
+ ..\%result
+ end
+ end --when == ?
+ return %result
# Try/except
-compile [..]
- try %action and if it succeeds %success or if it fails %fallback
- try %action and if it fails %fallback or if it succeeds %success
-..to code: ".."
- do
- local fell_through = false;
- local ok, ret1, ret2 = pcall(function(nomsu, vars)
- \(%action as lua statements)
- fell_through = true;
- end, nomsu, vars);
- if ok then
- \(%success as lua statements)
- end
- if not ok then
- \(%fallback as lua statements)
- elseif not fell_through then
- return ret1, ret2;
+immediately:
+ compile [..]
+ try %action and if it succeeds %success or if it fails %fallback
+ try %action and if it fails %fallback or if it succeeds %success
+ ..to code: ".."
+ do
+ local fell_through = false;
+ local ok, ret1, ret2 = pcall(function(nomsu, vars)
+ \(%action as lua statements)
+ fell_through = true;
+ end, nomsu, vars);
+ if ok then
+ \(%success as lua statements)
+ end
+ if not ok then
+ \(%fallback as lua statements)
+ elseif not fell_through then
+ return ret1, ret2;
+ end
end
- end
-parse [try %action] as:
- try %action and if it succeeds: pass
- ..or if it fails: pass
-parse [try %action and if it fails %fallback] as:
- try %action and if it succeeds: pass
- ..or if it fails %fallback
-parse [try %action and if it succeeds %success] as:
- try %action and if it succeeds %success or if it fails: pass
+ parse [try %action] as:
+ try %action and if it succeeds: pass
+ ..or if it fails: pass
+ parse [try %action and if it fails %fallback] as:
+ try %action and if it succeeds: pass
+ ..or if it fails %fallback
+ parse [try %action and if it succeeds %success] as:
+ try %action and if it succeeds %success or if it fails: pass
# Do/finally:
-compile [do %action then always %final_action] to code: ".."
- do
- local fell_through = false;
- local ok, ret1, ret2 = pcall(function(nomsu, vars)
- \(%action as lua statements)
- fell_through = true;
- end, nomsu, vars);
- local ok2, _ = pcall(function(nomsu, vars)
- \(%final_action as lua statements)
- end, nomsu, vars);
- if not ok then nomsu:error(ret1); end
- if not ok2 then nomsu:error(ret2); end
- if not fell_through then
- return ret1, ret2;
+immediately:
+ compile [do %action then always %final_action] to code: ".."
+ do
+ local fell_through = false;
+ local ok, ret1, ret2 = pcall(function(nomsu, vars)
+ \(%action as lua statements)
+ fell_through = true;
+ end, nomsu, vars);
+ local ok2, _ = pcall(function(nomsu, vars)
+ \(%final_action as lua statements)
+ end, nomsu, vars);
+ if not ok then nomsu:error(ret1); end
+ if not ok2 then nomsu:error(ret2); end
+ if not fell_through then
+ return ret1, ret2;
+ end
end
- end
diff --git a/lib/metaprogramming.nom b/lib/metaprogramming.nom
index f59ce04..1477175 100644
--- a/lib/metaprogramming.nom
+++ b/lib/metaprogramming.nom
@@ -2,33 +2,33 @@
This File contains rules for making rules and macros and some helper functions to make
that easier.
-# Rule to make rules:
+# Rule to make macros:
immediately:
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:defmacro("compile %macro_def to %body", function(nomsu, vars)
+ 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 rule definition body. Expected Block, but got: "..tostring(\%body.type));
+ "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
local signature = {};
- for i, alias in ipairs(\%signature.value) do
+ for i, alias in ipairs(\%macro_def.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));
+ body_lua = body_lua.statements or ("return "..body_lua.expr..";");
+ local lua = ([[
+ do
+ local function macro(nomsu, vars)
+ %s
+ end
+ local function macro_wrapper(...) return {expr=macro(...)}; end
+ nomsu:defmacro(%s, macro_wrapper, %s);
+ end]]):format(body_lua, nomsu:repr(signature), nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
+ return {statements=lua};
+ end, \(__src__ 1));
-# Rules to make lua macros:
-immediately:
- rule [compile \%macro_def to \%body] =:
- lua> ".."
+ lua> ".."
+ nomsu:defmacro("compile %macro_def to code %body", function(nomsu, vars)
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",
@@ -38,32 +38,40 @@ immediately:
signature[i] = alias.src;
end
local body_lua = nomsu:tree_to_lua(\%body);
- local fn_src = ([[
- function(nomsu, vars)
+ body_lua = body_lua.statements or ("return "..body_lua.expr..";");
+ local lua = ([[
+ do
+ local function macro(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));
+ end
+ local function macro_wrapper(...) return {statements=macro(...)}; end
+ nomsu:defmacro(%s, macro_wrapper, %s);
+ end]]):format(body_lua, nomsu:repr(signature), nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
+ return {statements=lua};
+ end, \(__src__ 1));
- rule [compile \%macro_def to code \%body] =:
+compile [rand] to: "math.random()"
+
+# Rule to make rules:
+immediately:
+ compile [rule %signature = %body] to code:
lua> ".."
- nomsu:assert(\%macro_def.type == "List",
- "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
+ 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 compile definition body. Expected Block, but got: "..tostring(\%body.type));
+ "Invalid type for rule definition body. Expected Block, but got: "..tostring(\%body.type));
local signature = {};
- for i, alias in ipairs(\%macro_def.value) do
+ for i, alias in ipairs(\%signature.value) do
signature[i] = alias.src;
end
local body_lua = nomsu:tree_to_lua(\%body);
- local fn_src = ([[
- function(nomsu, vars)
+ body_lua = body_lua.statements or ("return "..body_lua.expr..";");
+ local src = nomsu:dedent(nomsu:source_code(0));
+ local def_lua = ([[
+ nomsu:def(%s, 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));
+ end, %s);]]):format(nomsu:repr(signature), body_lua, nomsu:repr(src));
+ return def_lua;
# Rule to make nomsu macros:
immediately: