Switched to use load() with environment table instead of passing in

nomsu to everything. This has some nice code cleanliness benefits.
This commit is contained in:
Bruce Hill 2018-01-12 16:33:11 -08:00
parent e09f05a50c
commit 6b09187899
10 changed files with 194 additions and 145 deletions

View File

@ -16,7 +16,7 @@ if [ "$FLUSH" = true ] ; then
done done
fi fi
for file in $(cat lib/core.nom | lua -e "for filename in io.read('*a'):gmatch('require \"([^\"]*)\"') do print(filename) end") ; do for file in $(cat lib/core.nom | lua -e "for filename in io.read('*a'):gmatch('use \"([^\"]*)\"') do print(filename) end") ; do
compilefile="${file/\.nom/.lua}" compilefile="${file/\.nom/.lua}"
if [ ! -e "$compilefile" ] || [ "$file" -nt "$compilefile" ] ; then if [ ! -e "$compilefile" ] || [ "$file" -nt "$compilefile" ] ; then
echo "Compiling $file into $compilefile" echo "Compiling $file into $compilefile"

View File

@ -16,7 +16,7 @@ parse [..]
compile [..] compile [..]
%index st to last in %list, %index nd to last in %list, %index rd to last in %list %index st to last in %list, %index nd to last in %list, %index rd to last in %list
%index th to last in %list %index th to last in %list
..to: "nomsu.utils.nth_to_last(\(%list as lua), \(%index as lua))" ..to: "utils.nth_to_last(\(%list as lua), \(%index as lua))"
parse [first in %list, first %list] as: 1 st in %list parse [first in %list, first %list] as: 1 st in %list
parse [last in %list, last %list] as: 1 st to last in %list parse [last in %list, last %list] as: 1 st to last in %list
@ -45,7 +45,7 @@ compile [..]
..to: "((\(%list as lua))[\(%index as lua)] ~= nil)" ..to: "((\(%list as lua))[\(%index as lua)] ~= nil)"
compile [length of %list, size of %list, size %list, number of %list, len %list] to: compile [length of %list, size of %list, size %list, number of %list, len %list] to:
"nomsu.utils.size(\(%list as lua))" "utils.size(\(%list as lua))"
# Chained lookup # Chained lookup
compile [%list ->* %indices] to: compile [%list ->* %indices] to:
@ -99,13 +99,13 @@ immediately:
assume ((%item's "type") is "Var") or barf ".." assume ((%item's "type") is "Var") or barf ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type") List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type")
return ".." return ".."
(function(nomsu); (function();
local comprehension = {}; local comprehension = {};
for i,\(%item as lua) in ipairs(\(%iterable as lua)) do; for i,\(%item as lua) in ipairs(\(%iterable as lua)) do;
comprehension[i] = \(%expression as lua); comprehension[i] = \(%expression as lua);
end; end;
return comprehension; return comprehension;
end)(nomsu) end)()
parse [%expression for all %iterable] as: %expression for % in %iterable parse [%expression for all %iterable] as: %expression for % in %iterable
compile [%expression for %key = %value in %iterable] to: compile [%expression for %key = %value in %iterable] to:
@ -114,13 +114,13 @@ immediately:
assume ((%value's "type") is "Var") or barf ".." assume ((%value's "type") is "Var") or barf ".."
List comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%value's "type") List comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%value's "type")
return ".." return ".."
(function(nomsu); (function();
local comprehension = {}; local comprehension = {};
for \(%key as lua), \(%value as lua) in pairs(\(%iterable as lua)) do; for \(%key as lua), \(%value as lua) in pairs(\(%iterable as lua)) do;
comprehension[i] = \(%expression as lua); comprehension[i] = \(%expression as lua);
end; end;
return comprehension; return comprehension;
end)(nomsu) end)()
# Dict comprehensions # Dict comprehensions
immediately: immediately:
@ -128,13 +128,13 @@ immediately:
assume ((%item's "type") is "Var") or barf ".." assume ((%item's "type") is "Var") or barf ".."
Dict comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type") Dict comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type")
return ".." return ".."
(function(nomsu); (function();
local comprehension = {}; local comprehension = {};
for i,\(%item as lua) in ipairs(\(%iterable as lua)) do; for i,\(%item as lua) in ipairs(\(%iterable as lua)) do;
comprehension[\(%key as lua)] = \(%value as lua); comprehension[\(%key as lua)] = \(%value as lua);
end; end;
return comprehension; return comprehension;
end)(nomsu) end)()
parse [%key = %value for all %iterable] as: %key = %value for % in %iterable parse [%key = %value for all %iterable] as: %key = %value for % in %iterable
compile [%key = %value for %src_key = %src_value in %iterable] to: compile [%key = %value for %src_key = %src_value in %iterable] to:
@ -143,18 +143,18 @@ immediately:
assume ((%src_value's "type") is "Var") or barf ".." assume ((%src_value's "type") is "Var") or barf ".."
Dict comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%src_value's "type") Dict comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%src_value's "type")
return ".." return ".."
(function(nomsu); (function();
local comprehension = {}; local comprehension = {};
for \(%src_key as lua), \(%src_value as lua) in pairs(\(%iterable as lua)) do; for \(%src_key as lua), \(%src_value as lua) in pairs(\(%iterable as lua)) do;
comprehension[\(%key as lua)] = \(%value as lua); comprehension[\(%key as lua)] = \(%value as lua);
end; end;
return comprehension; return comprehension;
end)(nomsu) end)()
# Sorting: # Sorting:
compile [sort %items] to: "table.sort(\(%items as lua))" compile [sort %items] to: "table.sort(\(%items as lua))"
compile [sort %items by %key_expr] to: ".." compile [sort %items by %key_expr] to: ".."
nomsu.utils.sort(\(%items as lua), function(\(\% as lua)) utils.sort(\(%items as lua), function(\(\% as lua))
return \(%key_expr as lua); return \(%key_expr as lua);
end) end)

