Auto-updated to version 5

This commit is contained in:
Bruce Hill 2018-12-14 20:21:03 -08:00
parent 6abec65843
commit 4fe63f253f
39 changed files with 1743 additions and 1770 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <2.3 to Nomsu 2.3 This file defines upgrades from Nomsu <2.3 to Nomsu 2.3
@ -6,15 +6,15 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action (%a = %b) to "2.3" as (%a == %b) upgrade action ($a = $b) to "2.3" as ($a == $b)
upgrade action (<- %) to "2.3" as (set %) upgrade action (<- $) to "2.3" as (set $)
upgrade action (assign %) to "2.3" as (set %) upgrade action (assign $) to "2.3" as (set $)
upgrade action (%a <- %b) to "2.3" as (%a = %b) upgrade action ($a <- $b) to "2.3" as ($a = $b)
upgrade action (external %a <- %b) to "2.3" as (external %a = %b) upgrade action (external $a <- $b) to "2.3" as (external $a = $b)
upgrade action (%a +<- %b) to "2.3" as (%a += %b) upgrade action ($a +<- $b) to "2.3" as ($a += $b)
upgrade action (%a -<- %b) to "2.3" as (%a -= %b) upgrade action ($a -<- $b) to "2.3" as ($a -= $b)
upgrade action (%a *<- %b) to "2.3" as (%a *= %b) upgrade action ($a *<- $b) to "2.3" as ($a *= $b)
upgrade action (%a /<- %b) to "2.3" as (%a /= %b) upgrade action ($a /<- $b) to "2.3" as ($a /= $b)
upgrade action (%a ^<- %b) to "2.3" as (%a ^= %b) upgrade action ($a ^<- $b) to "2.3" as ($a ^= $b)
upgrade action (%a and<- %b) to "2.3" as (%a and= %b) upgrade action ($a and<- $b) to "2.3" as ($a and= $b)
upgrade action (%a or<- %b) to "2.3" as (%a or= %b) upgrade action ($a or<- $b) to "2.3" as ($a or= $b)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <2.4 to Nomsu 2.4 This file defines upgrades from Nomsu <2.4 to Nomsu 2.4
@ -6,69 +6,65 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade %tree to "2.4" as: upgrade $tree to "2.4" as:
unless (%tree is "Action" syntax tree): return unless ($tree is "Action" syntax tree): return
if %tree.stub is: if $tree.stub is:
"when" "if": "when" "if":
if ((size of %tree) == 3): return %tree if ((size of $tree) == 3): return $tree
%conditions = [] $conditions = []
%new_lines = [] $new_lines = []
%body = ((%tree.2 upgraded) if (%tree.2 is "Block" syntax tree) else [%tree.2 upgraded]) $body = (($tree.2 upgraded) if ($tree.2 is "Block" syntax tree) else [$tree.2 upgraded])
for %line in %body: for $line in $body:
when: when:
(not (%line is "Action" syntax tree)): (not ($line is "Action" syntax tree)): $new_lines|add $line
%new_lines::add %line ($line.stub is "*"):
if ((size of $line) == 2):
(%line.stub is "*"): $conditions|add $line.2
if ((size of %line) == 2):
%conditions::add %line.2
..else: ..else:
%new_lines::add %line $new_lines|add $line
(%line.stub == "* else"): ($line.stub == "* else"):
%new_lines::add (\(else %block) with vars {block: %line.3}) $new_lines|add (\(else $block) with vars {block: $line.3})
else: else:
%conditions::add %line.2 $conditions|add $line.2
%action = %line.3 $action = $line.3
unless (%action is "Block" syntax tree): unless ($action is "Block" syntax tree):
%action = (=lua "SyntaxTree{type='Block', source=\%action.source, \%action}") $action = (=lua "SyntaxTree{type='Block', source=\$action.source, \$action}")
%conditions::add %action $conditions|add $action
%new_lines::add (..) $new_lines|
=lua "SyntaxTree{type='Action', source=\%conditions[1].source, unpack(\%conditions)}" add (=lua "SyntaxTree{type='Action', source=\$conditions[1].source, unpack(\$conditions)}")
%conditions = [] $conditions = []
return (..) return (..)
\(when %body) with vars {..} \(when $body) with vars {..}
body: =lua "SyntaxTree{type='Block', source=\%tree[2].source, unpack(\%new_lines)}" body: =lua "SyntaxTree{type='Block', source=\$tree[2].source, unpack(\$new_lines)}"
"if 1 is ?" "if 1 = ?": "if 1 is ?" "if 1 = ?":
%values = [] $values = []
%new_lines = [] $new_lines = []
%body = ((%tree.5 upgraded) if (%tree.5 is "Block" syntax tree) else [%tree.5 upgraded]) $body = (($tree.5 upgraded) if ($tree.5 is "Block" syntax tree) else [$tree.5 upgraded])
for %line in %body: for $line in $body:
when: when:
(not (%line is "Action" syntax tree)): (not ($line is "Action" syntax tree)): $new_lines|add $line
%new_lines::add %line ($line.stub is "*"):
if ((size of $line) == 2):
(%line.stub is "*"): $values|add $line.2
if ((size of %line) == 2):
%values::add %line.2
..else: ..else:
%new_lines::add %line $new_lines|add $line
(%line.stub == "* else"): ($line.stub == "* else"):
%new_lines::add (\(else %block) with vars {block: %line.3}) $new_lines|add (\(else $block) with vars {block: $line.3})
else: else:
%values::add %line.2 $values|add $line.2
%action = %line.3 $action = $line.3
unless (%action is "Block" syntax tree): %action = \(: %action) unless ($action is "Block" syntax tree): $action = \(: $action)
%values::add %action $values|add $action
%new_lines::add (..) $new_lines|
=lua "SyntaxTree{type='Action', source=\%values[1].source, unpack(\%values)}" add (=lua "SyntaxTree{type='Action', source=\$values[1].source, unpack(\$values)}")
%values = [] $values = []
return (..) return (..)
\(if %var is %body) with vars {..} \(if $var is $body) with vars {..}
var: %tree.2 upgraded, body: =lua "SyntaxTree{type='Block', source=\%tree[5].source, unpack(\%new_lines)}" var: $tree.2 upgraded, body: =lua "SyntaxTree{type='Block', source=\$tree[5].source, unpack(\$new_lines)}"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <2.5.5.5 to Nomsu 2.5.5.5 This file defines upgrades from Nomsu <2.5.5.5 to Nomsu 2.5.5.5
@ -6,9 +6,9 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action [hash %, sha1 %] to "2.5.5.5" as (..) upgrade action [hash $, sha1 $] to "2.5.5.5" as (..)
=lua "\(base64 decode (hash %)):gsub('.', function(c) return ('%x02'):format(c) end)" =lua "\(base64 decode (hash $)):gsub('.', function(c) return ('%x02'):format(c) end)"
upgrade action [file with hash %] to "2.5.5.5" as (..) upgrade action [file with hash $] to "2.5.5.5" as (..)
file with hash (..) file with hash (..)
base64 (=lua "\%:gsub('..', function(xx) return string.char(tonumber(xx, 16)) end)") base64 (=lua "\$:gsub('..', function(xx) return string.char(tonumber(xx, 16)) end)")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <2.5 to Nomsu 2.5 This file defines upgrades from Nomsu <2.5 to Nomsu 2.5
@ -6,8 +6,8 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action (for %1 where %2 matches %3 %4) to "2.5" as (..) upgrade action (for $1 where $2 matches $3 $4) to "2.5" as (..)
for %1 in %2 matching %3 %4 for $1 in $2 matching $3 $4
upgrade action (%1 for %2 where %3 matches %4) to "2.5" as (..) upgrade action ($1 for $2 where $3 matches $4) to "2.5" as (..)
%1 for %2 in %3 matching %4 $1 for $2 in $3 matching $4

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu 1 to Nomsu 2 This file defines upgrades from Nomsu 1 to Nomsu 2
@ -6,31 +6,31 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade %tree to "2" as: upgrade $tree to "2" as:
unless (%tree is "Action" syntax tree): return unless ($tree is "Action" syntax tree): return
if (%tree.stub is "if 1 2 else"): if ($tree.stub is "if 1 2 else"):
%true_body = (%tree.3 upgraded) $true_body = ($tree.3 upgraded)
unless (%true_body is "Block" syntax tree): unless ($true_body is "Block" syntax tree):
%true_body = \(: %true_body) $true_body = \(: $true_body)
%false_body = (%tree.5 upgraded) $false_body = ($tree.5 upgraded)
unless (%false_body is "Block" syntax tree): unless ($false_body is "Block" syntax tree):
%false_body = (=lua "Block(\%false_body.source, \%false_body)") $false_body = (=lua "Block(\$false_body.source, \$false_body)")
return (..) return (..)
\(if %cond %true_body else %false_body) with vars {..} \(if $cond $true_body else $false_body) with vars {..}
cond: %tree.2 upgraded, true_body: %true_body, false_body: %false_body cond: $tree.2 upgraded, true_body: $true_body, false_body: $false_body
%need_blocks = [..] $need_blocks = [..]
"if", "unless", "for 1 in", "for 1 = 2 in", "repeat while 1", "repeat 1 times" "if", "unless", "for 1 in", "for 1 = 2 in", "repeat while 1", "repeat 1 times"
"repeat", "repeat until 1", "for 1 in 2 to 3 by", "for 1 in 2 to 3 via" "repeat", "repeat until 1", "for 1 in 2 to 3 by", "for 1 in 2 to 3 via"
"for 1 in 2 to", "for 1 2 in", "do", "for 1 in recursive", "test", "with", "result of" "for 1 in 2 to", "for 1 2 in", "do", "for 1 in recursive", "test", "with", "result of"
"when" "when"
for %n in %need_blocks: for $n in $need_blocks:
if (%tree.stub is %n): if ($tree.stub is $n):
%bits = [: for % in %tree: add ((% upgraded) if (% is syntax tree) else %)] $bits = [: for $ in $tree: add (($ upgraded) if ($ is syntax tree) else $)]
unless ((%bits::last) is "Block" syntax tree): unless (($bits|last) is "Block" syntax tree):
%body = (%bits::last) $body = ($bits|last)
%bits.(size of %bits) = (..) $bits.(size of $bits) = (..)
=lua "SyntaxTree{type='Block', source=\%body.source, \%body}" =lua "SyntaxTree{type='Block', source=\$body.source, \$body}"
return (=lua "SyntaxTree{type='Action', source=\%tree.source, unpack(\%bits)}") return (=lua "SyntaxTree{type='Action', source=\$tree.source, unpack(\$bits)}")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <3.5.5.6 to Nomsu 3.5.5.6 This file defines upgrades from Nomsu <3.5.5.6 to Nomsu 3.5.5.6
@ -7,5 +7,5 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action "traceback" to "3.5.5.6" via (..) upgrade action "traceback" to "3.5.5.6" via (..)
for %tree: for $tree:
compile error at %tree "'traceback' has been deprecated." compile error at $tree "'traceback' has been deprecated."

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <3.6 to 3.6 This file defines upgrades from Nomsu <3.6 to 3.6
@ -7,24 +7,23 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action [..] upgrade action [..]
append %item to %list, add %item to %list, to %list add %item, to %list append %item append $item to $list, add $item to $list, to $list add $item, to $list append $item
..to "3.6" as (%list::add %item) ..to "3.6" as ($list|add $item)
upgrade action [add %item to %list at index %i] to "3.6" as (..) upgrade action [add $item to $list at index $i] to "3.6" as (..)
%list::at index %i add %item $list|at index $i add $item
upgrade action [pop from %list, remove last from %list] to "3.6" as (%list::pop) upgrade action [pop from $list, remove last from $list] to "3.6" as ($list|pop)
upgrade action [remove index %index from %list] to "3.6" as (..) upgrade action [remove index $index from $list] to "3.6" as (..)
%list::remove index %index $list|remove index $index
upgrade action [to %1 write %2, %1 <-write %2] to "3.6" as (%1::add %2) upgrade action [to $1 write $2, $1 <-write $2] to "3.6" as ($1|add $2)
upgrade action [to %1 write %2 joined by %3] to "3.6" as (..) upgrade action [to $1 write $2 joined by $3] to "3.6" as ($1|add $2 joined by $3)
%1::add %2 joined by %3 upgrade action [declare locals in $lua] to "3.6" as ($lua|declare locals)
upgrade action [declare locals in %lua] to "3.6" as (%lua::declare locals) upgrade action [declare locals $locs in $lua] to "3.6" as (..)
upgrade action [declare locals %locs in %lua] to "3.6" as (..) $lua|declare locals $locs
%lua::declare locals %locs
upgrade action [add free vars %vars to %lua] to "3.6" as (..) upgrade action [add free vars $vars to $lua] to "3.6" as (..)
%lua::add free vars %vars $lua|add free vars $vars
upgrade action [remove free vars %vars from %lua] to "3.6" as (..) upgrade action [remove free vars $vars from $lua] to "3.6" as (..)
%lua::remove free vars %vars $lua|remove free vars $vars

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <3.7 to 3.7 This file defines upgrades from Nomsu <3.7 to 3.7
@ -6,36 +6,28 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action [%index st to last in %list] to "3.7" as (..) upgrade action [$index st to last in $list] to "3.7" as ($list|$index st to last)
%list::%index st to last upgrade action [$index nd to last in $list] to "3.7" as ($list|$index nd to last)
upgrade action [$index rd to last in $list] to "3.7" as ($list|$index rd to last)
upgrade action [%index nd to last in %list] to "3.7" as (..) upgrade action [$index th to last in $list] to "3.7" as ($list|$index rd th last)
%list::%index nd to last upgrade action [last in $list] to "3.7" as ($list|last)
upgrade action [first in $list] to "3.7" as ($list|first)
upgrade action [%index rd to last in %list] to "3.7" as (..) upgrade action [$item is in $list, $list contains $item, $list has $item] to \
%list::%index rd to last .."3.7" as ($list|has $item)
upgrade action [%index th to last in %list] to "3.7" as (..)
%list::%index rd th last
upgrade action [last in %list] to "3.7" as (%list::last)
upgrade action [first in %list] to "3.7" as (%list::first)
upgrade action [%item is in %list, %list contains %item, %list has %item] to \
.."3.7" as (%list::has %item)
upgrade action [..] upgrade action [..]
%item isn't in %list, %item is not in %list, %list doesn't contain %item $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 $list does not contain $item, $list doesn't have $item, $list does not have $item
..to "3.7" as (not (%list::has %item)) ..to "3.7" as (not ($list|has $item))
upgrade action [%list has key %index, %list has index %index] to "3.7" as (..) upgrade action [$list has key $index, $list has index $index] to "3.7" as (..)
%list.%index != (nil) $list.$index != (nil)
upgrade action [..] upgrade action [..]
%list doesn't have key %index, %list does not have key %index $list doesn't have key $index, $list does not have key $index
%list doesn't have index %index, %list does not have index %index $list doesn't have index $index, $list does not have index $index
..to "3.7" as (%list.%index == (nil)) ..to "3.7" as ($list.$index == (nil))
upgrade action [..] upgrade action [..]
number of keys in %list, len %list, || %list ||, length %list, length of %list number of keys in $list, len $list, || $list ||, length $list, length of $list
..to "3.7" as (size of %list) ..to "3.7" as (size of $list)

View File

@ -1,19 +1,19 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <3.8 to 3.8 (Text method changes) This file defines upgrades from Nomsu <3.8 to 3.8 (Text method changes)
upgrade action [%texts joined with %glue] to "3.8" as (%texts::joined with %glue) upgrade action [$texts joined with $glue] to "3.8" as ($texts|joined with $glue)
upgrade action [%texts joined, joined %texts] to "3.8" as (%texts::joined) upgrade action [$texts joined, joined $texts] to "3.8" as ($texts|joined)
upgrade action [byte %i of %text] to "3.8" as (%text::byte %i) upgrade action [byte $i of $text] to "3.8" as ($text|byte $i)
upgrade action [bytes %start to %stop of %text] to "3.8" as (..) upgrade action [bytes $start to $stop of $text] to "3.8" as (..)
%text::bytes %start to %stop $text|bytes $start to $stop
upgrade action [bytes of %text] to "3.8" as (%text::bytes) upgrade action [bytes of $text] to "3.8" as ($text|bytes)
upgrade action [capitalized %text, %text capitalized] to "3.8" as (..) upgrade action [capitalized $text, $text capitalized] to "3.8" as (..)
%text::capitalized $text|capitalized
upgrade action [uppercase %text, %text uppercase] to "3.8" as (%text::uppercase) upgrade action [uppercase $text, $text uppercase] to "3.8" as ($text|uppercase)
upgrade action [..] upgrade action [..]
%text with %sub instead of %patt, %text with %patt replaced by %sub $text with $sub instead of $patt, $text with $patt replaced by $sub
%text s/ %patt / %sub $text s/ $patt / $sub
..to "3.8" as (%text::with %patt -> %sub) ..to "3.8" as ($text|with $patt -> $sub)
upgrade action [%text matches %pattern] to "3.8" as (%text::matches %pattern) upgrade action [$text matches $pattern] to "3.8" as ($text|matches $pattern)
upgrade action [%text matching %pattern] to "3.8" as (%text::matching %pattern).1 upgrade action [$text matching $pattern] to "3.8" as ($text|matching $pattern).1

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <=2 to Nomsu 3 This file defines upgrades from Nomsu <=2 to Nomsu 3
@ -6,10 +6,10 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action (method %spec %body) to "3" as (my action %spec %body) upgrade action (method $spec $body) to "3" as (my action $spec $body)
upgrade action (me) to "3" as %me upgrade action (me) to "3" as $me
upgrade action (@) to "3" as %me upgrade action (@) to "3" as $me
upgrade action "as" to "3" via (..) upgrade action "as" to "3" via (..)
for %tree: for $tree:
compile error at %tree "Object API has changed and 'as' is no longer supported." "\ compile error at $tree "Object API has changed and 'as' is no longer supported." \
..Use (%obj::action ...) instead of (as %obj: action ...)" .."Use (%obj::action ...) instead of (as %obj: action ...)"

View File

