bahasa-simpl 1.0.5 → 1.0.6
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/dist/simpl-interpreter.js +212 -194
- package/package.json +1 -1
|
@@ -49,117 +49,6 @@ class Environment {
|
|
|
49
49
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const RESERVED_KEYWORDS = [
|
|
53
|
-
"rubah",
|
|
54
|
-
"kalau",
|
|
55
|
-
"namun",
|
|
56
|
-
"slagi",
|
|
57
|
-
"untuk",
|
|
58
|
-
"cetak",
|
|
59
|
-
"henti",
|
|
60
|
-
"lewat",
|
|
61
|
-
"dalam",
|
|
62
|
-
"hasil",
|
|
63
|
-
"kerja",
|
|
64
|
-
"datum",
|
|
65
|
-
"jenis",
|
|
66
|
-
"model",
|
|
67
|
-
"error",
|
|
68
|
-
"tetap",
|
|
69
|
-
"modul",
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
const RUBAH = 0,
|
|
73
|
-
KALAU = 1,
|
|
74
|
-
NAMUN = 2,
|
|
75
|
-
SLAGI = 3,
|
|
76
|
-
UNTUK = 4,
|
|
77
|
-
CETAK = 5,
|
|
78
|
-
HENTI = 6,
|
|
79
|
-
LEWAT = 7,
|
|
80
|
-
DALAM = 8,
|
|
81
|
-
HASIL = 9,
|
|
82
|
-
KERJA = 10,
|
|
83
|
-
DATUM = 11,
|
|
84
|
-
JENIS = 12,
|
|
85
|
-
MODEL = 13,
|
|
86
|
-
TETAP = 15,
|
|
87
|
-
MODUL = 16,
|
|
88
|
-
EOF = 17,
|
|
89
|
-
ID = 18,
|
|
90
|
-
LITERAL = 19,
|
|
91
|
-
PLUS = 20,
|
|
92
|
-
MINUS = 21,
|
|
93
|
-
STAR = 22,
|
|
94
|
-
SLASH = 23,
|
|
95
|
-
LPAREN = 24,
|
|
96
|
-
RPAREN = 25,
|
|
97
|
-
GREATER = 26,
|
|
98
|
-
GREATER_EQUAL = 27,
|
|
99
|
-
LESS = 28,
|
|
100
|
-
LESS_EQUAL = 29,
|
|
101
|
-
EQUAL = 30,
|
|
102
|
-
EQUAL_EQUAL = 31,
|
|
103
|
-
DOT = 32,
|
|
104
|
-
LCURLY = 33,
|
|
105
|
-
RCURLY = 34,
|
|
106
|
-
COMMA = 35,
|
|
107
|
-
LSQUARE = 36,
|
|
108
|
-
RSQUARE = 37,
|
|
109
|
-
PIPE = 38,
|
|
110
|
-
AMPERSAND = 39,
|
|
111
|
-
BANG = 40,
|
|
112
|
-
ARROW = 41,
|
|
113
|
-
BANG_EQUAL = 42,
|
|
114
|
-
MODULUS = 43;
|
|
115
|
-
|
|
116
|
-
const TOKEN_STRING = [
|
|
117
|
-
"RUBAH",
|
|
118
|
-
"KALAU",
|
|
119
|
-
"NAMUN",
|
|
120
|
-
"SLAGI",
|
|
121
|
-
"UNTUK",
|
|
122
|
-
"CETAK",
|
|
123
|
-
"HENTI",
|
|
124
|
-
"LEWAT",
|
|
125
|
-
"DALAM",
|
|
126
|
-
"HASIL",
|
|
127
|
-
"KERJA",
|
|
128
|
-
"DATUM",
|
|
129
|
-
"JENIS",
|
|
130
|
-
"MODEL",
|
|
131
|
-
"ERROR",
|
|
132
|
-
"TETAP",
|
|
133
|
-
"MODUL",
|
|
134
|
-
"EOF",
|
|
135
|
-
"ID",
|
|
136
|
-
"LITERAL",
|
|
137
|
-
"PLUS",
|
|
138
|
-
"MINUS",
|
|
139
|
-
"BINTANG",
|
|
140
|
-
"GARIS_MIRING",
|
|
141
|
-
"LPAREN",
|
|
142
|
-
"RPAREN",
|
|
143
|
-
"LEBIH",
|
|
144
|
-
"LEBIH_SAMA",
|
|
145
|
-
"KURANG",
|
|
146
|
-
"KURANG_SAMA",
|
|
147
|
-
"SAMA",
|
|
148
|
-
"SAMA_SAMA",
|
|
149
|
-
"DOT",
|
|
150
|
-
"LCURLY",
|
|
151
|
-
"RCURLY",
|
|
152
|
-
"COMMA",
|
|
153
|
-
"LSQUARE",
|
|
154
|
-
"RSQUARE",
|
|
155
|
-
"PIPA",
|
|
156
|
-
"AMPERSAN",
|
|
157
|
-
"SERU",
|
|
158
|
-
"ARROW",
|
|
159
|
-
"SERU_SAMA",
|
|
160
|
-
"MODULUS",
|
|
161
|
-
];
|
|
162
|
-
|
|
163
52
|
const RESERVED_NAMES = [
|
|
164
53
|
"petik", "angka", "logis", "mesin", "baris", "stipe", "modul"
|
|
165
54
|
];
|
|
@@ -194,24 +83,9 @@ class Stipe extends Variable {
|
|
|
194
83
|
constructor(type, data) {
|
|
195
84
|
super(stipeSymbol, true, data);
|
|
196
85
|
this.symbol = type;
|
|
197
|
-
this.
|
|
198
|
-
this.member = null;
|
|
86
|
+
this.member = new Environment();
|
|
199
87
|
}
|
|
200
88
|
|
|
201
|
-
operate(visitor, op, right, left) {
|
|
202
|
-
let opLexeme = TOKEN_STRING[op] + (left ? "" : "_UNARY");
|
|
203
|
-
let operatorFunc = this.operators.get(opLexeme);
|
|
204
|
-
if (!operatorFunc)
|
|
205
|
-
visitor.error(`operator ${opLexeme} tidak terdefinisi untuk Model ${right.type.description}.`);
|
|
206
|
-
|
|
207
|
-
let result = null;
|
|
208
|
-
if (left) { // Binary
|
|
209
|
-
result = visitor.callFunc(operatorFunc.data, [right, left]);
|
|
210
|
-
} else { // Unary, safe because valid unary op is just + - ! in the parser
|
|
211
|
-
result = visitor.callFunc(operatorFunc.data, [right]);
|
|
212
|
-
}
|
|
213
|
-
return result;
|
|
214
|
-
}
|
|
215
89
|
}
|
|
216
90
|
|
|
217
91
|
class PetikTipe extends Stipe {
|
|
@@ -251,30 +125,28 @@ class PetikTipe extends Stipe {
|
|
|
251
125
|
|
|
252
126
|
init() {
|
|
253
127
|
// BINARY / UNARY OPERATORS
|
|
254
|
-
this.
|
|
128
|
+
this.member.define("PLUS",
|
|
255
129
|
makeBuiltInFunc([petikSymbol, petikSymbol], petikSymbol, (_, [r, l]) => new Value(petikSymbol, l.data + r.data)));
|
|
256
|
-
this.
|
|
130
|
+
this.member.define("LEBIH",
|
|
257
131
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
258
|
-
this.
|
|
132
|
+
this.member.define("KURANG",
|
|
259
133
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
260
|
-
this.
|
|
134
|
+
this.member.define("SAMA_SAMA",
|
|
261
135
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
262
|
-
this.
|
|
136
|
+
this.member.define("LEBIH_SAMA",
|
|
263
137
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
264
|
-
this.
|
|
138
|
+
this.member.define("KURANG_SAMA",
|
|
265
139
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
266
|
-
this.
|
|
140
|
+
this.member.define("SERU_SAMA",
|
|
267
141
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
268
|
-
this.
|
|
142
|
+
this.member.define("AMPERSAN",
|
|
269
143
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
270
|
-
this.
|
|
144
|
+
this.member.define("PIPA",
|
|
271
145
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
272
146
|
|
|
273
|
-
this.
|
|
147
|
+
this.member.define("SERU_UNER",
|
|
274
148
|
makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
275
149
|
|
|
276
|
-
this.member = new Environment();
|
|
277
|
-
|
|
278
150
|
this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
|
|
279
151
|
return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
|
|
280
152
|
}));
|
|
@@ -320,42 +192,40 @@ class AngkaTipe extends Stipe {
|
|
|
320
192
|
}
|
|
321
193
|
|
|
322
194
|
init() {
|
|
323
|
-
this.
|
|
195
|
+
this.member.define("PLUS",
|
|
324
196
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data + r.data)));
|
|
325
|
-
this.
|
|
197
|
+
this.member.define("MINUS",
|
|
326
198
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data - r.data)));
|
|
327
|
-
this.
|
|
199
|
+
this.member.define("BINTANG",
|
|
328
200
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data * r.data)));
|
|
329
|
-
this.
|
|
201
|
+
this.member.define("GARIS_MIRING",
|
|
330
202
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data / r.data)));
|
|
331
|
-
this.
|
|
203
|
+
this.member.define("MODULUS",
|
|
332
204
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data % r.data)));
|
|
333
205
|
|
|
334
|
-
this.
|
|
206
|
+
this.member.define("LEBIH",
|
|
335
207
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
336
|
-
this.
|
|
208
|
+
this.member.define("KURANG",
|
|
337
209
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
338
|
-
this.
|
|
210
|
+
this.member.define("SAMA_SAMA",
|
|
339
211
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
340
|
-
this.
|
|
212
|
+
this.member.define("LEBIH_SAMA",
|
|
341
213
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
342
|
-
this.
|
|
214
|
+
this.member.define("KURANG_SAMA",
|
|
343
215
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
344
|
-
this.
|
|
216
|
+
this.member.define("SERU_SAMA",
|
|
345
217
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
346
|
-
this.
|
|
218
|
+
this.member.define("AMPERSAN",
|
|
347
219
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
348
|
-
this.
|
|
220
|
+
this.member.define("PIPA",
|
|
349
221
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
350
|
-
this.
|
|
222
|
+
this.member.define("SERU_UNER",
|
|
351
223
|
makeBuiltInFunc([angkaSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
352
|
-
this.
|
|
224
|
+
this.member.define("PLUS_UNER",
|
|
353
225
|
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, +r.data)));
|
|
354
|
-
this.
|
|
226
|
+
this.member.define("MINUS_UNER",
|
|
355
227
|
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
|
|
356
228
|
|
|
357
|
-
this.member = new Environment();
|
|
358
|
-
|
|
359
229
|
this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
360
230
|
return new Value(angkaSymbol, Math.round(a.data));
|
|
361
231
|
}));
|
|
@@ -371,25 +241,23 @@ class AngkaTipe extends Stipe {
|
|
|
371
241
|
class LogisTipe extends Stipe {
|
|
372
242
|
constructor() {
|
|
373
243
|
super(logisSymbol, new Callable(null, (_, args) => {
|
|
374
|
-
return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data.member));
|
|
244
|
+
return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data.member.size));
|
|
375
245
|
}, [[null]], logisSymbol, true)
|
|
376
246
|
);
|
|
377
247
|
this.init();
|
|
378
248
|
}
|
|
379
249
|
|
|
380
250
|
init() {
|
|
381
|
-
this.
|
|
251
|
+
this.member.define("SAMA_SAMA",
|
|
382
252
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
383
|
-
this.
|
|
253
|
+
this.member.define("SERU_SAMA",
|
|
384
254
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
385
|
-
this.
|
|
255
|
+
this.member.define("AMPERSAN",
|
|
386
256
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
387
|
-
this.
|
|
257
|
+
this.member.define("PIPA",
|
|
388
258
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
389
|
-
this.
|
|
259
|
+
this.member.define("SERU_UNER",
|
|
390
260
|
makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
391
|
-
|
|
392
|
-
this.member = new Environment();
|
|
393
261
|
}
|
|
394
262
|
}
|
|
395
263
|
|
|
@@ -400,17 +268,17 @@ class BarisTipe extends Stipe {
|
|
|
400
268
|
}
|
|
401
269
|
|
|
402
270
|
init() {
|
|
403
|
-
this.
|
|
271
|
+
this.member.define("PLUS",
|
|
404
272
|
makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
|
|
405
273
|
new Value(barisSymbol, Array(...l.data, ...r.data))
|
|
406
274
|
));
|
|
407
275
|
|
|
408
|
-
this.
|
|
276
|
+
this.member.define("MINUS_UNER",
|
|
409
277
|
makeBuiltInFunc([barisSymbol], barisSymbol, (_, [r]) =>
|
|
410
278
|
new Value(barisSymbol, r.data.slice(0, r.length))
|
|
411
279
|
));
|
|
412
280
|
|
|
413
|
-
this.
|
|
281
|
+
this.member.define("SAMA_SAMA",
|
|
414
282
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
415
283
|
if (a.length !== b.length) return false;
|
|
416
284
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -420,7 +288,7 @@ class BarisTipe extends Stipe {
|
|
|
420
288
|
})(l.data, r.data)))
|
|
421
289
|
);
|
|
422
290
|
|
|
423
|
-
this.
|
|
291
|
+
this.member.define("SERU_SAMA",
|
|
424
292
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
425
293
|
if (a.length !== b.length) return true;
|
|
426
294
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -430,15 +298,13 @@ class BarisTipe extends Stipe {
|
|
|
430
298
|
})(l.data, r.data)))
|
|
431
299
|
);
|
|
432
300
|
|
|
433
|
-
this.
|
|
301
|
+
this.member.define("AMPERSAN",
|
|
434
302
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
435
|
-
this.
|
|
303
|
+
this.member.define("PIPA",
|
|
436
304
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
437
|
-
this.
|
|
305
|
+
this.member.define("SERU_UNER",
|
|
438
306
|
makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
439
307
|
|
|
440
|
-
this.member = new Environment();
|
|
441
|
-
|
|
442
308
|
this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
|
|
443
309
|
if (b.data.length <= i.data) {
|
|
444
310
|
v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
|
|
@@ -501,7 +367,7 @@ class BarisTipe extends Stipe {
|
|
|
501
367
|
class MesinTipe extends Stipe {
|
|
502
368
|
constructor() {
|
|
503
369
|
super(mesinSymbol);
|
|
504
|
-
this.member
|
|
370
|
+
this.member.define("$", null);
|
|
505
371
|
}
|
|
506
372
|
}
|
|
507
373
|
|
|
@@ -513,15 +379,20 @@ let Model$1 = class Model extends Stipe {
|
|
|
513
379
|
let obj = new Value(sym, true);
|
|
514
380
|
obj.member = new Environment();
|
|
515
381
|
|
|
382
|
+
let callLine = v.line;
|
|
383
|
+
|
|
516
384
|
for (let i = 0; i < args.length; i++) {
|
|
517
385
|
let type = params[i][0];
|
|
518
386
|
let symbol = type.accept(v);
|
|
519
387
|
let name = params[i][1].lexeme;
|
|
520
388
|
|
|
521
389
|
let val = new Variable(symbol, type.tetap, args[i].data);
|
|
522
|
-
if (
|
|
390
|
+
if (symbol === null) {
|
|
523
391
|
val.isDatum = true;
|
|
524
392
|
val.type = args[i].type;
|
|
393
|
+
} else if (args[i].type !== symbol) {
|
|
394
|
+
v.line = callLine;
|
|
395
|
+
v.error(`Argumen pembuatan objek tidak sama dengan argumen model, menemukan ${args[i].type?.description}, mengharapkan ${symbol ? symbol.description : "nihil" }`);
|
|
525
396
|
}
|
|
526
397
|
val.member = args[i].member;
|
|
527
398
|
obj.member.define(name, val);
|
|
@@ -537,7 +408,6 @@ let Jenis$1 = class Jenis extends Stipe {
|
|
|
537
408
|
constructor(name, enums) {
|
|
538
409
|
let sym = Symbol(name);
|
|
539
410
|
super(sym, null);
|
|
540
|
-
this.member = new Environment();
|
|
541
411
|
enums.forEach((thing, idx) => {
|
|
542
412
|
this.member.define(thing.lexeme, new Value(sym, idx));
|
|
543
413
|
});
|
|
@@ -545,9 +415,9 @@ let Jenis$1 = class Jenis extends Stipe {
|
|
|
545
415
|
}
|
|
546
416
|
|
|
547
417
|
init(sym) {
|
|
548
|
-
this.
|
|
418
|
+
this.member.define("SAMA_SAMA",
|
|
549
419
|
makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
550
|
-
this.
|
|
420
|
+
this.member.define("SERU_SAMA",
|
|
551
421
|
makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
552
422
|
}
|
|
553
423
|
};
|
|
@@ -632,11 +502,146 @@ const GLOBAL_ENV = (() => {
|
|
|
632
502
|
mtkModul.member.define("akar2", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
633
503
|
return new Value(angkaSymbol, Math.sqrt(a.data));
|
|
634
504
|
}));
|
|
505
|
+
mtkModul.member.define("min", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
506
|
+
return new Value(angkaSymbol, Math.min(a.data, b.data));
|
|
507
|
+
}));
|
|
508
|
+
mtkModul.member.define("maks", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
509
|
+
return new Value(angkaSymbol, Math.max(a.data, b.data));
|
|
510
|
+
}));
|
|
511
|
+
|
|
512
|
+
const fpb = (a, b) => {
|
|
513
|
+
[a, b] = [Math.max(a, b), Math.min(a, b)];
|
|
514
|
+
while (b > 0) {
|
|
515
|
+
[a, b] = [b, a % b];
|
|
516
|
+
}
|
|
517
|
+
return a
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
mtkModul.member.define("fpb", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
521
|
+
let fpbVal = fpb(a.data, b.data);
|
|
522
|
+
return new Value(angkaSymbol, fpbVal);
|
|
523
|
+
}));
|
|
524
|
+
|
|
525
|
+
mtkModul.member.define("kpk", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
526
|
+
let fpbVal = fpb(a.data, b.data);
|
|
527
|
+
return new Value(angkaSymbol, a.data*b*data/fpbVal);
|
|
528
|
+
}));
|
|
635
529
|
|
|
636
530
|
env.define("mtk", mtkModul);
|
|
637
531
|
return env;
|
|
638
532
|
})();
|
|
639
533
|
|
|
534
|
+
const RESERVED_KEYWORDS = [
|
|
535
|
+
"rubah",
|
|
536
|
+
"kalau",
|
|
537
|
+
"namun",
|
|
538
|
+
"slagi",
|
|
539
|
+
"untuk",
|
|
540
|
+
"cetak",
|
|
541
|
+
"henti",
|
|
542
|
+
"lewat",
|
|
543
|
+
"dalam",
|
|
544
|
+
"hasil",
|
|
545
|
+
"kerja",
|
|
546
|
+
"datum",
|
|
547
|
+
"jenis",
|
|
548
|
+
"model",
|
|
549
|
+
"error",
|
|
550
|
+
"tetap",
|
|
551
|
+
"modul",
|
|
552
|
+
];
|
|
553
|
+
|
|
554
|
+
const RUBAH = 0,
|
|
555
|
+
KALAU = 1,
|
|
556
|
+
NAMUN = 2,
|
|
557
|
+
SLAGI = 3,
|
|
558
|
+
UNTUK = 4,
|
|
559
|
+
CETAK = 5,
|
|
560
|
+
HENTI = 6,
|
|
561
|
+
LEWAT = 7,
|
|
562
|
+
DALAM = 8,
|
|
563
|
+
HASIL = 9,
|
|
564
|
+
KERJA = 10,
|
|
565
|
+
DATUM = 11,
|
|
566
|
+
JENIS = 12,
|
|
567
|
+
MODEL = 13,
|
|
568
|
+
TETAP = 15,
|
|
569
|
+
MODUL = 16,
|
|
570
|
+
EOF = 17,
|
|
571
|
+
ID = 18,
|
|
572
|
+
LITERAL = 19,
|
|
573
|
+
PLUS = 20,
|
|
574
|
+
MINUS = 21,
|
|
575
|
+
STAR = 22,
|
|
576
|
+
SLASH = 23,
|
|
577
|
+
LPAREN = 24,
|
|
578
|
+
RPAREN = 25,
|
|
579
|
+
GREATER = 26,
|
|
580
|
+
GREATER_EQUAL = 27,
|
|
581
|
+
LESS = 28,
|
|
582
|
+
LESS_EQUAL = 29,
|
|
583
|
+
EQUAL = 30,
|
|
584
|
+
EQUAL_EQUAL = 31,
|
|
585
|
+
DOT = 32,
|
|
586
|
+
LCURLY = 33,
|
|
587
|
+
RCURLY = 34,
|
|
588
|
+
COMMA = 35,
|
|
589
|
+
LSQUARE = 36,
|
|
590
|
+
RSQUARE = 37,
|
|
591
|
+
PIPE = 38,
|
|
592
|
+
AMPERSAND = 39,
|
|
593
|
+
BANG = 40,
|
|
594
|
+
ARROW = 41,
|
|
595
|
+
BANG_EQUAL = 42,
|
|
596
|
+
MODULUS = 43;
|
|
597
|
+
|
|
598
|
+
const TOKEN_STRING = [
|
|
599
|
+
"RUBAH",
|
|
600
|
+
"KALAU",
|
|
601
|
+
"NAMUN",
|
|
602
|
+
"SLAGI",
|
|
603
|
+
"UNTUK",
|
|
604
|
+
"CETAK",
|
|
605
|
+
"HENTI",
|
|
606
|
+
"LEWAT",
|
|
607
|
+
"DALAM",
|
|
608
|
+
"HASIL",
|
|
609
|
+
"KERJA",
|
|
610
|
+
"DATUM",
|
|
611
|
+
"JENIS",
|
|
612
|
+
"MODEL",
|
|
613
|
+
"ERROR",
|
|
614
|
+
"TETAP",
|
|
615
|
+
"MODUL",
|
|
616
|
+
"EOF",
|
|
617
|
+
"ID",
|
|
618
|
+
"LITERAL",
|
|
619
|
+
"PLUS",
|
|
620
|
+
"MINUS",
|
|
621
|
+
"BINTANG",
|
|
622
|
+
"GARIS_MIRING",
|
|
623
|
+
"LPAREN",
|
|
624
|
+
"RPAREN",
|
|
625
|
+
"LEBIH",
|
|
626
|
+
"LEBIH_SAMA",
|
|
627
|
+
"KURANG",
|
|
628
|
+
"KURANG_SAMA",
|
|
629
|
+
"SAMA",
|
|
630
|
+
"SAMA_SAMA",
|
|
631
|
+
"DOT",
|
|
632
|
+
"LCURLY",
|
|
633
|
+
"RCURLY",
|
|
634
|
+
"COMMA",
|
|
635
|
+
"LSQUARE",
|
|
636
|
+
"RSQUARE",
|
|
637
|
+
"PIPA",
|
|
638
|
+
"AMPERSAN",
|
|
639
|
+
"SERU",
|
|
640
|
+
"ARROW",
|
|
641
|
+
"SERU_SAMA",
|
|
642
|
+
"MODULUS",
|
|
643
|
+
];
|
|
644
|
+
|
|
640
645
|
let Henti$1 = class Henti { };
|
|
641
646
|
let Lewat$1 = class Lewat { };
|
|
642
647
|
let Hasil$1 = class Hasil {
|
|
@@ -855,8 +860,8 @@ class Interpreter {
|
|
|
855
860
|
}
|
|
856
861
|
this.typeCheck(leftValue, rightValue, `Pada operasi biner ${binaryExpr.op.lexeme}`);
|
|
857
862
|
|
|
858
|
-
let
|
|
859
|
-
|
|
863
|
+
let type = this.environment.get(leftValue.type.description);
|
|
864
|
+
let result = this.operate(type, binaryExpr.op.type, rightValue, leftValue);
|
|
860
865
|
|
|
861
866
|
return result;
|
|
862
867
|
}
|
|
@@ -871,9 +876,24 @@ class Interpreter {
|
|
|
871
876
|
this.error(`Tidak bisa mengoperasikan nilai Nihil.`);
|
|
872
877
|
}
|
|
873
878
|
|
|
874
|
-
let
|
|
875
|
-
|
|
879
|
+
let type = this.environment.get(rightValue.type.description);
|
|
880
|
+
let result = this.operate(type, unaryExpr.op.type, rightValue);
|
|
881
|
+
|
|
882
|
+
return result;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
operate(type, op, right, left) {
|
|
886
|
+
let opLexeme = TOKEN_STRING[op] + (left ? "" : "_UNER");
|
|
887
|
+
let operatorFunc = type.member.get(opLexeme);
|
|
888
|
+
if (!operatorFunc)
|
|
889
|
+
this.error(`operator ${opLexeme} tidak terdefinisi untuk Model ${right.type.description}.`);
|
|
876
890
|
|
|
891
|
+
let result = null;
|
|
892
|
+
if (left) { // Binary
|
|
893
|
+
result = this.callFunc(operatorFunc.data, [right, left]);
|
|
894
|
+
} else { // Unary, safe because valid unary op is just + - ! in the parser
|
|
895
|
+
result = this.callFunc(operatorFunc.data, [right]);
|
|
896
|
+
}
|
|
877
897
|
return result;
|
|
878
898
|
}
|
|
879
899
|
|
|
@@ -1019,7 +1039,7 @@ class Interpreter {
|
|
|
1019
1039
|
visitKalauStmt(kalauStmt) {
|
|
1020
1040
|
// condition may be null for 'namun', accept the thenBlock if it is
|
|
1021
1041
|
let condition = kalauStmt.condition?.accept(this);
|
|
1022
|
-
if (condition
|
|
1042
|
+
if (condition?.type && condition?.type !== logisSymbol) {
|
|
1023
1043
|
this.error(`Ekspresi dalam 'kalau' harus bertipe logis, menemukan ${condition.type ? condition.type.description : "nihil"}`);
|
|
1024
1044
|
}
|
|
1025
1045
|
if (condition === null || condition === undefined || condition.data) {
|
|
@@ -1151,26 +1171,24 @@ class Interpreter {
|
|
|
1151
1171
|
if (variable.type !== stipeSymbol) {
|
|
1152
1172
|
this.error(`Modul hanya bisa _ditambahkan_ pada tipe. '${name}' bukan merupakan tipe.`);
|
|
1153
1173
|
}
|
|
1154
|
-
if (variable.member) {
|
|
1174
|
+
if (variable.member.memory.size > 0) {
|
|
1155
1175
|
this.error(`Tipe '${name}' sudah memiliki modul sendiri, tidak bisa definisi ulang.`);
|
|
1156
1176
|
}
|
|
1177
|
+
} else {
|
|
1178
|
+
variable = new Variable(modulSymbol, true, null);
|
|
1179
|
+
variable.member = new Environment();
|
|
1180
|
+
this.environment.define(name, variable);
|
|
1157
1181
|
}
|
|
1158
1182
|
|
|
1159
1183
|
let lastEnv = this.environment;
|
|
1160
|
-
|
|
1184
|
+
variable.member.enclosing = this.environment;
|
|
1185
|
+
this.environment = variable.member;
|
|
1161
1186
|
for (let stmt of modulStmt.statements) {
|
|
1162
1187
|
stmt.accept(this);
|
|
1163
1188
|
}
|
|
1164
1189
|
|
|
1165
|
-
[this.environment,
|
|
1190
|
+
[this.environment, variable.member] = [lastEnv, this.environment];
|
|
1166
1191
|
|
|
1167
|
-
if (variable) {
|
|
1168
|
-
variable.member = lastEnv;
|
|
1169
|
-
} else {
|
|
1170
|
-
let res = new Variable(modulSymbol, true, null);
|
|
1171
|
-
res.member = lastEnv;
|
|
1172
|
-
this.environment.define(name, res);
|
|
1173
|
-
}
|
|
1174
1192
|
}
|
|
1175
1193
|
|
|
1176
1194
|
// UTILITIES
|