bahasa-simpl 1.0.12 → 1.0.14

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 "bahasa-simpl" {
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 };
package/package.json CHANGED
@@ -1,8 +1,19 @@
1
1
  {
2
2
  "name": "bahasa-simpl",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
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.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
6
17
  "scripts": {
7
18
  "build": "rollup -c"
8
19
  },
@@ -19,7 +30,7 @@
19
30
  },
20
31
  "homepage": "https://github.com/faeiz-ff/simpl#readme",
21
32
  "devDependencies": {
22
- "rollup": "^4.53.3"
33
+ "rollup": "^4.55.1"
23
34
  },
24
35
  "dependencies": {
25
36
  "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
- };