yukigo-ast 0.1.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 (42) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/globals/generics.d.ts +740 -0
  3. package/dist/globals/generics.js +1128 -0
  4. package/dist/globals/helpers.d.ts +4 -0
  5. package/dist/globals/helpers.js +76 -0
  6. package/dist/globals/operators.d.ts +251 -0
  7. package/dist/globals/operators.js +336 -0
  8. package/dist/globals/patterns.d.ts +170 -0
  9. package/dist/globals/patterns.js +261 -0
  10. package/dist/globals/runtime.d.ts +22 -0
  11. package/dist/globals/runtime.js +6 -0
  12. package/dist/globals/types.d.ts +185 -0
  13. package/dist/globals/types.js +329 -0
  14. package/dist/index.d.ts +12 -0
  15. package/dist/index.js +12 -0
  16. package/dist/paradigms/data.d.ts +246 -0
  17. package/dist/paradigms/data.js +348 -0
  18. package/dist/paradigms/functional.d.ts +59 -0
  19. package/dist/paradigms/functional.js +103 -0
  20. package/dist/paradigms/imperative.d.ts +124 -0
  21. package/dist/paradigms/imperative.js +188 -0
  22. package/dist/paradigms/logic.d.ts +163 -0
  23. package/dist/paradigms/logic.js +240 -0
  24. package/dist/paradigms/object.d.ts +201 -0
  25. package/dist/paradigms/object.js +308 -0
  26. package/dist/visitor.d.ts +254 -0
  27. package/dist/visitor.js +426 -0
  28. package/package.json +25 -0
  29. package/src/globals/generics.ts +1421 -0
  30. package/src/globals/helpers.ts +107 -0
  31. package/src/globals/operators.ts +515 -0
  32. package/src/globals/patterns.ts +321 -0
  33. package/src/globals/runtime.ts +33 -0
  34. package/src/globals/types.ts +375 -0
  35. package/src/index.ts +12 -0
  36. package/src/paradigms/data.ts +393 -0
  37. package/src/paradigms/functional.ts +129 -0
  38. package/src/paradigms/imperative.ts +232 -0
  39. package/src/paradigms/logic.ts +314 -0
  40. package/src/paradigms/object.ts +366 -0
  41. package/src/visitor.ts +692 -0
  42. package/tsconfig.json +22 -0
