From 67a59a9622699ed6cc69aa877e2330c6005089b1 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Wed, 15 Jun 2011 22:41:17 -0700 Subject: [PATCH] class inheritance --- moonscript/compile/line.lua | 16 ++++++++++++++-- moonscript/compile/line.moon | 21 ++++++++++++++++----- moonscript/parse.lua | 3 +-- tests/inputs/class.moon | 8 ++++++++ tests/outputs/class.lua | 27 +++++++++++++++++++++++++-- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/moonscript/compile/line.lua b/moonscript/compile/line.lua index 1c4951f..c658b77 100644 --- a/moonscript/compile/line.lua +++ b/moonscript/compile/line.lua @@ -209,7 +209,7 @@ line_compile = { return nil end, ["class"] = function(self, node) - local _, name, tbl = unpack(node) + local _, name, parent, tbl = unpack(node) local constructor = nil local final_properties = { } local find_special @@ -277,8 +277,20 @@ line_compile = { "slim", { { "raw", ("local self = setmetatable({}, %s)"):format(base_name) }, { "chain", "mt.__init", { "call", { "self", "..." } } }, "self" } } } } }) + local parent_var = def_scope:free_name("parent") + if parent ~= "" then + def_scope:stm({ "if", parent_var, { { "chain", "setmetatable", { "call", { base_name, { + "chain", + "getmetatable", + { "call", { parent_var } }, + { "dot", "__index" } + } } } } } }) + end def_scope:add_line(("return setmetatable(%s, %s)"):format(cls, cls_mt)) - local def = concat({ "(function()\n", (def_scope:render()), "\nend)()" }) + if parent ~= "" then + parent = self:value(parent) + end + local def = concat({ ("(function(%s)\n"):format(parent_var), (def_scope:render()), ("\nend)(%s)"):format(parent) }) return self:stm({ "assign", { name }, { def } }) end, comprehension = function(self, node, action) diff --git a/moonscript/compile/line.moon b/moonscript/compile/line.moon index 92f54ca..1803127 100644 --- a/moonscript/compile/line.moon +++ b/moonscript/compile/line.moon @@ -161,7 +161,7 @@ line_compile = nil ["class"]: (node) => - _, name, tbl = unpack node + _, name, parent, tbl = unpack node constructor = nil final_properties = {} @@ -195,9 +195,6 @@ line_compile = dests = [{"self", name} for name in *self_args] 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"} - def_scope = @block() base_name = def_scope:free_name "base" def_scope:add_line ("local %s ="):format(base_name), def_scope:value tbl @@ -216,9 +213,23 @@ line_compile = }}} }} + parent_var = def_scope:free_name "parent" + if parent != "" + def_scope:stm {"if", parent_var, + {{"chain", "setmetatable", {"call", + {base_name, {"chain", "getmetatable", + {"call", {parent_var}}, {"dot", "__index"}}}}}}} + def_scope:add_line ("return setmetatable(%s, %s)"):format(cls, cls_mt) - def = concat { "(function()\n", (def_scope:render()), "\nend)()" } + parent = @value parent if parent != "" + + def = concat { + ("(function(%s)\n"):format(parent_var) + (def_scope:render()) + ("\nend)(%s)"):format(parent) + } + @stm {"assign", {name}, {def}} comprehension: (node, action) => diff --git a/moonscript/parse.lua b/moonscript/parse.lua index b8d2cc6..c97fcf5 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -340,8 +340,7 @@ local build_grammar = wrap(function() TableBlock = Break * #Cmt(Indent, advance_indent) * TableBlockInner * OutBlock / mark"table", - ClassDecl = key"class" * Name * (key"extends" * Name)^-1 * TableBlock / mark"class", - + ClassDecl = key"class" * Name * (key"extends" * Exp + C"")^-1 * TableBlock / mark"class", Export = key"export" * Ct(NameList) / mark"export", KeyValue = Ct((Name + sym"[" * Exp * sym"]") * symx":" * (Exp + TableBlock)), diff --git a/tests/inputs/class.moon b/tests/inputs/class.moon index 13fe15c..5f72889 100644 --- a/tests/inputs/class.moon +++ b/tests/inputs/class.moon @@ -11,4 +11,12 @@ x:hello() print x +class Simple + cool: => print "cool" + +class Yikes extends Simple + new: => print "created hello" + +x = Yikes() +x:cool() diff --git a/tests/outputs/class.lua b/tests/outputs/class.lua index 44421f4..c054659 100644 --- a/tests/outputs/class.lua +++ b/tests/outputs/class.lua @@ -1,4 +1,4 @@ -local Hello = (function() +local Hello = (function(_parent_0) local _base_0 = { hello = function(self) return print(self.test, self.world) end, __tostring = function(self) return "hello world" end } _base_0.__index = _base_0 return setmetatable({ __init = function(self, test, world) @@ -12,4 +12,27 @@ local Hello = (function() end)() local x = Hello(1, 2) x:hello() -print(x) \ No newline at end of file +print(x) +local Simple = (function(_parent_0) + local _base_0 = { cool = function(self) return print("cool") end } + _base_0.__index = _base_0 + return setmetatable({ __init = function(self) end }, { __index = _base_0, __call = function(mt, ...) + local self = setmetatable({}, _base_0) + mt.__init(self, ...) + return self + end }) +end)() +local Yikes = (function(_parent_0) + local _base_0 = { } + _base_0.__index = _base_0 + if _parent_0 then + setmetatable(_base_0, getmetatable(_parent_0).__index) + end + return setmetatable({ __init = function(self) return print("created hello") end }, { __index = _base_0, __call = function(mt, ...) + local self = setmetatable({}, _base_0) + mt.__init(self, ...) + return self + end }) +end)(Simple) +x = Yikes() +x:cool() \ No newline at end of file