ranger-compiler 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +2482 -0
  2. package/LICENSE +28 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +1650 -1895
  5. package/dist/Lang.rgr +10946 -5852
  6. package/dist/README.md +3 -2
  7. package/dist/api.d.ts +1157 -29
  8. package/dist/api.js +66623 -38073
  9. package/dist/lib/ACEEditor.rgr +2 -0
  10. package/dist/lib/Ajax.rgr +2 -0
  11. package/dist/lib/CmdParams.rgr +2 -0
  12. package/dist/lib/Crypto.rgr +2 -0
  13. package/dist/lib/DOMLib.rgr +2 -0
  14. package/dist/lib/Engine3D.rgr +2 -0
  15. package/dist/lib/ImmutableVector.rgr +2 -0
  16. package/dist/lib/IndexedDB.rgr +2 -0
  17. package/dist/lib/IsoDate/DateMath.rgr +2 -0
  18. package/dist/lib/IsoDate/IsoCalendar.rgr +2 -0
  19. package/dist/lib/IsoDate/IsoDateParse.rgr +2 -0
  20. package/dist/lib/IsoDateLib.rgr +2 -0
  21. package/dist/lib/JSON.rgr +4906 -48
  22. package/dist/lib/JinxProcess.rgr +2 -0
  23. package/dist/lib/RangerProcess.rgr +2 -0
  24. package/dist/lib/Regex/RegexMatch.rgr +2 -0
  25. package/dist/lib/RegexLib.rgr +2 -0
  26. package/dist/lib/SQL.rgr +2 -0
  27. package/dist/lib/ServiceLib.rgr +2 -0
  28. package/dist/lib/Shell.rgr +326 -0
  29. package/dist/lib/Storage.rgr +2 -0
  30. package/dist/lib/Time.rgr +2 -0
  31. package/dist/lib/Timers.rgr +2 -0
  32. package/dist/lib/TypedArrays.rgr +2 -0
  33. package/dist/lib/ViewLib.rgr +2 -0
  34. package/dist/lib/WebLib.rgr +2 -0
  35. package/dist/lib/WebServerLib.rgr +2 -0
  36. package/dist/lib/apple/AppleAppBuilder.rgr +572 -0
  37. package/dist/lib/apple/AppleAppSpec.rgr +201 -0
  38. package/dist/lib/apple/AppleDevice.rgr +295 -0
  39. package/dist/lib/apple/AppleDeviceDoctor.rgr +453 -0
  40. package/dist/lib/apple/AppleSigning.rgr +379 -0
  41. package/dist/lib/apple/AppleSimulator.rgr +248 -0
  42. package/dist/lib/apple/AppleTarget.rgr +185 -0
  43. package/dist/lib/apple/AppleToolchain.rgr +458 -0
  44. package/dist/lib/apple/README.md +311 -0
  45. package/dist/lib/apple/apple_test.rgr +669 -0
  46. package/dist/lib/core/README.md +251 -0
  47. package/dist/lib/core/RgBase.rgr +313 -0
  48. package/dist/lib/core/RgNum.rgr +653 -0
  49. package/dist/lib/core/RgText.rgr +680 -0
  50. package/dist/lib/core/RgU32.rgr +309 -0
  51. package/dist/lib/ranger-dir.rgr +2 -0
  52. package/dist/lib/shell_test.rgr +193 -0
  53. package/dist/lib/stdlib.rgr +1176 -665
  54. package/dist/lib/stdops.rgr +2 -0
  55. package/dist/package.json +1 -1
  56. package/dist/rgrc.js +72955 -40753
  57. package/dist/stdops.rgr +2 -0
  58. package/package.json +1121 -339
