From 021d4878a0df427f5a87f17530cc1778a44bcb48 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Wed, 31 Oct 2012 00:07:59 -0700 Subject: [PATCH] class name can be any assignable expression #46 --- moonscript/parse.lua | 2 +- moonscript/transform.lua | 52 +++++++++++----- moonscript/transform.moon | 23 +++++-- tests/inputs/class.moon | 14 +++++ tests/outputs/class.lua | 122 +++++++++++++++++++++++++++++++++++++- 5 files changed, 191 insertions(+), 22 deletions(-) diff --git a/moonscript/parse.lua b/moonscript/parse.lua index f736f63..7598737 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -507,7 +507,7 @@ local build_grammar = wrap_env(function() TableBlockInner = Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0), TableBlock = SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table", - ClassDecl = key"class" * Name * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * ClassBlock / mark"class", + ClassDecl = key"class" * Assignable * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * ClassBlock / mark"class", ClassBlock = SpaceBreak^1 * Advance * Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent, diff --git a/moonscript/transform.lua b/moonscript/transform.lua index 8842196..e055c47 100644 --- a/moonscript/transform.lua +++ b/moonscript/transform.lua @@ -954,6 +954,28 @@ Statement = Transformer({ smart_node(constructor) constructor.arrow = "fat" end + local real_name + if ntype(name) == "chain" then + local last = name[#name] + local _exp_0 = ntype(last) + if "dot" == _exp_0 then + real_name = { + "string", + '"', + last[2] + } + elseif "index" == _exp_0 then + real_name = last[2] + else + real_name = "nil" + end + else + real_name = { + "string", + '"', + name + } + end local cls = build.table({ { "__init", @@ -965,11 +987,7 @@ Statement = Transformer({ }, { "__name", - { - "string", - '"', - name - } + real_name }, { "__parent", @@ -1197,21 +1215,25 @@ Statement = Transformer({ }) } }), - _with_0.assign_one(name, cls_name) + _with_0.assign_one(name, cls_name), + (function() + if ret then + return ret(cls_name) + end + end)() } hoist_declarations(out_body) value = _with_0.group({ - _with_0.declare({ - names = { - name - } - }), - _with_0["do"](out_body), (function() - if ret then - return ret(name) + if ntype(name) == "value" then + return _with_0.declare({ + names = { + name + } + }) end - end)() + end)(), + _with_0["do"](out_body) }) end return value diff --git a/moonscript/transform.moon b/moonscript/transform.moon index 21168c7..5e27aaa 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -488,10 +488,22 @@ Statement = Transformer { smart_node constructor constructor.arrow = "fat" + real_name = if ntype(name) == "chain" + last = name[#name] + switch ntype last + when "dot" + {"string", '"', last[2]} + when "index" + last[2] + else + "nil" + else + {"string", '"', name} + cls = build.table { {"__init", constructor} {"__base", base_name} - {"__name", {"string", '"', name}} -- "quote the string" + {"__name", real_name} -- "quote the string" {"__parent", parent_cls_name} } @@ -610,16 +622,17 @@ Statement = Transformer { } .assign_one name, cls_name + if ret + ret cls_name } hoist_declarations out_body value = .group { - .declare names: {name} - .do out_body + if ntype(name) == "value" + .declare names: {name} - if ret - ret name + .do out_body } value diff --git a/tests/inputs/class.moon b/tests/inputs/class.moon index 1677468..4b2e48c 100644 --- a/tests/inputs/class.moon +++ b/tests/inputs/class.moon @@ -133,3 +133,17 @@ yyy = -> class Cool nil + +-- + +class a.b.c.D + nil + + +class a.b["hello"] + nil + +class (-> require "moon")!.Something extends Hello.World + nil + + diff --git a/tests/outputs/class.lua b/tests/outputs/class.lua index efadb79..18eb968 100644 --- a/tests/outputs/class.lua +++ b/tests/outputs/class.lua @@ -631,6 +631,126 @@ yyy = function() _parent_0.__inherited(_parent_0, _class_0) end Cool = _class_0 + return _class_0 end - return Cool +end +do + local _parent_0 = nil + local _base_0 = { } + _base_0.__index = _base_0 + if _parent_0 then + 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, + __base = _base_0, + __name = "D", + __parent = _parent_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, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + _ = nil + if _parent_0 and _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + a.b.c.D = _class_0 +end +do + local _parent_0 = nil + local _base_0 = { } + _base_0.__index = _base_0 + if _parent_0 then + 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, + __base = _base_0, + __name = "hello", + __parent = _parent_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, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + _ = nil + if _parent_0 and _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + a.b["hello"] = _class_0 +end +do + local _parent_0 = Hello.World + local _base_0 = { } + _base_0.__index = _base_0 + if _parent_0 then + 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, + __base = _base_0, + __name = "Something", + __parent = _parent_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, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + _ = nil + if _parent_0 and _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + (function() + return require("moon") + end)().Something = _class_0 + return _class_0 end \ No newline at end of file