Add Concrete Syntax for Unstructured Programs in Strata Core#1132
Open
PROgram52bc wants to merge 58 commits into
Open
Add Concrete Syntax for Unstructured Programs in Strata Core#1132PROgram52bc wants to merge 58 commits into
PROgram52bc wants to merge 58 commits into
Conversation
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
Address PR review comments: note that the GOTO backend could be refactored into a two-stage pipeline (structured→cfg, then cfg→GOTO) to eliminate the pattern matching on Procedure.Body.
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
added 5 commits
May 6, 2026 14:08
- Add Body.getCfg accessor (mirrors getStructured) - CoreToCBMC: throw error on CFG body instead of returning [] - StatementEval: interpret CFG bodies by linearizing blocks - Grammar: add comment explaining why 'branch' is used instead of 'if' (DDM registers tokens globally, causing conflict with if-statement)
… with CFG as body
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
PROgram52bc
commented
May 6, 2026
Test 1 — Type-checking rejection: confirms Core.typeCheck rejects a CFG procedure with "expected structured body, got CFG" diagnostic. Test 2 — CFG body preservation: confirms a parsed CFG procedure retains .cfg body (isCfg=true, isStructured=false) with correct entry label and block count, guarding against the prior bug where type-checking collapsed CFG bodies to .structured []. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… type TerminationCheck.lean (from main) constructs a Procedure with body := stmts, but this branch changed Procedure.body from List Statement to Procedure.Body. Wrap with .structured to fix the merge-queue CI build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eBodyExec TODOs The postconditionsValid field in ProcedureCorrect was vacuously true for CFG procedures — the match expression produced [] for CFGs, making CoreStepStar terminate immediately with rho' = rho0. Split into two explicit fields: - postconditionsValid_structured: for structured bodies, uses CoreStepStar on the statement list (preserves existing proven behavior) - postconditionsValid_cfg: for CFG bodies, uses CoreCFGStepStar directly, making the soundness gap explicit and non-vacuous Updated procBodyVerify_procedureCorrect proof to construct all three fields. The CFG field is discharged by contradiction since procToVerifyStmt only succeeds for structured bodies. Added TODO comments on CoreBodyExec documenting: - Should be wired into postconditionsValid_cfg - The cfg constructor drops terminal eval (limiting postcondition support) - An equivalence theorem structured_iff_CoreStepStar would bridge the two representations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ionsValid Add a δ' : CoreEval output parameter to CoreBodyExec so it exposes the terminal evaluator. The structured constructor outputs ρ'.eval; the cfg constructor passes through the initial δ (since CoreCFGStepStar does not track eval changes). This enables unifying postconditionsValid_structured and postconditionsValid_cfg back into a single postconditionsValid field that uses CoreBodyExec to abstract over both body kinds. Updated call_sem to use the terminal eval (δ_final) from CoreBodyExec when checking postconditions, and updated procBodyVerify_procedureCorrect proof to invert the CoreBodyExec.structured constructor and reconcile the initial environment via ProcEnvWF.noFailure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
structural checks (unique labels, entry exists, valid targets) and expression-level type-checking.
- Uses a fuel-measure and throws error on running out of fuel - No path-merging - Added #guard_msg tests 1. Trivial CFG (single finish block) 2. Linear CFG (assignment + goto + postcondition holds) 3. Missing block error 4. Fuel exhaustion on loop back-edge 5. Postcondition failure (non-trivial proof obligation) 6. Diamond CFG with symbolic branch (two paths, two proof obligations with path conditions)
During structured-to-CFG lowering, loop invariants and decreases measures were only preserved as lowered assert commands, losing the connection to the original spec. Downstream CFG passes that need to recover the contract (e.g., for invariant inference or refinement) had no way to distinguish spec-level asserts from user asserts. Add `MetaData.specLoopInvariant` and `MetaData.specDecreases` fields and attach them to the loop entry block's transfer command metadata. The existing assert lowering is preserved (both representations coexist), so this is a non-breaking addition. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The grammar previously accepted `goto label1, label2, ..., labelN;` via CommaSepBy, but the translator rejected >2 targets at translation time. This meant users could write syntactically valid programs that failed during elaboration with a confusing error. Split into two grammar ops: - `transfer_goto (label : Ident)` — unconditional goto (1 target) - `transfer_nondet_goto (label1 : Ident, label2 : Ident)` — nondet (2 targets) The concrete syntax is unchanged: `goto a;` and `goto a, b;` parse as before. `goto a, b, c;` now fails at parse time with a clear syntax error instead of passing through to translation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
translateTransfer now increments the var_def counter after reading it for the $__nondet_N variable name, so multiple nondeterministic gotos in the same procedure get distinct names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 5 instances of the "match body with structured/cfg-error" pattern with the existing getStructured helper, which was defined but unused. Uses .mapError where the caller's error type differs from Except String. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `procedureToGotoCtxViaCFG`, a parallel pipeline that translates Core
procedures to CProver GOTO via the CFG representation:
Structured body → stmtsToCFG → coreCFGToGotoTransform → GOTO
CFG body → coreCFGToGotoTransform → GOTO
This coexists with the existing direct path in `procedureToGotoCtx`, which
remains unchanged.
Changes:
1. CFGToCProverGOTO.lean — close two gaps in `detCFGToGotoTransform`:
- Source locations: transfer command metadata is now used to derive
source locations via `metadataToSourceLoc` (previously ignored as
`_md`).
- Loop contracts: backward-edge GOTOs targeting loop entry blocks are
annotated with `#spec_loop_invariant` and `#spec_decreases` named
fields on the guard, matching CBMC's DFCC expectations. A post-
processing pass detects loop entries (by presence of contract
metadata on their condGoto transfer) and annotates GOTOs whose
target location ≤ source location (i.e., backward edges).
2. CoreToGOTOPipeline.lean — make `renameIdent`, `renameExpr`,
`renameCmd`, and `collectFuncDecls` non-private so the new pipeline
can reuse them.
3. CoreCFGToGOTOPipeline.lean (new) — contains:
- Rename helpers for Core commands (`CmdExt`): `renameCoreCommand`,
`renameCoreStmt`, `renameCoreDetCFG`.
- `coreCFGToGotoTransform`: Core-specific CFG-to-GOTO translation
that handles `CmdExt.call` (emits FUNCTION_CALL instructions) and
delegates `CmdExt.cmd` to `Cmd.toGotoInstructions`. Also handles
source locations and loop contract annotation.
- `procedureToGotoCtxViaCFG`: full pipeline wrapper mirroring
`procedureToGotoCtx` — renaming, type environment, axioms,
distinct declarations, contracts, lifted functions — but routing
through `stmtsToCFG` + `coreCFGToGotoTransform`.
4. E2E_CFGPipeline.lean (new) — 11 equivalence tests that run both
pipelines on the same Core programs and compare:
- Semantic instruction types (DECL, ASSIGN, ASSERT, ASSUME, etc.)
match between direct and CFG paths.
- Contract annotations (#spec_requires, #spec_ensures) match.
- Both paths produce valid, non-null JSON output.
Test programs cover: simple assert, var decl/assign, if-then-else,
contracts, axioms/distinct, free specs, cover, bitvector ops,
assume, multiple commands, and CFG-only output validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
atomb
reviewed
May 14, 2026
added 2 commits
May 14, 2026 12:05
Localized merge. --------- Co-authored-by: David Deng <htd@amazon.com>
Conflicts: - Strata/Transform/StructuredToUnstructured.lean: keep branch's loop-contract metadata (specLoopInvariant/specDecreases pushed to the transfer) and exit metadata propagation, while adopting main's String-only exit label and synthesizedMd-tagged synthesized commands. - Strata/Transform/ProcBodyVerifyCorrect.lean: adopt main's new Config.block (Option String × σ_parent × inner) shape, but keep the branch's destructured `ss : List Statement` (from procToVerifyStmt_is_structured) instead of `proc.body : Procedure.Body`. Follow-on fixes: - ProcBodyVerifyCorrect.lean lines 856/859/862: replace `proc.body` with `ss` so the new wf-preservation lemmas (core_wfVar_preserved, core_wfCong_preserved, core_wfExprCongr_preserved) typecheck. - Loops.lean / Exit.lean snapshots: replace `[fileRange]` tag with `[provenance]` and update shifted byte offsets to match the new Provenance metadata format introduced by #1140.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add Support for Unstructured Programs in Strata Core
Description of changes
Prior to this PR, the only way to obtain unstructured programs was to apply
StructuredToUnstructuredtransformation..core.stfile examples illustrating the syntax of unstructured programs.Procedure.bodyto handle thecfgcase based on the contextAdaptation Methods for
Procedure.bodyUsespipelines, graph-level inlining).
Procedure.Bodysum type.(Bolded items are updates since the initial PR draft)
postconditionsValidadapted withCoreBodyExecTransform/CoreSpecification.leanProcedureCorrect.postconditionsValidTransform/ProcBodyVerifyCorrect.leanprocToVerifyStmt_is_structured(new helper theorem)sswitnesses viasubstTransform/ProcBodyVerifyCorrect.leanprocBodyVerify_procedureCorrectLanguages/Core/ObligationExtraction.leanextractGo_okproofLanguages/Core/ProcedureEval.leanevalLanguages/Core/ProcedureType.leantypeCheck,checkModificationRightsprocedureToGotoCtxViaCFGBackends/CBMC/GOTO/CoreToCProverGOTO.leantransformToGotoprocedureToGotoCtxViaCFGBackends/CBMC/GOTO/CoreToGOTOPipeline.leanprocedureToGotoCtxprocedureToGotoCtxViaCFGStrataTest/.../E2E_CoreToGOTO.leancoreToGotoJsonWithSummaryprocedureToGotoCtxViaCFGBackends/CBMC/CoreToCBMC.leancreateImplementationSymbolFromASTextractCallsFromStatementsvsextractCallsFromDetCFGLanguages/Core/CallGraph.leanextractCallsFromProcedureblockToCSTvsdetCFGToCSTLanguages/Core/DDMTransform/FormatCore.leanprocToCSTrunStmtvsrunCFGLanguages/Core/StatementEval.leanCommand.runCallCoreBodyExecwith two constructors, andCoreStepStarvsCoreCFGStepStarLanguages/Core/StatementSemantics.leanEvalCommand.call_semLang.corevsLang.coreCFGTransform/CoreSpecification.leanAssertValidInProceduretransformStmtsvstransformDetCFGTransform/PrecondElim.leanprecondElimeraseTypes,stripMetaData,getVarsimplemented and used for CFGLanguages/Core/Procedure.leaneraseTypes,stripMetaData,getVarsextractFromStatementsvsextractFromDetCFGLanguages/Core/ObligationExtraction.leanextractObligationsreturn .noneon CFG, skip inlining, because the inlined procedure could be structured or unstructured. Semantics is largely undefined.Transform/ProcedureInlining.leaninlineCallCmdstmtsToCFGvs identity, latter is a no-op.StrataTest/.../Loops.leansingleCFGTransform/LoopElim.leanloopElim[]for CFG (no local funcDecls in CFG bodies)Languages/Core/Core.leanbuildEnvLanguages/Core/ObligationExtraction.leanextractFromDetCFGthrowon CFG, due to incompatible return type ofList Statementinstead ofList CommandTransform/CoreTransform.leanrunProgramthrowon CFG, VC for CFG bodies to be implemented, proof to be adapted as well.Transform/ProcBodyVerify.leanprocToVerifyStmtTransform/ANFEncoder.leananfEncodeProgramTransform/ProcedureInlining.leanrenameAllLocalNamesStrataTest/Boole/global_readonly_call.leancallHelperwfstmts,wfloclnd,bodyExitsCoveredconditioned on structured procedures, props for CFG to be implementedLanguages/Core/WF.leanWFProcedurePropBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.