diff --git a/moonscript/transform.lua b/moonscript/transform.lua index 810bf7b..ec6c49d 100644 --- a/moonscript/transform.lua +++ b/moonscript/transform.lua @@ -638,12 +638,69 @@ Statement = Transformer({ { "__init", 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({ { "__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", @@ -779,16 +836,10 @@ Statement = Transformer({ { base_name, _with_0.chain({ - base = "getmetatable", - { - "call", - { - parent_cls_name - } - }, + base = parent_cls_name, { "dot", - "__index" + "__base" } }) } diff --git a/moonscript/transform.moon b/moonscript/transform.moon index 4070586..91ba544 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -353,10 +353,30 @@ Statement = Transformer { cls = build.table { {"__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 { - {"__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 { args: {{"cls"}, {"..."}} body: { @@ -421,11 +441,10 @@ Statement = Transformer { then: { .chain { base: "setmetatable" - {"call", {base_name, .chain { - base: "getmetatable" - {"call", {parent_cls_name}} - {"dot", "__index"} - }}} + {"call", { + base_name, + .chain { base: parent_cls_name, {"dot", "__base"}} + }} } } } diff --git a/tests/outputs/class.lua b/tests/outputs/class.lua index b601e4e..a8c9d32 100644 --- a/tests/outputs/class.lua +++ b/tests/outputs/class.lua @@ -11,15 +11,25 @@ Hello = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, test, world) self.test, self.world = test, world 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -42,16 +52,26 @@ Simple = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -67,14 +87,24 @@ Yikes = (function() local _base_0 = { } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -96,14 +126,24 @@ Hi = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -122,14 +162,24 @@ Simple = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -150,16 +200,26 @@ Okay = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -181,16 +241,26 @@ Biggie = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -210,16 +280,26 @@ Yeah = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -239,16 +319,26 @@ What = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -274,16 +364,26 @@ Hello = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) @@ -315,16 +415,26 @@ CoolSuper = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) diff --git a/tests/outputs/export.lua b/tests/outputs/export.lua index be0be64..a7de1b2 100644 --- a/tests/outputs/export.lua +++ b/tests/outputs/export.lua @@ -7,16 +7,26 @@ Something = (function() } _base_0.__index = _base_0 if _parent_0 then - setmetatable(_base_0, getmetatable(_parent_0).__index) + setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) 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, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...)