Skip to content

Add OverapproxiatesUpto/OverapproximatesWhen/OverapproximatesAggressivelyWhen#1325

Draft
aqjune-aws wants to merge 1 commit into
mainfrom
jlee/sem-updates
Draft

Add OverapproxiatesUpto/OverapproximatesWhen/OverapproximatesAggressivelyWhen#1325
aqjune-aws wants to merge 1 commit into
mainfrom
jlee/sem-updates

Conversation

@aqjune-aws

@aqjune-aws aqjune-aws commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Updates in specification of transformations to support several missing features needed by loop elimination correctness.

  • A new OverapproximatesAggressively that allows spurious assertion failures even when executions started from the exactly same initial program state. :)

    • If transformation T satisfies OverapproximatesAggressively, it also satisfies Overapproximates.
  • A new OverapproximatesUpto(When): an extension of Overapproximates in the sense that it takes the mapping relation between program states of the input and output program.

    • OverapproxiamtesUptoWhen additionally takes the precondition on the input program.
  • New OverapproximatesWhen / OverapproximatesAggressivelyWhen:

    • Precondition-bearing variants: take a pre : Stmt → Prop that the input program (which is an imperative statement) must satisfy.
    • Original Overapproximates / OverapproximatesAggressively are now *When-wrappers with pre := fun _ => True.
    • *.toWhen and *When.strengthen provided in SpecificationProps.
  • InitEnvWF: a structure capturing well-formedness of the initial program state (Env).

    • defUseWellFormed / Block.defUseWellFormed: a static check that every use of a variable references a previously-defined variable, and every use of an operator references a previously-funcDecl'd name.

    • Reflection-based factoryDeclared predicate replacing the prior hard-coded factoryFuncNames list (derived from WFFactoryArray).

@aqjune-aws

Copy link
Copy Markdown
Contributor Author

Hey, this PR is too large. Can we split it into smaller ones?

@aqjune-aws

Copy link
Copy Markdown
Contributor Author

#1327

aqjune-aws added a commit that referenced this pull request Jun 5, 2026
… check

Reworks the small-step semantics of the Imperative dialect (Strata.DL.Imperative)
and Core (Strata.Languages.Core) to fix a scoping bug and add a missing
measure check. Subset of the changes from PR #1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work is
deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
  out of their enclosing block):
  Inner function declarations (`step_funcDecl`) extend the evaluator
  (`Env.eval`) with the new function, and previously, that extension
  persisted past the enclosing block — i.e. a `funcDecl` inside a block was
  visible to code AFTER the block exited. This is wrong: by the language's
  variable-scoping rules, a `funcDecl`'s scope is its enclosing block,
  exactly parallel to `init`. The fix:
  * `Config.block` now carries a snapshot of the parent evaluator
    (`e_parent`) in addition to the parent store (`σ_parent`):
    `Config.block label σ_parent e_parent inner` (was 3-arg).
  * On `step_block_done` / `step_block_exit_match` / `step_block_exit_mismatch`
    the result config's `eval` is RESTORED to `e_parent`, so a `funcDecl`
    introduced inside the block is NOT visible after exit.

* The same `Config.block` wrapper is used by `step_ite_*` and
  `step_loop_*` to scope `ite` branches and loop bodies, so this fix
  automatically covers `funcDecl`s leaking out of `if`/`else` branches
  and loop bodies as well.

* Implement the missing measure check of a loop in small-step semantics:
  * `step_loop_enter` / `step_loop_exit` / `step_loop_nondet_*` set
    `hasMeasureFailure` / `hasInvFailure` flags from the measure /
    invariants, and OR them into `Env.hasFailure`.
  * `Stmt.loop` carries an `Option (String × P.Expr)` measure (label +
    expr) rather than `Option P.Expr`; the label feeds into the
    assertion-label collection (so a verifier can identify the synthetic
    measure assertion).

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
  * `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
    referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
  * `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
    `HasBoolVal` is folded in).
  * Boolean operations split out into `HasBoolOps` (extends `HasBool`):
    not, and, imp.

* `Strata/DL/Imperative/StmtProps.lean` (new): theorems that depend only
  on `Stmt.lean` (currently `Stmt.funcDeclNames_eq_nil_of_noFuncDecl` and
  `Block.funcDeclNames_eq_nil_of_noFuncDecl`).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@aqjune-aws

Copy link
Copy Markdown
Contributor Author

#1337 will factor out (1) Updates / fixes in Imperative small-step semantics

@aqjune-aws

Copy link
Copy Markdown
Contributor Author

This pull request will be moved to the internal repository of Strata after migration.

