aboutsummaryrefslogtreecommitdiff
path: root/lib/operators.nom
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-02-02 15:48:28 -0800
committerBruce Hill <bitbucket@bruce-hill.com>2018-02-02 15:49:42 -0800
commit505fec2a61d2571317cc4bbc36ec0f4822a63f9d (patch)
treec2b37e9db8e2f958fbca0caa0a9c4924912a37a9 /lib/operators.nom
parent513c721198b2256235a95c98d161ab1bb51e6671 (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.nom209
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 %)