class level inheritance, changed class representation slightly

Looking up a class property will now search the parent class properties
if parent exists

Classes have a few more built in properties:

  * __name holds the name of the class as it was defined as a string
  * __base holds the instance metatable as it was defined (not dynamic)
  * __parent holds the class's parent class if it exists (not dynamic)

The way class inheritance is handled was CHANGED (uses __base instead of
looking at __index of parents metatable). Make sure you recompile all
your code if using class inheritance because old classes won't work with
new ones.
This commit is contained in:
leaf corcoran 2011-12-03 19:17:06 -08:00
parent e55fa25e6e
commit d1059b8f98
4 changed files with 241 additions and 51 deletions

View File

@ -638,12 +638,69 @@ Statement = Transformer({
{ {
"__init", "__init",
constructor constructor
},
{
"__base",
base_name
},
{
"__name",
{
"string",
'"',
name
}
},
{
"__parent",
parent_cls_name
}
})
local class_lookup = build["if"]({
cond = {
"exp",
"val",
"==",
"nil",
"and",
parent_cls_name
},
["then"] = {
parent_cls_name:index("name")
}
})
insert(class_lookup, {
"else",
{
"val"
} }
}) })
local cls_mt = build.table({ local cls_mt = build.table({
{ {
"__index", "__index",
base_name build.fndef({
args = {
{
"cls"
},
{
"name"
}
},
body = {
build.assign_one(LocalName("val"), build.chain({
base = "rawget",
{
"call",
{
base_name,
"name"
}
}
})),
class_lookup
}
})
}, },
{ {
"__call", "__call",
@ -779,16 +836,10 @@ Statement = Transformer({
{ {
base_name, base_name,
_with_0.chain({ _with_0.chain({
base = "getmetatable", base = parent_cls_name,
{
"call",
{
parent_cls_name
}
},
{ {
"dot", "dot",
"__index" "__base"
} }
}) })
} }

View File

@ -353,10 +353,30 @@ Statement = Transformer {
cls = build.table { cls = build.table {
{"__init", constructor} {"__init", constructor}
{"__base", base_name}
{"__name", {"string", '"', name}} -- "quote the string"
{"__parent", parent_cls_name}
} }
-- look up a name in the class object
class_lookup = build["if"] {
cond: {"exp", "val", "==", "nil", "and", parent_cls_name}
then: {
parent_cls_name\index"name"
}
}
insert class_lookup, {"else", {"val"}}
cls_mt = build.table { cls_mt = build.table {
{"__index", base_name} {"__index", build.fndef {
args: {{"cls"}, {"name"}}
body: {
build.assign_one LocalName"val", build.chain {
base: "rawget", {"call", {base_name, "name"}}
}
class_lookup
}
}}
{"__call", build.fndef { {"__call", build.fndef {
args: {{"cls"}, {"..."}} args: {{"cls"}, {"..."}}
body: { body: {
@ -421,11 +441,10 @@ Statement = Transformer {
then: { then: {
.chain { .chain {
base: "setmetatable" base: "setmetatable"
{"call", {base_name, .chain { {"call", {
base: "getmetatable" base_name,
{"call", {parent_cls_name}} .chain { base: parent_cls_name, {"dot", "__base"}}
{"dot", "__index"} }}
}}}
} }
} }
} }

View File

@ -11,15 +11,25 @@ Hello = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, test, world) __init = function(self, test, world)
self.test, self.world = test, world self.test, self.world = test, world
return print("creating object..") return print("creating object..")
end end,
__base = _base_0,
__name = "Hello",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -42,16 +52,26 @@ Simple = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Simple",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -67,14 +87,24 @@ Yikes = (function()
local _base_0 = { } local _base_0 = { }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self) __init = function(self)
return print("created hello") return print("created hello")
end end,
__base = _base_0,
__name = "Yikes",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -96,14 +126,24 @@ Hi = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, arg) __init = function(self, arg)
return print("init arg", arg) return print("init arg", arg)
end end,
__base = _base_0,
__name = "Hi",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -122,14 +162,24 @@ Simple = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self) __init = function(self)
return _parent_0.__init(self, "man") return _parent_0.__init(self, "man")
end end,
__base = _base_0,
__name = "Simple",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -150,16 +200,26 @@ Okay = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Okay",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -181,16 +241,26 @@ Biggie = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Biggie",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -210,16 +280,26 @@ Yeah = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Yeah",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -239,16 +319,26 @@ What = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "What",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -274,16 +364,26 @@ Hello = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Hello",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)
@ -315,16 +415,26 @@ CoolSuper = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "CoolSuper",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)

View File

@ -7,16 +7,26 @@ Something = (function()
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
if _parent_0 then if _parent_0 then
setmetatable(_base_0, getmetatable(_parent_0).__index) setmetatable(_base_0, _parent_0.__base)
end end
local _class_0 = setmetatable({ local _class_0 = setmetatable({
__init = function(self, ...) __init = function(self, ...)
if _parent_0 then if _parent_0 then
return _parent_0.__init(self, ...) return _parent_0.__init(self, ...)
end end
end end,
__base = _base_0,
__name = "Something",
__parent = _parent_0
}, { }, {
__index = _base_0, __index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil and _parent_0 then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...) __call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...) cls.__init(_self_0, ...)