implicity return for some types, temp storage for unary expressions

This commit is contained in:
leaf corcoran 2011-05-28 16:45:59 -07:00
parent 0babe3ad55
commit 75b834bbe5
6 changed files with 121 additions and 56 deletions

View File

@ -29,6 +29,8 @@ local moonlib = {
end
}
local must_return = data.Set{ 'parens', 'exp', 'value', 'string', 'table', 'fndef' }
local compiler_index = {
push = function(self) self._scope:push{} end,
pop = function(self) self._scope:pop() end,
@ -37,7 +39,7 @@ local compiler_index = {
self._indent = self._indent + amount
end,
pretty = function(self, tbl)
pretty = function(self, tbl, indent_front)
local out = {}
for _, line in ipairs(tbl) do
if type(line) == "table" then
@ -48,7 +50,12 @@ local compiler_index = {
table.insert(out, line)
end
end
return table.concat(out, "\n"..self:ichar())
local block = table.concat(out, "\n"..self:ichar())
if indent_front then
block = self:ichar()..block
end
return block
end,
has_name = function(self, name)
@ -181,24 +188,25 @@ local compiler_index = {
local out
if #block == 0 then
out = ("function(%s) end"):format(args)
elseif #block == 1 then
out = ("function(%s) %s end"):format(args, self:value(block[1]))
elseif #block == 1 and must_return[ntype(block[1])] then
out = ("function(%s) %s end"):format(args, self:block(block, true, 0))
else
out = ("function(%s)\n%s\n%send"):format(
args, self:block(block, 1), self:ichar())
args, self:block(block, true), self:ichar())
end
self:pop()
return out
end,
["if"] = function(self, node)
-- compile if
["if"] = function(self, node, return_value)
local cond, block = node[2], node[3]
local ichr = self:ichar()
local out = {
("if %s then"):format(self:value(cond)),
self:block(block, 1)
self:block(block, return_value)
}
for i = 4,#node do
@ -213,7 +221,7 @@ local compiler_index = {
else
error("Unknown if clause: "..clause[1])
end
table.insert(out, self:block(block, 1))
table.insert(out, self:block(block, return_value))
end
table.insert(out, ichr.."end")
@ -225,7 +233,8 @@ local compiler_index = {
local _, cond, block = unpack(node)
local ichr = self:ichar()
return ("while %s do\n%s\n%send"):format(self:value(cond), self:block(block, 1), ichr)
return ("while %s do\n%s\n%send"):format(self:value(cond),
self:block(block, nil, 1), ichr)
end,
name_list = function(self, node)
@ -267,17 +276,25 @@ local compiler_index = {
}
end,
block = function(self, node, inc)
block = function(self, node, return_value, inc)
inc = inc or 1
self:push()
if inc then self:indent(inc) end
self:indent(inc)
local lines = {}
local i = self:ichar()
for _, ln in ipairs(node) do
table.insert(lines, i..self:value(ln))
local len = #node
for i=1,len do
local ln = node[i]
local value = self:stm(ln, return_value and i == len)
if type(value) == "table" then
for _, v in value do
table.insert(lines, value)
end
else
table.insert(lines, value)
end
end
if inc then self:indent(-inc) end
self:pop()
-- add semicolons where they might be needed
for i, left, k, right in itwos(lines) do
@ -286,7 +303,12 @@ local compiler_index = {
end
end
return table.concat(lines, "\n")
local out = self:pretty(lines, true)
self:indent(-inc)
self:pop()
return out
end,
table = function(self, node)
@ -376,18 +398,35 @@ local compiler_index = {
return delim..inner..(delim_end or delim)
end,
value = function(self, node)
value = function(self, node, ...)
if return_value == nil then return_value = true end
if type(node) == "table" then
local fn = self[node[1]]
if not fn then
error("Unknown op: "..tostring(node[1]))
end
return fn(self, node)
return fn(self, node, ...)
end
return node
end,
-- has no return value, meant to be on line of it's own
stm = function(self, node, return_value)
local value = self:value(node, return_value)
if must_return[ntype(node)] then
if return_value then
return "return "..value
else
return self:value({"assign", {"_"}, {value}}, false)
end
end
return value
end,
minus = function(self, node)
local _, value = unpack(node)
return "-"..self:value(value)
@ -428,7 +467,7 @@ end
function tree(tree)
local compiler = build_compiler()
return compiler:block(tree)
return compiler:block(tree, false, 0)
end

View File

@ -29,3 +29,11 @@ function Stack(...)
return self
end
function Set(items)
local self = {}
for _,item in ipairs(items) do
self[item] = true
end
return self
end

View File

@ -1,6 +1,6 @@
function()
local _ = function()
local joop = 2302
function(hi)
return function(hi)
local d = 100
hi = 1021
local a, b, c = 1, 2, 3

View File

@ -1,25 +1,25 @@
local you_cool = false
if cool then
if you_cool then
one
local _ = one
else
if eatdic then
yeah
local _ = yeah
else
two
three
local _ = two
_ = three
end
end
else
no
local _ = no
end
if cool then
no
local _ = no
end
if cool then
no
local _ = no
else
yes
local _ = yes
end
if cool then
wow(cool)
@ -29,12 +29,12 @@ end
if working then
if cool then
if cool then
okay
local _ = okay
else
what
local _ = what
end
else
nah
local _ = nah
end
end
while true do
@ -46,7 +46,7 @@ while 5 + 5 do
end
while also do
i(work(too))
"okay"
local _ = "okay"
end
if yeah then
no(day)

View File

@ -62,13 +62,17 @@ end)();
return tmp
end)()
require("util")
local dump = function(x) print(util.dump(x)) end
local dump = function(x)
print(util.dump(x))
end
local range = function(count)
local i = 0
return(coroutine.wrap(function() while i < count do
coroutine.yield(i)
i = i + 1
end end))
return(coroutine.wrap(function()
while i < count do
coroutine.yield(i)
i = i + 1
end
end))
end
dump((function()
local tmp = {}

View File

@ -1,13 +1,19 @@
local x = function() print(what) end
function() end
function() function() function() end end end
local x = function()
print(what)
end
local _ = function() end
_ = function() return function() return function() end end end
go(to(the(barn)))
open(function() the(function() door end) end)
open(function()
the(function() return door end)
end)
open(function()
the(door)
local hello = function() my(func) end
local hello = function()
my(func)
end
end)
local h = function() hi end
local h = function() return hi end
eat(function() end, world)
local a = 1 + 2 * 3 / 6
a = another
@ -15,7 +21,7 @@ local bunch, go, here = world
func(arg1, arg2, another, arg3)
here = function() end
local we = yeah
local the, different = function() approach end, yeah
local the, different = function() return approach end, yeah
dad()
dad(lord)
hello(one, two)();
@ -34,25 +40,31 @@ yeah = ((1 + 5) * 3) / 2
yeah = ((1 + 5) * 3) / 2 + i % 100
local whoa = (1 + 2) * (3 + 4) * (4 + 5);
(function() end)()
return(5 + function() 4 + 2 end)
return(5 + (function() 4 end) + 2)
return(5 + function() return 4 + 2 end)
return(5 + (function() return 4 end) + 2)
print(5 + function()
34
_ = 34
good(nads)
end)
something('else', "ya")
something('else')
something("else")
here(we)("go")[12123]
local something = { test = 12323, what = function() print("hello world") end }
local something = { test = 12323, what = function()
print("hello world")
end }
print(something.test)
local frick = { hello = "world" }
local argon = { num = 100, world = function(self)
print(self.num)
return({ something = function() print("hi from something") end })
return({ something = function()
print("hi from something")
end })
end, somethin = function(self,str)
print("string is", str)
return({ world = function(a,b) print("sum", a + b) end })
return({ world = function(a,b)
print("sum", a + b)
end })
end }
something.what()
argon:world().something()
@ -70,19 +82,21 @@ end)()
if cool then
print("hello")
else
cool
_ = cool
end
print("nutjob")
if hello then
343
_ = 343
end
if cool then
print("what")
else
cool
_ = cool
end
local arg = { ... }
x = function(...) dump({ ... }) end
x = function(...)
dump({ ... })
end
x = not true
local y = not (5 + 5)
y = #"hello"