View File

@ -50,13 +50,13 @@ immediately:
doesn't have a proper ternary operator!) doesn't have a proper ternary operator!)
To see why this is necessary consider: (random()<.5 and false or 99) To see why this is necessary consider: (random()<.5 and false or 99)
return ".." return ".."
(function(nomsu) (function()
if \(%condition as lua) then if \(%condition as lua) then
return \(%when_true_expr as lua); return \(%when_true_expr as lua);
else else
return \(%when_false_expr as lua); return \(%when_false_expr as lua);
end end
end)(nomsu) end)()
# GOTOs # GOTOs
immediately: immediately:
@ -344,10 +344,10 @@ immediately:
..to code: ".." ..to code: ".."
do do
local fell_through = false; local fell_through = false;
local ok, ret = pcall(function(nomsu) local ok, ret = pcall(function()
\(%action as lua statements) \(%action as lua statements)
fell_through = true; fell_through = true;
end, nomsu); end);
if ok then if ok then
\(%success as lua statements) \(%success as lua statements)
end end
@ -375,15 +375,15 @@ immediately:
compile [do %action then always %final_action] to code: ".." compile [do %action then always %final_action] to code: ".."
do do
local fell_through = false; local fell_through = false;
local ok, ret1 = pcall(function(nomsu) local ok, ret1 = pcall(function()
\(%action as lua statements) \(%action as lua statements)
fell_through = true; fell_through = true;
end, nomsu); end);
local ok2, ret2 = pcall(function(nomsu) local ok2, ret2 = pcall(function()
\(%final_action as lua statements) \(%final_action as lua statements)
end, nomsu); end);
if not ok then nomsu:error(ret1); end if not ok then error(ret1); end
if not ok2 then nomsu:error(ret2); end if not ok2 then error(ret2); end
if not fell_through then if not fell_through then
return ret1; return ret1;
end end
@ -402,12 +402,12 @@ immediately:
local \(join %temp_vars with ", ") = \(join %old_vals with ", "); local \(join %temp_vars with ", ") = \(join %old_vals with ", ");
\(join %old_vals with ", ") = \(join %new_vals with ", "); \(join %old_vals with ", ") = \(join %new_vals with ", ");
local fell_through = false; local fell_through = false;
local ok, ret = pcall(function(nomsu) local ok, ret = pcall(function()
do do
\(%action as lua statements) \(%action as lua statements)
end end
fell_through = true; fell_through = true;
end, nomsu); end);
\(join %old_vals with ", ") = \(join %temp_vars with ", "); \(join %old_vals with ", ") = \(join %temp_vars with ", ");
if not ok then error(ret, 0); end if not ok then error(ret, 0); end
if not fell_through then return ret end if not fell_through then return ret end

View File

@ -38,30 +38,30 @@ action [%n to the nearest %rounder]:
# Any/all/none # Any/all/none
compile [all of %items, all %items] to: compile [all of %items, all %items] to:
"(\(join ((% as lua) for all (%items' "value")) with " and "))" "(\(join ((% as lua) for all (%items' "value")) with " and "))"
..if ((%items' "type") is "List") else "nomsu.utils.all(\(%items as lua))" ..if ((%items' "type") is "List") else "utils.all(\(%items as lua))"
parse [not all of %items, not all %items] as: not (all of %items) parse [not all of %items, not all %items] as: not (all of %items)
compile [any of %items, any %items] to: compile [any of %items, any %items] to:
"(\(join ((% as lua) for all (%items' "value")) with " or "))" "(\(join ((% as lua) for all (%items' "value")) with " or "))"
..if ((%items' "type") is "List") else "nomsu.utils.any(\(%items as lua))" ..if ((%items' "type") is "List") else "utils.any(\(%items as lua))"
parse [none of %items, none %items] as: not (any of %items) parse [none of %items, none %items] as: not (any of %items)
compile [sum of %items, sum %items] to: compile [sum of %items, sum %items] to:
"(\(join ((% as lua) for all (%items' "value")) with " + "))" "(\(join ((% as lua) for all (%items' "value")) with " + "))"
..if ((%items' "type") is "List") else "nomsu.utils.sum(\(%items as lua))" ..if ((%items' "type") is "List") else "utils.sum(\(%items as lua))"
compile [product of %items, product %items] to: compile [product of %items, product %items] to:
"(\(join ((% as lua) for all (%items' "value")) with " * "))" "(\(join ((% as lua) for all (%items' "value")) with " * "))"
..if ((%items' "type") is "List") else "nomsu.utils.product(\(%items as lua))" ..if ((%items' "type") is "List") else "utils.product(\(%items as lua))"
action [avg of %items, average of %items]: action [avg of %items, average of %items]:
=lua "(nomsu.utils.sum(\%items)/#\%items)" =lua "(utils.sum(\%items)/#\%items)"
compile [min of %items, smallest of %items, lowest of %items] to: compile [min of %items, smallest of %items, lowest of %items] to:
"nomsu.utils.min(\(%items as lua))" "utils.min(\(%items as lua))"
compile [max of %items, biggest of %items, largest of %items, highest of %items] to: compile [max of %items, biggest of %items, largest of %items, highest of %items] to:
"nomsu.utils.max(\(%items as lua))" "utils.max(\(%items as lua))"
compile [min of %items by %value_expr] to: ".." compile [min of %items by %value_expr] to: ".."
nomsu.utils.min(\(%items as lua), function(\(\% as lua)) utils.min(\(%items as lua), function(\(\% as lua))
return \(%value_expr as lua) return \(%value_expr as lua)
end) end)
compile [max of %items by %value_expr] to: ".." compile [max of %items by %value_expr] to: ".."
nomsu.utils.max(\(%items as lua), function(\(\% as lua)) utils.max(\(%items as lua), function(\(\% as lua))
return \(%value_expr as lua) return \(%value_expr as lua)
end) end)

