iter raw-buf.4 rawbuf-payload-termnew-desugar (DONE, drop-call deferred to .5): RawBuf works, prints 60 (refs #7)
Ships RawBuf end-to-end as a consumer of the raw-buf.3 scope-qualified
intrinsic mechanism, plus the general Term::New construction sugar.
Working subset committed; the drop-CALL ratification (no-leak) is
re-carved to raw-buf.5 (see b49f57d) — the flat drop FUNCTION ships here,
its call-insertion needs a codegen resolution mechanism.
What ships (all green):
- raw_buf kernel-tier submodule (crates/ailang-kernel/src/raw_buf/):
RawBuf TypeDef (param-in {Int,Float,Bool}, ctor B a) + four
(intrinsic) ops new/get/set/size. parse_raw_buf + workspace injection
(kernel-tier auto-imported); workspace count 4 -> 5.
- 12 scope-qualified INTERCEPTS entries RawBuf_{new,get,set,size}__{Int,
Float,Bool} + emit fns: new allocs an @ailang_rc_alloc slab
(8-byte i64 size header + n*width element bytes), get/set
getelementptr+load/store at offset 8 + i*width, size loads the header.
Mechanical on the raw-buf.3 naming + bijection machinery; bijection
green (4 markers -> 12 entries).
- Term::New desugar (crates/ailang-core/src/desugar.rs): (new T <types>
<values>) -> (app T.new <values>), runs before check so the
type-scoped callee flows through the raw-buf.3 scope threading to
RawBuf_new__T; drops the NewArg::Type (element type inferred from
use). Both codegen Term::New deferral arms removed (replaced with
unreachable!). Ratified by new_stubt_builds_and_runs.
- Flat intrinsic-storage drop FUNCTION @drop_raw_buf_RawBuf (single
@ailang_rc_dec on the slab), emitted for any TypeDef whose new op is
(intrinsic)-bodied — distinguishes RawBuf (intrinsic new) from StubT
(real-body new -> generic ADT drop).
- E2E: raw_buf_int (-> 60), raw_buf_float (-> 4.0), raw_buf_bool
(-> 42), raw_buf_param_in_reject (param-not-in-restricted-set).
In-scope additions beyond the literal plan (both sound, ratified):
- qualify_workspace_term now normalises a monomorphic cross-module
type-scoped callee (StubT.new) to <home>.f; without it
new_stubt_builds_and_runs cannot build (StubT.new is monomorphic, so
the raw-buf.3 poly-mono path mints no symbol). Same-module + polymorphic
callees carved out.
- diagnostic-behaviour: (new T ..) missing-new-op now surfaces
type-scoped-member-not-found (desugar runs before check, bypassing
synth's Term::New arm); new-arg-kind-mismatch obsoleted. Two unit
tests updated to the new behaviour. param-in reject unaffected.
The 5 .ll snapshots gained @drop_raw_buf_RawBuf (+ partial) — injecting
raw_buf emits its drop fn into every program; benign, regenerated to the
final IR. (The plan's "snapshots stay green" assumption was wrong.)
Verification (orchestrator, this session): cargo test --workspace 676
passed / 0 failed / 2 ignored. raw_buf_int_e2e prints 60; bijection,
round-trip, new_stubt, float/bool/reject all green. The raw_buf_no_leak
test is NOT in this commit — it moves to raw-buf.5 with the drop-call
resolution that makes it pass (the slab currently leaks at scope close;
tracked, fixed next iter; milestone not released until close).
This commit is contained in:
+70
-4
@@ -95,6 +95,17 @@ fn answer_intrinsic_builds_and_runs_printing_42() {
|
||||
assert_eq!(out.trim(), "42");
|
||||
}
|
||||
|
||||
/// raw-buf.4: the general `Term::New` desugar. `(new StubT 42)`
|
||||
/// desugars to `(app StubT.new 42)` (StubT.new has a real
|
||||
/// `(term-ctor StubT Stub x)` body, so it builds independent of
|
||||
/// RawBuf), the Int is matched back out and printed. Ratifies the
|
||||
/// desugar + the removal of both codegen `Term::New` deferral arms.
|
||||
#[test]
|
||||
fn new_stubt_builds_and_runs() {
|
||||
let out = build_and_run("new_stubt_smoke.ail");
|
||||
assert_eq!(out.trim(), "42");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loop_recur_sum_to_runs_to_value() {
|
||||
let stdout = build_and_run("loop_sum_to_run.ail");
|
||||
@@ -864,10 +875,11 @@ 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 prep.3 of the kernel-extension-mechanics
|
||||
// milestone, the ratifying `kernel_stub`), so the count is the
|
||||
// user's two modules plus the two built-ins.
|
||||
assert_eq!(modules.len(), 4, "expected 4 modules: {stdout}");
|
||||
// (`prelude`; since prep.3 of the kernel-extension-mechanics
|
||||
// milestone, the ratifying `kernel_stub`; and since raw-buf.4 the
|
||||
// first real-payload kernel extension `raw_buf`), 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()
|
||||
@@ -877,6 +889,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(&"kernel_stub"), "kernel_stub missing: {names:?}");
|
||||
assert!(names.contains(&"raw_buf"), "raw_buf missing: {names:?}");
|
||||
}
|
||||
|
||||
/// Guards Iter 5b: `ail check examples/ws_main.ail.json --json` must
|
||||
@@ -2210,6 +2223,59 @@ fn build_and_run_with_rc_stats(example: &str) -> (String, u64, u64, i64) {
|
||||
)
|
||||
}
|
||||
|
||||
/// raw-buf.4 worked consumer: a 3-slot Int RawBuf filled 10/20/30,
|
||||
/// summed and printed. The end-to-end acceptance criterion — parse →
|
||||
/// check → desugar `(new RawBuf …)` → mono `RawBuf_{new,set,get}__Int`
|
||||
/// → intercept-routed codegen (alloc/store/load over the slab) →
|
||||
/// native `60`.
|
||||
#[test]
|
||||
fn raw_buf_int_e2e() {
|
||||
let out = build_and_run("raw_buf_int.ail");
|
||||
assert_eq!(out.trim(), "60");
|
||||
}
|
||||
|
||||
/// raw-buf.4 Float variant: a 2-slot Float RawBuf (1.5 + 2.5),
|
||||
/// exercising the `double` load/store emits. Prints `4.0` (the `%g`
|
||||
/// whole-double `.0` fallback).
|
||||
#[test]
|
||||
fn raw_buf_float_e2e() {
|
||||
let out = build_and_run("raw_buf_float.ail");
|
||||
assert_eq!(out.trim(), "4.0");
|
||||
}
|
||||
|
||||
/// raw-buf.4 Bool variant: a 1-slot Bool RawBuf storing `true`, read
|
||||
/// back and discriminated to an Int. Catches the `i1` store/load
|
||||
/// syntax and the width-1 element offset.
|
||||
#[test]
|
||||
fn raw_buf_bool_e2e() {
|
||||
let out = build_and_run("raw_buf_bool.ail");
|
||||
assert_eq!(out.trim(), "42");
|
||||
}
|
||||
|
||||
/// raw-buf.4 must-fail: `(con RawBuf (con Str))` violates the
|
||||
/// `param-in (a Int Float Bool)` restriction. `ail check` exits
|
||||
/// non-zero with the prep.3 `param-not-in-restricted-set` diagnostic.
|
||||
#[test]
|
||||
fn raw_buf_param_in_reject_e2e() {
|
||||
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
|
||||
let src = workspace.join("examples").join("raw_buf_reject_str.ail");
|
||||
let output = Command::new(ail_bin())
|
||||
.args(["check", src.to_str().unwrap()])
|
||||
.output()
|
||||
.expect("ail check failed to run");
|
||||
assert!(
|
||||
!output.status.success(),
|
||||
"ail check must reject RawBuf<Str>"
|
||||
);
|
||||
let stderr = String::from_utf8(output.stderr).expect("stderr utf8");
|
||||
assert!(
|
||||
stderr.contains("param-not-in-restricted-set"),
|
||||
"expected param-not-in-restricted-set, stderr: {stderr}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// explicit-mode tail-recursive list-sum must
|
||||
/// not leak the LCons outer cells.
|
||||
///
|
||||
|
||||
@@ -249,6 +249,28 @@ 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 i32 @main() {
|
||||
call i8 @ail_hello_main()
|
||||
|
||||
@@ -385,6 +385,28 @@ 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 i32 @main() {
|
||||
call i8 @ail_list_main()
|
||||
|
||||
@@ -373,6 +373,28 @@ 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 i32 @main() {
|
||||
call i8 @ail_max3_main()
|
||||
|
||||
@@ -277,6 +277,28 @@ 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 i64 @ail_sum_sum(i64 %arg_n) {
|
||||
entry:
|
||||
%v1 = call i1 @ail_prelude_eq__Int(i64 %arg_n, i64 0)
|
||||
|
||||
@@ -264,6 +264,28 @@ 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 i64 @ail_ws_lib_add(i64 %arg_a, i64 %arg_b) {
|
||||
entry:
|
||||
%v1 = add i64 %arg_a, %arg_b
|
||||
|
||||
Reference in New Issue
Block a user