iter embedding-abi-m1.1 (PARTIAL 3/7): schema + surface + baseline prerequisites; plan Repair
Tasks 1-3 of docs/plans/embedding-abi-m1.1.md, a verified known-good subset (cargo build --workspace exit 0; full workspace green; the roundtrip_cli all-examples gate green): - Task 1: CLI build-path MissingEntryMain baseline pin (examples/embed_noentry_baseline.ail + embed_missing_main_baseline.rs; triple-assertion, layered on the green codegen-unit pin lib.rs:3314). - Task 2: additive FnDef.export: Option<String> (serde default + skip_serializing_if, modelled on FnDef.doc); compile-driven thread of export: None across ~85 FnDef/AstFnDef literals / 18 files incl. all in-source #[cfg(test)] mod tests + drift/hash/spec-drift literals + the codegen lib.rs:3320 in-source pin; hash-stability golden pin; DESIGN.md fn-JSON "export" line. DONE_WITH_CONCERNS (plan symbol content_hash_fn -> def_hash per hash_pin.rs, plan- pseudo-vs-reality class, plan corrected). - Task 3: Form-A (export "<sym>") modifier — parse_export + parse_fn thread + write_fn_def emission + form_a.md grammar; byte-identical round-trip. Task 4 BLOCKED (Boss plan-defect: fixtures declared module != file stem; AILang's loader hard-enforces module==stem at workspace.rs:438, so ail check panicked on load before the gate). Boss resolution (Option 2, overriding the orchestrator's Option 1, rationale in the journal + plan Design-decision 6): keep descriptive embed_* filenames, rename fixture MODULES to their stems — the C symbol backtest_step stays via (export ...), demonstrating spec Decision 2's mangling- decoupling rather than violating it; archive becomes libembed_backtest_step.a, internal symbol @ail_embed_backtest_step_step, host.c unchanged. Plan fixed (Design-decision 6 + Task-4 module==stem + Task-5/6/7 dependent strings + the no-*. Float-head + content_hash_fn concerns folded). Headline fixture corrected; blocked-Task-4 WIP discarded (recreated by the [4,7] re-dispatch from the fixed plan). PARTIAL commit (not the iter's final commit): the implement Repair path mandates committing the known-good subset so the [4,7] re-dispatch starts from a clean tree that includes Tasks 1-3 (Tasks 4-7 structurally depend on the schema field + surface). INDEX line added when the full iter lands post-re-dispatch.
This commit is contained in:
@@ -460,6 +460,31 @@ impl<'a> Parser<'a> {
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn parse_export(&mut self) -> Result<String, ParseError> {
|
||||
self.expect_lparen("export-attr")?;
|
||||
self.expect_keyword("export")?;
|
||||
let s = match self.peek().cloned() {
|
||||
Some(Token { tok: Tok::Str(s), .. }) => {
|
||||
self.cur += 1;
|
||||
s
|
||||
}
|
||||
Some(t) => {
|
||||
return Err(ParseError::Unexpected {
|
||||
expected: "string literal (export C symbol)".into(),
|
||||
got: tok_label(&t.tok),
|
||||
pos: t.span.start,
|
||||
});
|
||||
}
|
||||
None => {
|
||||
return Err(ParseError::UnexpectedEof {
|
||||
expected: "string literal (export C symbol)".into(),
|
||||
});
|
||||
}
|
||||
};
|
||||
self.expect_rparen("export-attr")?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn parse_ctor(&mut self) -> Result<Ctor, ParseError> {
|
||||
self.expect_lparen("ctor-decl")?;
|
||||
self.expect_keyword("ctor")?;
|
||||
@@ -479,6 +504,7 @@ impl<'a> Parser<'a> {
|
||||
self.expect_keyword("fn")?;
|
||||
let name = self.expect_ident("fn name")?;
|
||||
let mut doc: Option<String> = None;
|
||||
let mut export: Option<String> = None;
|
||||
let mut ty: Option<Type> = None;
|
||||
let mut params: Option<Vec<String>> = None;
|
||||
let mut body: Option<Term> = None;
|
||||
@@ -493,6 +519,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
doc = Some(self.parse_doc()?);
|
||||
}
|
||||
Some("export") => {
|
||||
if export.is_some() {
|
||||
return Err(self.duplicate_clause_err("fn-def", &format!("fn `{name}`"), "export"));
|
||||
}
|
||||
export = Some(self.parse_export()?);
|
||||
}
|
||||
Some("suppress") => suppress.push(self.parse_suppress_attr()?),
|
||||
Some("type") => {
|
||||
if ty.is_some() {
|
||||
@@ -517,7 +549,7 @@ impl<'a> Parser<'a> {
|
||||
return Err(ParseError::Production {
|
||||
production: "fn-def",
|
||||
message: format!(
|
||||
"unknown fn attribute `{other}`; expected `doc`, `suppress`, `type`, `params`, or `body`"
|
||||
"unknown fn attribute `{other}`; expected `doc`, `export`, `suppress`, `type`, `params`, or `body`"
|
||||
),
|
||||
pos,
|
||||
});
|
||||
@@ -547,6 +579,7 @@ impl<'a> Parser<'a> {
|
||||
params,
|
||||
body,
|
||||
doc,
|
||||
export,
|
||||
suppress,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -156,6 +156,13 @@ fn write_fn_def(out: &mut String, fd: &FnDef, level: usize) {
|
||||
write_string_lit(out, doc);
|
||||
out.push(')');
|
||||
}
|
||||
if let Some(export) = &fd.export {
|
||||
out.push('\n');
|
||||
indent(out, level + 1);
|
||||
out.push_str("(export ");
|
||||
write_string_lit(out, export);
|
||||
out.push(')');
|
||||
}
|
||||
// Iter 19b: emit one `(suppress ...)` clause per entry, after the
|
||||
// doc string and before the type. Round-trip stable: parser
|
||||
// re-reads each clause back into [`FnDef::suppress`].
|
||||
@@ -779,6 +786,7 @@ mod tests {
|
||||
params: vec!["x".into()],
|
||||
body: Term::Var { name: "x".into() },
|
||||
doc: None,
|
||||
export: None,
|
||||
suppress: vec![],
|
||||
})],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user