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.
- package/CHANGELOG.md +19 -0
- package/dist/globals/generics.d.ts +740 -0
- package/dist/globals/generics.js +1128 -0
- package/dist/globals/helpers.d.ts +4 -0
- package/dist/globals/helpers.js +76 -0
- package/dist/globals/operators.d.ts +251 -0
- package/dist/globals/operators.js +336 -0
- package/dist/globals/patterns.d.ts +170 -0
- package/dist/globals/patterns.js +261 -0
- package/dist/globals/runtime.d.ts +22 -0
- package/dist/globals/runtime.js +6 -0
- package/dist/globals/types.d.ts +185 -0
- package/dist/globals/types.js +329 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/paradigms/data.d.ts +246 -0
- package/dist/paradigms/data.js +348 -0
- package/dist/paradigms/functional.d.ts +59 -0
- package/dist/paradigms/functional.js +103 -0
- package/dist/paradigms/imperative.d.ts +124 -0
- package/dist/paradigms/imperative.js +188 -0
- package/dist/paradigms/logic.d.ts +163 -0
- package/dist/paradigms/logic.js +240 -0
- package/dist/paradigms/object.d.ts +201 -0
- package/dist/paradigms/object.js +308 -0
- package/dist/visitor.d.ts +254 -0
- package/dist/visitor.js +426 -0
- package/package.json +25 -0
- package/src/globals/generics.ts +1421 -0
- package/src/globals/helpers.ts +107 -0
- package/src/globals/operators.ts +515 -0
- package/src/globals/patterns.ts +321 -0
- package/src/globals/runtime.ts +33 -0
- package/src/globals/types.ts +375 -0
- package/src/index.ts +12 -0
- package/src/paradigms/data.ts +393 -0
- package/src/paradigms/functional.ts +129 -0
- package/src/paradigms/imperative.ts +232 -0
- package/src/paradigms/logic.ts +314 -0
- package/src/paradigms/object.ts +366 -0
- package/src/visitor.ts +692 -0
- 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
|
+
*/
|