Changelog

Semua perubahan penting pada AHA! Lang

Changelog

Semua perubahan penting pada AHA! Lang didokumentasikan dalam berkas ini. Anda selalu dapat membangun versi terbaru dari kode sumber — lihat Getting Started.

1.4.5 — 2026-08-16

Ditambahkan

  • Fungsi generik (F3): fn pick<T>(a: T, b: T) -> T { if a > b { a } else { b } } — fungsi dengan tipe parameter generik.
  • Monomorphization via LLVM: Setiap kombinasi unik (nama generik, tipe konkret) menjadi fungsi LLVM terpisah (pick_Int, pick_String, ...), dikompilasi lazy di call site pertama dan di-cache. Nol biaya runtime — generics resolve sepenuhnya saat kompilasi.
  • Banyak type params: fn first<A, B>(a: A, b: B) -> A — binding konkret di-infer dari argumen call site.
  • Anotasi return type: -> T atau -> int — return type generik atau konkret.
  • Monomorphization bersarang: Fungsi generik bisa memanggil fungsi generik lain (fn twice<U>(x: U) -> U { id(x) }).
  • Rangkaian Pengujian: 417 pengujian lulus (sebelumnya 404; +13 pengujian generics: identity int/string/bool/struct, pick, dua type params, panggilan bersarang, bentuk IR).

Diubah

  • predeclare_functions menyimpan fungsi generik di generic_defs (tanpa pre-deklarasi langsung); body dikompilasi saat monomorphization.
  • compile_function me-skip body fungsi generik di top-level (hanya di-instantiate saat dipanggil).
  • Fixpoint loop me-skip fungsi generik (return type hanya ada per instantiation).

Keamanan

  • Generics tidak menambah jalur unsafe: semua tipe tetap diverifikasi saat kompilasi; monomorphization murni duplikasi codegen per tipe.

1.4.4 — 2026-08-16

Ditambahkan

  • Anotasi Tipe (F2): let x: int = 5 — deklarasi variabel dapat membawa anotasi tipe eksplisit (int, string, bool, atau nama struct). Nilai diperiksa tipenya saat kompilasi:
    • let x: int = "hi" → error kompilasi Type mismatch: variable 'x' annotated as 'int' but value has type 'String'
    • let p: Point = Other { ... } → error kompilasi bila nama struct berbeda
  • Inferensi Tipe (F2): Variabel tanpa anotasi tipenya di-infer dari ekspresi (literal, panggilan fungsi, if-expression).
  • Inferensi return type fungsi: fn greet() { "hello" } ber-return type String — caller bisa let s = greet(); len(s).
  • If-expression dengan cabang string: fn pick(a) { if a > 0 { "pos" } else { "neg" } } kini mengembalikan string sungguhan (phi node memakai tipe cabang, bukan selalu i64).
  • Rangkaian Pengujian: 404 pengujian lulus (sebelumnya 384; +20 pengujian inferensi/anotasi tipe).

Diubah

  • infer_expr_type & infer_expr_type_with_scope mendukung anotasi dan inferensi return type fungsi.
  • Hint tipe yang tidak dikenal (let x: unknown = 7) bersifat lenient — fallback ke Int, konsisten dengan struct field hints.

Keamanan

  • Anotasi tipe diverifikasi saat kompilasi: ketidakcocokan anotasi dengan tipe nilai menghasilkan error kompilasi, bukan perilaku tak terdefinisi.

1.4.3 — 2026-08-16

