compile funcs use pretty to output when possible

This commit is contained in:
leaf corcoran 2011-05-28 18:36:19 -07:00
parent 3fbb35ac78
commit ee63375705
3 changed files with 77 additions and 59 deletions

View File

@ -21,6 +21,20 @@ function ntype(node)
return node[1] return node[1]
end end
-- number of newlines in string
local function num_lines(str)
local sum = 0
for v in str:gmatch("[\n]") do
sum = sum + 1
end
return sum
end
-- small enough to fit on one line
local function is_small(str)
return num_lines(str) == 0 and #str < 40
end
-- functions that can be inlined, or called from build in library -- functions that can be inlined, or called from build in library
local moonlib = { local moonlib = {
bind = function(tbl, name) bind = function(tbl, name)
@ -152,26 +166,28 @@ local compiler_index = {
return values return values
end end
-- importing from constant expression
if type(source) == "string" then if type(source) == "string" then
local values = get_values(source) local values = get_values(source)
return table.concat({"local", table.concat(final_names, ", "), return table.concat({"local", table.concat(final_names, ", "),
"=", table.concat(values, ", ")}, " ") "=", table.concat(values, ", ")}, " ")
end end
local outer, inner = self:ichar(0, 1)
local tmp_name = self:get_free_name("table") local tmp_name = self:get_free_name("table")
out = {
"local "..table.concat(final_names, ", "), self:push()
outer.."do", self:put_name(tmp_name)
inner.."local "..tmp_name.." = "..self:value(source) inner = { "local "..tmp_name.." = "..self:value(source) }
}
for i, value in ipairs(get_values(tmp_name)) do for i, value in ipairs(get_values(tmp_name)) do
table.insert(out, inner..final_names[i].." = "..value) table.insert(inner, final_names[i].." = "..value)
end end
self:pop()
table.insert(out, outer.."end") return self:pretty{
return table.concat(out, "\n") "local "..table.concat(final_names, ", "),
"do", inner, "end"
}
end, end,
fndef = function(self, node) fndef = function(self, node)
@ -182,17 +198,23 @@ local compiler_index = {
self:put_name(arg_name) self:put_name(arg_name)
end end
if arrow == "fat" then table.insert(args, "self") end if arrow == "fat" then table.insert(args, 1, "self") end
args = table.concat(args, ",") args = table.concat(args, ",")
local out local out
if #block == 0 then if #block == 0 then
out = ("function(%s) end"):format(args) out = ("function(%s) end"):format(args)
elseif #block == 1 and must_return[ntype(block[1])] then
out = ("function(%s) %s end"):format(args, self:block(block, true, 0))
else else
out = ("function(%s)\n%s\n%send"):format( local inner = self:block(block, true)
args, self:block(block, true), self:ichar()) if #inner == 1 and is_small(inner[1]) then
out = ("function(%s) %s end"):format(args, inner[1])
else
out = self:pretty{
("function(%s)"):format(args),
inner,
"end"
}
end
end end
self:pop() self:pop()
@ -202,7 +224,6 @@ local compiler_index = {
-- compile if -- compile if
["if"] = function(self, node, return_value) ["if"] = function(self, node, return_value)
local cond, block = node[2], node[3] local cond, block = node[2], node[3]
local ichr = self:ichar()
local out = { local out = {
("if %s then"):format(self:value(cond)), ("if %s then"):format(self:value(cond)),
@ -213,10 +234,10 @@ local compiler_index = {
local clause = node[i] local clause = node[i]
local block local block
if clause[1] == "else" then if clause[1] == "else" then
table.insert(out, ichr.."else") table.insert(out, "else")
block = clause[2] block = clause[2]
elseif clause[1] == "elseif" then elseif clause[1] == "elseif" then
table.insert(out, ichr.."elseif "..self:value(clause[2]).." then") table.insert(out, "elseif "..self:value(clause[2]).." then")
block = clause[3] block = clause[3]
else else
error("Unknown if clause: "..clause[1]) error("Unknown if clause: "..clause[1])
@ -224,17 +245,19 @@ local compiler_index = {
table.insert(out, self:block(block, return_value)) table.insert(out, self:block(block, return_value))
end end
table.insert(out, ichr.."end") table.insert(out, "end")
return table.concat(out, "\n") return self:pretty(out)
end, end,
['while'] = function(self, node) ['while'] = function(self, node)
local _, cond, block = unpack(node) local _, cond, block = unpack(node)
local ichr = self:ichar()
return ("while %s do\n%s\n%send"):format(self:value(cond), return self:pretty{
self:block(block, nil, 1), ichr) ("while %s do"):format(self:value(cond)),
self:block(block),
"end"
}
end, end,
name_list = function(self, node) name_list = function(self, node)
@ -276,6 +299,7 @@ local compiler_index = {
} }
end, end,
-- returns list of compiled statements
block = function(self, node, return_value, inc) block = function(self, node, return_value, inc)
inc = inc or 1 inc = inc or 1
@ -303,39 +327,45 @@ local compiler_index = {
end end
end end
local out = self:pretty(lines, true)
self:indent(-inc) self:indent(-inc)
self:pop() self:pop()
return out return lines
end, end,
table = function(self, node) table = function(self, node)
local _, items = unpack(node) local _, items = unpack(node)
self:indent(1) self:indent(1)
local len = #items
local item_values = {} local item_values = {}
for _, item in ipairs(items) do for i = 1,len do
local item = items[i]
local item_value
if #item == 1 then if #item == 1 then
table.insert(item_values, self:value(item[1])) item_value = self:value(item[1])
else else
local key = self:value(item[1]) local key = self:value(item[1])
if type(item[1]) ~= "string" then if type(item[1]) ~= "string" then
key = ("[%s]"):format(key) key = ("[%s]"):format(key)
end end
table.insert(item_values, key.." = "..self:value(item[2])) item_value = key.." = "..self:value(item[2])
end end
if i ~= len then
item_value = item_value..","
end
table.insert(item_values, item_value)
end end
local i = self:ichar()
self:indent(-1) self:indent(-1)
if #item_values > 3 then if #item_values > 3 then
return ("{\n%s%s\n%s}"):format(i, table.concat(item_values, ",\n"..i), self:ichar()) return self:pretty{ "{", item_values, "}" }
end end
return "{ "..table.concat(item_values, ", ").." }" return "{ "..table.concat(item_values, " ").." }"
end, end,
assign = function(self, node) assign = function(self, node)
@ -374,7 +404,9 @@ local compiler_index = {
local line = table.concat(names, ", ").." = "..table.concat(values, ", ") local line = table.concat(names, ", ").." = "..table.concat(values, ", ")
table.insert(lines, t == "local" and "local "..line or line) table.insert(lines, t == "local" and "local "..line or line)
end end
return table.concat(lines, "\n"..self:ichar())
return self:pretty(lines)
end, end,
exp = function(self, node) exp = function(self, node)
@ -467,7 +499,7 @@ end
function tree(tree) function tree(tree)
local compiler = build_compiler() local compiler = build_compiler()
return compiler:block(tree, false, 0) return compiler:pretty(compiler:block(tree, false, 0))
end end

View File

@ -62,9 +62,7 @@ end)();
return tmp return tmp
end)() end)()
require("util") require("util")
local dump = function(x) local dump = function(x) print(util.dump(x)) end
print(util.dump(x))
end
local range = function(count) local range = function(count)
local i = 0 local i = 0
return(coroutine.wrap(function() return(coroutine.wrap(function()

View File

@ -1,17 +1,13 @@
local x = function() local x = function() print(what) end
print(what)
end
local _ = function() end local _ = function() end
_ = function() return function() return function() end end end _ = function()
return function() return function() end end
end
go(to(the(barn))) go(to(the(barn)))
open(function() open(function() the(function() return door end) end)
the(function() return door end)
end)
open(function() open(function()
the(door) the(door)
local hello = function() local hello = function() my(func) end
my(func)
end
end) end)
local h = function() return hi end local h = function() return hi end
eat(function() end, world) eat(function() end, world)
@ -50,21 +46,15 @@ something('else', "ya")
something('else') something('else')
something("else") something("else")
here(we)("go")[12123] here(we)("go")[12123]
local something = { test = 12323, what = function() local something = { test = 12323, what = function() print("hello world") end }
print("hello world")
end }
print(something.test) print(something.test)
local frick = { hello = "world" } local frick = { hello = "world" }
local argon = { num = 100, world = function(self) local argon = { num = 100, world = function(self)
print(self.num) print(self.num)
return({ something = function() return({ something = function() print("hi from something") end })
print("hi from something")
end })
end, somethin = function(self,str) end, somethin = function(self,str)
print("string is", str) print("string is", str)
return({ world = function(a,b) return({ world = function(a,b) print("sum", a + b) end })
print("sum", a + b)
end })
end } end }
something.what() something.what()
argon:world().something() argon:world().something()
@ -94,9 +84,7 @@ else
_ = cool _ = cool
end end
local arg = { ... } local arg = { ... }
x = function(...) x = function(...) dump({ ... }) end
dump({ ... })
end
x = not true x = not true
local y = not (5 + 5) local y = not (5 + 5)
y = #"hello" y = #"hello"