aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core.nom39
-rwxr-xr-xnomic.moon34
2 files changed, 53 insertions, 20 deletions
diff --git a/core.nom b/core.nom
index 45b4116..8ef2a80 100644
--- a/core.nom
+++ b/core.nom
@@ -17,7 +17,7 @@ rule "macro block %spec %body":
| 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.")
+ | compiler:error("Macro: "..spec.." was defined to be a block, but is being used as an expression.")
| end
| return body(compiler, vars, kind), true
| end
@@ -127,7 +127,7 @@ rule "do %action":
macro block "if %condition %if_body":
concat [..]
"if ",%condition as lua expr," then"
- "\n ",lua expr "vars.if_body.value.value" as lua block
+ "\n ",(lua expr "vars.if_body.value.value") as lua block
"\nend"
macro block "if %condition %if_body else %else_body":
@@ -195,7 +195,7 @@ macro ["%index st in %list", "%index nd in %list", "%index rd in %list", "%index
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"]:
+macro ["length of %list", "size of %list", "number of %list"]:
concat ["#(",%list as lua expr,")"]
rule "restrict %fn to within %whitelist":
@@ -203,11 +203,16 @@ rule "restrict %fn to within %whitelist":
|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 _,w in ipairs(whitelist) do
+ | if not compiler.defs[w] then
+ | compiler:error("Undefined function: "..tostring(w))
+ | else whiteset[w] = true
+ | end
+ |end
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
- | print("Undefined function: "..tostring(fn))
+ | compiler:error("Undefined function: "..tostring(fn))
| elseif not compiler:check_permission(fn) then
| print("You do not have permission to restrict function: "..tostring(fn))
| else
@@ -219,16 +224,23 @@ 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 _,w in ipairs(whitelist) do
+ | if not compiler.defs[w] then
+ | compiler:error("Undefined function: "..tostring(w))
+ | end
+ |end
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
- | print("Undefined function: "..tostring(fn))
+ | compiler:error("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
+ | for _,w in ipairs(whitelist) do
+ | fn_info.whiteset[w] = true
+ | end
| end
|end
@@ -236,10 +248,15 @@ 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 _,b in ipairs(blacklist) do
+ | if not compiler.defs[b] then
+ | compiler:error("Undefined function: "..tostring(b))
+ | end
+ |end
|for _,fn in ipairs(fns) do
| local fn_info = compiler.defs[fn]
| if fn_info == nil then
- | print("Undefined function: "..tostring(fn))
+ | compiler:error("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
@@ -248,3 +265,9 @@ rule "forbid %blacklist to use %fn":
| for _,b in ipairs(blacklist) do fn_info.whiteset[b] = nil end
| end
|end
+
+rule "error!":
+ lua block "compiler:error()"
+
+rule "error %msg":
+ lua block "compiler:error(vars.msg)"
diff --git a/nomic.moon b/nomic.moon
index 73b48c2..3a72664 100755
--- a/nomic.moon
+++ b/nomic.moon
@@ -93,11 +93,11 @@ class Compiler
call: (fn_name,...)=>
fn_info = @defs[fn_name]
if fn_info == nil
- error "Attempt to call undefined function: #{fn_name}"
+ @error "Attempt to call undefined function: #{fn_name}"
if fn_info.is_macro
- error "Attempt to call macro at runtime: #{fn_name}"
+ @error "Attempt to call macro at runtime: #{fn_name}"
unless @check_permission(fn_name)
- error "You do not have the authority to call: #{fn_name}"
+ @error "You do not have the authority to call: #{fn_name}"
table.insert @callstack, fn_name
{:fn, :arg_names} = fn_info
args = {name, select(i,...) for i,name in ipairs(arg_names)}
@@ -110,7 +110,7 @@ class Compiler
check_permission: (fn_name)=>
fn_info = @defs[fn_name]
if fn_info == nil
- error "Undefined function: #{fn_name}"
+ @error "Undefined function: #{fn_name}"
if fn_info.whiteset == nil then return true
for caller in *@callstack
if fn_info.whiteset[caller]
@@ -135,7 +135,7 @@ class Compiler
table.insert(invocations, invocation)
if arg_names
if not utils.equivalent(utils.set(arg_names), utils.set(_arg_names))
- error("Conflicting argument names #{utils.repr(arg_names)} and #{utils.repr(_arg_names)} for #{utils.repr(text)}")
+ @error("Conflicting argument names #{utils.repr(arg_names)} and #{utils.repr(_arg_names)} for #{utils.repr(text)}")
else arg_names = _arg_names
return invocations, arg_names
@@ -249,10 +249,13 @@ class Compiler
for statement in *tree.value.body.value
code = to_lua(statement)
-- Run the fuckers as we go
- lua_thunk, err = loadstring("return (function(compiler, vars)\n#{code}\nend)")
+ lua_thunk, err = load("return (function(compiler, vars)\n#{code}\nend)")
if not lua_thunk
error("Failed to compile generated code:\n#{code}\n\n#{err}")
- lua_thunk!(self, vars)
+ ok,err = pcall(lua_thunk)
+ if not ok then error(err)
+ ok,err = pcall(err, self, vars)
+ if not ok then @error(err)
add code
add [[
return ret
@@ -354,9 +357,9 @@ class Compiler
run_macro: (tree, kind="Expression")=>
name = @fn_name_from_tree(tree)
unless @defs[name] and @defs[name].is_macro
- error("Macro not found: #{name}")
+ @error("Macro not found: #{name}")
unless @check_permission(name)
- error "You do not have the authority to call: #{name}"
+ @error "You do not have the authority to call: #{name}"
{:fn, :arg_names} = @defs[name]
args = [a for a in *tree.value when a.type != "Word"]
args = {name,args[i] for i,name in ipairs(arg_names)}
@@ -364,7 +367,7 @@ class Compiler
ret, manual_mode = fn(self, args, kind)
table.remove @callstack
if not ret
- error("No return value for macro: #{name}")
+ @error("No return value for macro: #{name}")
if kind == "Statement" and not manual_mode
ret = "ret = "..ret
return ret
@@ -450,6 +453,13 @@ class Compiler
output\write(code)
return code
+ error: (...)=>
+ print(...)
+ print("Callstack:")
+ for i=#@callstack,1,-1
+ print " #{@callstack[i]}"
+ error!
+
test: (src, expected)=>
i = 1
while i != nil
@@ -459,13 +469,13 @@ class Compiler
i = stop
start,stop = test\find"==="
if not start or not stop then
- error("WHERE'S THE ===? in:\n#{test}")
+ @error("WHERE'S THE ===? in:\n#{test}")
test_src, expected = test\sub(1,start-1), test\sub(stop+1,-1)
expected = expected\match'[\n]*(.*[^\n])'
tree = @parse(test_src)
got = @stringify_tree(tree.value.body)
if got != expected
- error"TEST FAILED!\nSource:\n#{test_src}\nExpected:\n#{expected}\n\nGot:\n#{got}"
+ @error"TEST FAILED!\nSource:\n#{test_src}\nExpected:\n#{expected}\n\nGot:\n#{got}"
initialize_core: =>