Skip to content

refactor(pl): swap as program transformations - #1181

Open
strub wants to merge 1 commit into
pl/condfrom
pl/swap
Open

strub wants to merge 1 commit into
pl/condfrom
pl/swap

Conversation

@strub

@strub strub commented Oct 8, 2026

Copy link
Copy Markdown
Member

PR of the program-logic reorganization stack (see src/phl/REFACTORING.md).
It migrates the swap tactic class:

  • new catalogue entry swap (EcTrSwap, rules/transforms/): moves the
    block [s..f) of the (possibly nested) block at a normalized path to
    the gap t of that block, outside of the moved block. Its parameters
    are resolved (nm_codegap_range, nm_codegap1); the absence of
    raise and the independence of the exchanged statements are checked
    inside the entry, with today's messages, so that the checkers of the
    transformation rules re-validate them. No obligation, same memory.
  • swap is derived in every logic (hoare, ehoare, phoare, equiv on one
    side, both sides one after the other): it resolves the range and the
    offset (same messages, same order), then applies the transformation
    rule of the logic with the entry. The tactic being uniform, the
    dispatch on the goal kind is a single function in EcPhlSwap (no
    per-logic module). It no longer emits its own Swap mutate node.
  • interleave stays derived (a sequence of swaps).
  • EcMatching.Zipper.zipper_of_nm_cgap: the pure zipper on a
    normalized code gap (no lookup), used by the entry;
    zipper_step_into_block now resolves the step then calls its
    normalized counterpart.
  • EcPhlSwap.mli unchanged; t_swap is a dispatcher, t_low2 dropped.
  • REFACTORING.md, README.md, EcPlTransform: the catalogue lists swap.

Behaviour preserved: identical goals at every step (compile -trace
diff against the base build) and identical error messages (every
failing call of the new test, and of the existing swap tests).

Validation: new test tests/swap.ec (every logic, both equiv sides,
nested positions in if/while/match branches, absolute and relative
offsets, interleave, every error path), passing with the base build
and this one under EC_RECHECK=1; stdlib, unit and examples under
EC_RECHECK=1 (ECJOBS=4): all pass, no RecheckFailure. Each
transformation checker reached by swap (hoare-, ehoare-, bdhoare-,
equiv-transform), broken on swap nodes only, is caught only under
EC_RECHECK=1: on the test (one lemma per logic) and on stdlib / unit
/ examples, files caught per checker: equiv-transform 13 / 1 / 14,
bdhoare-transform 0 / 0 / 4, hoare-transform 0 / 3 / 0,
ehoare-transform 0 / 0 / 0 (reached by the new test only).

@strub strub added the stacked Intermediate PR of a stack: CI skipped unless it targets main label Oct 8, 2026
@strub
strub added this pull request to stack #1156 October 8, 2026 05:52
PR of the program-logic reorganization stack (see src/phl/REFACTORING.md).
It migrates the `swap` tactic class:

- new catalogue entry `swap` (`EcTrSwap`, rules/transforms/): moves the
  block [s..f) of the (possibly nested) block at a normalized path to
  the gap t of that block, outside of the moved block. Its parameters
  are resolved (`nm_codegap_range`, `nm_codegap1`); the absence of
  `raise` (and, when the judgement observes exceptions, of calls that
  may raise) and the independence of the exchanged statements are
  checked inside the entry, with today's messages, so that the checkers
  of the transformation rules re-validate them. No obligation, same
  memory.
- the transformation context gets `trc_exn`: whether the judgement
  observes exceptions (a hoare postcondition constraining some
  exception, `EcLowPhlGoal.hs_observes_exn`; false in the other logics),
  computed by each rule from its goal.
- `swap` is derived in every logic (hoare, ehoare, phoare, equiv on one
  side, both sides one after the other): it resolves the range and the
  offset (same messages, same order), then applies the transformation
  rule of the logic with the entry. The tactic being uniform, the
  dispatch on the goal kind is a single function in `EcPhlSwap` (no
  per-logic module). It no longer emits its own `Swap` mutate node.
- `interleave` stays derived (a sequence of swaps).
- `EcMatching.Zipper.zipper_of_nm_cgap`: the pure zipper on a
  normalized code gap (no lookup), used by the entry;
  `zipper_step_into_block` now resolves the step then calls its
  normalized counterpart.
- `EcPhlSwap.mli` unchanged; `t_swap` is a dispatcher, `t_low2` dropped.
- REFACTORING.md, README.md, EcPlTransform: the catalogue lists swap.

Behaviour preserved: identical goals at every step (compile -trace
diff against the base build) and identical error messages (every
failing call of the new test, and of the existing swap tests).

Validation: new test tests/swap.ec (every logic, both equiv sides,
nested positions in if/while/match branches, absolute and relative
offsets, interleave, every error path), passing with the base build
and this one under EC_RECHECK=1; stdlib, unit and examples under
EC_RECHECK=1 (ECJOBS=4): all pass, no RecheckFailure. Each
transformation checker reached by `swap` (hoare-, ehoare-, bdhoare-,
equiv-transform), broken on swap nodes only, is caught only under
EC_RECHECK=1: on the test (one lemma per logic) and on stdlib / unit
/ examples, files caught per checker: equiv-transform 13 / 1 / 14,
bdhoare-transform 0 / 0 / 4, hoare-transform 0 / 3 / 0,
ehoare-transform 0 / 0 / 0 (reached by the new test only).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stacked Intermediate PR of a stack: CI skipped unless it targets main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant