diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-02-02 15:48:28 -0800 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-02-02 15:49:42 -0800 |
| commit | 505fec2a61d2571317cc4bbc36ec0f4822a63f9d (patch) | |
| tree | c2b37e9db8e2f958fbca0caa0a9c4924912a37a9 /lib/operators.nom | |
| parent | 513c721198b2256235a95c98d161ab1bb51e6671 (diff) | |
Restructured the nomsu files to group all the essentials into core/ and
all the optionals into lib/. lib/core.nom and tests/all.nom are no
longer needed now.
Diffstat (limited to 'lib/operators.nom')
| -rw-r--r-- | lib/operators.nom | 209 |
1 files changed, 0 insertions, 209 deletions
diff --git a/lib/operators.nom b/lib/operators.nom deleted file mode 100644 index 5d5a7a8..0000000 --- a/lib/operators.nom +++ /dev/null @@ -1,209 +0,0 @@ -#.. - This file contains definitions of operators like "+" and "and". - -use "lib/metaprogramming.nom" - -# Indexing: -immediately: - #.. NOTE!!! It's critical that there are spaces around %key if it's a string, - otherwise, Lua will get confused and interpret %obj[[[foo]]] as %obj("[foo]") - instead of %obj[ "foo" ]. - It's also critical to have parens around %obj, otherwise Lua is too dumb to - realize that {x=1}["x"] is the same as ({x=1})["x"] or that - {x=1}.x is the same as ({x=1}).x - compile [..] - %obj' %key, %obj's %key, %key in %obj, %key'th in %obj, %key of %obj, - %key st in %obj, %key nd in %obj, %key rd in %obj, %key th in %obj, - ..to: - lua> ".." - local obj_lua = \(%obj as lua expr); - if not obj_lua:sub(-1,-1):match("[a-zA-Z)]") then - obj_lua = "("..obj_lua..")"; - end - local key_lua = \(%key as lua expr); - local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'") - or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"')); - if key_attr then - return {expr=obj_lua.."."..key_attr}; - elseif key_lua:sub(1,1) == "[" then - key_lua = " "..key_lua.." "; - end - return {expr=obj_lua.."["..key_lua.."]"}; - -# Comparison Operators -immediately: - compile [%x < %y] to {expr:"(\(%x as lua expr) < \(%y as lua expr))"} - compile [%x > %y] to {expr:"(\(%x as lua expr) > \(%y as lua expr))"} - compile [%x <= %y] to {expr:"(\(%x as lua expr) <= \(%y as lua expr))"} - compile [%x >= %y] to {expr:"(\(%x as lua expr) >= \(%y as lua expr))"} - # TODO: optimize case of [%x,%y] = [1,2] - compile [%a is %b, %a = %b, %a == %b] to: - lua> ".." - local safe = {Text=true, Number=true}; - local a_lua, b_lua = nomsu:tree_to_lua(\%a).expr, nomsu:tree_to_lua(\%b).expr; - if safe[\%a.type] or safe[\%b.type] then - return {expr="("..a_lua.." == "..b_lua..")"}; - else - return {expr="utils.equivalent("..a_lua..", "..b_lua..")"}; - end - compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to: - lua> ".." - local safe = {Text=true, Number=true}; - local a_lua, b_lua = nomsu:tree_to_lua(\%a).expr, nomsu:tree_to_lua(\%b).expr; - if safe[\%a.type] or safe[\%b.type] then - return {expr="("..a_lua.." ~= "..b_lua..")"}; - else - return {expr="(not utils.equivalent("..a_lua..", "..b_lua.."))"}; - end - # For strict identity checking, use (%x's id) is (%y's id) - compile [%'s id, id of %] to {expr:"nomsu.ids[\(% as lua expr)]"} - -# Variable assignment operator -immediately: - compile [%var <- %value] to: - lua> "local \%var_lua = nomsu:tree_to_lua(\%var);" - assume (%var_lua's "expr") or barf "Invalid target for assignment: \(%var's source code)" - lua> "local \%value_lua = nomsu:tree_to_lua(\%value);" - assume (%value_lua's "expr") or barf "Invalid value for assignment: \(%value's source code)" - return {..} - statements:"\(%var_lua's "expr") = \(%value_lua's "expr");" - locals: =lua "(\%var.type == 'Var' and {\%var_lua.expr} or nil)" - -immediately: - # Simultaneous mutli-assignments like: x,y,z = 1,x,3; - compile [<- %assignments] to: - %locals <- [] - %targets <- [] - %values <- [] - assume ((%assignments' "type") is "Dict") or barf ".." - Expected a Dict for the assignments part of '<- %' statement, not \(%assignments' source code) - lua> ".." - for i, item in ipairs(\%assignments.value) do - local target, value = item.dict_key, item.dict_value; - local target_lua = nomsu:tree_to_lua(target); - if not target_lua.expr then error("Invalid target for assignment: "..target:get_src()); end - local value_lua = nomsu:tree_to_lua(value); - if not value_lua.expr then error("Invalid value for assignment: "..value:get_src()); end - if target.type == "Var" then - table.insert(\%locals, target_lua.expr); - end - table.insert(\%targets, target_lua.expr); - table.insert(\%values, value_lua.expr); - end - utils.deduplicate(\%locals); - return {locals=\%locals, statements=(table.concat(\%targets, ", ").." = "..table.concat(\%values, ", ")..";")}; - -immediately: - compile [export %var <- %value] to: - %var_lua <- (%var as lua) - assume (%var_lua's "expr") or barf "Invalid target for assignment: \(%var's source code)" - %value_lua <- (%value as lua) - assume (%value_lua's "expr") or barf "Invalid value for assignment: \(%value's source code)" - return {statements:"\(%var_lua's "expr") = \(%value_lua's "expr");"} - - compile [exporting %exported %body] to: - %body_lua <- (%body as lua) - %leftover_locals <- (=lua "{unpack(\%body_lua.locals or {})}") - assume ((%exported's "type") = "List") or barf ".." - Expected a List for the export part of 'exporting' statement, not \(%exported's source code) - lua> ".." - for i, item in ipairs(\%exported.value) do - if item.type ~= "Var" then - error("'exporting' statement expects Vars, not: "..item:get_src()); - end - local var = nomsu:tree_to_lua(item).expr; - utils.remove_from_list(\%leftover_locals, var); - end - return {locals:%leftover_locals, statements:=lua "\%body_lua.statements or (\%body_lua.expr..';')"} - - compile [with %assignments %body] to: - %body_lua <- (%body as lua) - %locals <- [] - %declarations <- [] - %leftover_locals <- (=lua "{unpack(\%body_lua.locals or {})}") - assume ((%assignments' "type") is "List") or barf ".." - Expected a List for the assignments part of 'with' statement, not \(%assignments' source code) - lua> ".." - for i, item in ipairs(\%assignments.value) do - if item.type == "Var" then - local var = nomsu:tree_to_lua(item).expr; - utils.remove_from_list(\%leftover_locals, var); - table.insert(\%locals, var); - else - if not (item.type == "FunctionCall" and #item.value == 3 and item.value[2].value == "<-") then - error("'with' statement expects entries of the form: '%var <- %value', not: "..item:get_src()); - end - local target, value = item.value[1], item.value[3]; - local target_lua = nomsu:tree_to_lua(target); - if not target_lua.expr then error("Invalid target for assignment: "..target:get_src()); end - local value_lua = nomsu:tree_to_lua(value); - if not value_lua.expr then error("Invalid value for assignment: "..value:get_src()); end - if target.type == "Var" then - utils.remove_from_list(\%leftover_locals, target_lua.expr); - end - table.insert(\%declarations, (("local %s = %s;\\n "):format( - target_lua.expr, value_lua.expr))); - end - end - local locals_code = ""; - if #\%locals > 0 then - locals_code = "\\nlocal "..table.concat(\%locals, ", ")..";"; - end - local declaration_code = ""; - if #\%declarations > 0 then - declaration_code = "\\n"..table.concat(\%declarations, "\\n"); - end - return {locals=\%leftover_locals, statements=([[ - do%s%s - %s - end]]):format(locals_code, declaration_code, \%body_lua.statements or (\%body_lua.expr..";"))}; - -immediately: - # Math Operators - compile [%x + %y] to {expr:"(\(%x as lua expr) + \(%y as lua expr))"} - compile [%x - %y] to {expr:"(\(%x as lua expr) - \(%y as lua expr))"} - compile [%x * %y] to {expr:"(\(%x as lua expr) * \(%y as lua expr))"} - compile [%x / %y] to {expr:"(\(%x as lua expr) / \(%y as lua expr))"} - compile [%x ^ %y] to {expr:"(\(%x as lua expr) ^ \(%y as lua expr))"} - compile [%x wrapped around %y, %x mod %y] to {expr:"(\(%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) - parse [%x < %y < %z] as: =lua "(function(x,y,z) return x < y and y < z; end)(\%x,\%y,\%z)" - parse [%x <= %y < %z] as: =lua "(function(x,y,z) return x <= y and y < z; end)(\%x,\%y,\%z)" - parse [%x < %y <= %z] as: =lua "(function(x,y,z) return x < y and y <= z; end)(\%x,\%y,\%z)" - parse [%x <= %y <= %z] as: =lua "(function(x,y,z) return x <= y and y <= z; end)(\%x,\%y,\%z)" - parse [%x > %y > %z] as: =lua "(function(x,y,z) return x > y and y > z; end)(\%x,\%y,\%z)" - parse [%x >= %y > %z] as: =lua "(function(x,y,z) return x >= y and y > z; end)(\%x,\%y,\%z)" - parse [%x > %y >= %z] as: =lua "(function(x,y,z) return x > y and y >= z; end)(\%x,\%y,\%z)" - parse [%x >= %y >= %z] as: =lua "(function(x,y,z) return x >= y and y >= z; end)(\%x,\%y,\%z)" - # TODO: optimize for common case where x,y,z are all either variables or number literals - - # Boolean Operators - compile [%x and %y] to {expr:"(\(%x as lua expr) and \(%y as lua expr))"} - compile [%x or %y] to {expr:"(\(%x as lua expr) or \(%y as lua expr))"} - - # Bitwise Operators - compile [%a OR %b, %a | %b] to {expr:"bit32.bor(\(%a as lua expr), \(%b as lua expr))"} - compile [%a XOR %b] to {expr:"bit32.bxor(\(%a as lua expr), \(%b as lua expr))"} - compile [%a AND %b, %a & %b] to {expr:"bit32.band(\(%a as lua expr), \(%b as lua expr))"} - compile [NOT %, ~ %] to {expr:"bit32.bnot(\(% as lua expr))"} - compile [%x LSHIFT %shift, %x << %shift] to {expr:"bit32.lshift(\(%x as lua expr), \(%shift as lua expr))"} - compile [%x RSHIFT %shift, %x >>> %shift] to {expr:"bit32.rshift(\(%x as lua expr), \(%shift as lua expr))"} - compile [%x ARSHIFT %shift, %x >> %shift] to {expr:"bit32.arshift(\(%x as lua expr), \(%shift as lua expr))"} - # TODO: implement OR, XOR, AND for multiple operands? - - # Unary operators - compile [- %] to {expr:"(- \(% as lua expr))"} - compile [not %] to {expr:"(not \(% as lua expr))"} - -# Update operators -immediately: - parse [%var + <- %, %var +<- %] as: %var <- (%var + %) - parse [%var - <- %, %var -<- %] as: %var <- (%var - %) - parse [%var * <- %, %var *<- %] as: %var <- (%var * %) - parse [%var / <- %, %var /<- %] as: %var <- (%var / %) - parse [%var ^ <- %, %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 %) |
