aboutsummaryrefslogtreecommitdiff
path: root/spec/inputs/props.yue
blob: bbb7aaecddbada4b1b4462bf653359cd6c8b44e7 (plain)
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