@@ -0,0 +1,1421 @@
1
+ import {
2
+ Application,
3
+ CompositionExpression,
4
+ Lambda,
5
+ Yield,
6
+ } from "../paradigms/functional.js";
7
+ import {
8
+ EntryPoint,
9
+ Enumeration,
10
+ ForLoop,
11
+ Procedure,
12
+ Repeat,
13
+ Structure,
14
+ While,
15
+ } from "../paradigms/imperative.js";
16
+ import {
17
+ Call,
18
+ Clause,
19
+ Exist,
20
+ Findall,
21
+ Forall,
22
+ Not,
23
+ RuntimePredicate,
24
+ } from "../paradigms/logic.js";
25
+ import {
26
+ Attribute,
27
+ Class,
28
+ Implement,
29
+ Include,
30
+ Interface,
31
+ Method,
32
+ New,
33
+ Object,
34
+ Self,
35
+ Send,
36
+ Super,
37
+ } from "../paradigms/object.js";
38
+ import { Visitor } from "../visitor.js";
39
+ import { Operation } from "./operators.js";
40
+ import { Pattern } from "./patterns.js";
41
+ import { LazyList, RuntimeFunction } from "./runtime.js";
42
+ import { Type, TypeAlias, TypeCast, TypeSignature } from "./types.js";
43
+
44
+ export type Modify<T, R> = Omit<T, keyof R> & R;
45
+
46
+ // Universal primitive value types
47
+
48
+ type Metadata = Map<string, any>;
49
+ /**
50
+ * @hidden
51
+ */
52
+ export abstract class ASTNode {
53
+ /** @hidden */
54
+ public loc: SourceLocation;
55
+ /** @hidden */
56
+ public metadata: Metadata = new Map();
57
+
58
+ constructor(loc?: SourceLocation, metadata?: Metadata) {
59
+ this.loc = loc;
60
+ this.metadata = metadata ?? new Map();
61
+ }
62
+
63
+ public setMetadata(key: string, value: any): void {
64
+ this.metadata.set(key, value);
65
+ }
66
+
67
+ public getMetadata<T>(key: string): T | undefined {
68
+ return this.metadata.get(key);
69
+ }
70
+
71
+ public hasMetadata(key: string): boolean {
72
+ return this.metadata.has(key);
73
+ }
74
+
75
+ /** @hidden */
76
+ abstract accept<R>(visitor: Visitor<R>): R;
77
+ /** @hidden */
78
+ abstract toJSON(): object;
79
+ }
80
+
81
+ /**
82
+ * Generic number primitive
83
+ * @category Literals
84
+ */
85
+ export class NumberPrimitive extends ASTNode {
86
+ /** @hidden */
87
+ public value: number;
88
+
89
+ constructor(value: number, loc?: SourceLocation) {
90
+ super(loc);
91
+ this.value = value;
92
+ }
93
+ public accept<R>(visitor: Visitor<R>): R {
94
+ return visitor.visitNumberPrimitive?.(this);
95
+ }
96
+ /**
97
+ * Compares the primitive to other Primitive passed by argument
98
+ * @param other Another Primitive to compare to.
99
+ * @returns True if both primitive have the same value
100
+ */
101
+ public equals(other: Primitive): boolean {
102
+ if (!(other instanceof NumberPrimitive)) return false;
103
+ return this.value === other.value;
104
+ }
105
+ public toJSON() {
106
+ return {
107
+ type: "YuNumber",
108
+ value: this.value,
109
+ };
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Generic boolean primitive
115
+ * @category Literals
116
+ */
117
+ export class BooleanPrimitive extends ASTNode {
118
+ /** @hidden */
119
+ public value: boolean;
120
+
121
+ constructor(value: boolean, loc?: SourceLocation) {
122
+ super(loc);
123
+ this.value = value;
124
+ }
125
+ public accept<R>(visitor: Visitor<R>): R {
126
+ return visitor.visitBooleanPrimitive?.(this);
127
+ }
128
+ /**
129
+ * Compares the primitive to other Primitive passed by argument
130
+ * @param other Another Primitive to compare to.
131
+ * @returns True if both primitive have the same value
132
+ */
133
+ public equals(other: Primitive): boolean {
134
+ if (!(other instanceof BooleanPrimitive)) return false;
135
+ return this.value === other.value;
136
+ }
137
+ public toJSON() {
138
+ return {
139
+ type: "YuBoolean",
140
+ value: this.value,
141
+ };
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Represent lists - generic uniform variable-size collection of elements. Lists typically map to arrays, lists or sequence-like structures.
147
+ * @category Literals
148
+ */
149
+ export class ListPrimitive extends ASTNode {
150
+ /** @hidden */
151
+ public elements: Expression[];
152
+
153
+ constructor(elements: Expression[], loc?: SourceLocation) {
154
+ super(loc);
155
+ this.elements = elements;
156
+ }
157
+ public accept<R>(visitor: Visitor<R>): R {
158
+ return visitor.visitListPrimitive?.(this);
159
+ }
160
+ /**
161
+ * Compares the primitive to other Primitive passed by argument
162
+ * @param other Another Primitive to compare to.
163
+ * @returns True if both primitive have the same value
164
+ */
165
+ public equals(other: Primitive): boolean {
166
+ if (!(other instanceof ListPrimitive)) return false;
167
+ return this.elements.every((elem, i) => elem === other.elements[i]);
168
+ }
169
+ public toJSON() {
170
+ return {
171
+ type: "YuList",
172
+ value: this.elements,
173
+ };
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Generic char primitive
179
+ * @category Literals
180
+ */
181
+ export class CharPrimitive extends ASTNode {
182
+ /** @hidden */
183
+ public value: string;
184
+
185
+ constructor(value: string, loc?: SourceLocation) {
186
+ super(loc);
187
+ this.value = value;
188
+ }
189
+ public accept<R>(visitor: Visitor<R>): R {
190
+ return visitor.visitCharPrimitive?.(this);
191
+ }
192
+ /**
193
+ * Compares the primitive to other Primitive passed by argument
194
+ * @param other Another Primitive to compare to.
195
+ * @returns True if both primitive have the same value
196
+ */
197
+ public equals(other: Primitive): boolean {
198
+ if (!(other instanceof CharPrimitive)) return false;
199
+ return this.value === other.value;
200
+ }
201
+ public toJSON() {
202
+ return {
203
+ type: "YuChar",
204
+ value: this.value,
205
+ };
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Generic string primitive
211
+ * @category Literals
212
+ */
213
+ export class StringPrimitive extends ASTNode {
214
+ /** @hidden */
215
+ public value: string;
216
+
217
+ constructor(value: string, loc?: SourceLocation) {
218
+ super(loc);
219
+ this.value = value;
220
+ }
221
+ public accept<R>(visitor: Visitor<R>): R {
222
+ return visitor.visitStringPrimitive?.(this);
223
+ }
224
+ /**
225
+ * Compares the primitive to other Primitive passed by argument
226
+ * @param other Another Primitive to compare to.
227
+ * @returns True if both primitive have the same value
228
+ */
229
+ public equals(other: Primitive): boolean {
230
+ if (!(other instanceof StringPrimitive)) return false;
231
+ return this.value === other.value;
232
+ }
233
+ public toJSON() {
234
+ return {
235
+ type: "YuString",
236
+ value: this.value,
237
+ };
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Generic null/undefined primitive
243
+ * @category Literals
244
+ */
245
+ export class NilPrimitive extends ASTNode {
246
+ /** @hidden */
247
+ public value: undefined | null;
248
+
249
+ constructor(value: undefined | null, loc?: SourceLocation) {
250
+ super(loc);
251
+ this.value = value;
252
+ }
253
+ public accept<R>(visitor: Visitor<R>): R {
254
+ return visitor.visitNilPrimitive?.(this);
255
+ }
256
+ /**
257
+ * Compares the primitive to other Primitive passed by argument
258
+ * @param other Another Primitive to compare to.
259
+ * @returns True if both primitive have the same value
260
+ */
261
+ public equals(other: Primitive): boolean {
262
+ if (!(other instanceof NilPrimitive)) return false;
263
+ return this.value === other.value;
264
+ }
265
+ public toJSON() {
266
+ return {
267
+ type: "YuNil",
268
+ value: this.value,
269
+ };
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Generic symbol primitive
275
+ * @category Literals
276
+ */
277
+ export class SymbolPrimitive extends ASTNode {
278
+ /** @hidden */
279
+ public value: string;
280
+
281
+ constructor(value: string, loc?: SourceLocation) {
282
+ super(loc);
283
+ this.value = value;
284
+ }
285
+ public accept<R>(visitor: Visitor<R>): R {
286
+ return visitor.visitSymbolPrimitive?.(this);
287
+ }
288
+ /**
289
+ * Compares the primitive to other Primitive passed by argument
290
+ * @param other Another Primitive to compare to.
291
+ * @returns True if both primitive have the same value
292
+ */
293
+ public equals(other: Primitive): boolean {
294
+ if (!(other instanceof SymbolPrimitive)) return false;
295
+ return this.value === other.value;
296
+ }
297
+ public toJSON() {
298
+ return {
299
+ type: "YuSymbol",
300
+ value: this.value,
301
+ };
302
+ }
303
+ }
304
+
305
+ export type YukigoPrimitive =
306
+ | "YuNumber"
307
+ | "YuString"
308
+ | "YuChar"
309
+ | "YuBoolean"
310
+ | "YuTuple"
311
+ | "YuList"
312
+ | "YuNil"
313
+ | "YuDict"
314
+ | "YuObject"
315
+ | "YuSymbol";
316
+
317
+ export type LogicResult = {
318
+ success: boolean;
319
+ solutions: Map<string, string>;
320
+ };
321
+
322
+ export type PrimitiveValue =
323
+ | number
324
+ | boolean
325
+ | string
326
+ | RuntimeFunction
327
+ | RuntimePredicate
328
+ | LogicResult
329
+ | LazyList
330
+ | null
331
+ | void
332
+ | PrimitiveValue[]
333
+ | undefined;
334
+
335
+ export type Primitive =
336
+ | NumberPrimitive
337
+ | BooleanPrimitive
338
+ | CharPrimitive
339
+ | StringPrimitive
340
+ | NilPrimitive
341
+ | SymbolPrimitive
342
+ | ListPrimitive;
343
+
344
+ /**
345
+ * Source location information
346
+ */
347
+ export class SourceLocation {
348
+ constructor(public line: number, public column: number) {}
349
+ public toJSON() {
350
+ return {
351
+ type: "SourceLocation",
352
+ line: this.line,
353
+ column: this.column,
354
+ };
355
+ }
356
+ }
357
+
358
+ // Expressions
359
+
360
+ /**
361
+ * Represent tuples - generic non-uniform fixed-size collection of elements
362
+ *
363
+ * @example
364
+ * (1, "Hello", true)
365
+ * @category Expressions
366
+ */
367
+ export class TupleExpression extends ASTNode {
368
+ /** @hidden */
369
+ public elements: Expression[];
370
+
371
+ constructor(elements: Expression[], loc?: SourceLocation) {
372
+ super(loc);
373
+ this.elements = elements;
374
+ }
375
+ public accept<R>(visitor: Visitor<R>): R {
376
+ return visitor.visitTupleExpr?.(this);
377
+ }
378
+ public toJSON() {
379
+ return {
380
+ type: "TupleExpression",
381
+ elements: this.elements.map((expr) => expr.toJSON()),
382
+ };
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Fields of a data expression representations
388
+ * @category Expressions
389
+ */
390
+ export class FieldExpression extends ASTNode {
391
+ /** @hidden */
392
+ public expression: Expression;
393
+ /** @hidden */
394
+ public name: SymbolPrimitive;
395
+
396
+ constructor(
397
+ name: SymbolPrimitive,
398
+ expression: Expression,
399
+ loc?: SourceLocation
400
+ ) {
401
+ super(loc);
402
+ this.name = name;
403
+ this.expression = expression;
404
+ }
405
+ public accept<R>(visitor: Visitor<R>): R {
406
+ return visitor.visitFieldExpr?.(this);
407
+ }
408
+ public toJSON() {
409
+ return {
410
+ type: "FieldExpression",
411
+ name: this.name.toJSON(),
412
+ expression: this.expression.toJSON(),
413
+ };
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Data expression, used to construct Records
419
+ * @example
420
+ * f = DataName { fieldName = 2 }
421
+ * @category Expressions
422
+ */
423
+ export class DataExpression extends ASTNode {
424
+ /** @hidden */
425
+ public contents: FieldExpression[];
426
+ /** @hidden */
427
+ public name: SymbolPrimitive;
428
+
429
+ constructor(
430
+ name: SymbolPrimitive,
431
+ contents: FieldExpression[],
432
+ loc?: SourceLocation
433
+ ) {
434
+ super(loc);
435
+ this.name = name;
436
+ this.contents = contents;
437
+ }
438
+ public accept<R>(visitor: Visitor<R>): R {
439
+ return visitor.visitDataExpr?.(this);
440
+ }
441
+ public toJSON() {
442
+ return {
443
+ type: "DataExpression",
444
+ name: this.name.toJSON(),
445
+ contents: this.contents.map((expr) => expr.toJSON()),
446
+ };
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Cons expression, represent a concatenation of a head and a tail
452
+ * @example
453
+ * f = x : xs
454
+ * @category Expressions
455
+ */
456
+ export class ConsExpression extends ASTNode {
457
+ /** @hidden */
458
+ public tail: Expression;
459
+ /** @hidden */
460
+ public head: Expression;
461
+
462
+ constructor(head: Expression, tail: Expression, loc?: SourceLocation) {
463
+ super(loc);
464
+ this.head = head;
465
+ this.tail = tail;
466
+ }
467
+ public accept<R>(visitor: Visitor<R>): R {
468
+ return visitor.visitConsExpr?.(this);
469
+ }
470
+ public toJSON() {
471
+ return {
472
+ type: "ConsExpression",
473
+ head: this.head.toJSON(),
474
+ tail: this.tail.toJSON(),
475
+ };
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Represent let...in expressions normally used in Haskell
481
+ * @example
482
+ * f = let x = 2 in x * 4
483
+ * @category Expressions
484
+ */
485
+ export class LetInExpression extends ASTNode {
486
+ /** @hidden */
487
+ public expression: Expression;
488
+ /** @hidden */
489
+ public declarations: Sequence;
490
+
491
+ constructor(
492
+ declarations: Sequence,
493
+ expression: Expression,
494
+ loc?: SourceLocation
495
+ ) {
496
+ super(loc);
497
+ this.declarations = declarations;
498
+ this.expression = expression;
499
+ }
500
+ public accept<R>(visitor: Visitor<R>): R {
501
+ return visitor.visitLetInExpr?.(this);
502
+ }
503
+ public toJSON() {
504
+ return {
505
+ type: "LetInExpression",
506
+ declarations: this.declarations.toJSON(),
507
+ expression: this.expression.toJSON(),
508
+ };
509
+ }
510
+ }
511
+
512
+ /**
513
+ * Otherwise used as the default case in GuardBody
514
+ * @example
515
+ * f x
516
+ * | x == 2 = 16
517
+ * | otherwise = x * 8
518
+ * @category Declarations
519
+ */
520
+ export class Otherwise extends ASTNode {
521
+ public accept<R>(visitor: Visitor<R>): R {
522
+ return visitor.visitOtherwise?.(this);
523
+ }
524
+ public toJSON() {
525
+ return {
526
+ type: "Otherwise",
527
+ };
528
+ }
529
+ }
530
+
531
+ /**
532
+ * ListComprehension when the for expression is a yield.
533
+ * Scala's for comprehensions, Erlang's and Haskell's list comprehensions
534
+ * @example
535
+ * m = [ f x | x <- [1, 2, 3, 4] ]
536
+ * @category Expressions
537
+ */
538
+ export class ListComprehension extends ASTNode {
539
+ /** @hidden */
540
+ public generators: (Generator | Expression)[];
541
+ /** @hidden */
542
+ public projection: Expression;
543
+
544
+ constructor(
545
+ projection: Expression,
546
+ generators: (Generator | Expression)[],
547
+ loc?: SourceLocation
548
+ ) {
549
+ super(loc);
550
+ this.projection = projection;
551
+ this.generators = generators;
552
+ }
553
+ public accept<R>(visitor: Visitor<R>): R {
554
+ return visitor.visitListComprehension?.(this);
555
+ }
556
+ public toJSON() {
557
+ return {
558
+ type: "ListComprehension",
559
+ projection: this.projection.toJSON(),
560
+ generators: this.generators.map((gen) => gen.toJSON()),
561
+ };
562
+ }
563
+ }
564
+
565
+ /**
566
+ * Generator represents patterns like "Just m <- ms" or "x <- [1,2,3]"
567
+ * @example
568
+ * x <- [1, 2, 3, 4]
569
+ * @category Declarations
570
+ */
571
+ export class Generator extends ASTNode {
572
+ /** @hidden */
573
+ public expression: Expression;
574
+ /** @hidden */
575
+ public variable: SymbolPrimitive;
576
+
577
+ constructor(
578
+ variable: SymbolPrimitive,
579
+ expression: Expression,
580
+ loc?: SourceLocation
581
+ ) {
582
+ super(loc);
583
+ this.variable = variable;
584
+ this.expression = expression;
585
+ }
586
+ public accept<R>(visitor: Visitor<R>): R {
587
+ return visitor.visitGenerator?.(this);
588
+ }
589
+ public toJSON() {
590
+ return {
591
+ type: "Generator",
592
+ variable: this.variable.toJSON(),
593
+ expression: this.expression.toJSON(),
594
+ };
595
+ }
596
+ }
597
+
598
+ /**
599
+ * RangeExpression represents when a list is given by comprehension in a defined range
600
+ * @example
601
+ * (1..10)
602
+ * @example
603
+ * (1, 2..10)
604
+ * @example
605
+ * (1..)
606
+ * @category Expressions
607
+ */
608
+ export class RangeExpression extends ASTNode {
609
+ /** @hidden */
610
+ public step?: Expression;
611
+ /** @hidden */
612
+ public end?: Expression;
613
+ /** @hidden */
614
+ public start: Expression;
615
+
616
+ constructor(
617
+ start: Expression,
618
+ end?: Expression, // undefined for infinite ranges like [0..]
619
+ step?: Expression, // for [start, second .. end] syntax
620
+ loc?: SourceLocation
621
+ ) {
622
+ super(loc);
623
+ this.start = start;
624
+ this.end = end;
625
+ this.step = step;
626
+ }
627
+ public accept<R>(visitor: Visitor<R>): R {
628
+ return visitor.visitRangeExpression?.(this);
629
+ }
630
+ public toJSON() {
631
+ return {
632
+ type: "RangeExpression",
633
+ start: this.start.toJSON(),
634
+ end: this.end?.toJSON(),
635
+ step: this.step?.toJSON(),
636
+ };
637
+ }
638
+ }
639
+
640
+ export type Expression =
641
+ | Primitive
642
+ | Operation
643
+ | TupleExpression
644
+ | Print
645
+ | Otherwise
646
+ | ConsExpression
647
+ | Self
648
+ | Sequence
649
+ | New
650
+ | Include
651
+ | Implement
652
+ | DataExpression
653
+ | CompositionExpression
654
+ | Lambda
655
+ | For
656
+ | Application
657
+ | Exist
658
+ | Forall
659
+ | Findall
660
+ | Not
661
+ | TypeCast
662
+ | ListComprehension
663
+ | RangeExpression;
664
+
665
+ //export type Expression = {
666
+ // type: "Expression";
667
+ // body: BodyExpression;
668
+ //};
669
+
670
+ // Statements
671
+
672
+ /**
673
+ * Generic conditional If statements.
674
+ * Nested `else if` need to be desugared into `else { if ... }`
675
+ * @example
676
+ * if (condition) { ... } else { ... }
677
+ * @category Expressions
678
+ */
679
+ export class If extends ASTNode {
680
+ /** @hidden */
681
+ public elseExpr: Expression;
682
+ /** @hidden */
683
+ public then: Expression;
684
+ /** @hidden */
685
+ public condition: Expression;
686
+
687
+ constructor(
688
+ condition: Expression,
689
+ then: Expression,
690
+ elseExpr: Expression,
691
+ loc?: SourceLocation
692
+ ) {
693
+ super(loc);
694
+ this.condition = condition;
695
+ this.then = then;
696
+ this.elseExpr = elseExpr;
697
+ }
698
+ public accept<R>(visitor: Visitor<R>): R {
699
+ return visitor.visitIf?.(this);
700
+ }
701
+ public toJSON() {
702
+ return {
703
+ type: "If",
704
+ condition: this.condition.toJSON(),
705
+ then: this.then.toJSON(),
706
+ else: this.elseExpr.toJSON(),
707
+ };
708
+ }
709
+ }
710
+
711
+ /**
712
+ * Generic return statement.
713
+ * @example
714
+ * // In Haskell
715
+ * f x = x * 2
716
+ * // The parser takes the body and uses it as a Return
717
+ * @example
718
+ * function f(x) {
719
+ * return x * 2 // The node holds this expression
720
+ * }
721
+ * @category Statements
722
+ */
723
+ export class Return extends ASTNode {
724
+ /** @hidden */
725
+ public body?: Expression;
726
+
727
+ constructor(body: Expression = new NilPrimitive(null), loc?: SourceLocation) {
728
+ super(loc);
729
+ this.body = body;
730
+ }
731
+ public accept<R>(visitor: Visitor<R>): R {
732
+ return visitor.visitReturn?.(this);
733
+ }
734
+ public toJSON() {
735
+ return {
736
+ type: "Return",
737
+ body: this.body.toJSON(),
738
+ };
739
+ }
740
+ }
741
+
742
+ /**
743
+ * Generic field in a Record statement.
744
+ * The name can be undefined to support positional-only Records
745
+ * @example
746
+ * ... { name :: String }
747
+ * @category Declarations
748
+ */
749
+ export class Field extends ASTNode {
750
+ /** @hidden */
751
+ public value: Type;
752
+ /** @hidden */
753
+ public name: SymbolPrimitive | undefined;
754
+
755
+ constructor(
756
+ name: SymbolPrimitive | undefined,
757
+ value: Type,
758
+ loc?: SourceLocation
759
+ ) {
760
+ super(loc);
761
+ this.name = name;
762
+ this.value = value;
763
+ }
764
+ public accept<R>(visitor: Visitor<R>): R {
765
+ return visitor.visitField?.(this);
766
+ }
767
+ public toJSON() {
768
+ return {
769
+ type: "Field",
770
+ name: this.name.toJSON(),
771
+ value: this.value.toJSON(),
772
+ };
773
+ }
774
+ }
775
+
776
+ /**
777
+ * Generic constructor node.
778
+ * Holds an array of Field nodes.
779
+ * @example
780
+ * data Record = Constructor { field :: String }
781
+ * @category Declarations
782
+ */
783
+ export class Constructor extends ASTNode {
784
+ /** @hidden */
785
+ public fields: Field[];
786
+ /** @hidden */
787
+ public name: SymbolPrimitive;
788
+
789
+ constructor(name: SymbolPrimitive, fields: Field[], loc?: SourceLocation) {
790
+ super(loc);
791
+ this.name = name;
792
+ this.fields = fields;
793
+ }
794
+ public accept<R>(visitor: Visitor<R>): R {
795
+ return visitor.visitConstructor?.(this);
796
+ }
797
+ public toJSON() {
798
+ return {
799
+ type: "Constructor",
800
+ name: this.name.toJSON(),
801
+ fields: this.fields.map((f) => f.toJSON()),
802
+ };
803
+ }
804
+ }
805
+
806
+ /**
807
+ * Generic Record statement node.
808
+ * @example
809
+ * data Record = Constructor { field :: String }
810
+ * data PositionalRecord = Constructor String String
811
+ * @category Declarations
812
+ */
813
+ export class Record extends ASTNode {
814
+ /** @hidden */
815
+ public deriving?: SymbolPrimitive[];
816
+ /** @hidden */
817
+ public contents: Constructor[];
818
+ /** @hidden */
819
+ public name: SymbolPrimitive;
820
+
821
+ constructor(
822
+ name: SymbolPrimitive,
823
+ contents: Constructor[],
824
+ deriving?: SymbolPrimitive[],
825
+ loc?: SourceLocation
826
+ ) {
827
+ super(loc);
828
+ this.name = name;
829
+ this.contents = contents;
830
+ this.deriving = deriving;
831
+ }
832
+ public accept<R>(visitor: Visitor<R>): R {
833
+ return visitor.visitRecord?.(this);
834
+ }
835
+ public toJSON() {
836
+ return {
837
+ type: "Record",
838
+ name: this.name.toJSON(),
839
+ contents: this.contents.map((constructor) => constructor.toJSON()),
840
+ deriving: this.deriving?.map((d) => d.toJSON()),
841
+ };
842
+ }
843
+ }
844
+
845
+ /**
846
+ * Represents the body of an Equation that does not have guards.
847
+ * Most languages match the body of its equations to it.
848
+ * @example
849
+ * f x = x + 2
850
+ * // The body is the `x + 2` part
851
+ * @example
852
+ * function f(x) {
853
+ * return x + 2;
854
+ * }
855
+ * @category Declarations
856
+ */
857
+ export class UnguardedBody extends ASTNode {
858
+ /** @hidden */
859
+ public sequence: Sequence;
860
+
861
+ constructor(sequence: Sequence, loc?: SourceLocation) {
862
+ super(loc);
863
+ this.sequence = sequence;
864
+ }
865
+ public accept<R>(visitor: Visitor<R>): R {
866
+ return visitor.visitUnguardedBody?.(this);
867
+ }
868
+ public toJSON() {
869
+ return {
870
+ type: "UnguardedBody",
871
+ sequence: this.sequence.toJSON(),
872
+ };
873
+ }
874
+ }
875
+
876
+ /**
877
+ * Represents the body of an Equation that does have guards.
878
+ * For example, Haskell's guards
879
+ * @example
880
+ * f x
881
+ * | x > 2 = x * 2
882
+ * | otherwise = x / 2
883
+ * @category Declarations
884
+ */
885
+ export class GuardedBody extends ASTNode {
886
+ /** @hidden */
887
+ public body: Expression;
888
+ /** @hidden */
889
+ public condition: Expression;
890
+
891
+ constructor(condition: Expression, body: Expression, loc?: SourceLocation) {
892
+ super(loc);
893
+ this.condition = condition;
894
+ this.body = body;
895
+ }
896
+ public accept<R>(visitor: Visitor<R>): R {
897
+ return visitor.visitGuardedBody?.(this);
898
+ }
899
+ public toJSON() {
900
+ return {
901
+ type: "GuardedBody",
902
+ condition: this.condition.toJSON(),
903
+ body: this.body.toJSON(),
904
+ };
905
+ }
906
+ }
907
+
908
+ /**
909
+ * Represents one Equation with its arguments and body. Allows for overloading and pattern matching.
910
+ * You may define the return statement to access it more easily.
911
+ *
912
+ * @example
913
+ * add 0 y = y
914
+ * add x y = x + y
915
+ * @category Declarations
916
+ */
917
+ export class Equation extends ASTNode {
918
+ /** @hidden */
919
+ public patterns: Pattern[];
920
+ /** @hidden */
921
+ public body: UnguardedBody | GuardedBody[];
922
+ /** @hidden */
923
+ public returnExpr?: Return;
924
+ constructor(
925
+ patterns: Pattern[],
926
+ body: UnguardedBody | GuardedBody[],
927
+ returnExpr?: Return,
928
+ loc?: SourceLocation
929
+ ) {
930
+ super(loc);
931
+ this.patterns = patterns;
932
+ this.body = body;
933
+ this.returnExpr = returnExpr;
934
+ }
935
+ /** @hidden */
936
+ public accept<R>(visitor: Visitor<R>): R {
937
+ return visitor.visitEquation?.(this);
938
+ }
939
+ /** @hidden */
940
+ public toJSON() {
941
+ return {
942
+ type: "Equation",
943
+ patterns: this.patterns.map((pattern) => pattern.toJSON),
944
+ body: Array.isArray(this.body)
945
+ ? this.body.map((guard) => guard.toJSON())
946
+ : this.body.toJSON(),
947
+ return: this.returnExpr.toJSON(),
948
+ };
949
+ }
950
+ }
951
+
952
+ /**
953
+ * Functional / Imperative programming function declaration.
954
+ * It is is composed by an identifier and one or more equations
955
+ * @example
956
+ * int foo (int bar) {
957
+ * return bar;
958
+ * }
959
+ * @example
960
+ * def foo(bar):
961
+ * return bar
962
+ * @category Declarations
963
+ */
964
+ export class Function extends ASTNode {
965
+ /** @hidden */
966
+ public equations: Equation[];
967
+ /** @hidden */
968
+ public identifier: SymbolPrimitive;
969
+
970
+ constructor(
971
+ identifier: SymbolPrimitive,
972
+ equations: Equation[],
973
+ loc?: SourceLocation
974
+ ) {
975
+ super(loc);
976
+ this.identifier = identifier;
977
+ this.equations = equations;
978
+ }
979
+ public accept<R>(visitor: Visitor<R>): R {
980
+ return visitor.visitFunction?.(this);
981
+ }
982
+ public toJSON() {
983
+ return {
984
+ type: "Function",
985
+ identifier: this.identifier.toJSON(),
986
+ equations: this.equations.map((eq) => eq.toJSON()),
987
+ };
988
+ }
989
+ }
990
+
991
+ /**
992
+ * Represents a case expression, selecting a branch based on pattern matching against a value.
993
+ *
994
+ * @example
995
+ * case x of
996
+ * [] -> 0
997
+ * (x:xs) -> 1 + length xs
998
+ * @category Expressions
999
+ */
1000
+ export class Case extends ASTNode {
1001
+ /** @hidden */
1002
+ public body: Expression;
1003
+ /** @hidden */
1004
+ public condition: Expression;
1005
+
1006
+ constructor(condition: Expression, body: Expression, loc?: SourceLocation) {
1007
+ super(loc);
1008
+ this.condition = condition;
1009
+ this.body = body;
1010
+ }
1011
+ public accept<R>(visitor: Visitor<R>): R {
1012
+ return visitor.visitCase?.(this);
1013
+ }
1014
+ public toJSON() {
1015
+ return {
1016
+ type: "Case",
1017
+ condition: this.condition.toJSON(),
1018
+ body: this.body.toJSON(),
1019
+ };
1020
+ }
1021
+ }
1022
+ /**
1023
+ * Represents a switch statement, selecting execution paths based on value equality.
1024
+ * @category Expressions
1025
+ */
1026
+ export class Switch extends ASTNode {
1027
+ /** @hidden */
1028
+ public defaultExpr?: Expression;
1029
+ /** @hidden */
1030
+ public cases: Case[];
1031
+ /** @hidden */
1032
+ public value: Expression;
1033
+
1034
+ constructor(
1035
+ value: Expression,
1036
+ cases: Case[],
1037
+ defaultExpr?: Expression,
1038
+ loc?: SourceLocation
1039
+ ) {
1040
+ super(loc);
1041
+ this.value = value;
1042
+ this.cases = cases;
1043
+ this.defaultExpr = defaultExpr;
1044
+ }
1045
+ public accept<R>(visitor: Visitor<R>): R {
1046
+ return visitor.visitSwitch?.(this);
1047
+ }
1048
+ public toJSON() {
1049
+ return {
1050
+ type: "Switch",
1051
+ value: this.value.toJSON(),
1052
+ cases: this.cases.map((caseVal) => ({
1053
+ condition: caseVal.condition.toJSON(),
1054
+ body: caseVal.body.toJSON(),
1055
+ })),
1056
+ default: this.defaultExpr.toJSON(),
1057
+ };
1058
+ }
1059
+ }
1060
+
1061
+ /**
1062
+ * Represents a catch block for handling exceptions thrown in a try block.
1063
+ * @category Statements
1064
+ */
1065
+ export class Catch extends ASTNode {
1066
+ /** @hidden */
1067
+ public body: Expression;
1068
+ /** @hidden */
1069
+ public patterns: Pattern[];
1070
+
1071
+ constructor(patterns: Pattern[], body: Expression, loc?: SourceLocation) {
1072
+ super(loc);
1073
+ this.patterns = patterns;
1074
+ this.body = body;
1075
+ }
1076
+ public accept<R>(visitor: Visitor<R>): R {
1077
+ return visitor.visitCatch?.(this);
1078
+ }
1079
+ public toJSON() {
1080
+ return {
1081
+ type: "Catch",
1082
+ patterns: this.patterns.map((pat) => pat.toJSON()),
1083
+ body: this.body.toJSON(),
1084
+ };
1085
+ }
1086
+ }
1087
+ /**
1088
+ * Represents a try block, wrapping code that might throw exceptions.
1089
+ *
1090
+ * @example
1091
+ * try { ... } catch e : DomainException { ... }
1092
+ * @category Statements
1093
+ */
1094
+ export class Try extends ASTNode {
1095
+ /** @hidden */
1096
+ public finallyExpr: Expression;
1097
+ /** @hidden */
1098
+ public catchExpr: Catch[];
1099
+ /** @hidden */
1100
+ public body: Expression;
1101
+
1102
+ constructor(
1103
+ body: Expression,
1104
+ catchExpr: Catch[],
1105
+ finallyExpr: Expression,
1106
+ loc?: SourceLocation
1107
+ ) {
1108
+ super(loc);
1109
+ this.body = body;
1110
+ this.catchExpr = catchExpr;
1111
+ this.finallyExpr = finallyExpr;
1112
+ }
1113
+ public accept<R>(visitor: Visitor<R>): R {
1114
+ return visitor.visitTry?.(this);
1115
+ }
1116
+ public toJSON() {
1117
+ return {
1118
+ type: "Try",
1119
+ body: this.body.toJSON(),
1120
+ catch: this.catchExpr.map(({ patterns, body }) => ({
1121
+ condition: patterns.map((pattern) => pattern.toJSON()),
1122
+ body: body.toJSON(),
1123
+ })),
1124
+ finally: this.finallyExpr.toJSON(),
1125
+ };
1126
+ }
1127
+ }
1128
+
1129
+ /**
1130
+ * Represents an explicit raising or throwing of an exception or error.
1131
+ * @category Statements
1132
+ */
1133
+ export class Raise extends ASTNode {
1134
+ /** @hidden */
1135
+ public body: Expression;
1136
+
1137
+ constructor(body: Expression, loc?: SourceLocation) {
1138
+ super(loc);
1139
+ this.body = body;
1140
+ }
1141
+ public accept<R>(visitor: Visitor<R>): R {
1142
+ return visitor.visitRaise?.(this);
1143
+ }
1144
+ public toJSON() {
1145
+ return {
1146
+ type: "Raise",
1147
+ body: this.body.toJSON(),
1148
+ };
1149
+ }
1150
+ }
1151
+
1152
+ /**
1153
+ * Represents a command to output data to the standard output.
1154
+ * @category Statements
1155
+ */
1156
+ export class Print extends ASTNode {
1157
+ /** @hidden */
1158
+ public expression: Expression;
1159
+
1160
+ constructor(expression: Expression, loc?: SourceLocation) {
1161
+ super(loc);
1162
+ this.expression = expression;
1163
+ }
1164
+ public accept<R>(visitor: Visitor<R>): R {
1165
+ return visitor.visitPrint?.(this);
1166
+ }
1167
+ public toJSON() {
1168
+ return {
1169
+ type: "Print",
1170
+ expression: this.expression.toJSON(),
1171
+ };
1172
+ }
1173
+ }
1174
+ /**
1175
+ * Represents a command to read input from the user or standard input.
1176
+ * @category Statements
1177
+ */
1178
+ export class Input extends ASTNode {
1179
+ /** @hidden */
1180
+ public variable: SymbolPrimitive;
1181
+ /** @hidden */
1182
+ public message: Expression;
1183
+
1184
+ constructor(
1185
+ message: Expression,
1186
+ variable: SymbolPrimitive,
1187
+ loc?: SourceLocation
1188
+ ) {
1189
+ super(loc);
1190
+ this.message = message;
1191
+ this.variable = variable;
1192
+ }
1193
+ public accept<R>(visitor: Visitor<R>): R {
1194
+ return visitor.visitInput?.(this);
1195
+ }
1196
+ public toJSON() {
1197
+ return {
1198
+ type: "Input",
1199
+ message: this.message.toJSON(),
1200
+ variable: this.variable.toJSON(),
1201
+ };
1202
+ }
1203
+ }
1204
+
1205
+ /**
1206
+ * Represents a for-loop control structure for iterating over a sequence or range.
1207
+ * @category Statements
1208
+ */
1209
+ export class For extends ASTNode {
1210
+ /** @hidden */
1211
+ public statements: Statement[];
1212
+ /** @hidden */
1213
+ public body: Expression;
1214
+
1215
+ constructor(body: Expression, statements: Statement[], loc?: SourceLocation) {
1216
+ super(loc);
1217
+ this.body = body;
1218
+ this.statements = statements;
1219
+ }
1220
+ public accept<R>(visitor: Visitor<R>): R {
1221
+ return visitor.visitFor?.(this);
1222
+ }
1223
+ public toJSON() {
1224
+ return {
1225
+ type: "For",
1226
+ body: this.body.toJSON(),
1227
+ statements: this.statements.map((stmt) => stmt.toJSON()),
1228
+ };
1229
+ }
1230
+ }
1231
+ /**
1232
+ * Represents a control flow statement to exit the current loop immediately.
1233
+ * @category Statements
1234
+ */
1235
+ export class Break extends ASTNode {
1236
+ /** @hidden */
1237
+ public body?: Expression;
1238
+
1239
+ constructor(body: Expression = new NilPrimitive(null), loc?: SourceLocation) {
1240
+ super(loc);
1241
+ this.body = body;
1242
+ }
1243
+ public accept<R>(visitor: Visitor<R>): R {
1244
+ return visitor.visitBreak?.(this);
1245
+ }
1246
+ public toJSON() {
1247
+ return {
1248
+ type: "Break",
1249
+ body: this.body.toJSON(),
1250
+ };
1251
+ }
1252
+ }
1253
+ /**
1254
+ * Represents a control flow statement to skip the rest of the current loop iteration.
1255
+ * @category Statements
1256
+ */
1257
+ export class Continue extends ASTNode {
1258
+ /** @hidden */
1259
+ public body?: Expression;
1260
+
1261
+ constructor(body: Expression = new NilPrimitive(null), loc?: SourceLocation) {
1262
+ super(loc);
1263
+ this.body = body;
1264
+ }
1265
+ public accept<R>(visitor: Visitor<R>): R {
1266
+ return visitor.visitContinue?.(this);
1267
+ }
1268
+ public toJSON() {
1269
+ return {
1270
+ type: "Continue",
1271
+ body: this.body.toJSON(),
1272
+ };
1273
+ }
1274
+ }
1275
+
1276
+ /**
1277
+ * Represents a variable usage or reference in an expression.
1278
+ * @category Expressions
1279
+ */
1280
+ export class Variable extends ASTNode {
1281
+ /** @hidden */
1282
+ public variableType?: Type;
1283
+ /** @hidden */
1284
+ public expression: Expression;
1285
+ /** @hidden */
1286
+ public identifier: SymbolPrimitive;
1287
+
1288
+ constructor(
1289
+ identifier: SymbolPrimitive,
1290
+ expression: Expression,
1291
+ variableType?: Type,
1292
+ loc?: SourceLocation
1293
+ ) {
1294
+ super(loc);
1295
+ this.identifier = identifier;
1296
+ this.expression = expression;
1297
+ this.variableType = variableType;
1298
+ }
1299
+ public accept<R>(visitor: Visitor<R>): R {
1300
+ return visitor.visitVariable?.(this);
1301
+ }
1302
+ public toJSON() {
1303
+ return {
1304
+ type: "Variable",
1305
+ identifier: this.identifier.toJSON(),
1306
+ expression: this.expression.toJSON(),
1307
+ variableType: this.variableType.toJSON(),
1308
+ };
1309
+ }
1310
+ }
1311
+
1312
+ /**
1313
+ * Represents an assignment operation, binding a value to a variable.
1314
+ *
1315
+ * @example
1316
+ * count = count + 1
1317
+ * @category Statements
1318
+ */
1319
+ export class Assignment extends ASTNode {
1320
+ /** @hidden */
1321
+ public expression: Expression;
1322
+ /** @hidden */
1323
+ public identifier: SymbolPrimitive;
1324
+
1325
+ constructor(
1326
+ identifier: SymbolPrimitive,
1327
+ expression: Expression,
1328
+ loc?: SourceLocation
1329
+ ) {
1330
+ super(loc);
1331
+ this.identifier = identifier;
1332
+ this.expression = expression;
1333
+ }
1334
+ public accept<R>(visitor: Visitor<R>): R {
1335
+ return visitor.visitAssignment?.(this);
1336
+ }
1337
+ public toJSON() {
1338
+ return {
1339
+ type: "Assignment",
1340
+ identifier: this.identifier.toJSON(),
1341
+ expression: this.expression.toJSON(),
1342
+ };
1343
+ }
1344
+ }
1345
+
1346
+ /**
1347
+ * Represents a sequence of statements executed in order.
1348
+ * @category Statements
1349
+ */
1350
+ export class Sequence extends ASTNode {
1351
+ /** @hidden */
1352
+ public statements: Statement[];
1353
+
1354
+ constructor(statements: Statement[], loc?: SourceLocation) {
1355
+ super(loc);
1356
+ this.statements = statements;
1357
+ }
1358
+ public accept<R>(visitor: Visitor<R>): R {
1359
+ return visitor.visitSequence?.(this);
1360
+ }
1361
+ public toJSON() {
1362
+ return {
1363
+ type: "Sequence",
1364
+ statements: this.statements.map((stmt) => stmt.toJSON()),
1365
+ };
1366
+ }
1367
+ }
1368
+
1369
+ export type Statement =
1370
+ | EntryPoint
1371
+ | Function
1372
+ | Clause
1373
+ | Procedure
1374
+ | TypeAlias
1375
+ | TypeSignature
1376
+ | Class
1377
+ | Object
1378
+ | Method
1379
+ | Super
1380
+ | Attribute
1381
+ | Interface
1382
+ | Switch
1383
+ | Send
1384
+ | Try
1385
+ | Return
1386
+ | Print
1387
+ | Input
1388
+ | Raise
1389
+ | Structure
1390
+ | Break
1391
+ | Continue
1392
+ | Call
1393
+ | Enumeration
1394
+ | Variable
1395
+ | Assignment
1396
+ | Yield
1397
+ | Record
1398
+ | If
1399
+ | Repeat
1400
+ | ForLoop
1401
+ | While;
1402
+
1403
+ export type AST = Statement[];
1404
+
1405
+ export interface YukigoParser {
1406
+ errors?: string[];
1407
+ parse: (code: string) => AST;
1408
+ }
1409
+
1410
+ /* export interface Match {
1411
+ type: "Match";
1412
+ condition: Expression;
1413
+ body: Equation[];
1414
+ }
1415
+
1416
+ export interface Arrow {
1417
+ type: "Arrow";
1418
+ expression1: Expression[];
1419
+ expression2: Expression[];
1420
+ }
1421
+ */