use relative reference to parent class instead of closure

This commit is contained in:
leaf corcoran 2015-11-19 18:01:22 -08:00
parent 24b3a86c68
commit 11f0b022c4
3 changed files with 102 additions and 11 deletions

View File

@ -638,7 +638,7 @@ do
__init = function(self, options) __init = function(self, options)
self.options = options self.options = options
self.root = self self.root = self
return _parent_0.__init(self) return self.__class.__parent.__init(self)
end, end,
__base = _base_0, __base = _base_0,
__name = "RootBlock", __name = "RootBlock",
@ -647,7 +647,10 @@ do
__index = function(cls, name) __index = function(cls, name)
local val = rawget(_base_0, name) local val = rawget(_base_0, name)
if val == nil then if val == nil then
return _parent_0[name] local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else else
return val return val
end end

View File

@ -612,7 +612,25 @@ Statement = Transformer {
class_lookup = build["if"] { class_lookup = build["if"] {
cond: { "exp", {"ref", "val"}, "==", "nil" } cond: { "exp", {"ref", "val"}, "==", "nil" }
then: { then: {
parent_cls_name\index"name" build.assign_one LocalName"parent", build.chain {
base: "rawget"
{
"call", {
{"ref", "cls"}
{"string", '"', "__parent"}
}
}
}
build.if {
cond: LocalName "parent"
then: {
build.chain {
base: LocalName "parent"
{"index", "name"}
}
}
}
} }
} }
insert class_lookup, {"else", {"val"}} insert class_lookup, {"else", {"val"}}
@ -660,14 +678,21 @@ Statement = Transformer {
@put_name name if name @put_name name if name
@set "super", (block, chain) -> @set "super", (block, chain) ->
relative_parent = {
"chain",
"self"
{"dot", "__class"}
{"dot", "__parent"}
}
if chain if chain
chain_tail = { unpack chain, 3 } chain_tail = { unpack chain, 3 }
new_chain = {"chain", parent_cls_name}
head = chain_tail[1] head = chain_tail[1]
if head == nil if head == nil
return parent_cls_name return relative_parent
new_chain = relative_parent
switch head[1] switch head[1]
-- calling super, inject calling name and self into chain -- calling super, inject calling name and self into chain
@ -702,7 +727,7 @@ Statement = Transformer {
new_chain new_chain
else else
parent_cls_name relative_parent
{"declare_glob", "*"} {"declare_glob", "*"}

View File

@ -19,8 +19,7 @@ describe "class", ->
instance = Thing! instance = Thing!
assert.same instance\get_color!, "blue" assert.same instance\get_color!, "blue"
it "should have base properies from class", ->
it "should have class property", ->
class Thing class Thing
color: "blue" color: "blue"
get_color: => @color get_color: => @color
@ -54,7 +53,6 @@ describe "class", ->
assert.same instance.property, "name" assert.same instance.property, "name"
assert.same instance.name, "the_thing" assert.same instance.name, "the_thing"
it "should call super method", -> it "should call super method", ->
class Base class Base
_count: 111 _count: 111
@ -66,6 +64,18 @@ describe "class", ->
instance = Thing! instance = Thing!
assert.same instance\counter!, "00000111" assert.same instance\counter!, "00000111"
it "should call other method from super", ->
class Base
_count: 111
counter: =>
@_count
class Thing extends Base
other_method: => super\counter!
instance = Thing!
assert.same instance\other_method!, 111
it "should get super class", -> it "should get super class", ->
class Base class Base
class Thing extends Base class Thing extends Base
@ -102,7 +112,6 @@ describe "class", ->
Thing = class Thing = class
assert.same Thing.__name, "Thing" assert.same Thing.__name, "Thing"
it "should not expose class properties on instance", -> it "should not expose class properties on instance", ->
class Thing class Thing
@height: 10 @height: 10
@ -135,3 +144,57 @@ describe "class", ->
instance = Thing! instance = Thing!
instance\go! instance\go!
it "should have class properies take precedence over base properties", ->
class Thing
@prop: "hello"
prop: "world"
assert.same "hello", Thing.prop
it "class properties take precedence in super class over base", ->
class Thing
@prop: "hello"
prop: "world"
class OtherThing extends Thing
assert.same "hello", OtherThing.prop
it "gets value from base in super class", ->
class Thing
prop: "world"
class OtherThing extends Thing
assert.same "world", OtherThing.prop
it "should let parent be replaced on class", ->
class A
@prop: "yeah"
cool: => 1234
plain: => "a"
class B
@prop: "okay"
cool: => 9999
plain: => "b"
class Thing extends A
cool: =>
super! + 1
get_super: =>
super
instance = Thing!
assert.same "a", instance\plain!
assert.same 1235, instance\cool!
assert A == instance\get_super!, "expected super to be B"
Thing.__parent = B
setmetatable Thing.__base, B.__base
assert.same "b", instance\plain!
assert.same 10000, instance\cool!
assert B == instance\get_super!, "expected super to be B"