@@ -1,665 +1,1176 @@
1
-
2
- ; union type operators
3
-
4
- Import "stdops.rgr"
5
- Import "JSON.rgr"
6
-
7
- operators {
8
-
9
- cast _:Any (arg:T target@(noeval):Any) {
10
- templates {
11
- go ( (e 1) )
12
- }
13
- }
14
-
15
- case _@(newcontext):void ( arg@(union):T item2@(define):boolean code:block ) {
16
- templates {
17
- es6 (
18
- (forkctx _ ) (def 2) "if( typeof(" (e 1) ") === 'boolean' ) /* union case for boolean */ {" nl I
19
- "var " (e 2) " = " (e 1) ";" nl
20
- (block 3)
21
- nl i "}"
22
- )
23
- kotlin (
24
- (forkctx _ ) (def 2) "if( " (e 1) " is Boolean ) /* union case for boolean */ {" nl I
25
- "val " (e 2) " : Boolean = " (e 1) " as Boolean;" nl
26
- (block 3)
27
- nl i "}"
28
- )
29
- }
30
- }
31
- case _@(newcontext):void ( arg@(union):T item2@(define):int code:block ) {
32
- templates {
33
- es6 (
34
- (forkctx _ ) (def 2) "if( " "Number.isInteger ? Number.isInteger(" (e 1) ") : (function(v) { return typeof v === 'number' && isFinite(v) && Math.floor(v) === v; })(" (e 1) ")" " ) /* union case for int */ {" nl I
35
- "var " (e 2) " = " (e 1) ";" nl
36
- (block 3)
37
- nl i "}"
38
- )
39
- php (
40
- (forkctx _ ) (def 2) "if( is_int(" (e 1) ") ) {" nl I
41
- (e 2) " = " (e 1) ";" nl
42
- (block 3)
43
- nl i "}"
44
- )
45
- kotlin (
46
- (forkctx _ ) (def 2) "if( " (e 1) " is Int ) /* union case for int */ {" nl I
47
- "val " (e 2) " : Int = " (e 1) " as Int;" nl
48
- (block 3)
49
- nl i "}"
50
- )
51
- }
52
- }
53
- case _@(newcontext):void ( arg@(union):T item2@(define):double code:block ) {
54
- templates {
55
- es6 (
56
- (forkctx _ ) (def 2) "if ( (function(v) { return typeof v === 'number' && isFinite(v); })(" (e 1) "))" " /* union case for double */ {" nl I
57
- "var " (e 2) " = " (e 1) ";" nl
58
- (block 3)
59
- nl i "}"
60
- )
61
- php (
62
- (forkctx _ ) (def 2) "if( is_double(" (e 1) ") ) {" nl I
63
- (e 2) " = " (e 1) ";" nl
64
- (block 3)
65
- nl i "}"
66
- )
67
- kotlin (
68
- (forkctx _ ) (def 2) "if( " (e 1) " is Double ) /* union case for double */ {" nl I
69
- "val " (e 2) " : Double = " (e 1) " as Double;" nl
70
- (block 3)
71
- nl i "}"
72
- )
73
- }
74
- }
75
-
76
- case _@(newcontext):void ( arg@(union):T item2@(define):string code:block ) {
77
- templates {
78
- es6 (
79
- (forkctx _ ) (def 2) "if( typeof(" (e 1) ") === 'string' ) /* union case for string */ {" nl I
80
- "var " (e 2) " = " (e 1) ";" nl
81
- (block 3)
82
- nl i "}"
83
- )
84
- php (
85
- (forkctx _ ) (def 2) "if( is_string(" (e 1) ") ) {" nl I
86
- (e 2) " = " (e 1) ";" nl
87
- (block 3)
88
- nl i "}"
89
- )
90
- kotlin (
91
- (forkctx _ ) (def 2) "if( " (e 1) " is String ) /* union case for string */ {" nl I
92
- "val " (e 2) " : String = " (e 1) " as String;" nl
93
- (block 3)
94
- nl i "}"
95
- )
96
- ranger ( 'case ' (e 1) " " (e 2) ":" (typeof 2) " {" nl
97
- I (block 3) i nl "}" nl
98
- )
99
- }
100
- }
101
- case _@(newcontext):void ( arg@(union):T item@(define):T code:block ) {
102
- templates {
103
- ranger ( "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl
104
- I (block 3) i nl "}" nl
105
- )
106
- php (
107
- (forkctx _ ) (def 2) "if( is_object(" (e 1) ") && get_class(" (e 1) ") == \"" (typeof 2) "\" ) /* union case */ {" nl I
108
- (e 2) " = " (e 1) ";" nl
109
- (block 3)
110
- nl i "}"
111
- )
112
- es6 (
113
- (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) " ) /* union case */ {" nl I
114
- "var " (e 2) " = " (e 1) ";" nl
115
- (block 3)
116
-
117
- nl i "}"
118
- )
119
- go (
120
- (forkctx _ ) (def 2) "switch " (e 1) ".(type) {" nl I
121
- "case " (typeof 2) ":" nl
122
- I nl
123
- "var " (e 2) " " (typeof 2) " = " (e 1) ".(" (typeof 2) ");" nl
124
- (block 3)
125
- i nl
126
- nl i "}"
127
- )
128
- csharp (
129
- (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) {" nl I
130
- (typeof 2) " " (e 2) " = (" (typeof 2) ")" (e 1) ";" nl
131
- (block 3)
132
- nl i "}"
133
- )
134
- swift3 (
135
- (forkctx _ ) (def 2) "if type(of: " (e 1) ") == " (typeof 2) ".self {" nl I
136
- "let " (e 2) " = " (e 1) " as! " (typeof 2)";" nl
137
- (block 3)
138
-
139
- nl i "}"
140
- )
141
- java7 (
142
- (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) ") {" nl I
143
- (typeof 2) " " (e 2) " = (" (typeof 2) ") " (e 1) ";" nl
144
- (block 3)
145
-
146
- nl i "}"
147
- )
148
- kotlin (
149
- (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
150
- "val " (e 2) " : " (typeof 2) " = " (e 1) " as " (typeof 2) ";" nl
151
- (block 3)
152
- nl i "}"
153
- )
154
- cpp (
155
- (forkctx _ ) (def 2) "if( mpark::holds_alternative<" (typeof 2) ">(" (e 1) ") ) {" nl I
156
- (typeof 2) " " (e 2) " = mpark::get<" (typeof 2) ">(" (e 1) ");" nl
157
- (block 3)
158
-
159
- nl i "}"
160
-
161
- (plugin 'makefile' ((dep 'variant.hpp' 'https://github.com/mpark/variant/releases/download/v1.2.2/variant.hpp')))
162
- )
163
- scala (
164
- (forkctx _ ) (def 2) (e 1) " match {" nl
165
- I "case " (e 2) " : " (typeof 2) " => {" nl I
166
- (block 3)
167
- nl i "}" nl
168
- "case _ => {} " nl i
169
- "}" nl
170
- )
171
-
172
- }
173
- }
174
- to _:T ( to@(union noeval):T item:T) {
175
- templates {
176
- cpp.disabled ( "(r_create_union<" (typeof 1) ", " (typeof 2)">(" (e 2) "))"
177
- (create_polyfill
178
- '
179
- template<typename T, typename S>
180
- T r_create_union (S value) {
181
- T rv;
182
- rv = value;
183
- return rv;
184
- };
185
- '
186
- )
187
- )
188
- * ( (e 2) )
189
- }
190
- }
191
- }
192
-
193
-
194
- operator type:[string:T] all {
195
- fn forEach:void (cb:(_:void (item:T index:string )) ) {
196
- def list (keys self)
197
- for list kk:string i {
198
- def value (unwrap (get self kk))
199
- cb( value kk )
200
- }
201
- }
202
- fn forKeys:void (cb:(_:void (index:string))) {
203
- def list (keys self)
204
- for list it:string i {
205
- cb(it)
206
- }
207
- }
208
- }
209
-
210
- ; commented out native ops, because they are not compatible with async operators
211
- operator type:[T] all {
212
-
213
- ; pure function or operator could be simply inlined...
214
- fn forEach@(pure):void (cb:(_:void (item:T index:int))) @doc('Call `fb` for each item in array') {
215
- for self it:T i {
216
- cb(it i)
217
- }
218
- }
219
-
220
- fn has:boolen ( el:T) {
221
- def idx (indexOf el)
222
- return (idx >= 0)
223
- }
224
-
225
- fn map:[T] (cb:(_:T (item:T index:int))) {
226
- def len (array_length self)
227
- def res:[T]
228
- for self it:T i {
229
- push res (cb(it i))
230
- }
231
- return res
232
- }
233
-
234
- fn map:[S] (cb:(_:S (item:T index:int)) to@(noeval):[S] ) {
235
- def len (array_length self)
236
- def res:[S]
237
- for self it:T i {
238
- push res (cb(it i))
239
- }
240
- return res
241
- }
242
-
243
- fn filter:[T] (cb:(_:boolean (item:T index:int))) {
244
- def res:[T]
245
- for self it:T i {
246
- if( cb(it i) ) {
247
- push res it
248
- }
249
- }
250
- return res
251
- }
252
- fn reduce@(weak):T (cb:(_:T (left:T right:T index:int)) initialValue:T) {
253
- def len (array_length self)
254
- def res:T initialValue
255
- if( len >= 1 ) {
256
- for self it:T i {
257
- res = ( cb ( res it i))
258
- }
259
- }
260
- return res
261
- }
262
- fn reduce@(weak):K (cb:(_:K (left:K right:T index:int)) initialValue:K) {
263
- def len (array_length self)
264
- def res initialValue
265
- if( len >= 1 ) {
266
- for self it:T i {
267
- res = ( cb ( res it i ))
268
- }
269
- }
270
- return res
271
- }
272
-
273
- fn groupBy:[T] ( cb:(_:string (item:T)) ) {
274
- def res:[T]
275
- def mapper:[string:boolean]
276
- for self it:T i {
277
- def key (cb(it))
278
- if( false == ( has mapper key ) ) {
279
- push res it
280
- set mapper key true
281
- }
282
- }
283
- return res
284
- }
285
-
286
- fn clone:[T] () {
287
- def res:[T]
288
- for self it:T i {
289
- push res it
290
- }
291
- return res
292
- }
293
-
294
-
295
- ; some useful functions from scala
296
- fn find@(optional):T (cb:(_:boolean (item:T))) {
297
- def res@(optional):T
298
- for self it@(lives):T i {
299
- if( cb(it) ) {
300
- def res2@(optional):T
301
- res2 = it
302
- return res2
303
- }
304
- }
305
- return res
306
- }
307
-
308
- fn count:int (cb:(_:boolean (item:T))) {
309
- def res 0
310
- for self it@(lives):T i {
311
- if( cb(it) ) {
312
- res = res + 1
313
- }
314
- }
315
- return res
316
- }
317
-
318
- fn contains:boolean (cb:(_:boolean (item:T))) {
319
- for self it@(lives):T i {
320
- if( cb(it) ) {
321
- return true
322
- }
323
- }
324
- return false
325
- }
326
-
327
-
328
- }
329
-
330
- ; immutable map type
331
- trait Map @params( K T S ) {
332
- def elements@(weak):[K:T]
333
- }
334
-
335
- trait Vector @params( T S ) {
336
-
337
- def start:int 0
338
- def cardinality 3
339
- def end:int 0
340
- def elements@(weak):[T]
341
- def parent@(weak):S
342
-
343
- ; inserting a new element inside the array
344
- ; you can re-use the arrays but the index ranges will change
345
-
346
- fn localCopy:S () {
347
- def obj (new S)
348
- obj.start = start
349
- obj.end = end
350
- obj.parent = this.parent
351
- obj.cardinality = cardinality
352
- obj.elements = elements
353
- return obj
354
- }
355
-
356
- fn set:S (idx:int item:T) {
357
-
358
- if( idx >= start ) {
359
- def res (this.localCopy())
360
- res.elements = (make _:[T] (res.cardinality) item)
361
- for elements e@(lives):T i {
362
- if ( (res.start + i) != idx ) {
363
- set res.elements i e
364
- } {
365
- set res.elements i item
366
- }
367
- }
368
- return res
369
- }
370
- def root (this.localCopy())
371
- def res root
372
-
373
- def p@(weak):S parent
374
- while( (!null? p) && (idx < p.start) ) {
375
- def newSlice@(lives) (p.localCopy())
376
- res.parent = newSlice
377
- res = newSlice
378
- if(!null? p.parent) {
379
- p = p.parent
380
- }
381
- }
382
- def newSlice@(lives) (p.localCopy())
383
- newSlice.elements = (make _:[T] (newSlice.cardinality) item)
384
- for p.elements e@(lives):T i {
385
- set newSlice.elements i e
386
- }
387
- set newSlice.elements (idx - newSlice.start) item
388
- res.parent = newSlice
389
- return root
390
- }
391
-
392
- fn insert:S (idx:int item:T) {
393
- if( idx >= start ) {
394
- def res (this.localCopy())
395
- def use_card cardinality
396
- if( ( array_length res.elements) >= (use_card - 1) ) {
397
- use_card = ( array_length res.elements) + 1
398
- }
399
- res.elements = (make _:[T] (use_card) item)
400
- for elements e@(lives):T i {
401
- if ( res.start + i < idx ) {
402
- set res.elements i e
403
- } {
404
- if( idx == ( res.start + i )) {
405
- set res.elements i item
406
- set res.elements (i + 1) e
407
- } {
408
- set res.elements (i + 1) e
409
- }
410
- }
411
- }
412
- if( (idx - start) >= (array_length elements)) {
413
- set res.elements (idx - start) item
414
- }
415
- res.start = start
416
- res.end = end + 1
417
- res.cardinality = use_card
418
- return res
419
- }
420
- def root (this.localCopy())
421
- def res root
422
- res.start = start + 1
423
- res.end = end + 1
424
- def p@(weak):S parent
425
- while( (!null? p) && (idx < p.start) ) {
426
- def newSlice@(lives) (p.localCopy())
427
- newSlice.start = newSlice.start + 1
428
- newSlice.end = newSlice.end + 1
429
- res.parent = newSlice
430
- res = newSlice
431
- if(!null? p.parent) {
432
- p = p.parent
433
- }
434
- }
435
-
436
- def newSlice@(lives) (p.localCopy())
437
- def use_card newSlice.cardinality
438
- if( ( array_length p.elements) >= (use_card - 1) ) {
439
- use_card = ( array_length p.elements) + 1
440
- }
441
- newSlice.elements = (make _:[T] (use_card) item)
442
- for p.elements e@(lives):T i {
443
- if ( newSlice.start + i < idx ) {
444
- set newSlice.elements i e
445
- } {
446
- if( idx == ( newSlice.start + i )) {
447
- set newSlice.elements i item
448
- set newSlice.elements (i + 1) e
449
- } {
450
- set newSlice.elements (i + 1) e
451
- }
452
- }
453
- }
454
-
455
- newSlice.end = newSlice.end + 1
456
- newSlice.cardinality = use_card
457
- if ( (idx - newSlice.start) >= p.cardinality ) {
458
- newSlice.end = idx + 1
459
- }
460
- newSlice.parent = p.parent
461
- res.parent = newSlice
462
- return root
463
- }
464
-
465
- fn get:T (idx:int) {
466
- if( idx < 0 ) {
467
- ; should be runtime error here...
468
- return (itemAt elements 0)
469
- }
470
- if( idx >= start && idx < end ) {
471
- return (itemAt elements (idx - start))
472
- }
473
- def p@(weak):S parent
474
- while( (!null? p) && (idx < p.start) ) {
475
- p = p.parent
476
- }
477
- if(!null? p ) {
478
- return (itemAt p.elements (idx - p.start))
479
- }
480
- return (itemAt elements 0)
481
- }
482
- fn add:S (item:T) {
483
- if((end - start) >= cardinality) {
484
- def res (new S)
485
- res.start = this.end
486
- res.end = (this.end + 1)
487
- res.parent = this
488
- res.cardinality = (cardinality + 1)
489
- res.elements = (make _:[T] (res.cardinality) item)
490
- set res.elements 0 item
491
- return res
492
- }
493
- def res (new S)
494
- res.elements = (make _:[T] (cardinality) item)
495
- for elements e@(lives):T i {
496
- set res.elements i e
497
- }
498
- set res.elements (end - start) item
499
- res.parent = parent
500
- res.start = start
501
- res.end = end + 1
502
- res.cardinality = cardinality
503
- return res
504
- }
505
-
506
- fn count:int () {
507
- return end
508
- }
509
-
510
- ; TODO: create faster version which uses (make ) operator
511
- fn map:S (cb:(_:T (item:T)) ) {
512
- def res:S (new S)
513
- def cnt (this.count())
514
- def i 0
515
- while( i < cnt ) {
516
- def item (this.get(i))
517
- def new_value (cb(item))
518
- res = (res.add(new_value))
519
- i = i + 1
520
- }
521
- return res
522
- }
523
- }
524
-
525
-
526
- operator type:Vector all {
527
-
528
- ; TODO: strict type checking for this
529
- ; fn for (iIndex@(ignore):T iteIndex@(ignore):int code:block ) (
530
- ; "def " (e 3) ":int 0" nl
531
- ; "def loop_cnt (" (e 1) ".count())" nl
532
- ; "while( " (e 3) " < loop_cnt ) {" nl
533
- ; I
534
- ; "def " (e 2) " (" (e 1) ".get(" (e 3) "))" nl
535
- ; (block 4)
536
- ; (e 3) " = " (e 3) " + 1" nl
537
- ; i
538
- ; "}" nl
539
- ; )
540
-
541
- fn indexOf:int ( elem:T ) {
542
- def cnt (self.count())
543
- def i 0
544
- while( i < cnt ) {
545
- def item (itemAt self i)
546
- if(item == elem) {
547
- return i
548
- }
549
- i = i + 1
550
- }
551
- return -1
552
- }
553
- fn clear:T (idx:int) {
554
- ; def val (self.get(idx))
555
- return (new T)
556
- }
557
-
558
- fn itemAt:T (idx:int) {
559
- def val (self.get(idx))
560
- return val
561
- }
562
- fn at:T (idx:int) {
563
- def val (self.get(idx))
564
- return val
565
- }
566
- fn push:S (item:T) {
567
- return (self.add(item))
568
- }
569
- fn last:T () {
570
- return (itemAt self ((self.count()) - 1) )
571
- }
572
- fn array_length:int () {
573
- return (self.count())
574
- }
575
- fn length:int () {
576
- return (self.count())
577
- }
578
- fn size:int () {
579
- return (self.count())
580
- }
581
- fn forEach:void (cb:(_:void (item:T))) {
582
- def cnt (self.count())
583
- def i 0
584
- while( i < cnt ) {
585
- def item (itemAt self i)
586
- cb(item)
587
- i = i + 1
588
- }
589
- }
590
-
591
- fn forUntil:void (cb:(_:boolean (item:T))) {
592
- def cnt (self.count())
593
- def i 0
594
- while( i < cnt ) {
595
- def item (itemAt self i)
596
- if( (cb(item)) == false ) {
597
- return
598
- }
599
- i = i + 1
600
- }
601
- }
602
-
603
- fn map:S ( cb:(_:T (item:T)) ) {
604
- def res (new S)
605
- def cnt (self.count())
606
- def i 0
607
- while( i < cnt ) {
608
- def item (itemAt self i)
609
- def value (cb(item))
610
- res = res.add(value)
611
- i = i + 1
612
- }
613
- return res
614
- }
615
-
616
- ; TODO: faster version ....
617
- fn map:[K] (cb:(_:K (item:T)) to@(noeval):[K] ) {
618
- def res:[K]
619
- def cnt (self.count())
620
- def i 0
621
- while( i < cnt ) {
622
- def item (itemAt self i)
623
- push res (cb(item))
624
- i = i + 1
625
- }
626
- return res
627
- }
628
-
629
-
630
- }
631
-
632
- operator type:Map all {
633
- fn keys:[K] () {
634
- return (keys self.elements)
635
- }
636
- fn get@(optional):T (key:K) {
637
- return (get self.elements key)
638
- }
639
- fn has:boolean (key:K) {
640
- return (has self.elements key)
641
- }
642
- fn set:S (key:K value:T) {
643
- def c (new S)
644
- def keys ( keys self.elements)
645
- for keys k:string i {
646
- if(k==key) {
647
-
648
- } {
649
- set c.elements k (unwrap (get self.elements k))
650
- }
651
- }
652
- set c.elements key value
653
- return c
654
- }
655
- fn forEach@(weak):S ( cb:(_:void (item:T index:K)) ) {
656
- def keys (keys self.elements)
657
- for keys key:K i {
658
- cb( (unwrap (get self.elements key)) key )
659
- }
660
- return self
661
- }
662
-
663
- }
664
-
665
-
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+
4
+ ; union type operators
5
+
6
+ Import "stdops.rgr"
7
+ Import "JSON.rgr"
8
+
9
+ operators {
10
+
11
+ cast _:Any (arg:T target@(noeval):Any) {
12
+ templates {
13
+ go ( (e 1) )
14
+ }
15
+ }
16
+
17
+ case _@(newcontext):void ( arg@(union):T item2@(define):boolean code:block ) {
18
+ templates {
19
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
20
+ ; A union that holds a primitive is not sealable, so its Go type is
21
+ ; interface{} and there is no tag struct: the generic overload below
22
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
23
+ ; syntax. A type assertion is the narrowing here.
24
+ go (
25
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
26
+ "_ = " (e 2) ";" nl
27
+ (block 3)
28
+ nl i "}"
29
+ )
30
+ dart (
31
+ (forkctx _ ) (def 2) "if( " (e 1) " is bool ) /* union case for boolean */ {" nl I
32
+ "bool " (e 2) " = " (e 1) " as bool;" nl
33
+ (block 3)
34
+ nl i "}"
35
+ )
36
+ cpp (
37
+ (forkctx _ ) (def 2) "if( std::holds_alternative<bool>(" (e 1) ") ) /* union case for boolean */ {" nl I
38
+ "bool " (e 2) " = std::get<bool>(" (e 1) ");" nl
39
+ (block 3)
40
+ nl i "}"
41
+ )
42
+ es6 (
43
+ (forkctx _ ) (def 2) "if( typeof(" (e 1) ") === 'boolean' ) /* union case for boolean */ {" nl I
44
+ "var " (e 2) " = " (e 1) ";" nl
45
+ (block 3)
46
+ nl i "}"
47
+ )
48
+ kotlin (
49
+ (forkctx _ ) (def 2) "if( " (e 1) " is Boolean ) /* union case for boolean */ {" nl I
50
+ "val " (e 2) " : Boolean = " (e 1) " as Boolean;" nl
51
+ (block 3)
52
+ nl i "}"
53
+ )
54
+ python (
55
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", bool):" nl I
56
+ (e 2) " = " (e 1) nl
57
+ (block 3)
58
+ nl i
59
+ )
60
+ rust (
61
+ (forkctx _ ) (def 2) "if let RJson::Bool(" (e 2) ") = &" (e 1) " {" nl I
62
+ "let " (e 2) " : bool = *" (e 2) ";" nl
63
+ (block 3)
64
+ nl i "}"
65
+ )
66
+ }
67
+ }
68
+ case _@(newcontext):void ( arg@(union):T item2@(define):int code:block ) {
69
+ templates {
70
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
71
+ ; A union that holds a primitive is not sealable, so its Go type is
72
+ ; interface{} and there is no tag struct: the generic overload below
73
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
74
+ ; syntax. A type assertion is the narrowing here.
75
+ go (
76
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
77
+ "_ = " (e 2) ";" nl
78
+ (block 3)
79
+ nl i "}"
80
+ )
81
+ dart (
82
+ (forkctx _ ) (def 2) "if( " (e 1) " is int ) /* union case for int */ {" nl I
83
+ "int " (e 2) " = " (e 1) " as int;" nl
84
+ (block 3)
85
+ nl i "}"
86
+ )
87
+ cpp (
88
+ (forkctx _ ) (def 2) "if( std::holds_alternative<int>(" (e 1) ") ) /* union case for int */ {" nl I
89
+ "int " (e 2) " = std::get<int>(" (e 1) ");" nl
90
+ (block 3)
91
+ nl i "}"
92
+ )
93
+ es6 (
94
+ (forkctx _ ) (def 2) "if( " "Number.isInteger ? Number.isInteger(" (e 1) ") : (function(v) { return typeof v === 'number' && isFinite(v) && Math.floor(v) === v; })(" (e 1) ")" " ) /* union case for int */ {" nl I
95
+ "var " (e 2) " = " (e 1) ";" nl
96
+ (block 3)
97
+ nl i "}"
98
+ )
99
+ php (
100
+ (forkctx _ ) (def 2) "if( is_int(" (e 1) ") ) {" nl I
101
+ (e 2) " = " (e 1) ";" nl
102
+ (block 3)
103
+ nl i "}"
104
+ )
105
+ kotlin (
106
+ (forkctx _ ) (def 2) "if( " (e 1) " is Int ) /* union case for int */ {" nl I
107
+ "val " (e 2) " : Int = " (e 1) " as Int;" nl
108
+ (block 3)
109
+ nl i "}"
110
+ )
111
+ python (
112
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", int) and not isinstance(" (e 1) ", bool):" nl I
113
+ (e 2) " = " (e 1) nl
114
+ (block 3)
115
+ nl i
116
+ )
117
+ rust (
118
+ (forkctx _ ) (def 2) "if let RJson::Int(" (e 2) ") = &" (e 1) " {" nl I
119
+ "let " (e 2) " : i64 = *" (e 2) ";" nl
120
+ (block 3)
121
+ nl i "}"
122
+ )
123
+ }
124
+ }
125
+ case _@(newcontext):void ( arg@(union):T item2@(define):double code:block ) {
126
+ templates {
127
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
128
+ ; A union that holds a primitive is not sealable, so its Go type is
129
+ ; interface{} and there is no tag struct: the generic overload below
130
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
131
+ ; syntax. A type assertion is the narrowing here.
132
+ go (
133
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
134
+ "_ = " (e 2) ";" nl
135
+ (block 3)
136
+ nl i "}"
137
+ )
138
+ dart (
139
+ (forkctx _ ) (def 2) "if( " (e 1) " is double ) /* union case for double */ {" nl I
140
+ "double " (e 2) " = " (e 1) " as double;" nl
141
+ (block 3)
142
+ nl i "}"
143
+ )
144
+ cpp (
145
+ (forkctx _ ) (def 2) "if( std::holds_alternative<double>(" (e 1) ") ) /* union case for double */ {" nl I
146
+ "double " (e 2) " = std::get<double>(" (e 1) ");" nl
147
+ (block 3)
148
+ nl i "}"
149
+ )
150
+ es6 (
151
+ (forkctx _ ) (def 2) "if ( (function(v) { return typeof v === 'number' && isFinite(v); })(" (e 1) "))" " /* union case for double */ {" nl I
152
+ "var " (e 2) " = " (e 1) ";" nl
153
+ (block 3)
154
+ nl i "}"
155
+ )
156
+ php (
157
+ (forkctx _ ) (def 2) "if( is_double(" (e 1) ") ) {" nl I
158
+ (e 2) " = " (e 1) ";" nl
159
+ (block 3)
160
+ nl i "}"
161
+ )
162
+ kotlin (
163
+ (forkctx _ ) (def 2) "if( " (e 1) " is Double ) /* union case for double */ {" nl I
164
+ "val " (e 2) " : Double = " (e 1) " as Double;" nl
165
+ (block 3)
166
+ nl i "}"
167
+ )
168
+ python (
169
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", float):" nl I
170
+ (e 2) " = " (e 1) nl
171
+ (block 3)
172
+ nl i
173
+ )
174
+ rust (
175
+ (forkctx _ ) (def 2) "if let RJson::Double(" (e 2) ") = &" (e 1) " {" nl I
176
+ "let " (e 2) " : f64 = *" (e 2) ";" nl
177
+ (block 3)
178
+ nl i "}"
179
+ )
180
+ }
181
+ }
182
+
183
+ case _@(newcontext):void ( arg@(union):T item2@(define):string code:block ) {
184
+ templates {
185
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
186
+ ; A union that holds a primitive is not sealable, so its Go type is
187
+ ; interface{} and there is no tag struct: the generic overload below
188
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
189
+ ; syntax. A type assertion is the narrowing here.
190
+ go (
191
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
192
+ "_ = " (e 2) ";" nl
193
+ (block 3)
194
+ nl i "}"
195
+ )
196
+ dart (
197
+ (forkctx _ ) (def 2) "if( " (e 1) " is String ) /* union case for string */ {" nl I
198
+ "String " (e 2) " = " (e 1) " as String;" nl
199
+ (block 3)
200
+ nl i "}"
201
+ )
202
+ cpp (
203
+ (forkctx _ ) (def 2) "if( std::holds_alternative<std::string>(" (e 1) ") ) /* union case for string */ {" nl I
204
+ "std::string " (e 2) " = std::get<std::string>(" (e 1) ");" nl
205
+ (block 3)
206
+ nl i "}"
207
+ )
208
+ es6 (
209
+ (forkctx _ ) (def 2) "if( typeof(" (e 1) ") === 'string' ) /* union case for string */ {" nl I
210
+ "var " (e 2) " = " (e 1) ";" nl
211
+ (block 3)
212
+ nl i "}"
213
+ )
214
+ php (
215
+ (forkctx _ ) (def 2) "if( is_string(" (e 1) ") ) {" nl I
216
+ (e 2) " = " (e 1) ";" nl
217
+ (block 3)
218
+ nl i "}"
219
+ )
220
+ kotlin (
221
+ (forkctx _ ) (def 2) "if( " (e 1) " is String ) /* union case for string */ {" nl I
222
+ "val " (e 2) " : String = " (e 1) " as String;" nl
223
+ (block 3)
224
+ nl i "}"
225
+ )
226
+ python (
227
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", str):" nl I
228
+ (e 2) " = " (e 1) nl
229
+ (block 3)
230
+ nl i
231
+ )
232
+ rust (
233
+ (forkctx _ ) (def 2) "if let RJson::Str(" (e 2) ") = &" (e 1) " {" nl I
234
+ "let " (e 2) " : String = " (e 2) ".clone();" nl
235
+ (block 3)
236
+ nl i "}"
237
+ )
238
+ ranger ( 'case ' (e 1) " " (e 2) ":" (typeof 2) " {" nl
239
+ I (block 3) i nl "}" nl
240
+ )
241
+ }
242
+ }
243
+ ; A member of a system union -- the JSON unions over JSONDataObject and
244
+ ; JSONArrayObject -- is an ordinary object of the target language. It
245
+ ; carries no shape tag, so the generic overload below, which narrows on
246
+ ; __rg_kind / _rg_kind / .tag, can never be true for one. These two
247
+ ; overloads keep the class test that a system union needs; the generic
248
+ ; overload keeps the tag test that a shape case needs.
249
+ ; Every `@serialize` deserializer emits `case item oo:JSONDataObject`,
250
+ ; so without these the reader of an array of objects reads nothing.
251
+ case _@(newcontext):void ( arg@(union):T item2@(define):JSONDataObject code:block ) {
252
+ templates {
253
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
254
+ ; A union that holds a primitive is not sealable, so its Go type is
255
+ ; interface{} and there is no tag struct: the generic overload below
256
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
257
+ ; syntax. A type assertion is the narrowing here.
258
+ go (
259
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
260
+ "_ = " (e 2) ";" nl
261
+ (block 3)
262
+ nl i "}"
263
+ )
264
+ ranger ( "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl
265
+ I (block 3) i nl "}" nl
266
+ )
267
+ php (
268
+ (forkctx _ ) (def 2) "if( is_object(" (e 1) ") && get_class(" (e 1) ") == \"" (typeof 2) "\" ) /* union case */ {" nl I
269
+ (e 2) " = " (e 1) ";" nl
270
+ (block 3)
271
+ nl i "}"
272
+ )
273
+ es6 (
274
+ (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) " ) /* union case */ {" nl I
275
+ "var " (e 2) " = " (e 1) ";" nl
276
+ (block 3)
277
+
278
+ nl i "}"
279
+ )
280
+ go (
281
+ (forkctx _ ) (def 2) "switch " (e 1) ".(type) {" nl I
282
+ "case " (typeof 2) ":" nl
283
+ I nl
284
+ "var " (e 2) " " (typeof 2) " = " (e 1) ".(" (typeof 2) ");" nl
285
+ ; Go rejects a declared-and-unused local, and an arm
286
+ ; that only tests the type never reads the binding.
287
+ "_ = " (e 2) ";" nl
288
+ (block 3)
289
+ i nl
290
+ nl i "}"
291
+ )
292
+ csharp (
293
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) {" nl I
294
+ (typeof 2) " " (e 2) " = (" (typeof 2) ")" (e 1) ";" nl
295
+ (block 3)
296
+ nl i "}"
297
+ )
298
+ swift3 (
299
+ (forkctx _ ) (def 2) "if type(of: " (e 1) ") == " (typeof 2) ".self {" nl I
300
+ "let " (e 2) " = " (e 1) " as! " (typeof 2)";" nl
301
+ (block 3)
302
+
303
+ nl i "}"
304
+ )
305
+ swift6 (
306
+ (forkctx _ ) (def 2) "if type(of: " (e 1) ") == " (typeof 2) ".self {" nl I
307
+ "let " (e 2) " = " (e 1) " as! " (typeof 2)";" nl
308
+ (block 3)
309
+
310
+ nl i "}"
311
+ )
312
+ java7 (
313
+ (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) ") {" nl I
314
+ (typeof 2) " " (e 2) " = (" (typeof 2) ") " (e 1) ";" nl
315
+ (block 3)
316
+
317
+ nl i "}"
318
+ )
319
+ kotlin (
320
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
321
+ "val " (e 2) " : " (typeof 2) " = " (e 1) " as " (typeof 2) ";" nl
322
+ (block 3)
323
+ nl i "}"
324
+ )
325
+ python (
326
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", " (typeof 2) "):" nl I
327
+ (e 2) " = " (e 1) nl
328
+ (block 3)
329
+ nl i
330
+ )
331
+ cpp (
332
+ (forkctx _ ) (def 2) "if( std::holds_alternative<" (typeof 2) ">(" (e 1) ") ) {" nl I
333
+ (typeof 2) " " (e 2) " = std::get<" (typeof 2) ">(" (e 1) ");" nl
334
+ (block 3)
335
+
336
+ nl i "}"
337
+ )
338
+ scala (
339
+ (forkctx _ ) (def 2) (e 1) " match {" nl
340
+ I "case " (e 2) " : " (typeof 2) " => {" nl I
341
+ (block 3)
342
+ nl i "}" nl
343
+ "case _ => {} " nl i
344
+ "}" nl
345
+ )
346
+ dart (
347
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
348
+ (typeof 2) " " (e 2) " = " (e 1) " as " (typeof 2) ";" nl
349
+ (block 3)
350
+ nl i "}"
351
+ )
352
+ rust (
353
+ (forkctx _ ) (def 2) "if let " (typeof 1) "::" (typeof 2) "(" (e 2) ") = " (e 1) ".clone() { /* union case */" nl I
354
+ (block 3)
355
+ nl i "}"
356
+ )
357
+
358
+ }
359
+ }
360
+ case _@(newcontext):void ( arg@(union):T item2@(define):JSONArrayObject code:block ) {
361
+ templates {
362
+ llvm ( nl "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl I (block 3) nl i "}" nl )
363
+ ; A union that holds a primitive is not sealable, so its Go type is
364
+ ; interface{} and there is no tag struct: the generic overload below
365
+ ; wrote `x.tag == interface{}_tag_string`, which is not even Go
366
+ ; syntax. A type assertion is the narrowing here.
367
+ go (
368
+ (forkctx _ ) (def 2) "if " (e 2) ", __rg_ok := " (e 1) ".(" (typeof 2) "); __rg_ok { /* union case */" nl I
369
+ "_ = " (e 2) ";" nl
370
+ (block 3)
371
+ nl i "}"
372
+ )
373
+ ranger ( "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl
374
+ I (block 3) i nl "}" nl
375
+ )
376
+ php (
377
+ (forkctx _ ) (def 2) "if( is_object(" (e 1) ") && get_class(" (e 1) ") == \"" (typeof 2) "\" ) /* union case */ {" nl I
378
+ (e 2) " = " (e 1) ";" nl
379
+ (block 3)
380
+ nl i "}"
381
+ )
382
+ es6 (
383
+ (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) " ) /* union case */ {" nl I
384
+ "var " (e 2) " = " (e 1) ";" nl
385
+ (block 3)
386
+
387
+ nl i "}"
388
+ )
389
+ go (
390
+ (forkctx _ ) (def 2) "switch " (e 1) ".(type) {" nl I
391
+ "case " (typeof 2) ":" nl
392
+ I nl
393
+ "var " (e 2) " " (typeof 2) " = " (e 1) ".(" (typeof 2) ");" nl
394
+ ; Go rejects a declared-and-unused local, and an arm
395
+ ; that only tests the type never reads the binding.
396
+ "_ = " (e 2) ";" nl
397
+ (block 3)
398
+ i nl
399
+ nl i "}"
400
+ )
401
+ csharp (
402
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) {" nl I
403
+ (typeof 2) " " (e 2) " = (" (typeof 2) ")" (e 1) ";" nl
404
+ (block 3)
405
+ nl i "}"
406
+ )
407
+ swift3 (
408
+ (forkctx _ ) (def 2) "if type(of: " (e 1) ") == " (typeof 2) ".self {" nl I
409
+ "let " (e 2) " = " (e 1) " as! " (typeof 2)";" nl
410
+ (block 3)
411
+
412
+ nl i "}"
413
+ )
414
+ swift6 (
415
+ (forkctx _ ) (def 2) "if type(of: " (e 1) ") == " (typeof 2) ".self {" nl I
416
+ "let " (e 2) " = " (e 1) " as! " (typeof 2)";" nl
417
+ (block 3)
418
+
419
+ nl i "}"
420
+ )
421
+ java7 (
422
+ (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) ") {" nl I
423
+ (typeof 2) " " (e 2) " = (" (typeof 2) ") " (e 1) ";" nl
424
+ (block 3)
425
+
426
+ nl i "}"
427
+ )
428
+ kotlin (
429
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
430
+ "val " (e 2) " : " (typeof 2) " = " (e 1) " as " (typeof 2) ";" nl
431
+ (block 3)
432
+ nl i "}"
433
+ )
434
+ python (
435
+ (forkctx _ ) (def 2) "if isinstance(" (e 1) ", " (typeof 2) "):" nl I
436
+ (e 2) " = " (e 1) nl
437
+ (block 3)
438
+ nl i
439
+ )
440
+ cpp (
441
+ (forkctx _ ) (def 2) "if( std::holds_alternative<" (typeof 2) ">(" (e 1) ") ) {" nl I
442
+ (typeof 2) " " (e 2) " = std::get<" (typeof 2) ">(" (e 1) ");" nl
443
+ (block 3)
444
+
445
+ nl i "}"
446
+ )
447
+ scala (
448
+ (forkctx _ ) (def 2) (e 1) " match {" nl
449
+ I "case " (e 2) " : " (typeof 2) " => {" nl I
450
+ (block 3)
451
+ nl i "}" nl
452
+ "case _ => {} " nl i
453
+ "}" nl
454
+ )
455
+ dart (
456
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
457
+ (typeof 2) " " (e 2) " = " (e 1) " as " (typeof 2) ";" nl
458
+ (block 3)
459
+ nl i "}"
460
+ )
461
+ rust (
462
+ (forkctx _ ) (def 2) "if let " (typeof 1) "::" (typeof 2) "(" (e 2) ") = " (e 1) ".clone() { /* union case */" nl I
463
+ (block 3)
464
+ nl i "}"
465
+ )
466
+
467
+ }
468
+ }
469
+ case _@(newcontext):void ( arg@(union):T item@(define):T code:block ) {
470
+ templates {
471
+ ranger ( "case " (e 1) " " (e 2) ":" (typeof 2) " {" nl
472
+ I (block 3) i nl "}" nl
473
+ )
474
+ php (
475
+ (forkctx _ ) (def 2) "if( is_object(" (e 1) ") && get_class(" (e 1) ") == \"" (typeof 2) "\" ) /* union case */ {" nl I
476
+ (e 2) " = " (e 1) ";" nl
477
+ (block 3)
478
+ nl i "}"
479
+ )
480
+ es6 (
481
+ ; S5 FlatTaggedObject: narrow on the stable kind tag. Sealable
482
+ ; union members declare/set __rg_kind; a dual instanceof OR
483
+ ; would defeat TypeScript control-flow narrowing.
484
+ (forkctx _ ) (def 2) "if( " (e 1) " != null && " (e 1) ".__rg_kind === \"" (typeof 2) "\" ) /* union case */ {" nl I
485
+ "var " (e 2) " = " (e 1) ";" nl
486
+ (block 3)
487
+
488
+ nl i "}"
489
+ )
490
+ go (
491
+ ; S5 tagged struct: narrow on the tag, bind the variant pointer.
492
+ (forkctx _ ) (def 2) "if " (e 1) ".tag == " (typeof 1) "_tag_" (rawtype 2) " { /* union case */" nl I
493
+ "var " (e 2) " " (typeof 2) " = " (e 1) "." (rawtype 2) ";" nl
494
+ ; Go rejects a declared-and-unused local, and an arm
495
+ ; that only tests the type never reads the binding.
496
+ "_ = " (e 2) ";" nl
497
+ (block 3)
498
+ nl i "}"
499
+ )
500
+ csharp (
501
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) {" nl I
502
+ (typeof 2) " " (e 2) " = (" (typeof 2) ")" (e 1) ";" nl
503
+ (block 3)
504
+ nl i "}"
505
+ )
506
+ swift3 (
507
+ (forkctx _ ) (def 2) "if case let ." (rawtype 2) "(" (e 2) ") = " (e 1) " { /* union case */" nl I
508
+ (block 3)
509
+ nl i "}"
510
+ )
511
+ swift6 (
512
+ (forkctx _ ) (def 2) "if case let ." (rawtype 2) "(" (e 2) ") = " (e 1) " { /* union case */" nl I
513
+ (block 3)
514
+ nl i "}"
515
+ )
516
+ java7 (
517
+ (forkctx _ ) (def 2) "if( " (e 1) " instanceof " (typeof 2) ") {" nl I
518
+ (typeof 2) " " (e 2) " = (" (typeof 2) ") " (e 1) ";" nl
519
+ (block 3)
520
+
521
+ nl i "}"
522
+ )
523
+ kotlin (
524
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
525
+ "val " (e 2) " : " (typeof 2) " = " (e 1) " as " (typeof 2) ";" nl
526
+ (block 3)
527
+ nl i "}"
528
+ )
529
+ python (
530
+ ; S5 FlatTaggedObject: narrow on _rg_kind (single underscore —
531
+ ; __rg_kind would be Python-mangled on the instance).
532
+ (forkctx _ ) (def 2) "if " (e 1) " is not None and getattr(" (e 1) ", \"_rg_kind\", None) == \"" (typeof 2) "\":" nl I
533
+ (e 2) " = " (e 1) nl
534
+ (block 3)
535
+ nl i
536
+ )
537
+ cpp (
538
+ (forkctx _ ) (def 2) "if( std::holds_alternative<" (typeof 2) ">(" (e 1) ") ) {" nl I
539
+ (typeof 2) " " (e 2) " = std::get<" (typeof 2) ">(" (e 1) ");" nl
540
+ (block 3)
541
+
542
+ nl i "}"
543
+ )
544
+ scala (
545
+ (forkctx _ ) (def 2) (e 1) " match {" nl
546
+ I "case " (e 2) " : " (typeof 2) " => {" nl I
547
+ (block 3)
548
+ nl i "}" nl
549
+ "case _ => {} " nl i
550
+ "}" nl
551
+ )
552
+ dart (
553
+ (forkctx _ ) (def 2) "if( " (e 1) " is " (typeof 2) " ) /* union case */ {" nl I
554
+ (typeof 2) " " (e 2) " = " (e 1) " as " (typeof 2) ";" nl
555
+ (block 3)
556
+ nl i "}"
557
+ )
558
+ rust (
559
+ (forkctx _ ) (def 2) "if let " (typeof 1) "::" (typeof 2) "(" (e 2) ") = &" (e 1) " { /* union case */" nl I
560
+ (block 3)
561
+ nl i "}"
562
+ )
563
+
564
+ }
565
+ }
566
+ ; `is v Shape.Case` — the kind test of `case` with the binding and the
567
+ ; block taken away. `case v x:Shape.Case { … }` answers "is it this case?"
568
+ ; and then hands the arm a narrowed `x`; an arm that only wants the answer
569
+ ; pays for a binding it never reads. On Rust that binding costs a
570
+ ; `.clone()` of the scrutinee (a refcount pair for every reference case),
571
+ ; on Go a declared-and-discarded local, on ES6/Python a dead assignment.
572
+ ; This is an expression, so it composes: `return (is self EvalValue.Number)`
573
+ ; replaces the whole `case self n:… { return true } return false` shape.
574
+ ; Every template below is the same discriminant test the `case` operator
575
+ ; above already lowers to on that target — nothing new is invented, and no
576
+ ; target evaluates (e 1) more than once.
577
+ is _:boolean ( arg@(union):T item@(noeval):T ) {
578
+ templates {
579
+ ranger ( "(is " (e 1) " " (typeof 2) ")" )
580
+ ; S5 FlatTaggedObject: the stable kind tag, no `var x = …` after it
581
+ es6 ( "(" (e 1) " != null && " (e 1) ".__rg_kind === \"" (typeof 2) "\")" )
582
+ ; single underscore — __rg_kind would be Python-mangled on the instance
583
+ python ( "(" (e 1) " is not None and getattr(" (e 1) ", \"_rg_kind\", None) == \"" (typeof 2) "\")" )
584
+ ; S5 tagged struct: the tag compare alone, no variant pointer bound
585
+ go ( "(" (e 1) ".tag == " (typeof 1) "_tag_" (rawtype 2) ")" )
586
+ ; matches! reads the discriminant in place — no clone of the
587
+ ; scrutinee, which is the whole point of this operator on Rust
588
+ rust ( "matches!(" (e 1) ", " (typeof 1) "::" (typeof 2) "(..))" )
589
+ ; holds_alternative is already the bare index compare; the `case`
590
+ ; template only added std::get on top of it
591
+ cpp ( "std::holds_alternative<" (typeof 2) ">(" (e 1) ")" )
592
+ csharp ( "(" (e 1) " is " (typeof 2) ")" )
593
+ kotlin ( "(" (e 1) " is " (typeof 2) ")" )
594
+ dart ( "(" (e 1) " is " (typeof 2) ")" )
595
+ java7 ( "(" (e 1) " instanceof " (typeof 2) ")" )
596
+ php ( "(is_object(" (e 1) ") && get_class(" (e 1) ") == \"" (typeof 2) "\")" )
597
+ scala ( "(" (e 1) ".isInstanceOf[" (typeof 2) "])" )
598
+ ; Swift's enum test is `if case`, a statement — an immediately
599
+ ; applied closure is the only way to spell it as an expression.
600
+ ; (e 1) is still named once, so it is still evaluated once.
601
+ swift3 ( "({ () -> Bool in if case ." (rawtype 2) " = " (e 1) " { return true }; return false })()" )
602
+ swift6 ( "({ () -> Bool in if case ." (rawtype 2) " = " (e 1) " { return true }; return false })()" )
603
+ }
604
+ }
605
+ ; Reference identity: are these two names the same object? `==` means
606
+ ; something different on every target — structural on Kotlin, a trait bound
607
+ ; on Rust, pointer on C++ — so identity gets its own operator rather than a
608
+ ; per-target reading of equality. Used by the generated equality of a shape's
609
+ ; `@(reference)` cases (PLAN_SHAPES.md S4), and useful on its own.
610
+ identical _:boolean ( a:T b:T ) {
611
+ templates {
612
+ es6 ( "(" (e 1) " === " (e 2) ")" )
613
+ python ( "(" (e 1) " is " (e 2) ")" )
614
+ kotlin ( "(" (e 1) " === " (e 2) ")" )
615
+ csharp ( "Object.ReferenceEquals(" (e 1) ", " (e 2) ")" )
616
+ dart ( "identical(" (e 1) ", " (e 2) ")" )
617
+ swift3 ( "(" (e 1) " === " (e 2) ")" )
618
+ swift6 ( "(" (e 1) " === " (e 2) ")" )
619
+ scala ( "(" (e 1) " eq " (e 2) ")" )
620
+ php ( "(" (e 1) " === " (e 2) ")" )
621
+ rust ( (e 1) ".rg_identical(&" (e 2) ")" )
622
+ ; java7, go and cpp compare the handle itself: a reference, a
623
+ ; pointer and a shared_ptr respectively
624
+ * ( "(" (e 1) " == " (e 2) ")" )
625
+ }
626
+ }
627
+ to _:T ( to@(union noeval):T item:T) {
628
+ templates {
629
+ cpp.disabled ( "(r_create_union<" (typeof 1) ", " (typeof 2)">(" (e 2) "))"
630
+ (create_polyfill
631
+ '
632
+ template<typename T, typename S>
633
+ T r_create_union (S value) {
634
+ T rv;
635
+ rv = value;
636
+ return rv;
637
+ };
638
+ '
639
+ )
640
+ )
641
+ * ( (e 2) )
642
+ }
643
+ }
644
+ }
645
+
646
+
647
+ operator type:[string:T] all {
648
+ fn forEach:void (cb:(_:void (item:T index:string )) ) {
649
+ def list (keys self)
650
+ for list kk:string i {
651
+ def value (unwrap (get self kk))
652
+ cb( value kk )
653
+ }
654
+ }
655
+ fn forKeys:void (cb:(_:void (index:string))) {
656
+ def list (keys self)
657
+ for list it:string i {
658
+ cb(it)
659
+ }
660
+ }
661
+
662
+ fn values:[T] () @doc('All values of the map') {
663
+ def res:[T]
664
+ def list (keys self)
665
+ for list kk:string i {
666
+ push res (unwrap (get self kk))
667
+ }
668
+ return res
669
+ }
670
+
671
+ fn map_length:int () @doc('Number of keys in the map') {
672
+ def list (keys self)
673
+ return (array_length list)
674
+ }
675
+
676
+ fn get_or:T (key:string fallback:T) @doc('Value at `key`, or `fallback` when absent') {
677
+ if( has self key ) {
678
+ return (unwrap (get self key))
679
+ }
680
+ return fallback
681
+ }
682
+ }
683
+
684
+ ; commented out native ops, because they are not compatible with async operators
685
+ operator type:[T] all {
686
+
687
+ ; pure function or operator could be simply inlined...
688
+ fn forEach@(pure):void (cb:(_:void (item:T index:int))) @doc('Call `fb` for each item in array') {
689
+ for self it:T i {
690
+ cb(it i)
691
+ }
692
+ }
693
+
694
+ fn has:boolean ( el:T) {
695
+ def idx (indexOf el)
696
+ return (idx >= 0)
697
+ }
698
+
699
+ fn map:[T] (cb:(_:T (item:T index:int))) {
700
+ def len (array_length self)
701
+ def res:[T]
702
+ for self it:T i {
703
+ push res (cb(it i))
704
+ }
705
+ return res
706
+ }
707
+
708
+ fn map:[S] (cb:(_:S (item:T index:int)) to@(noeval):[S] ) {
709
+ def len (array_length self)
710
+ def res:[S]
711
+ for self it:T i {
712
+ push res (cb(it i))
713
+ }
714
+ return res
715
+ }
716
+
717
+ fn filter:[T] (cb:(_:boolean (item:T index:int))) {
718
+ def res:[T]
719
+ for self it:T i {
720
+ if( cb(it i) ) {
721
+ push res it
722
+ }
723
+ }
724
+ return res
725
+ }
726
+ fn reduce@(weak):T (cb:(_:T (left:T right:T index:int)) initialValue:T) {
727
+ def len (array_length self)
728
+ def res:T initialValue
729
+ if( len >= 1 ) {
730
+ for self it:T i {
731
+ res = ( cb ( res it i))
732
+ }
733
+ }
734
+ return res
735
+ }
736
+ fn reduce@(weak):K (cb:(_:K (left:K right:T index:int)) initialValue:K) {
737
+ def len (array_length self)
738
+ def res initialValue
739
+ if( len >= 1 ) {
740
+ for self it:T i {
741
+ res = ( cb ( res it i ))
742
+ }
743
+ }
744
+ return res
745
+ }
746
+
747
+ fn groupBy:[T] ( cb:(_:string (item:T)) ) {
748
+ def res:[T]
749
+ def mapper:[string:boolean]
750
+ for self it:T i {
751
+ def key (cb(it))
752
+ if( false == ( has mapper key ) ) {
753
+ push res it
754
+ set mapper key true
755
+ }
756
+ }
757
+ return res
758
+ }
759
+
760
+ fn clone:[T] () {
761
+ def res:[T]
762
+ for self it:T i {
763
+ push res it
764
+ }
765
+ return res
766
+ }
767
+
768
+
769
+ ; some useful functions from scala
770
+ fn find@(optional):T (cb:(_:boolean (item:T))) {
771
+ def res@(optional):T
772
+ for self it@(lives):T i {
773
+ if( cb(it) ) {
774
+ def res2@(optional):T
775
+ res2 = it
776
+ return res2
777
+ }
778
+ }
779
+ return res
780
+ }
781
+
782
+ fn count:int (cb:(_:boolean (item:T))) {
783
+ def res 0
784
+ for self it@(lives):T i {
785
+ if( cb(it) ) {
786
+ res = res + 1
787
+ }
788
+ }
789
+ return res
790
+ }
791
+
792
+ fn contains:boolean (cb:(_:boolean (item:T))) {
793
+ for self it@(lives):T i {
794
+ if( cb(it) ) {
795
+ return true
796
+ }
797
+ }
798
+ return false
799
+ }
800
+
801
+ fn any:boolean (cb:(_:boolean (item:T))) @doc('True when `cb` holds for at least one item') {
802
+ for self it@(lives):T i {
803
+ if( cb(it) ) {
804
+ return true
805
+ }
806
+ }
807
+ return false
808
+ }
809
+
810
+ fn all:boolean (cb:(_:boolean (item:T))) @doc('True when `cb` holds for every item (true when empty)') {
811
+ for self it@(lives):T i {
812
+ if( (cb(it)) == false ) {
813
+ return false
814
+ }
815
+ }
816
+ return true
817
+ }
818
+
819
+ fn slice:[T] (start:int end:int) @doc('Items from `start` up to but not including `end`') {
820
+ def res:[T]
821
+ def len (array_length self)
822
+ def from start
823
+ def to end
824
+ if( from < 0 ) {
825
+ from = 0
826
+ }
827
+ if( to > len ) {
828
+ to = len
829
+ }
830
+ def i from
831
+ while( i < to ) {
832
+ push res (itemAt self i)
833
+ i = i + 1
834
+ }
835
+ return res
836
+ }
837
+
838
+
839
+ }
840
+
841
+ ; immutable map type
842
+ trait Map @params( K T S ) {
843
+ def elements@(weak):[K:T]
844
+ }
845
+
846
+ trait Vector @params( T S ) {
847
+
848
+ def start:int 0
849
+ def cardinality 3
850
+ def end:int 0
851
+ def elements@(weak):[T]
852
+ def parent@(weak):S
853
+
854
+ ; inserting a new element inside the array
855
+ ; you can re-use the arrays but the index ranges will change
856
+
857
+ fn localCopy:S () {
858
+ def obj (new S)
859
+ obj.start = start
860
+ obj.end = end
861
+ obj.parent = this.parent
862
+ obj.cardinality = cardinality
863
+ obj.elements = elements
864
+ return obj
865
+ }
866
+
867
+ fn set:S (idx:int item:T) {
868
+
869
+ if( idx >= start ) {
870
+ def res (this.localCopy())
871
+ res.elements = (make _:[T] (res.cardinality) item)
872
+ for elements e@(lives):T i {
873
+ if ( (res.start + i) != idx ) {
874
+ set res.elements i e
875
+ } {
876
+ set res.elements i item
877
+ }
878
+ }
879
+ return res
880
+ }
881
+ def root (this.localCopy())
882
+ def res root
883
+
884
+ def p@(weak):S parent
885
+ while( (!null? p) && (idx < p.start) ) {
886
+ def newSlice@(lives) (p.localCopy())
887
+ res.parent = newSlice
888
+ res = newSlice
889
+ if(!null? p.parent) {
890
+ p = p.parent
891
+ }
892
+ }
893
+ def newSlice@(lives) (p.localCopy())
894
+ newSlice.elements = (make _:[T] (newSlice.cardinality) item)
895
+ for p.elements e@(lives):T i {
896
+ set newSlice.elements i e
897
+ }
898
+ set newSlice.elements (idx - newSlice.start) item
899
+ res.parent = newSlice
900
+ return root
901
+ }
902
+
903
+ fn insert:S (idx:int item:T) {
904
+ if( idx >= start ) {
905
+ def res (this.localCopy())
906
+ def use_card cardinality
907
+ if( ( array_length res.elements) >= (use_card - 1) ) {
908
+ use_card = ( array_length res.elements) + 1
909
+ }
910
+ res.elements = (make _:[T] (use_card) item)
911
+ for elements e@(lives):T i {
912
+ if ( res.start + i < idx ) {
913
+ set res.elements i e
914
+ } {
915
+ if( idx == ( res.start + i )) {
916
+ set res.elements i item
917
+ set res.elements (i + 1) e
918
+ } {
919
+ set res.elements (i + 1) e
920
+ }
921
+ }
922
+ }
923
+ if( (idx - start) >= (array_length elements)) {
924
+ set res.elements (idx - start) item
925
+ }
926
+ res.start = start
927
+ res.end = end + 1
928
+ res.cardinality = use_card
929
+ return res
930
+ }
931
+ def root (this.localCopy())
932
+ def res root
933
+ res.start = start + 1
934
+ res.end = end + 1
935
+ def p@(weak):S parent
936
+ while( (!null? p) && (idx < p.start) ) {
937
+ def newSlice@(lives) (p.localCopy())
938
+ newSlice.start = newSlice.start + 1
939
+ newSlice.end = newSlice.end + 1
940
+ res.parent = newSlice
941
+ res = newSlice
942
+ if(!null? p.parent) {
943
+ p = p.parent
944
+ }
945
+ }
946
+
947
+ def newSlice@(lives) (p.localCopy())
948
+ def use_card newSlice.cardinality
949
+ if( ( array_length p.elements) >= (use_card - 1) ) {
950
+ use_card = ( array_length p.elements) + 1
951
+ }
952
+ newSlice.elements = (make _:[T] (use_card) item)
953
+ for p.elements e@(lives):T i {
954
+ if ( newSlice.start + i < idx ) {
955
+ set newSlice.elements i e
956
+ } {
957
+ if( idx == ( newSlice.start + i )) {
958
+ set newSlice.elements i item
959
+ set newSlice.elements (i + 1) e
960
+ } {
961
+ set newSlice.elements (i + 1) e
962
+ }
963
+ }
964
+ }
965
+
966
+ newSlice.end = newSlice.end + 1
967
+ newSlice.cardinality = use_card
968
+ if ( (idx - newSlice.start) >= p.cardinality ) {
969
+ newSlice.end = idx + 1
970
+ }
971
+ newSlice.parent = p.parent
972
+ res.parent = newSlice
973
+ return root
974
+ }
975
+
976
+ fn get:T (idx:int) {
977
+ if( idx < 0 ) {
978
+ ; should be runtime error here...
979
+ return (itemAt elements 0)
980
+ }
981
+ if( idx >= start && idx < end ) {
982
+ return (itemAt elements (idx - start))
983
+ }
984
+ def p@(weak):S parent
985
+ while( (!null? p) && (idx < p.start) ) {
986
+ p = p.parent
987
+ }
988
+ if(!null? p ) {
989
+ return (itemAt p.elements (idx - p.start))
990
+ }
991
+ return (itemAt elements 0)
992
+ }
993
+ fn add:S (item:T) {
994
+ if((end - start) >= cardinality) {
995
+ def res (new S)
996
+ res.start = this.end
997
+ res.end = (this.end + 1)
998
+ res.parent = this
999
+ res.cardinality = (cardinality + 1)
1000
+ res.elements = (make _:[T] (res.cardinality) item)
1001
+ set res.elements 0 item
1002
+ return res
1003
+ }
1004
+ def res (new S)
1005
+ res.elements = (make _:[T] (cardinality) item)
1006
+ for elements e@(lives):T i {
1007
+ set res.elements i e
1008
+ }
1009
+ set res.elements (end - start) item
1010
+ res.parent = parent
1011
+ res.start = start
1012
+ res.end = end + 1
1013
+ res.cardinality = cardinality
1014
+ return res
1015
+ }
1016
+
1017
+ fn count:int () {
1018
+ return end
1019
+ }
1020
+
1021
+ ; TODO: create faster version which uses (make ) operator
1022
+ fn map:S (cb:(_:T (item:T)) ) {
1023
+ def res:S (new S)
1024
+ def cnt (this.count())
1025
+ def i 0
1026
+ while( i < cnt ) {
1027
+ def item (this.get(i))
1028
+ def new_value (cb(item))
1029
+ res = (res.add(new_value))
1030
+ i = i + 1
1031
+ }
1032
+ return res
1033
+ }
1034
+ }
1035
+
1036
+
1037
+ operator type:Vector all {
1038
+
1039
+ ; TODO: strict type checking for this
1040
+ ; fn for (iIndex@(ignore):T iteIndex@(ignore):int code:block ) (
1041
+ ; "def " (e 3) ":int 0" nl
1042
+ ; "def loop_cnt (" (e 1) ".count())" nl
1043
+ ; "while( " (e 3) " < loop_cnt ) {" nl
1044
+ ; I
1045
+ ; "def " (e 2) " (" (e 1) ".get(" (e 3) "))" nl
1046
+ ; (block 4)
1047
+ ; (e 3) " = " (e 3) " + 1" nl
1048
+ ; i
1049
+ ; "}" nl
1050
+ ; )
1051
+
1052
+ fn indexOf:int ( elem:T ) {
1053
+ def cnt (self.count())
1054
+ def i 0
1055
+ while( i < cnt ) {
1056
+ def item (itemAt self i)
1057
+ if(item == elem) {
1058
+ return i
1059
+ }
1060
+ i = i + 1
1061
+ }
1062
+ return -1
1063
+ }
1064
+ fn clear:T (idx:int) {
1065
+ ; def val (self.get(idx))
1066
+ return (new T)
1067
+ }
1068
+
1069
+ fn itemAt:T (idx:int) {
1070
+ def val (self.get(idx))
1071
+ return val
1072
+ }
1073
+ fn at:T (idx:int) {
1074
+ def val (self.get(idx))
1075
+ return val
1076
+ }
1077
+ fn push:S (item:T) {
1078
+ return (self.add(item))
1079
+ }
1080
+ fn last:T () {
1081
+ return (itemAt self ((self.count()) - 1) )
1082
+ }
1083
+ fn array_length:int () {
1084
+ return (self.count())
1085
+ }
1086
+ fn length:int () {
1087
+ return (self.count())
1088
+ }
1089
+ fn size:int () {
1090
+ return (self.count())
1091
+ }
1092
+ fn forEach:void (cb:(_:void (item:T))) {
1093
+ def cnt (self.count())
1094
+ def i 0
1095
+ while( i < cnt ) {
1096
+ def item (itemAt self i)
1097
+ cb(item)
1098
+ i = i + 1
1099
+ }
1100
+ }
1101
+
1102
+ fn forUntil:void (cb:(_:boolean (item:T))) {
1103
+ def cnt (self.count())
1104
+ def i 0
1105
+ while( i < cnt ) {
1106
+ def item (itemAt self i)
1107
+ if( (cb(item)) == false ) {
1108
+ return
1109
+ }
1110
+ i = i + 1
1111
+ }
1112
+ }
1113
+
1114
+ fn map:S ( cb:(_:T (item:T)) ) {
1115
+ def res (new S)
1116
+ def cnt (self.count())
1117
+ def i 0
1118
+ while( i < cnt ) {
1119
+ def item (itemAt self i)
1120
+ def value (cb(item))
1121
+ res = res.add(value)
1122
+ i = i + 1
1123
+ }
1124
+ return res
1125
+ }
1126
+
1127
+ ; TODO: faster version ....
1128
+ fn map:[K] (cb:(_:K (item:T)) to@(noeval):[K] ) {
1129
+ def res:[K]
1130
+ def cnt (self.count())
1131
+ def i 0
1132
+ while( i < cnt ) {
1133
+ def item (itemAt self i)
1134
+ push res (cb(item))
1135
+ i = i + 1
1136
+ }
1137
+ return res
1138
+ }
1139
+
1140
+
1141
+ }
1142
+
1143
+ operator type:Map all {
1144
+ fn keys:[K] () {
1145
+ return (keys self.elements)
1146
+ }
1147
+ fn get@(optional):T (key:K) {
1148
+ return (get self.elements key)
1149
+ }
1150
+ fn has:boolean (key:K) {
1151
+ return (has self.elements key)
1152
+ }
1153
+ fn set:S (key:K value:T) {
1154
+ def c (new S)
1155
+ def keys ( keys self.elements)
1156
+ for keys k:string i {
1157
+ if(k==key) {
1158
+
1159
+ } {
1160
+ set c.elements k (unwrap (get self.elements k))
1161
+ }
1162
+ }
1163
+ set c.elements key value
1164
+ return c
1165
+ }
1166
+ fn forEach@(weak):S ( cb:(_:void (item:T index:K)) ) {
1167
+ def keys (keys self.elements)
1168
+ for keys key:K i {
1169
+ cb( (unwrap (get self.elements key)) key )
1170
+ }
1171
+ return self
1172
+ }
1173
+
1174
+ }
1175
+
1176
+