nomsu/core.nom
2017-09-12 20:00:19 -07:00

251 lines
11 KiB
Plaintext

(# Global import #)
lua block ".."
|utils = require('utils')
lua block ".."
|compiler:def("rule %spec %body", function(compiler, vars)
| return compiler:def(vars.spec, vars.body)
|end)
rule "macro %spec %body":
lua block ".."
|compiler:defmacro(vars.spec, vars.body)
rule "macro block %spec %body":
lua block ".."
|do
| local spec, body = vars.spec, vars.body
| local wrapper = function(compiler, vars, kind)
| if kind == "Expression" then
| error("Macro: "..spec.." was defined to be a block, but is being used as an expression.")
| end
| return body(compiler, vars, kind), true
| end
| compiler:defmacro(spec, wrapper)
| return nil
|end
rule ["eval %code", "run %code"]:
lua expr "compiler:run(vars.code)"
macro "source code %code":
lua expr "utils.repr(vars.code.src, true)"
rule "run file %filename":
lua block [..]
"do"
"\n local file = io.open(vars.filename)"
"\n return compiler:run(file:read('*a'))"
"\nend"
rule "%tree as lua block":
lua block [..]
"do return compiler:tree_to_lua(", %tree, ", 'Statement'), true end"
rule "%tree as lua expr":
lua expr [..]
"compiler:tree_to_lua(", %tree, ", 'Expression')"
rule "concat %strs":
lua block [..]
"local str_bits = {}"
"\nfor i,bit in ipairs(vars.strs) do str_bits[i] = utils.repr(bit) end"
"\ndo return table.concat(str_bits) end"
rule "concat %strs with glue %glue":
lua block [..]
"local str_bits = {}"
"\nfor i,bit in ipairs(vars.strs) do str_bits[i] = utils.repr(bit) end"
"\ndo return table.concat(str_bits, vars.glue) end"
macro block "return %return-value":
concat ["do return ",%return-value as lua expr," end"]
macro block "let %varname = %value":
concat ["vars[",%varname as lua expr,"] = ",%value as lua expr]
macro ["true","yes"]: "true"
macro ["false","no"]: "false"
macro ["nil","null"]: "nil"
macro block ["nop", "pass"]: ""
macro "%a + %b": concat ["(",%a as lua expr," + ",%b as lua expr,")"]
macro "%a + %b + %c": concat ["(",%a as lua expr," + ",%b as lua expr," + ",%c as lua expr,")"]
macro "%a + %b + %c + %d": concat ["(",%a as lua expr," + ",%b as lua expr," + ",%c as lua expr," + ",%d as lua expr,")"]
macro "%a - %b": concat ["(",%a as lua expr," - ",%b as lua expr,")"]
macro "%a * %b": concat ["(",%a as lua expr," * ",%b as lua expr,")"]
macro "%a * %b * %c": concat ["(",%a as lua expr," * ",%b as lua expr," * ",%c as lua expr,")"]
macro "%a * %b * %c * %d": concat ["(",%a as lua expr," * ",%b as lua expr," * ",%c as lua expr," * ",%d as lua expr,")"]
macro "%a / %b": concat ["(",%a as lua expr," / ",%b as lua expr,")"]
macro "%a === %b": concat ["(",%a as lua expr," == ",%b as lua expr,")"]
macro "%a !== %b": concat ["(",%a as lua expr," ~= ",%b as lua expr,")"]
macro "%a < %b": concat ["(",%a as lua expr," < ",%b as lua expr,")"]
macro "%a < %b < %c": concat ["((",%a as lua expr," < ",%b as lua expr,") and (",%b as lua expr," < ",%c as lua expr,"))"]
macro "%a <= %b < %c": concat ["((",%a as lua expr," <= ",%b as lua expr,") and (",%b as lua expr," < ",%c as lua expr,"))"]
macro "%a <= %b <= %c": concat ["((",%a as lua expr," <= ",%b as lua expr,") and (",%b as lua expr," <= ",%c as lua expr,"))"]
macro "%a < %b <= %c": concat ["((",%a as lua expr," < ",%b as lua expr,") and (",%b as lua expr," <= ",%c as lua expr,"))"]
macro "%a > %b > %c": concat ["((",%a as lua expr," > ",%b as lua expr,") and (",%b as lua expr," > ",%c as lua expr,"))"]
macro "%a >= %b > %c": concat ["((",%a as lua expr," >= ",%b as lua expr,") and (",%b as lua expr," > ",%c as lua expr,"))"]
macro "%a >= %b >= %c": concat ["((",%a as lua expr," >= ",%b as lua expr,") and (",%b as lua expr," >= ",%c as lua expr,"))"]
macro "%a > %b >= %c": concat ["((",%a as lua expr," > ",%b as lua expr,") and (",%b as lua expr," >= ",%c as lua expr,"))"]
macro "%a <= %b": concat ["(",%a as lua expr," <= ",%b as lua expr,")"]
macro "%a > %b": concat ["(",%a as lua expr," > ",%b as lua expr,")"]
macro "%a >= %b": concat ["(",%a as lua expr," >= ",%b as lua expr,")"]
macro "%a ^ %b": concat ["(",%a as lua expr," ^ ",%b as lua expr,")"]
macro "%a and %b": concat ["(",%a as lua expr," and ",%b as lua expr,")"]
macro "%a and %b and %c":
concat ["(",%a as lua expr," and ",%b as lua expr," and ",%c as lua expr,")"]
macro "%a and %b and %c and %d":
concat ["(",%a as lua expr," and ",%b as lua expr," and ",%c as lua expr," and ",%d as lua expr,")"]
macro "%a or %b": concat ["(",%a as lua expr," or ",%b as lua expr,")"]
macro "%a or %b or %c":
concat ["(",%a as lua expr," or ",%b as lua expr," or ",%c as lua expr,")"]
macro "%a or %b or %c or %d":
concat ["(",%a as lua expr," or ",%b as lua expr," or ",%c as lua expr," or ",%d as lua expr,")"]
macro "%a mod %b": concat ["(",%a as lua expr," mod ",%b as lua expr,")"]
macro "- %a": concat ["-(",%a as lua expr,")"]
macro "not %a": concat ["not (",%a as lua expr,")"]
macro "# %a": concat ["#(",%a as lua expr,")"]
(# This does equivalence checking instead of identity checking. #)
rule "%a == %b":
lua expr "utils.equivalent(vars.a, vars.b)"
macro "%a != %b": concat ["not (",%a as lua expr," == ",%b as lua expr,")"]
rule "say %str":
lua block ["print(", %str, ")"]
rule "printf %str":
lua block ".."
|for _,s in ipairs(vars.str) do
| io.write(utils.repr(s))
|end
|io.write("\n")
rule "do %action":
lua expr "vars.action(compiler, setmetatable({}, {__index=vars}))"
macro block "if %condition %if_body":
concat [..]
"if ",%condition as lua expr," then"
"\n ",lua expr "vars.if_body.value.value" as lua block
"\nend"
macro block "if %condition %if_body else %else_body":
concat [..]
"if ",%condition as lua expr," then"
"\n ",(lua expr "vars.if_body.value.value") as lua block
"\nelse"
"\n ",(lua expr "vars.else_body.value.value") as lua block
"\nend"
macro "%if_expr if %condition else %else_expr":
concat [..]
"(function(compiler, vars)"
"\n if ",%condition as lua expr," then"
"\n return ",%if_expr as lua expr
"\n else"
"\n return ",%else_expr as lua expr
"\n end"
"\nend)(compiler, vars)"
macro block "for %varname in %iterable %body":
let "varname" = (%varname as lua expr)
concat [..]
"do"
"\n local old_loopval = vars[", %varname, "]"
"\n for i,value in ipairs(", %iterable as lua expr, ") do"
"\n vars[", %varname, "] = value"
"\n ",(lua expr "vars.body.value.value") as lua block
"\n end"
"\n vars[", %varname, "] = old_loopval"
"\nend"
rule "%start up to %stop":
lua expr "utils.range(vars.start,vars.stop-1)"
rule ["%start thru %stop", "%start through %stop"]:
lua expr "utils.range(vars.start,vars.stop)"
rule "%start down to %stop":
lua expr "utils.range(vars.start,vars.stop+1,-1)"
rule ["%start down thru %stop", "%start down through %stop"]:
lua expr "utils.range(vars.start,vars.stop,-1)"
rule ["random number"]: lua expr "math.random()"
rule ["sum of %items"]: lua expr "utils.sum(vars.items)"
rule ["product of %items"]: lua expr "utils.product(vars.items)"
rule ["all of %items"]: lua expr "utils.all(vars.items)"
rule ["any of %items"]: lua expr "utils.any(vars.items)"
rule ["avg of %items", "average of %items"]: lua expr "(utils.sum(vars.items)/#vars.items)"
rule ["min of %items", "smallest of %items", "lowest of %items"]:
lua expr "utils.min(vars.items)"
rule ["max of %items", "biggest of %items", "largest of %items", "highest of %items"]:
lua expr "utils.min(vars.items)"
rule ["min of %items with respect to %keys"]:
lua expr "utils.min(vars.items, vars.keys)"
rule ["max of %items with respect to %keys"]:
lua expr "utils.max(vars.items, vars.keys)"
macro ["%index st in %list", "%index nd in %list", "%index rd in %list", "%index th in %list"]:
concat [(%list as lua expr), "[", (%index as lua expr), "]"]
macro ["%item is in %list", "%list contains %item"]:
concat ["(",%list as lua expr,"[",%index as lua expr,"] ~= nil)"]
macro ["length of %list", "size of %list"]:
concat ["#(",%list as lua expr,")"]
rule "restrict %fn to within %whitelist":
lua block ".."
|local fns = (type(vars.fn) == 'string') and {vars.fn} or vars.fn
|local whitelist = (type(vars.whitelist) == 'string') and {vars.whitelist} or vars.whitelist
|local whiteset = {}
|for _,w in ipairs(whitelist) do whiteset[w] = true end
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
| print("Undefined function: "..tostring(fn))
| elseif not compiler:check_permission(fn) then
| print("You do not have permission to restrict function: "..tostring(fn))
| else
| compiler.defs[fn].whiteset = whiteset
| end
|end
rule "allow %whitelist to use %fn":
lua block ".."
|local fns = (type(vars.fn) == 'string') and {vars.fn} or vars.fn
|local whitelist = (type(vars.whitelist) == 'string') and {vars.whitelist} or vars.whitelist
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
| print("Undefined function: "..tostring(fn))
| elseif fn_info.whiteset == nil then
| print("Function is already allowed by everyone: "..tostring(fn))
| elseif not compiler:check_permission(fn) then
| print("You do not have permission to grant permissions for function: "..tostring(fn))
| else
| for _,w in ipairs(whitelist) do fn_info.whiteset[w] = true end
| end
|end
rule "forbid %blacklist to use %fn":
lua block ".."
|local fns = (type(vars.fn) == 'string') and {vars.fn} or vars.fn
|local blacklist = (type(vars.blacklist) == 'string') and {vars.blacklist} or vars.blacklist
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
| print("Undefined function: "..tostring(fn))
| elseif fn_info.whiteset == nil then
| print("Cannot remove items from a whitelist when there is no whitelist on function: "..tostring(fn))
| elseif not compiler:check_permission(fn) then
| print("You do not have permission to restrict function: "..tostring(fn))
| else
| for _,b in ipairs(blacklist) do fn_info.whiteset[b] = nil end
| end
|end