diff --git a/README.md b/README.md index 21c56f7..bfe65b2 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,9 @@ compatibility corpus and pinned OverPy reference evidence. | Workshop β†’ OPY reconstruction | ⏳ Not yet | Will consume canonical `workshop-rs` semantics and remain owned by `opy-rs` | Exact per-feature evidence remains available in the -[human-readable support reference](docs/opy/support-matrix.md) and -[machine-readable support matrix](compatibility/support-matrix.json). +[canonical human-readable support contract](docs/language-support.md). Internal +fixture and implementation metadata remains in +[compatibility/support-matrix.json](compatibility/support-matrix.json). ## Relationship with Wright diff --git a/compatibility/support-matrix.json b/compatibility/support-matrix.json index 25e9376..247030e 100644 --- a/compatibility/support-matrix.json +++ b/compatibility/support-matrix.json @@ -1,5 +1,6 @@ { "schemaVersion": 1, + "visibility": "internal-engineering-metadata", "artifact": "opy-rs OverPy feature inventory and support matrix", "reference": { "name": "overpy", diff --git a/docs/README.md b/docs/README.md index 80efea6..c4465b5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,7 +18,7 @@ architecture, compatibility evidence, APIs, and internal contracts live here. ## Compatibility -- [Support reference](opy/support-matrix.md): detailed, corpus-evidenced OverPy +- [OverPy support contract](language-support.md): audited, human-readable OverPy feature coverage. - [Compatibility baseline](opy/compatibility-baseline.md): planning/reference inventory for remaining OverPy surface and compatibility priorities. diff --git a/docs/compatibility/upstream-references.md b/docs/compatibility/upstream-references.md index e784113..5040e0d 100644 --- a/docs/compatibility/upstream-references.md +++ b/docs/compatibility/upstream-references.md @@ -103,8 +103,8 @@ The harness invokes the oracle only through documented, isolated entry points: ### Upstream surfaces inspected for the inventory -The feature inventory in [`docs/opy/support-matrix.md`](../opy/support-matrix.md) -and [`docs/opy/compatibility-baseline.md`](../opy/compatibility-baseline.md) is +The feature inventory in [`docs/language-support.md`](../language-support.md) and +its linked component inventories is grounded in the pinned tree, specifically: * `README.md`: user-visible syntax tour (rules, annotations, subroutines, @@ -259,7 +259,7 @@ when the oracle is absent. ## Related documents -* [`docs/opy/support-matrix.md`](../opy/support-matrix.md): corpus-evidenced declared surface and current states +* [`docs/language-support.md`](../language-support.md): audited public support contract and current states * [`docs/opy/compatibility-baseline.md`](../opy/compatibility-baseline.md): tiered planning baseline * [`docs/opy/compat-manifest-spec.md`](../opy/compat-manifest-spec.md): machine-readable semantic manifest specification * [`docs/opy/tooling-notes.md`](../opy/tooling-notes.md): harness usage diff --git a/docs/language-support.md b/docs/language-support.md new file mode 100644 index 0000000..c6f3906 --- /dev/null +++ b/docs/language-support.md @@ -0,0 +1,65 @@ +# OverPy support + +This is the canonical, human-readable compatibility contract for `opy-rs`. +The detailed inventories linked here are part of the same contract. + +## Reference and audit boundary + +| Field | Value | +| --- | --- | +| OverPy package | `9.7.10` | +| Content commit | `889d9749d1def17f146548cbddb94ea1ab015847` (`v9.7.10`) | +| Repository | | +| Registry integrity | `sha512-oX17nauJcPTaKIrRFY/rD0Rl8atqFUVv9Hg2TKH+A68/fC8+ZO344Mkd1A/Y0oOVp1hr5tktMBjzMEDDnMEYUw==` | +| Audited language | `en-US` | + +The inventory was audited from the pinned upstream tree, from outside the +`opy-rs` implementation: the upstream README and public API declaration; +`src/compiler/` grammar, preprocessing, compiler, translation and decompiler +surfaces; `src/data/opy/` keyword, annotation, builtin, member, module, macro +and preprocessing registries; `src/data/` Workshop domains; upstream compile, +decompile, CLI and QuickJS tests; and the pinned executable oracle. Existing +`opy-rs` fixtures, HIR names, support matrix entries and issue lists were used +only to determine the second column, never to construct the audited set. + +## Status vocabulary + +Only these public states are used: + +- `βœ… Supported` β€” the claimed user-visible behavior works within the notes. +- `🚧 Coming soon` β€” the pinned capability is recognized, but current behavior + is incomplete. +- `❌ Unsupported` β€” the capability is outside the current contract. + +β€œSupported” is an end-to-end claim for the stated row. Parsing a construct or +having a name in a manifest is not enough to make a compilation row green. + +## Audited capability summary + +| Area | Status | Detailed inventory | +| --- | --- | --- | +| Source syntax, literals and expressions | 🚧 Coming soon | [syntax and project composition](language-support/syntax-and-projects.md) | +| Assignments, declarations, rules and control flow | 🚧 Coming soon | [syntax and project composition](language-support/syntax-and-projects.md) | +| Builtins, member functions, constants and contextual domains | 🚧 Coming soon | [callables and domains](language-support/callables-and-domains.md) and [complete registries](language-support/registries.md) | +| Preprocessing, includes, modules and macros | 🚧 Coming soon | [syntax and project composition](language-support/syntax-and-projects.md) and [complete registries](language-support/registries.md) | +| Strings, translations and custom-game settings | 🚧 Coming soon | [syntax and project composition](language-support/syntax-and-projects.md) | +| Compiler directives, optimization and post-compile hooks | 🚧 Coming soon | [tooling and backend](language-support/tooling-and-backend.md) and [complete registries](language-support/registries.md) | +| Standalone compiler and CLI | βœ… Supported | [tooling and backend](language-support/tooling-and-backend.md) | +| Workshop-to-OPY decompilation | ❌ Unsupported | [tooling and backend](language-support/tooling-and-backend.md) | + +The summary is intentionally conservative: the audited upstream surface is +larger than the currently evidenced `opy-rs` surface. Detailed rows make gaps +explicit instead of hiding them in a category-level green row. + +## Contract maintenance + +`compatibility/support-matrix.json` is retained as **internal engineering +metadata** for fixture relationships, provenance and implementation tracking. +It is not a public inventory and its internal states are not public support +states. `docs/opy/support-matrix.md` is retained as historical context and +must not introduce another public status vocabulary. + +The next step is a separate exhaustive conformance issue driven by the audited +leaf identities in these documents. This issue does not turn the inventory +into a fixed feature-count assertion or silently convert known gaps into +passing cases. diff --git a/docs/language-support/callables-and-domains.md b/docs/language-support/callables-and-domains.md new file mode 100644 index 0000000..2c76525 --- /dev/null +++ b/docs/language-support/callables-and-domains.md @@ -0,0 +1,63 @@ +# OverPy audited inventory: callables and domains + +Source: pinned OverPy `9.7.10`, content commit +`889d9749d1def17f146548cbddb94ea1ab015847`. The external callable registries +are `src/data/opy/functions.ts`, `memberFunctions.ts`, `constants.ts`, +`modules.ts`, and `macros.ts`; Workshop registries are `src/data/actions.ts`, +`values.ts`, `constants.ts`, `heroes.ts`, `maps.ts`, `gamemodes.ts`, +`localizedStrings.ts`, and `customGameSettings.ts`. + +The upstream registries are the audited inventory source and are not copied +into `opy-rs`. Each callable contract has a spelling, receiver (if any), +ordered arguments, argument type/domain, optional/default behavior, return +behavior, and dispatch rule. + +## Standalone functions and operators + +| Feature / representative leaf | Status | Audited contract | +| --- | --- | --- | +| `abs(value)` | βœ… Supported | One numeric value; numeric result. | +| `len(arrayOrString)` | βœ… Supported | One array/string value; integer result. | +| `range(stop)` / `range(start, stop[, step])` | βœ… Supported | Optional start and step have distinct defaults. | +| `wait(duration[, reevaluation])` | βœ… Supported | Reevaluation has an optional default. | +| `raiseToPower(base, exponent)` | βœ… Supported | Two numeric arguments in order; value operation. | +| `sorted(array[, key])` | βœ… Supported | Optional lambda key; element/index binder is contextual. | +| `all(array)` / `any(array)` | βœ… Supported | One boolean-array value. | +| `random.randint(min, max)` | 🚧 Coming soon | Two inclusive integer bounds; integer result. | +| `random.uniform(min, max)` | 🚧 Coming soon | Two float bounds; float result. | +| `random.choice(array)` | 🚧 Coming soon | One array; returns an element or supplied non-array value. | +| `random.shuffle(array)` | 🚧 Coming soon | One array; returns a copied array. | +| `_(contextOrString[, string])` | 🚧 Coming soon | One-argument and two-argument modes differ. | + +## Receiver/member functions + +| Feature / representative leaf | Status | Audited contract | +| --- | --- | --- | +| `array.append(value)` | βœ… Supported | Array receiver; mutating; arrays are extended. | +| `array.concat(value)` | βœ… Supported | Array receiver; returns a copy. | +| `array.filter(lambda)` | βœ… Supported | Lambda result selects elements; optional index binder. | +| `array.map(lambda)` | βœ… Supported | Lambda result replaces each element. | +| `array.all([lambda])` / `array.any([lambda])` | βœ… Supported | Optional lambda defaults to element truthiness. | +| `array[index]` and `array.slice(start, count)` | βœ… Supported | Indexing and slicing have different arguments. | +| `string.format(...)` | 🚧 Coming soon | Variadic formatting remains incomplete. | +| `player.setStatusEffect(player, assister, status, duration)` | 🚧 Coming soon | Receiver plus four ordered explicit arguments. | +| `vector.x`, `.y`, `.z` | βœ… Supported | Property-like vector access; numeric result. | +| `self` in member macros | 🚧 Coming soon | Dispatch target is the macro receiver. | + +## Constants, enums and contextual dispatch + +| Feature | Status | Notes | +| --- | --- | --- | +| `Hero`, `Map`, `Gamemode`, `Team`, `Slot`, `Color`, `Button` domains | 🚧 Coming soon | Membership and spelling are domain-specific. | +| `Vector.UP/DOWN/LEFT/RIGHT/FORWARD/BACKWARD` | βœ… Supported | Constants are separate from arbitrary vectors. | +| `Math.PI`, `Math.E`, `Math.INFINITY`, `Math.EPSILON` | 🚧 Coming soon | Numeric constants are distinct leaves. | +| User enum assignment and inferred increments | βœ… Supported | Separate from Workshop catalog domains. | +| Contextual `None`/reevaluation enum dispatch | 🚧 Coming soon | `ChaseTimeReeval`, `ChaseRateReeval` and `Invis` differ. | +| Alias resolution (`getCurrentHero`, `hasStatusEffect`, `ChaseReeval`) | βœ… Supported | Non-contextual and call-context aliases differ. | + +The pinned `functions.ts`, `actions.ts`, `memberFunctions.ts` and `values.ts` +registries contain the complete callable surface. The audit keeps families +separate because action/value position, receiver type, defaults, overloads and +return behavior differ. A name in the current internal manifest is evidence +for `opy-rs` only; it does not expand this inventory or make an incomplete +callable green. diff --git a/docs/language-support/registries.md b/docs/language-support/registries.md new file mode 100644 index 0000000..224a033 --- /dev/null +++ b/docs/language-support/registries.md @@ -0,0 +1,193 @@ +# OverPy audited inventory: complete source registries + +This page is the leaf inventory for the named upstream registries. Every key +in the pinned OverPy `9.7.10` files is listed below; no current `opy-rs` +manifest or fixture is used to define the set. The upstream registry supplies +the full argument order, argument type/domain, defaults, return behavior and +dispatch rule. The user-facing status is reconciled against current +`opy-rs` evidence. + +Reference: `889d9749d1def17f146548cbddb94ea1ab015847`. + +## Keywords (`src/data/opy/keywords.ts`) + +| Upstream key | Status | +| --- | --- | +| `and` | βœ… Supported | +| `or` | βœ… Supported | +| `not` | βœ… Supported | +| `bool` | βœ… Supported | +| `float` | βœ… Supported | +| `int` | βœ… Supported | +| `signed` | βœ… Supported | +| `unsigned` | βœ… Supported | +| `case` | βœ… Supported | +| `default` | βœ… Supported | +| `switch` | βœ… Supported | +| `def` | βœ… Supported | +| `subroutine` | βœ… Supported | +| `rule` | βœ… Supported | +| `del` | 🚧 Coming soon | +| `elif` | βœ… Supported | +| `else` | βœ… Supported | +| `if` | βœ… Supported | +| `enum` | βœ… Supported | +| `for` | βœ… Supported | +| `while` | βœ… Supported | +| `globalvar` | βœ… Supported | +| `playervar` | βœ… Supported | +| `goto` | 🚧 Coming soon | +| `loc` | 🚧 Coming soon | +| `in` | βœ… Supported | +| `lambda` | βœ… Supported | +| `macro` | βœ… Supported | +| `self` | 🚧 Coming soon | +| `settings` | 🚧 Coming soon | +| `main` | 🚧 Coming soon | +| `gamemodes` | 🚧 Coming soon | +| `heroes` | 🚧 Coming soon | + +## Preprocessing directives (`src/data/opy/preprocessing.ts`) + +| Upstream key | Status | +| --- | --- | +| `allowMacroRedeclaration` | 🚧 Coming soon | +| `define` | βœ… Supported | +| `debugElementCount` | 🚧 Coming soon | +| `disableInspector` | 🚧 Coming soon | +| `suppressWarnings` | 🚧 Coming soon | +| `mainFile` | βœ… Supported | +| `include` | βœ… Supported | +| `excludeVariablesInCompilation` | 🚧 Coming soon | +| `setupTags` | 🚧 Coming soon | +| `disableOptimizations` | 🚧 Coming soon | +| `enableOptimizations` | 🚧 Coming soon | +| `optimizeForSize` | 🚧 Coming soon | +| `optimizeForSizeAggressive` | 🚧 Coming soon | +| `disableOptimizeForSize` | 🚧 Coming soon | +| `optimizeStrict` | 🚧 Coming soon | +| `disableOptimizeStrict` | 🚧 Coming soon | +| `replace0ByCapturePercentage` | 🚧 Coming soon | +| `replace0ByPayloadProgressPercentage` | 🚧 Coming soon | +| `replace0ByIsMatchComplete` | 🚧 Coming soon | +| `replace1ByMatchRound` | 🚧 Coming soon | +| `replaceTeam1ByControlScoringTeam` | 🚧 Coming soon | +| `replaceEmptyStringByEmptyArray` | 🚧 Coming soon | +| `replaceEmptyStringByVariable` | 🚧 Coming soon | +| `translations` | 🚧 Coming soon | +| `translateWithPlayerVar` | 🚧 Coming soon | +| `useVariableForCompressionAlphabet` | 🚧 Coming soon | +| `extension` | 🚧 Coming soon | +| `globalvarInitRuleName` | 🚧 Coming soon | +| `playervarInitRuleName` | 🚧 Coming soon | +| `keepUnusedTranslations` | 🚧 Coming soon | +| `disableTranslationSourceLines` | 🚧 Coming soon | +| `writeToOutputFile` | 🚧 Coming soon | +| `postCompileHook` | 🚧 Coming soon | +| `rulePrefix`, `rulePrefixTemplate` | 🚧 Coming soon | + +## Annotations (`src/data/opy/annotations.ts`) + +| Upstream key | Status | Contract | +| --- | --- | --- | +| `@Name` | βœ… Supported | One string literal; subroutine rule name. | +| `@Event` | βœ… Supported | One event-domain value. | +| `@Team` | βœ… Supported | One team-domain value. | +| `@Slot` | βœ… Supported | One slot-domain value; mutually exclusive with `@Hero`. | +| `@Hero` | βœ… Supported | One hero-domain value; mutually exclusive with `@Slot`. | +| `@Condition` | βœ… Supported | One condition expression; repeatable. | +| `@SuppressWarnings` | βœ… Supported | Space-separated warning names. | +| `@Disabled` | βœ… Supported | No arguments; disables generated rule. | +| `@Delimiter` | βœ… Supported | No arguments; preserves a UI delimiter rule. | +| `@NewPage` | βœ… Supported | No required arguments; inserts page boundary rules. | + +## Modules (`src/data/opy/modules.ts`) + +| Upstream key | Status | Contract | +| --- | --- | --- | +| `random.randint(min, max)` | 🚧 Coming soon | Two inclusive integer bounds; integer result. | +| `random.uniform(min, max)` | 🚧 Coming soon | Two float bounds; float result. | +| `random.choice(array)` | 🚧 Coming soon | One array; element result. | +| `random.shuffle(array)` | 🚧 Coming soon | One array; copied array result. | + +## Built-in macros (`src/data/opy/macros.ts`) + +| Upstream key | Status | +| --- | --- | +| `buttonToString` | 🚧 Coming soon | +| `.getEffectiveHero`, `.getOppositeTeam` | 🚧 Coming soon | +| `getRealClosestPlayer`, `getRealClosestPlayers` | 🚧 Coming soon | +| `getRealFarthestPlayer`, `getRealFarthestPlayers` | 🚧 Coming soon | +| `.getRealPlayerClosestToReticle`, `.getRealPlayersClosestToReticle` | 🚧 Coming soon | +| `getRealPlayersInRadius`, `.getRealPlayersInViewAngle` | 🚧 Coming soon | +| `getSign`, `getAllPlayers` | 🚧 Coming soon | +| `hudHeader`, `hudSubheader`, `hudSubtext` | 🚧 Coming soon | +| `lerp`, `lineIntersectsSphere` | 🚧 Coming soon | +| `print`, `.reverse`, `timeToString`, `.unique` | 🚧 Coming soon | + +## Built-in functions and member functions + +The following table lists every key in `src/data/opy/functions.ts`; entries +beginning with `.` are receiver dispatch entries. The separate +`src/data/opy/memberFunctions.ts` property entries follow it. + +| Upstream key | Status | +| --- | --- | +| `_`, `__`, `___` | 🚧 Coming soon | +| `all` | βœ… Supported | +| `any` | βœ… Supported | +| `.append` | βœ… Supported | +| `.all` | βœ… Supported | +| `.any` | βœ… Supported | +| `.filter` | βœ… Supported | +| `.map` | βœ… Supported | +| `arrayToString` | 🚧 Coming soon | +| `ceil` | 🚧 Coming soon | +| `floor` | 🚧 Coming soon | +| `round` | 🚧 Coming soon | +| `hsl` | 🚧 Coming soon | +| `chaseAtRate` | 🚧 Coming soon | +| `chaseOverTime` | 🚧 Coming soon | +| `compress` | 🚧 Coming soon | +| `compressed` | 🚧 Coming soon | +| `decompressNumbers` | 🚧 Coming soon | +| `decompressVectors` | 🚧 Coming soon | +| `createCasedProgressBarIwt` | 🚧 Coming soon | +| `debug` | 🚧 Coming soon | +| `.format` | 🚧 Coming soon | +| `.remove` | 🚧 Coming soon | +| `getCurrentMap` | βœ… Supported | +| `.getNormal` | 🚧 Coming soon | +| `.getPlayerHit` | 🚧 Coming soon | +| `.getHitPosition` | 🚧 Coming soon | +| `log` | 🚧 Coming soon | +| `pass` | βœ… Supported | +| `range` | βœ… Supported | +| `raycast` | 🚧 Coming soon | +| `ruleCondition` | βœ… Supported | +| `sorted` | βœ… Supported | +| `spacesForString` | 🚧 Coming soon | +| `spacesForLength` | 🚧 Coming soon | +| `strVisualLength` | 🚧 Coming soon | +| `splitDictArray` | 🚧 Coming soon | +| `stopChasing` | 🚧 Coming soon | +| `tabular` | 🚧 Coming soon | +| `.toArray` | 🚧 Coming soon | +| `x` (property member) | βœ… Supported | +| `y` (property member) | βœ… Supported | +| `z` (property member) | βœ… Supported | + +The upstream Workshop action/value registries are separate complete data +surfaces in `src/data/actions.ts` and `src/data/values.ts`. They are canonical +Workshop semantics owned by `workshop-rs`; this document does not copy those +registries into `opy-rs`. Their OPY spellings and dispatch contracts are +tracked by the function/member rows above and by the owning Workshop +catalogue. + +## Constants (`src/data/opy/constants.ts`) + +| Upstream key | Status | +| --- | --- | +| `Vector` (`UP`, `DOWN`, `LEFT`, `RIGHT`, `FORWARD`, `BACKWARD`) | βœ… Supported | +| `Math` (`PI`, `E`, `INFINITY`, `EPSILON`, and documented spacing/radius constants) | 🚧 Coming soon | +| `Texture` (complete texture constant registry) | 🚧 Coming soon | diff --git a/docs/language-support/syntax-and-projects.md b/docs/language-support/syntax-and-projects.md new file mode 100644 index 0000000..dc4f9b3 --- /dev/null +++ b/docs/language-support/syntax-and-projects.md @@ -0,0 +1,72 @@ +# OverPy audited inventory: syntax and project composition + +Source: pinned OverPy `9.7.10`, content commit +`889d9749d1def17f146548cbddb94ea1ab015847`. The source surfaces used are +`README.md`, `src/compiler/tokenizer.ts`, `parser.ts`, `astParser.ts`, +`src/data/opy/keywords.ts`, `annotations.ts`, `preprocessing.ts`, +`modules.ts`, `macros.ts`, and the upstream files under `src/tests/`. + +## Lexical and expression surface + +| Feature | Status | Notes | +| --- | --- | --- | +| `#` line comments and `/* ... */` block comments | βœ… Supported | Source parsing is covered by the native pipeline and corpus. | +| Identifiers, indentation and rule/subroutine blocks | βœ… Supported | Includes `rule "name":` and `def name():`. | +| Boolean, integer, float and `null` literals | βœ… Supported | Numeric edge cases remain conformance work. | +| Strings, escaped strings and implicit concatenation | βœ… Supported | String modifiers are separate rows. | +| f-string/interpolated strings | βœ… Supported | Supported formatting subset is fixture-covered. | +| String modifiers `f`, `w`, `l`, `b`, `c`, `t` | βœ… Supported | Each modifier is a distinct lexical form. | +| Array literals and indexing | βœ… Supported | Includes nested arrays. | +| Dictionary literals and keyed access | 🚧 Coming soon | Source analysis exists; full compilation is incomplete. | +| List comprehensions | βœ… Supported | Mapping and filtering are separate behaviors. | +| `lambda` with element/index binders | βœ… Supported | Valid positions are contextual. | +| Member access, calls and postfix expressions | βœ… Supported | Receiver and dispatch checks are contract-sensitive. | +| `del` array element statement | 🚧 Coming soon | Audited upstream keyword; compilation support is incomplete. | +| Conditional value `a if condition else b` | 🚧 Coming soon | Distinct from statement `if`. | +| `in` and `not in` membership | βœ… Supported | String containment uses `strContains`. | +| Arithmetic, comparison, boolean and unary operators | βœ… Supported | Augmented forms are separate rows below. | +| `++` and `--` postfix modifiers | 🚧 Coming soon | Audited upstream operator surface. | +| `0x`/`0X` hexadecimal literals | βœ… Supported | Case variants are one semantic capability. | + +## Assignments and declarations + +| Feature | Status | Notes | +| --- | --- | --- | +| Simple assignment `=` | βœ… Supported | Global, player and indexed forms differ at lowering. | +| `+=`, `-=`, `*=`, `/=`, `%=` | βœ… Supported | Each spelling is independently audited. | +| `**=` augmented assignment | βœ… Supported | Separate from `**`; uses Raise To Power. | +| `min=` and `max=` modification forms | 🚧 Coming soon | Recognized by the audit; Workshop support is not claimed. | +| `globalvar name [index]` | βœ… Supported | Explicit and implicit index forms are distinct. | +| `playervar name [index]` | βœ… Supported | Explicit and implicit index forms are distinct. | +| Variable initializer `globalvar/playervar name = value` | βœ… Supported | Constant-zero behavior is observable. | +| `enum` declarations and inferred member values | βœ… Supported | Contextual enum use is separate. | +| `macro` constants and function macros | βœ… Supported | Member/default-parameter forms are separate contracts. | +| `def` subroutines, calls and `return` | βœ… Supported | Upstream subroutines have no parameters or returns. | + +## Rules, control flow and project composition + +| Feature | Status | Notes | +| --- | --- | --- | +| Rule events: `global`, `eachPlayer`, team/hero/slot domains | βœ… Supported | Event and domain arguments are distinct. | +| `@Condition` and multiple conditions | βœ… Supported | | +| `@Name`, `@Disabled`, `@Delimiter`, `@NewPage`, `@SuppressWarnings` | βœ… Supported | Each annotation has independent effects. | +| `if` / `elif` / `else` statements | βœ… Supported | Inline conditional values are separate. | +| `for ... in range(start, stop, step)` | βœ… Supported | Global/player binders are separate. | +| `while` and `do ... while` loops | βœ… Supported | Distinct entry-condition behavior. | +| `switch` / `case` / `default` | βœ… Supported | Fall-through and `break` are separate. | +| `break` in loops and switch arms | βœ… Supported | | +| `continue` in loops | 🚧 Coming soon | Upstream keyword exists; end-to-end support is incomplete. | +| `goto`, labels and dynamic `loc+` targets | 🚧 Coming soon | Audited from keyword registry and `src/tests/gotos.opy`. | +| `pass` and `return` statements | βœ… Supported | Context restrictions remain conformance work. | +| `#!include` root-relative composition | βœ… Supported | Missing files and cycles have distinct failures. | +| Nested include closure and main-file selection | βœ… Supported | Project behavior is not inferred from one-file tests. | + +## Settings, strings and translations + +| Feature | Status | Notes | +| --- | --- | --- | +| `settings { ... }` custom-game-settings block | 🚧 Coming soon | Typed source representation exists; complete behavior is incomplete. | +| Schema keys, enum values and map/hero list settings | 🚧 Coming soon | Audited against upstream schema/data. | +| `#!translations` and `.po` translation sources | 🚧 Coming soon | Declaration and output lifecycle are separate. | +| `_`, `__`, `___` translation functions | 🚧 Coming soon | One- and two-argument modes differ. | +| Localized output language selection | 🚧 Coming soon | Upstream supports all in-game languages. | diff --git a/docs/language-support/tooling-and-backend.md b/docs/language-support/tooling-and-backend.md new file mode 100644 index 0000000..531f11b --- /dev/null +++ b/docs/language-support/tooling-and-backend.md @@ -0,0 +1,47 @@ +# OverPy audited inventory: tooling and backend behavior + +Source: pinned OverPy `9.7.10`, content commit +`889d9749d1def17f146548cbddb94ea1ab015847`. Evidence surfaces are the +upstream README, `overpy.d.ts`, `cli.js`, compiler/decompiler sources, +`runTests.mjs`, `runCliTests.mjs`, QuickJS fixtures and the executable oracle. + +## Preprocessing, macros and hooks + +| Feature | Status | Notes | +| --- | --- | --- | +| `#!define` object/function macros and `#!undef` | βœ… Supported | Expansion, precedence and recursion are distinct checks. | +| `#!allowMacroRedeclaration` | 🚧 Coming soon | Changes duplicate-definition failure behavior. | +| `#!mainFile`, `#!include`, `#!excludeVariablesInCompilation` | βœ… Supported | Selection and output filtering have separate effects. | +| Optimization controls (`#!enableOptimizations`, `#!disableOptimizations`, `#!optimize*`) | 🚧 Coming soon | Recognition is not backend-effect support. | +| Replacement directives (`#!replace0By*`, team/string replacements) | 🚧 Coming soon | Each replacement target has its own output contract. | +| `#!rulePrefix` and `#!rulePrefixTemplate` | 🚧 Coming soon | Prefix text and placeholders are separate. | +| `#!extension` and extension-point accounting | 🚧 Coming soon | Output metadata is part of the contract. | +| `macro name(params)` function/constant macros | βœ… Supported | Defaults, keywords and member macros differ. | +| `__script__` JavaScript macros | 🚧 Coming soon | QuickJS return ABI and limits are observable. | +| `#!postCompileHook` | 🚧 Coming soon | Parsing is not execution against final Workshop text. | + +## Compilation, CLI and API + +| Feature | Status | Notes | +| --- | --- | --- | +| Standalone `.opy` compiler library | βœ… Supported | Supported within the documented source/compile scope. | +| CLI compile/check invocation and structured diagnostics | βœ… Supported | Exit behavior and source attribution are contractual. | +| Upstream JS `compile(content, language, rootPath, mainFileName)` API | 🚧 Coming soon | API shape audited; Rust parity is incomplete. | +| Compile metadata: variables, subroutines, warnings, translations, element count | 🚧 Coming soon | Fields have independent completeness requirements. | +| Localized Workshop text and custom settings emission | 🚧 Coming soon | Canonical Workshop semantics remain in `workshop-rs`. | +| Observable optimization/replacement effects | 🚧 Coming soon | Formatting is not a target unless observable. | + +## Decompilation and round trips + +| Feature | Status | Notes | +| --- | --- | --- | +| `decompileAllRules` Workshop-to-OPY reconstruction | ❌ Unsupported | Outside the current `opy-rs` contract. | +| `decompileActions` and `decompileConditions` | ❌ Unsupported | Same boundary as full decompilation. | +| Workshop settings decompilation | ❌ Unsupported | No claim of recovering original source abstractions. | +| Compile/decompile round trip preserving source identity | ❌ Unsupported | Comments, macros, names and formatting are not promised. | + +The upstream source is GPL-3.0-only and is used as an external audit +reference/oracle. Its implementation and data are not copied into `opy-rs`. +The exhaustive conformance follow-up should derive stable leaf cases from the +audited registries, preserve negative behavior, and compare observable +semantics rather than Workshop formatting or internal compiler structure. diff --git a/docs/opy/support-matrix.md b/docs/opy/support-matrix.md index 4780245..57980d7 100644 --- a/docs/opy/support-matrix.md +++ b/docs/opy/support-matrix.md @@ -1,408 +1,9 @@ -# opy-rs Native .opy Frontend Support Matrix +# Support documentation redirect -Status: accepted baseline. A living .opy frontend support matrix for the -opy-rs evidence base (issue #2) -Scope: the `.opy` source-language surface the opy-rs native frontend targets, -with corpus/production evidence for each feature and explicitly deferred -constructs; the current per-feature implementation state is tracked -mechanically in [`compatibility/support-matrix.json`](../../compatibility/support-matrix.json) +The canonical public OverPy compatibility contract is +[`../language-support.md`](../language-support.md). Its linked inventories are +the complete audited support documentation for pinned OverPy `9.7.10`. -This matrix records the **declared, corpus-evidenced surface**: every claimed -feature is backed by the compatibility corpus -(`compatibility/fixtures/**/source.opy`, `oracle.json` snapshots) or marked as -investigation. It is ported and adapted from the WrightKit project's evidence -base (wright `docs/opy/support-matrix.md`); the reference identity behind both -is recorded centrally in -[`docs/compatibility/upstream-references.md`](../compatibility/upstream-references.md). - -The forward-looking, tiered baseline (what is planned, evidence-prioritized, -or demand-driven) lives in -[`compatibility-baseline.md`](compatibility-baseline.md), and the -machine-readable semantic contract for builtins is specified in -[`compat-manifest-spec.md`](compat-manifest-spec.md). - -## Current implementation state - -The standalone frontend foundation and #7 readiness work are merged on `main` -(issues #2–#7, #28–#30, and #33): the native pipeline (lexer β†’ -preprocess β†’ CST/parser β†’ semantic resolution β†’ Opy HIR v2), the bounded -JavaScript macro runtime, the tooling API/CLI, and the native differential -suite are implemented and CI-covered. The rows they evidence are flipped to -`frontend-supported`/`semantic-supported` in -`compatibility/support-matrix.json`, the mechanically checked state source; -features whose completion requires the full canonical Workshop surface remain -`lowering-dependent`; the bounded #35 adapter, the #40 structural HIR β†’ -canonical WIR lowering, the #46 non-control-flow primitive lowering, and the -#47 control-flow lowering are -separately recorded as `end-to-end-supported` and -do not reclassify broader Workshop-owned rows. -Here, `end-to-end-supported` is scoped to the explicitly evidenced feature or -vertical slice; it never means full-language OPY-to-Workshop parity. The wider -#8 lowering stage remains outside this frontend gate. Per-fixture differential status (resolve / -expected-diagnostic / divergence) is recorded in -`target/opy-differential-report.json` by `cargo test -p opy-frontend ---test differential`. - -The declared pipeline is `lexer β†’ preprocess β†’ CST/parser β†’ semantic -resolution β†’ OPY semantic model (Opy HIR v2, see -[`docs/hir/opy-hir-v2.md`](../hir/opy-hir-v2.md))`, fully -Workshop-independent up to the documented integration boundary toward -`workshop-rs` (see [`architecture.md`](architecture.md)). - -## Evidence sources - -| Source | Use | -| --- | --- | -| `compatibility/fixtures/synthetic/{basic-rule,control-flow,declarations-rules,declarations-numbers,expressions-values,preprocessing,diagnostics,settings,receiver-calls,chase-*}/source.opy` | Synthetic corpus surface (WrightKit-authored; oracle snapshots in the same directory) | -| `compatibility/fixtures/real-world/overpy-*/` | Real-world surface from the pinned OverPy `examples/` tree (arrays, macros, effects, settings, subroutines, include closures; provenance in `compatibility/fixtures/README.md`) | -| `compatibility/fixtures/real-world/{ow1-emulator,6v6-adjustments}/` | Independent third-party projects (BSD-2-Clause), full include closures | -| `compatibility/fixtures/**/oracle.json` | Pinned OverPy 9.7.10 reference snapshots (normalized Workshop output, diagnostics, exit codes) | -| `compatibility/fixtures/synthetic/issue-35-integration/` | #35 OPY-to-Workshop vertical-slice evidence; oracle provenance remains separate from implementation-specific WIR/emission assertions | -| `compatibility/fixtures/synthetic/issue-40-structural/` | #40 pinned OverPy oracle evidence for subroutine identity, deterministic variable allocation, and player event filters | -| `compatibility/fixtures/synthetic/issue-46-primitives/` | #46 pinned OverPy oracle evidence for non-control-flow statement and value primitive lowering (assignments and modifications including `**=`, global/player implicit default variables at fixed slots, hex-number normalization, index-0 `firstOf` read normalization, negated-comparison lowering); the oracle snapshot constrains the native compiler through the canonical `workshop-rs` parser and structural equivalence | -| `compatibility/fixtures/synthetic/issue-46-unsupported/` | #46 negative primitive-lowering evidence: the frontend and pinned oracle accept a dict-indexed assignment while the compiler rejects it with the stable source-attributed `unsupported-integration-surface` diagnostic | -| `compatibility/fixtures/synthetic/issue-47-control-flow/` | #47 pinned OverPy oracle evidence for if/elif/else, while, range-for, do-while expansion, switch fallthrough/default, and direct break lowering; native output is reparsed through `workshop-rs` and compared structurally | -| `compatibility/fixtures/synthetic/issue-47-unsupported/` | #47 negative evidence: nested conditional switch-break is preserved by the frontend/oracle and rejected at the canonical WIR boundary with a source-attributed diagnostic | -| `compatibility/fixtures/synthetic/issue-47-switch-order/` | #47 pinned oracle evidence for default-before-case source order and fallthrough; native output is reparsed through `workshop-rs` and compared structurally | -| `compatibility/fixtures/synthetic/issue-47-switch-multiple-break/` | #47 multi-break evidence: frontend/oracle preserve the source, while later reachable actions are rejected explicitly at the canonical WIR boundary because v0.1.11 has no lossless multi-target switch carrier | -| `compatibility/fixtures/synthetic/issue-47-do-while-shapes/` | #47 pinned oracle evidence for direct, conditional, nested, and structured-tail do-while breaks; native output is reparsed through `workshop-rs` and compared structurally | -| `compatibility/fixtures/synthetic/issue-47-do-while-invalid-placement/` | #47 negative evidence for the stable source-attributed do-while placement diagnostic | -| `crates/opy-compiler/src/lib.rs` structural tests | #40/#46/#47 declarations, subroutines, rules, event filters, assignments, expressions, indexing, format, pass, control-flow lowering, and source-attributed negative lowering evidence | -| `crates/opy-compiler/tests/issue_46_oracle.rs` | #46 oracle-constrained differential equivalence: native output and the pinned oracle Workshop text both reparse through the canonical `workshop-rs` parser and must satisfy `roundtrip::equivalent` | -| `crates/opy-compiler/tests/issue_47_oracle.rs` | #47 oracle-constrained control-flow equivalence for ordered switches and do-while break shapes, plus source-attributed negative diagnostics for unsupported switch targets and invalid do-while placement | -| `compatibility/support-matrix.json` | Machine-readable state tracking of every declared feature (the mechanically checkable artifact) | - | `crates/opy-frontend/src/manifest/` | The opy-rs-owned semantic compatibility manifest and its oracle probes (ported with the frontend, issue #3/#4) | - | `crates/opy-frontend/tests/differential.rs` + `compatibility/diff.py` | Native-vs-reference differential parity (issue #7): the rust suite runs every corpus fixture through the native pipeline in `cargo test` (no Node), compares status/rule-name evidence against the recorded `oracle.json` snapshots, and writes `target/opy-differential-report.json` | - | `crates/opy-frontend/tests/fixtures/macros/` | JavaScript macro / post-compile hook end-to-end fixtures (issue #5/#6) | - | `crates/opy-macro-js/tests/` | Bounded QuickJS runtime ABI fixtures (issue #6) | - -## Supported surface (corpus-evidenced contract) - -The sections below describe the declared surface with the corpus/oracle -evidence behind each item. They are the contract the merged frontend -implements; "reference" always means the pinned OverPy 9.7.10 -(`889d9749d1def17f146548cbddb94ea1ab015847`). - -### Lexing -- Identifiers, integer and decimal number literals (source text preserved), - double-quoted strings with `\n`/`\t`/`\\` escapes, `true`/`false`/`None`. -- Line comments (`#`), block comments (`/* */`), `#!` directives. -- Operators: `+ - * / % ** == != < <= > >= = += -= *= /= %= **= and or not`, - `in`/`not in`, plus `.`/`,`/`:`/`(`/`)`/`[`/`]`/`@`. - -### Pure OPY syntax and source semantics -- `switch`/`case`/`default` preserve source-order fallthrough; `break` is a - real HIR statement valid in the innermost switch or loop. -- `do ... while`, hexadecimal literals, and expression-level `in`/`not in` - are represented in the source-language HIR. The #47 integration slice lowers - if/elif/else, while, global-binder range-for, do-while, switch - fallthrough/default, and direct loop/switch break into canonical WIR. Do-while - is accepted only at the beginning of a rule/definition or nested do-while - body (preceded only by `pass`). Multiple switch breaks with later reachable - actions, and an evidence-insufficient nested conditional switch break, remain - source-attributed diagnostics because the pinned canonical WIR has no - lossless multi-target switch carrier. -- String modifiers, including f-string interpolation, preserve semantic - format text, interpolation expressions, and source spans; dict literals, - keyed access, list comprehensions, and lambda binders preserve local scope. -- Lambda expressions are accepted only in the pinned signature-approved - positions (`sorted` key and array `map`/`filter`/`all`/`any`); other - positions produce structured diagnostics. - -### Declarations -- `globalvar name` / `globalvar name = expr` / `globalvar name ` - (the bare-integer form is an explicit Workshop variable index, matching the - reference; integer-`0` literal initializers are dropped from HIR (matching - the reference); non-zero and non-integer numeric initializers are - preserved, e.g. `j = 5` and `k = 0.0` keep the source spelling). - Initializer semantics are **lowering-dependent**: the #46 evidence covers - non-null initializers, while OverPy's null-default initializer quirk is - tracked separately in #58. The Initialize rules are synthesized by the HIR - β†’ Workshop lowering, which is inventory-only until the `workshop-rs` - integration stage. -- `playervar name` (same forms). -- `subroutine name`. -- `def name():` subroutine bodies (parameters are outside the declared - surface; rejected explicitly). -- `enum Name: MEMBER, ...`: members fold to numeric constants - (`Phase.FINISHED` β†’ `1`), matching the reference. -- `macro name(params):` statement bodies with `MacroParam` references. - -### Preprocessing -- `#!include "file.opy"`: root-relative include resolution, cycle detection - (`include-cycle`), missing-file diagnostics (`include-not-found`), included - files registered in the HIR file registry (reference behavior). -- `#!define NAME value`: object-like macros; recursive expansion at use sites - (a define may reference earlier defines); recursion guard - (`macro-recursion`). -- `#!define name(args) value`: function-like macros with argument - substitution (`cakeBeam(start, end, yPos) β†’ createBeam(...)`). -- `#!define name(args) __script__("path.js")`: OverPy-compatible - **JavaScript macros** (see below). -- `#!undef NAME`. -- `#!mainFile "path.opy"` redirects the frontend entry point and preserves - file provenance; `#!allowMacroRedeclaration` changes duplicate handling at - `#!define`, enum-member, and AST-macro surfaces. -- `#!rulePrefix`/`#!rulePrefixTemplate` are retained as source state and - rendered against every rule/subroutine (including rules before the template - directive); include prefix state is restored after child includes. -- `#!translations`, `#!optimize*`, and `#!replace0By*` forms are parsed, - validated, and exposed as frontend preprocessing state. Directive records - retain include depth and state snapshots, so nested transitions are - observable without claiming optimizer execution. Locale availability, - `.po` content, generated translation helpers, optimizer rewrites, and - replacement effects are lowering-dependent and are not fabricated here. -- `#!postCompileHook "hook.js"`: post-compile hook registration (see below). -- Unsupported directives fail explicitly (`unsupported-directive`). - -### JavaScript macros and post-compile hooks (issue #5/#6) - -The pinned reference ABI (`src/compiler/tokenizer.ts`, `src/quickjs.ts`, -`src/globalVars.ts`) is implemented through the embedded runtime -(`crates/opy-macro-js`, QuickJS-NG; no Node required): - -- A function-like define whose replacement is `__script__("path.js")` is a - script macro: the script path resolves root-relative at the define site - (missing files: `script-not-found`, mirroring the reference's ENOENT - failure), and each expansion executes the script with the call-site - arguments injected as `var =;` (raw argument text is - reconstructed from tokens; string literals are re-quoted with JSON - escaping, which is JavaScript-value-equivalent to the reference's raw text - injection). The string completion value becomes the expanded text, which is - re-lexed into the token stream at the call site. Script-macro expansion is - compile-time behavior and is **frontend-supported**. Thrown exceptions, - resource-limit aborts (`script-timeout` for the 1000 ms budget, - `script-memory-limit` for the 64 MiB memory limit, `script-stack-limit` - for the 512 KiB stack), and non-string results - (`script-result-not-string`, with the reference's wording) map to - structured `script-*` diagnostics carrying the script path and - line/column. The reference's `vect(x, y, z)` helper and the constant - objects (`Map`, `Hero`, `Gamemode`, `Color`, `Team`, `Button`) are always - defined (constants empty until catalog data lands with `workshop-rs`). -- `#!postCompileHook "hook.js"` is recognized, parsed, validated, and - **recorded only**: the frontend never executes the hook (duplicate - declarations: `post-compile-hook-duplicate`, matching the reference). Real - hook execution receives the **final Workshop text** produced by lowering - and is **lowering-dependent** (`hooks/post-compile-workshop` in the - support matrix, issue #8); the frontend never fabricates a Workshop - payload. The runtime's hook ABI (content injection, console capture, - result/error semantics, 2000 ms budget) is tested on synthetic content in - `crates/opy-macro-js/tests/hooks.rs`. -- There is no `#!require` directive in the pinned reference; the script - macro form is the only JavaScript declaration surface (verified against - OverPy 9.7.10, `src/compiler/tokenizer.ts`). - -### Rules and directives -- `rule "name":` with `@Event global` / `@Event eachPlayer` / `@Condition `. -- `@Team`/`@Slot` arguments, `@Hero`, `@Name`, `@Disabled`, `@Delimiter`, - `@NewPage`, and `@SuppressWarnings` are parsed, validated, and retained in - the OPY HIR. Hero/team/slot domain checks and Workshop UI effects remain - lowering-dependent; malformed or misplaced annotations fail with structured - source-located diagnostics. Issue #40 lowers the WIR-representable subset: - disabled state, canonical event identities, and catalog-resolved team/slot/ - hero filters. Delimiter, new-page, suppression, and other metadata without a - canonical WIR carrier remain explicit integration diagnostics. -- Statements: expression statements, `=` and the evidenced augmented - assignment subset (`+= -= *= /= %= **=`), - `if`/`elif`/`else`, `for x in range(...)`, `while`, `pass`. -- `for`-loop binder resolution: the loop variable must resolve to a global - variable, either a declared `globalvar`, or an OverPy **default variable - name** (`A`–`Z`, `AA`–`AZ`, …, `DA`–`DX`), which the pinned reference - accepts as an implicit global at its fixed Workshop slot (e.g. `for I in - range(0, 10):` with no declaration, the agent-lab regression). Nested - same-name loops reuse the same implicit variable (no separate binding), - matching the reference. An undeclared lowercase binder is rejected exactly - like the reference rejects it (`unknown-identifier`, reference: "Unknown - function name"). `range(stop)` / `range(start, stop)` / - `range(start, stop, step)` are all supported. - -### Expressions and resolution -- Literals, arrays `[...]`, parenthesized expressions. -- Calls (`range`, `len`, `abs`, `sqrt`, `debug`, `print`, `wait`, - `createBeam`, `playEffect`, `getAllPlayers`, `disableInspector`, …). -- `vect(x, y, z)` β†’ HIR `Vector` (3 arguments required; other arities are an - explicit error). -- `"text".format(args)` β†’ HIR `Format`; bare calls of declared subroutines β†’ - `CallSubroutine` statements; dotted module calls `random.uniform` / - `random.choice` β†’ `random.` calls; `eventPlayer.member` β†’ - `PlayerVar`/receiver call on `EventPlayer`; variable receivers - (`points.append`, `candlePos[i2]`) β†’ `ReceiverCall`/`Index`. -- OPY-owned builtin action/value/member identity, signatures, receiver categories, - parameter enum domains, and non-contextual aliases resolve through the OPY - semantic compatibility manifest (`crates/opy-frontend/src/manifest/`, schema - v1; spec in [`compat-manifest-spec.md`](compat-manifest-spec.md)), the - single authoritative semantic table. Every manifest entry is - probe-validated against the pinned OverPy 9.7.10 oracle - (`crates/opy-frontend/src/manifest/probes/`). Unknown or misplaced builtins - fail at semantic resolution with structured, source-located diagnostics - (`unknown-action`, `unknown-value`, `unknown-member`, `invalid-arity`, - `invalid-receiver`, `action-in-value-position`, - `value-in-action-position`, `invalid-call-context`, `invalid-iterable`, - plus the argument-binding codes `unknown-keyword`, `duplicate-argument`, - `missing-argument`, `positional-after-keyword`, `keyword-required`, - `keyword-unsupported`, `invalid-argument`), never as emitter catalog - misses. -- Reference-validated evidence surface: `chaseOverTime(...)` (action; 3–4 - arguments, reevaluation defaults to `DESTINATION_AND_DURATION`), - `isGameInProgress()` (value), `getPlayersInRadius(...)` (value; team - `Team.ALL` and `LosCheck.OFF` defaults fill), `worldVector(...)` (value, - `Transform` argument), and the enum-gated members - `eventPlayer.setInvisibility(Invis.X)`, - `eventPlayer.setStatusEffect(..., Status.X, ...)`, `eventPlayer.getThrottle()`. -- Receiver/member calls (`eventPlayer.setMoveSpeed(100)`, - `eventPlayer.teleport(eventPlayer.getPosition())`, - `target.setMoveSpeed(50)` on a player-valued global) lower to - `ReceiverCall`; their Workshop emission resolves through the `workshop-rs` - catalog, **lowering-dependent** (inventory-only until integration); the - corpus-evidenced receiver methods are the `synthetic/receiver-calls` - fixture methods plus the enum-gated members (en-US spellings per the - oracle-transcribed evidence). -- Non-contextual source aliases resolve to their canonical names - (`stopChasingVariable` β†’ `stopChasing`; member aliases `getCurrentHero` β†’ - `getHero`, `hasStatusEffect` β†’ `hasStatus`); their emission spellings are - catalog-covered only at integration time (documented emission gap). The - `ChaseReeval` contextual alias resolves only through the `chase` keyword - call context and stays out of the alias table. -- Builtin Workshop enums from the manifest's reference-validated domains: - `Beam.{GOOD,GRAPPLE}`, `Color.{YELLOW,WHITE,RED,ORANGE,GREEN,BLUE,BLACK, - PURPLE,AQUA,VIOLET,ROSE}`, `DynamicEffect.{BAD_EXPLOSION,GOOD_EXPLOSION, - RING_EXPLOSION,GOOD_PICKUP_EFFECT,BAD_PICKUP_EFFECT,BUFF_IMPACT_SOUND, - DEBUFF_IMPACT_SOUND}`, `EffectReeval.{VISIBILITY,COLOR,VISIBILITY_AND_COLOR}`, - `Wait.IGNORE_CONDITION`, - `ChaseTimeReeval.{NONE,DESTINATION_AND_DURATION}` (reference-validated - against the pinned OverPy 9.7.10 enum block and emission), - `ChaseRateReeval.{NONE,DESTINATION_AND_RATE}` (`NONE` additionally - corpus-evidenced by the real-world overpy-meipocalypse `ChaseReeval.NONE` - rate-chase calls, which the reference resolves to the `ChaseRateReeval` - domain), plus the evidence domains `Invis.{ALL,ENEMIES,NONE}`, - `Transform.{ROTATION,ROTATION_AND_TRANSLATION}`, - `Status.{ASLEEP,BURNING,FROZEN,HACKED,INVINCIBLE,KNOCKED_DOWN,PHASED_OUT, - ROOTED,STUNNED,UNKILLABLE}`, `LosCheck.{OFF,SURFACES, - SURFACES_AND_ALL_BARRIERS,SURFACES_AND_ENEMY_BARRIERS}`, `Team.ALL`. - Member accesses on declared domain identities resolve as **opaque - identities**; Workshop enum member-existence and domain validation was - removed from the frontend core and is **lowering-dependent** (#8). The - checks are never approximated (custom, user-declared enum members are - OPY-level source semantics and stay frontend-validated). Enum - complete Workshop domain/member catalog remains `lowering-dependent` and is - owned by `workshop-rs`; the manifest carries identity links only and never a - copied member allowlist. -- `wait()` / `wait(time)` default-argument filling: the reference appends - `Wait.IGNORE_CONDITION` (and `0.016` for the no-argument form). -- **Named/keyword arguments** (`name = expr` call arguments) bind against the - manifest's canonical parameter names, the pinned reference's declared - names (`wait(time=1)`, `wait(waitBehavior=Wait.IGNORE_CONDITION, time=2)`, - `chaseOverTime(g, 10, duration=3)`, - `chaseOverTime(g, 10, 3, reevaluation=ChaseTimeReeval.NONE)`, - `vect(x=1, y=2, z=3)`, `getPlayersInRadius(center=…, radius=…, - team=Team.ALL)`, `eventPlayer.setStatusEffect(assister=…, status=…, - duration=…)`, `print(text="x")`, `len(array=…)`, `debug(value=…)`, - `stopChasing(variable=g)`, member forms like - `eventPlayer.setMaxHealth(healthPercent=100)`). Keyword arguments may - appear in any order before the first positional argument; the reference - rejects positional arguments after keyword arguments - (`positional-after-keyword`), unknown keyword names (`unknown-keyword`), - duplicate bindings (`duplicate-argument`), and missing required arguments - (`missing-argument`), all structured, source-located diagnostics. The - reference's generic binder is routed around for `range`, `random.*`, and - `.format` (keyword arguments on those fail with `keyword-unsupported`), - and for `macro` invocations. -- **The `chase` keyword form** (reference special form): - `chase(variable, destination, rate=…, ChaseReeval.MEMBER)` and - `chase(variable, destination, duration=…, ChaseReeval.MEMBER)`, exactly - four arguments, the 3rd passed as the `rate`/`duration` keyword and the - 4th as a bare `ChaseReeval.MEMBER` access. `ChaseReeval` resolves **only** - in this call context: `rate=` selects the `ChaseRateReeval` domain and - lowers the call to `chaseAtRate`; `duration=` selects `ChaseTimeReeval` - and lowers to `chaseOverTime`. The contextual member is rewritten to the - keyword-selected domain without membership checks. Member/domain - validation is **lowering-dependent** (#8), matching the reference's - "Unknown chaseratereeval" as a lowering-time outcome. Outside the chase - signature `ChaseReeval` never - resolves (a bare `g = ChaseReeval.NONE` is rejected like the reference). - The first argument must be a variable (`invalid-argument` otherwise); - emission dispatches on its kind (global vs player variable) and is - **lowering-dependent**. -- `chaseOverTime(...)` requires a variable first argument like the - reference (`invalid-argument` for `chaseOverTime(10, …)`). -- Undeclared identifiers, enum types without members, and unsupported member - accesses are structured, source-located semantic errors - (`unknown-identifier`, `enum-type-without-member`, `unsupported-member`). - -### Diagnostics -- Malformed input produces structured frontend errors (stable codes like - `parse-error`, `lex-error`) with 1-based source spans; the parser recovers - at statement boundaries to report multiple useful errors. -- Frontend diagnostics map into the shared `wright-result/v1` contract (stage - `frontend`, severity `error`) consumed by WrightKit tooling. - -### Settings -- Top-of-file `settings { ... }` custom-game-settings blocks (JSONC: quoted - keys, `"`/`'` strings with escapes, numbers, `true`/`false`, string lists, - nested groups, trailing commas), recognized and consumed before lexing - (scoped lexing: the block never enters the token stream and the lexer - gains no global braces), parsed into the typed HIR `settings` payload. -- Placement rules: the block must be the first construct in the main file - (`settings-placement` otherwise); a second block is rejected; a - `settings "file"` form is rejected (`settings-invalid`); settings blocks - in included files are rejected (`settings-placement` at the included - file's keyword span). -- Emission of the Workshop `settings` section (the key table, enum values, - map/hero list elements) is **lowering-dependent**: the typed payload is - frontend-owned; the emission table and its domain data are Workshop data - owned by `workshop-rs`. Key-existence and leaf-kind settings validation - is Workshop schema content and **lowering-dependent** (#8). The frontend - validates structure only (group shape, span validity, non-empty key - names). The emitted `settings` section is deliberately not - reparseable by the Workshop parser (a `.ws` decompiler is a non-goal). - -## Deferred / out of scope - -- **Reconstruction / decompilation (Workshop β†’ OPY)**: deferred and - `lowering-dependent`. Full Workshop-to-OPY reconstruction requires the - canonical Workshop semantic representation from `workshop-rs` and is - inventory-only (see `compatibility/support-matrix.json`, category - `decompilation`; wright's implemented reconstruction surface is not ported - as a claim; it becomes an opy-rs contract only at the integration stage). -- Macro/`#!define` values that require runtime evaluation are **implemented** - for the reference's `__script__` ABI (see "JavaScript macros and - post-compile hooks" above); the remaining runtime surface is - `lowering-dependent`: hook output into Workshop emission and catalog - constant population (`Map`/`Hero`/… objects stay empty). -- Canonical Workshop enum domains/members and emission spellings are - `lowering-dependent` and owned by `workshop-rs`; they are not OPY frontend - gaps. Manifest entries without a direct catalog id carry an explicit - `catalogLink` reason (`special-lowering`, `legacy-alias`, or `catalog-gap`) - and remain visible to the integration adapter. - - Emission spellings for manifest-valid entries not yet catalog-covered - (alias targets `stopChasing`/`getHero`/`hasStatus`, and enum members - without a catalogged spelling); these fail at emission with catalog - diagnostics once integration lands, never silently. -- Backslash line continuation (`\` at end of line inside string - concatenations / macro bodies): rejected at lexing. -- Postfix increment/decrement (`++`/`--`): rejected at parsing. -- Triple-quoted strings / docstrings (`"""`): rejected at lexing. -- Subroutine parameters, default `@Team`/`@Slot` overrides, `raycast` - `include=`/`exclude=` named-argument forms (no reference/corpus evidence - in the declared surface; the reference's `raycast` special form is not - manifest-declared), and macro keyword arguments (the reference's macro - substitution treats them as raw text; rejected explicitly). -- Full OverPy formatting semantics: `debug()`/`print()` emission - (`Create HUD Text` etc.) follows simplified semantic formatting - (presentation differences are not compatibility bugs unless they change - observable semantics). -- Emission presentation: variable references may emit as `Global.` - where the reference emits the bare variable name; observable semantics and - round-trip validity are unchanged (output-text identity is explicitly not - the compatibility contract; see `upstream-references.md`). - -## Boundary contract - -The frontend produces the Opy HIR v2 program model -([`docs/hir/opy-hir-v2.md`](../hir/opy-hir-v2.md)) with the protocol envelope, -file registry, declarations, and rules as specified there. It never requires -Node or OverPy at build/runtime; the oracle remains available as an explicit -`pnpm install --dir compatibility/oracle` step for the compatibility harness -only. Differential parity runs in `cargo test -p opy-frontend --test -differential` against the recorded oracle snapshots (issue #7); the report -and per-fixture native HIR dumps land in `target/`. +`compatibility/support-matrix.json` remains internal engineering metadata for +fixture relationships and implementation evidence. Its internal states are +not public support statuses. diff --git a/docs/opy/tooling-notes.md b/docs/opy/tooling-notes.md index e28a46c..bd2a700 100644 --- a/docs/opy/tooling-notes.md +++ b/docs/opy/tooling-notes.md @@ -35,10 +35,12 @@ python3 compatibility/diff.py --producer-command '' --report compa ## Machine-readable support matrix -`compatibility/support-matrix.json` is the mechanically checkable state -tracking of the declared OverPy feature surface (states `planned`, -`frontend-supported`, `semantic-supported`, `lowering-dependent`, -`end-to-end-supported`; see [`docs/opy/support-matrix.md`](../opy/support-matrix.md)). +The canonical public support contract is [`../language-support.md`](../language-support.md). +`compatibility/support-matrix.json` is retained as internal, mechanically +checkable engineering metadata tracking the declared OverPy feature surface +(states `planned`, +`source-supported`, `semantic-supported`, `lowering-dependent`, +`end-to-end-supported`; see [`../language-support.md`](../language-support.md)). The consistency check lives in `compatibility/tests/test_support_matrix.py` and runs as part of the harness test suite: every feature id is unique, every state/category is from the declared domains, and every `fixtures:` evidence