Skip to content

Latest commit

 

History

History
394 lines (339 loc) · 16.2 KB

File metadata and controls

394 lines (339 loc) · 16.2 KB

Tugas: Bahasa Pemrograman Bergaya Ruby dengan Sintaks Bahasa Indonesia (SBCL)

Visi

Membuat bahasa pemrograman dinamis, berorientasi objek, dengan sintaks Bahasa Indonesia yang terinspirasi oleh Ruby, diimplementasikan menggunakan SBCL (Steel Bank Common Lisp).


Fase 1: Fondasi Inti

1.1 Analisis & Perancangan Leksikon/Awalan Kata

  • Tentukan daftar kata kunci bahasa Indonesia (pemetaan lengkap dari Ruby)
    if      → jika       | end       → selesai      | def      → fungsi
    else    → lain       | class     → kelas         | return   → kembali
    elsif   → lainjika   | module    → modul         | self     → diri
    unless  → kecuali    | do        → lakukan       | nil      → kosong
    while   → selama     | begin     → mulai         | true     → benar
    until   → sampai     | rescue    → selamatkan    | false    → salah
    for     → untuk      | ensure    → pastikan      | raise    → lempar
    in      → dalam      | require   → butuh         | include  → sertakan
    next    → lanjut     | break     → hentikan      | super    → induk
    and     → dan        | or        → atau          | not      → bukan
    
  • Definisikan spesifikasi token (identifier, number, string, operator, delimiter)
  • Desain format komentar (# komentar baris, #= ... =# komentar blok)
  • Tentukan simbol-simbol operator (aritmatika, perbandingan, logika, penugasan)

1.2 Tokenizer/Lexer (src/lexer.lisp)

  • Implementasi fungsi tokenize(string) → daftar token
  • Kenali: identifier, keyword, integer, float, string, simbol, operator
  • Tangani interpolasi string ("Halo, #{nama}") (lexer + parser + executor)
  • Tangani heredoc string (idn-heredoc via registry)
  • Laporkan kesalahan leksikal dengan nomor baris & kolom
  • Tulis unit test untuk setiap jenis token

1.3 AST (Abstract Syntax Tree) (src/ast.lisp)

  • Definisikan struktur/node AST (gunakan CLOS classes atau defstruct)
    • literal-node (nil, benar, salah, integer, float, string, simbol)
    • identifier-node (variabel, konstanta, pemanggilan metode)
    • binary-op-node (+, -, *, /, ==, !=, <, >, dsb.)
    • unary-op-node (!, -)
    • if-node (kondisi, tubuh, cabang-lain)
    • while-node / until-node
    • for-node / each-node
    • function-def-node (nama, parameter, tubuh)
    • class-def-node (nama, induk, tubuh)
    • module-def-node (nama, tubuh)
    • call-node (penerima, metode, argumen, blok)
    • assignment-node (target, nilai)
    • array-literal-node / hash-literal-node
    • block-node (parameter, tubuh)
    • return-node
    • require-node
  • Fungsi bantu untuk membangun dan berjalan di AST

1.4 Parser (src/parser.lisp)

  • Implementasi recursive descent parser atau Pratt parser
  • Fungsi parse(tokens) → AST
  • Tangani ekspresi dengan presedensi operator yang benar
  • Parsing struktur kontrol: jika/lain/selesai, selama/selesai, untuk/dalam/selesai
  • Parsing definisi fungsi: fungsi nama(param) ... selesai
  • Parsing definisi kelas: kelas Nama < Induk ... selesai
  • Parsing definisi modul: modul Nama ... selesai
  • Parsing literal array: [1, 2, 3]
  • Parsing literal hash: {kunci => nilai}
  • Parsing pemanggilan metode dengan blok: objek.metode(arg) lakukan |x| ... selesai (parser + executor)
  • Parsing operator penugasan: =, +=, -=, ||=
  • Laporkan kesalahan sintaks yang baik
  • Tulis unit test parser

Fase 2: Eksekutor & Runtime

2.1 Kompilator/Eksekutor (src/eksekutor.lisp)

  • Implementasi walker AST: fungsi eksekusi(ast, lingkungan)
  • Pilihan strategi eksekusi: B. Interpreter murni — Walk AST dan eksekusi langsung
  • Eksekusi ekspresi literal
  • Eksekusi operasi biner dan unary
  • Evaluasi jika/kecuali conditional
  • Evaluasi loop selama/sampai/untuk
  • Eksekusi kembali (return)
  • Eksekusi pemanggilan fungsi dan metode

2.2 Lingkungan & Scope (src/lingkungan.lisp)

  • Implementasi rantai lingkungan (lexical scope)
  • Fungsi lingkungan-cari(lingkungan, nama)
  • Fungsi lingkungan-tetapkan(lingkungan, nama, nilai)
  • Dukungan closure: lingkungan menangkap variabel luar
  • Lingkungan global untuk konstanta dan definisi level atas
  • Lingkungan lokal per pemanggilan fungsi / blok

2.3 Sistem Objek (src/objek.lisp)

  • Definisikan root class Objek (semua adalah objek)
  • Definisikan Kelas sebagai metaclass
  • Sistem pewarisan tunggal dengan induk (super)
  • Metode lookup: diri → kelas → induk → ... → Objek
  • Konstruktor awali (initialize)
  • Akses variabel instans @nama
  • Akses variabel kelas @@nama
  • Variabel global $nama
  • Metode diri (self)
  • induk untuk memanggil metode parent
  • Mixins: sertakan (include) — idn-sertakan di src/objek.lisp
  • Visibilitas metode: umum, pribadi, terlindung (infrastruktur siap)
  • Aksesor atribut: baca_atribut, tulis_atribut, akses_atribut (idn-definisikan-aksesor)

2.4 Blok, Proc, dan Lambda (src/blok.lisp)

  • Parsing blok inline lakukan |param| ... selesai (parser: parse-block-after-call)
  • Objek Proc untuk blok yang dapat disimpan
  • Keyword lambda untuk fungsi anonim
  • Keyword hasilkan (yield) untuk memanggil blok
  • Metode .panggil pada Proc/Lambda
  • Konversi blok implisit ke Proc melalui &blok (via executor block passing)

Fase 3: Tipe Data Bawaan

3.1 Integer & Float (src/angka.lisp)

  • Kelas Angka (Numeric) abstrak
  • Kelas BilanganBulat (Integer) — di-back oleh SBCL integer
  • Kelas BilanganPecahan (Float) — di-back oleh SBCL float
  • Operasi aritmatika: +, -, *, /, % (modulo), ** (pangkat)
  • Metode: .abs, .ke_atas (ceil), .ke_bawah (floor), .bulatkan (round)
  • Metode: .ganjil?, .genap?, .positif?, .negatif?, .nol?
  • Iterasi: 3.kali lakukan |i| ... selesai (via block passing ke metode kali)
  • Range: 1.sampai(10), 1...10

3.2 String (src/teks.lisp)

  • Kelas Teks (String)
  • Interpolasi: "Nama saya #{nama}" (lexer + parser + executor)
  • Konkatenasi: +, penggandaan: *
  • Metode: .panjang, .besar (upcase), .kecil (downcase), .kapital
  • Metode: .potong, .ganti, .pisah, .berisi?
  • Metode: .kosong?, .awalan?, .akhiran?, .lucuti, .balik
  • Metode: .==, .ke_integer, .ke_simbol
  • Heredoc: <<~TEKS ... TEKS
  • Encoding UTF-8 (didukung SBCL secara default)

3.3 Larik/Array (src/larik.lisp)

  • Kelas Larik (Array)
  • Literal: [1, 2, 3]
  • Akses: larik[0]
  • Metode: .panjang, .kosong?
  • Metode: .dorong (push), .ambil (pop), .sisipkan, .hapus_pada
  • Iterasi: .setiap, .peta (map), .pilih (select), .tolak (reject)
  • Metode: .pertama, .terakhir, .gabung (join)
  • Metode: .urutkan (sort), .balik (reverse), .unik (uniq)
  • Metode: .jumlah, .termasuk?, .ke_teks

3.4 Hash/Kamus (src/kamus.lisp)

  • Kelas Kamus (Hash)
  • Literal: {kunci => nilai}
  • Akses: .ambil(kunci), .atur(kunci, nilai)
  • Metode: .kunci, .nilai, .ukuran
  • Iterasi: .setiap_pasangan (each_pair)
  • Metode: .gabung (merge), .punya_kunci?, .hapus
  • Metode: .kosong?, .ke_teks
  • Default value / default proc (idn-buat-kamus dengan parameter opsional)

3.5 Simbol (src/simbol.lisp)

  • Kelas Simbol (Symbol)
  • Literal: :nama
  • Konversi ke/dari Teks: .to_s, .nama
  • Perbandingan: .==

3.6 Range/Rentang (src/rentang.lisp)

  • Kelas Rentang (Range)
  • Literal inklusif: 1..10
  • Literal eksklusif: 1...10
  • Iterasi range (via untuk .. dalam)
  • Metode: .berisi? (cover?/include?)
  • Metode: .ke_larik, .to_s, .awal, .akhir, .eksklusif?

Fase 4: Perpustakaan Standar

4.1 Input/Output (src/stdlib/io.lisp)

  • tulis, cetak — output ke stdout
  • baca — input dari stdin
  • Kelas Berkas (File): .buka, .baca, .baca_semua, .tulis, .tulis_baris, .tutup, .nama
  • Blok File: Berkas.buka("path") lakukan |f| ... selesai (via block passing)
  • Direktori: dir_sekarang, dir_daftar, dir_ada?, dir_buat

4.2 Manipulasi Teks (src/teks.lisp)

  • Strip: .lucuti (sudah ada di Teks)
  • Padding: .isi_kiri, .isi_kanan, .tengah
  • Format string: "Halo ~@!".format(nama) di Teks

4.3 Waktu & Tanggal (src/stdlib/waktu.lisp)

  • Kelas Waktu (Time)
  • waktu_sekarang
  • Metode: .tahun, .bulan, .hari, .jam, .menit, .detik
  • Metode: .to_s, .+detik, .-
  • Format tanggal: .format(fmt) mirip strftime

4.4 Enumerasi (src/stdlib/enumerasi.lisp)

  • Modul enumerasi diterapkan ke Larik
  • Metode: .suntik/.lipat (inject/reduce)
  • Metode: .semua?, .ada?
  • Metode: .hitung
  • Metode: .kelompokkan (group_by)
  • Metode: .urutkan_menurut (sort_by), .tak_ada?

4.5 JSON & Serialisasi (src/stdlib/json.lisp)

  • json_urai(teks) — parse JSON → objek IDN
  • json_hasilkan(objek) — objek IDN → JSON string
  • Tanpa dependensi eksternal (parser & serializer murni CL)

Fase 5: Penanganan Kesalahan

5.1 Eksepsi (src/eksepsi.lisp)

  • Kelas dasar Eksepsi (Exception)
  • Sintaks: mulai ... selamatkan NamEksepsi => e ... selesai
  • pastikan (ensure) untuk cleanup
  • lain (else) untuk kasus tanpa eksepsi
  • lempar (raise) untuk melempar eksepsi
  • Backtrace yang informatif (nama tipe AST + lokasi di pesan error)
  • Eksepsi bawaan:
    • KesalahanArgumen, KesalahanNama, KesalahanTipe
    • TanpaMetode, KesalahanSintaks, KesalahanIO

Fase 6: REPL & Alat Pengembangan

6.1 REPL (src/repl.lisp)

  • Read-Eval-Print Loop interaktif (make repl atau bin/idn)
  • Multi-line input (deteksi selesai yang belum ditutup)
  • History dengan readline/editline (rlwrap bin/idn)
  • Auto-completion (:complete <awal> — saran keyword, fungsi, variabel)
  • Pretty-print hasil evaluasi (angka, teks, larik, kamus, dll.)
  • Mode debug / inspeksi (:debug, :inspeksi <var>, breakpoints)
  • Variabel khusus: _ (hasil terakhir), _galat (error terakhir)

6.2 Loader File (src/loader.lisp)

  • Fungsi butuh "nama_file" untuk load file .idn
  • Path pencarian: direktori kerja, ./lib, ~/.idn/lib
  • Flag -e 'kode' untuk eksekusi inline
  • Flag -c untuk check sintaks saja
  • Shebang support: #!/usr/bin/env idn

6.3 Executable & Packaging

  • Buat executable binary idn dari SBCL image (make build)
  • Script Makefile atau build.lisp untuk build
  • Instalasi via make install
  • Dokumentasi CLI (idn --help, idn --version)

Fase 7: Pengujian & Jaminan Kualitas

7.1 Framework Pengujian (test/)

  • Test runner kustom dengan macro uji, uji-token, uji-parse
  • Test suite untuk lexer (81 tes)
  • Test suite untuk parser (63 tes)
  • Test suite untuk eksekutor (40 tes)
  • Test suite untuk tipe data bawaan (67 tes)
  • Test suite untuk stdlib (17 tes)
  • Test suite untuk eksepsi (6 tes)
  • Test suite untuk REPL (5 tes)
  • Total: 279 tes, semua lulus

7.2 Contoh Program (contoh/)

  • halo_dunia.idn — program sederhana
  • faktorial.idn — rekursi
  • fibonacci.idn — iterasi & rekursi
  • kelas.idn — OOP: kelas, pewarisan
  • blok.idn — lambda
  • larik.idn — manipulasi larik & enumerasi
  • kamus.idn — manipulasi hash
  • berkas.idn — operasi file I/O
  • eksepsi.idn — penanganan kesalahan
  • web_server.idn — HTTP server sederhana (src/stdlib/webserver.lisp)

Fase 8: Perbaikan Lanjutan (Roadmap Masa Depan)

8.1 Optimisasi Kinerja

  • JIT compilation via SBCL native compiler
  • Inline caching untuk method lookup
  • Constant folding & dead code elimination

8.2 Fitur Lanjutan

  • Pattern matching cocokkan/kasus/ketika (src/stdlib/fase8.lisp)
  • Keyword arguments: fungsi(nama:, umur: 0)
  • Splat operator: *arg, **opsi
  • Refinements / monkey patching
  • Metaprogramming: definisi_metode, definisi_kelas (src/stdlib/fase8.lisp)
  • Method hilang_metode (method_missing)
  • const_missing
  • Threading / konkurensi
  • Fibers / coroutines

8.3 Perkakas Pengembangan

  • LSP (Language Server Protocol) — via formatter/linter built-in
  • Formatter kode (idn fmtsrc/stdlib/formatter.lisp)
  • Linter (idn lintsrc/stdlib/formatter.lisp)
  • Debugger interaktif
  • Profiler
  • Documentation generator (seperti RDoc/YARD)

8.4 Interoperabilitas

  • FFI untuk memanggil fungsi C (src/stdlib/fase8.lisp)
  • Embedding: panggil SBCL Common Lisp dari kode IDN
  • Compile to binary standalone executable (make build via build.lisp)

Struktur Direktori Proyek

IDN/
├── bin/
│   └── idn                    # Entry point executable (SBCL script)
├── src/
│   ├── packages.lisp          # Definisi package CL
│   ├── utils.lisp              # Fungsi utilitas
│   ├── lexer.lisp              # Tokenizer
│   ├── ast.lisp                # Definisi AST node
│   ├── parser.lisp             # Parser
│   ├── lingkungan.lisp         # Environment/scope
│   ├── eksekutor.lisp          # AST executor/interpreter
│   ├── objek.lisp              # Sistem objek/kernel
│   ├── blok.lisp               # Blok, Proc, Lambda
│   ├── eksepsi.lisp            # Exception system
│   ├── angka.lisp              # Kelas angka (Integer, Float)
│   ├── teks.lisp               # Kelas String
│   ├── larik.lisp              # Kelas Array
│   ├── kamus.lisp              # Kelas Hash
│   ├── simbol.lisp             # Kelas Symbol
│   ├── rentang.lisp            # Kelas Range
│   └── loader.lisp             # File loader / 'butuh'
├── stdlib/
│   ├── io.idn                  # I/O built-in
│   ├── teks_util.idn           # String utilities
│   ├── waktu.idn               # Time/Date
│   ├── enumerasi.idn           # Enumerable module
│   └── json.idn                # JSON handler
├── test/
│   ├── test_runner.lisp        # Test framework & runner
│   ├── test_lexer.lisp
│   ├── test_parser.lisp
│   ├── test_eksekutor.lisp
│   ├── test_objek.lisp
│   └── test_stdlib.lisp
├── contoh/
│   ├── halo_dunia.idn
│   ├── faktorial.idn
│   ├── fibonacci.idn
│   ├── kelas.idn
│   ├── blok.idn
│   ├── larik.idn
│   ├── kamus.idn
│   ├── berkas.idn
│   └── eksepsi.idn
├── dok/
│   ├── sintaks.md              # Referensi sintaks lengkap
│   ├── stdlib.md               # Dokumentasi stdlib
│   └── tutorial.md             # Tutorial pengguna
├── Makefile                    # Build script
├── build.lisp                  # SBCL build script (dump executable)
├── idn.asd                     # ASDF system definition
├── task.md                     # File ini
└── README.md

Catatan Implementasi

  1. Bahasa Indonesia standar: Gunakan KBBI sebagai acuan kata kunci. Hindari kata serapan yang ambigu.
  2. Inspirasi Ruby: Prioritaskan "programmer happiness" — sintaks harus bersih, ekspresif, dan intuitif.
  3. Pendekatan Kompilasi: Strategi awal adalah kompilasi AST ke kode Common Lisp (seperti cara Clojure di JVM). Setiap node AST menghasilkan kode CL yang ekuivalen, lalu dievaluasi oleh SBCL. Ini memberi kita garbage collection, optimisasi, dan runtime yang matang secara gratis.
  4. Konvensi penamaan file: Gunakan .idn sebagai ekstensi file bahasa ini.
  5. Nama bahasa: IDN (singkatan dari IDonesiaN), diucapkan "idian".

MVP (Minimum Viable Product) — Target Fase 1-3 + REPL

Yang harus selesai untuk rilis awal:

  • Tokenizer & Parser lengkap
  • Eksekusi ekspresi, kondisional, loop, fungsi
  • Kelas, pewarisan, mixin
  • Tipe data: Angka, Teks, Larik, Kamus, Simbol
  • Blok & lambda
  • REPL yang berfungsi
  • Contoh program bekerja