-
Notifications
You must be signed in to change notification settings - Fork 2
Derive normalization rules from phino as checked data #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
cd8a83f
46ade3d
74b06a1
edb5aa1
9fe9659
9e775bd
dd7688f
ea8c98f
d1b1939
76d9ac9
b6d4074
82fe64d
6058493
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,14 @@ jobs: | |
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: ./.github/actions/setup-lean | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.x' | ||
| - name: Regenerate Rules.lean and RuleData.lean from pinned phino | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| run: | | ||
| pip install pyyaml | ||
| bash scripts/regen-rules.sh | ||
| bash scripts/regen-rule-data.sh | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regenerating into the working tree right before bash scripts/regen-rules.sh
bash scripts/regen-rule-data.sh
git diff --exit-code PhiConfluence/Rules.lean PhiConfluence/RuleData.lean \
|| { echo "::error::generated rules are out of sync — run the regen scripts and commit"; exit 1; }That way the build still compiles phino-derived rules, and a stale committed file fails instead of being silently replaced. |
||
| - name: Build the library and executables | ||
| run: | | ||
| lake build | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,9 +16,10 @@ jobs: | |
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Install phino (latest) | ||
| - name: Install phino (pinned via .phino-version) | ||
| run: | | ||
| sudo curl -fsSL -o /usr/local/bin/phino http://phino.objectionary.com/releases/ubuntu-24.04/phino-latest | ||
| version="$(cat .phino-version)" | ||
| sudo curl -fsSL -o /usr/local/bin/phino "http://phino.objectionary.com/releases/ubuntu-24.04/phino-$version" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this line is being rewritten anyway: it fetches an executable over plain |
||
| sudo chmod +x /usr/local/bin/phino | ||
| phino --version | ||
| - uses: ./.github/actions/setup-lean | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 Objectionary.com | ||
| # SPDX-License-Identifier: MIT | ||
| --- | ||
| name: ruff | ||
| 'on': | ||
| push: | ||
| branches: | ||
| - master | ||
| pull_request: | ||
| branches: | ||
| - master | ||
| jobs: | ||
| ruff: | ||
| timeout-minutes: 15 | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: astral-sh/ruff-action@v3 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice to have lint on the two scripts. |
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 0.0.0.74 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Since |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ import PhiConfluence.Step | |
| import PhiConfluence.Reduce | ||
| import PhiConfluence.Render | ||
| import PhiConfluence.Rules | ||
| import PhiConfluence.RuleSchema | ||
| import PhiConfluence.RuleData | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The description says the Lean layer "ships here as a reviewed draft only — it is not imported into No objection to importing them — the build proves they are fine. But please correct the description: a reviewer taking that caveat at face value would assume the root module is untouched and skim these files, which is the opposite of what should happen. |
||
| import PhiConfluence.Parallel | ||
| import PhiConfluence.Preservation | ||
| import PhiConfluence.Diamond | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| -- SPDX-FileCopyrightText: Copyright (c) 2026 Objectionary.com | ||
| -- SPDX-License-Identifier: MIT | ||
|
|
||
| -- AUTO-GENERATED by scripts/gen-rule-data.py from objectionary/phino resources/*.yaml. | ||
| -- DO NOT EDIT BY HAND. Regenerate after phino's rules change. | ||
|
|
||
| import PhiConfluence.RuleSchema | ||
|
|
||
| /-! | ||
| # Normalization rules as structured data, generated from phino | ||
|
|
||
| The eleven rules as `RuleEntry` tags (types in PhiConfluence/RuleSchema.lean), emitted | ||
| by the fidelity-lock deriver `scripts/gen-rule-data.py`. The CI build regenerates this | ||
| file from pinned phino and compiles it, so the proof builds against phino's rules. | ||
| -/ | ||
|
|
||
| namespace PhiConfluence | ||
|
|
||
| /-- The φ-calculus normalization rules as structured, interpretable data. -/ | ||
| def normalizationRuleData : List RuleEntry := | ||
| [ { name := "alpha", shape := .appForm, conds := [.alphaVoidOrdinal], rhs := .alphaRename } | ||
| , { name := "copy", shape := .appForm, conds := [.slotVoid, .argXiFree, .argNf], rhs := .copyFill } | ||
| , { name := "dc", shape := .appBot, conds := [], rhs := .bot } | ||
| , { name := "dd", shape := .dispatchBot, conds := [], rhs := .bot } | ||
| , { name := "dot", shape := .dispatchForm, conds := [.slotAttached, .valNf], rhs := .dotFeedback } | ||
| , { name := "miss", shape := .appForm, conds := [.slotAbsent, .attrNotAlpha], rhs := .bot } | ||
| , { name := "null", shape := .dispatchForm, conds := [.slotVoid], rhs := .bot } | ||
| , { name := "over", shape := .appForm, conds := [.slotAttached, .attrNeRho], rhs := .bot } | ||
| , { name := "phi", shape := .dispatchForm, conds := [.phiPresent, .slotAbsent], rhs := .phiExpand } | ||
| , { name := "stay", shape := .appForm, conds := [.attrIsRho, .slotAttached], rhs := .formSame } | ||
| , { name := "stop", shape := .dispatchForm, conds := [.slotAbsent, .phiAbsent, .noLambda], rhs := .bot } ] | ||
|
|
||
| end PhiConfluence |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| -- SPDX-FileCopyrightText: Copyright (c) 2026 Objectionary.com | ||
| -- SPDX-License-Identifier: MIT | ||
|
|
||
| /-! | ||
| # Schema for the generated rule data | ||
|
|
||
| The typed vocabulary that `PhiConfluence/RuleData.lean` (generated from phino by | ||
| `scripts/gen-rule-data.py`) is written in: each normalization rule is a `RuleEntry` of | ||
| tags — the redex it fires on, its side-conditions, and its contractum. These are *data* | ||
| describing the eleven `phino` rules; the proof relation `Step` (`Step.lean`) is the | ||
| authoritative hand-written object, and `RuleData.lean` is kept identical to phino by the | ||
| `rule-data-in-sync` CI job. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. References the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "kept identical to phino by the |
||
| -/ | ||
|
|
||
| namespace PhiConfluence | ||
|
|
||
| /-- Which redex a rule fires on: `⊥.a`, `⊥(a↦arg)`, `⟦bs⟧.a`, or `⟦bs⟧(a↦arg)`. -/ | ||
| inductive RedexShape where | ||
| | dispatchBot | appBot | dispatchForm | appForm | ||
| deriving Repr, DecidableEq | ||
|
|
||
| /-- A side condition on the redex's formation, attribute, and argument. -/ | ||
| inductive Cond where | ||
| | slotVoid | slotAttached | slotAbsent | ||
| | attrNeRho | attrIsRho | attrNotAlpha | ||
| | phiAbsent | phiPresent | noLambda | ||
| | valNf | argXiFree | argNf | alphaVoidOrdinal | ||
| deriving Repr, DecidableEq | ||
|
|
||
| /-- The contractum a rule rewrites its redex to. -/ | ||
| inductive Contractum where | ||
| | bot | formSame | phiExpand | dotFeedback | copyFill | alphaRename | ||
| deriving Repr, DecidableEq | ||
|
|
||
| /-- One normalization rule as structured data. (Named `RuleEntry`, not `RuleSpec`, | ||
| to avoid colliding with `Render.lean`'s display-string `RuleSpec`.) -/ | ||
| structure RuleEntry where | ||
| name : String | ||
| shape : RedexShape | ||
| conds : List Cond | ||
| rhs : Contractum | ||
|
|
||
| end PhiConfluence | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ version = 1 | |
| [[annotations]] | ||
| path = [ | ||
| ".gitignore", | ||
| ".phino-version", | ||
| ".yamllint", | ||
| "**.json", | ||
| "**.md", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,13 @@ | |
| # | ||
| # Differential test: for each example program, check that phino's normal form | ||
| # (`phino rewrite --normalize`) equals our reducer's normal form. The behavioral | ||
| # pin between this prover's Step relation and phino. Requires `phino` on PATH. | ||
| # pin between this prover's Step relation and phino. Requires `phino` on PATH, | ||
| # pinned via `--pin` to the version in .phino-version (phino aborts on a mismatch). | ||
|
|
||
| set -uo pipefail | ||
| cd "$(dirname "$0")/.." | ||
| export PATH="$HOME/.elan/bin:$PATH" | ||
| PHINO_VERSION="$(cat .phino-version)" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reads |
||
|
|
||
| if ! command -v phino >/dev/null 2>&1; then | ||
| echo "FATAL: phino not found on PATH; the differential test requires it (fail-fast, not skip)" >&2 | ||
|
|
@@ -22,7 +24,7 @@ count=0 | |
| while IFS=$'\t' read -r input expected; do | ||
| [ -z "${input:-}" ] && continue | ||
| count=$((count + 1)) | ||
| out=$(printf '%s\n' "$input" | phino rewrite --normalize --flat 2>/dev/null) | ||
| out=$(printf '%s\n' "$input" | phino --pin="$PHINO_VERSION" rewrite --normalize --flat 2>/dev/null) | ||
| pn=$(printf '%s' "$out" | tr -d '[:space:]'); pn=${pn#Φ↦} | ||
| ours=$(printf '%s' "$expected" | tr -d '[:space:]') | ||
| if [ "$pn" = "$ours" ]; then | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
python-version: '3.x'plus an unpinnedpip install pyyamlon line 25 sits oddly in a PR whose whole subject is making the toolchain deterministic. Both float, and either one can change the generatedRuleData.lean(or breakgen-rule-data.py) without a commit here. If phino is worth pinning to a four-part version, Python and PyYAML are worth pinning to at least a minor.