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
This commit is contained in:
@@ -942,10 +942,10 @@ fn workspace_lists_imported_modules() {
|
||||
|
||||
let modules = v["modules"].as_array().expect("modules must be array");
|
||||
// the loader auto-injects every built-in kernel-tier module
|
||||
// (`prelude` and, since raw-buf.4, the first real-payload kernel
|
||||
// extension `raw_buf`), so the count is the user's two modules plus
|
||||
// the two built-ins.
|
||||
assert_eq!(modules.len(), 4, "expected 4 modules: {stdout}");
|
||||
// (`prelude`; `raw_buf` since raw-buf.4; and `series`, the first pure
|
||||
// AILang library extension, since feat-series-step1), so the count is
|
||||
// the user's two modules plus the three built-ins.
|
||||
assert_eq!(modules.len(), 5, "expected 5 modules: {stdout}");
|
||||
|
||||
let names: Vec<&str> = modules
|
||||
.iter()
|
||||
@@ -955,6 +955,7 @@ fn workspace_lists_imported_modules() {
|
||||
assert!(names.contains(&"ws_lib"), "ws_lib missing: {names:?}");
|
||||
assert!(names.contains(&"prelude"), "prelude missing: {names:?}");
|
||||
assert!(names.contains(&"raw_buf"), "raw_buf missing: {names:?}");
|
||||
assert!(names.contains(&"series"), "series missing: {names:?}");
|
||||
}
|
||||
|
||||
/// Guards Iter 5b: `ail check examples/ws_main.ail.json --json` must
|
||||
|
||||
@@ -31,6 +31,8 @@ declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
@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
|
||||
@@ -117,6 +119,45 @@ entry:
|
||||
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
|
||||
@@ -191,6 +232,58 @@ 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()
|
||||
|
||||
@@ -32,6 +32,8 @@ declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
@ail_prelude_float_ge_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ge_adapter, ptr null }
|
||||
@ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null }
|
||||
@ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_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 i64 @ail_list_sum_list(ptr %arg_xs) {
|
||||
entry:
|
||||
%v1 = load i64, ptr %arg_xs, align 8
|
||||
@@ -254,6 +256,45 @@ entry:
|
||||
ret i8 %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
|
||||
@@ -328,6 +369,58 @@ 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_list_main()
|
||||
|
||||
@@ -35,6 +35,7 @@ declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
@ail_prelude_gt__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_gt__Int_adapter, ptr null }
|
||||
@ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null }
|
||||
@ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null }
|
||||
@ail_prelude_lt__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_lt__Int_adapter, ptr null }
|
||||
define i64 @ail_max3_max(i64 %arg_a, i64 %arg_b) {
|
||||
entry:
|
||||
%v1 = call i1 @ail_prelude_gt__Int(i64 %arg_a, i64 %arg_b)
|
||||
@@ -241,6 +242,18 @@ entry:
|
||||
ret i8 %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
|
||||
@@ -315,6 +328,58 @@ 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_max3_main()
|
||||
|
||||
@@ -28,6 +28,8 @@ declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
@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 }
|
||||
@ail_prelude_eq__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_eq__Int_adapter, ptr null }
|
||||
@ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null }
|
||||
@ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null }
|
||||
@@ -105,6 +107,45 @@ entry:
|
||||
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 i1 @ail_prelude_eq__Int(i64 %arg_x, i64 %arg_y) alwaysinline {
|
||||
entry:
|
||||
%v1 = icmp eq i64 %arg_x, %arg_y
|
||||
@@ -219,6 +260,58 @@ 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 i64 @ail_sum_sum(i64 %arg_n) {
|
||||
entry:
|
||||
%v1 = call i1 @ail_prelude_eq__Int(i64 %arg_n, i64 0)
|
||||
|
||||
@@ -28,6 +28,8 @@ declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
@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 }
|
||||
@ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null }
|
||||
@ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null }
|
||||
@ail_ws_lib_add_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_ws_lib_add_adapter, ptr null }
|
||||
@@ -104,6 +106,45 @@ entry:
|
||||
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 ptr @ail_prelude_show__Int(i64 %arg_x) {
|
||||
entry:
|
||||
%v1 = call ptr @ailang_int_to_str(i64 %arg_x)
|
||||
@@ -206,6 +247,58 @@ 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 i64 @ail_ws_lib_add(i64 %arg_a, i64 %arg_b) {
|
||||
entry:
|
||||
%v1 = add i64 %arg_a, %arg_b
|
||||
|
||||
@@ -30,7 +30,21 @@ fn monomorphise_workspace_is_identity_on_class_free_workspace() {
|
||||
"module set must be identical"
|
||||
);
|
||||
// Per-module def list unchanged (compare by canonical-JSON hash).
|
||||
//
|
||||
// Exception: `prelude` is no longer hash-identical through mono for
|
||||
// ANY entry since feat-series-step1. The auto-imported `series`
|
||||
// kernel module is a real-bodied (non-intrinsic) consumer of the
|
||||
// prelude polyfns `lt`/`compare` over `Int`, so the workspace-wide
|
||||
// mono pass now materialises `lt__Int` / `compare__Int` into the
|
||||
// prelude module regardless of the user entry. That is a concrete
|
||||
// call site driven by an auto-imported library module, not gratuitous
|
||||
// mutation — the test's real invariant (mono does not rewrite modules
|
||||
// with no work to do) holds for every other module. `series` itself
|
||||
// is excluded for the same reason: it may gain its own specialisations.
|
||||
for (mname, m) in &ws.modules {
|
||||
if mname == "prelude" || mname == "series" {
|
||||
continue;
|
||||
}
|
||||
let before_m = &before.modules[mname];
|
||||
let h_after = ailang_core::module_hash(m);
|
||||
let h_before = ailang_core::module_hash(before_m);
|
||||
@@ -72,8 +86,18 @@ fn monomorphise_workspace_is_identity_when_no_concrete_call_sites() {
|
||||
"module set must be identical"
|
||||
);
|
||||
// Each module hashes byte-identical — no synth fns appended
|
||||
// because no call site triggered a target.
|
||||
// because no class-method call site triggered a target.
|
||||
//
|
||||
// Exception: `prelude` and `series` — see the sibling test
|
||||
// `monomorphise_workspace_is_identity_on_class_free_workspace` for
|
||||
// the rationale. The auto-imported, real-bodied `series` kernel
|
||||
// module pins `lt__Int` / `compare__Int` specialisations into
|
||||
// `prelude` for every workspace; that is a legitimate concrete call
|
||||
// site, orthogonal to this test's typeclass-call-site invariant.
|
||||
for (mname, m) in &ws_after.modules {
|
||||
if mname == "prelude" || mname == "series" {
|
||||
continue;
|
||||
}
|
||||
let before_m = &before.modules[mname];
|
||||
let h_after = ailang_core::module_hash(m);
|
||||
let h_before = ailang_core::module_hash(before_m);
|
||||
|
||||
Reference in New Issue
Block a user