aboutsummaryrefslogtreecommitdiff
path: root/core.nom
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2017-09-12 20:00:19 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2017-09-12 20:00:19 -0700
commitaa3401ab215cd2d3e60608da385477f154c58175 (patch)
treeb798ccc1857a91ac905acb6358a02131b6d7eac1 /core.nom
parentc0efa6c7d12e3f9749f6e2dafe507799aa47fad6 (diff)
Major cleanup and consolidation.
Diffstat (limited to 'core.nom')
-rw-r--r--core.nom250
1 files changed, 250 insertions, 0 deletions
diff --git a/core.nom b/core.nom
new file mode 100644
index 0000000..45b4116
--- /dev/null
+++ b/core.nom
@@ -0,0 +1,250 @@
+(# 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