Some overhaul of binary operators so that arbitrary math patterns work
fine.
This commit is contained in:
parent
b1c6354464
commit
c92e5fbc81
@ -7,10 +7,11 @@ compile [if %condition %if_body] to code: ".."
|
|||||||
if \(%condition as lua) then
|
if \(%condition as lua) then
|
||||||
\(%if_body as lua statements)
|
\(%if_body as lua statements)
|
||||||
end --end if
|
end --end if
|
||||||
compile [unless %condition %body] to code: ".."
|
parse [unless %condition %unless_body] as: if (not %condition) %unless_body
|
||||||
if not (\(%condition as lua)) then
|
parse [if %x == %y %if_body] as: if (%x == %y) %if_body
|
||||||
\(%body as lua statements)
|
parse [if %x != %y %if_body] as: if (%x != %y) %if_body
|
||||||
end --end if
|
parse [unless %x == %y %if_body] as: if (%x != %y) %if_body
|
||||||
|
parse [unless %x != %y %if_body] as: if (%x == %y) %if_body
|
||||||
|
|
||||||
compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to code: ".."
|
compile [if %condition %if_body else %else_body, unless %condition %else_body else %if_body] to code: ".."
|
||||||
if \(%condition as lua) then
|
if \(%condition as lua) then
|
||||||
@ -18,6 +19,10 @@ compile [if %condition %if_body else %else_body, unless %condition %else_body el
|
|||||||
else
|
else
|
||||||
\(%else_body as lua statements)
|
\(%else_body as lua statements)
|
||||||
end --end if
|
end --end if
|
||||||
|
parse [if %x == %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
|
||||||
|
parse [if %x != %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
|
||||||
|
parse [unless %x == %y %if_body else %else_body] as: if (%x != %y) %if_body else %else_body
|
||||||
|
parse [unless %x != %y %if_body else %else_body] as: if (%x == %y) %if_body else %else_body
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
compile [return] to code: "do return; end"
|
compile [return] to code: "do return; end"
|
||||||
@ -60,6 +65,10 @@ compile [repeat while %condition %body] to code:
|
|||||||
return %code
|
return %code
|
||||||
parse [repeat %body] as: repeat while (true) %body
|
parse [repeat %body] as: repeat while (true) %body
|
||||||
parse [repeat until %condition %body] as: repeat while (not %condition) %body
|
parse [repeat until %condition %body] as: repeat while (not %condition) %body
|
||||||
|
parse [repeat while %x == %y %body] as: repeat while (%x == %y) %body
|
||||||
|
parse [repeat while %x != %y %body] as: repeat while (%x != %y) %body
|
||||||
|
parse [repeat until %x == %y %body] as: repeat while (%x != %y) %body
|
||||||
|
parse [repeat until %x != %y %body] as: repeat while (%x == %y) %body
|
||||||
|
|
||||||
# For loop control flow:
|
# For loop control flow:
|
||||||
compile [stop for-loop] to code: "goto stop_for;"
|
compile [stop for-loop] to code: "goto stop_for;"
|
||||||
|
@ -57,84 +57,51 @@ compile [%var or= %val] to code: "\(%var as lua) = \(%var as lua) or \(%val as l
|
|||||||
compile [%var join= %val] to code: "\(%var as lua) = \(%var as lua) .. \(%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);"
|
compile [%var mod= %val] to code: "\(%var as lua) = \(%var as lua) % \(%val as lua);"
|
||||||
|
|
||||||
# Binary Operators
|
# Math Operators
|
||||||
lua do> ".."
|
compile [%x + %y] to: "(\(%x as lua) + \(%y as lua))"
|
||||||
local binops = {"-","/","<","<=",">",">=","^",{"===","=="},{"!==","~="},{"mod","%"}};
|
compile [%x - %y] to: "(\(%x as lua) - \(%y as lua))"
|
||||||
for _,op in ipairs(binops) do
|
compile [%x * %y] to: "(\(%x as lua) * \(%y as lua))"
|
||||||
local nomsu_alias = op;
|
compile [%x / %y] to: "(\(%x as lua) / \(%y as lua))"
|
||||||
if type(op) == 'table' then;
|
compile [%x ^ %y] to: "(\(%x as lua) ^ \(%y as lua))"
|
||||||
nomsu_alias, op = unpack(op);
|
compile [%x mod %y] to: "(\(%x as lua) % \(%y as lua))"
|
||||||
end
|
|
||||||
nomsu:defmacro("%a "..nomsu_alias.." %b", (function(nomsu, vars)
|
|
||||||
return "("..nomsu:tree_to_lua(\%a).." "..op.." "..nomsu:tree_to_lua(\%b)..")";
|
|
||||||
end), [["(\\%a ]]..op..[[ \\%b)"]]);
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: implement OR, XOR, AND for multiple operands
|
# Comparison Operators
|
||||||
|
compile [%x < %y] to: "(\(%x as lua) < \(%y as lua))"
|
||||||
|
compile [%x > %y] to: "(\(%x as lua) > \(%y as lua))"
|
||||||
|
compile [%x <= %y] to: "(\(%x as lua) <= \(%y as lua))"
|
||||||
|
compile [%x >= %y] to: "(\(%x as lua) >= \(%y 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)))"
|
||||||
|
# For strict identity checking:
|
||||||
|
compile [%x === %y] to: "(\(%x as lua) == \(%y as lua))"
|
||||||
|
compile [%x !== %y] to: "(\(%x as lua) ~= \(%y as lua))"
|
||||||
|
|
||||||
|
# 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: "(\(%x as lua) and \(%y as lua))"
|
||||||
|
compile [%x or %y] to: "(\(%x as lua) or \(%y as lua))"
|
||||||
|
|
||||||
|
# Bitwise Operators
|
||||||
compile [%a OR %b, %a | %b] to: "bit32.bor(\(%a as lua), \(%b 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 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 [%a AND %b, %a & %b] to: "bit32.band(\(%a as lua), \(%b as lua))"
|
||||||
compile [NOT %, ~ %] to: "bit32.bnot(\(% 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 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 RSHIFT %shift, %x >>> %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 [%x ARSHIFT %shift, %x >> %shift] to: "bit32.arshift(\(%x as lua), \(%shift as lua))"
|
||||||
# == and != do equivalence checking, rather than identity checking
|
# TODO: implement OR, XOR, AND for multiple operands?
|
||||||
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 do> ".."
|
|
||||||
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
|
|
||||||
|
|
||||||
# Chained compairsions (e.g. x < y <= z) are defined up to 3 operands
|
|
||||||
lua 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
|
|
||||||
-- 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[tostring(i)], vars[tostring(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
|
|
||||||
|
|
||||||
# Unary operators
|
# Unary operators
|
||||||
compile [- %] to: "-(\(% as lua))"
|
compile [- %] to: "-(\(% as lua))"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
require "lib/metaprogramming.nom"
|
require "lib/metaprogramming.nom"
|
||||||
require "lib/operators.nom"
|
require "lib/operators.nom"
|
||||||
require "lib/control_flow.nom"
|
require "lib/control_flow.nom"
|
||||||
|
require "lib/collections.nom"
|
||||||
|
|
||||||
compile [<%var> = %value] to code: ".."
|
compile [<%var> = %value] to code: ".."
|
||||||
nomsu.defs['#vars'][\(repr (%var's "value"))] = \(%value as lua);
|
nomsu.defs['#vars'][\(repr (%var's "value"))] = \(%value as lua);
|
||||||
@ -12,25 +13,30 @@ compile [str %] to: "tostring(\(% as lua))"
|
|||||||
compile [scope] to: "nomsu.defs"
|
compile [scope] to: "nomsu.defs"
|
||||||
compile [parent scope] to: "getmetatable(nomsu.defs).__index"
|
compile [parent scope] to: "getmetatable(nomsu.defs).__index"
|
||||||
|
|
||||||
parse [using %scoped do %actions] as:
|
compile [using %scoped do %actions] to code: ".."
|
||||||
%scope = (=lua "setmetatable({['#vars']=setmetatable({}, {__index=nomsu.defs['#vars']})}, {__index=nomsu.defs})")
|
do
|
||||||
with (nomsu's "defs") = %scope:
|
local old_scope, old_vars = nomsu.defs, vars;
|
||||||
do %scoped
|
local use_vars = setmetatable({}, {__index=old_scope['#vars']});
|
||||||
lua> ".."
|
local scope = setmetatable({['#vars']=use_vars}, {__index=old_scope});
|
||||||
getmetatable(nomsu.defs).__newindex = getmetatable(nomsu.defs).__index;
|
nomsu.defs = scope;
|
||||||
getmetatable(nomsu.defs["#vars"]).__newindex = getmetatable(nomsu.defs["#vars"]).__index;
|
local ok, ret = pcall(function(nomsu, vars)
|
||||||
do %actions
|
local ret;
|
||||||
|
do
|
||||||
|
\(%scoped as lua statements)
|
||||||
|
end
|
||||||
|
getmetatable(scope).__newindex = old_scope;
|
||||||
|
getmetatable(use_vars).__newindex = old_vars;
|
||||||
|
do
|
||||||
|
\(%actions as lua statements)
|
||||||
|
end
|
||||||
|
return ret;
|
||||||
|
end, nomsu, use_vars);
|
||||||
|
nomsu.defs = old_scope;
|
||||||
|
if not ok then nomsu:error(ret); end
|
||||||
|
end
|
||||||
|
|
||||||
parse [scoped %actions] as: using %actions do (:pass)
|
parse [scoped %actions] as: using %actions do (:pass)
|
||||||
|
|
||||||
rule [from %filename import %rules] =:
|
|
||||||
using:
|
|
||||||
require %filename
|
|
||||||
..do:
|
|
||||||
%srcs = ((%'s "src") for %_ = % in (parent scope))
|
|
||||||
for %src in (unique %srcs):
|
|
||||||
run %src
|
|
||||||
|
|
||||||
parse [wrap %signature with %body] as:
|
parse [wrap %signature with %body] as:
|
||||||
using:
|
using:
|
||||||
run ((nomsu)->*["defs",nomsu "get_stub" [\%signature->*["value",1]],"src"])
|
run ((nomsu)->*["defs",nomsu "get_stub" [\%signature->*["value",1]],"src"])
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
require "lib/core.nom"
|
|
||||||
|
|
||||||
compile [with secrets %block] to code: ".."
|
|
||||||
do
|
|
||||||
local secrets = {};
|
|
||||||
\(%block as lua statements)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Access the lua variable that should be within scope
|
|
||||||
compile [secrets] to: "secrets"
|
|
||||||
|
|
||||||
compile [secret %key, secret value of %key, secret value for %key] to:
|
|
||||||
assert ((%key's "type") == "Var") ".."
|
|
||||||
|Wrong type, expected Var, but got: \(%key's "type")
|
|
||||||
"secrets[\(repr (%key's "value"))]"
|
|
||||||
|
|
||||||
compile [secret %key = %new_value] to code:
|
|
||||||
assert ((%key's "type") == "Var") ".."
|
|
||||||
|Wrong type, expected Var, but got: \(%key's "type")
|
|
||||||
"secrets[\(repr (%key's "value"))] = \(%new_value as lua);"
|
|
||||||
|
|
||||||
rule [rules about secrecy] =: ["with secrets %"]
|
|
||||||
|
|
@ -73,10 +73,6 @@ compile [e] to: "math.e"
|
|||||||
compile [golden ratio, phi] to: "((1 + math.sqrt(5)) / 2)"
|
compile [golden ratio, phi] to: "((1 + math.sqrt(5)) / 2)"
|
||||||
|
|
||||||
# Common utility functions
|
# Common utility functions
|
||||||
compile [sum of %items, sum %items] to: "nomsu.utils.sum(\(%items as lua))"
|
|
||||||
compile [product of %items, product %items] to: "nomsu.utils.product(\(%items as lua))"
|
|
||||||
compile [all of %items] to: "nomsu.utils.all(\(%items as lua))"
|
|
||||||
compile [any of %items] to: "nomsu.utils.any(\(%items as lua))"
|
|
||||||
rule [avg of %items, average of %items] =:
|
rule [avg of %items, average of %items] =:
|
||||||
=lua "(nomsu.utils.sum(\%items)/#\%items)"
|
=lua "(nomsu.utils.sum(\%items)/#\%items)"
|
||||||
compile [min of %items, smallest of %items, lowest of %items] to:
|
compile [min of %items, smallest of %items, lowest of %items] to:
|
||||||
|
@ -49,3 +49,28 @@ compile [with %assignments %action] to code:
|
|||||||
end
|
end
|
||||||
parse [with %thing = %value %action] as: with [%thing = %value] %action
|
parse [with %thing = %value %action] as: with [%thing = %value] %action
|
||||||
|
|
||||||
|
# Any/all/none
|
||||||
|
compile [all of %items, all %items] to:
|
||||||
|
if (%items' "type") == "List":
|
||||||
|
"(\(join ((% as lua) for all (%items' "value")) with glue " and "))"
|
||||||
|
..else:
|
||||||
|
"nomsu.utils.all(\(%items as lua))"
|
||||||
|
parse [not all of %items, not all %items] as: not (all of %items)
|
||||||
|
compile [any of %items, any %items] to:
|
||||||
|
if (%items' "type") == "List":
|
||||||
|
"(\(join ((% as lua) for all (%items' "value")) with glue " or "))"
|
||||||
|
..else:
|
||||||
|
"nomsu.utils.any(\(%items as lua))"
|
||||||
|
parse [none of %items, none %items] as: not (any of %items)
|
||||||
|
|
||||||
|
|
||||||
|
compile [sum of %items, sum %items] to:
|
||||||
|
if (%items' "type") == "List":
|
||||||
|
"(\(join ((% as lua) for all (%items' "value")) with glue " + "))"
|
||||||
|
..else:
|
||||||
|
"nomsu.utils.sum(\(%items as lua))"
|
||||||
|
compile [product of %items, product %items] to:
|
||||||
|
if (%items' "type") == "List":
|
||||||
|
"(\(join ((% as lua) for all (%items' "value")) with glue " * "))"
|
||||||
|
..else:
|
||||||
|
"nomsu.utils.product(\(%items as lua))"
|
||||||
|
23
nomsu.lua
23
nomsu.lua
@ -846,16 +846,22 @@ end)]]):format(concat(lua_bits, "\n"))
|
|||||||
local def = self.defs[tree.stub]
|
local def = self.defs[tree.stub]
|
||||||
if def and def.is_macro then
|
if def and def.is_macro then
|
||||||
local expr, statement = self:run_macro(tree)
|
local expr, statement = self:run_macro(tree)
|
||||||
if def.whiteset then
|
|
||||||
if expr then
|
|
||||||
expr = "(nomsu:assert_permission(" .. tostring(repr(tree.stub)) .. ") and " .. tostring(expr) .. ")"
|
|
||||||
end
|
|
||||||
if statement then
|
|
||||||
statement = "nomsu:assert_permission(" .. tostring(repr(tree.stub)) .. ");\n" .. statement
|
|
||||||
end
|
|
||||||
end
|
|
||||||
remove(self.compilestack)
|
remove(self.compilestack)
|
||||||
return expr, statement
|
return expr, statement
|
||||||
|
elseif not def and self.__class.math_patt:match(tree.stub) then
|
||||||
|
local bits = { }
|
||||||
|
local _list_0 = tree.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local tok = _list_0[_index_0]
|
||||||
|
if tok.type == "Word" then
|
||||||
|
insert(bits, tok.value)
|
||||||
|
else
|
||||||
|
local expr, statement = self:tree_to_lua(tok, filename)
|
||||||
|
self:assert(statement == nil, "non-expression value inside math expression")
|
||||||
|
insert(bits, expr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "(" .. tostring(concat(bits, " ")) .. ")"
|
||||||
end
|
end
|
||||||
local args = {
|
local args = {
|
||||||
repr(tree.stub),
|
repr(tree.stub),
|
||||||
@ -1402,6 +1408,7 @@ end)]]):format(concat(lua_bits, "\n"))
|
|||||||
_base_0.__class = _class_0
|
_base_0.__class = _class_0
|
||||||
local self = _class_0
|
local self = _class_0
|
||||||
self.def_number = 0
|
self.def_number = 0
|
||||||
|
self.math_patt = re.compile([[ "%" (" " [*/^+-] " %")+ ]])
|
||||||
self.unescape_string = function(self, str)
|
self.unescape_string = function(self, str)
|
||||||
return Cs(((P("\\\\") / "\\") + (P("\\\"") / '"') + ESCAPE_CHAR + P(1)) ^ 0):match(str)
|
return Cs(((P("\\\\") / "\\") + (P("\\\"") / '"') + ESCAPE_CHAR + P(1)) ^ 0):match(str)
|
||||||
end
|
end
|
||||||
|
17
nomsu.moon
17
nomsu.moon
@ -533,6 +533,7 @@ end);]])\format(concat(buffer, "\n"))
|
|||||||
else
|
else
|
||||||
error("Unsupported value_to_nomsu type: #{type(value)}")
|
error("Unsupported value_to_nomsu type: #{type(value)}")
|
||||||
|
|
||||||
|
@math_patt: re.compile [[ "%" (" " [*/^+-] " %")+ ]]
|
||||||
tree_to_lua: (tree, filename)=>
|
tree_to_lua: (tree, filename)=>
|
||||||
-- Return <lua code for value>, <additional lua code>
|
-- Return <lua code for value>, <additional lua code>
|
||||||
@assert tree, "No tree provided."
|
@assert tree, "No tree provided."
|
||||||
@ -570,13 +571,19 @@ end)]])\format(concat(lua_bits, "\n"))
|
|||||||
def = @defs[tree.stub]
|
def = @defs[tree.stub]
|
||||||
if def and def.is_macro
|
if def and def.is_macro
|
||||||
expr, statement = @run_macro(tree)
|
expr, statement = @run_macro(tree)
|
||||||
if def.whiteset
|
|
||||||
if expr
|
|
||||||
expr = "(nomsu:assert_permission(#{repr tree.stub}) and #{expr})"
|
|
||||||
if statement
|
|
||||||
statement = "nomsu:assert_permission(#{repr tree.stub});\n"..statement
|
|
||||||
remove @compilestack
|
remove @compilestack
|
||||||
return expr, statement
|
return expr, statement
|
||||||
|
elseif not def and @@math_patt\match(tree.stub)
|
||||||
|
bits = {}
|
||||||
|
for tok in *tree.value
|
||||||
|
if tok.type == "Word"
|
||||||
|
insert bits, tok.value
|
||||||
|
else
|
||||||
|
expr, statement = @tree_to_lua(tok, filename)
|
||||||
|
@assert(statement == nil, "non-expression value inside math expression")
|
||||||
|
insert bits, expr
|
||||||
|
return "(#{concat bits, " "})"
|
||||||
|
|
||||||
args = {repr(tree.stub), repr(tree.line_no)}
|
args = {repr(tree.stub), repr(tree.line_no)}
|
||||||
local arg_names, escaped_args
|
local arg_names, escaped_args
|
||||||
if def
|
if def
|
||||||
|
Loading…
Reference in New Issue
Block a user