Fully working version of (action [foo]: baz) -> ((foo) means: baz)
refactor and misc other changes.
This commit is contained in:
parent
e7e84c9eda
commit
ea3197aaff
@ -25,12 +25,12 @@ say "Hello"
|
||||
for %num in %my_nums:
|
||||
say "\%num is one of my nums"
|
||||
|
||||
action [sing %n bottles of beer]:
|
||||
(sing %n bottles of beer) means:
|
||||
for %i in %n to 1 by -1:
|
||||
say ".."
|
||||
\%i bottle\("s" if (%i > 1) else "") of beer on the wall,
|
||||
say "\
|
||||
..\%i bottle\("s" if (%i > 1) else "") of beer on the wall,
|
||||
\%i bottle\("s" if (%i > 1) else "") of beer!
|
||||
Take one down, pass it around...
|
||||
Take one down, pass it around..."
|
||||
say "No bottles of beer on the wall. Go to the store, buy some more..."
|
||||
|
||||
sing 99 bottles of beer
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains code for defining ways to upgrade code between different versions
|
||||
of Nomsu.
|
||||
@ -6,17 +6,17 @@
|
||||
use "lib/os.nom"
|
||||
|
||||
%UPGRADES = {}
|
||||
action [upgrade to %version via %upgrade_fn]:
|
||||
externally (upgrade to %version via %upgrade_fn) means:
|
||||
%UPGRADES.%version = %upgrade_fn
|
||||
|
||||
%ACTION_UPGRADES = ({} with fallback % -> {})
|
||||
action [upgrade action %stub to %version via %upgrade_fn]:
|
||||
externally (upgrade action %stub to %version via %upgrade_fn) means:
|
||||
%ACTION_UPGRADES.%version.%stub = %upgrade_fn
|
||||
|
||||
parse [upgrade %tree to %version as %body] as (..)
|
||||
upgrade to %version via ([%] -> (% with %tree -> %body))
|
||||
(upgrade %tree to %version as %body) parses as (..)
|
||||
upgrade to %version via ([%, %end_version] -> (% with %tree -> %body))
|
||||
|
||||
compile [upgrade action %actions to %version as %body] to:
|
||||
(upgrade action %actions to %version as %body) compiles to:
|
||||
if (%actions is "Action" syntax tree):
|
||||
%actions = \[%actions]
|
||||
%lua = (Lua "")
|
||||
@ -27,7 +27,7 @@ compile [upgrade action %actions to %version as %body] to:
|
||||
%replacements.(%action.%i.1) = "\(\%tree as lua id)[\%i]"
|
||||
|
||||
define mangler
|
||||
local action [make tree %t]:
|
||||
(make tree %t) means:
|
||||
when:
|
||||
(%t is "Var" syntax tree):
|
||||
if %replacements.(%t.1):
|
||||
@ -60,11 +60,12 @@ compile [upgrade action %actions to %version as %body] to:
|
||||
|
||||
return %lua
|
||||
|
||||
action [..]
|
||||
externally [..]
|
||||
%tree upgraded from %start_version to %end_version
|
||||
%tree upgraded to %end_version from %start_version
|
||||
..:
|
||||
local action [%ver as list] ((% as number) for % in %ver matching "[0-9]+")
|
||||
..all mean:
|
||||
unless (%tree is syntax tree): return %tree
|
||||
(%ver as list) means ((% as number) for % in %ver matching "[0-9]+")
|
||||
%versions = {}
|
||||
for %v = % in %UPGRADES:
|
||||
%versions.%v = (yes)
|
||||
@ -78,25 +79,31 @@ action [..]
|
||||
%tree = (..)
|
||||
%tree with % -> (..)
|
||||
if ((% is "Action" syntax tree) and %ACTION_UPGRADES.%ver.(%.stub)):
|
||||
return (call %ACTION_UPGRADES.%ver.(%.stub) with [%])
|
||||
%with_upgraded_args = (..)
|
||||
%k = (%v upgraded from %start_version to %end_version) \
|
||||
..for %k = %v in %
|
||||
set %with_upgraded_args's metatable to (%'s metatable)
|
||||
return (call %ACTION_UPGRADES.%ver.(%.stub) with [%with_upgraded_args, %end_version])
|
||||
|
||||
if %UPGRADES.%ver:
|
||||
%tree = (call %UPGRADES.%ver with [%tree])
|
||||
%with_upgraded_args = (..)
|
||||
%k = (%v upgraded from %start_version to %end_version) \
|
||||
..for %k = %v in %tree
|
||||
set %with_upgraded_args's metatable to (%tree's metatable)
|
||||
%tree = (call %UPGRADES.%ver with [%with_upgraded_args, %end_version])
|
||||
|
||||
return %tree
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
parse [%tree upgraded from %start_version] as (..)
|
||||
externally (%tree upgraded from %start_version) means (..)
|
||||
%tree upgraded from %start_version to (Nomsu version)
|
||||
|
||||
parse [%tree upgraded to %end_version] as (..)
|
||||
externally (%tree upgraded to %end_version) means (..)
|
||||
%tree upgraded from (%tree.version or (Nomsu version)) to %end_version
|
||||
|
||||
parse [%tree upgraded] as (..)
|
||||
externally (%tree upgraded) means (..)
|
||||
%tree upgraded from (%tree.version or (Nomsu version)) to (Nomsu version)
|
||||
|
||||
action [use %path from version %version]:
|
||||
externally (use %path from version %version) means:
|
||||
for file %filename in %path:
|
||||
if (=lua "LOADED[\%filename]"): do next %filename
|
||||
%file = (read file %filename)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains code that supports manipulating and using collections like lists
|
||||
and dictionaries.
|
||||
@ -45,17 +45,17 @@ test:
|
||||
# List Comprehension
|
||||
test:
|
||||
assume (((% * %) for % in [1, 2, 3]) == [1, 4, 9])
|
||||
parse [%expression for %item in %iterable] as (..)
|
||||
(%expression for %item in %iterable) parses as (..)
|
||||
result of:
|
||||
%comprehension = []
|
||||
for %item in %iterable:
|
||||
%comprehension::add %expression
|
||||
return %comprehension
|
||||
|
||||
parse [..]
|
||||
[..]
|
||||
%expression for %index in %start to %stop via %step
|
||||
%expression for %index in %start to %stop by %step
|
||||
..as (..)
|
||||
..all parse as (..)
|
||||
result of:
|
||||
%comprehension = []
|
||||
for %index in %start to %stop via %step:
|
||||
@ -66,15 +66,15 @@ parse [..]
|
||||
|
||||
test:
|
||||
assume (((% * %) for % in 1 to 3) == [1, 4, 9])
|
||||
parse [%expression for %var in %start to %stop] as (..)
|
||||
(%expression for %var in %start to %stop) parses as (..)
|
||||
%expression for %var in %start to %stop via 1
|
||||
|
||||
test:
|
||||
assume (("\%k,\%v" for %k = %v in {x:1}) == ["x,1"])
|
||||
parse [..]
|
||||
[..]
|
||||
%expression for %key = %value in %iterable
|
||||
%expression for %key %value in %iterable
|
||||
..as (..)
|
||||
..all parse as (..)
|
||||
result of:
|
||||
%comprehension = []
|
||||
for %key = %value in %iterable:
|
||||
@ -84,7 +84,9 @@ parse [..]
|
||||
# Dict comprehensions
|
||||
test:
|
||||
assume (((% * %) = % for % in [1, 2, 3]) == {1:1, 4:2, 9:3})
|
||||
parse [%key = %value for %item in %iterable, %key %value for %item in %iterable] as (..)
|
||||
[..]
|
||||
%key = %value for %item in %iterable, %key %value for %item in %iterable
|
||||
..all parse as (..)
|
||||
result of:
|
||||
%comprehension = {}
|
||||
for %item in %iterable:
|
||||
@ -93,20 +95,20 @@ parse [%key = %value for %item in %iterable, %key %value for %item in %iterable]
|
||||
|
||||
test:
|
||||
assume ((%k = (%v * %v) for %k = %v in {x:1, y:2, z:3}) == {x:1, y:4, z:9})
|
||||
parse [..]
|
||||
[..]
|
||||
%key = %value for %src_key = %src_value in %iterable
|
||||
%key %value for %src_key %src_value in %iterable
|
||||
..as (..)
|
||||
..all parse as (..)
|
||||
result of:
|
||||
%comprehension = {}
|
||||
for %src_key = %src_value in %iterable:
|
||||
%comprehension.%key = %value
|
||||
return %comprehension
|
||||
|
||||
parse [..]
|
||||
[..]
|
||||
%key = %value for %item in %start to %stop via %step
|
||||
%key %value for %item in %start to %stop via %step
|
||||
..as (..)
|
||||
..all parse as (..)
|
||||
result of:
|
||||
%comprehension = {}
|
||||
for %item in %start to %stop via %step:
|
||||
@ -117,14 +119,14 @@ parse [..]
|
||||
|
||||
test:
|
||||
assume (((% * %) = % for % in 1 to 3) == {1:1, 4:2, 9:3})
|
||||
parse [..]
|
||||
[..]
|
||||
%key = %value for %item in %start to %stop
|
||||
%key %value for %item in %start to %stop
|
||||
..as (%key = %value for %item in %start to %stop via 1)
|
||||
..all parse as (%key = %value for %item in %start to %stop via 1)
|
||||
|
||||
test:
|
||||
assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4])
|
||||
action [%lists flattened]:
|
||||
externally (%lists flattened) means:
|
||||
%flat = []
|
||||
for %list in %lists:
|
||||
for %item in %list: %flat::add %item
|
||||
@ -132,29 +134,30 @@ action [%lists flattened]:
|
||||
|
||||
test:
|
||||
assume ((entries in {x:1}) == [{key:"x", value:1}])
|
||||
parse [entries in %dict] as ({key:%k, value:%v} for %k = %v in %dict)
|
||||
(entries in %dict) parses as ({key:%k, value:%v} for %k = %v in %dict)
|
||||
|
||||
test:
|
||||
assume ((keys in {x:1}) == ["x"])
|
||||
parse [keys in %dict, keys of %dict] as (%k for %k = %v in %dict)
|
||||
[keys in %dict, keys of %dict] all parse as (%k for %k = %v in %dict)
|
||||
|
||||
test:
|
||||
assume ((values in {x:1}) == [1])
|
||||
parse [values in %dict, values of %dict] as (%v for %k = %v in %dict)
|
||||
[values in %dict, values of %dict] all parse as (%v for %k = %v in %dict)
|
||||
|
||||
# Metatable stuff
|
||||
test:
|
||||
%t = {}
|
||||
set %t 's metatable to {__tostring:[%] -> "XXX"}
|
||||
assume ("\%t" == "XXX")
|
||||
compile [set %dict 's metatable to %metatable] to (..)
|
||||
(set %dict 's metatable to %metatable) compiles to (..)
|
||||
Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
|
||||
compile [%'s metatable, %' metatable] to (..)
|
||||
|
||||
[% 's metatable, % 'metatable] all compile to (..)
|
||||
Lua value "getmetatable(\(% as lua expr))"
|
||||
|
||||
test:
|
||||
assume (({} with fallback % -> (% + 1)).10 == 11)
|
||||
compile [%dict with fallback %key -> %value] to (..)
|
||||
(%dict with fallback %key -> %value) compiles to (..)
|
||||
Lua value "\
|
||||
..(function(d)
|
||||
local mt = {}
|
||||
@ -177,8 +180,10 @@ test:
|
||||
%keys = {1:999, 2:0, 3:50}
|
||||
sort %x by % = %keys.%
|
||||
assume (%x == [2, 3, 1])
|
||||
compile [sort %items] to (Lua "table.sort(\(%items as lua expr));")
|
||||
parse [sort %items by %item = %key_expr, sort %items by %item -> %key_expr] as (..)
|
||||
(sort %items) compiles to (Lua "table.sort(\(%items as lua expr));")
|
||||
[..]
|
||||
sort %items by %item = %key_expr, sort %items by %item -> %key_expr
|
||||
..all parse as (..)
|
||||
do:
|
||||
%keys = ({} with fallback %item -> %key_expr)
|
||||
lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)"
|
||||
@ -187,12 +192,12 @@ parse [sort %items by %item = %key_expr, sort %items by %item -> %key_expr] as (
|
||||
|
||||
test:
|
||||
assume ((sorted [3, 1, 2]) == [1, 2, 3])
|
||||
action [%items sorted, sorted %items]:
|
||||
externally [%items sorted, sorted %items] all mean:
|
||||
%copy = (% for % in %items)
|
||||
sort %copy
|
||||
return %copy
|
||||
|
||||
parse [%items sorted by %item = %key, %items sorted by %item -> %key] as (..)
|
||||
[%items sorted by %item = %key, %items sorted by %item -> %key] all parse as (..)
|
||||
result of:
|
||||
%copy = (% for % in %items)
|
||||
sort %copy by %item = %key
|
||||
@ -200,7 +205,7 @@ parse [%items sorted by %item = %key, %items sorted by %item -> %key] as (..)
|
||||
|
||||
test:
|
||||
assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3])
|
||||
action [unique %items]:
|
||||
externally (unique %items) means:
|
||||
%unique = []
|
||||
%seen = {}
|
||||
for % in %items:
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains compile-time actions that define basic control flow structures
|
||||
like "if" statements and loops.
|
||||
@ -10,13 +10,13 @@ use "core/errors.nom"
|
||||
|
||||
# No-Op
|
||||
test: do nothing
|
||||
compile [do nothing] to (Lua "")
|
||||
(do nothing) compiles to (Lua "")
|
||||
|
||||
# Conditionals
|
||||
test:
|
||||
if (no):
|
||||
barf "conditional fail"
|
||||
compile [if %condition %if_body] to:
|
||||
(if %condition %if_body) compiles to:
|
||||
%lua = (Lua "if ")
|
||||
%lua::append (%condition as lua expr)
|
||||
%lua::append " then\n "
|
||||
@ -27,10 +27,10 @@ compile [if %condition %if_body] to:
|
||||
test:
|
||||
unless (yes):
|
||||
barf "conditional fail"
|
||||
parse [unless %condition %unless_body] as (if (not %condition) %unless_body)
|
||||
compile [..]
|
||||
(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
|
||||
..to:
|
||||
..all compile to:
|
||||
%lua = (Lua "if ")
|
||||
%lua::append (%condition as lua expr)
|
||||
%lua::append " then\n "
|
||||
@ -48,12 +48,12 @@ compile [..]
|
||||
test:
|
||||
assume ((1 if (yes) else 2) == 1)
|
||||
assume ((1 if (no) else 2) == 2)
|
||||
compile [..]
|
||||
[..]
|
||||
%when_true_expr if %condition else %when_false_expr
|
||||
%when_true_expr if %condition otherwise %when_false_expr
|
||||
%when_false_expr unless %condition else %when_true_expr
|
||||
%when_false_expr unless %condition then %when_true_expr
|
||||
..to:
|
||||
..all compile to:
|
||||
# If %when_true_expr is guaranteed to be truthy, we can use Lua's idiomatic
|
||||
equivalent of a conditional expression: (cond and if_true or if_false)
|
||||
if {Text:yes, List:yes, Dict:yes, Number:yes}.(%when_true_expr.type):
|
||||
@ -89,15 +89,21 @@ test:
|
||||
%i -= 1
|
||||
unless (%i == 0): go to (Loop)
|
||||
assume (%i == 0)
|
||||
compile [=== %label ===, --- %label ---, *** %label ***] to (..)
|
||||
Lua "::label_\((%label.stub if (%label.type == "Action") else %label) as lua identifier)::"
|
||||
[=== %label ===, --- %label ---, *** %label ***] all compile to (..)
|
||||
Lua "\
|
||||
..::label_\(..)
|
||||
(%label.stub if (%label.type == "Action") else %label) as lua identifier
|
||||
..::"
|
||||
|
||||
compile [go to %label] to (..)
|
||||
Lua "goto label_\((%label.stub if (%label.type == "Action") else %label) as lua identifier)"
|
||||
(go to %label) compiles to (..)
|
||||
Lua "\
|
||||
..goto label_\(..)
|
||||
(%label.stub if (%label.type == "Action") else %label) as lua identifier
|
||||
.."
|
||||
|
||||
# Basic loop control
|
||||
compile [do next] to (Lua "goto continue")
|
||||
compile [stop] to (Lua "break")
|
||||
(do next) compiles to (Lua "goto continue")
|
||||
(stop) compiles to (Lua "break")
|
||||
|
||||
# While loops
|
||||
test:
|
||||
@ -119,9 +125,9 @@ test:
|
||||
barf "Failed to 'do next repeat'"
|
||||
|
||||
assume (%x == 30)
|
||||
compile [do next repeat] to (Lua "goto continue_repeat")
|
||||
compile [stop repeating] to (Lua "goto stop_repeat")
|
||||
compile [repeat while %condition %body] to:
|
||||
(do next repeat) compiles to (Lua "goto continue_repeat")
|
||||
(stop repeating) compiles to (Lua "goto stop_repeat")
|
||||
(repeat while %condition %body) compiles to:
|
||||
%lua = (..)
|
||||
Lua "\
|
||||
..while \(%condition as lua expr) do
|
||||
@ -137,25 +143,24 @@ compile [repeat while %condition %body] to:
|
||||
%lua = (Lua "do -- scope of 'stop repeating' label\n ")
|
||||
%lua::append %inner_lua
|
||||
%lua::append "\
|
||||
..
|
||||
::stop_repeat::
|
||||
end -- end of 'stop repeating' label scope"
|
||||
..
|
||||
::stop_repeat::
|
||||
end -- end of 'stop repeating' label scope"
|
||||
|
||||
return %lua
|
||||
|
||||
parse [repeat %body] as (repeat while (yes) %body)
|
||||
parse [repeat until %condition %body] as (repeat while (not %condition) %body)
|
||||
(repeat %body) parses as (repeat while (yes) %body)
|
||||
(repeat until %condition %body) parses as (repeat while (not %condition) %body)
|
||||
|
||||
test:
|
||||
%x = 0
|
||||
repeat 10 times: %x += 1
|
||||
assume (%x == 10)
|
||||
compile [repeat %n times %body] to:
|
||||
(repeat %n times %body) compiles to:
|
||||
define mangler
|
||||
%lua = (..)
|
||||
Lua "for \(mangle "i")=1,\(%n as lua expr) do\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next repeat)):
|
||||
@ -166,21 +171,20 @@ compile [repeat %n times %body] to:
|
||||
%lua = (Lua "do -- scope of 'stop repeating' label\n ")
|
||||
%lua::append %inner_lua
|
||||
%lua::append "\
|
||||
..
|
||||
::stop_repeat::
|
||||
end -- end of 'stop repeating' label scope"
|
||||
..
|
||||
::stop_repeat::
|
||||
end -- end of 'stop repeating' label scope"
|
||||
|
||||
return %lua
|
||||
|
||||
# For loop control flow
|
||||
compile [stop %var] to (..)
|
||||
(stop %var) compiles to (..)
|
||||
Lua "goto stop_\((%var.stub if (%var.type == "Action") else %var) as lua identifier)"
|
||||
compile [do next %var] to (..)
|
||||
(do next %var) compiles to (..)
|
||||
Lua "goto continue_\((%var.stub if (%var.type == "Action") else %var) as lua identifier)"
|
||||
compile [===stop %var ===, ---stop %var ---, ***stop %var ***] to (..)
|
||||
[===stop %var ===, ---stop %var ---, ***stop %var ***] all compile to (..)
|
||||
Lua "::stop_\((%var.stub if (%var.type == "Action") else %var) as lua identifier)::"
|
||||
|
||||
compile [===next %var ===, ---next %var ---, ***next %var ***] to (..)
|
||||
[===next %var ===, ---next %var ---, ***next %var ***] all compile to (..)
|
||||
Lua "::continue_\((%var.stub if (%var.type == "Action") else %var) as lua identifier)::"
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -205,10 +209,10 @@ test:
|
||||
assume (%nums == [1, -2, 3, -2, 3, 4, 3, 4, 5])
|
||||
|
||||
# Numeric range for loops
|
||||
compile [..]
|
||||
[..]
|
||||
for %var in %start to %stop by %step %body
|
||||
for %var in %start to %stop via %step %body
|
||||
..to:
|
||||
..all compile to:
|
||||
# This uses Lua's approach of only allowing loop-scoped variables in a loop
|
||||
unless (%var.type is "Var"):
|
||||
compile error at %var "Expected a variable here, not a \(%var.type)"
|
||||
@ -217,28 +221,29 @@ compile [..]
|
||||
..for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(..)
|
||||
%step as lua expr
|
||||
.. do"
|
||||
|
||||
%lua::append "\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next %var)):
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===next %var ===))
|
||||
%lua::append (what (===next %var ===) compiles to)
|
||||
|
||||
%lua::append "\nend --numeric for-loop"
|
||||
if (%body has subtree \(stop %var)):
|
||||
%inner_lua = %lua
|
||||
%lua = (Lua "do -- scope for stopping for-loop\n ")
|
||||
%lua::append %inner_lua
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===stop %var ===))
|
||||
%lua::append (what (===stop %var ===) compiles to)
|
||||
%lua::append "\nend -- end of scope for stopping for-loop"
|
||||
|
||||
return %lua
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
parse [for %var in %start to %stop %body] as (..)
|
||||
(for %var in %start to %stop %body) parses as (..)
|
||||
for %var in %start to %stop via 1 %body
|
||||
|
||||
test:
|
||||
@ -255,48 +260,48 @@ test:
|
||||
assume (%b == [20, 30, 40])
|
||||
|
||||
# For-each loop (lua's "ipairs()")
|
||||
compile [for %var in %iterable %body] to:
|
||||
(for %var in %iterable %body) compiles to:
|
||||
define mangler
|
||||
# This uses Lua's approach of only allowing loop-scoped variables in a loop
|
||||
%lua = (..)
|
||||
Lua "for \(mangle "i"),\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next %var)):
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===next %var ===))
|
||||
%lua::append (what (===next %var ===) compiles to)
|
||||
|
||||
%lua::append "\nend --foreach-loop"
|
||||
if (%body has subtree \(stop %var)):
|
||||
%inner_lua = %lua
|
||||
%lua = (Lua "do -- scope for stopping for-loop\n ")
|
||||
%lua::append %inner_lua
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===stop %var ===))
|
||||
%lua::append (what (===stop %var ===) compiles to)
|
||||
%lua::append "\nend -- end of scope for stopping for-loop"
|
||||
|
||||
return %lua
|
||||
|
||||
# TODO: reduce code duplication
|
||||
compile [for %var in %iterable at %i %body] to:
|
||||
(for %var in %iterable at %i %body) compiles to:
|
||||
# This uses Lua's approach of only allowing loop-scoped variables in a loop
|
||||
%lua = (..)
|
||||
Lua "for \(%i as lua identifier),\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next %var)):
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===next %var ===))
|
||||
%lua::append (what (===next %var ===) compiles to)
|
||||
|
||||
%lua::append "\nend --foreach-loop"
|
||||
if (%body has subtree \(stop %var)):
|
||||
%inner_lua = %lua
|
||||
%lua = (Lua "do -- scope for stopping for-loop\n ")
|
||||
%lua::append %inner_lua
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===stop %var ===))
|
||||
%lua::append (what (===stop %var ===) compiles to)
|
||||
%lua::append "\nend -- end of scope for stopping for-loop"
|
||||
|
||||
return %lua
|
||||
@ -312,9 +317,9 @@ test:
|
||||
assume ((%result sorted) == ["c = 30", "d = 40", "e = 50"])
|
||||
|
||||
# Dict iteration (lua's "pairs()")
|
||||
compile [..]
|
||||
[..]
|
||||
for %key = %value in %iterable %body, for %key %value in %iterable %body
|
||||
..to:
|
||||
..all compile to:
|
||||
# This uses Lua's approach of only allowing loop-scoped variables in a loop
|
||||
unless (%key.type is "Var"):
|
||||
compile error at %key "Expected a variable here, not a \(%key.type)"
|
||||
@ -325,25 +330,29 @@ compile [..]
|
||||
..for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(..)
|
||||
%iterable as lua expr
|
||||
..) do"
|
||||
|
||||
%lua::append "\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next %key)):
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===next %key ===))
|
||||
%lua::append (what (===next %key ===) compiles to)
|
||||
|
||||
if (%body has subtree \(do next %value)):
|
||||
%lua::append "\n "
|
||||
%lua::append (compile as (===next %value ===))
|
||||
%lua::append (what (===next %value ===) compiles to)
|
||||
|
||||
%lua::append "\nend --foreach-loop"
|
||||
%stop_labels = (Lua "")
|
||||
if (%body has subtree \(stop %key)):
|
||||
%stop_labels::append "\n"
|
||||
%stop_labels::append (compile as (===stop %key ===))
|
||||
%stop_labels::append (what (===stop %key ===) compiles to)
|
||||
|
||||
if (%body has subtree \(stop %value)):
|
||||
%stop_labels::append "\n"
|
||||
%stop_labels::append (compile as (===stop %value ===))
|
||||
%stop_labels::append (what (===stop %value ===) compiles to)
|
||||
|
||||
if ((size of "\%stop_labels") > 0):
|
||||
%inner_lua = %lua
|
||||
%lua = (Lua "do -- scope for stopping for % = % loop\n ")
|
||||
@ -368,13 +377,14 @@ test:
|
||||
barf "bad conditional"
|
||||
|
||||
# Multi-branch conditional (if..elseif..else)
|
||||
compile [if %body, when %body] to:
|
||||
[if %body, when %body] all compile to:
|
||||
%code = (Lua "")
|
||||
%clause = "if"
|
||||
%else_allowed = (yes)
|
||||
unless (%body.type is "Block"):
|
||||
compile error at %body "'if' expected a Block, but got a \(%body.type)."
|
||||
..hint "Perhaps you forgot to put a ':' after 'if'?"
|
||||
|
||||
for %line in %body:
|
||||
unless (..)
|
||||
((%line.type is "Action") and ((size of %line) >= 2)) and (..)
|
||||
@ -389,13 +399,14 @@ compile [if %body, when %body] to:
|
||||
unless %else_allowed:
|
||||
compile error at %line "You can't have two 'else' blocks."
|
||||
..hint "Merge all of the 'else' blocks together."
|
||||
|
||||
unless ((size of "\%code") > 0):
|
||||
compile error at %line "\
|
||||
..You can't have an 'else' block without a preceeding condition"
|
||||
..hint "If you want the code in this block to always execute, you don't \
|
||||
..need a conditional block around it. Otherwise, make sure the 'else' \
|
||||
..block comes last."
|
||||
|
||||
|
||||
%code::append "\nelse\n "
|
||||
%code::append (%action as lua statements)
|
||||
%else_allowed = (no)
|
||||
@ -428,7 +439,7 @@ test:
|
||||
barf "bad switch statement"
|
||||
|
||||
# Switch statement
|
||||
compile [if %branch_value is %body, when %branch_value is %body] to:
|
||||
[if %branch_value is %body, when %branch_value is %body] all compile to:
|
||||
%code = (Lua "")
|
||||
%clause = "if"
|
||||
%else_allowed = (yes)
|
||||
@ -488,7 +499,7 @@ compile [if %branch_value is %body, when %branch_value is %body] to:
|
||||
return %lua
|
||||
|
||||
# Do/finally
|
||||
compile [do %action] to:
|
||||
(do %action) compiles to:
|
||||
%lua = (Lua "do\n ")
|
||||
%lua::append (%action as lua statements)
|
||||
%lua::append "\nend -- do"
|
||||
@ -504,7 +515,7 @@ test:
|
||||
..and if it barfs: do nothing
|
||||
|
||||
assume (%d.x == "good")
|
||||
compile [do %action then always %final_action] to:
|
||||
(do %action then always %final_action) compiles to:
|
||||
define mangler
|
||||
%lua = (..)
|
||||
Lua "\
|
||||
@ -528,7 +539,7 @@ test:
|
||||
assume ((result of (: return 99)) == 99)
|
||||
|
||||
# Inline thunk:
|
||||
compile [result of %body] to (Lua value "\(compile as ([] -> %body))()")
|
||||
(result of %body) compiles to (Lua value "\(what ([] -> %body) compiles to)()")
|
||||
|
||||
test:
|
||||
%t = [1, [2, [[3], 4], 5, [[[6]]]]]
|
||||
@ -541,10 +552,10 @@ test:
|
||||
assume (sorted %flat) == [1, 2, 3, 4, 5, 6]
|
||||
|
||||
# Recurion control flow
|
||||
compile [for %var in recursive %structure %body] to:
|
||||
(for %var in recursive %structure %body) compiles to:
|
||||
with local compile actions:
|
||||
define mangler
|
||||
compile [recurse %v on %x] to (..)
|
||||
(recurse %v on %x) compiles to (..)
|
||||
Lua "table.insert(\(mangle "stack \(%v.1)"), \(%x as lua expr))"
|
||||
%lua = (..)
|
||||
Lua "\
|
||||
@ -554,13 +565,12 @@ compile [for %var in recursive %structure %body] to:
|
||||
\(%var as lua expr) = table.remove(\(mangle "stack \(%var.1)"), 1)"
|
||||
%lua::append "\n "
|
||||
%lua::append (%body as lua statements)
|
||||
|
||||
if (%body has subtree \(do next)):
|
||||
%lua::append "\n ::continue::"
|
||||
if (%body has subtree \(do next %var)):
|
||||
%lua::append "\n \(compile as (===next %var ===))"
|
||||
%lua::append "\n \(what (===next %var ===) compiles to)"
|
||||
%lua::append "\n end -- Recursive loop"
|
||||
if (%body has subtree \(stop %var)):
|
||||
%lua::append "\n \(compile as (===stop %var ===))"
|
||||
%lua::append "\n \(what (===stop %var ===) compiles to)"
|
||||
%lua::append "\nend -- Recursive scope"
|
||||
return %lua
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines the code that creates and manipulates coroutines
|
||||
|
||||
@ -14,15 +14,15 @@ test:
|
||||
|
||||
for % in coroutine %co: %nums::add %
|
||||
assume (%nums == [4, 5, 6, 6, 6]) or barf "Coroutine iteration failed"
|
||||
compile [coroutine %body, generator %body] to (..)
|
||||
[coroutine %body, generator %body] all compile to (..)
|
||||
Lua value "\
|
||||
..(function()
|
||||
\(%body as lua statements)
|
||||
end)"
|
||||
|
||||
compile [->] to (Lua value "coroutine.yield(true)")
|
||||
compile [-> %] to (Lua value "coroutine.yield(true, \(% as lua expr))")
|
||||
compile [for % in coroutine %co %body] to (..)
|
||||
(->) compiles to (Lua value "coroutine.yield(true)")
|
||||
(-> %) compiles to (Lua value "coroutine.yield(true, \(% as lua expr))")
|
||||
(for % in coroutine %co %body) compiles to (..)
|
||||
Lua "\
|
||||
..for junk,\(% as lua expr) in coroutine.wrap(\(%co as lua expr)) do
|
||||
\(%body as lua statements)
|
||||
|
@ -1,17 +1,17 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains basic error reporting code
|
||||
|
||||
use "core/metaprogramming.nom"
|
||||
|
||||
compile [barf] to (Lua "error(nil, 0);")
|
||||
compile [barf %msg] to (Lua "error(\(%msg as lua expr), 0);")
|
||||
compile [compile error at %tree %msg] to (..)
|
||||
(barf) compiles to (Lua "error(nil, 0);")
|
||||
(barf %msg) compiles to (Lua "error(\(%msg as lua expr), 0);")
|
||||
(compile error at %tree %msg) compiles to (..)
|
||||
Lua "nomsu:compile_error(\(%tree as lua expr), \(%msg as lua expr))"
|
||||
compile [compile error at %tree %msg hint %hint] to (..)
|
||||
(compile error at %tree %msg hint %hint) compiles to (..)
|
||||
Lua "nomsu:compile_error(\(%tree as lua expr), \(%msg as lua expr), \(%hint as lua expr))"
|
||||
|
||||
compile [assume %condition] to:
|
||||
(assume %condition) compiles to:
|
||||
lua> "\
|
||||
..local \%assumption = 'Assumption failed: '..tostring(nomsu:tree_to_nomsu(\%condition))"
|
||||
return (..)
|
||||
@ -20,7 +20,7 @@ compile [assume %condition] to:
|
||||
error(\(quote "\%assumption"), 0)
|
||||
end"
|
||||
|
||||
compile [assume %a == %b] to:
|
||||
(assume %a == %b) compiles to:
|
||||
lua> "\
|
||||
..local \%assumption = 'Assumption failed: '..tostring(nomsu:tree_to_nomsu(\(\(%a == %b))))"
|
||||
define mangler
|
||||
@ -35,7 +35,7 @@ compile [assume %a == %b] to:
|
||||
end
|
||||
end"
|
||||
|
||||
compile [assume %condition or barf %message] to (..)
|
||||
(assume %condition or barf %message) compiles to (..)
|
||||
Lua "\
|
||||
..if not \(%condition as lua expr) then
|
||||
error(\(%message as lua expr), 0)
|
||||
@ -55,10 +55,10 @@ test:
|
||||
assume (%x == 3) or barf "do/then always failed"
|
||||
|
||||
# Try/except
|
||||
compile [..]
|
||||
[..]
|
||||
try %action and if it succeeds %success or if it barfs %msg %fallback
|
||||
try %action and if it barfs %msg %fallback or if it succeeds %success
|
||||
..to (..)
|
||||
..all compile to (..)
|
||||
Lua "\
|
||||
..do
|
||||
local fell_through = false
|
||||
@ -84,21 +84,22 @@ compile [..]
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
parse [..]
|
||||
[..]
|
||||
try %action and if it succeeds %success or if it barfs %fallback
|
||||
try %action and if it barfs %fallback or if it succeeds %success
|
||||
..as (try %action and if it succeeds %success or if it barfs (=lua "") %fallback)
|
||||
..all parse as (..)
|
||||
try %action and if it succeeds %success or if it barfs (=lua "") %fallback
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
parse [try %action] as (..)
|
||||
(try %action) parses as (..)
|
||||
try %action and if it succeeds (do nothing) or if it barfs (do nothing)
|
||||
|
||||
parse [try %action and if it barfs %fallback] as (..)
|
||||
(try %action and if it barfs %fallback) parses as (..)
|
||||
try %action and if it succeeds (do nothing) or if it barfs %fallback
|
||||
|
||||
parse [try %action and if it barfs %msg %fallback] as (..)
|
||||
(try %action and if it barfs %msg %fallback) parses as (..)
|
||||
try %action and if it succeeds (do nothing) or if it barfs %msg %fallback
|
||||
|
||||
parse [try %action and if it succeeds %success] as (..)
|
||||
(try %action and if it succeeds %success) parses as (..)
|
||||
try %action and if it succeeds %success or if it barfs (do nothing)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
A simple UUID function based on RFC 4122: http://www.ietf.org/rfc/rfc4122.txt
|
||||
|
||||
@ -27,7 +27,7 @@ set %id_by_obj 's metatable to {..}
|
||||
%obj_by_id.%id = %key
|
||||
return %id
|
||||
|
||||
action [uuid]:
|
||||
externally (uuid) means:
|
||||
# Set all the other bits to randomly (or pseudo-randomly) chosen values.
|
||||
%bytes = [..]
|
||||
# time-low, time-mid, time-high-and-version
|
||||
@ -56,4 +56,4 @@ test:
|
||||
seed random with 0
|
||||
assume ((id of %x) != (id of []))
|
||||
seed random
|
||||
action [id of %, %'s id, %' id] %id_by_obj.%
|
||||
externally [id of %, %'s id, %'id] all mean %id_by_obj.%
|
||||
|
@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains basic input/output code
|
||||
|
||||
use "core/metaprogramming.nom"
|
||||
|
||||
compile [say %message] to (..)
|
||||
(say %message) compiles to (..)
|
||||
lua> "\
|
||||
..if \%message.type == "Text" then
|
||||
return LuaCode(tree.source, "print(", \(%message as lua expr), ");");
|
||||
@ -12,7 +12,7 @@ compile [say %message] to (..)
|
||||
return LuaCode(tree.source, "print(tostring(", \(%message as lua expr), "));");
|
||||
end"
|
||||
|
||||
compile [ask %prompt] to (..)
|
||||
(ask %prompt) compiles to (..)
|
||||
lua> "\
|
||||
..if \%prompt.type == "Text" then
|
||||
return LuaCode.Value(tree.source, "(io.write(", \(%prompt as lua expr), ") and io.read())");
|
||||
|
162
core/math.nom
162
core/math.nom
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines some common math literals and functions
|
||||
|
||||
@ -14,17 +14,18 @@ test:
|
||||
..math constants failed"
|
||||
%nan = (NaN)
|
||||
assume (%nan != %nan) or barf "NaN failed"
|
||||
compile [infinity, inf] to (Lua value "math.huge")
|
||||
compile [not a number, NaN, nan] to (Lua value "(0/0)")
|
||||
compile [pi, Pi, PI] to (Lua value "math.pi")
|
||||
compile [tau, Tau, TAU] to (Lua value "(2*math.pi)")
|
||||
compile [golden ratio] to (Lua value "((1+math.sqrt(5))/2)")
|
||||
compile [e] to (Lua value "math.exp(1)")
|
||||
[infinity, inf] all compile to (Lua value "math.huge")
|
||||
[not a number, NaN, nan] all compile to (Lua value "(0/0)")
|
||||
[pi, Pi, PI] all compile to (Lua value "math.pi")
|
||||
[tau, Tau, TAU] all compile to (Lua value "(2*math.pi)")
|
||||
(golden ratio) compiles to (Lua value "((1+math.sqrt(5))/2)")
|
||||
(e) compiles to (Lua value "math.exp(1)")
|
||||
|
||||
# Functions:
|
||||
test:
|
||||
assume (("5" as a number) == 5)
|
||||
compile [% as a number, % as number] to (Lua value "tonumber(\(% as lua expr))")
|
||||
[% as a number, % as number] all compile to (..)
|
||||
Lua value "tonumber(\(% as lua expr))"
|
||||
|
||||
test:
|
||||
assume (..)
|
||||
@ -33,105 +34,127 @@ test:
|
||||
arc tangent 5, arc tangent 5 / 10, hyperbolic sine 5, hyperbolic cosine 5
|
||||
hyperbolic tangent 5, e^ 5, ln 5, log base 2 of 5, floor 5, ceiling 5, round 5
|
||||
..or barf "math functions failed"
|
||||
compile [absolute value %, | % |, abs %] to (..)
|
||||
[absolute value %, | % |, abs %] all compile to (..)
|
||||
Lua value "math.abs(\(% as lua expr))"
|
||||
|
||||
compile [square root %, square root of %, √ %, sqrt %] to (..)
|
||||
[square root %, square root of %, √ %, sqrt %] all compile to (..)
|
||||
Lua value "math.sqrt(\(% as lua expr))"
|
||||
|
||||
compile [sine %, sin %] to (Lua value "math.sin(\(% as lua expr))")
|
||||
compile [cosine %, cos %] to (Lua value "math.cos(\(% as lua expr))")
|
||||
compile [tangent %, tan %] to (Lua value "math.tan(\(% as lua expr))")
|
||||
compile [arc sine %, asin %] to (Lua value "math.asin(\(% as lua expr))")
|
||||
compile [arc cosine %, acos %] to (Lua value "math.acos(\(% as lua expr))")
|
||||
compile [arc tangent %, atan %] to (Lua value "math.atan(\(% as lua expr))")
|
||||
compile [arc tangent %y / %x, atan2 %y %x] to (..)
|
||||
[sine %, sin %] all compile to (Lua value "math.sin(\(% as lua expr))")
|
||||
[cosine %, cos %] all compile to (Lua value "math.cos(\(% as lua expr))")
|
||||
[tangent %, tan %] all compile to (Lua value "math.tan(\(% as lua expr))")
|
||||
[arc sine %, asin %] all compile to (Lua value "math.asin(\(% as lua expr))")
|
||||
[arc cosine %, acos %] all compile to (Lua value "math.acos(\(% as lua expr))")
|
||||
[arc tangent %, atan %] all compile to (Lua value "math.atan(\(% as lua expr))")
|
||||
[arc tangent %y / %x, atan2 %y %x] all compile to (..)
|
||||
Lua value "math.atan2(\(%y as lua expr), \(%x as lua expr))"
|
||||
|
||||
compile [hyperbolic sine %, sinh %] to (Lua value "math.sinh(\(% as lua expr))")
|
||||
compile [hyperbolic cosine %, cosh %] to (Lua value "math.cosh(\(% as lua expr))")
|
||||
compile [hyperbolic tangent %, tanh %] to (..)
|
||||
[hyperbolic sine %, sinh %] all compile to (..)
|
||||
Lua value "math.sinh(\(% as lua expr))"
|
||||
|
||||
[hyperbolic cosine %, cosh %] all compile to (..)
|
||||
Lua value "math.cosh(\(% as lua expr))"
|
||||
|
||||
[hyperbolic tangent %, tanh %] all compile to (..)
|
||||
Lua value "math.tanh(\(% as lua expr))"
|
||||
|
||||
compile [e^ %, exp %] to (Lua value "math.exp(\(% as lua expr))")
|
||||
compile [natural log %, ln %, log %] to (Lua value "math.log(\(% as lua expr))")
|
||||
compile [log % base %base, log base %base of %] to (..)
|
||||
[e^ %, exp %] all compile to (Lua value "math.exp(\(% as lua expr))")
|
||||
[natural log %, ln %, log %] all compile to (..)
|
||||
Lua value "math.log(\(% as lua expr))"
|
||||
|
||||
[log % base %base, log base %base of %] all compile to (..)
|
||||
Lua value "math.log(\(% as lua expr), \(%base as lua expr))"
|
||||
|
||||
compile [floor %] to (Lua value "math.floor(\(% as lua expr))")
|
||||
compile [ceiling %, ceil %] to (Lua value "math.ceil(\(% as lua expr))")
|
||||
compile [round %, % rounded] to (Lua value "math.floor(\(% as lua expr) + .5)")
|
||||
(floor %) compiles to (Lua value "math.floor(\(% as lua expr))")
|
||||
[ceiling %, ceil %] all compile to (Lua value "math.ceil(\(% as lua expr))")
|
||||
[round %, % rounded] all compile to (..)
|
||||
Lua value "math.floor(\(% as lua expr) + .5)"
|
||||
|
||||
test:
|
||||
assume ((463 to the nearest 100) == 500) or barf "rounding failed"
|
||||
assume ((2.6 to the nearest 0.25) == 2.5) or barf "rounding failed"
|
||||
action [%n to the nearest %rounder] (..)
|
||||
externally (%n to the nearest %rounder) means (..)
|
||||
=lua "(\%rounder)*math.floor((\%n / \%rounder) + .5)"
|
||||
|
||||
# Any/all/none
|
||||
compile [all of %items, all %items] to:
|
||||
[all of %items, all %items] all compile to:
|
||||
unless (%items.type is "List"):
|
||||
return (Lua value "utils.all(\(%items as lua expr))")
|
||||
%clauses = (((% as lua expr)::as smext) for % in %items)
|
||||
return (Lua value "(\(%clauses::joined with " and "))")
|
||||
|
||||
parse [not all of %items, not all %items] as (not (all of %items))
|
||||
compile [any of %items, any %items] to:
|
||||
[not all of %items, not all %items] all parse as (not (all of %items))
|
||||
[any of %items, any %items] all compile to:
|
||||
unless (%items.type is "List"):
|
||||
return (Lua value "utils.any(\(%items as lua expr))")
|
||||
%clauses = (((% as lua expr)::as smext) for % in %items)
|
||||
return (Lua value "(\(%clauses::joined with " or "))")
|
||||
|
||||
parse [none of %items, none %items] as (not (any of %items))
|
||||
compile [sum of %items, sum %items] to:
|
||||
[none of %items, none %items] all parse as (not (any of %items))
|
||||
[sum of %items, sum %items] all compile to:
|
||||
unless (%items.type is "List"):
|
||||
return (Lua value "utils.sum(\(%items as lua expr))")
|
||||
%clauses = (((% as lua expr)::as smext) for % in %items)
|
||||
return (Lua value "(\(%clauses::joined with " + "))")
|
||||
|
||||
parse [if all of %items %body, if all of %items then %body] as (..)
|
||||
[if all of %items %body, if all of %items then %body] all parse as (..)
|
||||
if (all of %items) %body
|
||||
parse [unless all of %items %body, unless all of %items then %body] as (..)
|
||||
|
||||
[unless all of %items %body, unless all of %items then %body] all parse as (..)
|
||||
if (not (all of %items)) %body
|
||||
parse [if any of %items %body, if any of %items then %body] as (..)
|
||||
if (any of %items) %body
|
||||
parse [unless any of %items %body, unless any of %items then %body] as (..)
|
||||
if (not (any of %items)) %body
|
||||
parse [if none of %items %body, if none of %items then %body] as (..)
|
||||
if (not (any of %items)) %body
|
||||
parse [unless none of %items %body, unless none of %items then %body] as (..)
|
||||
|
||||
[if any of %items %body, if any of %items then %body] all parse as (..)
|
||||
if (any of %items) %body
|
||||
|
||||
parse [if all of %items %body else %else, if all of %items then %body else %else] as (..)
|
||||
if (all of %items) %body else %else
|
||||
parse [unless all of %items %body else %else, unless all of %items then %body else %else] as (..)
|
||||
if (not (all of %items)) %body else %else
|
||||
parse [if any of %items %body else %else, if any of %items then %body else %else] as (..)
|
||||
if (any of %items) %body else %else
|
||||
parse [unless any of %items %body else %else, unless any of %items then %body else %else] as (..)
|
||||
if (not (any of %items)) %body else %else
|
||||
parse [if none of %items %body else %else, if none of %items then %body else %else] as (..)
|
||||
if (not (any of %items)) %body else %else
|
||||
parse [unless none of %items %body else %else, unless none of %items then %body else %else] as (..)
|
||||
if (any of %items) %body else %else
|
||||
[unless any of %items %body, unless any of %items then %body] all parse as (..)
|
||||
if (not (any of %items)) %body
|
||||
|
||||
compile [product of %items, product %items] to:
|
||||
[if none of %items %body, if none of %items then %body] all parse as (..)
|
||||
if (not (any of %items)) %body
|
||||
|
||||
[unless none of %items %body, unless none of %items then %body] all parse as (..)
|
||||
if (any of %items) %body
|
||||
|
||||
[if all of %items %body else %else, if all of %items then %body else %else] all parse \
|
||||
..as (if (all of %items) %body else %else)
|
||||
|
||||
[..]
|
||||
unless all of %items %body else %else, unless all of %items then %body else %else
|
||||
..all parse as (if (not (all of %items)) %body else %else)
|
||||
|
||||
[if any of %items %body else %else, if any of %items then %body else %else] all parse \
|
||||
..as (if (any of %items) %body else %else)
|
||||
|
||||
[..]
|
||||
unless any of %items %body else %else, unless any of %items then %body else %else
|
||||
..all parse as (if (not (any of %items)) %body else %else)
|
||||
|
||||
[if none of %items %body else %else, if none of %items then %body else %else] all \
|
||||
..parse as (if (not (any of %items)) %body else %else)
|
||||
|
||||
[..]
|
||||
unless none of %items %body else %else, unless none of %items then %body else %else
|
||||
..all parse as (if (any of %items) %body else %else)
|
||||
|
||||
[product of %items, product %items] all compile to:
|
||||
unless (%items.type is "List"):
|
||||
return (Lua value "utils.product(\(%items as lua expr))")
|
||||
%clauses = (((% as lua expr)::as smext) for % in %items)
|
||||
return (Lua value "(\(%clauses::joined with " * "))")
|
||||
|
||||
action [avg of %items, average of %items] (=lua "(utils.sum(\%items)/#\%items)")
|
||||
compile [min of %items, smallest of %items, lowest of %items] to (..)
|
||||
externally [avg of %items, average of %items] all mean (..)
|
||||
=lua "(utils.sum(\%items)/#\%items)"
|
||||
|
||||
[min of %items, smallest of %items, lowest of %items] all compile to (..)
|
||||
Lua value "utils.min(\(%items as lua expr))"
|
||||
|
||||
compile [max of %items, biggest of %items, largest of %items, highest of %items] to (..)
|
||||
Lua value "utils.max(\(%items as lua expr))"
|
||||
[max of %items, biggest of %items, largest of %items, highest of %items] all compile \
|
||||
..to (Lua value "utils.max(\(%items as lua expr))")
|
||||
|
||||
test:
|
||||
assume ((min of [3, -4, 1, 2] by % = (% * %)) == 1)
|
||||
assume ((max of [3, -4, 1, 2] by % = (% * %)) == -4)
|
||||
parse [min of %items by %item = %value_expr] as (..)
|
||||
(min of %items by %item = %value_expr) parses as (..)
|
||||
result of:
|
||||
set {%best:nil, %best_key:nil}
|
||||
for %item in %items:
|
||||
@ -141,7 +164,7 @@ parse [min of %items by %item = %value_expr] as (..)
|
||||
|
||||
return %best
|
||||
|
||||
parse [max of %items by %item = %value_expr] as (..)
|
||||
(max of %items by %item = %value_expr) parses as (..)
|
||||
result of:
|
||||
set {%best:nil, %best_key:nil}
|
||||
for %item in %items:
|
||||
@ -152,20 +175,19 @@ parse [max of %items by %item = %value_expr] as (..)
|
||||
return %best
|
||||
|
||||
# Random functions
|
||||
action [seed random with %] (..)
|
||||
externally (seed random with %) means (..)
|
||||
lua> "\
|
||||
..math.randomseed(\%);
|
||||
for i=1,20 do math.random(); end"
|
||||
|
||||
parse [seed random] as (seed random with (=lua "os.time()"))
|
||||
compile [random number, random, rand] to (Lua value "math.random()")
|
||||
compile [random int %n, random integer %n, randint %n] to (..)
|
||||
(seed random) parses as (seed random with (=lua "os.time()"))
|
||||
[random number, random, rand] all compile to (Lua value "math.random()")
|
||||
[random int %n, random integer %n, randint %n] all compile to (..)
|
||||
Lua value "math.random(\(%n as lua expr))"
|
||||
|
||||
compile [..]
|
||||
random from %low to %high, random number from %low to %high
|
||||
rand %low %high
|
||||
..to (Lua value "math.random(\(%low as lua expr), \(%high as lua expr))")
|
||||
[random from %low to %high, random number from %low to %high, rand %low %high] all \
|
||||
..compile to (Lua value "math.random(\(%low as lua expr), \(%high as lua expr))")
|
||||
|
||||
action [random choice from %elements, random choice %elements, random %elements] (..)
|
||||
=lua "\%elements[math.random(#\%elements)]"
|
||||
externally [..]
|
||||
random choice from %elements, random choice %elements, random %elements
|
||||
..all mean (=lua "\%elements[math.random(#\%elements)]")
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This File contains actions for making actions and compile-time actions and some helper
|
||||
functions to make that easier.
|
||||
@ -33,7 +33,7 @@ lua> "\
|
||||
end"
|
||||
|
||||
lua> "\
|
||||
..COMPILE_ACTIONS["compile as 1"] = function(nomsu, tree, \%action)
|
||||
..COMPILE_ACTIONS["what 1 compiles to"] = function(nomsu, tree, \%action)
|
||||
local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", \%action.stub:as_lua(), "](")
|
||||
local lua_args = table.map(\%action:get_args(), function(a) return nomsu:compile(a) end)
|
||||
table.insert(lua_args, 1, "nomsu")
|
||||
@ -46,32 +46,32 @@ lua> "\
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
test:
|
||||
compile [five] to (Lua value "5")
|
||||
(five) compiles to (Lua value "5")
|
||||
test:
|
||||
assume ((five) == 5) or barf "Compile to expression failed."
|
||||
compile [loc x] to (Lua "local x = 99;")
|
||||
(loc x) compiles to (Lua "local x = 99;")
|
||||
test:
|
||||
lua> "do"
|
||||
loc x
|
||||
assume (%x is 99) or barf "Compile to statements with locals failed."
|
||||
lua> "end"
|
||||
assume (%x is (nil)) or barf "Failed to properly localize a variable."
|
||||
compile [asdf] to:
|
||||
(asdf) compiles to:
|
||||
%tmp = ""
|
||||
return (Lua %tmp)
|
||||
test:
|
||||
asdf
|
||||
assume (%tmp is (nil)) or barf "compile to is leaking variables"
|
||||
lua> "\
|
||||
..COMPILE_ACTIONS["compile 1 to 2"] = function(nomsu, tree, \%actions, \%body)
|
||||
local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return nomsu:compile(\
|
||||
..a):as_smext() end))}
|
||||
..COMPILE_ACTIONS["1 compiles to 2"] = function(nomsu, tree, \%actions, \%body)
|
||||
if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end
|
||||
local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return nomsu:compile(a):as_smext() end))}
|
||||
local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%actions[1].stub:as_lua(),
|
||||
"] = ", \(compile as (%args -> %body)))
|
||||
"] = ", \(what (%args -> %body) compiles to))
|
||||
for i=2,#\%actions do
|
||||
local alias = \%actions[i]
|
||||
local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return nomsu:compile(\
|
||||
..a):as_smext() end))}
|
||||
local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return nomsu:compile(a):as_\
|
||||
..smext() end))}
|
||||
lua:append("\\nCOMPILE_ACTIONS[", alias.stub:as_lua(), "] = ")
|
||||
if utils.equivalent(\%args, \%alias_args) then
|
||||
lua:append("COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "]")
|
||||
@ -84,11 +84,12 @@ lua> "\
|
||||
end
|
||||
end
|
||||
return lua
|
||||
end"
|
||||
end
|
||||
COMPILE_ACTIONS["1 all compile to 2"] = COMPILE_ACTIONS["1 compiles to 2"]"
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
compile [call %fn with %args] to:
|
||||
(call %fn with %args) compiles to:
|
||||
lua> "\
|
||||
..local lua = LuaCode.Value(tree.source, nomsu:compile(\%fn), "(")
|
||||
if \%args.type == 'List' then
|
||||
@ -100,22 +101,23 @@ compile [call %fn with %args] to:
|
||||
return lua"
|
||||
|
||||
test:
|
||||
local action [foo %x]: return "outer"
|
||||
(foo %x) means (return "outer")
|
||||
with local [action (foo %)]:
|
||||
local action [foo %x]:
|
||||
(foo %x) means:
|
||||
%y = (%x + 1)
|
||||
return %y
|
||||
|
||||
assume ((foo 10) == 11) or barf "Action didn't work."
|
||||
assume (%y is (nil)) or barf "Action leaked a local into globals."
|
||||
parse [baz %] as (foo %)
|
||||
(baz %) parses as (foo %)
|
||||
|
||||
assume ((foo 1) == "outer")
|
||||
compile [local action %actions %body] to:
|
||||
[%actions means %body, %actions all mean %body] all compile to:
|
||||
lua> "\
|
||||
..local fn_name = \%actions[1].stub:as_lua_id()
|
||||
..if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end
|
||||
local fn_name = \%actions[1].stub:as_lua_id()
|
||||
local \%args = table.map(\%actions[1]:get_args(), function(a) return nomsu:compile(a):as_smext() end)
|
||||
local lua = LuaCode(tree.source, fn_name, " = ", \(compile as (%args -> %body)))
|
||||
local lua = LuaCode(tree.source, fn_name, " = ", \(what (%args -> %body) compiles to))
|
||||
lua:add_free_vars({fn_name})
|
||||
for i=2,#\%actions do
|
||||
local alias = \%actions[i]
|
||||
@ -136,23 +138,24 @@ compile [local action %actions %body] to:
|
||||
return lua"
|
||||
|
||||
test:
|
||||
action [baz1]: return "baz1"
|
||||
action [baz2] "baz2"
|
||||
externally (baz1) means: return "baz1"
|
||||
externally (baz2) means "baz2"
|
||||
test:
|
||||
assume ((baz1) == "baz1")
|
||||
assume ((baz2) == "baz2")
|
||||
compile [action %actions %body] to (..)
|
||||
[externally %actions means %body, externally %actions all mean %body] all compile to:
|
||||
lua> "\
|
||||
..local lua = \(compile as (local action %actions %body))
|
||||
..local lua = \(what (%actions means %body) compiles to)
|
||||
if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end
|
||||
lua:remove_free_vars(table.map(\%actions, function(a) return a.stub:as_lua_id() end))
|
||||
return lua"
|
||||
|
||||
test:
|
||||
assume ((action (say %)) == (=lua "say_1"))
|
||||
compile [action %action] to (Lua value (%action.stub as lua id))
|
||||
(action %action) compiles to (Lua value (%action.stub as lua id))
|
||||
|
||||
test:
|
||||
parse [swap %x and %y] as (..)
|
||||
(swap %x and %y) parses as (..)
|
||||
do:
|
||||
%tmp = %x
|
||||
%x = %y
|
||||
@ -166,9 +169,10 @@ test:
|
||||
swap %tmp and %tmp2
|
||||
assume ((%tmp == 2) and (%tmp2 == 1)) or barf "\
|
||||
..'parse % as %' variable mangling failed."
|
||||
compile [parse %actions as %body] to (..)
|
||||
[%actions parses as %body, %actions all parse as %body] all compile to:
|
||||
lua> "\
|
||||
..local replacements = {}
|
||||
if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end
|
||||
for i,arg in ipairs(\%actions[1]:get_args()) do
|
||||
replacements[arg[1]] = nomsu:compile(arg):as_smext()
|
||||
end
|
||||
@ -204,36 +208,37 @@ compile [parse %actions as %body] to (..)
|
||||
local \%new_body = LuaCode(\%body.source,
|
||||
"local mangle = mangler()",
|
||||
"\\nreturn ", make_tree(\%body))
|
||||
local ret = \(compile as (compile %actions to %new_body))
|
||||
local ret = \(what (%actions compiles to %new_body) compiles to)
|
||||
return ret"
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# TODO: add check for .is_value
|
||||
compile [%tree as lua expr] to (Lua value "nomsu:compile(\(=lua "nomsu:compile(\%tree, nil, true)"), nil, true)")
|
||||
(%tree as lua expr) compiles to (..)
|
||||
Lua value "nomsu:compile(\(=lua "nomsu:compile(\%tree, nil, true)"), nil, true)"
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
compile [%tree as lua] to (Lua value "nomsu:compile(\(%tree as lua expr))")
|
||||
compile [%tree as lua statements] to (..)
|
||||
(%tree as lua) compiles to (Lua value "nomsu:compile(\(%tree as lua expr))")
|
||||
(%tree as lua statements) compiles to (..)
|
||||
Lua value "nomsu:compile(\(%tree as lua expr)):as_statements()"
|
||||
|
||||
compile [%tree as lua return] to (..)
|
||||
(%tree as lua return) compiles to (..)
|
||||
Lua value "nomsu:compile(\(%tree as lua expr)):as_statements('return ')"
|
||||
|
||||
compile [remove action %action] to (..)
|
||||
(remove action %action) compiles to (..)
|
||||
Lua "\(=lua "(\(%action.stub)):as_lua_id()") = nil"
|
||||
|
||||
test:
|
||||
assume ("\(\(foo \%x) as nomsu)" == "foo %x") or barf "\
|
||||
..action source code failed."
|
||||
compile [%tree as nomsu] to (..)
|
||||
(%tree as nomsu) compiles to (..)
|
||||
Lua value "nomsu:tree_to_nomsu(\(%tree as lua expr))"
|
||||
|
||||
compile [%tree as inline nomsu] to (..)
|
||||
(%tree as inline nomsu) compiles to (..)
|
||||
Lua value "nomsu:tree_to_inline_nomsu(\(%tree as lua expr), true)"
|
||||
|
||||
action [%var as lua identifier, %var as lua id] (..)
|
||||
externally [%var as lua identifier, %var as lua id] all mean:
|
||||
lua> "\
|
||||
..if lua_type_of_1(\%var) == 'string' then return \%var:as_lua_id()
|
||||
elseif AST.is_syntax_tree(\%var, 'Var') then return \%var[1]:as_lua_id()
|
||||
@ -248,17 +253,17 @@ action [%var as lua identifier, %var as lua id] (..)
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
compile [% is syntax tree] to (Lua value "AST.is_syntax_tree(\(% as lua expr))")
|
||||
compile [% is %kind syntax tree] to (..)
|
||||
(% is syntax tree) compiles to (Lua value "AST.is_syntax_tree(\(% as lua expr))")
|
||||
(% is %kind syntax tree) compiles to (..)
|
||||
Lua value "AST.is_syntax_tree(\(% as lua expr), \(%kind as lua expr))"
|
||||
|
||||
compile [%tree with %t -> %replacement] to (..)
|
||||
(%tree with %t -> %replacement) compiles to (..)
|
||||
Lua value "\
|
||||
..\(%tree as lua expr):map(function(\(%t as lua expr))
|
||||
\(%replacement as lua return)
|
||||
end)"
|
||||
|
||||
action [%tree with vars %replacements] (..)
|
||||
externally (%tree with vars %replacements) means (..)
|
||||
=lua "\
|
||||
..\%tree:map(function(\%t)
|
||||
if \%t.type == "Var" then
|
||||
@ -266,7 +271,7 @@ action [%tree with vars %replacements] (..)
|
||||
end
|
||||
end)"
|
||||
|
||||
compile [tree %tree with vars %replacements] to (..)
|
||||
(tree %tree with vars %replacements) compiles to (..)
|
||||
Lua value "\
|
||||
..\(=lua "(\%tree):as_lua()"):map(function(t)
|
||||
if t.type == "Var" then
|
||||
@ -274,7 +279,7 @@ compile [tree %tree with vars %replacements] to (..)
|
||||
end
|
||||
end)"
|
||||
|
||||
compile [%tree has subtree %match_tree] to (..)
|
||||
(%tree has subtree %match_tree) compiles to (..)
|
||||
Lua value "\
|
||||
..(function()
|
||||
local match_tree = \(%match_tree as lua expr)
|
||||
@ -283,7 +288,7 @@ compile [%tree has subtree %match_tree] to (..)
|
||||
end
|
||||
end)()"
|
||||
|
||||
action [match %tree with %patt]:
|
||||
externally (match %tree with %patt) means:
|
||||
lua> "\
|
||||
..if \%patt.type == "Var" then return _Dict{[\%patt[1]]=\%tree} end
|
||||
if \%patt.type == "Action" and \%patt.stub ~= \%tree.stub then return nil end
|
||||
@ -301,7 +306,7 @@ action [match %tree with %patt]:
|
||||
end
|
||||
return matches"
|
||||
|
||||
action [%tree with %patt ~> %replacement]:
|
||||
externally (%tree with %patt ~> %replacement) means:
|
||||
lua> "\
|
||||
..return \%tree:map(function(\%t)
|
||||
local \%vars = \(match %t with %patt)
|
||||
@ -323,7 +328,7 @@ test:
|
||||
..one
|
||||
"two""
|
||||
..== "\"one\\n\\\"two\\\"\""
|
||||
compile [quote %s] to (Lua value "tostring(\(%s as lua expr)):as_lua()")
|
||||
(quote %s) compiles to (Lua value "tostring(\(%s as lua expr)):as_lua()")
|
||||
|
||||
test:
|
||||
assume (lua type of {}) == "table"
|
||||
@ -331,21 +336,23 @@ test:
|
||||
assume ({} is a "Dict")
|
||||
assume ("" is text)
|
||||
assume ("" isn't a "Dict")
|
||||
externally (% is text) means (=lua "\(lua type of %) == 'string'")
|
||||
externally [% is not text, % isn't text] all mean (..)
|
||||
=lua "\(lua type of %) ~= 'string'"
|
||||
|
||||
action [% is text] (=lua "\(lua type of %) == 'string'")
|
||||
action [% is not text, % isn't text] (=lua "\(lua type of %) ~= 'string'")
|
||||
action [type of %]:
|
||||
externally (type of %) means:
|
||||
lua> "\
|
||||
local lua_type = \(lua type of %)
|
||||
..local lua_type = \(lua type of %)
|
||||
if lua_type == 'string' then return 'Text'
|
||||
elseif lua_type == 'table' then
|
||||
local mt = getmetatable(\%)
|
||||
if mt and mt.__type then return mt.__type end
|
||||
return 'Lua table'
|
||||
else return lua_type end"
|
||||
parse [% is a %type, % is an %type] as ((type of %) == %type)
|
||||
parse [% isn't a %type, % isn't an %type, % is not a %type, % is not an %type]
|
||||
..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] all parse as (..)
|
||||
(type of %) != %type
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -354,8 +361,8 @@ test:
|
||||
%a = (parse "\\1")
|
||||
%b = \(\(1))
|
||||
assume ((parse "\\1") == \(\(1)))
|
||||
compile [parse %text] to (Lua value "nomsu:parse(\(%text as lua expr))")
|
||||
compile [parse %text from %filename] to (..)
|
||||
(parse %text) compiles to (Lua value "nomsu:parse(\(%text as lua expr))")
|
||||
(parse %text from %filename) compiles to (..)
|
||||
Lua value "\
|
||||
..nomsu:parse(NomsuCode(Source(\(%filename as lua expr), 1, #\(%text as lua expr)), \(..)
|
||||
%text as lua expr
|
||||
@ -366,37 +373,39 @@ test:
|
||||
external %passed = (no)
|
||||
run "external %passed = (yes)"
|
||||
assume %passed
|
||||
compile [run %nomsu_code] to (..)
|
||||
(run %nomsu_code) compiles to (..)
|
||||
Lua value "\
|
||||
..nomsu:run(NomsuCode(\(..)
|
||||
=lua "tostring(\(%nomsu_code.source)):as_lua()"
|
||||
.., \(%nomsu_code as lua expr)))"
|
||||
..nomsu:run(NomsuCode(\(=lua "tostring(\(%nomsu_code.source)):as_lua()"), \(..)
|
||||
%nomsu_code as lua expr
|
||||
..))"
|
||||
|
||||
test:
|
||||
assume ((\(\(5) + \(5)) as value) == 10) or barf "%tree as value failed."
|
||||
compile [run tree %tree, %tree as value] to (Lua value "nomsu:run(\(%tree as lua expr))")
|
||||
compile [compile %block, compiled %block, %block compiled] to (..)
|
||||
[run tree %tree, %tree as value] all compile to (..)
|
||||
Lua value "nomsu:run(\(%tree as lua expr))"
|
||||
|
||||
[compile %block, compiled %block, %block compiled] all compile to (..)
|
||||
Lua value "nomsu:compile(\(%block as lua))"
|
||||
|
||||
# Return statement is wrapped in a do..end block because Lua is unhappy if you
|
||||
put code after a return statement, unless you wrap it in a block.
|
||||
compile [return] to (Lua "do return; end")
|
||||
compile [return %return_value] to (..)
|
||||
(return) compiles to (Lua "do return; end")
|
||||
(return %return_value) compiles to (..)
|
||||
Lua "do return \(%return_value as lua expr) end"
|
||||
|
||||
# Literals
|
||||
compile [yes] to (Lua value "true")
|
||||
compile [no] to (Lua value "false")
|
||||
compile [nothing, nil, null] to (Lua value "nil")
|
||||
compile [Nomsu syntax version] to (Lua value "NOMSU_SYNTAX_VERSION")
|
||||
compile [Nomsu compiler version] to (Lua value "NOMSU_COMPILER_VERSION")
|
||||
compile [core version] to (Lua value "NOMSU_CORE_VERSION")
|
||||
compile [lib version] to (Lua value "NOMSU_LIB_VERSION")
|
||||
compile [command line args] to (Lua value "arg")
|
||||
(yes) compiles to (Lua value "true")
|
||||
(no) compiles to (Lua value "false")
|
||||
[nothing, nil, null] all compile to (Lua value "nil")
|
||||
(Nomsu syntax version) compiles to (Lua value "NOMSU_SYNTAX_VERSION")
|
||||
(Nomsu compiler version) compiles to (Lua value "NOMSU_COMPILER_VERSION")
|
||||
(core version) compiles to (Lua value "NOMSU_CORE_VERSION")
|
||||
(lib version) compiles to (Lua value "NOMSU_LIB_VERSION")
|
||||
(command line args) compiles to (Lua value "arg")
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
compile [with local compile actions %body] to (..)
|
||||
(with local compile actions %body) compiles to (..)
|
||||
Lua "\
|
||||
..do
|
||||
local nomsu = nomsu:fork()
|
||||
@ -404,7 +413,7 @@ compile [with local compile actions %body] to (..)
|
||||
\(%body as lua statements)
|
||||
end"
|
||||
|
||||
action [Nomsu version]:
|
||||
externally (Nomsu version) means:
|
||||
use "lib/version.nom"
|
||||
return "\
|
||||
..\(Nomsu syntax version).\(core version).\(Nomsu compiler version).\(lib version)"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains definitions of operators like "+" and "and".
|
||||
|
||||
@ -9,14 +9,14 @@ test:
|
||||
assume (all [1 < 2, 2 > 1, 1 <= 2, 2 >= 1, 1 == 1, 1 != 2])
|
||||
|
||||
# Comparison Operators
|
||||
compile [%x < %y] to (Lua value "(\(%x as lua expr) < \(%y as lua expr))")
|
||||
compile [%x > %y] to (Lua value "(\(%x as lua expr) > \(%y as lua expr))")
|
||||
compile [%x <= %y] to (Lua value "(\(%x as lua expr) <= \(%y as lua expr))")
|
||||
compile [%x >= %y] to (Lua value "(\(%x as lua expr) >= \(%y as lua expr))")
|
||||
compile [%a is %b, %a == %b] to (..)
|
||||
(%x < %y) compiles to (Lua value "(\(%x as lua expr) < \(%y as lua expr))")
|
||||
(%x > %y) compiles to (Lua value "(\(%x as lua expr) > \(%y as lua expr))")
|
||||
(%x <= %y) compiles to (Lua value "(\(%x as lua expr) <= \(%y as lua expr))")
|
||||
(%x >= %y) compiles to (Lua value "(\(%x as lua expr) >= \(%y as lua expr))")
|
||||
[%a is %b, %a == %b] all compile to (..)
|
||||
Lua value "(\(%a as lua expr) == \(%b as lua expr))"
|
||||
|
||||
compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to (..)
|
||||
[%a isn't %b, %a is not %b, %a not= %b, %a != %b] all compile to (..)
|
||||
Lua value "(\(%a as lua expr) ~= \(%b as lua expr))"
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -26,7 +26,7 @@ test:
|
||||
assume (%x == 10)
|
||||
|
||||
# Variable assignment operator
|
||||
compile [%var = %value] to:
|
||||
(%var = %value) compiles to:
|
||||
lua> "local \%var_lua = \(%var as lua expr)"
|
||||
assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
|
||||
lua> "local \%value_lua = \(%value as lua expr)"
|
||||
@ -45,7 +45,7 @@ test:
|
||||
assume ((%y == 10) and (%x == 20)) or barf "swapping vars failed."
|
||||
|
||||
# Simultaneous mutli-assignments like: x,y,z = 1,x,3;
|
||||
compile [set %assignments] to:
|
||||
(set %assignments) compiles to:
|
||||
assume (%assignments.type is "Dict") or barf "\
|
||||
..Expected a Dict for the assignments part of '<- %' statement, not \%assignments"
|
||||
lua> "\
|
||||
@ -81,13 +81,13 @@ compile [set %assignments] to:
|
||||
|
||||
test:
|
||||
set {%foozle:"outer", %y:"outer"}
|
||||
action [set global x local y]:
|
||||
externally (set global x local y) means:
|
||||
external %foozle = "inner"
|
||||
%y = "inner"
|
||||
|
||||
set global x local y
|
||||
assume ((%foozle == "inner") and (%y == "outer")) or barf "external failed."
|
||||
compile [external %var = %value] to:
|
||||
(external %var = %value) compiles to:
|
||||
%var_lua = (%var as lua)
|
||||
assume %var_lua.is_value or barf "Invalid target for assignment: \%var"
|
||||
%value_lua = (%value as lua)
|
||||
@ -96,7 +96,7 @@ compile [external %var = %value] to:
|
||||
|
||||
test:
|
||||
set {%foozle:"outer", %y:"outer"}
|
||||
action [set global x local y] (..)
|
||||
externally (set global x local y) means (..)
|
||||
with external [%foozle]:
|
||||
%foozle = "inner"
|
||||
%y = "inner"
|
||||
@ -104,7 +104,7 @@ test:
|
||||
set global x local y
|
||||
assume ((%foozle == "inner") and (%y == "outer")) or barf "\
|
||||
..'with external' failed."
|
||||
compile [with external %externs %body] to:
|
||||
(with external %externs %body) compiles to:
|
||||
%body_lua = (%body as lua statements)
|
||||
lua> "\
|
||||
..\%body_lua:remove_free_vars(table.map(\%externs, function(v) return nomsu:compile(v):as_smext() end))"
|
||||
@ -119,7 +119,7 @@ test:
|
||||
|
||||
assume (%x == 1) or barf "'with' scoping failed"
|
||||
assume (%z == (nil)) or barf "'with' scoping failed"
|
||||
compile [with %assignments %body] to:
|
||||
(with %assignments %body) compiles to:
|
||||
%lua = (%body as lua statements)
|
||||
lua> "\
|
||||
..local lhs, rhs = LuaCode(tree.source), LuaCode(tree.source)
|
||||
@ -156,53 +156,53 @@ compile [with %assignments %body] to:
|
||||
# Math Operators
|
||||
test:
|
||||
assume ((5 wrapped around 2) == 1) or barf "mod not working"
|
||||
compile [%x wrapped around %y, %x mod %y] to (..)
|
||||
[%x wrapped around %y, %x mod %y] all compile to (..)
|
||||
Lua value "((\(%x as lua expr)) % (\(%y as lua expr)))"
|
||||
|
||||
# 3-part chained comparisons
|
||||
# (uses a lambda to avoid re-evaluating middle value, while still being an expression)
|
||||
test:
|
||||
%calls = 0
|
||||
local action [one]:
|
||||
(one) means:
|
||||
external %calls = (%calls + 1)
|
||||
return 1
|
||||
|
||||
assume (0 <= (one) <= 2) or barf "Three-way chained comparison failed."
|
||||
assume (%calls == 1) or barf "\
|
||||
..Three-way comparison evaluated middle value multiple times"
|
||||
parse [%x < %y < %z] as (..)
|
||||
(%x < %y < %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a < %b) and (%b < %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x <= %y < %z] as (..)
|
||||
(%x <= %y < %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a <= %b) and (%b < %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x < %y <= %z] as (..)
|
||||
(%x < %y <= %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a < %b) and (%b <= %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x <= %y <= %z] as (..)
|
||||
(%x <= %y <= %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a <= %b) and (%b <= %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x > %y > %z] as (..)
|
||||
(%x > %y > %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a > %b) and (%b > %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x >= %y > %z] as (..)
|
||||
(%x >= %y > %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a >= %b) and (%b > %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x > %y >= %z] as (..)
|
||||
(%x > %y >= %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a > %b) and (%b >= %c))) with [%x, %y, %z]
|
||||
|
||||
parse [%x >= %y >= %z] as (..)
|
||||
(%x >= %y >= %z) parses as (..)
|
||||
call ([%a, %b, %c] -> ((%a >= %b) and (%b >= %c))) with [%x, %y, %z]
|
||||
|
||||
# TODO: optimize for common case where x,y,z are all either variables or number literals
|
||||
# Boolean Operators
|
||||
test:
|
||||
local action [barfer] (barf "short circuiting failed")
|
||||
(barfer) means (barf "short circuiting failed")
|
||||
assume (((no) and (barfer)) == (no))
|
||||
assume ((no) or (yes))
|
||||
assume ((yes) or (barfer))
|
||||
compile [%x and %y] to (Lua value "(\(%x as lua expr) and \(%y as lua expr))")
|
||||
compile [%x or %y] to (Lua value "(\(%x as lua expr) or \(%y as lua expr))")
|
||||
(%x and %y) compiles to (Lua value "(\(%x as lua expr) and \(%y as lua expr))")
|
||||
(%x or %y) compiles to (Lua value "(\(%x as lua expr) or \(%y as lua expr))")
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -219,31 +219,31 @@ test:
|
||||
# Lua 5.3 introduced bit operators like | and &. Use them when possible, otherwise
|
||||
fall back to bit.bor(), bit.band(), etc.
|
||||
%use_bitops = ((is jit) or ((Lua version) == "Lua 5.2"))
|
||||
compile [NOT %, ~ %] to (..)
|
||||
[NOT %, ~ %] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.bnot(\(% as lua expr))") or "~(\(% as lua expr))"
|
||||
|
||||
compile [%a OR %b, %a | %b] to (..)
|
||||
[%a OR %b, %a | %b] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.bor(\(%a as lua expr), \(%b as lua expr))") or "\
|
||||
..(\(%a as lua expr) | \(%b as lua expr))"
|
||||
|
||||
compile [%a XOR %b, %a ~ %b] to (..)
|
||||
[%a XOR %b, %a ~ %b] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.bxor(\(%a as lua expr), \(%b as lua expr))") or "\
|
||||
..(\(%a as lua expr) ~ \(%b as lua expr))"
|
||||
|
||||
compile [%a AND %b, %a & %b] to (..)
|
||||
[%a AND %b, %a & %b] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.band(\(%a as lua expr), \(%b as lua expr))") or "\
|
||||
..(\(%a as lua expr) & \(%b as lua expr))"
|
||||
|
||||
compile [%x LSHIFT %shift, %x << %shift] to (..)
|
||||
[%x LSHIFT %shift, %x << %shift] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.lshift(\(%x as lua expr), \(%shift as lua expr))") or "\
|
||||
..(\(%x as lua expr) << \(%shift as lua expr))"
|
||||
|
||||
compile [%x RSHIFT %shift, %x >> %shift] to (..)
|
||||
[%x RSHIFT %shift, %x >> %shift] all compile to (..)
|
||||
Lua value (..)
|
||||
(%use_bitops and "bit.rshift(\(%x as lua expr), \(%shift as lua expr))") or "\
|
||||
..(\(%x as lua expr) >> \(%shift as lua expr))"
|
||||
@ -252,15 +252,15 @@ compile [%x RSHIFT %shift, %x >> %shift] to (..)
|
||||
test:
|
||||
assume ((- 5) == -5)
|
||||
assume ((not (yes)) == (no))
|
||||
compile [- %] to (Lua value "(- \(% as lua expr))")
|
||||
compile [not %] to (Lua value "(not \(% as lua expr))")
|
||||
(- %) compiles to (Lua value "(- \(% as lua expr))")
|
||||
(not %) compiles to (Lua value "(not \(% as lua expr))")
|
||||
|
||||
test:
|
||||
assume ((size of [1, 2, 3]) == 3)
|
||||
compile [size of %list, size of %list, size of %list, size of %list] to (..)
|
||||
[size of %list, size of %list, size of %list, size of %list] all compile to (..)
|
||||
Lua value "(#\(%list as lua expr))"
|
||||
|
||||
compile [%list is empty] to (Lua value "(#\(%list as lua expr) == 0)")
|
||||
(%list is empty) compiles to (Lua value "(#\(%list as lua expr) == 0)")
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -273,11 +273,11 @@ test:
|
||||
assume (%x == 4) or barf "*= failed"
|
||||
wrap %x around 3
|
||||
assume (%x == 1) or barf "wrap around failed"
|
||||
parse [%var += %] as (%var = (%var + %))
|
||||
parse [%var -= %] as (%var = (%var - %))
|
||||
parse [%var *= %] as (%var = (%var * %))
|
||||
parse [%var /= %] as (%var = (%var / %))
|
||||
parse [%var ^= %] as (%var = (%var ^ %))
|
||||
parse [%var and= %] as (%var = (%var and %))
|
||||
parse [%var or= %] as (%var = (%var or %))
|
||||
parse [wrap %var around %] as (%var = (%var wrapped around %))
|
||||
(%var += %) parses as (%var = (%var + %))
|
||||
(%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 or= %) parses as (%var = (%var or %))
|
||||
(wrap %var around %) parses as (%var = (%var wrapped around %))
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains definitions pertaining to variable scoping
|
||||
|
||||
@ -14,19 +14,19 @@ test:
|
||||
assume (%x == "inner")
|
||||
|
||||
assume (%x == "outer")
|
||||
action [foo] "outer foo"
|
||||
externally (foo) means "outer foo"
|
||||
with local [action (foo)]:
|
||||
action [foo] "inner foo"
|
||||
externally (foo) means "inner foo"
|
||||
assume ((foo) == "inner foo")
|
||||
|
||||
assume ((foo) == "outer foo")
|
||||
compile [with local %locals %body, with local %locals do %body] to:
|
||||
[with local %locals %body, with local %locals do %body] all compile to:
|
||||
%body_lua = (%body as lua statements)
|
||||
if %locals.type is:
|
||||
"Dict":
|
||||
%body_lua = (..)
|
||||
Lua "\
|
||||
..\(compile as (<- %locals))
|
||||
..\(what (<- %locals) compiles to)
|
||||
\%body_lua"
|
||||
|
||||
%body_lua::declare locals ("\(%.1 as lua)" for % in %locals)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains some definitions of text escape sequences, including ANSI console
|
||||
color codes.
|
||||
@ -22,12 +22,12 @@ test:
|
||||
assume ("asdf"::uppercase) == "ASDF"
|
||||
assume ("asdf"::with "s" -> "X") == "aXdf"
|
||||
assume ("one\ntwo\n"::lines) == ["one", "two", ""]
|
||||
parse [アクション %spec %body] as (action %spec %body)
|
||||
(アクション %spec %body) parses as (externally %spec means %body)
|
||||
test:
|
||||
%こんにちは = "こんにちは"
|
||||
アクション [% と言う] "\(%)世界"
|
||||
assume (%こんにちは と言う) == "こんにちは世界"
|
||||
compile [%expr for %match in %text matching %patt] to (..)
|
||||
(%expr for %match in %text matching %patt) compiles to (..)
|
||||
Lua value "\
|
||||
..(function()
|
||||
local ret = _List{}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
# How do I...
|
||||
# Write a comment? Put a # and go till the end of the line
|
||||
# How do I write a multi-line comment?
|
||||
After a comment line, any indented text
|
||||
is considered part of the comment
|
||||
(including any deeper-level indented text)
|
||||
(including any deeper-level indented text)
|
||||
The comment ends when the indentation ends
|
||||
# How do I import a file?
|
||||
use "lib/os.nom"
|
||||
@ -167,14 +167,14 @@ do:
|
||||
|
||||
# How do I define a function/method/procedure?
|
||||
# In nomsu, they're called "action"s, and they can be declared like this:
|
||||
action [say both %first and also %second]:
|
||||
(say both %first and also %second) means:
|
||||
say %first
|
||||
|
||||
# Function arguments are accessed just like variables
|
||||
say %second
|
||||
|
||||
# Actions can use "return" to return a value early
|
||||
action [first fibonacci above %n]:
|
||||
(first fibonacci above %n) means:
|
||||
%f1 = 0
|
||||
%f2 = 1
|
||||
repeat:
|
||||
@ -186,11 +186,11 @@ action [first fibonacci above %n]:
|
||||
say (first fibonacci above 10)
|
||||
|
||||
# Actions can have aliases, which may or may not have the arguments in different order
|
||||
action [..]
|
||||
[..]
|
||||
I hate %worse_things more than %better_things
|
||||
I think %worse_things are worse than %better_things
|
||||
I like %better_things more than %worse_things
|
||||
..:
|
||||
..all mean:
|
||||
say "\(%better_things::capitalized) rule and \%worse_things drool!"
|
||||
|
||||
I like "dogs" more than "cats"
|
||||
@ -201,7 +201,7 @@ I think "chihuahuas" are worse than "corgis"
|
||||
say both "Hello" and also "again!"
|
||||
|
||||
# Actions can even start with a parameter
|
||||
action [%what_she_said is what she said]:
|
||||
(%what_she_said is what she said) means:
|
||||
say %what_she_said
|
||||
say "-- she said"
|
||||
|
||||
@ -209,7 +209,7 @@ action [%what_she_said is what she said]:
|
||||
|
||||
# The language only reserves []{}().,:;% as special characters, so actions
|
||||
can have really funky names!
|
||||
action [>> %foo_bar $$$^ --> % @&_~-^-~_~-^ %1 !]:
|
||||
(>> %foo_bar $$$^ --> % @&_~-^-~_~-^ %1 !) means:
|
||||
say %foo_bar
|
||||
say %
|
||||
say %1
|
||||
@ -218,7 +218,7 @@ action [>> %foo_bar $$$^ --> % @&_~-^-~_~-^ %1 !]:
|
||||
|
||||
# There's also full unicode support
|
||||
%こんにちは = "こんにちは"
|
||||
action [% と言う] "\%世界"
|
||||
(% と言う) means "\%世界"
|
||||
say (%こんにちは と言う)
|
||||
|
||||
# Math and logic operations are just treated the same as actions in the syntax
|
||||
@ -226,7 +226,7 @@ say (2 + 3)
|
||||
|
||||
# So you can define your own operators, although they will need to be parenthesized to
|
||||
play nicely with other operators
|
||||
action [%a ++ %b] (2 * (%a + %b))
|
||||
(%a ++ %b) means (2 * (%a + %b))
|
||||
say (1 ++ (2 * 3))
|
||||
|
||||
# How do I do grouping?
|
||||
@ -240,36 +240,38 @@ say (2 + 3)
|
||||
say both "Very long first argument that needs its own line" and also "\
|
||||
..short second arg"
|
||||
|
||||
action [my favorite number] (21 + 2)
|
||||
(my favorite number) means (21 + 2)
|
||||
|
||||
# This can be nested:
|
||||
say both (my favorite number) and also "foo"
|
||||
|
||||
# Macros:
|
||||
# The "lua> %" and "=lua %" macros can be used to write raw lua code:
|
||||
action [say the time] (lua> "io.write(\"The OS time is: \", os.time(), \"\\n\");")
|
||||
(say the time) means (..)
|
||||
lua> "io.write(\"The OS time is: \", os.time(), \"\\n\");"
|
||||
|
||||
say the time
|
||||
say "Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2")"
|
||||
|
||||
# Variables can be accessed via \%varname
|
||||
action [square root of %n] (=lua "math.sqrt(\%n)")
|
||||
(square root of %n) means (=lua "math.sqrt(\%n)")
|
||||
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 %":
|
||||
parse [if %condition is untrue %body] 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 %"
|
||||
compile [if %condition on opposite day %body] to (..)
|
||||
(if %condition on opposite day %body) compiles to (..)
|
||||
Lua "\
|
||||
..if not \(%condition as lua expr) then
|
||||
\(%body as lua statements)
|
||||
end"
|
||||
|
||||
# Constants can be defined as macros
|
||||
parse [TWENTY] as 20
|
||||
(TWENTY) parses as 20
|
||||
|
||||
# When they're invoked, they'll need parentheses just like a function call
|
||||
parse [TWENTY ONE] as 21
|
||||
(TWENTY ONE) parses as 21
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -286,7 +288,7 @@ if (1 > (TWENTY)) on opposite day:
|
||||
|
||||
# How do I use an action as a value?
|
||||
# Well... it's always *possible* to fall back to Lua behavior for something like this:
|
||||
action [best of %items according to %key_fn]:
|
||||
(best of %items according to %key_fn) means:
|
||||
set {%best:nil, %best_key:nil}
|
||||
for %item in %items:
|
||||
%key = (=lua "\%key_fn(\%item)")
|
||||
@ -301,7 +303,7 @@ say (best of [2, -3, 4, -8] according to ([%x] -> (%x * %x)))
|
||||
one-off function to pass to another function and get called a bunch of times, you
|
||||
could use a macro to generate a single block of code that inlines the expression you
|
||||
want to use:
|
||||
parse [best of %items where %item_var has score %key_expr] as (..)
|
||||
(best of %items where %item_var has score %key_expr) parses as (..)
|
||||
result of:
|
||||
set {%best:nil, %best_key:nil}
|
||||
for %item_var in %items:
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines actions for encoding/decoding base 64, as specified in:
|
||||
https://tools.ietf.org/html/rfc4648
|
||||
@ -13,7 +13,7 @@ test:
|
||||
%plain = "foobar".[1, %len - 1]
|
||||
assume (base64 %plain) == %encoded
|
||||
assume (base64 decode %encoded) == %plain
|
||||
action [base64 %str, base64 encode %str, %str base64]:
|
||||
externally [base64 %str, base64 encode %str, %str base64] all mean:
|
||||
%chars = []
|
||||
for %i in 1 to (size of %str) via 3:
|
||||
%bytes = [=lua "\%str:byte(\%i, \(%i + 2))"]
|
||||
@ -36,8 +36,8 @@ action [base64 %str, base64 encode %str, %str base64]:
|
||||
|
||||
return (%chars::joined)
|
||||
|
||||
action [chr %] (=lua "string.char(\%)")
|
||||
action [decode base64 %str, %str base64 decoded, base64 decode %str]:
|
||||
externally (chr %) means (=lua "string.char(\%)")
|
||||
externally [decode base64 %str, %str base64 decoded, base64 decode %str] all mean:
|
||||
%chars = []
|
||||
for %i in 1 to (size of %str) via 4:
|
||||
%indices = (%reverse_b64.(%str.%) for % in %i to (%i + 3))
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines actions for ANSI console color escape codes.
|
||||
|
||||
@ -15,8 +15,7 @@ test:
|
||||
for %name = %colornum in %colors:
|
||||
%colornum = "\%colornum"
|
||||
(=lua "COMPILE_ACTIONS").%name = (..)
|
||||
[%nomsu, %tree] -> (..)
|
||||
Lua value "'\\027[\(%colornum)m'"
|
||||
[%nomsu, %tree] -> (Lua value "'\\027[\(%colornum)m'")
|
||||
(=lua "COMPILE_ACTIONS")."\%name 1" = (..)
|
||||
[%nomsu, %tree, %text] -> (..)
|
||||
Lua value "('\\027[\(%colornum)m'..\(%text as lua expr)..'\\027[0m')"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines some actions for hashing files and looking up files by hash.
|
||||
|
||||
@ -26,14 +26,14 @@ test:
|
||||
if %use_sha1:
|
||||
assume ((hash "hello world") == "Kq5sNclPz7QV2+lfQIuc6R7oRu0=")
|
||||
if %use_sha1:
|
||||
action [hash %]:
|
||||
externally (hash %) means:
|
||||
%hash = (=lua "\%hashlib.new('sha1'):final(\%)")
|
||||
return (base64 %hash)
|
||||
..else:
|
||||
# TODO: remove warning?
|
||||
say "\
|
||||
..\027[31;1mWARNING: OpenSSL module not found. Defaulting to a non-cryptographically secure hash function.\027[0m"
|
||||
action [hash %]:
|
||||
externally (hash %) means:
|
||||
%bytes = (%::bytes)
|
||||
%hash = (%bytes.1 << 7)
|
||||
for %i in 2 to (size of %bytes):
|
||||
@ -41,10 +41,10 @@ if %use_sha1:
|
||||
%hash = (%hash ~ (size of %bytes))
|
||||
return "\%hash"
|
||||
|
||||
action [file with hash %hash]:
|
||||
externally (file with hash %hash) means:
|
||||
for file %filename in ".":
|
||||
%contents = (read file %filename)
|
||||
%file_hash = (hash %contents)
|
||||
if (%file_hash == %hash): return %filename
|
||||
|
||||
parse [hash of file %filename] as (hash (read file %filename))
|
||||
(hash of file %filename) parses as (hash (read file %filename))
|
||||
|
@ -1,15 +1,13 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains the implementation of an Object-Oriented programming system.
|
||||
|
||||
%globals.METAMETHOD_MAP = {..}
|
||||
"as text": "__tostring", "clean up": "__gc",
|
||||
"+ 1": "__add", "- 1": "__sub", "* 1": "__mul", "/ 1": "__div",
|
||||
"-": "__unm", "// 1": "__idiv", "mod 1": "__mod", "^ 1": "__pow",
|
||||
"& 1": "__band", "| 1": "__bor", "~ 1": "__bxor", "~": "__bnot",
|
||||
"<< 1": "__bshl", ">> 1": "__bshr", "== 1": "__eq", "< 1": "__lt",
|
||||
"<= 1": "__le", "set 1 = 2": "__newindex", "size": "__len",
|
||||
"iterate": "__ipairs", "iterate all": "__pairs",
|
||||
"as text":"__tostring", "clean up":"__gc", "+ 1":"__add", "- 1":"__sub"
|
||||
"* 1":"__mul", "/ 1":"__div", "-":"__unm", "// 1":"__idiv", "mod 1":"__mod"
|
||||
"^ 1":"__pow", "& 1":"__band", "| 1":"__bor", "~ 1":"__bxor", "~":"__bnot"
|
||||
"<< 1":"__bshl", ">> 1":"__bshr", "== 1":"__eq", "< 1":"__lt", "<= 1":"__le"
|
||||
"set 1 = 2":"__newindex", size:"__len", iterate:"__ipairs", "iterate all":"__pairs"
|
||||
|
||||
test:
|
||||
object (Dog):
|
||||
@ -53,13 +51,13 @@ test:
|
||||
|
||||
with {%d:Dog {barks:2}}:
|
||||
assume ((%d::bark) == "Bark! Bark!")
|
||||
compile [my action %actions %body] to:
|
||||
(my action %actions %body) compiles to:
|
||||
lua> "\
|
||||
..local fn_name = \%actions[1].stub:as_lua_id()
|
||||
local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end)
|
||||
table.insert(\%args, 1, \(\%me as lua id))
|
||||
local lua = LuaCode(tree.source, "class.", fn_name, " = ", \(..)
|
||||
compile as (%args -> %body)
|
||||
what (%args -> %body) compiles to
|
||||
..)
|
||||
for i=2,#\%actions do
|
||||
local alias = \%actions[i]
|
||||
@ -79,12 +77,13 @@ compile [my action %actions %body] to:
|
||||
end
|
||||
return lua"
|
||||
|
||||
compile [object %classname extends %parent %class_body] to:
|
||||
(object %classname extends %parent %class_body) compiles to:
|
||||
unless (%classname.type == "Action"):
|
||||
compile error at %classname "Expected this to be an action, not a \(%classname.type)"
|
||||
for % in %classname:
|
||||
unless (% is text):
|
||||
compile error at % "Class names should not have arguments."
|
||||
|
||||
return (..)
|
||||
Lua "\
|
||||
..do
|
||||
@ -112,6 +111,5 @@ compile [object %classname extends %parent %class_body] to:
|
||||
end
|
||||
end"
|
||||
|
||||
parse [object %classname %class_body] as (..)
|
||||
(object %classname %class_body) parses as (..)
|
||||
object %classname extends (nil) %class_body
|
||||
|
||||
|
28
lib/os.nom
28
lib/os.nom
@ -1,14 +1,14 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file defines some actions that interact with the operating system and filesystem.
|
||||
|
||||
test:
|
||||
path of Nomsu file "lib/os.nom"
|
||||
action [path of Nomsu file %filename]:
|
||||
externally (path of Nomsu file %filename) means:
|
||||
lua> "for i,f in Files.walk(\%filename) do return f end"
|
||||
barf "Could not find file: \%filename"
|
||||
|
||||
action [sh> %cmd]:
|
||||
externally (sh> %cmd) means:
|
||||
lua> "\
|
||||
..local result = io.popen(\%cmd)
|
||||
local contents = result:read("*a")
|
||||
@ -17,19 +17,19 @@ action [sh> %cmd]:
|
||||
|
||||
test:
|
||||
read file "lib/os.nom"
|
||||
action [read file %filename] (=lua "Files.read(\%filename)")
|
||||
externally (read file %filename) means (=lua "Files.read(\%filename)")
|
||||
|
||||
test:
|
||||
for file %f in "core": do nothing
|
||||
compile [for file %f in %path %body] to (..)
|
||||
(for file %f in %path %body) compiles to (..)
|
||||
Lua "\
|
||||
..for i,\(%f as lua expr) in Files.walk(\(%path as lua expr)) do
|
||||
\(%body as lua statements)
|
||||
\(compile as (===next %f ===))
|
||||
\(what (===next %f ===) compiles to)
|
||||
end
|
||||
\(compile as (===stop %f ===))"
|
||||
\(what (===stop %f ===) compiles to)"
|
||||
|
||||
compile [%expr for file %f in %path] to (..)
|
||||
(%expr for file %f in %path) compiles to (..)
|
||||
Lua value "\
|
||||
..(function()
|
||||
local ret = _List{}
|
||||
@ -39,10 +39,10 @@ compile [%expr for file %f in %path] to (..)
|
||||
return ret
|
||||
end)()"
|
||||
|
||||
action [..]
|
||||
externally [..]
|
||||
write to file %filename %text, to file %filename write %text
|
||||
write %text to file %filename
|
||||
..:
|
||||
..all mean:
|
||||
assume (%filename != "stdin") or barf "Cannot write to stdin"
|
||||
lua> "\
|
||||
..local file = io.open(\%filename, 'w')
|
||||
@ -51,15 +51,17 @@ action [..]
|
||||
|
||||
test:
|
||||
assume (line number of 3 in "x\ny") == 2
|
||||
action [line number of %pos in %str] (=lua "Files.get_line_number(\%str, \%pos)")
|
||||
externally (line number of %pos in %str) means (..)
|
||||
=lua "Files.get_line_number(\%str, \%pos)"
|
||||
|
||||
test:
|
||||
assume (line 2 in "one\ntwo\nthree") == "two"
|
||||
action [line %line_num in %str] (=lua "Files.get_line(\%str, \%line_num)")
|
||||
externally (line %line_num in %str) means (..)
|
||||
=lua "Files.get_line(\%str, \%line_num)"
|
||||
|
||||
test:
|
||||
assume (source lines of \(this))
|
||||
action [source lines of %tree]:
|
||||
externally (source lines of %tree) means:
|
||||
%source = (%tree.source if (%tree is syntax tree) else %tree)
|
||||
%file = (read file %source.filename)
|
||||
return (..)
|
||||
|
@ -1,26 +1,28 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
This file contains a set of definitions that bring some familiar language features
|
||||
from other languages into nomsu (e.g. "||" and "continue")
|
||||
|
||||
parse [%a === %b] as ((%a 's id) is (%b 's id))
|
||||
parse [%a !== %b] as ((%a 's id) is not (%b 's id))
|
||||
parse [function %names %body, def %names %body] as (action %names %body)
|
||||
parse [switch %branch_value %body] as (if %branch_value is %body)
|
||||
parse [None, Null] as (nil)
|
||||
parse [True, true] as (yes)
|
||||
parse [False, false] as (no)
|
||||
parse [pass] as (do nothing)
|
||||
parse [%a || %b] as (%a or %b)
|
||||
parse [%a && %b] as (%a and %b)
|
||||
parse [continue] as (do next)
|
||||
parse [break] as (stop)
|
||||
parse [let %thing = %value in %action] as (with local {%thing:%value})
|
||||
parse [print %, println %] as (say %)
|
||||
parse [error!, panic!, fail!, abort!] as (barf!)
|
||||
parse [error %, panic %, fail %, abort %] as (barf %)
|
||||
parse [assert %condition] as (assume %condition)
|
||||
parse [assert %condition %message] as (assume %condition or barf %message)
|
||||
parse [%cond ? %if_true %if_false] as (%if_true if %cond else %if_false)
|
||||
parse [lambda %args %body] as (%args -> %body)
|
||||
parse [function %name %args %body] as (%name = (%args -> %body))
|
||||
(%a === %b) parses as ((%a 's id) is (%b 's id))
|
||||
(%a !== %b) parses as ((%a 's id) is not (%b 's id))
|
||||
[function %names %body, def %names %body] all parse as (..)
|
||||
externally %names means %body
|
||||
|
||||
(switch %branch_value %body) parses as (if %branch_value is %body)
|
||||
[None, Null] all parse as (nil)
|
||||
[True, true] all parse as (yes)
|
||||
[False, false] all parse as (no)
|
||||
(pass) parses as (do nothing)
|
||||
(%a || %b) parses as (%a or %b)
|
||||
(%a && %b) parses as (%a and %b)
|
||||
(continue) parses as (do next)
|
||||
(break) parses as (stop)
|
||||
(let %thing = %value in %action) parses as (with local {%thing:%value})
|
||||
[print %, println %] all parse as (say %)
|
||||
[error!, panic!, fail!, abort!] all parse as (barf!)
|
||||
[error %, panic %, fail %, abort %] all parse as (barf %)
|
||||
(assert %condition) parses as (assume %condition)
|
||||
(assert %condition %message) parses as (assume %condition or barf %message)
|
||||
(%cond ? %if_true %if_false) parses as (%if_true if %cond else %if_false)
|
||||
(lambda %args %body) parses as (%args -> %body)
|
||||
(function %name %args %body) parses as (%name = (%args -> %body))
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
# This file sets the current library version.
|
||||
lua> "NOMSU_LIB_VERSION = 6"
|
||||
|
@ -459,12 +459,19 @@ do
|
||||
return add_lua_bits(self, "value", code)
|
||||
end,
|
||||
["use 1"] = function(self, tree, path)
|
||||
local lua = LuaCode(tree.source)
|
||||
if path.type == 'Text' and #path == 1 and type(path[1]) == 'string' then
|
||||
for _, f in Files.walk(path[1]) do
|
||||
self:import(self:run_file(f))
|
||||
if match(f, "%.lua$") or match(f, "%.nom$") or match(f, "^/dev/fd/[012]$") then
|
||||
self:import(self:run_file(f))
|
||||
if #lua.bits > 0 then
|
||||
lua:append("\n")
|
||||
end
|
||||
lua:append("nomsu:import(nomsu:run_file(" .. tostring(f:as_lua()) .. "))")
|
||||
end
|
||||
end
|
||||
end
|
||||
return LuaCode(tree.source, "for i,f in Files.walk(", self:compile(path), ") do nomsu:import(nomsu:run_file(f)) end")
|
||||
return lua
|
||||
end,
|
||||
["tests"] = function(self, tree)
|
||||
return LuaCode.Value(tree.source, "TESTS")
|
||||
|
@ -264,11 +264,14 @@ with NomsuCompiler
|
||||
return add_lua_bits(@, "value", code)
|
||||
|
||||
["use 1"]: (tree, path)=>
|
||||
lua = LuaCode(tree.source)
|
||||
if path.type == 'Text' and #path == 1 and type(path[1]) == 'string'
|
||||
for _,f in Files.walk(path[1])
|
||||
@import(@run_file(f))
|
||||
|
||||
return LuaCode(tree.source, "for i,f in Files.walk(", @compile(path), ") do nomsu:import(nomsu:run_file(f)) end")
|
||||
if match(f, "%.lua$") or match(f, "%.nom$") or match(f, "^/dev/fd/[012]$")
|
||||
@import(@run_file(f))
|
||||
if #lua.bits > 0 then lua\append "\n"
|
||||
lua\append "nomsu:import(nomsu:run_file(#{f\as_lua!}))"
|
||||
return lua
|
||||
|
||||
["tests"]: (tree)=> LuaCode.Value(tree.source, "TESTS")
|
||||
["test 1"]: (tree, body)=>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env nomsu -V4.8.8.6
|
||||
#!/usr/bin/env nomsu -V4.8.10
|
||||
#
|
||||
Tool to automatically update code from old versions of Nomsu. Usage:
|
||||
nomsu tools/upgrade.nom [-i] file1 file2 directory1 ...
|
||||
|
Loading…
Reference in New Issue
Block a user