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 | |
392 | // other script-defined class as field type |
393 | |
394 | runScript([[ |
395 | class MyA {}
|
396 | class MyB { settable a: MyA }
|
397 | ]]); |
398 | } |
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/92 |
| Text MD5: | 1ac7c1a91c4070e6cceb222065a59daf |
| Author: | stefan |
| Category: | javax / left arrow script |
| Type: | JavaX fragment (include) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2025-04-26 23:06:02 |
| Source code size: | 8798 bytes / 398 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 3042 / 3807 |
| Version history: | 91 change(s) |
| Referenced in: | [show references] |