
return values with either an explicit "return" statement or if they're the only line in the function, and the line is an expression.
120 lines
5.7 KiB
Plaintext
120 lines
5.7 KiB
Plaintext
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: ""
|
|
|
|
# Ternary operator
|
|
#.. Note: this uses a function instead of "(condition and if_expr or else_expr)"
|
|
because that breaks if %if_expr is falsey, e.g. "x < 5 and false or 99"
|
|
compile [..]
|
|
%when_true_expr if %condition else %when_false_expr
|
|
%when_true_expr if %condition otherwise %when_false_expr
|
|
%when_false_expr unless %condition else %when_true_expr
|
|
%when_false_expr unless %condition then %when_true_expr
|
|
..to: ".."
|
|
(function(nomsu, vars)
|
|
if \(%condition as lua) then
|
|
return \(%when_true_expr as lua);
|
|
else
|
|
return \(%when_false_expr as lua);
|
|
end
|
|
end)(nomsu, vars)
|
|
parse [..]
|
|
%true if %x == %y else %false, %true if %x == %y otherwise %false
|
|
%false unless %x == %y else %true, %false unless %x == %y otherwise %true
|
|
..as:
|
|
%true if (%x == %y) else %false
|
|
|
|
parse [..]
|
|
%true if %x != %y else %false, %true if %x != %y otherwise %false
|
|
%false unless %x != %y else %true, %false unless %x != %y otherwise %true
|
|
..as:
|
|
%true if (%x != %y) else %false
|
|
|
|
# Indexing:
|
|
compile [%obj'%key, %obj's %key, %obj -> %key] to: "(\(%obj as lua))[\(%key as lua)]"
|
|
|
|
# Substring
|
|
compile [%str |%start|] to: "\(%str as lua):sub(\(%start as lua), \(%start as lua))"
|
|
compile [%str |%start - %stop|] to: "\(%str as lua):sub(\(%start as lua), \(%stop as lua))"
|
|
|
|
# Variable assignment operator, and += type versions
|
|
compile [%var = %val] to code:
|
|
lua> ".."
|
|
if \%var.type == 'List' and \%val.type == 'List' then
|
|
local lhs = {};
|
|
for i,x in ipairs(\%var.value) do lhs[i] = nomsu:tree_to_lua(x); end
|
|
local rhs = {};
|
|
for i,x in ipairs(\%val.value) do rhs[i] = nomsu:tree_to_lua(x); end
|
|
return table.concat(lhs, ", ").." = "..table.concat(rhs, ", ")..";";
|
|
else
|
|
return \(%var as lua).." = "..\(%val as lua)..";";
|
|
end
|
|
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);"
|
|
|
|
# Math 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))"
|
|
compile [%x ^ %y] to: "(\(%x as lua) ^ \(%y as lua))"
|
|
compile [%x mod %y] to: "(\(%x as lua) % \(%y as lua))"
|
|
|
|
# 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 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, %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))"
|
|
# TODO: implement OR, XOR, AND for multiple operands?
|
|
|
|
# Unary operators
|
|
compile [- %] to: "-(\(% as lua))"
|
|
compile [not %] to: "not (\(% as lua))"
|