@ -1,80 +1,80 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <4.10.12.7 to 4.10.12.7 This file defines upgrades from Nomsu <4.10.12.7 to 4.10.12.7
use "compatibility/compatibility.nom" use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action (% as lua statements) to "4.10.12.7" as (% as lua) upgrade action ($ as lua statements) to "4.10.12.7" as ($ as lua)
upgrade action (% as lua return) to "4.10.12.7" as (..) upgrade action ($ as lua return) to "4.10.12.7" as (..)
=lua "\%.type == 'Block' and \(% as lua) or 'return '..\(% as lua expr)" =lua "\$.type == 'Block' and \($ as lua) or 'return '..\($ as lua expr)"
upgrade action (Lua value %) to "4.10.12.7" as (Lua %) upgrade action (Lua value $) to "4.10.12.7" as (Lua $)
upgrade action (%e for % in %items) to "4.10.12.7" as [: for % in %items: add %e] upgrade action ($e for $ in $items) to "4.10.12.7" as [: for $ in $items: add $e]
upgrade action (%e for %k = %v in %items) to "4.10.12.7" as [..] upgrade action ($e for $k = $v in $items) to "4.10.12.7" as [..]
: for %k = %v in %items: add %e : for $k = $v in $items: add $e
upgrade action (%e for %i in %start to %stop) to "4.10.12.7" as [..] upgrade action ($e for $i in $start to $stop) to "4.10.12.7" as [..]
: for %i in %start to %stop: add %e : for $i in $start to $stop: add $e
upgrade action (%e for %i in %start to %stop by %step) to "4.10.12.7" as [..] upgrade action ($e for $i in $start to $stop by $step) to "4.10.12.7" as [..]
: for %i in %start to %stop by %step: add %e : for $i in $start to $stop by $step: add $e
upgrade action (%e for %i in %start to %stop via %step) to "4.10.12.7" as [..] upgrade action ($e for $i in $start to $stop via $step) to "4.10.12.7" as [..]
: for %i in %start to %stop by %step: add %e : for $i in $start to $stop by $step: add $e
upgrade action (%k = %v for % in %items) to "4.10.12.7" as {..} upgrade action ($k = $v for $ in $items) to "4.10.12.7" as {..}
: for % in %items: add %k = %v : for $ in $items: add $k = $v
upgrade action (%k = %v for %k0 = %v0 in %items) to "4.10.12.7" as {..} upgrade action ($k = $v for $k0 = $v0 in $items) to "4.10.12.7" as {..}
: for %k0 = %v0 in %items: add %k = %v : for $k0 = $v0 in $items: add $k = $v
upgrade action (%k = %v for %i in %start to %stop) to "4.10.12.7" as {..} upgrade action ($k = $v for $i in $start to $stop) to "4.10.12.7" as {..}
: for %i in %start to %stop: add %k = %v : for $i in $start to $stop: add $k = $v
upgrade action (%k = %v for %i in %start to %stop by %step) to "4.10.12.7" as {..} upgrade action ($k = $v for $i in $start to $stop by $step) to "4.10.12.7" as {..}
: for %i in %start to %stop by %step: add %k = %v : for $i in $start to $stop by $step: add $k = $v
upgrade action (%k = %v for %i in %start to %stop via %step) to "4.10.12.7" as {..} upgrade action ($k = $v for $i in $start to $stop via $step) to "4.10.12.7" as {..}
: for %i in %start to %stop by %step: add %k = %v : for $i in $start to $stop by $step: add $k = $v
upgrade action (parse %text from %filename) to "4.10.12.7" as (..) upgrade action (parse $text from $filename) to "4.10.12.7" as (..)
(NomsuCode from (Source %filename 1 (size of %text)) %text) parsed (NomsuCode from (Source $filename 1 (size of $text)) $text) parsed
upgrade action (% as lua statements) to "4.10.12.7" as (% as lua) upgrade action ($ as lua statements) to "4.10.12.7" as ($ as lua)
upgrade action (compile error at %pos %err hint %hint) to "4.10.12.7" as (..) upgrade action (compile error at $pos $err hint $hint) to "4.10.12.7" as (..)
compile error at %pos %err %hint compile error at $pos $err $hint
# In old code, it was okay to have imports at the top of the file in the same chunk, # In old code, it was okay to have imports at the top of the file in the same chunk,
but changes to the API now require imports to be in their own file chunk in order but changes to the API now require imports to be in their own file chunk in order
for compilation to work properly. for compilation to work properly.
upgrade %tree to "4.10.12.7" as: upgrade $tree to "4.10.12.7" as:
if (%tree.type == "FileChunks"): if ($tree.type == "FileChunks"):
%first_chunk = %tree.1 $first_chunk = $tree.1
%i = 1 $i = 1
%has_use = (no) $has_use = (no)
repeat while (%i <= (size of %first_chunk)): repeat while ($i <= (size of $first_chunk)):
if ((%first_chunk.%i.type == "Action") and (%first_chunk.%i.stub == "use")): if (($first_chunk.$i.type == "Action") and ($first_chunk.$i.stub == "use")):
%has_use = (yes) $has_use = (yes)
..else: ..else:
if %has_use: if $has_use:
go to (insert chunk) go to (insert chunk)
%i += 1 $i += 1
return return
--- (insert chunk) --- --- (insert chunk) ---
[%chunk1, %chunk2] = [..] [$chunk1, $chunk2] = [..]
SyntaxTree {type: "Block", source: %first_chunk.source} SyntaxTree {type: "Block", source: $first_chunk.source}
SyntaxTree {type: "Block", source: %first_chunk.source} SyntaxTree {type: "Block", source: $first_chunk.source}
for %j in 1 to (%i - 1): for $j in 1 to ($i - 1):
%chunk1.%j = %first_chunk.%j $chunk1.$j = $first_chunk.$j
for %j in %i to (size of %first_chunk): for $j in $i to (size of $first_chunk):
%chunk2.(%j - %i + 1) = %first_chunk.%j $chunk2.($j - $i + 1) = $first_chunk.$j
%new_tree = (..) $new_tree = (..)
SyntaxTree {source: %tree.source, type: "FileChunks", 1: %chunk1, 2: %chunk2} SyntaxTree {source: $tree.source, type: "FileChunks", 1: $chunk1, 2: $chunk2}
for %i in 2 to (size of %tree): for $i in 2 to (size of $tree):
%new_tree.(%i + 1) = %tree.%i $new_tree.($i + 1) = $tree.$i
return %new_tree return $new_tree

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <4.11 to Nomsu 4.11 This file defines upgrades from Nomsu <4.11 to Nomsu 4.11
(overhaul of function literals, deleting (if all of ...), etc. shorthand) (overhaul of function literals, deleting (if all of ...), etc. shorthand)
@ -9,87 +9,87 @@ use "compatibility/compatibility.nom"
# Overhaul of function literals: # Overhaul of function literals:
upgrade action "call 1 with" to "4.11" via (..) upgrade action "call 1 with" to "4.11" via (..)
for (%tree %end_version): for ($tree $end_version):
%tree2 = {type: "Action", source: %tree.source, 1: %tree.2} $tree2 = {type: "Action", source: $tree.source, 1: $tree.2}
for %arg in %tree.4 at %i: for $arg in $tree.4 at $i:
%tree2.(%i + 1) = %arg $tree2.($i + 1) = $arg
return (SyntaxTree %tree2) return (SyntaxTree $tree2)
upgrade action (-> %yield_value) to "4.11" as (yield %yield_value) upgrade action (-> $yield_value) to "4.11" as (yield $yield_value)
# Replace set {%x:1, %y:2} with [%x, %y] = [1, 2] # Replace set {%x:1, %y:2} with [%x, %y] = [1, 2]
upgrade action "set" to "4.11" via (..) upgrade action "set" to "4.11" via (..)
for (%tree %end_version): for ($tree $end_version):
[%lhs, %rhs] = [\[], \[]] [$lhs, $rhs] = [\[], \[]]
%lhs.source = %tree.(2).source $lhs.source = $tree.2.source
%rhs.source = %tree.(2).source $rhs.source = $tree.2.source
for %entry in %tree.2 at %i: for $entry in $tree.2 at $i:
%lhs.%i = %entry.1 $lhs.$i = $entry.1
%rhs.%i = %entry.2 $rhs.$i = $entry.2
return (SyntaxTree {type: "Action", source: %tree.source, 1: %lhs, 2: "=", 3: %rhs}) return (SyntaxTree {type: "Action", source: $tree.source, 1: $lhs, 2: "=", 3: $rhs})
upgrade action "1 with 2 ~>" to "4.11" via (..) upgrade action "1 with 2 ~>" to "4.11" via (..)
for %tree: for $tree:
compile error at %tree "This method has been deprecated." "\ compile error at $tree "This method has been deprecated." \
..Perhaps this could be use %tree::map instead." .."Perhaps this could be use %tree::map instead."
# Changing filesystem API: # Changing filesystem API:
upgrade action (for file %f in %path %body) to "4.11" as (..) upgrade action (for file $f in $path $body) to "4.11" as (..)
for %f in (files for %path) %body for $f in (files for $path) $body
upgrade action (%expr for file %f in %path) to "4.11" as [..] upgrade action ($expr for file $f in $path) to "4.11" as [..]
: for %f in (files for %path): add %expr : for $f in (files for $path): add $expr
upgrade action (line %n in %text) to "4.11" as (%text::line %n) upgrade action (line $n in $text) to "4.11" as ($text|line $n)
upgrade action (line number of %pos in %text) to "4.11" as (..) upgrade action (line number of $pos in $text) to "4.11" as (..)
%text::line number at %pos $text|line number at $pos
# Deduplicating goto labels: # Deduplicating goto labels:
upgrade action [=== %label ===, *** %label ***] to "4.11" as (--- %label ---) upgrade action [=== $label ===, *** $label ***] to "4.11" as (--- $label ---)
upgrade action [===stop %label ===, ***stop %label ***] to "4.11" as (..) upgrade action [===stop $label ===, ***stop $label ***] to "4.11" as (..)
---stop %label --- ---stop $label ---
upgrade action [===next %label ===, ***next %label ***] to "4.11" as (..) upgrade action [===next $label ===, ***next $label ***] to "4.11" as (..)
---next %label --- ---next $label ---
# Deprecating shorthand functions: # Deprecating shorthand functions:
upgrade action [if all of %items %body, if all of %items then %body] to "4.11" as (..) upgrade action [if all of $items $body, if all of $items then $body] to "4.11" as (..)
if (all of %items) %body if (all of $items) $body
upgrade action [unless all of %items %body, unless all of %items then %body] to \ upgrade action [unless all of $items $body, unless all of $items then $body] to \
.."4.11" as (if (not (all of %items)) %body) .."4.11" as (if (not (all of $items)) $body)
upgrade action [if any of %items %body, if any of %items then %body] to "4.11" as (..) upgrade action [if any of $items $body, if any of $items then $body] to "4.11" as (..)
if (any of %items) %body if (any of $items) $body
upgrade action [unless any of %items %body, unless any of %items then %body] to \ upgrade action [unless any of $items $body, unless any of $items then $body] to \
.."4.11" as (if (not (any of %items)) %body) .."4.11" as (if (not (any of $items)) $body)
upgrade action [if none of %items %body, if none of %items then %body] to "4.11" \ upgrade action [if none of $items $body, if none of $items then $body] to "4.11" \
..as (if (not (any of %items)) %body) ..as (if (not (any of $items)) $body)
upgrade action [unless none of %items %body, unless none of %items then %body] to \ upgrade action [unless none of $items $body, unless none of $items then $body] to \
.."4.11" as (if (any of %items) %body) .."4.11" as (if (any of $items) $body)
upgrade action [..] upgrade action [..]
if all of %items %body else %else, if all of %items then %body else %else if all of $items $body else $else, if all of $items then $body else $else
..to "4.11" as (if (all of %items) %body else %else) ..to "4.11" as (if (all of $items) $body else $else)
upgrade action [..] upgrade action [..]
unless all of %items %body else %else, unless all of %items then %body else %else unless all of $items $body else $else, unless all of $items then $body else $else
..to "4.11" as (if (not (all of %items)) %body else %else) ..to "4.11" as (if (not (all of $items)) $body else $else)
upgrade action [..] upgrade action [..]
if any of %items %body else %else, if any of %items then %body else %else if any of $items $body else $else, if any of $items then $body else $else
..to "4.11" as (if (any of %items) %body else %else) ..to "4.11" as (if (any of $items) $body else $else)
upgrade action [..] upgrade action [..]
unless any of %items %body else %else, unless any of %items then %body else %else unless any of $items $body else $else, unless any of $items then $body else $else
..to "4.11" as (if (not (any of %items)) %body else %else) ..to "4.11" as (if (not (any of $items)) $body else $else)
upgrade action [..] upgrade action [..]
if none of %items %body else %else, if none of %items then %body else %else if none of $items $body else $else, if none of $items then $body else $else
..to "4.11" as (if (not (any of %items)) %body else %else) ..to "4.11" as (if (not (any of $items)) $body else $else)
upgrade action [..] upgrade action [..]
unless none of %items %body else %else, unless none of %items then %body else %else unless none of $items $body else $else, unless none of $items then $body else $else
..to "4.11" as (if (any of %items) %body else %else) ..to "4.11" as (if (any of $items) $body else $else)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <4.11 to Nomsu 4.11 This file defines upgrades from Nomsu <4.11 to Nomsu 4.11
(overhaul of function literals, deleting (if all of ...), etc. shorthand) (overhaul of function literals, deleting (if all of ...), etc. shorthand)
@ -8,11 +8,11 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action "do next repeat" to "4.12" via (..) upgrade action "do next repeat" to "4.12" via (..)
for %tree: for $tree:
compile error at %tree "This method has been deprecated." "\ compile error at $tree "This method has been deprecated." \
..Use either (do next) or (go to (label)) instead." .."Use either (do next) or (go to (label)) instead."
upgrade action "stop repeating" to "4.12" via (..) upgrade action "stop repeating" to "4.12" via (..)
for %tree: for $tree:
compile error at %tree "This method has been deprecated." "\ compile error at $tree "This method has been deprecated." \
..Use either (stop) or (go to (label)) instead." .."Use either (stop) or (go to (label)) instead."

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <4.8.10 to 4.8.10 (renaming "action" -> "means") This file defines upgrades from Nomsu <4.8.10 to 4.8.10 (renaming "action" -> "means")
use "compatibility/compatibility.nom" use "compatibility/compatibility.nom"
@ -6,63 +6,63 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action "local action" to "4.8.10" via (..) upgrade action "local action" to "4.8.10" via (..)
for (%tree %end_version): for ($tree $end_version):
%spec = %tree.3 $spec = $tree.3
%body = %tree.4 $body = $tree.4
if %spec.type is: if $spec.type is:
"List": "List":
if ((size of %spec) == 1): if ((size of $spec) == 1):
return \(%spec.1 means %body) return \($spec.1 means $body)
..else: ..else:
return \(%spec all mean %body) return \($spec all mean $body)
else: else:
return \(%spec means %body) return \($spec means $body)
upgrade action "action" to "4.8.10" via (..) upgrade action "action" to "4.8.10" via (..)
for (%tree %end_version): for ($tree $end_version):
%spec = %tree.2 $spec = $tree.2
%body = %tree.3 $body = $tree.3
if %body: if $body:
if %spec.type is: if $spec.type is:
"List": "List":
if ((size of %spec) == 1): if ((size of $spec) == 1):
return \(externally %spec.1 means %body) return \(externally $spec.1 means $body)
..else: ..else:
return \(externally %spec all mean %body) return \(externally $spec all mean $body)
else: else:
return \(externally %spec means %body) return \(externally $spec means $body)
..else: ..else:
return \(%spec's meaning) return \($spec's meaning)
upgrade action "compile 1 to" to "4.8.10" via (..) upgrade action "compile 1 to" to "4.8.10" via (..)
for (%tree %end_version): for ($tree $end_version):
%spec = %tree.2 $spec = $tree.2
%body = %tree.4 $body = $tree.4
if %spec.type is: if $spec.type is:
"List": "List":
if ((size of %spec) == 1): if ((size of $spec) == 1):
return \(%spec.1 compiles to %body) return \($spec.1 compiles to $body)
..else: ..else:
return \(%spec all compile to %body) return \($spec all compile to $body)
else: else:
return \(%spec compiles to %body) return \($spec compiles to $body)
upgrade action "parse 1 as" to "4.8.10" via (..) upgrade action "parse 1 as" to "4.8.10" via (..)
for (%tree %end_version): for ($tree $end_version):
%spec = %tree.2 $spec = $tree.2
%body = %tree.4 $body = $tree.4
if %spec.type is: if $spec.type is:
"List": "List":
if ((size of %spec) == 1): if ((size of $spec) == 1):
return \(%spec.1 parses as %body) return \($spec.1 parses as $body)
..else: ..else:
return \(%spec all parse as %body) return \($spec all parse as $body)
else: else:
return \(%spec parse as %body) return \($spec parse as $body)
upgrade action (compile as %) to "4.8.10" as (what % compiles to) upgrade action (compile as $) to "4.8.10" as (what $ compiles to)
upgrade action (remove action %) to "4.8.10" as ((%'s meaning) = (nil)) upgrade action (remove action $) to "4.8.10" as (($'s meaning) = (nil))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines upgrades from Nomsu <4.9 to 4.9 This file defines upgrades from Nomsu <4.9 to 4.9
use "compatibility/compatibility.nom" use "compatibility/compatibility.nom"
@ -6,6 +6,6 @@ use "compatibility/compatibility.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
upgrade action "if" to "4.9" via (..) upgrade action "if" to "4.9" via (..)
for (%tree %end_version): for ($tree $end_version):
if ((size of %tree) > 2): return %tree if ((size of $tree) > 2): return $tree
return \(when %tree.2) return \(when $tree.2)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains code for defining ways to upgrade code between different versions This file contains code for defining ways to upgrade code between different versions
of Nomsu. of Nomsu.
@ -7,114 +7,114 @@ use "lib/os.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%UPGRADES = {} $UPGRADES = {}
externally (upgrade to %version via %upgrade_fn) means: externally (upgrade to $version via $upgrade_fn) means:
%UPGRADES.%version = %upgrade_fn $UPGRADES.$version = $upgrade_fn
%ACTION_UPGRADES = ({} with fallback % -> {}) $ACTION_UPGRADES = ({} with fallback $ -> {})
externally (upgrade action %stub to %version via %upgrade_fn) means: externally (upgrade action $stub to $version via $upgrade_fn) means:
%ACTION_UPGRADES.%version.%stub = %upgrade_fn $ACTION_UPGRADES.$version.$stub = $upgrade_fn
(upgrade %tree to %version as %body) parses as (..) (upgrade $tree to $version as $body) parses as (..)
upgrade to %version via ((% %end_version) -> (% with %tree -> %body)) upgrade to $version via (($ $end_version) -> ($ with $tree -> $body))
(upgrade action %actions to %version as %body) compiles to: (upgrade action $actions to $version as $body) compiles to:
if (%actions is "Action" syntax tree): if ($actions is "Action" syntax tree):
%actions = \[%actions] $actions = \[$actions]
%lua = (Lua "") $lua = (Lua "")
for %action in %actions: for $action in $actions:
%replacements = {} $replacements = {}
for %i in 1 to (size of %action): for $i in 1 to (size of $action):
if (%action.%i is "Var" syntax tree): if ($action.$i is "Var" syntax tree):
%replacements.(%action.%i.1) = "\(\%tree as lua id)[\%i]" $replacements.($action.$i.1) = "\(\$tree as lua id)[\$i]"
define mangler define mangler
(make tree %t) means: (make tree $t) means:
when: when:
(%t is "Var" syntax tree): ($t is "Var" syntax tree):
if %replacements.(%t.1): if $replacements.($t.1):
return %replacements.(%t.1) return $replacements.($t.1)
..else: ..else:
external %needs_mangle = (yes) external $needs_mangle = (yes)
return "SyntaxTree{type=\(quote %t.type), source=\(quote "\(%t.source)"), \(quote (mangle %t.1))}" return "SyntaxTree{type=\(quote $t.type), source=\(quote "\($t.source)"), \(quote (mangle $t.1))}"
(%t is syntax tree): ($t is syntax tree):
%args = [] $args = []
for %k = %v in %t: for $k = $v in $t:
if ((type of %k) == "number"): if ((type of $k) == "number"):
%args::add (make tree %v) $args|add (make tree $v)
..else: ..else:
%args::add "\(%k)=\(make tree %v)" $args|add "\($k)=\(make tree $v)"
return "SyntaxTree{\(%args::joined with ", ")}" return "SyntaxTree{\($args|joined with ", ")}"
else: else:
return (quote %t) return (quote $t)
unless ("\%lua" == ""): unless ("\$lua" == ""):
%lua::add "\n" $lua|add "\n"
%retval = (make tree %body) $retval = (make tree $body)
%lua::add (..) $lua|add (..)
Lua "\ Lua "
..upgrade_action_1_to_2_via(\(quote %action.stub), \(%version as lua expr), function(\(\%tree as lua id)) upgrade_action_1_to_2_via(\(quote $action.stub), \($version as lua expr), function(\(\$tree as lua id))
return \%retval return \$retval
end)" end)"
return %lua return $lua
externally [..] externally [..]
%tree upgraded from %start_version to %end_version $tree upgraded from $start_version to $end_version
%tree upgraded to %end_version from %start_version $tree upgraded to $end_version from $start_version
..all mean: ..all mean:
unless (%tree is syntax tree): return %tree unless ($tree is syntax tree): return $tree
(%ver as list) means ((% as number) for % in %ver matching "[0-9]+") ($ver as list) means (($ as number) for $ in $ver matching "[0-9]+")
%versions = {} $versions = {}
for %v = % in %UPGRADES: for $v = $ in $UPGRADES:
%versions.%v = (yes) $versions.$v = (yes)
for %v = % in %ACTION_UPGRADES: for $v = $ in $ACTION_UPGRADES:
%versions.%v = (yes) $versions.$v = (yes)
%versions = ((keys in %versions) sorted by % -> (% as list)) $versions = ((keys in $versions) sorted by $ -> ($ as list))
for %ver in %versions: for $ver in $versions:
if ((%ver as list) <= (%start_version as list)): do next %ver if (($ver as list) <= ($start_version as list)): do next $ver
if ((%ver as list) > (%end_version as list)): stop %ver if (($ver as list) > ($end_version as list)): stop $ver
if %ACTION_UPGRADES.%ver: if $ACTION_UPGRADES.$ver:
%tree = (..) $tree = (..)
%tree with % ->: $tree with $ ->:
if ((% is "Action" syntax tree) and %ACTION_UPGRADES.%ver.(%.stub)): if (($ is "Action" syntax tree) and $ACTION_UPGRADES.$ver.($.stub)):
%with_upgraded_args = {..} $with_upgraded_args = {..}
: for %k = %v in %: add %k = (%v upgraded from %start_version to %end_version) : for $k = $v in $: add $k = ($v upgraded from $start_version to $end_version)
set %with_upgraded_args's metatable to (%'s metatable) set $with_upgraded_args's metatable to ($'s metatable)
return (%ACTION_UPGRADES.%ver.(%.stub) %with_upgraded_args %end_version) return ($ACTION_UPGRADES.$ver.($.stub) $with_upgraded_args $end_version)
if %UPGRADES.%ver: if $UPGRADES.$ver:
%with_upgraded_args = {..} $with_upgraded_args = {..}
: :
for %k = %v in %tree: for $k = $v in $tree:
add %k = (%v upgraded from %start_version to %end_version) add $k = ($v upgraded from $start_version to $end_version)
set %with_upgraded_args's metatable to (%tree's metatable) set $with_upgraded_args's metatable to ($tree's metatable)
%tree = (%UPGRADES.%ver %with_upgraded_args %end_version) $tree = ($UPGRADES.$ver $with_upgraded_args $end_version)
if (%tree.version != %end_version): if ($tree.version != $end_version):
%tree = (SyntaxTree {: for %k = %v in %tree: add %k = %v}) $tree = (SyntaxTree {: for $k = $v in $tree: add $k = $v})
%tree.version = %end_version $tree.version = $end_version
if %tree.shebang: if $tree.shebang:
%tree.shebang = "#!/usr/bin/env nomsu -V\%end_version\n" $tree.shebang = "#!/usr/bin/env nomsu -V\$end_version\n"
return %tree return $tree
externally (%tree upgraded from %start_version) means (..) externally ($tree upgraded from $start_version) means (..)
%tree upgraded from %start_version to (Nomsu version) $tree upgraded from $start_version to (Nomsu version)
externally (%tree upgraded to %end_version) means (..) externally ($tree upgraded to $end_version) means (..)
%tree upgraded from (%tree.version or (Nomsu version)) to %end_version $tree upgraded from ($tree.version or (Nomsu version)) to $end_version
externally (%tree upgraded) means (..) externally ($tree upgraded) means (..)
%tree upgraded from (%tree.version or (Nomsu version)) to (Nomsu version) $tree upgraded from ($tree.version or (Nomsu version)) to (Nomsu version)
externally (use %path from version %version) means: externally (use $path from version $version) means:
for %filename in (files for %path): for $filename in (files for $path):
if (=lua "LOADED[\%filename]"): if (=lua "LOADED[\$filename]"):
do next %filename do next $filename
%file = (read file %filename) $file = (read file $filename)
%tree = (parse %file from %filename) $tree = (parse $file from $filename)
%tree = (upgrade %tree from %version) $tree = (upgrade $tree from $version)
run tree %tree run tree $tree

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains code that supports manipulating and using collections like lists This file contains code that supports manipulating and using collections like lists
and dictionaries. and dictionaries.
@ -11,34 +11,34 @@ use "core/operators.nom"
# List functionality: # List functionality:
test: test:
%list = [1, 2, 3, 4, 5] $list = [1, 2, 3, 4, 5]
%visited = {} $visited = {}
for %i = %x in %list: for $i = $x in $list:
%visited.%i = (yes) $visited.$i = (yes)
assume (%visited == {1, 2, 3, 4, 5}) assume ($visited == {1, 2, 3, 4, 5})
%visited = {} $visited = {}
for %x in %list: for $x in $list:
%visited.%x = (yes) $visited.$x = (yes)
assume (%visited == {1, 2, 3, 4, 5}) assume ($visited == {1, 2, 3, 4, 5})
assume ((%list::2 nd to last) == 4) assume (($list|2 nd to last) == 4)
assume ((%list::first) == 1) assume (($list|first) == 1)
assume (%list::has 3) assume ($list|has 3)
assume ((%list::index of 3) == 3) assume (($list|index of 3) == 3)
assume ((size of %list) == 5) assume ((size of $list) == 5)
%list::add 6 $list|add 6
assume ((%list::last) == 6) assume (($list|last) == 6)
%list::pop $list|pop
assume ((%list::last) == 5) assume (($list|last) == 5)
%list::remove index 1 $list|remove index 1
assume ((%list::first) == 2) assume (($list|first) == 2)
assume (([1, 2] + [3, 4]) == [1, 2, 3, 4]) assume (([1, 2] + [3, 4]) == [1, 2, 3, 4])
# Dict functionality # Dict functionality
test: test:
%dict = {x: 1, y: 2, z: 3} $dict = {x: 1, y: 2, z: 3}
assume (size of %dict) == 3 assume (size of $dict) == 3
assume [: for % in {x: 1}: add %] == [{key: "x", value: 1}] assume [: for $ in {x: 1}: add $] == [{key: "x", value: 1}]
assume [: for %k = %v in {x: 1}: add {key: %k, value: %v}] == [..] assume [: for $k = $v in {x: 1}: add {key: $k, value: $v}] == [..]
{key: "x", value: 1} {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: 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}) == {x: 1, y: 1, z: 10}
@ -48,93 +48,93 @@ test:
test: test:
assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4]) assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4])
externally (%lists flattened) means: externally ($lists flattened) means:
%flat = [] $flat = []
for %item in recursive %lists: for $item in recursive $lists:
if (%item is a "List"): if ($item is a "List"):
for % in %item: for $ in $item:
recurse %item on % recurse $item on $
..else: ..else:
%flat::add %item $flat|add $item
return %flat return $flat
test: 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: 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] [keys in $dict, keys of $dict] all parse as [: for $k = $v in $dict: add $k]
test: 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] [values in $dict, values of $dict] all parse as [: for $k = $v in $dict: add $v]
# Metatable stuff # Metatable stuff
test: test:
%t = {} $t = {}
set %t's metatable to {__tostring: % -> "XXX"} set $t's metatable to {__tostring: $ -> "XXX"}
assume ("\%t" == "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));" .."setmetatable(\($dict as lua expr), \($metatable as lua expr));"
[%'s metatable, %'metatable] all compile to "getmetatable(\(% as lua expr))" [$'s metatable, $'metatable] all compile to "getmetatable(\($ as lua expr))"
test: test:
assume (({} with fallback % -> (% + 1)).10 == 11) assume (({} with fallback $ -> ($ + 1)).10 == 11)
(%dict with fallback %key -> %value) compiles to "\ ($dict with fallback $key -> $value) compiles to "
..(function(d) (function(d)
local mt = {} local mt = {}
for k,v in pairs(getmetatable(d) or {}) do mt[k] = v end for k,v in pairs(getmetatable(d) or {}) do mt[k] = v end
mt.__index = function(self, \(%key as lua expr)) mt.__index = function(self, \($key as lua expr))
local value = \(%value as lua expr) local value = \($value as lua expr)
self[\(%key as lua expr)] = value self[\($key as lua expr)] = value
return value return value
end end
return setmetatable(d, mt) return setmetatable(d, mt)
end)(\(%dict as lua expr))" end)(\($dict as lua expr))"
# Sorting # Sorting
test: test:
%x = [3, 1, 2] $x = [3, 1, 2]
sort %x sort $x
assume (%x == [1, 2, 3]) assume ($x == [1, 2, 3])
sort %x by % = (- %) sort $x by $ = (- $)
assume (%x == [3, 2, 1]) assume ($x == [3, 2, 1])
%keys = {1: 999, 2: 0, 3: 50} $keys = {1: 999, 2: 0, 3: 50}
sort %x by % = %keys.% sort $x by $ = $keys.$
assume (%x == [2, 3, 1]) assume ($x == [2, 3, 1])
(sort %items) compiles to "table.sort(\(%items as lua expr));" (sort $items) compiles to "table.sort(\($items as lua expr));"
[sort %items by %item = %key_expr, sort %items by %item -> %key_expr] \ [sort $items by $item = $key_expr, sort $items by $item -> $key_expr] \
..all parse as (..) ..all parse as (..)
do: do:
%keys = ({} with fallback %item -> %key_expr) $keys = ({} with fallback $item -> $key_expr)
lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)" lua> "table.sort(\$items, function(x,y) return \$keys[x] < \$keys[y] end)"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
assume ((sorted [3, 1, 2]) == [1, 2, 3]) assume ((sorted [3, 1, 2]) == [1, 2, 3])
externally [%items sorted, sorted %items] all mean: externally [$items sorted, sorted $items] all mean:
%copy = [: for % in %items: add %] $copy = [: for $ in $items: add $]
sort %copy sort $copy
return %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: result of:
%copy = [: for % in %items: add %] $copy = [: for $ in $items: add $]
sort %copy by %item = %key sort $copy by $item = $key
return %copy return $copy
test: test:
assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3]) assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3])
externally (unique %items) means: externally (unique $items) means:
%unique = [] $unique = []
%seen = {} $seen = {}
for % in %items: for $ in $items:
unless %seen.%: unless $seen.$:
%unique::add % $unique|add $
%seen.% = (yes) $seen.$ = (yes)
return %unique return $unique

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains compile-time actions that define basic control flow structures This file contains compile-time actions that define basic control flow structures
like "if" statements and loops. like "if" statements and loops.
@ -19,22 +19,22 @@ test:
if (no): if (no):
barf "conditional fail" barf "conditional fail"
(if %condition %if_body) compiles to "\ (if $condition $if_body) compiles to "
..if \(%condition as lua expr) then if \($condition as lua expr) then
\(%if_body as lua) \($if_body as lua)
end" end"
test: test:
unless (yes): unless (yes):
barf "conditional fail" barf "conditional fail"
(unless %condition %unless_body) parses as (if (not %condition) %unless_body) (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] \ [if $condition $if_body else $else_body, unless $condition $else_body else $if_body] \
..all compile to "\ ..all compile to "
..if \(%condition as lua expr) then if \($condition as lua expr) then
\(%if_body as lua) \($if_body as lua)
else else
\(%else_body as lua) \($else_body as lua)
end" end"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -47,26 +47,26 @@ test:
assume ((1 if (no) else 2) == 2) assume ((1 if (no) else 2) == 2)
[..] [..]
%when_true_expr if %condition else %when_false_expr $when_true_expr if $condition else $when_false_expr
%when_true_expr if %condition otherwise %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 else $when_true_expr
%when_false_expr unless %condition then %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 # 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) equivalent of a conditional expression: (cond and if_true or if_false)
if {Text, List, Dict, Number}.(%when_true_expr.type): 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: ..else:
# Otherwise, need to do an anonymous inline function (yuck, too bad lua # Otherwise, need to do an anonymous inline function (yuck, too bad lua
doesn't have a proper ternary operator!) doesn't have a proper ternary operator!)
To see why this is necessary consider: (random()<.5 and false or 99) To see why this is necessary consider: (random()<.5 and false or 99)
return (..) return (..)
Lua "\ Lua "
..((function() ((function()
if \(%condition as lua expr) then if \($condition as lua expr) then
return \(%when_true_expr as lua expr) return \($when_true_expr as lua expr)
else else
return \(%when_false_expr as lua expr) return \($when_false_expr as lua expr)
end end
end)())" end)())"
@ -74,212 +74,212 @@ test:
# GOTOs # GOTOs
test: test:
%i = 0 $i = 0
--- %loop --- --- $loop ---
%i += 1 $i += 1
unless (%i == 10): unless ($i == 10):
go to %loop go to $loop
assume (%i == 10) assume ($i == 10)
--- (Loop) --- --- (Loop) ---
%i -= 1 $i -= 1
unless (%i == 0): unless ($i == 0):
go to (Loop) go to (Loop)
assume (%i == 0) assume ($i == 0)
(--- %label ---) compiles to "\ (--- $label ---) compiles to "
..::label_\(..) ::label_\(..)
(%label.stub::as lua id) if (%label.type == "Action") else (..) ($label.stub|as lua id) if ($label.type == "Action") else (..)
%label as lua identifier $label as lua identifier
..::" ..::"
(go to %label) compiles to "\ (go to $label) compiles to "
..goto label_\(..) goto label_\(..)
(%label.stub::as lua id) if (%label.type == "Action") else (..) ($label.stub|as lua id) if ($label.type == "Action") else (..)
%label as lua identifier $label as lua identifier
.." .."
# Basic loop control # Basic loop control
(stop %var) compiles to: (stop $var) compiles to:
if %var: if $var:
return (Lua "goto stop_\(%var as lua identifier)") return (Lua "goto stop_\($var as lua identifier)")
..else: ..else:
return (Lua "break") return (Lua "break")
(do next %var) compiles to: (do next $var) compiles to:
if %var: if $var:
return (Lua "goto continue_\(%var as lua identifier)") return (Lua "goto continue_\($var as lua identifier)")
..else: ..else:
return (Lua "goto continue") return (Lua "goto continue")
(---stop %var ---) compiles to "::stop_\(%var as lua identifier)::" (---stop $var ---) compiles to "::stop_\($var as lua identifier)::"
(---next %var ---) compiles to "::continue_\(%var as lua identifier)::" (---next $var ---) compiles to "::continue_\($var as lua identifier)::"
# While loops # While loops
test: test:
%x = 0 $x = 0
repeat while (%x < 10): %x += 1 repeat while ($x < 10): $x += 1
assume (%x == 10) assume ($x == 10)
repeat while (%x < 20): stop repeat while ($x < 20): stop
assume (%x == 10) assume ($x == 10)
repeat while (%x < 20): repeat while ($x < 20):
%x += 1 $x += 1
if (yes): if (yes):
do next do next
barf "Failed to 'do next'" barf "Failed to 'do next'"
assume (%x == 20) assume ($x == 20)
(repeat while %condition %body) compiles to: (repeat while $condition $body) compiles to:
%lua = (Lua "while \(%condition as lua expr) do\n \(%body as lua)") $lua = (Lua "while \($condition as lua expr) do\n \($body as lua)")
if (%body has subtree \(do next)): if ($body has subtree \(do next)):
%lua::add "\n ::continue::" $lua|add "\n ::continue::"
%lua::add "\nend --while-loop" $lua|add "\nend --while-loop"
return %lua return $lua
(repeat %body) parses as (repeat while (yes) %body) (repeat $body) parses as (repeat while (yes) $body)
(repeat until %condition %body) parses as (repeat while (not %condition) %body) (repeat until $condition $body) parses as (repeat while (not $condition) $body)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
%nums = [] $nums = []
for %x in 1 to 5: for $x in 1 to 5:
%nums::add %x $nums|add $x
assume (%nums == [1, 2, 3, 4, 5]) assume ($nums == [1, 2, 3, 4, 5])
%nums = [] $nums = []
for %x in 1 to 5 via 2: for $x in 1 to 5 via 2:
%nums::add %x $nums|add $x
assume (%nums == [1, 3, 5]) assume ($nums == [1, 3, 5])
%nums = [] $nums = []
for %outer in 1 to 100: for $outer in 1 to 100:
for %inner in %outer to (%outer + 2): for $inner in $outer to ($outer + 2):
if (%inner == 2): if ($inner == 2):
%nums::add -2 $nums|add -2
do next %inner do next $inner
%nums::add %inner $nums|add $inner
if (%inner == 5): if ($inner == 5):
stop %outer stop $outer
assume (%nums == [1, -2, 3, -2, 3, 4, 3, 4, 5]) assume ($nums == [1, -2, 3, -2, 3, 4, 3, 4, 5])
# Numeric range for loops # Numeric range for loops
[..] [..]
for %var in %start to %stop by %step %body for $var in $start to $stop by $step $body
for %var in %start to %stop via %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 # 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 = (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|add "\n " ($body as lua)
if (%body has subtree \(do next)): if ($body has subtree \(do next)):
%lua::add "\n ::continue::" $lua|add "\n ::continue::"
if (%body has subtree \(do next %var)): 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)): if ($body has subtree \(stop $var)):
%lua = (..) $lua = (..)
Lua "\ Lua "
..do -- scope for (stop \(%var as lua identifier)) do -- scope for (stop \($var as lua identifier))
\%lua \$lua
\(\(---stop %var ---) as lua) \(\(---stop $var ---) as lua)
end -- scope for (stop \(%var as lua identifier))" end -- scope for (stop \($var as lua identifier))"
return %lua 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 for $var in $start to $stop via 1 $body
test: test:
%x = 0 $x = 0
repeat 5 times: repeat 5 times:
%x += 1 $x += 1
assume %x == 5 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 $body)
test: test:
%a = [10, 20, 30, 40, 50] $a = [10, 20, 30, 40, 50]
%b = [] $b = []
for %x in %a: for $x in $a:
%b::add %x $b|add $x
assume (%a == %b) assume ($a == $b)
%b = [] $b = []
for %x in %a: for $x in $a:
if (%x == 10): if ($x == 10):
do next %x do next $x
if (%x == 50): if ($x == 50):
stop %x stop $x
%b::add %x $b|add $x
assume (%b == [20, 30, 40]) assume ($b == [20, 30, 40])
# For-each loop (lua's "ipairs()") # For-each loop (lua's "ipairs()")
(for %var in %iterable at %i %body) compiles to: (for $var in $iterable at $i $body) compiles to:
# This uses Lua's approach of only allowing loop-scoped variables in a loop # 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 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)): if ($body has subtree \(do next)):
%lua::add "\n ::continue::" $lua|add "\n ::continue::"
if (%body has subtree \(do next %var)): 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)): if ($body has subtree \(stop $var)):
%inner_lua = %lua $inner_lua = $lua
%lua = (Lua "do -- scope for stopping for-loop\n ") $lua = (Lua "do -- scope for stopping for-loop\n ")
%lua::add %inner_lua "\n " $lua|add $inner_lua "\n "
%lua::add (\(---stop %var ---) as lua) $lua|add (\(---stop $var ---) as lua)
%lua::add "\nend -- end of scope for stopping for-loop" $lua|add "\nend -- end of scope for stopping for-loop"
return %lua return $lua
(for %var in %iterable %body) parses as (..) (for $var in $iterable $body) parses as (..)
for %var in %iterable at (=lua "__") %body for $var in $iterable at (=lua "__") $body
test: test:
%d = {a: 10, b: 20, c: 30, d: 40, e: 50} $d = {a: 10, b: 20, c: 30, d: 40, e: 50}
%result = [] $result = []
for %k = %v in %d: for $k = $v in $d:
if (%k == "a"): if ($k == "a"):
do next %k do next $k
if (%v == 20): if ($v == 20):
do next %v do next $v
%result::add "\%k = \%v" $result|add "\$k = \$v"
assume ((%result sorted) == ["c = 30", "d = 40", "e = 50"]) assume (($result sorted) == ["c = 30", "d = 40", "e = 50"])
# Dict iteration (lua's "pairs()") # 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: ..all compile to:
%lua = (Lua "for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do") $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|add "\n " ($body as lua)
if (%body has subtree \(do next)): if ($body has subtree \(do next)):
%lua::add "\n ::continue::" $lua|add "\n ::continue::"
if (%body has subtree \(do next %key)): 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)): 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 "") $stop_labels = (Lua "")
if (%body has subtree \(stop %key)): 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)): 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): if ((size of "\$stop_labels") > 0):
%inner_lua = %lua $inner_lua = $lua
%lua = (Lua "do -- scope for stopping for % = % loop\n ") $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 return $lua
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -287,7 +287,7 @@ test:
when: when:
(1 == 2) (100 < 0): (1 == 2) (100 < 0):
barf "bad conditional" barf "bad conditional"
(1 == 0) (1 == 1) %not_a_variable.x: do nothing (1 == 0) (1 == 1) $not_a_variable.x: do nothing
(1 == 1): (1 == 1):
barf "bad conditional" barf "bad conditional"
@ -298,52 +298,51 @@ test:
barf "bad conditional" barf "bad conditional"
# Multi-branch conditional (if..elseif..else) # Multi-branch conditional (if..elseif..else)
(when %body) compiles to: (when $body) compiles to:
%code = (Lua "") $code = (Lua "")
%clause = "if" $clause = "if"
%else_allowed = (yes) $else_allowed = (yes)
unless (%body.type is "Block"): 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'?" .."Perhaps you forgot to put a ':' after 'if'?"
for %line in %body: for $line in $body:
unless (..) unless (..)
((%line.type is "Action") and ((size of %line) >= 2)) and (..) (($line.type is "Action") and ((size of $line) >= 2)) and (..)
%line.(size of %line) is "Block" syntax tree $line.(size of $line) is "Block" syntax tree
..: ..:
compile error at %line "Invalid line for the body of an 'if' 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 \ Each line should contain one or more conditional expressions followed by a block, or "else" followed \
..by a block." ..by a block."
%action = %line.(size of %line) $action = $line.(size of $line)
if ((%line.1 is "else") and ((size of %line) == 2)): if (($line.1 is "else") and ((size of $line) == 2)):
unless %else_allowed: 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." .."Merge all of the 'else' blocks together."
unless ((size of "\%code") > 0): unless ((size of "\$code") > 0):
compile error at %line "\ compile error at $line \
..You can't have an 'else' block without a preceding condition" .."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. \
..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." ..Otherwise, make sure the 'else' block comes last."
%code::add "\nelse\n " (%action as lua) $code|add "\nelse\n " ($action as lua)
%else_allowed = (no) $else_allowed = (no)
..else: ..else:
%code::add %clause " " $code|add $clause " "
for %i in 1 to ((size of %line) - 1): for $i in 1 to ((size of $line) - 1):
if (%i > 1): if ($i > 1):
%code::add " or " $code|add " or "
%code::add (%line.%i as lua expr) $code|add ($line.$i as lua expr)
%code::add " then\n " (%action as lua) $code|add " then\n " ($action as lua)
%clause = "\nelseif" $clause = "\nelseif"
if ((size of "\%code") == 0): 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." .."This means nothing would happen, so the 'if' block should be deleted."
%code::add "\nend --when" $code|add "\nend --when"
return %code return $code
test: test:
if 5 is: if 5 is:
@ -360,81 +359,80 @@ test:
barf "bad switch statement" barf "bad switch statement"
# Switch statement # Switch statement
[if %branch_value is %body, when %branch_value is %body] all compile to: [if $branch_value is $body, when $branch_value is $body] all compile to:
%code = (Lua "") $code = (Lua "")
%clause = "if" $clause = "if"
%else_allowed = (yes) $else_allowed = (yes)
define mangler define mangler
unless (%body.type is "Block"): 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'?" .."Perhaps you forgot to put a ':' after the 'is'?"
for %line in %body: for $line in $body:
unless (..) unless (..)
((%line.type is "Action") and ((size of %line) >= 2)) and (..) (($line.type is "Action") and ((size of $line) >= 2)) and (..)
%line.(size of %line) is "Block" syntax tree $line.(size of $line) is "Block" syntax tree
..: ..:
compile error at %line "Invalid line for 'if' 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" Each line should contain expressions followed by a block, or "else" followed by a block"
%action = %line.(size of %line) $action = $line.(size of $line)
if ((%line.1 is "else") and ((size of %line) == 2)): if (($line.1 is "else") and ((size of $line) == 2)):
unless %else_allowed: 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." .."Merge all of the 'else' blocks together."
unless ((size of "\%code") > 0): unless ((size of "\$code") > 0):
compile error at %line "\ compile error at $line \
..You can't have an 'else' block without a preceding condition" .."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. \
..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." ..Otherwise, make sure the 'else' block comes last."
%code::add "\nelse\n " (%action as lua) $code|add "\nelse\n " ($action as lua)
%else_allowed = (no) $else_allowed = (no)
..else: ..else:
%code::add %clause " " $code|add $clause " "
for %i in 1 to ((size of %line) - 1): for $i in 1 to ((size of $line) - 1):
if (%i > 1): if ($i > 1):
%code::add " or " $code|add " or "
%code::add "\(mangle "branch value") == " (%line.%i as lua expr) $code|add "\(mangle "branch value") == " ($line.$i as lua expr)
%code::add " then\n " (%action as lua) $code|add " then\n " ($action as lua)
%clause = "\nelseif" $clause = "\nelseif"
if ((size of "\%code") == 0): 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." .."This means nothing would happen, so the 'if' block should be deleted."
%code::add "\nend --when" $code|add "\nend --when"
return (..) return (..)
Lua "\ Lua "
..do --if % is... do --if % is...
local \(mangle "branch value") = \(%branch_value as lua expr) local \(mangle "branch value") = \($branch_value as lua expr)
\%code \$code
end -- if % is..." end -- if % is..."
# Do/finally # Do/finally
(do %action) compiles to "do\n \(%action as lua)\nend -- do" (do $action) compiles to "do\n \($action as lua)\nend -- do"
test: test:
%d = {} $d = {}
try: try:
do: do:
%d.x = "bad" $d.x = "bad"
barf barf
..then always: ..then always:
%d.x = "good" $d.x = "good"
assume (%d.x == "good") assume ($d.x == "good")
(do %action then always %final_action) compiles to: (do $action then always $final_action) compiles to:
define mangler define mangler
return (..) return (..)
Lua "\ Lua "
..do do
local \(mangle "fell_through") = false local \(mangle "fell_through") = false
local \(mangle "ok"), \(mangle "ret") = pcall(function() local \(mangle "ok"), \(mangle "ret") = pcall(function()
\(%action as lua) \($action as lua)
\(mangle "fell_through") = true \(mangle "fell_through") = true
end) end)
\(%final_action as lua) \($final_action as lua)
if not \(mangle "ok") then error(ret, 0) end if not \(mangle "ok") then error(ret, 0) end
if not \(mangle "fell_through") then return ret end if not \(mangle "fell_through") then return ret end
end" end"
@ -443,41 +441,41 @@ test:
assume ((result of: return 99) == 99) assume ((result of: return 99) == 99)
# Inline thunk: # Inline thunk:
(result of %body) compiles to "\(\(-> %body) as lua)()" (result of $body) compiles to "\(\(-> $body) as lua)()"
test: test:
%t = [1, [2, [[3], 4], 5, [[[6]]]]] $t = [1, [2, [[3], 4], 5, [[[6]]]]]
%flat = [] $flat = []
for % in recursive %t: for $ in recursive $t:
if ((lua type of %) is "table"): if ((lua type of $) is "table"):
for %2 in %: for $2 in $:
recurse % on %2 recurse $ on $2
..else: ..else:
%flat::add % $flat|add $
assume (sorted %flat) == [1, 2, 3, 4, 5, 6] assume (sorted $flat) == [1, 2, 3, 4, 5, 6]
# Recurion control flow # Recurion control flow
(for %var in recursive %structure %body) compiles to: (for $var in recursive $structure $body) compiles to:
with local compile actions: with local compile actions:
define mangler 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 "table.insert(\(mangle "stack \($v.1)"), \($x as lua expr))"
%lua = (..) $lua = (..)
Lua "\ Lua "
..do do
local \(mangle "stack \(%var.1)") = List{\(%structure as lua expr)} local \(mangle "stack \($var.1)") = List{\($structure as lua expr)}
while #\(mangle "stack \(%var.1)") > 0 do while #\(mangle "stack \($var.1)") > 0 do
\(%var as lua expr) = table.remove(\(mangle "stack \(%var.1)"), 1) \($var as lua expr) = table.remove(\(mangle "stack \($var.1)"), 1)
\(%body as lua)" \($body as lua)"
if (%body has subtree \(do next)): if ($body has subtree \(do next)):
%lua::add "\n ::continue::" $lua|add "\n ::continue::"
if (%body has subtree \(do next %var)): 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)): if ($body has subtree \(stop $var)):
%lua::add "\n \(\(---stop %var ---) as lua)" $lua|add "\n \(\(---stop $var ---) as lua)"
%lua::add "\nend -- Recursive scope" $lua|add "\nend -- Recursive scope"
return %lua return $lua

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines the code that creates and manipulates coroutines This file defines the code that creates and manipulates coroutines
@ -9,28 +9,27 @@ use "core/control_flow.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
%co = (..) $co = (..)
->: ->:
yield 4 yield 4
yield 5 yield 5
repeat 3 times: repeat 3 times:
yield 6 yield 6
%nums = [] $nums = []
for % in coroutine %co: for $ in coroutine $co: $nums|add $
%nums::add % assume ($nums == [4, 5, 6, 6, 6]) or barf "Coroutine iteration failed"
assume (%nums == [4, 5, 6, 6, 6]) or barf "Coroutine iteration failed" $d = {x: 0}
%d = {x: 0} $co2 = (..)
%co2 = (..)
coroutine: coroutine:
%d.x += 1 $d.x += 1
yield 1 yield 1
%d.x += 1 $d.x += 1
yield yield
%d.x += 1 $d.x += 1
repeat while ((coroutine status of %co2) != "dead"): resume %co2 repeat while ((coroutine status of $co2) != "dead"): resume $co2
assume %d.x == 3 assume $d.x == 3
(coroutine %body) parses as (coroutine from (-> %body)) (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 for \($ as lua expr) in coroutine_wrap(\($co as lua expr)) do
\(%body as lua) \($body as lua)
end" end"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains basic error reporting code This file contains basic error reporting code
@ -6,68 +6,68 @@ use "core/metaprogramming.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(barf %msg) compiles to "\ (barf $msg) compiles to \
..error(\(=lua "\%msg and \(%msg as lua expr) or 'nil'"), 0);" .."error(\(=lua "\$msg and \($msg as lua expr) or 'nil'"), 0);"
(assume %condition) compiles to: (assume $condition) compiles to:
lua> "local \%assumption = 'Assumption failed: '..tostring((\%condition):get_source_code())" lua> "local \$assumption = 'Assumption failed: '..tostring((\$condition):get_source_code())"
return (..) return (..)
Lua "\ Lua "
..if not \(%condition as lua expr) then if not \($condition as lua expr) then
error(\(quote "\%assumption"), 0) error(\(quote "\$assumption"), 0)
end" end"
(assume %a == %b) compiles to: (assume $a == $b) compiles to:
lua> "local \%assumption = 'Assumption failed: '..tostring(\(\(%a == %b) as nomsu))" lua> "local \$assumption = 'Assumption failed: '..tostring(\(\($a == $b) as nomsu))"
define mangler define mangler
return (..) return (..)
Lua "\ Lua "
..do do
local \(mangle "a"), \(mangle "b") = \(%a as lua expr), \(%b as lua expr) local \(mangle "a"), \(mangle "b") = \($a as lua expr), \($b as lua expr)
if \(mangle "a") ~= \(mangle "b") then if \(mangle "a") ~= \(mangle "b") then
error(\(quote "\%assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\(mangle "b")), 0) error(\(quote "\$assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\(mangle "b")), 0)
end end
end" end"
(assume %condition or barf %message) compiles to "\ (assume $condition or barf $message) compiles to "
..if not \(%condition as lua expr) then if not \($condition as lua expr) then
error(\(%message as lua expr), 0) error(\($message as lua expr), 0)
end" end"
test: test:
try (barf) and if it succeeds: try (barf) and if it succeeds:
barf "try failed." barf "try failed."
%worked = (no) $worked = (no)
try (barf) and if it barfs: try (barf) and if it barfs:
%worked = (yes) $worked = (yes)
assume %worked or barf "try/catch failed" assume $worked or barf "try/catch failed"
%x = 1 $x = 1
try: try:
%x = 2 $x = 2
do (barf) then always: %x = 3 do (barf) then always: $x = 3
..and if it barfs: ..and if it barfs:
do nothing do nothing
assume (%x == 3) or barf "do/then always failed" assume ($x == 3) or barf "do/then always failed"
# Try/except # Try/except
[..] [..]
try %action and if it succeeds %success or if it barfs %msg %fallback 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 try $action and if it barfs $msg $fallback or if it succeeds $success
..all compile to "\ ..all compile to "
..do do
local fell_through = false local fell_through = false
local err, erred = nil, false local err, erred = nil, false
local ok, ret = xpcall(function() local ok, ret = xpcall(function()
\(%action as lua) \($action as lua)
fell_through = true fell_through = true
end, function(\(=lua "\%fallback and \(%msg as lua expr) or ''")) end, function(\(=lua "\$fallback and \($msg as lua expr) or ''"))
local ok, ret = pcall(function() local ok, ret = pcall(function()
\((=lua "\%fallback or \%msg") as lua) \((=lua "\$fallback or \$msg") as lua)
end) end)
if not ok then err, erred = ret, true end if not ok then err, erred = ret, true end
end) end)
if ok then if ok then
\(%success as lua) \($success as lua)
if not fell_through then if not fell_through then
return ret return ret
end end
@ -87,14 +87,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 succeeds (do nothing) or if it barfs (do nothing)
#(try %action and if it barfs %fallback) parses as (..) #(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 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 (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) try $action and if it succeeds $success or if it barfs (do nothing)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
A simple UUID function based on RFC 4122: http://www.ietf.org/rfc/rfc4122.txt A simple UUID function based on RFC 4122: http://www.ietf.org/rfc/rfc4122.txt
@ -10,29 +10,29 @@ use "core/control_flow.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%NaN_surrogate = {} $NaN_surrogate = {}
%nil_surrogate = {} $nil_surrogate = {}
%obj_by_id = {} $obj_by_id = {}
set %obj_by_id's metatable to {__mode: "v"} set $obj_by_id's metatable to {__mode: "v"}
%id_by_obj = {} $id_by_obj = {}
set %id_by_obj's metatable to {..} set $id_by_obj's metatable to {..}
__mode: "k", __index: for (%self %key): __mode: "k", __index: for ($self $key):
if (%key == (nil)): if ($key == (nil)):
return %self.%nil_surrogate return $self.$nil_surrogate
if (%key != %key): if ($key != $key):
return %self.%NaN_surrogate return $self.$NaN_surrogate
--- (retry) --- --- (retry) ---
%id = (uuid) $id = (uuid)
if (%obj_by_id.%id != (nil)): go to (retry) if ($obj_by_id.$id != (nil)): go to (retry)
%self.%key = %id $self.$key = $id
%obj_by_id.%id = %key $obj_by_id.$id = $key
return %id return $id
externally (uuid) means: externally (uuid) means:
# Set all the other bits to randomly (or pseudo-randomly) chosen values. # Set all the other bits to randomly (or pseudo-randomly) chosen values.
%bytes = [..] $bytes = [..]
# time-low, time-mid, time-high-and-version # time-low, time-mid, time-high-and-version
randint (2 ^ (4 * 8)), randint (2 ^ (2 * 8)), randint (2 ^ (2 * 8 - 4)) randint (2 ^ (4 * 8)), randint (2 ^ (2 * 8)), randint (2 ^ (2 * 8 - 4))
# clock-seq-and-reserved, clock-seq-low # clock-seq-and-reserved, clock-seq-low
@ -43,20 +43,20 @@ externally (uuid) means:
# Set the four most significant bits (bits 12 through 15) of the # Set the four most significant bits (bits 12 through 15) of the
# time_hi_and_version field to the 4-bit version number from # time_hi_and_version field to the 4-bit version number from
# Section 4.1.3. # Section 4.1.3.
%bytes.3 += 0x4000 $bytes.3 += 0x4000
# Set the two most significant bits (bits 6 and 7) of the # Set the two most significant bits (bits 6 and 7) of the
# clock_seq_hi_and_reserved to zero and one, respectively. # clock_seq_hi_and_reserved to zero and one, respectively.
%bytes.4 += 0xC0 $bytes.4 += 0xC0
return (=lua "('%08x-%04x-%04x-%02x%02x-%6x%6x'):format(unpack(\%bytes))") return (=lua "('%08x-%04x-%04x-%02x%02x-%6x%6x'):format(unpack(\$bytes))")
# For strict identity checking, use (%x's id) == (%y's id) # For strict identity checking, use (%x's id) == (%y's id)
test: test:
assume (([] == []) and ((id of []) != (id of []))) assume (([] == []) and ((id of []) != (id of [])))
seed random with 0 seed random with 0
%x = [] $x = []
assume ((id of %x) == (id of %x)) assume ((id of $x) == (id of $x))
seed random with 0 seed random with 0
assume ((id of %x) != (id of [])) assume ((id of $x) != (id of []))
seed random seed random
externally [id of %, %'s id, %'id] all mean %id_by_obj.% externally [id of $, $'s id, $'id] all mean $id_by_obj.$

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains basic input/output code This file contains basic input/output code
@ -6,26 +6,26 @@ use "core/metaprogramming.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(say %message) compiles to: (say $message) compiles to:
lua> "\ lua> "
..if \%message.type == "Text" then if \$message.type == "Text" then
return LuaCode("say(", \(%message as lua expr), ");"); return LuaCode("say(", \($message as lua expr), ");");
else else
return LuaCode("say(tostring(", \(%message as lua expr), "));"); return LuaCode("say(tostring(", \($message as lua expr), "));");
end" end"
(say %message inline) compiles to: (say $message inline) compiles to:
lua> "\ lua> "
..if \%message.type == "Text" then if \$message.type == "Text" then
return LuaCode("io.write(", \(%message as lua expr), ")"); return LuaCode("io.write(", \($message as lua expr), ")");
else else
return LuaCode("io.write(tostring(", \(%message as lua expr), "))"); return LuaCode("io.write(tostring(", \($message as lua expr), "))");
end" end"
(ask %prompt) compiles to: (ask $prompt) compiles to:
lua> "\ lua> "
..if \%prompt.type == "Text" then if \$prompt.type == "Text" then
return LuaCode("(io.write(", \(%prompt as lua expr), ") and io.read())"); return LuaCode("(io.write(", \($prompt as lua expr), ") and io.read())");
else else
return LuaCode("(io.write(tostring(", \(%prompt as lua expr), ")) and io.read())"); return LuaCode("(io.write(tostring(", \($prompt as lua expr), ")) and io.read())");
end" end"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines some common math literals and functions This file defines some common math literals and functions
@ -12,10 +12,10 @@ use "core/collections.nom"
# Literals: # Literals:
test: 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" .."math constants failed"
%nan = (NaN) $nan = (NaN)
assume (%nan != %nan) or barf "NaN failed" assume ($nan != $nan) or barf "NaN failed"
[infinity, inf] all compile to "math.huge" [infinity, inf] all compile to "math.huge"
[not a number, NaN, nan] all compile to "(0/0)" [not a number, NaN, nan] all compile to "(0/0)"
[pi, Pi, PI] all compile to "math.pi" [pi, Pi, PI] all compile to "math.pi"
@ -26,8 +26,8 @@ test:
# Functions: # Functions:
test: test:
assume (("5" as a number) == 5) assume (("5" as a number) == 5)
((% as a number)'s meaning) = ((tonumber %)'s meaning) (($ as a number)'s meaning) = ((tonumber $)'s meaning)
((% as number)'s meaning) = ((tonumber %)'s meaning) (($ as number)'s meaning) = ((tonumber $)'s meaning)
test: test:
assume (..) assume (..)
all of [..] all of [..]
@ -35,38 +35,38 @@ test:
arc tangent 5, arc tangent 5 / 10, hyperbolic sine 5, hyperbolic 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 hyperbolic tangent 5, e^ 5, ln 5, log base 2 of 5, floor 5, ceiling 5, round 5
..or barf "math functions failed" ..or barf "math functions failed"
[absolute value %, | % |, abs %] all compile to "math.abs(\(% as lua expr))" [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))" .."math.sqrt(\($ as lua expr))"
[sine %, sin %] all compile to "math.sin(\(% as lua expr))" [sine $, sin $] all compile to "math.sin(\($ as lua expr))"
[cosine %, cos %] all compile to "math.cos(\(% as lua expr))" [cosine $, cos $] all compile to "math.cos(\($ as lua expr))"
[tangent %, tan %] all compile to "math.tan(\(% 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 sine $, asin $] all compile to "math.asin(\($ as lua expr))"
[arc cosine %, acos %] all compile to "math.acos(\(% 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 $, 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))" .."math.atan2(\($y as lua expr), \($x as lua expr))"
[hyperbolic sine %, sinh %] all compile to "math.sinh(\(% 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 cosine $, cosh $] all compile to "math.cosh(\($ as lua expr))"
[hyperbolic tangent %, tanh %] all compile to "math.tanh(\(% as lua expr))" [hyperbolic tangent $, tanh $] all compile to "math.tanh(\($ as lua expr))"
[e^ %, exp %] all compile to "math.exp(\(% 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))" [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))" .."math.log(\($ as lua expr), \($base as lua expr))"
(floor %) compiles to "math.floor(\(% as lua expr))" (floor $) compiles to "math.floor(\($ as lua expr))"
[ceiling %, ceil %] all compile to "math.ceil(\(% as lua expr))" [ceiling $, ceil $] all compile to "math.ceil(\($ as lua expr))"
[round %, % rounded] all compile to "math.floor(\(% as lua expr) + .5)" [round $, $ rounded] all compile to "math.floor(\($ as lua expr) + .5)"
test: test:
assume ((463 to the nearest 100) == 500) or barf "rounding failed" 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" 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)" =lua "(\$rounder)*math.floor((\$n / \$rounder) + .5)"
# Any/all # Any/all
externally [all of %items, all %items] all mean: externally [all of $items, all $items] all mean:
for % in %items: for $ in $items:
unless %: unless $:
return (no) return (no)
return (yes) return (yes)
@ -82,10 +82,10 @@ externally [all of %items, all %items] all mean:
%lua::add ")" %lua::add ")"
return %lua return %lua
[not all of %items, not all %items] all parse as (not (all of %items)) [not all of $items, not all $items] all parse as (not (all of $items))
externally [any of %items, any %items] all mean: externally [any of $items, any $items] all mean:
for % in %items: for $ in $items:
if %: if $:
return (yes) return (yes)
return (no) return (no)
@ -101,14 +101,14 @@ externally [any of %items, any %items] all mean:
%lua::add ")" %lua::add ")"
return %lua return %lua
[none of %items, none %items] all parse as (not (any of %items)) [none of $items, none $items] all parse as (not (any of $items))
# Sum/product # Sum/product
externally [sum of %items, sum %items] all mean: externally [sum of $items, sum $items] all mean:
%total = 0 $total = 0
for % in %items: for $ in $items:
%total += % $total += $
return %total return $total
#[sum of %items, sum %items] all compile to: #[sum of %items, sum %items] all compile to:
unless (%items.type is "List"): unless (%items.type is "List"):
@ -122,11 +122,11 @@ externally [sum of %items, sum %items] all mean:
%lua::add ")" %lua::add ")"
return %lua return %lua
externally [product of %items, product %items] all mean: externally [product of $items, product $items] all mean:
%prod = 1 $prod = 1
for % in %items: for $ in $items:
%prod *= % $prod *= $
return %prod return $prod
#[product of %items, product %items] all compile to: #[product of %items, product %items] all compile to:
unless (%items.type is "List"): unless (%items.type is "List"):
@ -140,61 +140,61 @@ externally [product of %items, product %items] all mean:
%lua::add ")" %lua::add ")"
return %lua 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) (sum of $items) / (size of $items)
# Min/max # Min/max
externally [min of %items, smallest of %items, lowest of %items] all mean: externally [min of $items, smallest of $items, lowest of $items] all mean:
%best = (nil) $best = (nil)
for % in %items: for $ in $items:
if ((%best == (nil)) or (% < %best)): %best = % if (($best == (nil)) or ($ < $best)): $best = $
return %best return $best
externally [..] externally [..]
max of %items, biggest of %items, largest of %items, highest of %items max of $items, biggest of $items, largest of $items, highest of $items
..all mean: ..all mean:
%best = (nil) $best = (nil)
for % in %items: for $ in $items:
if ((%best == (nil)) or (% > %best)): %best = % if (($best == (nil)) or ($ > $best)): $best = $
return %best return $best
test: test:
assume ((min of [3, -4, 1, 2] by % = (% * %)) == 1) assume ((min of [3, -4, 1, 2] by $ = ($ * $)) == 1)
assume ((max of [3, -4, 1, 2] by % = (% * %)) == -4) 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: result of:
%best = (nil) $best = (nil)
%best_key = (nil) $best_key = (nil)
for %item in %items: for $item in $items:
%key = %value_expr $key = $value_expr
if ((%best == (nil)) or (%key < %best_key)): if (($best == (nil)) or ($key < $best_key)):
%best = %item $best = $item
%best_key = %key $best_key = $key
return %best return $best
(max of %items by %item = %value_expr) parses as (..) (max of $items by $item = $value_expr) parses as (..)
result of: result of:
%best = (nil) $best = (nil)
%best_key = (nil) $best_key = (nil)
for %item in %items: for $item in $items:
%key = %value_expr $key = $value_expr
if ((%best == (nil)) or (%key > %best_key)): if (($best == (nil)) or ($key > $best_key)):
%best = %item $best = $item
%best_key = %key $best_key = $key
return %best return $best
# Random functions # Random functions
externally (seed random with %) means: externally (seed random with $) means:
lua> "math.randomseed(\%);\nfor i=1,20 do math.random(); end" lua> "math.randomseed(\$);\nfor i=1,20 do math.random(); end"
(seed random) parses as (seed random with (=lua "os.time()")) (seed random) parses as (seed random with (=lua "os.time()"))
[random number, random, rand] all compile to "math.random()" [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))" .."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))" ..all compile to "math.random(\($low as lua expr), \($high as lua expr))"
externally [..] externally [..]
random choice from %elements, random choice %elements, random %elements random choice from $elements, random choice $elements, random $elements
..all mean (=lua "\%elements[math.random(#\%elements)]") ..all mean (=lua "\$elements[math.random(#\$elements)]")

