bahasa-simpl 1.0.5 → 1.0.6

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