@aqjune-aws aqjune-aws force-pushed the jlee/sem-updates branch 3 times, most recently from e820081 to 1e514c3 Compare June 12, 2026 01:21
@github-actions github-actions Bot removed the GOTO label Jun 12, 2026
@aqjune-aws aqjune-aws changed the title Imperative semantic bug fixes/updates and supporting infrastructure Add OverapproximatesWhen/OverapproximatesAggressivelyWhen Jun 12, 2026
@aqjune-aws aqjune-aws force-pushed the jlee/sem-updates branch 2 times, most recently from be91096 to c600d79 Compare June 12, 2026 01:28
@github-actions github-actions Bot removed the Laurel label Jun 12, 2026
@aqjune-aws aqjune-aws force-pushed the jlee/sem-updates branch 2 times, most recently from d6fc11e to a1b8bf8 Compare June 12, 2026 01:57
kondylidou pushed a commit to kondylidou/Strata that referenced this pull request Jun 12, 2026
…1337)

Reworks the small-step semantics of Imperative to dix a scoping bug
regarding internal function declaration.

Subset of the changes from PR strata-org#1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work
is deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
out of their enclosing block): Inner function declarations
(`step_funcDecl`) extend the evaluator (`Env.eval`) with the new
function, and previously, that extension persisted past the enclosing
block — i.e. a `funcDecl` inside a block was visible to code AFTER the
block exited. This is wrong: by the language's variable-scoping rules, a
`funcDecl`'s scope is its enclosing block, exactly parallel to `init`.
The fix:
* `Config.block` now carries a snapshot of the parent evaluator
(`e_parent`) in addition to the parent store (`σ_parent`): `Config.block
label σ_parent e_parent inner` (was 3-arg).
* On `step_block_done` / `step_block_exit_match` /
`step_block_exit_mismatch` the result config's `eval` is RESTORED to
`e_parent`, so a `funcDecl` introduced inside the block is NOT visible
after exit.

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
* `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
* `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
`HasBoolVal` is folded in).
* Boolean operations split out into `HasBoolOps` (extends `HasBool`):
not, and, imp.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Aaron Tomb <aarotomb@amazon.com>
shigoel pushed a commit that referenced this pull request Jun 15, 2026
Reworks the small-step semantics of Imperative to dix a scoping bug
regarding internal function declaration.

Subset of the changes from PR #1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work
is deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
out of their enclosing block): Inner function declarations
(`step_funcDecl`) extend the evaluator (`Env.eval`) with the new
function, and previously, that extension persisted past the enclosing
block — i.e. a `funcDecl` inside a block was visible to code AFTER the
block exited. This is wrong: by the language's variable-scoping rules, a
`funcDecl`'s scope is its enclosing block, exactly parallel to `init`.
The fix:
* `Config.block` now carries a snapshot of the parent evaluator
(`e_parent`) in addition to the parent store (`σ_parent`): `Config.block
label σ_parent e_parent inner` (was 3-arg).
* On `step_block_done` / `step_block_exit_match` /
`step_block_exit_mismatch` the result config's `eval` is RESTORED to
`e_parent`, so a `funcDecl` introduced inside the block is NOT visible
after exit.

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
* `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
* `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
`HasBoolVal` is folded in).
* Boolean operations split out into `HasBoolOps` (extends `HasBool`):
not, and, imp.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Aaron Tomb <aarotomb@amazon.com>
shigoel pushed a commit that referenced this pull request Jun 16, 2026
Reworks the small-step semantics of Imperative to dix a scoping bug
regarding internal function declaration.

Subset of the changes from PR #1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work
is deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
out of their enclosing block): Inner function declarations
(`step_funcDecl`) extend the evaluator (`Env.eval`) with the new
function, and previously, that extension persisted past the enclosing
block — i.e. a `funcDecl` inside a block was visible to code AFTER the
block exited. This is wrong: by the language's variable-scoping rules, a
`funcDecl`'s scope is its enclosing block, exactly parallel to `init`.
The fix:
* `Config.block` now carries a snapshot of the parent evaluator
(`e_parent`) in addition to the parent store (`σ_parent`): `Config.block
label σ_parent e_parent inner` (was 3-arg).
* On `step_block_done` / `step_block_exit_match` /
`step_block_exit_mismatch` the result config's `eval` is RESTORED to
`e_parent`, so a `funcDecl` introduced inside the block is NOT visible
after exit.

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
* `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
* `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
`HasBoolVal` is folded in).
* Boolean operations split out into `HasBoolOps` (extends `HasBool`):
not, and, imp.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Aaron Tomb <aarotomb@amazon.com>
shigoel pushed a commit that referenced this pull request Jun 16, 2026
Reworks the small-step semantics of Imperative to dix a scoping bug
regarding internal function declaration.

