Metadata-Version: 2.4
Name: idscript
Version: 0.1.7
Summary: IDScript adalah bahasa pemrograman berbahasa Indonesia penerus Indonesian Script (IS), dengan interpreter dan compiler VM resmi.
Home-page: https://github.com/Elang-elang/IDScript
Author: Elang MRJ
Author-email: elangmuhamad888@gmail.com
License: MIT
Project-URL: Indonesian Script (IS), https://github.com/Elang-elang/indonesian_script
Project-URL: Source, https://github.com/Elang-elang/IDScript
Project-URL: Display Icon, https://raw.githubusercontent.com/Elang-elang/IDScript/main/icons/big.jpg
Project-URL: Small Icon, https://raw.githubusercontent.com/Elang-elang/IDScript/main/icons/small.jpg
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: click>=8.0
Requires-Dist: lark>=1.0
Requires-Dist: typeguard>=4.0
Requires-Dist: prompt_toolkit>=3.0
Requires-Dist: Pygments>=2.0
Provides-Extra: dev
Requires-Dist: mypy; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Provides-Extra: all
Requires-Dist: click; extra == "all"
Requires-Dist: lark; extra == "all"
Requires-Dist: typeguard; extra == "all"
Requires-Dist: prompt_toolkit; extra == "all"
Requires-Dist: Pygments; extra == "all"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

<div align="center">

<img src="https://github.com/Elang-elang/IDScript/blob/main/icons/small.jpg" alt="IDScript" width="160">

# IDScript

**Bahasa pemrograman berbahasa Indonesia dengan interpreter, compiler VM, dan bytecode resmi.**

`IDScript` / `IDS` = `I[n]D[onesian] Script` atau ringkasnya `I[n]D[o] Script`.

[Mulai Cepat](#mulai-cepat) • [CLI](#cli-idscript) • [Format File](#format-file) • [Sintaks](#panduan-sintaks) • [VM](#compiler-vm) • [Lisensi](#lisensi)

</div>

---

## Tentang

| Info | Nilai |
|---|---|
| Pembuat | Elang MRJ |
| GitHub | [`Elang-elang`](https://github.com/Elang-elang) |
| Email | `elangmuhamad888@gmail.com` |
| Repository | <https://github.com/Elang-elang/IDScript> |
| Pendahulu | [Indonesian Script / IS](https://github.com/Elang-elang/indonesian_script) |
| Status | Prototype / pre-alpha |
| Python | `>=3.13` |

<details open>
<summary><strong>Latar Belakang Singkat</strong></summary>

IDScript lahir sebagai kelanjutan dari Indonesian Script atau IS, sebuah proyek bahasa pemrograman berbahasa Indonesia yang sebelumnya dibuat sebagai prototype dan kemudian terbengkalai. IS membuktikan bahwa sintaks pemrograman dapat dibuat lebih dekat dengan istilah Indonesia, tetapi proyek tersebut belum memiliki struktur compiler, runtime, dan format bytecode yang cukup rapi untuk dilanjutkan sebagai bahasa yang lebih stabil.

IDScript meneruskan gagasan itu dengan fondasi baru: grammar Lark, AST, interpreter normal, compiler VM resmi, format module `.idsm`, format compiled bytecode `.idsc`, builtin runtime, dan CLI publik bernama `idscript`.

</details>

---

## Mulai Cepat

<details open>
<summary><strong>Instalasi Lokal</strong></summary>

```bash
python -m pip install -e .
```

Dengan dependency pengembangan:

```bash
python -m pip install -e .[dev]
```

</details>

<details open>
<summary><strong>Program Pertama</strong></summary>

```ids
fungsi utama(): Angka {
    println("Halo dari IDScript");
    kembalikan 0;
}
```

Jalankan:

```bash
idscript main.ids
```

</details>

---

## CLI `idscript`

Format utama:

```bash
idscript <file> {-m|--module,-c|--bytecode,--both} <outputFile>
```

<details open>
<summary><strong>Mode Interpreter</strong></summary>

Tanpa flag compile, `idscript` menjalankan interpreter normal dan tidak membuat `.idsm` atau `.idsc`.

```bash
idscript program.ids
```

Entrypoint default adalah `utama`. Entrypoint lain dapat dipilih dengan `--main`.

```bash
idscript program.ids --main jalankan
```

</details>

<details>
<summary><strong>Mode Module `.idsm`</strong></summary>

```bash
idscript program.ids -m build/program
idscript program.ids --module build/program.idsm
```

Jika `outputFile` tidak punya suffix, CLI otomatis memakai `.idsm`.

</details>

<details>
<summary><strong>Mode Bytecode `.idsc`</strong></summary>

```bash
idscript program.ids -c build/program
idscript program.ids --bytecode build/program.idsc
```

Mode ini menulis `.idsc` saja dan tidak membuat `.idsm` sebagai side effect.

</details>

<details>
<summary><strong>Mode Both</strong></summary>

```bash
idscript program.ids --both build/program
```

Output:

```text
build/program.idsm
build/program.idsc
```

</details>

<details>
<summary><strong>Menjalankan Bytecode</strong></summary>

File `.ids`, `.idsm` dan `.idsc` dapat diberikan langsung ke CLI.

```bash
idscript build/program.idsc
```

</details>

<details>
<summary><strong>Mode REPL</strong></summary>

Tanpa argumen file, `idscript` masuk ke **REPL interaktif** dengan syntax highlighting via `prompt_toolkit` + Pygments.

```bash
idscript
```

Setiap input **harus diakhiri `;`**. Ekspresi akan langsung dievaluasi, statement akan dieksekusi.

Informasi lebih lanjut: [README IDSRepl](src/IDScript/IDSRepl/README.md)

</details>

---

## Format File

| Format | Fungsi |
|---|---|
| `.ids` | Source IDScript yang ditulis manusia. |
| `.idsm` | IDScript Module, format module VM yang masih deskriptif/readable. |
| `.idsc` | IDScript Compiled, bytecode final yang opcode-nya dikodekan. |

<details>
<summary><strong>Alur Compile</strong></summary>

```text
program.ids -> program.idsm -> program.idsc -> VM
```

Contoh:

```bash
idscript app.ids --module app.idsm
idscript app.ids --bytecode app.idsc
idscript app.idsc
```

**Catatan versi:** Format `.idsm`/`.idsc` lawas (sebelum penambahan opcode `MAKE_FUNCTION`) **tidak kompatibel** dengan compiler/VM saat ini. Jika mengalami error "Opcode VM ... belum diimplementasikan", rebuild module dengan compiler terbaru.

</details>

---

## Aturan Import

| Bentuk Import | Resolusi Path |
|---|---|
| `dari "./mod.ids" impor ...` | Relatif ke file pemanggil. |
| `dari "../mod.ids" impor ...` | Relatif ke file pemanggil. |
| `dari "iterasi.ids" impor ...` | Folder builtin `IDScript/builtins`. |
| `dari "atribut.ids" impor ...` | Folder builtin `IDScript/builtins`. |

```ids
dari "./math.ids" impor { var tambah, konstan VERSI };
dari "./math.ids" impor { var tambah sebagai plus };
dari "iterasi.ids" impor { var panjang, var Daftar };
```

---

## Panduan Sintaks

Bagian ini dibuat sebagai referensi cepat. Buka bagian yang dibutuhkan saja.

<details open>
<summary><strong>Tipe Bawaan</strong></summary>

| Tipe IDScript | Makna Runtime |
|---|---|
| `Teks` | String |
| `Angka` | Integer |
| `Float` | Float |
| `Boolean` | Boolean |
| `Kosong` | `kosong` / `None` |
| `Apapun` | Nilai bebas |

```ids
var nama: Teks = "Budi";
var umur: Angka = 20;
var rasio: Float = 1.5;
var aktif: Boolean = benar;
var nihil: Kosong = kosong;
var bebas: Apapun = [1, "dua", benar];
```

</details>

<details>
<summary><strong>Komentar</strong></summary>

```ids
// komentar satu baris

/*
   komentar banyak baris
*/
```

</details>

<details>
<summary><strong>Konstanta `KONSTANTA`</strong></summary>

```ids
KONSTANTA NILAI: Angka = 10;
publik KONSTANTA VERSI: Teks = "0.1.0";
privat KONSTANTA RAHASIA: Teks = "internal";
```

Catatan:

- `KONSTANTA` hanya ada di top-level.
- `publik` berarti dapat diekspor dari module.
- Default visibility adalah privat.

</details>

<details>
<summary><strong>Variabel `var` dan Final `final`</strong></summary>

```ids
var nilai: Angka = 1;
nilai = nilai + 1;

final total: Angka = 100;
```

Optional type:

```ids
var mungkin: ?Angka = kosong;
```

</details>

<details>
<summary><strong>Return, Throw, Break, Continue</strong></summary>

```ids
fungsi ambil(): Angka {
    kembalikan 7;
}

fungsi gagal(): Teks {
    kesalahan "terjadi kesalahan";
}

fungsi hitung(): Angka {
    var total: Angka = 0;
    untuk (var angka dari dalam [1, 2, 3, 4]) {
        jika (angka == 2) { lanjutkan; }
        jika (angka == 4) { berhentikan; }
        total = total + angka;
    }
    kembalikan total;
}
```

</details>

<details open>
<summary><strong>Fungsi</strong></summary>

Deklarasi fungsi bernama:

```ids
fungsi tambah(a: Angka, b: Angka): Angka {
    kembalikan a + b;
}

fungsi kali(final a: Angka, final b: Angka): Angka {
    kembalikan a * b;
}

publik fungsi utama(): Angka {
    kembalikan tambah(2, 3);
}
```

Fungsi Generik (type parameter):

```ids
fungsi identitas<T>(nilai: T): T {
    kembalikan nilai;
}

fungsi utama(): Angka {
    kembalikan identitas<Angka>(5);
}
```

Fungsi Ekspresi / Anonymous / Lambda (ExprFunc):

```ids
fungsi utama(): Angka {
    var kali: Apapun = fungsi(a: Angka, b: Angka): Angka {
        kembalikan a * b;
    };
    kembalikan kali(3, 4);  // 12
}
```

Fungsi ekspresi dapat ditangkap di variabel, dijadikan argumen, dikembalikan, dan juga mendukung generic params:

```ids
fungsi utama(): Angka {
    var fn: Apapun = fungsi<T>(x: T): T {
        kembalikan x;
    };
    kembalikan fn<Angka>(5);  // 5
}
```

Catatan:

- Entrypoint default adalah `fungsi utama()`.
- Interpreter normal memperketat `utama` agar tidak menerima argumen dan mengembalikan `Angka` atau `?Angka`.
- Fungsi ekspresi memiliki nama sintetis `'<anonim>'` untuk keperluan stack trace.
- Fungsi ekspresi didukung penuh di interpreter normal (runtime compiler) dan VM bytecode compiler.

</details>

<details>
<summary><strong>If / Elif / Else</strong></summary>

```ids
fungsi status(nilai: Angka): Teks {
    jika (nilai > 80) {
        kembalikan "baik";
    } namun jika (nilai > 60) {
        kembalikan "cukup";
    } jika tidak {
        kembalikan "kurang";
    }
}
```

Negasi memakai `bukan`.

```ids
fungsi cek(flag: Boolean): Angka {
    jika (bukan flag) {
        kembalikan 0;
    }
    kembalikan 1;
}
```

Di VM, `jika (bukan x)` dikompilasi ke `TO_BOOL` lalu `POP_JUMP_IF_TRUE`.

</details>

<details>
<summary><strong>Loop `selama` dan `untuk`</strong></summary>

```ids
fungsi sampai_lima(): Angka {
    var angka: Angka = 0;
    selama (angka < 5) {
        angka = angka + 1;
    }
    kembalikan angka;
}
```

```ids
fungsi jumlah(): Angka {
    var total: Angka = 0;
    untuk (var angka dari dalam [1, 2, 3]) {
        total = total + angka;
    }
    kembalikan total;
}
```

Destructuring target:

```ids
fungsi jumlah_pasangan(): Angka {
    var total: Angka = 0;
    untuk (var (a, b) dari dalam [[1, 2], [3, 4]]) {
        total = total + a + b;
    }
    kembalikan total;
}
```

</details>

<details open>
<summary><strong>Try / Catch / Else / Finally</strong></summary>

```ids
fungsi aman(): Angka {
    var nilai: Angka = 0;

    coba {
        kesalahan 5;
    } tangkap (e) {
        nilai = 5;
    } jika tidak {
        nilai = 99;
    } diakhiri {
        nilai = nilai + 1;
    }

    kembalikan nilai;
}
```

Semantik mengikuti model Python:

- Blok `coba` dijalankan lebih dulu.
- Blok `tangkap` berjalan jika ada error.
- Blok `jika tidak` berjalan hanya jika tidak ada error.
- Blok `diakhiri` selalu berjalan, termasuk sebelum `kembalikan` keluar dari blok `coba`.

Catatan VM:

- VM resmi sudah mendukung `coba/tangkap/jika tidak/diakhiri` melalui opcode `SETUP_TRY`.
- Handler pertama menangani error yang dilempar oleh `kesalahan` atau exception runtime.

</details>

<details>
<summary><strong>Switch / Match `pilah`</strong></summary>

```ids
fungsi pilih(x: Angka): Teks {
    pilah (x) {
        kasus 1:
            kembalikan "satu";
        kasus 2:
            kembalikan "dua";
        kasus bawaan:
            kembalikan "lain";
    }
}
```

Pattern sequence:

```ids
fungsi total_data(): Angka {
    var total: Angka = 0;
    pilah ([1, 2, 3]) {
        kasus [kepala, ...ekor]:
            total = kepala + ekor[0] + ekor[1];
    }
    kembalikan total;
}
```

</details>

<details>
<summary><strong>Type Alias `tipe`</strong></summary>

```ids
tipe ID = Angka;
tipe Nama = Teks;

fungsi ambil_id(): ID {
    kembalikan 7;
}
```

Dynamic alias:

```ids
tipe Kotak<T> = daftar<T>;
var angka: Kotak<Angka> = [1, 2, 3];
```

</details>

<details>
<summary><strong>Antarmuka `antarmuka`</strong></summary>

```ids
antarmuka User {
    nama: Teks,
    umur: Angka,
}

fungsi ambil_umur(user: User): Angka {
    kembalikan user["umur"];
}
```

</details>

<details open>
<summary><strong>Struktur, Turunan, Implementasi, dan Sifat</strong></summary>

Struktur:

```ids
struktur Orang {
    publik nama: Teks,
    privat umur: Angka,
}
```

Turunan:

```ids
struktur Makhluk {
    publik nama: Teks,
}

struktur Orang {
    publik umur: Angka,
} turunan dari Makhluk;
```

Implementasi metode:

```ids
implementasi Orang {
    publik metode sapa(ini: Orang): Teks {
        kembalikan "Halo " + ini.nama;
    }
}
```

Sifat / trait:

```ids
sifat BisaSapa {
    metode sapa(ini: Orang): Teks;
}

implementasi BisaSapa untuk Orang {
    publik metode sapa(ini: Orang): Teks {
        kembalikan ini.nama;
    }
}
```

Aturan penting:

- Field default privat.
- Duplicate field saat turunan menghasilkan error.
- Duplicate method saat turunan menghasilkan error.
- Tidak ada override implicit.
- Trait memvalidasi nama argumen, tipe argumen, dan return type.

</details>

<details open>
<summary><strong>Enum</strong></summary>

Unit variant:

```ids
enum Gender {
    publik Pria,
    publik Wanita,
}
```

Tuple variant:

```ids
enum Data {
    publik Nomor(Angka),
    publik Pasangan(Teks, Angka),
}
```

Struct variant:

```ids
enum Event {
    publik Login { nama: Teks, umur: Angka },
}
```

Discriminant variant:

```ids
enum Kode {
    publik Oke = 200,
    publik Gagal = 500,
}
```

Metode enum:

```ids
implementasi Kode {
    publik metode nilai(ini: Apapun): Angka {
        kembalikan ini.value;
    }
}
```

</details>

<details>
<summary><strong>Expression</strong></summary>

Literal:

```ids
var teks: Teks = "halo";
var angka: Angka = 10;
var pecahan: Float = 3.14;
var flag: Boolean = benar;
var kosong_nilai: Kosong = kosong;
```

List dan kamus:

```ids
var angka: daftar<Angka> = [1, 2, 3];
var user: kamus<Teks, Apapun> = {"nama": "Budi", "umur": 20};
```

Call, attribute, dan index:

```ids
println("Halo");
var nama: Teks = user.nama;
var pertama: Angka = [1, 2, 3][0];
```

Operator:

```ids
var hasil: Angka = 1 + 2 * 3;
var pangkat: Angka = 2 ** 3;
```

Boolean dan comparison:

```ids
jika (benar dan bukan salah) {
    println("oke");
}

jika (2 didalam [1, 2, 3]) {
    println("ada");
}
```

`identifikasi` dan `info`:

```ids
var angka: Angka = 7;
var salin: Angka = identifikasi angka;

jika (info angka == "Angka") {
    println("ini angka");
}
```

Hasil dari `info` atau `identifikasi` mencangkup
| Nama | Penjelasan |
|---|---|
| `Teks` | berisi string atau sebuah teks |
| `Angka` | berisi integer atau angka bulat |
| `Float` | berisi float atau angka desimal |
| `Boolean` | berisi kondisi benar atau salah |
| `Daftar` | berisi list atau daftar |
| `Kamus` | berisi dictionary atau kamus |
| `Fungsi` | berisi fungsi atau metode |
| `Struktur` | berisi struktur dari objek struktur |
| `Antarmuka` | berisi tipe kamus dari objek tipe |
| `Tipe` | berisi objek tipe |
| `Objek` | berisi objek yang tak terdefinisi |
| `Kosong` | berisi kekosongan |

</details>

<details>
<summary><strong>Type Annotation Lanjutan</strong></summary>

```ids
var mungkin: ?Angka = kosong;
var angka: daftar<Angka> = [1, 2, 3];
var data: kamus<Teks, Angka> = {"a": 1};
var operasi: fungsi<(Angka, Angka): Angka>;
var hasil_operasi: hasil<Angka, Teks>;
var nilai: <Angka, Teks> = 1;
var mode: <"dev", "prod"> = "dev";
```

</details>

---

## Contoh Program Lengkap

<details open>
<summary><strong>Buka contoh</strong></summary>

```ids
tipe Nama = Teks

struktur Orang {
    publik nama: Nama,
    publik umur: Angka,
}

sifat BisaSapa {
    metode sapa(ini: Orang): Teks;
}

implementasi BisaSapa untuk Orang {
    publik metode sapa(ini: Orang): Teks {
        kembalikan "Halo " + ini.nama;
    }
}

fungsi utama(): Angka {
    final budi: Orang = Orang { nama: "Budi", umur: 20 };
    println(budi.sapa());

    jika (info budi == "Struktur") {
        println("Budi adalah struktur Orang");
    }

    kembalikan budi.umur;
}
```

</details>

---

## Compiler VM

<details open>
<summary><strong>Opcode bergaya Python</strong></summary>

VM resmi memakai opcode eksplisit agar mudah dibaca dan didebug.

| Lama | Baru |
|---|---|
| `CONST` | `LOAD_CONST` |
| `LOAD` | `LOAD_NAME` |
| `STORE` | `STORE_NAME` |
| `STORE_LOCAL` | `STORE_FAST` |
| `POP` | `POP_TOP` |
| `BINARY` | `BINARY_OP` |
| `COMPARE` | `COMPARE_OP` |
| `JUMP` | `JUMP_ABSOLUTE` |
| `POP_JUMP_IF_FALSE` | `POP_JUMP_IF_FALSE` |
| `CALL` | `CALL_FUNCTION` |
| `RETURN` | `RETURN_VALUE` |
| `FUNC` | `MAKE_FUNCTION` |

Opcode lama **TIDAK** didukung lagi untuk kompatibilitas.

</details>

<details>
<summary><strong>Contoh bytecode konseptual if/else</strong></summary>

```text
LOAD_NAME pi
TO_BOOL
POP_JUMP_IF_FALSE L_else

LOAD_NAME pi
STORE_NAME Pi
JUMP_ABSOLUTE L_end

L_else:
LOAD_CONST 0
STORE_NAME Pi

L_end:
LOAD_CONST None
RETURN_VALUE
```

Catatan: label seperti `L_else` hanya simbol disassembler/compiler. Runtime tetap memakai offset angka.

</details>

---

## Struktur Project

| Path | Fungsi |
|---|---|
| `src/IDScript/__main__.py` | CLI publik `idscript`. |
| `src/IDScript/gramm.lark` | Grammar utama IDScript. |
| `src/IDScript/compile/entrypoint.py` | Entrypoint interpreter normal. |
| `src/IDScript/compile/ids_ast` | Definisi AST. |
| `src/IDScript/compile/parser` | Transformer parse tree ke AST. |
| `src/IDScript/compile/runtime` | Interpreter normal dan runtime model. |
| `src/IDScript/compile/Compiler` | Compiler VM resmi, bytecode, dan VM runtime. |
| `src/IDScript/IDSRepl` | REPL interaktif — [README](src/IDScript/IDSRepl/README.md) |
| `src/IDScript/maker` | Python-to-IDScript binding API — [README](src/IDScript/maker/README.md) |
| `src/IDScript/builtins` | Builtin standar — [README](src/IDScript/builtins/README.md) |

---

## Verifikasi

Jalankan dari folder `src`:

```bash
bash run_tests.sh          # full suite (~10 menit)
bash run_tests.sh --fast   # hanya test cepat (tanpa parser/VM)
```

Atau secara manual:

```bash
cd src
python -m pytest IDScript/compile/testing/ IDScript/maker/testing/ -q -k 'not test_compile_example_file'
python -m pytest IDScript/compile/testing/test_compile.py -q -k 'not test_compile_example_file'
python -m pytest IDScript/compile/Compiler/testing/test_compiler.py -q
```

Catatan:

- `test_compile_example_file` membutuhkan `Example/main.ids` pada root project yang belum tersedia.
- `test_permintaan_builtin_wraps_requests_response` membutuhkan `requests` yang diinstal secara otomatis oleh test.
- VM bytecode compiler dan interpreter normal sudah mendukung semua fitur bahasa termasuk fungsi ekspresi dan generic.

---

## Lisensi

IDScript menggunakan **MIT License**.

<details open>
<summary><strong>Ringkasan Lisensi</strong></summary>

- Kamu boleh memakai, menyalin, memodifikasi, menggabungkan, mempublish, mendistribusikan, sublicense, dan menjual IDScript.
- Kamu boleh memakai IDScript untuk proyek pribadi, pendidikan, riset, maupun komersial.
- Copyright notice dan permission notice MIT harus tetap disertakan pada salinan atau bagian substantial dari software.
- IDScript diberikan apa adanya, tanpa garansi apa pun.
- Pembuat dan pemegang hak cipta tidak bertanggung jawab atas klaim, kerusakan, atau masalah lain dari penggunaan IDScript.

Lihat file [`LICENSE.md`](LICENSE.md) untuk teks lengkap.

</details>
