bahasa-simpl 1.0.5 → 1.0.7
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 +222 -202
- 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 {
|
|
@@ -235,9 +109,7 @@ class PetikTipe extends Stipe {
|
|
|
235
109
|
if (!thing?.type) return `nihil`;
|
|
236
110
|
let type = v.environment.get(thing.type.description);
|
|
237
111
|
if (type?.member.has("kePetik")) {
|
|
238
|
-
v.stack.push(v.line);
|
|
239
112
|
let res = v.callFunc(type.member.get("kePetik").data, [thing]).data;
|
|
240
|
-
v.stack.pop();
|
|
241
113
|
return res;
|
|
242
114
|
}
|
|
243
115
|
return `${thing.type.description}<>`;
|
|
@@ -251,30 +123,28 @@ class PetikTipe extends Stipe {
|
|
|
251
123
|
|
|
252
124
|
init() {
|
|
253
125
|
// BINARY / UNARY OPERATORS
|
|
254
|
-
this.
|
|
126
|
+
this.member.define("PLUS",
|
|
255
127
|
makeBuiltInFunc([petikSymbol, petikSymbol], petikSymbol, (_, [r, l]) => new Value(petikSymbol, l.data + r.data)));
|
|
256
|
-
this.
|
|
128
|
+
this.member.define("LEBIH",
|
|
257
129
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
258
|
-
this.
|
|
130
|
+
this.member.define("KURANG",
|
|
259
131
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
260
|
-
this.
|
|
132
|
+
this.member.define("SAMA_SAMA",
|
|
261
133
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
262
|
-
this.
|
|
134
|
+
this.member.define("LEBIH_SAMA",
|
|
263
135
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
264
|
-
this.
|
|
136
|
+
this.member.define("KURANG_SAMA",
|
|
265
137
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
266
|
-
this.
|
|
138
|
+
this.member.define("SERU_SAMA",
|
|
267
139
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
268
|
-
this.
|
|
140
|
+
this.member.define("AMPERSAN",
|
|
269
141
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
270
|
-
this.
|
|
142
|
+
this.member.define("PIPA",
|
|
271
143
|
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
272
144
|
|
|
273
|
-
this.
|
|
145
|
+
this.member.define("SERU_UNER",
|
|
274
146
|
makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
275
147
|
|
|
276
|
-
this.member = new Environment();
|
|
277
|
-
|
|
278
148
|
this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
|
|
279
149
|
return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
|
|
280
150
|
}));
|
|
@@ -320,42 +190,40 @@ class AngkaTipe extends Stipe {
|
|
|
320
190
|
}
|
|
321
191
|
|
|
322
192
|
init() {
|
|
323
|
-
this.
|
|
193
|
+
this.member.define("PLUS",
|
|
324
194
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data + r.data)));
|
|
325
|
-
this.
|
|
195
|
+
this.member.define("MINUS",
|
|
326
196
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data - r.data)));
|
|
327
|
-
this.
|
|
197
|
+
this.member.define("BINTANG",
|
|
328
198
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data * r.data)));
|
|
329
|
-
this.
|
|
199
|
+
this.member.define("GARIS_MIRING",
|
|
330
200
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data / r.data)));
|
|
331
|
-
this.
|
|
201
|
+
this.member.define("MODULUS",
|
|
332
202
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data % r.data)));
|
|
333
203
|
|
|
334
|
-
this.
|
|
204
|
+
this.member.define("LEBIH",
|
|
335
205
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
336
|
-
this.
|
|
206
|
+
this.member.define("KURANG",
|
|
337
207
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
338
|
-
this.
|
|
208
|
+
this.member.define("SAMA_SAMA",
|
|
339
209
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
340
|
-
this.
|
|
210
|
+
this.member.define("LEBIH_SAMA",
|
|
341
211
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
342
|
-
this.
|
|
212
|
+
this.member.define("KURANG_SAMA",
|
|
343
213
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
344
|
-
this.
|
|
214
|
+
this.member.define("SERU_SAMA",
|
|
345
215
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
346
|
-
this.
|
|
216
|
+
this.member.define("AMPERSAN",
|
|
347
217
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
348
|
-
this.
|
|
218
|
+
this.member.define("PIPA",
|
|
349
219
|
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
350
|
-
this.
|
|
220
|
+
this.member.define("SERU_UNER",
|
|
351
221
|
makeBuiltInFunc([angkaSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
352
|
-
this.
|
|
222
|
+
this.member.define("PLUS_UNER",
|
|
353
223
|
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, +r.data)));
|
|
354
|
-
this.
|
|
224
|
+
this.member.define("MINUS_UNER",
|
|
355
225
|
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
|
|
356
226
|
|
|
357
|
-
this.member = new Environment();
|
|
358
|
-
|
|
359
227
|
this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
360
228
|
return new Value(angkaSymbol, Math.round(a.data));
|
|
361
229
|
}));
|
|
@@ -371,25 +239,26 @@ class AngkaTipe extends Stipe {
|
|
|
371
239
|
class LogisTipe extends Stipe {
|
|
372
240
|
constructor() {
|
|
373
241
|
super(logisSymbol, new Callable(null, (_, args) => {
|
|
374
|
-
|
|
242
|
+
if (args[0].type === barisSymbol && args[0].data.length === 0) {
|
|
243
|
+
return new Value(logisSymbol, false);
|
|
244
|
+
}
|
|
245
|
+
return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data?.member?.size));
|
|
375
246
|
}, [[null]], logisSymbol, true)
|
|
376
247
|
);
|
|
377
248
|
this.init();
|
|
378
249
|
}
|
|
379
250
|
|
|
380
251
|
init() {
|
|
381
|
-
this.
|
|
252
|
+
this.member.define("SAMA_SAMA",
|
|
382
253
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
383
|
-
this.
|
|
254
|
+
this.member.define("SERU_SAMA",
|
|
384
255
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
385
|
-
this.
|
|
256
|
+
this.member.define("AMPERSAN",
|
|
386
257
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
387
|
-
this.
|
|
258
|
+
this.member.define("PIPA",
|
|
388
259
|
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
389
|
-
this.
|
|
260
|
+
this.member.define("SERU_UNER",
|
|
390
261
|
makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
391
|
-
|
|
392
|
-
this.member = new Environment();
|
|
393
262
|
}
|
|
394
263
|
}
|
|
395
264
|
|
|
@@ -400,17 +269,17 @@ class BarisTipe extends Stipe {
|
|
|
400
269
|
}
|
|
401
270
|
|
|
402
271
|
init() {
|
|
403
|
-
this.
|
|
272
|
+
this.member.define("PLUS",
|
|
404
273
|
makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
|
|
405
274
|
new Value(barisSymbol, Array(...l.data, ...r.data))
|
|
406
275
|
));
|
|
407
276
|
|
|
408
|
-
this.
|
|
277
|
+
this.member.define("MINUS_UNER",
|
|
409
278
|
makeBuiltInFunc([barisSymbol], barisSymbol, (_, [r]) =>
|
|
410
279
|
new Value(barisSymbol, r.data.slice(0, r.length))
|
|
411
280
|
));
|
|
412
281
|
|
|
413
|
-
this.
|
|
282
|
+
this.member.define("SAMA_SAMA",
|
|
414
283
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
415
284
|
if (a.length !== b.length) return false;
|
|
416
285
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -420,7 +289,7 @@ class BarisTipe extends Stipe {
|
|
|
420
289
|
})(l.data, r.data)))
|
|
421
290
|
);
|
|
422
291
|
|
|
423
|
-
this.
|
|
292
|
+
this.member.define("SERU_SAMA",
|
|
424
293
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
425
294
|
if (a.length !== b.length) return true;
|
|
426
295
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -430,15 +299,13 @@ class BarisTipe extends Stipe {
|
|
|
430
299
|
})(l.data, r.data)))
|
|
431
300
|
);
|
|
432
301
|
|
|
433
|
-
this.
|
|
302
|
+
this.member.define("AMPERSAN",
|
|
434
303
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
435
|
-
this.
|
|
304
|
+
this.member.define("PIPA",
|
|
436
305
|
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
437
|
-
this.
|
|
306
|
+
this.member.define("SERU_UNER",
|
|
438
307
|
makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
439
308
|
|
|
440
|
-
this.member = new Environment();
|
|
441
|
-
|
|
442
309
|
this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
|
|
443
310
|
if (b.data.length <= i.data) {
|
|
444
311
|
v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
|
|
@@ -501,7 +368,7 @@ class BarisTipe extends Stipe {
|
|
|
501
368
|
class MesinTipe extends Stipe {
|
|
502
369
|
constructor() {
|
|
503
370
|
super(mesinSymbol);
|
|
504
|
-
this.member
|
|
371
|
+
this.member.define("$", null);
|
|
505
372
|
}
|
|
506
373
|
}
|
|
507
374
|
|
|
@@ -513,15 +380,20 @@ let Model$1 = class Model extends Stipe {
|
|
|
513
380
|
let obj = new Value(sym, true);
|
|
514
381
|
obj.member = new Environment();
|
|
515
382
|
|
|
383
|
+
let callLine = v.line;
|
|
384
|
+
|
|
516
385
|
for (let i = 0; i < args.length; i++) {
|
|
517
386
|
let type = params[i][0];
|
|
518
387
|
let symbol = type.accept(v);
|
|
519
388
|
let name = params[i][1].lexeme;
|
|
520
389
|
|
|
521
390
|
let val = new Variable(symbol, type.tetap, args[i].data);
|
|
522
|
-
if (
|
|
391
|
+
if (symbol === null) {
|
|
523
392
|
val.isDatum = true;
|
|
524
393
|
val.type = args[i].type;
|
|
394
|
+
} else if (args[i].type !== symbol) {
|
|
395
|
+
v.line = callLine;
|
|
396
|
+
v.error(`Argumen pembuatan objek tidak sama dengan argumen model, menemukan ${args[i].type?.description}, mengharapkan ${symbol ? symbol.description : "nihil" }`);
|
|
525
397
|
}
|
|
526
398
|
val.member = args[i].member;
|
|
527
399
|
obj.member.define(name, val);
|
|
@@ -537,17 +409,20 @@ let Jenis$1 = class Jenis extends Stipe {
|
|
|
537
409
|
constructor(name, enums) {
|
|
538
410
|
let sym = Symbol(name);
|
|
539
411
|
super(sym, null);
|
|
540
|
-
this.member = new Environment();
|
|
541
412
|
enums.forEach((thing, idx) => {
|
|
542
413
|
this.member.define(thing.lexeme, new Value(sym, idx));
|
|
543
414
|
});
|
|
415
|
+
this.member.define("kePetik", makeBuiltInFunc([sym], petikSymbol, (_, [j]) => {
|
|
416
|
+
let enumName = enums.map(thing=>thing.lexeme)[j.data];
|
|
417
|
+
return new Value(petikSymbol, `${name}.${enumName}`);
|
|
418
|
+
}));
|
|
544
419
|
this.init(sym);
|
|
545
420
|
}
|
|
546
421
|
|
|
547
422
|
init(sym) {
|
|
548
|
-
this.
|
|
423
|
+
this.member.define("SAMA_SAMA",
|
|
549
424
|
makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
550
|
-
this.
|
|
425
|
+
this.member.define("SERU_SAMA",
|
|
551
426
|
makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
552
427
|
}
|
|
553
428
|
};
|
|
@@ -632,11 +507,146 @@ const GLOBAL_ENV = (() => {
|
|
|
632
507
|
mtkModul.member.define("akar2", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
633
508
|
return new Value(angkaSymbol, Math.sqrt(a.data));
|
|
634
509
|
}));
|
|
510
|
+
mtkModul.member.define("min", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
511
|
+
return new Value(angkaSymbol, Math.min(a.data, b.data));
|
|
512
|
+
}));
|
|
513
|
+
mtkModul.member.define("maks", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
514
|
+
return new Value(angkaSymbol, Math.max(a.data, b.data));
|
|
515
|
+
}));
|
|
516
|
+
|
|
517
|
+
const fpb = (a, b) => {
|
|
518
|
+
[a, b] = [Math.max(a, b), Math.min(a, b)];
|
|
519
|
+
while (b > 0) {
|
|
520
|
+
[a, b] = [b, a % b];
|
|
521
|
+
}
|
|
522
|
+
return a
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
mtkModul.member.define("fpb", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
526
|
+
let fpbVal = fpb(a.data, b.data);
|
|
527
|
+
return new Value(angkaSymbol, fpbVal);
|
|
528
|
+
}));
|
|
529
|
+
|
|
530
|
+
mtkModul.member.define("kpk", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
531
|
+
let fpbVal = fpb(a.data, b.data);
|
|
532
|
+
return new Value(angkaSymbol, a.data*b*data/fpbVal);
|
|
533
|
+
}));
|
|
635
534
|
|
|
636
535
|
env.define("mtk", mtkModul);
|
|
637
536
|
return env;
|
|
638
537
|
})();
|
|
639
538
|
|
|
539
|
+
const RESERVED_KEYWORDS = [
|
|
540
|
+
"rubah",
|
|
541
|
+
"kalau",
|
|
542
|
+
"namun",
|
|
543
|
+
"slagi",
|
|
544
|
+
"untuk",
|
|
545
|
+
"cetak",
|
|
546
|
+
"henti",
|
|
547
|
+
"lewat",
|
|
548
|
+
"dalam",
|
|
549
|
+
"hasil",
|
|
550
|
+
"kerja",
|
|
551
|
+
"datum",
|
|
552
|
+
"jenis",
|
|
553
|
+
"model",
|
|
554
|
+
"error",
|
|
555
|
+
"tetap",
|
|
556
|
+
"modul",
|
|
557
|
+
];
|
|
558
|
+
|
|
559
|
+
const RUBAH = 0,
|
|
560
|
+
KALAU = 1,
|
|
561
|
+
NAMUN = 2,
|
|
562
|
+
SLAGI = 3,
|
|
563
|
+
UNTUK = 4,
|
|
564
|
+
CETAK = 5,
|
|
565
|
+
HENTI = 6,
|
|
566
|
+
LEWAT = 7,
|
|
567
|
+
DALAM = 8,
|
|
568
|
+
HASIL = 9,
|
|
569
|
+
KERJA = 10,
|
|
570
|
+
DATUM = 11,
|
|
571
|
+
JENIS = 12,
|
|
572
|
+
MODEL = 13,
|
|
573
|
+
TETAP = 15,
|
|
574
|
+
MODUL = 16,
|
|
575
|
+
EOF = 17,
|
|
576
|
+
ID = 18,
|
|
577
|
+
LITERAL = 19,
|
|
578
|
+
PLUS = 20,
|
|
579
|
+
MINUS = 21,
|
|
580
|
+
STAR = 22,
|
|
581
|
+
SLASH = 23,
|
|
582
|
+
LPAREN = 24,
|
|
583
|
+
RPAREN = 25,
|
|
584
|
+
GREATER = 26,
|
|
585
|
+
GREATER_EQUAL = 27,
|
|
586
|
+
LESS = 28,
|
|
587
|
+
LESS_EQUAL = 29,
|
|
588
|
+
EQUAL = 30,
|
|
589
|
+
EQUAL_EQUAL = 31,
|
|
590
|
+
DOT = 32,
|
|
591
|
+
LCURLY = 33,
|
|
592
|
+
RCURLY = 34,
|
|
593
|
+
COMMA = 35,
|
|
594
|
+
LSQUARE = 36,
|
|
595
|
+
RSQUARE = 37,
|
|
596
|
+
PIPE = 38,
|
|
597
|
+
AMPERSAND = 39,
|
|
598
|
+
BANG = 40,
|
|
599
|
+
ARROW = 41,
|
|
600
|
+
BANG_EQUAL = 42,
|
|
601
|
+
MODULUS = 43;
|
|
602
|
+
|
|
603
|
+
const TOKEN_STRING = [
|
|
604
|
+
"RUBAH",
|
|
605
|
+
"KALAU",
|
|
606
|
+
"NAMUN",
|
|
607
|
+
"SLAGI",
|
|
608
|
+
"UNTUK",
|
|
609
|
+
"CETAK",
|
|
610
|
+
"HENTI",
|
|
611
|
+
"LEWAT",
|
|
612
|
+
"DALAM",
|
|
613
|
+
"HASIL",
|
|
614
|
+
"KERJA",
|
|
615
|
+
"DATUM",
|
|
616
|
+
"JENIS",
|
|
617
|
+
"MODEL",
|
|
618
|
+
"ERROR",
|
|
619
|
+
"TETAP",
|
|
620
|
+
"MODUL",
|
|
621
|
+
"EOF",
|
|
622
|
+
"ID",
|
|
623
|
+
"LITERAL",
|
|
624
|
+
"PLUS",
|
|
625
|
+
"MINUS",
|
|
626
|
+
"BINTANG",
|
|
627
|
+
"GARIS_MIRING",
|
|
628
|
+
"LPAREN",
|
|
629
|
+
"RPAREN",
|
|
630
|
+
"LEBIH",
|
|
631
|
+
"LEBIH_SAMA",
|
|
632
|
+
"KURANG",
|
|
633
|
+
"KURANG_SAMA",
|
|
634
|
+
"SAMA",
|
|
635
|
+
"SAMA_SAMA",
|
|
636
|
+
"DOT",
|
|
637
|
+
"LCURLY",
|
|
638
|
+
"RCURLY",
|
|
639
|
+
"COMMA",
|
|
640
|
+
"LSQUARE",
|
|
641
|
+
"RSQUARE",
|
|
642
|
+
"PIPA",
|
|
643
|
+
"AMPERSAN",
|
|
644
|
+
"SERU",
|
|
645
|
+
"ARROW",
|
|
646
|
+
"SERU_SAMA",
|
|
647
|
+
"MODULUS",
|
|
648
|
+
];
|
|
649
|
+
|
|
640
650
|
let Henti$1 = class Henti { };
|
|
641
651
|
let Lewat$1 = class Lewat { };
|
|
642
652
|
let Hasil$1 = class Hasil {
|
|
@@ -855,8 +865,8 @@ class Interpreter {
|
|
|
855
865
|
}
|
|
856
866
|
this.typeCheck(leftValue, rightValue, `Pada operasi biner ${binaryExpr.op.lexeme}`);
|
|
857
867
|
|
|
858
|
-
let
|
|
859
|
-
|
|
868
|
+
let type = this.environment.get(leftValue.type.description);
|
|
869
|
+
let result = this.operate(type, binaryExpr.op.type, rightValue, leftValue);
|
|
860
870
|
|
|
861
871
|
return result;
|
|
862
872
|
}
|
|
@@ -871,9 +881,24 @@ class Interpreter {
|
|
|
871
881
|
this.error(`Tidak bisa mengoperasikan nilai Nihil.`);
|
|
872
882
|
}
|
|
873
883
|
|
|
874
|
-
let
|
|
875
|
-
|
|
884
|
+
let type = this.environment.get(rightValue.type.description);
|
|
885
|
+
let result = this.operate(type, unaryExpr.op.type, rightValue);
|
|
886
|
+
|
|
887
|
+
return result;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
operate(type, op, right, left) {
|
|
891
|
+
let opLexeme = TOKEN_STRING[op] + (left ? "" : "_UNER");
|
|
892
|
+
let operatorFunc = type.member.get(opLexeme);
|
|
893
|
+
if (!operatorFunc)
|
|
894
|
+
this.error(`operator ${opLexeme} tidak terdefinisi untuk Model ${right.type.description}.`);
|
|
876
895
|
|
|
896
|
+
let result = null;
|
|
897
|
+
if (left) { // Binary
|
|
898
|
+
result = this.callFunc(operatorFunc.data, [right, left]);
|
|
899
|
+
} else { // Unary, safe because valid unary op is just + - ! in the parser
|
|
900
|
+
result = this.callFunc(operatorFunc.data, [right]);
|
|
901
|
+
}
|
|
877
902
|
return result;
|
|
878
903
|
}
|
|
879
904
|
|
|
@@ -902,8 +927,9 @@ class Interpreter {
|
|
|
902
927
|
if (type.member?.has(name)) {
|
|
903
928
|
if (willBeCalled) {
|
|
904
929
|
this.objectStack = main;
|
|
930
|
+
return type.member.get(name);
|
|
905
931
|
}
|
|
906
|
-
|
|
932
|
+
this.error(`akses titik . dari objek ke model harus berupa panggilan/penggunaaan mesin.`);
|
|
907
933
|
}
|
|
908
934
|
this.error(`nama .${name} tidak ditemukan dalam tipe ${main.type.description}`);
|
|
909
935
|
} else {
|
|
@@ -944,12 +970,7 @@ class Interpreter {
|
|
|
944
970
|
if (!thing?.type) return `nihil`;
|
|
945
971
|
let type = this.environment.get(thing.type.description);
|
|
946
972
|
if (type?.member?.has("kePetik")) {
|
|
947
|
-
let prevState = this.state;
|
|
948
|
-
this.state = location.MESIN;
|
|
949
|
-
this.stack.push(this.line);
|
|
950
973
|
let res = this.callFunc(type.member.get("kePetik").data, [thing]).data;
|
|
951
|
-
this.stack.pop();
|
|
952
|
-
this.state = prevState;
|
|
953
974
|
return res;
|
|
954
975
|
}
|
|
955
976
|
return `${thing.type.description}<>`;
|
|
@@ -1019,7 +1040,7 @@ class Interpreter {
|
|
|
1019
1040
|
visitKalauStmt(kalauStmt) {
|
|
1020
1041
|
// condition may be null for 'namun', accept the thenBlock if it is
|
|
1021
1042
|
let condition = kalauStmt.condition?.accept(this);
|
|
1022
|
-
if (condition
|
|
1043
|
+
if (condition?.type && condition?.type !== logisSymbol) {
|
|
1023
1044
|
this.error(`Ekspresi dalam 'kalau' harus bertipe logis, menemukan ${condition.type ? condition.type.description : "nihil"}`);
|
|
1024
1045
|
}
|
|
1025
1046
|
if (condition === null || condition === undefined || condition.data) {
|
|
@@ -1151,26 +1172,24 @@ class Interpreter {
|
|
|
1151
1172
|
if (variable.type !== stipeSymbol) {
|
|
1152
1173
|
this.error(`Modul hanya bisa _ditambahkan_ pada tipe. '${name}' bukan merupakan tipe.`);
|
|
1153
1174
|
}
|
|
1154
|
-
if (variable.member) {
|
|
1175
|
+
if (variable.member.memory.size > 0) {
|
|
1155
1176
|
this.error(`Tipe '${name}' sudah memiliki modul sendiri, tidak bisa definisi ulang.`);
|
|
1156
1177
|
}
|
|
1178
|
+
} else {
|
|
1179
|
+
variable = new Variable(modulSymbol, true, null);
|
|
1180
|
+
variable.member = new Environment();
|
|
1181
|
+
this.environment.define(name, variable);
|
|
1157
1182
|
}
|
|
1158
1183
|
|
|
1159
1184
|
let lastEnv = this.environment;
|
|
1160
|
-
|
|
1185
|
+
variable.member.enclosing = this.environment;
|
|
1186
|
+
this.environment = variable.member;
|
|
1161
1187
|
for (let stmt of modulStmt.statements) {
|
|
1162
1188
|
stmt.accept(this);
|
|
1163
1189
|
}
|
|
1164
1190
|
|
|
1165
|
-
[this.environment,
|
|
1191
|
+
[this.environment, variable.member] = [lastEnv, this.environment];
|
|
1166
1192
|
|
|
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
1193
|
}
|
|
1175
1194
|
|
|
1176
1195
|
// UTILITIES
|
|
@@ -2277,6 +2296,7 @@ class Simpl {
|
|
|
2277
2296
|
let output = this.interpreter.interpret(pohon);
|
|
2278
2297
|
return output.join("\n");
|
|
2279
2298
|
} catch (err) {
|
|
2299
|
+
// throw err
|
|
2280
2300
|
if (err instanceof SimplError) {
|
|
2281
2301
|
const errorCode = textLines[err.line - 1];
|
|
2282
2302
|
let errorText = (errorCode ? `ERROR! Pada baris ke-${err.line}\n>> ` + errorCode + '\n' : "") + err.message;
|