remove the extra newlines, see class decl

This commit is contained in:
leaf corcoran 2011-07-11 09:38:22 -07:00
parent d66b7f3af5
commit ba3769e3aa
9 changed files with 261 additions and 266 deletions

View File

@ -69,6 +69,9 @@ end)()
local Block_
Block_ = (function(_parent_0)
local _base_0 = {
header = "do",
footer = "end",
delim = "\n",
line_table = function(self) return self._posmap end,
set = function(self, name, value) self._state[name] = value end,
get = function(self, name) return self._state[name] end,
@ -145,7 +148,16 @@ Block_ = (function(_parent_0)
local footer = flatten(self.footer)
return(concat({ header, footer }, " "))
end
local body = pretty(self._lines, indent_char:rep(self.indent))
local indent = indent_char:rep(self.indent)
if not self.delim then
for i = 1, #self._lines - 1 do
local left, right = self._lines[i], self._lines[i + 1]
if left:sub(-1) == ")" and right:sub(1, 1) == "(" then
self._lines[i] = self._lines[i] .. ";"
end
end
end
local body = indent .. concat(self._lines, (self.delim or "") .. "\n" .. indent)
return concat({ header, body, indent_char:rep(self.indent - 1) .. (function()
if self.next then
return self.next:render()
@ -181,15 +193,19 @@ Block_ = (function(_parent_0)
end,
values = function(self, values, delim)
delim = delim or ', '
return concat((function()
local _moon_0 = {}
local _item_0 = values
for _index_0=1,#_item_0 do
local v = _item_0[_index_0]
table.insert(_moon_0, self:value(v))
end
return _moon_0
end)(), delim)
do
local _with_0 = Line()
_with_0:append_list((function()
local _moon_0 = {}
local _item_0 = values
for _index_0=1,#_item_0 do
local v = _item_0[_index_0]
table.insert(_moon_0, self:value(v))
end
return _moon_0
end)(), delim)
return _with_0
end
end,
stm = function(self, node, ...)
local fn = line_compile[ntype(node)]
@ -248,12 +264,6 @@ Block_ = (function(_parent_0)
_base_0.__index = _base_0
local _class_0 = setmetatable({ __init = function(self, parent, header, footer)
self.parent, self.header, self.footer = parent, header, footer
if not self.header then
self.header = "do"
end
if not self.footer then
self.footer = "end"
end
self.line_offset = 1
self._lines = { }
self._posmap = { }

View File

@ -43,10 +43,11 @@ class Line
concat buff
class Block_
new: (@parent, @header, @footer) =>
@header = "do" if not @header
@footer = "end" if not @footer
header: "do"
footer: "end"
delim: "\n"
new: (@parent, @header, @footer) =>
@line_offset = 1
@_lines = {}
@ -138,7 +139,16 @@ class Block_
footer = flatten @footer
return concat {header, footer}, " "
body = pretty @_lines, indent_char\rep @indent
indent = indent_char\rep @indent
-- inject semicolons for ambiguous lines
if not @delim
for i = 1, #@_lines - 1
left, right = @_lines[i], @_lines[i+1]
if left\sub(-1) == ")" and right\sub(1,1) == "("
@_lines[i] = @_lines[i]..";"
body = indent .. concat @_lines, (@delim or "") .. "\n" .. indent
concat {
header,
@ -171,7 +181,8 @@ class Block_
values: (values, delim) =>
delim = delim or ', '
concat [@value v for v in *values], delim
with Line!
\append_list [@value v for v in *values], delim
stm: (node, ...) =>
fn = line_compile[ntype(node)]

View File

@ -5,36 +5,6 @@ local itwos = util.itwos
local Set, ntype = data.Set, data.ntype
local concat, insert = table.concat, table.insert
indent_char = " "
pretty = function(lines, indent)
indent = indent or ""
local render
render = function(line)
if type(line) == "table" then
return indent_char .. pretty(line, indent .. indent_char)
else
return line
end
end
lines = (function()
local _moon_0 = {}
local _item_0 = lines
for _index_0=1,#_item_0 do
local line = _item_0[_index_0]
table.insert(_moon_0, render(line))
end
return _moon_0
end)()
local fix
fix = function(i, left, k, right)
if left:sub(-1) == ")" and right:sub(1, 1) == "(" then
lines[i] = lines[i] .. ";"
end
end
for i, l, k, r in itwos(lines) do
fix(i, l, k, r)
end
return indent .. concat(lines, "\n" .. indent)
end
returner = function(exp)
if ntype(exp) == "chain" and exp[2] == "return" then
local items = { "explist" }

View File

@ -7,27 +7,10 @@ import itwos from util
import Set, ntype from data
import concat, insert from table
export indent_char, pretty, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic
export indent_char, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic
export count_lines
indent_char = " "
pretty = (lines, indent) ->
indent = indent or ""
render = (line) ->
if type(line) == "table"
indent_char..pretty(line, indent..indent_char)
else
line
lines = [render line for line in *lines]
-- add semicolons for ambiguities
fix = (i, left, k, right) ->
if left\sub(-1) == ")" and right\sub(1,1) == "("
lines[i] = lines[i]..";"
fix(i,l, k,r) for i,l,k,r in itwos lines
indent .. concat lines, "\n"..indent
returner = (exp) ->
if ntype(exp) == "chain" and exp[2] == "return"

View File

@ -14,6 +14,17 @@ line_compile = {
local _, text = unpack(node)
return self:add(text)
end,
declare = function(self, node)
local _, names = unpack(node)
local undeclared = self:declare(names)
if #undeclared > 0 then
do
local _with_0 = self:line("local ")
_with_0:append_list(names, ", ")
return _with_0
end
end
end,
assign = function(self, node)
local _, names, values = unpack(node)
local undeclared = self:declare(names)
@ -234,27 +245,6 @@ line_compile = {
find_special(unpack(entry))
end
tbl[2] = final_properties
local def_scope = self:block()
local parent_loc = def_scope:free_name("parent")
def_scope:set("super", function(block, chain)
local calling_name = block:get("current_block")
local slice = (function()
local _moon_0 = {}
local _item_0 = chain
for _index_0=3,#_item_0 do
local item = _item_0[_index_0]
table.insert(_moon_0, item)
end
return _moon_0
end)()
slice[1] = { "call", { "self", unpack(slice[1][2]) } }
return {
"chain",
parent_loc,
{ "dot", calling_name },
unpack(slice)
}
end)
if not constructor then
constructor = {
"fndef",
@ -295,35 +285,57 @@ line_compile = {
if #self_args > 0 then
insert(body, 1, { "assign", dests, self_args })
end
local base_name = def_scope:free_name("base")
def_scope:add_line(("local %s ="):format(base_name), def_scope:value(tbl))
def_scope:add_line(("%s.__index = %s"):format(base_name, base_name))
local cls = def_scope:value({ "table", { { "__init", constructor } } })
local cls_mt = def_scope:value({ "table", { { "__index", base_name }, { "__call", {
"fndef",
{ "mt", "..." },
"slim",
{ { "raw", ("local self = setmetatable({}, %s)"):format(base_name) }, { "chain", "mt.__init", { "call", { "self", "..." } } }, "self" }
} } } })
if parent_val ~= "" then
def_scope:stm({ "if", parent_loc, { { "chain", "setmetatable", { "call", { base_name, {
local parent_loc = self:free_name("parent", false)
local def_scope
do
local _with_0 = self:block()
if parent_val ~= "" then
local parent = self:value(parent_val)
end
_with_0:put_name(parent_loc)
_with_0.header = self:line("(function(", parent_loc, ")")
_with_0.footer = self:line("end)(", parent, ")")
_with_0:set("super", function(block, chain)
local calling_name = block:get("current_block")
local slice = (function()
local _moon_0 = {}
local _item_0 = chain
for _index_0=3,#_item_0 do
local item = _item_0[_index_0]
table.insert(_moon_0, item)
end
return _moon_0
end)()
slice[1] = { "call", { "self", unpack(slice[1][2]) } }
return {
"chain",
parent_loc,
{ "dot", calling_name },
unpack(slice)
}
end)
local base_name = _with_0:init_free_var("base", tbl)
_with_0:stm({ "assign", { { "chain", base_name, { "dot", "__index" } } }, { base_name } })
_with_0:stm({ "if", parent_loc, { { "chain", "setmetatable", { "call", { base_name, {
"chain",
"getmetatable",
{ "call", { parent_loc } },
{ "dot", "__index" }
} } } } } })
local cls = { "table", { { "__init", constructor } } }
local cls_mt = { "table", { { "__index", base_name }, { "__call", {
"fndef",
{ "mt", "..." },
"slim",
{ { "raw", ("local self = setmetatable({}, %s)"):format(base_name) }, { "chain", "mt.__init", { "call", { "self", "..." } } }, "self" }
} } } }
local cls_name = _with_0:init_free_var("class", { "chain", "setmetatable", { "call", { cls, cls_mt } } })
_with_0:stm({ "assign", { { "chain", base_name, { "dot", "__class" } } }, { cls_name } })
_with_0:stm({ "return", cls_name })
def_scope = _with_0
end
local cls_name = def_scope:free_name("class")
def_scope:add_line(("local %s = setmetatable(%s, %s)"):format(cls_name, cls, cls_mt))
def_scope:add_line(("%s.__class = %s"):format(base_name, cls_name))
def_scope:add_line("return", cls_name)
if parent_val ~= "" then
parent_val = self:value(parent_val)
end
local def = concat({ ("(function(%s)\n"):format(parent_loc), def_scope:render(), ("\nend)(%s)"):format(parent_val) })
self:add_line("local", name)
self:put_name(name)
return self:stm({ "assign", { name }, { def } })
self:stm({ "declare", { name } })
return self:line(name, " = ", def_scope)
end,
comprehension = function(self, node, action)
local _, exp, clauses = unpack(node)

View File

@ -22,6 +22,13 @@ line_compile =
_, text = unpack node
@add text
declare: (node) =>
_, names = unpack node
undeclared = @declare names
if #undeclared > 0
with @line "local "
\append_list names, ", "
assign: (node) =>
_, names, values = unpack node
@ -146,7 +153,7 @@ line_compile =
@put_name name for name in *names when type(name) == "string"
nil
-- TODO convert this
-- fix newlines
class: (node) =>
_, name, parent_val, tbl = unpack node
@ -163,17 +170,6 @@ line_compile =
find_special unpack entry for entry in *tbl[2]
tbl[2] = final_properties
def_scope = @block!
parent_loc = def_scope\free_name "parent"
def_scope\set "super" (block, chain) ->
calling_name = block\get"current_block"
slice = [item for item in *chain[3:]]
-- inject self
slice[1] = {"call", {"self", unpack slice[1][2]}}
{"chain", parent_loc, {"dot", calling_name}, unpack slice}
-- synthesize constructor if needed
if not constructor
constructor = {"fndef", {"..."}, "fat", {
@ -182,7 +178,7 @@ line_compile =
}}
}}
-- organize constructor
-- organize constructor arguments
-- extract self arguments
self_args = {}
get_initializers = (arg) ->
@ -199,45 +195,61 @@ line_compile =
dests = [{"self", name} for name in *self_args]
insert body, 1, {"assign", dests, self_args} if #self_args > 0
base_name = def_scope\free_name "base"
def_scope\add_line ("local %s =")\format(base_name), def_scope\value tbl
def_scope\add_line ("%s.__index = %s")\format(base_name, base_name)
-- now create the class's initialization block
parent_loc = @free_name "parent", false
cls = def_scope\value {"table", {
{"__init", constructor}
}}
def_scope = with @block!
parent = @value parent_val if parent_val != ""
\put_name parent_loc
cls_mt = def_scope\value {"table", {
{"__index", base_name}
{"__call", {"fndef", {"mt", "..."}, "slim", {
{"raw", ("local self = setmetatable({}, %s)")\format(base_name)}
{"chain", "mt.__init", {"call", {"self", "..."}}}
"self"
}}}
}}
.header = @line "(function(", parent_loc, ")"
.footer = @line "end)(", parent, ")"
if parent_val != ""
def_scope\stm {"if", parent_loc,
\set "super", (block, chain) ->
calling_name = block\get"current_block"
slice = [item for item in *chain[3:]]
-- inject self
slice[1] = {"call", {"self", unpack slice[1][2]}}
{"chain", parent_loc, {"dot", calling_name}, unpack slice}
-- the metatable holding all the class methods
base_name = \init_free_var "base", tbl
\stm {"assign", { {"chain", base_name, {"dot", "__index"}} }, { base_name }}
-- handle super class if there is one
\stm {"if", parent_loc,
{{"chain", "setmetatable", {"call",
{base_name, {"chain", "getmetatable",
{"call", {parent_loc}}, {"dot", "__index"}}}}}}}
cls_name = def_scope\free_name "class"
def_scope\add_line ("local %s = setmetatable(%s, %s)")\format(cls_name, cls, cls_mt)
def_scope\add_line ("%s.__class = %s")\format base_name, cls_name
def_scope\add_line "return", cls_name
-- the class object that is returned
cls = {"table", {
{"__init", constructor}
}}
parent_val = @value parent_val if parent_val != ""
-- the class's meta table, gives us call and access to base methods
cls_mt = {"table", {
{"__index", base_name}
{"__call", {"fndef", {"mt", "..."}, "slim", {
{"raw", ("local self = setmetatable({}, %s)")\format(base_name)}
{"chain", "mt.__init", {"call", {"self", "..."}}}
"self"
}}}
}}
def = concat {
("(function(%s)\n")\format(parent_loc)
def_scope\render()
("\nend)(%s)")\format(parent_val)
}
cls_name = \init_free_var "class", {
"chain", "setmetatable", {"call", {cls, cls_mt}}
}
@add_line "local", name
@put_name name
@stm {"assign", {name}, {def}}
\stm {"assign"
{{"chain", base_name, {"dot", "__class"}}}
{cls_name}
}
\stm {"return", cls_name}
@stm {"declare", {name}}
@line name, " = ", def_scope
comprehension: (node, action) =>
_, exp, clauses = unpack node

View File

@ -50,20 +50,27 @@ value_compile = {
return delim .. inner .. (delim_end or delim)
end,
["if"] = function(self, node)
local func = self:block()
func:stm(node, returner)
return self:format("(function()", func:render(), "end)()")
do
local _with_0 = self:block("(function()", "end)()")
_with_0:stm(node, returner)
return _with_0
end
end,
comprehension = function(self, node)
local exp = node[2]
local func = self:block()
local tmp_name = func:free_name()
func:add_line("local", tmp_name, "= {}")
local action = func:block()
action:add_line(("table.insert(%s, %s)"):format(tmp_name, func:value(exp)))
func:stm(node, action)
func:add_line("return", tmp_name)
return self:format("(function()", func:render(), "end)()")
do
local _with_0 = self:block("(function()", "end()")
local tmp_name = _with_0:init_free_var("accum", { "table" })
local action
do
local _with_1 = _with_1:block()
_with_1:stm({ "chain", "table.insert", { "call", { tmp_name, _with_1:value(exp) } } })
action = _with_1
end
_with_1:stm(node, action)
_with_1:stm({ "return", tmp_name })
return _with_0
end
end,
chain = function(self, node)
local callee = node[2]
@ -81,34 +88,37 @@ value_compile = {
chain_item = function(node)
local t, arg = unpack(node)
if t == "call" then
return "(" .. (self:values(arg)) .. ")"
return "(", self:values(arg), ")"
elseif t == "index" then
return "[" .. (self:value(arg)) .. "]"
return "[", self:value(arg), "]"
elseif t == "dot" then
return "." .. arg
return ".", arg
elseif t == "colon" then
return ":" .. arg .. (chain_item(node[3]))
return ":", arg, chain_item(node[3])
elseif t == "colon_stub" then
return error("Uncalled colon stub")
else
return error("Unknown chain action: " .. t)
end
end
local actions = (function()
local _moon_0 = {}
local actions
do
local _with_0 = self:line()
local _item_0 = node
for _index_0=3,#_item_0 do
local act = _item_0[_index_0]
table.insert(_moon_0, chain_item(act))
local action = _item_0[_index_0]
_with_0:append(chain_item(action))
end
return _moon_0
end)()
actions = _with_0
end
if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call" then
callee[1] = "self_colon"
end
local callee_value = self:name(callee)
if ntype(callee) == "exp" then
callee_value = "(" .. callee_value .. ")"
callee_value = self:line("(", callee_value, ")")
end
return self:name(callee) .. concat(actions)
return self:line(callee, actions)
end,
fndef = function(self, node)
local _, args, arrow, block = unpack(node)
@ -128,50 +138,43 @@ value_compile = {
end,
table = function(self, node)
local _, items = unpack(node)
local inner = self:block()
local _comp
_comp = function(i, tuple)
local out
if #tuple == 2 then
local key, value = unpack(tuple)
if type(key) == "string" and data.lua_keywords[key] then
key = { "string", '"', key }
end
local key_val = self:value(key)
if type(key) ~= "string" then
key = ("[%s]"):format(key_val)
do
local _with_0 = self:block("{", "}")
_with_0.delim = ","
local format_line
format_line = function(tuple)
if #tuple == 2 then
local key, value = unpack(tuple)
if type(key) == "string" and data.lua_keywords[key] then
key = { "string", '"', key }
end
local assign
if type(key) ~= "string" then
assign = self:line("[", _with_0:value(key), "]")
else
assign = key
end
_with_0:set("current_block", key)
local out = self:line(assign, " = ", _with_0:value(value))
_with_0:set("current_block", nil)
return out
else
key = key_val
return self:line(_with_0:value(tuple[1]))
end
inner:set("current_block", key_val)
value = inner:value(value)
inner:set("current_block", nil)
out = ("%s = %s"):format(key, value)
else
out = inner:value(tuple[1])
end
if i ~= #items then
return out .. ","
else
return out
if items then
local _item_0 = items
for _index_0=1,#_item_0 do
local line = _item_0[_index_0]
_with_0:add(format_line(line))
end
end
end
local values = (function()
local _moon_0 = {}
for i, v in ipairs(items) do
table.insert(_moon_0, _comp(i, v))
end
return _moon_0
end)()
if #values > 3 then
return self:format("{", values, "}")
else
return "{ " .. (concat(values, " ")) .. " }"
return _with_0
end
end,
minus = function(self, node) return "-" .. self:value(node[2]) end,
length = function(self, node) return "#" .. self:value(node[2]) end,
["not"] = function(self, node) return "not " .. self:value(node[2]) end,
minus = function(self, node) return self:line("-", self:value(node[2])) end,
length = function(self, node) return self:line("#", self:value(node[2])) end,
["not"] = function(self, node) return self:line("not ", self:value(node[2])) end,
self = function(self, node) return "self." .. self:value(node[2]) end,
self_colon = function(self, node) return "self:" .. self:value(node[2]) end
}

View File

@ -39,31 +39,28 @@ value_compile =
delim..inner..(delim_end or delim)
if: (node) =>
func = @block!
func\stm node, returner
@format "(function()", func\render!, "end)()"
with @block "(function()", "end)()"
\stm node, returner
comprehension: (node) =>
exp = node[2]
func = @block!
tmp_name = func\free_name!
func\add_line "local", tmp_name, "= {}"
with @block "(function()", "end()"
tmp_name = \init_free_var "accum", {"table"}
action = func\block!
action\add_line ("table.insert(%s, %s)")\format(tmp_name, func\value exp)
func\stm node, action
-- TODO change this to function
action = with \block!
\stm {"chain", "table.insert", {"call", {tmp_name, \value exp}}}
func\add_line "return", tmp_name
@format "(function()", func\render!, "end)()"
\stm node, action
\stm {"return", tmp_name}
chain: (node) =>
callee = node[2]
if callee == -1
callee = @get"scope_var"
if not callee then error"Short-dot syntax must be called within a with block"
callee = @get "scope_var"
if not callee then error "Short-dot syntax must be called within a with block"
sup = @get "super"
if callee == "super" and sup
@ -72,25 +69,28 @@ value_compile =
chain_item = (node) ->
t, arg = unpack node
if t == "call"
"("..(@values arg)..")"
"(", @values(arg), ")"
elseif t == "index"
"["..(@value arg).."]"
"[", @value(arg), "]"
elseif t == "dot"
"."..arg
".", arg
elseif t == "colon"
":"..arg..(chain_item node[3])
":", arg, chain_item(node[3])
elseif t == "colon_stub"
error "Uncalled colon stub"
else
error "Unknown chain action: "..t
actions = [chain_item act for act in *node[3:]]
actions = with @line!
\append chain_item action for action in *node[3:]
if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call"
callee[1] = "self_colon"
callee_value = @name callee
callee_value = "("..callee_value..")" if ntype(callee) == "exp"
callee_value = @line "(", callee_value, ")" if ntype(callee) == "exp"
return @name(callee)..concat(actions)
@line callee, actions
fndef: (node) =>
_, args, arrow, block = unpack node
@ -104,46 +104,39 @@ value_compile =
table: (node) =>
_, items = unpack node
with @block "{", "}"
.delim = ","
inner = @block! -- handle indent
_comp = (i, tuple) ->
out = if #tuple == 2
key, value = unpack tuple
format_line = (tuple) ->
if #tuple == 2
key, value = unpack tuple
if type(key) == "string" and data.lua_keywords[key]
key = {"string", '"', key}
if type(key) == "string" and data.lua_keywords[key]
key = {"string", '"', key}
key_val = @value key
key = if type(key) != "string"
("[%s]")\format key_val
assign = if type(key) != "string"
@line "[", \value(key), "]"
else
key
\set "current_block", key
out = @line assign, " = ", \value(value)
\set "current_block", nil
out
else
key_val
@line \value tuple[1]
inner\set "current_block", key_val
value = inner\value value
inner\set "current_block", nil
("%s = %s")\format key, value
else
inner\value tuple[1]
out.."," if i != #items else out
values = [_comp i,v for i,v in ipairs items]
if #values > 3
@format "{", values, "}"
else
"{ "..(concat values, " ").." }"
if items
\add format_line line for line in *items
minus: (node) =>
"-"..@value node[2]
@line "-", @value node[2]
length: (node) =>
"#"..@value node[2]
@line "#", @value node[2]
not: (node) =>
"not "..@value node[2]
@line "not ", @value node[2]
self: (node) =>
"self."..@value node[2]

1
todo
View File

@ -10,6 +10,7 @@ differentiate root block and normal block
- use `with` as an arugment to function (normal expression)
- varargs that get put in a nested generated function aren't valid anymor:
- variable declartion for classes is messed up (always local)
- class expressions, x = class extends Hello do new: => print "hello"
- add all lines through Block