OILS / spec / ysh-object.test.sh View on Github | oilshell.org

263 lines, 121 significant
1## our_shell: ysh
2## oils_failures_allowed: 1
3
4#### Object() creates prototype chain
5
6func Rect_area(this) {
7 return (this.x * this.y)
8}
9
10var Rect = Object(null, {area: Rect_area})
11
12var rect1 = Object(Rect, {x: 3, y: 4})
13var rect2 = Object(Rect, {x: 10, y: 20})
14
15# This could change to show the object?
16# pp test_ (rect)
17
18# TODO: This should be a bound function
19#pp asdl_ (rect)
20#pp (rect.area)
21#pp (rect->area)
22
23var area1 = rect1.area()
24var area2 = rect2.area()
25
26pp test_ ([rect1.x, rect1.y])
27echo "area1 = $area1"
28
29pp test_ ([rect2.x, rect2.y])
30echo "area2 = $area2"
31
32#pp test_ (rect1.nonexistent)
33
34## STDOUT:
35(List) [3,4]
36area1 = 12
37(List) [10,20]
38area2 = 200
39## END
40
41#### prototype()
42
43func Rect_area(this) {
44 return (this.x * this.y)
45}
46
47var Rect = Object(null, {area: Rect_area})
48
49var obj = Object(Rect, {x: 3, y: 4})
50
51pp test_ (prototype(Rect))
52pp test_ (prototype(obj))
53
54## STDOUT:
55(Null) null
56(Obj) ("area":<Func>)
57## END
58
59#### propView()
60
61var obj = Object(null, {x: 3, y: 4})
62var props = propView(obj)
63
64pp test_ (props)
65
66# object can be mutated
67setvar props.x = 99
68
69pp test_ (props)
70
71var e = propView(null) # error
72
73## status: 3
74## STDOUT:
75(Dict) {"x":3,"y":4}
76(Dict) {"x":99,"y":4}
77## END
78
79#### Mutating method lookup with ->
80
81func inc(self, n) {
82 setvar self.i += n
83}
84var Counter_methods = Object(null, {'M/inc': inc})
85
86var c = Object(Counter_methods, {i: 5})
87
88echo $[c.i]
89call c->inc(3)
90echo $[c.i]
91
92## STDOUT:
935
948
95## END
96
97#### Mutating method must be up the prototype chain, not on the object
98
99func inc(self, n) {
100 setvar self.i += n
101}
102var c = Object(null, {'M/inc': inc, i: 0})
103
104call c->inc(3)
105
106## status: 3
107## STDOUT:
108## END
109
110
111#### Copy to Dict with dict(), and mutate
112
113var rect = Object(null, {x: 3, y: 4})
114var d = dict(rect)
115
116pp test_ (rect)
117pp test_ (d)
118
119setvar rect.x = 99
120setvar d.x = 100
121
122pp test_ (rect)
123pp test_ (d)
124## STDOUT:
125(Obj) ("x":3,"y":4)
126(Dict) {"x":3,"y":4}
127(Obj) ("x":99,"y":4)
128(Dict) {"x":100,"y":4}
129## END
130
131#### setvar obj.attr = and += and ...
132
133var rect = Object(null, {x: 3, y: 4})
134pp test_ (rect)
135
136setvar rect.y = 99
137pp test_ (rect)
138
139setvar rect.y += 3
140pp test_ (rect)
141
142setvar rect.x *= 5
143pp test_ (rect)
144
145## STDOUT:
146(Obj) ("x":3,"y":4)
147(Obj) ("x":3,"y":99)
148(Obj) ("x":3,"y":102)
149(Obj) ("x":15,"y":102)
150## END
151
152#### obj['attr'] not allowed (for now)
153
154var rect = Object(null, {x: 3, y: 4})
155
156pp test_ ([rect['x'], rect['y']])
157
158## status: 3
159## STDOUT:
160## END
161
162#### setvar obj['attr'] = 3 ?
163
164var rect = Object(null, {x: 3, y: 4})
165
166setvar rect['x'] = 99
167
168pp test_ (rect)
169
170# The reason this is allowed is because setvar does EvalLhsExpr(), which
171# handles:
172#
173# - y_lhs.SubScript -> y_lvalue.Container
174# - y_lhs.Attribute -> y_lvalue.Container
175#
176# So that means obj['x'] is allowed too?
177# We could possible add y_lvalue.Container(is_subscript)
178
179## status: 3
180## STDOUT:
181## END
182
183#### can't encode objects as JSON
184
185var Rect = Object(null, {})
186
187json write (Rect)
188echo 'nope'
189
190## status: 1
191## STDOUT:
192## END
193
194#### Can all builtin methods with s.upper()
195
196var s = 'foo'
197var x = s.upper()
198var y = "--$[x.lower()]"
199
200pp test_ (x)
201pp test_ (y)
202
203## STDOUT:
204(Str) "FOO"
205(Str) "--foo"
206## END
207
208#### invokable Obj must be have prototype containing __invoke__ of value.Proc - type -t
209
210proc p (w; self) {
211 pp test_ ([w, self])
212}
213p a ({x: 5, y: 6})
214echo
215
216var methods = Object(null, {__invoke__: p})
217
218var o1 = Object(methods, {})
219type -t o1
220echo
221
222# errors
223
224var o2 = Object(null, {})
225if ! type -t o2 {
226 echo 'no prototype'
227}
228
229var o3 = Object(Object(null, {}), {})
230if ! type -t o3 {
231 echo 'no __invoke__ method in prototype'
232}
233
234var bad_methods = Object(null, {__invoke__: 42})
235var o4 = Object(bad_methods, {})
236if ! type -t o4 {
237 echo '__invoke__ of wrong type'
238}
239
240## STDOUT:
241(List) ["a",{"x":5,"y":6}]
242
243invokable
244
245no prototype
246no __invoke__ method in prototype
247__invoke__ of wrong type
248## END
249
250#### Object with longer prototype chain
251
252# prototypal inheritance pattern
253var superClassMethods = Object(null, {foo: 'zz'})
254var methods = Object(superClassMethods, {foo: 42, bar: [1,2]})
255var instance = Object(methods, {foo: 1, bar: 2, x: 3})
256
257pp test_ (instance)
258pp value (instance)
259
260## STDOUT:
261(Obj) ("foo":1,"bar":2,"x":3) --> ("foo":42,"bar":[1,2]) --> ("foo":"zz")
262(Obj) (foo: 1, bar: 2, x: 3) --> (foo: 42, bar: [1, 2]) --> (foo: 'zz')
263## END