working towards moving more code into nomic.

This commit is contained in:
Bruce Hill 2017-09-11 19:23:55 -07:00
parent e0d39996be
commit c26db225f3
3 changed files with 13 additions and 25 deletions

View File

@ -71,7 +71,7 @@ g\def {"restrict %fn to %whitelist"}, (vars)=>
unless self\check_permission(fn) unless self\check_permission(fn)
print "You do not have permission to restrict function: #{fn}" print "You do not have permission to restrict function: #{fn}"
continue continue
@defs[fn] = whitelist @defs[fn].whitelist = whitelist
g\def {"allow %whitelist to %fn"}, (vars)=> g\def {"allow %whitelist to %fn"}, (vars)=>
fns = if type(vars.fn) == 'string' then {vars.fn} else vars.fn fns = if type(vars.fn) == 'string' then {vars.fn} else vars.fn

View File

@ -93,6 +93,8 @@ class Game
fn_info = @defs[fn_name] fn_info = @defs[fn_name]
if fn_info == nil 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}"
{:fn, :arg_names} = fn_info {:fn, :arg_names} = fn_info
args = {name, select(i,...) for i,name in ipairs(arg_names)} args = {name, select(i,...) for i,name in ipairs(arg_names)}
if @debug if @debug
@ -119,32 +121,11 @@ class Game
else arg_names = _arg_names else arg_names = _arg_names
return invocations, arg_names return invocations, arg_names
defmacro: (spec, fn)=> defmacro: (spec, lua_gen_fn)=>
invocations,arg_names = self\get_invocations spec invocations,arg_names = self\get_invocations spec
fn_info = {:fn, :arg_names, :invocations, is_macro:true} fn_info = {fn:lua_gen_fn, :arg_names, :invocations, is_macro:true}
for invocation in *invocations for invocation in *invocations
@defs[invocation] = fn_info @defs[invocation] = fn_info
simplemacro: (spec, replacement)=>
spec = spec\gsub("\r", "")
replacement = replacement\gsub("\r", "")
replace_grammar = [=[
stuff <- {~ (var / longstring / string / .)+ ~}
var <- ("%" {%wordchar+}) -> replacer
string <- '"' (("\" .) / [^"])* '"'
longstring <- ('".."' %ws? %indent {(%new_line "|" [^%nl]*)+} %dedent (%new_line '..')?)
]=]
fn = (vars, kind)=>
replacer = (varname)->
ret = vars[varname].src
return ret
replacement_grammar = make_parser replace_grammar, {:replacer}
code = replacement_grammar\match(replacement)
tree = self\parse(code)
-- Ugh, this is magic code.
return @tree_to_lua(tree.value.body.value[1].value.value.value, kind), true
self\defmacro spec, fn
run: (text)=> run: (text)=>
if @debug if @debug
@ -228,6 +209,13 @@ class Game
assert tree, "Failed to parse: #{str}" assert tree, "Failed to parse: #{str}"
return tree return tree
tree_to_value: (tree)=>
code = "return (function(game, vars)\nreturn #{@tree_to_lua(tree)}\nend)"
lua_thunk, err = loadstring(code)
if not lua_thunk
error("Failed to compile generated code:\n#{code}\n\n#{err}")
return (lua_thunk!)(self, {})
tree_to_lua: (tree, kind="Expression")=> tree_to_lua: (tree, kind="Expression")=>
assert tree, "No tree provided." assert tree, "No tree provided."
indent = "" indent = ""

View File

@ -13,7 +13,7 @@ utils = {
if utils.is_list x if utils.is_list x
"{#{table.concat([utils.repr(i, true) for i in *x], ", ")}}" "{#{table.concat([utils.repr(i, true) for i in *x], ", ")}}"
else else
"{#{table.concat(["[#{utils.repr(k, true)}]: #{utils.repr(v, true)}" for k,v in pairs x], ", ")}}" "{#{table.concat(["[#{utils.repr(k, true)}]= #{utils.repr(v, true)}" for k,v in pairs x], ", ")}}"
when 'string' when 'string'
if not add_quotes if not add_quotes
x x