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

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