View File

@ -1,12 +1,12 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This File contains actions for making actions and compile-time actions and some helper This File contains actions for making actions and compile-time actions and some helper
functions to make that easier. functions to make that easier.
lua> "NOMSU_CORE_VERSION = 12" lua> "NOMSU_CORE_VERSION = 12"
lua> "NOMSU_LIB_VERSION = 8" lua> "NOMSU_LIB_VERSION = 8"
lua> "\ lua> "
..do do
local mangle_index = 0 local mangle_index = 0
function mangler() function mangler()
local my_mangle_index = mangle_index local my_mangle_index = mangle_index
@ -20,19 +20,19 @@ lua> "\
return LuaCode("local mangle = mangler()") return LuaCode("local mangle = mangler()")
end" end"
lua> "\ lua> "
..compile.action["1 ->"] = function(compile, \%args, \%body) compile.action["1 ->"] = function(compile, \$args, \$body)
if \%args and not \%body then \%args, \%body = {}, \%args end if \$args and not \$body then \$args, \$body = {}, \$args end
local body_lua = SyntaxTree:is_instance(\%body) and compile(\%body) or \%body 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(") local lua = LuaCode("(function(")
if SyntaxTree:is_instance(\%args) and (\%args.type == "Action" or \%args.type == "MethodCall") then if SyntaxTree:is_instance(\$args) and (\$args.type == "Action" or \$args.type == "MethodCall") then
\%args = \%args:get_args() \$args = \$args:get_args()
elseif SyntaxTree:is_instance(\%args) and \%args.type == "Var" then \%args = {\%args} end elseif SyntaxTree:is_instance(\$args) and \$args.type == "Var" then \$args = {\$args} end
for i, arg in ipairs(\%args) do for i, arg in ipairs(\$args) do
local arg_lua = SyntaxTree:is_instance(arg) and compile(arg):text() or arg local arg_lua = SyntaxTree:is_instance(arg) and compile(arg):text() or arg
if arg_lua == "..." then if arg_lua == "..." then
if i < #\%args then if i < #\$args then
compile_error_at(SyntaxTree:is_instance(arg) and arg or nil, 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 end
@ -51,10 +51,10 @@ lua> "\
compile.action["->"] = compile.action["1 ->"] compile.action["->"] = compile.action["1 ->"]
compile.action["for"] = compile.action["1 ->"]" compile.action["for"] = compile.action["1 ->"]"
lua> "\ lua> "
..compile.action["what 1 compiles to"] = function(compile, \%action) compile.action["what 1 compiles to"] = function(compile, \$action)
local lua = LuaCode("compile.action[", \%action.stub:as_lua(), "](") local lua = LuaCode("compile.action[", \$action.stub:as_lua(), "](")
local lua_args = table.map(\%action:get_args(), compile) local lua_args = table.map(\$action:get_args(), compile)
table.insert(lua_args, 1, "compile") table.insert(lua_args, 1, "compile")
lua:concat_add(lua_args, ", ") lua:concat_add(lua_args, ", ")
lua:add(")") lua:add(")")
@ -73,48 +73,48 @@ test:
test: test:
lua> "do" lua> "do"
loc x loc x
assume (%x is 99) or barf "Compile to statements with locals failed." assume ($x is 99) or barf "Compile to statements with locals failed."
lua> "end" lua> "end"
assume (%x is (nil)) or barf "Failed to properly localize a variable." assume ($x is (nil)) or barf "Failed to properly localize a variable."
(asdf) compiles to: (asdf) compiles to:
%tmp = "" $tmp = ""
return (Lua %tmp) return (Lua $tmp)
test: test:
asdf asdf
assume (%tmp is (nil)) or barf "compile to is leaking variables" assume ($tmp is (nil)) or barf "compile to is leaking variables"
lua> "\ lua> "
..compile.action["1 compiles to"] = function(compile, \%action, \%body) compile.action["1 compiles to"] = function(compile, \$action, \$body)
local \%args = List{\(\%compile), unpack(\%action:get_args())} local \$args = List{\(\$compile), unpack(\$action:get_args())}
if \%body.type == "Text" then if \$body.type == "Text" then
\%body = SyntaxTree{source=\%body.source, type="Action", "Lua", \%body} \$body = SyntaxTree{source=\$body.source, type="Action", "Lua", \$body}
end end
return LuaCode("compile.action[", \%action.stub:as_lua(), return LuaCode("compile.action[", \$action.stub:as_lua(),
"] = ", \(\(%args -> %body) as lua)) "] = ", \(\($args -> $body) as lua))
end" end"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(%actions all compile to %body) compiles to: ($actions all compile to $body) compiles to:
lua> "\ lua> "
..if \%actions.type ~= "List" then if \$actions.type ~= "List" then
compile_error(\%actions, "This should be a list of actions.") compile_error(\$actions, "This should be a list of actions.")
end end
local lua = \(\(%actions.1 compiles to %body) as lua) local lua = \(\($actions.1 compiles to $body) as lua)
local \%args = List{\(\%compile), unpack(\%actions[1]:get_args())} local \$args = List{\(\$compile), unpack(\$actions[1]:get_args())}
local \%compiled_args = List(table.map(\%args, compile)) local \$compiled_args = List(table.map(\$args, compile))
for i=2,#\%actions do for i=2,#\$actions do
local alias = \%actions[i] local alias = \$actions[i]
local \%alias_args = List{\(\%compile), unpack(alias:get_args())} local \$alias_args = List{\(\$compile), unpack(alias:get_args())}
lua:add("\\ncompile.action[", alias.stub:as_lua(), "] = ") lua:add("\\ncompile.action[", alias.stub:as_lua(), "] = ")
if \%alias_args == \%args then if \$alias_args == \$args then
lua:add("compile.action[", \%actions[1].stub:as_lua(), "]") lua:add("compile.action[", \$actions[1].stub:as_lua(), "]")
else else
lua:add("function(") lua:add("function(")
lua:concat_add(table.map(\%alias_args, compile), ", ") lua:concat_add(table.map(\$alias_args, compile), ", ")
lua:add(") return compile.action[", \%actions[1].stub:as_lua(), "](") lua:add(") return compile.action[", \$actions[1].stub:as_lua(), "](")
lua:concat_add(\%compiled_args, ", ") lua:concat_add(\$compiled_args, ", ")
lua:add(") end") lua:add(") end")
end end
end end
@ -123,41 +123,41 @@ lua> "\
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
(foo %x) means "outer" (foo $x) means "outer"
with {((foo %)'s meaning)}: with {((foo $)'s meaning)}:
(foo %x) means: (foo $x) means:
%y = (%x + 1) $y = ($x + 1)
return %y return $y
assume ((foo 10) == 11) or barf "Action didn't work." assume ((foo 10) == 11) or barf "Action didn't work."
assume (%y is (nil)) or barf "Action leaked a local into globals." assume ($y is (nil)) or barf "Action leaked a local into globals."
(baz %) parses as (foo %) (baz $) parses as (foo $)
assume ((foo 1) == "outer") assume ((foo 1) == "outer")
(%action means %body) compiles to: ($action means $body) compiles to:
lua> "\ lua> "
..
local lua = LuaCode() local lua = LuaCode()
if \%action.type == "MethodCall" then if \$action.type == "MethodCall" then
lua:add(compile(\%action[1]), ".", \%action[2].stub:as_lua_id()) lua:add(compile(\$action[1]), ".", \$action[2].stub:as_lua_id())
elseif \%action.type == "Action" then elseif \$action.type == "Action" then
lua:add(\%action.stub:as_lua_id()) lua:add(\$action.stub:as_lua_id())
lua:add_free_vars({\%action.stub:as_lua_id()}) lua:add_free_vars({\$action.stub:as_lua_id()})
else else
compile_error_at(\%action, "Expected an action or method call here") compile_error_at(\$action, "Expected an action or method call here")
end end
lua:add(" = ", \(\(%action -> %body) as lua), ";") lua:add(" = ", \(\($action -> $body) as lua), ";")
return lua" return lua"
(%actions all mean %body) compiles to: ($actions all mean $body) compiles to:
lua> "\ lua> "
..local lua = \(\(%actions.1 means %body) as lua) local lua = \(\($actions.1 means $body) as lua)
local first_def = (\%actions[1].type == "MethodCall" local first_def = (\$actions[1].type == "MethodCall"
and LuaCode(compile(\%actions[1][1]), ".", \%actions[1].stub:as_lua_id()) and LuaCode(compile(\$actions[1][1]), ".", \$actions[1].stub:as_lua_id())
or LuaCode(\%actions[1].stub:as_lua_id())) or LuaCode(\$actions[1].stub:as_lua_id()))
local \%args = List(\%actions[1]:get_args()) local \$args = List(\$actions[1]:get_args())
for i=2,#\%actions do for i=2,#\$actions do
local alias = \%actions[i] local alias = \$actions[i]
local \%alias_args = List(alias:get_args()) local \$alias_args = List(alias:get_args())
lua:add("\\n") lua:add("\\n")
if alias.type == "MethodCall" then if alias.type == "MethodCall" then
lua:add(compile(alias[1]), ".", alias.stub:as_lua_id()) lua:add(compile(alias[1]), ".", alias.stub:as_lua_id())
@ -165,10 +165,10 @@ test:
lua:add(alias.stub:as_lua_id()) lua:add(alias.stub:as_lua_id())
lua:add_free_vars({alias_name}) lua:add_free_vars({alias_name})
end end
if \%args == \%alias_args then if \$args == \$alias_args then
lua:add(" = ", first_def, ";") lua:add(" = ", first_def, ";")
else else
lua:add(" = ", \(\(%alias_args -> %actions.1) as lua), ";") lua:add(" = ", \(\($alias_args -> $actions.1) as lua), ";")
end end
end end
return lua" return lua"
@ -182,46 +182,46 @@ test:
assume ((baz1) == "baz1") assume ((baz1) == "baz1")
assume ((baz2) == "baz2") assume ((baz2) == "baz2")
(externally %action means %body) compiles to: (externally $action means $body) compiles to:
lua> "\ lua> "
..local lua = \(\(%action means %body) as lua) local lua = \(\($action means $body) as lua)
lua:remove_free_vars({\%action.stub:as_lua_id()}) lua:remove_free_vars({\$action.stub:as_lua_id()})
return lua" return lua"
(externally %actions all mean %body) compiles to: (externally $actions all mean $body) compiles to:
lua> "\ lua> "
..local lua = \(\(%actions all mean %body) as lua) local lua = \(\($actions all mean $body) as lua)
lua:remove_free_vars(table.map(\%actions, function(a) return a.stub:as_lua_id() end)) lua:remove_free_vars(table.map(\$actions, function(a) return a.stub:as_lua_id() end))
return lua" return lua"
test: test:
assume (((say %)'s meaning) == (=lua "say")) assume (((say $)'s meaning) == (=lua "say"))
(%action's meaning) compiles to (Lua (%action.stub::as lua id)) ($action's meaning) compiles to (Lua ($action.stub|as lua id))
test: test:
(swap %x and %y) parses as (..) (swap $x and $y) parses as (..)
do: do:
%tmp = %x $tmp = $x
%x = %y $x = $y
%y = %tmp $y = $tmp
test: test:
[%1, %2] = [1, 2] [$1, $2] = [1, 2]
swap %1 and %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 %'" .."'parse % as %' failed on 'swap % and %'"
[%tmp, %tmp2] = [1, 2] [$tmp, $tmp2] = [1, 2]
swap %tmp and %tmp2 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." .."'parse % as %' variable mangling failed."
(%actions all parse as %body) compiles to: ($actions all parse as $body) compiles to:
lua> "\ lua> "
..local replacements = {} local replacements = {}
if \%actions.type ~= "List" then if \$actions.type ~= "List" then
compile_error(\%actions, "This should be a list.") compile_error(\$actions, "This should be a list.")
end end
for i,arg in ipairs(\%actions[1]:get_args()) do for i,arg in ipairs(\$actions[1]:get_args()) do
replacements[arg[1]] = compile(arg):text() replacements[arg[1]] = compile(arg):text()
end end
local function make_tree(t) local function make_tree(t)
@ -254,33 +254,33 @@ test:
return t:as_lua() return t:as_lua()
end end
end end
local \%new_body = LuaCode:from(\%body.source, local \$new_body = LuaCode:from(\$body.source,
"local mangle = mangler()", "local mangle = mangler()",
"\\nreturn ", make_tree(\%body)) "\\nreturn ", make_tree(\$body))
local ret = \(\(%actions all compile to %new_body) as lua) local ret = \(\($actions all compile to $new_body) as lua)
return ret" return ret"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[%action parses as %body] all parse as ([%action] all parse as %body) [$action parses as $body] all parse as ([$action] all parse as $body)
#(%tree as lua expr) compiles to "compile(\(=lua "compile(\%tree, true)"), true)" #(%tree as lua expr) compiles to "compile(\(=lua "compile(\%tree, true)"), true)"
externally (%tree as lua expr) means: externally ($tree as lua expr) means:
lua> "\ lua> "
..local tree_lua = compile(\%tree) local tree_lua = compile(\$tree)
if \%tree.type == 'Block' then if \$tree.type == 'Block' then
tree_lua = LuaCode:from(\%tree.source, '(function()\\n ', tree_lua, '\\nend)()') tree_lua = LuaCode:from(\$tree.source, '(function()\\n ', tree_lua, '\\nend)()')
elseif \%tree.type == 'MethodCall' and #\%tree > 2 then 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.") "Replace this with a single method call.")
end end
return tree_lua" return tree_lua"
externally [%var as lua identifier, %var as lua id] all mean: externally [$var as lua identifier, $var as lua id] all mean:
lua> "\ lua> "
..local lua = \(%var as lua) local lua = \($var as lua)
if not lua:text():is_a_lua_id() then if not lua:text():is_a_lua_id() then
compile_error(\%var, compile_error(\$var,
"This is supposed to be something that compiles to a valid Lua identifier.", "This is supposed to be something that compiles to a valid Lua identifier.",
"This should probably be a variable.") "This should probably be a variable.")
end end
@ -295,50 +295,50 @@ test:
assume (third arg 5 6 7 8) == 7 assume (third arg 5 6 7 8) == 7
(*extra arguments*) compiles to "..." (*extra arguments*) compiles to "..."
(% is syntax tree) compiles to "SyntaxTree:is_instance(\(% as lua expr))" ($ 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" =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)) \($tree as lua expr):map(function(\($t as lua expr))
\(..) \(..)
(%replacement as lua) if (%replacement.type == "Block") else "\ ($replacement as lua) if ($replacement.type == "Block") else \
..return \(%replacement as lua expr)" .."return \($replacement as lua expr)"
.. ..
end)" end)"
externally (%tree with vars %replacements) means (..) externally ($tree with vars $replacements) means (..)
=lua "\ =lua "
..\%tree:map(function(\%t) \$tree:map(function(\$t)
if \%t.type == "Var" then if \$t.type == "Var" then
return \%replacements[\%t[1]] return \$replacements[\$t[1]]
end end
end)" end)"
(tree %tree with vars %replacements) compiles to "\ (tree $tree with vars $replacements) compiles to "
..\(=lua "(\%tree):as_lua()"):map(function(t) \(=lua "(\$tree):as_lua()"):map(function(t)
if t.type == "Var" then if t.type == "Var" then
return \(%replacements as lua expr)[t[1]] return \($replacements as lua expr)[t[1]]
end end
end)" end)"
(%tree has subtree %match_tree) compiles to "\ ($tree has subtree $match_tree) compiles to "
..(function() (function()
local match_tree = \(%match_tree as lua expr) local match_tree = \($match_tree as lua expr)
for subtree in coroutine_wrap(function() \(%tree as lua expr):map(yield) end) do for subtree in coroutine_wrap(function() \($tree as lua expr):map(yield) end) do
if subtree == match_tree then return true end if subtree == match_tree then return true end
end end
end)()" end)()"
externally (match %tree with %patt) means: externally (match $tree with $patt) means:
lua> "\ lua> "
..if \%patt.type == "Var" then return Dict{[\%patt[1]]=\%tree} end if \$patt.type == "Var" then return Dict{[\$patt[1]]=\$tree} end
if \%patt.type == "Action" and \%patt.stub ~= \%tree.stub then return nil end if \$patt.type == "Action" and \$patt.stub ~= \$tree.stub then return nil end
if #\%patt ~= #\%tree then return nil end if #\$patt ~= #\$tree then return nil end
local matches = Dict{} local matches = Dict{}
for \%i=1,#\%patt do for \($i)=1,#\$patt do
if SyntaxTree:is_instance(\%tree[\%i]) then if SyntaxTree:is_instance(\$tree[\$i]) then
local submatch = \(match %tree.%i with %patt.%i) local submatch = \(match $tree.$i with $patt.$i)
if not submatch then return nil end if not submatch then return nil end
for k,v in pairs(submatch) do for k,v in pairs(submatch) do
if matches[k] and matches[k] ~= v then return nil end if matches[k] and matches[k] ~= v then return nil end
@ -351,44 +351,44 @@ externally (match %tree with %patt) means:
test: test:
assume ((quote "one\n\"two\"") == "\"one\\n\\\"two\\\"\"") assume ((quote "one\n\"two\"") == "\"one\\n\\\"two\\\"\"")
(quote %s) compiles to "tostring(\(%s as lua expr)):as_lua()" (quote $s) compiles to "tostring(\($s as lua expr)):as_lua()"
test: test:
assume (lua type of {}) == "table" assume (lua type of {}) == "table"
assume (type of {}) == "Dict" assume (type of {}) == "Dict"
assume ({} is a "Dict") assume ({} is a "Dict")
assume ("" is text) assume ("" is text)
assume ("" isn't a "Dict") assume ("" isn't a "Dict")
externally (% is text) means (=lua "\(lua type of %) == 'string'") 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'" =lua "\(lua type of $) ~= 'string'"
externally (type of %) means: externally (type of $) means:
lua> "\ lua> "
..local lua_type = \(lua type of %) local lua_type = \(lua type of $)
if lua_type == 'string' then return 'Text' if lua_type == 'string' then return 'Text'
elseif lua_type == 'table' or lua_type == 'userdata' then elseif lua_type == 'table' or lua_type == 'userdata' then
local mt = getmetatable(\%) local mt = getmetatable(\$)
if mt and mt.__type then return mt.__type end if mt and mt.__type then return mt.__type end
end end
return lua_type" return lua_type"
[% is a %type, % is an %type] all parse as ((type of %) == %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) ..all parse as ((type of $) != $type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
assume ((run "return (2 + 99)") == 101) assume ((run "return (2 + 99)") == 101)
%x = 0 $x = 0
externally (set to %) means: externally (set to $) means:
external %x = % external $x = $
run "set to 1" run "set to 1"
assume %x == 1 assume $x == 1
assume (run \(return \(\(5) + \(5)))) == 10 assume (run \(return \(\(5) + \(5)))) == 10
(run %nomsu_code) compiles to "run_1_in(\(%nomsu_code as lua expr), _ENV)" (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))" .."compile(\($block as lua))"
test: test:
(foo) means: (foo) means:
@ -398,8 +398,8 @@ test:
# Return statement is wrapped in a do..end block because Lua is unhappy if you # 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. put code after a return statement, unless you wrap it in a block.
(return (*extra arguments*)) compiles to: (return (*extra arguments*)) compiles to:
lua> "\ lua> "
..local lua = \(Lua "do return ") local lua = \(Lua "do return ")
for i=1,select('#',...) do for i=1,select('#',...) do
if i > 1 then lua:add(", ") end if i > 1 then lua:add(", ") end
lua:add(_1_as_lua((select(i, ...)))) lua:add(_1_as_lua((select(i, ...))))
@ -419,12 +419,12 @@ test:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(with local compile actions %body) compiles to "\ (with local compile actions $body) compiles to "
..do do
--local compile = _1_forked(compile) --local compile = _1_forked(compile)
local old_action = compile.action local old_action = compile.action
compile.action = _1_forked(old_action) compile.action = _1_forked(old_action)
\(%body as lua) \($body as lua)
compile.action = old_action compile.action = old_action
end" end"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains definitions of operators like "+" and "and". This file contains definitions of operators like "+" and "and".
@ -11,115 +11,115 @@ test:
assume (all [1 < 2, 2 > 1, 1 <= 2, 2 >= 1, 1 == 1, 1 != 2]) assume (all [1 < 2, 2 > 1, 1 <= 2, 2 >= 1, 1 == 1, 1 != 2])
# Comparison Operators # Comparison Operators
(%x < %y) compiles to "(\(%x as lua expr) < \(%y as lua expr))" ($x < $y) compiles to "(\($x as lua expr) < \($y as lua expr))"
(%x > %y) compiles to "(\(%x as lua expr) > \(%y as lua expr))" ($x > $y) compiles to "(\($x as lua expr) > \($y as lua expr))"
(%x <= %y) compiles to "(\(%x as lua expr) <= \(%y as lua expr))" ($x <= $y) compiles to "(\($x as lua expr) <= \($y as lua expr))"
(%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 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))" .."(\($a as lua expr) ~= \($b as lua expr))"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
%x = 10 $x = 10
assume (%x == 10) assume ($x == 10)
[%x, %y] = [10, 20] [$x, $y] = [10, 20]
assume ((%x == 10) and (%y == 20)) or barf "mutli-assignment failed." assume (($x == 10) and ($y == 20)) or barf "mutli-assignment failed."
[%x, %y] = [%y, %x] [$x, $y] = [$y, $x]
assume ((%y == 10) and (%x == 20)) or barf "swapping vars failed." assume (($y == 10) and ($x == 20)) or barf "swapping vars failed."
%vals = [4, 5] $vals = [4, 5]
[%x, %y] = (unpack %vals) [$x, $y] = (unpack $vals)
assume ((%x == 4) and (%y == 5)) or barf "unpacking failed" assume (($x == 4) and ($y == 5)) or barf "unpacking failed"
# Variable assignment operator # Variable assignment operator
(%var = %value) compiles to: ($var = $value) compiles to:
lua> "\ lua> "
..local lua = LuaCode() local lua = LuaCode()
if \%var.type == "List" then if \$var.type == "List" then
for i, \%assignment in ipairs(\%var) do for i, \$assignment in ipairs(\$var) do
if i > 1 then lua:add(", ") end if i > 1 then lua:add(", ") end
local assignment_lua = \(%assignment as lua expr) local assignment_lua = \($assignment as lua expr)
lua:add(assignment_lua) lua:add(assignment_lua)
if \%assignment.type == 'Var' then if \$assignment.type == 'Var' then
lua:add_free_vars({assignment_lua:text()}) lua:add_free_vars({assignment_lua:text()})
end end
end end
lua:add(' = ') lua:add(' = ')
if \%value.type == "List" then if \$value.type == "List" then
if #\%value ~= #\%var then if #\$value ~= #\$var then
compile_error_at(\%value, compile_error_at(\$value,
"This assignment has too "..(#\%value > #\%var and "many" or "few").." values.", "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 '\ "Make sure it has the same number of values on the left and right hand side of the '\
..=' operator.") ..=' operator.")
end end
for i, \%val in ipairs(\%value) do for i, \$val in ipairs(\$value) do
if i > 1 then lua:add(", ") end if i > 1 then lua:add(", ") end
local val_lua = \(%val as lua expr) local val_lua = \($val as lua expr)
lua:add(val_lua) lua:add(val_lua)
end end
lua:add(";") lua:add(";")
else else
lua:add(\(%value as lua expr), ';') lua:add(\($value as lua expr), ';')
end end
else else
local var_lua = \(%var as lua expr) local var_lua = \($var as lua expr)
lua:add(var_lua) lua:add(var_lua)
if \%var.type == 'Var' then if \$var.type == 'Var' then
lua:add_free_vars({var_lua:text()}) lua:add_free_vars({var_lua:text()})
end end
lua:add(' = ', \(%value as lua expr), ';') lua:add(' = ', \($value as lua expr), ';')
end end
return lua" return lua"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test: test:
[%foozle, %y] = ["outer", "outer"] [$foozle, $y] = ["outer", "outer"]
externally (set global x local y) means: externally (set global x local y) means:
external %foozle = "inner" external $foozle = "inner"
%y = "inner" $y = "inner"
set global x local y set global x local y
assume ((%foozle == "inner") and (%y == "outer")) or barf "external failed." assume (($foozle == "inner") and ($y == "outer")) or barf "external failed."
(external %var = %value) compiles to "\(%var as lua) = \(%value as lua)" (external $var = $value) compiles to "\($var as lua) = \($value as lua)"
test: test:
[%foozle, %y] = ["outer", "outer"] [$foozle, $y] = ["outer", "outer"]
externally (set global x local y) means: externally (set global x local y) means:
with external [%foozle]: with external [$foozle]:
%foozle = "inner" $foozle = "inner"
%y = "inner" $y = "inner"
set global x local y 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' failed."
(with external %externs %body) compiles to: (with external $externs $body) compiles to:
%body_lua = (%body as lua) $body_lua = ($body as lua)
lua> "\%body_lua:remove_free_vars(table.map(\%externs, function(v) return compile(v):text() end))" lua> "\$body_lua:remove_free_vars(table.map(\$externs, function(v) return compile(v):text() end))"
return %body_lua return $body_lua
test: test:
[%x, %y] = [1, 2] [$x, $y] = [1, 2]
with {%z, %x: 999}: with {$z, $x: 999}:
assume %z == (nil) assume $z == (nil)
%z = 999 $z = 999
assume (%z == 999) or barf "'with' failed." assume ($z == 999) or barf "'with' failed."
assume (%x == 999) or barf "'with' assignment failed." assume ($x == 999) or barf "'with' assignment failed."
assume (%x == 1) or barf "'with' scoping failed" assume ($x == 1) or barf "'with' scoping failed"
assume (%z == (nil)) or barf "'with' scoping failed" assume ($z == (nil)) or barf "'with' scoping failed"
(with %assignments %body) compiles to: (with $assignments $body) compiles to:
%lua = (%body as lua) $lua = ($body as lua)
lua> "\ lua> "
..local lhs, rhs = LuaCode(), LuaCode() local lhs, rhs = LuaCode(), LuaCode()
local vars = {} local vars = {}
for i, item in ipairs(\%assignments) do for i, item in ipairs(\$assignments) do
local \%target, \%value = item[1], item[2] local \$target, \$value = item[1], item[2]
local target_lua = \(%target as lua) local target_lua = \($target as lua)
if not target_lua:text():is_lua_id() then if not target_lua:text():is_lua_id() then
compile_error_at(\%target, "Invalid target for 'with' scope assignment.", compile_error_at(\$target, "Invalid target for 'with' scope assignment.",
"This should be either a variable or an action's meaning.") "This should be either a variable or an action's meaning.")
end end
local value_lua = \%value and \(%value as lua) or "nil" local value_lua = \$value and \($value as lua) or "nil"
if i > 1 then if i > 1 then
lhs:add(", ") lhs:add(", ")
rhs:add(", ") rhs:add(", ")
@ -128,35 +128,35 @@ test:
rhs:add(value_lua) rhs:add(value_lua)
vars[i] = target_lua:text() vars[i] = target_lua:text()
end end
\%lua:remove_free_vars(vars) \$lua:remove_free_vars(vars)
\%lua:prepend("local ", lhs, " = ", rhs, ";\\n")" \$lua:prepend("local ", lhs, " = ", rhs, ";\\n")"
return (Lua "do\n \%lua\nend -- 'with' block") return (Lua "do\n \$lua\nend -- 'with' block")
# Math Operators # Math Operators
test: test:
assume ((5 wrapped around 2) == 1) or barf "mod not working" 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)))" .."((\($x as lua expr)) % (\($y as lua expr)))"
# 3-part chained comparisons # 3-part chained comparisons
# (uses a lambda to avoid re-evaluating middle value, while still being an expression) # (uses a lambda to avoid re-evaluating middle value, while still being an expression)
test: test:
%calls = 0 $calls = 0
(one) means: (one) means:
external %calls = (%calls + 1) external $calls = ($calls + 1)
return 1 return 1
assume (0 <= (one) <= 2) or barf "Three-way chained comparison failed." 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" .."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)
(%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)
(%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)
(%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)
# TODO: optimize for common case where x,y,z are all either variables or number literals # TODO: optimize for common case where x,y,z are all either variables or number literals
# Boolean Operators # Boolean Operators
@ -165,8 +165,8 @@ test:
assume (((no) and (barfer)) == (no)) assume (((no) and (barfer)) == (no))
assume ((no) or (yes)) assume ((no) or (yes))
assume ((yes) or (barfer)) assume ((yes) or (barfer))
(%x and %y) compiles to "(\(%x as lua expr) and \(%y as lua expr))" ($x and $y) compiles to "(\($x as lua expr) and \($y as lua expr))"
(%x or %y) compiles to "(\(%x as lua expr) or \(%y as lua expr))" ($x or $y) compiles to "(\($x as lua expr) or \($y as lua expr))"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -183,32 +183,32 @@ test:
# Lua 5.3 introduced bit operators like | and &. Use them when possible, otherwise # Lua 5.3 introduced bit operators like | and &. Use them when possible, otherwise
fall back to bit.bor(), bit.band(), etc. fall back to bit.bor(), bit.band(), etc.
lua> "if \((is jit) or ((Lua version) == "Lua 5.2")) then" lua> "if \((is jit) or ((Lua version) == "Lua 5.2")) then"
[NOT %, ~ %] all compile to "bit.bnot(\(% as lua expr))" [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))" .."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))" .."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))" .."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))" .."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))" .."bit.rshift(\($x as lua expr), \($shift as lua expr))"
lua> "else" lua> "else"
[NOT %, ~ %] all compile to "~(\(% as lua expr))" [NOT $, ~ $] all compile to "~(\($ as lua expr))"
[%x OR %y, %x | %y] all compile to "(\(%x as lua expr) | \(%y 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 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 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 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))" .."(\($x as lua expr) >> \($shift as lua expr))"
lua> "end" lua> "end"
@ -216,29 +216,29 @@ lua> "end"
test: test:
assume ((- 5) == -5) assume ((- 5) == -5)
assume ((not (yes)) == (no)) assume ((not (yes)) == (no))
(- %) compiles to "(- \(% as lua expr))" (- $) compiles to "(- \($ as lua expr))"
(not %) compiles to "(not \(% as lua expr))" (not $) compiles to "(not \($ as lua expr))"
test: test:
assume ((size of [1, 2, 3]) == 3) assume ((size of [1, 2, 3]) == 3)
(size of %list) compiles to "(#\(%list as lua expr))" (size of $list) compiles to "(#\($list as lua expr))"
(%list is empty) compiles to "(#\(%list as lua expr) == 0)" ($list is empty) compiles to "(#\($list as lua expr) == 0)"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Update operators # Update operators
test: test:
%x = 1 $x = 1
%x += 1 $x += 1
assume (%x == 2) or barf "+= failed" assume ($x == 2) or barf "+= failed"
%x *= 2 $x *= 2
assume (%x == 4) or barf "*= failed" assume ($x == 4) or barf "*= failed"
wrap %x around 3 wrap $x around 3
assume (%x == 1) or barf "wrap around failed" assume ($x == 1) or barf "wrap around failed"
(%var += %) parses as (%var = ((%var or 0) + %)) ($var += $) parses as ($var = (($var or 0) + $))
(%var -= %) parses as (%var = ((%var or 0) - %)) ($var -= $) parses as ($var = (($var or 0) - $))
(%var *= %) parses as (%var = ((%var or 1) * %)) ($var *= $) parses as ($var = (($var or 1) * $))
(%var /= %) parses as (%var = (%var / %)) ($var /= $) parses as ($var = ($var / $))
(%var ^= %) parses as (%var = (%var ^ %)) ($var ^= $) parses as ($var = ($var ^ $))
(%var and= %) parses as (%var = (%var and %)) ($var and= $) parses as ($var = ($var and $))
(%var or= %) parses as (%var = (%var or %)) ($var or= $) parses as ($var = ($var or $))
(wrap %var around %) parses as (%var = (%var wrapped around %)) (wrap $var around $) parses as ($var = ($var wrapped around $))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains some definitions of text escape sequences, including ANSI console This file contains some definitions of text escape sequences, including ANSI console
color codes. color codes.
@ -12,35 +12,31 @@ use "core/control_flow.nom"
test: test:
assume "\[1, 2, 3]" == "[1, 2, 3]" assume "\[1, 2, 3]" == "[1, 2, 3]"
assume "foo = \(1 + 2)!" == "foo = 3!" assume "foo = \(1 + 2)!" == "foo = 3!"
assume "one\ntwo" == "\ assume "one\ntwo" == "one\ntwo"
..one assume "nogap" == "nogap"
two" assume (["x", "y"]|joined with ",") == "x,y"
assume "nogap" == "\ assume (["x", "y"]|joined) == "xy"
..no\ assume ("BAR"|byte 2) == 65
..gap" assume ("BAR"|bytes 1 to 2) == [66, 65]
assume (["x", "y"]::joined with ",") == "x,y" assume ("asdf"|capitalized) == "Asdf"
assume (["x", "y"]::joined) == "xy" assume ("asdf"|uppercase) == "ASDF"
assume ("BAR"::byte 2) == 65 assume ("asdf"|with "s" -> "X") == "aXdf"
assume ("BAR"::bytes 1 to 2) == [66, 65] assume ("one\ntwo\n"|lines) == ["one", "two", ""]
assume ("asdf"::capitalized) == "Asdf" ($spec とは $body) parses as ($spec means $body)
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: test:
%こんにちは = "こんにちは" $こんにちは = "こんにちは"
(% と言う) とは "\(%)世界" ($ と言う) とは "\($)世界"
assume (%こんにちは と言う) == "こんにちは世界" assume ($こんにちは と言う) == "こんにちは世界"
(%expr for %match in %text matching %patt) compiles to: ($expr for $match in $text matching $patt) compiles to:
define mangler define mangler
return (..) return (..)
Lua "\ Lua "
..(function() (function()
local \(mangle "comprehension") = List{} local \(mangle "comprehension") = List{}
for \(%match as lua expr) in (\(%text as lua expr)):gmatch(\(%patt as lua expr)) do for \($match as lua expr) in (\($text as lua expr)):gmatch(\($patt as lua expr)) do
\(mangle "comprehension")[#\(mangle "comprehension")+1] = \(%expr as lua) \(mangle "comprehension")[#\(mangle "comprehension")+1] = \($expr as lua)
end end
return \(mangle "comprehension") return \(mangle "comprehension")
end)()" end)()"
@ -51,17 +47,17 @@ test:
test: test:
assume (0xDEADBEEF as hex) == "0xDEADBEEF" assume (0xDEADBEEF as hex) == "0xDEADBEEF"
externally (%num as hex) means: externally ($num as hex) means:
if (%num < 0): if ($num < 0):
return ("-0x%X"::formatted with (- %num)) return ("-0x%X"|formatted with (- $num))
..else: ..else:
return ("0x%X"::formatted with %num) return ("0x%X"|formatted with $num)
# Text literals # Text literals
%escapes = {..} $escapes = {..}
nl: "\n", newline: "\n", tab: "\t", bell: "\a", cr: "\r", "carriage return": "\r" nl: "\n", newline: "\n", tab: "\t", bell: "\a", cr: "\r", "carriage return": "\r"
backspace: "\b", "form feed": "\f", formfeed: "\f", "vertical tab": "\v" backspace: "\b", "form feed": "\f", formfeed: "\f", "vertical tab": "\v"
for %name = %str in %escapes: for $name = $str in $escapes:
with {%lua: Lua (quote %str)}: with {$lua: Lua (quote $str)}:
%compile.action.%name = (-> %lua) $compile.action.$name = (-> $lua)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# How do I... # How do I...
# Write a comment? Put a # and go till the end of the line # Write a comment? Put a # and go till the end of the line
# How do I write a multi-line comment? # How do I write a multi-line comment?
@ -19,26 +19,26 @@ say "Hello world!"
# How do I set a variable? # How do I set a variable?
# Variables have "%" prefix: # Variables have "%" prefix:
%foobar = 1 $foobar = 1
%text = "Hello world" $text = "Hello world"
# Expressions that are more than just literal values require parentheses: # Expressions that are more than just literal values require parentheses:
%foobar = (2 + 3) $foobar = (2 + 3)
%one_two = 12 $one_two = 12
say %one_two say $one_two
# How do I modify a variable? # How do I modify a variable?
%foobar = (%foobar + 1) $foobar = ($foobar + 1)
# Or, as a shorthand, you can do this to increment a variable: # Or, as a shorthand, you can do this to increment a variable:
%foobar += 1 $foobar += 1
# How do I define a multi-line string? # How do I define a multi-line string?
# In Nomsu, the name "text" is used, rather than "string", and multi-line text looks like: # In Nomsu, the name "text" is used, rather than "string", and multi-line text looks like:
%multi_text = "\ $multi_text = "
..Start with a quote mark and a backslash and an indented "..", then put indented Start with a quotation mark, then put indented lines below it. The indented
lines below it. The indented lines will not include the indentation, except when lines will not include the indentation, except when the lines are indented
the lines are indented more than 4 spaces relative to the original quote mark. more than 4 spaces relative to the original quote mark.
<- E.g. the 2 spaces here will be included as part of the text. <- E.g. the 2 spaces here will be included as part of the text.
But this line will have no leading spaces. But this line will have no leading spaces.
@ -46,10 +46,10 @@ say %one_two
indentation level." indentation level."
# How do I put values inside text? (AKA string formatting, string interpolation) # How do I put values inside text? (AKA string formatting, string interpolation)
say "\ say "
..Text can contain a backslash followed by a variable, list, dict, or parenthesized Text can contain a backslash followed by a variable, list, dict, or parenthesized
expression. This escaped value will be converted to readable text, like so: expression. This escaped value will be converted to readable text, like so:
The value of %foobar is \%foobar, isn't that nice? The value of %foobar is \$foobar, isn't that nice?
These are some numbers: \[1, 2, 3] These are some numbers: \[1, 2, 3]
The sum of 2 and 4 is \(2 + 4). The sum of 2 and 4 is \(2 + 4).
@ -59,46 +59,45 @@ say "\
Or, two backlashes will be treated as a single backslash, no matter what follows, Or, two backlashes will be treated as a single backslash, no matter what follows,
like this: \\%foobar <- won't insert any values like this: \\%foobar <- won't insert any values
If you need to split a long line without inserting a newline, you can end a line with backslash and start the next line \ If you need to split a long line without inserting a newline, you can end a line with backslash and \
..with two periods, like that. ..start the next line with two periods, like that.
Similarly, you can put a long interpolated indented value like: \(..) Similarly, you can put a long interpolated indented value like: \(..)
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900
.. between a backslash and two periods." ..between a backslash and two periods."
say "Single-line text can contain escape sequences like \", \\, \000, and \n" say "Single-line text can contain escape sequences like \", \\, \000, and \n"
# How do I define a list? # How do I define a list?
%my_list = ["first", "second", "third", 4] $my_list = ["first", "second", "third", 4]
# Really long lists can use [..] followed by a bunch of indented values delimited # Really long lists can use [..] followed by a bunch of indented values delimited
by commas and/or newlines by commas and/or newlines
%my_really_long_list = [..] $my_really_long_list = [..]
10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000
120000, 130000, 140000, 150000, 160000, 170000 120000, 130000, 140000, 150000, 160000, 170000
# How do I use a list? # How do I use a list?
# Lists are 1-indexed because they're implemented as Lua tables, so this prints "first" # Lists are 1-indexed because they're implemented as Lua tables, so this prints "first"
say %my_list.1 say $my_list.1
# List entries can be modified like this: # List entries can be modified like this:
%my_list.1 = "ONE!!!" $my_list.1 = "ONE!!!"
# Or appended to/removed from: # Or appended to/removed from:
%my_list::add "extra item" $my_list|add "extra item"
%my_list::pop $my_list|pop
# How do I define a dictionary/hash map? # How do I define a dictionary/hash map?
One-word text keys don't need quotes, otherwise the key is an expression. One-word text keys don't need quotes, otherwise the key is an expression.
If the expression is more complex than a literal, it needs parentheses: If the expression is more complex than a literal, it needs parentheses:
%my_dict = {x: 101, y: 2, "how many bottles": 99, 653: 292, (5 + 6): 11} $my_dict = {x: 101, y: 2, "how many bottles": 99, 653: 292, (5 + 6): 11}
# How do I use a dict? # How do I use a dict?
# Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists # Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
say %my_dict.x say $my_dict.x
say %my_dict."how many bottles" say $my_dict."how many bottles"
say %my_dict.653 say $my_dict.653
%my_dict.x = 9999 $my_dict.x = 9999
# How do I do conditional branching? # How do I do conditional branching?
if (1 < 10): if (1 < 10):
@ -135,106 +134,106 @@ if (1 + 2) is:
say "this won't print" say "this won't print"
# How do I loop over a list (a foreach loop)? # How do I loop over a list (a foreach loop)?
%list = [1, 2, 3] $list = [1, 2, 3]
for %x in %list: for $x in $list:
say "For %x loop #\%x" say "For %x loop #\$x"
# How do I loop over a number range? # How do I loop over a number range?
# This is inclusive, so it will loop over 1,2, and 3 # This is inclusive, so it will loop over 1,2, and 3
for %i in 1 to 3: for $i in 1 to 3:
say "For %i in 1 to 3 loop #\%i" say "For %i in 1 to 3 loop #\$i"
# This will print 0,2, and 4 # This will print 0,2, and 4
for %even in 0 to 5 by 2: for $even in 0 to 5 by 2:
say "Even #\%even" say "Even #\$even"
for %backwards in 3 to 1 by -1: for $backwards in 3 to 1 by -1:
say "Backwards #\%backwards" say "Backwards #\$backwards"
# How do I do a 'while' loop? # How do I do a 'while' loop?
%x = 1 $x = 1
repeat while (%x <= 3): repeat while ($x <= 3):
say "repeat while loop #\%x" say "repeat while loop #\$x"
%x += 1 $x += 1
%x = 1 $x = 1
repeat until (%x > 3): repeat until ($x > 3):
say "repeat until loop #\%x" say "repeat until loop #\$x"
%x += 1 $x += 1
# How do I do an infinite loop? # How do I do an infinite loop?
%x = 1 $x = 1
repeat: repeat:
say "repeat loop #\%x" say "repeat loop #\$x"
%x += 1 $x += 1
if (%x > 3): stop if ($x > 3): stop
# How do I do a 'goto'? # How do I do a 'goto'?
do: do:
%x = 1 $x = 1
--- (my loop) --- --- (my loop) ---
say "GOTO loop #\%x" say "GOTO loop #\$x"
%x += 1 $x += 1
if (%x <= 3): if ($x <= 3):
go to (my loop) go to (my loop)
say "finished going to" say "finished going to"
# How do I define a function/method/procedure? # How do I define a function/method/procedure?
# In nomsu, they're called "action"s, and they can be declared like this: # In nomsu, they're called "action"s, and they can be declared like this:
(say both %first and also %second) means: (say both $first and also $second) means:
say %first say $first
say %second say $second
# Actions can have parts of the action's name spread throughout. # Actions can have parts of the action's name spread throughout.
Everything that's not a literal value is treated as part of the action's name Everything that's not a literal value is treated as part of the action's name
say both "Hello" and also "world!" say both "Hello" and also "world!"
# Actions can use "return" to return a value early # Actions can use "return" to return a value early
(first fibonacci above %n) means: (first fibonacci above $n) means:
%f1 = 0 $f1 = 0
%f2 = 1 $f2 = 1
repeat: repeat:
%tmp = (%f1 + %f2) $tmp = ($f1 + $f2)
%f1 = %f2 $f1 = $f2
%f2 = %tmp $f2 = $tmp
if (%f2 > %n): if ($f2 > $n):
return %f2 return $f2
say (first fibonacci above 10) say (first fibonacci above 10)
# Actions can have aliases, which may or may not have the arguments in different order # Actions can have aliases, which may or may not have the arguments in different order
[..] [..]
I hate %worse_things more than %better_things I hate $worse_things more than $better_things
I think %worse_things are worse than %better_things I think $worse_things are worse than $better_things
I like %better_things more than %worse_things I like $better_things more than $worse_things
..all mean: ..all mean:
say "\(%better_things::capitalized) rule and \%worse_things drool!" say "\($better_things|capitalized) rule and \$worse_things drool!"
I like "dogs" more than "cats" I like "dogs" more than "cats"
I think "chihuahuas" are worse than "corgis" I think "chihuahuas" are worse than "corgis"
# Actions can even start with a parameter # Actions can even start with a parameter
(%what_she_said is what she said) means: ($what_she_said is what she said) means:
say %what_she_said say $what_she_said
say "-- she said" say "-- she said"
"Howdy pardner" is what she said "Howdy pardner" is what she said
# The language only reserves []{}().,:;%#\ as special characters, so actions # The language only reserves []{}().,:;%#\ as special characters, so actions
can have really funky names! can have really funky names!
(>> %foo_bar $@&' -->< % @&_~-^-~_~-^ %1 !) means: (>> $foo_bar @&' -->< $ @&_~-^-~_~-^ $1 !) means:
say %foo_bar say $foo_bar
say % say $
say %1 say $1
>> "wow" $@&' -->< "so flexible!" @&_~-^-~_~-^ "even numbers can be variables!" ! >> "wow" @&' -->< "so flexible!" @&_~-^-~_~-^ "even numbers can be variables!" !
# There's also full unicode support # There's also full unicode support
%こんにちは = "こんにちは" $こんにちは = "こんにちは"
(% と言う) means "\%世界" ($ と言う) means "\($)世界"
say (%こんにちは と言う) say ($こんにちは と言う)
# Math and logic operations are just treated the same as actions in the syntax # Math and logic operations are just treated the same as actions in the syntax
say (2 + 3) say (2 + 3)
# So you can define your own operators, although they will need to be parenthesized to # So you can define your own operators, although they will need to be parenthesized to
play nicely with other operators play nicely with other operators
(%a ++ %b) means (2 * (%a + %b)) ($a ++ $b) means (2 * ($a + $b))
say (1 ++ (2 * 3)) say (1 ++ (2 * 3))
# How do I do grouping? # How do I do grouping?
@ -245,8 +244,8 @@ say (2 + 3)
say (2 + 3) say (2 + 3)
# If you need to keep going after an indented region, you can start the next line with ".." # If you need to keep going after an indented region, you can start the next line with ".."
say both "Very long first argument that needs its own line" and also "\ say both "Very long first argument that needs its own line" and also \
..short second arg" .."short second arg"
(my favorite number) means (21 + 2) (my favorite number) means (21 + 2)
# This can be nested: # This can be nested:
@ -260,19 +259,19 @@ say the time
say "Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2 % 5")" say "Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2 % 5")"
# Variables can be accessed via \%var # Variables can be accessed via \%var
(square root of %n) means (=lua "math.sqrt(\%n)") (square root of $n) means (=lua "math.sqrt(\$n)")
say "The square root of 2 is \(square root of 2)" say "The square root of 2 is \(square root of 2)"
# Macros can be defined to transform one bit of nomsu code into another using "parse % as %": # Macros can be defined to transform one bit of nomsu code into another using "parse % as %":
(if %condition is untrue %body) parses as (if (not %condition) %body) (if $condition is untrue $body) parses as (if (not $condition) $body)
# Or to transform nomsu code into custom lua code using "compile % to %" # Or to transform nomsu code into custom lua code using "compile % to %"
(debug only %body) compiles to: (debug only $body) compiles to:
if %DEBUG_ENABLED: if $DEBUG_ENABLED:
return (Lua "-- Debug code:\n\(%body as lua)") return (Lua "-- Debug code:\n\($body as lua)")
..else: ..else:
return (Lua "-- (debug code removed for production)") return (Lua "-- (debug code removed for production)")
%DEBUG_ENABLED = (yes) $DEBUG_ENABLED = (yes)
# Constants can be defined as macros # Constants can be defined as macros
(TWENTY) parses as 20 (TWENTY) parses as 20
@ -294,37 +293,37 @@ debug only:
# How do I use an action as a value? # How do I use an action as a value?
# Well... it's always *possible* to fall back to Lua behavior for something like this: # Well... it's always *possible* to fall back to Lua behavior for something like this:
(best of %items according to %key_fn) means: (best of $items according to $key_fn) means:
%best = (nil) $best = (nil)
%best_key = (nil) $best_key = (nil)
for %item in %items: for $item in $items:
%key = (%key_fn %item) $key = ($key_fn $item)
if ((%best is (nil)) or (%key > %best_key)): if (($best is (nil)) or ($key > $best_key)):
%best = %item $best = $item
%best_key = %key $best_key = $key
return %best return $best
# Function literals look like: %x -> (%x * %x) # Function literals look like: %x -> (%x * %x)
say (best of [2, -3, 4, -8] according to (%x -> (%x * %x))) say (best of [2, -3, 4, -8] according to ($x -> ($x * $x)))
# Or, you can use ((foo %)'s meaning) to access the function that gets called by (foo %) # Or, you can use ((foo %)'s meaning) to access the function that gets called by (foo %)
(%x squared) means (%x * %x) ($x squared) means ($x * $x)
say (best of [2, -3, 4, -8] according to ((% squared)'s meaning)) say (best of [2, -3, 4, -8] according to (($ squared)'s meaning))
# But nomsu was designed with flexible alternatives that are often better than passing functions. # But nomsu was designed with flexible alternatives that are often better than passing functions.
For example, instead of calling a key function on every item, you could instead define a macro For example, instead of calling a key function on every item, you could instead define a macro
that gives you a value based on an inlined expression: that gives you a value based on an inlined expression:
(best of %items where %item has score %key_expr) parses as (..) (best of $items where $item has score $key_expr) parses as (..)
result of: result of:
%best = (nil) $best = (nil)
%best_key = (nil) $best_key = (nil)
for %item in %items: for $item in $items:
%key = %key_expr $key = $key_expr
if ((%best is (nil)) or (%key > %best_key)): if (($best is (nil)) or ($key > $best_key)):
%best = %item $best = $item
%best_key = %key $best_key = $key
return %best return $best
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
say (best of [2, -3, 4, -8] where %x has score (%x * %x)) say (best of [2, -3, 4, -8] where $x has score ($x * $x))

View File

@ -1,50 +1,50 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines actions for encoding/decoding base 64, as specified in: This file defines actions for encoding/decoding base 64, as specified in:
https://tools.ietf.org/html/rfc4648 https://tools.ietf.org/html/rfc4648
%b64_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" $b64_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
%b64_chars = [: for % in 1 to (size of %b64_str): add (%b64_str::character %)] $b64_chars = [: for $ in 1 to (size of $b64_str): add ($b64_str|character $)]
%reverse_b64 = {: for %c in %b64_chars at %i: add %c = (%i - 1)} $reverse_b64 = {: for $c in $b64_chars at $i: add $c = ($i - 1)}
%reverse_b64."=" = 64 $reverse_b64."=" = 64
set %reverse_b64's metatable to {__index: -> 0} set $reverse_b64's metatable to {__index: -> 0}
test: test:
%cases = ["", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy"] $cases = ["", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy"]
for %len = %encoded in %cases: for $len = $encoded in $cases:
%plain = ("foobar"::from 1 to (%len - 1)) $plain = ("foobar"|from 1 to ($len - 1))
assume (base64 %plain) == %encoded assume (base64 $plain) == $encoded
assume (base64 decode %encoded) == %plain assume (base64 decode $encoded) == $plain
externally [base64 %str, base64 encode %str, %str base64] all mean: externally [base64 $str, base64 encode $str, $str base64] all mean:
%chars = [] $chars = []
for %i in 1 to (size of %str) via 3: for $i in 1 to (size of $str) via 3:
%bytes = [=lua "\%str:byte(\%i, \(%i + 2))"] $bytes = [=lua "\$str:byte(\$i, \($i + 2))"]
%chars::add %b64_chars.(((%bytes.1 & 252) >> 2) + 1) $chars|add $b64_chars.((($bytes.1 & 252) >> 2) + 1)
if (size of %bytes) is: if (size of $bytes) is:
3: 3:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1) $chars|add $b64_chars.((($bytes.1 & 3) << 4) + (($bytes.2 & 240) >> 4) + 1)
%chars::add %b64_chars.(((%bytes.2 & 15) << 2) + ((%bytes.3 & 192) >> 6) + 1) $chars|add $b64_chars.((($bytes.2 & 15) << 2) + (($bytes.3 & 192) >> 6) + 1)
%chars::add %b64_chars.((%bytes.3 & 63) + 1) $chars|add $b64_chars.(($bytes.3 & 63) + 1)
2: 2:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1) $chars|add $b64_chars.((($bytes.1 & 3) << 4) + (($bytes.2 & 240) >> 4) + 1)
%chars::add %b64_chars.(((%bytes.2 & 15) << 2) + 1) $chars|add $b64_chars.((($bytes.2 & 15) << 2) + 1)
%chars::add "=" $chars|add "="
1: 1:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + 1) $chars|add $b64_chars.((($bytes.1 & 3) << 4) + 1)
%chars::add "=" $chars|add "="
%chars::add "=" $chars|add "="
return (%chars::joined) return ($chars|joined)
externally (chr %) means (=lua "string.char(\%)") externally (chr $) means (=lua "string.char(\$)")
externally [decode base64 %str, %str base64 decoded, base64 decode %str] all mean: externally [decode base64 $str, $str base64 decoded, base64 decode $str] all mean:
%chars = [] $chars = []
for %i in 1 to (size of %str) via 4: for $i in 1 to (size of $str) via 4:
%indices = [: for %j in %i to (%i + 3): add %reverse_b64.(%str::character %j)] $indices = [: for $j in $i to ($i + 3): add $reverse_b64.($str|character $j)]
%chars::add (chr ((%indices.1 << 2) + ((%indices.2 & 48) >> 4))) $chars|add (chr (($indices.1 << 2) + (($indices.2 & 48) >> 4)))
if ((%str::character (%i + 2)) == "="): stop if (($str|character ($i + 2)) == "="): stop
%chars::add (chr (((%indices.2 & 15) << 4) + ((%indices.3 & 60) >> 2))) $chars|add (chr ((($indices.2 & 15) << 4) + (($indices.3 & 60) >> 2)))
if ((%str::character (%i + 3)) == "="): stop if (($str|character ($i + 3)) == "="): stop
%chars::add (chr (((%indices.3 & 3) << 6) + %indices.4)) $chars|add (chr ((($indices.3 & 3) << 6) + $indices.4))
return (%chars::joined) return ($chars|joined)

