diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2018-11-02 15:17:48 -0700 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2018-11-02 15:17:49 -0700 |
| commit | 0f17c5eb9ac4660f2f969bd1e67af42713e45eac (patch) | |
| tree | 279ca7da2de0efe2f363684f3c84a540635f11a8 /core | |
| parent | acd9c2acd4688f2301b091daad910c04e402bd6a (diff) | |
| parent | dc41f30c73c9686685e3a4183c1213fb4ba55c90 (diff) | |
Merge branch 'master' into working
Diffstat (limited to 'core')
| -rw-r--r-- | core/collections.nom | 57 | ||||
| -rw-r--r-- | core/control_flow.nom | 358 | ||||
| -rw-r--r-- | core/coroutines.nom | 10 | ||||
| -rw-r--r-- | core/errors.nom | 43 | ||||
| -rw-r--r-- | core/id.nom | 6 | ||||
| -rw-r--r-- | core/io.nom | 6 | ||||
| -rw-r--r-- | core/math.nom | 154 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 233 | ||||
| -rw-r--r-- | core/operators.nom | 102 | ||||
| -rw-r--r-- | core/scopes.nom | 12 | ||||
| -rw-r--r-- | core/text.nom | 6 |
11 files changed, 566 insertions, 421 deletions
diff --git a/core/collections.nom b/core/collections.nom index 8dbc79d..ae7f5f1 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -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,27 +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));" +[% '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 = {} @@ -175,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)" @@ -185,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 @@ -198,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: diff --git a/core/control_flow.nom b/core/control_flow.nom index a9e0ae0..bbc98f1 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -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,31 +10,35 @@ 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 (..) - Lua "\ - ..if \(%condition as lua expr) then - \(%if_body as lua statements) - end" +(if %condition %if_body) compiles to: + %lua = (Lua "if ") + %lua::append (%condition as lua expr) + %lua::append " then\n " + %lua::append (%if_body as lua statements) + %lua::append "\nend" + return %lua 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 (..) - Lua "\ - ..if \(%condition as lua expr) then - \(%if_body as lua statements) - else - \(%else_body as lua statements) - end" +..all compile to: + %lua = (Lua "if ") + %lua::append (%condition as lua expr) + %lua::append " then\n " + %lua::append (%if_body as lua statements) + %lua::append "\nelse\n " + %lua::append (%else_body as lua statements) + %lua::append "\nend" + return %lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -44,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): @@ -72,6 +76,8 @@ compile [..] end end)())" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # GOTOs test: %i = 0 @@ -79,14 +85,37 @@ test: %i += 1 unless (%i == 10): go to %loop assume (%i == 10) -compile [=== %label ===, --- %label ---, *** %label ***] to (..) - Lua "::label_\(%label as lua identifier)::" + === (Loop) === + %i -= 1 + unless (%i == 0): go to (Loop) + assume (%i == 0) +[=== %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 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") +(stop %var) compiles to: + if %var: + return (..) + Lua "goto stop_\((%var.stub if (%var.type == "action") else %var) as lua identifier)" + ..else: return (Lua "break") +(do next %var) compiles to: + if %var: + return (..) + Lua "goto continue_\((%var.stub if (%var.type == "action") else %var) as lua identifier)" + ..else: return (Lua "goto continue") +[===stop %var ===, ---stop %var ---, ***stop %var ***] all compile to (..) + Lua "::stop_\((%var.stub if (%var.type == "action") else %var) as lua identifier)::" +[===next %var ===, ---next %var ---, ***next %var ***] all compile to (..) + Lua "::continue_\((%var.stub if (%var.type == "action") else %var) as lua identifier)::" # While loops test: @@ -108,9 +137,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 @@ -122,53 +151,44 @@ compile [repeat while %condition %body] to: %lua::append "\n ::continue_repeat::" %lua::append "\nend --while-loop" if (%body has subtree \(stop repeating)): - %lua = (..) - Lua "\ - ..do -- scope of "stop repeating" label - \%lua - ::stop_repeat:: - end -- end of "stop repeating" label scope" + %inner_lua = %lua + %lua = (Lua "do -- scope of 'stop repeating' label\n ") + %lua::append %inner_lua + %lua::append "\ + .. + ::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 - \(%body as lua statements)" - + 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)): %lua::append "\n ::continue_repeat::" %lua::append "\nend --numeric for-loop" if (%body has subtree \(stop repeating)): - %lua = (..) - Lua "\ - ..do -- scope of "stop repeating" label - \%lua - ::stop_repeat:: - end -- end of "stop repeating" label scope" + %inner_lua = %lua + %lua = (Lua "do -- scope of 'stop repeating' label\n ") + %lua::append %inner_lua + %lua::append "\ + .. + ::stop_repeat:: + end -- end of 'stop repeating' label scope" return %lua -# For loop control flow -compile [stop %var] to (Lua "goto stop_\(%var as lua identifier)") -compile [do next %var] to (Lua "goto continue_\(%var as lua identifier)") -compile [===stop %var ===, ---stop %var ---, ***stop %var ***] to (..) - Lua "::stop_\(%var as lua identifier)::" - -compile [===next %var ===, ---next %var ---, ***next %var ***] to (..) - Lua "::continue_\(%var as lua identifier)::" - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: @@ -191,38 +211,41 @@ 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)." + compile error at %var "Expected a variable here, not a \(%var.type)" %lua = (..) Lua "\ ..for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(..) %step as lua expr - .. do - \(%body as lua statements)" + .. 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 \(compile as (===next %var ===))" + %lua::append "\n " + %lua::append (what (===next %var ===) compiles to) + %lua::append "\nend --numeric for-loop" if (%body has subtree \(stop %var)): - %lua = (..) - Lua "\ - ..do -- scope for stopping for-loop - \%lua - \(compile as (===stop %var ===)) - end -- end of scope for stopping for-loop" + %inner_lua = %lua + %lua = (Lua "do -- scope for stopping for-loop\n ") + %lua::append %inner_lua + %lua::append "\n " + %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: @@ -239,28 +262,49 @@ test: assume (%b == [20, 30, 40]) # For-each loop (lua's "ipairs()") -compile [for %var in %iterable %body] 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)." +(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 - \(%body as lua statements)" + 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 (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 (what (===stop %var ===) compiles to) + %lua::append "\nend -- end of scope for stopping for-loop" + + return %lua + +# TODO: reduce code duplication +(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 (Lua "\n\(compile as (===next %var ===))") + %lua::append "\n " + %lua::append (what (===next %var ===) compiles to) + %lua::append "\nend --foreach-loop" if (%body has subtree \(stop %var)): - %lua = (..) - Lua "\ - ..do -- scope for stopping for-loop - \%lua - \(compile as (===stop %var ===)) - end -- end of scope for stopping for-loop" + %inner_lua = %lua + %lua = (Lua "do -- scope for stopping for-loop\n ") + %lua::append %inner_lua + %lua::append "\n " + %lua::append (what (===stop %var ===) compiles to) + %lua::append "\nend -- end of scope for stopping for-loop" return %lua @@ -275,46 +319,55 @@ 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)." + compile error at %key "Expected a variable here, not a \(%key.type)" unless (%value.type is "Var"): - compile error at %value "Expected a variable here, not a \(%value.type)." + compile error at %value "Expected a variable here, not a \(%value.type)" %lua = (..) Lua "\ ..for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(..) %iterable as lua expr - ..) do - \(%body as lua statements)" + ..) 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 (Lua "\n\(compile as (===next %key ===))") + %lua::append "\n " + %lua::append (what (===next %key ===) compiles to) + if (%body has subtree \(do next %value)): - %lua::append (Lua "\n\(compile as (===next %value ===))") + %lua::append "\n " + %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\(compile as (===stop %key ===))" + %stop_labels::append "\n" + %stop_labels::append (what (===stop %key ===) compiles to) + if (%body has subtree \(stop %value)): - %stop_labels::append "\n\(compile as (===stop %value ===))" + %stop_labels::append "\n" + %stop_labels::append (what (===stop %value ===) compiles to) + if ((size of "\%stop_labels") > 0): - %lua = (..) - Lua "\ - ..do -- scope for stopping for % = % loop - \%lua\%stop_labels - end" + %inner_lua = %lua + %lua = (Lua "do -- scope for stopping for % = % loop\n ") + %lua::append %inner_lua + %lua::append %stop_labels + %lua::append "\nend" return %lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: - if: + when: (1 == 2) (100 < 0): barf "bad conditional" (1 == 0) (1 == 1) %not_a_variable.x: do nothing @@ -326,13 +379,14 @@ test: barf "bad conditional" # Multi-branch conditional (if..elseif..else) -compile [if %body, when %body] to: +(when %body) compiles 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 (..) @@ -347,6 +401,7 @@ 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" @@ -354,23 +409,19 @@ compile [if %body, when %body] to: ..need a conditional block around it. Otherwise, make sure the 'else' \ ..block comes last." - %code::append "\ - .. - else - \(%action as lua statements)" - + %code::append "\nelse\n " + %code::append (%action as lua statements) %else_allowed = (no) ..else: - %code::append "\%clause " + %code::append %clause + %code::append " " for %i in 1 to ((size of %line) - 1): if (%i > 1): %code::append " or " %code::append (%line.%i as lua expr) - %code::append "\ - .. then - \(%action as lua statements)" - + %code::append " then\n " + %code::append (%action as lua statements) %clause = "\nelseif" if ((size of "\%code") == 0): @@ -390,7 +441,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) @@ -419,42 +470,42 @@ compile [if %branch_value is %body, when %branch_value is %body] to: ..need a conditional block around it. Otherwise, make sure the 'else' \ ..block comes last." - %code::append "\ - .. - else - \(%action as lua statements)" - + %code::append "\nelse\n " + %code::append (%action as lua statements) %else_allowed = (no) ..else: - %code::append "\%clause " + %code::append %clause + %code::append " " for %i in 1 to ((size of %line) - 1): if (%i > 1): %code::append " or " - %code::append "\(mangle "branch value") == \(%line.%i as lua expr)" - - %code::append "\ - .. then - \(%action as lua statements)" + %code::append "\(mangle "branch value") == " + %code::append (%line.%i as lua expr) + %code::append " then\n " + %code::append (%action as lua statements) %clause = "\nelseif" if ((size of "\%code") == 0): compile error at %body "'if' block has an empty body." ..hint "This means nothing would happen, so the 'if' block should be deleted." %code::append "\nend --when" - return (..) + %lua = (..) Lua "\ - ..do --if % is - local \(mangle "branch value") = \(%branch_value as lua expr) - \%code - end --if % is" + ..do --if % is... + local \(mangle "branch value") = " + %lua::append (%branch_value as lua expr) + %lua::append "\n " + %lua::append %code + %lua::append "\nend --if % is..." + return %lua # Do/finally -compile [do %action] to (..) - Lua "\ - ..do - \(%action as lua statements) - end --do" +(do %action) compiles to: + %lua = (Lua "do\n ") + %lua::append (%action as lua statements) + %lua::append "\nend -- do" + return %lua test: %d = {} @@ -463,60 +514,63 @@ test: %d.x = "bad" barf ..then always: %d.x = "good" - ..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 - return (..) + %lua = (..) Lua "\ ..do local \(mangle "fell_through") = false - local \(mangle "ok"), \(mangle "ret") = pcall(function() - \(%action as lua statements) - \(mangle "fell_through") = true - end) - \(%final_action as lua statements) - if not \(mangle "ok") then error(ret, 0) end - if not \(mangle "fell_through") then return ret end - end" + local \(mangle "ok"), \(mangle "ret") = pcall(function()" + %lua::append "\n " + %lua::append (%action as lua statements) + %lua::append "\ + .. \(mangle "fell_through") = true + end)" + %lua::append "\n " + %lua::append (%final_action as lua statements) + %lua::append "\ + .. if not \(mangle "ok") then error(ret, 0) end + if not \(mangle "fell_through") then return ret end + end" + return %lua 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]]]]] %flat = [] for % in recursive %t: - if ((type of %) is "table"): + if ((lua type of %) is "table"): for %2 in %: recurse % on %2 ..else: %flat::add % - assume ((sorted %flat) == [1, 2, 3, 4, 5, 6]) + 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 "\ ..do local \(mangle "stack \(%var.1)") = _List{\(%structure as lua expr)} while #\(mangle "stack \(%var.1)") > 0 do - \(%var as lua expr) = table.remove(\(mangle "stack \(%var.1)"), 1) - \(%body as lua statements)" - + \(%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 diff --git a/core/coroutines.nom b/core/coroutines.nom index e7ec41e..246a2ef 100644 --- a/core/coroutines.nom +++ b/core/coroutines.nom @@ -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) diff --git a/core/errors.nom b/core/errors.nom index 1157cb1..0b0a6a3 100644 --- a/core/errors.nom +++ b/core/errors.nom @@ -1,17 +1,16 @@ -#!/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 %msg) compiles to (Lua "error(\(=lua "\%msg and \(%msg as lua expr) or 'nil'"), 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 +19,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 +34,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 +54,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 @@ -66,9 +65,9 @@ compile [..] local ok, ret = xpcall(function() \(%action as lua statements) fell_through = true - end, function(\(%msg as lua expr)) + end, function(\(=lua "\%fallback and \(%msg as lua expr) or ''")) local ok, ret = pcall(function() - \(%fallback as lua statements) + \((=lua "\%fallback or \%msg") as lua statements) end) if not ok then err, erred = ret, true end end) @@ -84,21 +83,23 @@ 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) +# + [..] + try %action and if it succeeds %success or if it barfs %fallback + try %action and if it barfs %fallback or if it succeeds %success + ..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) diff --git a/core/id.nom b/core/id.nom index d3b2b71..a9231b9 100644 --- a/core/id.nom +++ b/core/id.nom @@ -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.% diff --git a/core/io.nom b/core/io.nom index 1e87209..6b67b50 100644 --- a/core/io.nom +++ b/core/io.nom @@ -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())"); diff --git a/core/math.nom b/core/math.nom index d6ddbce..66f5aba 100644 --- a/core/math.nom +++ b/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,79 +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) for % in %items) + %clauses = (((% as lua expr)::text) 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) for % in %items) + %clauses = (((% as lua expr)::text) 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) for % in %items) + %clauses = (((% as lua expr)::text) for % in %items) return (Lua value "(\(%clauses::joined with " + "))") -compile [product of %items, product %items] to: +[if all of %items %body, if all of %items then %body] all parse as (..) + if (all of %items) %body + +[unless all of %items %body, unless all of %items then %body] all parse as (..) + if (not (all of %items)) %body + +[if any of %items %body, if any of %items then %body] all parse as (..) + if (any of %items) %body + +[unless any of %items %body, unless any of %items then %body] all parse as (..) + if (not (any of %items)) %body + +[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) for % in %items) + %clauses = (((% as lua expr)::text) 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: @@ -115,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: @@ -126,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)]") diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index c50f783..61c877f 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -1,9 +1,9 @@ -#!/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. -lua> "NOMSU_CORE_VERSION = 8" +lua> "NOMSU_CORE_VERSION = 9" lua> "\ ..do local mangle_index = 0 @@ -16,16 +16,16 @@ lua> "\ end end COMPILE_ACTIONS["define mangler"] = function(nomsu, tree) - return LuaCode(tree.source, "local mangle_1 = mangler()") + return LuaCode(tree.source, "local mangle = mangler()") end" lua> "\ - ..COMPILE_ACTIONS["1 -> 2"] = function(nomsu, tree, \%args, \%body) + ..COMPILE_ACTIONS["1 ->"] = function(nomsu, tree, \%args, \%body) local lua = LuaCode.Value(tree.source, "(function(") - if AST.is_syntax_tree(\%args, "Action") then \%args = \%args:get_args() end - local lua_args = table.map(\%args, function(a) return AST.is_syntax_tree(a) and tostring(nomsu:compile(a)) or a end) + if SyntaxTree:is_instance(\%args) and \%args.type == "Action" then \%args = \%args:get_args() end + local lua_args = table.map(\%args, function(a) return SyntaxTree:is_instance(a) and nomsu:compile(a):text() or a end) lua:concat_append(lua_args, ", ") - local body_lua = AST.is_syntax_tree(\%body) and nomsu:compile(\%body):as_statements("return ") or \%body + local body_lua = SyntaxTree:is_instance(\%body) and nomsu:compile(\%body):as_statements("return ") or \%body body_lua:remove_free_vars(lua_args) body_lua:declare_locals() lua:append(")\\n ", body_lua, "\\nend)") @@ -33,8 +33,8 @@ lua> "\ end" lua> "\ - ..COMPILE_ACTIONS["compile as 1"] = function(nomsu, tree, \%action) - local lua = LuaCode.Value(tree.source, "COMPILE_ACTIONS[", repr(\%action.stub), "](") + ..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") table.insert(lua_args, 2, "tree") @@ -46,78 +46,84 @@ 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 tostring(nomsu:compile(\ - ..a)) end))} - local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", repr(\%actions[1].stub), - "] = ", \(compile as (%args -> %body))) + ..COMPILE_ACTIONS["1 compiles to"] = 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):text() end))} + local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), + "] = ", \(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 tostring(nomsu:compile(\ - ..a)) end))} - lua:append("\\nCOMPILE_ACTIONS[", repr(alias.stub), "] = ") + local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return nomsu:compile(a):text() \ + ..end))} + lua:append("\\nCOMPILE_ACTIONS[", alias.stub:as_lua(), "] = ") if utils.equivalent(\%args, \%alias_args) then - lua:append("COMPILE_ACTIONS[", repr(\%actions[1].stub), "]") + lua:append("COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "]") else lua:append("function(") lua:concat_append(\%alias_args, ", ") - lua:append(")\\n return COMPILE_ACTIONS[", repr(\%actions[1].stub), "](") + lua:append(")\\n return COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "](") lua:concat_append(\%args, ", ") lua:append(")\\nend") end end return lua - end" + end + COMPILE_ACTIONS["1 all compile to"] = COMPILE_ACTIONS["1 compiles to"]" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -compile [call %fn with %args] to: +(call %fn with %args) compiles to: lua> "\ ..local lua = LuaCode.Value(tree.source, nomsu:compile(\%fn), "(") - lua:concat_append(table.map(\%args, function(a) return nomsu:compile(a) end), ", ") + if \%args.type == 'List' then + lua:concat_append(table.map(\%args, function(a) return nomsu:compile(a) end), ", ") + else + lua:append('unpack(', nomsu:compile(\%args), ')') + end lua:append(")") return lua" test: - local action [foo %x]: return "outer" - with local [action (foo %)]: - local action [foo %x]: + (foo %x) means (return "outer") + with local [(foo %)'s meaning]: + (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() - local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end) - local lua = LuaCode(tree.source, fn_name, " = ", \(compile as (%args -> %body))) + ..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):text() end) + 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] local alias_name = alias.stub:as_lua_id() lua:add_free_vars({alias_name}) - local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end) + local \%alias_args = table.map(alias:get_args(), function(a) return nomsu:compile(a):text() end) lua:append("\\n", alias_name, " = ") if utils.equivalent(\%args, \%alias_args) then lua:append(fn_name) @@ -132,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 as lua id)) + assume (((say %)'s meaning) == (=lua "say")) +(%action's meaning) 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 @@ -162,20 +169,21 @@ 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]] = tostring(nomsu:compile(arg)) + replacements[arg[1]] = nomsu:compile(arg):text() end local function make_tree(t) - if AST.is_syntax_tree(t, "Var") then + if SyntaxTree:is_instance(t) and t.type == "Var" then if replacements[t[1]] then return replacements[t[1]] else - return t.type.."{mangle("..repr(t[1]).."), source="..repr(tostring(t.source)).."}" + return "SyntaxTree{mangle("..t[1]:as_lua().."), type="..t.type:as_lua()..", source="..tostring(t.source):as_lua().."}" end - elseif AST.is_syntax_tree(t) then + elseif SyntaxTree:is_instance(t) then local ret = {} local i = 1 for k, v in pairs(t) do @@ -183,71 +191,76 @@ compile [parse %actions as %body] to (..) ret[#ret+1] = make_tree(t[i]) i = i + 1 elseif k == "source" then - ret[#ret+1] = k.."= "..repr(tostring(v)) - elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then + ret[#ret+1] = k.."= "..tostring(v):as_lua() + elseif lua_type_of(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then ret[#ret+1] = k.."= "..make_tree(v) else ret[#ret+1] = "["..make_tree(k).."]= "..make_tree(v) end end - return t.type.."{"..table.concat(ret, ", ").."}" + return "SyntaxTree{"..table.concat(ret, ", ").."}" + elseif lua_type_of(t) == 'number' then + return tostring(t) else - return repr(t) + return t:as_lua() end end 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 (..) - 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 (..) - Lua value "nomsu:tree_to_nomsu(\(%tree as lua expr), true)" +(%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 type(\%var) == 'string' then return \%var:as_lua_id() - elseif AST.is_syntax_tree(\%var, 'Var') then return \%var[1]:as_lua_id() - elseif AST.is_syntax_tree(\%var, 'Action') then return \%var.stub:as_lua_id() + ..if lua_type_of(\%var) == 'string' then return \%var:as_lua_id() + elseif SyntaxTree:is_instance(\%var, 'Var') then return \%var[1]:as_lua_id() + elseif SyntaxTree:is_instance(\%var) then + local lua = \(%var as lua expr) + if not lua:text():match("^[_a-zA-Z][_a-zA-Z0-9]*$") then + nomsu:compile_error(\%var, "This is not a valid Lua identifier.") + end + return lua else error("Unknown type: "..tostring(\%var)) end" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -compile [% is syntax tree] to (Lua value "AST.is_syntax_tree(\(% as lua expr))") -compile [% is %kind syntax tree] to (..) - Lua value "AST.is_syntax_tree(\(% as lua expr), \(%kind as lua expr))" +(% is syntax tree) compiles to (Lua value "SyntaxTree:is_instance(\(% as lua expr))") +(% is %kind syntax tree) compiles to (..) + Lua value "SyntaxTree:is_instance(\(% 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 @@ -255,15 +268,15 @@ action [%tree with vars %replacements] (..) end end)" -compile [tree %tree with vars %replacements] to (..) +(tree %tree with vars %replacements) compiles to (..) Lua value "\ - ..\(=lua "repr(\%tree)"):map(function(t) + ..\(=lua "(\%tree):as_lua()"):map(function(t) if t.type == "Var" then return \(%replacements as lua expr)[t[1]] 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) @@ -272,14 +285,14 @@ 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 if #\%patt ~= #\%tree then return nil end local matches = _Dict{} for \%i=1,#\%patt do - if AST.is_syntax_tree(\%tree[\%i]) then + if SyntaxTree:is_instance(\%tree[\%i]) then local submatch = \(match %tree.%i with %patt.%i) if not submatch then return nil end for k,v in pairs(submatch) do @@ -290,7 +303,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) @@ -312,11 +325,31 @@ test: ..one "two"" ..== "\"one\\n\\\"two\\\"\"" -compile [quote %s] to (Lua value "repr(\(%s as lua expr))") +(quote %s) compiles to (Lua value "tostring(\(%s as lua expr)):as_lua()") test: - assume ((type of {}) == "table") or barf "type of failed." -compile [type of %obj] to (Lua value "type(\(%obj as lua expr))") + assume (lua type of {}) == "table" + assume (type of {}) == "Dict" + 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'" + +externally (type of %) means: + lua> "\ + ..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" + +[% 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -325,8 +358,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 @@ -337,37 +370,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 "repr(tostring(\(%nomsu_code.source)))" - .., \(%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() @@ -375,7 +410,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)" diff --git a/core/operators.nom b/core/operators.nom index 3ae7c2f..6d574b7 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -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)" @@ -34,7 +34,7 @@ compile [%var = %value] to: lua> "\ ..local lua = LuaCode(tree.source, \%var_lua, ' = ', \%value_lua, ';') if \%var.type == 'Var' then - lua:add_free_vars({tostring(nomsu:compile(\%var))}) + lua:add_free_vars({nomsu:compile(\%var):text()}) end return lua" @@ -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> "\ @@ -53,7 +53,7 @@ compile [set %assignments] to: for i, item in ipairs(\%assignments) do local \%target, \%value = item[1], item[2] \%value = \%value:map(function(t) - if Action:is_instance(t) and t.stub == "?" then + if SyntaxTree:is_instance(t) and t.type == "Action" and t.stub == "?" then return \%target end end) @@ -66,7 +66,7 @@ compile [set %assignments] to: %value as text ..) end if \%target.type == "Var" then - lhs:add_free_vars({tostring(target_lua)}) + lhs:add_free_vars({target_lua:text()}) end if i > 1 then lhs:append(", ") @@ -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,10 +104,10 @@ 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 tostring(nomsu:compile(v)) end))" + ..\%body_lua:remove_free_vars(table.map(\%externs, function(v) return nomsu:compile(v):text() end))" return %body_lua test: @@ -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) @@ -141,7 +141,7 @@ compile [with %assignments %body] to: lhs:append(target_lua) rhs:append(value_lua) if \%target.type == "Var" then - vars[i] = tostring(target_lua) + vars[i] = target_lua:text() end end \%lua:remove_free_vars(vars) @@ -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 (..) - Lua value "(\(%x as lua expr) % \(%y as lua expr))" +[%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 %)) diff --git a/core/scopes.nom b/core/scopes.nom index c01a361..2d86ca4 100644 --- a/core/scopes.nom +++ b/core/scopes.nom @@ -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" - with local [action (foo)]: - action [foo] "inner foo" + externally (foo) means "outer foo" + with local [(foo)'s meaning]: + 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) diff --git a/core/text.nom b/core/text.nom index 25e9c3c..05ec409 100644 --- a/core/text.nom +++ b/core/text.nom @@ -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{} |
