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

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