View File

@ -1,11 +1,11 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines actions for ANSI console color escape codes. This file defines actions for ANSI console color escape codes.
test: test:
% = (bright "\(green)Color test passed.") $ = (bright "\(green)Color test passed.")
%colors = {..} $colors = {..}
normal: 0, "reset color": 0, bright: 1, bold: 1, dim: 2, italic: 3, underscore: 4 normal: 0, "reset color": 0, bright: 1, bold: 1, dim: 2, italic: 3, underscore: 4
"slow blink": 5, "fast blink": 6, reverse: 7, inverse: 7, inverted: 7 "slow blink": 5, "fast blink": 6, reverse: 7, inverse: 7, inverted: 7
hidden: 8, # There's some other codes, but they're not currently implemented hidden: 8, # There's some other codes, but they're not currently implemented
@ -13,14 +13,14 @@ test:
white: 37, "on black": 40, "on red": 41, "on green": 42, "on yellow": 43 white: 37, "on black": 40, "on red": 41, "on green": 42, "on yellow": 43
"on blue": 44, "on magenta": 45, "on cyan": 46, "on white": 47 "on blue": 44, "on magenta": 45, "on cyan": 46, "on white": 47
for %name = %colornum in %colors: for $name = $colornum in $colors:
%colornum = "\%colornum" $colornum = "\$colornum"
#(=lua "COMPILE_ACTIONS").%name = (..) #(=lua "COMPILE_ACTIONS").%name = (..)
[%nomsu, %tree] -> (Lua "'\\027[\(%colornum)m'") [%nomsu, %tree] -> (Lua "'\\027[\(%colornum)m'")
%compile.action.%name = (..) $compile.action.$name = (..)
for (%compile %text): for ($compile $text):
if %text: if $text:
return (Lua "('\\027[\(%colornum)m'..\(%text as lua expr)..'\\027[0m')") return (Lua "('\\027[\($colornum)m'..\($text as lua expr)..'\\027[0m')")
..else: ..else:
return (Lua "'\\027[\(%colornum)m'") return (Lua "'\\027[\($colornum)m'")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines some actions for hashing files and looking up files by hash. This file defines some actions for hashing files and looking up files by hash.
@ -7,47 +7,47 @@ use "lib/base64.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lua> "local \%use_sha1, \%hashlib = pcall(require, 'openssl.digest')" lua> "local \$use_sha1, \$hashlib = pcall(require, 'openssl.digest')"
test: test:
assume (hash "hello world") == (hash "hello world") assume (hash "hello world") == (hash "hello world")
assume ((hash "hello world") != (hash "goodbye")) or barf "\ assume ((hash "hello world") != (hash "goodbye")) or barf "
..Hash collision: Hash collision:
(hash "hello world") = \(hash "hello world") (hash "hello world") = \(hash "hello world")
(hash "goodbye") = \(hash "goodbye")" (hash "goodbye") = \(hash "goodbye")"
assume (..) assume (..)
(..) (..)
hash "\ hash "
..This is a really long string meant to stress test the hashing function and This is a really long string meant to stress test the hashing function and
ensure that it's not overflowing with long inputs." ensure that it's not overflowing with long inputs."
..!= "inf" ..!= "inf"
assume ((hash "\000") != (hash "\000\000\000\000\000")) or barf "\ assume ((hash "\000") != (hash "\000\000\000\000\000")) or barf \
..Incorrect hashing of null strings" .."Incorrect hashing of null strings"
if %use_sha1: if $use_sha1:
assume ((hash "hello world") == "Kq5sNclPz7QV2+lfQIuc6R7oRu0=") assume ((hash "hello world") == "Kq5sNclPz7QV2+lfQIuc6R7oRu0=")
if %use_sha1: if $use_sha1:
externally (hash %) means: externally (hash $) means:
%hash = (=lua "\%hashlib.new('sha1'):final(\%)") $hash = (=lua "\$hashlib.new('sha1'):final(\$)")
return (base64 %hash) return (base64 $hash)
..else: ..else:
# TODO: remove warning? # TODO: remove warning?
say "\027[31;1mWARNING: OpenSSL module not found. Defaulting to a non-cryptographically secure hash function.\027[0m" say "\027[31;1mWARNING: OpenSSL module not found. Defaulting to a non-cryptographically secure hash function.\027[0m"
externally (hash %) means: externally (hash $) means:
%bytes = (%::bytes) $bytes = ($|bytes)
%hash = (%bytes.1 << 7) $hash = ($bytes.1 << 7)
for %i in 2 to (size of %bytes): for $i in 2 to (size of $bytes):
%hash = ((1000003 * %hash) ~ %bytes.%i) $hash = ((1000003 * $hash) ~ $bytes.$i)
%hash = (%hash ~ (size of %bytes)) $hash = ($hash ~ (size of $bytes))
return "\%hash" return "\$hash"
externally (file with hash %hash) means: externally (file with hash $hash) means:
for %filename in (files for "."): for $filename in (files for "."):
%contents = (read file %filename) $contents = (read file $filename)
%file_hash = (hash %contents) $file_hash = (hash $contents)
if (%file_hash == %hash): if ($file_hash == $hash):
return %filename return $filename
(hash of file %filename) parses as (hash (read file %filename)) (hash of file $filename) parses as (hash (read file $filename))

