feat(sim): describe_project — the frozen IR as a protocol description - #15
Conversation
Milestone 1a of the playground simulation (docs: design/playground-simulation.md).
`describe_project(files)` returns a `ProjectShape`: per schema, the
`::`-namespace, `ir_hash`, every protocol (name, framing from `@framing`,
functions), errors (ordinal, name, message, fields) and types (structs /
enums) — all read straight off the frozen units `interpret_project`
already produces. No new `comline-core` surface.
Function shapes carry the 0-based index (the `Call` id `resolveKind`
matches), `oneway` (`_return` is None), args and return as a `TypeRef`
(`prim` / `ref` / `array` / `unit` / `union` — classified from the
`Namespaced("T[]")` strings the freezer emits), and `throws` joined to
the error table.
`ir_hash` is `comline_core::schema::ir::frozen::schema_ir_hash(units)` —
the exact call both generators make — so a sim connection's handshake
mirrors a real one. Verified: `describe_project`'s `ir_hash` equals the
`IR_HASH` constant `generate_project` emits for the same schema.
`shape.ts` mirrors the output 1:1; the worker gains a `describeProject`
command. No UI yet (that's 1d).
| const PRIM_NAMES: &[&str] = &[ | ||
| "bool", "u8", "u16", "u32", "u64", "u128", "s8", "s16", "s32", "s64", "s128", "f32", "f64", | ||
| "float", "str", "string", | ||
| ]; |
There was a problem hiding this comment.
Primitive names often get repeated across repositories, i wonder if it can be improved with some single source of truth
There was a problem hiding this comment.
Good catch — turns out the list wasn't just duplicated, it was doing nothing.
name_ref only needs to answer "is this a type declared in this project?" (render its fields) vs. "anything else" (one scalar input). The grammar reserves the primitive keywords, so a declared struct/enum name can never be u64/string/etc. — meaning known.contains(n) is already the whole decision. A primitive falls through to the same Prim arm as an unresolved import, which is the intended fallback for both.
So I dropped the list entirely rather than centralizing it — known (built from the frozen IR) is the single source of truth. comline-core does keep its own private PRIMITIVE_NAMES in validation::validator; making that pub would be the fix if a real need for a shared list comes up, but it'd be a core-lockstep bump for a 16-element array, so not now.
Pushed as 962d80e; output is byte-identical (the 1a smoke still passes, including nested string[]).
Per PR review — it duplicated knowledge that lives in comline-core (which keeps its own private copy in validation::validator). It was also redundant: the grammar reserves the primitive keywords, so a declared struct/enum name can never be `u64` / `string` / etc. `name_ref` now only asks whether a name is a type declared in this project (the IR-built `known` set); anything else — a primitive or an unresolved import — renders as one scalar input, which is the intended fallback either way. Output is byte-identical: the 1a smoke (indices, oneway, throws, nested `string[]`, ir_hash parity) still passes.
Milestone 1a of playground simulation — the one read-only WASM function the simulator is built on.
describe_project(files)→ProjectShape: per schema, the::-namespace,ir_hash, every protocol (name, framing from@framing, functions), errors, and types (structs / enums). All read off the frozen unitsinterpret_projectalready produces — no newcomline-coresurface.Function shapes carry:
index— 0-based position = theCallidresolveKindmatches (same order as the generatedCHAT_CALLS)oneway—_returnisNoneargs/returnsas aTypeRef(prim/ref/array/unit/union), classified from theNamespaced("T[]")strings the freezer emits; struct/enum names resolve project-wide so a cross-file type still reads asrefthrows—u16ordinals joined to the error table byordinalir_hash parity — the risk the spec flagged
ir_hashiscomline_core::schema::ir::frozen::schema_ir_hash(units)— the exact callcomline-codegen-rustandcomline-codegen-typescriptboth make. Verified against the built wasm:describe_project(chat+types).schemas[chat].ir_hash===theIR_HASHconstantgenerate_project(…, "typescript")emits. Identical by construction; the field doc records the invariant.Also confirmed: arrays freeze as
KindValue::Namespaced("T[]")— the spec's open question.TypeRefhandles the[]suffix; the doc's "unconfirmed" note can drop.Scope
shape.tsmirrors the output 1:1; the worker gains adescribeProjectcommand. No UI — that's 1d.wasm-pack build+tsc --noEmit+vite buildgreen; the 1a acceptance assertions (protocol / indices / oneway / throws / ir_hash parity) pass against the built binary.