Reworking some stuff so that functions only allow expressions to be

return values with either an explicit "return" statement or if they're
the only line in the function, and the line is an expression.
This commit is contained in:
Bruce Hill 2018-01-07 18:45:27 -08:00
parent c92e5fbc81
commit 568a44ef19
6 changed files with 69 additions and 70 deletions

View File

@ -51,7 +51,7 @@ compile [%list ->* %indices] to:
%ret = "\(%list as lua)"
for %index in (%indices's "value"):
%ret join= "[\(%index as lua)]"
"\%ret"
return "\%ret"
# Assignment
compile [..]
@ -76,35 +76,35 @@ rule [flatten %lists] =:
for %list in %lists:
for %item in %list:
add %item to %flat
%flat
return %flat
rule [dict %items] =:
%dict = []
for %pair in %items:
%dict -> (%pair -> 1) = (%pair -> 2)
%dict
return %dict
rule [entries in %dict] =:
%entries = []
for %k = %v in %dict:
add {key=%k, value=%v} to %entries
%entries
return %entries
rule [keys in %dict] =:
%keys = []
for %k = %v in %dict: add %k to %keys
%keys
return %keys
rule [values in %dict] =:
%values = []
for %k = %v in %dict: add %v to %values
%values
return %values
# List Comprehension
compile [%expression for %item in %iterable] to:
assert ((%item's "type") == "Var") ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type")
".."
return ".."
(function(nomsu, vars);
local comprehension = {};
for i,item in ipairs(\(%iterable as lua)) do;
@ -120,7 +120,7 @@ compile [%expression for %key = %value in %iterable] to:
List comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%key's "type")
assert ((%value's "type") == "Var") ".."
List comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%value's "type")
".."
return ".."
(function(nomsu, vars);
local comprehension = {};
for key,value in pairs(\(%iterable as lua)) do;
@ -133,11 +133,11 @@ compile [%expression for %key = %value in %iterable] to:
rule [%items sorted] =:
%copy = (% for all %items)
sort %copy
%copy
return %copy
rule [%items sorted by %key] =:
%copy = (% for all %items)
sort %copy by %key
%copy
return %copy
rule [unique %items] =:
keys in (dict ([%,yes] for all %items))
@ -165,7 +165,7 @@ rule [chain %dict to %fallback] =:
compile [%key = %value for %item in %iterable] to:
assert ((%item's "type") == "Var") ".."
Dict comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item's "type")
".."
return ".."
(function(nomsu, vars);
local comprehension = {};
for i,value in ipairs(\(%iterable as lua)) do;
@ -181,7 +181,7 @@ compile [%key = %value for %src_key = %src_value in %iterable] to:
Dict comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%src_key's "type")
assert ((%src_value's "type") == "Var") ".."
Dict comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%src_value's "type")
".."
return ".."
(function(nomsu, vars);
local comprehension = {};
for key,value in pairs(\(%iterable as lua)) do;

View File

@ -210,7 +210,7 @@ compile [when %body] to code:
if (%result != ""):
%result join= "\nend"
%result
return %result
# Switch statement
compile [when %branch_value == ? %body] to code:
@ -259,7 +259,7 @@ compile [when %branch_value == ? %body] to code:
..\%result
end
end --when == ?
%result
return %result
# Try/except
compile [..]

View File

@ -12,8 +12,8 @@ compile [phi, PHI, golden ratio] to: "((1+math.sqrt(5))/2)"
compile [nop, pass] to code: ""
# Ternary operator
#.. Note: this uses a function instead of (condition and if_expr or else_expr)
because that breaks if %if_expr is falsey.
#.. Note: this uses a function instead of "(condition and if_expr or else_expr)"
because that breaks if %if_expr is falsey, e.g. "x < 5 and false or 99"
compile [..]
%when_true_expr if %condition else %when_false_expr
%when_true_expr if %condition otherwise %when_false_expr
@ -27,6 +27,17 @@ compile [..]
return \(%when_false_expr as lua);
end
end)(nomsu, vars)
parse [..]
%true if %x == %y else %false, %true if %x == %y otherwise %false
%false unless %x == %y else %true, %false unless %x == %y otherwise %true
..as:
%true if (%x == %y) else %false
parse [..]
%true if %x != %y else %false, %true if %x != %y otherwise %false
%false unless %x != %y else %true, %false unless %x != %y otherwise %true
..as:
%true if (%x != %y) else %false
# Indexing:
compile [%obj'%key, %obj's %key, %obj -> %key] to: "(\(%obj as lua))[\(%key as lua)]"

View File

@ -6,16 +6,12 @@ require "lib/collections.nom"
compile [say %str] to:
if ((%str's "type") == "String"):
"nomsu:writeln(\(%str as lua))"
..else:
"nomsu:writeln(nomsu:stringify(\(%str as lua)))"
"nomsu:writeln(\(%str as lua))" if ((%str's "type") == "String")
..else "nomsu:writeln(nomsu:stringify(\(%str as lua)))"
compile [do %action] to code:
if ((%action's "type") == "Thunk"):
%action as lua statements
..else:
"(\(%action as lua))(nomsu, vars);"
(%action as lua statements) if ((%action's "type") == "Thunk")
..else "(\(%action as lua))(nomsu, vars);"
# With statement
compile [with %assignments %action] to code:
@ -33,7 +29,7 @@ compile [with %assignments %action] to code:
"local old_value\(%->"i") = \((%->"var") as lua); \((%->"var") as lua) = \((%->"value") as lua);"
..for all %data
..with glue "\n "
".."
return ".."
do
\%setup
local fell_through = false;
@ -51,26 +47,17 @@ parse [with %thing = %value %action] as: with [%thing = %value] %action
# Any/all/none
compile [all of %items, all %items] to:
if (%items' "type") == "List":
"(\(join ((% as lua) for all (%items' "value")) with glue " and "))"
..else:
"nomsu.utils.all(\(%items as lua))"
"(\(join ((% as lua) for all (%items' "value")) with glue " and "))"
..if (%items' "type") == "List" else "nomsu.utils.all(\(%items as lua))"
parse [not all of %items, not all %items] as: not (all of %items)
compile [any of %items, any %items] to:
if (%items' "type") == "List":
"(\(join ((% as lua) for all (%items' "value")) with glue " or "))"
..else:
"nomsu.utils.any(\(%items as lua))"
"(\(join ((% as lua) for all (%items' "value")) with glue " or "))"
..if (%items' "type") == "List" else "nomsu.utils.any(\(%items as lua))"
parse [none of %items, none %items] as: not (any of %items)
compile [sum of %items, sum %items] to:
if (%items' "type") == "List":
"(\(join ((% as lua) for all (%items' "value")) with glue " + "))"
..else:
"nomsu.utils.sum(\(%items as lua))"
"(\(join ((% as lua) for all (%items' "value")) with glue " + "))"
..if (%items' "type") == "List" else "nomsu.utils.sum(\(%items as lua))"
compile [product of %items, product %items] to:
if (%items' "type") == "List":
"(\(join ((% as lua) for all (%items' "value")) with glue " * "))"
..else:
"nomsu.utils.product(\(%items as lua))"
"(\(join ((% as lua) for all (%items' "value")) with glue " * "))"
..if (%items' "type") == "List" else "nomsu.utils.product(\(%items as lua))"

View File

@ -528,7 +528,6 @@ do
self:assert(tree, "Tree failed to compile: " .. tostring(src))
self:assert(tree.type == "File", "Attempt to run non-file: " .. tostring(tree.type))
local buffer = { }
local return_value = nil
local _list_0 = tree.value
for _index_0 = 1, #_list_0 do
local statement = _list_0[_index_0]
@ -544,8 +543,7 @@ do
end
local code_for_statement = ([[return (function(nomsu, vars)
%s
return %s;
end);]]):format(statements or "", expr or "ret")
end);]]):format(statements or ("return " .. expr .. ";"))
if output_file then
if statements and #statements > 0 then
output_file:write("lua> \"..\"\n " .. tostring(self:indent(statements:gsub("\\", "\\\\"))) .. "\n")
@ -571,9 +569,6 @@ end);]]):format(statements or "", expr or "ret")
local run_statement = lua_thunk()
local ret
ok, ret = pcall(run_statement, self, vars)
if expr then
return_value = ret
end
if not ok then
self:errorln(tostring(colored.red("Error occurred in statement:")) .. "\n" .. tostring(colored.yellow(statement.src)))
self:errorln(debug.traceback())
@ -583,18 +578,16 @@ end);]]):format(statements or "", expr or "ret")
insert(buffer, statements)
end
if expr then
insert(buffer, "ret = " .. tostring(expr) .. ";")
insert(buffer, tostring(expr) .. ";")
end
end
if max_operations then
debug.sethook()
end
local lua_code = ([[return (function(nomsu, vars)
local ret;
%s
return ret;
end);]]):format(concat(buffer, "\n"))
return return_value, lua_code, vars
return nil, lua_code, vars
end,
tree_to_value = function(self, tree, vars, filename)
local code = "return (function(nomsu, vars)\nreturn " .. tostring(self:tree_to_lua(tree, filename)) .. ";\nend);"
@ -817,7 +810,7 @@ end);]]):format(concat(buffer, "\n"))
insert(lua_bits, statement)
end
if expr then
insert(lua_bits, "ret = " .. tostring(expr) .. ";")
insert(lua_bits, tostring(expr) .. ";")
end
end
return nil, concat(lua_bits, "\n")
@ -829,17 +822,20 @@ end);]]):format(concat(buffer, "\n"))
for _index_0 = 1, #_list_0 do
local arg = _list_0[_index_0]
local expr, statement = self:tree_to_lua(arg, filename)
if #tree.value == 1 and expr and not statement then
return ([[(function(nomsu, vars)
return %s;
end)]]):format(expr)
end
if statement then
insert(lua_bits, statement)
end
if expr then
insert(lua_bits, "ret = " .. tostring(expr) .. ";")
insert(lua_bits, tostring(expr) .. ";")
end
end
return ([[(function(nomsu, vars)
local ret;
%s
return ret;
end)]]):format(concat(lua_bits, "\n"))
elseif "FunctionCall" == _exp_0 then
insert(self.compilestack, tree)
@ -1441,7 +1437,7 @@ if arg then
colors = require('consolecolors')
local parser = re.compile([[ args <- {| {:flags: flags? :} ({:input: input :} ";" ("-o;"{:output: output :} ";")?)? (";")? |} !.
flags <- (({| ({flag} ";")* |}) -> set)
flag <- "-c" / "-i" / "-p" / "-O" / "--help" / "-h"
flag <- "-c" / "-i" / "-p" / "-O" / "--help" / "-h" / "-v"
input <- "-" / [^;]+
output <- "-" / [^;]+
]], {
@ -1454,6 +1450,9 @@ if arg then
os.exit()
end
local c = NomsuCompiler()
if args.flags["-v"] then
c.debug = true
end
c.skip_precompiled = not args.flags["-O"]
if args.input then
if args.flags["-c"] and not args.output then

View File

@ -342,7 +342,7 @@ class NomsuCompiler
@assert tree.type == "File", "Attempt to run non-file: #{tree.type}"
buffer = {}
return_value = nil
-- TODO: handle return statements in a file
for statement in *tree.value
if @debug
@writeln "#{colored.bright "RUNNING NOMSU:"}\n#{colored.bright colored.yellow statement.src}"
@ -355,8 +355,7 @@ class NomsuCompiler
code_for_statement = ([[
return (function(nomsu, vars)
%s
return %s;
end);]])\format(statements or "", expr or "ret")
end);]])\format(statements or ("return "..expr..";"))
if output_file
if statements and #statements > 0
output_file\write "lua> \"..\"\n #{@indent statements\gsub("\\","\\\\")}\n"
@ -374,7 +373,6 @@ end);]])\format(statements or "", expr or "ret")
error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{err}\n\nProduced by statement:\n#{colored.bright colored.yellow statement.src}")
run_statement = lua_thunk!
ok,ret = pcall(run_statement, self, vars)
if expr then return_value = ret
if not ok
@errorln "#{colored.red "Error occurred in statement:"}\n#{colored.yellow statement.src}"
@errorln debug.traceback!
@ -382,17 +380,15 @@ end);]])\format(statements or "", expr or "ret")
if statements
insert buffer, statements
if expr
insert buffer, "ret = #{expr};"
insert buffer, "#{expr};"
if max_operations
debug.sethook!
lua_code = ([[
return (function(nomsu, vars)
local ret;
%s
return ret;
end);]])\format(concat(buffer, "\n"))
return return_value, lua_code, vars
return nil, lua_code, vars
tree_to_value: (tree, vars, filename)=>
code = "return (function(nomsu, vars)\nreturn #{@tree_to_lua(tree, filename)};\nend);"
@ -546,7 +542,7 @@ end);]])\format(concat(buffer, "\n"))
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};"
if expr then insert lua_bits, "#{expr};"
return nil, concat(lua_bits, "\n")
when "Nomsu"
@ -556,13 +552,16 @@ end);]])\format(concat(buffer, "\n"))
lua_bits = {}
for arg in *tree.value
expr,statement = @tree_to_lua arg, filename
if #tree.value == 1 and expr and not statement
return ([[
(function(nomsu, vars)
return %s;
end)]])\format(expr)
if statement then insert lua_bits, statement
if expr then insert lua_bits, "ret = #{expr};"
if expr then insert lua_bits, "#{expr};"
return ([[
(function(nomsu, vars)
local ret;
%s
return ret;
end)]])\format(concat(lua_bits, "\n"))
when "FunctionCall"
@ -889,7 +888,7 @@ if arg
parser = re.compile([[
args <- {| {:flags: flags? :} ({:input: input :} ";" ("-o;"{:output: output :} ";")?)? (";")? |} !.
flags <- (({| ({flag} ";")* |}) -> set)
flag <- "-c" / "-i" / "-p" / "-O" / "--help" / "-h"
flag <- "-c" / "-i" / "-p" / "-O" / "--help" / "-h" / "-v"
input <- "-" / [^;]+
output <- "-" / [^;]+
]], {:set})
@ -901,6 +900,9 @@ if arg
c = NomsuCompiler()
if args.flags["-v"]
c.debug = true
c.skip_precompiled = not args.flags["-O"]
if args.input
-- Read a file or stdin and output either the printouts or the compiled lua