new class system

This commit is contained in:
leaf corcoran 2011-06-15 08:52:01 -07:00
parent 858608a04d
commit 65fdf7e6b2
4 changed files with 59 additions and 45 deletions

View File

@ -210,21 +210,12 @@ line_compile = {
end, end,
["class"] = function(self, node) ["class"] = function(self, node)
local _, name, tbl = unpack(node) local _, name, tbl = unpack(node)
local mt_name = "_" .. name .. "_mt"
self:add_line("local", concat(self:declare({ name, mt_name }), ", "))
local constructor = nil local constructor = nil
local meta_methods = { }
local final_properties = { } local final_properties = { }
local overloaded_index = value
local find_special local find_special
find_special = function(name, value) find_special = function(name, value)
if name == constructor_name then if name == constructor_name then
constructor = value constructor = value
elseif name:match("^__%a") then
insert(meta_methods, { name, value })
if name == "__index" then
overloaded_index = value
end
else else
return insert(final_properties, { name, value }) return insert(final_properties, { name, value })
end end
@ -234,15 +225,12 @@ line_compile = {
local entry = _item_0[_index_0] local entry = _item_0[_index_0]
find_special(unpack(entry)) find_special(unpack(entry))
end end
if not overloaded_index then tbl[2] = final_properties
insert(meta_methods, { "__index", { "table", final_properties } })
end
self:stm({ "assign", { mt_name }, { { "table", meta_methods } } })
if not constructor then if not constructor then
constructor = { constructor = {
"fndef", "fndef",
{ }, { },
"slim", "fat",
{ } { }
} }
end end
@ -264,7 +252,7 @@ line_compile = {
end end
return _moon_0 return _moon_0
end)() end)()
constructor[3] = "slim" constructor[3] = "fat"
local body = constructor[4] local body = constructor[4]
local dests = (function() local dests = (function()
local _moon_0 = {} local _moon_0 = {}
@ -278,9 +266,20 @@ line_compile = {
if #self_args > 0 then if #self_args > 0 then
insert(body, 1, { "assign", dests, self_args }) insert(body, 1, { "assign", dests, self_args })
end end
insert(body, 1, { "raw", ("local self = setmetatable({}, %s)"):format(mt_name) }) local def_scope = self:block()
insert(body, { "return", "self" }) local base_name = def_scope:free_name("base")
return self:stm({ "assign", { name }, { constructor } }) 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" }
} } } })
def_scope:add_line(("return setmetatable(%s, %s)"):format(cls, cls_mt))
local def = concat({ "(function()\n", (def_scope:render()), "\nend)()" })
return self:stm({ "assign", { name }, { def } })
end, end,
comprehension = function(self, node, action) comprehension = function(self, node, action)
local _, exp, clauses = unpack(node) local _, exp, clauses = unpack(node)

View File

@ -162,35 +162,24 @@ line_compile =
["class"]: (node) => ["class"]: (node) =>
_, name, tbl = unpack node _, name, tbl = unpack node
mt_name = "_"..name.."_mt"
@add_line "local", concat @declare({ name, mt_name }), ", "
constructor = nil constructor = nil
meta_methods = {}
final_properties = {} final_properties = {}
overloaded_index = value
find_special = (name, value) -> find_special = (name, value) ->
if name == constructor_name if name == constructor_name
constructor = value constructor = value
elseif name:match("^__%a")
insert meta_methods, {name, value}
overloaded_index = value if name == "__index"
else else
insert final_properties, {name, value} insert final_properties, {name, value}
find_special unpack entry for entry in *tbl[2] find_special unpack entry for entry in *tbl[2]
tbl[2] = final_properties
if not overloaded_index
insert meta_methods, {"__index", {"table", final_properties}}
@stm {"assign", {mt_name}, {{"table", meta_methods}}}
-- synthesize constructor -- synthesize constructor
if not constructor if not constructor
constructor = {"fndef", {}, "slim", {}} constructor = {"fndef", {}, "fat", {}}
-- organize constructor
-- extract self arguments -- extract self arguments
self_args = {} self_args = {}
get_initializers = (arg) -> get_initializers = (arg) ->
@ -200,15 +189,37 @@ line_compile =
arg arg
constructor[2] = [get_initializers arg for arg in *constructor[2]] constructor[2] = [get_initializers arg for arg in *constructor[2]]
constructor[3] = "slim" constructor[3] = "fat"
body = constructor[4] body = constructor[4]
dests = [{"self", name} for name in *self_args] dests = [{"self", name} for name in *self_args]
insert body, 1, {"assign", dests, self_args} if #self_args > 0 insert body, 1, {"assign", dests, self_args} if #self_args > 0
insert body, 1, {"raw", ("local self = setmetatable({}, %s)"):format(mt_name)}
insert body, {"return", "self"}
@stm {"assign", {name}, {constructor}} -- insert body, 1, {"raw", ("local self = setmetatable({}, %s)"):format(mt_name)}
-- insert body, {"return", "self"}
def_scope = @block()
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)
cls = def_scope:value {"table", {
{"__init", constructor}
}}
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"
}}}
}}
def_scope:add_line ("return setmetatable(%s, %s)"):format(cls, cls_mt)
def = concat { "(function()\n", (def_scope:render()), "\nend)()" }
@stm {"assign", {name}, {def}}
comprehension: (node, action) => comprehension: (node, action) =>
_, exp, clauses = unpack node _, exp, clauses = unpack node

View File

@ -340,7 +340,7 @@ local build_grammar = wrap(function()
TableBlock = Break * #Cmt(Indent, advance_indent) * TableBlockInner * OutBlock / mark"table", TableBlock = Break * #Cmt(Indent, advance_indent) * TableBlockInner * OutBlock / mark"table",
ClassDecl = key"class" * Name * TableBlock / mark"class", ClassDecl = key"class" * Name * (key"extends" * Name)^-1 * TableBlock / mark"class",
Export = key"export" * Ct(NameList) / mark"export", Export = key"export" * Ct(NameList) / mark"export",

View File

@ -1,11 +1,15 @@
local Hello, _Hello_mt local Hello = (function()
_Hello_mt = { __tostring = function(self) return "hello world" end, __index = { hello = function(self) return print(self.test, self.world) end } } local _base_0 = { hello = function(self) return print(self.test, self.world) end, __tostring = function(self) return "hello world" end }
Hello = function(test, world) _base_0.__index = _base_0
local self = setmetatable({}, _Hello_mt) return setmetatable({ __init = function(self, test, world)
self.test, self.world = test, world self.test, self.world = test, world
print("creating object..") return print("creating object..")
return self end }, { __index = _base_0, __call = function(mt, ...)
end local self = setmetatable({}, _base_0)
mt.__init(self, ...)
return self
end })
end)()
local x = Hello(1, 2) local x = Hello(1, 2)
x:hello() x:hello()
print(x) print(x)