FS3: CkLang StdoutLog provider — Log::info runs freestanding #43
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/043-fs3-cklang-stdoutlog-provider-log-info-runs-fr"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
FS3: CkLang StdoutLog provider — Log::info runs freestanding
Along the way:
fn rec<N>recursion-depth spelling (owner decision)Touches 94 files:
current-state.md,docs/errors/E0901.md,docs/errors/E0902.md,docs/impl/memory-model/arenas.md,scripts/clean.sh,src/rust/crates/ck_driver/src/compile/fn_main.rsand 88 more.Nothing outside calls
exec. It is pub(crate) insrc/rust/crates/ck_driver/src/container.rsnow.Approving. I would have split
src/rust/crates/ck_driver/src/container.rsdifferently, but not enough to hold this up.@ -111,3 +159,3 @@/// [`ContainerError`] if `docker` cannot be spawned. A non-zero *program* exit/// is **not** an error — it is the returned code (the program's value).pub fn exec(name: &str, bin: &str) -> Result<i32, ContainerError> {pub fn exec(name: &str, work_subdir: &str, bin: &str) -> Result<i32, ContainerError> {execis public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.The payoff of Phase FS-2: `fn main() -> Unit effect Log { Log::info("Hello, world") }` compiles, runs freestanding (no libc, no ck_rt), prints `Hello, world` via a real write syscall, exits 0. - stdlib (promote into live tests/corpus/stdlib): StdoutLog.ck rewritten from six `= intrinsic` ops to real CkLang — `fn info(msg) { Sys::write(1, msg) }` (raw message; the level prefix needs String::concat, rides the operators arc). Log.ck + Log.ckh (effect Log + LogLevel/LogLine) promoted. String.ck/Bytes.ck stay in stdlib_old (String is builtin; both carry ck_rt-backed = intrinsic bodies that don't lower freestanding — the doc's Promotes list is aspirational for FS3). - codegen/call.rs (new): the SHARED intrinsic-call site emit_intrinsic_call + emit_syscall_leaf — checks syscall_spec before intrinsic_target, emits `call ck_syscall(nr, …)`. Lifted out of the freestanding-only module so a syscall leaf emits uniformly from ck_entry, a user fn, or (later) an actor. - codegen/freestanding.rs: emit_fn_main_object_freestanding now REUSES user_fn::emit_user_fns + emit_effect — only ck_entry + the LinkMode predicate (fn_main_is_freestanding: freestanding iff no reachable leaf is a ck_rt symbol) are freestanding-specific. THIN FORK held (201 lines). - driver/compile/fn_main.rs (new): try_emit_fn_main + resolve_fn_main + lower_dispatched_providers (cross-module lowering of CkLang provider fns) + emit_by_link_mode. Split from compile/mod.rs (no LoC cap raised). - Gate: tests/corpus/freestanding_log + freestanding_log_run.rs; in RUNTIME_TESTED + LIVE_STDLIB_APPS. Corpus reconcile self-closes the live stdlib. Two-link-mode contract: Log/StdoutLog deliberately live in BOTH stdlib dirs during the transition (= intrinsic form for the libc apps which have no ck_syscall; CkLang form for freestanding) — FS8 deletes the = intrinsic form. stdlib_old/README.md corrected to state this real invariant (was: "never hold the same live unit"). Observed: freestanding `Hello, world`, exit 0, 9040-byte static ELF, empty NEEDED, empty `nm -u`, no ck_rt/printf/malloc/__libc. Libc path (helloWorld 2.1 MB, greeter) confirmed green. Gates (all green): fmt pass; clippy 0 warnings; cargo test --workspace exit 0 (no libtest failures); R1-R4 arch caps pass (split, not raised); Docker e2e green. Docs: stdlib.md §8 FS3 -> DONE; current-state.md FS3 note; stdlib_old/README.md.fn rec<N>recursion-depth spelling (owner decision) e39a6da247The compiler statically CALCULATES an actor's arena size from its reachable bounded types, per docs/impl/memory-model/arenas.md. The reusable, correctness- critical composition core + function-frame sizing; recursion/mailbox/captures + per-actor assembly are FS5.1, --mem surfacing is FS5. - ck_types/src/arena_size/: type_size(&Ty) -> TypeSize { bounded_bytes, unbounded: Vec<UnboundedComponent{path,ty,reason}> }; frame_size (Σ of a fn's locals); arena_size -> ArenaSize { state, call_stack{frame,recursion_depth}, mailbox{max_messages,message_size}, unbounded }. Lives in ck_types (owns type layout); InternerLayout adapter is the driver-consumable query FS5's --mem calls. recursion_depth (default 1) + mailbox factors (default 0) exposed as NAMED factors so FS5.1 fills them without reshaping the API. - Composition: record = Σ fields; variant/data = max of cases + one tag word; bounded List<T,N> = handle + N×stride(T); scalars fixed. Widths reconciled with codegen::record::value_width (Int=8, String handle=16, tag=8); the calc adds the out-of-line N×stride list buffer codegen allocs. - HONESTY: an unbounded type (bare String, List<T> without N, Unknown, generic Var, Fn, named-payload variant not collected by the front-end, recursive-type cycle) yields an UnboundedComponent with a reason — NEVER a fabricated number. Bounded List<T,N>'s N IS representable today (ConstValue::Int in the nominal args), so bounded lists are fully sizable. - 77 exact-byte unit tests: scalars, records (sum, mixed/sub-word widths, field- order independence), variants (max+tag, the sum-vs-max distinguisher 24-not-32, not-first-wins), bounded lists (N=0/1/4/12, record stride), deep nesting, recursion cycle-detection, frames + assembly + named factors, and the InternerLayout real adapter end-to-end. Combined with FS5.1 this exceeds the owner's ≥100 floor. - Invariant (documented): calculated bounded_bytes ≥ runtime ArenaHighWater for a fully-bounded actor; today's corpus uses bare String (growable interim) so it reports unbounded components — not a clean validation target until String<N>. Gates (all green): fmt pass; clippy 0 warnings; cargo test --workspace exit 0 (no libtest failures); R3/R4 caps ok (mod.rs 633 + tests split, no cap raised). Docs: stdlib.md §8 FS5.0 -> DONE; current-state.md arena section.The per-actor "arena = entire size of everything" assembly on FS5.0's core (additive API, no reshape). 116 combined arena tests (≥100 owner floor). - ck_lower/arena.rs: frame_alloc_footprint(body) — body-allocation analysis ("each method's allocations get space"). Counts EXACTLY codegen's arena sites: Record (static frame), List (ck_rt_alloc buffer), String-typed BinaryOp::Add concat. NOT counted: literals (.rodata), param/local refs (registers), scalar Int + (iadd), projections, index-reads, calls (each callee is its own chain node — no double-count). Run-path lowering has empty TypeckResults so a value's type is often absent → reported UntypedAllocation (conservative/honest, never a fabricated number). - ck_types/arena_size/assembly.rs: CallGraph + deepest_chain (bounded = MAX over root→leaf paths of Σ frame bytes — a stack holds one active chain; unbounded collected graph-wide; cycles surfaced Recursive, DAG-only). capture_size + assemble_arena. Pure (Floor-IR-free) so the path math is exactly unit-testable. - ck_driver/compile/mem.rs: actor_arena_size(app, stdlib) -> ArenaSize — the driver query FS5's --mem consumes. - Mailbox + captures: synthetic plumbing only (no send/lambdas in the front-end) — max×size / capture Σ, tested with labelled synthetic inputs, documented as not-wired-from-real-programs. Recursion left at depth 1 (FS5.2). - Real actors: helloWorld → fully bounded, 0 arena bytes (its string is a rodata literal, not an allocation — honest); greeter → unbounded (its greet concat, UntypedAllocation on the run path). Both asserted. - 39 new exact-byte tests (20 ck_types + 16 ck_lower + 3 driver): body-allocation, deepest-chain incl. the max-path-vs-sum distinguisher (106 not 116), mailbox/ capture synthetic, assembly, real-actor queries. Total 116. Note for FS5: the query lowers with empty TypeckResults → UntypedAllocation for typed allocs; --mem should feed the type-checked HIR to get real numbers. Gates (all green): fmt pass; clippy 0 warnings; cargo test --workspace exit 0 (no libtest failures); R3/R4 caps ok (split, not raised). Docs: stdlib.md §8 FS5.1 -> landed; current-state.md arena section.