Ditambahkan

  • Halaman Referensi Sintaks: Referensi lengkap seluruh sintaks AHA! yang terverifikasi dari compiler — 13 kata kunci, identifier, literal, tipe, operator dengan tabel precedence, statement, ekspresi, alur kontrol, komentar, builtin, dan ringkasan grammar EBNF. Tersedia di /id/syntax (ID) dan /en/syntax (EN).
  • Struct sebagai parameter fungsi (F1): Struct dapat dioper by-value ke fungsi. Parameter dialokasikan dengan tipe LLVM struct yang benar; akses field di dalam fungsi bekerja normal.
  • Struct sebagai return value fungsi (F1): Fungsi dapat mengembalikan struct literal. Caller menyimpan hasilnya ke binding let dan membaca field-nya.
  • Struct literal langsung sebagai argumen: sum(Point { x: 1, y: 2 }) — tanpa variabel perantara.
  • Rantai fungsi struct: sum(make(20, 22)) — return value struct langsung dioper ke fungsi lain.
  • unify_with() pada AhaType: Menyatukan tipe parameter dari beberapa call site (String dan nama struct meng-override default Int).
  • Rangkaian Pengujian: 384 pengujian lulus (sebelumnya 373; +11 pengujian struct param/return).

Diubah

  • infer_expr_type & infer_expr_type_with_scope kini mengenali StructLiteral dan FieldAccess untuk inferensi tipe pre-pass yang akurat.
  • scan_call_sites melacak binding variabel struct (struct_var_types) agar inferensi tipe bisa resolve struct variable sebagai argumen fungsi.
  • Language Tour: Memperbaiki sintaks for dari for i 0..10 menjadi for i in 0..10 — kata kunci in wajib menurut parser. Juga menambahkan "Referensi Sintaks" ke navigasi docs.

1.4.2 — 2026-08-16

Ditambahkan

  • Mutasi Field (F1): p.x = value — penugasan field struct saat runtime. p.x kini menjadi lvalue: load struct, insertvalue field baru, store kembali. Tipe diperiksa terhadap deklarasi field (field string menolak nilai int dan sebaliknya).
  • Target Penugasan Generik: Parser kini memperlakukan = sebagai operator infix, sehingga baik x = 5 (identifier) maupun p.x = 5 (field access) mengurai menjadi AssignmentExpression dengan target ekspresi generik.
  • Rangkaian Pengujian: 373 pengujian lulus (sebelumnya 363; +10 pengujian mutasi field, termasuk mutasi di dalam loop dan penugasan ulang field string).

Diubah

  • AssignmentExpression.name: IdentifierAssignmentExpression.target: Box<Expression> — memungkinkan bentuk lvalue di masa depan (mis. penugasan elemen array arr[0] = x).

Diperbaiki

  • TokenType::Assign tidak ada di precedence(), sehingga = jatuh ke parse_prefix sebagai token tak terduga. Ditambahkan Precedence::Assign.

Keamanan

  • Menugaskan nilai dengan tipe yang salah ke field bertipe menghasilkan kesalahan saat kompilasi.

1.4.1 — 2026-08-16

