Transpiled version (37081L) is out of date.
1 | set flag OurSyncCollections. |
2 | |
3 | !include once #1034831 // Gazelle 22 Function Include for Testing |
4 | |
5 | svoid test_leftArrowScript_classDefs() { |
6 | temp LASMultiClassLoader cl = new(mc()); |
7 | test_leftArrowScript_classDefs(cl); |
8 | } |
9 | |
10 | sclass test_leftArrowScript_classDefs_Base { |
11 | S hey() { ret "ho"; } |
12 | } |
13 | |
14 | svoid test_leftArrowScript_classDefs(LASMultiClassLoader cl) { |
15 | var test = new TestFunctionValues<S, O>(l1 leftArrowVerbose); |
16 | |
17 | // define a class with two fields |
18 | |
19 | S classPrefix = "scriptClasses."; |
20 | |
21 | embedded O runScript(S code) { |
22 | new GazelleV_LeftArrowScriptParser parser; |
23 | enableScaffolding(parser); |
24 | parser.classDefPrefix(classPrefix); |
25 | parser.lasClassLoader(cl); |
26 | ret leftArrowVerbose(parser, code); |
27 | } |
28 | |
29 | S classSrc = [[ |
30 | class MyClass { |
31 | a: String |
32 | b: String |
33 | } |
34 | ]], src = classSrc; |
35 | |
36 | Class c = cast runScript(src); |
37 | assertStartsWith(print(c.getName()), classPrefix + "MyClass" + "_"); |
38 | |
39 | // compile same source again - make sure we get the same class object |
40 | assertSame(c, runScript(src)); |
41 | |
42 | assertEqualsVerbose("Number of fields", 3, l(getDeclaredFields_cached(c))); |
43 | assertEqualsVerbose("Type of a", S.class, getField(c, "a").getType()); |
44 | assertEqualsVerbose("Type of b", S.class, getField(c, "b").getType()); |
45 | |
46 | // Make sure a change in the class definition gives us a new class name |
47 | Class c2 = cast runScript([[ |
48 | class MyClass { |
49 | a: String |
50 | c: String |
51 | } |
52 | ]]); |
53 | print(className(c2)); |
54 | assertNotSame(c, c2); |
55 | |
56 | // Make sure a change in the methods also gives us a new class name |
57 | S classSrc2 = [[ |
58 | class MyClass { |
59 | def bla { "x" } |
60 | } |
61 | ]]; |
62 | c = (Class) runScript(classSrc2); |
63 | assertSame(c, runScript(classSrc2)); |
64 | c2 = (Class) runScript([[ |
65 | class MyClass { |
66 | def bla { "y" } |
67 | } |
68 | ]]); |
69 | assertNotSame(c, c2); |
70 | |
71 | // Now let's try and use a script-defined class |
72 | |
73 | src = classSrc + [[ |
74 | x <- new MyClass |
75 | y <- new MyClass |
76 | x a <- "yo" |
77 | y a <- "oy" |
78 | x a |
79 | ]]; |
80 | |
81 | assertEqualsVerbose("yo", runScript(src)); |
82 | |
83 | // Using the class in a function |
84 | |
85 | src = classSrc + [[ |
86 | def bla { |
87 | x <- new MyClass |
88 | x a <- "yo" |
89 | x a |
90 | } |
91 | bla |
92 | ]]; |
93 | |
94 | assertEqualsVerbose("yo", runScript(src)); |
95 | |
96 | // Now for defining some methods (yay!) |
97 | |
98 | src = [[ |
99 | class MyClass2 { |
100 | def method1 { "I'm here" } |
101 | def method2 a { reversed a } |
102 | } |
103 | |
104 | x <- new MyClass2 |
105 | pair (x method1) (x method2 "sey") |
106 | ]]; |
107 | |
108 | assertEqualsVerbose(pair("I'm here", "yes"), runScript(src)); |
109 | |
110 | // accessing instance fields |
111 | |
112 | src = [[ |
113 | class MyClass3 { |
114 | a: String |
115 | |
116 | def getA { this a } // requiring the this keyword for now |
117 | def setA a { this a <- a } |
118 | def aLength { (this a) length } |
119 | } |
120 | |
121 | x <- new MyClass3 |
122 | x setA "abc" |
123 | assertEquals (x aLength) 3 |
124 | x getA |
125 | ]]; |
126 | |
127 | assertEqualsVerbose("abc", runScript(src)); |
128 | |
129 | // fully qualified type |
130 | classSrc = [[ |
131 | class MyClass4 { |
132 | a: java.util.List |
133 | } |
134 | ]]; |
135 | |
136 | c = (Class) runScript(classSrc); |
137 | assertEqualsVerbose(fieldType(c, "a"), L.class); |
138 | |
139 | // type with type parameter |
140 | classSrc = [[ |
141 | class MyClass5 { |
142 | a: L<S> |
143 | } |
144 | ]]; |
145 | |
146 | c = (Class) runScript(classSrc); |
147 | assertEqualsVerbose("Raw type of L<S> field", fieldType(c, "a"), L.class); |
148 | assertEqualsVerbose("Generic type of L<S> field", genericFieldType(c, "a"), |
149 | new ParameterizedTypeImpl(null, L, S)); |
150 | |
151 | // primitive type |
152 | classSrc = [[ |
153 | class MyClass6 { |
154 | x: int |
155 | } |
156 | ]]; |
157 | |
158 | c = (Class) runScript(classSrc); |
159 | assertEqualsVerbose(fieldType(c, "x"), int.class); |
160 | |
161 | classSrc = [[ |
162 | class ToString { |
163 | def toString : S { "It's me, George!" } |
164 | } |
165 | new ToString |
166 | ]]; |
167 | |
168 | assertEqualsVerbose("It's me, George!", str(runScript(classSrc))); |
169 | |
170 | // primitive array |
171 | classSrc = [[ |
172 | class MyClass7 { |
173 | x: int[] |
174 | } |
175 | ]]; |
176 | |
177 | c = (Class) runScript(classSrc); |
178 | assertEqualsVerbose(fieldType(c, "x"), int[].class); |
179 | |
180 | // define class implementing interface |
181 | |
182 | classSrc = |
183 | [[ class Bla is IF0 { def get { "hello" } } |
184 | new Bla ]]; |
185 | |
186 | IF0 f = cast runScript(classSrc); |
187 | assertEqualsVerbose("hello", f!); |
188 | |
189 | // call function on class defined inline |
190 | |
191 | assertEqualsVerbose(Class.class, runScript([[ |
192 | _getClass2 class A { } |
193 | ]])); |
194 | |
195 | // constructor |
196 | |
197 | assertEqualsVerbose(5, runScript([[ |
198 | class MyClass8 { |
199 | x: int |
200 | |
201 | ctor { this x <- 5 } |
202 | } |
203 | |
204 | new MyClass8, x |
205 | ]]); |
206 | |
207 | // initialized field |
208 | |
209 | assertEqualsVerbose(7, runScript([[ |
210 | class MyClass9 { |
211 | x: int <- 7 |
212 | } |
213 | |
214 | new MyClass9, x |
215 | ]]); |
216 | |
217 | cl.rememberClassBytes(true); |
218 | cl.onClassDefined(l1 disassembleClass); |
219 | |
220 | // define class with superclass |
221 | |
222 | classSrc = [[ |
223 | class A { def yo { "yay" } } |
224 | class B extends A { def wow { joinWithSpace (this yo) "amazing!" } } |
225 | new B, wow |
226 | ]]; |
227 | |
228 | assertEqualsVerbose("yay amazing!", runScript(classSrc)); |
229 | |
230 | // define class with superclass from outside of script |
231 | |
232 | classSrc = [[ |
233 | class B extends test_leftArrowScript_classDefs_Base { |
234 | def wow { joinWithSpace (this hey) (this hey) (this hey) } } |
235 | new B, wow |
236 | ]]; |
237 | |
238 | assertEqualsVerbose("ho ho ho", runScript(classSrc)); |
239 | |
240 | // initializer |
241 | |
242 | runScript([[ |
243 | class MyClass9 { |
244 | x: int |
245 | initializer { this x <- 5 } |
246 | } |
247 | |
248 | assertEqualsVerbose 5 < new MyClass9, x |
249 | ]]); |
250 | |
251 | runScript([[ |
252 | class MyClass10 { |
253 | l: L <- new ArrayList |
254 | initializer { this l, add "init" } |
255 | ctor { this l, add "ctor" } |
256 | } |
257 | |
258 | assertEqualsVerbose (ll "init" "ctor") < new MyClass10, l |
259 | ]]); |
260 | |
261 | // TODO: Call superclass method (basically needs full method compilation) |
262 | |
263 | /*runScript([[ |
264 | class MyClassA { |
265 | def x: S { "hello" } |
266 | } |
267 | |
268 | class MyClassB extends MyClassA { |
269 | def x: S { ret concat (super x) " world" } |
270 | } |
271 | |
272 | assertEqualsVerbose "hello world" < new MyClassB, x |
273 | ]]);*/ |
274 | |
275 | // Reference own class name |
276 | |
277 | runScript([[ |
278 | class MyClassSelf { |
279 | def me: MyClassSelf { this } |
280 | } |
281 | ]]); |
282 | |
283 | // Methods have proper argument types |
284 | |
285 | runScript([[ |
286 | class ArgTypes { |
287 | def doIt (s: S) { "a string" } |
288 | def doIt (s: O) { "not a string" } |
289 | } |
290 | |
291 | assertEqualsVerbose "a string" < new ArgTypes, doIt "yo" |
292 | assertEqualsVerbose "not a string" < new ArgTypes, doIt 123 |
293 | ]]); |
294 | |
295 | // Methods with primitive return type |
296 | |
297 | runScript([[ |
298 | class PrimReturn { |
299 | def theNumber: int { 123 } |
300 | } |
301 | |
302 | assertEqualsVerbose 123 < new PrimReturn, theNumber |
303 | assertEqualsVerbose "int" < str < findMethod (new PrimReturn) "theNumber", getReturnType |
304 | ]]); |
305 | |
306 | // settable fields |
307 | |
308 | runScript([[ |
309 | class Settable { |
310 | settable x: int |
311 | settable b: bool |
312 | settable l: long |
313 | settable d: double |
314 | settable y: S |
315 | } |
316 | |
317 | s <- new Settable, x 5, y "test", b true |
318 | assertEqualsVerbose 5 < s x |
319 | assertEqualsVerbose 5 < call s "x" |
320 | assertEqualsVerbose "test" < s y |
321 | assertEqualsVerbose "test" < call s "y" |
322 | assertEqualsVerbose true < s b |
323 | ]]); |
324 | |
325 | // settable field with initializer |
326 | |
327 | runScript([[ |
328 | class Settable { |
329 | settable s: S <- "hello" |
330 | } |
331 | |
332 | assertEqualsVerbose "hello" < new Settable, s |
333 | ]]); |
334 | |
335 | // selfType as method return type |
336 | |
337 | runScript([[ |
338 | class SelfTypeTest { |
339 | def me: selfType { this } |
340 | } |
341 | |
342 | t <- new SelfTypeTest |
343 | assertEqualsVerbose t < t me |
344 | ]]); |
345 | |
346 | // void methods |
347 | |
348 | runScript([[ |
349 | class VoidMethodTest is Closeable { |
350 | def close: void {} |
351 | } |
352 | ]]); |
353 | |
354 | // transient field |
355 | |
356 | O o = runScript([[ |
357 | class TransientTest { |
358 | transient i: int |
359 | } |
360 | new TransientTest |
361 | ]]); |
362 | assertTrueVerbose("transient", isTransient(fieldObject(o, "i"))); |
363 | |
364 | // LS as type |
365 | |
366 | o = runScript([[ |
367 | class LSTest { |
368 | l: LS |
369 | } |
370 | new LSTest |
371 | ]]); |
372 | assertEqualsVerbose("java.util.List<java.lang.String>", |
373 | str(genericFieldType(o, "l"))); |
374 | |
375 | // Referring to a script-defined class as a Class |
376 | |
377 | o = runScript([[ |
378 | class MyClass {} |
379 | MyClass |
380 | ]]); |
381 | assertContainsVerbose("MyClass", className((Class) o)); |
382 | |
383 | // static field |
384 | |
385 | o = runScript([[ |
386 | class MyClass { |
387 | static hello: S <- "world" |
388 | } |
389 | ]]); |
390 | assertEqualsVerbose("world", get((Class) o, "hello")); |
391 | } |
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, ekrmjmnbrukm, elmgxqgtpvxh, mowyntqkapby, mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1035077 |
Snippet name: | test_leftArrowScript_classDefs (OK) |
Eternal ID of this version: | #1035077/86 |
Text MD5: | 63cf200439f165632fcba747d09ca9cf |
Author: | stefan |
Category: | javax / left arrow script |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2023-04-29 23:36:14 |
Source code size: | 8666 bytes / 391 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 353 / 806 |
Version history: | 85 change(s) |
Referenced in: | [show references] |