bahasa-simpl 1.0.12 → 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.
@@ -0,0 +1,8 @@
1
+ declare module "simpl-interpreter" {
2
+ export class Simpl {
3
+ constructor(opts: {
4
+ keepMemory?: boolean,
5
+ });
6
+ runCode(code: string): string;
7
+ }
8
+ }
@@ -84,7 +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 Value(mesinSymbol, data));
87
+ this.member.define("buat", new Variable(mesinSymbol, true, data));
88
88
  }
89
89
 
90
90
  }
@@ -93,9 +93,9 @@ function kePetik(v, thing) {
93
93
  if (thing.type === logisSymbol) {
94
94
  return thing.data ? "benar" : "salah";
95
95
  } else if (thing.type === barisSymbol) {
96
- 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) + ' ]';
97
97
  } else if (thing.type === stipeSymbol) {
98
- return `Model<${thing.symbol.description}>`;
98
+ return `Model<${thing.symbol?.description ? thing.symbol.description : ""}>`;
99
99
  } else if (thing.type === mesinSymbol) {
100
100
  let underlying = thing.data.returnType?.description;
101
101
  return `Mesin<${underlying ? underlying : 'datum'}>`;
@@ -113,304 +113,6 @@ function kePetik(v, thing) {
113
113
  return `${thing.type.description}<>`;
114
114
  }
115
115
  }
