Commit Graph

7 Commits

Author SHA1 Message Date
Brummel 99f68e89fa Iter 8a: closure-pair ABI for fn-values
Every fn-value is now a `ptr` to a closure pair `{ ptr thunk, ptr env }`,
not a raw fn-pointer. Top-level fns get an auto-generated adapter
`@ail_<m>_<f>_adapter(ptr %_env, params...)` that ignores env and
forwards to the real fn, plus a static closure constant
`@ail_<m>_<f>_clos = { @adapter, null }`. References to a fn as a
value return the closure-pair address.

Indirect calls now GEP the thunk + env slots, load both, and call
`thunk(env, args...)`. Direct calls to statically-known callees stay
on the original fast path (no adapter).

This is the ABI groundwork for Iter 8b lambdas: a captured-env closure
will reuse the same value shape, just with a non-null env produced by
malloc.

Tests: 48 still green. IR snapshots refreshed (every fn now carries an
adapter + static closure pair). Iter 7's hof.ail.json prints 42
unchanged — `apply(inc, 41)` now hands `@ail_hof_inc_clos` to apply,
which unpacks and indirect-calls as designed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 12:56:12 +02:00
Brummel c6c0a10788 Iter 7: first-class function references (no capture)
Top-level fn names are now usable as values, fn-typed parameters can
be called as `f(args)`. KISS slice of "closures + HOFs + TIR": no
TIR, no heap, no ABI shift — that bundle stays in Iter 8 where
closure-with-capture and lambdas land together.

Codegen:
- Type::Fn lowers to LLVM `ptr`; sig travels via a per-fn-body
  `ssa_fn_sigs` sidetable on `Emitter`.
- Term::Var falls through to `resolve_top_level_fn` when the name is
  not a local; emits `@ail_<m>_<def>` and registers the sig.
- Term::App splits: static callee (builtin / current-module / qualified)
  keeps the existing direct path; otherwise lower the callee, look up
  the sig, emit indirect `call <ret> (<param-tys>) %fn(args...)`.
- emit_fn registers fn-typed params in the sidetable on entry.
- If branches propagate a fn-pointer sig to their phi when both arms
  match.

Typechecker: unchanged. It already accepted `synth(callee)` against
Type::Fn; the only blocker was codegen rejecting non-Var callees.

Tests: 48 green (was 47). New `examples/hof.ail.json` and e2e
`higher_order_apply_inc` exercise `apply(inc, 41) == 42` end-to-end.

DESIGN.md: "What is not (yet) supported" rewritten — closures-with-
capture and lambdas remain pending, first-class fn-refs added as
positive bullet. Smoke-test list extended with `hof.ail.json`.

JOURNAL.md: Iter 7 entry with rationale, scope choice, architecture
self-check, Iter 8 plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 12:44:10 +02:00
Brummel 7577ab8a90 Translate project content to English
Make English the project-wide language: all comments, string literals,
CLI help text, design docs, journal, agent prompts, and README. Only
CLAUDE.md (the user's own instruction file) stays German, and the live
conversation between user and Claude continues in German.

Adds a new "Project language: English" section to docs/DESIGN.md as
the durable convention. No logic changes — translation only. Four
internal error strings in the typechecker were retranslated; no
test asserts on their wording.

Verified: cargo test --workspace passes (44/44).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 12:17:48 +02:00
Brummel a20ab93c66 Iter 5c: Cross-Module-Codegen
Symbol-Mangling-Schema einheitlich auf @ail_<modul>_<def> umgestellt
(auch für Single-Modul-Programme), String-Globals als
@.str_<modul>_<idx>. main bleibt LLVM-/C-ABI-Eintrittspunkt und ist
ein Trampoline auf @ail_<entry>_main. lower_workspace emittiert eine
einzige .ll für den ganzen Workspace, alphabetisch nach Modulname,
Cross-Module-Calls über Import-Map aufgelöst. ail build / ail emit-ir
laufen jetzt durch den Workspace-Pfad. IR-Snapshots regeneriert,
neuer ws_main-Snapshot. E2E-Test workspace_build_runs_imported_fn
prüft, dass das Binary die importierte Funktion korrekt aufruft.
Schuld #19 (source_filename) durch einheitliches <entry>.ail-Schema
geschlossen.
2026-05-07 11:39:59 +02:00
Brummel 21606c9340 Iter 3: ADTs + Pattern Matching
- AST: Def::Type mit Ctors; Term::Ctor (Konstruktion) und Term::Match
  mit Arm/Pattern. Patterns: Wild, Var, Lit, Ctor { ctor, fields } —
  Sub-Patterns im MVP auf Var/Wild beschränkt.
- Typchecker: Type-Registry, ctor_index für O(1)-Resolution, Pattern-
  Bindings, Exhaustiveness-Check gegen volle Konstruktormenge plus
  Negativ-Tests.
- Codegen: Boxed-Heap-Layout via malloc; Tag in Offset 0, Felder ab
  Offset 8 in 8-Byte-Slots. Match lowert zu load tag + switch + Phi
  am Join. Default-Block ist unreachable, wenn vom Typchecker geprüft.
- examples/list.ail.json: rekursive Int-Liste mit sum_list via match.
  E2E-Test + Exhaustiveness-Tests. 19/19 Tests grün.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:38:07 +02:00
Brummel 6e6b6a14fb Iter 2: verschachteltes if, Strings, JSON-Output, deps
- Codegen: current_block-Tracking ersetzt die Heuristik im phi-Lowering;
  verschachtelte if-Ausdrücke produzieren jetzt korrekte LLVM IR.
  examples/max3.ail.json + Test schützt gegen Regression.
- Strings: Lit::Str / Type Str / io/print_str Effekt-Op; Strings sind im
  MVP immutable Konstanten. examples/hello.ail.json als zweiter E2E-Test.
- CLI: --json für manifest und builtins; neuer deps-Subcommand listet
  statische Symbol-Referenzen pro Definition. Effekt-Ops mit Prefix
  effect: markiert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:28:16 +02:00
Brummel 2fbcdba0b1 MVP: AILang-Sprache mit JSON-AST, Typchecker, LLVM-IR-Backend
Erste lauffähige Iteration. examples/sum.ail.json wird zu nativem Binary
kompiliert und druckt 55 (Summe 1..10) als End-to-End-Test.

Architektur:
- ailang-core: hashbares JSON-AST + canonical-form + pretty-printer
- ailang-check: monomorpher HM-Subset + Effekt-Set-Tracking
- ailang-codegen: LLVM-IR-Text-Emitter (kein libllvm-link)
- ail: CLI mit check/manifest/render/describe/emit-ir/build/builtins

Designentscheidungen sind in docs/DESIGN.md dokumentiert; der Verlauf
in docs/JOURNAL.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:18:32 +02:00