View File

@ -11,19 +11,19 @@ immediately:
names[i] = alias.src; names[i] = alias.src;
end end
local _, arg_names, _ = nomsu:get_stub(spec.value[1]); local _, arg_names, _ = nomsu:get_stub(spec.value[1]);
local args = {"nomsu"}; local args = {};
for i, a in ipairs(arg_names) do args[i+1] = "_"..nomsu:var_to_lua_identifier(a); end for i, a in ipairs(arg_names) do args[i] = "_"..nomsu:var_to_lua_identifier(a); end
names, args = nomsu:repr(names), table.concat(args, ", "); names, args = repr(names), table.concat(args, ", ");
return names, args; return names, args;
end end
# Compile-time action to make compile-time actions: # Compile-time action to make compile-time actions:
immediately: immediately:
lua> ".." lua> ".."
nomsu:define_compile_action("compile %names to %body", \(__line_no__), function(nomsu, \%names, \%body) nomsu:define_compile_action("compile %names to %body", \(__line_no__), function(\%names, \%body)
nomsu:assert(\%names.type == "List", assert(\%names.type == "List",
"Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type)); "Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type));
nomsu:assert(\%body.type == "Block", assert(\%body.type == "Block",
"Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type)); "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
local names, args = nomsu:parse_spec(\%names); local names, args = nomsu:parse_spec(\%names);
local body_lua = nomsu:tree_to_lua(\%body); local body_lua = nomsu:tree_to_lua(\%body);
@ -35,16 +35,16 @@ immediately:
end end
local function compile_action_wrapper(...) return {expr=compile_action(...)}; end local function compile_action_wrapper(...) return {expr=compile_action(...)}; end
nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s); nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s);
end]]):format(args, body_lua, names, nomsu:repr(\%names:get_line_no()), end]]):format(args, body_lua, names, repr(\%names:get_line_no()),
nomsu:repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src))); repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src)));
return {statements=lua}; return {statements=lua};
end, \(__src__ 1)); end, \(__src__ 1));
lua> ".." lua> ".."
nomsu:define_compile_action("compile %names to code %body", \(__line_no__), function(nomsu, \%names, \%body) nomsu:define_compile_action("compile %names to code %body", \(__line_no__), function(\%names, \%body)
nomsu:assert(\%names.type == "List", assert(\%names.type == "List",
"Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type)); "Invalid type for compile definition names. Expected List, but got: "..tostring(\%names.type));
nomsu:assert(\%body.type == "Block", assert(\%body.type == "Block",
"Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type)); "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type));
local names, args = nomsu:parse_spec(\%names); local names, args = nomsu:parse_spec(\%names);
local body_lua = nomsu:tree_to_lua(\%body); local body_lua = nomsu:tree_to_lua(\%body);
@ -56,8 +56,8 @@ immediately:
end end
local function compile_action_wrapper(...) return {statements=compile_action(...)}; end local function compile_action_wrapper(...) return {statements=compile_action(...)}; end
nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s); nomsu:define_compile_action(%s, %s, compile_action_wrapper, %s);
end]]):format(args, body_lua, names, nomsu:repr(\%names:get_line_no()), end]]):format(args, body_lua, names, repr(\%names:get_line_no()),
nomsu:repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src))); repr(("compile %s\\n..to code %s"):format(\%names.src, \%body.src)));
return {statements=lua}; return {statements=lua};
end, \(__src__ 1)); end, \(__src__ 1));
@ -65,9 +65,9 @@ immediately:
immediately: immediately:
compile [action %names %body] to code: compile [action %names %body] to code:
lua> ".." lua> ".."
nomsu:assert(\%names.type == "List", assert(\%names.type == "List",
"Invalid type for action definition names. Expected List, but got: "..tostring(\%names.type)); "Invalid type for action definition names. Expected List, but got: "..tostring(\%names.type));
nomsu:assert(\%body.type == "Block", assert(\%body.type == "Block",
"Invalid type for action definition body. Expected Block, but got: "..tostring(\%body.type)); "Invalid type for action definition body. Expected Block, but got: "..tostring(\%body.type));
local names, args = nomsu:parse_spec(\%names); local names, args = nomsu:parse_spec(\%names);
local body_lua = nomsu:tree_to_lua(\%body); local body_lua = nomsu:tree_to_lua(\%body);
@ -76,34 +76,34 @@ immediately:
local def_lua = ([[ local def_lua = ([[
nomsu:define_action(%s, \(__line_no__), function(%s) nomsu:define_action(%s, \(__line_no__), function(%s)
%s %s
end, %s);]]):format(names, args, body_lua, nomsu:repr(src)); end, %s);]]):format(names, args, body_lua, repr(src));
return def_lua; return def_lua;
# Macro to make nomsu macros: # Macro to make nomsu macros:
immediately: immediately:
lua> ".." lua> ".."
nomsu:define_compile_action("parse %shorthand as %longhand", \(__line_no__), (function(nomsu, \%shorthand, \%longhand) nomsu:define_compile_action("parse %shorthand as %longhand", \(__line_no__), (function(\%shorthand, \%longhand)
nomsu:assert(\%shorthand.type == "List", assert(\%shorthand.type == "List",
"Invalid type for parse definition shorthand. 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", assert(\%longhand.type == "Block",
"Invalid type for parse definition body. Expected Block, but got: "..tostring(\%longhand.type)); "Invalid type for parse definition body. Expected Block, but got: "..tostring(\%longhand.type));
local names, args = nomsu:parse_spec(\%shorthand); local names, args = nomsu:parse_spec(\%shorthand);
local template = {}; local template = {};
for i, line in ipairs(\%longhand.value) do for i, line in ipairs(\%longhand.value) do
template[i] = nomsu:dedent(line.src); template[i] = nomsu:dedent(line.src);
end end
template = nomsu:repr(table.concat(template, "\\n")); template = repr(table.concat(template, "\\n"));
local _, arg_names, _ = nomsu:get_stub(\%shorthand.value[1]); local _, arg_names, _ = nomsu:get_stub(\%shorthand.value[1]);
local replacements = {}; local replacements = {};
for i, a in ipairs(arg_names) do replacements[i] = "["..nomsu:repr(a).."]=_"..nomsu:var_to_lua_identifier(a); end for i, a in ipairs(arg_names) do replacements[i] = "["..repr(a).."]=_"..nomsu:var_to_lua_identifier(a); end
replacements = "{"..table.concat(replacements, ", ").."}"; replacements = "{"..table.concat(replacements, ", ").."}";
local lua_code = ([[ local lua_code = ([[
nomsu:define_compile_action(%s, %s, (function(%s) nomsu:define_compile_action(%s, %s, (function(%s)
local template = nomsu:parse(%s, %s); local template = nomsu:parse(%s, %s);
local replacement = nomsu:replaced_vars(template, %s); local replacement = nomsu:replaced_vars(template, %s);
return nomsu:tree_to_lua(replacement); return nomsu:tree_to_lua(replacement);
end), %s)]]):format(names, nomsu:repr(\%shorthand:get_line_no()), args, template, end), %s)]]):format(names, repr(\%shorthand:get_line_no()), args, template,
nomsu:repr(\%shorthand:get_line_no()), replacements, nomsu:repr(nomsu:source_code(0))); repr(\%shorthand:get_line_no()), replacements, repr(nomsu:source_code(0)));
return {statements=lua_code}; return {statements=lua_code};
end), \(__src__ 1)); end), \(__src__ 1));
@ -124,7 +124,7 @@ immediately:
action [%tree as value]: action [%tree as value]:
=lua "nomsu:tree_to_value(\%tree)" =lua "nomsu:tree_to_value(\%tree)"
compile [repr %obj] to: compile [repr %obj] to:
"nomsu:repr(\(%obj as lua))" "repr(\(%obj as lua))"
compile [indented %obj] to: compile [indented %obj] to:
"nomsu:indent(\(%obj as lua))" "nomsu:indent(\(%obj as lua))"
compile [dedented %obj] to: compile [dedented %obj] to:
@ -153,7 +153,7 @@ action [help %action]:
lua> ".." lua> ".."
local fn_def = nomsu.defs[nomsu:get_stub(\%action)] local fn_def = nomsu.defs[nomsu:get_stub(\%action)]
if not fn_def then if not fn_def then
nomsu:writeln("Action not found: "..nomsu:repr(\%action)); nomsu:writeln("Action not found: "..repr(\%action));
else else
nomsu:writeln(fn_def.src or "<unknown source code>"); nomsu:writeln(fn_def.src or "<unknown source code>");
end end
@ -182,7 +182,7 @@ compile [say %str] to:
if \%str.type == "Text" then if \%str.type == "Text" then
return "nomsu:writeln("..\(%str as lua)..")"; return "nomsu:writeln("..\(%str as lua)..")";
else else
return "nomsu:writeln(nomsu:stringify("..\(%str as lua).."))"; return "nomsu:writeln(stringify("..\(%str as lua).."))";
end end
# Error functions # Error functions

View File

@ -20,7 +20,7 @@ immediately:
if safe[\%a.type] or safe[\%b.type] then if safe[\%a.type] or safe[\%b.type] then
return "("..a_lua.." == "..b_lua..")"; return "("..a_lua.." == "..b_lua..")";
else else
return "nomsu.utils.equivalent("..a_lua..", "..b_lua..")"; return "utils.equivalent("..a_lua..", "..b_lua..")";
end end
compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to: compile [%a isn't %b, %a is not %b, %a not= %b, %a != %b] to:
lua> ".." lua> ".."
@ -29,7 +29,7 @@ immediately:
if safe[\%a.type] or safe[\%b.type] then if safe[\%a.type] or safe[\%b.type] then
return "("..a_lua.." ~= "..b_lua..")"; return "("..a_lua.." ~= "..b_lua..")";
else else
return "(not nomsu.utils.equivalent("..a_lua..", "..b_lua.."))"; return "(not utils.equivalent("..a_lua..", "..b_lua.."))";
end end
# For strict identity checking, use (%x's id) is (%y's id) # For strict identity checking, use (%x's id) is (%y's id)
compile [%'s id, id of %] to: "nomsu.ids[\(% as lua)]" compile [%'s id, id of %] to: "nomsu.ids[\(% as lua)]"

View File

@ -8,7 +8,7 @@ use "lib/metaprogramming.nom"
action [join %strs with %glue]: action [join %strs with %glue]:
lua> ".." lua> ".."
local str_bits = {} local str_bits = {}
for i,bit in ipairs(\%strs) do str_bits[i] = nomsu:stringify(bit) end for i,bit in ipairs(\%strs) do str_bits[i] = stringify(bit) end
return table.concat(str_bits, \%glue) return table.concat(str_bits, \%glue)
parse [join %strs] as: join %strs with "" parse [join %strs] as: join %strs with ""
@ -49,7 +49,7 @@ lua do> ".."
local color = "'"..c.."'"; local color = "'"..c.."'";
local reset = "'"..colors["reset color"].."'"; local reset = "'"..colors["reset color"].."'";
nomsu:define_compile_action(name, \(__line_no__), function() return {expr=color}; end, \(__src__ 1)); nomsu:define_compile_action(name, \(__line_no__), function() return {expr=color}; end, \(__src__ 1));
nomsu:define_compile_action(name.." %", \(__line_no__), function(nomsu, _) nomsu:define_compile_action(name.." %", \(__line_no__), function(_)
return {expr=color..".."..nomsu:tree_to_lua(_).expr..".."..reset}; return {expr=color..".."..nomsu:tree_to_lua(_).expr..".."..reset};
end, \(__src__ 1)); end, \(__src__ 1));
end end

115
nomsu.lua
View File

@ -442,7 +442,10 @@ do
end, end,
run_file = function(self, filename) run_file = function(self, filename)
if filename:match(".*%.lua") then if filename:match(".*%.lua") then
return dofile(filename)(self) local file = io.open(filename)
local contents = file:read("*a")
file:close()
return assert(load(contents, nil, nil, self.environment))()
end end
if filename:match(".*%.nom") then if filename:match(".*%.nom") then
if not self.skip_precompiled then if not self.skip_precompiled then
@ -472,13 +475,11 @@ do
return loaded[filename] return loaded[filename]
end, end,
run_lua = function(self, lua_code) run_lua = function(self, lua_code)
local load_lua_fn, err = load(([[return function(nomsu) local run_lua_fn, err = load(lua_code, nil, nil, self.environment)
%s
end]]):format(lua_code))
if self.debug then if self.debug then
self:writeln(tostring(colored.bright("RUNNING LUA:")) .. "\n" .. tostring(colored.blue(colored.bright(lua_code)))) self:writeln(tostring(colored.bright("RUNNING LUA:")) .. "\n" .. tostring(colored.blue(colored.bright(lua_code))))
end end
if not load_lua_fn then if not run_lua_fn then
local n = 1 local n = 1
local fn local fn
fn = function() fn = function()
@ -488,21 +489,18 @@ end]]):format(lua_code))
local code = "1 |" .. lua_code:gsub("\n", fn) local code = "1 |" .. lua_code:gsub("\n", fn)
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err)) self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err))
end end
local run_lua_fn = load_lua_fn() return run_lua_fn()
run_lua_fn(self)
return ret
end, end,
tree_to_value = function(self, tree, filename) tree_to_value = function(self, tree, filename)
local code = "return (function(nomsu)\nreturn " .. tostring(self:tree_to_lua(tree).expr) .. ";\nend);" local code = "return " .. tostring(self:tree_to_lua(tree).expr) .. ";"
code = "-- Tree to value: " .. tostring(filename) .. "\n" .. code
if self.debug then if self.debug then
self:writeln(tostring(colored.bright("RUNNING LUA TO GET VALUE:")) .. "\n" .. tostring(colored.blue(colored.bright(code)))) self:writeln(tostring(colored.bright("RUNNING LUA TO GET VALUE:")) .. "\n" .. tostring(colored.blue(colored.bright(code))))
end end
local lua_thunk, err = load(code) local lua_thunk, err = load(code, nil, nil, self.environment)
if not lua_thunk then if not lua_thunk then
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(colored.red(err))) self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(colored.red(err)))
end end
return (lua_thunk())(self) return lua_thunk()
end, end,
tree_to_nomsu = function(self, tree, force_inline) tree_to_nomsu = function(self, tree, force_inline)
if force_inline == nil then if force_inline == nil then
@ -780,7 +778,7 @@ end]]):format(lua_code))
return _accum_0 return _accum_0
end)())))) end)()))))
end end
local lua = self.defs[tree.stub].fn(self, unpack(args)) local lua = self.defs[tree.stub].fn(unpack(args))
remove(self.compilestack) remove(self.compilestack)
return lua return lua
elseif not def and self.__class.math_patt:match(tree.stub) then elseif not def and self.__class.math_patt:match(tree.stub) then
@ -836,7 +834,6 @@ end]]):format(lua_code))
end end
args = new_args args = new_args
end end
insert(args, 1, "nomsu")
remove(self.compilestack) remove(self.compilestack)
return { return {
expr = self.__class:comma_separated_items("nomsu.defs[" .. tostring(repr(tree.stub)) .. "].fn(", args, ")") expr = self.__class:comma_separated_items("nomsu.defs[" .. tostring(repr(tree.stub)) .. "].fn(", args, ")")
@ -1164,8 +1161,9 @@ end]]):format(lua_code))
return self:dedent(self.compilestack[#self.compilestack - level].src) return self:dedent(self.compilestack[#self.compilestack - level].src)
end, end,
initialize_core = function(self) initialize_core = function(self)
local nomsu = self
local nomsu_string_as_lua local nomsu_string_as_lua
nomsu_string_as_lua = function(self, code) nomsu_string_as_lua = function(code)
local concat_parts = { } local concat_parts = { }
local _list_0 = code.value local _list_0 = code.value
for _index_0 = 1, #_list_0 do for _index_0 = 1, #_list_0 do
@ -1173,65 +1171,65 @@ end]]):format(lua_code))
if type(bit) == "string" then if type(bit) == "string" then
insert(concat_parts, bit) insert(concat_parts, bit)
else else
local lua = self:tree_to_lua(bit) local lua = nomsu:tree_to_lua(bit)
if lua.statements then if lua.statements then
self:error("Cannot use [[" .. tostring(bit.src) .. "]] as a string interpolation value, since it's not an expression.") error("Cannot use [[" .. tostring(bit.src) .. "]] as a string interpolation value, since it's not an expression.")
end end
insert(concat_parts, lua.expr) insert(concat_parts, lua.expr)
end end
end end
return concat(concat_parts) return concat(concat_parts)
end end
self:define_compile_action("do %block", "nomsu.moon", function(self, _block) self:define_compile_action("do %block", "nomsu.moon", function(_block)
local make_line local make_line
make_line = function(lua) make_line = function(lua)
return lua.expr and (lua.expr .. ";") or lua.statements return lua.expr and (lua.expr .. ";") or lua.statements
end end
if _block.type == "Block" then if _block.type == "Block" then
return self:tree_to_lua(_block) return nomsu:tree_to_lua(_block)
else else
return { return {
expr = tostring(self:tree_to_lua(_block)) .. "(nomsu)" expr = tostring(nomsu:tree_to_lua(_block)) .. "(nomsu)"
} }
end end
end) end)
self:define_compile_action("immediately %block", "nomsu.moon", function(self, _block) self:define_compile_action("immediately %block", "nomsu.moon", function(_block)
local lua = self:tree_to_lua(_block) local lua = nomsu:tree_to_lua(_block)
local lua_code = lua.statements or (lua.expr .. ";") local lua_code = lua.statements or (lua.expr .. ";")
lua_code = "-- Immediately:\n" .. lua_code lua_code = "-- Immediately:\n" .. lua_code
self:run_lua(lua_code) nomsu:run_lua(lua_code)
return { return {
statements = lua_code statements = lua_code
} }
end) end)
self:define_compile_action("lua> %code", "nomsu.moon", function(self, _code) self:define_compile_action("lua> %code", "nomsu.moon", function(_code)
local lua = nomsu_string_as_lua(self, _code) local lua = nomsu_string_as_lua(_code)
return { return {
statements = lua statements = lua
} }
end) end)
self:define_compile_action("=lua %code", "nomsu.moon", function(self, _code) self:define_compile_action("=lua %code", "nomsu.moon", function(_code)
local lua = nomsu_string_as_lua(self, _code) local lua = nomsu_string_as_lua(_code)
return { return {
expr = lua expr = lua
} }
end) end)
self:define_compile_action("__line_no__", "nomsu.moon", function(self) self:define_compile_action("__line_no__", "nomsu.moon", function()
return { return {
expr = repr(self.compilestack[#self.compilestack]:get_line_no()) expr = repr(nomsu.compilestack[#nomsu.compilestack]:get_line_no())
} }
end) end)
self:define_compile_action("__src__ %level", "nomsu.moon", function(self, _level) self:define_compile_action("__src__ %level", "nomsu.moon", function(_level)
return { return {
expr = repr(self:source_code(self:tree_to_value(_level))) expr = repr(nomsu:source_code(nomsu:tree_to_value(_level)))
} }
end) end)
self:define_action("run file %filename", "nomsu.moon", function(self, _filename) self:define_action("run file %filename", "nomsu.moon", function(_filename)
return self:run_file(_filename) return nomus:run_file(_filename)
end) end)
return self:define_compile_action("use %filename", "nomsu.moon", function(self, _filename) return self:define_compile_action("use %filename", "nomsu.moon", function(_filename)
local filename = self:tree_to_value(_filename) local filename = nomsu:tree_to_value(_filename)
self:require_file(filename) nomsu:require_file(filename)
return { return {
statements = "nomsu:require_file(" .. tostring(repr(filename)) .. ");" statements = "nomsu:require_file(" .. tostring(repr(filename)) .. ");"
} }
@ -1272,13 +1270,56 @@ end]]):format(lua_code))
end end
self.compilestack = { } self.compilestack = { }
self.debug = false self.debug = false
self.utils = utils
self.repr = function(self, ...) self.repr = function(self, ...)
return repr(...) return repr(...)
end end
self.stringify = function(self, ...) self.stringify = function(self, ...)
return stringify(...) return stringify(...)
end end
self.environment = {
nomsu = self,
repr = repr,
stringify = stringify,
utils = utils,
lpeg = lpeg,
re = re,
next = next,
unpack = unpack,
setmetatable = setmetatable,
coroutine = coroutine,
rawequal = rawequal,
getmetatable = getmetatable,
pcall = pcall,
error = error,
package = package,
os = os,
require = require,
tonumber = tonumber,
tostring = tostring,
string = string,
xpcall = xpcall,
module = module,
print = print,
loadfile = loadfile,
rawset = rawset,
_VERSION = _VERSION,
collectgarbage = collectgarbage,
rawget = rawget,
bit32 = bit32,
rawlen = rawlen,
table = table,
assert = assert,
dofile = dofile,
loadstring = loadstring,
type = type,
select = select,
debug = debug,
math = math,
io = io,
pairs = pairs,
load = load,
ipairs = ipairs
}
if not parent then if not parent then
return self:initialize_core() return self:initialize_core()
end end

