aboutsummaryrefslogtreecommitdiff
path: root/lib/core/control_flow.nom
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-02-05 15:45:27 -0800
committerBruce Hill <bruce@bruce-hill.com>2019-02-05 15:47:01 -0800
commit72d699fe86ddb34473b54a0df27d21b4a9159284 (patch)
treebdb4036181b5c15d920d1500f8f67407a44d2014 /lib/core/control_flow.nom
parent0ff3219f355b4307783288800724213636920912 (diff)
Bunch of changes:
- Added shebangs to generated code output - SyntaxTree:map() -> SyntaxTree:with(), and corresponding changes to metaprogramming API - Added (return Lua 1) shorthand for (return (Lua 1)) - (1 and 2 and 3) compile rule mapping to -> (1 and (*extra arguments*)) - Don't scan for errors, just report them when compiling - Syntax changes: - Added prefix actions (e.g. #$foo) - Operator chars now include utf8 chars - Ditch "escaped nomsu" type (use (\ 1) compile action instead)
Diffstat (limited to 'lib/core/control_flow.nom')
-rw-r--r--lib/core/control_flow.nom205
1 files changed, 99 insertions, 106 deletions
diff --git a/lib/core/control_flow.nom b/lib/core/control_flow.nom
index 415611b..ca67394 100644
--- a/lib/core/control_flow.nom
+++ b/lib/core/control_flow.nom
@@ -64,25 +64,23 @@ test:
# 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, .List, .Dict, .Number}.($when_true_expr.type):
- return
- Lua ("
- (\($condition as lua expr) and \($when_true_expr as lua expr) or \
- ..\($when_false_expr as lua expr))
- ")
+ return Lua ("
+ (\($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 ("
- ((function()
- if \($condition as lua expr) then
- return \($when_true_expr as lua expr)
- else
- return \($when_false_expr as lua expr)
- end
- end)())
- ")
+ return Lua ("
+ ((function()
+ if \($condition as lua expr) then
+ return \($when_true_expr as lua expr)
+ else
+ return \($when_false_expr as lua expr)
+ end
+ end)())
+ ")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -117,15 +115,15 @@ test:
# Basic loop control
(stop $var) compiles to:
if $var:
- return (Lua "goto stop_\($var as lua identifier)")
+ return Lua "goto stop_\($var as lua identifier)"
..else:
- return (Lua "break")
+ return Lua "break"
(do next $var) compiles to:
if $var:
- return (Lua "goto continue_\($var as lua identifier)")
+ return Lua "goto continue_\($var as lua identifier)"
..else:
- return (Lua "goto continue")
+ return Lua "goto continue"
(---stop $var ---) compiles to "::stop_\($var as lua identifier)::"
(---next $var ---) compiles to "::continue_\($var as lua identifier)::"
@@ -162,18 +160,75 @@ test:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# For-each loop (lua's "ipairs()")
+(for $var in $iterable at $i $body) compiles to:
+ # This uses Lua's approach of only allowing loop-scoped variables in a loop
+ if (($iterable.type == "Action") and (($iterable, get stub) == "1 to")):
+ [$start, $stop] = [$iterable.1, $iterable.3]
+ $loop =
+ Lua ("
+ local _start = \($start as lua expr)
+ for \($var as lua identifier)=_start,\($stop as lua expr) do
+ \($i as lua identifier) = \($var as lua identifier) - _start + 1
+ ")
+ if (($iterable.type == "Action") and (($iterable, get stub) == "1 to 2 by")):
+ [$start, $stop, $step] = [$iterable.1, $iterable.3, $iterable.5]
+ $loop =
+ Lua ("
+ local _start, _step = \($start as lua expr), \($step as lua expr)
+ for \($var as lua identifier)=_start,\($stop as lua expr),_step do
+ \($i as lua identifier) = (\($var as lua identifier) - _start)/_step + 1
+ ")
+ unless $loop:
+ $loop =
+ Lua ("
+ local _iterating = _1_as_list(\($iterable as lua expr))
+ for \($i as lua identifier)=1,#_iterating do
+ \($var as lua identifier) = _iterating[\($i as lua identifier)]
+ ")
+ $lua =
+ Lua ("
+ do -- for-loop
+ \$loop
+ \;
+ ")
+ $lua, add ($body as lua)
+ if ($body has subtree \(do next)):
+ $lua, add "\n ::continue::"
+
+ if ($body has subtree \(do next $var)):
+ $lua, add "\n " (\(---next $var ---) as lua)
+
+ $lua, add "\n end"
+ if ($body has subtree \(stop $var)):
+ $lua, add "\n " (\(---stop $var ---) as lua)
+ $lua, add "\nend -- for-loop"
+ return $lua
+
+(for $var in $iterable $body) parses as
+ for $var in $iterable at (=lua "_i") $body
+
test:
+ $d = {.a = 10, .b = 20, .c = 30, .d = 40, .e = 50}
+ $result = []
+ for $k = $v in $d:
+ if ($k == "a"):
+ do next $k
+
+ if ($v == 20):
+ do next $v
+
+ $result, add "\$k = \$v"
+ assume (($result sorted) == ["c = 30", "d = 40", "e = 50"])
+
+# Numeric range for loops
+test:
+ assume ([: for $ in (1 to 5): add $] == [1, 2, 3, 4, 5])
+ assume ([: for $ in (1 to 5 by 2): add $] == [1, 3, 5])
+ assume ([: for $ in (5 to 1): add $] == [])
$nums = []
- for $x in 1 to 5:
- $nums, add $x
- assume ($nums == [1, 2, 3, 4, 5])
- $nums = []
- for $x in 1 to 5 via 2:
- $nums, add $x
- assume ($nums == [1, 3, 5])
- $nums = []
- for $outer in 1 to 100:
- for $inner in $outer to ($outer + 2):
+ for $outer in (1 to 100):
+ for $inner in ($outer to ($outer + 2)):
if ($inner == 2):
$nums, add -2
do next $inner
@@ -182,47 +237,25 @@ test:
stop $outer
assume ($nums == [1, -2, 3, -2, 3, 4, 3, 4, 5])
-# Numeric range for loops
+# These are shims, and should be phased out:
[
for $var in $start to $stop by $step $body
for $var in $start to $stop via $step $body
-] all compile to:
- # This uses Lua's approach of only allowing loop-scoped variables in a loop
- $lua =
- Lua ("
- for \($var as lua identifier)=\($start as lua expr),\($stop as lua expr),\
- ..\($step as lua expr) do
- ")
- $lua, add "\n " ($body as lua)
- if ($body has subtree \(do next)):
- $lua, add "\n ::continue::"
-
- if ($body has subtree \(do next $var)):
- $lua, add "\n " (\(---next $var ---) as lua)
-
- $lua, add "\nend -- numeric for " ($var as lua identifier) " loop"
- if ($body has subtree \(stop $var)):
- $lua =
- Lua ("
- do -- scope for (stop \($var as lua identifier))
- \$lua
- \(\(---stop $var ---) as lua)
- end -- scope for (stop \($var as lua identifier))
- ")
- return $lua
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+] all parse as (for $var in ($start to $stop by $step) $body)
(for $var in $start to $stop $body) parses as
- for $var in $start to $stop via 1 $body
+ for $var in ($start to $stop) $body
+# repeat $n times is a shorthand:
test:
$x = 0
repeat 5 times:
$x += 1
assume $x == 5
-(repeat $n times $body) parses as (for (=lua "_XXX_") in 1 to $n $body)
+(repeat $n times $body) parses as (for (=lua "_XXX_") in (1 to $n by 1) $body)
+
+# Dict iteration (lua's "pairs()")
test:
$a = [10, 20, 30, 40, 50]
$b = []
@@ -239,48 +272,9 @@ test:
$b, add $x
assume ($b == [20, 30, 40])
+ # Small memory footprint:
+ assume (1 to (1 << 31))
-# For-each loop (lua's "ipairs()")
-(for $var in $iterable at $i $body) compiles to:
- # This uses Lua's approach of only allowing loop-scoped variables in a loop
- $lua =
- Lua ("
- for \($i as lua identifier),\($var as lua identifier) in ipairs(\($iterable as lua expr)) do
- \;
- ")
- $lua, add ($body as lua)
- if ($body has subtree \(do next)):
- $lua, add "\n ::continue::"
-
- if ($body has subtree \(do next $var)):
- $lua, add "\n " (\(---next $var ---) as lua)
-
- $lua, add "\nend --for \($var as lua identifier) loop"
- if ($body has subtree \(stop $var)):
- $inner_lua = $lua
- $lua = (Lua "do -- scope for stopping for-loop\n ")
- $lua, add $inner_lua "\n "
- $lua, add (\(---stop $var ---) as lua)
- $lua, add "\nend -- end of scope for stopping for-loop"
- return $lua
-
-(for $var in $iterable $body) parses as
- for $var in $iterable at (=lua "__") $body
-
-test:
- $d = {.a = 10, .b = 20, .c = 30, .d = 40, .e = 50}
- $result = []
- for $k = $v in $d:
- if ($k == "a"):
- do next $k
-
- if ($v == 20):
- do next $v
-
- $result, add "\$k = \$v"
- assume (($result sorted) == ["c = 30", "d = 40", "e = 50"])
-
-# Dict iteration (lua's "pairs()")
[for $key = $value in $iterable $body, for $key $value in $iterable $body]
..all compile to:
$lua =
@@ -453,13 +447,12 @@ test:
")
$code, add "\nend --when"
- return
- Lua ("
- do --if $ is...
- local \(mangle "branch value") = \($branch_value as lua expr)
- \$code
- end -- if $ is...
- ")
+ return Lua ("
+ do --if $ is...
+ local \(mangle "branch value") = \($branch_value as lua expr)
+ \$code
+ end -- if $ is...
+ ")
# Do/finally
(do $action) compiles to ("