Ditambahkan

  • Codegen Struct (Roadmap Phase 2 #1): definisi struct Point { x, y } kini menghasilkan tipe struct LLVM yang sesungguhnya. Literal Point { x: 1, y: 2 } membangun agregat via insertvalue; akses field p.x dibaca via extractvalue.
  • Field Struct Bertipe: anotasi tipe field (name: string, age: int) dihormati saat runtime — field string memakai layout {i8*, i64}, field int memakai i64. Literal diperiksa tipenya terhadap deklarasi. Akses field mempertahankan tipe yang dideklarasikan, sehingga len(p.name), p.name == "...", dan p.first + p.last bekerja dengan benar.
  • Sintaks Literal Struct: TypeName { field: value, ... } — dibatasi oleh registry nama struct sehingga kondisi blok biasa if x { ... } tidak terpengaruh.
  • PRD (Product Requirements Document): PRD.md — mendefinisikan visi AHA! dari web hingga aerospace, prioritas roadmap, dan tata kelola proyek.
  • Rangkaian Pengujian (struct): 28 pengujian backend mencakup semantik JIT, bentuk IR, field bertipe, dan jalur kesalahan.

Diubah

  • Alur kerja branch: semua pengembangan kini terjadi di branch development; main hanya menerima PR dengan CI hijau.
  • PRD menggantikan perencanaan ad-hoc: semua fitur masa depan wajib berasal dari roadmap di PRD.md.
  • F5 (Resource lifetimes) dibekukan: ownership/lifetimes tidak akan disentuh sampai F1–F4 (penyelesaian struct, inferensi tipe, generics, sistem modul) stabil.

Keamanan

  • Tipe field struct diperiksa saat kompilasi: menugaskan literal string ke field int (atau sebaliknya) menghasilkan kesalahan saat kompilasi, bukan perilaku runtime tak terdefinisi.

1.4.0 — 2026-05-17

Ditambahkan

  • Sistem Tipe (src/types.rs): enum AhaType (Int, Bool, String, Void, Array, Function) dengan pemeriksaan tipe saat kompilasi via check_binary_op() dan check_prefix_op()
  • TypedValue: semua metode ekspresi codegen kini mengembalikan TypedValue yang memasangkan nilai LLVM dengan AhaType-nya
  • Tipe String: string kini merupakan struct LLVM {i8*, i64} (pointer + panjang), menggantikan cast pointer-ke-int yang tidak aman
  • Konkatenasi String: "hello" + " world" mengalokasikan buffer baru via malloc, menyalin via memcpy, menambahkan null-terminator
  • Perbandingan String: == dan != pada string menggunakan strcmp dari pustaka standar C
  • Builtin len(): mengembalikan panjang string dalam O(1) dengan membaca field panjang struct
  • Penautan C Runtime: deklarasi eksternal untuk malloc, memcpy, strlen, strcmp
  • Komentar Blok: komentar multi-baris /* ... */
  • Urutan Escape String: \n, \t, \\, \", \r, \0
  • Peningkatan Identifier: digit setelah karakter pertama (my_var2), prefiks garis bawah (_private)
  • Rangkaian Pengujian: 84 pengujian di 4 modul — lexer, parser, sistem tipe, dan JIT ujung-ke-ujung

Diubah

  • Token.r#type diganti nama menjadi Token.kind — mengikuti konvensi Rust, menghilangkan sintaks raw identifier
  • Cakupan variabel: peta datar → tumpukan cakupan dengan pelacakan tipe
  • compile_expression() mengembalikan TypedValue di seluruh penangan ekspresi
  • Semua pesan keluaran dan komentar sumber distandarkan ke bahasa Inggris
  • Roadmap README diperbarui untuk mencerminkan status implementasi secara akurat

Diperbaiki

  • Operator != menghasilkan "==" alih-alih "!=" (kesalahan copy-paste di lexer)
  • Kondisi if tidak dikonversi dari i64 ke i1 sebelum build_conditional_branch
  • Node phi mereferensikan basic block asli alih-alih end block sebenarnya
  • Ekspresi terakhir di badan program dikompilasi dua kali
  • Fungsi memancarkan return implisit dan eksplisit sekaligus, menyebabkan kesalahan LLVM "multiple terminators"
  • Kompilasi fungsi dapat membocorkan state scope/builder saat terjadi kesalahan
  • Parser mengembalikan Expression::Identifier("ERROR") saat gagal parse, menyebarkan AST tidak valid ke codegen

Keamanan

  • Ketidakcocokan tipe ("hello" + 5) kini menghasilkan kesalahan saat kompilasi alih-alih perilaku runtime tak terdefinisi
  • Semua panggilan .unwrap() diganti dengan .expect("descriptive context") untuk panic yang dapat di-debug

1.3.0 — Rilis Sebelumnya

  • Compiler awal dengan lexer, parser, codegen
  • Tipe bilangan bulat, boolean, string (sebagai trik pointer)
  • Perulangan If/else, while, for
  • Fungsi dengan parameter
  • Stdlib dasar: print, print_str, abs, min, max