Subset of the changes from PR #1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work
is deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
out of their enclosing block): Inner function declarations
(`step_funcDecl`) extend the evaluator (`Env.eval`) with the new
function, and previously, that extension persisted past the enclosing
block — i.e. a `funcDecl` inside a block was visible to code AFTER the
block exited. This is wrong: by the language's variable-scoping rules, a
`funcDecl`'s scope is its enclosing block, exactly parallel to `init`.
The fix:
* `Config.block` now carries a snapshot of the parent evaluator
(`e_parent`) in addition to the parent store (`σ_parent`): `Config.block
label σ_parent e_parent inner` (was 3-arg).
* On `step_block_done` / `step_block_exit_match` /
`step_block_exit_mismatch` the result config's `eval` is RESTORED to
`e_parent`, so a `funcDecl` introduced inside the block is NOT visible
after exit.

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
* `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
* `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
`HasBoolVal` is folded in).
* Boolean operations split out into `HasBoolOps` (extends `HasBool`):
not, and, imp.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Aaron Tomb <aarotomb@amazon.com>
joehendrix pushed a commit that referenced this pull request Jun 16, 2026
Reworks the small-step semantics of Imperative to dix a scoping bug
regarding internal function declaration.

Subset of the changes from PR #1325 — the
`OverapproximatesWhen`/`OverapproximatesAggressively`/`InitEnvWF` work
is deferred to a follow-up PR.

* Evaluator scoping (FIX of a scoping bug — function declarations leaked
out of their enclosing block): Inner function declarations
(`step_funcDecl`) extend the evaluator (`Env.eval`) with the new
function, and previously, that extension persisted past the enclosing
block — i.e. a `funcDecl` inside a block was visible to code AFTER the
block exited. This is wrong: by the language's variable-scoping rules, a
`funcDecl`'s scope is its enclosing block, exactly parallel to `init`.
The fix:
* `Config.block` now carries a snapshot of the parent evaluator
(`e_parent`) in addition to the parent store (`σ_parent`): `Config.block
label σ_parent e_parent inner` (was 3-arg).
* On `step_block_done` / `step_block_exit_match` /
`step_block_exit_mismatch` the result config's `eval` is RESTORED to
`e_parent`, so a `funcDecl` introduced inside the block is NOT visible
after exit.

* New HasFvars / HasOps / HasOpsImp typeclasses:
  * `HasFvars` returns ALL free variables in an expression.
* `HasOps` (`P.Expr → List P.Ident`) returns operator/function names
referenced in an expression, parallel to `HasFvars` for variables.
  * `HasOpsImp` lifts that to commands (`Cmd.getOps`, `Cmds.getOps`).

* Refactoring of HasBool / HasBoolOps:
* `HasBool` now extends `HasVal` and bundles `boolIsVal` (former
`HasBoolVal` is folded in).
* Boolean operations split out into `HasBoolOps` (extends `HasBool`):
not, and, imp.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Aaron Tomb <aarotomb@amazon.com>
…matesUpto(When) and WF of program state

* `OverapproximatesUpto(When)`: an extension of `Overapproximates` in the sense that it takes the mapping relation between program states of the input and output program.
  * `OverapproxiamtesUptoWhen` additionally takes the precondition on the input program.

* `OverapproximatesWhen` / `OverapproximatesAggressivelyWhen`:
  * Precondition-bearing variants: take a `pre : L₁.StmtT → Prop` that the
    initial source statement must satisfy.
  * Original `Overapproximates` / `OverapproximatesAggressively` are now
    `*When`-wrappers with `pre := fun _ => True`.
  * `*.toWhen` and `*When.strengthen` provided in SpecificationProps.

* `OverapproximatesAggressively`: a new variant that allows spurious assertion
  failures — the target is allowed to terminate with `hasFailure = true`
  instead of matching the source's terminal/exiting env exactly.

* `Overapproximates` is extended to also preserve `CanFail` and the
  `initEnvWF` of the target; the `prefixIdents` discipline tracks fresh
  identifier prefixes that downstream transforms reserve.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@aqjune-aws aqjune-aws changed the title Add OverapproximatesWhen/OverapproximatesAggressivelyWhen Add OverapproxiatesUpto/OverapproximatesWhen/OverapproximatesAggressivelyWhen Jun 23, 2026
@github-actions github-actions Bot added dependencies Pull requests that update a dependency file github_actions Pull requests that update GitHub Actions code SMT Java labels Jun 23, 2026
@aqjune-aws aqjune-aws changed the base branch from main2 to main June 23, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Core dependencies Pull requests that update a dependency file Git conflicts github_actions Pull requests that update GitHub Actions code GOTO Java Laurel SMT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant