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:
@@ -923,16 +923,32 @@ impl Desugarer {
|
||||
}));
|
||||
in_full
|
||||
}
|
||||
Term::New { type_name, args } => Term::New {
|
||||
type_name: type_name.clone(),
|
||||
args: args
|
||||
Term::New { type_name, args } => {
|
||||
// raw-buf.4: (new T <types…> <values…>) desugars to
|
||||
// (app T.new <values…>) — a type-scoped call so synth's
|
||||
// dotted-name branch resolves it through the
|
||||
// TypeDef-first ladder and the raw-buf.3 scope threading
|
||||
// mints `T_new__<elem>`. The leading NewArg::Type is
|
||||
// dropped: the AST carries no type-args on App, and the
|
||||
// element type is recovered by ordinary inference from
|
||||
// how the result is used (spec § Term::New desugar).
|
||||
// Runs before check, so no Term::New reaches the
|
||||
// type-checker or codegen.
|
||||
let value_args: Vec<Term> = args
|
||||
.iter()
|
||||
.map(|arg| match arg {
|
||||
NewArg::Value(v) => NewArg::Value(self.desugar_term(v, scope)),
|
||||
NewArg::Type(t) => NewArg::Type(t.clone()),
|
||||
.filter_map(|arg| match arg {
|
||||
NewArg::Value(v) => Some(self.desugar_term(v, scope)),
|
||||
NewArg::Type(_) => None,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
.collect();
|
||||
Term::App {
|
||||
callee: Box::new(Term::Var {
|
||||
name: format!("{type_name}.new"),
|
||||
}),
|
||||
args: value_args,
|
||||
tail: false,
|
||||
}
|
||||
}
|
||||
Term::Intrinsic => t.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,3 +772,23 @@ fn kernel_stub_module_round_trips() {
|
||||
}).expect("kernel_stub ships the peek ratifier op (raw-buf.3)");
|
||||
assert!(matches!(peek.body, Term::Intrinsic), "peek is an (intrinsic) marker");
|
||||
}
|
||||
|
||||
/// raw-buf.4: pin the JSON byte-shape of the raw_buf kernel-tier
|
||||
/// base-extension module. Mirror of `kernel_stub_module_round_trips`.
|
||||
#[test]
|
||||
fn raw_buf_module_round_trips() {
|
||||
let m = ailang_surface::parse_raw_buf();
|
||||
assert!(m.kernel, "raw_buf is kernel-tier");
|
||||
assert_eq!(m.name, "raw_buf");
|
||||
let json = serde_json::to_value(&m).expect("serialise raw_buf");
|
||||
let recovered: Module =
|
||||
serde_json::from_value(json).expect("raw_buf round-trips through serde");
|
||||
assert!(recovered.kernel);
|
||||
assert_eq!(recovered.name, "raw_buf");
|
||||
let td = recovered.defs.iter().find_map(|d| match d {
|
||||
Def::Type(t) if t.name == "RawBuf" => Some(t),
|
||||
_ => None,
|
||||
}).expect("RawBuf TypeDef present");
|
||||
let allowed = td.param_in.get("a").expect("RawBuf.a restricted");
|
||||
assert!(allowed.contains("Int") && allowed.contains("Float") && allowed.contains("Bool"));
|
||||
}
|
||||
|
||||
@@ -49,13 +49,15 @@ fn loads_example_workspace_happy_path() {
|
||||
assert_eq!(ws.entry, "ws_main");
|
||||
assert!(ws.modules.contains_key("ws_main"));
|
||||
assert!(ws.modules.contains_key("ws_lib"));
|
||||
// the loader auto-injects two built-in kernel-tier modules
|
||||
// (`prelude` and `kernel_stub` — see prep.3 of the
|
||||
// kernel-extension-mechanics milestone), so the count is the
|
||||
// user's two modules plus those two.
|
||||
assert_eq!(ws.modules.len(), 4);
|
||||
// the loader auto-injects three built-in kernel-tier modules
|
||||
// (`prelude`, `kernel_stub` — see prep.3 of the
|
||||
// kernel-extension-mechanics milestone — and `raw_buf`, the
|
||||
// first real-payload kernel extension, raw-buf.4), so the count
|
||||
// is the user's two modules plus those three.
|
||||
assert_eq!(ws.modules.len(), 5);
|
||||
assert!(ws.modules.contains_key("prelude"));
|
||||
assert!(ws.modules.contains_key("kernel_stub"));
|
||||
assert!(ws.modules.contains_key("raw_buf"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user