diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/collections.nom | 77 | ||||
| -rw-r--r-- | core/control_flow.nom | 274 | ||||
| -rw-r--r-- | core/coroutines.nom | 16 | ||||
| -rw-r--r-- | core/errors.nom | 39 | ||||
| -rw-r--r-- | core/id.nom | 38 | ||||
| -rw-r--r-- | core/io.nom | 17 | ||||
| -rw-r--r-- | core/math.nom | 50 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 137 | ||||
| -rw-r--r-- | core/operators.nom | 79 | ||||
| -rw-r--r-- | core/text.nom | 46 |
10 files changed, 444 insertions, 329 deletions
diff --git a/core/collections.nom b/core/collections.nom index d24152b..77da968 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains code that supports manipulating and using collections like lists and dictionaries. @@ -15,35 +15,36 @@ test: $visited = {} for $i = $x in $list: $visited.$i = (yes) - assume ($visited == {1, 2, 3, 4, 5}) + assume ($visited == {.1, .2, .3, .4, .5}) $visited = {} for $x in $list: $visited.$x = (yes) - assume ($visited == {1, 2, 3, 4, 5}) - assume (($list|2 nd to last) == 4) - assume (($list|first) == 1) - assume ($list|has 3) - assume (($list|index of 3) == 3) + assume ($visited == {.1, .2, .3, .4, .5}) + assume (($list, 2 nd to last) == 4) + assume (($list, first) == 1) + assume ($list, has 3) + assume (($list, index of 3) == 3) assume ((size of $list) == 5) - $list|add 6 - assume (($list|last) == 6) - $list|pop - assume (($list|last) == 5) - $list|remove index 1 - assume (($list|first) == 2) + $list, add 6 + assume (($list, last) == 6) + $list, pop + assume (($list, last) == 5) + $list, remove index 1 + assume (($list, first) == 2) assume (([1, 2] + [3, 4]) == [1, 2, 3, 4]) # Dict functionality test: - $dict = {x: 1, y: 2, z: 3} + $dict = {.x = 1, .y = 2, .z = 3} assume (size of $dict) == 3 - assume [: for $ in {x: 1}: add $] == [{key: "x", value: 1}] - assume [: for $k = $v in {x: 1}: add {key: $k, value: $v}] == [..] - {key: "x", value: 1} - assume ({x: 1, y: 1} + {y: 10, z: 10}) == {x: 1, y: 11, z: 10} - assume ({x: 1, y: 1} | {y: 10, z: 10}) == {x: 1, y: 1, z: 10} - assume ({x: 1, y: 1} & {y: 10, z: 10}) == {y: 1} - assume ({x: 1, y: 1} ~ {y: 10, z: 10}) == {x: 1, z: 10} + assume [: for $ in {.x = 1}: add $] == [{.key = "x", .value = 1}] + assume [: for $k = $v in {.x = 1}: add {.key = $k, .value = $v}] == [ + {.key = "x", .value = 1} + ] + assume ({.x = 1, .y = 1} + {.y = 10, .z = 10}) == {.x = 1, .y = 11, .z = 10} + assume ({.x = 1, .y = 1} | {.y = 10, .z = 10}) == {.x = 1, .y = 1, .z = 10} + assume ({.x = 1, .y = 1} & {.y = 10, .z = 10}) == {.y = 1} + assume ({.x = 1, .y = 1} ~ {.y = 10, .z = 10}) == {.x = 1, .z = 10} test: assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4]) @@ -55,34 +56,39 @@ externally ($lists flattened) means: for $ in $item: recurse $item on $ ..else: - $flat|add $item + $flat, add $item return $flat test: - assume ((entries in {x: 1}) == [{key: "x", value: 1}]) + assume ((entries in {.x = 1}) == [{.key = "x", .value = 1}]) + +(entries in $dict) parses as [ + : for $k = $v in $dict: add {.key = $k, .value = $v} +] -(entries in $dict) parses as [: for $k = $v in $dict: add {key: $k, value: $v}] test: - assume ((keys in {x: 1}) == ["x"]) + assume ((keys in {.x = 1}) == ["x"]) + [keys in $dict, keys of $dict] all parse as [: for $k = $v in $dict: add $k] test: - assume ((values in {x: 1}) == [1]) + assume ((values in {.x = 1}) == [1]) [values in $dict, values of $dict] all parse as [: for $k = $v in $dict: add $v] # Metatable stuff test: $t = {} - set $t's metatable to {__tostring: $ -> "XXX"} + set $t's metatable to {.__tostring = ($ -> "XXX")} assume ("\$t" == "XXX") -(set $dict's metatable to $metatable) compiles to \ +(set $dict's metatable to $metatable) compiles to .."setmetatable(\($dict as lua expr), \($metatable as lua expr));" [$'s metatable, $'metatable] all compile to "getmetatable(\($ as lua expr))" + test: assume (({} with fallback $ -> ($ + 1)).10 == 11) -($dict with fallback $key -> $value) compiles to " +($dict with fallback $key -> $value) compiles to (" (function(d) local mt = {} for k,v in pairs(getmetatable(d) or {}) do mt[k] = v end @@ -92,7 +98,8 @@ test: return value end return setmetatable(d, mt) - end)(\($dict as lua expr))" + end)(\($dict as lua expr)) +") # Sorting test: @@ -101,12 +108,12 @@ test: assume ($x == [1, 2, 3]) sort $x by $ = (- $) assume ($x == [3, 2, 1]) - $keys = {1: 999, 2: 0, 3: 50} + $keys = {.1 = 999, .2 = 0, .3 = 50} sort $x by $ = $keys.$ assume ($x == [2, 3, 1]) (sort $items) compiles to "table.sort(\($items as lua expr));" -[sort $items by $item = $key_expr, sort $items by $item -> $key_expr] \ -..all parse as (..) +[sort $items by $item = $key_expr, sort $items by $item -> $key_expr] +..all parse as do: $keys = ({} with fallback $item -> $key_expr) lua> "table.sort(\$items, function(x,y) return \$keys[x] < \$keys[y] end)" @@ -121,7 +128,7 @@ externally [$items sorted, sorted $items] all mean: sort $copy return $copy -[$items sorted by $item = $key, $items sorted by $item -> $key] all parse as (..) +[$items sorted by $item = $key, $items sorted by $item -> $key] all parse as result of: $copy = [: for $ in $items: add $] sort $copy by $item = $key @@ -135,6 +142,6 @@ externally (unique $items) means: $seen = {} for $ in $items: unless $seen.$: - $unique|add $ + $unique, add $ $seen.$ = (yes) return $unique diff --git a/core/control_flow.nom b/core/control_flow.nom index 03861e3..b2db945 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains compile-time actions that define basic control flow structures like "if" statements and loops. @@ -19,23 +19,25 @@ test: if (no): barf "conditional fail" -(if $condition $if_body) compiles to " +(if $condition $if_body) compiles to (" if \($condition as lua expr) then \($if_body as lua) - end" + end +") test: unless (yes): barf "conditional fail" (unless $condition $unless_body) parses as (if (not $condition) $unless_body) -[if $condition $if_body else $else_body, unless $condition $else_body else $if_body] \ -..all compile to " +[if $condition $if_body else $else_body, unless $condition $else_body else $if_body] +..all compile to (" if \($condition as lua expr) then \($if_body as lua) else \($else_body as lua) - end" + end +") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,29 +48,31 @@ test: assume ((1 if (yes) else 2) == 1) assume ((1 if (no) else 2) == 2) -[..] +[ $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 -..all compile to: +] all compile 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, 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))") + 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))" ..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 " + 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)())" + end)()) + ") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -86,17 +90,19 @@ test: go to (Loop) assume ($i == 0) -(--- $label ---) compiles to " - ::label_\(..) - ($label.stub|as lua id) if ($label.type == "Action") else (..) +(--- $label ---) compiles to (" + ::label_\( + ($label.stub, as lua id) if ($label.type == "Action") else $label as lua identifier - ..::" + ):: +") -(go to $label) compiles to " - goto label_\(..) - ($label.stub|as lua id) if ($label.type == "Action") else (..) +(go to $label) compiles to (" + goto label_\( + ($label.stub, as lua id) if ($label.type == "Action") else $label as lua identifier - .." + ) +") # Basic loop control (stop $var) compiles to: @@ -131,8 +137,8 @@ test: (repeat while $condition $body) compiles to: $lua = (Lua "while \($condition as lua expr) do\n \($body as lua)") if ($body has subtree \(do next)): - $lua|add "\n ::continue::" - $lua|add "\nend --while-loop" + $lua, add "\n ::continue::" + $lua, add "\nend --while-loop" return $lua (repeat $body) parses as (repeat while (yes) $body) @@ -143,50 +149,52 @@ test: test: $nums = [] for $x in 1 to 5: - $nums|add $x + $nums, add $x assume ($nums == [1, 2, 3, 4, 5]) $nums = [] for $x in 1 to 5 via 2: - $nums|add $x + $nums, add $x assume ($nums == [1, 3, 5]) $nums = [] for $outer in 1 to 100: for $inner in $outer to ($outer + 2): if ($inner == 2): - $nums|add -2 + $nums, add -2 do next $inner - $nums|add $inner + $nums, add $inner if ($inner == 5): stop $outer assume ($nums == [1, -2, 3, -2, 3, 4, 3, 4, 5]) # Numeric range for loops -[..] +[ for $var in $start to $stop by $step $body for $var in $start to $stop via $step $body -..all compile to: +] 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) + $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::" + $lua, add "\n ::continue::" if ($body has subtree \(do next $var)): - $lua|add "\n " (\(---next $var ---) as lua) + $lua, add "\n " (\(---next $var ---) as lua) - $lua|add "\nend -- numeric for " ($var as lua identifier) " loop" + $lua, add "\nend -- numeric for " ($var as lua identifier) " loop" if ($body has subtree \(stop $var)): - $lua = (..) - Lua " + $lua = + Lua (" do -- scope for (stop \($var as lua identifier)) \$lua \(\(---stop $var ---) as lua) - end -- scope for (stop \($var as lua identifier))" + end -- scope for (stop \($var as lua identifier)) + ") return $lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(for $var in $start to $stop $body) parses as (..) +(for $var in $start to $stop $body) parses as for $var in $start to $stop via 1 $body test: @@ -200,7 +208,7 @@ test: $a = [10, 20, 30, 40, 50] $b = [] for $x in $a: - $b|add $x + $b, add $x assume ($a == $b) $b = [] for $x in $a: @@ -210,37 +218,38 @@ test: if ($x == 50): stop $x - $b|add $x + $b, add $x assume ($b == [20, 30, 40]) # 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 " + $lua = + Lua (" for \($i as lua identifier),\($var as lua identifier) in ipairs(\($iterable as lua expr)) do - " - $lua|add ($body as lua) + \; + ") + $lua, add ($body as lua) if ($body has subtree \(do next)): - $lua|add "\n ::continue::" + $lua, add "\n ::continue::" if ($body has subtree \(do next $var)): - $lua|add "\n " (\(---next $var ---) as lua) + $lua, add "\n " (\(---next $var ---) as lua) - $lua|add "\nend --for \($var as lua identifier) loop" + $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" + $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 $body) parses as for $var in $iterable at (=lua "__") $body test: - $d = {a: 10, b: 20, c: 30, d: 40, e: 50} + $d = {.a = 10, .b = 20, .c = 30, .d = 40, .e = 50} $result = [] for $k = $v in $d: if ($k == "a"): @@ -249,35 +258,36 @@ test: if ($v == 20): do next $v - $result|add "\$k = \$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] \ +[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) + $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::" + $lua, add "\n ::continue::" if ($body has subtree \(do next $key)): - $lua|add "\n " (\(---next $key ---) as lua) + $lua, add "\n " (\(---next $key ---) as lua) if ($body has subtree \(do next $value)): - $lua|add "\n " (\(---next $value ---) as lua) + $lua, add "\n " (\(---next $value ---) as lua) - $lua|add "\nend --foreach-loop" + $lua, add "\nend --foreach-loop" $stop_labels = (Lua "") if ($body has subtree \(stop $key)): - $stop_labels|add "\n" (\(---stop $key ---) as lua) + $stop_labels, add "\n" (\(---stop $key ---) as lua) if ($body has subtree \(stop $value)): - $stop_labels|add "\n" (\(---stop $value ---) as lua) + $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" + $lua, add $inner_lua $stop_labels "\nend" return $lua @@ -303,45 +313,58 @@ test: $clause = "if" $else_allowed = (yes) unless ($body.type is "Block"): - compile error at $body "'if' expected a Block, but got a \($body.type)." \ + compile error at $body "'if' expected a Block, but got a \($body.type)." .."Perhaps you forgot to put a ':' after 'if'?" for $line in $body: - unless (..) - (($line.type is "Action") and ((size of $line) >= 2)) and (..) + unless + (($line.type is "Action") and ((size of $line) >= 2)) and $line.(size of $line) is "Block" syntax tree ..: - compile error at $line "Invalid line for the body of an 'if' block." " - Each line should contain one or more conditional expressions followed by a block, or "else" followed \ - ..by a block." + compile error at $line "Invalid line for the body of an 'if' block." (" + Each line should contain one or more conditional expressions followed by a block, or "else"\ + .. followed by a block. + ") $action = $line.(size of $line) if (($line.1 is "else") and ((size of $line) == 2)): unless $else_allowed: - compile error at $line "You can't have two 'else' blocks." \ + compile error at $line "You can't have two 'else' blocks." .."Merge all of the 'else' blocks together." unless ((size of "\$code") > 0): - compile error at $line \ - .."You can't have an 'else' block without a preceding condition" " - If you want the code in this block to always execute, you don't need a conditional block around it. \ - ..Otherwise, make sure the 'else' block comes last." + compile error at $line + .."You can't have an 'else' block without a preceding condition" (" + If you want the code in this block to always execute, you don't need a conditional block \ + ..around it. Otherwise, make sure the 'else' block comes last. + ") + + $code, add (" + + else + \; + ") ($action as lua) - $code|add "\nelse\n " ($action as lua) $else_allowed = (no) ..else: - $code|add $clause " " + $code, add $clause " " for $i in 1 to ((size of $line) - 1): if ($i > 1): - $code|add " or " - $code|add ($line.$i as lua expr) - $code|add " then\n " ($action as lua) + $code, add " or " + $code, add ($line.$i as lua expr) + + $code, add (" + then + \; + ") ($action as lua) + $clause = "\nelseif" if ((size of "\$code") == 0): - compile error at $body "'if' block has an empty body." \ + compile error at $body "'if' block has an empty body." .."This means nothing would happen, so the 'if' block should be deleted." - $code|add "\nend --when" + $code, add "\nend --when" + return $code test: @@ -365,53 +388,72 @@ test: $else_allowed = (yes) define mangler unless ($body.type is "Block"): - compile error at $body "'if' expected a Block, but got a \($body.type)" \ + compile error at $body "'if' expected a Block, but got a \($body.type)" .."Perhaps you forgot to put a ':' after the 'is'?" for $line in $body: - unless (..) - (($line.type is "Action") and ((size of $line) >= 2)) and (..) + unless + (($line.type is "Action") and ((size of $line) >= 2)) and $line.(size of $line) is "Block" syntax tree ..: - compile error at $line "Invalid line for 'if' block." " - Each line should contain expressions followed by a block, or "else" followed by a block" + compile error at $line "Invalid line for 'if' block." (" + Each line should contain expressions followed by a block, or "else" followed by a block + ") $action = $line.(size of $line) if (($line.1 is "else") and ((size of $line) == 2)): unless $else_allowed: - compile error at $line "You can't have two 'else' blocks." \ + compile error at $line "You can't have two 'else' blocks." .."Merge all of the 'else' blocks together." unless ((size of "\$code") > 0): - compile error at $line \ - .."You can't have an 'else' block without a preceding condition" " - If you want the code in this block to always execute, you don't need a conditional block around it. \ - ..Otherwise, make sure the 'else' block comes last." + compile error at $line + .."You can't have an 'else' block without a preceding condition" (" + If you want the code in this block to always execute, you don't need a conditional block \ + ..around it. Otherwise, make sure the 'else' block comes last. + ") + + $code, add (" + + else + \; + ") ($action as lua) - $code|add "\nelse\n " ($action as lua) $else_allowed = (no) ..else: - $code|add $clause " " + $code, add $clause " " for $i in 1 to ((size of $line) - 1): if ($i > 1): - $code|add " or " - $code|add "\(mangle "branch value") == " ($line.$i as lua expr) - $code|add " then\n " ($action as lua) + $code, add " or " + $code, add "\(mangle "branch value") == " ($line.$i as lua expr) + + $code, add (" + then + \; + ") ($action as lua) + $clause = "\nelseif" if ((size of "\$code") == 0): - compile error at $body "'if' block has an empty body." \ + compile error at $body "'if' block has an empty body." .."This means nothing would happen, so the 'if' block should be deleted." - $code|add "\nend --when" - return (..) - Lua " + $code, add "\nend --when" + + return + Lua (" do --if % is... local \(mangle "branch value") = \($branch_value as lua expr) \$code - end -- if % is..." + end -- if % is... + ") # Do/finally -(do $action) compiles to "do\n \($action as lua)\nend -- do" +(do $action) compiles to (" + do + \($action as lua) + end -- do +") + test: $d = {} try: @@ -424,8 +466,8 @@ test: (do $action then always $final_action) compiles to: define mangler - return (..) - Lua " + return + Lua (" do local \(mangle "fell_through") = false local \(mangle "ok"), \(mangle "ret") = pcall(function() @@ -435,7 +477,8 @@ test: \($final_action as lua) if not \(mangle "ok") then error(ret, 0) end if not \(mangle "fell_through") then return ret end - end" + end + ") test: assume ((result of: return 99) == 99) @@ -450,32 +493,33 @@ test: for $2 in $: recurse $ on $2 ..else: - $flat|add $ + $flat, add $ assume (sorted $flat) == [1, 2, 3, 4, 5, 6] # Recurion control flow (for $var in recursive $structure $body) compiles to: with local compile actions: define mangler - (recurse $v on $x) compiles to (..) + (recurse $v on $x) compiles to Lua "table.insert(\(mangle "stack \($v.1)"), \($x as lua expr))" - $lua = (..) - Lua " + $lua = + Lua (" do local \(mangle "stack \($var.1)") = List{\($structure as lua expr)} while #\(mangle "stack \($var.1)") > 0 do \($var as lua expr) = table.remove(\(mangle "stack \($var.1)"), 1) - \($body as lua)" + \($body as lua) + ") if ($body has subtree \(do next)): - $lua|add "\n ::continue::" + $lua, add "\n ::continue::" if ($body has subtree \(do next $var)): - $lua|add "\n \(\(---next $var ---) as lua)" + $lua, add "\n \(\(---next $var ---) as lua)" - $lua|add "\n end -- Recursive loop" + $lua, add "\n end -- Recursive loop" if ($body has subtree \(stop $var)): - $lua|add "\n \(\(---stop $var ---) as lua)" - $lua|add "\nend -- Recursive scope" + $lua, add "\n \(\(---stop $var ---) as lua)" + $lua, add "\nend -- Recursive scope" return $lua diff --git a/core/coroutines.nom b/core/coroutines.nom index 9f6f6f4..c1dd21d 100644 --- a/core/coroutines.nom +++ b/core/coroutines.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file defines the code that creates and manipulates coroutines @@ -9,17 +9,18 @@ use "core/control_flow.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: - $co = (..) + $co = ->: yield 4 yield 5 repeat 3 times: yield 6 $nums = [] - for $ in coroutine $co: $nums|add $ + for $ in coroutine $co: + $nums, add $ assume ($nums == [4, 5, 6, 6, 6]) or barf "Coroutine iteration failed" - $d = {x: 0} - $co2 = (..) + $d = {.x = 0} + $co2 = coroutine: $d.x += 1 yield 1 @@ -29,7 +30,8 @@ test: repeat while ((coroutine status of $co2) != "dead"): resume $co2 assume $d.x == 3 (coroutine $body) parses as (coroutine from (-> $body)) -(for $ in coroutine $co $body) compiles to " +(for $ in coroutine $co $body) compiles to (" for \($ as lua expr) in coroutine_wrap(\($co as lua expr)) do \($body as lua) - end" + end +") diff --git a/core/errors.nom b/core/errors.nom index 07b743c..9cf7a23 100644 --- a/core/errors.nom +++ b/core/errors.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains basic error reporting code @@ -6,33 +6,39 @@ use "core/metaprogramming.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(barf $msg) compiles to \ +(barf $msg) compiles to .."error(\(=lua "\$msg and \($msg as lua expr) or 'nil'"), 0);" (assume $condition) compiles to: lua> "local \$assumption = 'Assumption failed: '..tostring((\$condition):get_source_code())" - return (..) - Lua " + + return + Lua (" if not \($condition as lua expr) then error(\(quote "\$assumption"), 0) - end" + end + ") (assume $a == $b) compiles to: lua> "local \$assumption = 'Assumption failed: '..tostring(\(\($a == $b) as nomsu))" + define mangler - return (..) - Lua " + + return + Lua (" do local \(mangle "a"), \(mangle "b") = \($a as lua expr), \($b as lua expr) if \(mangle "a") ~= \(mangle "b") then error(\(quote "\$assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\(mangle "b")), 0) end - end" + end + ") -(assume $condition or barf $message) compiles to " +(assume $condition or barf $message) compiles to (" if not \($condition as lua expr) then error(\($message as lua expr), 0) - end" + end +") test: try (barf) and if it succeeds: @@ -50,10 +56,10 @@ test: assume ($x == 3) or barf "do/then always failed" # Try/except -[..] +[ 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 -..all compile to " +] all compile to (" do local fell_through = false local err, erred = nil, false @@ -74,7 +80,8 @@ test: elseif erred then error(err, 0) end - end" + end +") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -87,14 +94,14 @@ test: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(try $action) parses as (..) +(try $action) parses as try $action and if it succeeds (do nothing) or if it barfs (do nothing) #(try %action and if it barfs %fallback) parses as (..) try %action and if it succeeds (do nothing) or if it barfs %fallback -(try $action and if it barfs $msg $fallback) parses as (..) +(try $action and if it barfs $msg $fallback) parses as try $action and if it succeeds (do nothing) or if it barfs $msg $fallback -(try $action and if it succeeds $success) parses as (..) +(try $action and if it succeeds $success) parses as try $action and if it succeeds $success or if it barfs (do nothing) diff --git a/core/id.nom b/core/id.nom index 6512bf5..bc9a96c 100644 --- a/core/id.nom +++ b/core/id.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # A simple UUID function based on RFC 4122: http://www.ietf.org/rfc/rfc4122.txt @@ -13,32 +13,36 @@ use "core/control_flow.nom" $NaN_surrogate = {} $nil_surrogate = {} $obj_by_id = {} -set $obj_by_id's metatable to {__mode: "v"} +set $obj_by_id's metatable to {.__mode = "v"} $id_by_obj = {} -set $id_by_obj's metatable to {..} - __mode: "k", __index: for ($self $key): - if ($key == (nil)): - return $self.$nil_surrogate - - if ($key != $key): - return $self.$NaN_surrogate - - --- (retry) --- - $id = (uuid) - if ($obj_by_id.$id != (nil)): go to (retry) - $self.$key = $id - $obj_by_id.$id = $key - return $id +set $id_by_obj's metatable to { + .__mode = "k", .__index = ( + for ($self $key): + if ($key == (nil)): + return $self.$nil_surrogate + + if ($key != $key): + return $self.$NaN_surrogate + + --- (retry) --- + $id = (uuid) + if ($obj_by_id.$id != (nil)): go to (retry) + $self.$key = $id + $obj_by_id.$id = $key + return $id + ) +} externally (uuid) means: # Set all the other bits to randomly (or pseudo-randomly) chosen values. - $bytes = [..] + $bytes = [ # time-low, time-mid, time-high-and-version randint (2 ^ (4 * 8)), randint (2 ^ (2 * 8)), randint (2 ^ (2 * 8 - 4)) # clock-seq-and-reserved, clock-seq-low randint (2 ^ (1 * 8 - 2)), randint (2 ^ (1 * 8)), randint (2 ^ (3 * 8)) # node randint (2 ^ (3 * 8)) + ] # Set the four most significant bits (bits 12 through 15) of the # time_hi_and_version field to the 4-bit version number from diff --git a/core/io.nom b/core/io.nom index 4bf2028..1d8bac4 100644 --- a/core/io.nom +++ b/core/io.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains basic input/output code @@ -7,25 +7,28 @@ use "core/metaprogramming.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (say $message) compiles to: - lua> " + lua> (" if \$message.type == "Text" then return LuaCode("say(", \($message as lua expr), ");"); else return LuaCode("say(tostring(", \($message as lua expr), "));"); - end" + end + ") (say $message inline) compiles to: - lua> " + lua> (" if \$message.type == "Text" then return LuaCode("io.write(", \($message as lua expr), ")"); else return LuaCode("io.write(tostring(", \($message as lua expr), "))"); - end" + end + ") (ask $prompt) compiles to: - lua> " + lua> (" if \$prompt.type == "Text" then return LuaCode("(io.write(", \($prompt as lua expr), ") and io.read())"); else return LuaCode("(io.write(tostring(", \($prompt as lua expr), ")) and io.read())"); - end" + end + ") diff --git a/core/math.nom b/core/math.nom index 8ee5d62..d456bff 100644 --- a/core/math.nom +++ b/core/math.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file defines some common math literals and functions @@ -12,9 +12,11 @@ use "core/collections.nom" # Literals: test: - assume (all of [inf, NaN, pi, tau, golden ratio, e]) or barf \ + assume (all of [inf, NaN, pi, tau, golden ratio, e]) or barf .."math constants failed" + $nan = (NaN) + assume ($nan != $nan) or barf "NaN failed" [infinity, inf] all compile to "math.huge" [not a number, NaN, nan] all compile to "(0/0)" @@ -29,38 +31,47 @@ test: (($ as a number)'s meaning) = ((tonumber $)'s meaning) (($ as number)'s meaning) = ((tonumber $)'s meaning) test: - assume (..) - all of [..] + assume + all of [ abs 5, | 5 |, sqrt 5, √ 5, sine 5, cosine 5, tangent 5, arc sine 5, arc cosine 5 arc tangent 5, arc tangent 5 / 10, hyperbolic sine 5, hyperbolic cosine 5 hyperbolic tangent 5, e^ 5, ln 5, log base 2 of 5, floor 5, ceiling 5, round 5 + ] ..or barf "math functions failed" + [absolute value $, | $ |, abs $] all compile to "math.abs(\($ as lua expr))" -[square root $, square root of $, √ $, sqrt $] all compile to \ + +[square root $, square root of $, √ $, sqrt $] all compile to .."math.sqrt(\($ as lua expr))" + [sine $, sin $] all compile to "math.sin(\($ as lua expr))" + [cosine $, cos $] all compile to "math.cos(\($ as lua expr))" [tangent $, tan $] all compile to "math.tan(\($ as lua expr))" [arc sine $, asin $] all compile to "math.asin(\($ as lua expr))" [arc cosine $, acos $] all compile to "math.acos(\($ as lua expr))" [arc tangent $, atan $] all compile to "math.atan(\($ as lua expr))" -[arc tangent $y / $x, atan2 $y $x] all compile to \ +[arc tangent $y / $x, atan2 $y $x] all compile to .."math.atan2(\($y as lua expr), \($x as lua expr))" + [hyperbolic sine $, sinh $] all compile to "math.sinh(\($ as lua expr))" + [hyperbolic cosine $, cosh $] all compile to "math.cosh(\($ as lua expr))" [hyperbolic tangent $, tanh $] all compile to "math.tanh(\($ as lua expr))" [e^ $, exp $] all compile to "math.exp(\($ as lua expr))" [natural log $, ln $, log $] all compile to "math.log(\($ as lua expr))" -[log $ base $base, log base $base of $] all compile to \ +[log $ base $base, log base $base of $] all compile to .."math.log(\($ as lua expr), \($base as lua expr))" + (floor $) compiles to "math.floor(\($ as lua expr))" + [ceiling $, ceil $] all compile to "math.ceil(\($ as lua expr))" [round $, $ rounded] all compile to "math.floor(\($ as lua expr) + .5)" test: assume ((463 to the nearest 100) == 500) or barf "rounding failed" assume ((2.6 to the nearest 0.25) == 2.5) or barf "rounding failed" -externally ($n to the nearest $rounder) means (..) +externally ($n to the nearest $rounder) means =lua "(\$rounder)*math.floor((\$n / \$rounder) + .5)" # Any/all @@ -140,7 +151,7 @@ externally [product of $items, product $items] all mean: %lua::add ")" return %lua -externally [avg of $items, average of $items] all mean (..) +externally [avg of $items, average of $items] all mean (sum of $items) / (size of $items) # Min/max @@ -150,9 +161,9 @@ externally [min of $items, smallest of $items, lowest of $items] all mean: if (($best == (nil)) or ($ < $best)): $best = $ return $best -externally [..] +externally [ max of $items, biggest of $items, largest of $items, highest of $items -..all mean: +] all mean: $best = (nil) for $ in $items: if (($best == (nil)) or ($ > $best)): $best = $ @@ -162,7 +173,7 @@ test: assume ((min of [3, -4, 1, 2] by $ = ($ * $)) == 1) assume ((max of [3, -4, 1, 2] by $ = ($ * $)) == -4) -(min of $items by $item = $value_expr) parses as (..) +(min of $items by $item = $value_expr) parses as result of: $best = (nil) $best_key = (nil) @@ -173,7 +184,7 @@ test: $best_key = $key return $best -(max of $items by $item = $value_expr) parses as (..) +(max of $items by $item = $value_expr) parses as result of: $best = (nil) $best_key = (nil) @@ -186,15 +197,18 @@ test: # Random functions externally (seed random with $) means: - lua> "math.randomseed(\$);\nfor i=1,20 do math.random(); end" + lua> (" + math.randomseed(\$); + for i=1,20 do math.random(); end + ") (seed random) parses as (seed random with (=lua "os.time()")) [random number, random, rand] all compile to "math.random()" -[random int $n, random integer $n, randint $n] all compile to \ +[random int $n, random integer $n, randint $n] all compile to .."math.random(\($n as lua expr))" -[random from $low to $high, random number from $low to $high, rand $low $high] \ +[random from $low to $high, random number from $low to $high, rand $low $high] ..all compile to "math.random(\($low as lua expr), \($high as lua expr))" -externally [..] +externally [ random choice from $elements, random choice $elements, random $elements -..all mean (=lua "\$elements[math.random(#\$elements)]") +] all mean (=lua "\$elements[math.random(#\$elements)]") diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 6d9ced4..6dea00f 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -1,11 +1,11 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This File contains actions for making actions and compile-time actions and some helper functions to make that easier. lua> "NOMSU_CORE_VERSION = 12" lua> "NOMSU_LIB_VERSION = 8" -lua> " +lua> (" do local mangle_index = 0 function mangler() @@ -18,13 +18,15 @@ lua> " end compile.action["define mangler"] = function(compile) return LuaCode("local mangle = mangler()") - end" + end +") -lua> " +lua> (" compile.action["1 ->"] = function(compile, \$args, \$body) if \$args and not \$body then \$args, \$body = {}, \$args end local body_lua = SyntaxTree:is_instance(\$body) and compile(\$body) or \$body - if SyntaxTree:is_instance(\$body) and \$body.type ~= "Block" then body_lua:prepend("return ") end + if SyntaxTree:is_instance(\$body) and \$body.type ~= "Block" then body_lua:prepend("\ + ..return ") end local lua = LuaCode("(function(") if SyntaxTree:is_instance(\$args) and (\$args.type == "Action" or \$args.type == "MethodCall") then \$args = \$args:get_args() @@ -34,11 +36,13 @@ lua> " if arg_lua == "..." then if i < #\$args then compile_error_at(SyntaxTree:is_instance(arg) and arg or nil, - "Extra arguments must come last.", "Try removing any arguments after (*extra arguments*)") + "Extra arguments must come last.", "Try removing any arguments after \ + ..(*extra arguments*)") end elseif not arg_lua:is_lua_id() then compile_error_at(SyntaxTree:is_instance(arg) and arg or nil, - "This does not compile to a Lua identifier, so it can't be used as a function argument.", + "This does not compile to a Lua identifier, so it can't be used as a function \ + ..argument.", "This should probably be a Nomsu variable instead (like $x).") end lua:add(i > 1 and ", " or "", arg_lua) @@ -49,7 +53,8 @@ lua> " return lua end compile.action["->"] = compile.action["1 ->"] - compile.action["for"] = compile.action["1 ->"]" + compile.action["for"] = compile.action["1 ->"] +") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -74,7 +79,7 @@ test: asdf assume ($tmp is (nil)) or barf "compile to is leaking variables" -lua> " +lua> (" compile.action["1 compiles to"] = function(compile, \$action, \$body) local \$args = List{\(\$compile), unpack(\$action:get_args())} if \$body.type == "Text" then @@ -82,12 +87,13 @@ lua> " end return LuaCode("compile.action[", \$action:get_stub():as_lua(), "] = ", \(\($args -> $body) as lua)) - end" + end +") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ($actions all compile to $body) compiles to: - lua> " + lua> (" if \$actions.type ~= "List" then compile_error(\$actions, "This should be a list of actions.") end @@ -108,13 +114,14 @@ lua> " lua:add(") end") end end - return lua" + return lua + ") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: (foo $x) means "outer" - with {((foo $)'s meaning)}: + with [(foo $)'s meaning]: (foo $x) means: $y = ($x + 1) return $y @@ -124,7 +131,7 @@ test: assume ((foo 1) == "outer") ($action means $body) compiles to: - lua> " + lua> (" local lua = LuaCode() if \$action.type == "MethodCall" then @@ -136,10 +143,11 @@ test: compile_error_at(\$action, "Expected an action or method call here") end lua:add(" = ", \(\($action -> $body) as lua), ";") - return lua" + return lua + ") ($actions all mean $body) compiles to: - lua> " + lua> (" local lua = \(\($actions.1 means $body) as lua) local first_def = (\$actions[1].type == "MethodCall" and LuaCode(compile(\$actions[1][1]), ".", \$actions[1]:get_stub():as_lua_id()) @@ -161,7 +169,8 @@ test: lua:add(" = ", \(\($alias_args -> $actions.1) as lua), ";") end end - return lua" + return lua + ") test: externally (baz1) means: @@ -173,23 +182,25 @@ test: assume ((baz2) == "baz2") (externally $action means $body) compiles to: - lua> " + lua> (" local lua = \(\($action means $body) as lua) lua:remove_free_vars({\$action:get_stub():as_lua_id()}) - return lua" + return lua + ") (externally $actions all mean $body) compiles to: - lua> " + lua> (" local lua = \(\($actions all mean $body) as lua) lua:remove_free_vars(table.map(\$actions, function(a) return a:get_stub():as_lua_id() end)) - return lua" + return lua + ") test: assume (((say $)'s meaning) == (=lua "say")) -($action's meaning) compiles to (Lua (($action|get stub)|as lua id)) +($action's meaning) compiles to (Lua ($action, get stub, as lua id)) test: - (swap $x and $y) parses as (..) + (swap $x and $y) parses as do: $tmp = $x $x = $y @@ -198,15 +209,17 @@ test: test: [$1, $2] = [1, 2] swap $1 and $2 - assume (($1 == 2) and ($2 == 1)) or barf \ + assume (($1 == 2) and ($2 == 1)) or barf .."'parse % as %' failed on 'swap % and %'" + [$tmp, $tmp2] = [1, 2] + swap $tmp and $tmp2 - assume (($tmp == 2) and ($tmp2 == 1)) or barf \ + assume (($tmp == 2) and ($tmp2 == 1)) or barf .."'parse % as %' variable mangling failed." ($actions all parse as $body) compiles to: - lua> " + lua> (" local replacements = {} if \$actions.type ~= "List" then compile_error(\$actions, "This should be a list.") @@ -219,8 +232,8 @@ test: if replacements[t[1]] then return replacements[t[1]] else - return "SyntaxTree{mangle("..t[1]:as_lua().."), type="..t.type:as_lua()..", source="..tostring(\ - ..t.source):as_lua().."}" + return "SyntaxTree{mangle("..t[1]:as_lua().."), type="..t.type:as_lua()..", \ + ..source="..tostring(t.source):as_lua().."}" end elseif SyntaxTree:is_instance(t) then local ret = {} @@ -248,7 +261,8 @@ test: "local mangle = mangler()", "\\nreturn ", make_tree(\$body)) local ret = \(\($actions all compile to $new_body) as lua) - return ret" + return ret + ") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -256,25 +270,28 @@ test: #(%tree as lua expr) compiles to "compile(\(=lua "compile(\%tree, true)"), true)" externally ($tree as lua expr) means: - lua> " + lua> (" local tree_lua = compile(\$tree) if \$tree.type == 'Block' then tree_lua = LuaCode:from(\$tree.source, '(function()\\n ', tree_lua, '\\nend)()') elseif \$tree.type == 'MethodCall' and #\$tree > 2 then - compile_error_at(\$tree, "This must be a single value instead of "..(#\$tree - 1).." method calls.", + compile_error_at(\$tree, "This must be a single value instead of "..(#\$tree - 1).."\ + .. method calls.", "Replace this with a single method call.") end - return tree_lua" + return tree_lua + ") externally [$var as lua identifier, $var as lua id] all mean: - lua> " + lua> (" local lua = \($var as lua) if not lua:text():is_a_lua_id() then compile_error(\$var, "This is supposed to be something that compiles to a valid Lua identifier.", "This should probably be a variable.") end - return lua" + return lua + ") test: (num args (*extra arguments*)) means (select "#" (*extra arguments*)) @@ -285,40 +302,46 @@ test: assume (third arg 5 6 7 8) == 7 (*extra arguments*) compiles to "..." + ($ is syntax tree) compiles to "SyntaxTree:is_instance(\($ as lua expr))" -externally ($ is $kind syntax tree) means (..) + +externally ($ is $kind syntax tree) means =lua "SyntaxTree:is_instance(\$) and \$.type == \$kind" -($tree with $t -> $replacement) compiles to " +($tree with $t -> $replacement) compiles to (" \($tree as lua expr):map(function(\($t as lua expr)) \(=lua "\$replacement.type == 'Block' and \($replacement as lua) or 'return '..\($replacement as lua expr)") - end)" + end) +") -externally ($tree with vars $replacements) means (..) - =lua " +externally ($tree with vars $replacements) means + =lua (" \$tree:map(function(\$t) if \$t.type == "Var" then return \$replacements[\$t[1]] end - end)" + end) + ") -(tree $tree with vars $replacements) compiles to " +(tree $tree with vars $replacements) compiles to (" \(=lua "(\$tree):as_lua()"):map(function(t) if t.type == "Var" then return \($replacements as lua expr)[t[1]] end - end)" + end) +") -($tree has subtree $match_tree) compiles to " +($tree has subtree $match_tree) compiles to (" (function() local match_tree = \($match_tree as lua expr) for subtree in coroutine_wrap(function() \($tree as lua expr):map(yield) end) do if subtree == match_tree then return true end end - end)()" + end)() +") externally (match $tree with $patt) means: - lua> " + lua> (" if \$patt.type == "Var" then return Dict{[\$patt[1]]=\$tree} end if \$patt.type == "Action" and \$patt:get_stub() ~= \$tree:get_stub() then return nil end if #\$patt ~= #\$tree then return nil end @@ -333,7 +356,8 @@ externally (match $tree with $patt) means: end end end - return matches" + return matches + ") test: assume ((quote "one\n\"two\"") == "\"one\\n\\\"two\\\"\"") @@ -346,21 +370,22 @@ test: assume ("" is text) assume ("" isn't a "Dict") externally ($ is text) means (=lua "\(lua type of $) == 'string'") -externally [$ is not text, $ isn't text] all mean (..) +externally [$ is not text, $ isn't text] all mean =lua "\(lua type of $) ~= 'string'" externally (type of $) means: - lua> " + lua> (" local lua_type = \(lua type of $) if lua_type == 'string' then return 'Text' elseif lua_type == 'table' or lua_type == 'userdata' then local mt = getmetatable(\$) if mt and mt.__type then return mt.__type end end - return lua_type" + return lua_type + ") [$ is a $type, $ is an $type] all parse as ((type of $) == $type) -[$ isn't a $type, $ isn't an $type, $ is not a $type, $ is not an $type] \ +[$ isn't a $type, $ isn't an $type, $ is not a $type, $ is not an $type] ..all parse as ((type of $) != $type) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -374,7 +399,7 @@ test: assume $x == 1 assume (run \(return \(\(5) + \(5)))) == 10 (run $nomsu_code) compiles to "run_1_in(\($nomsu_code as lua expr), _ENV)" -[compile $block, compiled $block, $block compiled] all compile to \ +[compile $block, compiled $block, $block compiled] all compile to .."compile(\($block as lua))" test: @@ -385,14 +410,15 @@ test: # 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. (return (*extra arguments*)) compiles to: - lua> " + lua> (" local lua = \(Lua "do return ") for i=1,select('#',...) do if i > 1 then lua:add(", ") end lua:add(_1_as_lua((select(i, ...)))) end lua:add(" end") - return lua" + return lua + ") # Literals (yes) compiles to "true" @@ -406,14 +432,15 @@ test: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(with local compile actions $body) compiles to " +(with local compile actions $body) compiles to (" do --local compile = _1_forked(compile) local old_action = compile.action compile.action = _1_forked(old_action) \($body as lua) compile.action = old_action - end" + end +") externally (Nomsu version) means: return "\(Nomsu syntax version).\(core version).\(Nomsu compiler version).\(lib version)" diff --git a/core/operators.nom b/core/operators.nom index 1bb9f0b..8dfac09 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains definitions of operators like "+" and "and". @@ -16,7 +16,7 @@ test: ($x <= $y) compiles to "(\($x as lua expr) <= \($y as lua expr))" ($x >= $y) compiles to "(\($x as lua expr) >= \($y as lua expr))" [$a is $b, $a == $b] all compile to "(\($a as lua expr) == \($b as lua expr))" -[$a isn't $b, $a is not $b, $a not= $b, $a != $b] all compile to \ +[$a isn't $b, $a is not $b, $a not= $b, $a != $b] all compile to .."(\($a as lua expr) ~= \($b as lua expr))" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -34,7 +34,7 @@ test: # Variable assignment operator ($var = $value) compiles to: - lua> " + lua> (" local lua = LuaCode() if \$var.type == "List" then for i, \$assignment in ipairs(\$var) do @@ -50,8 +50,8 @@ test: if #\$value ~= #\$var then compile_error_at(\$value, "This assignment has too "..(#\$value > #\$var and "many" or "few").." values.", - "Make sure it has the same number of values on the left and right hand side of the '\ - ..=' operator.") + "Make sure it has the same number of values on the left and right hand side \ + ..of the '=' operator.") end for i, \$val in ipairs(\$value) do if i > 1 then lua:add(", ") end @@ -70,7 +70,8 @@ test: end lua:add(' = ', \($value as lua expr)) end - return lua" + return lua + ") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -89,7 +90,7 @@ test: $foozle = "inner" $y = "inner" set global x local y - assume (($foozle == "inner") and ($y == "outer")) or barf \ + assume (($foozle == "inner") and ($y == "outer")) or barf .."'with external' failed." (with external $externs $body) compiles to: @@ -99,7 +100,7 @@ test: test: [$x, $y] = [1, 2] - with {$z, $x: 999}: + with [$z, $x = 999]: assume $z == (nil) $z = 999 assume ($z == 999) or barf "'with' failed." @@ -108,35 +109,30 @@ test: assume ($z == (nil)) or barf "'with' scoping failed" (with $assignments $body) compiles to: - $lua = ($body as lua) - lua> " - local lhs, rhs = LuaCode(), LuaCode() - local vars = {} - for i, item in ipairs(\$assignments) do - local \$target, \$value = item[1], item[2] - local target_lua = \($target as lua) - if not target_lua:text():is_lua_id() then - compile_error_at(\$target, "Invalid target for 'with' scope assignment.", - "This should be either a variable or an action's meaning.") + lua> (" + local \$defs = LuaCode() + for i, \$item in ipairs(\$assignments) do + if i > 1 then \$defs:add("\\n") end + local item_lua = \($item as lua) + if \$item.type == 'Action' and \$item.stub == '1 =' then + item_lua:remove_free_vars(item_lua.free_vars) end - local value_lua = \$value and \($value as lua) or "nil" - if i > 1 then - lhs:add(", ") - rhs:add(", ") - end - lhs:add(target_lua) - rhs:add(value_lua) - vars[i] = target_lua:text() + \$defs:add("local ", item_lua, ";") end - \$lua:remove_free_vars(vars) - \$lua:prepend("local ", lhs, " = ", rhs, ";\\n")" - return (Lua "do\n \$lua\nend -- 'with' block") + ") + return + Lua (" + do + \$defs + \($body as lua) + end -- 'with' block + ") # Math Operators test: assume ((5 wrapped around 2) == 1) or barf "mod not working" -[$x wrapped around $y, $x mod $y] all compile to \ +[$x wrapped around $y, $x mod $y] all compile to .."((\($x as lua expr)) % (\($y as lua expr)))" # 3-part chained comparisons @@ -147,9 +143,11 @@ test: external $calls = ($calls + 1) return 1 assume (0 <= (one) <= 2) or barf "Three-way chained comparison failed." - assume ($calls == 1) or barf \ + assume ($calls == 1) or barf .."Three-way comparison evaluated middle value multiple times" + ($x < $y < $z) parses as ((($a $b $c) -> (($a < $b) and ($b < $c))) $x $y $z) + ($x <= $y < $z) parses as ((($a $b $c) -> (($a <= $b) and ($b < $c))) $x $y $z) ($x < $y <= $z) parses as ((($a $b $c) -> (($a < $b) and ($b <= $c))) $x $y $z) ($x <= $y <= $z) parses as ((($a $b $c) -> (($a <= $b) and ($b <= $c))) $x $y $z) @@ -184,30 +182,31 @@ test: fall back to bit.bor(), bit.band(), etc. lua> "if \((is jit) or ((Lua version) == "Lua 5.2")) then" [NOT $, ~ $] all compile to "bit.bnot(\($ as lua expr))" -[$x OR $y, $x | $y] all compile to \ +[$x OR $y, $x | $y] all compile to .."bit.bor(\($x as lua expr), \($y as lua expr))" -[$x XOR $y, $x ~ $y] all compile to \ +[$x XOR $y, $x ~ $y] all compile to .."bit.bxor(\($x as lua expr), \($y as lua expr))" -[$x AND $y, $x & $y] all compile to \ +[$x AND $y, $x & $y] all compile to .."bit.band(\($x as lua expr), \($y as lua expr))" -[$x LSHIFT $shift, $x << $shift] all compile to \ +[$x LSHIFT $shift, $x << $shift] all compile to .."bit.lshift(\($x as lua expr), \($shift as lua expr))" -[$x RSHIFT $shift, $x >> $shift] all compile to \ +[$x RSHIFT $shift, $x >> $shift] all compile to .."bit.rshift(\($x as lua expr), \($shift as lua expr))" lua> "else" + [NOT $, ~ $] all compile to "~(\($ as lua expr))" [$x OR $y, $x | $y] all compile to "(\($x as lua expr) | \($y as lua expr))" [$x XOR $y, $x ~ $y] all compile to "(\($x as lua expr) ~ \($y as lua expr))" [$x AND $y, $x & $y] all compile to "(\($x as lua expr) & \($y as lua expr))" -[$x LSHIFT $shift, $x << $shift] all compile to \ +[$x LSHIFT $shift, $x << $shift] all compile to .."(\($x as lua expr) << \($shift as lua expr))" -[$x RSHIFT $shift, $x >> $shift] all compile to \ +[$x RSHIFT $shift, $x >> $shift] all compile to .."(\($x as lua expr) >> \($shift as lua expr))" lua> "end" @@ -220,8 +219,8 @@ test: (not $) compiles to "(not \($ as lua expr))" test: assume ((size of [1, 2, 3]) == 3) - assume ((# [1, 2, 3]) == 3) -[# $list, size of $list] all compile to "(#\($list as lua expr))" + assume ((#[1, 2, 3]) == 3) +[#$list, size of $list] all compile to "(#\($list as lua expr))" ($list is empty) compiles to "(#\($list as lua expr) == 0)" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/core/text.nom b/core/text.nom index 8b500f7..b5b22b3 100644 --- a/core/text.nom +++ b/core/text.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V5.12.12.8 +#!/usr/bin/env nomsu -V6.12.12.8 # This file contains some definitions of text escape sequences, including ANSI console color codes. @@ -12,16 +12,22 @@ use "core/control_flow.nom" test: assume "\[1, 2, 3]" == "[1, 2, 3]" assume "foo = \(1 + 2)!" == "foo = 3!" - assume "one\ntwo" == "one\ntwo" + assume (" + one + two + ") == (" + one + two + ") assume "nogap" == "nogap" - assume (["x", "y"]|joined with ",") == "x,y" - assume (["x", "y"]|joined) == "xy" - assume ("BAR"|byte 2) == 65 - assume ("BAR"|bytes 1 to 2) == [66, 65] - assume ("asdf"|capitalized) == "Asdf" - assume ("asdf"|uppercase) == "ASDF" - assume ("asdf"|with "s" -> "X") == "aXdf" - assume ("one\ntwo\n"|lines) == ["one", "two", ""] + assume (["x", "y"], joined with ",") == "x,y" + assume (["x", "y"], joined) == "xy" + assume ("BAR", byte 2) == 65 + assume ("BAR", bytes 1 to 2) == [66, 65] + assume ("asdf", capitalized) == "Asdf" + assume ("asdf", uppercase) == "ASDF" + assume ("asdf", with "s" -> "X") == "aXdf" + assume ("one\ntwo\n", lines) == ["one", "two", ""] ($spec とは $body) parses as ($spec means $body) test: @@ -31,15 +37,16 @@ test: ($expr for $match in $text matching $patt) compiles to: define mangler - return (..) - Lua " + return + Lua (" (function() local \(mangle "comprehension") = List{} for \($match as lua expr) in (\($text as lua expr)):gmatch(\($patt as lua expr)) do \(mangle "comprehension")[#\(mangle "comprehension")+1] = \($expr as lua) end return \(mangle "comprehension") - end)()" + end)() + ") test: assume "\n" == (newline) @@ -49,15 +56,16 @@ test: externally ($num as hex) means: if ($num < 0): - return ("-0x%X"|formatted with (- $num)) + return ("-0x%X", formatted with (- $num)) ..else: - return ("0x%X"|formatted with $num) + return ("0x%X", formatted with $num) # Text literals -$escapes = {..} - nl: "\n", newline: "\n", tab: "\t", bell: "\a", cr: "\r", "carriage return": "\r" - backspace: "\b", "form feed": "\f", formfeed: "\f", "vertical tab": "\v" +$escapes = { + .nl = "\n", .newline = "\n", .tab = "\t", .bell = "\a", .cr = "\r", ."carriage return" = "\r" + .backspace = "\b", ."form feed" = "\f", .formfeed = "\f", ."vertical tab" = "\v" +} for $name = $str in $escapes: - with {$lua: Lua (quote $str)}: + with [$lua = (Lua (quote $str))]: $compile.action.$name = (-> $lua) |
