diff options
Diffstat (limited to 'lib/operators.nom')
| -rw-r--r-- | lib/operators.nom | 176 |
1 files changed, 87 insertions, 89 deletions
diff --git a/lib/operators.nom b/lib/operators.nom index 7a926f3..c15298f 100644 --- a/lib/operators.nom +++ b/lib/operators.nom @@ -1,124 +1,122 @@ require "lib/metaprogramming.nom" # Literals -compile (true; yes) to: "true" -compile (false; no) to: "false" -compile (nil; null) to: "nil" -compile (inf; infinity) to: "math.huge" -compile (nan; NaN; not a number) to: "(0/0)" -compile (pi; PI) to: "math.pi" -compile (tau; TAU) to: "(2*math.pi)" -compile (phi; PHI; golden ratio) to: "((1+math.sqrt(5))/2)" -compile (nop; pass) to code: "" +compile [true, yes] to: "true" +compile [false, no] to: "false" +compile [nil, null] to: "nil" +compile [inf, infinity] to: "math.huge" +compile [nan, NaN, not a number] to: "(0/0)" +compile [pi, PI] to: "math.pi" +compile [tau, TAU] to: "(2*math.pi)" +compile [phi, PHI, golden ratio] to: "((1+math.sqrt(5))/2)" +compile [nop, pass] to code: "" # Ternary operator -compile (%if_expr if %condition else %else_expr) to: ".." +compile [%if_expr if %condition else %else_expr] to: ".." |(function(nomsu, vars) # TODO: fix compiler bug that breaks this code if comments immediately follow ".." #.. Note: this uses a function instead of (condition and if_expr or else_expr) because that breaks if %if_expr is falsey. - | if \(%condition) then - | return \(%if_expr) - | else - | return \(%else_expr) - | end + | if \(%condition) then; + | return \(%if_expr); + | else; + | return \(%else_expr); + | end; |end)(nomsu, vars) # Indexing: -compile (%obj's %key; %obj -> %key) to: "\(%obj as lua)[\(%key as lua)]" +compile [%obj's %key, %obj -> %key] to: "(\(%obj as lua))[\(%key as lua)]" # Variable assignment operator, and += type versions -compile (%var = %val) to code: "\(%var as lua) = \(%val as lua)" -compile (%var += %val) to code: "\(%var as lua) = \(%var as lua) + \(%val as lua)" -compile (%var -= %val) to code: "\(%var as lua) = \(%var as lua) - \(%val as lua)" -compile (%var *= %val) to code: "\(%var as lua) = \(%var as lua) * \(%val as lua)" -compile (%var /= %val) to code: "\(%var as lua) = \(%var as lua) / \(%val as lua)" -compile (%var ^= %val) to code: "\(%var as lua) = \(%var as lua) ^ \(%val as lua)" -compile (%var and= %val) to code: "\(%var as lua) = \(%var as lua) and\(%val as lua)" -compile (%var or= %val) to code: "\(%var as lua) = \(%var as lua) or \(%val as lua)" -compile (%var join= %val) to code: "\(%var as lua) = \(%var as lua) .. \(%val as lua)" -compile (%var mod= %val) to code: "\(%var as lua) = \(%var as lua) % \(%val as lua)" - -%x =: 5 +compile [%var = %val] to code: "\(%var as lua) = \(%val as lua);" +compile [%var += %val] to code: "\(%var as lua) = \(%var as lua) + \(%val as lua);" +compile [%var -= %val] to code: "\(%var as lua) = \(%var as lua) - \(%val as lua);" +compile [%var *= %val] to code: "\(%var as lua) = \(%var as lua) * \(%val as lua);" +compile [%var /= %val] to code: "\(%var as lua) = \(%var as lua) / \(%val as lua);" +compile [%var ^= %val] to code: "\(%var as lua) = \(%var as lua) ^ \(%val as lua);" +compile [%var and= %val] to code: "\(%var as lua) = \(%var as lua) and\(%val as lua);" +compile [%var or= %val] to code: "\(%var as lua) = \(%var as lua) or \(%val as lua);" +compile [%var join= %val] to code: "\(%var as lua) = \(%var as lua) .. \(%val as lua);" +compile [%var mod= %val] to code: "\(%var as lua) = \(%var as lua) % \(%val as lua);" # Binary Operators lua block ".." - |local binops = {"-","/","<","<=",">",">=","^",{"===","=="},{"!==","~="},{"mod","%"}} - |for _,op in ipairs(binops) do - | local nomsu_alias = op - | if type(op) == 'table' then - | nomsu_alias, op = unpack(op) - | end + |local binops = {"-","/","<","<=",">",">=","^",{"===","=="},{"!==","~="},{"mod","%"}}; + |for _,op in ipairs(binops) do; + | local nomsu_alias = op; + | if type(op) == 'table' then; + | nomsu_alias, op = unpack(op); + | end; | nomsu:defmacro("%a "..nomsu_alias.." %b", (function(nomsu, vars) - | return "("..nomsu:tree_to_lua(vars.a).." "..op.." "..nomsu:tree_to_lua(vars.b)..")" - | end), [["(\\(%a) ]]..op..[[ \\(%b))"]]) - |end + | return "("..nomsu:tree_to_lua(vars.a).." "..op.." "..nomsu:tree_to_lua(vars.b)..")"; + | end), [["(\\(%a) ]]..op..[[ \\(%b))"]]); + |end; # TODO: implement OR, XOR, AND for multiple operands -compile (%a OR %b; %a | %b) to: "bit32.bor(\(%a as lua), \(%b as lua))" -compile (%a XOR %b) to: "bit32.bxor(\(%a as lua), \(%b as lua))" -compile (%a AND %b; %a & %b) to: "bit32.band(\(%a as lua), \(%b as lua))" -compile (NOT %; ~ %) to: "bit32.bnot(\(% as lua))" -compile (%x LSHIFT %shift; %x << %shift) to: "bit32.lshift(\(%x as lua), \(%shift as lua))" -compile (%x RSHIFT %shift) to: "bit32.rshift(\(%x as lua), \(%shift as lua))" -compile (%x ARSHIFT %shift; %x >> %shift) to: "bit32.arshift(\(%x as lua), \(%shift as lua))" +compile [%a OR %b, %a | %b] to: "bit32.bor(\(%a as lua), \(%b as lua))" +compile [%a XOR %b] to: "bit32.bxor(\(%a as lua), \(%b as lua))" +compile [%a AND %b, %a & %b] to: "bit32.band(\(%a as lua), \(%b as lua))" +compile [NOT %, ~ %] to: "bit32.bnot(\(% as lua))" +compile [%x LSHIFT %shift, %x << %shift] to: "bit32.lshift(\(%x as lua), \(%shift as lua))" +compile [%x RSHIFT %shift] to: "bit32.rshift(\(%x as lua), \(%shift as lua))" +compile [%x ARSHIFT %shift, %x >> %shift] to: "bit32.arshift(\(%x as lua), \(%shift as lua))" # == and != do equivalence checking, rather than identity checking -compile (%a == %b) to: "nomsu.utils.equivalent(\(%a as lua), \(%b as lua))" -compile (%a != %b) to: "(not nomsu.utils.equivalent(\(%a as lua), \(%b as lua)))" +compile [%a == %b] to: "nomsu.utils.equivalent(\(%a as lua), \(%b as lua))" +compile [%a != %b] to: "(not nomsu.utils.equivalent(\(%a as lua), \(%b as lua)))" # Commutative Operators defined for up to 8 operands # TODO: work out solution for commutative operators using more clever macros lua block ".." - |local max_operands = 8 - |local comops = {"+","*","and","or"} - |for _,_op in ipairs(comops) do - | local op = _op - | local spec = "%1 " - | for n=2,max_operands do - | spec = spec .." "..op.." %"..tostring(n) + |local max_operands = 8; + |local comops = {"+","*","and","or"}; + |for _,_op in ipairs(comops) do; + | local op = _op; + | local spec = "%1 "; + | for n=2,max_operands do; + | spec = spec .." "..op.." %"..tostring(n); | nomsu:defmacro(spec, (function(nomsu, vars) - | local bits = {} - | for i=1,n do - | table.insert(bits, (nomsu:tree_to_lua(vars[tostring(i)]))) - | end - | return "("..table.concat(bits, " "..op.." ")..")" - | end)) - | end - |end + | local bits = {}; + | for i=1,n do; + | table.insert(bits, (nomsu:tree_to_lua(vars[tostring(i)]))); + | end; + | return "("..table.concat(bits, " "..op.." ")..")"; + | end)); + | end; + |end; # Chained compairsions (e.g. x < y <= z) are defined up to 3 operands lua block ".." - |local max_operands = 3 - |for _,chainers in ipairs({{"<","<="},{">",">="}}) do + |local max_operands = 3; + |for _,chainers in ipairs({{"<","<="},{">",">="}}) do; | local function recurse(chainers, chain) # The 1-op versions are already more efficiently defined, and a 0-op version doesnt make sense - | if #chain >= 2 then - | local spec = "%1" - | for i,op in ipairs(chain) do - | spec = spec .. " "..op.." %"..tostring(i+1) - | end + | if #chain >= 2 then; + | local spec = "%1"; + | for i,op in ipairs(chain) do; + | spec = spec .. " "..op.." %"..tostring(i+1); + | end; # Chained comparisons need to be functions to avoid re-evaluating their arguments :\ | nomsu:def(spec, function(nomsu, vars) - | for i,op in ipairs(chain) do - | local a, b, result = vars[i], vars[i+1] - | if op == "<" then result = a < b - | elseif op == "<=" then result = a <= b - | elseif op == ">" then result = a > b - | elseif op == ">=" then result = a >= b end + | for i,op in ipairs(chain) do; + | local a, b, result = vars[i], vars[i+1]; + | if op == "<" then; result = a < b; + | elseif op == "<=" then; result = a <= b; + | elseif op == ">" then; result = a > b; + | elseif op == ">=" then; result = a >= b; end; # Short circuit - | if not result then return false end - | end - | end) - | end - | if #chain + 1 >= max_operands then return end - | for _,c in ipairs(chainers) do - | table.insert(chain, c) - | recurse(chainers, chain) - | table.remove(chain) - | end - | end - | recurse(chainers, {}) - |end + | if not result then; return false; end; + | end; + | end); + | end; + | if #chain + 1 >= max_operands then; return; end; + | for _,c in ipairs(chainers) do; + | table.insert(chain, c); + | recurse(chainers, chain); + | table.remove(chain); + | end; + | end; + | recurse(chainers, {}); + |end; # Unary operators -compile (- %) to: "-(\(% as lua))" -compile (not %) to: "not (\(% as lua))" +compile [- %] to: "-(\(% as lua))" +compile [not %] to: "not (\(% as lua))" |
