bahasa-simpl 1.0.5 → 1.0.7

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