View File

@ -164,9 +164,17 @@ class NomsuCompiler
setmetatable(@defs["#loaded_files"], {__index:parent["#loaded_files"]}) setmetatable(@defs["#loaded_files"], {__index:parent["#loaded_files"]})
@compilestack = {} @compilestack = {}
@debug = false @debug = false
@utils = utils
@repr = (...)=> repr(...) @environment = {
@stringify = (...)=> stringify(...) -- Discretionary/convenience stuff
nomsu:self, repr:repr, stringify:stringify, utils:utils, lpeg:lpeg, re:re,
-- Lua stuff:
:next, :unpack, :setmetatable, :coroutine, :rawequal, :getmetatable, :pcall,
:error, :package, :os, :require, :tonumber, :tostring, :string, :xpcall, :module,
:print, :loadfile, :rawset, :_VERSION, :collectgarbage, :rawget, :bit32, :rawlen,
:table, :assert, :dofile, :loadstring, :type, :select, :debug, :math, :io, :pairs,
:load, :ipairs,
}
if not parent if not parent
@initialize_core! @initialize_core!
@ -303,7 +311,10 @@ class NomsuCompiler
run_file: (filename)=> run_file: (filename)=>
if filename\match(".*%.lua") if filename\match(".*%.lua")
return dofile(filename)(@) file = io.open(filename)
contents = file\read("*a")
file\close!
return assert(load(contents, nil, nil, @environment))!
if filename\match(".*%.nom") if filename\match(".*%.nom")
if not @skip_precompiled -- Look for precompiled version if not @skip_precompiled -- Look for precompiled version
file = io.open(filename\gsub("%.nom", ".lua"), "r") file = io.open(filename\gsub("%.nom", ".lua"), "r")
@ -327,32 +338,26 @@ class NomsuCompiler
return loaded[filename] return loaded[filename]
run_lua: (lua_code)=> run_lua: (lua_code)=>
load_lua_fn, err = load([[ run_lua_fn, err = load(lua_code, nil, nil, @environment)
return function(nomsu)
%s
end]]\format(lua_code))
if @debug if @debug
@writeln "#{colored.bright "RUNNING LUA:"}\n#{colored.blue colored.bright(lua_code)}" @writeln "#{colored.bright "RUNNING LUA:"}\n#{colored.blue colored.bright(lua_code)}"
if not load_lua_fn if not run_lua_fn
n = 1 n = 1
fn = -> fn = ->
n = n + 1 n = n + 1
("\n%-3d|")\format(n) ("\n%-3d|")\format(n)
code = "1 |"..lua_code\gsub("\n", fn) code = "1 |"..lua_code\gsub("\n", fn)
@error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{err}") @error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{err}")
run_lua_fn = load_lua_fn! return run_lua_fn!
run_lua_fn(self)
return ret
tree_to_value: (tree, filename)=> tree_to_value: (tree, filename)=>
code = "return (function(nomsu)\nreturn #{@tree_to_lua(tree).expr};\nend);" code = "return #{@tree_to_lua(tree).expr};"
code = "-- Tree to value: #{filename}\n"..code
if @debug if @debug
@writeln "#{colored.bright "RUNNING LUA TO GET VALUE:"}\n#{colored.blue colored.bright(code)}" @writeln "#{colored.bright "RUNNING LUA TO GET VALUE:"}\n#{colored.blue colored.bright(code)}"
lua_thunk, err = load(code) lua_thunk, err = load(code, nil, nil, @environment)
if not lua_thunk if not lua_thunk
@error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{colored.red err}") @error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{colored.red err}")
return (lua_thunk!)(self) return lua_thunk!
tree_to_nomsu: (tree, force_inline=false)=> tree_to_nomsu: (tree, force_inline=false)=>
-- Return <nomsu code>, <is safe for inline use> -- Return <nomsu code>, <is safe for inline use>
@ -527,7 +532,7 @@ end]]\format(lua_code))
if @debug if @debug
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} " @write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr [(repr a)\sub(1,50) for a in *args]}" @writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr [(repr a)\sub(1,50) for a in *args]}"
lua = @defs[tree.stub].fn(self, unpack(args)) lua = @defs[tree.stub].fn(unpack(args))
remove @compilestack remove @compilestack
return lua return lua
elseif not def and @@math_patt\match(tree.stub) elseif not def and @@math_patt\match(tree.stub)
@ -557,7 +562,6 @@ end]]\format(lua_code))
new_args = [args[p] for p in *def.arg_positions] new_args = [args[p] for p in *def.arg_positions]
args = new_args args = new_args
insert args, 1, "nomsu"
remove @compilestack remove @compilestack
return expr:@@comma_separated_items("nomsu.defs[#{repr tree.stub}].fn(", args, ")") return expr:@@comma_separated_items("nomsu.defs[#{repr tree.stub}].fn(", args, ")")
@ -578,7 +582,7 @@ end]]\format(lua_code))
@writeln "#{colored.bright "EXPR:"} #{lua.expr}, #{colored.bright "STATEMENT:"} #{lua.statements}" @writeln "#{colored.bright "EXPR:"} #{lua.expr}, #{colored.bright "STATEMENT:"} #{lua.statements}"
if lua.statements if lua.statements
@error "Cannot use [[#{bit.src}]] as a string interpolation value, since it's not an expression." @error "Cannot use [[#{bit.src}]] as a string interpolation value, since it's not an expression."
insert concat_parts, "nomsu:stringify(#{lua.expr})" insert concat_parts, "stringify(#{lua.expr})"
if string_buffer ~= "" if string_buffer ~= ""
insert concat_parts, repr(string_buffer) insert concat_parts, repr(string_buffer)
@ -759,52 +763,53 @@ end]]\format(lua_code))
initialize_core: => initialize_core: =>
-- Sets up some core functionality -- Sets up some core functionality
nomsu_string_as_lua = (code)=> nomsu = self
nomsu_string_as_lua = (code)->
concat_parts = {} concat_parts = {}
for bit in *code.value for bit in *code.value
if type(bit) == "string" if type(bit) == "string"
insert concat_parts, bit insert concat_parts, bit
else else
lua = @tree_to_lua bit lua = nomsu\tree_to_lua bit
if lua.statements if lua.statements
@error "Cannot use [[#{bit.src}]] as a string interpolation value, since it's not an expression." error "Cannot use [[#{bit.src}]] as a string interpolation value, since it's not an expression."
insert concat_parts, lua.expr insert concat_parts, lua.expr
return concat(concat_parts) return concat(concat_parts)
@define_compile_action "do %block", "nomsu.moon", (_block)=> @define_compile_action "do %block", "nomsu.moon", (_block)->
make_line = (lua)-> lua.expr and (lua.expr..";") or lua.statements make_line = (lua)-> lua.expr and (lua.expr..";") or lua.statements
if _block.type == "Block" if _block.type == "Block"
return @tree_to_lua(_block) return nomsu\tree_to_lua(_block)
else else
return expr:"#{@tree_to_lua _block}(nomsu)" return expr:"#{nomsu\tree_to_lua _block}(nomsu)"
@define_compile_action "immediately %block", "nomsu.moon", (_block)=> @define_compile_action "immediately %block", "nomsu.moon", (_block)->
lua = @tree_to_lua(_block) lua = nomsu\tree_to_lua(_block)
lua_code = lua.statements or (lua.expr..";") lua_code = lua.statements or (lua.expr..";")
lua_code = "-- Immediately:\n"..lua_code lua_code = "-- Immediately:\n"..lua_code
@run_lua(lua_code) nomsu\run_lua(lua_code)
return statements:lua_code return statements:lua_code
@define_compile_action "lua> %code", "nomsu.moon", (_code)=> @define_compile_action "lua> %code", "nomsu.moon", (_code)->
lua = nomsu_string_as_lua(@, _code) lua = nomsu_string_as_lua(_code)
return statements:lua return statements:lua
@define_compile_action "=lua %code", "nomsu.moon", (_code)=> @define_compile_action "=lua %code", "nomsu.moon", (_code)->
lua = nomsu_string_as_lua(@, _code) lua = nomsu_string_as_lua(_code)
return expr:lua return expr:lua
@define_compile_action "__line_no__", "nomsu.moon", ()=> @define_compile_action "__line_no__", "nomsu.moon", ->
expr: repr(@compilestack[#@compilestack]\get_line_no!) expr: repr(nomsu.compilestack[#nomsu.compilestack]\get_line_no!)
@define_compile_action "__src__ %level", "nomsu.moon", (_level)=> @define_compile_action "__src__ %level", "nomsu.moon", (_level)->
expr: repr(@source_code(@tree_to_value(_level))) expr: repr(nomsu\source_code(nomsu\tree_to_value(_level)))
@define_action "run file %filename", "nomsu.moon", (_filename)=> @define_action "run file %filename", "nomsu.moon", (_filename)->
@run_file(_filename) nomus\run_file(_filename)
@define_compile_action "use %filename", "nomsu.moon", (_filename)=> @define_compile_action "use %filename", "nomsu.moon", (_filename)->
filename = @tree_to_value(_filename) filename = nomsu\tree_to_value(_filename)
@require_file(filename) nomsu\require_file(filename)
return statements:"nomsu:require_file(#{repr filename});" return statements:"nomsu:require_file(#{repr filename});"
if arg if arg

View File

@ -42,9 +42,12 @@ local _quote_patt = re.compile("(({'\n' / '\"' / \"'\" / '\\'}->mark_char) / (']
mark_eq=function(eq) mark_eq=function(eq)
_quote_state.min_eq = max(_quote_state.min_eq or 0, #eq+1) _quote_state.min_eq = max(_quote_state.min_eq or 0, #eq+1)
end}) end})
local function repr(x) local function repr(x, depth)
-- Create a string representation of the object that is close to the lua code that will -- Create a string representation of the object that is close to the lua code that will
-- reproduce the object (similar to Python's "repr" function) -- reproduce the object (similar to Python's "repr" function)
depth = depth or 10
if depth == 0 then return "..." end
depth = depth - 1
local x_type = type(x) local x_type = type(x)
if x_type == 'table' then if x_type == 'table' then
if getmetatable(x) then if getmetatable(x) then
@ -55,12 +58,12 @@ local function repr(x)
local i = 1 local i = 1
for k, v in pairs(x) do for k, v in pairs(x) do
if k == i then if k == i then
ret[#ret+1] = repr(x[i]) ret[#ret+1] = repr(x[i], depth)
i = i + 1 i = i + 1
elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then
ret[#ret+1] = k.."= "..repr(v) ret[#ret+1] = k.."= "..repr(v,depth)
else else
ret[#ret+1] = "["..repr(k).."]= "..repr(v) ret[#ret+1] = "["..repr(k,depth).."]= "..repr(v,depth)
end end
end end
return "{"..table.concat(ret, ", ").."}" return "{"..table.concat(ret, ", ").."}"