Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repository = "https://github.com/wrightkit/opy-rs"
opy-frontend = { path = "crates/opy-frontend" }
serde = "1"
serde_json = "1"
workshop-rs = "=0.1.8"
workshop-rs = "=0.1.11"

[workspace.lints.rust]
unsafe_op_in_unsafe_fn = "deny"
Expand Down
4 changes: 2 additions & 2 deletions compatibility/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ compatibility/fixtures/<category>/<name>/

Imported fixtures should also record an immutable `sourceCommit`, a direct
`sourceUrl`, a `licenseUrl`, and whether the source was modified. The corpus
contains 44 fixtures: 30 WrightKit-authored synthetic cases, one census boundary
contains 50 fixtures: 36 WrightKit-authored synthetic cases, one census boundary
fixture, and 13
real-world projects (11 derived from the pinned OverPy `examples/` tree,
GPL-3.0-only, provenance-recorded evidence, plus the independent BSD-2-Clause
Expand Down Expand Up @@ -111,7 +111,7 @@ cargo test -p opy-frontend --test differential
```

It compiles every fixture through the native pipeline (preprocess → parse →
lower), verifies the Opy HIR v1 structure (validation, wire round-trip,
lower), verifies the Opy HIR v2 structure (validation, wire round-trip,
deterministic dump), and compares the outcome against the recorded
`oracle.json` evidence: status parity (resolve vs expected diagnostic),
ordered authored rule names (normalized to drop reference-synthesized
Expand Down
7 changes: 7 additions & 0 deletions compatibility/differential-expectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@
{"fixture": "synthetic/issue-40-structural", "nativeStatus": "success", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-40-structural/oracle.json", "implementation-invariant:opy-compiler-structural-lowering"], "note": "The pinned oracle records subroutine source identity, deterministic explicit/implicit variable allocation, and player event filters; the dedicated opy-compiler test independently asserts those structures in canonical WIR."},
{"fixture": "synthetic/issue-46-primitives", "nativeStatus": "success", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-46-primitives/oracle.json", "implementation-invariant:opy-compiler-primitive-lowering", "test:opy-compiler-issue-46-oracle-equivalence"], "note": "The pinned oracle records the evidenced assignment and modification lowering (including **= and single-level indexed forms), value expressions, array indexing (including the firstOf index-0 read normalization), not-comparison negation, implicit default variables at fixed Workshop slots, and non-null variable initializers; null-default initializer semantics and deeper indexed writes remain explicit follow-ups. The opy-compiler test suite reparses both the native output and the oracle Workshop text through the canonical workshop-rs parser and requires structural equivalence."},
{"fixture": "synthetic/issue-46-unsupported", "nativeStatus": "success", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-46-unsupported/oracle.json", "implementation-invariant:opy-compiler-primitive-lowering-limits"], "note": "Negative #46 probe: the frontend resolves and the pinned oracle compiles the dict-indexed assignment, while the native compiler rejects the dict primitive with the stable source-attributed unsupported-integration-surface diagnostic."},
{"fixture": "synthetic/issue-47-control-flow", "nativeStatus": "success", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-47-control-flow/oracle.json", "test:opy-compiler-issue-47-oracle-equivalence"], "note": "The #47 control-flow slice resolves in the frontend and lowers to canonical WIR with structural equivalence to the pinned oracle; direct loop/switch break and the nested switch shape are independently covered by opy-compiler tests."},
{"fixture": "synthetic/issue-47-unsupported", "nativeStatus": "success", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-47-unsupported/oracle.json", "test:opy-compiler-issue-47-nested-negative"], "note": "Negative #47 probe: the frontend and pinned oracle accept the nested conditional switch-break HIR, while the compiler rejects the form because canonical WIR has no equivalent structured break carrier."},
{"fixture": "synthetic/issue-47-switch-order", "nativeStatus": "success", "classification": "match", "ruleNames": true, "evidence": ["oracle:synthetic/issue-47-switch-order/oracle.json", "test:opy-compiler-issue-47-switch-order"], "note": "The #47 default-before-case probe preserves authored arm order and fallthrough in the frontend; native and pinned Workshop both reparse to equivalent canonical WIR."},
{"fixture": "synthetic/issue-47-switch-structured-target", "nativeStatus": "success", "classification": "match", "ruleNames": true, "evidence": ["oracle:synthetic/issue-47-switch-structured-target/oracle.json", "test:opy-compiler-issue-47-structured-switch-target"], "note": "The #47 structured switch probe places nested if/while actions in an earlier arm and verifies later case/default targets against canonical emitted action widths through native/oracle WIR equivalence."},
{"fixture": "synthetic/issue-47-switch-multiple-break", "nativeStatus": "success", "classification": "match", "ruleNames": true, "evidence": ["oracle:synthetic/issue-47-switch-multiple-break/oracle.json", "test:opy-compiler-issue-47-multiple-switch-break"], "note": "The frontend preserves the multi-break source and the pinned oracle accepts it; the compiler rejects the later-reachable multi-target shape explicitly because workshop-rs v0.1.11 has one canonical else carrier."},
{"fixture": "synthetic/issue-47-do-while-shapes", "nativeStatus": "success", "classification": "match", "ruleNames": true, "evidence": ["oracle:synthetic/issue-47-do-while-shapes/oracle.json", "test:opy-compiler-issue-47-do-while-break-shapes"], "note": "Direct, conditional, and nested do-while break shapes resolve and match the pinned Workshop after native and oracle reparsing through workshop-rs."},
{"fixture": "synthetic/issue-47-do-while-invalid-placement", "nativeStatus": "failure", "classification": "match", "ruleNames": false, "evidence": ["oracle:synthetic/issue-47-do-while-invalid-placement/oracle.json", "test:opy-compiler-issue-47-invalid-do-while-placement"], "note": "The frontend reports the stable source-attributed do-while-placement diagnostic for a non-prefix do-while."},
{"fixture": "census/workshop-feature-census", "nativeStatus": "success", "classification": "match", "ruleNames": true, "evidence": ["oracle:census/workshop-feature-census/oracle.json", "contract:workshop-rs#10-feature-census"], "note": "OPy source records opaque Workshop feature identities for the future workshop-rs lowering boundary."}
]
}
13 changes: 10 additions & 3 deletions compatibility/fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This directory is the opy-rs compatibility corpus: OPY sources with their
pinned-oracle snapshots (`oracle.json`), ported from the WrightKit project's
evidence base (wright `compatibility/fixtures/`) and re-verified against the
pinned OverPy 9.7.10 oracle (all 44 snapshots match; see
pinned OverPy 9.7.10 oracle (all 46 snapshots match; see
[`docs/compatibility/upstream-references.md`](../../docs/compatibility/upstream-references.md)
for the dated verification record).

Expand All @@ -29,7 +29,7 @@ fixtures/<category>/<name>/

## Synthetic fixtures (WrightKit-authored)

`fixtures/synthetic/` — 30 fixtures authored for the WrightKit compatibility
`fixtures/synthetic/` — 32 fixtures authored for the WrightKit compatibility
corpus (AGPL-3.0-or-later, `kind: original`): an initial set ported unchanged
from the wright repository corpus, extended by fixtures added in this
repository:
Expand All @@ -56,6 +56,13 @@ repository:
| `issue-35-integration` | minimal OPY HIR to canonical Workshop WIR validation and deterministic emission slice |
| `issue-46-primitives` | #46 oracle-backed primitive lowering probe: assignments and modifications (including `**=`), expressions, indexing, format, initializers, implicit default variables at fixed slots; the snapshot constrains the native compiler through structural equivalence |
| `issue-46-unsupported` | #46 negative probe: a dict-indexed assignment the compiler rejects with the stable source-attributed diagnostic while the oracle compiles it |
| `issue-47-control-flow` | #47 pinned oracle-backed control-flow lowering probe: if/elif/else, while, range-for, do-while expansion, switch fallthrough/default, and direct break |
| `issue-47-unsupported` | #47 negative probe: a break hidden inside a conditional switch arm is accepted by the frontend/oracle but rejected by the compiler with a stable source-attributed diagnostic |
| `issue-47-switch-order` | #47 pinned oracle probe for a default arm before later case arms and source-order fallthrough |
| `issue-47-switch-structured-target` | #47 pinned oracle probe for nested if/while structure in an earlier arm and later case/default targets |
| `issue-47-switch-multiple-break` | #47 pinned oracle probe for multiple direct breaks; frontend preserves the source while the compiler reports the canonical multi-target WIR gap |
| `issue-47-do-while-shapes` | #47 pinned oracle probe for direct, conditional, and nested do-while break lowering |
| `issue-47-do-while-invalid-placement` | #47 pinned negative probe for the stable do-while placement diagnostic |
| `issue-29-*` | directive/include/main-file preprocessing probes |
| `issue-33-*` | switch break/fallthrough, f-string interpolation, and lambda negative probes |
| `receiver-playervar` | bare variable member expression `A = B.C` with preserved receiver/member provenance |
Expand Down Expand Up @@ -128,7 +135,7 @@ reference diagnostics, exactly like the pinned oracle behaves.

## Not ported / dropped

* **No fixture was dropped for provenance reasons**: all 44 fixtures in the
* **No fixture was dropped for provenance reasons**: all 46 fixtures in the
WrightKit corpus carried complete, reviewed provenance and are ported.
* Upstream `examples/` not ported (candidates for later expansion once a
demonstrated need exists): `lucioball_all_heroes.opy`, `skirmish_elim.opy`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"schemaVersion": 1,
"id": "synthetic/issue-47-control-flow",
"category": "compilation",
"features": ["control flow", "if", "while", "for", "doWhile", "switch", "break"],
"source": "source.opy",
"expectedStatus": "success",
"provenance": {
"kind": "original",
"origin": "opy-rs Issue #47 pinned control-flow lowering probe",
"license": "AGPL-3.0-or-later",
"redistributable": true
}
}
27 changes: 27 additions & 0 deletions compatibility/fixtures/synthetic/issue-47-control-flow/oracle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compile": {
"diagnostics": [],
"exitCode": 0,
"status": "success",
"stdout": "",
"workshop": "variables {\n global:\n 0: value\n 8: I\n}\n\nrule (\"issue 47 control flow\") {\n event {\n Ongoing - Global;\n }\n actions {\n Modify Global Variable(value, Add, 1);\n Skip If(Compare(Global.value, ==, 1), 2);\n Modify Global Variable(value, Add, 10);\n Loop If(Compare(Global.value, <, 2));\n //__label_break_2__:\n If(Compare(Global.value, ==, 2));\n Set Global Variable(value, 3);\n Else If(Compare(Global.value, ==, 4));\n Set Global Variable(value, 5);\n Else;\n Set Global Variable(value, 6);\n End;\n For Global Variable(I, 0, 2, 1);\n If(Compare(Global.I, ==, 1));\n Modify Global Variable(value, Add, 1);\n End;\n End;\n While(Compare(Global.value, <, 5));\n Modify Global Variable(value, Add, 1);\n End;\n If(True);\n Skip(Value In Array(Array(3, 0, 1), Add(1, Index Of Array Value(Array(5, 6), Global.value))));\n //__label_switch_3_0__:\n Set Global Variable(value, 6);\n //__label_switch_3_1__:\n Set Global Variable(value, 7);\n Else;\n //__label_switch_3_default__:\n Set Global Variable(value, 8);\n End;\n }\n}\n",
"workshopExact": "variables {\n global:\n 0: value\n 8: I\n}\n\nrule (\"issue 47 control flow\") {\n event {\n Ongoing - Global;\n }\n actions {\n Modify Global Variable(value, Add, 1);\n Skip If(Compare(Global.value, ==, 1), 2);\n Modify Global Variable(value, Add, 10);\n Loop If(Compare(Global.value, <, 2));\n //__label_break_2__:\n If(Compare(Global.value, ==, 2));\n Set Global Variable(value, 3);\n Else If(Compare(Global.value, ==, 4));\n Set Global Variable(value, 5);\n Else;\n Set Global Variable(value, 6);\n End;\n For Global Variable(I, 0, 2, 1);\n If(Compare(Global.I, ==, 1));\n Modify Global Variable(value, Add, 1);\n End;\n End;\n While(Compare(Global.value, <, 5));\n Modify Global Variable(value, Add, 1);\n End;\n If(True);\n Skip(Value In Array(Array(3, 0, 1), Add(1, Index Of Array Value(Array(5, 6), Global.value))));\n //__label_switch_3_0__:\n Set Global Variable(value, 6);\n //__label_switch_3_1__:\n Set Global Variable(value, 7);\n Else;\n //__label_switch_3_default__:\n Set Global Variable(value, 8);\n End;\n }\n}\n\n",
"workshopSha256": "70c21e1ee305a46f8195e9ff0f322ac22797314c1f157e07ad3e333ea6d9bc69"
},
"fixture": "synthetic/issue-47-control-flow",
"input": {
"sha256": "8ff446e90c2d5b1827c42d4d3480951b8059dad1c7f9ecb7f0a6e18a63f1ca77",
"source": "source.opy"
},
"oracle": {
"gitHead": "1e2688954302a402d076944b46db07efb14d7b61",
"integrity": "sha512-oX17nauJcPTaKIrRFY/rD0Rl8atqFUVv9Hg2TKH+A68/fC8+ZO344Mkd1A/Y0oOVp1hr5tktMBjzMEDDnMEYUw==",
"language": "en-US",
"license": "GPL-3.0-only",
"name": "overpy",
"registryTarball": "https://registry.npmjs.org/overpy/-/overpy-9.7.10.tgz",
"repository": "https://github.com/Zezombye/overpy",
"version": "9.7.10"
},
"schemaVersion": 1
}
29 changes: 29 additions & 0 deletions compatibility/fixtures/synthetic/issue-47-control-flow/source.opy
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
globalvar value = 0

rule "issue 47 control flow":
@Event global
do:
value += 1
if value == 1:
break
value += 10
while value < 2
if value == 2:
value = 3
elif value == 4:
value = 5
else:
value = 6
for I in range(0, 2):
if I == 1:
value += 1
while value < 5:
value += 1
switch value:
case 5:
value = 6
case 6:
value = 7
break
default:
value = 8
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"schemaVersion": 1,
"id": "synthetic/issue-47-do-while-invalid-placement",
"category": "diagnostics",
"features": ["doWhile", "placement-diagnostic"],
"source": "source.opy",
"expectedStatus": "failure",
"provenance": {
"kind": "original",
"origin": "opy-rs Issue #47 pinned do-while placement diagnostic probe",
"license": "AGPL-3.0-or-later",
"redistributable": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"compile": {
"diagnostics": [
{
"severity": "error",
"text": "Error: Do/While loops can only be at the beginning of a rule: parent is '__rule__' and childIndex is 1\n | line 6, col 5, at source.opy"
}
],
"exitCode": 1,
"status": "failure",
"stdout": "",
"workshop": "",
"workshopExact": "",
"workshopSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"fixture": "synthetic/issue-47-do-while-invalid-placement",
"input": {
"sha256": "b7df07df9799afec1c139cd0a23764804feeaccf7aae8dc7d9be575f37c1e5c7",
"source": "source.opy"
},
"oracle": {
"gitHead": "1e2688954302a402d076944b46db07efb14d7b61",
"integrity": "sha512-oX17nauJcPTaKIrRFY/rD0Rl8atqFUVv9Hg2TKH+A68/fC8+ZO344Mkd1A/Y0oOVp1hr5tktMBjzMEDDnMEYUw==",
"language": "en-US",
"license": "GPL-3.0-only",
"name": "overpy",
"registryTarball": "https://registry.npmjs.org/overpy/-/overpy-9.7.10.tgz",
"repository": "https://github.com/Zezombye/overpy",
"version": "9.7.10"
},
"schemaVersion": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
globalvar value

rule "issue 47 invalid do while placement":
@Event global
value = 1
do:
value += 1
while value < 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"schemaVersion": 1,
"id": "synthetic/issue-47-do-while-shapes",
"category": "compilation",
"features": ["doWhile", "break", "nested-doWhile"],
"source": "source.opy",
"expectedStatus": "success",
"provenance": {
"kind": "original",
"origin": "opy-rs Issue #47 pinned do-while break-shape lowering probe",
"license": "AGPL-3.0-or-later",
"redistributable": true
}
}
Loading