More updates with more functional macros and source code storage.

This commit is contained in:
Bruce Hill 2017-12-11 17:53:23 -08:00
parent 0f0dcaac37
commit 0c1c406ce0
4 changed files with 71 additions and 46 deletions

View File

@ -13,7 +13,8 @@ if [ "$FLUSH" = true ] ; then
rm $file
done
fi
for file in $(find lib/ -name "*.nom") ; do
for file in $(cat compile_order.txt) ; do
luafile="$file.lua"
if [ ! -e "$luafile" ] || [ "$file" -nt "$luafile" ] ; then
echo "Compiling $file into $luafile"

View File

@ -10,36 +10,11 @@ lua> ".."
| signature[i] = alias.src;
| end
| local body = nomsu:typecheck(vars, "body", "Thunk");
| return ([[
| local src = nomsu:source_code(0);
| return nil, ([[
|nomsu:def(%s, %s, %s)
|]]):format(nomsu:repr(signature), nomsu:tree_to_lua(body), nomsu:repr(nomsu:dedent(nomsu.defs["#macro_tree"].src))), nil;
|end), \(__src__));
# Rule to make nomsu macros:
rule [parse \%shorthand as \%longhand] =:
lua> ".."
|local signature = {};
|for i, alias in ipairs(nomsu:typecheck(vars, "shorthand", "List").value) do
| signature[i] = alias.src;
|end
|local template = nomsu:typecheck(vars, "longhand", "Thunk").value;
|local function parsing_as(nomsu, vars)
# Single expression/statement
| if #template == 1 then
| local replacement = nomsu:replaced_vars(template[1], vars);
| return nomsu:tree_to_lua(replacement);
| end
# Multiple statements
| local lua_bits = {};
| for _,bit in ipairs(template) do
| bit = nomsu:replaced_vars(bit, vars);
| local expr, statement = nomsu:tree_to_lua(bit);
| if statement then table.insert(lua_bits, statement); end
| if expr then table.insert(lua_bits, "ret = "..expr..";"); end
| end
| return nil, table.concat(lua_bits, "\\n");
|end
|nomsu:defmacro(signature, parsing_as, \(__src__));
|]]):format(nomsu:repr(signature), nomsu:tree_to_lua(body), nomsu:repr(nomsu:dedent(src)));
|end), \(__src__ 1));
# Rule to make lua macros:
rule [compile \%macro_def to \%body] =:
@ -62,6 +37,27 @@ rule [compile \%macro_def to code \%body] =:
|local thunk_wrapper = function(nomsu, vars) return nil, thunk(nomsu, vars); end
|nomsu:defmacro(signature, thunk_wrapper, ("compile %s\\n..to code %s"):format(vars.macro_def.src, body.src));
# Rule to make nomsu macros:
lua> ".."
|nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, vars)
| local signature = {};
| for i, alias in ipairs(nomsu:typecheck(vars, "shorthand", "List").value) do
| signature[i] = alias.src;
| end
| local template = {};
| for i, line in ipairs(nomsu:typecheck(vars, "longhand", "Thunk").value) do
| template[i] = nomsu:dedent(line.src);
| end
| signature, template = nomsu:repr(signature), nomsu:repr(table.concat(template, "\\n"));
| return nil, ([[
|nomsu:defmacro(%s, (function(nomsu, vars)
| local template = nomsu:parse(%s, %s);
| if #template.value == 1 then template = template.value[1]; end
| local replacement = nomsu:replaced_vars(template, vars);
| return nomsu:tree_to_lua(replacement);
|end), %s)]]):format(signature, template, nomsu:repr(vars.shorthand.line_no), nomsu:repr(nomsu:source_code(0)));
|end), \(__src__ 1));
rule [remove rule %stub] =:
lua> ".."
|local def = nomsu.defs[\(%stub)];

View File

