1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
|