116
-
117
- class PetikTipe extends Stipe {
118
- constructor() {
119
- super(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
120
- [[null]], petikSymbol, true));
121
- this.init();
122
- }
123
-
124
- init() {
125
- // BINARY / UNARY OPERATORS
126
- this.member.define("PLUS",
127
- makeBuiltInFunc([petikSymbol, petikSymbol], petikSymbol, (_, [r, l]) => new Value(petikSymbol, l.data + r.data)));
128
- this.member.define("LEBIH",
129
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
130
- this.member.define("KURANG",
131
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
132
- this.member.define("SAMA_SAMA",
133
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
134
- this.member.define("LEBIH_SAMA",
135
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
136
- this.member.define("KURANG_SAMA",
137
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
138
- this.member.define("SERU_SAMA",
139
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
140
- this.member.define("AMPERSAN",
141
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
142
- this.member.define("PIPA",
143
- makeBuiltInFunc([petikSymbol, petikSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
144
-
145
- this.member.define("SERU_UNER",
146
- makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
147
-
148
- this.member.define("kePetik",
149
- makeBuiltInFunc([petikSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
150
-
151
- this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
152
- return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
153
- }));
154
- this.member.define("bersih", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [d]) => {
155
- return new Value(petikSymbol, d.data.trim())
156
- }));
157
- this.member.define("ganti", makeBuiltInFunc([petikSymbol, petikSymbol, petikSymbol], petikSymbol,
158
- (_, [d, what, rep]) => new Value(petikSymbol, d.data.replaceAll(what.data, rep.data))
159
- ));
160
- this.member.define("besar", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
161
- return new Value(petikSymbol, p.data.toUpperCase())
162
- }));
163
- this.member.define("kecil", makeBuiltInFunc([petikSymbol], petikSymbol, (_, [p]) => {
164
- return new Value(petikSymbol, p.data.toLowerCase())
165
- }));
166
- }
167
- }
168
-
169
- class AngkaTipe extends Stipe {
170
- constructor() {
171
- super(angkaSymbol, new Callable(null, (v, args) => {
172
- if (typeof args[0].data === "number") {
173
- return new Value(angkaSymbol, args[0].data);
174
- }
175
-
176
- switch (args[0].type) {
177
- case petikSymbol:
178
- if (isNaN(Number(args[0].data))) {
179
- v.error("Nilai dari petik bukanlah sebuah angka, konversi gagal.");
180
- }
181
- return new Value(angkaSymbol, Number(args[0].data));
182
- case angkaSymbol:
183
- return new Value(angkaSymbol, args[0].data);
184
- case logisSymbol:
185
- return new Value(angkaSymbol, Number(args[0].data));
186
- default:
187
- v.error(`Tipe yang dapat diterima hanyalah petik, angka, logis, dan jenis. Mendapatkan ${args[0].type.description}.`);
188
- return;
189
- }
190
- }, [[null]], angkaSymbol, true)
191
- );
192
- this.init();
193
- }
194
-
195
- init() {
196
- this.member.define("PLUS",
197
- makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data + r.data)));
198
- this.member.define("MINUS",
199
- makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data - r.data)));
200
- this.member.define("BINTANG",
201
- makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data * r.data)));
202
- this.member.define("GARIS_MIRING",
203
- makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data / r.data)));
204
- this.member.define("MODULUS",
205
- makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [r, l]) => new Value(angkaSymbol, l.data % r.data)));
206
-
207
- this.member.define("LEBIH",
208
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data > r.data)));
209
- this.member.define("KURANG",
210
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data < r.data)));
211
- this.member.define("SAMA_SAMA",
212
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
213
- this.member.define("LEBIH_SAMA",
214
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data >= r.data)));
215
- this.member.define("KURANG_SAMA",
216
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data <= r.data)));
217
- this.member.define("SERU_SAMA",
218
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
219
- this.member.define("AMPERSAN",
220
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
221
- this.member.define("PIPA",
222
- makeBuiltInFunc([angkaSymbol, angkaSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
223
- this.member.define("SERU_UNER",
224
- makeBuiltInFunc([angkaSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
225
- this.member.define("PLUS_UNER",
226
- makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, +r.data)));
227
- this.member.define("MINUS_UNER",
228
- makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
229
-
230
- this.member.define("kePetik",
231
- makeBuiltInFunc([angkaSymbol], petikSymbol, (v, [a]) => new Value(petikSymbol, kePetik(v, a))));
232
-
233
- this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
234
- return new Value(angkaSymbol, Math.round(a.data));
235
- }));
236
- this.member.define("bulatAtas", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
237
- return new Value(angkaSymbol, Math.ceil(a.data))
238
- }));
239
- this.member.define("bulatBawah", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
240
- return new Value(angkaSymbol, Math.floor(a.data))
241
- }));
242
- }
243
- }
244
-
245
- class LogisTipe extends Stipe {
246
- constructor() {
247
- super(logisSymbol, new Callable(null, (_, args) => {
248
- if (args[0].type === barisSymbol && args[0].data.length === 0) {
249
- return new Value(logisSymbol, false);
250
- }
251
- return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data?.member?.size));
252
- }, [[null]], logisSymbol, true)
253
- );
254
- this.init();
255
- }
256
-
257
- init() {
258
- this.member.define("SAMA_SAMA",
259
- makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
260
- this.member.define("SERU_SAMA",
261
- makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data !== r.data)));
262
- this.member.define("AMPERSAN",
263
- makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
264
- this.member.define("PIPA",
265
- makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
266
- this.member.define("SERU_UNER",
267
- makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
268
-
269
- this.member.define("kePetik",
270
- makeBuiltInFunc([logisSymbol], petikSymbol, (v, [l]) => new Value(petikSymbol, kePetik(v, l))));
271
- }
272
- }
273
-
274
- class BarisTipe extends Stipe {
275
- constructor() {
276
- super(barisSymbol);
277
- this.init();
278
- }
279
-
280
- init() {
281
- const valueToVariableDatum = (d) => {
282
- let input = new Variable(d.type, false, d.data);
283
- input.member = d.member;
284
- input.isDatum = true;
285
- return input;
286
- };
287
-
288
- this.member.define("PLUS",
289
- makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
290
- new Value(barisSymbol, Array(...l.data, ...r.data))
291
- ));
292
-
293
- this.member.define("MINUS_UNER",
294
- makeBuiltInFunc([barisSymbol], barisSymbol, (_, [r]) =>
295
- new Value(barisSymbol, r.data.slice(0, r.length))
296
- ));
297
-
298
- this.member.define("SAMA_SAMA",
299
- makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
300
- if (a.length !== b.length) return false;
301
- for (let i = 0; i < a.length; i++) {
302
- if (a[i].data !== b[i].data) return false;
303
- }
304
- return true;
305
- })(l.data, r.data)))
306
- );
307
-
308
- this.member.define("SERU_SAMA",
309
- makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, ((a, b) => {
310
- if (a.length !== b.length) return true;
311
- for (let i = 0; i < a.length; i++) {
312
- if (a[i].data !== b[i].data) return true;
313
- }
314
- return false;
315
- })(l.data, r.data)))
316
- );
317
-
318
- this.member.define("AMPERSAN",
319
- makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data && r.data)));
320
- this.member.define("PIPA",
321
- makeBuiltInFunc([barisSymbol, barisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
322
- this.member.define("SERU_UNER",
323
- makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
324
-
325
- this.member.define("kePetik",
326
- makeBuiltInFunc([barisSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
327
-
328
- this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
329
- if (b.data.length <= i.data) {
330
- v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
331
- }
332
-
333
- while (i.data < 0) i.data += b.data.length;
334
- b.data = b.data.filter((_, idx) => idx !== i.data);
335
- return b;
336
- }));
337
-
338
- this.member.define("potongan", makeBuiltInFunc([barisSymbol, angkaSymbol, angkaSymbol], barisSymbol, (v, [b, fr, to]) => {
339
- if (fr.data >= b.data.length || fr.data < 0 || to.data <= fr.data || to.data > b.data.length) {
340
- v.error(`Indeks tidak valid, ${fr.data} sampai ${to.data}, dengan ukuran baris ${b.data.length}`);
341
- }
342
- return new Value(barisSymbol, b.data.slice(fr.data, to.data));
343
- }));
344
- this.member.define("tumpuk", makeBuiltInFunc([barisSymbol, null], null, (_, [b, d]) => {
345
- b.data.push(valueToVariableDatum(d));
346
- return b;
347
- }));
348
- this.member.define("tumpah", makeBuiltInFunc([barisSymbol], null, (_, [b]) => {
349
- b.data.pop();
350
- return b;
351
- }));
352
- this.member.define("masuk", makeBuiltInFunc([barisSymbol, null, angkaSymbol], null, (v, [b, d, idx]) => {
353
- if (idx.data > b.data.length) {
354
- v.error(`Indeks tidak valid, ${idx.data}, dengan ukuran baris ${b.data.length}`);
355
- }
356
- b.data.splice(idx.data, 0, valueToVariableDatum(d));
357
- return b;
358
- }));
359
- this.member.define("petakan", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
360
- let newBaris = new Value(barisSymbol, []);
361
- for (let datum of b.data) {
362
- let result = v.callFunc(m.data, [datum]);
363
- newBaris.data.push(valueToVariableDatum(result));
364
- }
365
- return newBaris;
366
- }));
367
- this.member.define("saring", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
368
- let newBaris = new Value(barisSymbol, []);
369
- for (let datum of b.data) {
370
- let result = v.callFunc(m.data, [datum]);
371
- if (result.data === true) {
372
- newBaris.data.push(valueToVariableDatum(datum));
373
- }
374
- }
375
- return newBaris;
376
- }));
377
- this.member.define("reduksi", makeBuiltInFunc([barisSymbol, mesinSymbol, null], null, (v, [b, m, d]) => {
378
- for (let datum of b.data) {
379
- let result = v.callFunc(m.data, [d, datum]);
380
- d = result;
381
- }
382
- return d;
383
- }));
384
-
385
- this.member.define("punya?", makeBuiltInFunc([barisSymbol, null], logisSymbol, (v, [b, d]) => {
386
- let type = v.environment.get(d.type?.description);
387
- if (!type)
388
- v.error(`Tipe tidak ditemukan atau tidak valid`);
389
- let equalFunc;
390
- if (type.member?.has("SAMA_SAMA")) {
391
- equalFunc = type.member.get("SAMA_SAMA");
392
- } else {
393
- v.error(`model ${d.type.description} tidak mempunyai mesin SAMA_SAMA di dalam modulnya.`);
394
- }
395
- for (let datum of b.data) {
396
- if (datum.type !== d.type) continue;
397
- let isEqual = v.callFunc(equalFunc.data, [datum, d]);
398
- if (isEqual.data) return new Value(logisSymbol, true);
399
- }
400
- return new Value(logisSymbol, false);
401
- }));
402
- }
403
- }
404
-
405
- class MesinTipe extends Stipe {
406
- constructor() {
407
- super(mesinSymbol);
408
-
409
- this.member.define("kePetik",
410
- makeBuiltInFunc([mesinSymbol], petikSymbol, (v, [m]) => new Value(petikSymbol, kePetik(v, m))));
411
- }
412
- }
413
-
414
116
  let Model$1 = class Model extends Stipe {
415
117
  constructor(name, params) {
416
118
  let sym = Symbol(name);
@@ -454,10 +156,7 @@ let Jenis$1 = class Jenis extends Stipe {
454
156
  this.member.define("kePetik", makeBuiltInFunc([sym], petikSymbol, (_, [j]) => {
455
157
  return new Value(petikSymbol, `${name}<${j.data}>`);
456
158
  }));
457
- this.init(sym);
458
- }
459
159
 
460
- init(sym) {
461
160
  this.member.define("SAMA_SAMA",
462
161
  makeBuiltInFunc([sym, sym], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data === r.data)));
463
162
  this.member.define("SERU_SAMA",
@@ -516,13 +215,302 @@ function copier(thing) {
516
215
  }
517
216
 
518
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
+
519
507
  const GLOBAL_ENV = (() => {
520
508
  let env = new Environment();
521
- env.define("petik", new PetikTipe());
522
- env.define("angka", new AngkaTipe());
523
- env.define("logis", new LogisTipe());
524
- env.define("baris", new BarisTipe());
525
- env.define("mesin", new MesinTipe());
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);
526
514
 
527
515
  env.define("jarak", makeBuiltInFunc([angkaSymbol, angkaSymbol], barisSymbol,
528
516
  (_, [from, to]) => new Value(barisSymbol,
@@ -717,23 +705,26 @@ let Hasil$1 = class Hasil {
717
705
  }
718
706
  };
719
707
 
720
- const location = {
721
- GLOBAL: 1,
722
- SLAGI: 2,
723
- UNTUK: 3,
724
- MESIN: 4,
725
- LIHAT: 5,
726
- };
727
- const MAX_STACK_SIZE = 500;
728
-
729
708
  // Implements all Expressions and Statements Visitor
730
709
  class Interpreter {
731
710
  constructor() {
732
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() {
733
724
  this.line = 0;
734
725
  this.environment = new Environment(this.globalEnvironment);
735
726
  this.tree = null;
736
- this.state = location.GLOBAL;
727
+ this.state = this.location.GLOBAL;
737
728
  this.stack = [];
738
729
  this.output = [];
739
730
  this.objectStack = null;
@@ -741,6 +732,14 @@ class Interpreter {
741
732
  this.pipeStack = [];
742
733
  }
743
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
+
744
743
  // EXPRESSION VISITORS
745
744
 
746
745
  visitLiteralExpr(literalExpr) {
@@ -762,7 +761,7 @@ class Interpreter {
762
761
  let value = new Value(barisSymbol, []);
763
762
 
764
763
  for (let expr of arrayExpr.contents) {
765
- let v = this.validValue(expr.accept(this));
764
+ let v = expr.accept(this);
766
765
  let newVar = new Variable(v.type, false, v.data);
767
766
  newVar.member = v.member;
768
767
  newVar.isDatum = true;
@@ -830,7 +829,7 @@ class Interpreter {
830
829
  this.error(`Hanya bisa 'memanggil' mesin atau model, malah menemukan ${callable.type.description}. `);
831
830
  }
832
831
 
833
- if (!callable.data?.block) {
832
+ if (!callable?.data?.block) {
834
833
  this.error(`Mesin tidak terdefinisi, tidak bisa dipanggil.`);
835
834
  }
836
835
 
@@ -841,7 +840,7 @@ class Interpreter {
841
840
  this.objectStack = null;
842
841
  }
843
842
 
844
- args = [...args, ...callExpr.args.map(val => this.validValue(val.accept(this)))];
843
+ args = [...args, ...callExpr.args.map(val => val.accept(this))];
845
844
 
846
845
  let result = this.callFunc(callable.data, args);
847
846
  return result;
@@ -851,13 +850,16 @@ class Interpreter {
851
850
  // args.forEach((val,idx)=>{
852
851
  // console.log(idx, val);
853
852
  // });
853
+ if (!callable) {
854
+ this.error(`Mesin tidak terdefinisi, tidak bisa dipanggil.`);
855
+ }
854
856
  this.stack.push(this.line);
855
- if (this.stack.length > MAX_STACK_SIZE)
856
- 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}`);
857
859
 
858
860
  let prevState = this.state;
859
861
  this.line = this.stack[this.stack.length - 1];
860
- this.state = location.MESIN;
862
+ this.state = this.location.MESIN;
861
863
 
862
864
  if (args.length !== callable.parameters.length) {
863
865
  this.error(`Jumlah argumen tidak sama dengan parameter mesin. Menemukan ${args.length}, harusnya ${callable.parameters.length}.`);
@@ -918,8 +920,8 @@ class Interpreter {
918
920
 
919
921
 
920
922
  visitBinaryExpr(binaryExpr) {
921
- let leftValue = this.validValue(binaryExpr.left.accept(this));
922
- let rightValue = this.validValue(binaryExpr.right.accept(this));
923
+ let leftValue = binaryExpr.left.accept(this);
924
+ let rightValue = binaryExpr.right.accept(this);
923
925
 
924
926
  this.line = binaryExpr.op.line;
925
927
 
@@ -936,7 +938,7 @@ class Interpreter {
936
938
  }
937
939
 
938
940
  visitUnaryExpr(unaryExpr) {
939
- let rightValue = this.validValue(unaryExpr.right.accept(this));
941
+ let rightValue = unaryExpr.right.accept(this);
940
942
 
941
943
  this.line = unaryExpr.op.line;
942
944
 
@@ -967,7 +969,7 @@ class Interpreter {
967
969
  }
968
970
 
969
971
  visitGroupingExpr(groupingExpr) {
970
- return this.validValue(groupingExpr.expr.accept(this));
972
+ return groupingExpr.expr.accept(this);
971
973
  }
972
974
 
973
975
  visitIdentifierExpr(identifierExpr) {
@@ -1010,11 +1012,11 @@ class Interpreter {
1010
1012
  }
1011
1013
 
1012
1014
  visitPipeLineExpr (pipeLineExpr) {
1013
- let expr = this.validValue(pipeLineExpr.expr.accept(this));
1015
+ let expr = pipeLineExpr.expr.accept(this);
1014
1016
 
1015
1017
  this.pipeStack.push(expr);
1016
1018
 
1017
- let pipeValue = this.validValue(pipeLineExpr.pipeTo.accept(this));
1019
+ let pipeValue = pipeLineExpr.pipeTo.accept(this);
1018
1020
 
1019
1021
  this.pipeStack.pop();
1020
1022
 
@@ -1027,7 +1029,8 @@ class Interpreter {
1027
1029
  visitTypeStmt(typeStmt) {
1028
1030
  if (typeStmt.type === null) return null;
1029
1031
  let type = typeStmt.type.accept(this);
1030
- if (type.type !== stipeSymbol) this.error(`'${type.type.description}' bukan sebuah Model/Tipe Valid.`);
1032
+ if (type.type !== stipeSymbol || !(type.symbol))
1033
+ this.error(`'${type.type.description}' bukan sebuah Model/Tipe Valid.`);
1031
1034
  return type.symbol;
1032
1035
  }
1033
1036
 
@@ -1048,7 +1051,7 @@ class Interpreter {
1048
1051
 
1049
1052
  let variable = new Variable(type, datumStmt.type.tetap);
1050
1053
 
1051
- let value = this.validValue(datumStmt.expr.accept(this));
1054
+ let value = datumStmt.expr.accept(this);
1052
1055
 
1053
1056
  if (value.data === null) value.type = variable.type; // if nihil, ok
1054
1057
 
@@ -1071,7 +1074,7 @@ class Interpreter {
1071
1074
  if (variable.tetap) {
1072
1075
  this.error(`Variabel tetap tidak dapat di-rubah.`);
1073
1076
  }
1074
- let value = this.validValue(rubahStmt.value.accept(this));
1077
+ let value = rubahStmt.value.accept(this);
1075
1078
  if (value.data === null) value.type = variable.type; // if nihil, ok
1076
1079
 
1077
1080
  if (variable.isDatum)
@@ -1110,20 +1113,20 @@ class Interpreter {
1110
1113
  }
1111
1114
 
1112
1115
  visitHentiStmt() {
1113
- if (this.state === location.UNTUK || this.state === location.SLAGI)
1116
+ if (this.state === this.location.UNTUK || this.state === this.location.SLAGI)
1114
1117
  throw new Henti$1(); // throws exception to escape from deep recursion
1115
1118
  else this.error("Tidak ada pengulangan untuk dihentikan.");
1116
1119
  }
1117
1120
 
1118
1121
 
1119
1122
  visitLewatStmt() {
1120
- if (this.state === location.UNTUK || this.state === location.SLAGI)
1123
+ if (this.state === this.location.UNTUK || this.state === this.location.SLAGI)
1121
1124
  throw new Lewat$1(); // throws exception to escape from deep recursion
1122
1125
  else this.error("Tidak ada pengulangan untuk dilewatkan.");
1123
1126
  }
1124
1127
 
1125
1128
  visitJatuhStmt() {
1126
- if (this.state === location.LIHAT)
1129
+ if (this.state === this.location.LIHAT)
1127
1130
  throw new Jatuh$1();
1128
1131
  else this.error("Tidak bisa jatuh di luar blok kasus.");
1129
1132
  }
@@ -1147,9 +1150,9 @@ class Interpreter {
1147
1150
  this.environment = new Environment(lastEnv);
1148
1151
  try {
1149
1152
  for (let stmt of slagiStmt.block.statements) {
1150
- this.state = location.SLAGI;
1153
+ this.state = this.location.SLAGI;
1151
1154
  stmt.accept(this);
1152
- this.state = location.SLAGI;
1155
+ this.state = this.location.SLAGI;
1153
1156
  }
1154
1157
  } catch (err) {
1155
1158
  if (err instanceof Henti$1) {
@@ -1160,15 +1163,15 @@ class Interpreter {
1160
1163
  }
1161
1164
  }
1162
1165
  this.environment = lastEnv;
1163
- if (this.stackNum !== 0) this.state = location.MESIN;
1164
- else this.state = location.GLOBAL;
1166
+ if (this.stackNum !== 0) this.state = this.location.MESIN;
1167
+ else this.state = this.location.GLOBAL;
1165
1168
  }
1166
1169
 
1167
1170
  visitUntukStmt(untukStmt) {
1168
1171
  let name = this.validName(untukStmt.varName.lexeme, false);
1169
1172
  let type = untukStmt.varType.accept(this);
1170
1173
 
1171
- let iter = this.validValue(untukStmt.iterable.accept(this));
1174
+ let iter = untukStmt.iterable.accept(this);
1172
1175
  if (iter.type === petikSymbol) {
1173
1176
  iter = new Value(barisSymbol, iter.data.split("").map(str => new Value(petikSymbol, str)));
1174
1177
  }
@@ -1189,9 +1192,9 @@ class Interpreter {
1189
1192
  try {
1190
1193
  // didn't 'accept' the block, just uses it directly
1191
1194
  for (let stmt of untukStmt.block.statements) {
1192
- this.state = location.UNTUK;
1195
+ this.state = this.location.UNTUK;
1193
1196
  stmt.accept(this);
1194
- this.state = location.UNTUK;
1197
+ this.state = this.location.UNTUK;
1195
1198
  }
1196
1199
  } catch (err) {
1197
1200
  this.environment = untukEnv.enclosing;
@@ -1205,8 +1208,8 @@ class Interpreter {
1205
1208
  }
1206
1209
  this.environment = untukEnv.enclosing;
1207
1210
  }
1208
- if (this.stackNum !== 0) this.state = location.MESIN;
1209
- else this.state = location.GLOBAL;
1211
+ if (this.stackNum !== 0) this.state = this.location.MESIN;
1212
+ else this.state = this.location.GLOBAL;
1210
1213
  }
1211
1214
 
1212
1215
  visitJenisStmt(jenisStmt) {
@@ -1216,7 +1219,7 @@ class Interpreter {
1216
1219
  }
1217
1220
 
1218
1221
  visitLihatStmt(lihatStmt) {
1219
- let match = this.validValue(lihatStmt.expr.accept(this));
1222
+ let match = lihatStmt.expr.accept(this);
1220
1223
  let matchType = this.environment.get(match?.type?.description);
1221
1224
  if (!matchType?.member?.has("SAMA_SAMA")) {
1222
1225
  this.error(`tipe ${matchType ? match.type.description : "nihil"} tidak mempunyai mesin SAMA_SAMA.`);
@@ -1226,9 +1229,9 @@ class Interpreter {
1226
1229
  const handleBlock = (index) => {
1227
1230
  while (index < lihatStmt.cases.length) {
1228
1231
  try {
1229
- this.state = location.LIHAT;
1232
+ this.state = this.location.LIHAT;
1230
1233
  lihatStmt.cases[index][1].accept(this);
1231
- this.state = location.LIHAT;
1234
+ this.state = this.location.LIHAT;
1232
1235
  } catch (err) {
1233
1236
  if (err instanceof Jatuh$1) {
1234
1237
  index++; continue;
@@ -1236,8 +1239,8 @@ class Interpreter {
1236
1239
  }
1237
1240
  break;
1238
1241
  }
1239
- if (this.stackNum !== 0) this.state = location.MESIN;
1240
- else this.state = location.GLOBAL;
1242
+ if (this.stackNum !== 0) this.state = this.location.MESIN;
1243
+ else this.state = this.location.GLOBAL;
1241
1244
  };
1242
1245
 
1243
1246
  for (let i = 0; i < lihatStmt.cases.length; i++) {
@@ -1271,7 +1274,7 @@ class Interpreter {
1271
1274
  if (variable.type !== stipeSymbol) {
1272
1275
  this.error(`Modul hanya bisa _ditambahkan_ pada tipe. '${name}' bukan merupakan tipe.`);
1273
1276
  }
1274
- if (variable.member.memory.size > 0) {
1277
+ if (variable.member.memory.size > 1) {
1275
1278
  this.error(`Tipe '${name}' sudah memiliki modul sendiri, tidak bisa definisi ulang.`);
1276
1279
  }
1277
1280
  } else {
@@ -1295,6 +1298,7 @@ class Interpreter {
1295
1298
 
1296
1299
  typeCheck(a, b, message) {
1297
1300
  if (a.type !== b.type) {
1301
+ console.log(a, b);
1298
1302
  this.error(`Tipe data tidak sama: ${a.type.description} != ${b.type.description}. ` + message);
1299
1303
  }
1300
1304
  }
@@ -1306,11 +1310,6 @@ class Interpreter {
1306
1310
  return false;
1307
1311
  }
1308
1312
 
1309
- validValue(v) {
1310
- if (v.type !== stipeSymbol) return v;
1311
- this.error("stipe tidak dapat menjadi nilai.");
1312
- }
1313
-
1314
1313
  validName(n, checkExisted = true) {
1315
1314
  if (RESERVED_NAMES.some(v => v === n)) {
1316
1315
  this.error(`Nama sistem (${n}) tidak boleh didefinisi ulang.`);
@@ -1324,13 +1323,7 @@ class Interpreter {
1324
1323
  throw new SimplErrorEksekusi(`Error Eksekusi => ${message}`, this.line, this.output.join('\n'));
1325
1324
  }
1326
1325
 
1327
- interpret(tree) {
1328
- this.line = 0;
1329
- this.output = [];
1330
- this.tree = tree;
1331
- tree.accept(this);
1332
- return this.output;
1333
- }
1326
+
1334
1327
  }
1335
1328
 
1336
1329
  class Token {
@@ -1360,6 +1353,23 @@ class Lexer {
1360
1353
  this.errors = [];
1361
1354
  }
1362
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
+
1363
1373
  isAtEnd() {
1364
1374
  return this.charIndex >= this.text.length;
1365
1375
  }
@@ -1402,23 +1412,6 @@ class Lexer {
1402
1412
  return this.text.slice(this.charStart, this.charIndex);
1403
1413
  }
1404
1414
 
1405
- scanTokens(text) {
1406
- this.init();
1407
- this.text = text;
1408
- let tokens = [];
1409
-
1410
- while (!this.isAtEnd()) {
1411
- let token = this.scan();
1412
- this.charStart = this.charIndex;
1413
- if (token) tokens.push(token);
1414
- }
1415
-
1416
- tokens.push(new Token(EOF, "Akhir dokumen", null, this.lineIndex));
1417
-
1418
- this.tokens = tokens;
1419
- return this.tokens;
1420
- }
1421
-
1422
1415
  id() {
1423
1416
  while (!this.isAtEnd() && this.isAlphaNumeric(this.see())) this.advance();
1424
1417
 
@@ -1968,6 +1961,17 @@ class Parser {
1968
1961
  this.tree = null;
1969
1962
  }
1970
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
+
1971
1975
  see() {
1972
1976
  return this.tokens[this.tokenIndex];
1973
1977
  }
@@ -2446,28 +2450,23 @@ class Parser {
2446
2450
  throw new SimplErrorStruktur(`Error Struktur => ` + errmsg + ((found) ? ` Menemukan '${this.see().lexeme}'.` : ""), this.see().line);
2447
2451
  }
2448
2452
 
2449
- parse(tokens) {
2450
- this.init();
2451
- this.tokens = tokens;
2452
- let treeList = [];
2453
- while (!this.match(EOF)) {
2454
- treeList.push(this.statement());
2455
- }
2456
- this.tree = new Simpl$1(treeList);
2457
- return this.tree;
2458
- }
2459
2453
  }
2460
2454
 
2461
2455
  // Simpl: Indonesian Mini Programming Language !!
2462
2456
 
2463
2457
  class Simpl {
2464
- constructor() {
2458
+ constructor(opts = {
2459
+ keepMemory: false
2460
+ }) {
2465
2461
  this.lexer = new Lexer();
2466
2462
  this.parser = new Parser();
2467
2463
  this.interpreter = new Interpreter();
2464
+ this.keepMemory = opts?.keepMemory ? opts.keepMemory : false;
2468
2465
  }
2469
2466
 
2470
2467
  runCode(text) {
2468
+ if (!this.keepMemory) this.interpreter.init();
2469
+
2471
2470
  // console.log(text.split("\n").reduce((codeStr, line, idx) => codeStr + `${idx + 1}.\t${line}\n`, ''));
2472
2471
  const textLines = text.split("\n");
2473
2472
  try {
@@ -2476,7 +2475,6 @@ class Simpl {
2476
2475
  let output = this.interpreter.interpret(pohon);
2477
2476
  return output.join("\n");
2478
2477
  } catch (err) {
2479
- // throw err
2480
2478
  if (err instanceof SimplError) {
2481
2479
  const errorCode = textLines[err.line - 1];
2482
2480
  let errorText = (errorCode ? `ERROR! Pada baris ke-${err.line}\n>> ` + errorCode + '\n' : "") + err.message;
@@ -2490,10 +2488,6 @@ class Simpl {
2490
2488
  }
2491
2489
 
2492
2490
  }
2493
- }
2494
-
2495
- function run(code) {
2496
- return new Simpl().runCode(code);
2497
2491
  }
2498
2492
 
2499
- export { run as default };
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.12",
3
+ "version": "1.0.13",
4
4
  "description": "Simpl: Indonesian Mini Programming Language interpreter",
5
- "main": "./dist/simpl-interpreter.js",
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.53.3"
33
+ "@rollup/plugin-terser": "^0.4.4",
34
+ "rollup": "^4.55.1"
23
35
  },
24
36
  "dependencies": {
25
37
  "bahasa-simpl": "^1.0.3"
package/rollup.config.js DELETED
@@ -1,8 +0,0 @@
1
- export default {
2
- input: "src/simpl.js",
3
- output: {
4
- file: "dist/simpl-interpreter.js",
5
- format: "es",
6
- name: "Simpl",
7
- },
8
- };