aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/collections.nom294
-rw-r--r--core/control_flow.nom668
-rw-r--r--core/errors.nom82
-rw-r--r--core/io.nom8
-rw-r--r--core/metaprogramming.nom328
-rw-r--r--core/operators.nom303
-rw-r--r--core/text.nom8
7 files changed, 864 insertions, 827 deletions
diff --git a/core/collections.nom b/core/collections.nom
index 8a59852..69a51c7 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -9,162 +9,158 @@ use "core/operators.nom"
# List/dict functions:
# Indexing
-immediately
- compile [..]
- %index st to last in %list, %index nd to last in %list, %index rd to last in %list
- %index th to last in %list
- ..to: Lua value "utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))"
+compile [..]
+ %index st to last in %list, %index nd to last in %list, %index rd to last in %list
+ %index th to last in %list
+..to: Lua value "utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))"
-immediately
- parse [last in %list] as: 1st to last in %list
- parse [first in %list] as: %list.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+parse [last in %list] as: 1st to last in %list
+parse [first in %list] as: %list.1
# Membership testing
-immediately
- action [%item is in %list, %list contains %item, %list has %item]
- for %key = %value in %list
- if (%key is %item): return (yes)
- return (no)
-
- action [..]
- %item isn't in %list, %item is not in %list
- %list doesn't contain %item, %list does not contain %item
- %list doesn't have %item, %list does not have %item
- ..
- for %key = %value in %list
- if (%key is %item): return (no)
- return (yes)
-
-immediately
- parse [%list has key %index, %list has index %index] as
- %list.%index != (nil)
-
- parse [..]
- %list doesn't have key %index, %list does not have key %index
- %list doesn't have index %index, %list does not have index %index
- ..as
- %list.%index = (nil)
-
- compile [number of keys in %list] to
- Lua value "utils.size(\(%list as lua expr))"
-
- compile [append %item to %list, add %item to %list, to %list add %item, to %list append %item] to
- Lua "table.insert(\(%list as lua expr), \(%item as lua expr))"
-
- compile [pop from %list, remove last from %list] to
- Lua "table.remove(\(%list as lua expr))"
-
- compile [remove index %index from %list] to
- Lua "table.remove(\(%list as lua expr), \(%index as lua expr))"
+action [%item is in %list, %list contains %item, %list has %item]
+ for %key = %value in %list
+ if (%key is %item): return (yes)
+ return (no)
+
+action [..]
+ %item isn't in %list, %item is not in %list
+ %list doesn't contain %item, %list does not contain %item
+ %list doesn't have %item, %list does not have %item
+..
+ for %key = %value in %list
+ if (%key is %item): return (no)
+ return (yes)
+
+parse [%list has key %index, %list has index %index] as
+ %list.%index != (nil)
+
+parse [..]
+ %list doesn't have key %index, %list does not have key %index
+ %list doesn't have index %index, %list does not have index %index
+..as
+ %list.%index = (nil)
+
+compile [number of keys in %list] to
+ Lua value "utils.size(\(%list as lua expr))"
+
+compile [append %item to %list, add %item to %list, to %list add %item, to %list append %item] to
+ Lua "table.insert(\(%list as lua expr), \(%item as lua expr))"
+
+compile [pop from %list, remove last from %list] to
+ Lua "table.remove(\(%list as lua expr))"
+
+compile [remove index %index from %list] to
+ Lua "table.remove(\(%list as lua expr), \(%index as lua expr))"
# List Comprehension
-immediately
- parse [%expression for %item in %iterable] as
- result of
- %comprehension <- []
- for %item in %iterable
- add %expression to %comprehension
- return %comprehension
-
- parse [..]
- %expression for %index in %start to %stop via %step
- %expression for %index in %start to %stop by %step
- ..as
- result of
- %comprehension <- []
- for %index in %start to %stop via %step
- add %expression to %comprehension
- return %comprehension
-
- parse [%expression for %var in %start to %stop] as
- %expression for %var in %start to %stop via 1
-
- parse [..]
- %expression for %key = %value in %iterable
- %expression for (%key,%value) in %iterable
- ..as
- result of
- %comprehension <- []
- for %key = %value in %iterable
- add %expression to %comprehension
- return %comprehension
-
- # Dict comprehensions
- parse [..]
- %key = %value for %item in %iterable
- (%key,%value) for %item in %iterable
- ..as
- result of
- %comprehension <- {}
- for %item in %iterable
- %comprehension.%key <- %value
- return %comprehension
-
- parse [..]
- %key = %value for %src_key = %src_value in %iterable
- (%key,%value) for (%src_key,%src_value) in %iterable
- ..as
- result of
- %comprehension <- {}
- for %src_key = %src_value in %iterable
- %comprehension.%key <- %value
- return %comprehension
-
-immediately
- action [%lists flattened]
- %flat <- []
- for %list in %lists
- for %item in %list
- add %item to %flat
- return %flat
-
- parse [entries in %dict] as: {key:%k, value:%v} for %k = %v in %dict
- parse [keys in %dict, keys of %dict] as: %k for %k = %v in %dict
- parse [values in %dict, values of %dict] as: %v for %k = %v in %dict
+parse [%expression for %item in %iterable] as
+ result of
+ %comprehension <- []
+ for %item in %iterable
+ add %expression to %comprehension
+ return %comprehension
+
+parse [..]
+ %expression for %index in %start to %stop via %step
+ %expression for %index in %start to %stop by %step
+..as
+ result of
+ %comprehension <- []
+ for %index in %start to %stop via %step
+ add %expression to %comprehension
+ return %comprehension
+
+parse [%expression for %var in %start to %stop] as
+ %expression for %var in %start to %stop via 1
+
+parse [..]
+ %expression for %key = %value in %iterable
+ %expression for (%key,%value) in %iterable
+..as
+ result of
+ %comprehension <- []
+ for %key = %value in %iterable
+ add %expression to %comprehension
+ return %comprehension
+
+# Dict comprehensions
+parse [..]
+ %key = %value for %item in %iterable
+ (%key,%value) for %item in %iterable
+..as
+ result of
+ %comprehension <- {}
+ for %item in %iterable
+ %comprehension.%key <- %value
+ return %comprehension
+
+parse [..]
+ %key = %value for %src_key = %src_value in %iterable
+ (%key,%value) for (%src_key,%src_value) in %iterable
+..as
+ result of
+ %comprehension <- {}
+ for %src_key = %src_value in %iterable
+ %comprehension.%key <- %value
+ return %comprehension
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+action [%lists flattened]
+ %flat <- []
+ for %list in %lists
+ for %item in %list
+ add %item to %flat
+ return %flat
+
+parse [entries in %dict] as: {key:%k, value:%v} for %k = %v in %dict
+parse [keys in %dict, keys of %dict] as: %k for %k = %v in %dict
+parse [values in %dict, values of %dict] as: %v for %k = %v in %dict
# Metatable stuff
-immediately
- compile [set %dict's metatable to %metatable] to
- Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
-
- compile [%dict with fallback %key -> %value] to
- Lua value ".."
- setmetatable(\(%dict as lua expr), {__index=function(self, \(%key as lua expr))
- local value = \(%value as lua expr)
- self[\(%key as lua expr)] = value
- return value
- end})
+compile [set %dict's metatable to %metatable] to
+ Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
+
+compile [%dict with fallback %key -> %value] to
+ Lua value ".."
+ setmetatable(\(%dict as lua expr), {__index=function(self, \(%key as lua expr))
+ local value = \(%value as lua expr)
+ self[\(%key as lua expr)] = value
+ return value
+ end})
# Sorting
-immediately
- compile [sort %items] to: Lua "table.sort(\(%items as lua expr));"
- parse [..]
- sort %items by %item = %key_expr
- sort %items by %item -> %key_expr
- ..as
- do
- %keys <- ({} with fallback %item -> %key_expr)
- lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)"
-
-immediately
- action [%items sorted, sorted %items]
- %copy <- (% for % in %items)
- sort %copy
- return %copy
- action [..]
- %items sorted by %item = %key
- %items sorted by %item -> %key
- ..
- %copy <- (% for % in %items)
- sort %copy by %item = %key
- return %copy
-
- action [unique %items]
- %unique <- []
- %seen <- {}
- for % in %items
- unless: %seen.%
- add % to %unique
- %seen.% <- (yes)
- return %unique
+compile [sort %items] to: Lua "table.sort(\(%items as lua expr));"
+parse [..]
+ sort %items by %item = %key_expr
+ sort %items by %item -> %key_expr
+..as
+ do
+ %keys <- ({} with fallback %item -> %key_expr)
+ lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+action [%items sorted, sorted %items]
+ %copy <- (% for % in %items)
+ sort %copy
+ return %copy
+action [..]
+ %items sorted by %item = %key
+ %items sorted by %item -> %key
+..
+ %copy <- (% for % in %items)
+ sort %copy by %item = %key
+ return %copy
+
+action [unique %items]
+ %unique <- []
+ %seen <- {}
+ for % in %items
+ unless: %seen.%
+ add % to %unique
+ %seen.% <- (yes)
+ return %unique
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 15c1ca1..fccdfca 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -8,387 +8,381 @@ use "core/operators.nom"
use "core/errors.nom"
# No-Op
-immediately
- compile [do nothing] to: Lua ""
+compile [do nothing] to: Lua ""
# Conditionals
-immediately
- compile [if %condition %if_body] to
- Lua ".."
- if \(%condition as lua expr) then
- \(%if_body as lua statements)
- end
- parse [unless %condition %unless_body] as: if (not %condition) %unless_body
-
- compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to
- Lua ".."
- if \(%condition as lua expr) then
- \(%if_body as lua statements)
- else
- \(%else_body as lua statements)
- end
+compile [if %condition %if_body] to
+ Lua ".."
+ if \(%condition as lua expr) then
+ \(%if_body as lua statements)
+ end
+parse [unless %condition %unless_body] as: if (not %condition) %unless_body
+
+compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to
+ Lua ".."
+ if \(%condition as lua expr) then
+ \(%if_body as lua statements)
+ else
+ \(%else_body as lua statements)
+ end
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Conditional expression (ternary operator)
# Note: this uses a function instead of "(condition and if_expr or else_expr)"
because that breaks if %if_expr is falsey, e.g. "x < 5 and false or 99"
-immediately
- compile [..]
- %when_true_expr if %condition else %when_false_expr
- %when_true_expr if %condition otherwise %when_false_expr
- %when_false_expr unless %condition else %when_true_expr
- %when_false_expr unless %condition then %when_true_expr
- ..to
- # If %when_true_expr is guaranteed to be truthy, we can use Lua's idiomatic
- equivalent of a conditional expression: (cond and if_true or if_false)
- if: {Text:yes, List:yes, Dict:yes, Number:yes}.(%when_true_expr.type)
- return
- Lua value ".."
- (\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(%when_false_expr as lua expr))
- ..else
- # Otherwise, need to do an anonymous inline function (yuck, too bad lua
- doesn't have a proper ternary operator!)
- To see why this is necessary consider: (random()<.5 and false or 99)
- return
- Lua value ".."
- ((function()
- if \(%condition as lua expr) then
- return \(%when_true_expr as lua expr)
- else
- return \(%when_false_expr as lua expr)
- end
- end)())
+compile [..]
+ %when_true_expr if %condition else %when_false_expr
+ %when_true_expr if %condition otherwise %when_false_expr
+ %when_false_expr unless %condition else %when_true_expr
+ %when_false_expr unless %condition then %when_true_expr
+..to
+ # If %when_true_expr is guaranteed to be truthy, we can use Lua's idiomatic
+ equivalent of a conditional expression: (cond and if_true or if_false)
+ if: {Text:yes, List:yes, Dict:yes, Number:yes}.(%when_true_expr.type)
+ return
+ Lua value ".."
+ (\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(%when_false_expr as lua expr))
+ ..else
+ # Otherwise, need to do an anonymous inline function (yuck, too bad lua
+ doesn't have a proper ternary operator!)
+ To see why this is necessary consider: (random()<.5 and false or 99)
+ return
+ Lua value ".."
+ ((function()
+ if \(%condition as lua expr) then
+ return \(%when_true_expr as lua expr)
+ else
+ return \(%when_false_expr as lua expr)
+ end
+ end)())
# GOTOs
-immediately
- compile [=== %label ===, --- %label ---, *** %label ***] to
- Lua "::label_\(%label as lua identifier)::"
- compile [go to %label] to
- Lua "goto label_\(%label as lua identifier)"
+compile [=== %label ===, --- %label ---, *** %label ***] to
+ Lua "::label_\(%label as lua identifier)::"
+compile [go to %label] to
+ Lua "goto label_\(%label as lua identifier)"
# Basic loop control
-immediately
- compile [do next] to: Lua "continue"
- compile [stop] to: Lua "break"
+compile [do next] to: Lua "continue"
+compile [stop] to: Lua "break"
# Helper function
-immediately
- compile [%tree has subtree %subtree where %condition] to
- Lua value ".."
- (function()
- for \(%subtree as lua expr) in coroutine.wrap(function() \(%tree as lua expr):map(coroutine.yield) end) do
- if \(%condition as lua expr) then
- return true
- end
+#TODO: do "using % compile %" instead so it's actually a helper function
+compile [%tree has subtree %subtree where %condition] to
+ Lua value ".."
+ (function()
+ for \(%subtree as lua expr) in coroutine.wrap(function() \(%tree as lua expr):map(coroutine.yield) end) do
+ if \(%condition as lua expr) then
+ return true
end
- return false
- end)()
+ end
+ return false
+ end)()
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# While loops
-immediately
- compile [do next repeat] to: Lua "goto continue_repeat"
- compile [stop repeating] to: Lua "goto stop_repeat"
- compile [repeat while %condition %body] to
+compile [do next repeat] to: Lua "goto continue_repeat"
+compile [stop repeating] to: Lua "goto stop_repeat"
+compile [repeat while %condition %body] to
+ %lua <-
+ Lua ".."
+ while \(%condition as lua expr) do
+ \(%body as lua statements)
+ if
+ %body has subtree % where: (%.type = "Action") and (%.stub is "do next repeat")
+ ..: to %lua write "\n ::continue_repeat::"
+ to %lua write "\nend --while-loop"
+ if
+ %body has subtree % where: (%.type = "Action") and (%.stub is "stop repeating")
+ ..
%lua <-
Lua ".."
- while \(%condition as lua expr) do
- \(%body as lua statements)
- if
- %body has subtree % where: (%.type = "Action") and (%.stub is "do next repeat")
- ..: to %lua write "\n ::continue_repeat::"
- to %lua write "\nend --while-loop"
- if
- %body has subtree % where: (%.type = "Action") and (%.stub is "stop repeating")
- ..
- %lua <-
- Lua ".."
- do -- scope of "stop repeating" label
- \%lua
- ::stop_repeat::
- end -- end of "stop repeating" label scope
- return %lua
- parse [repeat %body] as: repeat while (yes) %body
- parse [repeat until %condition %body] as: repeat while (not %condition) %body
-
- compile [..]
- repeat %n times %body
- ..to
+ do -- scope of "stop repeating" label
+ \%lua
+ ::stop_repeat::
+ end -- end of "stop repeating" label scope
+ return %lua
+parse [repeat %body] as: repeat while (yes) %body
+parse [repeat until %condition %body] as: repeat while (not %condition) %body
+
+compile [..]
+ repeat %n times %body
+..to
+ %lua <-
+ Lua ".."
+ for i=1,\(%n as lua expr) do
+ \(%body as lua statements)
+ if
+ %body has subtree % where: (%.type = "Action") and (%.stub is "do next repeat")
+ ..: to %lua write "\n ::continue_repeat::"
+ to %lua write "\nend --numeric for-loop"
+ if
+ %body has subtree % where: (%.type = "Action") and (%.stub is "stop repeating")
+ ..
%lua <-
Lua ".."
- for i=1,\(%n as lua expr) do
- \(%body as lua statements)
- if
- %body has subtree % where: (%.type = "Action") and (%.stub is "do next repeat")
- ..: to %lua write "\n ::continue_repeat::"
- to %lua write "\nend --numeric for-loop"
- if
- %body has subtree % where: (%.type = "Action") and (%.stub is "stop repeating")
- ..
- %lua <-
- Lua ".."
- do -- scope of "stop repeating" label
- \%lua
- ::stop_repeat::
- end -- end of "stop repeating" label scope
- return %lua
+ do -- scope of "stop repeating" label
+ \%lua
+ ::stop_repeat::
+ end -- end of "stop repeating" label scope
+ return %lua
# For loop control flow
-immediately
- compile [stop %var] to
- Lua "goto stop_\(%var as lua identifier)"
- compile [do next %var] to
- Lua "goto continue_\(%var as lua identifier)"
+compile [stop %var] to
+ Lua "goto stop_\(%var as lua identifier)"
+compile [do next %var] to
+ Lua "goto continue_\(%var as lua identifier)"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Numeric range for loops
-immediately
- compile [..]
- for %var in %start to %stop by %step %body
- for %var in %start to %stop via %step %body
- ..to
- # This uses Lua's approach of only allowing loop-scoped variables in a loop
- assume (%var.type is "Var") or barf "Loop expected variable, not: \%var"
+compile [..]
+ for %var in %start to %stop by %step %body
+ for %var in %start to %stop via %step %body
+..to
+ # This uses Lua's approach of only allowing loop-scoped variables in a loop
+ assume (%var.type is "Var") or barf "Loop expected variable, not: \%var"
+ %lua <-
+ Lua ".."
+ for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do
+ \(%body as lua statements)
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "do next %") and
+ %.3 = %var
+ ..: to %lua write "\n ::continue_\(%var as lua identifier)::"
+ to %lua write "\nend --numeric for-loop"
+
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "stop %") and
+ %.2 = %var
+ ..
%lua <-
Lua ".."
- for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do
- \(%body as lua statements)
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "do next %") and
- %.3 = %var
- ..: to %lua write "\n ::continue_\(%var as lua identifier)::"
- to %lua write "\nend --numeric for-loop"
-
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "stop %") and
- %.2 = %var
- ..
- %lua <-
- Lua ".."
- do -- scope for stopping for-loop
- \%lua
- ::stop_\(%var as lua identifier)::
- end -- end of scope for stopping for-loop
+ do -- scope for stopping for-loop
+ \%lua
+ ::stop_\(%var as lua identifier)::
+ end -- end of scope for stopping for-loop
+
+ return %lua
- return %lua
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-immediately
- parse [for %var in %start to %stop %body] as: for %var in %start to %stop via 1 %body
+parse [for %var in %start to %stop %body] as: for %var in %start to %stop via 1 %body
# For-each loop (lua's "ipairs()")
-immediately
- compile [for %var in %iterable %body] to
- # This uses Lua's approach of only allowing loop-scoped variables in a loop
- assume (%var.type is "Var") or barf "Loop expected variable, not: \%var"
+compile [for %var in %iterable %body] to
+ # This uses Lua's approach of only allowing loop-scoped variables in a loop
+ assume (%var.type is "Var") or barf "Loop expected variable, not: \%var"
+ %lua <-
+ Lua ".."
+ for i,\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do
+ \(%body as lua statements)
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "do next %") and
+ %.3.(1) = %var.(1)
+ ..: to %lua write (Lua "\n ::continue_\(%var as lua identifier)::")
+ to %lua write "\nend --foreach-loop"
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "stop %") and
+ %.2.(1) = %var.(1)
+ ..
%lua <-
Lua ".."
- for i,\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do
- \(%body as lua statements)
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "do next %") and
- %.3.(1) = %var.(1)
- ..: to %lua write (Lua "\n ::continue_\(%var as lua identifier)::")
- to %lua write "\nend --foreach-loop"
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "stop %") and
- %.2.(1) = %var.(1)
- ..
- %lua <-
- Lua ".."
- do -- scope for stopping for-loop
- \%lua
- ::stop_\(%var as lua identifier)::
- end -- end of scope for stopping for-loop
- return %lua
+ do -- scope for stopping for-loop
+ \%lua
+ ::stop_\(%var as lua identifier)::
+ end -- end of scope for stopping for-loop
+ return %lua
# Dict iteration (lua's "pairs()")
-immediately
- compile [..]
- for %key = %value in %iterable %body
- for (%key,%value) in %iterable %body
- ..to
- # This uses Lua's approach of only allowing loop-scoped variables in a loop
- assume (%key.type is "Var") or barf "Loop expected variable, not: \%key"
- assume (%value.type is "Var") or barf "Loop expected variable, not: \%value"
+compile [..]
+ for %key = %value in %iterable %body
+ for (%key,%value) in %iterable %body
+..to
+ # This uses Lua's approach of only allowing loop-scoped variables in a loop
+ assume (%key.type is "Var") or barf "Loop expected variable, not: \%key"
+ assume (%value.type is "Var") or barf "Loop expected variable, not: \%value"
+ %lua <-
+ Lua ".."
+ for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do
+ \(%body as lua statements)
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "do next %") and
+ %.3.(1) = %key.(1)
+ ..: to %lua write (Lua "\n ::continue_\(%key as lua identifier)::")
+
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "do next %") and
+ %.3.(1) = %value.(1)
+ ..: to %lua write (Lua "\n ::continue_\(%value as lua identifier)::")
+ to %lua write "\nend --foreach-loop"
+
+ %stop_labels <- (Lua "")
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "stop %") and
+ %.2.(1) = %key.(1)
+ ..: to %stop_labels write "\n::stop_\(%key as lua identifier)::"
+
+ if
+ %body has subtree % where
+ (%.type = "Action") and
+ (%.stub is "stop %") and
+ %.2.(1) = %value.(1)
+ ..: to %stop_labels write "\n::stop_\(%value as lua identifier)::"
+
+ if: (length of %stop_labels) > 0
%lua <-
Lua ".."
- for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do
- \(%body as lua statements)
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "do next %") and
- %.3.(1) = %key.(1)
- ..: to %lua write (Lua "\n ::continue_\(%key as lua identifier)::")
-
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "do next %") and
- %.3.(1) = %value.(1)
- ..: to %lua write (Lua "\n ::continue_\(%value as lua identifier)::")
- to %lua write "\nend --foreach-loop"
-
- %stop_labels <- (Lua "")
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "stop %") and
- %.2.(1) = %key.(1)
- ..: to %stop_labels write "\n::stop_\(%key as lua identifier)::"
-
- if
- %body has subtree % where
- (%.type = "Action") and
- (%.stub is "stop %") and
- %.2.(1) = %value.(1)
- ..: to %stop_labels write "\n::stop_\(%value as lua identifier)::"
-
- if: (length of %stop_labels) > 0
- %lua <-
- Lua ".."
- do -- scope for stopping for % = % loop
- \%lua
- \%stop_labels
- end
- return %lua
+ do -- scope for stopping for % = % loop
+ \%lua
+ \%stop_labels
+ end
+ return %lua
-# Switch statement/multi-branch if
-immediately
- compile [when %body] to
- %code <- (Lua "")
- %fallthroughs <- []
- %is_first <- (yes)
- %seen_else <- (no)
- %branches <-
- %body if (%body.type = "Block") else [%body]
- for %func_call in %branches
- assume (%func_call.type is "Action") or barf ".."
- Invalid format for 'when' statement. Only '*' blocks are allowed.
- with {..}
- %star: %func_call.1
- %condition: %func_call.2
- %action: %func_call.3
- ..
- assume (%star = "*") or barf ".."
- Invalid format for 'when' statement. Lines must begin with '*'
- assume %condition or barf ".."
- Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
- if: %action is (nil)
- lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
- do next %func_call
-
- if: %condition = "else"
- assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
- to %code write "\nelse\n "
- to %code write: %action as lua statements
- %seen_else <- (yes)
- ..else
- assume (not %seen_else) or barf "'else' clause needs to be last in 'when' block"
- lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
- to %code write "\("if" if %is_first else "\nelseif") "
- for %i = %condition in %fallthroughs
- if (%i > 1): to %code write " or "
- to %code write %condition
- to %code write " then\n "
- to %code write (%action as lua statements)
-
- %fallthroughs <- []
- %is_first <- (no)
-
- assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
- assume ((length of %code) > 0) or barf "Empty body for 'when' block"
- to %code write "\nend --when"
- return %code
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Switch statement
-immediately
- compile [when %branch_value = ? %body, when %branch_value is ? %body] to
- %code <- (Lua "")
- %fallthroughs <- []
- %is_first <- (yes)
- %seen_else <- (no)
- %branches <-
- %body if (%body.type = "Block") else [%body]
- for %func_call in %branches
- assume (%func_call.type is "Action") or barf ".."
- Invalid format for 'when' statement. Only '*' blocks are allowed.
- with {%star:%func_call.1, %condition:%func_call.2, %action:%func_call.3}
- assume (%star = "*") or barf ".."
- Invalid format for 'when' statement. Lines must begin with '*'
- assume %condition or barf ".."
- Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
- if: %action is (nil)
- lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
- do next %func_call
-
- if: %condition = "else"
- assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
- to %code write "\nelse\n "
- to %code write: %action as lua statements
- ..else
- assume (not %seen_else) or barf "'else' clause needs to be last in 'when % = ?' block"
- to %code write "\("if" if %is_first else "\nelseif") "
- lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
- for %i = % in %fallthroughs
- if: %i > 1
- to %code write " or "
- if: (%.type is "Text") or (%.type is "Number")
- to %code write "branch_value == \%"
- ..else
- to %code write "utils.equivalent(branch_value, \%)"
- to %code write "then\n "
- to %code write (%action as lua statements)
+# Switch statement/multi-branch if
+compile [when %body] to
+ %code <- (Lua "")
+ %fallthroughs <- []
+ %is_first <- (yes)
+ %seen_else <- (no)
+ %branches <-
+ %body if (%body.type = "Block") else [%body]
+ for %func_call in %branches
+ assume (%func_call.type is "Action") or barf ".."
+ Invalid format for 'when' statement. Only '*' blocks are allowed.
+ with {..}
+ %star: %func_call.1
+ %condition: %func_call.2
+ %action: %func_call.3
+ ..
+ assume (%star = "*") or barf ".."
+ Invalid format for 'when' statement. Lines must begin with '*'
+ assume %condition or barf ".."
+ Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
+ if: %action is (nil)
+ lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
+ do next %func_call
+
+ if: %condition = "else"
+ assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
+ to %code write "\nelse\n "
+ to %code write: %action as lua statements
+ %seen_else <- (yes)
+ ..else
+ assume (not %seen_else) or barf "'else' clause needs to be last in 'when' block"
+ lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
+ to %code write "\("if" if %is_first else "\nelseif") "
+ for %i = %condition in %fallthroughs
+ if (%i > 1): to %code write " or "
+ to %code write %condition
+ to %code write " then\n "
+ to %code write (%action as lua statements)
%fallthroughs <- []
%is_first <- (no)
-
- assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
- assume ((length of %code) > 0) or barf "No body for 'when % = ?' block!"
- to %code write "\nend"
- %code <-
- Lua ".."
- do --when % = ?
- local branch_value = \(%branch_value as lua expr)
- \%code
- end --when % = ?
- return %code
+ assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
+ assume ((length of %code) > 0) or barf "Empty body for 'when' block"
+ to %code write "\nend --when"
+ return %code
-# Do/finally
-immediately
- compile [do %action] to
- Lua ".."
- do
- \(%action as lua statements)
- end --do
+# Switch statement
+compile [when %branch_value = ? %body, when %branch_value is ? %body] to
+ %code <- (Lua "")
+ %fallthroughs <- []
+ %is_first <- (yes)
+ %seen_else <- (no)
+ %branches <-
+ %body if (%body.type = "Block") else [%body]
+ for %func_call in %branches
+ assume (%func_call.type is "Action") or barf ".."
+ Invalid format for 'when' statement. Only '*' blocks are allowed.
+ with {%star:%func_call.1, %condition:%func_call.2, %action:%func_call.3}
+ assume (%star = "*") or barf ".."
+ Invalid format for 'when' statement. Lines must begin with '*'
+ assume %condition or barf ".."
+ Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
+ if: %action is (nil)
+ lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
+ do next %func_call
+
+ if: %condition = "else"
+ assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
+ to %code write "\nelse\n "
+ to %code write: %action as lua statements
+ ..else
+ assume (not %seen_else) or barf "'else' clause needs to be last in 'when % = ?' block"
+ to %code write "\("if" if %is_first else "\nelseif") "
+ lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
+ for %i = % in %fallthroughs
+ if: %i > 1
+ to %code write " or "
+ if: (%.type is "Text") or (%.type is "Number")
+ to %code write "branch_value == \%"
+ ..else
+ to %code write "utils.equivalent(branch_value, \%)"
+ to %code write "then\n "
+ to %code write (%action as lua statements)
- compile [do %action then always %final_action] to
+ %fallthroughs <- []
+ %is_first <- (no)
+
+ assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
+ assume ((length of %code) > 0) or barf "No body for 'when % = ?' block!"
+ to %code write "\nend"
+ %code <-
Lua ".."
- do
- local fell_through = false
- local ok, ret = pcall(function()
- \(%action as lua statements)
- fell_through = true
- end)
- \(%final_action as lua statements)
- if not ok then error(ret, 0) end
- if not fell_through then return ret end
- end
+ do --when % = ?
+ local branch_value = \(%branch_value as lua expr)
+ \%code
+ end --when % = ?
+ return %code
+
+# Do/finally
+compile [do %action] to
+ Lua ".."
+ do
+ \(%action as lua statements)
+ end --do
+
+compile [do %action then always %final_action] to
+ Lua ".."
+ do
+ local fell_through = false
+ local ok, ret = pcall(function()
+ \(%action as lua statements)
+ fell_through = true
+ end)
+ \(%final_action as lua statements)
+ if not ok then error(ret, 0) end
+ if not fell_through then return ret end
+ end
# Inline thunk:
-immediately
- compile [result of %body] to
- %body <- (%body as lua statements)
- declare locals in %body
- return
- Lua value ".."
- (function()
- \%body
- end)()
+compile [result of %body] to
+ %body <- (%body as lua statements)
+ declare locals in %body
+ return
+ Lua value ".."
+ (function()
+ \%body
+ end)()
diff --git a/core/errors.nom b/core/errors.nom
index 8c6261a..812052e 100644
--- a/core/errors.nom
+++ b/core/errors.nom
@@ -22,47 +22,47 @@ compile [assume %condition or barf %message] to
end
# Try/except
-immediately
- compile [..]
- try %action and if it succeeds %success or if it barfs %msg %fallback
- try %action and if it barfs %msg %fallback or if it succeeds %success
- ..to
- Lua ".."
- do
- local fell_through = false
- local err, erred = nil, false
- local ok, ret = xpcall(function()
- \(%action as lua statements)
- fell_through = true
- end, function(\(%msg as lua expr))
- local ok, ret = pcall(function()
- \(%fallback as lua statements)
- end)
- if not ok then err, erred = ret, true end
+compile [..]
+ try %action and if it succeeds %success or if it barfs %msg %fallback
+ try %action and if it barfs %msg %fallback or if it succeeds %success
+..to
+ Lua ".."
+ do
+ local fell_through = false
+ local err, erred = nil, false
+ local ok, ret = xpcall(function()
+ \(%action as lua statements)
+ fell_through = true
+ end, function(\(%msg as lua expr))
+ local ok, ret = pcall(function()
+ \(%fallback as lua statements)
end)
- if ok then
- \(%success as lua statements)
- if not fell_through then
- return ret
- end
- elseif erred then
- error(err, 0)
+ if not ok then err, erred = ret, true end
+ end)
+ if ok then
+ \(%success as lua statements)
+ if not fell_through then
+ return ret
end
+ elseif erred then
+ error(err, 0)
end
-immediately
- parse [..]
- try %action and if it succeeds %success or if it barfs %fallback
- try %action and if it barfs %fallback or if it succeeds %success
- ..as: try %action and if it succeeds %success or if it barfs (=lua "") %fallback
-immediately
- parse [try %action] as
- try %action and if it succeeds: do nothing
- ..or if it barfs: do nothing
- parse [try %action and if it barfs %fallback] as
- try %action and if it succeeds: do nothing
- ..or if it barfs %fallback
- parse [try %action and if it barfs %msg %fallback] as
- try %action and if it succeeds: do nothing
- ..or if it barfs %msg %fallback
- parse [try %action and if it succeeds %success] as
- try %action and if it succeeds %success or if it barfs: do nothing
+ end
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+parse [..]
+ try %action and if it succeeds %success or if it barfs %fallback
+ try %action and if it barfs %fallback or if it succeeds %success
+..as: try %action and if it succeeds %success or if it barfs (=lua "") %fallback
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+parse [try %action] as
+ try %action and if it succeeds: do nothing
+ ..or if it barfs: do nothing
+parse [try %action and if it barfs %fallback] as
+ try %action and if it succeeds: do nothing
+ ..or if it barfs %fallback
+parse [try %action and if it barfs %msg %fallback] as
+ try %action and if it succeeds: do nothing
+ ..or if it barfs %msg %fallback
+parse [try %action and if it succeeds %success] as
+ try %action and if it succeeds %success or if it barfs: do nothing
diff --git a/core/io.nom b/core/io.nom
index 4f12e57..751650d 100644
--- a/core/io.nom
+++ b/core/io.nom
@@ -6,15 +6,15 @@ use "core/metaprogramming.nom"
compile [say %message] to
lua> ".."
if \%message.type == "Text" then
- return Lua(tree.source, "io.write(", \(%message as lua expr), ", '\\\\n');");
+ return LuaCode(tree.source, "io.write(", \(%message as lua expr), ", '\\\\n');");
else
- return Lua(tree.source, "io.write(tostring(", \(%message as lua expr), "), '\\\\n');");
+ return LuaCode(tree.source, "io.write(tostring(", \(%message as lua expr), "), '\\\\n');");
end
compile [ask %prompt] to
lua> ".."
if \%prompt.type == "Text" then
- return Lua.Value(tree.source, "(io.write(", \(%prompt as lua expr), ") and io.read())");
+ return LuaCode.Value(tree.source, "(io.write(", \(%prompt as lua expr), ") and io.read())");
else
- return Lua.Value(tree.source, "(io.write(tostring(", \(%prompt as lua expr), ")) and io.read())");
+ return LuaCode.Value(tree.source, "(io.write(tostring(", \(%prompt as lua expr), ")) and io.read())");
end
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 82447b3..d04ced3 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -3,89 +3,122 @@
functions to make that easier.
# Compile-time action to make compile-time actions:
-immediately
- lua> ".."
- A_give_1_nickname_2 = compile_time(function(tree, \%action, \%nickname, is_compile_time)
- local function arg_to_string(a) return tostring(nomsu:tree_to_lua(a)) end
- local action_args = table.map(\%action:get_args(), arg_to_string)
- local nickname_args = table.map(\%nickname:get_args(), arg_to_string)
- if utils.equivalent(action_args, nickname_args) then
- return Lua(tree.source, "A", string.as_lua_id(\%nickname.stub), " = A", string.as_lua_id(\%action.stub))
- end
- local lua = Lua(tree.source, "A", string.as_lua_id(\%nickname.stub), " = ")
- if is_compile_time or COMPILE_TIME[_ENV["A"..string.as_lua_id(\%action.stub)]] then
- lua:append("compile_time")
- table.insert(action_args, 1, "tree")
- table.insert(nickname_args, 1, "tree")
+lua> ".."
+ nomsu.COMPILE_ACTIONS["give % nickname %"] = (function(nomsu, tree, \%action, \%nickname, is_compile_time)
+ local function arg_to_string(a) return tostring(nomsu:compile(a)) end
+ local action_args = table.map(\%action:get_args(), arg_to_string)
+ local nickname_args = table.map(\%nickname:get_args(), arg_to_string)
+ if utils.equivalent(action_args, nickname_args) then
+ if is_compile_time then
+ return LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%nickname.stub), "] = nomsu.COMPILE_ACTIONS[", repr(\%action.stub), "]")
+ else
+ return LuaCode(tree.source, "A", string.as_lua_id(\%nickname.stub), " = A", string.as_lua_id(\%action.stub))
end
- lua:append("(function(")
- lua:concat_append(nickname_args, ", ")
+ end
+ local lua = LuaCode(tree.source)
+ if is_compile_time then
+ lua:append("nomsu.COMPILE_ACTIONS[", repr(\%nickname.stub), "] = ")
+ table.insert(action_args, 1, "nomsu")
+ table.insert(nickname_args, 1, "nomsu")
+ table.insert(action_args, 2, "tree")
+ table.insert(nickname_args, 2, "tree")
+ else
+ lua:append("A", string.as_lua_id(\%nickname.stub), " = ")
+ end
+ lua:append("(function(")
+ lua:concat_append(nickname_args, ", ")
+ if is_compile_time then
+ lua:append(")\n return nomsu.COMPILE_ACTIONS[", repr(\%action.stub), "](")
+ else
lua:append(")\n return A", string.as_lua_id(\%action.stub), "(")
- lua:concat_append(action_args, ", ")
- lua:append(")\nend)")
- return lua
- end)
-
- __MANGLE_INDEX = 0
- A_parse_1_as_2 = compile_time(function(tree, \%actions, \%body)
- local replacements = {}
- for i,arg in ipairs(\%actions[1]:get_args()) do
- replacements[arg[1]] = tostring(nomsu:tree_to_lua(arg))
- end
- local function make_tree(t)
- if not AST.is_syntax_tree(t) then
- return repr(t)
- elseif t.type ~= 'Var' then
- local args = table.map(t, make_tree)
- table.insert(args, 1, repr(tostring(t.source)))
- return t.type.."("..table.concat(args, ", ")..")"
- elseif replacements[t[1]] then
- return replacements[t[1]]
- else
- return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].." \\0").."..('%X'):format(__MANGLE_INDEX))"
- end
- end
- local lua = Lua(tree.source, "A", string.as_lua_id(\%actions[1].stub), " = compile_time(function(tree")
- for _,arg in ipairs(\%actions[1]:get_args()) do
- lua:append(", ", nomsu:tree_to_lua(arg))
- end
- lua:append(")\n __MANGLE_INDEX = __MANGLE_INDEX + 1",
- "\n local tree = ", make_tree(\%body),
- "\n local lua = nomsu:tree_to_lua(tree)",
- "\n lua:remove_free_vars({")
- local vars = table.map(\%actions[1]:get_args(), function(a)
- return "Var("..repr(tostring(a.source))..", "..repr(a[1])..")"
- end)
- lua:concat_append(vars, ", ")
- lua:append("})\n return lua\nend)")
-
- for i=2,#\%actions do
- lua:append("\n", A_give_1_nickname_2(\%actions[i], \%actions[1], \%actions[i], true))
+ end
+ lua:concat_append(action_args, ", ")
+ lua:append(")\nend)")
+ if not is_compile_time then
+ lua:add_free_vars({"A"..string.as_lua_id(\%nickname.stub)})
+ end
+ return lua
+ end)
+
+ __MANGLE_INDEX = 0
+ nomsu.COMPILE_ACTIONS["parse % as %"] = (function(nomsu, tree, \%actions, \%body)
+ local replacements = {}
+ for i,arg in ipairs(\%actions[1]:get_args()) do
+ replacements[arg[1]] = tostring(nomsu:compile(arg))
+ end
+ local function make_tree(t)
+ if not AST.is_syntax_tree(t) then
+ return repr(t)
+ elseif t.type ~= 'Var' then
+ local args = table.map(t, make_tree)
+ table.insert(args, 1, repr(tostring(t.source)))
+ return t.type.."("..table.concat(args, ", ")..")"
+ elseif replacements[t[1]] then
+ return replacements[t[1]]
+ else
+ return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].." \\0").."..('%X'):format(__MANGLE_INDEX))"
end
- return lua
- end)
-
- A_action_1_2 = compile_time(function(tree, \%actions, \%body, is_compile_time)
- local lua = Lua(tree.source, "A", string.as_lua_id(\%actions[1].stub), " = ")
- if is_compile_time then lua:append("compile_time") end
- lua:append("(function(")
- local args = \%actions[1]:get_args()
- local lua_args = table.map(args, function(a) return nomsu:tree_to_lua(a) end)
- if is_compile_time then table.insert(lua_args, 1, "tree") end
- lua:concat_append(lua_args, ", ")
- local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ")
- body_lua:remove_free_vars(args)
- body_lua:declare_locals()
- lua:append(")\n ", body_lua, "\nend)")
- for i=2,#\%actions do
- lua:append("\n", A_give_1_nickname_2(\%actions[i], \%actions[1], \%actions[i], is_compile_time))
- end
- return lua
- end)
-
- A_compile_1_to_2 = compile_time(function(tree, \%actions, \%body)
- return A_action_1_2(tree, \%actions, \%body, true)
+ end
+ local lua = LuaCode(tree.source, "nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "] = (function(nomsu, tree")
+ lua:add_free_vars({"A"..string.as_lua_id(\%actions[1].stub)})
+ for _,arg in ipairs(\%actions[1]:get_args()) do
+ lua:append(", ", nomsu:compile(arg))
+ end
+ lua:append(")\n __MANGLE_INDEX = __MANGLE_INDEX + 1",
+ "\n local tree = ", make_tree(\%body),
+ "\n local lua = nomsu:compile(tree)",
+ "\n lua:remove_free_vars({")
+ local vars = table.map(\%actions[1]:get_args(), function(a)
+ return "Var("..repr(tostring(a.source))..", "..repr(a[1])..")"
end)
+ lua:concat_append(vars, ", ")
+ lua:append("})\n return lua\nend)")
+
+ for i=2,#\%actions do
+ lua:append("\n", nomsu.COMPILE_ACTIONS["give % nickname %"](nomsu, \%actions[i], \%actions[1], \%actions[i], true))
+ end
+ return lua
+ end)
+
+ nomsu.COMPILE_ACTIONS["local action % %"] = (function(nomsu, tree, \%actions, \%body, is_compile_time)
+ local lua = LuaCode(tree.source)
+ if is_compile_time then
+ lua:append("nomsu.COMPILE_ACTIONS[", repr(\%actions[1].stub), "] = ")
+ else
+ lua:append("A", string.as_lua_id(\%actions[1].stub), " = ")
+ lua:add_free_vars({"A"..string.as_lua_id(\%actions[1].stub)})
+ end
+ lua:append("(function(")
+ local args = \%actions[1]:get_args()
+ local lua_args = table.map(args, function(a) return nomsu:compile(a) end)
+ if is_compile_time then
+ table.insert(lua_args, 1, "nomsu")
+ table.insert(lua_args, 2, "tree")
+ end
+ lua:concat_append(lua_args, ", ")
+ local body_lua = nomsu:compile(\%body):as_statements("return ")
+ body_lua:remove_free_vars(args)
+ body_lua:declare_locals()
+ lua:append(")\n ", body_lua, "\nend)")
+ for i=2,#\%actions do
+ lua:append("\n", nomsu.COMPILE_ACTIONS["give % nickname %"](nomsu, \%actions[i], \%actions[1], \%actions[i], is_compile_time))
+ end
+ return lua
+ end)
+
+ -- Compile-time actions are always global, since they affect the state of the compiler
+ nomsu.COMPILE_ACTIONS["compile % to %"] = (function(nomsu, tree, \%actions, \%body)
+ local lua = nomsu.COMPILE_ACTIONS["local action % %"](nomsu, tree, \%actions, \%body, true)
+ return lua
+ end)
+
+ nomsu.COMPILE_ACTIONS["action % %"] = (function(nomsu, tree, \%actions, \%body)
+ local lua = nomsu.COMPILE_ACTIONS["local action % %"](nomsu, tree, \%actions, \%body)
+ lua:remove_free_vars(table.map(\%actions, function(a) return "A"..a.stub:as_lua_id() end))
+ return lua
+ end)
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compile [remove action %action] to
Lua ".."
@@ -93,90 +126,87 @@ compile [remove action %action] to
ARG_ORDERS[fn] = nil
COMPILE_TIME[fn] = nil
-immediately
- action [%tree as nomsu]
- =lua "nomsu:tree_to_nomsu(\%tree)"
+action [%tree as nomsu]
+ =lua "nomsu:tree_to_nomsu(\%tree)"
- action [%tree as inline nomsu]
- =lua "nomsu:tree_to_nomsu(\%tree, true)"
+action [%tree as inline nomsu]
+ =lua "nomsu:tree_to_nomsu(\%tree, true)"
- action [%tree as lua]
- =lua "nomsu:tree_to_lua(\%tree)"
+action [%tree as lua]
+ =lua "nomsu:compile(\%tree)"
- action [%tree as lua expr]
- lua> ".."
- local lua = nomsu:tree_to_lua(\%tree)
- if not lua.is_value then
- compile_error(\%tree, "Invalid thing to convert to lua expr:\n%s")
- end
- return lua
+action [%tree as lua expr]
+ lua> ".."
+ local lua = nomsu:compile(\%tree)
+ if not lua.is_value then
+ nomsu:compile_error(\%tree, "Invalid thing to convert to lua expr:\n%s")
+ end
+ return lua
- action [%tree as lua statements]
- =lua "nomsu:tree_to_lua(\%tree):as_statements()"
+action [%tree as lua statements]
+ =lua "nomsu:compile(\%tree):as_statements()"
- action [%tree as lua return]
- =lua "nomsu:tree_to_lua(\%tree):as_statements('return ')"
+action [%tree as lua return]
+ =lua "nomsu:compile(\%tree):as_statements('return ')"
- action [%var as lua identifier, %var as lua id]
- lua> ".."
- if type(\%var) == 'string' then return string.as_lua_id(\%var)
- elseif \%var.type == 'Var' then return string.as_lua_id(\%var[1])
- elseif \%var.type == 'Action' then return "A"..string.as_lua_id(\%var.stub)
- end
-
-immediately
- compile [%tree with %t -> %replacement] to
- Lua value ".."
- \(%tree as lua expr):map(function(\(%t as lua expr))
- \(%replacement as lua return)
- end)
-
- compile [declare locals in %code] to
- Lua value "\(%code as lua expr):declare_locals()"
-
- compile [declare locals %locals in %code] to
- Lua value "\(%code as lua expr):declare_locals(\(%locals as lua expr))"
+action [%var as lua identifier, %var as lua id]
+ lua> ".."
+ if type(\%var) == 'string' then return string.as_lua_id(\%var)
+ elseif \%var.type == 'Var' then return string.as_lua_id(\%var[1])
+ elseif \%var.type == 'Action' then return "A"..string.as_lua_id(\%var.stub)
+ end
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- compile [remove free vars %vars from %code] to
- Lua "\(%code as lua expr):remove_free_vars(\(%vars as lua expr));"
+compile [%tree with %t -> %replacement] to
+ Lua value ".."
+ \(%tree as lua expr):map(function(\(%t as lua expr))
+ \(%replacement as lua return)
+ end)
- parse [%lua <-write %code, to %lua write %code] as: lua> "\%lua:append(\%code);"
+compile [declare locals in %code] to
+ Lua value "\(%code as lua expr):declare_locals()"
-immediately
- compile [quote %s] to
- Lua value ".."
- ('"'..\(%s as lua expr):gsub("\\\\", "\\\\\\\\"):gsub("\n","\\\\n"):gsub('"', '\\\\"')..'"')
- compile [type of %obj] to: Lua value "type(\(%obj as lua expr))"
+compile [declare locals %locals in %code] to
+ Lua value "\(%code as lua expr):declare_locals(\(%locals as lua expr))"
-immediately
- compile [parse %text] to
- Lua value ".."
- nomsu:parse(Nomsu("\("\(%text.source)")", \(%text as lua expr)))
+compile [remove free vars %vars from %code] to
+ Lua "\(%code as lua expr):remove_free_vars(\(%vars as lua expr));"
- compile [run %nomsu_code] to
- Lua value "nomsu:run(Nomsu(\(quote "\(%nomsu_code.source)"), \(%nomsu_code as lua expr)))"
+parse [%lua <-write %code, to %lua write %code] as: lua> "\%lua:append(\%code);"
- action [run tree %tree, %tree as value]
- lua> ".."
- if \%tree.type == 'Text' and #\%tree == 1 and type(\%tree[1]) == 'string' then
- return \%tree[1]
- end
- local lua = Lua(\%tree.source, "return ",nomsu:tree_to_lua(\%tree))
- return nomsu:run_lua(lua)
+compile [quote %s] to
+ Lua value ".."
+ ('"'..\(%s as lua expr):gsub("\\\\", "\\\\\\\\"):gsub("\n","\\\\n"):gsub('"', '\\\\"')..'"')
+compile [type of %obj] to: Lua value "type(\(%obj as lua expr))"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+compile [parse %text] to
+ Lua value ".."
+ nomsu:parse(NomsuCode("\("\(%text.source)")", \(%text as lua expr)))
+
+compile [run %nomsu_code] to
+ Lua value "nomsu:run(NomsuCode(\(quote "\(%nomsu_code.source)"), \(%nomsu_code as lua expr)))"
+
+action [run tree %tree, %tree as value]
+ lua> ".."
+ if \%tree.type == 'Text' and #\%tree == 1 and type(\%tree[1]) == 'string' then
+ return \%tree[1]
+ end
+ local lua = LuaCode(\%tree.source, "return ",nomsu:compile(\%tree))
+ return nomsu:run_lua(lua)
- compile [compile %block, compiled %block, %block compiled] to
- Lua value "nomsu:tree_to_lua(\(%block as lua))"
+compile [compile %block, compiled %block, %block compiled] to
+ Lua value "nomsu:compile(\(%block as lua))"
-# Return
-immediately
- # 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.
- compile [return] to: Lua "do return; end"
- compile [return %return_value] to: Lua "do return \(%return_value as lua expr); end"
+# 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.
+compile [return] to: Lua "do return; end"
+compile [return %return_value] to: Lua "do return \(%return_value as lua expr); end"
# Literals
-immediately
- compile [yes] to: Lua value "true"
- compile [no] to: Lua value "false"
- compile [nothing, nil, null] to: Lua value "nil"
+compile [yes] to: Lua value "true"
+compile [no] to: Lua value "false"
+compile [nothing, nil, null] to: Lua value "nil"
diff --git a/core/operators.nom b/core/operators.nom
index f07ab3f..b4567b1 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -5,158 +5,175 @@ use "core/metaprogramming.nom"
use "core/errors.nom"
# Comparison Operators
-immediately
- compile [%x < %y] to: Lua value "(\(%x as lua expr) < \(%y as lua expr))"
- compile [%x > %y] to: Lua value "(\(%x as lua expr) > \(%y as lua expr))"
- compile [%x <= %y] to: Lua value "(\(%x as lua expr) <= \(%y as lua expr))"
- compile [%x >= %y] to: Lua value "(\(%x as lua expr) >= \(%y as lua expr))"
- compile [%a is %b, %a = %b, %a == %b] to
- Lua value "(\(%a as lua expr) == \(%b as lua expr))"
- compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to
- Lua value "(\(%a as lua expr) ~= \(%b as lua expr))"
- # For strict identity checking, use (%x's id) is (%y's id)
- compile [%'s id, id of %] to: Lua value "nomsu.ids[\(% as lua expr)]"
+compile [%x < %y] to: Lua value "(\(%x as lua expr) < \(%y as lua expr))"
+compile [%x > %y] to: Lua value "(\(%x as lua expr) > \(%y as lua expr))"
+compile [%x <= %y] to: Lua value "(\(%x as lua expr) <= \(%y as lua expr))"
+compile [%x >= %y] to: Lua value "(\(%x as lua expr) >= \(%y as lua expr))"
+compile [%a is %b, %a = %b, %a == %b] to
+ Lua value "(\(%a as lua expr) == \(%b as lua expr))"
+compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to
+ Lua value "(\(%a as lua expr) ~= \(%b as lua expr))"
+# For strict identity checking, use (%x's id) is (%y's id)
+lua> ".."
+ do
+ local new_uuid = require('uuid')
+ local NaN_surrogate = {}
+ local nil_surrogate = {}
+ IDS = setmetatable({}, {
+ __mode = "k",
+ __index = function(self, key)
+ if key == nil then return self[nil_surrogate]
+ elseif key ~= key then return self[NaN_surrogate] end
+ local id = new_uuid()
+ self[key] = id
+ return id
+ end
+ })
+ end
+compile [%'s id, id of %] to: Lua value "IDS[\(% as lua expr)]"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Variable assignment operator
-immediately
- compile [%var <- %value] to
- lua> "local \%var_lua = \(%var as lua)"
- assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
- lua> ".."
+compile [%var <- %value] to
+ lua> "local \%var_lua = \(%var as lua)"
+ assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
+ lua> ".."
+ \%value = \%value:map(function(t)
+ if Action:is_instance(t) and t.stub == "?" then
+ return \%var
+ end
+ end)
+ local \%value_lua = \(%value as lua)
+
+ assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
+ lua> ".."
+ local lua = LuaCode(tree.source, \%var_lua, ' = ', \%value_lua, ';')
+ if \%var.type == 'Var' then
+ lua:add_free_vars({\%var})
+ end
+ return lua
+
+# Simultaneous mutli-assignments like: x,y,z = 1,x,3;
+compile [<- %assignments, assign %assignments] to
+ assume (%assignments.type is "Dict") or barf ".."
+ Expected a Dict for the assignments part of '<- %' statement, not \%assignments
+ lua> ".."
+ local lhs, rhs = LuaCode(tree.source), LuaCode(tree.source)
+ for i, item in ipairs(\%assignments) do
+ local \%target, \%value = item[1], item[2]
\%value = \%value:map(function(t)
if Action:is_instance(t) and t.stub == "?" then
- return \%var
+ return \%target
end
end)
- local \%value_lua = \(%value as lua)
+ local target_lua = \(%target as lua)
+ if not target_lua.is_value then error("Invalid target for assignment: "..\(%target as text)) end
+ local value_lua = \(%value as lua)
+ if not value_lua.is_value then error("Invalid value for assignment: "..\(%value as text)) end
+ if \%target.type == "Var" then
+ lhs:add_free_vars({\%target})
+ end
+ if i > 1 then
+ lhs:append(", ")
+ rhs:append(", ")
+ end
+ lhs:append(target_lua)
+ rhs:append(value_lua)
+ end
+ return LuaCode(tree.source, lhs, " = ", rhs, ";")
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+compile [external %var <- %value] to
+ %var_lua <- (%var as lua)
+ assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
+ %value_lua <- (%value as lua)
+ assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
+ return: Lua "\%var_lua = \%value_lua;"
- assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
- lua> ".."
- local lua = Lua(tree.source, \%var_lua, ' = ', \%value_lua, ';')
- if \%var.type == 'Var' then
- lua:add_free_vars({\%var})
+compile [with external %externs %body] to
+ %body_lua <- (%body as lua statements)
+ lua> "\%body_lua:remove_free_vars(\%externs);"
+ return %body_lua
+
+compile [with %assignments %body] to
+ %lua <- (%body as lua statements)
+ lua> ".."
+ local lhs, rhs = LuaCode(tree.source), LuaCode(tree.source)
+ local vars = {}
+ for i, item in ipairs(\%assignments) do
+ local \%target, \%value = item[1], item[2]
+ if not \%target.type == "Var" then
+ error("Invalid target for 'with' assignment: "..tostring(\%target))
end
- return lua;
-
-immediately
- # Simultaneous mutli-assignments like: x,y,z = 1,x,3;
- compile [<- %assignments, assign %assignments] to
- assume (%assignments.type is "Dict") or barf ".."
- Expected a Dict for the assignments part of '<- %' statement, not \%assignments
- lua> ".."
- local lhs, rhs = Lua(tree.source), Lua(tree.source)
- for i, item in ipairs(\%assignments) do
- local \%target, \%value = item[1], item[2]
- \%value = \%value:map(function(t)
- if Action:is_instance(t) and t.stub == "?" then
- return \%target
- end
- end)
- local target_lua = \(%target as lua)
- if not target_lua.is_value then error("Invalid target for assignment: "..\(%target as text)) end
- local value_lua = \(%value as lua)
- if not value_lua.is_value then error("Invalid value for assignment: "..\(%value as text)) end
- if \%target.type == "Var" then
- lhs:add_free_vars({\%target})
- end
- if i > 1 then
- lhs:append(", ")
- rhs:append(", ")
- end
- lhs:append(target_lua)
- rhs:append(value_lua)
+ local target_lua = \(%target as lua)
+ local value_lua = \(%value as lua)
+ if not value_lua.is_value then
+ error("Invalid value for assignment: "..tostring(\%value))
end
- return Lua(tree.source, lhs, " = ", rhs, ";")
-
-immediately
- compile [external %var <- %value] to
- %var_lua <- (%var as lua)
- assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
- %value_lua <- (%value as lua)
- assume %value_lua.is_value or barf "Invalid value for assignment: \%value"
- return: Lua "\%var_lua = \%value_lua;"
-
- compile [with external %externs %body] to
- %body_lua <- (%body as lua statements)
- lua> "\%body_lua:remove_free_vars(\%externs);"
- return %body_lua
-
- compile [with %assignments %body] to
- %lua <- (%body as lua statements)
- lua> ".."
- local lhs, rhs = Lua(tree.source), Lua(tree.source)
- local vars = {}
- for i, item in ipairs(\%assignments) do
- local \%target, \%value = item[1], item[2]
- if not \%target.type == "Var" then
- error("Invalid target for 'with' assignment: "..tostring(\%target))
- end
- local target_lua = \(%target as lua)
- local value_lua = \(%value as lua)
- if not value_lua.is_value then
- error("Invalid value for assignment: "..tostring(\%value))
- end
- if \%target.type == "Var" then
- lhs:add_free_vars({\%target})
- end
- if i > 1 then
- lhs:append(", ")
- rhs:append(", ")
- end
- lhs:append(target_lua)
- rhs:append(value_lua)
- vars[i] = \%target
+ if \%target.type == "Var" then
+ lhs:add_free_vars({\%target})
+ end
+ if i > 1 then
+ lhs:append(", ")
+ rhs:append(", ")
end
- \%lua:remove_free_vars(vars)
- \%lua:prepend("local ", lhs, " = ", rhs, ";\n")
- return
- Lua ".."
- do
- \%lua
- end -- 'with' block
-
-immediately
- # Math Operators
- compile [%x wrapped around %y, %x mod %y] to: Lua value "(\(%x as lua expr) % \(%y as lua expr))"
-
- # 3-part chained comparisons
- # (uses a lambda to avoid re-evaluating middle value, while still being an expression)
- parse [%x < %y < %z] as: =lua "(function(x,y,z) return x < y and y < z; end)(\%x,\%y,\%z)"
- parse [%x <= %y < %z] as: =lua "(function(x,y,z) return x <= y and y < z; end)(\%x,\%y,\%z)"
- parse [%x < %y <= %z] as: =lua "(function(x,y,z) return x < y and y <= z; end)(\%x,\%y,\%z)"
- parse [%x <= %y <= %z] as: =lua "(function(x,y,z) return x <= y and y <= z; end)(\%x,\%y,\%z)"
- parse [%x > %y > %z] as: =lua "(function(x,y,z) return x > y and y > z; end)(\%x,\%y,\%z)"
- parse [%x >= %y > %z] as: =lua "(function(x,y,z) return x >= y and y > z; end)(\%x,\%y,\%z)"
- parse [%x > %y >= %z] as: =lua "(function(x,y,z) return x > y and y >= z; end)(\%x,\%y,\%z)"
- parse [%x >= %y >= %z] as: =lua "(function(x,y,z) return x >= y and y >= z; end)(\%x,\%y,\%z)"
- # TODO: optimize for common case where x,y,z are all either variables or number literals
-
- # Boolean Operators
- compile [%x and %y] to: Lua value "(\(%x as lua expr) and \(%y as lua expr))"
- compile [%x or %y] to: Lua value "(\(%x as lua expr) or \(%y as lua expr))"
-
- # Bitwise Operators
- compile [%a OR %b, %a | %b] to: Lua value "bit32.bor(\(%a as lua expr), \(%b as lua expr))"
- compile [%a XOR %b] to: Lua value "bit32.bxor(\(%a as lua expr), \(%b as lua expr))"
- compile [%a AND %b, %a & %b] to: Lua value "bit32.band(\(%a as lua expr), \(%b as lua expr))"
- compile [NOT %, ~ %] to: Lua value "bit32.bnot(\(% as lua expr))"
- compile [%x LSHIFT %shift, %x << %shift] to: Lua value "bit32.lshift(\(%x as lua expr), \(%shift as lua expr))"
- compile [%x RSHIFT %shift, %x >>> %shift] to: Lua value "bit32.rshift(\(%x as lua expr), \(%shift as lua expr))"
- compile [%x ARSHIFT %shift, %x >> %shift] to: Lua value "bit32.arshift(\(%x as lua expr), \(%shift as lua expr))"
- # TODO: implement OR, XOR, AND for multiple operands?
-
- # Unary operators
- compile [- %] to: Lua value "(- \(% as lua expr))"
- compile [not %] to: Lua value "(not \(% as lua expr))"
- compile [length of %list] to: Lua value "(#\(%list as lua expr))"
+ lhs:append(target_lua)
+ rhs:append(value_lua)
+ vars[i] = \%target
+ end
+ \%lua:remove_free_vars(vars)
+ \%lua:prepend("local ", lhs, " = ", rhs, ";\n")
+ return
+ Lua ".."
+ do
+ \%lua
+ end -- 'with' block
+
+# Math Operators
+compile [%x wrapped around %y, %x mod %y] to: Lua value "(\(%x as lua expr) % \(%y as lua expr))"
+
+# 3-part chained comparisons
+# (uses a lambda to avoid re-evaluating middle value, while still being an expression)
+parse [%x < %y < %z] as: =lua "(function(x,y,z) return x < y and y < z; end)(\%x,\%y,\%z)"
+parse [%x <= %y < %z] as: =lua "(function(x,y,z) return x <= y and y < z; end)(\%x,\%y,\%z)"
+parse [%x < %y <= %z] as: =lua "(function(x,y,z) return x < y and y <= z; end)(\%x,\%y,\%z)"
+parse [%x <= %y <= %z] as: =lua "(function(x,y,z) return x <= y and y <= z; end)(\%x,\%y,\%z)"
+parse [%x > %y > %z] as: =lua "(function(x,y,z) return x > y and y > z; end)(\%x,\%y,\%z)"
+parse [%x >= %y > %z] as: =lua "(function(x,y,z) return x >= y and y > z; end)(\%x,\%y,\%z)"
+parse [%x > %y >= %z] as: =lua "(function(x,y,z) return x > y and y >= z; end)(\%x,\%y,\%z)"
+parse [%x >= %y >= %z] as: =lua "(function(x,y,z) return x >= y and y >= z; end)(\%x,\%y,\%z)"
+# TODO: optimize for common case where x,y,z are all either variables or number literals
+
+# Boolean Operators
+compile [%x and %y] to: Lua value "(\(%x as lua expr) and \(%y as lua expr))"
+compile [%x or %y] to: Lua value "(\(%x as lua expr) or \(%y as lua expr))"
+
+# Bitwise Operators
+# TODO: support bit.???() for luajit and bit32.??? for lua 5.2
+compile [%a OR %b, %a | %b] to: Lua value "(\(%a as lua expr) | \(%b as lua expr))"
+compile [%a XOR %b] to: Lua value "(\(%a as lua expr) ^ \(%b as lua expr))"
+compile [%a AND %b, %a & %b] to: Lua value "(\(%a as lua expr) & \(%b as lua expr))"
+compile [NOT %, ~ %] to: Lua value "~(\(% as lua expr))"
+compile [%x LSHIFT %shift, %x << %shift] to: Lua value "(\(%x as lua expr) << \(%shift as lua expr))"
+compile [%x RSHIFT %shift, %x >>> %shift] to: Lua value "(\(%x as lua expr) >>> \(%shift as lua expr))"
+compile [%x ARSHIFT %shift, %x >> %shift] to: Lua value "(\(%x as lua expr) >> \(%shift as lua expr))"
+# TODO: implement OR, XOR, AND for multiple operands?
+
+# Unary operators
+compile [- %] to: Lua value "(- \(% as lua expr))"
+compile [not %] to: Lua value "(not \(% as lua expr))"
+compile [length of %list] to: Lua value "(#\(%list as lua expr))"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Update operators
-immediately
- parse [%var + <- %, %var +<- %] as: %var <- (%var + %)
- parse [%var - <- %, %var -<- %] as: %var <- (%var - %)
- parse [%var * <- %, %var *<- %] as: %var <- (%var * %)
- parse [%var / <- %, %var /<- %] as: %var <- (%var / %)
- parse [%var ^ <- %, %var ^<- %] as: %var <- (%var ^ %)
- parse [%var and <- %] as: %var <- (%var and %)
- parse [%var or <- %] as: %var <- (%var or %)
- parse [wrap %var around %] as: %var <- (%var wrapped around %)
+parse [%var + <- %, %var +<- %] as: %var <- (%var + %)
+parse [%var - <- %, %var -<- %] as: %var <- (%var - %)
+parse [%var * <- %, %var *<- %] as: %var <- (%var * %)
+parse [%var / <- %, %var /<- %] as: %var <- (%var / %)
+parse [%var ^ <- %, %var ^<- %] as: %var <- (%var ^ %)
+parse [%var and <- %] as: %var <- (%var and %)
+parse [%var or <- %] as: %var <- (%var or %)
+parse [wrap %var around %] as: %var <- (%var wrapped around %)
diff --git a/core/text.nom b/core/text.nom
index 8b26ccb..b576127 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -35,7 +35,7 @@ lua> ".."
};
for name, e in pairs(escapes) do
local lua = "'"..e.."'"
- _ENV["A"..name:as_lua_id()] = compile_time(function(tree) return Lua.Value(tree.source, lua) end)
+ nomsu.COMPILE_ACTIONS[name] = (function(nomsu, tree) return LuaCode.Value(tree.source, lua) end)
end
local colors = {
["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m",
@@ -50,9 +50,9 @@ lua> ".."
for name, c in pairs(colors) do
local color = "'"..c.."'";
local reset = "'"..colors["reset color"].."'";
- _ENV["A"..name:as_lua_id()] = compile_time(function(tree) return Lua.Value(tree.source, color) end)
- _ENV["A"..name:as_lua_id().."_1"] = compile_time(function(tree, text)
- return Lua.Value(tree.source, color, "..", nomsu:tree_to_lua(text), "..", reset);
+ nomsu.COMPILE_ACTIONS[name] = (function(nomsu, tree) return LuaCode.Value(tree.source, color) end)
+ nomsu.COMPILE_ACTIONS[name.." %"] = (function(nomsu, tree, text)
+ return LuaCode.Value(tree.source, color, "..", nomsu:tree_to_lua(text), "..", reset);
end)
end
end