Uses 679K of libraries. Click here for Pure Java version (38850L/197K).
1 | !include once #1034831 // Gazelle 22 Function Include for Testing |
2 | |
3 | set flag PingV3. |
4 | |
5 | scope test_leftArrowScript |
6 | |
7 | sclass #ClassA {} |
8 | sclass #ClassB extends ClassA {} |
9 | sclass #ClassC extends ClassB {} |
10 | |
11 | sclass #StaticField { |
12 | sS theField; |
13 | } |
14 | |
15 | sclass #StaticFieldSubClass extends StaticField { |
16 | } |
17 | |
18 | interface #StaticFieldInInterface { |
19 | sS daField = "yo"; |
20 | } |
21 | |
22 | sclass #StaticFieldInterfaceImplementor is StaticFieldInInterface { |
23 | } |
24 | |
25 | sclass #InheritanceDispatchTest { |
26 | static S f(ClassA a) { ret "a"; } |
27 | static S f(ClassB a) { ret "b"; } |
28 | } |
29 | |
30 | sclass #Tester { |
31 | O value = "123"; |
32 | sO myStaticField = "ok"; |
33 | } |
34 | |
35 | sclass #Sub1 { |
36 | sclass X { static int value = 1; } |
37 | } |
38 | |
39 | sclass #Sub2 { |
40 | sclass X { static int value = 2; } |
41 | } |
42 | |
43 | interface #DefaultMethodInterface { |
44 | default S x() { ret "y"; } |
45 | } |
46 | |
47 | sclass #DefaultMethodTest is DefaultMethodInterface { |
48 | } |
49 | |
50 | svoid test_leftArrowScript() { |
51 | test_leftArrowScript_pinging(); |
52 | |
53 | embedded S countLoop(int n) { |
54 | ret [[ i <- 0; while lessThan i ]] + n + [[ { i <- plus i 1 }; i ]]; |
55 | } |
56 | |
57 | S ifThenElseScript = [[ |
58 | if lessThan a b { joinWithSpace "It's" "less" } |
59 | else if greaterThan a b { joinWithSpace "It's" "greater" } |
60 | else { joinWithSpace "They're" "equal" } |
61 | ]]; |
62 | |
63 | testFunctionValues(script -> leftArrowVerbose((S) script), |
64 | // int primitive |
65 | |
66 | [[ 5 ]], 5, |
67 | [[ -5 ]], -5, |
68 | |
69 | // function definition & call |
70 | [[ |
71 | def double x { |
72 | Math multiplyExact x 2 |
73 | } |
74 | |
75 | double 10 |
76 | ]], 20, |
77 | |
78 | // new object with constructor arguments |
79 | [[ new Pair "hello" "world" ]], pair("hello", "world"), |
80 | |
81 | // double constant |
82 | [[ str 1.5e2 ]], "150.0", |
83 | |
84 | // float constant |
85 | [[ 1.5e2f ]], 150f, |
86 | [[ 1.5e2F ]], 150f, |
87 | |
88 | // long constant |
89 | [[ 0L ]], 0L, |
90 | |
91 | // hex constant |
92 | [[ 0x80 ]], 0x80, |
93 | |
94 | // hex constant (long) |
95 | [[ 0x5DEECE66DL ]], 0x5DEECE66DL, |
96 | |
97 | // binary constant |
98 | [[ 0B101 ]], 0B101, |
99 | |
100 | // character constant |
101 | [[ '\t' ]], '\t', |
102 | |
103 | // [not implemented, too complicated] |
104 | // last = result of last statement |
105 | // [[ plus 1 2; Math addExact 5 last ]], 8, |
106 | |
107 | // get static field |
108 | [[ Color black ]], Color.black, |
109 | |
110 | // get instance field, |
111 | [[ tester <- new test_leftArrowScript_Tester; tester value ]], "123", |
112 | |
113 | // while loop |
114 | countLoop(5), 5, |
115 | |
116 | // if statement |
117 | [[ if lessThan 0 1 { "ok" } ]], "ok", |
118 | [[ if lessThan 1 0 { "ok" } ]], null, |
119 | |
120 | // for each |
121 | [[ l <- ll 2 3 |
122 | sum <- 0 |
123 | for number in l { sum <- plus sum number } |
124 | sum |
125 | ]], 5, |
126 | |
127 | // for each is also map() |
128 | [[ for i in ll 2 3 { plus i 1 } |
129 | ]], ll(3, 4), |
130 | |
131 | // for each as nested expression |
132 | [[ joinWithSpace (for i in ll 2 3 { i }) ]], "2 3", |
133 | |
134 | // for i to n |
135 | [[ for i to 2 { i } |
136 | ]], ll(0, 1), |
137 | |
138 | // for with byte array |
139 | [[ for b in litbytearray (toByte 5) (toByte 7) { b } ]], ll((byte) 5, (byte) 7), |
140 | |
141 | // for with double array |
142 | [[ for b in litdoublearray 5.0 7.0 { b } ]], ll(5.0, 7.0), |
143 | |
144 | // for with char array |
145 | [[ for c in chars "AB" { c } ]], ll('A', 'B'), |
146 | |
147 | // for with typed variable |
148 | [[ for c: char in chars "AB" { c } ]], ll('A', 'B'), |
149 | |
150 | // some bug |
151 | [[ |
152 | img <- newImage 10 10 |
153 | r <- randomRect img 10 10 |
154 | ]], rect(0, 0, 10, 10), |
155 | |
156 | // another bug |
157 | [[ |
158 | a <- 1 |
159 | b <- a |
160 | a |
161 | ]], 1, |
162 | |
163 | // null bug |
164 | [[ |
165 | a <- 1 |
166 | a <- null |
167 | a |
168 | ]], null, |
169 | |
170 | // return at the end |
171 | [[ |
172 | return 17 |
173 | ]], 17, |
174 | |
175 | // two returns (first wins) |
176 | [[ |
177 | return 13 |
178 | return 22 |
179 | ]], 13, |
180 | |
181 | // same with "ret" for "return" |
182 | [[ |
183 | ret 13 |
184 | ret 22 |
185 | ]], 13, |
186 | |
187 | // conditional return |
188 | |
189 | [[ |
190 | if true { return "so true" } |
191 | return "oops" |
192 | ]], "so true", |
193 | |
194 | [[ |
195 | if false { return "not true" } |
196 | return "but this" |
197 | ]], "but this", |
198 | |
199 | // if-then-else |
200 | |
201 | [[ a <- 1; b <- 2; ]] + ifThenElseScript, "It's less", |
202 | [[ a <- 6; b <- 2; ]] + ifThenElseScript, "It's greater", |
203 | [[ a <- 5.0; b <- 5.0; ]] + ifThenElseScript, "They're equal", |
204 | |
205 | // if-then-else with "then" keyword but without curly braces |
206 | [[ if true then "ok" else "not ok" ]], "ok", |
207 | [[ if false then "ok" else "not ok" ]], "not ok", |
208 | |
209 | // nested expressions |
210 | |
211 | [[ plus (plus 1 2) 4 ]], 7, |
212 | [[ (plus 5 6) toString ]], "11", |
213 | |
214 | // nested expressions over 2 lines (it's ok to split an expression |
215 | // over multiple lines if you at least parenthesis is still open) |
216 | |
217 | [[ (plus 1 |
218 | (plus 2 3)) ]], 6, |
219 | |
220 | // another case for nested expressions |
221 | [[ str (Color black) ]], str(Color.black), |
222 | |
223 | // bug with nested for + new + linebreak + for (phew) |
224 | [[ (for y in ll 1 { |
225 | new Pair 1 2 |
226 | for x in null {} |
227 | }); 0 ]], 0, |
228 | |
229 | // param declares a variable |
230 | [[ param x; x ]], null, |
231 | |
232 | // same with type |
233 | [[ param x : int; x ]], null, |
234 | |
235 | // return with assignment |
236 | [[ return x <- 1 ]], 1, |
237 | |
238 | // for pair |
239 | [[ for pair a b in ll (pair 1 2) (pair 3 4) { |
240 | plus a b |
241 | } ]], ll(3, 7), |
242 | |
243 | // for key, value (map) |
244 | [[ for a, b in litorderedmap 1 2 3 4 { |
245 | plus a b |
246 | } ]], ll(3, 7), |
247 | |
248 | // for index, value (list) |
249 | [[ for index i, a in ll "a" "b" { |
250 | concatStrings i a |
251 | } ]], ll("0a", "1b"), |
252 | |
253 | // automatically convert int to long for method call |
254 | [[ longPlus 1 2 ]], 3L, |
255 | |
256 | // same for constructors |
257 | [[ new Ratio 1 ]], Ratio(1), |
258 | |
259 | // call a function from another function |
260 | [[ def f1 { 1 } |
261 | def f2 { plus (f1) 2 } |
262 | f2 ]], 3, |
263 | |
264 | // return out of for loop |
265 | [[ for x in iota 2 { return x } ]], 1, |
266 | |
267 | // continue loop |
268 | [[ for x in iota 2 { |
269 | if eq x 1 { continue } |
270 | return "ok" |
271 | } ]], "ok", |
272 | |
273 | // break loop (TODO) |
274 | /*[[ for x in iota 2 { |
275 | if eq x 1 { break } |
276 | return "what" |
277 | } |
278 | "ok" |
279 | ]], "ok",*/ |
280 | |
281 | // new without new |
282 | [[ Pair (neg 1) (neg 2) ]], pair(-1, -2), |
283 | |
284 | // variable doesn't come into scope until it's initialized |
285 | [[ neg <- neg 1; neg ]], -1, |
286 | |
287 | // repeat x { ... } construct |
288 | [[ x <- 0 |
289 | repeat plus 1 2 { x <- plus x 1 } |
290 | x ]], 3, |
291 | |
292 | // update outer variable from function |
293 | [[ x <- 0 |
294 | def incIt { outer x <- plus x 1 } |
295 | incIt |
296 | x ]], 1, |
297 | |
298 | // return directly followed by } |
299 | [[ if true { return } ]], null, |
300 | |
301 | // return from lambda (exits only the lambda, just like in Java) |
302 | [[ repF 2 (IF0 -> { return 1; null }) ]], ll(1, 1), |
303 | |
304 | // "temp" (like in JavaX) |
305 | [[ list <- new ArrayList |
306 | { |
307 | temp tempAdd list 5 |
308 | assertContains list 5 |
309 | } |
310 | list |
311 | ]], ll(), |
312 | |
313 | // "temp" test 2 (assure it handles exceptions properly) |
314 | [[ list <- new ArrayList |
315 | pcallF (Runnable -> { |
316 | temp tempAdd list 5 |
317 | fail |
318 | }) |
319 | list |
320 | ]], ll(), |
321 | |
322 | // "temp" combined with variable declaration |
323 | [[ list <- new ArrayList |
324 | { |
325 | temp x <- tempAdd list 5 |
326 | assertInstanceOf x AutoCloseable |
327 | assertContains list 5 |
328 | } |
329 | list |
330 | ]], ll(), |
331 | |
332 | // reference to functionContainer class itself |
333 | [[ main ]], mc(), |
334 | |
335 | // referencing class with full package name |
336 | [[ java.util.Arrays sort (newFloatArray 1) ]], null, |
337 | |
338 | [[ new java.util.ArrayList ]], ll(), |
339 | |
340 | // call method on literal |
341 | [[ "" length ]], 0, |
342 | |
343 | // L or List to make a new list |
344 | [[ new List ]], ll(), |
345 | [[ new L ]], ll(), |
346 | |
347 | // Map to make a new HashMap |
348 | [[ new Map ]], new Map, |
349 | |
350 | // new with a variable containing a class |
351 | [[ c <- ArrayList; new c ]], ll(), |
352 | |
353 | [[ new Var<S>, getClass ]], Var.class, |
354 | |
355 | shortName(InheritanceDispatchTest) + " f (new " + shortName(ClassC) + ")", "b", |
356 | |
357 | [[ |
358 | sleepSeconds 0 |
359 | sleepSeconds 0 |
360 | ]], null, |
361 | |
362 | // variable declaration with type |
363 | |
364 | [[ a : S <- "s"; a ]], "s", |
365 | |
366 | // try/finally |
367 | |
368 | [[ |
369 | a <- 0 |
370 | try { |
371 | try { a <- plus a 1 } finally { a <- plus a 2 } |
372 | try { fail } finally { a <- plus a 3 } |
373 | } catch e {} |
374 | a |
375 | ]], 6, |
376 | |
377 | // try is also an expression |
378 | |
379 | [[ |
380 | list { |
381 | try { fail } catch {} |
382 | try { fail } catch { "oops" } |
383 | try { "a" } catch {} |
384 | } |
385 | ]], ll(null, "oops", "a"), |
386 | |
387 | // function definition with explicit parameter type |
388 | [[ |
389 | def f x: int { |
390 | plus x 1 |
391 | } |
392 | f 5 |
393 | ]], 6, |
394 | |
395 | // same with parameter in parentheses |
396 | [[ |
397 | def f (x: int) { |
398 | plus x 1 |
399 | } |
400 | f 5 |
401 | ]], 6, |
402 | |
403 | // param with nested parameterized type |
404 | [[ |
405 | param x : L<Pair<Int, Int>> |
406 | ]], null, |
407 | |
408 | // +id shortcut |
409 | [[ x <- 5; ll +x ]], ll(x := 5), |
410 | |
411 | // unclosed multi-line string |
412 | "splitAtSpace [[a b", ll("a", "b"), |
413 | "splitAtSpace [=[c d", ll("c", "d"), |
414 | |
415 | // list { } |
416 | [[ list { |
417 | plus 1 2 |
418 | minus 8 4 |
419 | } ]], ll(3, 4), |
420 | |
421 | // same in one line with semicolons |
422 | [[ list { plus 1 2; minus 8 4 } ]], ll(3, 4), |
423 | |
424 | // parsing bug |
425 | [[ for x in ll |
426 | 1 { x } ]], ll(1), |
427 | |
428 | // will return |
429 | [[ data <- new Var |
430 | will return data get |
431 | data set 1 ]], 1, |
432 | |
433 | // recursive script-defined function |
434 | [[ def myFactorial n { |
435 | if n lessThan 2 |
436 | { 1 } |
437 | else { myFactorial (n minus 1), mul n } |
438 | } |
439 | myFactorial 5 |
440 | ]], 120, |
441 | |
442 | // for each closes the iterator if it's closeable |
443 | [[ |
444 | iterator <- new TestCloseableIterableIterator |
445 | closed <- new Flag |
446 | iterator onClosing closed |
447 | for i in iterator {} |
448 | closed isUp |
449 | ]], true, |
450 | |
451 | // same test with exception in loop |
452 | [[ |
453 | iterator <- new TestCloseableIterableIterator |
454 | closed <- new Flag |
455 | iterator onClosing closed |
456 | try { |
457 | for i in iterator { fail } |
458 | } catch e {} |
459 | closed isUp |
460 | ]], true, |
461 | |
462 | // make sure my own classes are found before Java SDK classes |
463 | [[ new Timestamp 1000, unixDate ]], |
464 | 1000L, |
465 | |
466 | // TO FIX |
467 | // TODO [[ max 1000L 100 ]], 1000L, |
468 | |
469 | // couldn't fix this quickly (have ~ binding stronger) |
470 | //[[ map <- litmap "a" 1 "b" 2; plus map~a map~b ]], 3, |
471 | |
472 | // question mark syntax for calling methods on null targets |
473 | [[ a <- null; a intValue? ]], null, |
474 | [[ a <- 5L; a intValue? ]], 5, |
475 | |
476 | // long constants without L |
477 | [[ 1234567812345678 ]], 1234567812345678, |
478 | |
479 | // Duration is a standard import |
480 | [[ d: Duration <- daysToDuration 1 ]], |
481 | daysToDuration(1), |
482 | |
483 | // first called with subtype array |
484 | [[ fileName < first < toTypedArray File < ll < newFile "hello" ]], |
485 | "hello", |
486 | |
487 | [[ |
488 | o <- new O |
489 | assertFalse < Thread holdsLock o |
490 | synchronized o { |
491 | assertTrue < Thread holdsLock o |
492 | } |
493 | assertFalse < Thread holdsLock o |
494 | null |
495 | ]], null, |
496 | |
497 | // , +abc syntax (= , abc abc) |
498 | [[ a <- "1"; b <- "2"; new Pair, +a, +b ]], |
499 | pair("1", "2"), |
500 | |
501 | // call default method |
502 | jreplace([[ new DefaultMethodTest, x ]], |
503 | "DefaultMethodTest", shortName(DefaultMethodTest)), |
504 | "y", |
505 | |
506 | // function with only varargs |
507 | [[ def f b... { second b } |
508 | ll (f) (f 7) (f 9 11) ]], |
509 | ll(null, null, 11), |
510 | |
511 | // function with 1 normal arg and varargs |
512 | [[ def f a b... { first b } |
513 | ll (f 5 ) (f 5 3) (f 5 6 7) ]], |
514 | ll(null, 3, 6), |
515 | |
516 | // function with 2 normal args and varargs |
517 | [[ def f a b c... { first c } |
518 | ll (f) (f 1 5) (f 1 5 3) (f 1 5 6 7) ]], |
519 | ll(null, null, 3, 6), |
520 | |
521 | // add simple tests here |
522 | ); |
523 | |
524 | // get reference to current var context with _context |
525 | |
526 | new GazelleV_LeftArrowScriptParser parser; |
527 | enableScaffolding(parser); |
528 | parser.allowTheWorld(); |
529 | new FlexibleVarContext ctx; |
530 | assertSame(ctx, parser.parse("_context").get(ctx)); |
531 | |
532 | test_leftArrowScriptParseErrors(); |
533 | |
534 | test_leftArrowScript_lambdas(); |
535 | |
536 | test_leftArrowScript_binaryOperators(); |
537 | |
538 | test_leftArrowScriptCompileErrors(); |
539 | |
540 | // get static field in functionContainer |
541 | |
542 | parser = new GazelleV_LeftArrowScriptParser; |
543 | parser.allowTheWorld(Tester, mc()); |
544 | assertEqualsVerbose("ok", parser.parse("myStaticField")!); |
545 | assertEqualsVerbose("ko", parser.parse("reversed myStaticField")!); |
546 | assertEqualsVerbose(2, parser.parse("myStaticField length")!); |
547 | |
548 | test_leftArrowScript_classDefs(); |
549 | |
550 | test_leftArrowScript_forIterator(); |
551 | |
552 | var exception = leftArrowVerbose([[ |
553 | try { throw new RuntimeException } catch e { e } |
554 | ]]); |
555 | assertEqualsVerbose(exception.getClass(), RuntimeException.class); |
556 | |
557 | // trying to get non-existant field/method on object |
558 | assertFailVerbose(-> leftArrowVerbose([[ "" lengthX ]])); |
559 | |
560 | // make sure fields local to function are not visible outside |
561 | assertFailVerbose(-> leftArrowParse([[ def x { y <- 1 } y ]])); |
562 | |
563 | test_leftArrowScript_comma(); |
564 | test_leftArrowScript_antiComma(); |
565 | |
566 | // test priority of class resolution |
567 | parser = new GazelleV_LeftArrowScriptParser; |
568 | enableScaffolding(parser); |
569 | parser.allowTheWorld(Sub1.class, Sub2.class); |
570 | assertEqualsVerbose(1, parser.parse("X value")!); |
571 | parser = new GazelleV_LeftArrowScriptParser; |
572 | enableScaffolding(parser); |
573 | parser.allowTheWorld(Sub2.class, Sub1.class); |
574 | assertEqualsVerbose(2, parser.parse("X value")!); |
575 | |
576 | test_leftArrowScript_returnValueNotNeededOptimization(); |
577 | |
578 | // test addClassAlias |
579 | |
580 | parser = new GazelleV_LeftArrowScriptParser; |
581 | parser.allowTheWorld(); |
582 | parser.addClassAlias("Paar", "Pair"); |
583 | assertEqualsVerbose(pair(1, 2), parser.parse("new Paar 1 2")!); |
584 | |
585 | // test that params are stored in parsed script |
586 | |
587 | var script = leftArrowParseVerbose("param x : int"); |
588 | assertEqualsVerbose(1, l(script.params)); |
589 | assertEqualsVerbose("x", firstKey(script.params)); |
590 | assertEqualsVerbose(int.class, firstValue(script.params).javaClass()); |
591 | |
592 | // +id shortcut doesn't work with a space |
593 | assertFailVerbose(-> leftArrowParseVerbose([[ x <- 5; ll + x ]])); |
594 | |
595 | test_leftArrowScript_magicSwitch(); |
596 | |
597 | test_leftArrowScript_tilde(); |
598 | |
599 | test_leftArrowScript_then(); |
600 | |
601 | assertInstanceOf IF0(leftArrowVerbose([[ abcd <- IF0 {}; abcd ]])); |
602 | |
603 | // Test def ... returning a FunctionDef |
604 | O o = leftArrow([[def bla { null } ]]); |
605 | assertEqualsVerbose("bla", ((GazelleV_LeftArrowScript.FunctionDef) o).name); |
606 | |
607 | o = leftArrow([[a <- def bla { null }; a]]); |
608 | assertEqualsVerbose("bla", ((GazelleV_LeftArrowScript.FunctionDef) o).name); |
609 | |
610 | test_leftArrowScript_pcall(); |
611 | |
612 | test_leftArrowScript_ifdef(); |
613 | |
614 | //test_leftArrowScript_var(); |
615 | |
616 | // assignment to static field |
617 | leftArrowVerbose(replace( |
618 | [[ StaticField theField <- "hello" |
619 | ]], "StaticField", className(StaticField))); |
620 | assertEqualsVerbose("hello", StaticField.theField); |
621 | |
622 | // get static field from subclass |
623 | assertEqualsVerbose("hello", leftArrowVerbose(replace( |
624 | [[ StaticFieldSubClass theField ]], |
625 | "StaticFieldSubClass", className(StaticFieldSubClass)))); |
626 | |
627 | // get static field from implemented interface |
628 | assertEqualsVerbose("yo", leftArrowVerbose(replace( |
629 | [[ StaticFieldInterfaceImplementor daField ]], |
630 | "StaticFieldInterfaceImplementor", className(StaticFieldInterfaceImplementor)))); |
631 | |
632 | test_leftArrowScript_scriptError(); |
633 | |
634 | test_leftArrowScript_objectScope(); |
635 | |
636 | test_leftArrowScript_doWhile(); |
637 | |
638 | // Test that string literals are interned |
639 | assertSame(intern("abc"), leftArrowVerbose([["abc"]]); |
640 | |
641 | // add tests here |
642 | |
643 | print("All left-arrow script tests OK!"); |
644 | } |
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, ekrmjmnbrukm, elmgxqgtpvxh, gjtlkbvenryc, mowyntqkapby, mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1033988 |
Snippet name: | test_leftArrowScript - all tests for Left-Arrow-Script |
Eternal ID of this version: | #1033988/200 |
Text MD5: | 7914191c70aea482a5d79e2374d629b0 |
Transpilation MD5: | deb5e4a1d140992d3873e41af8d362bb |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2025-01-09 17:39:02 |
Source code size: | 16349 bytes / 644 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 907 / 3194 |
Version history: | 199 change(s) |
Referenced in: | [show references] |