bahasa-simpl 1.0.11 → 1.0.13
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.d.ts +8 -0
- package/dist/{simpl-interpreter.js → simpl.js} +392 -397
- package/dist/simpl.min.js +1 -0
- package/package.json +15 -3
- package/rollup.config.js +0 -8
package/dist/simpl.d.ts
ADDED
|
@@ -84,6 +84,7 @@ class Stipe extends Variable {
|
|
|
84
84
|
super(stipeSymbol, true, data);
|
|
85
85
|
this.symbol = type;
|
|
86
86
|
this.member = new Environment();
|
|
87
|
+
this.member.define("buat", new Variable(mesinSymbol, true, data));
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
}
|
|
@@ -92,9 +93,9 @@ function kePetik(v, thing) {
|
|
|
92
93
|
if (thing.type === logisSymbol) {
|
|
93
94
|
return thing.data ? "benar" : "salah";
|
|
94
95
|
} else if (thing.type === barisSymbol) {
|
|
95
|
-
return '[' + thing.data.reduce((str, val) => str+", "+kePetik(v, val), "").slice(1) + ' ]';
|
|
96
|
+
return '[' + thing.data.reduce((str, val) => str + ", " + kePetik(v, val), "").slice(1) + ' ]';
|
|
96
97
|
} else if (thing.type === stipeSymbol) {
|
|
97
|
-
return `Model<${thing.symbol.description}>`;
|
|
98
|
+
return `Model<${thing.symbol?.description ? thing.symbol.description : ""}>`;
|
|
98
99
|
} else if (thing.type === mesinSymbol) {
|
|
99
100
|
let underlying = thing.data.returnType?.description;
|
|
100
101
|
return `Mesin<${underlying ? underlying : 'datum'}>`;
|
|
@@ -112,304 +113,6 @@ function kePetik(v, thing) {
|
|
|
112
113
|
return `${thing.type.description}<>`;
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
class PetikTipe extends Stipe {
|
|
117
|
-
constructor() {
|
|
118
|
-
super(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
|
|
119
|
-
[[null]], petikSymbol, true));
|
|
120
|
-
this.init();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
init() {
|
|
124
|
-
// BINARY / UNARY OPERATORS
|
|
125
|
-
this.member.define("PLUS",
|
|
126
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], petikSymbol, (_, [r, l]) => new Value(petikSymbol, l.data + r.data)));
|
|
127
|
-
this.member.define("LEBIH",
|
|
128
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
129
|
-
this.member.define("KURANG",
|
|
130
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
131
|
-
this.member.define("SAMA_SAMA",
|
|
132
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
133
|
-
this.member.define("LEBIH_SAMA",
|
|
134
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
135
|
-
this.member.define("KURANG_SAMA",
|
|
136
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
137
|
-
this.member.define("SERU_SAMA",
|
|
138
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
139
|
-
this.member.define("AMPERSAN",
|
|
140
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
141
|
-
this.member.define("PIPA",
|
|
142
|
-
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
143
|
-
|
|
144
|
-
this.member.define("SERU_UNER",
|
|
145
|
-
makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
146
|
-
|
|
147
|
-
this.member.define("kePetik",
|
|
148
|
-
makeBuiltInFunc([petikSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
149
|
-
|
|
150
|
-
this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
|
|
151
|
-
return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
|
|
152
|
-
}));
|
|
153
|
-
this.member.define("bersih", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [d]) => {
|
|
154
|
-
return new Value(petikSymbol, d.data.trim())
|
|
155
|
-
}));
|
|
156
|
-
this.member.define("ganti", makeBuiltInFunc([petikSymbol, petikSymbol, petikSymbol], petikSymbol,
|
|
157
|
-
(_, [d, what, rep]) => new Value(petikSymbol, d.data.replaceAll(what.data, rep.data))
|
|
158
|
-
));
|
|
159
|
-
this.member.define("besar", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
|
|
160
|
-
return new Value(petikSymbol, p.data.toUpperCase())
|
|
161
|
-
}));
|
|
162
|
-
this.member.define("kecil", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
|
|
163
|
-
return new Value(petikSymbol, p.data.toLowerCase())
|
|
164
|
-
}));
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
class AngkaTipe extends Stipe {
|
|
169
|
-
constructor() {
|
|
170
|
-
super(angkaSymbol, new Callable(null, (v, args) => {
|
|
171
|
-
if (typeof args[0].data === "number") {
|
|
172
|
-
return new Value(angkaSymbol, args[0].data);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
switch (args[0].type) {
|
|
176
|
-
case petikSymbol:
|
|
177
|
-
if (isNaN(Number(args[0].data))) {
|
|
178
|
-
v.error("Nilai dari petik bukanlah sebuah angka, konversi gagal.");
|
|
179
|
-
}
|
|
180
|
-
return new Value(angkaSymbol, Number(args[0].data));
|
|
181
|
-
case angkaSymbol:
|
|
182
|
-
return new Value(angkaSymbol, args[0].data);
|
|
183
|
-
case logisSymbol:
|
|
184
|
-
return new Value(angkaSymbol, Number(args[0].data));
|
|
185
|
-
default:
|
|
186
|
-
v.error(`Tipe yang dapat diterima hanyalah petik, angka, logis, dan jenis. Mendapatkan ${args[0].type.description}.`);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
}, [[null]], angkaSymbol, true)
|
|
190
|
-
);
|
|
191
|
-
this.init();
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
init() {
|
|
195
|
-
this.member.define("PLUS",
|
|
196
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data + r.data)));
|
|
197
|
-
this.member.define("MINUS",
|
|
198
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data - r.data)));
|
|
199
|
-
this.member.define("BINTANG",
|
|
200
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data * r.data)));
|
|
201
|
-
this.member.define("GARIS_MIRING",
|
|
202
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data / r.data)));
|
|
203
|
-
this.member.define("MODULUS",
|
|
204
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data % r.data)));
|
|
205
|
-
|
|
206
|
-
this.member.define("LEBIH",
|
|
207
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
208
|
-
this.member.define("KURANG",
|
|
209
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
210
|
-
this.member.define("SAMA_SAMA",
|
|
211
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
212
|
-
this.member.define("LEBIH_SAMA",
|
|
213
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
214
|
-
this.member.define("KURANG_SAMA",
|
|
215
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
216
|
-
this.member.define("SERU_SAMA",
|
|
217
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
218
|
-
this.member.define("AMPERSAN",
|
|
219
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
220
|
-
this.member.define("PIPA",
|
|
221
|
-
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
222
|
-
this.member.define("SERU_UNER",
|
|
223
|
-
makeBuiltInFunc([angkaSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
224
|
-
this.member.define("PLUS_UNER",
|
|
225
|
-
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, +r.data)));
|
|
226
|
-
this.member.define("MINUS_UNER",
|
|
227
|
-
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
|
|
228
|
-
|
|
229
|
-
this.member.define("kePetik",
|
|
230
|
-
makeBuiltInFunc([angkaSymbol], petikSymbol, (v, [a]) => new Value(petikSymbol, kePetik(v, a))));
|
|
231
|
-
|
|
232
|
-
this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
233
|
-
return new Value(angkaSymbol, Math.round(a.data));
|
|
234
|
-
}));
|
|
235
|
-
this.member.define("bulatAtas", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
236
|
-
return new Value(angkaSymbol, Math.ceil(a.data))
|
|
237
|
-
}));
|
|
238
|
-
this.member.define("bulatBawah", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
239
|
-
return new Value(angkaSymbol, Math.floor(a.data))
|
|
240
|
-
}));
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
class LogisTipe extends Stipe {
|
|
245
|
-
constructor() {
|
|
246
|
-
super(logisSymbol, new Callable(null, (_, args) => {
|
|
247
|
-
if (args[0].type === barisSymbol && args[0].data.length === 0) {
|
|
248
|
-
return new Value(logisSymbol, false);
|
|
249
|
-
}
|
|
250
|
-
return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data?.member?.size));
|
|
251
|
-
}, [[null]], logisSymbol, true)
|
|
252
|
-
);
|
|
253
|
-
this.init();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
init() {
|
|
257
|
-
this.member.define("SAMA_SAMA",
|
|
258
|
-
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
259
|
-
this.member.define("SERU_SAMA",
|
|
260
|
-
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
261
|
-
this.member.define("AMPERSAN",
|
|
262
|
-
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
263
|
-
this.member.define("PIPA",
|
|
264
|
-
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
265
|
-
this.member.define("SERU_UNER",
|
|
266
|
-
makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
267
|
-
|
|
268
|
-
this.member.define("kePetik",
|
|
269
|
-
makeBuiltInFunc([logisSymbol], petikSymbol, (v, [l]) => new Value(petikSymbol, kePetik(v, l))));
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
class BarisTipe extends Stipe {
|
|
274
|
-
constructor() {
|
|
275
|
-
super(barisSymbol);
|
|
276
|
-
this.init();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
init() {
|
|
280
|
-
const valueToVariableDatum = (d) => {
|
|
281
|
-
let input = new Variable(d.type, false, d.data);
|
|
282
|
-
input.member = d.member;
|
|
283
|
-
input.isDatum = true;
|
|
284
|
-
return input;
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
this.member.define("PLUS",
|
|
288
|
-
makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
|
|
289
|
-
new Value(barisSymbol, Array(...l.data, ...r.data))
|
|
290
|
-
));
|
|
291
|
-
|
|
292
|
-
this.member.define("MINUS_UNER",
|
|
293
|
-
makeBuiltInFunc([barisSymbol], barisSymbol, (_, [r]) =>
|
|
294
|
-
new Value(barisSymbol, r.data.slice(0, r.length))
|
|
295
|
-
));
|
|
296
|
-
|
|
297
|
-
this.member.define("SAMA_SAMA",
|
|
298
|
-
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
299
|
-
if (a.length !== b.length) return false;
|
|
300
|
-
for (let i = 0; i < a.length; i++) {
|
|
301
|
-
if (a[i].data !== b[i].data) return false;
|
|
302
|
-
}
|
|
303
|
-
return true;
|
|
304
|
-
})(l.data, r.data)))
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
this.member.define("SERU_SAMA",
|
|
308
|
-
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
309
|
-
if (a.length !== b.length) return true;
|
|
310
|
-
for (let i = 0; i < a.length; i++) {
|
|
311
|
-
if (a[i].data !== b[i].data) return true;
|
|
312
|
-
}
|
|
313
|
-
return false;
|
|
314
|
-
})(l.data, r.data)))
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
this.member.define("AMPERSAN",
|
|
318
|
-
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
319
|
-
this.member.define("PIPA",
|
|
320
|
-
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
321
|
-
this.member.define("SERU_UNER",
|
|
322
|
-
makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
323
|
-
|
|
324
|
-
this.member.define("kePetik",
|
|
325
|
-
makeBuiltInFunc([barisSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
326
|
-
|
|
327
|
-
this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
|
|
328
|
-
if (b.data.length <= i.data) {
|
|
329
|
-
v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
while (i.data < 0) i.data += b.data.length;
|
|
333
|
-
b.data = b.data.filter((_, idx) => idx !== i.data);
|
|
334
|
-
return b;
|
|
335
|
-
}));
|
|
336
|
-
|
|
337
|
-
this.member.define("potongan", makeBuiltInFunc([barisSymbol, angkaSymbol, angkaSymbol], barisSymbol, (v, [b, fr, to]) => {
|
|
338
|
-
if (fr.data >= b.data.length || fr.data < 0 || to.data <= fr.data || to.data > b.data.length) {
|
|
339
|
-
v.error(`Indeks tidak valid, ${fr.data} sampai ${to.data}, dengan ukuran baris ${b.data.length}`);
|
|
340
|
-
}
|
|
341
|
-
return new Value(barisSymbol, b.data.slice(fr.data, to.data));
|
|
342
|
-
}));
|
|
343
|
-
this.member.define("tumpuk", makeBuiltInFunc([barisSymbol, null], null, (_, [b, d]) => {
|
|
344
|
-
b.data.push(valueToVariableDatum(d));
|
|
345
|
-
return b;
|
|
346
|
-
}));
|
|
347
|
-
this.member.define("tumpah", makeBuiltInFunc([barisSymbol], null, (_, [b]) => {
|
|
348
|
-
b.data.pop();
|
|
349
|
-
return b;
|
|
350
|
-
}));
|
|
351
|
-
this.member.define("masuk", makeBuiltInFunc([barisSymbol, null, angkaSymbol], null, (v, [b, d, idx]) => {
|
|
352
|
-
if (idx.data > b.data.length) {
|
|
353
|
-
v.error(`Indeks tidak valid, ${idx.data}, dengan ukuran baris ${b.data.length}`);
|
|
354
|
-
}
|
|
355
|
-
b.data.splice(idx.data, 0, valueToVariableDatum(d));
|
|
356
|
-
return b;
|
|
357
|
-
}));
|
|
358
|
-
this.member.define("petakan", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
|
|
359
|
-
let newBaris = new Value(barisSymbol, []);
|
|
360
|
-
for (let datum of b.data) {
|
|
361
|
-
let result = v.callFunc(m.data, [datum]);
|
|
362
|
-
newBaris.data.push(valueToVariableDatum(result));
|
|
363
|
-
}
|
|
364
|
-
return newBaris;
|
|
365
|
-
}));
|
|
366
|
-
this.member.define("saring", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
|
|
367
|
-
let newBaris = new Value(barisSymbol, []);
|
|
368
|
-
for (let datum of b.data) {
|
|
369
|
-
let result = v.callFunc(m.data, [datum]);
|
|
370
|
-
if (result.data === true) {
|
|
371
|
-
newBaris.data.push(valueToVariableDatum(datum));
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return newBaris;
|
|
375
|
-
}));
|
|
376
|
-
this.member.define("reduksi", makeBuiltInFunc([barisSymbol, mesinSymbol, null], null, (v, [b, m, d]) => {
|
|
377
|
-
for (let datum of b.data) {
|
|
378
|
-
let result = v.callFunc(m.data, [d, datum]);
|
|
379
|
-
d = result;
|
|
380
|
-
}
|
|
381
|
-
return d;
|
|
382
|
-
}));
|
|
383
|
-
|
|
384
|
-
this.member.define("punya?", makeBuiltInFunc([barisSymbol, null], logisSymbol, (v, [b, d]) => {
|
|
385
|
-
let type = v.environment.get(d.type?.description);
|
|
386
|
-
if (!type)
|
|
387
|
-
v.error(`Tipe tidak ditemukan atau tidak valid`);
|
|
388
|
-
let equalFunc;
|
|
389
|
-
if (type.member?.has("SAMA_SAMA")) {
|
|
390
|
-
equalFunc = type.member.get("SAMA_SAMA");
|
|
391
|
-
} else {
|
|
392
|
-
v.error(`model ${d.type.description} tidak mempunyai mesin SAMA_SAMA di dalam modulnya.`);
|
|
393
|
-
}
|
|
394
|
-
for (let datum of b.data) {
|
|
395
|
-
if (datum.type !== d.type) continue;
|
|
396
|
-
let isEqual = v.callFunc(equalFunc.data, [datum, d]);
|
|
397
|
-
if (isEqual.data) return new Value(logisSymbol, true);
|
|
398
|
-
}
|
|
399
|
-
return new Value(logisSymbol, false);
|
|
400
|
-
}));
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
class MesinTipe extends Stipe {
|
|
405
|
-
constructor() {
|
|
406
|
-
super(mesinSymbol);
|
|
407
|
-
|
|
408
|
-
this.member.define("kePetik",
|
|
409
|
-
makeBuiltInFunc([mesinSymbol], petikSymbol, (v, [m]) => new Value(petikSymbol, kePetik(v, m))));
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
116
|
let Model$1 = class Model extends Stipe {
|
|
414
117
|
constructor(name, params) {
|
|
415
118
|
let sym = Symbol(name);
|
|
@@ -453,10 +156,7 @@ let Jenis$1 = class Jenis extends Stipe {
|
|
|
453
156
|
this.member.define("kePetik", makeBuiltInFunc([sym], petikSymbol, (_, [j]) => {
|
|
454
157
|
return new Value(petikSymbol, `${name}<${j.data}>`);
|
|
455
158
|
}));
|
|
456
|
-
this.init(sym);
|
|
457
|
-
}
|
|
458
159
|
|
|
459
|
-
init(sym) {
|
|
460
160
|
this.member.define("SAMA_SAMA",
|
|
461
161
|
makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
462
162
|
this.member.define("SERU_SAMA",
|
|
@@ -515,13 +215,302 @@ function copier(thing) {
|
|
|
515
215
|
}
|
|
516
216
|
|
|
517
217
|
|
|
218
|
+
const PetikTipe = (() => {
|
|
219
|
+
let tipe = new Stipe(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
|
|
220
|
+
[[null]], petikSymbol, true));
|
|
221
|
+
|
|
222
|
+
tipe.member.define("PLUS",
|
|
223
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], petikSymbol, (_, [r, l]) => new Value(petikSymbol, l.data + r.data)));
|
|
224
|
+
tipe.member.define("LEBIH",
|
|
225
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
226
|
+
tipe.member.define("KURANG",
|
|
227
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
228
|
+
tipe.member.define("SAMA_SAMA",
|
|
229
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
230
|
+
tipe.member.define("LEBIH_SAMA",
|
|
231
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
232
|
+
tipe.member.define("KURANG_SAMA",
|
|
233
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
234
|
+
tipe.member.define("SERU_SAMA",
|
|
235
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
236
|
+
tipe.member.define("AMPERSAN",
|
|
237
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
238
|
+
tipe.member.define("PIPA",
|
|
239
|
+
makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
240
|
+
|
|
241
|
+
tipe.member.define("SERU_UNER",
|
|
242
|
+
makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
243
|
+
|
|
244
|
+
tipe.member.define("kePetik",
|
|
245
|
+
makeBuiltInFunc([petikSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
246
|
+
|
|
247
|
+
tipe.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
|
|
248
|
+
return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
|
|
249
|
+
}));
|
|
250
|
+
tipe.member.define("bersih", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [d]) => {
|
|
251
|
+
return new Value(petikSymbol, d.data.trim())
|
|
252
|
+
}));
|
|
253
|
+
tipe.member.define("ganti", makeBuiltInFunc([petikSymbol, petikSymbol, petikSymbol], petikSymbol,
|
|
254
|
+
(_, [d, what, rep]) => new Value(petikSymbol, d.data.replaceAll(what.data, rep.data))
|
|
255
|
+
));
|
|
256
|
+
tipe.member.define("besar", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
|
|
257
|
+
return new Value(petikSymbol, p.data.toUpperCase())
|
|
258
|
+
}));
|
|
259
|
+
tipe.member.define("kecil", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
|
|
260
|
+
return new Value(petikSymbol, p.data.toLowerCase())
|
|
261
|
+
}));
|
|
262
|
+
|
|
263
|
+
return tipe;
|
|
264
|
+
})();
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
const AngkaTipe = (() => {
|
|
268
|
+
let tipe = new Stipe(angkaSymbol, new Callable(null, (v, args) => {
|
|
269
|
+
if (typeof args[0].data === "number") {
|
|
270
|
+
return new Value(angkaSymbol, args[0].data);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
switch (args[0].type) {
|
|
274
|
+
case petikSymbol:
|
|
275
|
+
if (isNaN(Number(args[0].data))) {
|
|
276
|
+
v.error("Nilai dari petik bukanlah sebuah angka, konversi gagal.");
|
|
277
|
+
}
|
|
278
|
+
return new Value(angkaSymbol, Number(args[0].data));
|
|
279
|
+
case angkaSymbol:
|
|
280
|
+
return new Value(angkaSymbol, args[0].data);
|
|
281
|
+
case logisSymbol:
|
|
282
|
+
return new Value(angkaSymbol, Number(args[0].data));
|
|
283
|
+
default:
|
|
284
|
+
v.error(`Tipe yang dapat diterima hanyalah petik, angka, logis, dan jenis. Mendapatkan ${args[0].type.description}.`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
}, [[null]], angkaSymbol, true)
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
tipe.member.define("PLUS",
|
|
291
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data + r.data)));
|
|
292
|
+
tipe.member.define("MINUS",
|
|
293
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data - r.data)));
|
|
294
|
+
tipe.member.define("BINTANG",
|
|
295
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data * r.data)));
|
|
296
|
+
tipe.member.define("GARIS_MIRING",
|
|
297
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data / r.data)));
|
|
298
|
+
tipe.member.define("MODULUS",
|
|
299
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data % r.data)));
|
|
300
|
+
|
|
301
|
+
tipe.member.define("LEBIH",
|
|
302
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
|
|
303
|
+
tipe.member.define("KURANG",
|
|
304
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
|
|
305
|
+
tipe.member.define("SAMA_SAMA",
|
|
306
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
307
|
+
tipe.member.define("LEBIH_SAMA",
|
|
308
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
|
|
309
|
+
tipe.member.define("KURANG_SAMA",
|
|
310
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
|
|
311
|
+
tipe.member.define("SERU_SAMA",
|
|
312
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
313
|
+
tipe.member.define("AMPERSAN",
|
|
314
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
315
|
+
tipe.member.define("PIPA",
|
|
316
|
+
makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
317
|
+
tipe.member.define("SERU_UNER",
|
|
318
|
+
makeBuiltInFunc([angkaSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
319
|
+
tipe.member.define("PLUS_UNER",
|
|
320
|
+
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, +r.data)));
|
|
321
|
+
tipe.member.define("MINUS_UNER",
|
|
322
|
+
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
|
|
323
|
+
|
|
324
|
+
tipe.member.define("kePetik",
|
|
325
|
+
makeBuiltInFunc([angkaSymbol], petikSymbol, (v, [a]) => new Value(petikSymbol, kePetik(v, a))));
|
|
326
|
+
|
|
327
|
+
tipe.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
328
|
+
return new Value(angkaSymbol, Math.round(a.data));
|
|
329
|
+
}));
|
|
330
|
+
tipe.member.define("bulatAtas", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
331
|
+
return new Value(angkaSymbol, Math.ceil(a.data))
|
|
332
|
+
}));
|
|
333
|
+
tipe.member.define("bulatBawah", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
334
|
+
return new Value(angkaSymbol, Math.floor(a.data))
|
|
335
|
+
}));
|
|
336
|
+
|
|
337
|
+
return tipe;
|
|
338
|
+
})();
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
const LogisTipe = (() => {
|
|
342
|
+
let tipe = new Stipe(logisSymbol, new Callable(null, (_, args) => {
|
|
343
|
+
if (args[0].type === barisSymbol && args[0].data.length === 0) {
|
|
344
|
+
return new Value(logisSymbol, false);
|
|
345
|
+
}
|
|
346
|
+
return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data?.member?.size));
|
|
347
|
+
}, [[null]], logisSymbol, true)
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
tipe.member.define("SAMA_SAMA",
|
|
351
|
+
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
|
|
352
|
+
tipe.member.define("SERU_SAMA",
|
|
353
|
+
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
|
|
354
|
+
tipe.member.define("AMPERSAN",
|
|
355
|
+
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
356
|
+
tipe.member.define("PIPA",
|
|
357
|
+
makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
358
|
+
tipe.member.define("SERU_UNER",
|
|
359
|
+
makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
360
|
+
|
|
361
|
+
tipe.member.define("kePetik",
|
|
362
|
+
makeBuiltInFunc([logisSymbol], petikSymbol, (v, [l]) => new Value(petikSymbol, kePetik(v, l))));
|
|
363
|
+
|
|
364
|
+
return tipe;
|
|
365
|
+
})();
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
const BarisTipe = (() => {
|
|
369
|
+
let tipe = new Stipe(barisSymbol);
|
|
370
|
+
|
|
371
|
+
const valueToVariableDatum = (d) => {
|
|
372
|
+
let input = new Variable(d.type, false, d.data);
|
|
373
|
+
input.member = d.member;
|
|
374
|
+
input.isDatum = true;
|
|
375
|
+
return input;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
tipe.member.define("PLUS",
|
|
379
|
+
makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
|
|
380
|
+
new Value(barisSymbol, Array(...l.data, ...r.data))
|
|
381
|
+
));
|
|
382
|
+
|
|
383
|
+
tipe.member.define("MINUS_UNER",
|
|
384
|
+
makeBuiltInFunc([barisSymbol], barisSymbol, (_, [r]) =>
|
|
385
|
+
new Value(barisSymbol, r.data.slice(0, r.length))
|
|
386
|
+
));
|
|
387
|
+
|
|
388
|
+
tipe.member.define("SAMA_SAMA",
|
|
389
|
+
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
390
|
+
if (a.length !== b.length) return false;
|
|
391
|
+
for (let i = 0; i < a.length; i++) {
|
|
392
|
+
if (a[i].data !== b[i].data) return false;
|
|
393
|
+
}
|
|
394
|
+
return true;
|
|
395
|
+
})(l.data, r.data)))
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
tipe.member.define("SERU_SAMA",
|
|
399
|
+
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
|
|
400
|
+
if (a.length !== b.length) return true;
|
|
401
|
+
for (let i = 0; i < a.length; i++) {
|
|
402
|
+
if (a[i].data !== b[i].data) return true;
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
})(l.data, r.data)))
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
tipe.member.define("AMPERSAN",
|
|
409
|
+
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
|
|
410
|
+
tipe.member.define("PIPA",
|
|
411
|
+
makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
|
|
412
|
+
tipe.member.define("SERU_UNER",
|
|
413
|
+
makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
414
|
+
|
|
415
|
+
tipe.member.define("kePetik",
|
|
416
|
+
makeBuiltInFunc([barisSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
417
|
+
|
|
418
|
+
tipe.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
|
|
419
|
+
if (b.data.length <= i.data) {
|
|
420
|
+
v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
while (i.data < 0) i.data += b.data.length;
|
|
424
|
+
b.data = b.data.filter((_, idx) => idx !== i.data);
|
|
425
|
+
return b;
|
|
426
|
+
}));
|
|
427
|
+
|
|
428
|
+
tipe.member.define("potongan", makeBuiltInFunc([barisSymbol, angkaSymbol, angkaSymbol], barisSymbol, (v, [b, fr, to]) => {
|
|
429
|
+
if (fr.data >= b.data.length || fr.data < 0 || to.data <= fr.data || to.data > b.data.length) {
|
|
430
|
+
v.error(`Indeks tidak valid, ${fr.data} sampai ${to.data}, dengan ukuran baris ${b.data.length}`);
|
|
431
|
+
}
|
|
432
|
+
return new Value(barisSymbol, b.data.slice(fr.data, to.data));
|
|
433
|
+
}));
|
|
434
|
+
tipe.member.define("tumpuk", makeBuiltInFunc([barisSymbol, null], null, (_, [b, d]) => {
|
|
435
|
+
b.data.push(valueToVariableDatum(d));
|
|
436
|
+
return b;
|
|
437
|
+
}));
|
|
438
|
+
tipe.member.define("tumpah", makeBuiltInFunc([barisSymbol], null, (_, [b]) => {
|
|
439
|
+
b.data.pop();
|
|
440
|
+
return b;
|
|
441
|
+
}));
|
|
442
|
+
tipe.member.define("masuk", makeBuiltInFunc([barisSymbol, null, angkaSymbol], null, (v, [b, d, idx]) => {
|
|
443
|
+
if (idx.data > b.data.length) {
|
|
444
|
+
v.error(`Indeks tidak valid, ${idx.data}, dengan ukuran baris ${b.data.length}`);
|
|
445
|
+
}
|
|
446
|
+
b.data.splice(idx.data, 0, valueToVariableDatum(d));
|
|
447
|
+
return b;
|
|
448
|
+
}));
|
|
449
|
+
tipe.member.define("petakan", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
|
|
450
|
+
let newBaris = new Value(barisSymbol, []);
|
|
451
|
+
for (let datum of b.data) {
|
|
452
|
+
let result = v.callFunc(m.data, [datum]);
|
|
453
|
+
newBaris.data.push(valueToVariableDatum(result));
|
|
454
|
+
}
|
|
455
|
+
return newBaris;
|
|
456
|
+
}));
|
|
457
|
+
tipe.member.define("saring", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
|
|
458
|
+
let newBaris = new Value(barisSymbol, []);
|
|
459
|
+
for (let datum of b.data) {
|
|
460
|
+
let result = v.callFunc(m.data, [datum]);
|
|
461
|
+
if (result.data === true) {
|
|
462
|
+
newBaris.data.push(valueToVariableDatum(datum));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return newBaris;
|
|
466
|
+
}));
|
|
467
|
+
tipe.member.define("reduksi", makeBuiltInFunc([barisSymbol, mesinSymbol, null], null, (v, [b, m, d]) => {
|
|
468
|
+
for (let datum of b.data) {
|
|
469
|
+
let result = v.callFunc(m.data, [d, datum]);
|
|
470
|
+
d = result;
|
|
471
|
+
}
|
|
472
|
+
return d;
|
|
473
|
+
}));
|
|
474
|
+
|
|
475
|
+
tipe.member.define("punya?", makeBuiltInFunc([barisSymbol, null], logisSymbol, (v, [b, d]) => {
|
|
476
|
+
let type = v.environment.get(d.type?.description);
|
|
477
|
+
if (!type)
|
|
478
|
+
v.error(`Tipe tidak ditemukan atau tidak valid`);
|
|
479
|
+
let equalFunc;
|
|
480
|
+
if (type.member?.has("SAMA_SAMA")) {
|
|
481
|
+
equalFunc = type.member.get("SAMA_SAMA");
|
|
482
|
+
} else {
|
|
483
|
+
v.error(`model ${d.type.description} tidak mempunyai mesin SAMA_SAMA di dalam modulnya.`);
|
|
484
|
+
}
|
|
485
|
+
for (let datum of b.data) {
|
|
486
|
+
if (datum.type !== d.type) continue;
|
|
487
|
+
let isEqual = v.callFunc(equalFunc.data, [datum, d]);
|
|
488
|
+
if (isEqual.data) return new Value(logisSymbol, true);
|
|
489
|
+
}
|
|
490
|
+
return new Value(logisSymbol, false);
|
|
491
|
+
}));
|
|
492
|
+
|
|
493
|
+
return tipe;
|
|
494
|
+
})();
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
const MesinTipe = (() => {
|
|
498
|
+
let tipe = new Stipe(mesinSymbol);
|
|
499
|
+
|
|
500
|
+
tipe.member.define("kePetik",
|
|
501
|
+
makeBuiltInFunc([mesinSymbol], petikSymbol, (v, [m]) => new Value(petikSymbol, kePetik(v, m))));
|
|
502
|
+
|
|
503
|
+
return tipe;
|
|
504
|
+
})();
|
|
505
|
+
|
|
506
|
+
|
|
518
507
|
const GLOBAL_ENV = (() => {
|
|
519
508
|
let env = new Environment();
|
|
520
|
-
env.define("petik",
|
|
521
|
-
env.define("angka",
|
|
522
|
-
env.define("logis",
|
|
523
|
-
env.define("baris",
|
|
524
|
-
env.define("mesin",
|
|
509
|
+
env.define("petik", PetikTipe);
|
|
510
|
+
env.define("angka", AngkaTipe);
|
|
511
|
+
env.define("logis", LogisTipe);
|
|
512
|
+
env.define("baris", BarisTipe);
|
|
513
|
+
env.define("mesin", MesinTipe);
|
|
525
514
|
|
|
526
515
|
env.define("jarak", makeBuiltInFunc([angkaSymbol, angkaSymbol], barisSymbol,
|
|
527
516
|
(_, [from, to]) => new Value(barisSymbol,
|
|
@@ -716,23 +705,26 @@ let Hasil$1 = class Hasil {
|
|
|
716
705
|
}
|
|
717
706
|
};
|
|
718
707
|
|
|
719
|
-
const location = {
|
|
720
|
-
GLOBAL: 1,
|
|
721
|
-
SLAGI: 2,
|
|
722
|
-
UNTUK: 3,
|
|
723
|
-
MESIN: 4,
|
|
724
|
-
LIHAT: 5,
|
|
725
|
-
};
|
|
726
|
-
const MAX_STACK_SIZE = 500;
|
|
727
|
-
|
|
728
708
|
// Implements all Expressions and Statements Visitor
|
|
729
709
|
class Interpreter {
|
|
730
710
|
constructor() {
|
|
731
711
|
this.globalEnvironment = GLOBAL_ENV;
|
|
712
|
+
this.location = {
|
|
713
|
+
GLOBAL: 1,
|
|
714
|
+
SLAGI: 2,
|
|
715
|
+
UNTUK: 3,
|
|
716
|
+
MESIN: 4,
|
|
717
|
+
LIHAT: 5,
|
|
718
|
+
};
|
|
719
|
+
this.MAX_STACK_SIZE = 500;
|
|
720
|
+
this.init();
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
init() {
|
|
732
724
|
this.line = 0;
|
|
733
725
|
this.environment = new Environment(this.globalEnvironment);
|
|
734
726
|
this.tree = null;
|
|
735
|
-
this.state = location.GLOBAL;
|
|
727
|
+
this.state = this.location.GLOBAL;
|
|
736
728
|
this.stack = [];
|
|
737
729
|
this.output = [];
|
|
738
730
|
this.objectStack = null;
|
|
@@ -740,6 +732,14 @@ class Interpreter {
|
|
|
740
732
|
this.pipeStack = [];
|
|
741
733
|
}
|
|
742
734
|
|
|
735
|
+
interpret(tree) {
|
|
736
|
+
this.line = 0;
|
|
737
|
+
this.output = [];
|
|
738
|
+
this.tree = tree;
|
|
739
|
+
tree.accept(this);
|
|
740
|
+
return this.output;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
743
|
// EXPRESSION VISITORS
|
|
744
744
|
|
|
745
745
|
visitLiteralExpr(literalExpr) {
|
|
@@ -761,7 +761,7 @@ class Interpreter {
|
|
|
761
761
|
let value = new Value(barisSymbol, []);
|
|
762
762
|
|
|
763
763
|
for (let expr of arrayExpr.contents) {
|
|
764
|
-
let v =
|
|
764
|
+
let v = expr.accept(this);
|
|
765
765
|
let newVar = new Variable(v.type, false, v.data);
|
|
766
766
|
newVar.member = v.member;
|
|
767
767
|
newVar.isDatum = true;
|
|
@@ -829,7 +829,7 @@ class Interpreter {
|
|
|
829
829
|
this.error(`Hanya bisa 'memanggil' mesin atau model, malah menemukan ${callable.type.description}. `);
|
|
830
830
|
}
|
|
831
831
|
|
|
832
|
-
if (!callable
|
|
832
|
+
if (!callable?.data?.block) {
|
|
833
833
|
this.error(`Mesin tidak terdefinisi, tidak bisa dipanggil.`);
|
|
834
834
|
}
|
|
835
835
|
|
|
@@ -840,7 +840,7 @@ class Interpreter {
|
|
|
840
840
|
this.objectStack = null;
|
|
841
841
|
}
|
|
842
842
|
|
|
843
|
-
args = [...args, ...callExpr.args.map(val =>
|
|
843
|
+
args = [...args, ...callExpr.args.map(val => val.accept(this))];
|
|
844
844
|
|
|
845
845
|
let result = this.callFunc(callable.data, args);
|
|
846
846
|
return result;
|
|
@@ -850,13 +850,16 @@ class Interpreter {
|
|
|
850
850
|
// args.forEach((val,idx)=>{
|
|
851
851
|
// console.log(idx, val);
|
|
852
852
|
// });
|
|
853
|
+
if (!callable) {
|
|
854
|
+
this.error(`Mesin tidak terdefinisi, tidak bisa dipanggil.`);
|
|
855
|
+
}
|
|
853
856
|
this.stack.push(this.line);
|
|
854
|
-
if (this.stack.length > MAX_STACK_SIZE)
|
|
855
|
-
this.error(`Rekursi melebihi batas: Lebih dari ${MAX_STACK_SIZE}`);
|
|
857
|
+
if (this.stack.length > this.MAX_STACK_SIZE)
|
|
858
|
+
this.error(`Rekursi melebihi batas: Lebih dari ${this.MAX_STACK_SIZE}`);
|
|
856
859
|
|
|
857
860
|
let prevState = this.state;
|
|
858
861
|
this.line = this.stack[this.stack.length - 1];
|
|
859
|
-
this.state = location.MESIN;
|
|
862
|
+
this.state = this.location.MESIN;
|
|
860
863
|
|
|
861
864
|
if (args.length !== callable.parameters.length) {
|
|
862
865
|
this.error(`Jumlah argumen tidak sama dengan parameter mesin. Menemukan ${args.length}, harusnya ${callable.parameters.length}.`);
|
|
@@ -917,8 +920,8 @@ class Interpreter {
|
|
|
917
920
|
|
|
918
921
|
|
|
919
922
|
visitBinaryExpr(binaryExpr) {
|
|
920
|
-
let leftValue =
|
|
921
|
-
let rightValue =
|
|
923
|
+
let leftValue = binaryExpr.left.accept(this);
|
|
924
|
+
let rightValue = binaryExpr.right.accept(this);
|
|
922
925
|
|
|
923
926
|
this.line = binaryExpr.op.line;
|
|
924
927
|
|
|
@@ -935,7 +938,7 @@ class Interpreter {
|
|
|
935
938
|
}
|
|
936
939
|
|
|
937
940
|
visitUnaryExpr(unaryExpr) {
|
|
938
|
-
let rightValue =
|
|
941
|
+
let rightValue = unaryExpr.right.accept(this);
|
|
939
942
|
|
|
940
943
|
this.line = unaryExpr.op.line;
|
|
941
944
|
|
|
@@ -966,7 +969,7 @@ class Interpreter {
|
|
|
966
969
|
}
|
|
967
970
|
|
|
968
971
|
visitGroupingExpr(groupingExpr) {
|
|
969
|
-
return
|
|
972
|
+
return groupingExpr.expr.accept(this);
|
|
970
973
|
}
|
|
971
974
|
|
|
972
975
|
visitIdentifierExpr(identifierExpr) {
|
|
@@ -1009,11 +1012,11 @@ class Interpreter {
|
|
|
1009
1012
|
}
|
|
1010
1013
|
|
|
1011
1014
|
visitPipeLineExpr (pipeLineExpr) {
|
|
1012
|
-
let expr =
|
|
1015
|
+
let expr = pipeLineExpr.expr.accept(this);
|
|
1013
1016
|
|
|
1014
1017
|
this.pipeStack.push(expr);
|
|
1015
1018
|
|
|
1016
|
-
let pipeValue =
|
|
1019
|
+
let pipeValue = pipeLineExpr.pipeTo.accept(this);
|
|
1017
1020
|
|
|
1018
1021
|
this.pipeStack.pop();
|
|
1019
1022
|
|
|
@@ -1026,7 +1029,8 @@ class Interpreter {
|
|
|
1026
1029
|
visitTypeStmt(typeStmt) {
|
|
1027
1030
|
if (typeStmt.type === null) return null;
|
|
1028
1031
|
let type = typeStmt.type.accept(this);
|
|
1029
|
-
if (type.type !== stipeSymbol
|
|
1032
|
+
if (type.type !== stipeSymbol || !(type.symbol))
|
|
1033
|
+
this.error(`'${type.type.description}' bukan sebuah Model/Tipe Valid.`);
|
|
1030
1034
|
return type.symbol;
|
|
1031
1035
|
}
|
|
1032
1036
|
|
|
@@ -1047,7 +1051,7 @@ class Interpreter {
|
|
|
1047
1051
|
|
|
1048
1052
|
let variable = new Variable(type, datumStmt.type.tetap);
|
|
1049
1053
|
|
|
1050
|
-
let value =
|
|
1054
|
+
let value = datumStmt.expr.accept(this);
|
|
1051
1055
|
|
|
1052
1056
|
if (value.data === null) value.type = variable.type; // if nihil, ok
|
|
1053
1057
|
|
|
@@ -1070,7 +1074,7 @@ class Interpreter {
|
|
|
1070
1074
|
if (variable.tetap) {
|
|
1071
1075
|
this.error(`Variabel tetap tidak dapat di-rubah.`);
|
|
1072
1076
|
}
|
|
1073
|
-
let value =
|
|
1077
|
+
let value = rubahStmt.value.accept(this);
|
|
1074
1078
|
if (value.data === null) value.type = variable.type; // if nihil, ok
|
|
1075
1079
|
|
|
1076
1080
|
if (variable.isDatum)
|
|
@@ -1109,20 +1113,20 @@ class Interpreter {
|
|
|
1109
1113
|
}
|
|
1110
1114
|
|
|
1111
1115
|
visitHentiStmt() {
|
|
1112
|
-
if (this.state === location.UNTUK || this.state === location.SLAGI)
|
|
1116
|
+
if (this.state === this.location.UNTUK || this.state === this.location.SLAGI)
|
|
1113
1117
|
throw new Henti$1(); // throws exception to escape from deep recursion
|
|
1114
1118
|
else this.error("Tidak ada pengulangan untuk dihentikan.");
|
|
1115
1119
|
}
|
|
1116
1120
|
|
|
1117
1121
|
|
|
1118
1122
|
visitLewatStmt() {
|
|
1119
|
-
if (this.state === location.UNTUK || this.state === location.SLAGI)
|
|
1123
|
+
if (this.state === this.location.UNTUK || this.state === this.location.SLAGI)
|
|
1120
1124
|
throw new Lewat$1(); // throws exception to escape from deep recursion
|
|
1121
1125
|
else this.error("Tidak ada pengulangan untuk dilewatkan.");
|
|
1122
1126
|
}
|
|
1123
1127
|
|
|
1124
1128
|
visitJatuhStmt() {
|
|
1125
|
-
if (this.state === location.LIHAT)
|
|
1129
|
+
if (this.state === this.location.LIHAT)
|
|
1126
1130
|
throw new Jatuh$1();
|
|
1127
1131
|
else this.error("Tidak bisa jatuh di luar blok kasus.");
|
|
1128
1132
|
}
|
|
@@ -1146,9 +1150,9 @@ class Interpreter {
|
|
|
1146
1150
|
this.environment = new Environment(lastEnv);
|
|
1147
1151
|
try {
|
|
1148
1152
|
for (let stmt of slagiStmt.block.statements) {
|
|
1149
|
-
this.state = location.SLAGI;
|
|
1153
|
+
this.state = this.location.SLAGI;
|
|
1150
1154
|
stmt.accept(this);
|
|
1151
|
-
this.state = location.SLAGI;
|
|
1155
|
+
this.state = this.location.SLAGI;
|
|
1152
1156
|
}
|
|
1153
1157
|
} catch (err) {
|
|
1154
1158
|
if (err instanceof Henti$1) {
|
|
@@ -1159,15 +1163,15 @@ class Interpreter {
|
|
|
1159
1163
|
}
|
|
1160
1164
|
}
|
|
1161
1165
|
this.environment = lastEnv;
|
|
1162
|
-
if (this.stackNum !== 0) this.state = location.MESIN;
|
|
1163
|
-
else this.state = location.GLOBAL;
|
|
1166
|
+
if (this.stackNum !== 0) this.state = this.location.MESIN;
|
|
1167
|
+
else this.state = this.location.GLOBAL;
|
|
1164
1168
|
}
|
|
1165
1169
|
|
|
1166
1170
|
visitUntukStmt(untukStmt) {
|
|
1167
1171
|
let name = this.validName(untukStmt.varName.lexeme, false);
|
|
1168
1172
|
let type = untukStmt.varType.accept(this);
|
|
1169
1173
|
|
|
1170
|
-
let iter =
|
|
1174
|
+
let iter = untukStmt.iterable.accept(this);
|
|
1171
1175
|
if (iter.type === petikSymbol) {
|
|
1172
1176
|
iter = new Value(barisSymbol, iter.data.split("").map(str => new Value(petikSymbol, str)));
|
|
1173
1177
|
}
|
|
@@ -1188,9 +1192,9 @@ class Interpreter {
|
|
|
1188
1192
|
try {
|
|
1189
1193
|
// didn't 'accept' the block, just uses it directly
|
|
1190
1194
|
for (let stmt of untukStmt.block.statements) {
|
|
1191
|
-
this.state = location.UNTUK;
|
|
1195
|
+
this.state = this.location.UNTUK;
|
|
1192
1196
|
stmt.accept(this);
|
|
1193
|
-
this.state = location.UNTUK;
|
|
1197
|
+
this.state = this.location.UNTUK;
|
|
1194
1198
|
}
|
|
1195
1199
|
} catch (err) {
|
|
1196
1200
|
this.environment = untukEnv.enclosing;
|
|
@@ -1204,8 +1208,8 @@ class Interpreter {
|
|
|
1204
1208
|
}
|
|
1205
1209
|
this.environment = untukEnv.enclosing;
|
|
1206
1210
|
}
|
|
1207
|
-
if (this.stackNum !== 0) this.state = location.MESIN;
|
|
1208
|
-
else this.state = location.GLOBAL;
|
|
1211
|
+
if (this.stackNum !== 0) this.state = this.location.MESIN;
|
|
1212
|
+
else this.state = this.location.GLOBAL;
|
|
1209
1213
|
}
|
|
1210
1214
|
|
|
1211
1215
|
visitJenisStmt(jenisStmt) {
|
|
@@ -1215,7 +1219,7 @@ class Interpreter {
|
|
|
1215
1219
|
}
|
|
1216
1220
|
|
|
1217
1221
|
visitLihatStmt(lihatStmt) {
|
|
1218
|
-
let match =
|
|
1222
|
+
let match = lihatStmt.expr.accept(this);
|
|
1219
1223
|
let matchType = this.environment.get(match?.type?.description);
|
|
1220
1224
|
if (!matchType?.member?.has("SAMA_SAMA")) {
|
|
1221
1225
|
this.error(`tipe ${matchType ? match.type.description : "nihil"} tidak mempunyai mesin SAMA_SAMA.`);
|
|
@@ -1225,9 +1229,9 @@ class Interpreter {
|
|
|
1225
1229
|
const handleBlock = (index) => {
|
|
1226
1230
|
while (index < lihatStmt.cases.length) {
|
|
1227
1231
|
try {
|
|
1228
|
-
this.state = location.LIHAT;
|
|
1232
|
+
this.state = this.location.LIHAT;
|
|
1229
1233
|
lihatStmt.cases[index][1].accept(this);
|
|
1230
|
-
this.state = location.LIHAT;
|
|
1234
|
+
this.state = this.location.LIHAT;
|
|
1231
1235
|
} catch (err) {
|
|
1232
1236
|
if (err instanceof Jatuh$1) {
|
|
1233
1237
|
index++; continue;
|
|
@@ -1235,8 +1239,8 @@ class Interpreter {
|
|
|
1235
1239
|
}
|
|
1236
1240
|
break;
|
|
1237
1241
|
}
|
|
1238
|
-
if (this.stackNum !== 0) this.state = location.MESIN;
|
|
1239
|
-
else this.state = location.GLOBAL;
|
|
1242
|
+
if (this.stackNum !== 0) this.state = this.location.MESIN;
|
|
1243
|
+
else this.state = this.location.GLOBAL;
|
|
1240
1244
|
};
|
|
1241
1245
|
|
|
1242
1246
|
for (let i = 0; i < lihatStmt.cases.length; i++) {
|
|
@@ -1270,7 +1274,7 @@ class Interpreter {
|
|
|
1270
1274
|
if (variable.type !== stipeSymbol) {
|
|
1271
1275
|
this.error(`Modul hanya bisa _ditambahkan_ pada tipe. '${name}' bukan merupakan tipe.`);
|
|
1272
1276
|
}
|
|
1273
|
-
if (variable.member.memory.size >
|
|
1277
|
+
if (variable.member.memory.size > 1) {
|
|
1274
1278
|
this.error(`Tipe '${name}' sudah memiliki modul sendiri, tidak bisa definisi ulang.`);
|
|
1275
1279
|
}
|
|
1276
1280
|
} else {
|
|
@@ -1294,6 +1298,7 @@ class Interpreter {
|
|
|
1294
1298
|
|
|
1295
1299
|
typeCheck(a, b, message) {
|
|
1296
1300
|
if (a.type !== b.type) {
|
|
1301
|
+
console.log(a, b);
|
|
1297
1302
|
this.error(`Tipe data tidak sama: ${a.type.description} != ${b.type.description}. ` + message);
|
|
1298
1303
|
}
|
|
1299
1304
|
}
|
|
@@ -1305,11 +1310,6 @@ class Interpreter {
|
|
|
1305
1310
|
return false;
|
|
1306
1311
|
}
|
|
1307
1312
|
|
|
1308
|
-
validValue(v) {
|
|
1309
|
-
if (v.type !== stipeSymbol) return v;
|
|
1310
|
-
this.error("stipe tidak dapat menjadi nilai.");
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
1313
|
validName(n, checkExisted = true) {
|
|
1314
1314
|
if (RESERVED_NAMES.some(v => v === n)) {
|
|
1315
1315
|
this.error(`Nama sistem (${n}) tidak boleh didefinisi ulang.`);
|
|
@@ -1323,13 +1323,7 @@ class Interpreter {
|
|
|
1323
1323
|
throw new SimplErrorEksekusi(`Error Eksekusi => ${message}`, this.line, this.output.join('\n'));
|
|
1324
1324
|
}
|
|
1325
1325
|
|
|
1326
|
-
|
|
1327
|
-
this.line = 0;
|
|
1328
|
-
this.output = [];
|
|
1329
|
-
this.tree = tree;
|
|
1330
|
-
tree.accept(this);
|
|
1331
|
-
return this.output;
|
|
1332
|
-
}
|
|
1326
|
+
|
|
1333
1327
|
}
|
|
1334
1328
|
|
|
1335
1329
|
class Token {
|
|
@@ -1359,6 +1353,23 @@ class Lexer {
|
|
|
1359
1353
|
this.errors = [];
|
|
1360
1354
|
}
|
|
1361
1355
|
|
|
1356
|
+
scanTokens(text) {
|
|
1357
|
+
this.init();
|
|
1358
|
+
this.text = text;
|
|
1359
|
+
let tokens = [];
|
|
1360
|
+
|
|
1361
|
+
while (!this.isAtEnd()) {
|
|
1362
|
+
let token = this.scan();
|
|
1363
|
+
this.charStart = this.charIndex;
|
|
1364
|
+
if (token) tokens.push(token);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
tokens.push(new Token(EOF, "Akhir dokumen", null, this.lineIndex));
|
|
1368
|
+
|
|
1369
|
+
this.tokens = tokens;
|
|
1370
|
+
return this.tokens;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1362
1373
|
isAtEnd() {
|
|
1363
1374
|
return this.charIndex >= this.text.length;
|
|
1364
1375
|
}
|
|
@@ -1401,23 +1412,6 @@ class Lexer {
|
|
|
1401
1412
|
return this.text.slice(this.charStart, this.charIndex);
|
|
1402
1413
|
}
|
|
1403
1414
|
|
|
1404
|
-
scanTokens(text) {
|
|
1405
|
-
this.init();
|
|
1406
|
-
this.text = text;
|
|
1407
|
-
let tokens = [];
|
|
1408
|
-
|
|
1409
|
-
while (!this.isAtEnd()) {
|
|
1410
|
-
let token = this.scan();
|
|
1411
|
-
this.charStart = this.charIndex;
|
|
1412
|
-
if (token) tokens.push(token);
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
tokens.push(new Token(EOF, "Akhir dokumen", null, this.lineIndex));
|
|
1416
|
-
|
|
1417
|
-
this.tokens = tokens;
|
|
1418
|
-
return this.tokens;
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
1415
|
id() {
|
|
1422
1416
|
while (!this.isAtEnd() && this.isAlphaNumeric(this.see())) this.advance();
|
|
1423
1417
|
|
|
@@ -1967,6 +1961,17 @@ class Parser {
|
|
|
1967
1961
|
this.tree = null;
|
|
1968
1962
|
}
|
|
1969
1963
|
|
|
1964
|
+
parse(tokens) {
|
|
1965
|
+
this.init();
|
|
1966
|
+
this.tokens = tokens;
|
|
1967
|
+
let treeList = [];
|
|
1968
|
+
while (!this.match(EOF)) {
|
|
1969
|
+
treeList.push(this.statement());
|
|
1970
|
+
}
|
|
1971
|
+
this.tree = new Simpl$1(treeList);
|
|
1972
|
+
return this.tree;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1970
1975
|
see() {
|
|
1971
1976
|
return this.tokens[this.tokenIndex];
|
|
1972
1977
|
}
|
|
@@ -2445,28 +2450,23 @@ class Parser {
|
|
|
2445
2450
|
throw new SimplErrorStruktur(`Error Struktur => ` + errmsg + ((found) ? ` Menemukan '${this.see().lexeme}'.` : ""), this.see().line);
|
|
2446
2451
|
}
|
|
2447
2452
|
|
|
2448
|
-
parse(tokens) {
|
|
2449
|
-
this.init();
|
|
2450
|
-
this.tokens = tokens;
|
|
2451
|
-
let treeList = [];
|
|
2452
|
-
while (!this.match(EOF)) {
|
|
2453
|
-
treeList.push(this.statement());
|
|
2454
|
-
}
|
|
2455
|
-
this.tree = new Simpl$1(treeList);
|
|
2456
|
-
return this.tree;
|
|
2457
|
-
}
|
|
2458
2453
|
}
|
|
2459
2454
|
|
|
2460
2455
|
// Simpl: Indonesian Mini Programming Language !!
|
|
2461
2456
|
|
|
2462
2457
|
class Simpl {
|
|
2463
|
-
constructor(
|
|
2458
|
+
constructor(opts = {
|
|
2459
|
+
keepMemory: false
|
|
2460
|
+
}) {
|
|
2464
2461
|
this.lexer = new Lexer();
|
|
2465
2462
|
this.parser = new Parser();
|
|
2466
2463
|
this.interpreter = new Interpreter();
|
|
2464
|
+
this.keepMemory = opts?.keepMemory ? opts.keepMemory : false;
|
|
2467
2465
|
}
|
|
2468
2466
|
|
|
2469
2467
|
runCode(text) {
|
|
2468
|
+
if (!this.keepMemory) this.interpreter.init();
|
|
2469
|
+
|
|
2470
2470
|
// console.log(text.split("\n").reduce((codeStr, line, idx) => codeStr + `${idx + 1}.\t${line}\n`, ''));
|
|
2471
2471
|
const textLines = text.split("\n");
|
|
2472
2472
|
try {
|
|
@@ -2475,7 +2475,6 @@ class Simpl {
|
|
|
2475
2475
|
let output = this.interpreter.interpret(pohon);
|
|
2476
2476
|
return output.join("\n");
|
|
2477
2477
|
} catch (err) {
|
|
2478
|
-
// throw err
|
|
2479
2478
|
if (err instanceof SimplError) {
|
|
2480
2479
|
const errorCode = textLines[err.line - 1];
|
|
2481
2480
|
let errorText = (errorCode ? `ERROR! Pada baris ke-${err.line}\n>> ` + errorCode + '\n' : "") + err.message;
|
|
@@ -2489,10 +2488,6 @@ class Simpl {
|
|
|
2489
2488
|
}
|
|
2490
2489
|
|
|
2491
2490
|
}
|
|
2492
|
-
}
|
|
2493
|
-
|
|
2494
|
-
function run(code) {
|
|
2495
|
-
return new Simpl().runCode(code);
|
|
2496
2491
|
}
|
|
2497
2492
|
|
|
2498
|
-
export {
|
|
2493
|
+
export { Simpl };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class e extends Error{constructor(e,t){super(e),this.line=t}}class t extends e{constructor(e,t,i){super(e,t),this.output=i}}class i extends e{}class a extends e{}class s{constructor(e){this.enclosing=e,this.memory=new Map}define(e,t){this.memory.set(e,t)}assign(e,t){return this.has(e)?this.memory.set(e,t):this.enclosing&&this.enclosing.assign(e,t),null}get(e){return this.has(e)?this.memory.get(e):this.enclosing?this.enclosing.get(e):null}has(e){return this.memory.has(e)}}const n=["petik","angka","logis","mesin","baris","stipe","modul"],r=Symbol("petik"),h=Symbol("angka"),l=Symbol("logis"),m=Symbol("mesin"),o=Symbol("baris"),d=Symbol("stipe"),u=Symbol("modul");class c{constructor(e,t){this.type=e,this.data=t,this.member=null}}const p=new c(null,null);class k extends c{constructor(e,t,i){super(e,i),this.tetap=t,this.isDatum=!1}}class b extends k{constructor(e,t){super(d,!0,t),this.symbol=e,this.member=new s,this.member.define("buat",new k(m,!0,t))}}function f(e,t){if(t.type===l)return t.data?"benar":"salah";if(t.type===o)return"["+t.data.reduce((t,i)=>t+", "+f(e,i),"").slice(1)+" ]";if(t.type===d)return`Model<${t.symbol?.description?t.symbol.description:""}>`;if(t.type===m){let e=t.data.returnType?.description;return`Mesin<${e||"datum"}>`}if(t.type===h)return t.data.toString();if(t.type===r)return t.data;{if(!t?.type)return"nihil";let i=e.environment.get(t.type.description);if(i?.member.has("kePetik")){return e.callFunc(i.member.get("kePetik").data,[t]).data}return`${t.type.description}<>`}}let w=class extends b{constructor(e,t){let i=Symbol(e);super(i,new g(null,(e,a)=>{let n=new c(i,!0);n.member=new s;let r=e.line;for(let i=0;i<a.length;i++){let s=t[i][0],h=s.accept(e),l=t[i][1].lexeme,m=new k(h,s.tetap,a[i].data);null===h?(m.isDatum=!0,m.type=a[i].type):a[i].type!==h&&(e.line=r,e.error(`Argumen pembuatan objek tidak sama dengan argumen model, menemukan ${a[i].type?.description}, mengharapkan ${h?h.description:"nihil"}`)),m.member=a[i].member,n.member.define(l,m)}return n},t.map(e=>[null]),i,!0))}},S=class extends b{constructor(e,t){let i=Symbol(e);super(i,null),t.forEach((e,t)=>{this.member.define(e.lexeme,new c(i,t))}),this.member.define("kePetik",y([i],r,(t,[i])=>new c(r,`${e}<${i.data}>`))),this.member.define("SAMA_SAMA",y([i,i],l,(e,[t,i])=>new c(l,i.data===t.data))),this.member.define("SERU_SAMA",y([i,i],l,(e,[t,i])=>new c(l,i.data!==t.data)))}};class g{constructor(e,t,i,a,s=!1){this.closure=e,this.block=t,this.parameters=i,this.returnType=a,this.isBuiltIn=s}}function y(e,t,i){let a=new g(null,i,e.map(e=>[e]),t,!0);return new k(m,!0,a)}function A(e){switch(e.type){case r:return new c(r,e.data);case h:return new c(h,e.data);case l:return new c(l,e.data);case m:return new c(m,e.data);case o:return new c(o,e.data.map(e=>{let t=A(e),i=new k(t.type,!1,t.data);return i.member=t.member,i}));case d:case u:return p;default:if(e.member&&e.member instanceof s){let t=e.member.memory.keys(),i=new c(e.type,null),a=new s;for(let i of t){let t=e.member.get(i),s=A(t),n=new k(t.type,t.tetap,s.data);n.member=s.member,a.define(i,n)}return i.member=a,i.data=e.data,i}return new c(e.type,e.data)}}const x=(()=>{let e=new b(r,new g(null,(e,t)=>new c(r,f(e,t[0])),[[null]],r,!0));return e.member.define("PLUS",y([r,r],r,(e,[t,i])=>new c(r,i.data+t.data))),e.member.define("LEBIH",y([r,r],l,(e,[t,i])=>new c(l,i.data>t.data))),e.member.define("KURANG",y([r,r],l,(e,[t,i])=>new c(l,i.data<t.data))),e.member.define("SAMA_SAMA",y([r,r],l,(e,[t,i])=>new c(l,i.data===t.data))),e.member.define("LEBIH_SAMA",y([r,r],l,(e,[t,i])=>new c(l,i.data>=t.data))),e.member.define("KURANG_SAMA",y([r,r],l,(e,[t,i])=>new c(l,i.data<=t.data))),e.member.define("SERU_SAMA",y([r,r],l,(e,[t,i])=>new c(l,i.data!==t.data))),e.member.define("AMPERSAN",y([r,r],l,(e,[t,i])=>new c(l,i.data&&t.data))),e.member.define("PIPA",y([r,r],l,(e,[t,i])=>new c(l,i.data||t.data))),e.member.define("SERU_UNER",y([r],l,(e,[t])=>new c(l,!Boolean(t.data)))),e.member.define("kePetik",y([r],r,(e,[t])=>new c(r,f(e,t)))),e.member.define("pisah",y([r,r],o,(e,[t,i])=>new c(o,t.data.split(i.data).map(e=>new c(r,e))))),e.member.define("bersih",y([r],r,(e,[t])=>new c(r,t.data.trim()))),e.member.define("ganti",y([r,r,r],r,(e,[t,i,a])=>new c(r,t.data.replaceAll(i.data,a.data)))),e.member.define("besar",y([r],r,(e,[t])=>new c(r,t.data.toUpperCase()))),e.member.define("kecil",y([r],r,(e,[t])=>new c(r,t.data.toLowerCase()))),e})(),M=(()=>{let e=new b(h,new g(null,(e,t)=>{if("number"==typeof t[0].data)return new c(h,t[0].data);switch(t[0].type){case r:return isNaN(Number(t[0].data))&&e.error("Nilai dari petik bukanlah sebuah angka, konversi gagal."),new c(h,Number(t[0].data));case h:return new c(h,t[0].data);case l:return new c(h,Number(t[0].data));default:return void e.error(`Tipe yang dapat diterima hanyalah petik, angka, logis, dan jenis. Mendapatkan ${t[0].type.description}.`)}},[[null]],h,!0));return e.member.define("PLUS",y([h,h],h,(e,[t,i])=>new c(h,i.data+t.data))),e.member.define("MINUS",y([h,h],h,(e,[t,i])=>new c(h,i.data-t.data))),e.member.define("BINTANG",y([h,h],h,(e,[t,i])=>new c(h,i.data*t.data))),e.member.define("GARIS_MIRING",y([h,h],h,(e,[t,i])=>new c(h,i.data/t.data))),e.member.define("MODULUS",y([h,h],h,(e,[t,i])=>new c(h,i.data%t.data))),e.member.define("LEBIH",y([h,h],l,(e,[t,i])=>new c(l,i.data>t.data))),e.member.define("KURANG",y([h,h],l,(e,[t,i])=>new c(l,i.data<t.data))),e.member.define("SAMA_SAMA",y([h,h],l,(e,[t,i])=>new c(l,i.data===t.data))),e.member.define("LEBIH_SAMA",y([h,h],l,(e,[t,i])=>new c(l,i.data>=t.data))),e.member.define("KURANG_SAMA",y([h,h],l,(e,[t,i])=>new c(l,i.data<=t.data))),e.member.define("SERU_SAMA",y([h,h],l,(e,[t,i])=>new c(l,i.data!==t.data))),e.member.define("AMPERSAN",y([h,h],l,(e,[t,i])=>new c(l,i.data&&t.data))),e.member.define("PIPA",y([h,h],l,(e,[t,i])=>new c(l,i.data||t.data))),e.member.define("SERU_UNER",y([h],l,(e,[t])=>new c(l,!Boolean(t.data)))),e.member.define("PLUS_UNER",y([h],h,(e,[t])=>new c(h,+t.data))),e.member.define("MINUS_UNER",y([h],h,(e,[t])=>new c(h,-t.data))),e.member.define("kePetik",y([h],r,(e,[t])=>new c(r,f(e,t)))),e.member.define("bulat",y([h],h,(e,[t])=>new c(h,Math.round(t.data)))),e.member.define("bulatAtas",y([h],h,(e,[t])=>new c(h,Math.ceil(t.data)))),e.member.define("bulatBawah",y([h],h,(e,[t])=>new c(h,Math.floor(t.data)))),e})(),E=(()=>{let e=new b(l,new g(null,(e,t)=>t[0].type===o&&0===t[0].data.length?new c(l,!1):new c(l,Boolean(t[0].data)||Boolean(t[0].data?.member?.size)),[[null]],l,!0));return e.member.define("SAMA_SAMA",y([l,l],l,(e,[t,i])=>new c(l,i.data===t.data))),e.member.define("SERU_SAMA",y([l,l],l,(e,[t,i])=>new c(l,i.data!==t.data))),e.member.define("AMPERSAN",y([l,l],l,(e,[t,i])=>new c(l,i.data&&t.data))),e.member.define("PIPA",y([l,l],l,(e,[t,i])=>new c(l,i.data||t.data))),e.member.define("SERU_UNER",y([l],l,(e,[t])=>new c(l,!Boolean(t.data)))),e.member.define("kePetik",y([l],r,(e,[t])=>new c(r,f(e,t)))),e})(),T=(()=>{let e=new b(o);const t=e=>{let t=new k(e.type,!1,e.data);return t.member=e.member,t.isDatum=!0,t};return e.member.define("PLUS",y([o,o],o,(e,[t,i])=>new c(o,Array(...i.data,...t.data)))),e.member.define("MINUS_UNER",y([o],o,(e,[t])=>new c(o,t.data.slice(0,t.length)))),e.member.define("SAMA_SAMA",y([o,o],l,(e,[t,i])=>new c(l,((e,t)=>{if(e.length!==t.length)return!1;for(let i=0;i<e.length;i++)if(e[i].data!==t[i].data)return!1;return!0})(i.data,t.data)))),e.member.define("SERU_SAMA",y([o,o],l,(e,[t,i])=>new c(l,((e,t)=>{if(e.length!==t.length)return!0;for(let i=0;i<e.length;i++)if(e[i].data!==t[i].data)return!0;return!1})(i.data,t.data)))),e.member.define("AMPERSAN",y([o,o],l,(e,[t,i])=>new c(l,i.data&&t.data))),e.member.define("PIPA",y([o,o],l,(e,[t,i])=>new c(l,i.data||t.data))),e.member.define("SERU_UNER",y([o],l,(e,[t])=>new c(l,!Boolean(t.data)))),e.member.define("kePetik",y([o],r,(e,[t])=>new c(r,f(e,t)))),e.member.define("hapus",y([o,h],o,(e,[t,i])=>{for(t.data.length<=i.data&&e.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${t.data.length}`);i.data<0;)i.data+=t.data.length;return t.data=t.data.filter((e,t)=>t!==i.data),t})),e.member.define("potongan",y([o,h,h],o,(e,[t,i,a])=>((i.data>=t.data.length||i.data<0||a.data<=i.data||a.data>t.data.length)&&e.error(`Indeks tidak valid, ${i.data} sampai ${a.data}, dengan ukuran baris ${t.data.length}`),new c(o,t.data.slice(i.data,a.data))))),e.member.define("tumpuk",y([o,null],null,(e,[i,a])=>(i.data.push(t(a)),i))),e.member.define("tumpah",y([o],null,(e,[t])=>(t.data.pop(),t))),e.member.define("masuk",y([o,null,h],null,(e,[i,a,s])=>(s.data>i.data.length&&e.error(`Indeks tidak valid, ${s.data}, dengan ukuran baris ${i.data.length}`),i.data.splice(s.data,0,t(a)),i))),e.member.define("petakan",y([o,m],o,(e,[i,a])=>{let s=new c(o,[]);for(let n of i.data){let i=e.callFunc(a.data,[n]);s.data.push(t(i))}return s})),e.member.define("saring",y([o,m],o,(e,[i,a])=>{let s=new c(o,[]);for(let n of i.data){!0===e.callFunc(a.data,[n]).data&&s.data.push(t(n))}return s})),e.member.define("reduksi",y([o,m,null],null,(e,[t,i,a])=>{for(let s of t.data){a=e.callFunc(i.data,[a,s])}return a})),e.member.define("punya?",y([o,null],l,(e,[t,i])=>{let a,s=e.environment.get(i.type?.description);s||e.error("Tipe tidak ditemukan atau tidak valid"),s.member?.has("SAMA_SAMA")?a=s.member.get("SAMA_SAMA"):e.error(`model ${i.type.description} tidak mempunyai mesin SAMA_SAMA di dalam modulnya.`);for(let s of t.data){if(s.type!==i.type)continue;if(e.callFunc(a.data,[s,i]).data)return new c(l,!0)}return new c(l,!1)})),e})(),I=(()=>{let e=new b(m);return e.member.define("kePetik",y([m],r,(e,[t])=>new c(r,f(e,t)))),e})(),N=(()=>{let e=new s;e.define("petik",x),e.define("angka",M),e.define("logis",E),e.define("baris",T),e.define("mesin",I),e.define("jarak",y([h,h],o,(e,[t,i])=>new c(o,Array(Math.abs(Math.floor(i.data-t.data))).fill(0).map((e,a)=>new c(h,t.data+(i.data>t.data?1:-1)*a))))),e.define("nihil?",y([null],l,(e,[t])=>new c(l,null===t.data))),e.define("ukuran",y([null],h,(e,[t])=>t.type===o||t.type===r?new c(h,t.data.length):v.error(`Ukuran hanya terdapat untuk tipe petik atau baris. Menemukan tipe ${t.type.description}.`))),e.define("salin",y([null],null,(e,[t])=>A(t))),e.define("tipe",y([null],r,(e,[t])=>t.type?.description?new c(r,t.type.description):new c(r,"datum")));let t=new k(u,!0,null);t.member=new s,t.member.define("acak",y([h,h],h,(e,[t,i])=>{let a=Math.abs(t.data-i.data),s=Math.random()*a+Math.min(t.data,i.data);return new c(h,s)})),t.member.define("akar2",y([h],h,(e,[t])=>new c(h,Math.sqrt(t.data)))),t.member.define("min",y([h,h],h,(e,[t,i])=>new c(h,Math.min(t.data,i.data)))),t.member.define("maks",y([h,h],h,(e,[t,i])=>new c(h,Math.max(t.data,i.data))));const i=(e,t)=>{for([e,t]=[Math.max(e,t),Math.min(e,t)];t>0;)[e,t]=[t,e%t];return e};return t.member.define("fpb",y([h,h],h,(e,[t,a])=>{let s=i(t.data,a.data);return new c(h,s)})),t.member.define("kpk",y([h,h],h,(e,[t,a])=>{let s=i(t.data,a.data);return new c(h,t.data*a*data/s)})),e.define("mtk",t),e})(),L=["rubah","kalau","namun","slagi","untuk","cetak","henti","lewat","dalam","hasil","kerja","datum","jenis","model","tetap","modul","lihat","kasus","jatuh"],U=11,$=20,R=21,P=26,_=27,B=37,C=["RUBAH","KALAU","NAMUN","SLAGI","UNTUK","CETAK","HENTI","LEWAT","DALAM","HASIL","KERJA","DATUM","JENIS","MODEL","TETAP","MODUL","LIHAT","KASUS","JATUH","EOF","ID","LITERAL","PLUS","MINUS","BINTANG","GARIS_MIRING","LPAREN","RPAREN","LEBIH","LEBIH_SAMA","KURANG","KURANG_SAMA","SAMA","SAMA_SAMA","DOT","LCURLY","RCURLY","COMMA","LSQUARE","RSQUARE","PIPA","AMPERSAN","SERU","ARROW","SERU_SAMA","MODULUS","PIPELINE","COLON","DOLLAR"];let j=class{},G=class{},K=class{},H=class{constructor(e){this.value=e}};class O{constructor(){this.globalEnvironment=N,this.location={GLOBAL:1,SLAGI:2,UNTUK:3,MESIN:4,LIHAT:5},this.MAX_STACK_SIZE=500,this.init()}init(){this.line=0,this.environment=new s(this.globalEnvironment),this.tree=null,this.state=this.location.GLOBAL,this.stack=[],this.output=[],this.objectStack=null,this.exprWillBeCalled=!1,this.pipeStack=[]}interpret(e){return this.line=0,this.output=[],this.tree=e,e.accept(this),this.output}visitLiteralExpr(e){let t=e.token;switch(this.line=t.line,typeof t.value){case"string":return new c(r,t.value);case"number":return new c(h,t.value);case"boolean":return new c(l,t.value);default:return p}}visitArrayExpr(e){let t=new c(o,[]);for(let i of e.contents){let e=i.accept(this),a=new k(e.type,!1,e.data);a.member=e.member,a.isDatum=!0,t.data.push(a)}return t}visitIndexExpr(e){let t=e.iterable.accept(this);t.type===r&&(t=new c(o,t.data.split("").map(e=>new c(r,e)))),t.type!==o&&this.error(`'${t.type.description}' bukan baris/petik, tidak bisa di-indeks`);let i=e.index.accept(this);for(i.type!==h&&this.error(`Ekspresi di dalam indeks harus bertipe angka. Menemukan ${i.type.description}`),i.data>=t.data.length&&this.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris: ${i.data} >= ${t.data.length}`);i.data<0;)i.data+=t.data.length;return t.data[i.data]}visitLambdaExpr(e){let t=e.params.map(e=>[e[0].accept(this),e[0].tetap,e[1].lexeme]);t.length>1&&(e=>{let t=new Map;for(let i of e){if(t.has(i))return!0;t.set(i,!0)}return!1})(t.map(e=>e[2]))&&this.error("Parameter mesin tidak boleh mempunyai nama yang sama.");let i=null;e.returnType&&(i=e.returnType.accept(this));let a=new g(this.environment,e.block,t,i);return new c(m,a)}visitCallExpr(e){this.exprWillBeCalled=!0;let t=e.callable.accept(this);this.exprWillBeCalled=!1,t.type!==m&&t.type!==d&&this.error(`Hanya bisa 'memanggil' mesin atau model, malah menemukan ${t.type.description}. `),t?.data?.block||this.error("Mesin tidak terdefinisi, tidak bisa dipanggil.");let i=[];return this.objectStack&&(i=[this.objectStack],this.objectStack=null),i=[...i,...e.args.map(e=>e.accept(this))],this.callFunc(t.data,i)}callFunc(e,t){e||this.error("Mesin tidak terdefinisi, tidak bisa dipanggil."),this.stack.push(this.line),this.stack.length>this.MAX_STACK_SIZE&&this.error(`Rekursi melebihi batas: Lebih dari ${this.MAX_STACK_SIZE}`);let i=this.state;this.line=this.stack[this.stack.length-1],this.state=this.location.MESIN,t.length!==e.parameters.length&&this.error(`Jumlah argumen tidak sama dengan parameter mesin. Menemukan ${t.length}, harusnya ${e.parameters.length}.`);let a=this.line;for(let i=0;i<t.length;i++){let s=e.parameters[i][0];null!==s&&(t[i].type!==s&&(this.line=a,this.error(`Tipe argumen tidak sama dengan parameter. Menemukan ${t[i].type.description}, harusnya ${s.description}`)))}if(e.isBuiltIn)return this.stack.pop(),this.state=i,e.block(this,t);let n=this.environment,r=new s(e.closure);this.environment=r;for(let i=0;i<t.length;i++){let[a,s,n]=e.parameters[i];null===a&&(a=t[i].type);let r=new k(a,s,t[i].data);r.member=t[i].member,this.environment.define(n,r)}let h=p;for(let t of e.block.statements)try{t.accept(this)}catch(e){if(e instanceof H){h=e.value;break}if(!(e instanceof j||e instanceof K))throw e;this.error("Tidak bisa menghentikan atau melewatkan mesin. ")}return this.stack.pop(),this.state=i,this.environment=n,h}visitBinaryExpr(e){let t=e.left.accept(this),i=e.right.accept(this);this.line=e.op.line,this.nullCheck(t,i)&&this.error("Tidak bisa mengoperasikan nilai Nihil."),this.typeCheck(t,i,`Pada operasi biner ${e.op.lexeme}`);let a=this.environment.get(t.type.description);return this.operate(a,e.op.type,i,t)}visitUnaryExpr(e){let t=e.right.accept(this);this.line=e.op.line,this.nullCheck(t)&&this.error("Tidak bisa mengoperasikan nilai Nihil.");let i=this.environment.get(t.type.description);return this.operate(i,e.op.type,t)}operate(e,t,i,a){let s=C[t]+(a?"":"_UNER"),n=e.member.get(s);n||this.error(`operator ${s} tidak terdefinisi untuk Model ${i.type.description}.`);let r=null;return r=a?this.callFunc(n.data,[i,a]):this.callFunc(n.data,[i]),r}visitGroupingExpr(e){return e.expr.accept(this)}visitIdentifierExpr(e){if("$"===e.token.lexeme){if(this.line=e.token.line,!(this.pipeStack.length<=0))return this.pipeStack[this.pipeStack.length-1];this.error("$ hanya ada dalam ekspresi saluran.")}let t=this.environment.get(e.token.lexeme);return this.line=e.token.line,t||this.error(`'${e.token.lexeme}' tidak dapat ditemukan.`),t}visitMemberExpr(e){let t=this.exprWillBeCalled;this.exprWillBeCalled=!1;let i=e.main.accept(this),a=e.member.token.lexeme;if(this.line=e.member.token.line,i?.member&&i.member.has(a))return i.member.get(a);{const e=this.environment.get(i.type.description);if(e||this.error(`nama .${a} tidak ditemukan.`),e.member?.has(a)){if(t)return this.objectStack=i,e.member.get(a);this.error("akses titik . dari objek ke model harus berupa panggilan/penggunaaan mesin.")}this.error(`nama .${a} tidak ditemukan dalam tipe ${i.type.description}`)}}visitPipeLineExpr(e){let t=e.expr.accept(this);this.pipeStack.push(t);let i=e.pipeTo.accept(this);return this.pipeStack.pop(),i}visitTypeStmt(e){if(null===e.type)return null;let t=e.type.accept(this);return t.type===d&&t.symbol||this.error(`'${t.type.description}' bukan sebuah Model/Tipe Valid.`),t.symbol}visitCetakStmt(e){let t=e.expr.accept(this);this.output.push(f(this,t))}visitKerjaStmt(e){e.expr.accept(this)}visitDatumStmt(e){let t=e.type.accept(this),i=this.validName(e.name.lexeme);this.line=e.name.line;let a=new k(t,e.type.tetap),s=e.expr.accept(this);null===s.data&&(s.type=a.type),null===t?(a.isDatum=!0,a.type=s.type):this.typeCheck(a,s,`Pada pembuatan variabel '${i}'`),a.data=s.data,a.member=s.member,this.environment.define(i,a)}visitRubahStmt(e){let t=e.variable.accept(this);void 0===t.tetap&&this.error("Pe-rubah-an hanya dapat dilakukan kepada Variabel!"),t.tetap&&this.error("Variabel tetap tidak dapat di-rubah.");let i=e.value.accept(this);null===i.data&&(i.type=t.type),t.isDatum?t.type=i.type:this.typeCheck(t,i,"Pada perubahan variabel."),t.data=i.data,t.member=i.member}visitBlockStmt(e){let t=new s(this.environment);this.environment=t;try{for(let t of e.statements)t.accept(this)}catch(e){throw this.environment=t.enclosing,e}this.environment=t.enclosing}visitKalauStmt(e){let t=e.condition?.accept(this);t?.type&&t?.type!==l&&this.error(`Ekspresi dalam 'kalau' harus bertipe logis, menemukan ${t.type?t.type.description:"nihil"}`),null==t||t.data?e.thenBlock.accept(this):e.elseKalau?.accept(this)}visitHentiStmt(){if(this.state===this.location.UNTUK||this.state===this.location.SLAGI)throw new j;this.error("Tidak ada pengulangan untuk dihentikan.")}visitLewatStmt(){if(this.state===this.location.UNTUK||this.state===this.location.SLAGI)throw new K;this.error("Tidak ada pengulangan untuk dilewatkan.")}visitJatuhStmt(){if(this.state===this.location.LIHAT)throw new G;this.error("Tidak bisa jatuh di luar blok kasus.")}visitHasilStmt(e){throw 0==this.stack.length&&this.error("Tidak bisa menghasilkan diluar blok mesin."),new H(e.expr.accept(this))}visitSlagiStmt(e){const t=e=>(e.type!==l&&this.error(`Ekspresi dalam 'slagi' harus bertipe 'logis', menemukan ${e.type?e.type.description:"nihil"}`),e.data);let i=this.environment;for(;t(e.condition.accept(this));){this.environment=new s(i);try{for(let t of e.block.statements)this.state=this.location.SLAGI,t.accept(this),this.state=this.location.SLAGI}catch(e){if(e instanceof j)break;if(e instanceof K)continue;throw e}}this.environment=i,0!==this.stackNum?this.state=this.location.MESIN:this.state=this.location.GLOBAL}visitUntukStmt(e){let t=this.validName(e.varName.lexeme,!1),i=e.varType.accept(this),a=e.iterable.accept(this);a.type===r&&(a=new c(o,a.data.split("").map(e=>new c(r,e)))),a.type!==o&&this.error(`Pernyataan 'untuk' harus mengiterasi sebuah baris atau petik, bukan ${a.type.description}`);for(let n=0;n<a.data.length;n++){let r=a.data[n],h=new k(r.type,!!e.type?.tetap,r.data);null===i?h.isDatum=!0:r.type!==i&&this.error(`Tipe data tidak sama pada indeks ke-${n}: ${r.type.description} != ${i.description}.`);let l=new s(this.environment);l.define(t,h),this.environment=l;try{for(let t of e.block.statements)this.state=this.location.UNTUK,t.accept(this),this.state=this.location.UNTUK}catch(e){if(this.environment=l.enclosing,e instanceof K)continue;if(e instanceof j)break;throw e}this.environment=l.enclosing}0!==this.stackNum?this.state=this.location.MESIN:this.state=this.location.GLOBAL}visitJenisStmt(e){let t=this.validName(e.name.lexeme);this.line=e.name.line,this.environment.define(t,new S(t,e.enums))}visitLihatStmt(e){let t=e.expr.accept(this),i=this.environment.get(t?.type?.description);i?.member?.has("SAMA_SAMA")||this.error(`tipe ${i?t.type.description:"nihil"} tidak mempunyai mesin SAMA_SAMA.`);let a=i.member.get("SAMA_SAMA");const s=t=>{for(;t<e.cases.length;){try{this.state=this.location.LIHAT,e.cases[t][1].accept(this),this.state=this.location.LIHAT}catch(e){if(e instanceof G){t++;continue}throw e}break}0!==this.stackNum?this.state=this.location.MESIN:this.state=this.location.GLOBAL};for(let i=0;i<e.cases.length;i++){let n=e.cases[i];if(!n[0])return s(i);let r=n[0].accept(this);if(this.callFunc(a.data,[t,r]).data)return s(i)}}visitSimplStmt(e){for(let t of e.statements)t.accept(this)}visitModelStmt(e){let t=this.validName(e.name.lexeme);this.line=e.name.line,this.environment.define(t,new w(t,e.contents))}visitModulStmt(e){let t=this.validName(e.name.lexeme,!1);this.line=e.name.line;let i=this.environment.get(t);i?(i.type!==d&&this.error(`Modul hanya bisa _ditambahkan_ pada tipe. '${t}' bukan merupakan tipe.`),i.member.memory.size>1&&this.error(`Tipe '${t}' sudah memiliki modul sendiri, tidak bisa definisi ulang.`)):(i=new k(u,!0,null),i.member=new s,this.environment.define(t,i));let a=this.environment;i.member.enclosing=this.environment,this.environment=i.member;for(let t of e.statements)t.accept(this);[this.environment,i.member]=[a,this.environment]}typeCheck(e,t,i){e.type!==t.type&&(console.log(e,t),this.error(`Tipe data tidak sama: ${e.type.description} != ${t.type.description}. `+i))}nullCheck(...e){for(let t of e)if(null===t.data||null===t.type)return t;return!1}validName(e,t=!0){return n.some(t=>t===e)?this.error(`Nama sistem (${e}) tidak boleh didefinisi ulang.`):t&&this.environment.has(e)&&this.error(`Variabel dengan nama '${e}' sudah ada. Tidak bisa didefinisi ulang.`),e}error(e){throw new t(`Error Eksekusi => ${e}`,this.line,this.output.join("\n"))}}class D{constructor(e,t,i,a){this.type=e,this.lexeme=t,this.value=i,this.line=a}toString(){return`< [${this.line}] ${C[this.type]}, ${this.lexeme} >`}}class F{constructor(){this.init()}init(){this.text=null,this.charStart=0,this.charIndex=0,this.lineIndex=1,this.tokens=[],this.errors=[]}scanTokens(e){this.init(),this.text=e;let t=[];for(;!this.isAtEnd();){let e=this.scan();this.charStart=this.charIndex,e&&t.push(e)}return t.push(new D(19,"Akhir dokumen",null,this.lineIndex)),this.tokens=t,this.tokens}isAtEnd(){return this.charIndex>=this.text.length}advance(){this.isAtEnd()||("\n"===this.see()&&this.lineIndex++,this.charIndex++)}see(){return this.isAtEnd()?"EOF":this.text[this.charIndex]}peek(e=1){return this.isAtEnd()?null:this.text[this.charIndex+e]}isAlpha(e){return/^[a-zA-Z_]$/.test(e)}isNumeric(e){return/^[0-9]$/.test(e)}isAlphaNumeric(e){return this.isAlpha(e)||this.isNumeric(e)||"?"===e}skipWhitespaces(){for(;!this.isAtEnd()&&/\s/.test(this.see());)this.advance(),this.charStart++}parseLexeme(){return this.text.slice(this.charStart,this.charIndex)}id(){for(;!this.isAtEnd()&&this.isAlphaNumeric(this.see());)this.advance();let e=this.parseLexeme(),t=L.findIndex(t=>t===e);return-1!=t?new D(t,e,null,this.lineIndex):["benar","salah"].some(t=>t===e)?new D(R,e,"benar"===e,this.lineIndex):new D("nihil"===e?R:$,e,null,this.lineIndex)}number(){let e=!1;for(;!this.isAtEnd()&&this.isNumeric(this.see());)if(this.advance(),"."===this.see()){if(e)break;e=!0,this.advance()}let t=parseFloat(e?this.parseLexeme():this.parseLexeme()+".");return new D(R,this.parseLexeme(),t,this.lineIndex)}string(){for(this.advance();!this.isAtEnd()&&'"'!==this.see();)this.advance();this.isAtEnd()&&this.error("Petik tidak tertutup."),this.advance();let e=this.parseLexeme();return new D(R,e,e.slice(1,e.length-1),this.lineIndex)}comment(){for(;!this.isAtEnd()&&"\n"!==this.see();)this.advance(),this.charStart++;this.advance(),this.charStart++}multilineComment(){for(this.advance(),this.advance(),this.charStart=this.charStart+2;!this.isAtEnd()&&("*"!==this.see()||"/"!==this.peek());)this.advance(),this.charStart++;this.advance(),this.advance(),this.charStart=this.charStart+2}makeToken(e){return this.advance(),new D(e,this.parseLexeme(),null,this.lineIndex)}scan(){for(this.skipWhitespaces();"#"===this.see()||"/"===this.see()&&"*"===this.peek();)"#"===this.see()?this.comment():this.multilineComment(),this.skipWhitespaces();if(this.isAlpha(this.see()))return this.id();if(this.isNumeric(this.see()))return this.number();switch(this.see()){case"$":return this.makeToken(48);case":":return this.makeToken(47);case"+":return this.makeToken(22);case"-":return this.makeToken(23);case"/":return this.makeToken(25);case"*":return this.makeToken(24);case"(":return this.makeToken(P);case")":return this.makeToken(_);case".":return this.makeToken(34);case",":return this.makeToken(B);case"{":return this.makeToken(35);case"}":return this.makeToken(36);case"[":return this.makeToken(38);case"]":return this.makeToken(39);case"|":return">"===this.peek()?(this.advance(),this.makeToken(46)):this.makeToken(40);case"&":return this.makeToken(41);case"%":return this.makeToken(45);case"!":return"="===this.peek()?(this.advance(),this.makeToken(44)):this.makeToken(42);case">":return"="===this.peek()?(this.advance(),this.makeToken(29)):this.makeToken(28);case"<":return"="===this.peek()?(this.advance(),this.makeToken(31)):this.makeToken(30);case"=":return"="===this.peek()&&">"===this.peek(2)?this.makeToken(32):"="===this.peek()?(this.advance(),this.makeToken(33)):">"===this.peek()?(this.advance(),this.makeToken(43)):this.makeToken(32);case'"':return this.string()}this.isAtEnd()||this.error(`karakter tidak valid: Menemukan '${this.see()}'.`)}error(e){throw new a("Error Tulisan => "+e,this.see().line)}debugPrintTokens(e){for(let t of e)console.log(t.toString())}}class J{accept(e){return this.visit(e)}}class W extends J{constructor(e,t,i){super(),this.left=e,this.op=t,this.right=i}visit(e){return e.visitBinaryExpr(this)}}class q extends J{constructor(e,t){super(),this.op=e,this.right=t}visit(e){return e.visitUnaryExpr(this)}}class V extends J{constructor(e){super(),this.token=e}visit(e){return e.visitLiteralExpr(this)}}class Z extends J{constructor(e){super(),this.expr=e}visit(e){return e.visitGroupingExpr(this)}}class z extends J{constructor(e,t){super(),this.main=e,this.member=t}visit(e){return e.visitMemberExpr(this)}}class X extends J{constructor(e){super(),this.token=e}visit(e){return e.visitIdentifierExpr(this)}}class Q extends J{constructor(e,t,i){super(),this.params=e,this.returnType=t,this.block=i}visit(e){return e.visitLambdaExpr(this)}}class Y extends J{constructor(e,t){super(),this.callable=e,this.args=t}visit(e){return e.visitCallExpr(this)}}let ee=class extends J{constructor(e){super(),this.contents=e}visit(e){return e.visitArrayExpr(this)}};class te extends J{constructor(e,t){super(),this.iterable=e,this.index=t}visit(e){return e.visitIndexExpr(this)}}class ie extends J{constructor(e,t){super(),this.expr=e,this.pipeTo=t}visit(e){return e.visitPipeLineExpr(this)}}class ae{accept(e){return this.visit(e)}}class se extends ae{constructor(e){super(),this.expr=e}visit(e){return e.visitCetakStmt(this)}}class ne extends ae{constructor(e,t,i){super(),this.type=e,this.name=t,this.expr=i}visit(e){return e.visitDatumStmt(this)}}class re extends ae{constructor(e,t,i){super(),this.type=e,this.tetap=t,this.contents=i}visit(e){return e.visitTypeStmt(this)}}class he extends ae{constructor(e){super(),this.expr=e}visit(e){return e.visitKerjaStmt(this)}}class le extends ae{constructor(e){super(),this.statements=e}visit(e){return e.visitBlockStmt(this)}}class me extends ae{constructor(e,t,i){super(),this.condition=e,this.thenBlock=t,this.elseKalau=i}visit(e){return e.visitKalauStmt(this)}}class oe extends ae{constructor(e,t,i,a){super(),this.varType=e,this.varName=t,this.iterable=i,this.block=a}visit(e){return e.visitUntukStmt(this)}}class de extends ae{constructor(e,t){super(),this.condition=e,this.block=t}visit(e){return e.visitSlagiStmt(this)}}class ue extends ae{constructor(){super()}visit(e){return e.visitHentiStmt(this)}}class ce extends ae{constructor(){super()}visit(e){return e.visitLewatStmt(this)}}class pe extends ae{constructor(){super()}visit(e){return e.visitJatuhStmt(this)}}class ke extends ae{constructor(e,t){super(),this.variable=e,this.value=t}visit(e){return e.visitRubahStmt(this)}}class be extends ae{constructor(e){super(),this.expr=e}visit(e){return e.visitHasilStmt(this)}}class fe extends ae{constructor(e,t){super(),this.name=e,this.enums=t}visit(e){return e.visitJenisStmt(this)}}class we extends ae{constructor(e,t){super(),this.expr=e,this.cases=t}visit(e){return e.visitLihatStmt(this)}}class ve extends ae{constructor(e,t){super(),this.name=e,this.contents=t}visit(e){return e.visitModelStmt(this)}}let Se=class extends ae{constructor(e){super(),this.statements=e}visit(e){return e.visitSimplStmt(this)}};class ge extends ae{constructor(e,t){super(),this.name=e,this.statements=t}visit(e){return e.visitModulStmt(this)}}class ye{constructor(){this.init()}init(){this.tokens=[],this.tokenIndex=0,this.tree=null}parse(e){this.init(),this.tokens=e;let t=[];for(;!this.match(19);)t.push(this.statement());return this.tree=new Se(t),this.tree}see(){return this.tokens[this.tokenIndex]}peek(){return this.tokenIndex+1>=this.tokens.length?null:this.tokens[this.tokenIndex+1]}check(e){return this.tokens[this.tokenIndex].type===e}isAtEnd(){return this.tokenIndex>=this.tokens.length}match(...e){if(this.isAtEnd())return!1;for(let t of e)if(this.check(t))return this.tokenIndex++,!0;return!1}eat(e,t){this.match(e)||this.error(t)}previous(){return this.tokens[this.tokenIndex-1]}blockStmt(){if(this.match(47))return new le([this.statement()]);this.eat(35,"Mengharapkan sebuah blok.");let e=[];for(;!this.match(36);)e.push(this.statement());return new le(e)}functionCallExpr(e){let t=[];if(this.check(_));else do{let e=this.expression();t.push(e)}while(this.match(B));return this.eat(_,"Mengharapkan ')' setelah penggunaan mesin."),new Y(e,t)}lambda(){let e=[];if(this.eat(P,"Mengharapkan '(' setelah '=>' untuk deklarasi objek `mesin`."),this.match($,U)){let t=this.typeStmt();this.eat($,"Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam objek `mesin`.");let i=this.previous();for(e.push([t,i]);this.match(B);){this.match($,U)||this.error("Mengharapkan Tipe parameter setelah koma dalam objek `mesin`.");let t=this.typeStmt();this.eat($,"Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam objek `mesin`.");let i=this.previous();e.push([t,i])}}this.eat(_,"Mengharapkan ')' setelah deklarasi parameter objek `mesin`.");let t=null;this.match($,U)&&(t=this.typeStmt()),this.match(R)&&(null!==this.previous().value&&this.error("Mengharapkan Tipe Hasil yang valid."),t=null);let i=this.blockStmt();return new Q(e,t,i)}arrayExpr(){if(this.match(39))return new ee([]);let e=[];do{if(this.check(39))break;let t=this.expression();e.push(t)}while(this.match(B));return this.eat(39,"Mengharapkan ']' untuk menutup 'baris'."),new ee(e)}arrayIndex(e){let t=this.expression();return this.eat(39,"Mengharapkan ']' untuk menutup indeks."),new te(e,t)}primary(){if(this.match(P)){let e=this.expression();return this.eat(_,"Mengharapkan ')' untuk mengakhiri ekspresi kurung"),new Z(e)}return this.match(R)?new V(this.previous()):this.match($,48)?this.identifier():this.match(43)?this.lambda():this.match(38)?this.arrayExpr():void this.error("Mengharapkan Ekspresi valid.")}valuable(){let e=this.primary();for(;;)if(this.match(P))e=this.functionCallExpr(e);else if(this.match(38))e=this.arrayIndex(e);else{if(!this.match(34))break;e=this.member(e)}return e}unary(){if(this.match(22,23,42)){let e=this.previous(),t=this.unary();return new q(e,t)}return this.valuable()}identifier(){return new X(this.previous())}member(e){this.eat($,"Mengharapkan Nama variabel setelah '.'.");let t=this.identifier();return new z(e,t)}factor(){let e=this.unary();for(;this.match(45,24,25);){let t=this.previous(),i=this.unary();e=new W(e,t,i)}return e}term(){let e=this.factor();for(;this.match(22,23);){let t=this.previous(),i=this.factor();e=new W(e,t,i)}return e}equality(){let e=this.term();if(this.match(28,29,30,31,33,44)){let t=this.previous(),i=this.term();e=new W(e,t,i)}return e}andTerm(){let e=this.equality();for(;this.match(41);){let t=this.previous(),i=this.equality();e=new W(e,t,i)}return e}orTerm(){let e=this.andTerm();for(;this.match(40);){let t=this.previous(),i=this.andTerm();e=new W(e,t,i)}return e}pipeLine(){let e=this.orTerm();for(;this.match(46);){let t=this.orTerm();e=new ie(e,t)}return e}expression(){return this.pipeLine()}cetakStmt(){let e=this.expression();return new se(e)}typeStmt(){if(this.previous().type===U){let e=!1;return this.match(14)&&(e=!0),new re(null,e,null)}let e=this.identifier(),t=!1;return this.match(14)&&(t=!0),new re(e,t,null)}datumStmt(){let e=this.typeStmt();this.eat($,"Mengharapkan Nama setelah Tipe pada deklarasi variabel.");let t=this.previous();this.eat(32,"Mengharapkan '=' setelah Nama variabel.");let i=this.expression();return new ne(e,t,i)}kalauStmt(){this.check(35)&&this.error("Mengharapkan ekspresi setelah 'kalau'.");let e=this.expression(),t=this.blockStmt(),i=null;if(this.match(2))if(this.match(1))i=this.kalauStmt();else{let e=null,t=this.blockStmt();i=new me(e,t)}return new me(e,t,i)}untukStmt(){this.match($,U)||this.error("Mengharapkan Tipe variabel untuk diinisialisasi setelah 'untuk'.");let e=this.typeStmt();this.eat($,"Mengharapkan Nama variabel setelah Tipe dalam pernyataan 'untuk'.");let t=this.previous();this.eat(8,"Mengharapkan 'dalam' setelah deklarasi variabel pada pernyataan 'untuk'.");let i=this.expression(),a=this.blockStmt();return new oe(e,t,i,a)}slagiStmt(){let e=this.expression(),t=this.blockStmt();return new de(e,t)}rubahStmt(){let e=this.valuable(),t=null;this.match(22,23,24,25,41,40,45)&&(t=new W(e,this.previous(),null)),this.eat(32,"Mengharapkan '=' setelah variable yang ingin di-'rubah'.");let i=this.expression();return t&&(t.right=i,i=t),new ke(e,i)}jenisStmt(){this.eat($,"Mengharapkan Nama Jenis setelah 'jenis'.");let e=this.previous();this.eat(P,"Mengharapkan '(' setelah deklarasi Nama Jenis."),this.check(_)&&this.error("Isian Jenis tidak boleh kosong.",!1);let t=[];do{this.eat($,"Mengharapkan macam jenis dalam 'jenis'.");let e=this.previous();t.push(e)}while(this.match(B));return this.eat(_,"Mengharapkan ')' untuk mengakhiri deklarasi 'jenis'."),new fe(e,t)}lihatStmt(){let e=this.expression(),t=[];for(this.check(17)||this.error("Mengharapkan `kasus` setelah ekspresi dalam `lihat`.");this.match(17);)t.push([this.expression(),this.blockStmt()]);return this.match(2)&&t.push([null,this.blockStmt()]),new we(e,t)}modelStmt(){this.eat($,"Mengharapkan Nama Model setelah 'model'.");let e=this.previous();this.eat(P,"Mengharapkan '(' setelah Nama Model dalam 'model'."),this.check(_)&&this.error("Model tidak boleh tanpa isian.",!1);let t=[];do{this.match($,U)||this.error("Mengharapkan Tipe variabel dalam deklarasi 'Model'.");let e=this.typeStmt();this.eat($,"Mengharapkan Nama variabel dalam deklarasi 'model'.");let i=this.previous();t.push([e,i])}while(this.match(B));return this.eat(_,"Mengharapkan ')' untuk mengakhiri deklarasi 'model'."),new ve(e,t)}modulStmt(){this.eat($,"Mengharapkan Nama modul setelah deklarasi.");let e=this.previous(),t=this.blockStmt();return new ge(e,t.statements)}statement(){return this.match(5)?this.cetakStmt():this.match($,U)?this.datumStmt():this.match(10)?new he(this.expression()):this.match(1)?this.kalauStmt():this.check(35)?this.blockStmt():this.match(4)?this.untukStmt():this.match(3)?this.slagiStmt():this.match(6)?new ue:this.match(7)?new ce:this.match(18)?new pe:this.match(0)?this.rubahStmt():this.match(9)?new be(this.expression()):this.match(12)?this.jenisStmt():this.match(16)?this.lihatStmt():this.match(13)?this.modelStmt():this.match(15)?this.modulStmt():void this.error(`Pernyataan tidak bisa diawali '${this.see().lexeme}'.`,!1)}error(e,t=!0){throw new i("Error Struktur => "+e+(t?` Menemukan '${this.see().lexeme}'.`:""),this.see().line)}}class Ae{constructor(e={keepMemory:!1}){this.lexer=new F,this.parser=new ye,this.interpreter=new O,this.keepMemory=!!e?.keepMemory&&e.keepMemory}runCode(i){this.keepMemory||this.interpreter.init();const a=i.split("\n");try{let e=this.lexer.scanTokens(i),t=this.parser.parse(e);return this.interpreter.interpret(t).join("\n")}catch(i){if(i instanceof e){const e=a[i.line-1];let s=(e?`ERROR! Pada baris ke-${i.line}\n>> `+e+"\n":"")+i.message;return i instanceof t&&(s+=(i.output?"\nOutput dari kode:\n":"")+i.output),s}return`[Pada baris ke-${this.interpreter.line}] Uh Oh, ini error sistem. Mohon laporkan agar diperbaiki. [ ${i} ]`}}}export{Ae as Simpl};
|
package/package.json
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bahasa-simpl",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Simpl: Indonesian Mini Programming Language interpreter",
|
|
5
|
-
"
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/simpl.d.ts",
|
|
8
|
+
"import": "./dist/simpl.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/simpl.js",
|
|
12
|
+
"module": "./dist/simpl.js",
|
|
13
|
+
"types": "./dist/simpl.js",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
6
17
|
"scripts": {
|
|
7
18
|
"build": "rollup -c"
|
|
8
19
|
},
|
|
@@ -19,7 +30,8 @@
|
|
|
19
30
|
},
|
|
20
31
|
"homepage": "https://github.com/faeiz-ff/simpl#readme",
|
|
21
32
|
"devDependencies": {
|
|
22
|
-
"rollup": "^4.
|
|
33
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
34
|
+
"rollup": "^4.55.1"
|
|
23
35
|
},
|
|
24
36
|
"dependencies": {
|
|
25
37
|
"bahasa-simpl": "^1.0.3"
|