aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/control_flow.nom138
1 files changed, 68 insertions, 70 deletions
diff --git a/lib/core/control_flow.nom b/lib/core/control_flow.nom
index ca67394..a1fdeee 100644
--- a/lib/core/control_flow.nom
+++ b/lib/core/control_flow.nom
@@ -161,31 +161,71 @@ test:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# For-each loop (lua's "ipairs()")
-(for $var in $iterable at $i $body) compiles to:
+(for $var in $iterable $body) compiles to:
+ unless $var:
+ at (this tree) fail "No var here"
# This uses Lua's approach of only allowing loop-scoped variables in a loop
+ if (($var.type == "Action") and ($var.stub == "1 =")):
+ [$key, $value] = [$var.1, $var.3]
+ go to (vars set)
+ if (($var.type == "Action") and ($var.stub == "1 at")):
+ [$key, $value] = [$var.3, $var.1]
+ ..else:
+ [$key, $value] = [nil, $var]
+
+ --- (vars set) ---
+ unless $value:
+ at (this tree) fail "No value here"
+
+ # Numeric 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
+ for \($value as lua identifier)=_start,\($stop as lua expr) do
+ ")
+ if $key:
+ $loop, add ("
+
+ local \($key as lua identifier) = \($value as lua identifier) - _start + 1;
")
+ go to (loop set)
+
+ # Numeric loop with step:
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
+ local _start, _step = \($start as lua expr), \($step as lua expr);
+ for \($value as lua identifier)=_start,\($stop as lua expr),_step do
+ ")
+ if $key:
+ $loop, add ("
+
+ local \($key as lua identifier) = (\($value as lua identifier) - _start)/_step + 1
+ ")
+ go to (loop set)
+
+ # for $ in (...):
+ if $key:
+ $loop =
+ Lua ("
+ local _iterating = \($iterable as lua expr);
+ local _next = getmetatable(_iterating).__next or next;
+ for \($key as lua identifier),\($value as lua identifier) in _next,_iterating,nil do
+ if \($value as lua identifier) == nil and _1_is_a_dead_coroutine(_iterating) then break end
")
- unless $loop:
+ ..else:
$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)]
+ local _iterating = _1_as_an_iterable(\($iterable as lua expr))
+ for _i=1,#_iterating do
+ local \($value as lua identifier) = _iterating[_i]
+ if \($value as lua identifier) == nil and _1_is_a_dead_coroutine(_iterating) then break end
")
+
+ --- (loop set) ---
$lua =
Lua ("
do -- for-loop
@@ -196,17 +236,27 @@ test:
if ($body has subtree \(do next)):
$lua, add "\n ::continue::"
- if ($body has subtree \(do next $var)):
- $lua, add "\n " (\(---next $var ---) as lua)
+ if ($key and ($body has subtree \(do next $key))):
+ $lua, add "\n " (\(---next $key ---) as lua)
+
+ if ($body has subtree \(do next $value)):
+ $lua, add "\n " (\(---next $value ---) as lua)
$lua, add "\n end"
- if ($body has subtree \(stop $var)):
- $lua, add "\n " (\(---stop $var ---) as lua)
+ if ($key and ($body has subtree \(stop $key))):
+ $lua, add "\n " (\(---stop $key ---) as lua)
+ if ($body has subtree \(stop $value)):
+ $lua, add "\n " (\(---stop $value ---) as lua)
$lua, add "\nend -- for-loop"
+ $lua, remove free vars [($value as lua identifier, text), $key and ($key as lua identifier, text)]
return $lua
-(for $var in $iterable $body) parses as
- for $var in $iterable at (=lua "_i") $body
+# TODO: remove these shims:
+(for $var in $iterable at $i $body) parses as
+ for ($i = $var) in $iterable $body
+
+(for $k = $v in $iterable $body) parses as
+ for ($k = $v) in $iterable $body
test:
$d = {.a = 10, .b = 20, .c = 30, .d = 40, .e = 50}
@@ -237,7 +287,7 @@ test:
stop $outer
assume ($nums == [1, -2, 3, -2, 3, 4, 3, 4, 5])
-# These are shims, and should be phased out:
+# TODO: 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
@@ -253,59 +303,7 @@ test:
$x += 1
assume $x == 5
-(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 = []
- for $x in $a:
- $b, add $x
- assume ($a == $b)
- $b = []
- for $x in $a:
- if ($x == 10):
- do next $x
-
- if ($x == 50):
- stop $x
-
- $b, add $x
- assume ($b == [20, 30, 40])
- # Small memory footprint:
- assume (1 to (1 << 31))
-
-[for $key = $value in $iterable $body, for $key $value in $iterable $body]
-..all compile to:
- $lua =
- Lua ("
- for \($key as lua identifier),\($value as lua identifier) in pairs(\
- ..\($iterable 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 $key)):
- $lua, add "\n " (\(---next $key ---) as lua)
-
- if ($body has subtree \(do next $value)):
- $lua, add "\n " (\(---next $value ---) as lua)
-
- $lua, add "\nend --foreach-loop"
- $stop_labels = (Lua "")
- if ($body has subtree \(stop $key)):
- $stop_labels, add "\n" (\(---stop $key ---) as lua)
-
- if ($body has subtree \(stop $value)):
- $stop_labels, add "\n" (\(---stop $value ---) as lua)
-
- if ((size of "\$stop_labels") > 0):
- $inner_lua = $lua
- $lua = (Lua "do -- scope for stopping for $ = $ loop\n ")
- $lua, add $inner_lua $stop_labels "\nend"
-
- return $lua
+(repeat $n times $body) parses as (for (=lua "_i") in (1 to $n by 1) $body)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~