bahasa-simpl 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,6 @@ Berikut fitur yang _sekarang_ sudah diimplementasikan:
16
16
  - **Semua** kata kunci berjumlah 5 huruf dan dalam bahasa Indonesia
17
17
 
18
18
  Fitur yang akan datang:
19
- - Website untuk menjalankan `simpl`
20
19
  - dokumentasi penuh
21
20
  - Pembersihan dan perapihan kode sumber :')
22
21
  - Pengecekan sebelum eksekusi (Analisa semantik)
@@ -114,7 +113,7 @@ Pengguna lain = Pengguna.baru("Hengker Anongnimus")
114
113
  cetak Pengguna.kepetik(admin)
115
114
  # "{ nama: zie, id: 0, status: online }"
116
115
 
117
- cetak Pengguna.kePetik(lain)
116
+ cetak lain.kePetik()
118
117
  # "{ nama: Hengker Anongnimus, id: 1, status: online }"
119
118
  ```
120
119
 
@@ -124,4 +123,4 @@ cetak Pengguna.kePetik(lain)
124
123
  - [https://ruslanspivak.com/lsbasi-part1/](https://ruslanspivak.com/lsbasi-part1/)
125
124
  - [https://craftinginterpreters.com/](https://craftinginterpreters.com/)
126
125
 
127
- (No AI was used while making this, the proof is apparent in the spaghetti codebase)
126
+
@@ -88,38 +88,38 @@ class Stipe extends Variable {
88
88
 
89
89
  }
90
90
 
91
+ function kePetik(v, thing) {
92
+ if (thing.type === logisSymbol) {
93
+ return thing.data ? "benar" : "salah";
94
+ } else if (thing.type === barisSymbol) {
95
+ return '[' + thing.data.reduce((str, val) => {
96
+ let item = kePetik(v, val);
97
+ return str + ", " + (val.type === Value.petikSymbol ? `"${item}"` : item);
98
+ }, "").slice(1) + ' ]';
99
+ } else if (thing.type === stipeSymbol) {
100
+ return `Model<${thing.symbol.description}>`;
101
+ } else if (thing.type === mesinSymbol) {
102
+ let underlying = thing.data.returnType?.description;
103
+ return `Mesin<${underlying ? underlying : 'datum'}>`;
104
+ } else if (thing.type === angkaSymbol) {
105
+ return thing.data.toString();
106
+ } else if (thing.type === petikSymbol) {
107
+ return '"' + thing.data + '"';
108
+ } else {
109
+ if (!thing?.type) return `nihil`;
110
+ let type = v.environment.get(thing.type.description);
111
+ if (type?.member.has("kePetik")) {
112
+ let res = v.callFunc(type.member.get("kePetik").data, [thing]).data;
113
+ return res;
114
+ }
115
+ return `${thing.type.description}<>`;
116
+ }
117
+ }
118
+
91
119
  class PetikTipe extends Stipe {
92
120
  constructor() {
93
- super(petikSymbol, new Callable(null, (v, args) => {
94
- const kePetik = (thing) => {
95
- if (thing.type === logisSymbol) {
96
- return thing.data ? "benar" : "salah";
97
- } else if (thing.type === barisSymbol) {
98
- return '[' + thing.data.reduce((str, val) => str + ", " + kePetik(val), "").slice(1) + ' ]';
99
- } else if (thing.type === stipeSymbol) {
100
- return `Model<${thing.symbol.description}>`;
101
- } else if (thing.type === mesinSymbol) {
102
- let underlying = thing.data.returnType?.description;
103
- return `Mesin<${underlying ? underlying : 'datum'}>`;
104
- } else if (thing.type === angkaSymbol) {
105
- return thing.data.toString();
106
- } else if (thing.type === petikSymbol) {
107
- return '"' + thing.data + '"';
108
- } else {
109
- if (!thing?.type) return `nihil`;
110
- let type = v.environment.get(thing.type.description);
111
- if (type?.member.has("kePetik")) {
112
- v.stack.push(v.line);
113
- let res = v.callFunc(type.member.get("kePetik").data, [thing]).data;
114
- v.stack.pop();
115
- return res;
116
- }
117
- return `${thing.type.description}<>`;
118
- }
119
- };
120
- return new Value(petikSymbol, kePetik(args[0]));
121
- }, [[null]], petikSymbol, true)
122
- );
121
+ super(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
122
+ [[null]], petikSymbol, true) );
123
123
  this.init();
124
124
  }
125
125
 
@@ -147,6 +147,9 @@ class PetikTipe extends Stipe {
147
147
  this.member.define("SERU_UNER",
148
148
  makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
149
149
 
150
+ this.member.define("kePetik",
151
+ makeBuiltInFunc([petikSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
152
+
150
153
  this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
151
154
  return new Value(barisSymbol, d.data.split(sep.data).map(val => new Value(petikSymbol, val)));
152
155
  }));
@@ -226,6 +229,9 @@ class AngkaTipe extends Stipe {
226
229
  this.member.define("MINUS_UNER",
227
230
  makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
228
231
 
232
+ this.member.define("kePetik",
233
+ makeBuiltInFunc([angkaSymbol], petikSymbol, (v, [a]) => new Value(petikSymbol, kePetik(v, a))));
234
+
229
235
  this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
230
236
  return new Value(angkaSymbol, Math.round(a.data));
231
237
  }));
@@ -241,7 +247,10 @@ class AngkaTipe extends Stipe {
241
247
  class LogisTipe extends Stipe {
242
248
  constructor() {
243
249
  super(logisSymbol, new Callable(null, (_, args) => {
244
- return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data.member.size));
250
+ if (args[0].type === barisSymbol && args[0].data.length === 0) {
251
+ return new Value(logisSymbol, false);
252
+ }
253
+ return new Value(logisSymbol, Boolean(args[0].data) || Boolean(args[0].data?.member?.size));
245
254
  }, [[null]], logisSymbol, true)
246
255
  );
247
256
  this.init();
@@ -258,6 +267,9 @@ class LogisTipe extends Stipe {
258
267
  makeBuiltInFunc([logisSymbol, logisSymbol], logisSymbol, (_, [r, l]) => new Value(logisSymbol, l.data || r.data)));
259
268
  this.member.define("SERU_UNER",
260
269
  makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
270
+
271
+ this.member.define("kePetik",
272
+ makeBuiltInFunc([logisSymbol], petikSymbol, (v, [l]) => new Value(petikSymbol, kePetik(v, l))));
261
273
  }
262
274
  }
263
275
 
@@ -268,6 +280,13 @@ class BarisTipe extends Stipe {
268
280
  }
269
281
 
270
282
  init() {
283
+ const valueToVariableDatum = (d) => {
284
+ let input = new Variable(d.type, false, d.data);
285
+ input.member = d.member;
286
+ input.isDatum = true;
287
+ return input;
288
+ };
289
+
271
290
  this.member.define("PLUS",
272
291
  makeBuiltInFunc([barisSymbol, barisSymbol], barisSymbol, (_, [r, l]) =>
273
292
  new Value(barisSymbol, Array(...l.data, ...r.data))
@@ -305,6 +324,9 @@ class BarisTipe extends Stipe {
305
324
  this.member.define("SERU_UNER",
306
325
  makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
307
326
 
327
+ this.member.define("kePetik",
328
+ makeBuiltInFunc([barisSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
329
+
308
330
  this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
309
331
  if (b.data.length <= i.data) {
310
332
  v.error(`Indeks tidak boleh lebih besar atau sama dengan ukuran baris, ${i.data} >= ${b.data.length}`);
@@ -317,12 +339,12 @@ class BarisTipe extends Stipe {
317
339
 
318
340
  this.member.define("potongan", makeBuiltInFunc([barisSymbol, angkaSymbol, angkaSymbol], barisSymbol, (v, [b, fr, to]) => {
319
341
  if (fr.data >= b.data.length || fr.data < 0 || to.data <= fr.data || to.data > b.data.length) {
320
- v.error(`Indeks tidak valid, ${fr.data}:${to.data}, dengan ukuran baris ${b.data.length}`);
342
+ v.error(`Indeks tidak valid, ${fr.data} sampai ${to.data}, dengan ukuran baris ${b.data.length}`);
321
343
  }
322
344
  return new Value(barisSymbol, b.data.slice(fr.data, to.data));
323
345
  }));
324
346
  this.member.define("tumpuk", makeBuiltInFunc([barisSymbol, null], null, (_, [b, d]) => {
325
- b.data.push(d);
347
+ b.data.push(valueToVariableDatum(d));
326
348
  return b;
327
349
  }));
328
350
  this.member.define("tumpah", makeBuiltInFunc([barisSymbol], null, (_, [b]) => {
@@ -333,14 +355,14 @@ class BarisTipe extends Stipe {
333
355
  if (idx.data > b.data.length) {
334
356
  v.error(`Indeks tidak valid, ${idx.data}, dengan ukuran baris ${b.data.length}`);
335
357
  }
336
- b.data.splice(idx.data, 0, d);
358
+ b.data.splice(idx.data, 0, valueToVariableDatum(d));
337
359
  return b;
338
360
  }));
339
361
  this.member.define("petakan", makeBuiltInFunc([barisSymbol, mesinSymbol], barisSymbol, (v, [b, m]) => {
340
362
  let newBaris = new Value(barisSymbol, []);
341
363
  for (let datum of b.data) {
342
364
  let result = v.callFunc(m.data, [datum]);
343
- newBaris.data.push(result);
365
+ newBaris.data.push(valueToVariableDatum(result));
344
366
  }
345
367
  return newBaris;
346
368
  }));
@@ -349,7 +371,7 @@ class BarisTipe extends Stipe {
349
371
  for (let datum of b.data) {
350
372
  let result = v.callFunc(m.data, [datum]);
351
373
  if (result.data === true) {
352
- newBaris.data.push(datum);
374
+ newBaris.data.push(valueToVariableDatum(datum));
353
375
  }
354
376
  }
355
377
  return newBaris;
@@ -361,13 +383,33 @@ class BarisTipe extends Stipe {
361
383
  }
362
384
  return d;
363
385
  }));
386
+
387
+ this.member.define("punya?", makeBuiltInFunc([barisSymbol, null], logisSymbol, (v, [b, d]) => {
388
+ let type = v.environment.get(d.type?.description);
389
+ if (!type)
390
+ v.error(`Tipe tidak ditemukan atau tidak valid`);
391
+ let equalFunc;
392
+ if (type.member?.has("SAMA_SAMA")) {
393
+ equalFunc = type.member.get("SAMA_SAMA");
394
+ } else {
395
+ v.error(`model ${d.type.description} tidak mempunyai mesin SAMA_SAMA di dalam modulnya.`);
396
+ }
397
+ for (let datum of b.data) {
398
+ if (datum.type !== d.type) continue;
399
+ let isEqual = v.callFunc(equalFunc.data, [datum, d]);
400
+ if (isEqual.data) return new Value(logisSymbol, true);
401
+ }
402
+ return new Value(logisSymbol, false);
403
+ }));
364
404
  }
365
405
  }
366
406
 
367
407
  class MesinTipe extends Stipe {
368
408
  constructor() {
369
409
  super(mesinSymbol);
370
- this.member.define("$", null);
410
+
411
+ this.member.define("kePetik",
412
+ makeBuiltInFunc([mesinSymbol], petikSymbol, (v, [m]) => new Value(petikSymbol, kePetik(v, m))));
371
413
  }
372
414
  }
373
415
 
@@ -411,6 +453,10 @@ let Jenis$1 = class Jenis extends Stipe {
411
453
  enums.forEach((thing, idx) => {
412
454
  this.member.define(thing.lexeme, new Value(sym, idx));
413
455
  });
456
+ this.member.define("kePetik", makeBuiltInFunc([sym], petikSymbol, (_, [j]) => {
457
+ let enumName = enums.map(thing=>thing.lexeme)[j.data];
458
+ return new Value(petikSymbol, `${name}.${enumName}`);
459
+ }));
414
460
  this.init(sym);
415
461
  }
416
462
 
@@ -444,7 +490,12 @@ function copier(thing) {
444
490
  case angkaSymbol: return new Value(angkaSymbol, thing.data);
445
491
  case logisSymbol: return new Value(logisSymbol, thing.data);
446
492
  case mesinSymbol: return new Value(mesinSymbol, thing.data);
447
- case barisSymbol: return new Value(barisSymbol, thing.data.map((val) => copier(val)));
493
+ case barisSymbol: return new Value(barisSymbol, thing.data.map((val) => {
494
+ let copy = copier(val);
495
+ let varCopy = new Variable(copy.type, false, copy.data);
496
+ varCopy.member = copy.member;
497
+ return varCopy
498
+ }));
448
499
  case stipeSymbol: return NIHIL;
449
500
  case modulSymbol: return NIHIL;
450
501
  default:
@@ -453,13 +504,17 @@ function copier(thing) {
453
504
  let valCopy = new Value(thing.type, null);
454
505
  let newMember = new Environment();
455
506
  for (let i of keys) {
456
- newMember.define(i, copier(thing.member.get(i)));
507
+ let varPrev = thing.member.get(i);
508
+ let tempCopy = copier(varPrev);
509
+ let varCopy = new Variable(varPrev.type, varPrev.tetap, tempCopy.data);
510
+ varCopy.member = tempCopy.member;
511
+ newMember.define(i, varCopy);
457
512
  }
458
513
  valCopy.member = newMember;
459
-
514
+ valCopy.data = thing.data;
460
515
  return valCopy;
461
516
  }
462
- return NIHIL;
517
+ return new Value(thing.type, thing.data);
463
518
  }
464
519
  }
465
520
 
@@ -922,8 +977,9 @@ class Interpreter {
922
977
  if (type.member?.has(name)) {
923
978
  if (willBeCalled) {
924
979
  this.objectStack = main;
980
+ return type.member.get(name);
925
981
  }
926
- return type.member.get(name);
982
+ this.error(`akses titik . dari objek ke model harus berupa panggilan/penggunaaan mesin.`);
927
983
  }
928
984
  this.error(`nama .${name} tidak ditemukan dalam tipe ${main.type.description}`);
929
985
  } else {
@@ -943,40 +999,7 @@ class Interpreter {
943
999
 
944
1000
  visitCetakStmt(cetakStmt) {
945
1001
  let result = cetakStmt.expr.accept(this);
946
- const kePetik = (thing) => {
947
- if (thing.type === logisSymbol) {
948
- return thing.data ? "benar" : "salah";
949
- } else if (thing.type === barisSymbol) {
950
- return '[' + thing.data.reduce((str, val) => {
951
- let item = kePetik(val);
952
- return str + ", " + (val.type === petikSymbol ? `"${item}"` : item);
953
- }, "").slice(1) + ' ]';
954
- } else if (thing.type === stipeSymbol) {
955
- return `Model<${thing.symbol.description}>`;
956
- } else if (thing.type === mesinSymbol) {
957
- let underlying = thing.data.returnType?.description;
958
- return `Mesin<${underlying ? underlying : 'datum'}>`;
959
- } else if (thing.type === angkaSymbol) {
960
- return thing.data.toString();
961
- } else if (thing.type === petikSymbol) {
962
- return thing.data;
963
- } else {
964
- if (!thing?.type) return `nihil`;
965
- let type = this.environment.get(thing.type.description);
966
- if (type?.member?.has("kePetik")) {
967
- let prevState = this.state;
968
- this.state = location.MESIN;
969
- this.stack.push(this.line);
970
- let res = this.callFunc(type.member.get("kePetik").data, [thing]).data;
971
- this.stack.pop();
972
- this.state = prevState;
973
- return res;
974
- }
975
- return `${thing.type.description}<>`;
976
- }
977
- };
978
-
979
- this.output.push(kePetik(result));
1002
+ this.output.push(kePetik(this, result));
980
1003
 
981
1004
  }
982
1005
 
@@ -1008,6 +1031,9 @@ class Interpreter {
1008
1031
 
1009
1032
  visitRubahStmt(rubahStmt) {
1010
1033
  let variable = rubahStmt.variable.accept(this); // is a reference to the variable data
1034
+ if (variable.tetap === undefined) {
1035
+ this.error(`Pe-rubah-an hanya dapat dilakukan kepada Variabel!`);
1036
+ }
1011
1037
  if (variable.tetap) {
1012
1038
  this.error(`Variabel tetap tidak dapat di-rubah.`);
1013
1039
  }
@@ -2295,6 +2321,7 @@ class Simpl {
2295
2321
  let output = this.interpreter.interpret(pohon);
2296
2322
  return output.join("\n");
2297
2323
  } catch (err) {
2324
+ // throw err
2298
2325
  if (err instanceof SimplError) {
2299
2326
  const errorCode = textLines[err.line - 1];
2300
2327
  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.6",
3
+ "version": "1.0.8",
4
4
  "description": "Simpl: Indonesian Mini Programming Language interpreter",
5
5
  "main": "./dist/simpl-interpreter.js",
6
6
  "scripts": {