Files
AILang/crates/ail/tests/snapshots/hello.ll
T
Brummel 35a9bc67b1 feat(series): ship the kernel-tier Series library extension (#61)
Series a is a bounded ring buffer with financial-style indexing
(index 0 = newest), shipped as a PURE AILang library extension over
RawBuf — zero Rust codegen, zero intercepts, zero (intrinsic)
markers. It is the first kernel-tier module that depends on another
kernel-tier module (raw_buf). This turns the committed SMA headline
pin (6b7ee45) green and closes the step-1 scope of #61.

The module lives at crates/ailang-kernel/src/series/{source.ail,
mod.rs} and is auto-injected by the loader exactly like raw_buf
(parse_series + injection in ailang-surface/src/loader.rs, re-export
in lib.rs). Five real-bodied ops: new / push / at / len /
total_count, all built on RawBuf.{new,set,get}.

The source is the model-0007 sketch with every defect corrected and
each correction verified against the live tool:
- param-in narrowed to (a Int Float); Bool deferred per #61.
- inner alloc is `(new RawBuf lookback)` with no element type-arg —
  the element is solved from the `(con RawBuf a)` ctor-field context,
  which the base-tier mono fix (b11a6d9) carries through to the
  caller's concrete type. This is the capability that lets Series be
  pure AILang.
- element-typed params/rets are bare `a`, not `(con a)` (a type
  variable, not a nullary ctor).
- op signatures bind `a` via `(forall (vars a) ...)`.
- comparison uses the named helper `lt`, not the non-existent `<`.
- the at-index formula is `(head - 1 - i + 2*lookback) mod lookback`
  (0007 had the sign on i wrong, walking the wrong direction).

Cross-kernel-module visibility — the flagged risk — needed ZERO
mechanism change: the loader derives its implicit-import set from
every kernel module, so series's body resolves `RawBuf.*` and
`(con RawBuf a)` via the existing kernel auto-visibility.

Both CLAUDE.md lockstep pairs stay intact:
- INTERCEPTS <-> (intrinsic) markers: unchanged. Series is
  pure-AILang, adds neither; intercepts_bijection_with_intrinsic_
  markers still green.
- Term::New typecheck/reject <-> pre_desugar_validation.rs:
  untouched; the new/Series construction exercises existing paths.

Test-surface ripple, all verified:
- workspace module-count pins 4 -> 5 (e2e.rs, workspace_pin.rs),
  with a `series` membership assertion added — the kernel set grew
  by one deliberate module.
- two mono-identity tests (typeclass_22b3.rs) now skip `prelude`
  and `series`: series is the first auto-imported real-bodied
  consumer of the prelude polyfns `lt`/`compare` over Int, so mono
  legitimately materialises `lt__Int`/`compare__Int` into prelude
  for every workspace. That is a concrete call site, not gratuitous
  mutation; the tests' real invariant (mono leaves work-free modules
  untouched) still holds for every other module.
- five IR snapshots refreshed; the deltas are strictly additive
  (zero IR deletions) — the same series-driven Int specialisations.

Verified: full `cargo test --workspace` green; SMA binary built via
`ail build --alloc=rc` prints `3.0 / 5.33333 / 5.66667 / 5.33333`.

refs #61
2026-06-02 13:09:17 +02:00

292 lines
7.5 KiB
LLVM

; AILang generated workspace; entry: hello
source_filename = "hello.ail"
target triple = "<NORMALIZED>"
@.str_hello_str_0 = private unnamed_addr constant <{ i64, [15 x i8] }> <{ i64 14, [15 x i8] c"Hello, AILang.\00" }>, align 8
declare i32 @printf(ptr, ...)
declare i32 @fputs(ptr, ptr)
@stdout = external global ptr
declare ptr @ailang_rc_alloc(i64)
declare void @ailang_rc_inc(ptr)
declare void @ailang_rc_dec(ptr)
declare ptr @ailang_drop_worklist_new()
declare void @ailang_drop_worklist_push(ptr, ptr)
declare ptr @ailang_drop_worklist_pop(ptr)
declare void @ailang_drop_worklist_free(ptr)
declare i32 @strcmp(ptr, ptr)
declare zeroext i1 @ail_str_eq(ptr, ptr)
declare i32 @ail_str_compare(ptr, ptr)
declare ptr @ailang_int_to_str(i64)
declare ptr @ailang_float_to_str(double)
declare ptr @ailang_bool_to_str(i1)
declare ptr @ailang_str_clone(ptr)
declare ptr @ailang_str_concat(ptr, ptr)
declare i64 @llvm.fptosi.sat.i64.f64(double)
@ail_hello_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_hello_main_adapter, ptr null }
@ail_prelude_float_eq_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_eq_adapter, ptr null }
@ail_prelude_float_ne_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ne_adapter, ptr null }
@ail_prelude_float_lt_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_lt_adapter, ptr null }
@ail_prelude_float_le_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_le_adapter, ptr null }
@ail_prelude_float_gt_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_gt_adapter, ptr null }
@ail_prelude_float_ge_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ge_adapter, ptr null }
@ail_prelude_compare__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_compare__Int_adapter, ptr null }
@ail_prelude_lt__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_lt__Int_adapter, ptr null }
define i8 @ail_hello_main() {
entry:
%v1 = getelementptr inbounds i8, ptr getelementptr inbounds (<{ i64, [15 x i8] }>, ptr @.str_hello_str_0, i32 0, i32 0), i64 8
%v2 = load ptr, ptr @stdout, align 8
call i32 @fputs(ptr %v1, ptr %v2)
ret i8 0
}
define i8 @ail_hello_main_adapter(ptr %_env) {
entry:
%r = call i8 @ail_hello_main()
ret i8 %r
}
define i1 @ail_prelude_float_eq(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp oeq double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_eq_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_eq(double %a0, double %a1)
ret i1 %r
}
define i1 @ail_prelude_float_ne(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp une double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_ne_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_ne(double %a0, double %a1)
ret i1 %r
}
define i1 @ail_prelude_float_lt(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp olt double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_lt_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_lt(double %a0, double %a1)
ret i1 %r
}
define i1 @ail_prelude_float_le(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp ole double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_le_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_le(double %a0, double %a1)
ret i1 %r
}
define i1 @ail_prelude_float_gt(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp ogt double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_gt_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_gt(double %a0, double %a1)
ret i1 %r
}
define i1 @ail_prelude_float_ge(double %arg_x, double %arg_y) alwaysinline {
entry:
%v1 = fcmp oge double %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_float_ge_adapter(ptr %_env, double %a0, double %a1) {
entry:
%r = call i1 @ail_prelude_float_ge(double %a0, double %a1)
ret i1 %r
}
define ptr @ail_prelude_compare__Int(i64 %arg_x, i64 %arg_y) alwaysinline {
entry:
%v1 = icmp slt i64 %arg_x, %arg_y
br i1 %v1, label %cmp_lt_2, label %cmp_after_lt_2
cmp_lt_2:
%v3 = call ptr @ailang_rc_alloc(i64 8)
store i64 0, ptr %v3, align 8
ret ptr %v3
cmp_after_lt_2:
%v4 = icmp eq i64 %arg_x, %arg_y
br i1 %v4, label %cmp_eq_2, label %cmp_gt_2
cmp_eq_2:
%v5 = call ptr @ailang_rc_alloc(i64 8)
store i64 1, ptr %v5, align 8
ret ptr %v5
cmp_gt_2:
%v6 = call ptr @ailang_rc_alloc(i64 8)
store i64 2, ptr %v6, align 8
ret ptr %v6
}
define ptr @ail_prelude_compare__Int_adapter(ptr %_env, i64 %a0, i64 %a1) {
entry:
%r = call ptr @ail_prelude_compare__Int(i64 %a0, i64 %a1)
ret ptr %r
}
define i1 @ail_prelude_lt__Int(i64 %arg_x, i64 %arg_y) alwaysinline {
entry:
%v1 = icmp slt i64 %arg_x, %arg_y
ret i1 %v1
}
define i1 @ail_prelude_lt__Int_adapter(ptr %_env, i64 %a0, i64 %a1) {
entry:
%r = call i1 @ail_prelude_lt__Int(i64 %a0, i64 %a1)
ret i1 %r
}
define void @drop_prelude_Ordering(ptr %p) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
%tag = load i64, ptr %p, align 8
switch i64 %tag, label %dflt [
i64 0, label %arm_0
i64 1, label %arm_1
i64 2, label %arm_2
]
arm_0:
br label %join
arm_1:
br label %join
arm_2:
br label %join
dflt:
unreachable
join:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define void @partial_drop_prelude_Ordering(ptr %p, i64 %mask) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
%tag = load i64, ptr %p, align 8
switch i64 %tag, label %dflt [
i64 0, label %arm_0
i64 1, label %arm_1
i64 2, label %arm_2
]
arm_0:
br label %join
arm_1:
br label %join
arm_2:
br label %join
dflt:
unreachable
join:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define void @drop_raw_buf_RawBuf(ptr %p) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define void @partial_drop_raw_buf_RawBuf(ptr %p, i64 %mask) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define void @drop_series_Series__6ddcf58f(ptr %p) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
%tag = load i64, ptr %p, align 8
switch i64 %tag, label %dflt [
i64 0, label %arm_0
]
arm_0:
%a0 = getelementptr inbounds i8, ptr %p, i64 8
%v1 = load ptr, ptr %a0, align 8
call void @drop_raw_buf_RawBuf(ptr %v1)
br label %join
dflt:
unreachable
join:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define void @partial_drop_series_Series__6ddcf58f(ptr %p, i64 %mask) {
entry:
%is_null = icmp eq ptr %p, null
br i1 %is_null, label %ret, label %live
live:
%tag = load i64, ptr %p, align 8
switch i64 %tag, label %dflt [
i64 0, label %arm_0
]
arm_0:
%b0 = and i64 %mask, 1
%s1 = icmp ne i64 %b0, 0
br i1 %s1, label %after_0_0, label %do_0_0
do_0_0:
%a2 = getelementptr inbounds i8, ptr %p, i64 8
%v3 = load ptr, ptr %a2, align 8
call void @drop_raw_buf_RawBuf(ptr %v3)
br label %after_0_0
after_0_0:
br label %join
dflt:
unreachable
join:
call void @ailang_rc_dec(ptr %p)
br label %ret
ret:
ret void
}
define i32 @main() {
call i8 @ail_hello_main()
ret i32 0
}