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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
describe "metatable", ->
it "should get metatable with <> syntax", ->
obj = setmetatable {value: 42}, {__index: {extra: "data"}}
mt = obj.<>
assert.is_true mt ~= nil
it "should set metatable with <>", ->
obj = {}
obj.<> = {__index: {value: 100}}
assert.same obj.value, 100
it "should access metatable with <>", ->
obj = setmetatable {}, {__index: {value: 50}}
result = obj.<>.__index.value
assert.same result, 50
it "should work with <index> metamethod", ->
obj = setmetatable {}, {
__index: (self, key) ->
if key == "computed"
return "computed_value"
}
assert.same obj.computed, "computed_value"
it "should work with <newindex> metamethod", ->
obj = setmetatable {}, {
__newindex: (self, key, value) ->
rawset self, "stored_" .. key, value
}
obj.test = 123
assert.same obj.stored_test, 123
it "should work with <add> metamethod", ->
obj = setmetatable({value: 10}, {
__add: (a, b) -> a.value + b.value
})
obj2 = setmetatable({value: 20}, {
__add: (a, b) -> a.value + b.value
})
result = obj + obj2
assert.same result, 30
it "should work with <call> metamethod", ->
obj = setmetatable {}, {
__call: (self, x) -> x * 2
}
result = obj 5
assert.same result, 10
it "should work with <tostring> metamethod", ->
obj = setmetatable {value: 42}, {
__tostring: (self) -> "Value: #{self.value}"
}
result = tostring obj
assert.same result, "Value: 42"
it "should work with <eq> metamethod", ->
obj1 = setmetatable({id: 1}, {
__eq: (a, b) -> a.id == b.id
})
obj2 = setmetatable({id: 1}, {
__eq: (a, b) -> a.id == b.id
})
assert.is_true obj1 == obj2
it "should destructure metatable", ->
obj = setmetatable {}, {
new: -> "new result"
update: -> "update result"
}
{:new, :update} = obj.<>
assert.is_true type(new) == "function"
assert.is_true type(update) == "function"
it "should check if two objects have same metatable", ->
mt = {value: 100}
obj1 = setmetatable {}, mt
obj2 = setmetatable {}, mt
assert.is_true obj1.<> == obj2.<>
it "should work with <concat> metamethod", ->
obj = setmetatable {value: "hello"}, {
__concat: (a, b) -> a.value .. b
}
result = obj .. " world"
assert.same result, "hello world"
|