Purged references to "macro" and replaced with "compile action" or
"compile-time action".
This commit is contained in:
parent
199161a438
commit
8c1da9a6c3
@ -1,93 +1,93 @@
|
||||
#..
|
||||
This File contains actions for making actions and macros and some helper functions to make
|
||||
that easier.
|
||||
This File contains actions for making actions and compile-time actions and some helper
|
||||
functions to make that easier.
|
||||
|
||||
# Helper function
|
||||
immediately:
|
||||
lua> ".."
|
||||
nomsu.parse_spec = function(nomsu, spec)
|
||||
local signature = {};
|
||||
local names = {};
|
||||
for i, alias in ipairs(spec.value) do
|
||||
signature[i] = alias.src;
|
||||
names[i] = alias.src;
|
||||
end
|
||||
local _, arg_names, _ = nomsu:get_stub(spec.value[1]);
|
||||
local args = {"nomsu"};
|
||||
for i, a in ipairs(arg_names) do args[i+1] = "_"..nomsu:var_to_lua_identifier(a); end
|
||||
signature, args = nomsu:repr(signature), table.concat(args, ", ");
|
||||
return signature, args;
|
||||
names, args = nomsu:repr(names), table.concat(args, ", ");
|
||||
return names, args;
|
||||
end
|
||||
|
||||
# Macro to make macros:
|
||||
# Compile-time action to make compile-time actions:
|
||||
immediately:
|
||||
lua> ".."
|
||||
nomsu:define_macro("compile %macro_def to %body", \(__line_no__), function(nomsu, \%macro_def, \%body)
|
||||
nomsu:assert(\%macro_def.type == "List",
|
||||
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
||||
nomsu:define_compile_action("compile %names to %body", \(__line_no__), function(nomsu, \%names, \%body)
|
||||
nomsu:assert(\%names.type == "List",
|
||||
"Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type));
|
||||
nomsu:assert(\%body.type == "Block",
|
||||
"Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
|
||||
local signature, args = nomsu:parse_spec(\%macro_def);
|
||||
local names, args = nomsu:parse_spec(\%names);
|
||||
local body_lua = nomsu:tree_to_lua(\%body);
|
||||
body_lua = body_lua.statements or ("return "..body_lua.expr..";");
|
||||
local lua = ([[
|
||||
do
|
||||
local function macro(%s)
|
||||
local function compile_action(%s)
|
||||
%s
|
||||
end
|
||||
local function macro_wrapper(...) return {expr=macro(...)}; end
|
||||
nomsu:define_macro(%s, %s, macro_wrapper, %s);
|
||||
end]]):format(args, body_lua, signature, nomsu:repr(\%macro_def:get_line_no()),
|
||||
nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
||||
local function compile_action_wrapper(...) return {expr=compile_action(...)}; end
|
||||
nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s);
|
||||
end]]):format(args, body_lua, names, nomsu:repr(\%names:get_line_no()),
|
||||
nomsu:repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src)));
|
||||
return {statements=lua};
|
||||
end, \(__src__ 1));
|
||||
|
||||
lua> ".."
|
||||
nomsu:define_macro("compile %macro_def to code %body", \(__line_no__), function(nomsu, \%macro_def, \%body)
|
||||
nomsu:assert(\%macro_def.type == "List",
|
||||
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
||||
nomsu:define_compile_action("compile %names to code %body", \(__line_no__), function(nomsu, \%names, \%body)
|
||||
nomsu:assert(\%names.type == "List",
|
||||
"Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type));
|
||||
nomsu:assert(\%body.type == "Block",
|
||||
"Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
|
||||
local signature, args = nomsu:parse_spec(\%macro_def);
|
||||
local names, args = nomsu:parse_spec(\%names);
|
||||
local body_lua = nomsu:tree_to_lua(\%body);
|
||||
body_lua = body_lua.statements or ("return "..body_lua.expr..";");
|
||||
local lua = ([[
|
||||
do
|
||||
local function macro(%s)
|
||||
local function compile_action(%s)
|
||||
%s
|
||||
end
|
||||
local function macro_wrapper(...) return {statements=macro(...)}; end
|
||||
nomsu:define_macro(%s, %s, macro_wrapper, %s);
|
||||
end]]):format(args, body_lua, signature, nomsu:repr(\%macro_def:get_line_no()),
|
||||
nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
||||
local function compile_action_wrapper(...) return {statements=compile_action(...)}; end
|
||||
nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s);
|
||||
end]]):format(args, body_lua, names, nomsu:repr(\%names:get_line_no()),
|
||||
nomsu:repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src)));
|
||||
return {statements=lua};
|
||||
end, \(__src__ 1));
|
||||
|
||||
# Macro to make actions:
|
||||
# Compile-time action to make actions
|
||||
immediately:
|
||||
compile [action %signature %body] to code:
|
||||
compile [action %names %body] to code:
|
||||
lua> ".."
|
||||
nomsu:assert(\%signature.type == "List",
|
||||
"Invalid type for action definition signature. Expected List, but got: "..tostring(\%signature.type));
|
||||
nomsu:assert(\%names.type == "List",
|
||||
"Invalid type for action definition names. Expected List, but got: "..tostring(\%names.type));
|
||||
nomsu:assert(\%body.type == "Block",
|
||||
"Invalid type for action definition body. Expected Block, but got: "..tostring(\%body.type));
|
||||
local signature, args = nomsu:parse_spec(\%signature);
|
||||
local names, args = nomsu:parse_spec(\%names);
|
||||
local body_lua = nomsu:tree_to_lua(\%body);
|
||||
body_lua = body_lua.statements or ("return "..body_lua.expr..";");
|
||||
local src = nomsu:dedent(nomsu:source_code(0));
|
||||
local def_lua = ([[
|
||||
nomsu:define_action(%s, \(__line_no__), function(%s)
|
||||
%s
|
||||
end, %s);]]):format(signature, args, body_lua, nomsu:repr(src));
|
||||
end, %s);]]):format(names, args, body_lua, nomsu:repr(src));
|
||||
return def_lua;
|
||||
|
||||
# Macro to make nomsu macros:
|
||||
immediately:
|
||||
lua> ".."
|
||||
nomsu:define_macro("parse %shorthand as %longhand", \(__line_no__), (function(nomsu, \%shorthand, \%longhand)
|
||||
nomsu:define_compile_action("parse %shorthand as %longhand", \(__line_no__), (function(nomsu, \%shorthand, \%longhand)
|
||||
nomsu:assert(\%shorthand.type == "List",
|
||||
"Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type));
|
||||
"Invalid type for parse definition shorthand. Expected List, but got: "..tostring(\%shorthand.type));
|
||||
nomsu:assert(\%longhand.type == "Block",
|
||||
"Invalid type for parse definition body. Expected Block, but got: "..tostring(\%longhand.type));
|
||||
local signature, args = nomsu:parse_spec(\%shorthand);
|
||||
local names, args = nomsu:parse_spec(\%shorthand);
|
||||
local template = {};
|
||||
for i, line in ipairs(\%longhand.value) do
|
||||
template[i] = nomsu:dedent(line.src);
|
||||
@ -98,11 +98,11 @@ immediately:
|
||||
for i, a in ipairs(arg_names) do replacements[i] = "["..nomsu:repr(a).."]=_"..nomsu:var_to_lua_identifier(a); end
|
||||
replacements = "{"..table.concat(replacements, ", ").."}";
|
||||
local lua_code = ([[
|
||||
nomsu:define_macro(%s, %s, (function(%s)
|
||||
nomsu:define_compile_action(%s, %s, (function(%s)
|
||||
local template = nomsu:parse(%s, %s);
|
||||
local replacement = nomsu:replaced_vars(template, %s);
|
||||
return nomsu:tree_to_lua(replacement);
|
||||
end), %s)]]):format(signature, nomsu:repr(\%shorthand:get_line_no()), args, template,
|
||||
end), %s)]]):format(names, nomsu:repr(\%shorthand:get_line_no()), args, template,
|
||||
nomsu:repr(\%shorthand:get_line_no()), replacements, nomsu:repr(nomsu:source_code(0)));
|
||||
return {statements=lua_code};
|
||||
end), \(__src__ 1));
|
||||
@ -145,8 +145,8 @@ compile [nomsu %method %args] to: "nomsu[\(%method as lua)](nomsu, unpack(\(%arg
|
||||
compile [tree %tree with %replacements] to: ".."
|
||||
nomsu:replaced_vars(\(%tree as lua), \(%replacements as lua))
|
||||
|
||||
parse [action %signature] as:
|
||||
(nomsu's "defs")->(nomsu "get_stub" [\%signature])
|
||||
parse [action %names] as:
|
||||
(nomsu's "defs")->(nomsu "get_stub" [\%names])
|
||||
|
||||
# Get the source code for a function
|
||||
action [help %action]:
|
||||
|
@ -113,7 +113,7 @@ lua> ".."
|
||||
};
|
||||
for name,code in pairs(colors) do
|
||||
local escape = "\\"\\\\27["..tostring(code).."m\\""
|
||||
nomsu:define_macro(name, \(__line_no__), function() return escape end, "");
|
||||
nomsu:define_compile_action(name, \(__line_no__), function() return escape end, "");
|
||||
end
|
||||
end
|
||||
|
||||
|
71
nomsu.lua
71
nomsu.lua
@ -204,9 +204,9 @@ do
|
||||
self:write_err(...)
|
||||
return self:write_err("\n")
|
||||
end,
|
||||
def = function(self, signature, line_no, fn, src, is_macro)
|
||||
if is_macro == nil then
|
||||
is_macro = false
|
||||
define_action = function(self, signature, line_no, fn, src, compile_time)
|
||||
if compile_time == nil then
|
||||
compile_time = false
|
||||
end
|
||||
if type(signature) == 'string' then
|
||||
signature = self:get_stubs({
|
||||
@ -222,7 +222,7 @@ do
|
||||
fn = fn,
|
||||
src = src,
|
||||
line_no = line_no,
|
||||
is_macro = is_macro,
|
||||
compile_time = compile_time,
|
||||
aliases = { },
|
||||
def_number = self.__class.def_number,
|
||||
defs = self.defs
|
||||
@ -276,8 +276,8 @@ do
|
||||
rawset(where_defs_go, stub, stub_def)
|
||||
end
|
||||
end,
|
||||
defmacro = function(self, signature, line_no, fn, src)
|
||||
return self:def(signature, line_no, fn, src, true)
|
||||
define_compile_action = function(self, signature, line_no, fn, src)
|
||||
return self:define_action(signature, line_no, fn, src, true)
|
||||
end,
|
||||
serialize_defs = function(self, scope, after)
|
||||
if scope == nil then
|
||||
@ -348,27 +348,6 @@ do
|
||||
end
|
||||
return concat(buff, "\n")
|
||||
end,
|
||||
run_macro = function(self, tree)
|
||||
local args
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
local _list_0 = tree.value
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local arg = _list_0[_index_0]
|
||||
if arg.type ~= "Word" then
|
||||
_accum_0[_len_0] = arg
|
||||
_len_0 = _len_0 + 1
|
||||
end
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
if self.debug then
|
||||
self:write(tostring(colored.bright("RUNNING MACRO")) .. " " .. tostring(colored.underscore(colored.magenta(tree.stub))) .. " ")
|
||||
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
|
||||
end
|
||||
return self.defs[tree.stub].fn(self, unpack(args))
|
||||
end,
|
||||
dedent = function(self, code)
|
||||
if not (code:find("\n")) then
|
||||
return code
|
||||
@ -811,8 +790,26 @@ end]]):format(lua_code))
|
||||
elseif "FunctionCall" == _exp_0 then
|
||||
insert(self.compilestack, tree)
|
||||
local def = self.defs[tree.stub]
|
||||
if def and def.is_macro then
|
||||
local lua = self:run_macro(tree)
|
||||
if def and def.compile_time then
|
||||
local args
|
||||
do
|
||||
local _accum_0 = { }
|
||||
local _len_0 = 1
|
||||
local _list_0 = tree.value
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local arg = _list_0[_index_0]
|
||||
if arg.type ~= "Word" then
|
||||
_accum_0[_len_0] = arg
|
||||
_len_0 = _len_0 + 1
|
||||
end
|
||||
end
|
||||
args = _accum_0
|
||||
end
|
||||
if self.debug then
|
||||
self:write(tostring(colored.bright("RUNNING MACRO")) .. " " .. tostring(colored.underscore(colored.magenta(tree.stub))) .. " ")
|
||||
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
|
||||
end
|
||||
local lua = self.defs[tree.stub].fn(self, unpack(args))
|
||||
remove(self.compilestack)
|
||||
return lua
|
||||
elseif not def and self.__class.math_patt:match(tree.stub) then
|
||||
@ -1214,7 +1211,7 @@ end]]):format(lua_code))
|
||||
end
|
||||
return concat(concat_parts)
|
||||
end
|
||||
self:defmacro("do %block", "nomsu.moon", function(self, _block)
|
||||
self:define_compile_action("do %block", "nomsu.moon", function(self, _block)
|
||||
local make_line
|
||||
make_line = function(lua)
|
||||
return lua.expr and (lua.expr .. ";") or lua.statements
|
||||
@ -1227,7 +1224,7 @@ end]]):format(lua_code))
|
||||
}
|
||||
end
|
||||
end)
|
||||
self:defmacro("immediately %block", "nomsu.moon", function(self, _block)
|
||||
self:define_compile_action("immediately %block", "nomsu.moon", function(self, _block)
|
||||
local lua = self:tree_to_lua(_block)
|
||||
local lua_code = lua.statements or (lua.expr .. ";")
|
||||
lua_code = "-- Immediately:\n" .. lua_code
|
||||
@ -1236,32 +1233,32 @@ end]]):format(lua_code))
|
||||
statements = lua_code
|
||||
}
|
||||
end)
|
||||
self:defmacro("lua> %code", "nomsu.moon", function(self, _code)
|
||||
self:define_compile_action("lua> %code", "nomsu.moon", function(self, _code)
|
||||
local lua = nomsu_string_as_lua(self, _code)
|
||||
return {
|
||||
statements = lua
|
||||
}
|
||||
end)
|
||||
self:defmacro("=lua %code", "nomsu.moon", function(self, _code)
|
||||
self:define_compile_action("=lua %code", "nomsu.moon", function(self, _code)
|
||||
local lua = nomsu_string_as_lua(self, _code)
|
||||
return {
|
||||
expr = lua
|
||||
}
|
||||
end)
|
||||
self:defmacro("__line_no__", "nomsu.moon", function(self)
|
||||
self:define_compile_action("__line_no__", "nomsu.moon", function(self)
|
||||
return {
|
||||
expr = repr(self.compilestack[#self.compilestack]:get_line_no())
|
||||
}
|
||||
end)
|
||||
self:defmacro("__src__ %level", "nomsu.moon", function(self, _level)
|
||||
self:define_compile_action("__src__ %level", "nomsu.moon", function(self, _level)
|
||||
return {
|
||||
expr = repr(self:source_code(self:tree_to_value(_level)))
|
||||
}
|
||||
end)
|
||||
self:def("run file %filename", "nomsu.moon", function(self, _filename)
|
||||
self:define_action("run file %filename", "nomsu.moon", function(self, _filename)
|
||||
return self:run_file(_filename)
|
||||
end)
|
||||
return self:defmacro("require %filename", "nomsu.moon", function(self, _filename)
|
||||
return self:define_compile_action("require %filename", "nomsu.moon", function(self, _filename)
|
||||
local filename = self:tree_to_value(_filename)
|
||||
self:require_file(filename)
|
||||
return {
|
||||
|
61
nomsu.moon
61
nomsu.moon
@ -171,7 +171,7 @@ class NomsuCompiler
|
||||
@write_err(...)
|
||||
@write_err("\n")
|
||||
|
||||
define_action: (signature, line_no, fn, src, is_macro=false)=>
|
||||
define_action: (signature, line_no, fn, src, compile_time=false)=>
|
||||
if type(signature) == 'string'
|
||||
signature = @get_stubs {signature}
|
||||
elseif type(signature) == 'table' and type(signature[1]) == 'string'
|
||||
@ -179,7 +179,7 @@ class NomsuCompiler
|
||||
@assert type(fn) == 'function', "Bad fn: #{repr fn}"
|
||||
aliases = {}
|
||||
@@def_number += 1
|
||||
def = {:fn, :src, :line_no, :is_macro, aliases:{}, def_number:@@def_number, defs:@defs}
|
||||
def = {:fn, :src, :line_no, :compile_time, aliases:{}, def_number:@@def_number, defs:@defs}
|
||||
where_defs_go = (getmetatable(@defs) or {}).__newindex or @defs
|
||||
for sig_i=1,#signature
|
||||
stub, arg_names, escaped_args = unpack(signature[sig_i])
|
||||
@ -204,7 +204,7 @@ class NomsuCompiler
|
||||
stub_def = setmetatable({:stub, :arg_names, :arg_positions}, {__index:def})
|
||||
rawset(where_defs_go, stub, stub_def)
|
||||
|
||||
define_macro: (signature, line_no, fn, src)=>
|
||||
define_compile_action: (signature, line_no, fn, src)=>
|
||||
@define_action(signature, line_no, fn, src, true)
|
||||
|
||||
serialize_defs: (scope=nil, after=nil)=>
|
||||
@ -242,13 +242,6 @@ class NomsuCompiler
|
||||
|
||||
return concat buff, "\n"
|
||||
|
||||
run_macro: (tree)=>
|
||||
args = [arg for arg in *tree.value when arg.type != "Word"]
|
||||
if @debug
|
||||
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
|
||||
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr args}"
|
||||
return @defs[tree.stub].fn(self, unpack(args))
|
||||
|
||||
dedent: (code)=>
|
||||
unless code\find("\n")
|
||||
return code
|
||||
@ -268,32 +261,6 @@ class NomsuCompiler
|
||||
indent: (code, levels=1)=>
|
||||
return code\gsub("\n","\n"..(" ")\rep(levels))
|
||||
|
||||
assert_permission: (stub)=>
|
||||
fn_def = @defs[stub]
|
||||
unless fn_def
|
||||
@error "Undefined function: #{fn_name}"
|
||||
whiteset = fn_def.whiteset
|
||||
if whiteset == nil then return true
|
||||
-- TODO: maybe optimize this by making the callstack a Counter and using a
|
||||
-- move-to-front optimization on the whitelist to check most likely candidates sooner
|
||||
for caller in *@callstack
|
||||
if caller != "#macro" and whiteset[caller[1]] then return true
|
||||
@error "You do not have the authority to call: #{stub}"
|
||||
|
||||
check_permission: (fn_def)=>
|
||||
if getmetatable(fn_def) != functiondef_mt
|
||||
fn_name = fn_def
|
||||
fn_def = @defs[fn_name]
|
||||
if fn_def == nil
|
||||
@error "Undefined function: #{fn_name}"
|
||||
whiteset = fn_def.whiteset
|
||||
if whiteset == nil then return true
|
||||
-- TODO: maybe optimize this by making the callstack a Counter and using a
|
||||
-- move-to-front optimization on the whitelist to check most likely candidates sooner
|
||||
for caller in *@callstack
|
||||
if caller != "#macro" and whiteset[caller[1]] then return true
|
||||
return false
|
||||
|
||||
parse: (str, filename)=>
|
||||
@assert type(filename) == "string", "Bad filename type: #{type filename}"
|
||||
if @debug
|
||||
@ -548,8 +515,12 @@ end]]\format(lua_code))
|
||||
insert @compilestack, tree
|
||||
|
||||
def = @defs[tree.stub]
|
||||
if def and def.is_macro
|
||||
lua = @run_macro(tree)
|
||||
if def and def.compile_time
|
||||
args = [arg for arg in *tree.value when arg.type != "Word"]
|
||||
if @debug
|
||||
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
|
||||
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr args}"
|
||||
lua = @defs[tree.stub].fn(self, unpack(args))
|
||||
remove @compilestack
|
||||
return lua
|
||||
elseif not def and @@math_patt\match(tree.stub)
|
||||
@ -793,38 +764,38 @@ end]]\format(lua_code))
|
||||
insert concat_parts, lua.expr
|
||||
return concat(concat_parts)
|
||||
|
||||
@define_macro "do %block", "nomsu.moon", (_block)=>
|
||||
@define_compile_action "do %block", "nomsu.moon", (_block)=>
|
||||
make_line = (lua)-> lua.expr and (lua.expr..";") or lua.statements
|
||||
if _block.type == "Block"
|
||||
return @tree_to_lua(_block)
|
||||
else
|
||||
return expr:"#{@tree_to_lua _block}(nomsu)"
|
||||
|
||||
@define_macro "immediately %block", "nomsu.moon", (_block)=>
|
||||
@define_compile_action "immediately %block", "nomsu.moon", (_block)=>
|
||||
lua = @tree_to_lua(_block)
|
||||
lua_code = lua.statements or (lua.expr..";")
|
||||
lua_code = "-- Immediately:\n"..lua_code
|
||||
@run_lua(lua_code)
|
||||
return statements:lua_code
|
||||
|
||||
@define_macro "lua> %code", "nomsu.moon", (_code)=>
|
||||
@define_compile_action "lua> %code", "nomsu.moon", (_code)=>
|
||||
lua = nomsu_string_as_lua(@, _code)
|
||||
return statements:lua
|
||||
|
||||
@define_macro "=lua %code", "nomsu.moon", (_code)=>
|
||||
@define_compile_action "=lua %code", "nomsu.moon", (_code)=>
|
||||
lua = nomsu_string_as_lua(@, _code)
|
||||
return expr:lua
|
||||
|
||||
@define_macro "__line_no__", "nomsu.moon", ()=>
|
||||
@define_compile_action "__line_no__", "nomsu.moon", ()=>
|
||||
expr: repr(@compilestack[#@compilestack]\get_line_no!)
|
||||
|
||||
@define_macro "__src__ %level", "nomsu.moon", (_level)=>
|
||||
@define_compile_action "__src__ %level", "nomsu.moon", (_level)=>
|
||||
expr: repr(@source_code(@tree_to_value(_level)))
|
||||
|
||||
@define_action "run file %filename", "nomsu.moon", (_filename)=>
|
||||
@run_file(_filename)
|
||||
|
||||
@define_macro "require %filename", "nomsu.moon", (_filename)=>
|
||||
@define_compile_action "require %filename", "nomsu.moon", (_filename)=>
|
||||
filename = @tree_to_value(_filename)
|
||||
@require_file(filename)
|
||||
return statements:"nomsu:require_file(#{repr filename});"
|
||||
|
Loading…
Reference in New Issue
Block a user