From cea79554c2edceff30fe4815a3f784544f8557c3 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 30 May 2025 17:31:03 +0800 Subject: Added a new test. --- spec/inputs/props.yue | 61 +++++++++++++ spec/outputs/props.lua | 240 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 spec/inputs/props.yue create mode 100644 spec/outputs/props.lua (limited to 'spec') diff --git a/spec/inputs/props.yue b/spec/inputs/props.yue new file mode 100644 index 0000000..bbb7aae --- /dev/null +++ b/spec/inputs/props.yue @@ -0,0 +1,61 @@ +class Props + __index: (name): nil => + cls = @.<> + if item := cls.__getter?[name] -- access properties + return item @ + elseif item := rawget cls, name -- access member functions + return item + else + c = cls + while c := c.<> -- recursive to access base classes + if item := c.__getter?[name] + cls.__getter ??= {} + cls.__getter[name] = item -- cache base properties to class + return item @ + elseif item := rawget c, name + rawset cls, name, item -- cache base member to class + return item + + __newindex: (name, value) => + cls = @.<> + if item := cls.__setter?[name] -- access properties + item @, value + else + c = cls + while c := c.<> -- recursive to access base classes + if item := c.__setter?[name] + cls.__setter ??= {} + cls.__setter[name] = item -- cache base property to class + item @, value + return + rawset @, name, value -- assign field to self + + assignReadOnly = -> error "assigning a readonly property" + + prop: (name, props) => + { + :get + :set = assignReadOnly + } = props + if getter := rawget @__base, "__getter" + getter[name] = get + else + rawset @__base, "__getter", [name]: get + if setter := rawget @__base, "__setter" + setter[name] = set + else + rawset @__base, "__setter", [name]: set + +class A extends Props + @prop 'x' + get: => @_x + 1000 + set: (v) => @_x = v + new: => + @_x = 0 + +class B extends A + @prop 'abc', get: => "hello" + +b = B! +b.x = 999 +print b.x, b.abc diff --git a/spec/outputs/props.lua b/spec/outputs/props.lua new file mode 100644 index 0000000..2c282e0 --- /dev/null +++ b/spec/outputs/props.lua @@ -0,0 +1,240 @@ +local Props +do + local _class_0 + local assignReadOnly + local _base_0 = { + __index = function(self, name) + local cls = getmetatable(self) + do + local item + do + local _obj_0 = cls.__getter + if _obj_0 ~= nil then + item = _obj_0[name] + end + end + if item then + return item(self) + else + item = rawget(cls, name) + if item then + return item + else + local c = cls + repeat + c = getmetatable(c) + if c then + local _obj_0 = c.__getter + if _obj_0 ~= nil then + item = _obj_0[name] + end + if item then + if cls.__getter == nil then + cls.__getter = { } + end + cls.__getter[name] = item + return item(self) + else + item = rawget(c, name) + if item then + rawset(cls, name, item) + return item + end + end + else + break + end + until false + end + end + end + return nil + end, + __newindex = function(self, name, value) + local cls = getmetatable(self) + local item + local _obj_0 = cls.__setter + if _obj_0 ~= nil then + item = _obj_0[name] + end + if item then + return item(self, value) + else + local c = cls + repeat + c = getmetatable(c) + if c then + local _obj_1 = c.__setter + if _obj_1 ~= nil then + item = _obj_1[name] + end + if item then + if cls.__setter == nil then + cls.__setter = { } + end + cls.__setter[name] = item + item(self, value) + return + end + else + break + end + until false + return rawset(self, name, value) + end + end, + prop = function(self, name, props) + local get, set = props.get, props.set + if set == nil then + set = assignReadOnly + end + do + local getter = rawget(self.__base, "__getter") + if getter then + getter[name] = get + else + rawset(self.__base, "__getter", { + [name] = get + }) + end + end + local setter = rawget(self.__base, "__setter") + if setter then + setter[name] = set + else + return rawset(self.__base, "__setter", { + [name] = set + }) + end + end + } + if _base_0.__index == nil then + _base_0.__index = _base_0 + end + _class_0 = setmetatable({ + __init = function() end, + __base = _base_0, + __name = "Props" + }, { + __index = _base_0, + __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; + assignReadOnly = function() + return error("assigning a readonly property") + end + Props = _class_0 +end +local A +do + local _class_0 + local _parent_0 = Props + local _base_0 = { } + for _key_0, _val_0 in pairs(_parent_0.__base) do + if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then + _base_0[_key_0] = _val_0 + end + end + if _base_0.__index == nil then + _base_0.__index = _base_0 + end + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self) + self._x = 0 + end, + __base = _base_0, + __name = "A", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + 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; + self:prop('x', { + get = function(self) + return self._x + 1000 + end, + set = function(self, v) + self._x = v + end + }) + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + A = _class_0 +end +local B +do + local _class_0 + local _parent_0 = A + local _base_0 = { } + for _key_0, _val_0 in pairs(_parent_0.__base) do + if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then + _base_0[_key_0] = _val_0 + end + end + if _base_0.__index == nil then + _base_0.__index = _base_0 + end + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, ...) + return _class_0.__parent.__init(self, ...) + end, + __base = _base_0, + __name = "B", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + 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; + self:prop('abc', { + get = function(self) + return "hello" + end + }) + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + B = _class_0 +end +local b = B() +b.x = 999 +return print(b.x, b.abc) -- cgit v1.2.3-55-g6feb