diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/collections.nom | 151 | ||||
| -rw-r--r-- | core/control_flow.nom | 234 | ||||
| -rw-r--r-- | core/coroutines.nom | 9 | ||||
| -rw-r--r-- | core/errors.nom | 39 | ||||
| -rw-r--r-- | core/id.nom | 33 | ||||
| -rw-r--r-- | core/io.nom | 8 | ||||
| -rw-r--r-- | core/math.nom | 137 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 70 | ||||
| -rw-r--r-- | core/operators.nom | 59 | ||||
| -rw-r--r-- | core/scopes.nom | 26 | ||||
| -rw-r--r-- | core/text.nom | 17 |
11 files changed, 356 insertions, 427 deletions
diff --git a/core/collections.nom b/core/collections.nom index 9a7dbe4..e9457e6 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -1,8 +1,8 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains code that supports manipulating and using collections like lists and dictionaries. - + use "core/metaprogramming.nom" use "core/control_flow.nom" use "core/operators.nom" @@ -15,11 +15,11 @@ test: %visited = {} for %i = %x in %list: %visited.%i = (yes) - assume (%visited == {1:yes, 2:yes, 3:yes, 4:yes, 5:yes}) + assume (%visited == {1: yes, 2: yes, 3: yes, 4: yes, 5: yes}) %visited = {} for %x in %list: %visited.%x = (yes) - assume (%visited == {1:yes, 2:yes, 3:yes, 4:yes, 5:yes}) + assume (%visited == {1: yes, 2: yes, 3: yes, 4: yes, 5: yes}) assume ((%list::2 nd to last) == 4) assume ((%list::first) == 1) assume (%list::has 3) @@ -35,130 +35,53 @@ test: # Dict functionality test: - %dict = {x:1, y:2, z:3} - assume ((size of %dict) == 3) - assume ((% for % in {x:1}) == [{key:"x", value:1}]) - assume (({key:%k, value:%v} for %k = %v in {x:1}) == [{key:"x", value:1}]) - assume (({x:1, y:1} + {y:10, z:10}) == {x:1, y:11, z:10}) - assume (({x:1, y:1} | {y:10, z:10}) == {x:1, y:1, z:10}) - assume (({x:1, y:1} & {y:10, z:10}) == {y:1}) - assume (({x:1, y:1} ~ {y:10, z:10}) == {x:1, z:10}) - -# List Comprehension -test: - assume (((% * %) for % in [1, 2, 3]) == [1, 4, 9]) -(%expression for %item in %iterable) parses as (..) - result of: - %comprehension = [] - for %item in %iterable: - %comprehension::add %expression - return %comprehension - -[..] - %expression for %index in %start to %stop via %step - %expression for %index in %start to %stop by %step -..all parse as (..) - result of: - %comprehension = [] - for %index in %start to %stop via %step: - %comprehension::add %expression - return %comprehension - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -test: - assume (((% * %) for % in 1 to 3) == [1, 4, 9]) -(%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"]) -[..] - %expression for %key = %value in %iterable - %expression for %key %value in %iterable -..all parse as (..) - result of: - %comprehension = [] - for %key = %value in %iterable: - %comprehension::add %expression - return %comprehension - -# Dict comprehensions -test: - assume (((% * %) = % for % in [1, 2, 3]) == {1:1, 4:2, 9:3}) -[..] - %key = %value for %item in %iterable, %key %value for %item in %iterable -..all parse as (..) - result of: - %comprehension = {} - for %item in %iterable: - %comprehension.%key = %value - return %comprehension - -test: - assume ((%k = (%v * %v) for %k = %v in {x:1, y:2, z:3}) == {x:1, y:4, z:9}) -[..] - %key = %value for %src_key = %src_value in %iterable - %key %value for %src_key %src_value in %iterable -..all parse as (..) - result of: - %comprehension = {} - for %src_key = %src_value in %iterable: - %comprehension.%key = %value - return %comprehension - -[..] - %key = %value for %item in %start to %stop via %step - %key %value for %item in %start to %stop via %step -..all parse as (..) - result of: - %comprehension = {} - for %item in %start to %stop via %step: - %comprehension.%key = %value - return %comprehension - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -test: - assume (((% * %) = % for % in 1 to 3) == {1:1, 4:2, 9:3}) -[..] - %key = %value for %item in %start to %stop - %key %value for %item in %start to %stop -..all parse as (%key = %value for %item in %start to %stop via 1) + %dict = {x: 1, y: 2, z: 3} + assume (size of %dict) == 3 + assume [: for % in {x: 1}: add %] == [{key: "x", value: 1}] + assume [: for %k = %v in {x: 1}: add {key: %k, value: %v}] == [..] + {key: "x", value: 1} + assume ({x: 1, y: 1} + {y: 10, z: 10}) == {x: 1, y: 11, z: 10} + assume ({x: 1, y: 1} | {y: 10, z: 10}) == {x: 1, y: 1, z: 10} + assume ({x: 1, y: 1} & {y: 10, z: 10}) == {y: 1} + assume ({x: 1, y: 1} ~ {y: 10, z: 10}) == {x: 1, z: 10} test: assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4]) + externally (%lists flattened) means: %flat = [] - for %list in %lists: - for %item in %list: %flat::add %item + for %item in recursive %lists: + if (%item is a "List"): + for % in %item: + recurse %item on % + ..else: + %flat::add %item return %flat test: - assume ((entries in {x:1}) == [{key:"x", value:1}]) -(entries in %dict) parses as ({key:%k, value:%v} for %k = %v in %dict) + assume ((entries in {x: 1}) == [{key: "x", value: 1}]) +(entries in %dict) parses as [: for %k = %v in %dict: add {key: %k, value: %v}] test: - assume ((keys in {x:1}) == ["x"]) -[keys in %dict, keys of %dict] all parse as (%k for %k = %v in %dict) - + assume ((keys in {x: 1}) == ["x"]) +[keys in %dict, keys of %dict] all parse as [: for %k = %v in %dict: add %k] test: - assume ((values in {x:1}) == [1]) -[values in %dict, values of %dict] all parse as (%v for %k = %v in %dict) + assume ((values in {x: 1}) == [1]) +[values in %dict, values of %dict] all parse as [: for %k = %v in %dict: add %v] # Metatable stuff test: %t = {} - set %t 's metatable to {__tostring:[%] -> "XXX"} + set %t's metatable to {__tostring: [%] -> "XXX"} assume ("\%t" == "XXX") -(set %dict 's metatable to %metatable) compiles to "\ - ..setmetatable(\(%dict as lua expr), \(%metatable as lua expr));" -[% 's metatable, % 'metatable] all compile to "\ - ..getmetatable(\(% as lua expr))" +(set %dict's metatable to %metatable) compiles to "\ + ..setmetatable(\(%dict as lua expr), \(%metatable as lua expr));" +[%'s metatable, %'metatable] all compile to "getmetatable(\(% as lua expr))" test: assume (({} with fallback % -> (% + 1)).10 == 11) + (%dict with fallback %key -> %value) compiles to "\ ..(function(d) local mt = {} @@ -178,12 +101,11 @@ test: assume (%x == [1, 2, 3]) sort %x by % = (- %) assume (%x == [3, 2, 1]) - %keys = {1:999, 2:0, 3:50} + %keys = {1: 999, 2: 0, 3: 50} sort %x by % = %keys.% assume (%x == [2, 3, 1]) (sort %items) compiles to "table.sort(\(%items as lua expr));" -[..] - sort %items by %item = %key_expr, sort %items by %item -> %key_expr +[sort %items by %item = %key_expr, sort %items by %item -> %key_expr] \ ..all parse as (..) do: %keys = ({} with fallback %item -> %key_expr) @@ -193,19 +115,21 @@ test: test: assume ((sorted [3, 1, 2]) == [1, 2, 3]) + externally [%items sorted, sorted %items] all mean: - %copy = (% for % in %items) + %copy = [: for % in %items: add %] sort %copy return %copy [%items sorted by %item = %key, %items sorted by %item -> %key] all parse as (..) result of: - %copy = (% for % in %items) + %copy = [: for % in %items: add %] sort %copy by %item = %key return %copy test: assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3]) + externally (unique %items) means: %unique = [] %seen = {} @@ -213,5 +137,4 @@ externally (unique %items) means: unless %seen.%: %unique::add % %seen.% = (yes) - return %unique diff --git a/core/control_flow.nom b/core/control_flow.nom index ff1a7c1..d96e916 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -1,8 +1,8 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains compile-time actions that define basic control flow structures like "if" statements and loops. - + use "core/metaprogramming.nom" use "core/operators.nom" use "core/errors.nom" @@ -10,13 +10,15 @@ use "core/errors.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # No-Op -test: do nothing +test: + do nothing (do nothing) compiles to "" # Conditionals test: if (no): barf "conditional fail" + (if %condition %if_body) compiles to "\ ..if \(%condition as lua expr) then \(%if_body as lua) @@ -25,9 +27,9 @@ test: test: unless (yes): barf "conditional fail" + (unless %condition %unless_body) parses as (if (not %condition) %unless_body) -[..] - if %condition %if_body else %else_body, unless %condition %else_body else %if_body +[if %condition %if_body else %else_body, unless %condition %else_body else %if_body] \ ..all compile to "\ ..if \(%condition as lua expr) then \(%if_body as lua) @@ -43,6 +45,7 @@ test: test: assume ((1 if (yes) else 2) == 1) assume ((1 if (no) else 2) == 2) + [..] %when_true_expr if %condition else %when_false_expr %when_true_expr if %condition otherwise %when_false_expr @@ -51,12 +54,8 @@ test: ..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): - return (..) - Lua "\ - ..(\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(..) - %when_false_expr as lua expr - ..)" + if {Text: yes, List: yes, Dict: yes, Number: yes}.(%when_true_expr.type): + return (Lua "(\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(%when_false_expr as lua expr))") ..else: # Otherwise, need to do an anonymous inline function (yuck, too bad lua doesn't have a proper ternary operator!) @@ -78,35 +77,37 @@ test: %i = 0 === %loop === %i += 1 - unless (%i == 10): go to %loop + unless (%i == 10): + go to %loop assume (%i == 10) === (Loop) === %i -= 1 - unless (%i == 0): go to (Loop) + unless (%i == 0): + go to (Loop) assume (%i == 0) + [=== %label ===, --- %label ---, *** %label ***] all compile to "\ - ..::label_\(..) - (%label.stub if (%label.type == "Action") else %label) as lua identifier - ..::" + ..::label_\((%label.stub if (%label.type == "Action") else %label) as lua identifier)::" (go to %label) compiles to "\ - ..goto label_\(..) - (%label.stub if (%label.type == "Action") else %label) as lua identifier - .." + ..goto label_\((%label.stub if (%label.type == "Action") else %label) as lua identifier)" # Basic loop control (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") + 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") + 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 "\ ..::stop_\((%var.stub if (%var.type == "action") else %var) as lua identifier)::" + [===next %var ===, ---next %var ---, ***next %var ***] all compile to "\ ..::continue_\((%var.stub if (%var.type == "action") else %var) as lua identifier)::" @@ -116,32 +117,31 @@ test: repeat while (%x < 10): %x += 1 assume (%x == 10) repeat while (%x < 20): stop - repeat while (%x < 20): stop repeating + repeat while (%x < 20): + stop repeating assume (%x == 10) repeat while (%x < 20): %x += 1 - if (yes): do next + if (yes): + do next barf "Failed to 'do next'" - assume (%x == 20) repeat while (%x < 30): %x += 1 - if (yes): do next repeat + if (yes): + do next repeat barf "Failed to 'do next repeat'" - assume (%x == 30) (do next repeat) compiles to "goto continue_repeat" (stop repeating) compiles to "goto stop_repeat" (repeat while %condition %body) compiles to: - %lua = (..) - Lua "\ - ..while \(%condition as lua expr) do - \(%body as lua)" - + %lua = (Lua "while \(%condition as lua expr) do\n \(%body as lua)") 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 --while-loop" if (%body has subtree \(stop repeating)): %inner_lua = %lua @@ -150,25 +150,24 @@ test: .. ::stop_repeat:: end -- end of 'stop repeating' label scope" - return %lua - (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) + (repeat %n times %body) compiles to: define mangler - %lua = (..) - Lua "for \(mangle "i")=1,\(%n as lua expr) do\n " + %lua = (Lua "for \(mangle "i")=1,\(%n as lua expr) do\n ") %lua::append (%body as lua) 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)): %inner_lua = %lua @@ -177,17 +176,18 @@ test: .. ::stop_repeat:: end -- end of 'stop repeating' label scope" - return %lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: %nums = [] - for %x in 1 to 5: %nums::add %x + for %x in 1 to 5: + %nums::add %x assume (%nums == [1, 2, 3, 4, 5]) %nums = [] - for %x in 1 to 5 via 2: %nums::add %x + for %x in 1 to 5 via 2: + %nums::add %x assume (%nums == [1, 3, 5]) %nums = [] for %outer in 1 to 100: @@ -195,10 +195,9 @@ test: if (%inner == 2): %nums::add -2 do next %inner - %nums::add %inner - if (%inner == 5): stop %outer - + if (%inner == 5): + stop %outer assume (%nums == [1, -2, 3, -2, 3, 4, 3, 4, 5]) # Numeric range for loops @@ -209,15 +208,11 @@ test: # 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)" - %lua = (..) - Lua "\ - ..for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(..) - %step as lua expr - .. do" - + %lua = (Lua "for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do") %lua::append "\n " (%body as lua) if (%body has subtree \(do next)): %lua::append "\n ::continue::" + if (%body has subtree \(do next %var)): %lua::append "\n " (what (===next %var ===) compiles to) @@ -228,7 +223,6 @@ test: %lua::append %inner_lua "\n " %lua::append (what (===stop %var ===) compiles to) %lua::append "\nend -- end of scope for stopping for-loop" - return %lua ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -239,25 +233,33 @@ test: test: %a = [10, 20, 30, 40, 50] %b = [] - for %x in %a: %b::add %x + for %x in %a: + %b::add %x assume (%a == %b) %b = [] for %x in %a: - if (%x == 10): do next %x - if (%x == 50): stop %x + if (%x == 10): + do next %x + + if (%x == 50): + stop %x + %b::add %x - assume (%b == [20, 30, 40]) # For-each loop (lua's "ipairs()") (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 "\ + ..for \(mangle "i"),\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do + " %lua::append (%body as lua) if (%body has subtree \(do next)): %lua::append "\n ::continue::" + if (%body has subtree \(do next %var)): %lua::append "\n " (what (===next %var ===) compiles to) @@ -268,17 +270,19 @@ test: %lua::append %inner_lua "\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 "\ + ..for \(%i as lua identifier),\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do + " %lua::append (%body as lua) if (%body has subtree \(do next)): %lua::append "\n ::continue::" + if (%body has subtree \(do next %var)): %lua::append "\n " (what (===next %var ===) compiles to) @@ -289,37 +293,36 @@ test: %lua::append %inner_lua "\n " %lua::append (what (===stop %var ===) compiles to) %lua::append "\nend -- end of scope for stopping for-loop" - return %lua test: - %d = {a:10, b:20, c:30, d:40, e:50} + %d = {a: 10, b: 20, c: 30, d: 40, e: 50} %result = [] for %k = %v in %d: - if (%k == "a"): do next %k - if (%v == 20): do next %v + if (%k == "a"): + do next %k + + if (%v == 20): + do next %v + %result::add "\%k = \%v" - assume ((%result sorted) == ["c = 30", "d = 40", "e = 50"]) # Dict iteration (lua's "pairs()") -[..] - for %key = %value in %iterable %body, for %key %value in %iterable %body +[for %key = %value in %iterable %body, for %key %value in %iterable %body] \ ..all compile to: # 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)" + unless (%value.type is "Var"): 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" + %lua = (Lua "for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do") %lua::append "\n " (%body as lua) if (%body has subtree \(do next)): %lua::append "\n ::continue::" + if (%body has subtree \(do next %key)): %lua::append "\n " (what (===next %key ===) compiles to) @@ -350,8 +353,10 @@ test: (1 == 0) (1 == 1) %not_a_variable.x: do nothing (1 == 1): barf "bad conditional" + (1 == 2): barf "bad conditional" + else: barf "bad conditional" @@ -361,30 +366,29 @@ test: %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'?" + compile error at %body "'if' expected a Block, but got a \(%body.type)." "\ + ..Perhaps you forgot to put a ':' after 'if'?" for %line in %body: unless (..) ((%line.type is "Action") and ((size of %line) >= 2)) and (..) %line.(size of %line) is "Block" syntax tree ..: - compile error at %line "Invalid line for the body of an 'if' block." - ..hint "Each line should contain one or more conditional expressions \ - ..followed by a block, or "else" followed by a block." - + compile error at %line "Invalid line for the body of an 'if' block." "\ + ..Each line should contain one or more conditional expressions followed by a block, or "else" followed \ + ..by a block." %action = %line.(size of %line) if ((%line.1 is "else") and ((size of %line) == 2)): unless %else_allowed: - compile error at %line "You can't have two 'else' blocks." - ..hint "Merge all of the 'else' blocks together." + compile error at %line "You can't have two 'else' blocks." "\ + ..Merge all of the 'else' blocks together." unless ((size of "\%code") > 0): compile error at %line "\ ..You can't have an 'else' block without a 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." + .."\ + ..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 " (%action as lua) %else_allowed = (no) @@ -394,13 +398,13 @@ test: if (%i > 1): %code::append " or " %code::append (%line.%i as lua expr) - %code::append " then\n " (%action as lua) %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." + compile error at %body "'if' block has an empty body." "\ + ..This means nothing would happen, so the 'if' block should be deleted." + %code::append "\nend --when" return %code @@ -408,9 +412,13 @@ test: if 5 is: 1 2 3: barf "bad switch statement" - 4 5: do nothing + + 4 5: + do nothing + 5 6: barf "bad switch statement" + else: barf "bad switch statement" @@ -421,28 +429,28 @@ test: %else_allowed = (yes) define mangler 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 the 'is'?" + compile error at %body "'if' expected a Block, but got a \(%body.type)" "\ + ..Perhaps you forgot to put a ':' after the 'is'?" + for %line in %body: unless (..) ((%line.type is "Action") and ((size of %line) >= 2)) and (..) %line.(size of %line) is "Block" syntax tree ..: - compile error at %line "Invalid line for 'if' block." - ..hint "Each line should contain expressions \ - ..followed by a block, or "else" followed by a block" - + compile error at %line "Invalid line for 'if' block." "\ + ..Each line should contain expressions followed by a block, or "else" followed by a block" %action = %line.(size of %line) if ((%line.1 is "else") and ((size of %line) == 2)): unless %else_allowed: - compile error at %line "You can't have two 'else' blocks." - ..hint "Merge all of the 'else' blocks together." + compile error at %line "You can't have two 'else' blocks." "\ + ..Merge all of the 'else' blocks together." + unless ((size of "\%code") > 0): compile error at %line "\ ..You can't have an 'else' block without a 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." + .."\ + ..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 " (%action as lua) %else_allowed = (no) @@ -452,13 +460,13 @@ test: if (%i > 1): %code::append " or " %code::append "\(mangle "branch value") == " (%line.%i as lua expr) - %code::append " then\n " (%action as lua) %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." + compile error at %body "'if' block has an empty body." "\ + ..This means nothing would happen, so the 'if' block should be deleted." + %code::append "\nend --when" return (..) Lua "\ @@ -468,19 +476,17 @@ test: end -- if % is..." # Do/finally -(do %action) compiles to "\ - ..do - \(%action as lua) - end -- do" - +(do %action) compiles to "do\n \(%action as lua)\nend -- do" test: %d = {} try: do: %d.x = "bad" barf - ..then always: %d.x = "good" + ..then always: + %d.x = "good" assume (%d.x == "good") + (do %action then always %final_action) compiles to: define mangler return (..) @@ -497,19 +503,19 @@ test: end" test: - assume ((result of (: return 99)) == 99) + assume ((result of: return 99) == 99) # Inline thunk: (result of %body) compiles to "\(what ([] -> %body) compiles to)()" - test: %t = [1, [2, [[3], 4], 5, [[[6]]]]] %flat = [] for % in recursive %t: if ((lua type of %) is "table"): - for %2 in %: recurse % on %2 - ..else: %flat::add % - + for %2 in %: + recurse % on %2 + ..else: + %flat::add % assume (sorted %flat) == [1, 2, 3, 4, 5, 6] # Recurion control flow @@ -518,6 +524,7 @@ test: define mangler (recurse %v on %x) compiles to (..) Lua "table.insert(\(mangle "stack \(%v.1)"), \(%x as lua expr))" + %lua = (..) Lua "\ ..do @@ -525,10 +532,13 @@ test: while #\(mangle "stack \(%var.1)") > 0 do \(%var as lua expr) = table.remove(\(mangle "stack \(%var.1)"), 1) \(%body as lua)" + if (%body has subtree \(do next)): %lua::append "\n ::continue::" + if (%body has subtree \(do 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 \(what (===stop %var ===) compiles to)" diff --git a/core/coroutines.nom b/core/coroutines.nom index 27797fa..7d17d63 100644 --- a/core/coroutines.nom +++ b/core/coroutines.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file defines the code that creates and manipulates coroutines - + use "core/metaprogramming.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -14,8 +14,11 @@ test: -> 5 repeat 3 times: -> 6 - for % in coroutine %co: %nums::add % + for % in coroutine %co: + %nums::add % + assume (%nums == [4, 5, 6, 6, 6]) or barf "Coroutine iteration failed" + [coroutine %body, generator %body] all compile to "\ ..(function() \(%body as lua) diff --git a/core/errors.nom b/core/errors.nom index e254209..12a5b29 100644 --- a/core/errors.nom +++ b/core/errors.nom @@ -1,16 +1,16 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains basic error reporting code - + use "core/metaprogramming.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(barf %msg) compiles to "error(\(=lua "\%msg and \(%msg as lua expr) or 'nil'"), 0);" +(barf %msg) compiles to "\ + ..error(\(=lua "\%msg and \(%msg as lua expr) or 'nil'"), 0);" (assume %condition) compiles to: - lua> "\ - ..local \%assumption = 'Assumption failed: '..tostring((\%condition):get_source_code())" + lua> "local \%assumption = 'Assumption failed: '..tostring((\%condition):get_source_code())" return (..) Lua "\ ..if not \(%condition as lua expr) then @@ -18,17 +18,14 @@ use "core/metaprogramming.nom" end" (assume %a == %b) compiles to: - lua> "\ - ..local \%assumption = 'Assumption failed: '..tostring(\(\(%a == %b) as nomsu))" + lua> "local \%assumption = 'Assumption failed: '..tostring(\(\(%a == %b) as nomsu))" define mangler return (..) Lua "\ ..do local \(mangle "a"), \(mangle "b") = \(%a as lua expr), \(%b as lua expr) if \(mangle "a") ~= \(mangle "b") then - error(\(quote "\%assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\(..) - mangle "b" - ..), 0) + error(\(quote "\%assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\(mangle "b")), 0) end end" @@ -38,16 +35,18 @@ use "core/metaprogramming.nom" end" test: - try (barf) and if it succeeds: barf "try failed." + try (barf) and if it succeeds: + barf "try failed." %worked = (no) - try (barf) and if it barfs: %worked = (yes) + try (barf) and if it barfs: + %worked = (yes) assume %worked or barf "try/catch failed" %x = 1 try: %x = 2 do (barf) then always: %x = 3 - ..and if it barfs: do nothing - + ..and if it barfs: + do nothing assume (%x == 3) or barf "do/then always failed" # Try/except @@ -81,19 +80,19 @@ test: # [..] - try %action and if it succeeds %success or if it barfs %fallback - try %action and if it barfs %fallback or if it succeeds %success + 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 - + try %action and if it succeeds %success or if it barfs (=lua "") %fallback + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + (try %action) parses as (..) try %action and if it succeeds (do nothing) or if it barfs (do nothing) #(try %action and if it barfs %fallback) parses as (..) try %action and if it succeeds (do nothing) or if it barfs %fallback - + (try %action and if it barfs %msg %fallback) parses as (..) try %action and if it succeeds (do nothing) or if it barfs %msg %fallback diff --git a/core/id.nom b/core/id.nom index 8875696..9cf5820 100644 --- a/core/id.nom +++ b/core/id.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # A simple UUID function based on RFC 4122: http://www.ietf.org/rfc/rfc4122.txt - + use "core/metaprogramming.nom" use "core/operators.nom" use "core/math.nom" @@ -13,21 +13,22 @@ use "core/control_flow.nom" %NaN_surrogate = {} %nil_surrogate = {} %obj_by_id = {} -set %obj_by_id's metatable to {__mode:"v"} +set %obj_by_id's metatable to {__mode: "v"} %id_by_obj = {} -set %id_by_obj 's metatable to {..} - __mode:"k", __index: (..) - [%self, %key] ->: - if (%key == (nil)): - return %self.%nil_surrogate - if (%key != %key): - return %self.%NaN_surrogate - --- (retry) --- - %id = (uuid) - if (%obj_by_id.%id != (nil)): go to (retry) - %self.%key = %id - %obj_by_id.%id = %key - return %id +set %id_by_obj's metatable to {..} + __mode: "k", __index: [%self, %key] ->: + if (%key == (nil)): + return %self.%nil_surrogate + + if (%key != %key): + return %self.%NaN_surrogate + + --- (retry) --- + %id = (uuid) + if (%obj_by_id.%id != (nil)): go to (retry) + %self.%key = %id + %obj_by_id.%id = %key + return %id externally (uuid) means: # Set all the other bits to randomly (or pseudo-randomly) chosen values. diff --git a/core/io.nom b/core/io.nom index 2df0999..d9dbdd3 100644 --- a/core/io.nom +++ b/core/io.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains basic input/output code - + use "core/metaprogramming.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -19,7 +19,5 @@ use "core/metaprogramming.nom" ..if \%prompt.type == "Text" then return LuaCode("(io.write(", \(%prompt as lua expr), ") and io.read())"); else - return LuaCode("(io.write(tostring(", \(..) - %prompt as lua expr - .., ")) and io.read())"); + return LuaCode("(io.write(tostring(", \(%prompt as lua expr), ")) and io.read())"); end" diff --git a/core/math.nom b/core/math.nom index 8951721..583cc8c 100644 --- a/core/math.nom +++ b/core/math.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file defines some common math literals and functions - + use "core/metaprogramming.nom" use "core/text.nom" use "core/operators.nom" @@ -28,7 +28,6 @@ test: assume (("5" as a number) == 5) ((% as a number)'s meaning) = ((tonumber %)'s meaning) ((% as number)'s meaning) = ((tonumber %)'s meaning) - test: assume (..) all of [..] @@ -36,101 +35,108 @@ 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" -[absolute value %, | % |, abs %] all compile to (..) - "math.abs(\(% as lua expr))" - -[square root %, square root of %, √ %, sqrt %] all compile to (..) - "math.sqrt(\(% as lua expr))" - +[absolute value %, | % |, abs %] all compile to "math.abs(\(% as lua expr))" +[square root %, square root of %, √ %, sqrt %] all compile to "\ + ..math.sqrt(\(% as lua expr))" [sine %, sin %] all compile to "math.sin(\(% as lua expr))" [cosine %, cos %] all compile to "math.cos(\(% as lua expr))" [tangent %, tan %] all compile to "math.tan(\(% as lua expr))" [arc sine %, asin %] all compile to "math.asin(\(% as lua expr))" [arc cosine %, acos %] all compile to "math.acos(\(% as lua expr))" [arc tangent %, atan %] all compile to "math.atan(\(% as lua expr))" -[arc tangent %y / %x, atan2 %y %x] all compile to (..) - "math.atan2(\(%y as lua expr), \(%x as lua expr))" - -[hyperbolic sine %, sinh %] all compile to (..) - "math.sinh(\(% as lua expr))" - -[hyperbolic cosine %, cosh %] all compile to (..) - "math.cosh(\(% as lua expr))" - -[hyperbolic tangent %, tanh %] all compile to (..) - "math.tanh(\(% as lua expr))" - +[arc tangent %y / %x, atan2 %y %x] all compile to "\ + ..math.atan2(\(%y as lua expr), \(%x as lua expr))" +[hyperbolic sine %, sinh %] all compile to "math.sinh(\(% as lua expr))" +[hyperbolic cosine %, cosh %] all compile to "math.cosh(\(% as lua expr))" +[hyperbolic tangent %, tanh %] all compile to "math.tanh(\(% as lua expr))" [e^ %, exp %] all compile to "math.exp(\(% as lua expr))" -[natural log %, ln %, log %] all compile to (..) - "math.log(\(% as lua expr))" - -[log % base %base, log base %base of %] all compile to (..) - "math.log(\(% as lua expr), \(%base as lua expr))" - +[natural log %, ln %, log %] all compile to "math.log(\(% as lua expr))" +[log % base %base, log base %base of %] all compile to "\ + ..math.log(\(% as lua expr), \(%base as lua expr))" (floor %) compiles to "math.floor(\(% as lua expr))" [ceiling %, ceil %] all compile to "math.ceil(\(% as lua expr))" -[round %, % rounded] all compile to (..) - "math.floor(\(% as lua expr) + .5)" - +[round %, % rounded] all compile to "math.floor(\(% as lua expr) + .5)" test: assume ((463 to the nearest 100) == 500) or barf "rounding failed" assume ((2.6 to the nearest 0.25) == 2.5) or barf "rounding failed" + externally (%n to the nearest %rounder) means (..) =lua "(\%rounder)*math.floor((\%n / \%rounder) + .5)" # Any/all externally [all of %items, all %items] all mean: for % in %items: - unless %: return (no) + unless %: + return (no) return (yes) + [all of %items, all %items] all compile to: unless (%items.type is "List"): return \(all of %items) - if ((size of %items) == 0): return (Lua "true") + + if ((size of %items) == 0): + return (Lua "true") + %lua = (Lua "(") - %lua::add ((% as lua expr) for % in %items) joined with " and " + %lua::add [: for % in %items: add (% as lua expr)] joined with " and " %lua::append ")" return %lua -[not all of %items, not all %items] all parse as (not (all of %items)) +[not all of %items, not all %items] all parse as (not (all of %items)) externally [any of %items, any %items] all mean: for % in %items: - if %: return (yes) + if %: + return (yes) return (no) + [any of %items, any %items] all compile to: unless (%items.type is "List"): return \(any of %items) - if ((size of %items) == 0): return (Lua "false") + + if ((size of %items) == 0): + return (Lua "false") + %lua = (Lua "(") - %lua::add ((% as lua expr) for % in %items) joined with " or " + %lua::add [: for % in %items: add (% as lua expr)] joined with " or " %lua::append ")" return %lua + [none of %items, none %items] all parse as (not (any of %items)) # Sum/product externally [sum of %items, sum %items] all mean: %total = 0 - for % in %items: %total += % + for % in %items: + %total += % return %total + [sum of %items, sum %items] all compile to: unless (%items.type is "List"): return \(sum of %items) - if ((size of %items) == 0): return (Lua "0") + + if ((size of %items) == 0): + return (Lua "0") + %lua = (Lua "(") - %lua::add ((% as lua expr) for % in %items) joined with " + " + %lua::add [: for % in %items: add (% as lua expr)] joined with " + " %lua::append ")" return %lua externally [product of %items, product %items] all mean: %prod = 1 - for % in %items: %prod *= % + for % in %items: + %prod *= % return %prod + [product of %items, product %items] all compile to: unless (%items.type is "List"): return \(product of %items) - if ((size of %items) == 0): return (Lua "1") + + if ((size of %items) == 0): + return (Lua "1") + %lua = (Lua "(") - %lua::add ((% as lua expr) for % in %items) joined with " * " + %lua::add [: for % in %items: add (% as lua expr)] joined with " * " %lua::append ")" return %lua @@ -156,45 +162,43 @@ externally [avg of %items, average of %items] all mean (..) [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) +[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 +[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) +[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 +[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) +[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 +[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) # Min/max externally [min of %items, smallest of %items, lowest of %items] all mean: %best = (nil) for % in %items: - if ((%best == (nil)) or (% < %best)): - %best = % + if ((%best == (nil)) or (% < %best)): %best = % return %best -externally [max of %items, biggest of %items, largest of %items, highest of %items] all mean: +externally [..] + max of %items, biggest of %items, largest of %items, highest of %items +..all mean: %best = (nil) for % in %items: - if ((%best == (nil)) or (% > %best)): - %best = % + if ((%best == (nil)) or (% > %best)): %best = % return %best test: assume ((min of [3, -4, 1, 2] by % = (% * %)) == 1) assume ((max of [3, -4, 1, 2] by % = (% * %)) == -4) + (min of %items by %item = %value_expr) parses as (..) result of: %best = (nil) @@ -219,17 +223,14 @@ test: # Random functions externally (seed random with %) means: - lua> "\ - ..math.randomseed(\%); - for i=1,20 do math.random(); end" - + lua> "math.randomseed(\%);\nfor i=1,20 do math.random(); end" (seed random) parses as (seed random with (=lua "os.time()")) [random number, random, rand] all compile to "math.random()" -[random int %n, random integer %n, randint %n] all compile to (..) - "math.random(\(%n as lua expr))" +[random int %n, random integer %n, randint %n] all compile to "\ + ..math.random(\(%n as lua expr))" -[random from %low to %high, random number from %low to %high, rand %low %high] all \ -..compile to "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 "math.random(\(%low as lua expr), \(%high as lua expr))" externally [..] random choice from %elements, random choice %elements, random %elements diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index b27147d..944dc34 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -1,11 +1,9 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This File contains actions for making actions and compile-time actions and some helper functions to make that easier. - -lua> "\ - ..NOMSU_CORE_VERSION = 10 - NOMSU_LIB_VERSION = 7" + +lua> "NOMSU_CORE_VERSION = 10\nNOMSU_LIB_VERSION = 7" lua> "\ ..do local mangle_index = 0 @@ -25,7 +23,8 @@ lua> "\ ..compile.action["1 ->"] = function(compile, \%args, \%body) local lua = LuaCode("(function(") 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 compile(a):text() or a end) + local lua_args = table.map(\%args, function(a) return SyntaxTree:is_instance(a) and compile(a):text(\ + ..) or a end) lua:concat_append(lua_args, ", ") local body_lua = SyntaxTree:is_instance(\%body) and compile(\%body) or \%body if SyntaxTree:is_instance(\%body) and \%body.type ~= "Block" then body_lua:prepend("return ") end @@ -49,9 +48,11 @@ lua> "\ test: (five) compiles to "5" + test: assume ((five) == 5) or barf "Compile to expression failed." (loc x) compiles to "local x = 99;" + test: lua> "do" loc x @@ -61,9 +62,11 @@ test: (asdf) compiles to: %tmp = "" return (Lua %tmp) + test: asdf assume (%tmp is (nil)) or barf "compile to is leaking variables" + lua> "\ ..compile.action["1 compiles to"] = function(compile, \%action, \%body) local \%args = List{\(\%compile), unpack(\%action:get_args())} @@ -114,11 +117,9 @@ test: (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." (baz %) parses as (foo %) - assume ((foo 1) == "outer") (%action means %body) compiles to: @@ -128,6 +129,7 @@ test: local lua = LuaCode(fn_name, " = ", \(what (%args -> %body) compiles to)) lua:add_free_vars({fn_name}) return lua" + (%actions all mean %body) compiles to: lua> "\ ..local fn_name = \%actions[1].stub:as_lua_id() @@ -148,16 +150,20 @@ test: return lua" test: - externally (baz1) means: return "baz1" + externally (baz1) means: + return "baz1" externally (baz2) means "baz2" + test: assume ((baz1) == "baz1") assume ((baz2) == "baz2") + (externally %action means %body) compiles to: lua> "\ ..local lua = \(what (%action means %body) compiles to) lua:remove_free_vars({\%action.stub:as_lua_id()}) return lua" + (externally %actions all mean %body) compiles to: lua> "\ ..local lua = \(what (%actions all mean %body) compiles to) @@ -166,23 +172,25 @@ test: test: assume (((say %)'s meaning) == (=lua "say")) -(%action's meaning) compiles to (Lua (%action.stub as lua id)) +(%action's meaning) compiles to (Lua (%action.stub as lua id)) test: (swap %x and %y) parses as (..) do: %tmp = %x %x = %y %y = %tmp + test: - set {%1:1, %2:2} + set {%1: 1, %2: 2} swap %1 and %2 assume ((%1 == 2) and (%2 == 1)) or barf "\ ..'parse % as %' failed on 'swap % and %'" - set {%tmp:1, %tmp2:2} + set {%tmp: 1, %tmp2: 2} swap %tmp and %tmp2 assume ((%tmp == 2) and (%tmp2 == 1)) or barf "\ ..'parse % as %' variable mangling failed." + (%actions all parse as %body) compiles to: lua> "\ ..local replacements = {} @@ -197,7 +205,8 @@ test: if replacements[t[1]] then return replacements[t[1]] else - return "SyntaxTree{mangle("..t[1]:as_lua().."), type="..t.type:as_lua()..", source="..tostring(t.source):as_lua().."}" + return "SyntaxTree{mangle("..t[1]:as_lua().."), type="..t.type:as_lua()..", source="..tostring(\ + ..t.source):as_lua().."}" end elseif SyntaxTree:is_instance(t) then local ret = {} @@ -227,12 +236,10 @@ test: local ret = \(what (%actions all compile to %new_body) compiles to) return ret" -~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [%action parses as %body] all parse as ([%action] all parse as %body) - -(%tree as lua expr) compiles to "\ - ..compile(\(=lua "compile(\%tree, true)"), true)" +(%tree as lua expr) compiles to "compile(\(=lua "compile(\%tree, true)"), true)" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -257,7 +264,10 @@ externally (% is %kind syntax tree) means (..) (%tree with %t -> %replacement) compiles to "\ ..\(%tree as lua expr):map(function(\(%t as lua expr)) - \((%replacement as lua) if (%replacement.type == "Block") else ("return \(%replacement as lua expr)")) + \(..) + (%replacement as lua) if (%replacement.type == "Block") else "\ + ..return \(%replacement as lua expr)" + .. end)" externally (%tree with vars %replacements) means (..) @@ -317,14 +327,9 @@ externally (%tree with %patt ~> %replacement) means: end)" test: - assume (..) - (..) - quote "\ - ..one - "two"" - ..== "\"one\\n\\\"two\\\"\"" -(quote %s) compiles to "tostring(\(%s as lua expr)):as_lua()" + assume ((quote "one\n\"two\"") == "\"one\\n\\\"two\\\"\"") +(quote %s) compiles to "tostring(\(%s as lua expr)):as_lua()" test: assume (lua type of {}) == "table" assume (type of {}) == "Dict" @@ -346,8 +351,8 @@ externally (type of %) means: return lua_type" [% is a %type, % is an %type] all parse as ((type of %) == %type) -[% isn't a %type, % isn't an %type, % is not a %type, % is not an %type] 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) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -357,18 +362,14 @@ test: run "external %passed = (yes)" assume %passed assume (run \(return \(\(5) + \(5)))) == 10 -(run %nomsu_code) compiles to "\ - ..run_1_in(\(%nomsu_code as lua expr), _ENV)" - +(run %nomsu_code) compiles to "run_1_in(\(%nomsu_code as lua expr), _ENV)" [compile %block, compiled %block, %block compiled] all compile to "\ ..compile(\(%block 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. (return %return_value) compiles to "\ - ..do return \(..) - =lua "\%return_value and \(%return_value as lua expr) or ''" - .. end" + ..do return \(=lua "\%return_value and \(%return_value as lua expr) or ''") end" # Literals (yes) compiles to "true" @@ -392,5 +393,4 @@ test: end" externally (Nomsu version) means: - return "\ - ..\(Nomsu syntax version).\(core version).\(Nomsu compiler version).\(lib version)" + return "\(Nomsu syntax version).\(core version).\(Nomsu compiler version).\(lib version)" diff --git a/core/operators.nom b/core/operators.nom index 19a61d7..cc86398 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains definitions of operators like "+" and "and". - + use "core/metaprogramming.nom" use "core/errors.nom" @@ -16,7 +16,6 @@ test: (%x <= %y) compiles to "(\(%x as lua expr) <= \(%y as lua expr))" (%x >= %y) compiles to "(\(%x as lua expr) >= \(%y as lua expr))" [%a is %b, %a == %b] all compile to "(\(%a as lua expr) == \(%b as lua expr))" - [%a isn't %b, %a is not %b, %a not= %b, %a != %b] all compile to "\ ..(\(%a as lua expr) ~= \(%b as lua expr))" @@ -38,9 +37,9 @@ test: return lua" test: - set {%x:10, %y:20} + set {%x: 10, %y: 20} assume ((%x == 10) and (%y == 20)) or barf "mutli-assignment failed." - set {%x:%y, %y:%x} + set {%x: %y, %y: %x} assume ((%y == 10) and (%x == 20)) or barf "swapping vars failed." # Simultaneous mutli-assignments like: x,y,z = 1,x,3; @@ -48,6 +47,7 @@ test: (set %assignments) compiles to: assume (%assignments.type is "Dict") or barf "\ ..Expected a Dict for the assignments part of '<- %' statement, not \%assignments" + lua> "\ ..local lhs, rhs = LuaCode(), LuaCode() for i, item in ipairs(\%assignments) do @@ -74,40 +74,37 @@ test: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test: - set {%foozle:"outer", %y:"outer"} + set {%foozle: "outer", %y: "outer"} 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." (external %var = %value) compiles to "\(%var as lua) = \(%value as lua)" - test: - set {%foozle:"outer", %y:"outer"} + set {%foozle: "outer", %y: "outer"} externally (set global x local y) means: with external [%foozle]: %foozle = "inner" %y = "inner" - set global x local y assume ((%foozle == "inner") and (%y == "outer")) or barf "\ ..'with external' failed." + (with external %externs %body) compiles to: %body_lua = (%body as lua) - lua> "\ - ..\%body_lua:remove_free_vars(table.map(\%externs, function(v) return compile(v):text() end))" + lua> "\%body_lua:remove_free_vars(table.map(\%externs, function(v) return compile(v):text() end))" return %body_lua test: - set {%x:1, %y:2} - with {%z:nil, %x:999}: + set {%x: 1, %y: 2} + with {%z: nil, %x: 999}: %z = 999 assume (%z == 999) or barf "'with' failed." assume (%x == 999) or barf "'with' assignment failed." - assume (%x == 1) or barf "'with' scoping failed" assume (%z == (nil)) or barf "'with' scoping failed" + (with %assignments %body) compiles to: %lua = (%body as lua) lua> "\ @@ -132,18 +129,14 @@ test: end \%lua:remove_free_vars(vars) \%lua:prepend("local ", lhs, " = ", rhs, ";\\n")" - - return (..) - Lua "\ - ..do - \%lua - end -- 'with' block" + return (Lua "do\n \%lua\nend -- 'with' block") # Math Operators test: assume ((5 wrapped around 2) == 1) or barf "mod not working" -[%x wrapped around %y, %x mod %y] all compile to (..) - "((\(%x as lua expr)) % (\(%y as lua expr)))" + +[%x wrapped around %y, %x mod %y] all compile to "\ + ..((\(%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) @@ -152,10 +145,10 @@ test: (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" + (%x < %y < %z) parses as (..) call ([%a, %b, %c] -> ((%a < %b) and (%b < %c))) with [%x, %y, %z] @@ -206,13 +199,21 @@ test: fall back to bit.bor(), bit.band(), etc. lua> "if \((is jit) or ((Lua version) == "Lua 5.2")) then" [NOT %, ~ %] all compile to "bit.bnot(\(% as lua expr))" -[%x OR %y, %x | %y] all compile to "bit.bor(\(%x as lua expr), \(%y as lua expr))" -[%x XOR %y, %x ~ %y] all compile to "bit.bxor(\(%x as lua expr), \(%y as lua expr))" -[%x AND %y, %x & %y] all compile to "bit.band(\(%x as lua expr), \(%y as lua expr))" +[%x OR %y, %x | %y] all compile to "\ + ..bit.bor(\(%x as lua expr), \(%y as lua expr))" + +[%x XOR %y, %x ~ %y] all compile to "\ + ..bit.bxor(\(%x as lua expr), \(%y as lua expr))" + +[%x AND %y, %x & %y] all compile to "\ + ..bit.band(\(%x as lua expr), \(%y as lua expr))" + [%x LSHIFT %shift, %x << %shift] all compile to "\ ..bit.lshift(\(%x as lua expr), \(%shift as lua expr))" + [%x RSHIFT %shift, %x >> %shift] all compile to "\ ..bit.rshift(\(%x as lua expr), \(%shift as lua expr))" + lua> "else" [NOT %, ~ %] all compile to "~(\(% as lua expr))" [%x OR %y, %x | %y] all compile to "(\(%x as lua expr) | \(%y as lua expr))" @@ -220,8 +221,10 @@ lua> "else" [%x AND %y, %x & %y] all compile to "(\(%x as lua expr) & \(%y as lua expr))" [%x LSHIFT %shift, %x << %shift] all compile to "\ ..(\(%x as lua expr) << \(%shift as lua expr))" + [%x RSHIFT %shift, %x >> %shift] all compile to "\ ..(\(%x as lua expr) >> \(%shift as lua expr))" + lua> "end" # Unary operators @@ -230,11 +233,9 @@ test: assume ((not (yes)) == (no)) (- %) compiles to "(- \(% as lua expr))" (not %) compiles to "(not \(% as lua expr))" - test: assume ((size of [1, 2, 3]) == 3) (size of %list) compiles to "(#\(%list as lua expr))" - (%list is empty) compiles to "(#\(%list as lua expr) == 0)" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/core/scopes.nom b/core/scopes.nom index bd8b8a6..009728b 100644 --- a/core/scopes.nom +++ b/core/scopes.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains definitions pertaining to variable scoping - + use "core/metaprogramming.nom" use "core/operators.nom" use "core/collections.nom" @@ -14,34 +14,26 @@ test: with local %x: %x = "inner" assume (%x == "inner") - assume (%x == "outer") externally (foo) means "outer foo" with local [(foo)'s meaning]: externally (foo) means "inner foo" assume ((foo) == "inner foo") - assume ((foo) == "outer foo") + [with local %locals %body, with local %locals do %body] all compile to: %body_lua = (%body as lua) if %locals.type is: "Dict": - %body_lua = (..) - Lua "\ - ..\(what (<- %locals) compiles to) - \%body_lua" - - %body_lua::declare locals ("\(%.1 as lua)" for % in %locals) + %body_lua = (Lua "\(what (<- %locals) compiles to)\n\%body_lua") + %body_lua::declare locals [: for % in %locals: add "\(%.1 as lua)"] "List": - %body_lua::declare locals ("\(% as lua)" for % in %locals) + %body_lua::declare locals [: for % in %locals: add "\(% as lua)"] + "Var" "Action": %body_lua::declare locals ["\(%locals as lua)"] + else: compile error at %locals "Unexpected local value" - - return (..) - Lua "\ - ..do - \%body_lua - end" + return (Lua "do\n \%body_lua\nend") diff --git a/core/text.nom b/core/text.nom index 28944dd..86d8d45 100644 --- a/core/text.nom +++ b/core/text.nom @@ -1,8 +1,8 @@ -#!/usr/bin/env nomsu -V4.8.10 +#!/usr/bin/env nomsu -V4.10.12.7 # This file contains some definitions of text escape sequences, including ANSI console color codes. - + use "core/metaprogramming.nom" use "core/operators.nom" use "core/control_flow.nom" @@ -27,19 +27,19 @@ test: assume ("asdf"::with "s" -> "X") == "aXdf" assume ("one\ntwo\n"::lines) == ["one", "two", ""] (%spec とは %body) parses as (%spec means %body) + test: %こんにちは = "こんにちは" (% と言う) とは "\(%)世界" assume (%こんにちは と言う) == "こんにちは世界" + (%expr for %match in %text matching %patt) compiles to: define mangler return (..) Lua "\ ..(function() local \(mangle "comprehension") = List{} - for \(%match as lua expr) in (\(%text as lua expr)):gmatch(\(..) - %patt as lua expr - ..) do + for \(%match as lua expr) in (\(%text as lua expr)):gmatch(\(%patt as lua expr)) do \(mangle "comprehension")[#\(mangle "comprehension")+1] = \(%expr as lua) end return \(mangle "comprehension") @@ -50,8 +50,9 @@ test: # Text literals %escapes = {..} - nl:"\n", newline:"\n", tab:"\t", bell:"\a", cr:"\r", "carriage return":"\r", - backspace:"\b", "form feed":"\f", formfeed:"\f", "vertical tab":"\v" + nl: "\n", newline: "\n", tab: "\t", bell: "\a", cr: "\r", "carriage return": "\r" + backspace: "\b", "form feed": "\f", formfeed: "\f", "vertical tab": "\v" + for %name = %str in %escapes: with {%lua: Lua (quote %str)}: - %compile.action.%name = ([]-> %lua) + %compile.action.%name = ([] -> %lua) |
