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

261 lines, 129 significant
1## our_shell: ysh
2## oils_failures_allowed: 0
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
119# Right now, object attributes aren't mutable! Could change this.
120#
121setvar rect.x = 99
122setvar d.x = 100
123
124pp test_ (rect)
125pp test_ (d)
126## STDOUT:
127(Obj) ("x":3,"y":4)
128(Dict) {"x":3,"y":4}
129(Obj) ("x":99,"y":4)
130(Dict) {"x":100,"y":4}
131## END
132
133#### setvar obj.attr = and += and ...
134
135var rect = Object(null, {x: 3, y: 4})
136pp test_ (rect)
137
138setvar rect.y = 99
139pp test_ (rect)
140
141setvar rect.y += 3
142pp test_ (rect)
143
144setvar rect.x *= 5
145pp test_ (rect)
146
147## STDOUT:
148(Obj) ("x":3,"y":4)
149(Obj) ("x":3,"y":99)
150(Obj) ("x":3,"y":102)
151(Obj) ("x":15,"y":102)
152## END
153
154#### can't encode objects as JSON
155
156var Rect = Object(null, {})
157
158json write (Rect)
159echo 'nope'
160
161## status: 1
162## STDOUT:
163## END
164
165#### Can all builtin methods with s.upper()
166
167var s = 'foo'
168var x = s.upper()
169var y = "--$[x.lower()]"
170
171pp test_ (x)
172pp test_ (y)
173
174## STDOUT:
175(Str) "FOO"
176(Str) "--foo"
177## END
178
179#### invokable Obj must be have prototype containing __invoke__ of value.Proc - type -t
180
181proc p (w; self) {
182 pp test_ ([w, self])
183}
184p a ({x: 5, y: 6})
185echo
186
187var methods = Object(null, {__invoke__: p})
188
189var o1 = Object(methods, {})
190type -t o1
191echo
192
193# errors
194
195var o2 = Object(null, {})
196if ! type -t o2 {
197 echo 'no prototype'
198}
199
200var o3 = Object(Object(null, {}), {})
201if ! type -t o3 {
202 echo 'no __invoke__ method in prototype'
203}
204
205var bad_methods = Object(null, {__invoke__: 42})
206var o4 = Object(bad_methods, {})
207if ! type -t o4 {
208 echo '__invoke__ of wrong type'
209}
210
211## STDOUT:
212(List) ["a",{"x":5,"y":6}]
213
214invokable
215
216no prototype
217no __invoke__ method in prototype
218__invoke__ of wrong type
219## END
220
221#### Object with longer prototype chain
222
223# prototypal inheritance pattern
224var superClassMethods = Object(null, {foo: 'zz'})
225var methods = Object(superClassMethods, {foo: 42, bar: [1,2]})
226var instance = Object(methods, {foo: 1, bar: 2, x: 3})
227
228pp test_ (instance)
229
230## STDOUT:
231(Obj) ("foo":1,"bar":2,"x":3) --> ("foo":42,"bar":[1,2]) --> ("foo":"zz")
232## END
233
234
235#### Closures in a loop idiom
236
237var procs = []
238for i in (0 .. 3) {
239 proc __invoke__ (; self) {
240 echo "i = $[self.i]"
241 }
242 var methods = Object(null, {__invoke__})
243 var obj = Object(methods, {i})
244 call procs->append(obj)
245}
246
247for p in (procs) {
248 p
249}
250
251# TODO: sugar
252# proc p (; self) capture {i} {
253# echo "i = $[self.i]"
254# }
255# call procs->append(p)
256
257## STDOUT:
258i = 0
259i = 1
260i = 2
261## END