View File

@ -1,8 +1,8 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file contains the implementation of an Object-Oriented programming system. This file contains the implementation of an Object-Oriented programming system.
%globals.METAMETHOD_MAP = {..} $globals.METAMETHOD_MAP = {..}
"as text": "__tostring", "clean up": "__gc", "+ 1": "__add", "- 1": "__sub" "as text": "__tostring", "clean up": "__gc", "+ 1": "__add", "- 1": "__sub"
"* 1": "__mul", "/ 1": "__div", "-": "__unm", "// 1": "__idiv", "mod 1": "__mod" "* 1": "__mul", "/ 1": "__div", "-": "__unm", "// 1": "__idiv", "mod 1": "__mod"
"^ 1": "__pow", "& 1": "__band", "| 1": "__bor", "~ 1": "__bxor", "~": "__bnot" "^ 1": "__pow", "& 1": "__band", "| 1": "__bor", "~ 1": "__bxor", "~": "__bnot"
@ -14,83 +14,83 @@ test:
object (Dog): object (Dog):
(Dog).genus = "Canus" (Dog).genus = "Canus"
my action [set up]: my action [set up]:
%me.barks or= 0 $me.barks or= 0
my action [bark, woof]: my action [bark, woof]:
%barks = [: for % in 1 to %me.barks: add "Bark!"] $barks = [: for $ in 1 to $me.barks: add "Bark!"]
return (%barks::joined with " ") return ($barks|joined with " ")
my action [get pissed off]: %me.barks += 1 my action [get pissed off]: $me.barks += 1
%d = (Dog {barks: 2}) $d = (Dog {barks: 2})
assume (type of %d) == "Dog" assume (type of $d) == "Dog"
assume (%d is a "Dog") assume ($d is a "Dog")
assume %d.barks == 2 assume $d.barks == 2
assume ((%d::bark) == "Bark! Bark!") assume (($d|bark) == "Bark! Bark!")
assume ((%d::woof) == "Bark! Bark!") assume (($d|woof) == "Bark! Bark!")
%d::get pissed off $d|get pissed off
assume (%d.barks == 3) assume ($d.barks == 3)
assume ((%d::bark) == "Bark! Bark! Bark!") assume (($d|bark) == "Bark! Bark! Bark!")
assume (%d.genus == "Canus") assume ($d.genus == "Canus")
assume ("\(%d.class)" == "Dog") assume ("\($d.class)" == "Dog")
assume (%d.genus == "Canus") assume ($d.genus == "Canus")
assume (%d.barks == 3) assume ($d.barks == 3)
%d2 = (Dog {}) $d2 = (Dog {})
assume (%d2.barks == 0) or barf "Default initializer failed" assume ($d2.barks == 0) or barf "Default initializer failed"
with {%d: Dog {barks: 1}}: with {$d: Dog {barks: 1}}:
assume ((%d::bark) == "Bark!") assume (($d|bark) == "Bark!")
object (Corgi) extends (Dog): object (Corgi) extends (Dog):
my action [sploot] "splooted" my action [sploot] "splooted"
my action [bark, woof]: my action [bark, woof]:
%barks = [: for % in 1 to %me.barks: add "Yip!"] $barks = [: for $ in 1 to $me.barks: add "Yip!"]
return (%barks::joined with " ") return ($barks|joined with " ")
%corg = (Corgi {}) $corg = (Corgi {})
assume (%corg.barks == 0) assume ($corg.barks == 0)
with {%d: Corgi {barks: 1}}: with {$d: Corgi {barks: 1}}:
assume ((%d::sploot) == "splooted") or barf "subclass method failed" assume (($d|sploot) == "splooted") or barf "subclass method failed"
assume ((%d::bark) == "Yip!") or barf "inheritance failed" assume (($d|bark) == "Yip!") or barf "inheritance failed"
assume ((%d::woof) == "Yip!") assume (($d|woof) == "Yip!")
with {%d: Dog {barks: 2}}: with {$d: Dog {barks: 2}}:
assume ((%d::bark) == "Bark! Bark!") assume (($d|bark) == "Bark! Bark!")
(my action %actions %body) compiles to: (my action $actions $body) compiles to:
lua> "\ lua> "
..local fn_name = \%actions[1].stub:as_lua_id() local fn_name = \$actions[1].stub:as_lua_id()
local \%args = List(\%actions[1]:get_args()) local \$args = List(\$actions[1]:get_args())
table.insert(\%args, 1, \(\%me)) table.insert(\$args, 1, \(\$me))
local lua = LuaCode("class.", fn_name, " = ", \(what (%args -> %body) compiles to)) local lua = LuaCode("class.", fn_name, " = ", \(what ($args -> $body) compiles to))
for i=2,#\%actions do for i=2,#\$actions do
local alias = \%actions[i] local alias = \$actions[i]
local alias_name = alias.stub:as_lua_id() local alias_name = alias.stub:as_lua_id()
local \%alias_args = List(alias:get_args()) local \$alias_args = List(alias:get_args())
table.insert(\%alias_args, 1, \(\%me)) table.insert(\$alias_args, 1, \(\$me))
lua:add("\\nclass.", alias_name, " = ") lua:add("\\nclass.", alias_name, " = ")
if \%args == \%alias_args then if \$args == \$alias_args then
lua:add("class.", fn_name) lua:add("class.", fn_name)
else else
lua:add(\(what (%alias_args -> %actions.1) compiles to)) lua:add(\(what ($alias_args -> $actions.1) compiles to))
end end
end end
return lua" return lua"
(object %classname extends %parent %class_body) compiles to: (object $classname extends $parent $class_body) compiles to:
unless (%classname.type == "Action"): unless ($classname.type == "Action"):
compile error at %classname "\ compile error at $classname \
..Expected this to be an action, not a \%classname.type" .."Expected this to be an action, not a \$classname.type"
for % in %classname: for $ in $classname:
unless (% is text): unless ($ is text):
compile error at % "Class names should not have arguments." compile error at $ "Class names should not have arguments."
return (..) return (..)
Lua "\ Lua "
..do do
local class = {name=\(quote %classname.stub)} local class = {name=\(quote $classname.stub)}
class.__type = class.name class.__type = class.name
setmetatable(class, { setmetatable(class, {
__index=\(%parent as lua expr), __index=\($parent as lua expr),
__tostring=function(cls) return cls.name end, __tostring=function(cls) return cls.name end,
__call=function(cls, inst) __call=function(cls, inst)
if inst == nil then return cls end if inst == nil then return cls end
@ -105,11 +105,11 @@ test:
class.__tostring = function(inst) class.__tostring = function(inst)
return inst.name..getmetatable(Dict{}).__tostring(inst) return inst.name..getmetatable(Dict{}).__tostring(inst)
end end
\(%class_body as lua) \($class_body as lua)
for stub,metamethod in pairs(globals.METAMETHOD_MAP) do for stub,metamethod in pairs(globals.METAMETHOD_MAP) do
class[metamethod] = class[stub:as_lua_id()] class[metamethod] = class[stub:as_lua_id()]
end end
end" end"
(object %classname %class_body) parses as (..) (object $classname $class_body) parses as (..)
object %classname extends (nil) %class_body object $classname extends (nil) $class_body

View File

@ -1,25 +1,25 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines some actions that interact with the operating system and filesystem. This file defines some actions that interact with the operating system and filesystem.
test: test:
assume (nomsu files for "core") assume (nomsu files for "core")
externally (files for %path) means: externally (files for $path) means:
%files = (=lua "Files.list(\%path)") $files = (=lua "Files.list(\$path)")
if %files: if $files:
%files = (List %files) $files = (List $files)
return %files return $files
externally (nomsu files for %path) means: externally (nomsu files for $path) means:
for %nomsupath in (%package.nomsupath::all matches of "[^;]+"): for $nomsupath in ($package.nomsupath|all matches of "[^;]+"):
%files = (files for "\(%nomsupath)/\%path") $files = (files for "\($nomsupath)/\$path")
if %files: if $files:
return %files return $files
externally (sh> %cmd) means: externally (sh> $cmd) means:
lua> "\ lua> "
..local result = io.popen(\%cmd) local result = io.popen(\$cmd)
local contents = result:read("*a") local contents = result:read("*a")
result:close() result:close()
return contents" return contents"
@ -27,27 +27,24 @@ externally (sh> %cmd) means:
test: test:
read file "lib/os.nom" read file "lib/os.nom"
externally (read file %filename) means (=lua "Files.read(\%filename)") externally (read file $filename) means (=lua "Files.read(\$filename)")
externally [..] externally [..]
write to file %filename %text, to file %filename write %text write to file $filename $text, to file $filename write $text
write %text to file %filename write $text to file $filename
..all mean: ..all mean:
assume (%filename != "stdin") or barf "Cannot write to stdin" assume ($filename != "stdin") or barf "Cannot write to stdin"
lua> "\ lua> "local file = io.open(\$filename, 'w')\nfile:write(\$text)\nfile:close()"
..local file = io.open(\%filename, 'w')
file:write(\%text)
file:close()"
externally (source lines of %tree) means: externally (source lines of $tree) means:
%source = (%tree.source if (%tree is syntax tree) else %tree) $source = ($tree.source if ($tree is syntax tree) else $tree)
%file = (read file %source.filename) $file = (read file $source.filename)
return (..) return (..)
[..] [..]
: :
for % in (%file::line number at %source.start) to (..) for $ in ($file|line number at $source.start) to (..)
%file::line number at %source.stop $file|line number at $source.stop
..: add (%file::line %) ..: add ($file|line $)
..::joined with "\n" ..|joined with "\n"
externally (spoof file %text) means (%Files.spoof %text) externally (spoof file $text) means ($Files.spoof $text)
externally (spoof file %filename = %text) means (%Files.spoof %filename %text) externally (spoof file $filename = $text) means ($Files.spoof $filename $text)

View File

@ -1,140 +1,137 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
A library for simple object oriented programming. A library for simple object oriented programming.
test: test:
an (Empty) is a thing an (Empty) is a thing
a (Dog) is a thing: a (Dog) is a thing:
[%it, %its] = [Dog, Dog] [$it, $its] = [Dog, Dog]
(%its::set up) means: ($its|set up) means:
%its.barks or= 0 $its.barks or= 0
[%its::bark, %its::woof] all mean: [$its|bark, $its|woof] all mean:
%barks = [: for % in 1 to %its.barks: add "Bark!"] $barks = [: for $ in 1 to $its.barks: add "Bark!"]
return (%barks::joined with " ") return ($barks|joined with " ")
(%it::gets pissed off) means: %it.barks += 1 ($it|gets pissed off) means: $it.barks += 1
(Dog).genus = "Canus" (Dog).genus = "Canus"
%d = (a Dog with {barks: 2}) $d = (a Dog with {barks: 2})
assume "\%d" == "Dog {barks: 2}" assume "\$d" == "Dog {barks: 2}"
assume (type of %d) == "Dog" assume (type of $d) == "Dog"
assume (%d is a "Dog") assume ($d is a "Dog")
assume %d.barks == 2 assume $d.barks == 2
assume ((%d::bark) == "Bark! Bark!") assume (($d|bark) == "Bark! Bark!")
assume ((%d::woof) == "Bark! Bark!") assume (($d|woof) == "Bark! Bark!")
%d::gets pissed off $d|gets pissed off
assume (%d.barks == 3) assume ($d.barks == 3)
assume ((%d::bark) == "Bark! Bark! Bark!") assume (($d|bark) == "Bark! Bark! Bark!")
assume (%d.genus == "Canus") assume ($d.genus == "Canus")
assume ("\(%d.class)" == "Dog") assume ("\($d.class)" == "Dog")
assume (%d.genus == "Canus") assume ($d.genus == "Canus")
assume (%d.barks == 3) assume ($d.barks == 3)
%d2 = (a Dog) $d2 = (a Dog)
assume (%d2.barks == 0) or barf "Default initializer failed" assume ($d2.barks == 0) or barf "Default initializer failed"
with {%d: a Dog with {barks: 1}}: with {$d: a Dog with {barks: 1}}:
assume ((%d::bark) == "Bark!") assume (($d|bark) == "Bark!")
a (Corgi) is a thing: a (Corgi) is a thing:
[%it, %its] = [Corgi, Corgi] [$it, $its] = [Corgi, Corgi]
%it [set up, gets pissed off] like a (Dog) $it [set up, gets pissed off] like a (Dog)
(%it::as text) means "Dogloaf \{: for %k = %v in %it: add %k = %v}" ($it|as text) means "Dogloaf \{: for $k = $v in $it: add $k = $v}"
(%its::sploot) means "sploooot" ($its|sploot) means "sploooot"
[%its::bark, %its::woof] all mean: [$its|bark, $its|woof] all mean:
%barks = [: for % in 1 to %its.barks: add "Yip!"] $barks = [: for $ in 1 to $its.barks: add "Yip!"]
return (%barks::joined with " ") return ($barks|joined with " ")
%corg = (a Corgi) $corg = (a Corgi)
assume (%corg.barks == 0) assume ($corg.barks == 0)
assume "\%corg" == "Dogloaf {barks: 0}" assume "\$corg" == "Dogloaf {barks: 0}"
with {%d: a Corgi with {barks: 1}}: with {$d: a Corgi with {barks: 1}}:
assume ((%d::sploot) == "sploooot") or barf "subclass method failed" assume (($d|sploot) == "sploooot") or barf "subclass method failed"
assume ((%d::bark) == "Yip!") or barf "inheritance failed" assume (($d|bark) == "Yip!") or barf "inheritance failed"
assume ((%d::woof) == "Yip!") assume (($d|woof) == "Yip!")
with {%d: a Dog with {barks: 2}}: with {$d: a Dog with {barks: 2}}:
assume ((%d::bark) == "Bark! Bark!") assume (($d|bark) == "Bark! Bark!")
a (Vec) is a thing with {x, y}: a (Vec) is a thing with {x, y}:
%its = (Vec) $its = (Vec)
(%its::+ %other) means (Vec {x: %its.x + %other.x, y: %its.y + %other.y}) ($its|+ $other) means (Vec {x: $its.x + $other.x, y: $its.y + $other.y})
assume ((Vec {x: 1, y: 2}) + (Vec {x: 10, y: 10})) == (Vec {x: 11, y: 12}) assume ((Vec {x: 1, y: 2}) + (Vec {x: 10, y: 10})) == (Vec {x: 11, y: 12})
assume (((Vec {x: 1, y: 2}) + (Vec {x: 10, y: 10})) != (Vec {x: 0, y: 0})) assume (((Vec {x: 1, y: 2}) + (Vec {x: 10, y: 10})) != (Vec {x: 0, y: 0}))
[..] [..]
%it can %actions like a %class, %it can %actions like an %class $it can $actions like a $class, $it can $actions like an $class
%it has %actions like a %class, %it has %actions like an %class $it has $actions like a $class, $it has $actions like an $class
%it %actions like a %class, %it %actions like an %class $it $actions like a $class, $it $actions like an $class
..all compile to: ..all compile to:
%lua = (Lua "") $lua = (Lua "")
%class_expr = (%class as lua expr) $class_expr = ($class as lua expr)
%lines = [] $lines = []
for %a in %actions: for $a in $actions:
%lines::add "\ $lines|
..\(%it as lua expr).\(%a.stub::as lua id) = \%class_expr.\(%a.stub::as lua id)" add "\($it as lua expr).\($a.stub|as lua id) = \$class_expr.\($a.stub|as lua id)"
%lua::add %lines joined with "\n" $lua|add $lines joined with "\n"
return %lua return $lua
%METAMETHOD_MAP = {..} $METAMETHOD_MAP = {..}
"as text": "__tostring", "clean up": "__gc", "+": "__add", "-": "__sub" "as text": "__tostring", "clean up": "__gc", "+": "__add", "-": "__sub"
"*": "__mul", "/": "__div", negative: "__unm", "//": "__idiv", mod: "__mod" "*": "__mul", "/": "__div", negative: "__unm", "//": "__idiv", mod: "__mod"
"^": "__pow", "&": "__band", "|": "__bor", "~": "__bxor", "~": "__bnot" "^": "__pow", "&": "__band", "|": "__bor", "~": "__bxor", "~": "__bnot"
"<<": "__bshl", ">>": "__bshr", "==": "__eq", "<": "__lt", "<=": "__le" "<<": "__bshl", ">>": "__bshr", "==": "__eq", "<": "__lt", "<=": "__le"
"set 1 =": "__newindex", size: "__len", iterate: "__ipairs", "iterate all": "__pairs" "set 1 =": "__newindex", size: "__len", iterate: "__ipairs", "iterate all": "__pairs"
((% as text like a dict)'s meaning) = ({}'s metatable).__tostring (($ as text like a dict)'s meaning) = ({}'s metatable).__tostring
externally (a class named %classname with %members ((initialize %it)'s meaning)) \ externally (a class named $classname with $members ((initialize $it)'s meaning)) \
..means: ..means:
%class = {__type: %classname} $class = {__type: $classname}
%class.__index = %class $class.__index = $class
%class.class = %class $class.class = $class
%class.__tostring = (% -> "\(%.__type) \(% as text like a dict)") $class.__tostring = ($ -> "\($.__type) \($ as text like a dict)")
%class.__eq = ({}'s metatable).__eq $class.__eq = ({}'s metatable).__eq
%class.__len = ({}'s metatable).__len $class.__len = ({}'s metatable).__len
if %members: if $members:
%class.__members = %members $class.__members = $members
%class.__newindex = (..) $class.__newindex = (..)
for (%its %key = %value): for ($its $key = $value):
if %members.%key: if $members.$key:
rawset %its %key %value rawset $its $key $value
..else: ..else:
barf "Cannot set \%key, it's not one of the allowed member fields." barf "Cannot set \$key, it's not one of the allowed member fields."
set %class's metatable to {..} set $class's metatable to {..}
__tostring: %class -> %class.__type __tostring: $class -> $class.__type, __call: for ($class with $initial_values):
__call: for (%class with %initial_values): if ($initial_values == (nil)): return $class
if (%initial_values == (nil)): return %class set $initial_values's metatable to $class
set %initial_values's metatable to %class if $initial_values.set_up:
if %initial_values.set_up: $initial_values|set up
%initial_values::set up return $initial_values
return %initial_values
if ((initialize)'s meaning): if ((initialize)'s meaning):
initialize %class initialize $class
for %stub = %metamethod in %METAMETHOD_MAP: for $stub = $metamethod in $METAMETHOD_MAP:
if %class.(%stub::as lua id): if $class.($stub|as lua id):
%class.%metamethod = %class.(%stub::as lua id) $class.$metamethod = $class.($stub|as lua id)
return %class return $class
[..] [..]
a %classname is a thing with %members %class_body a $classname is a thing with $members $class_body
an %classname is a thing with %members %class_body an $classname is a thing with $members $class_body
..all compile to: ..all compile to:
%class_id = (%classname.stub::as lua id) $class_id = ($classname.stub|as lua id)
if %class_body: if $class_body:
%body_lua = (%class_body as lua) $body_lua = ($class_body as lua)
%body_lua::remove free vars [%class_id] $body_lua|remove free vars [$class_id]
%body_lua::declare locals $body_lua|declare locals
return (..) return (..)
Lua "\ Lua "
..\%class_id = a_class_named_1_with(\(quote %classname.stub), \(%members as lua)\(..) \$class_id = a_class_named_1_with(\(quote $classname.stub), \($members as lua)\((Lua ", function(\$class_id)\n \$body_lua\nend") if $class_body else "")\
(Lua ", function(\%class_id)\n \%body_lua\nend") if %class_body else ""
..) ..)
a_\%class_id = function(initial_values) return \(%classname.stub::as lua id)(initial_values or {}) end a_\$class_id = function(initial_values) return \($classname.stub|as lua id)(initial_values or {}) end
an_\%class_id, a_\(%class_id)_with, an_\(%class_id)_with = \ an_\$class_id, a_\($class_id)_with, an_\($class_id)_with = a_\$class_id, a_\$class_id, a_\$class_id"
..a_\%class_id, a_\%class_id, a_\%class_id"
[a %classname is a thing %class_body, an %classname is a thing] all parse as (..) [a $classname is a thing $class_body, an $classname is a thing] all parse as (..)
a %classname is a thing with (nil) %class_body a $classname is a thing with (nil) $class_body

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
Auto-format Nomsu code. Usage: Auto-format Nomsu code. Usage:
nomsu tools/autoformat.nom [-i] file1 file2 directory1 ... nomsu tools/autoformat.nom [-i] file1 file2 directory1 ...
@ -9,18 +9,18 @@ use "lib/os.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%args = (command line args) $args = (command line args)
for %filename in %args.extra_args: for $filename in $args.extra_args:
%file = (read file %filename) $file = (read file $filename)
unless %file: unless $file:
barf "File does not exist: \%filename" barf "File does not exist: \$filename"
%leading_indent = (%file::matching "[\n]*([ ]*)") $leading_indent = ($file|matching "[\n]*([ ]*)")
%code = (NomsuCode from (%Source %filename 1 (size of %file)) %file) $code = (NomsuCode from ($Source $filename 1 (size of $file)) $file)
%tree = (%code parsed) $tree = ($code parsed)
%formatted = "\ $formatted = "
..\%leading_indent\(((%tree as nomsu)::text)::with "\n" -> "\n\%leading_indent")" \$leading_indent\((($tree as nomsu)|text)|with "\n" -> "\n\$leading_indent")"
if %args."-i": if $args."-i":
write %formatted to file %filename write $formatted to file $filename
..else: ..else:
say %formatted inline say $formatted inline

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
Find an action by its stub. Usage: Find an action by its stub. Usage:
nomsu tools/find_action.nom "foo %" file1 file2 directory1 ... nomsu tools/find_action.nom "foo %" file1 file2 directory1 ...
@ -9,33 +9,33 @@ use "lib/consolecolor.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%stub = (command line args).extra_args.1 $stub = (command line args).extra_args.1
say "Looking for stub: \%stub..." say "Looking for stub: \$stub..."
for % in 2 to (size of (command line args).extra_args): for $ in 2 to (size of (command line args).extra_args):
%filename = (command line args).extra_args.% $filename = (command line args).extra_args.$
%file = (read file %filename) $file = (read file $filename)
unless %file: unless $file:
barf "File does not exist: \%filename" barf "File does not exist: \$filename"
%code = (NomsuCode from (%Source %filename 1 (size of %file)) %file) $code = (NomsuCode from ($Source $filename 1 (size of $file)) $file)
try: try:
%tree = (%code parsed) $tree = ($code parsed)
..and if it barfs %msg: ..and if it barfs $msg:
say (red "\%filename failed to parse:\n\%msg") say (red "\$filename failed to parse:\n\$msg")
%tree = (nil) $tree = (nil)
unless %tree: unless $tree:
do next %filename do next $filename
%results = [] $results = []
for %t in recursive %tree: for $t in recursive $tree:
if ((%t is "Action" syntax tree) and (%t.stub is %stub)): if (($t is "Action" syntax tree) and ($t.stub is $stub)):
%line_num = (%file::line number at %t.source.start) $line_num = ($file|line number at $t.source.start)
%results::add {..} $results|
line: %line_num, text: "\(blue "\%filename:\%line_num:")\n\(yellow (source lines of %t))" add {line: $line_num, text: "\(blue "\$filename:\$line_num:")\n\(yellow (source lines of $t))"}
if (%t is syntax tree): if ($t is syntax tree):
for %sub in %t: for $sub in $t:
recurse %t on %sub recurse $t on $sub
sort %results by % -> %.line sort $results by $ -> $.line
for % in %results: for $ in $results:
say %.text say $.text

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
Tool to print out a parse tree of files in an easy-to-read format. Usage: Tool to print out a parse tree of files in an easy-to-read format. Usage:
nomsu tools/parse.nom file1 file2 directory1 ... nomsu tools/parse.nom file1 file2 directory1 ...
@ -7,39 +7,39 @@ use "lib/os.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
externally (print tree %t at indent %indent) means: externally (print tree $t at indent $indent) means:
if %t.type is: if $t.type is:
"Action": "Action":
say "\(%indent)Action (\(%t.stub)):" say "\($indent)Action (\($t.stub)):"
for %arg in %t: for $arg in $t:
if (%arg is syntax tree): if ($arg is syntax tree):
print tree %arg at indent "\%indent " print tree $arg at indent "\$indent "
"MethodCall": "MethodCall":
say "\(%indent)MethodCall on:" say "\($indent)MethodCall on:"
print tree %t.1 at indent "\%indent " print tree $t.1 at indent "\$indent "
print tree %t.2 at indent "\%indent " print tree $t.2 at indent "\$indent "
"Number": "Number":
say "\%indent\(%t.1)" say "\$indent\($t.1)"
"Var": "Var":
say "\(%indent)%\(%t.1)" say "\($indent)%\($t.1)"
else: else:
say "\%indent\(%t.type):" say "\$indent\($t.type):"
for %arg in %t: for $arg in $t:
when: when:
(%arg is syntax tree): ($arg is syntax tree):
print tree %arg at indent "\%indent " print tree $arg at indent "\$indent "
else: else:
say "\%indent \(quote %arg)" say "\$indent \(quote $arg)"
for %filename in (command line args).extra_args: for $filename in (command line args).extra_args:
%file = (read file %filename) $file = (read file $filename)
unless %file: unless $file:
barf "File does not exist: \%filename" barf "File does not exist: \$filename"
%nomsu = (NomsuCode from (Source %filename 1 (size of %file)) %file) $nomsu = (NomsuCode from (Source $filename 1 (size of $file)) $file)
%tree = (%nomsu parsed) $tree = ($nomsu parsed)
print tree %tree at indent "" print tree $tree at indent ""

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
This file defines a Read-Evaluate-Print-Loop (REPL) for Nomsu This file defines a Read-Evaluate-Print-Loop (REPL) for Nomsu
@ -9,53 +9,53 @@ use "lib/os.nom"
externally [quit, exit] all mean: lua> "os.exit(0)" externally [quit, exit] all mean: lua> "os.exit(0)"
externally (help) means: externally (help) means:
say "\ say "
..This is the Nomsu v\(Nomsu version) interactive console. This is the Nomsu v\(Nomsu version) interactive console.
You can type in Nomsu code here and hit 'enter' twice to run it. You can type in Nomsu code here and hit 'enter' twice to run it.
To exit, type 'exit' or 'quit' and hit enter twice." To exit, type 'exit' or 'quit' and hit enter twice."
say "\ say "
..
\(bright)\(underscore)Welcome to the Nomsu v\(Nomsu version) interactive console!\(reset color) \(bright)\(underscore)Welcome to the Nomsu v\(Nomsu version) interactive console!\(reset color)
press 'enter' twice to run a command press 'enter' twice to run a command
" "
repeat: repeat:
say (bright (yellow ">> ")) inline say (bright (yellow ">> ")) inline
%buff = [] $buff = []
repeat: repeat:
say (bright) inline say (bright) inline
%line = (%io.read "*L") $line = ($io.read "*L")
say (reset color) inline say (reset color) inline
if ((%line == "\n") or (not %line)): if (($line == "\n") or (not $line)):
if ((size of %buff) > 0): if ((size of $buff) > 0):
# clear the line # clear the line
say "\027[1A\027[2K" inline say "\027[1A\027[2K" inline
go to (run buffer) go to (run buffer)
%buff::add (%line::with "\t" -> " ") $buff|add ($line|with "\t" -> " ")
say (dim (yellow ".. ")) inline say (dim (yellow ".. ")) inline
--- (run buffer) --- --- (run buffer) ---
if ((size of %buff) == 0): stop if ((size of $buff) == 0): stop
%buff = (%buff::joined) $buff = ($buff|joined)
# TODO: support local variables # TODO: support local variables
spoof file %buff spoof file $buff
try: try:
%ret = (run %buff) $ret = (run $buff)
..and if it barfs %err: say %err ..and if it barfs $err: say $err
..or if it succeeds: ..or if it succeeds:
if (type of %ret) is: if (type of $ret) is:
"nil": "nil":
do nothing do nothing
"boolean": "boolean":
say "= \("yes" if %ret else "no")" say "= \("yes" if $ret else "no")"
"table": "table":
if %ret.as_nomsu: if $ret.as_nomsu:
say "= \(%ret::as nomsu)" say "= \($ret|as nomsu)"
..else: ..else:
say "= \%ret" say "= \$ret"
else: else:
say "= \%ret" say "= \$ret"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
Tool to run all tests in a file (i.e. the code block inside a call to 'test %'). Usage: Tool to run all tests in a file (i.e. the code block inside a call to 'test %'). Usage:
nomsu tools/test.nom file1 file2 directory1 ... nomsu tools/test.nom file1 file2 directory1 ...
@ -9,26 +9,26 @@ use "lib/consolecolor.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Make sure all the files get run # Make sure all the files get run
for %filename in (command line args).extra_args: use %filename for $filename in (command line args).extra_args: use $filename
%tests = {: for %s = %t in (tests): add (=lua "Source:from_string(\%s)") = %t} $tests = {: for $s = $t in (tests): add (=lua "Source:from_string(\$s)") = $t}
for %filename in (command line args).extra_args: for $filename in (command line args).extra_args:
%file = (read file %filename) $file = (read file $filename)
%version = (%file::matching "#![^\n]* nomsu %-V[ ]*([^\n]*)") $version = ($file|matching "#![^\n]* nomsu %-V[ ]*([^\n]*)")
%file_tests = [] $file_tests = []
for %src = %test in %tests: for $src = $test in $tests:
if (%src.filename == %filename): if ($src.filename == $filename):
if %version: if $version:
%test = "#!/usr/bin/env nomsu -V\%version\n\%test" $test = "#!/usr/bin/env nomsu -V\$version\n\$test"
%file_tests::add {test: %test, source: %src} $file_tests|add {test: $test, source: $src}
unless (%file_tests is empty): unless ($file_tests is empty):
sort %file_tests by % -> %.source sort $file_tests by $ -> $.source
lua> "io.write('[ .. ] ', \%filename); io.flush()" lua> "io.write('[ .. ] ', \$filename); io.flush()"
if (command line args)."-v": say "" if (command line args)."-v": say ""
for % in %file_tests: for $ in $file_tests:
if (command line args)."-v": if (command line args)."-v":
say " \(yellow (%.test::with "\n" -> "\n "))" say " \(yellow ($.test|with "\n" -> "\n "))"
run %.test run $.test
if (command line args)."-v": if (command line args)."-v":
say (green "PASS") say (green "PASS")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env nomsu -V4.12.12.8 #!/usr/bin/env nomsu -V5.12.12.8
# #
Tool to automatically update code from old versions of Nomsu. Usage: Tool to automatically update code from old versions of Nomsu. Usage:
nomsu tools/upgrade.nom [-i] file1 file2 directory1 ... nomsu tools/upgrade.nom [-i] file1 file2 directory1 ...
@ -11,32 +11,32 @@ use "lib/consolecolor.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%args = (command line args) $args = (command line args)
%inplace = (%args."-i" or %args."--inplace") $inplace = ($args."-i" or $args."--inplace")
%start_version = %args."--upgrade-from" $start_version = $args."--upgrade-from"
%version = (%args."--upgrade-to" or (Nomsu version)) $version = ($args."--upgrade-to" or (Nomsu version))
%test = (%args."-t" or %args."--test") $test = ($args."-t" or $args."--test")
for %filename in %args.extra_args: for $filename in $args.extra_args:
%file = (read file %filename) $file = (read file $filename)
unless %file: unless $file:
barf "File does not exist: \%filename" barf "File does not exist: \$filename"
%leading_indent = (%file::matching "[\n]*([ ]*)") $leading_indent = ($file|matching "[\n]*([ ]*)")
%code = (NomsuCode from (Source %filename 1 (size of %file)) %file) $code = (NomsuCode from (Source $filename 1 (size of $file)) $file)
%tree = (%code parsed) $tree = ($code parsed)
%uptree = (..) $uptree = (..)
%tree upgraded from (%start_version or (%tree.version or (Nomsu version))) to \ $tree upgraded from ($start_version or ($tree.version or (Nomsu version))) to \
..%version ..$version
%text = "\%leading_indent\(((%uptree as nomsu)::text)::with "\n" -> "\n\%leading_indent")" $text = "\$leading_indent\((($uptree as nomsu)|text)|with "\n" -> "\n\$leading_indent")"
when: when:
%inplace: $inplace:
say "Upgraded \%filename" say "Upgraded \$filename"
write %text to file %filename write $text to file $filename
%test: $test:
if (%uptree == %tree): if ($uptree == $tree):
say (dim "\%filename will not be changed") say (dim "\$filename will not be changed")
..else: ..else:
say (bright "\%filename will be changed") say (bright "\$filename will be changed")
else: else:
say %text inline say $text inline