@ -467,12 +467,7 @@ do
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
end
insert(self.callstack, "#macro")
insert(self.macrostack, tree)
local old_tree
old_tree, self.defs["#macro_tree"] = self.defs["#macro_tree"], tree
local expr, statement = self:call(tree.stub, tree.line_no, unpack(args))
self.defs["#macro_tree"] = old_tree
remove(self.macrostack)
remove(self.callstack)
return expr, statement
end,
@ -863,7 +858,19 @@ end);]]):format(concat(buffer, "\n"))
end
local _exp_0 = tree.type
if "File" == _exp_0 then
return error("Should not be converting File to lua through this function.")
local lua_bits = { }
local _list_0 = tree.value
for _index_0 = 1, #_list_0 do
local line = _list_0[_index_0]
local expr, statement = self:tree_to_lua(line, filename)
if statement then
insert(lua_bits, statement)
end
if expr then
insert(lua_bits, "ret = " .. tostring(expr) .. ";")
end
end
return nil, concat(lua_bits, "\n")
elseif "Nomsu" == _exp_0 then
return "nomsu:parse(" .. tostring(repr(tree.value.src)) .. ", " .. tostring(repr(tree.line_no)) .. ").value[1]", nil
elseif "Thunk" == _exp_0 then
@ -885,6 +892,7 @@ local ret;
return ret;
end)]]):format(concat(lua_bits, "\n"))
elseif "FunctionCall" == _exp_0 then
insert(self.compilestack, tree)
local def = self.defs[tree.stub]
if def and def.is_macro then
local expr, statement = self:run_macro(tree)
@ -896,6 +904,7 @@ end)]]):format(concat(lua_bits, "\n"))
statement = "nomsu:assert_permission(" .. tostring(repr(tree.stub)) .. ");\n" .. statement
end
end
remove(self.compilestack)
return expr, statement
end
local args = {
@ -949,6 +958,7 @@ end)]]):format(concat(lua_bits, "\n"))
break
end
end
remove(self.compilestack)
return self.__class:comma_separated_items("nomsu:call(", args, ")"), nil
elseif "String" == _exp_0 then
if self.debug then
@ -1248,6 +1258,12 @@ end)]]):format(concat(lua_bits, "\n"))
end
return self:error("Invalid type for %" .. tostring(varname) .. ". Expected " .. tostring(desired_type) .. ", but got " .. tostring(repr(x)) .. ".")
end,
source_code = function(self, level)
if level == nil then
level = 0
end
return self:dedent(self.compilestack[#self.compilestack - level].src)
end,
initialize_core = function(self)
local nomsu_string_as_lua
nomsu_string_as_lua = function(self, code)
@ -1279,8 +1295,8 @@ end)]]):format(concat(lua_bits, "\n"))
return lua, nil
end
self:defmacro("=lua %code", lua_value)
self:defmacro("__src__", function(self)
return self:repr(self:dedent(self.macrostack[#self.macrostack - 1].src))
self:defmacro("__src__ %level", function(self, vars)
return self:repr(self:source_code(self:tree_to_value(vars.level)))
end)
local run_file
run_file = function(self, vars)
@ -1346,7 +1362,7 @@ end)]]):format(concat(lua_bits, "\n"))
})
end
self.callstack = { }
self.macrostack = { }
self.compilestack = { }
self.debug = false
self.utils = utils
self.repr = function(self, ...)

View File

@ -37,6 +37,8 @@ if _VERSION == "Lua 5.1"
-- type checking?
-- Fix compiler bug that breaks when file ends with a block comment
-- Add compiler options for optimization level (compile-fast vs. run-fast, etc.)
-- Change longstrings to be "..\n content\n.."
-- Change precompiling from producing lua code to producing lua> "code" nomsu files
lpeg.setmaxstack 10000 -- whoa
{:P,:R,:V,:S,:Cg,:C,:Cp,:B,:Cmt} = lpeg
@ -210,7 +212,7 @@ class NomsuCompiler
setmetatable(@defs["#vars"], {__index:parent["#vars"]})
setmetatable(@defs["#loaded_files"], {__index:parent["#loaded_files"]})
@callstack = {}
@macrostack = {}
@compilestack = {}
@debug = false
@utils = utils
@repr = (...)=> repr(...)
@ -333,11 +335,7 @@ class NomsuCompiler
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr args}"
insert @callstack, "#macro"
insert @macrostack, tree
old_tree, @defs["#macro_tree"] = @defs["#macro_tree"], tree
expr, statement = @call(tree.stub, tree.line_no, unpack(args))
@defs["#macro_tree"] = old_tree
remove @macrostack
remove @callstack
return expr, statement
@ -598,7 +596,12 @@ end);]])\format(concat(buffer, "\n"))
@error "Invalid tree: #{repr(tree)}"
switch tree.type
when "File"
error("Should not be converting File to lua through this function.")
lua_bits = {}
for line in *tree.value
expr,statement = @tree_to_lua line, filename
if statement then insert lua_bits, statement
if expr then insert lua_bits, "ret = #{expr};"
return nil, concat(lua_bits, "\n")
when "Nomsu"
return "nomsu:parse(#{repr tree.value.src}, #{repr tree.line_no}).value[1]", nil
@ -617,6 +620,8 @@ return ret;
end)]])\format(concat(lua_bits, "\n"))
when "FunctionCall"
insert @compilestack, tree
def = @defs[tree.stub]
if def and def.is_macro
expr, statement = @run_macro(tree)
@ -625,6 +630,7 @@ end)]])\format(concat(lua_bits, "\n"))
expr = "(nomsu:assert_permission(#{repr tree.stub}) and #{expr})"
if statement
statement = "nomsu:assert_permission(#{repr tree.stub});\n"..statement
remove @compilestack
return expr, statement
args = {repr(tree.stub), repr(tree.line_no)}
local arg_names, escaped_args
@ -642,6 +648,8 @@ end)]])\format(concat(lua_bits, "\n"))
@error "Cannot use [[#{arg.src}]] as a function argument, since it's not an expression."
insert args, expr
arg_num += 1
remove @compilestack
return @@comma_separated_items("nomsu:call(", args, ")"), nil
when "String"
@ -823,6 +831,9 @@ end)]])\format(concat(lua_bits, "\n"))
if type(x) == desired_type then return x
if type(x) == 'table' and x.type == desired_type then return x
@error "Invalid type for %#{varname}. Expected #{desired_type}, but got #{repr x}."
source_code: (level=0)=>
@dedent @compilestack[#@compilestack-level].src
initialize_core: =>
-- Sets up some core functionality
@ -849,7 +860,8 @@ end)]])\format(concat(lua_bits, "\n"))
return lua, nil
@defmacro "=lua %code", lua_value
@defmacro "__src__", => @repr @dedent @macrostack[#@macrostack-1].src
@defmacro "__src__ %level", (vars)=>
@repr @source_code @tree_to_value vars.level
run_file = (vars)=>
if vars.filename\match(".*%.lua")