diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2bfa92..58017dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,8 +24,10 @@ jobs: - run: cargo check --locked -p octoscript-sandbox --tests --target aarch64-unknown-linux-gnu - run: cargo check --locked -p octoscript-sandbox --tests --target riscv64gc-unknown-linux-gnu - run: cargo check --locked -p octoscript-sandbox --tests --target x86_64-pc-windows-gnu - - run: cargo test --manifest-path vendor/makepad/Cargo.toml -p makepad-script - - run: cargo test --manifest-path vendor/makepad/Cargo.toml -p makepad-regex + # The VM is a pinned git dependency (OctoSense-org/makepad, branch octoscript); + # -p resolves it from Cargo.lock so no separate checkout or second pin is needed. + - run: cargo test -p makepad-script + - run: cargo test -p makepad-regex # The project-quota positive-path test requires an explicitly provisioned host fixture. - run: > sudo -E env RUSTUP_HOME="$HOME/.rustup" @@ -193,5 +195,5 @@ jobs: - run: cargo +nightly miri setup - name: Check re-entrant VM body reload under Miri run: > - cargo +nightly miri test --manifest-path vendor/makepad/Cargo.toml -p makepad-script + cargo +nightly miri test -p makepad-script reentrant_reload_of_the_active_body_does_not_keep_an_opcode_pointer diff --git a/.gitignore b/.gitignore index 3b54ba5..f9ccc17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /target/ -vendor/makepad/target/ /fuzz/artifacts/ /fuzz/corpus/* !/fuzz/corpus/syntax/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb7a135..0780488 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,15 @@ # Contributing -Octoscript accepts changes to the language core, capability host, workflow engine, -or compatibility import only when the security boundary remains explicit. +Octoscript accepts changes to the language core, capability host, or workflow +engine only when the security boundary remains explicit. - Do not register filesystem, subprocess, raw socket, or HTTP server modules in `octoscript-core`. - Add effects as reviewed tool adapters in `octoscript-capabilities` with limits, audit coverage, and a documented containment strategy. -- Preserve Makepad provenance. Changes below `vendor/makepad/` need an entry - in `vendor/makepad/PATCHES.md` and an upstream-sync note. +- Do not patch the VM here. `makepad-script` is a pinned git dependency on the + `octoscript` branch of `OctoSense-org/makepad`; VM changes land there first + and reach this repository through a rev bump (see `UPSTREAM.md`). - Keep new language behavior in an executable fixture or regression test. Before opening a change, run the checks in `docs/development.md`. diff --git a/Cargo.toml b/Cargo.toml index 8805432..13333ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ default-members = [ "crates/octoscript-cli", "crates/octoscript-lsp", ] -exclude = ["vendor/makepad"] resolver = "2" [workspace.package] diff --git a/NOTICE b/NOTICE index 46892eb..6a6d0e7 100644 --- a/NOTICE +++ b/NOTICE @@ -1,12 +1,15 @@ -Octoscript contains a vendored compatibility core derived from Makepad. +Octoscript ships a compatibility core derived from Makepad. It is consumed as +the `makepad-script` git dependency pinned in `crates/octoscript-core/Cargo.toml` +and `crates/octoscript-capabilities/Cargo.toml`, taken from the `octoscript` +branch of https://github.com/OctoSense-org/makepad. Upstream project: https://github.com/makepad/makepad -Upstream revision: 4f9ce7a8bb3fd19e5c61dcf13edd2e6d4a04cefc -Imported paths: platform/script and the required leaf dependencies under libs/. +Original import revision: 4f9ce7a8bb3fd19e5c61dcf13edd2e6d4a04cefc +Shipped paths: platform/script and the leaf dependencies it pulls under libs/. Copyright (c) 2023 Makepad B.V. License: MIT (see LICENSE). Individual imported crates may additionally be licensed under Apache-2.0 as declared in their manifests. -The vendored copy of smallvec is Copyright (c) The Servo Project Developers -and is dual licensed under MIT OR Apache-2.0. Its license texts are retained -under vendor/makepad/libs/smallvec/. +The copy of smallvec carried by that dependency is Copyright (c) The Servo +Project Developers and is dual licensed under MIT OR Apache-2.0. Its license +texts are retained under libs/smallvec/ in the dependency's source tree. diff --git a/README.md b/README.md index 3362440..88a0232 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ and keeps UI support optional rather than making UI the language boundary. ## Current baseline -- A standalone, vendored VM and parser with upstream provenance. +- A standalone VM and parser with upstream provenance, consumed as a pinned + git dependency on the `octoscript` branch of `OctoSense-org/makepad`. - An effect-free, bounded canonical-language preflight with structured diagnostics for generated source and editor tooling, plus token-aware lowering of canonical newline statement boundaries for the inherited VM. @@ -235,7 +236,7 @@ and keeps UI support optional rather than making UI the language boundary. - A small `octoscript` CLI for local evaluation and the workflow example. No ambient filesystem, subprocess, raw socket, HTTP client/server, or Makepad -platform/debug module is source-reachable by default. The vendored VM bootstrap +platform/debug module is source-reachable by default. The inherited VM bootstrap retains compatibility objects internally, but `Runtime` masks their source entry points before either canonical or compatibility evaluation. The optional fixed-file and fixed-endpoint catalogs are explicit, bounded tools rather than @@ -757,10 +758,11 @@ both keys with JSON `null`. See [editor workflow-data projection](docs/workflow- declaration symbols, and bounded same-document lexical navigation, hover, and highlights plus lexical completion and version-bound guarded rename for open editor documents. -- `vendor/makepad`: provenance-preserving compatibility import. +- `makepad-script` (git dependency, `OctoSense-org/makepad` branch + `octoscript`): the inherited VM and parser; see `UPSTREAM.md`. See [SECURITY.md](SECURITY.md) for the current threat model and [UPSTREAM.md](UPSTREAM.md) -for the import boundary. The [worker protocol](docs/worker-protocol.md) +for the dependency boundary. The [worker protocol](docs/worker-protocol.md) defines the handoff to contained adapters. The [host tool catalog](docs/tool-catalog.md) defines safe discovery for an LLM orchestrator. [JSON tool contracts](docs/schema-contracts.md) define the executable structured-data boundary. [External tools](docs/external-tools.md) diff --git a/UPSTREAM.md b/UPSTREAM.md index 9038255..31e7104 100644 --- a/UPSTREAM.md +++ b/UPSTREAM.md @@ -1,27 +1,56 @@ # Upstream Policy -`vendor/makepad/` is a compatibility import from Makepad, not an ambient -runtime dependency. The initial import is pinned to: +Octoscript does not carry its own copy of the Makepad VM. The language VM, +parser, derive crate, and their leaf dependencies come from the `octoscript` +branch of the OctoSense fork of Makepad, consumed as a pinned git dependency: -```text -makepad/makepad dev -4f9ce7a8bb3fd19e5c61dcf13edd2e6d4a04cefc +```toml +makepad-script = { git = "https://github.com/OctoSense-org/makepad.git", rev = "1fdce273bf888239079754a1834734635eaed34f" } ``` -Only the language VM, parser, derive crate, and their direct leaf -dependencies are imported. Makepad widgets, platform scripting, filesystem, -process, timer, and network modules are intentionally excluded. +The pin appears in exactly two manifests, `crates/octoscript-core/Cargo.toml` +and `crates/octoscript-capabilities/Cargo.toml`, and must be the same rev in +both. `fuzz/Cargo.toml` reaches the VM only through path dependencies on those +crates and carries no pin of its own; if it ever depends on `makepad-script` +directly it must use the same rev. `Cargo.lock` records the resolved checkout. -The vendor tree is intentionally excluded from the Octoscript Cargo workspace. -It remains a path dependency of `octoscript-core`, but its upstream lint backlog -does not dilute the lint gate for Octoscript-owned crates. Run its test suite -explicitly with `cargo test --manifest-path vendor/makepad/Cargo.toml -p makepad-script`. +The `octoscript` branch descends from `makepad/makepad dev` (the original +import point was `4f9ce7a8bb3fd19e5c61dcf13edd2e6d4a04cefc`). Octoscript's VM +hardening, which this repository previously carried as local vendor patches, +was ported to that branch on 2026-09-13 in fork PR #1 and now lives there. +`docs/vm-hardening-history.md` keeps the description of those changes as a +history note. This repository no longer carries local patches to the VM: a VM +change is made as a pull request against the fork's `octoscript` branch, then +reaches Octoscript through a rev bump. -Upstream changes are reviewed and imported as explicit commits. New host -capabilities belong in `crates/octoscript-capabilities`, never in the vendored VM. +Only the VM, parser, derive crate, and their direct leaf dependencies are used. +Makepad widgets, platform scripting, filesystem, process, timer, and network +modules are not depended on. New host capabilities belong in +`crates/octoscript-capabilities`, never in the VM. A behavioral change to the +VM is allowed only when it implements a published Octoscript language +contract, carries focused compatibility and streaming regressions, and does +not add ambient host authority to the VM. -Every local vendor patch is documented in `vendor/makepad/PATCHES.md` and must -be reapplied or retired during each upstream update. Behavioral changes are -allowed only when they implement a published Octoscript language contract, carry -focused compatibility and streaming regressions, and do not add ambient host -authority to the VM. +The VM is not a workspace member, so its upstream lint backlog does not dilute +the lint gate for Octoscript-owned crates. Its test suite is still run +explicitly, resolved from the pinned checkout: + +```sh +cargo test -p makepad-script +cargo test -p makepad-regex +``` + +## Bumping the pin + +1. Land the change on the fork's `octoscript` branch first. +2. Move `rev` to the new commit in both manifests and run + `cargo update -p makepad-script` so `Cargo.lock` follows. +3. Run the Octoscript regression suite and the explicit `makepad-script` and + `makepad-regex` tests above, especially streaming precedence and + `try/catch` recovery. +4. Bump OctoSense and Octoscript-Makepad to the same rev in the same change + window. The three consumers are expected to track one commit of the + `octoscript` branch; a lone bump here is a divergence, not a release. + +Syncing the fork with `makepad/makepad` upstream happens on the fork, not +here; Octoscript sees the result as an ordinary rev bump. diff --git a/docs/development.md b/docs/development.md index bbd4d46..99967ce 100644 --- a/docs/development.md +++ b/docs/development.md @@ -44,16 +44,17 @@ The test only reads and validates quota state; it never enables, changes, or disables quota enforcement. It must fail rather than be skipped when that explicit host-provisioned fixture is invalid. -The Makepad compatibility import is deliberately outside the workspace lint -scope. Verify it explicitly after an upstream import or vendor patch: +The Makepad VM is a pinned git dependency, not a workspace member, so it is +outside the workspace lint scope. Verify it explicitly after a rev bump; Cargo +resolves the packages from the pinned checkout: ```sh -cargo test --manifest-path vendor/makepad/Cargo.toml -p makepad-script -cargo test --manifest-path vendor/makepad/Cargo.toml -p makepad-regex +cargo test -p makepad-script +cargo test -p makepad-regex ``` This keeps failures in source owned by Octoscript actionable while preserving -separate behavioral coverage for the imported VM. +separate behavioral coverage for the inherited VM. ## Sustained fuzzing @@ -86,8 +87,9 @@ RUSTFLAGS='--cfg fuzzing' cargo +nightly fuzz tmin --sanitizer none syntax artif Then add a focused unit or integration regression and, when it improves the campaign, a reviewed text, JSON, or `.seed` input under `fuzz/corpus`. Do not commit raw generated corpus entries or `fuzz/artifacts`; they can include -unreviewed input and are intentionally ignored. Keep vendor parser fixes -documented in `vendor/makepad/PATCHES.md`. +unreviewed input and are intentionally ignored. Parser fixes belong in the +`octoscript` branch of `OctoSense-org/makepad` and reach this repository +through a rev bump (see `UPSTREAM.md`). ## Language server @@ -366,7 +368,7 @@ Octoscript source cap. ## Syntax fuzzing The standalone `fuzz` package has bounded targets. `syntax` differentially -exercises the canonical profile and the vendored VM parser under a rotating set +exercises the canonical profile and the inherited VM parser under a rotating set of valid resource profiles, from 64 bytes, 8 tokens, and 2 nesting levels up to a 16 KiB source cap, a 2,048-token cap, and a 64-level nesting cap. It also sends every bounded UTF-8 input through the broader VM-compatibility preflight, diff --git a/docs/makepad-ui-compatibility.md b/docs/makepad-ui-compatibility.md index 4009a7d..f2816d6 100644 --- a/docs/makepad-ui-compatibility.md +++ b/docs/makepad-ui-compatibility.md @@ -34,7 +34,7 @@ runtime. It does not execute through `octoscript-cli`, render widgets, install `mod.prelude.widgets`, inject `ui`, or provide Makepad event-loop semantics. Use it only with a Makepad UI host that supplies those bindings. The fixture also is not an assertion of compatibility with every upstream Octoscript feature; -the vendored VM is intentionally smaller than a full Makepad checkout. In +the inherited VM is intentionally smaller than a full Makepad checkout. In particular, the standalone compatibility check rejects Makepad `@(index)` host-value tokens because it does not accept a host value table. diff --git a/docs/positioning.md b/docs/positioning.md index d8ca934..6a0b31e 100644 --- a/docs/positioning.md +++ b/docs/positioning.md @@ -17,7 +17,8 @@ embedded by a trusted application. Upstream modules and host bindings can be appropriate for a UI runtime, but they are not a stable capability boundary for untrusted generated programs. -This repository vendors that substrate with provenance, then defines a +This repository consumes that substrate as a pinned git dependency of the +`octoscript` branch of `OctoSense-org/makepad`, then defines a separate portable language contract and host model: | Area | Makepad-oriented substrate | Octoscript runtime profile | diff --git a/docs/scoped-state.md b/docs/scoped-state.md index d6fe726..510704f 100644 --- a/docs/scoped-state.md +++ b/docs/scoped-state.md @@ -15,13 +15,14 @@ question of *who emits* the declaration. §5.10.1 adds an obligation this docume carry: whoever owns the cells must be handed instance identity, because L0 rebuilds subtrees on data changes and a cell that cannot be re-found is a cell that is lost. -`UPSTREAM.md` permits a behavioural change to the vendored VM "only when [it] +`UPSTREAM.md` permits a behavioural change to the inherited VM "only when [it] implements a published Octoscript language contract". This is that contract. It is deliberately narrow: it publishes the smallest state mechanism that lets an interaction be handled locally, and defers everything that can be deferred. -**This contract has more than one implementer.** Octoscript's vendored VM -(`vendor/makepad/platform/script`, pinned to upstream `4f9ce7a8`) and the VM that +**This contract has more than one implementer.** Octoscript's VM +(`platform/script` on the `octoscript` branch of `OctoSense-org/makepad`, a +pinned git dependency of `octoscript-core`) and the VM that ships on device in octos-one (`makepad/platform/script`) are independent lineages — neither contains the other's history. That is a deliberate position, not an accident awaiting a merge, and it has one consequence that governs diff --git a/vendor/makepad/PATCHES.md b/docs/vm-hardening-history.md similarity index 94% rename from vendor/makepad/PATCHES.md rename to docs/vm-hardening-history.md index de1134d..45a6243 100644 --- a/vendor/makepad/PATCHES.md +++ b/docs/vm-hardening-history.md @@ -1,4 +1,12 @@ -# Local Vendor Patches +# VM hardening history + +The changes described below were Octoscript's local patches to its formerly +vendored copy of the Makepad VM (`vendor/makepad/PATCHES.md`). They were ported +to the `octoscript` branch of OctoSense-org/makepad on 2026-09-13 (fork PR #1) +and no longer live in this repository; Octoscript consumes them through the +pinned `makepad-script` git dependency described in `UPSTREAM.md`. The text is +kept as written, as a record of what was changed and why. The upstream-sync +notes it contains refer to the old vendoring workflow and are historical. ## `platform/script`: language review fixes (#9–#18) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 6a3b248..ace74f9 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -313,6 +313,7 @@ dependencies = [ [[package]] name = "makepad-error-log" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-micro-serde", ] @@ -320,6 +321,7 @@ dependencies = [ [[package]] name = "makepad-html" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-live-id", ] @@ -327,6 +329,7 @@ dependencies = [ [[package]] name = "makepad-live-id" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-live-id-macros", ] @@ -334,6 +337,7 @@ dependencies = [ [[package]] name = "makepad-live-id-macros" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-micro-proc-macro", ] @@ -341,6 +345,7 @@ dependencies = [ [[package]] name = "makepad-math" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-micro-serde", ] @@ -348,10 +353,12 @@ dependencies = [ [[package]] name = "makepad-micro-proc-macro" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" [[package]] name = "makepad-micro-serde" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-live-id", "makepad-micro-serde-derive", @@ -360,6 +367,7 @@ dependencies = [ [[package]] name = "makepad-micro-serde-derive" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-micro-proc-macro", ] @@ -367,10 +375,12 @@ dependencies = [ [[package]] name = "makepad-regex" version = "0.1.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" [[package]] name = "makepad-script" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-error-log", "makepad-html", @@ -378,22 +388,165 @@ dependencies = [ "makepad-math", "makepad-regex", "makepad-script-derive", + "makepad-stitch", "smallvec", ] [[package]] name = "makepad-script-derive" version = "1.0.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" dependencies = [ "makepad-micro-proc-macro", ] +[[package]] +name = "makepad-stitch" +version = "0.1.0" +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" + [[package]] name = "memchr" version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "octoscript-capabilities" +version = "0.1.0" +dependencies = [ + "blake3", + "getrandom 0.3.4", + "makepad-script", + "octoscript-core", + "octoscript-protocol", + "octoscript-schema", + "octoscript-storage", + "serde", + "serde_json", + "ureq", + "zeroize", +] + +[[package]] +name = "octoscript-core" +version = "0.1.0" +dependencies = [ + "makepad-script", + "octoscript-ui-l0", + "serde_json", +] + +[[package]] +name = "octoscript-fuzz" +version = "0.0.0" +dependencies = [ + "libfuzzer-sys", + "lsp-server", + "lsp-types", + "octoscript-capabilities", + "octoscript-core", + "octoscript-protocol", + "octoscript-sandbox", + "octoscript-schema", + "octoscript-storage", + "octoscript-worker", + "octoscript-workflow", + "serde_json", +] + +[[package]] +name = "octoscript-linux-project-quota" +version = "0.1.0" +dependencies = [ + "libc", + "linux-raw-sys", +] + +[[package]] +name = "octoscript-linux-seccomp" +version = "0.1.0" +dependencies = [ + "libc", + "linux-raw-sys", +] + +[[package]] +name = "octoscript-protocol" +version = "0.1.0" +dependencies = [ + "blake3", + "constant_time_eq", + "serde", + "serde_json", + "zeroize", +] + +[[package]] +name = "octoscript-sandbox" +version = "0.1.0" +dependencies = [ + "close_fds", + "landlock", + "linux-raw-sys", + "octoscript-linux-project-quota", + "octoscript-linux-seccomp", + "octoscript-protocol", + "rustix", +] + +[[package]] +name = "octoscript-schema" +version = "0.1.0" +dependencies = [ + "serde_json", +] + +[[package]] +name = "octoscript-storage" +version = "0.1.0" +dependencies = [ + "base64", + "blake3", + "serde", + "serde_json", + "subtle", + "zeroize", +] + +[[package]] +name = "octoscript-ui-l0" +version = "0.1.0" +dependencies = [ + "blake3", + "serde_json", +] + +[[package]] +name = "octoscript-worker" +version = "0.1.0" +dependencies = [ + "octoscript-protocol", + "octoscript-storage", + "serde", + "serde_json", + "zeroize", +] + +[[package]] +name = "octoscript-workflow" +version = "0.1.0" +dependencies = [ + "blake3", + "octoscript-capabilities", + "octoscript-core", + "octoscript-protocol", + "octoscript-schema", + "octoscript-storage", + "serde", + "serde_json", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -567,141 +720,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "smallvec" version = "1.15.1" - -[[package]] -name = "octoscript-capabilities" -version = "0.1.0" -dependencies = [ - "blake3", - "getrandom 0.3.4", - "makepad-script", - "serde", - "serde_json", - "octoscript-core", - "octoscript-protocol", - "octoscript-schema", - "octoscript-storage", - "ureq", - "zeroize", -] - -[[package]] -name = "octoscript-core" -version = "0.1.0" -dependencies = [ - "makepad-script", - "serde_json", - "octoscript-ui-l0", -] - -[[package]] -name = "octoscript-fuzz" -version = "0.0.0" -dependencies = [ - "libfuzzer-sys", - "lsp-server", - "lsp-types", - "serde_json", - "octoscript-capabilities", - "octoscript-core", - "octoscript-protocol", - "octoscript-sandbox", - "octoscript-schema", - "octoscript-storage", - "octoscript-worker", - "octoscript-workflow", -] - -[[package]] -name = "octoscript-linux-project-quota" -version = "0.1.0" -dependencies = [ - "libc", - "linux-raw-sys", -] - -[[package]] -name = "octoscript-linux-seccomp" -version = "0.1.0" -dependencies = [ - "libc", - "linux-raw-sys", -] - -[[package]] -name = "octoscript-protocol" -version = "0.1.0" -dependencies = [ - "blake3", - "constant_time_eq", - "serde", - "serde_json", - "zeroize", -] - -[[package]] -name = "octoscript-sandbox" -version = "0.1.0" -dependencies = [ - "close_fds", - "landlock", - "linux-raw-sys", - "rustix", - "octoscript-linux-project-quota", - "octoscript-linux-seccomp", - "octoscript-protocol", -] - -[[package]] -name = "octoscript-schema" -version = "0.1.0" -dependencies = [ - "serde_json", -] - -[[package]] -name = "octoscript-storage" -version = "0.1.0" -dependencies = [ - "base64", - "blake3", - "serde", - "serde_json", - "subtle", - "zeroize", -] - -[[package]] -name = "octoscript-ui-l0" -version = "0.1.0" -dependencies = [ - "serde_json", -] - -[[package]] -name = "octoscript-worker" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", - "octoscript-protocol", - "octoscript-storage", - "zeroize", -] - -[[package]] -name = "octoscript-workflow" -version = "0.1.0" -dependencies = [ - "blake3", - "serde", - "serde_json", - "octoscript-capabilities", - "octoscript-core", - "octoscript-protocol", - "octoscript-schema", - "octoscript-storage", -] +source = "git+https://github.com/OctoSense-org/makepad.git?rev=1fdce273bf888239079754a1834734635eaed34f#1fdce273bf888239079754a1834734635eaed34f" [[package]] name = "subtle" diff --git a/vendor/makepad/Cargo.lock b/vendor/makepad/Cargo.lock deleted file mode 100644 index 80c3892..0000000 --- a/vendor/makepad/Cargo.lock +++ /dev/null @@ -1,154 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "makepad-error-log" -version = "1.0.0" -dependencies = [ - "makepad-micro-serde", -] - -[[package]] -name = "makepad-html" -version = "1.0.0" -dependencies = [ - "makepad-live-id", -] - -[[package]] -name = "makepad-live-id" -version = "1.0.0" -dependencies = [ - "makepad-live-id-macros", - "serde", -] - -[[package]] -name = "makepad-live-id-macros" -version = "1.0.0" -dependencies = [ - "makepad-micro-proc-macro", -] - -[[package]] -name = "makepad-math" -version = "1.0.0" -dependencies = [ - "makepad-micro-serde", -] - -[[package]] -name = "makepad-micro-proc-macro" -version = "1.0.0" - -[[package]] -name = "makepad-micro-serde" -version = "1.0.0" -dependencies = [ - "makepad-live-id", - "makepad-micro-serde-derive", -] - -[[package]] -name = "makepad-micro-serde-derive" -version = "1.0.0" -dependencies = [ - "makepad-micro-proc-macro", -] - -[[package]] -name = "makepad-regex" -version = "0.1.0" - -[[package]] -name = "makepad-script" -version = "1.0.0" -dependencies = [ - "makepad-error-log", - "makepad-html", - "makepad-live-id", - "makepad-math", - "makepad-regex", - "makepad-script-derive", - "smallvec", -] - -[[package]] -name = "makepad-script-derive" -version = "1.0.0" -dependencies = [ - "makepad-micro-proc-macro", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -dependencies = [ - "serde", -] - -[[package]] -name = "syn" -version = "2.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/vendor/makepad/Cargo.toml b/vendor/makepad/Cargo.toml deleted file mode 100644 index 2b99ad7..0000000 --- a/vendor/makepad/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[workspace] -members = [ - "platform/script", - "platform/script/derive", - "libs/error_log", - "libs/math", - "libs/live_id", - "libs/live_id/id_macros", - "libs/regex", - "libs/html", - "libs/micro_serde", - "libs/micro_serde/derive", - "libs/micro_proc_macro", - "libs/smallvec", -] -exclude = ["libs/regex/src/fuzz"] -resolver = "2" diff --git a/vendor/makepad/libs/error_log/Cargo.toml b/vendor/makepad/libs/error_log/Cargo.toml deleted file mode 100644 index 69b3576..0000000 --- a/vendor/makepad/libs/error_log/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "makepad-error-log" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad error logging" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "5AyqeCUVreBmoPGamcLTzxafmVk=" - -[features] -nightly = [] - -[dependencies] -makepad-micro-serde = { path = "../../libs/micro_serde", version = "1.0.0" } \ No newline at end of file diff --git a/vendor/makepad/libs/error_log/src/error_log_android.rs b/vendor/makepad/libs/error_log/src/error_log_android.rs deleted file mode 100644 index 38c2b60..0000000 --- a/vendor/makepad/libs/error_log/src/error_log_android.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::panic; -use std::ffi::c_int; -pub use crate::LogType; - -pub fn log_with_type(file:&str, line_start:u32, column_start:u32, _line_end:u32, _column_end:u32, message:&str, _ty:LogType){ - let msg = format!("{}:{}:{} - {}\0", file, line_start, column_start, message); - unsafe{__android_log_write(3, "Makepad\0".as_ptr(), msg.as_ptr())}; -} - -extern "C" { - pub fn __android_log_write(prio: c_int, tag: *const u8, text: *const u8) -> c_int; -} - - -pub fn init_panic_hook() { - pub fn panic_hook(info: &panic::PanicInfo) { - log_with_type("",0,0,0,0,&format!("Panic - {}\0", info), LogType::Panic); - } - panic::set_hook(Box::new(panic_hook)); -} diff --git a/vendor/makepad/libs/error_log/src/error_log_desktop.rs b/vendor/makepad/libs/error_log/src/error_log_desktop.rs deleted file mode 100644 index 78d7af7..0000000 --- a/vendor/makepad/libs/error_log/src/error_log_desktop.rs +++ /dev/null @@ -1,27 +0,0 @@ - -pub use crate::LogType; - - -pub fn log_with_type(file:&str, line_start:u32, column_start:u32, line_end:u32, column_end:u32, message:&str, ty:LogType){ - if std::env::args().find(|v| v == "--message-format=json").is_some(){ - let out = ty.make_json(file, line_start, column_start, line_end, column_end, message); - println!("{}", out); - return - } - println!("{}:{}:{} - {}", file, line_start, column_start, message); -} -/* -pub fn set_panic_hook(){ - pub fn panic_hook(info: &panic::PanicInfo) { - if let Some(location) = info.location(){ - if let Some(s) = info.payload().downcast_ref::<&str>() { - return log_impl(location.file(), location.line(), location.column(), location.column()+5, s, LogType::Panic); - } - else if let Some(s) = info.payload().downcast_ref::() { - return log_impl(location.file(), location.line(), location.column(), location.column()+5, s, LogType::Panic); - } - } - eprintln!("{:?}", info); - } - panic::set_hook(Box::new(panic_hook)); -}*/ diff --git a/vendor/makepad/libs/error_log/src/error_log_wasm.rs b/vendor/makepad/libs/error_log/src/error_log_wasm.rs deleted file mode 100644 index 76f80e2..0000000 --- a/vendor/makepad/libs/error_log/src/error_log_wasm.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::panic; -pub use crate::LogType; - -extern "C" { - pub fn js_console_log(chars: u32, len: u32); - pub fn js_console_error(chars: u32, len: u32); -} - -pub fn log_with_type(file:&str, line_start:u32, column_start:u32, _line_end:u32, _column_end:u32, message:&str, ty:LogType){ - let msg = format!("{}:{}:{} - {}", file, line_start, column_start, message); - let chars = msg.chars().collect::> (); - if let LogType::Error = ty{ - unsafe{js_console_error(chars.as_ptr() as u32, chars.len() as u32)}; - } - else{ - unsafe{js_console_log(chars.as_ptr() as u32, chars.len() as u32)}; - } -} - -#[export_name = "wasm_init_panic_hook"] -pub unsafe extern "C" fn init_panic_hook() { - pub fn panic_hook(info: &panic::PanicInfo) { - error!("{}", info) - } - panic::set_hook(Box::new(panic_hook)); -} - diff --git a/vendor/makepad/libs/error_log/src/lib.rs b/vendor/makepad/libs/error_log/src/lib.rs deleted file mode 100644 index 2c9b0af..0000000 --- a/vendor/makepad/libs/error_log/src/lib.rs +++ /dev/null @@ -1,231 +0,0 @@ -use makepad_micro_serde::*; -use std::fmt::Write; -use std::sync::RwLock; - -#[macro_export] -macro_rules!log { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Log - ) - } -} - -#[macro_export] -macro_rules!error { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $crate::LogLevel::Error - ) - } -} - -#[macro_export] -macro_rules!warning { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Warning - ) - } -} - -#[macro_export] -macro_rules!warn { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Warning - ) - } -} - -#[macro_export] -macro_rules!info { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Log - ) - } -} - -#[macro_export] -macro_rules!debug { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Log - ) - } -} - -#[macro_export] -macro_rules!trace { - ( $ ( $ t: tt) *) => { - $crate::log_with_level( - file!(), - line!()-1, - column!()-1, - line!()-1, - column!() + 3, - format!( $ ( $ t) *), - $ crate::LogLevel::Log - ) - } -} - -fn log_with_level_rustc( - file_name: &str, - line_start: u32, - column_start: u32, - line_end: u32, - column_end: u32, - message: String, - level: LogLevel, -) { - println!( - "{}", - level.make_rustc_json( - file_name, - line_start, - column_start, - line_end, - column_end, - &message - ) - ); -} - -pub static LOG_WITH_LEVEL: RwLock = - RwLock::new(log_with_level_rustc); - -pub fn log_with_level( - file_name: &str, - line_start: u32, - column_start: u32, - line_end: u32, - column_end: u32, - message: String, - level: LogLevel, -) { - let logger = LOG_WITH_LEVEL.read().expect("Logger lock poisoned"); - logger( - file_name, - line_start, - column_start, - line_end, - column_end, - message, - level, - ); -} - -#[derive(Clone, PartialEq, Eq, Copy, Debug, SerBin, DeBin, SerJson, DeJson)] -pub enum LogLevel { - Warning, - Error, - Log, - Wait, - Panic, -} - -impl LogLevel { - pub fn make_rustc_json( - &self, - file: &str, - line_start: u32, - column_start: u32, - line_end: u32, - column_end: u32, - message: &str, - ) -> String { - let mut out = String::new(); - let _ = write!(out, "{{\"reason\":\"makepad-error-log\","); - let _ = write!(out, "\"message\":{{\"message\":\""); - for c in message.chars() { - match c { - '\n' => { - out.push('\\'); - out.push('n'); - } - '\r' => { - out.push('\\'); - out.push('r'); - } - '\t' => { - out.push('\\'); - out.push('t'); - } - '\0' => { - out.push('\\'); - out.push('0'); - } - '\\' => { - out.push('\\'); - out.push('\\'); - } - '"' => { - out.push('\\'); - out.push('"'); - } - _ => out.push(c), - } - } - let _ = write!(out, "\","); - let _ = match self { - LogLevel::Error => write!(out, "\"level\":\"error\","), - LogLevel::Log => write!(out, "\"level\":\"log\","), - LogLevel::Panic => write!(out, "\"level\":\"panic\","), - LogLevel::Warning => write!(out, "\"level\":\"warning\","), - LogLevel::Wait => write!(out, "\"level\":\"wait\","), - }; - let _ = write!(out, "\"spans\":[{{"); - let _ = write!(out, "\"file_name\":\"{}\",", file); - let _ = write!(out, "\"byte_start\":0,"); - let _ = write!(out, "\"byte_end\":0,"); - let _ = write!(out, "\"line_start\":{},", line_start + 1); - let _ = write!(out, "\"line_end\":{},", line_end + 1); - let _ = write!(out, "\"column_start\":{},", column_start); - let _ = write!(out, "\"column_end\":{},", column_end); - let _ = write!(out, "\"is_primary\":true,"); - let _ = write!(out, "\"text\":[]"); - let _ = write!(out, "}}],"); - let _ = write!(out, "\"children\":[]"); - let _ = write!(out, "}}"); - let _ = write!(out, "}}"); - out - } -} diff --git a/vendor/makepad/libs/html/Cargo.toml b/vendor/makepad/libs/html/Cargo.toml deleted file mode 100644 index 65165d6..0000000 --- a/vendor/makepad/libs/html/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "makepad-html" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad html parser" -license = "MIT OR Apache-2.0" -metadata.makepad-auto-version = "4Nv_oCgU_OE2jUlIZ6LxVkB7OeQ=" - -[dependencies] -makepad-live-id = { path = "../live_id", version = "1.0.0" } diff --git a/vendor/makepad/libs/html/src/lib.rs b/vendor/makepad/libs/html/src/lib.rs deleted file mode 100644 index c4b08fa..0000000 --- a/vendor/makepad/libs/html/src/lib.rs +++ /dev/null @@ -1,2382 +0,0 @@ -use makepad_live_id::*; - -#[derive(Debug)] -pub struct HtmlError { - pub message: String, - pub position: usize, -} - -#[derive(Default, PartialEq)] -pub struct HtmlDoc { - pub decoded: String, - pub nodes: Vec, -} - -#[derive(Debug, PartialEq)] -pub enum HtmlNode { - OpenTag { - lc: LiveId, - nc: LiveId, - }, - CloseTag { - lc: LiveId, - nc: LiveId, - }, - Attribute { - lc: LiveId, - nc: LiveId, - start: usize, - end: usize, - }, - Text { - start: usize, - end: usize, - all_ws: bool, - }, -} -/* -/// A standalone owned copy of an HTML attribute. -#[derive(Debug, Clone)] -pub struct HtmlAttribute { - /// The LiveID of this attribute's key converted to lowercase. - pub lc: LiveId, - /// The LiveID of this attribute's key in its original normal case. - pub nc: LiveId, - /// The value of this attribute. - pub value: String, -}*/ - -pub struct HtmlWalker<'a> { - decoded: &'a str, - pub nodes: &'a [HtmlNode], - pub index: usize, -} - -impl<'a> HtmlWalker<'a> { - pub fn index(&self) -> usize { - self.index - } - - pub fn walk(&mut self) { - if self.index < self.nodes.len() { - for i in self.index + 1..self.nodes.len() { - // we skip attributes - if let HtmlNode::Attribute { .. } = &self.nodes[i] { - } else { - self.index = i; - return; - } - } - self.index = self.nodes.len(); - } - } - - pub fn jump_to_close(&mut self) { - if self.index < self.nodes.len() { - let mut depth = 0; - for i in self.index + 1..self.nodes.len() { - match &self.nodes[i] { - HtmlNode::OpenTag { .. } => { - depth += 1; - } - HtmlNode::CloseTag { .. } => { - if depth == 0 { - self.index = i; - return; - } - depth -= 1; - } - _ => (), - } - } - } - self.index = self.nodes.len(); - } - - pub fn done(&self) -> bool { - self.index >= self.nodes.len() - } - /* - /// Iterates over and returns a list of all attributes for the current open HTML tag. - pub fn collect_attributes(&self) -> Vec { - let mut attrs = Vec::new(); - for node in &self.nodes[self.index ..] { - match node { - HtmlNode::Attribute { lc, nc, start, end } => { - attrs.push(HtmlAttribute { - lc: *lc, - nc: *nc, - value: String::from(&self.decoded[*start..*end]), - }); - } - HtmlNode::CloseTag { .. } => break, - _ => continue, - } - } - attrs - } - */ - /// Returns the first attribute of the currently-opened Html tag - /// whose key matches the given `flc` LiveId, which should be all lowercase. - /// - /// Matching is done after converting all attribute keys to lowercase. - pub fn find_attr_lc(&self, flc: LiveId) -> Option<&'a str> { - for i in (self.index + 1)..self.nodes.len() { - match &self.nodes[i] { - HtmlNode::OpenTag { .. } | HtmlNode::CloseTag { .. } => return None, - HtmlNode::Attribute { - lc, - nc: _, - start, - end, - } if *lc == flc => return Some(&self.decoded[*start..*end]), - _ => (), - } - } - None - } - - pub fn while_attr_lc(&mut self) -> Option<(LiveId, &'a str)> { - if self.index < self.nodes.len() { - match &self.nodes[self.index] { - HtmlNode::Attribute { - lc, - nc: _, - start, - end, - } => { - self.index += 1; - return Some((*lc, &self.decoded[*start..*end])); - } - _ => (), - } - } - None - } - - /// Returns the first attribute of the currently-opened Html tag - /// whose key matches the given `fnc` LiveId, which is case-sensitive. - /// - /// Matching is done in a case-sensitive manner. - pub fn find_attr_nc(&self, fnc: LiveId) -> Option<&'a str> { - for i in (self.index + 1)..self.nodes.len() { - match &self.nodes[i] { - HtmlNode::OpenTag { .. } | HtmlNode::CloseTag { .. } => return None, - HtmlNode::Attribute { - lc: _, - nc, - start, - end, - } if *nc == fnc => return Some(&self.decoded[*start..*end]), - _ => (), - } - } - None - } - - pub fn find_text(&self) -> Option<&'a str> { - for i in self.index..self.nodes.len() { - match &self.nodes[i] { - HtmlNode::CloseTag { .. } => return None, - HtmlNode::Text { start, end, .. } => return Some(&self.decoded[*start..*end]), - _ => (), - } - } - None - } - - pub fn find_tag_text(&self, tag: LiveId) -> Option<&'a str> { - for i in self.index..self.nodes.len() { - match &self.nodes[i] { - HtmlNode::OpenTag { nc, .. } if *nc == tag => { - // the next one must be a text node - if let Some(HtmlNode::Text { start, end, .. }) = self.nodes.get(i + 1) { - return Some(&self.decoded[*start..*end]); - } - } - _ => (), - } - } - None - } - - pub fn text(&self) -> Option<&'a str> { - match self.nodes.get(self.index) { - Some(HtmlNode::Text { start, end, .. }) => Some(&self.decoded[*start..*end]), - _ => None, - } - } - - pub fn text_is_all_ws(&self) -> bool { - match self.nodes.get(self.index) { - Some(HtmlNode::Text { all_ws, .. }) => *all_ws, - _ => false, - } - } - - pub fn open_tag_lc(&self) -> Option { - match self.nodes.get(self.index) { - Some(HtmlNode::OpenTag { lc, nc: _ }) => Some(*lc), - _ => None, - } - } - pub fn open_tag_nc(&self) -> Option { - match self.nodes.get(self.index) { - Some(HtmlNode::OpenTag { lc: _, nc }) => Some(*nc), - _ => None, - } - } - pub fn open_tag(&self) -> Option<(LiveId, LiveId)> { - match self.nodes.get(self.index) { - Some(HtmlNode::OpenTag { lc, nc }) => Some((*lc, *nc)), - _ => None, - } - } - - pub fn close_tag_lc(&self) -> Option { - match self.nodes.get(self.index) { - Some(HtmlNode::CloseTag { lc, nc: _ }) => Some(*lc), - _ => None, - } - } - pub fn close_tag_nc(&self) -> Option { - match self.nodes.get(self.index) { - Some(HtmlNode::CloseTag { lc: _, nc }) => Some(*nc), - _ => None, - } - } - pub fn close_tag(&self) -> Option<(LiveId, LiveId)> { - match self.nodes.get(self.index) { - Some(HtmlNode::CloseTag { lc, nc }) => Some((*lc, *nc)), - _ => None, - } - } -} - -impl HtmlDoc { - pub fn new_walker(&self) -> HtmlWalker<'_> { - HtmlWalker { - decoded: &self.decoded, - index: 0, - nodes: &self.nodes, - } - } - - pub fn new_walker_with_index(&self, index: usize) -> HtmlWalker<'_> { - HtmlWalker { - decoded: &self.decoded, - index, - nodes: &self.nodes, - } - } -} - -pub fn parse_html( - body: &str, - errors: &mut Option>, - intern: InternLiveId, -) -> HtmlDoc { - enum State { - Text { - start: usize, - dec_start: usize, - last_non_whitespace: usize, - collapse_ws: bool, - }, - ElementName(usize), - ElementClose(usize), - ElementAttrs, - ElementCloseScanSpaces, - ElementSelfClose, - AttribName(usize), - AttribValueEq(LiveId, LiveId), - AttribValueStart(LiveId, LiveId), - AttribValueSq(LiveId, LiveId, usize), - AttribValueDq(LiveId, LiveId, usize), - AttribValueBare(LiveId, LiveId, usize), - CommentStartDash1, - CommentStartDash2, - CommentEndDash, - CommentEnd, - DocType, - HeaderQuestion, - HeaderAngle, - CommentBody, - } - - fn process_entity( - c: char, - in_entity: &mut Option, - decoded: &mut String, - last_non_whitespace: &mut usize, - collapse_ws: bool, - ) { - if let Some(start) = *in_entity { - // scan entity - if c == ';' { - // potential end of entity - match match_entity(&decoded[start + 1..]) { - Err(_e) => { - *in_entity = None; - } - Ok(entity) => { - *in_entity = None; - decoded.truncate(start); - let ch = std::char::from_u32(entity).unwrap(); - decoded.push(ch); - // While the entity body was being scanned, each - // character was appended to `decoded` and (if - // non-whitespace) advanced `last_non_whitespace`. - // After truncating, that index is now stale and - // must be corrected — otherwise the next real - // whitespace char collapses against a phantom - // non-whitespace position past the buffer end, and - // gets silently dropped. - if ch.is_whitespace() { - *last_non_whitespace = (*last_non_whitespace).min(start); - } else { - *last_non_whitespace = decoded.len(); - } - return; - } - } - } - // definitely not an entity - else if c.is_whitespace() || decoded.len() - start > "DOWNLEFTRIGHTVECTOR".len() { - *in_entity = None; - } - } - if c == '&' { - *in_entity = Some(decoded.len()); - } - if collapse_ws && c.is_whitespace() { - if *last_non_whitespace == decoded.len() { - decoded.push(' '); - } - } else { - decoded.push(c); - if !c.is_whitespace() { - *last_non_whitespace = decoded.len(); - } - } - } - - let mut nodes = Vec::new(); - let mut state = State::Text { - start: 0, - dec_start: 0, - last_non_whitespace: 0, - collapse_ws: true, - }; - let mut decoded = String::new(); - let mut in_entity = None; - - for (i, c) in body.char_indices() { - state = match state { - State::DocType => { - if c == '>' { - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - State::DocType - } - } - State::HeaderQuestion => { - if c == '?' { - State::HeaderAngle - } else { - State::HeaderQuestion - } - } - State::HeaderAngle => { - if c == '>' { - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - State::HeaderQuestion - } - } - State::Text { - start, - dec_start, - last_non_whitespace, - collapse_ws, - } => { - if c == '<' { - if let Some(start) = in_entity { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Unterminated entity".into(), - position: start, - }) - }; - } - nodes.push(HtmlNode::Text { - start: dec_start, - end: decoded.len(), - all_ws: dec_start == last_non_whitespace, - }); - State::ElementName(i + 1) - } else { - let mut last_non_whitespace = last_non_whitespace; - process_entity( - c, - &mut in_entity, - &mut decoded, - &mut last_non_whitespace, - collapse_ws, - ); - State::Text { - start, - dec_start, - last_non_whitespace, - collapse_ws, - } - } - } - State::ElementName(start) => { - if c == '/' && i == start { - State::ElementClose(i + 1) - } else if c == '!' && i == start { - State::CommentStartDash1 - } else if c == '?' { - State::HeaderQuestion - } else if c.is_whitespace() { - if start == i { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Found whitespace at beginning of tag".into(), - position: i, - }) - }; - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - nodes.push(HtmlNode::OpenTag { - lc: LiveId::from_str_lc(&body[start..i]), - nc: LiveId::from_str_with_intern(&body[start..i], intern), - }); - State::ElementAttrs - } - } else if c == '/' { - nodes.push(HtmlNode::OpenTag { - lc: LiveId::from_str_lc(&body[start..i]), - nc: LiveId::from_str_with_intern(&body[start..i], intern), - }); - State::ElementSelfClose - } else if c == '>' { - let lc = LiveId::from_str_lc(&body[start..i]); - let nc = LiveId::from_str_with_intern(&body[start..i], intern); - nodes.push(HtmlNode::OpenTag { lc, nc }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: lc != live_id!(pre) && lc != live_id!(code), - } - } else { - State::ElementName(start) - } - } - State::ElementClose(start) => { - if c == '>' { - let lc = LiveId::from_str_lc(&body[start..i]); - let nc = LiveId::from_str_with_intern(&body[start..i], intern); - nodes.push(HtmlNode::CloseTag { lc, nc }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else if c.is_whitespace() { - nodes.push(HtmlNode::CloseTag { - lc: LiveId::from_str_lc(&body[start..i]), - nc: LiveId::from_str_with_intern(&body[start..i], intern), - }); - State::ElementCloseScanSpaces - } else { - State::ElementClose(start) - } - } - State::ElementCloseScanSpaces => { - if c == '>' { - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else if !c.is_whitespace() { - if let Some(errors) = errors { - errors.push(HtmlError{message:"Unexpected character after whitespace whilst looking for closing tag >".into(), position:i}) - }; - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - State::ElementCloseScanSpaces - } - } - State::ElementSelfClose => { - if c != '>' { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Expected > after / self closed tag".into(), - position: i, - }) - }; - } - // look backwards to the OpenTag - let begin = nodes - .iter() - .rev() - .find_map(|v| { - if let HtmlNode::OpenTag { lc, nc } = v { - Some((lc, nc)) - } else { - None - } - }) - .unwrap(); - nodes.push(HtmlNode::CloseTag { - lc: *begin.0, - nc: *begin.1, - }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } - State::ElementAttrs => { - if c == '/' { - //nodes.push(HtmlNode::BeginElement(HtmlId::new(&body, start, i))); - State::ElementSelfClose - } else if c == '>' { - let begin = nodes.iter().rev().find_map(|v| { - if let HtmlNode::OpenTag { lc, nc: _ } = v { - Some(*lc) - } else { - None - } - }); - - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: if let Some(lc) = begin { - lc != live_id!(pre) && lc != live_id!(code) - } else { - true - }, - } - } else if !c.is_whitespace() { - State::AttribName(i) - } else { - State::ElementAttrs - } - } - State::AttribName(start) => { - if c.is_whitespace() { - State::AttribValueEq( - LiveId::from_str_lc(&body[start..i]), - LiveId::from_str_with_intern(&body[start..i], intern), - ) - } else if c == '=' { - State::AttribValueStart( - LiveId::from_str_lc(&body[start..i]), - LiveId::from_str_with_intern(&body[start..i], intern), - ) - } else if c == '/' { - nodes.push(HtmlNode::Attribute { - lc: LiveId::from_str_lc(&body[start..i]), - nc: LiveId::from_str_with_intern(&body[start..i], intern), - start: 0, - end: 0, - }); - State::ElementSelfClose - } else if c == '>' { - nodes.push(HtmlNode::Attribute { - lc: LiveId::from_str_lc(&body[start..i]), - nc: LiveId::from_str_with_intern(&body[start..i], intern), - start: 0, - end: 0, - }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - State::AttribName(start) - } - } - State::AttribValueEq(lc, nc) => { - if c == '/' { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start: 0, - end: 0, - }); - State::ElementSelfClose - } else if c == '>' { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start: 0, - end: 0, - }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else if c == '=' { - State::AttribValueStart(lc, nc) - } else if !c.is_whitespace() { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start: 0, - end: 0, - }); - State::AttribName(i) - } else { - State::AttribValueEq(lc, nc) - } - } - State::AttribValueStart(lc, nc) => { - if c == '\"' { - // double quoted attrib - State::AttribValueDq(lc, nc, decoded.len()) - } else if c == '\'' { - // single quoted attrib - State::AttribValueSq(lc, nc, decoded.len()) - } else if !c.is_whitespace() { - decoded.push(c); - State::AttribValueBare(lc, nc, decoded.len() - 1) - } else { - State::AttribValueStart(lc, nc) - } - } - State::AttribValueSq(lc, nc, start) => { - if c == '\'' { - if let Some(start) = in_entity { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Unterminated entity".into(), - position: start, - }) - }; - } - nodes.push(HtmlNode::Attribute { - lc, - nc, - start, - end: decoded.len(), - }); - State::ElementAttrs - } else { - process_entity(c, &mut in_entity, &mut decoded, &mut 0, false); - State::AttribValueSq(lc, nc, start) - } - } - State::AttribValueDq(lc, nc, start) => { - if c == '\"' { - if let Some(start) = in_entity { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Unterminated entity".into(), - position: start, - }) - }; - } - nodes.push(HtmlNode::Attribute { - lc, - nc, - start, - end: decoded.len(), - }); - State::ElementAttrs - } else { - process_entity(c, &mut in_entity, &mut decoded, &mut 0, false); - State::AttribValueDq(lc, nc, start) - } - } - State::AttribValueBare(lc, nc, start) => { - if c == '/' { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start, - end: decoded.len(), - }); - State::ElementSelfClose - } else if c == '>' { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start, - end: decoded.len(), - }); - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else if c.is_whitespace() { - nodes.push(HtmlNode::Attribute { - lc, - nc, - start, - end: decoded.len(), - }); - State::ElementAttrs - } else { - decoded.push(c); - State::AttribValueBare(lc, nc, start) - } - } - State::CommentStartDash1 => { - if c != '-' { - // we should scan for > - State::DocType - // if let Some(errors) = errors{errors.push(HtmlError{message:"Unexpected //character looking for - after { - if c != '-' { - if let Some(errors) = errors { - errors.push(HtmlError { - message: "Unexpected character looking for - after { - if c == '-' { - State::CommentEndDash - } else { - State::CommentBody - } - } - State::CommentEndDash => { - if c == '-' { - State::CommentEnd - } else { - State::CommentBody - } - } - State::CommentEnd => { - if c == '>' { - State::Text { - start: i + 1, - dec_start: decoded.len(), - last_non_whitespace: decoded.len(), - collapse_ws: true, - } - } else { - State::CommentBody - } - } - } - } - if let State::Text { - start: _, - dec_start, - last_non_whitespace, - collapse_ws: _, - } = state - { - nodes.push(HtmlNode::Text { - start: dec_start, - end: decoded.len(), - all_ws: dec_start == last_non_whitespace, - }); - } else { - // if we didnt end in text state something is wrong - if let Some(errors) = errors { - errors.push(HtmlError { - message: "HTML Parsing endstate is not HtmlNode::Text".into(), - position: body.len(), - }) - }; - } - HtmlDoc { nodes, decoded } -} - -pub fn match_entity(what: &str) -> Result { - Ok(match what { - "dollar" => 36, - "DOLLAR" => 36, - "cent" => 162, - "CENT" => 162, - "pound" => 163, - "POUND" => 163, - "curren" => 164, - "CURREN" => 164, - "yen" => 165, - "YEN" => 165, - "copy" => 169, - "COPY" => 169, - "reg" => 174, - "REG" => 174, - "trade" => 8482, - "TRADE" => 8482, - "commat" => 64, - "COMMAT" => 64, - "Copf" => 8450, - "copf" => 8450, - "COPF" => 8450, - "incare" => 8453, - "INCARE" => 8453, - "gscr" => 8458, - "GSCR" => 8458, - "hamilt" => 8459, - "HAMILT" => 8459, - "Hfr" => 8460, - "hfr" => 8460, - "HFR" => 8460, - "Hopf" => 8461, - "hopf" => 8461, - "HOPF" => 8461, - "planckh" => 8462, - "PLANCKH" => 8462, - "planck" => 8463, - "PLANCK" => 8463, - "Iscr" => 8464, - "iscr" => 8464, - "ISCR" => 8464, - "image" => 8465, - "IMAGE" => 8465, - "Lscr" => 8466, - "lscr" => 8466, - "LSCR" => 8466, - "ell" => 8467, - "ELL" => 8467, - "Nopf" => 8469, - "nopf" => 8469, - "NOPF" => 8469, - "numero" => 8470, - "NUMERO" => 8470, - "copysr" => 8471, - "COPYSR" => 8471, - "weierp" => 8472, - "WEIERP" => 8472, - "Popf" => 8473, - "popf" => 8473, - "POPF" => 8473, - "Qopf" => 8474, - "qopf" => 8474, - "QOPF" => 8474, - "Rscr" => 8475, - "rscr" => 8475, - "RSCR" => 8475, - "real" => 8476, - "REAL" => 8476, - "Ropf" => 8477, - "ropf" => 8477, - "ROPF" => 8477, - "rx" => 8478, - "RX" => 8478, - "Zopf" => 8484, - "zopf" => 8484, - "ZOPF" => 8484, - "mho" => 8487, - "MHO" => 8487, - "Zfr" => 8488, - "zfr" => 8488, - "ZFR" => 8488, - "iiota" => 8489, - "IIOTA" => 8489, - "bernou" => 8492, - "BERNOU" => 8492, - "Cfr" => 8493, - "cfr" => 8493, - "CFR" => 8493, - "escr" => 8495, - "ESCR" => 8495, - "Escr" => 8496, - "Fscr" => 8497, - "fscr" => 8497, - "FSCR" => 8497, - "Mscr" => 8499, - "mscr" => 8499, - "MSCR" => 8499, - "oscr" => 8500, - "OSCR" => 8500, - "alefsym" => 8501, - "ALEFSYM" => 8501, - "beth" => 8502, - "BETH" => 8502, - "gimel" => 8503, - "GIMEL" => 8503, - "daleth" => 8504, - "DALETH" => 8504, - "DD" => 8517, - "dd" => 8517, - "ee" => 8519, - "EE" => 8519, - "ii" => 8520, - "II" => 8520, - "starf" => 9733, - "STARF" => 9733, - "star" => 9734, - "STAR" => 9734, - "phone" => 9742, - "PHONE" => 9742, - "female" => 9792, - "FEMALE" => 9792, - "male" => 9794, - "MALE" => 9794, - "spades" => 9824, - "SPADES" => 9824, - "clubs" => 9827, - "CLUBS" => 9827, - "hearts" => 9829, - "HEARTS" => 9829, - "diams" => 9830, - "DIAMS" => 9830, - "loz" => 9674, - "LOZ" => 9674, - "sung" => 9834, - "SUNG" => 9834, - "flat" => 9837, - "FLAT" => 9837, - "natural" => 9838, - "NATURAL" => 9838, - "sharp" => 9839, - "SHARP" => 9839, - "check" => 10003, - "CHECK" => 10003, - "cross" => 10007, - "CROSS" => 10007, - "malt" => 10016, - "MALT" => 10016, - "sext" => 10038, - "SEXT" => 10038, - "VerticalSeparator" => 10072, - "verticalseparator" => 10072, - "VERTICALSEPARATOR" => 10072, - "lbbrk" => 10098, - "LBBRK" => 10098, - "rbbrk" => 10099, - "RBBRK" => 10099, - "excl" => 33, - "EXCL" => 33, - "num" => 35, - "NUM" => 35, - "percnt" => 37, - "PERCNT" => 37, - "amp" => 38, - "AMP" => 38, - "lpar" => 40, - "LPAR" => 40, - "rpar" => 41, - "RPAR" => 41, - "ast" => 42, - "AST" => 42, - "comma" => 44, - "COMMA" => 44, - "period" => 46, - "PERIOD" => 46, - "sol" => 47, - "SOL" => 47, - "colon" => 58, - "COLON" => 58, - "semi" => 59, - "SEMI" => 59, - "quest" => 63, - "QUEST" => 63, - "lbrack" => 91, - "LBRACK" => 91, - "bsol" => 92, - "BSOL" => 92, - "rbrack" => 93, - "RBRACK" => 93, - "Hat" => 94, - "hat" => 94, - "HAT" => 94, - "lowbar" => 95, - "LOWBAR" => 95, - "grave" => 96, - "GRAVE" => 96, - "lbrace" => 123, - "LBRACE" => 123, - "vert" => 124, - "VERT" => 124, - "rbrace" => 125, - "RBRACE" => 125, - "tilde" => 126, - "TILDE" => 126, - "circ" => 710, - "CIRC" => 710, - "nbsp" => 160, - "NBSP" => 160, - "ensp" => 8194, - "ENSP" => 8194, - "emsp" => 8195, - "EMSP" => 8195, - "thinsp" => 8201, - "THINSP" => 8201, - "zwnj" => 8204, - "ZWNJ" => 8204, - "zwj" => 8205, - "ZWJ" => 8205, - "lrm" => 8206, - "LRM" => 8206, - "rlm" => 8207, - "RLM" => 8207, - "iexcl" => 161, - "IEXCL" => 161, - "brvbar" => 166, - "BRVBAR" => 166, - "sect" => 167, - "SECT" => 167, - "uml" => 168, - "UML" => 168, - "ordf" => 170, - "ORDF" => 170, - "not" => 172, - "NOT" => 172, - "shy" => 173, - "SHY" => 173, - "macr" => 175, - "MACR" => 175, - "sup2" => 178, - "SUP2" => 178, - "sup3" => 179, - "SUP3" => 179, - "acute" => 180, - "ACUTE" => 180, - "micro" => 181, - "MICRO" => 181, - "para" => 182, - "PARA" => 182, - "middot" => 183, - "MIDDOT" => 183, - "cedil" => 184, - "CEDIL" => 184, - "sup1" => 185, - "SUP1" => 185, - "ordm" => 186, - "ORDM" => 186, - "iquest" => 191, - "IQUEST" => 191, - "hyphen" => 8208, - "HYPHEN" => 8208, - "ndash" => 8211, - "NDASH" => 8211, - "mdash" => 8212, - "MDASH" => 8212, - "horbar" => 8213, - "HORBAR" => 8213, - "Vert" => 8214, - "dagger" => 8224, - "DAGGER" => 8224, - "Dagger" => 8225, - "bull" => 8226, - "BULL" => 8226, - "nldr" => 8229, - "NLDR" => 8229, - "hellip" => 8230, - "HELLIP" => 8230, - "" => 8240, - "pertenk" => 8241, - "PERTENK" => 8241, - "prime" => 8242, - "PRIME" => 8242, - "Prime" => 8243, - "tprime" => 8244, - "TPRIME" => 8244, - "bprime" => 8245, - "BPRIME" => 8245, - "oline" => 8254, - "OLINE" => 8254, - "caret" => 8257, - "CARET" => 8257, - "hybull" => 8259, - "HYBULL" => 8259, - "frasl" => 8260, - "FRASL" => 8260, - "bsemi" => 8271, - "BSEMI" => 8271, - "qprime" => 8279, - "QPRIME" => 8279, - "quot" => 34, - "QUOT" => 34, - "apos" => 39, - "APOS" => 39, - "laquo" => 171, - "LAQUO" => 171, - "raquo" => 187, - "RAQUO" => 187, - "lsquo" => 8216, - "LSQUO" => 8216, - "rsquo" => 8217, - "RSQUO" => 8217, - "sbquo" => 8218, - "SBQUO" => 8218, - "ldquo" => 8220, - "LDQUO" => 8220, - "rdquo" => 8221, - "RDQUO" => 8221, - "bdquo" => 8222, - "BDQUO" => 8222, - "lsaquo" => 8249, - "LSAQUO" => 8249, - "rsaquo" => 8250, - "RSAQUO" => 8250, - "frac14" => 188, - "FRAC14" => 188, - "frac12" => 189, - "FRAC12" => 189, - "frac34" => 190, - "FRAC34" => 190, - "frac13" => 8531, - "FRAC13" => 8531, - "frac23" => 8532, - "FRAC23" => 8532, - "frac15" => 8533, - "FRAC15" => 8533, - "frac25" => 8534, - "FRAC25" => 8534, - "frac35" => 8535, - "FRAC35" => 8535, - "frac45" => 8536, - "FRAC45" => 8536, - "frac16" => 8537, - "FRAC16" => 8537, - "frac56" => 8538, - "FRAC56" => 8538, - "frac18" => 8539, - "FRAC18" => 8539, - "frac38" => 8540, - "FRAC38" => 8540, - "frac58" => 8541, - "FRAC58" => 8541, - "frac78" => 8542, - "FRAC78" => 8542, - "plus" => 43, - "PLUS" => 43, - "minus" => 8722, - "MINUS" => 8722, - "times" => 215, - "TIMES" => 215, - "divide" => 247, - "DIVIDE" => 247, - "equals" => 61, - "EQUALS" => 61, - "ne" => 8800, - "NE" => 8800, - "plusmn" => 177, - "PLUSMN" => 177, - "lt" => 60, - "LT" => 60, - "gt" => 62, - "GT" => 62, - "deg" => 176, - "DEG" => 176, - "fnof" => 402, - "FNOF" => 402, - "permil" => 137, - "PERMIL" => 137, - "forall" => 8704, - "FORALL" => 8704, - "comp" => 8705, - "COMP" => 8705, - "part" => 8706, - "PART" => 8706, - "exist" => 8707, - "EXIST" => 8707, - "nexist" => 8708, - "NEXIST" => 8708, - "empty" => 8709, - "EMPTY" => 8709, - "nabla" => 8711, - "NABLA" => 8711, - "isin" => 8712, - "ISIN" => 8712, - "notin" => 8713, - "NOTIN" => 8713, - "ni" => 8715, - "NI" => 8715, - "notni" => 8716, - "NOTNI" => 8716, - "prod" => 8719, - "PROD" => 8719, - "coprod" => 8720, - "COPROD" => 8720, - "sum" => 8721, - "SUM" => 8721, - "mnplus" => 8723, - "MNPLUS" => 8723, - "plusdo" => 8724, - "PLUSDO" => 8724, - "setminus" => 8726, - "SETMINUS" => 8726, - "lowast" => 8727, - "LOWAST" => 8727, - "compfn" => 8728, - "COMPFN" => 8728, - "radic" => 8730, - "RADIC" => 8730, - "prop" => 8733, - "PROP" => 8733, - "infin" => 8734, - "INFIN" => 8734, - "angrt" => 8735, - "ANGRT" => 8735, - "ang" => 8736, - "ANG" => 8736, - "angmsd" => 8737, - "ANGMSD" => 8737, - "angsph" => 8738, - "ANGSPH" => 8738, - "mid" => 8739, - "MID" => 8739, - "nmid" => 8740, - "NMID" => 8740, - "parallel" => 8741, - "PARALLEL" => 8741, - "npar" => 8742, - "NPAR" => 8742, - "and" => 8743, - "AND" => 8743, - "or" => 8744, - "OR" => 8744, - "cap" => 8745, - "CAP" => 8745, - "cup" => 8746, - "CUP" => 8746, - "int" => 8747, - "INT" => 8747, - "Int" => 8748, - "iiint" => 8749, - "IIINT" => 8749, - "conint" => 8750, - "CONINT" => 8750, - "Conint" => 8751, - "Cconint" => 8752, - "cconint" => 8752, - "CCONINT" => 8752, - "cwint" => 8753, - "CWINT" => 8753, - "cwconint" => 8754, - "CWCONINT" => 8754, - "awconint" => 8755, - "AWCONINT" => 8755, - "there4" => 8756, - "THERE4" => 8756, - "because" => 8757, - "BECAUSE" => 8757, - "ratio" => 8758, - "RATIO" => 8758, - "Colon" => 8759, - "minusd" => 8760, - "MINUSD" => 8760, - "mDDot" => 8762, - "mddot" => 8762, - "MDDOT" => 8762, - "homtht" => 8763, - "HOMTHT" => 8763, - "sim" => 8764, - "SIM" => 8764, - "bsim" => 8765, - "BSIM" => 8765, - "ac" => 8766, - "AC" => 8766, - "acd" => 8767, - "ACD" => 8767, - "wreath" => 8768, - "WREATH" => 8768, - "nsim" => 8769, - "NSIM" => 8769, - "esim" => 8770, - "ESIM" => 8770, - "sime" => 8771, - "SIME" => 8771, - "nsime" => 8772, - "NSIME" => 8772, - "cong" => 8773, - "CONG" => 8773, - "simne" => 8774, - "SIMNE" => 8774, - "ncong" => 8775, - "NCONG" => 8775, - "asymp" => 8776, - "ASYMP" => 8776, - "nap" => 8777, - "NAP" => 8777, - "approxeq" => 8778, - "APPROXEQ" => 8778, - "apid" => 8779, - "APID" => 8779, - "bcong" => 8780, - "BCONG" => 8780, - "asympeq" => 8781, - "ASYMPEQ" => 8781, - "bump" => 8782, - "BUMP" => 8782, - "bumpe" => 8783, - "BUMPE" => 8783, - "esdot" => 8784, - "ESDOT" => 8784, - "eDot" => 8785, - "edot" => 8785, - "EDOT" => 8785, - "efDot" => 8786, - "efdot" => 8786, - "EFDOT" => 8786, - "erDot" => 8787, - "erdot" => 8787, - "ERDOT" => 8787, - "colone" => 8788, - "COLONE" => 8788, - "ecolon" => 8789, - "ECOLON" => 8789, - "ecir" => 8790, - "ECIR" => 8790, - "cire" => 8791, - "CIRE" => 8791, - "wedgeq" => 8793, - "WEDGEQ" => 8793, - "veeeq" => 8794, - "VEEEQ" => 8794, - "trie" => 8796, - "TRIE" => 8796, - "equest" => 8799, - "EQUEST" => 8799, - "equiv" => 8801, - "EQUIV" => 8801, - "nequiv" => 8802, - "NEQUIV" => 8802, - "le" => 8804, - "LE" => 8804, - "ge" => 8805, - "GE" => 8805, - "lE" => 8806, - "gE" => 8807, - "lnE" => 8808, - "lne" => 8808, - "LNE" => 8808, - "gnE" => 8809, - "gne" => 8809, - "GNE" => 8809, - "Lt" => 8810, - "Gt" => 8811, - "between" => 8812, - "BETWEEN" => 8812, - "NotCupCap" => 8813, - "notcupcap" => 8813, - "NOTCUPCAP" => 8813, - "nlt" => 8814, - "NLT" => 8814, - "ngt" => 8815, - "NGT" => 8815, - "nle" => 8816, - "NLE" => 8816, - "nge" => 8817, - "NGE" => 8817, - "lsim" => 8818, - "LSIM" => 8818, - "gsim" => 8819, - "GSIM" => 8819, - "nlsim" => 8820, - "NLSIM" => 8820, - "ngsim" => 8821, - "NGSIM" => 8821, - "lg" => 8822, - "LG" => 8822, - "gl" => 8823, - "GL" => 8823, - "ntlg" => 8824, - "NTLG" => 8824, - "ntgl" => 8825, - "NTGL" => 8825, - "pr" => 8826, - "PR" => 8826, - "sc" => 8827, - "SC" => 8827, - "prcue" => 8828, - "PRCUE" => 8828, - "sccue" => 8829, - "SCCUE" => 8829, - "prsim" => 8830, - "PRSIM" => 8830, - "scsim" => 8831, - "SCSIM" => 8831, - "npr" => 8832, - "NPR" => 8832, - "nsc" => 8833, - "NSC" => 8833, - "sub" => 8834, - "SUB" => 8834, - "sup" => 8835, - "SUP" => 8835, - "nsub" => 8836, - "NSUB" => 8836, - "nsup" => 8837, - "NSUP" => 8837, - "sube" => 8838, - "SUBE" => 8838, - "supe" => 8839, - "SUPE" => 8839, - "nsube" => 8840, - "NSUBE" => 8840, - "nsupe" => 8841, - "NSUPE" => 8841, - "subne" => 8842, - "SUBNE" => 8842, - "supne" => 8843, - "SUPNE" => 8843, - "cupdot" => 8845, - "CUPDOT" => 8845, - "uplus" => 8846, - "UPLUS" => 8846, - "sqsub" => 8847, - "SQSUB" => 8847, - "sqsup" => 8848, - "SQSUP" => 8848, - "sqsube" => 8849, - "SQSUBE" => 8849, - "sqsupe" => 8850, - "SQSUPE" => 8850, - "sqcap" => 8851, - "SQCAP" => 8851, - "sqcup" => 8852, - "SQCUP" => 8852, - "oplus" => 8853, - "OPLUS" => 8853, - "ominus" => 8854, - "OMINUS" => 8854, - "otimes" => 8855, - "OTIMES" => 8855, - "osol" => 8856, - "OSOL" => 8856, - "odot" => 8857, - "ODOT" => 8857, - "ocir" => 8858, - "OCIR" => 8858, - "oast" => 8859, - "OAST" => 8859, - "odash" => 8861, - "ODASH" => 8861, - "plusb" => 8862, - "PLUSB" => 8862, - "minusb" => 8863, - "MINUSB" => 8863, - "timesb" => 8864, - "TIMESB" => 8864, - "sdotb" => 8865, - "SDOTB" => 8865, - "vdash" => 8866, - "VDASH" => 8866, - "dashv" => 8867, - "DASHV" => 8867, - "top" => 8868, - "TOP" => 8868, - "perp" => 8869, - "PERP" => 8869, - "models" => 8871, - "MODELS" => 8871, - "vDash" => 8872, - "Vdash" => 8873, - "Vvdash" => 8874, - "vvdash" => 8874, - "VVDASH" => 8874, - "VDash" => 8875, - "nvdash" => 8876, - "NVDASH" => 8876, - "nvDash" => 8877, - "nVdash" => 8878, - "nVDash" => 8879, - "prurel" => 8880, - "PRUREL" => 8880, - "vltri" => 8882, - "VLTRI" => 8882, - "vrtri" => 8883, - "VRTRI" => 8883, - "ltrie" => 8884, - "LTRIE" => 8884, - "rtrie" => 8885, - "RTRIE" => 8885, - "origof" => 8886, - "ORIGOF" => 8886, - "imof" => 8887, - "IMOF" => 8887, - "mumap" => 8888, - "MUMAP" => 8888, - "hercon" => 8889, - "HERCON" => 8889, - "intcal" => 8890, - "INTCAL" => 8890, - "veebar" => 8891, - "VEEBAR" => 8891, - "barvee" => 8893, - "BARVEE" => 8893, - "angrtvb" => 8894, - "ANGRTVB" => 8894, - "lrtri" => 8895, - "LRTRI" => 8895, - "xwedge" => 8896, - "XWEDGE" => 8896, - "xvee" => 8897, - "XVEE" => 8897, - "xcap" => 8898, - "XCAP" => 8898, - "xcup" => 8899, - "XCUP" => 8899, - "diamond" => 8900, - "DIAMOND" => 8900, - "sdot" => 8901, - "SDOT" => 8901, - "Star" => 8902, - "divonx" => 8903, - "DIVONX" => 8903, - "bowtie" => 8904, - "BOWTIE" => 8904, - "ltimes" => 8905, - "LTIMES" => 8905, - "rtimes" => 8906, - "RTIMES" => 8906, - "lthree" => 8907, - "LTHREE" => 8907, - "rthree" => 8908, - "RTHREE" => 8908, - "bsime" => 8909, - "BSIME" => 8909, - "cuvee" => 8910, - "CUVEE" => 8910, - "cuwed" => 8911, - "CUWED" => 8911, - "Sub" => 8912, - "Sup" => 8913, - "Cap" => 8914, - "Cup" => 8915, - "fork" => 8916, - "FORK" => 8916, - "epar" => 8917, - "EPAR" => 8917, - "ltdot" => 8918, - "LTDOT" => 8918, - "gtdot" => 8919, - "GTDOT" => 8919, - "Ll" => 8920, - "ll" => 8920, - "LL" => 8920, - "Gg" => 8921, - "gg" => 8921, - "GG" => 8921, - "leg" => 8922, - "LEG" => 8922, - "gel" => 8923, - "GEL" => 8923, - "cuepr" => 8926, - "CUEPR" => 8926, - "cuesc" => 8927, - "CUESC" => 8927, - "nprcue" => 8928, - "NPRCUE" => 8928, - "nsccue" => 8929, - "NSCCUE" => 8929, - "nsqsube" => 8930, - "NSQSUBE" => 8930, - "nsqsupe" => 8931, - "NSQSUPE" => 8931, - "lnsim" => 8934, - "LNSIM" => 8934, - "gnsim" => 8935, - "GNSIM" => 8935, - "prnsim" => 8936, - "PRNSIM" => 8936, - "scnsim" => 8937, - "SCNSIM" => 8937, - "nltri" => 8938, - "NLTRI" => 8938, - "nrtri" => 8939, - "NRTRI" => 8939, - "nltrie" => 8940, - "NLTRIE" => 8940, - "nrtrie" => 8941, - "NRTRIE" => 8941, - "vellip" => 8942, - "VELLIP" => 8942, - "ctdot" => 8943, - "CTDOT" => 8943, - "utdot" => 8944, - "UTDOT" => 8944, - "dtdot" => 8945, - "DTDOT" => 8945, - "disin" => 8946, - "DISIN" => 8946, - "isinsv" => 8947, - "ISINSV" => 8947, - "isins" => 8948, - "ISINS" => 8948, - "isindot" => 8949, - "ISINDOT" => 8949, - "notinvc" => 8950, - "NOTINVC" => 8950, - "notinvb" => 8951, - "NOTINVB" => 8951, - "isinE" => 8953, - "isine" => 8953, - "ISINE" => 8953, - "nisd" => 8954, - "NISD" => 8954, - "xnis" => 8955, - "XNIS" => 8955, - "nis" => 8956, - "NIS" => 8956, - "notnivc" => 8957, - "NOTNIVC" => 8957, - "notnivb" => 8958, - "NOTNIVB" => 8958, - "lceil" => 8968, - "LCEIL" => 8968, - "rceil" => 8969, - "RCEIL" => 8969, - "lfloor" => 8970, - "LFLOOR" => 8970, - "rfloor" => 8971, - "RFLOOR" => 8971, - "lang" => 9001, - "LANG" => 9001, - "rang" => 9002, - "RANG" => 9002, - "Alpha" => 913, - "alpha" => 913, - "ALPHA" => 913, - "Beta" => 914, - "beta" => 914, - "BETA" => 914, - "Gamma" => 915, - "gamma" => 915, - "GAMMA" => 915, - "Delta" => 916, - "delta" => 916, - "DELTA" => 916, - "Epsilon" => 917, - "epsilon" => 917, - "EPSILON" => 917, - "Zeta" => 918, - "zeta" => 918, - "ZETA" => 918, - "Eta" => 919, - "eta" => 919, - "ETA" => 919, - "Theta" => 920, - "theta" => 920, - "THETA" => 920, - "Iota" => 921, - "iota" => 921, - "IOTA" => 921, - "Kappa" => 922, - "kappa" => 922, - "KAPPA" => 922, - "Lambda" => 923, - "lambda" => 923, - "LAMBDA" => 923, - "Mu" => 924, - "mu" => 924, - "MU" => 924, - "Nu" => 925, - "nu" => 925, - "NU" => 925, - "Xi" => 926, - "xi" => 926, - "XI" => 926, - "Omicron" => 927, - "omicron" => 927, - "OMICRON" => 927, - "Pi" => 928, - "pi" => 928, - "PI" => 928, - "Rho" => 929, - "rho" => 929, - "RHO" => 929, - "Sigma" => 931, - "sigma" => 931, - "SIGMA" => 931, - "Tau" => 932, - "tau" => 932, - "TAU" => 932, - "Upsilon" => 933, - "upsilon" => 933, - "UPSILON" => 933, - "Phi" => 934, - "phi" => 934, - "PHI" => 934, - "Chi" => 935, - "chi" => 935, - "CHI" => 935, - "Psi" => 936, - "psi" => 936, - "PSI" => 936, - "Omega" => 937, - "omega" => 937, - "OMEGA" => 937, - "sigmaf" => 962, - "SIGMAF" => 962, - "thetasym" => 977, - "THETASYM" => 977, - "upsih" => 978, - "UPSIH" => 978, - "piv" => 982, - "PIV" => 982, - "Agrave" => 192, - "agrave" => 192, - "AGRAVE" => 192, - "Aacute" => 193, - "aacute" => 193, - "AACUTE" => 193, - "Acirc" => 194, - "acirc" => 194, - "ACIRC" => 194, - "Atilde" => 195, - "atilde" => 195, - "ATILDE" => 195, - "Auml" => 196, - "auml" => 196, - "AUML" => 196, - "Aring" => 197, - "aring" => 197, - "ARING" => 197, - "AElig" => 198, - "aelig" => 198, - "AELIG" => 198, - "Ccedil" => 199, - "ccedil" => 199, - "CCEDIL" => 199, - "Egrave" => 200, - "egrave" => 200, - "EGRAVE" => 200, - "Eacute" => 201, - "eacute" => 201, - "EACUTE" => 201, - "Ecirc" => 202, - "ecirc" => 202, - "ECIRC" => 202, - "Euml" => 203, - "euml" => 203, - "EUML" => 203, - "Lgrave" => 204, - "lgrave" => 204, - "LGRAVE" => 204, - "Lacute" => 313, - "lacute" => 313, - "LACUTE" => 313, - "Lcirc" => 206, - "lcirc" => 206, - "LCIRC" => 206, - "Luml" => 207, - "luml" => 207, - "LUML" => 207, - "ETH" => 208, - "eth" => 208, - "Ntilde" => 209, - "ntilde" => 209, - "NTILDE" => 209, - "Ograve" => 210, - "ograve" => 210, - "OGRAVE" => 210, - "Oacute" => 211, - "oacute" => 211, - "OACUTE" => 211, - "Ocirc" => 212, - "ocirc" => 212, - "OCIRC" => 212, - "Otilde" => 213, - "otilde" => 213, - "OTILDE" => 213, - "Ouml" => 214, - "ouml" => 214, - "OUML" => 214, - "Oslash" => 216, - "oslash" => 216, - "OSLASH" => 216, - "Ugrave" => 217, - "ugrave" => 217, - "UGRAVE" => 217, - "Uacute" => 218, - "uacute" => 218, - "UACUTE" => 218, - "Ucirc" => 219, - "ucirc" => 219, - "UCIRC" => 219, - "Uuml" => 220, - "uuml" => 220, - "UUML" => 220, - "Yacute" => 221, - "yacute" => 221, - "YACUTE" => 221, - "THORN" => 222, - "thorn" => 222, - "szlig" => 223, - "SZLIG" => 223, - "igrave" => 236, - "IGRAVE" => 236, - "iacute" => 237, - "IACUTE" => 237, - "icirc" => 238, - "ICIRC" => 238, - "iuml" => 239, - "IUML" => 239, - "yuml" => 255, - "YUML" => 255, - "Amacr" => 256, - "amacr" => 256, - "AMACR" => 256, - "Abreve" => 258, - "abreve" => 258, - "ABREVE" => 258, - "Aogon" => 260, - "aogon" => 260, - "AOGON" => 260, - "Cacute" => 262, - "cacute" => 262, - "CACUTE" => 262, - "Ccirc" => 264, - "ccirc" => 264, - "CCIRC" => 264, - "Cdot" => 266, - "cdot" => 266, - "CDOT" => 266, - "Ccaron" => 268, - "ccaron" => 268, - "CCARON" => 268, - "Dcaron" => 270, - "dcaron" => 270, - "DCARON" => 270, - "Dstrok" => 272, - "dstrok" => 272, - "DSTROK" => 272, - "Emacr" => 274, - "emacr" => 274, - "EMACR" => 274, - "Edot" => 278, - "Eogon" => 280, - "eogon" => 280, - "EOGON" => 280, - "Ecaron" => 282, - "ecaron" => 282, - "ECARON" => 282, - "Gcirc" => 284, - "gcirc" => 284, - "GCIRC" => 284, - "Gbreve" => 286, - "gbreve" => 286, - "GBREVE" => 286, - "Gdot" => 288, - "gdot" => 288, - "GDOT" => 288, - "Gcedil" => 290, - "gcedil" => 290, - "GCEDIL" => 290, - "Hcirc" => 292, - "hcirc" => 292, - "HCIRC" => 292, - "Hstrok" => 294, - "hstrok" => 294, - "HSTROK" => 294, - "Itilde" => 296, - "itilde" => 296, - "ITILDE" => 296, - "Imacr" => 298, - "imacr" => 298, - "IMACR" => 298, - "Iogon" => 302, - "iogon" => 302, - "IOGON" => 302, - "Idot" => 304, - "idot" => 304, - "IDOT" => 304, - "imath" => 305, - "IMATH" => 305, - "IJlig" => 306, - "ijlig" => 306, - "IJLIG" => 306, - "Jcirc" => 308, - "jcirc" => 308, - "JCIRC" => 308, - "Kcedil" => 310, - "kcedil" => 310, - "KCEDIL" => 310, - "kgreen" => 312, - "KGREEN" => 312, - "Lcedil" => 315, - "lcedil" => 315, - "LCEDIL" => 315, - "Lcaron" => 317, - "lcaron" => 317, - "LCARON" => 317, - "Lmidot" => 319, - "lmidot" => 319, - "LMIDOT" => 319, - "Lstrok" => 321, - "lstrok" => 321, - "LSTROK" => 321, - "Nacute" => 323, - "nacute" => 323, - "NACUTE" => 323, - "Ncedil" => 325, - "ncedil" => 325, - "NCEDIL" => 325, - "Ncaron" => 327, - "ncaron" => 327, - "NCARON" => 327, - "napos" => 329, - "NAPOS" => 329, - "ENG" => 330, - "eng" => 330, - "Omacr" => 332, - "omacr" => 332, - "OMACR" => 332, - "Odblac" => 336, - "odblac" => 336, - "ODBLAC" => 336, - "OElig" => 338, - "oelig" => 338, - "OELIG" => 338, - "Racute" => 340, - "racute" => 340, - "RACUTE" => 340, - "Rcedil" => 342, - "rcedil" => 342, - "RCEDIL" => 342, - "Rcaron" => 344, - "rcaron" => 344, - "RCARON" => 344, - "Sacute" => 346, - "sacute" => 346, - "SACUTE" => 346, - "Scirc" => 348, - "scirc" => 348, - "SCIRC" => 348, - "Scedil" => 350, - "scedil" => 350, - "SCEDIL" => 350, - "Scaron" => 352, - "scaron" => 352, - "SCARON" => 352, - "Tcedil" => 354, - "tcedil" => 354, - "TCEDIL" => 354, - "Tcaron" => 356, - "tcaron" => 356, - "TCARON" => 356, - "Tstrok" => 358, - "tstrok" => 358, - "TSTROK" => 358, - "Utilde" => 360, - "utilde" => 360, - "UTILDE" => 360, - "Umacr" => 362, - "umacr" => 362, - "UMACR" => 362, - "Ubreve" => 364, - "ubreve" => 364, - "UBREVE" => 364, - "Uring" => 366, - "uring" => 366, - "URING" => 366, - "Udblac" => 368, - "udblac" => 368, - "UDBLAC" => 368, - "Uogon" => 370, - "uogon" => 370, - "UOGON" => 370, - "Wcirc" => 372, - "wcirc" => 372, - "WCIRC" => 372, - "Ycirc" => 374, - "ycirc" => 374, - "YCIRC" => 374, - "Yuml" => 376, - "Zacute" => 377, - "zacute" => 377, - "ZACUTE" => 377, - "Zdot" => 379, - "zdot" => 379, - "ZDOT" => 379, - "Zcaron" => 381, - "zcaron" => 381, - "ZCARON" => 381, - "DownBreve" => 785, - "downbreve" => 785, - "DOWNBREVE" => 785, - "olarr" => 8634, - "OLARR" => 8634, - "orarr" => 8635, - "ORARR" => 8635, - "lharu" => 8636, - "LHARU" => 8636, - "lhard" => 8637, - "LHARD" => 8637, - "uharr" => 8638, - "UHARR" => 8638, - "uharl" => 8639, - "UHARL" => 8639, - "rharu" => 8640, - "RHARU" => 8640, - "rhard" => 8641, - "RHARD" => 8641, - "dharr" => 8642, - "DHARR" => 8642, - "dharl" => 8643, - "DHARL" => 8643, - "rlarr" => 8644, - "RLARR" => 8644, - "udarr" => 8645, - "UDARR" => 8645, - "lrarr" => 8646, - "LRARR" => 8646, - "llarr" => 8647, - "LLARR" => 8647, - "uuarr" => 8648, - "UUARR" => 8648, - "rrarr" => 8649, - "RRARR" => 8649, - "ddarr" => 8650, - "DDARR" => 8650, - "lrhar" => 8651, - "LRHAR" => 8651, - "rlhar" => 8652, - "RLHAR" => 8652, - "nlArr" => 8653, - "nlarr" => 8653, - "NLARR" => 8653, - "nhArr" => 8654, - "nharr" => 8654, - "NHARR" => 8654, - "nrArr" => 8655, - "nrarr" => 8655, - "NRARR" => 8655, - "lArr" => 8656, - "larr" => 8656, - "LARR" => 8656, - "uArr" => 8657, - "uarr" => 8657, - "UARR" => 8657, - "rArr" => 8658, - "rarr" => 8658, - "RARR" => 8658, - "dArr" => 8659, - "darr" => 8659, - "DARR" => 8659, - "hArr" => 8660, - "harr" => 8660, - "HARR" => 8660, - "vArr" => 8661, - "varr" => 8661, - "VARR" => 8661, - "nwArr" => 8662, - "nwarr" => 8662, - "NWARR" => 8662, - "neArr" => 8663, - "nearr" => 8663, - "NEARR" => 8663, - "seArr" => 8664, - "searr" => 8664, - "SEARR" => 8664, - "swArr" => 8665, - "swarr" => 8665, - "SWARR" => 8665, - "lAarr" => 8666, - "laarr" => 8666, - "LAARR" => 8666, - "rAarr" => 8667, - "raarr" => 8667, - "RAARR" => 8667, - "ziglarr" => 8668, - "ZIGLARR" => 8668, - "zigrarr" => 8669, - "ZIGRARR" => 8669, - "larrb" => 8676, - "LARRB" => 8676, - "rarrb" => 8677, - "RARRB" => 8677, - "duarr" => 8693, - "DUARR" => 8693, - "hoarr" => 8703, - "HOARR" => 8703, - "loarr" => 8701, - "LOARR" => 8701, - "roarr" => 8702, - "ROARR" => 8702, - "xlarr" => 10229, - "XLARR" => 10229, - "xrarr" => 10230, - "XRARR" => 10230, - "xharr" => 10231, - "XHARR" => 10231, - "xlArr" => 10232, - "xrArr" => 10233, - "xhArr" => 10234, - "dzigrarr" => 10239, - "DZIGRARR" => 10239, - "xmap" => 10236, - "XMAP" => 10236, - "nvlArr" => 10498, - "nvlarr" => 10498, - "NVLARR" => 10498, - "nvrArr" => 10499, - "nvrarr" => 10499, - "NVRARR" => 10499, - "nvHarr" => 10500, - "nvharr" => 10500, - "NVHARR" => 10500, - "Map" => 10501, - "map" => 10501, - "MAP" => 10501, - "lbarr" => 10508, - "LBARR" => 10508, - "rbarr" => 10509, - "RBARR" => 10509, - "lBarr" => 10510, - "rBarr" => 10511, - "RBarr" => 10512, - "DDotrahd" => 10513, - "ddotrahd" => 10513, - "DDOTRAHD" => 10513, - "UpArrowBar" => 10514, - "uparrowbar" => 10514, - "UPARROWBAR" => 10514, - "DownArrowBar" => 10515, - "downarrowbar" => 10515, - "DOWNARROWBAR" => 10515, - "Rarrtl" => 10518, - "rarrtl" => 10518, - "RARRTL" => 10518, - "latail" => 10521, - "LATAIL" => 10521, - "ratail" => 10522, - "RATAIL" => 10522, - "lAtail" => 10523, - "rAtail" => 10524, - "larrfs" => 10525, - "LARRFS" => 10525, - "rarrfs" => 10526, - "RARRFS" => 10526, - "larrbfs" => 10527, - "LARRBFS" => 10527, - "rarrbfs" => 10528, - "RARRBFS" => 10528, - "nwarhk" => 10531, - "NWARHK" => 10531, - "nearhk" => 10532, - "NEARHK" => 10532, - "searhk" => 10533, - "SEARHK" => 10533, - "swarhk" => 10534, - "SWARHK" => 10534, - "nwnear" => 10535, - "NWNEAR" => 10535, - "nesear" => 10536, - "NESEAR" => 10536, - "seswar" => 10537, - "SESWAR" => 10537, - "swnwar" => 10538, - "SWNWAR" => 10538, - "cudarrr" => 10549, - "CUDARRR" => 10549, - "ldca" => 10550, - "LDCA" => 10550, - "rdca" => 10551, - "RDCA" => 10551, - "cudarrl" => 10552, - "CUDARRL" => 10552, - "larrpl" => 10553, - "LARRPL" => 10553, - "curarrm" => 10556, - "CURARRM" => 10556, - "cularrp" => 10557, - "CULARRP" => 10557, - "rarrpl" => 10565, - "RARRPL" => 10565, - "harrcir" => 10568, - "HARRCIR" => 10568, - "Uarrocir" => 10569, - "uarrocir" => 10569, - "UARROCIR" => 10569, - "lurdshar" => 10570, - "LURDSHAR" => 10570, - "ldrushar" => 10571, - "LDRUSHAR" => 10571, - "RightUpDownVector" => 10575, - "rightupdownvector" => 10575, - "RIGHTUPDOWNVECTOR" => 10575, - "DownLeftRightVector" => 10576, - "downleftrightvector" => 10576, - "DOWNLEFTRIGHTVECTOR" => 10576, - "LeftUpDownVector" => 10577, - "leftupdownvector" => 10577, - "LEFTUPDOWNVECTOR" => 10577, - "LeftVectorBar" => 10578, - "leftvectorbar" => 10578, - "LEFTVECTORBAR" => 10578, - "RightVectorBar" => 10579, - "rightvectorbar" => 10579, - "RIGHTVECTORBAR" => 10579, - "RightUpVectorBar" => 10580, - "rightupvectorbar" => 10580, - "RIGHTUPVECTORBAR" => 10580, - "RightDownVectorBar" => 10581, - "rightdownvectorbar" => 10581, - "RIGHTDOWNVECTORBAR" => 10581, - "DownLeftVectorBar" => 10582, - "downleftvectorbar" => 10582, - "DOWNLEFTVECTORBAR" => 10582, - "DownRightVectorBar" => 10583, - "downrightvectorbar" => 10583, - "DOWNRIGHTVECTORBAR" => 10583, - "LeftUpVectorBar" => 10584, - "leftupvectorbar" => 10584, - "LEFTUPVECTORBAR" => 10584, - "LeftDownVectorBar" => 10585, - "leftdownvectorbar" => 10585, - "LEFTDOWNVECTORBAR" => 10585, - "LeftTeeVector" => 10586, - "leftteevector" => 10586, - "LEFTTEEVECTOR" => 10586, - "RightTeeVector" => 10587, - "rightteevector" => 10587, - "RIGHTTEEVECTOR" => 10587, - "RightUpTeeVector" => 10588, - "rightupteevector" => 10588, - "RIGHTUPTEEVECTOR" => 10588, - "RightDownTeeVector" => 10589, - "rightdownteevector" => 10589, - "RIGHTDOWNTEEVECTOR" => 10589, - "DownLeftTeeVector" => 10590, - "downleftteevector" => 10590, - "DOWNLEFTTEEVECTOR" => 10590, - "DownRightTeeVector" => 10591, - "downrightteevector" => 10591, - "DOWNRIGHTTEEVECTOR" => 10591, - "LeftUpTeeVector" => 10592, - "leftupteevector" => 10592, - "LEFTUPTEEVECTOR" => 10592, - "LeftDownTeeVector" => 10593, - "leftdownteevector" => 10593, - "LEFTDOWNTEEVECTOR" => 10593, - "lHar" => 10594, - "lhar" => 10594, - "LHAR" => 10594, - "uHar" => 10595, - "uhar" => 10595, - "UHAR" => 10595, - "rHar" => 10596, - "rhar" => 10596, - "RHAR" => 10596, - "dHar" => 10597, - "dhar" => 10597, - "DHAR" => 10597, - "luruhar" => 10598, - "LURUHAR" => 10598, - "ldrdhar" => 10599, - "LDRDHAR" => 10599, - "ruluhar" => 10600, - "RULUHAR" => 10600, - "rdldhar" => 10601, - "RDLDHAR" => 10601, - "lharul" => 10602, - "LHARUL" => 10602, - "llhard" => 10603, - "LLHARD" => 10603, - "rharul" => 10604, - "RHARUL" => 10604, - "lrhard" => 10605, - "LRHARD" => 10605, - "udhar" => 10606, - "UDHAR" => 10606, - "duhar" => 10607, - "DUHAR" => 10607, - "RoundImplies" => 10608, - "roundimplies" => 10608, - "ROUNDIMPLIES" => 10608, - "erarr" => 10609, - "ERARR" => 10609, - "simrarr" => 10610, - "SIMRARR" => 10610, - "larrsim" => 10611, - "LARRSIM" => 10611, - "rarrsim" => 10612, - "RARRSIM" => 10612, - "rarrap" => 10613, - "RARRAP" => 10613, - "ltlarr" => 10614, - "LTLARR" => 10614, - "gtrarr" => 10616, - "GTRARR" => 10616, - "subrarr" => 10617, - "SUBRARR" => 10617, - "suplarr" => 10619, - "SUPLARR" => 10619, - "lfisht" => 10620, - "LFISHT" => 10620, - "rfisht" => 10621, - "RFISHT" => 10621, - "ufisht" => 10622, - "UFISHT" => 10622, - "dfisht" => 10623, - "DFISHT" => 10623, - x => { - // check if we are a bare unicode number - let x = x.as_bytes(); - if x[0] == b'#' { - if x.len() > 1 && x[1] == b'x' { - // hex - if let Ok(utf8) = std::str::from_utf8(&x[2..]) { - if let Ok(num) = i64::from_str_radix(utf8, 16) { - num as u32 - } else { - return Err("Cannot parse hex html entity".into()); - } - } else { - return Err("Cannot parse hex html entity".into()); - } - } else { - if let Ok(utf8) = std::str::from_utf8(&x[1..]) { - if let Ok(num) = utf8.parse::() { - num as u32 - } else { - return Err("Cannot parse digit html entity".into()); - } - } else { - return Err("Cannot parse digit html entity".into()); - } - } - } else { - return Err("unknown html entity".into()); - } - } - }) -} diff --git a/vendor/makepad/libs/live_id/Cargo.toml b/vendor/makepad/libs/live_id/Cargo.toml deleted file mode 100644 index c0d521f..0000000 --- a/vendor/makepad/libs/live_id/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "makepad-live-id" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad live id symbol interning" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "Fjf_rJTOgvZXwyU7Yb-CZMF6Hmo=" - -[dependencies] -makepad-live-id-macros = { path = "id_macros", version = "1.0.0" } -#makepad-error-log = { path = "../error_log", version = "0.4.0" } - -serde = { version = "1.0", optional = true, features = ["derive"] } - -[features] -default = [] -## Enables certain public-facing types to derive serde serialization traits. -serde = ["dep:serde"] diff --git a/vendor/makepad/libs/live_id/id_macros/Cargo.toml b/vendor/makepad/libs/live_id/id_macros/Cargo.toml deleted file mode 100644 index bb00334..0000000 --- a/vendor/makepad/libs/live_id/id_macros/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "makepad-live-id-macros" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad live id macros" -license = "MIT OR Apache-2.0" -metadata.makepad-auto-version = "lDtmHNCpwGDsVSuDhZxGSPFB0_0=" - -[lib] -proc-macro = true - -[dependencies] -makepad-micro-proc-macro = { path = "../../micro_proc_macro", version = "1.0.0" } - - diff --git a/vendor/makepad/libs/live_id/id_macros/src/derive_from_live_id.rs b/vendor/makepad/libs/live_id/id_macros/src/derive_from_live_id.rs deleted file mode 100644 index f487b88..0000000 --- a/vendor/makepad/libs/live_id/id_macros/src/derive_from_live_id.rs +++ /dev/null @@ -1,43 +0,0 @@ -use proc_macro::TokenStream; - -use makepad_micro_proc_macro::{TokenBuilder, TokenParser}; - -pub fn derive_from_live_id_impl(input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let mut parser = TokenParser::new(input); - let _main_attribs = parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(struct_name) = parser.eat_any_ident() { - tb.add("impl"); - tb.add("From for").ident(&struct_name).add("{"); - tb.add(" fn from(live_id:LiveId)->") - .ident(&struct_name) - .add("{") - .ident(&struct_name) - .add("(live_id)}"); - tb.add("}"); - - tb.add("impl"); - tb.add("From<&[LiveId;1]> for").ident(&struct_name).add("{"); - tb.add(" fn from(live_id:&[LiveId;1])->") - .ident(&struct_name) - .add("{") - .ident(&struct_name) - .add("(live_id[0])}"); - tb.add("}"); - - tb.add("impl"); - tb.add("From for").ident(&struct_name).add("{"); - tb.add(" fn from(live_id:u64)->") - .ident(&struct_name) - .add("{") - .ident(&struct_name) - .add("(LiveId(live_id))}"); - tb.add("}"); - - return tb.end(); - } - } - parser.unexpected() -} diff --git a/vendor/makepad/libs/live_id/id_macros/src/lib.rs b/vendor/makepad/libs/live_id/id_macros/src/lib.rs deleted file mode 100644 index fda6845..0000000 --- a/vendor/makepad/libs/live_id/id_macros/src/lib.rs +++ /dev/null @@ -1,174 +0,0 @@ -use proc_macro::TokenStream; - -use makepad_micro_proc_macro::{error, LiveId, TokenBuilder, TokenParser}; - -mod derive_from_live_id; -use crate::derive_from_live_id::*; - -fn parse_ident(parser: &mut TokenParser) -> Result { - parser.expect_any_ident() -} - -fn eat_ident(parser: &mut TokenParser) -> Option { - parser.eat_any_ident() -} - -fn parse_single_token(item: TokenStream) -> String { - let s = item.to_string(); - s.replace(' ', "") -} - -#[proc_macro] -pub fn live_id(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let v = parse_single_token(item); - let id = LiveId::from_str(&v); - tb.add("LiveId (").suf_u64(id.0).add(")"); - tb.end() -} - -#[proc_macro] -pub fn some_id(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let v = parse_single_token(item); - let id = LiveId::from_str(&v); - tb.add("Some(LiveId (").suf_u64(id.0).add("))"); - tb.end() -} - -#[proc_macro] -pub fn id(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let v = parse_single_token(item); - if !v.is_empty() { - let id = LiveId::from_str(&v); - tb.add("LiveId (").suf_u64(id.0).add(")"); - } else { - tb.add("LiveId (0)"); - } - tb.end() -} - -#[proc_macro] -pub fn ids(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let mut parser = TokenParser::new(item); - fn parse(parser: &mut TokenParser, tb: &mut TokenBuilder) -> Result<(), TokenStream> { - tb.add("&["); - loop { - // if its a {} insert it as code - if parser.open_paren() { - tb.stream(Some(parser.eat_level())); - tb.add(","); - } else { - let ident = parse_ident(parser)?; - let id = LiveId::from_str(&ident); - tb.add("LiveId (").suf_u64(id.0).add("),"); - } - - if parser.eat_eot() { - tb.add("]"); - return Ok(()); - } - parser.expect_punct_any('.')? - } - } - if let Err(e) = parse(&mut parser, &mut tb) { - return e; - }; - tb.end() -} - -fn ids_array_impl(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let mut parser = TokenParser::new(item); - fn parse(parser: &mut TokenParser, tb: &mut TokenBuilder) -> Result<(), TokenStream> { - tb.add("&["); - 'outer: loop { - tb.add("&["); - loop { - let ident = parse_ident(parser)?; - let id = LiveId::from_str(&ident); - tb.add("LiveId (").suf_u64(id.0).add("),"); - if parser.eat_eot() { - tb.add("]"); - break 'outer; - } - if parser.eat_punct_alone(',') { - tb.add("]"); - break; - } - parser.expect_punct_any('.')? - } - tb.add(","); - if parser.eat_eot() { - break; - } - } - tb.add("]"); - Ok(()) - } - if let Err(e) = parse(&mut parser, &mut tb) { - return e; - }; - tb.end() -} - -#[proc_macro] -pub fn ids_array(item: TokenStream) -> TokenStream { - ids_array_impl(item) -} - -#[proc_macro] -pub fn ids_list(item: TokenStream) -> TokenStream { - ids_array_impl(item) -} - -// absolutely a very bad idea but lets see if we can do this. -#[proc_macro] -pub fn live_id_num(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - - let mut parser = TokenParser::new(item); - if let Some(name) = eat_ident(&mut parser) { - if !parser.eat_punct_alone(',') { - return error("please add a number"); - } - // then eat the next bit - let arg = parser.eat_level(); - let id = LiveId::from_str(&name); - tb.add("LiveId::from_num(") - .suf_u64(id.0) - .add(",") - .stream(Some(arg)) - .add(")"); - tb.end() - } else { - parser.unexpected() - } -} - -#[proc_macro] -pub fn id_lut(item: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - - let mut parser = TokenParser::new(item); - if let Some(name) = eat_ident(&mut parser) { - tb.add("LiveId::from_str_with_lut(") - .string(&name) - .add(").unwrap()"); - tb.end() - } else if let Some(punct) = parser.eat_any_punct() { - tb.add("LiveId::from_str_with_lut(") - .string(&punct) - .add(").unwrap()"); - tb.end() - } else { - parser.unexpected() - } -} - -#[proc_macro_derive(FromLiveId)] -pub fn derive_from_live_id(input: TokenStream) -> TokenStream { - derive_from_live_id_impl(input) -} diff --git a/vendor/makepad/libs/live_id/src/lib.rs b/vendor/makepad/libs/live_id/src/lib.rs deleted file mode 100644 index 1a9c84d..0000000 --- a/vendor/makepad/libs/live_id/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub use makepad_live_id_macros; -pub use makepad_live_id_macros::*; -//pub use makepad_error_log; - -pub mod live_id; -pub use live_id::*; diff --git a/vendor/makepad/libs/live_id/src/live_id.rs b/vendor/makepad/libs/live_id/src/live_id.rs deleted file mode 100644 index febbbc6..0000000 --- a/vendor/makepad/libs/live_id/src/live_id.rs +++ /dev/null @@ -1,461 +0,0 @@ -#![allow(dead_code)] - -use std::{ - collections::HashMap, - fmt, - ops::{Deref, DerefMut, Index, IndexMut}, - sync::atomic::{AtomicU64, Ordering}, - sync::Mutex, - sync::Once, -}; - -impl LiveIdInterner { - pub fn add(&mut self, val: &str) { - self.id_to_string - .insert(LiveId::from_str(val), val.to_string()); - } - - pub fn contains(&mut self, val: &str) -> bool { - self.id_to_string.contains_key(&LiveId::from_str(val)) - } - - pub fn with(f: F) -> R - where - F: FnOnce(&mut Self) -> R, - { - static IDMAP: Mutex> = Mutex::new(None); - static ONCE: Once = Once::new(); - ONCE.call_once(|| { - let mut map = LiveIdInterner { - //alloc: 0, - id_to_string: HashMap::new(), - }; - // pre-seed list for debugging purposes - let fill = [ - "buffer", "this", "native", "vec2", "assert", "Range", "start", "end", "sin", "ty", - "step", "import", "retain", "extend", "push", "pop", "number", "nan", "bool", - "nil", "color", "string", "object", "factory", "opcode", "mod", "global", "scope", - "fn", "id", "default", "true", "false", "exp", "void", "use", "#", "$", "@", "^", - "^=", "|", "||", "|=", "%", "%=", "!=", "!", "&&", "*=", "*", "+=", "+", ",", "-=", - "->", "-", "..", "...", "..=", ".", "/=", "/", "::", ":", ":=", ";", "<=", "<", - "<<", "<<=", "==", "=", ">=", "=>", ">", ">>", ">>=", "?", "tracks", "state", - "state_id", "user", "play", "ended", "geom_pos", "geom_id", "geom_uv", - ]; - for item in &fill { - if map.contains(item) { - eprintln!("WE HAVE AN ID COLLISION!"); - } - map.add(item); - } - *IDMAP.lock().unwrap() = Some(map) - }); - let mut idmap = IDMAP.lock().unwrap(); - f(idmap.as_mut().unwrap()) - } -} - -#[derive(Clone, Default, Eq, Hash, Copy, Ord, PartialOrd, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct LiveId(pub u64); - -impl LiveId { - pub const SEED: u64 = 0xd6e8_feb8_6659_fd93; - - pub fn empty() -> Self { - Self(0) - } - pub fn from_lo_hi(lo: u32, hi: u32) -> Self { - Self((lo as u64) | ((hi as u64) << 32)) - } - pub fn lo(&self) -> u32 { - (self.0 & 0xffff_ffff) as u32 - } - pub fn hi(&self) -> u32 { - (self.0 >> 32) as u32 - } - - pub fn seeded() -> Self { - Self(Self::SEED) - } - /* - pub fn is_unique(&self) -> bool { - (self.0 & 0x8000_0000_0000_0000) == 0 && self.0 != 0 - } - - pub fn is_ident(&self) -> bool { - (self.0 & 0x8000_0000_0000_0000) != 0 - }*/ - - pub fn is_empty(&self) -> bool { - self.0 == 0 - } - - pub fn get_value(&self) -> u64 { - self.0 - } - - // from https://nullprogram.com/blog/2018/07/31/ - // i have no idea what im doing with start value and finalisation. - pub const fn from_bytes(seed: u64, id_bytes: &[u8], start: usize, end: usize, or: u64) -> Self { - let mut x = seed; - let mut i = start; - while i < end { - x = x.overflowing_add(id_bytes[i] as u64).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - i += 1; - } - Self((x & 0x0000_3fff_ffff_ffff) | or) - } - - pub fn add(&self, what: u64) -> Self { - Self(self.0 + what) - } - - pub fn xor(&self, what: u64) -> Self { - Self((self.0 ^ what) | 0x8000_0000_0000_0000) - } - - pub fn sub(&self, what: u64) -> Self { - Self(self.0 - what) - } - - pub const fn from_str(id_str: &str) -> Self { - let bytes = id_str.as_bytes(); - Self::from_bytes(Self::SEED, bytes, 0, bytes.len(), 0) - } - - pub const fn from_bytes_lc( - seed: u64, - id_bytes: &[u8], - start: usize, - end: usize, - or: u64, - ) -> Self { - let mut x = seed; - let mut i = start; - while i < end { - let byte = id_bytes[i]; - let byte = if byte >= 65 && byte <= 90 { - byte + 32 - } else { - byte - }; - x = x.overflowing_add(byte as u64).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - i += 1; - } - // mark high bit as meaning that this is a hash id - Self((x & 0x0000_3fff_ffff_ffff) | or) - } - - pub const fn from_str_lc(id_str: &str) -> Self { - let bytes = id_str.as_bytes(); - Self::from_bytes_lc(Self::SEED, bytes, 0, bytes.len(), 0) - } - - pub const fn str_append(self, id_str: &str) -> Self { - let bytes = id_str.as_bytes(); - Self::from_bytes(self.0, bytes, 0, bytes.len(), 0) - } - - pub const fn bytes_append(self, bytes: &[u8]) -> Self { - Self::from_bytes(self.0, bytes, 0, bytes.len(), 0) - } - - pub const fn id_append(self, id: LiveId) -> Self { - let bytes = id.0.to_be_bytes(); - Self::from_bytes(self.0, &bytes, 0, bytes.len(), 0) - } - - pub const fn from_str_num(id_str: &str, num: u64) -> Self { - let bytes = id_str.as_bytes(); - let id = Self::from_bytes(Self::SEED, bytes, 0, bytes.len(), 0); - Self::from_bytes(id.0, &num.to_be_bytes(), 0, 8, 0) - } - - pub const fn from_num(seed: u64, num: u64) -> Self { - Self::from_bytes(seed, &num.to_be_bytes(), 0, 8, 0) - } - - pub fn from_str_with_lut(id_str: &str) -> Result { - let id = Self::from_str(id_str); - LiveIdInterner::with(|idmap| { - if let Some(stored) = idmap.id_to_string.get(&id) { - if stored != id_str { - return Err(stored.clone()); - } - } else { - idmap.id_to_string.insert(id, id_str.to_string()); - } - Ok(id) - }) - } - - pub fn from_str_with_intern(id_str: &str, intern: InternLiveId) -> Self { - let id = Self::from_str(id_str); - if let InternLiveId::Yes = intern { - LiveIdInterner::with(|idmap| idmap.id_to_string.insert(id, id_str.to_string())); - } - id - } - - pub fn from_str_num_with_lut(id_str: &str, num: u64) -> Result { - let id = Self::from_str_num(id_str, num); - LiveIdInterner::with(|idmap| { - idmap.id_to_string.insert(id, format!("{}{}", id_str, num)); - Ok(id) - }) - } - - pub fn as_string(&self, f: F) -> R - where - F: FnOnce(Option<&str>) -> R, - { - LiveIdInterner::with(|idmap| match idmap.id_to_string.get(self) { - Some(v) => f(Some(v)), - None => f(None), - }) - } - - pub fn not_empty(&self) -> bool { - self.0 != 0 - } - - pub fn unique() -> Self { - LiveId(UNIQUE_LIVE_ID.fetch_add(1, Ordering::SeqCst)) - } -} - -#[derive(Clone, Copy)] -pub enum InternLiveId { - Yes, - No, -} - -pub(crate) static UNIQUE_LIVE_ID: AtomicU64 = AtomicU64::new(1); -/* -impl Ord for LiveId { - fn cmp(&self, other: &LiveId) -> cmp::Ordering { - LiveIdInterner::with( | idmap | { - if let Some(id1) = idmap.id_to_string.get(self) { - if let Some(id2) = idmap.id_to_string.get(other) { - return id1.cmp(id2) - } - } - cmp::Ordering::Equal - }) - } -} - -impl PartialOrd for LiveId { - fn partial_cmp(&self, other: &LiveId) -> Option { - Some(self.cmp(other)) - } -}*/ - -impl fmt::Debug for LiveId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for LiveId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if *self == LiveId::empty() { - write!(f, "0") - } - //else if self.is_unique(){ - // write!(f, "UniqueId {}", self.0) - //} - else { - self.as_string(|string| { - if let Some(id) = string { - write!(f, "{}", id) - } else { - write!(f, "{:016x}", self.0) - } - }) - } - } -} - -impl fmt::LowerHex for LiveId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -pub struct LiveIdInterner { - //alloc: u64, - id_to_string: HashMap, -} - -// ---------------------------------------------------------------------------- - -// Idea taken from the `nohash_hasher` crate. -#[derive(Default)] -pub struct LiveIdHasher(u64); - -impl std::hash::Hasher for LiveIdHasher { - fn write(&mut self, _: &[u8]) { - unreachable!("Invalid use of IdHasher"); - } - - fn write_u8(&mut self, _n: u8) { - unreachable!("Invalid use of IdHasher"); - } - fn write_u16(&mut self, _n: u16) { - unreachable!("Invalid use of IdHasher"); - } - fn write_u32(&mut self, _n: u32) { - unreachable!("Invalid use of IdHasher"); - } - - #[inline(always)] - fn write_u64(&mut self, n: u64) { - self.0 = n; - } - - fn write_usize(&mut self, _n: usize) { - unreachable!("Invalid use of IdHasher"); - } - - fn write_i8(&mut self, _n: i8) { - unreachable!("Invalid use of IdHasher"); - } - fn write_i16(&mut self, _n: i16) { - unreachable!("Invalid use of IdHasher"); - } - fn write_i32(&mut self, _n: i32) { - unreachable!("Invalid use of IdHasher"); - } - fn write_i64(&mut self, _n: i64) { - unreachable!("Invalid use of IdHasher"); - } - fn write_isize(&mut self, _n: isize) { - unreachable!("Invalid use of IdHasher"); - } - - #[inline(always)] - fn finish(&self) -> u64 { - self.0 - } -} - -#[derive(Copy, Clone, Default)] -pub struct LiveIdHasherBuilder {} - -impl std::hash::BuildHasher for LiveIdHasherBuilder { - type Hasher = LiveIdHasher; - - #[inline(always)] - fn build_hasher(&self) -> LiveIdHasher { - LiveIdHasher::default() - } -} - -#[derive(Clone, Debug)] -pub struct LiveIdMap { - map: HashMap, - //alloc_set: HashSet -} - -impl Default for LiveIdMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From + std::fmt::Debug, -{ - fn default() -> Self { - Self { - map: HashMap::with_hasher(LiveIdHasherBuilder {}), - //alloc_set: HashSet::with_hasher(LiveIdHasherBuilder {}) - } - } -} -/* -impl LiveIdMap -where K: std::cmp::Eq + std::hash::Hash + Copy + From + std::fmt::Debug -{ - pub fn new() -> Self {Self::default()} - - pub fn alloc_key(&mut self) -> K { - loop { - let new_id = LiveId::unique().into(); - if self.map.get(&new_id).is_none() && !self.alloc_set.contains(&new_id) { - self.alloc_set.insert(new_id); - return new_id - } - } - } - - pub fn insert_unique(&mut self, value: V) -> K { - loop { - let new_id = LiveId::unique().into(); - if self.alloc_set.contains(&new_id) { - continue - } - match self.map.entry(new_id) { - Entry::Occupied(_) => continue, - Entry::Vacant(v) => { - - v.insert(value); - return new_id - } - } - } - } - - pub fn insert(&mut self, k: impl Into, value: V) { - let k = k.into(); - self.alloc_set.remove(&k); - match self.map.entry(k) { - Entry::Occupied(_) => panic!("Item {:?} already inserted",k), - Entry::Vacant(v) => v.insert(value) - }; - } -} -*/ -impl Deref for LiveIdMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - type Target = HashMap; - fn deref(&self) -> &Self::Target { - &self.map - } -} - -impl DerefMut for LiveIdMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.map - } -} - -impl Index for LiveIdMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - type Output = V; - fn index(&self, index: K) -> &Self::Output { - self.map.get(&index).unwrap() - } -} - -impl IndexMut for LiveIdMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - fn index_mut(&mut self, index: K) -> &mut Self::Output { - self.map.get_mut(&index).unwrap() - } -} diff --git a/vendor/makepad/libs/math/Cargo.toml b/vendor/makepad/libs/math/Cargo.toml deleted file mode 100644 index f9dbfaa..0000000 --- a/vendor/makepad/libs/math/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "makepad-math" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad math functions" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "C4VIsC4byWBjPFWeuGD2ZHHSRRs=" - -[features] -[dependencies] -makepad-micro-serde = { path = "../../libs/micro_serde", version = "1.0.0" } diff --git a/vendor/makepad/libs/math/src/complex.rs b/vendor/makepad/libs/math/src/complex.rs deleted file mode 100644 index a53d0e1..0000000 --- a/vendor/makepad/libs/math/src/complex.rs +++ /dev/null @@ -1,127 +0,0 @@ -// very basic complex types just enough to write an fft below - -#[derive(Clone, Copy)] -pub struct ComplexF32 { - pub re: f32, - pub im: f32, -} - -#[derive(Clone, Copy)] -pub struct ComplexF64 { - pub re: f64, - pub im: f64, -} - -impl ComplexF32 { - pub fn magnitude(self) -> f32 { - (self.re * self.re + self.im * self.im).sqrt() - } -} - -pub const fn cf64(re: f64, im: f64) -> ComplexF64 { - ComplexF64 { re, im } -} -pub const fn cf32(re: f32, im: f32) -> ComplexF32 { - ComplexF32 { re, im } -} - -impl From for ComplexF64 { - fn from(v: ComplexF32) -> Self { - cf64(v.re as f64, v.im as f64) - } -} - -impl From for ComplexF32 { - fn from(v: ComplexF64) -> Self { - cf32(v.re as f32, v.im as f32) - } -} - -impl std::ops::Mul for ComplexF64 { - type Output = ComplexF64; - fn mul(self, rhs: ComplexF64) -> ComplexF64 { - cf64( - self.re * rhs.re - self.im * rhs.im, - self.re * rhs.im + self.im * rhs.re, - ) - } -} - -impl std::ops::Add for ComplexF64 { - type Output = ComplexF64; - fn add(self, rhs: ComplexF64) -> ComplexF64 { - cf64(self.re + rhs.re, self.im + rhs.im) - } -} - -impl std::ops::Sub for ComplexF64 { - type Output = ComplexF64; - fn sub(self, rhs: ComplexF64) -> ComplexF64 { - cf64(self.re - rhs.re, self.im - rhs.im) - } -} - -// FFT algo, ported from https://github.com/rshuston/FFT-C/ rewritten with a few Rust types. - -fn fft_f32_recursive_pow2_inner( - data: &mut [ComplexF32], - scratch: &mut [ComplexF32], - n: usize, - theta_pi: f64, - stride: usize, -) { - if stride < n { - let stride2 = stride * 2; - fft_f32_recursive_pow2_inner(scratch, data, n, theta_pi, stride2); - fft_f32_recursive_pow2_inner( - &mut scratch[stride..], - &mut data[stride..], - n, - theta_pi, - stride2, - ); - - let theta = (stride2 as f64 * theta_pi) / n as f64; - let wn = cf64(theta.cos(), theta.sin()); - let mut wnk = cf64(1.0, 0.0); - - for k in (0..n).step_by(stride2) { - let kd2 = k >> 1; - let kpnd2 = (k + n) >> 1; - - let u: ComplexF64 = scratch[k].into(); - let t: ComplexF64 = wnk * scratch[k + stride].into(); - - data[kd2] = (u + t).into(); - data[kpnd2] = (u - t).into(); - - wnk = wnk * wn; - } - } -} - -use std::f64::consts::PI; - -pub fn fft_f32_recursive_pow2_forward(data: &mut [ComplexF32], scratch: &mut [ComplexF32]) { - fft_f32_recursive_pow2(data, scratch, -PI) -} - -pub fn fft_f32_recursive_pow2_inverse(data: &mut [ComplexF32], scratch: &mut [ComplexF32]) { - fft_f32_recursive_pow2(data, scratch, PI) -} - -fn fft_f32_recursive_pow2(data: &mut [ComplexF32], scratch: &mut [ComplexF32], theta_pi: f64) { - let n = data.len(); - if data.len() != scratch.len() { - panic!() - } - fn is_power_of_2(n: usize) -> bool { - n != 0 && (!(n & (n - 1))) != 0 - } - if !is_power_of_2(n) { - // check power of two - panic!("fft data length must be power of 2"); - }; - scratch.copy_from_slice(data); - fft_f32_recursive_pow2_inner(data, scratch, n, theta_pi, 1); -} diff --git a/vendor/makepad/libs/math/src/geometry.rs b/vendor/makepad/libs/math/src/geometry.rs deleted file mode 100644 index c6552c8..0000000 --- a/vendor/makepad/libs/math/src/geometry.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[derive(Clone, Debug)] -pub struct DecodedPrimitive { - pub positions: Vec<[f32; 3]>, - pub normals: Option>, - pub tangents: Option>, - pub texcoords0: Option>, - pub indices: Vec, - pub material: Option, -} diff --git a/vendor/makepad/libs/math/src/lib.rs b/vendor/makepad/libs/math/src/lib.rs deleted file mode 100644 index 61783eb..0000000 --- a/vendor/makepad/libs/math/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub mod complex; -mod geometry; -pub mod math_f32; -pub mod math_f64; -pub mod math_usize; -pub mod shader; -pub mod shader_runtime; - -pub use geometry::*; -pub use makepad_micro_serde; -pub use math_f32::*; -pub use math_f64::*; -pub use math_usize::*; -pub use shader::*; -pub use shader_runtime::*; diff --git a/vendor/makepad/libs/math/src/math_f32.rs b/vendor/makepad/libs/math/src/math_f32.rs deleted file mode 100644 index 07f017b..0000000 --- a/vendor/makepad/libs/math/src/math_f32.rs +++ /dev/null @@ -1,2248 +0,0 @@ -use { - crate::math_f64::*, - makepad_micro_serde::*, - // crate::colorhex::* - std::{fmt, ops}, -}; - -// backwards compatibility -pub type Vec2 = Vec2f; -pub type Vec3 = Vec3f; -pub type Vec4 = Vec4f; -pub const fn vec2(x: f32, y: f32) -> Vec2f { - Vec2f { x, y } -} -pub const fn vec3(x: f32, y: f32, z: f32) -> Vec3f { - Vec3f { x, y, z } -} -pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4f { - Vec4f { x, y, z, w } -} - -pub struct PrettyPrintedF32(pub f32); - -impl fmt::Display for PrettyPrintedF32 { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.0.abs().fract() < 0.00000001 { - write!(f, "{}.0", self.0) - } else { - write!(f, "{}", self.0) - } - } -} - -pub const VF00: Vec4f = Vec4f { - x: 1.0, - y: 0.0, - z: 0.0, - w: 1.0, -}; -pub const V0F0: Vec4f = Vec4f { - x: 0.0, - y: 1.0, - z: 0.0, - w: 1.0, -}; -pub const V00F: Vec4f = Vec4f { - x: 0.0, - y: 0.0, - z: 1.0, - w: 1.0, -}; - -#[derive(Clone, Copy, PartialEq, Debug)] -#[repr(C)] -pub struct Mat4f { - pub v: [f32; 16], -} - -impl Default for Mat4f { - fn default() -> Self { - Self { - v: [ - 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., - ], - } - } -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Vec2Index { - X, - Y, -} - -#[repr(C)] -#[derive(Clone, Copy, Default, PartialEq, Debug, SerBin, DeBin)] -pub struct Pose { - pub orientation: Quat, - pub position: Vec3f, -} - -impl Pose { - pub fn new(orientation: Quat, position: Vec3f) -> Self { - Self { - orientation, - position, - } - } - - pub fn transform_vec3(&self, v: &Vec3f) -> Vec3f { - let r0 = self.orientation.rotate_vec3(v); - r0 + self.position - } - pub fn multiply(a: &Pose, b: &Pose) -> Self { - Self { - orientation: Quat::multiply(&b.orientation, &a.orientation), - position: a.transform_vec3(&b.position), - } - } - pub fn invert(&self) -> Self { - let orientation = self.orientation.invert(); - let neg_pos = self.position.scale(-1.0); - Self { - orientation, - position: orientation.rotate_vec3(&neg_pos), - } - } - - pub fn to_mat4(&self) -> Mat4f { - let q = self.orientation; - let t = self.position; /* - Mat4f {v: [ - (1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z), - (2.0 * q.x * q.y - 2.0 * q.z * q.w), - (2.0 * q.x * q.z + 2.0 * q.y * q.w), - t.x, - (2.0 * q.x * q.y + 2.0 * q.z * q.w), - (1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z), - (2.0 * q.y * q.z - 2.0 * q.x * q.w), - t.y, - (2.0 * q.x * q.z - 2.0 * q.y * q.w), - (2.0 * q.y * q.z + 2.0 * q.x * q.w), - (1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y), - t.z, - 0.0, - 0.0, - 0.0, - 1.0 - ]}*/ - Mat4f { - v: [ - (1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z), - (2.0 * q.x * q.y + 2.0 * q.z * q.w), - (2.0 * q.x * q.z - 2.0 * q.y * q.w), - 0.0, - (2.0 * q.x * q.y - 2.0 * q.z * q.w), - (1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z), - (2.0 * q.y * q.z + 2.0 * q.x * q.w), - 0.0, - (2.0 * q.x * q.z + 2.0 * q.y * q.w), - (2.0 * q.y * q.z - 2.0 * q.x * q.w), - (1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y), - 0.0, - t.x, - t.y, - t.z, - 1.0, - ], - } - } - - pub fn from_lerp(a: Pose, b: Pose, f: f32) -> Self { - Pose { - orientation: Quat::from_slerp(a.orientation, b.orientation, f), - position: Vec3f::from_lerp(a.position, b.position, f), - } - } - - pub fn from_slerp_orientation(a: Pose, b: Pose, f: f32) -> Self { - Pose { - orientation: Quat::from_slerp(a.orientation, b.orientation, f), - position: b.position, - } - } - - pub fn is_finite(&self) -> bool { - self.orientation.is_finite() && self.position.is_finite() - } -} - -#[repr(C)] -#[derive(Clone, Copy, Default, Debug, PartialEq, SerBin, DeBin)] -pub struct Vec2f { - pub x: f32, - pub y: f32, -} - -impl Vec2f { - pub fn new() -> Vec2f { - Vec2f::default() - } - - pub fn index(&self, index: Vec2Index) -> f32 { - match index { - Vec2Index::X => self.x, - Vec2Index::Y => self.y, - } - } - - pub fn set_index(&mut self, index: Vec2Index, v: f32) { - match index { - Vec2Index::X => self.x = v, - Vec2Index::Y => self.y = v, - } - } - - pub fn from_index_pair(index: Vec2Index, a: f32, b: f32) -> Self { - match index { - Vec2Index::X => Self { x: a, y: b }, - Vec2Index::Y => Self { x: b, y: a }, - } - } - - pub fn into_vec2d(self) -> Vec2d { - Vec2d { - x: self.x as f64, - y: self.y as f64, - } - } - - pub fn all(x: f32) -> Vec2f { - Vec2f { x, y: x } - } - - pub fn from_lerp(a: Vec2f, b: Vec2f, f: f32) -> Vec2f { - let nf = 1.0 - f; - Vec2f { - x: nf * a.x + f * b.x, - y: nf * a.y + f * b.y, - } - } - - pub fn distance(&self, other: &Vec2f) -> f32 { - let dx = self.x - other.x; - let dy = self.y - other.y; - (dx * dx + dy * dy).sqrt() - } - - pub fn angle_in_radians(&self) -> f32 { - self.y.atan2(self.x) - } - - pub fn angle_in_degrees(&self) -> f32 { - self.y.atan2(self.x) * (360.0 / (2. * std::f32::consts::PI)) - } - - pub fn length(&self) -> f32 { - (self.x * self.x + self.y * self.y).sqrt() - } - - pub fn lengthsquared(&self) -> f32 { - self.x * self.x + self.y * self.y - } - pub fn normalize(&self) -> Vec2f { - let l = self.length(); - if l == 0.0 { - return vec2(0., 0.); - } - return vec2(self.x / l, self.y / l); - } - pub fn normalize_to_x(&self) -> Vec2f { - let l = self.x; - if l == 0.0 { - return vec2(1., 0.); - } - return vec2(1., self.y / l); - } - - pub fn normalize_to_y(&self) -> Vec2f { - let l = self.y; - if l == 0.0 { - return vec2(1., 0.); - } - return vec2(self.x / l, 1.); - } - pub fn to_vec3f(&self) -> Vec3f { - Vec3f { - x: self.x, - y: self.y, - z: 0.0, - } - } -} - -impl fmt::Display for Vec2f { - // This trait requires `fmt` with this exact signature. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "vec2f({},{})", self.x, self.y) - } -} - -impl fmt::Display for Vec3f { - // This trait requires `fmt` with this exact signature. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "vec3f({},{},{})", self.x, self.y, self.z) - } -} - -pub const fn vec2f(x: f32, y: f32) -> Vec2f { - Vec2f { x, y } -} -pub const fn vec3f(x: f32, y: f32, z: f32) -> Vec3f { - Vec3f { x, y, z } -} -pub const fn vec4f(x: f32, y: f32, z: f32, w: f32) -> Vec4f { - Vec4f { x, y, z, w } -} - -const TORAD: f32 = 0.017453292; -const TODEG: f32 = 57.29578; - -#[repr(C)] -#[derive(Clone, Copy, Default, PartialEq, Debug, SerBin, DeBin)] -pub struct Vec3f { - pub x: f32, - pub y: f32, - pub z: f32, -} - -impl Vec3f { - pub fn from_lerp(a: Vec3f, b: Vec3f, f: f32) -> Vec3f { - Vec3f { - x: (b.x - a.x) * f + a.x, - y: (b.y - a.y) * f + a.y, - z: (b.z - a.z) * f + a.z, - } - } - - pub fn zero(&mut self) { - self.x = 0.0; - self.y = 0.0; - self.z = 0.0; - } - - pub const fn all(x: f32) -> Vec3f { - Vec3f { x, y: x, z: x } - } - - pub const fn to_vec2(&self) -> Vec2f { - Vec2f { - x: self.x, - y: self.y, - } - } - - pub const fn to_vec4(&self) -> Vec4f { - Vec4f { - x: self.x, - y: self.y, - z: self.z, - w: 1.0, - } - } - - pub fn scale(&self, f: f32) -> Vec3f { - Vec3f { - x: self.x * f, - y: self.y * f, - z: self.z * f, - } - } - - pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f { - Vec3f { - x: a.y * b.z - a.z * b.y, - y: a.z * b.x - a.x * b.z, - z: a.x * b.y - a.y * b.x, - } - } - - pub fn dot(&self, other: Vec3f) -> f32 { - self.x * other.x + self.y * other.y + self.z * other.z - } - - pub fn normalize(&self) -> Vec3f { - let sz = self.x * self.x + self.y * self.y + self.z * self.z; - if sz > 0.0 { - let sr = 1.0 / sz.sqrt(); - return Vec3f { - x: self.x * sr, - y: self.y * sr, - z: self.z * sr, - }; - } - Vec3f::default() - } - - pub fn length(&self) -> f32 { - let sz = self.x * self.x + self.y * self.y + self.z * self.z; - sz.sqrt() - } - - pub fn length_squared(&self) -> f32 { - self.x * self.x + self.y * self.y + self.z * self.z - } - - pub fn abs(&self) -> Vec3f { - Vec3f { - x: self.x.abs(), - y: self.y.abs(), - z: self.z.abs(), - } - } - - pub fn min_elem(&self) -> f32 { - self.x.min(self.y).min(self.z) - } - - pub fn max_elem(&self) -> f32 { - self.x.max(self.y).max(self.z) - } - - pub fn min_componentwise(a: Vec3f, b: Vec3f) -> Vec3f { - Vec3f { - x: a.x.min(b.x), - y: a.y.min(b.y), - z: a.z.min(b.z), - } - } - - pub fn max_componentwise(a: Vec3f, b: Vec3f) -> Vec3f { - Vec3f { - x: a.x.max(b.x), - y: a.y.max(b.y), - z: a.z.max(b.z), - } - } - - pub fn is_finite(&self) -> bool { - self.x.is_finite() && self.y.is_finite() && self.z.is_finite() - } -} - -/* -pub fn vec3(x:f32, y:f32, z:f32)->Vec3f{ - Vec3f{x:x, y:y, z:z} -}*/ - -// equation ax + by + cz + d = 0 -#[derive(Clone, Copy, Default, Debug, PartialEq)] -pub struct Plane { - pub a: f32, - pub b: f32, - pub c: f32, - pub d: f32, -} - -impl Plane { - pub fn from_point_normal(p: Vec3f, normal: Vec3f) -> Self { - let n = normal.normalize(); - Self { - a: n.x, - b: n.y, - c: n.z, - d: -p.dot(n), - } - } - - pub fn from_points(p1: Vec3f, p2: Vec3f, p3: Vec3f) -> Self { - let normal = Vec3f::cross(p2 - p1, p3 - p1); - Self::from_point_normal(p1, normal) - } - - pub fn intersect_line(&self, v1: Vec3f, v2: Vec3f) -> Vec3f { - let diff = v1 - v2; - let denom = self.a * diff.x + self.b * diff.y + self.c * diff.z; - if denom == 0.0 { - return (v1 * v2) * 0.5; - } - let u = (self.a * v1.x + self.b * v1.y + self.c * v1.z + self.d) / denom; - v1 + (v2 - v1) * u - } -} - -#[repr(C)] -#[derive(Clone, Copy, Default, Debug, PartialEq, SerBin, DeBin)] -pub struct Vec4f { - pub x: f32, - pub y: f32, - pub z: f32, - pub w: f32, -} - -impl fmt::Display for Vec4f { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "vec4({}, {}, {}, {})", - PrettyPrintedF32(self.x), - PrettyPrintedF32(self.y), - PrettyPrintedF32(self.z), - PrettyPrintedF32(self.w), - ) - } -} - -impl Vec4f { - pub const R: Vec4f = Vec4f { - x: 1.0, - y: 0.0, - z: 0.0, - w: 1.0, - }; - pub const G: Vec4f = Vec4f { - x: 0.0, - y: 1.0, - z: 0.0, - w: 1.0, - }; - pub const B: Vec4f = Vec4f { - x: 0.0, - y: 0.0, - z: 1.0, - w: 1.0, - }; - - pub const fn all(v: f32) -> Self { - Self { - x: v, - y: v, - z: v, - w: v, - } - } - - pub const fn to_vec3f(&self) -> Vec3f { - Vec3f { - x: self.x, - y: self.y, - z: self.z, - } - } - - pub fn dot(&self, other: Vec4f) -> f32 { - self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w - } - - pub fn from_lerp(a: Vec4f, b: Vec4f, f: f32) -> Vec4f { - let nf = 1.0 - f; - Vec4f { - x: nf * a.x + f * b.x, - y: nf * a.y + f * b.y, - z: nf * a.z + f * b.z, - w: nf * a.w + f * b.w, - } - } - - pub fn is_equal_enough(&self, other: &Vec4f, epsilon: f32) -> bool { - (self.x - other.x).abs() < epsilon - && (self.y - other.y).abs() < epsilon - && (self.z - other.z).abs() < epsilon - && (self.w - other.w).abs() < epsilon - } - - pub fn from_hsva(hsv: Vec4f) -> Vec4f { - fn mix(x: f32, y: f32, t: f32) -> f32 { - x + (y - x) * t - } - fn clamp(x: f32, mi: f32, ma: f32) -> f32 { - if x < mi { - mi - } else if x > ma { - ma - } else { - x - } - } - fn fract(x: f32) -> f32 { - x.fract() - } - fn abs(x: f32) -> f32 { - x.abs() - } - Vec4f { - x: hsv.z - * mix( - 1.0, - clamp(abs(fract(hsv.x + 1.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), - hsv.y, - ), - y: hsv.z - * mix( - 1.0, - clamp(abs(fract(hsv.x + 2.0 / 3.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), - hsv.y, - ), - z: hsv.z - * mix( - 1.0, - clamp(abs(fract(hsv.x + 1.0 / 3.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), - hsv.y, - ), - w: 1.0, - } - } - - pub fn to_hsva(&self) -> Vec4f { - let pc = self.y < self.z; //step(c[2],c[1]) - let p0 = if pc { self.z } else { self.y }; //mix(c[2],c[1],pc) - let p1 = if pc { self.y } else { self.z }; //mix(c[1],c[2],pc) - let p2 = if pc { -1.0 } else { 0.0 }; //mix(-1,0,pc) - let p3 = if pc { 2.0 / 3.0 } else { -1.0 / 3.0 }; //mix(2/3,-1/3,pc) - - let qc = self.x < p0; //step(p0, c[0]) - let q0 = if qc { p0 } else { self.x }; //mix(p0, c[0], qc) - let q1 = p1; - let q2 = if qc { p3 } else { p2 }; //mix(p3, p2, qc) - let q3 = if qc { self.x } else { p0 }; //mix(c[0], p0, qc) - - let d = q0 - q3.min(q1); - let e = 1.0e-10; - Vec4f { - x: (q2 + (q3 - q1) / (6.0 * d + e)).abs(), - y: d / (q0 + e), - z: q0, - w: self.w, - } - } - - pub fn from_u32(val: u32) -> Vec4f { - Vec4f { - x: ((val >> 24) & 0xff) as f32 / 255.0, - y: ((val >> 16) & 0xff) as f32 / 255.0, - z: ((val >> 8) & 0xff) as f32 / 255.0, - w: (val & 0xff) as f32 / 255.0, - } - } - - pub fn to_u32(&self) -> u32 { - let r = (self.x * 255.0) as u8 as u32; - let g = (self.y * 255.0) as u8 as u32; - let b = (self.z * 255.0) as u8 as u32; - let a = (self.w * 255.0) as u8 as u32; - (r << 24) | (g << 16) | (b << 8) | a - } - - pub const fn xy(&self) -> Vec2f { - Vec2f { - x: self.x, - y: self.y, - } - } - - pub const fn zw(&self) -> Vec2f { - Vec2f { - x: self.z, - y: self.w, - } - } -} - -impl From<(Vec2d, Vec2d)> for Vec4f { - fn from(other: (Vec2d, Vec2d)) -> Vec4f { - vec4( - other.0.x as f32, - other.0.y as f32, - other.1.x as f32, - other.1.y as f32, - ) - } -} - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, PartialEq)] -pub struct CameraFov { - pub angle_left: f32, - pub angle_right: f32, - pub angle_up: f32, - pub angle_down: f32, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, SerBin, DeBin)] -pub struct Quat { - pub x: f32, - pub y: f32, - pub z: f32, - pub w: f32, -} - -impl Default for Quat { - fn default() -> Self { - Self { - x: 0.0, - y: 0.0, - z: 0.0, - w: 1.0, - } - } -} - -impl Quat { - pub fn multiply(a: &Quat, b: &Quat) -> Self { - Self { - x: (b.w * a.x) + (b.x * a.w) + (b.y * a.z) - (b.z * a.y), - y: (b.w * a.y) - (b.x * a.z) + (b.y * a.w) + (b.z * a.x), - z: (b.w * a.z) + (b.x * a.y) - (b.y * a.x) + (b.z * a.w), - w: (b.w * a.w) - (b.x * a.x) - (b.y * a.y) - (b.z * a.z), - } - } - - pub fn invert(&self) -> Self { - Self { - x: -self.x, - y: -self.y, - z: -self.z, - w: self.w, - } - } - - pub fn rotate_vec3(&self, v: &Vec3f) -> Vec3f { - let q = Quat { - x: v.x, - y: v.y, - z: v.z, - w: 0.0, - }; - let aq = Quat::multiply(&q, self); - let ainv = self.invert(); - let aqainv = Quat::multiply(&ainv, &aq); - Vec3f { - x: aqainv.x, - y: aqainv.y, - z: aqainv.z, - } - } - - pub fn dot(&self, other: Quat) -> f32 { - self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w - } - - pub fn neg(&self) -> Quat { - Quat { - x: -self.x, - y: -self.y, - z: -self.z, - w: -self.w, - } - } - - pub fn get_angle_with(&self, other: Quat) -> f32 { - let dot = self.dot(other); - (2.0 * dot * dot - 1.0).acos() * TODEG - } - - pub fn from_slerp(n: Quat, mut m: Quat, t: f32) -> Quat { - // calc cosine - let mut cosom = n.dot(m); - // adjust signs (if necessary) - if cosom < 0.0 { - cosom = -cosom; - m = m.neg(); - } - // calculate coefficients - let (scale0, scale1) = if 1.0 - cosom > 0.000001 { - // standard case (slerp) - let omega = cosom.acos(); - let sinom = omega.sin(); - (((1.0 - t) * omega).sin() / sinom, (t * omega).sin() / sinom) - } else { - (1.0 - t, t) - }; - // calculate final values - (Quat { - x: scale0 * n.x + scale1 * m.x, - y: scale0 * n.y + scale1 * m.y, - z: scale0 * n.z + scale1 * m.z, - w: scale0 * m.w + scale1 * m.w, - }) - .normalized() - } - - pub fn length(self) -> f32 { - self.dot(self).sqrt() - } - - pub fn is_finite(&self) -> bool { - self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite() - } - - pub fn normalized(&mut self) -> Quat { - let len = self.length(); - Quat { - x: self.x / len, - y: self.y / len, - z: self.z / len, - w: self.w / len, - } - } - - pub fn from_axis_angle(axis: Vec3f, angle: f32) -> Self { - let half = angle * 0.5; - let s = half.sin(); - let c = half.cos(); - Quat { - x: axis.x * s, - y: axis.y * s, - z: axis.z * s, - w: c, - } - } - - /// First-order quaternion integration for world-space angular velocity: - /// q' = normalize(q + 0.5 * dt * omega_quat * q) - /// where omega_quat = Quat(wx, wy, wz, 0). No transcendentals needed. - pub fn integrate(&self, angular_velocity: Vec3f, dt: f32) -> Quat { - let omega = Quat { - x: angular_velocity.x, - y: angular_velocity.y, - z: angular_velocity.z, - w: 0.0, - }; - let omega_q = Quat::multiply(self, &omega); - let half_dt = 0.5 * dt; - let mut result = Quat { - x: self.x + half_dt * omega_q.x, - y: self.y + half_dt * omega_q.y, - z: self.z + half_dt * omega_q.z, - w: self.w + half_dt * omega_q.w, - }; - // Normalize to keep unit quaternion - let len = result.length(); - if len > 0.0 { - let inv = 1.0 / len; - result.x *= inv; - result.y *= inv; - result.z *= inv; - result.w *= inv; - } - result - } - - pub fn look_rotation(forward: Vec3f, up: Vec3f) -> Self { - let forward = forward.normalize(); - let up = up.normalize(); - let v2 = forward; - let v0 = Vec3f::cross(up, forward).normalize(); - let v1 = Vec3f::cross(v2, v0); - - let num = (v0.x + v1.y) + v2.z; - if num > 0.0 { - let num = (num + 1.0).sqrt(); - let numh = 0.5 / num; - return Quat { - x: (v1.z - v2.y) * numh, - y: (v2.x - v0.z) * numh, - z: (v0.y - v1.x) * numh, - w: num * 0.5, - }; - } - if (v0.x >= v1.y) && (v0.x >= v2.z) { - let num = (((1.0 + v0.x) - v1.y) - v2.z).sqrt(); - let numh = 0.5 / num; - return Quat { - x: 0.5 * num, - y: (v0.y + v1.x) * numh, - z: (v0.z + v2.x) * numh, - w: (v1.z - v2.y) * numh, - }; - } - if v1.y > v2.z { - let num = (((1.0 + v1.y) - v0.x) - v2.z).sqrt(); - let numh = 0.5 / num; - return Quat { - x: (v1.x + v0.y) * numh, - y: 0.5 * num, - z: (v2.y + v1.z) * numh, - w: (v2.x - v0.z) * numh, - }; - } - let num = (((1.0 + v2.z) - v0.x) - v1.y).sqrt(); - let numh = 0.5 / num; - Quat { - x: (v2.x + v0.z) * numh, - y: (v2.y + v1.z) * numh, - z: 0.5 * num, - w: (v0.y - v1.x) * numh, - } - } -} - -/* -pub fn vec4(x:f32, y:f32, z:f32, w:f32)->Vec4f{ - Vec4f{x:x, y:y, z:z, w:w} -}*/ - -impl Mat4f { - pub const fn identity() -> Mat4f { - Mat4f { - v: [ - 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, - ], - } - } - - pub fn transpose(&self) -> Mat4f { - Mat4f { - v: [ - self.v[0], self.v[4], self.v[8], self.v[12], self.v[1], self.v[5], self.v[9], - self.v[13], self.v[2], self.v[6], self.v[10], self.v[14], self.v[3], self.v[7], - self.v[11], self.v[15], - ], - } - } - - pub fn txyz_s_ry_rx_txyz(t1: Vec3f, s: f32, ry: f32, rx: f32, t2: Vec3f) -> Mat4f { - let cx = f32::cos(rx * TORAD); - let cy = f32::cos(ry * TORAD); - //let cz = f32::cos(r.z * TORAD); - let sx = f32::sin(rx * TORAD); - let sy = f32::sin(ry * TORAD); - //let sz = f32::sin(r.z * TORAD); - // y first, then x, then z - - // Y - // | cy, 0, sy | - // | 0, 1, 0 | - // | -sy, 0, cy | - - // X: - // | 1, 0, 0 | - // | 0, cx, -sx | - // | 0, sx, cx | - - // Z: - // | cz, -sz, 0 | - // | sz, cz, 0 | - // | 0, 0, 1 | - - // X * Y - // | cy, 0, sy | - // | -sx*-sy, cx, -sx*cy | - // | -sy * cx, sx, cx*cy | - - // Z * X * Y - // | cz * cy + -sz * -sx *-sy, -sz * cx, sy *cz + -sz * -sx * cy | - // | sz * cy + -sx*-sy * cz, sz * cx, sy * sz + cz * -sz * cy | - // | -sy * cx, sx, cx*cy | - - // Y * X * Z - // | c*c, c, s*s | - // | 0, c, -s | - // | -s, c*s, c*c | - - /* - let m0 = s * (cz * cy + (-sz) * (-sx) *(-sy)); - let m1 = s * (-sz * cx); - let m2 = s * (sy *cz + (-sz) * (-sx) * cy); - - let m4 = s * (sz * cy + (-sx)*(-sy) * cz); - let m5 = s * (sz * cx); - let m6 = s * (sy * sz + cz * (-sx) * cy); - - let m8 = s * (-sy*cx); - let m9 = s * (sx); - let m10 = s * (cx * cy); - */ - - let m0 = s * (cy); - let m1 = s * (0.0); - let m2 = s * (sy); - - let m4 = s * (-sx * -sy); - let m5 = s * (cx); - let m6 = s * (-sx * cy); - - let m8 = s * (-sy * cx); - let m9 = s * (sx); - let m10 = s * (cx * cy); - - /* - let m0 = s * (cy * cz + sx * sy * sz); - let m1 = s * (-sz * cy + cz * sx * sy); - let m2 = s * (sy * cx); - - let m4 = s * (sz * cx); - let m5 = s * (cx * cz); - let m6 = s * (-sx); - - let m8 = s * (-sy * cz + cy * sx * sz); - let m9 = s * (sy * sz + cy * sx * cz); - let m10 = s * (cx * cy); - */ - Mat4f { - v: [ - m0, - m4, - m8, - 0.0, - m1, - m5, - m9, - 0.0, - m2, - m6, - m10, - 0.0, - t2.x + (m0 * t1.x + m1 * t1.y + m2 * t1.z), - t2.y + (m4 * t1.x + m5 * t1.y + m6 * t1.z), - t2.z + (m8 * t1.x + m9 * t1.y + m10 * t1.z), - 1.0, - ], - } - } - - pub fn perspective(fov_y: f32, aspect: f32, near: f32, far: f32) -> Mat4f { - let f = 1.0 / f32::tan(fov_y * TORAD / 2.0); - let nf = 1.0 / (near - far); - Mat4f { - v: [ - f / aspect, - 0.0, - 0.0, - 0.0, - 0.0, - f, - 0.0, - 0.0, - 0.0, - 0.0, - (far + near) * nf, - -1.0, - 0.0, - 0.0, - (2.0 * far * near) * nf, - 0.0, - ], - } - } - - pub fn from_camera_fov(fov: &CameraFov, near: f32, far: f32) -> Mat4f { - let tan_left = fov.angle_left.tan(); - let tan_right = fov.angle_right.tan(); - let tan_down = fov.angle_down.tan(); - let tan_up = fov.angle_up.tan(); - - let tan_height = tan_up - tan_down; - let tan_width = tan_right - tan_left; - - if far <= near { - Mat4f { - v: [ - 2.0 / tan_width, - 0.0, - 0.0, - 0.0, - 0.0, - 2.0 / tan_height, - 0.0, - 0.0, - (tan_right + tan_left) / tan_width, - (tan_up + tan_down) / tan_height, - -1.0, - -1.0, - 0.0, - 0.0, - -2.0 * near, - 0.0, - ], - } - } else { - Mat4f { - v: [ - 2.0 / tan_width, - 0.0, - 0.0, - 0.0, - 0.0, - 2.0 / tan_height, - 0.0, - 0.0, - (tan_right + tan_left) / tan_width, - (tan_up + tan_down) / tan_height, - -(far + near) / (far - near), - -1.0, - 0.0, - 0.0, - -(far * 2.0 * near) / (far - near), - 0.0, - ], - } - } - } - - pub const fn translation(v: Vec3f) -> Mat4f { - Mat4f { - v: [ - 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, v.x, v.y, v.z, 1.0, - ], - } - } - - pub const fn nonuniform_scaled_translation(s: Vec3f, t: Vec3f) -> Mat4f { - Mat4f { - v: [ - s.x, 0.0, 0.0, 0.0, 0.0, s.y, 0.0, 0.0, 0.0, 0.0, s.z, 0.0, t.x, t.y, t.z, 1.0, - ], - } - } - - pub const fn scaled_translation(s: f32, t: Vec3f) -> Mat4f { - Mat4f { - v: [ - s, 0.0, 0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, s, 0.0, t.x, t.y, t.z, 1.0, - ], - } - } - - pub const fn scale(s: f32) -> Mat4f { - Mat4f { - v: [ - s, 0.0, 0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, 1.0, - ], - } - } - - pub fn rotation(r: Vec3f) -> Mat4f { - //const TORAD: f32 = 0.017453292; - let cx = f32::cos(r.x); - let cy = f32::cos(r.y); - let cz = f32::cos(r.z); - let sx = f32::sin(r.x); - let sy = f32::sin(r.y); - let sz = f32::sin(r.z); - let m0 = cy * cz + sx * sy * sz; - let m1 = -sz * cy + cz * sx * sy; - let m2 = sy * cx; - let m4 = sz * cx; - let m5 = cx * cz; - let m6 = -sx; - let m8 = -sy * cz + cy * sx * sz; - let m9 = sy * sz + cy * sx * cz; - let m10 = cx * cy; - Mat4f { - v: [ - m0, m4, m8, 0.0, m1, m5, m9, 0.0, m2, m6, m10, 0.0, 0.0, 0.0, 0.0, 1.0, - ], - } - } - - pub fn ortho( - left: f32, - right: f32, - top: f32, - bottom: f32, - near: f32, - far: f32, - scalex: f32, - scaley: f32, - ) -> Mat4f { - let lr = 1.0 / (left - right); - let bt = 1.0 / (bottom - top); - let nf = 1.0 / (near - far); - /*return Mat4f{v:[ - -2.0 * lr * scalex, 0.0, 0.0, (left+right) * lr, - 0.0, -2.0 * bt * scaley, 0.0, (top+bottom) * bt, - 0.0, 0.0, 2.0 * nf, (far + near) * nf, - 0.0, 0.0, 0.0, 1.0 - ]}*/ - Mat4f { - v: [ - -2.0 * lr * scalex, - 0.0, - 0.0, - 0.0, - 0.0, - -2.0 * bt * scaley, - 0.0, - 0.0, - 0.0, - 0.0, - -1.0 * nf, - 0.0, - (left + right) * lr, - (top + bottom) * bt, - 0.5 + (far + near) * nf, - 1.0, - ], - } - } - - pub fn transform_vec4(&self, v: Vec4f) -> Vec4f { - let m = &self.v; - Vec4f { - x: m[0] * v.x + m[4] * v.y + m[8] * v.z + m[12] * v.w, - y: m[1] * v.x + m[5] * v.y + m[9] * v.z + m[13] * v.w, - z: m[2] * v.x + m[6] * v.y + m[10] * v.z + m[14] * v.w, - w: m[3] * v.x + m[7] * v.y + m[11] * v.z + m[15] * v.w, - } - } - - pub fn look_at(eye: Vec3f, center: Vec3f, up: Vec3f) -> Mat4f { - let forward = (center - eye).normalize(); - let side = Vec3f::cross(forward, up).normalize(); - let up = Vec3f::cross(side, forward); - - Mat4f { - v: [ - side.x, - up.x, - -forward.x, - 0.0, - side.y, - up.y, - -forward.y, - 0.0, - side.z, - up.z, - -forward.z, - 0.0, - -side.dot(eye), - -up.dot(eye), - forward.dot(eye), - 1.0, - ], - } - } - - pub fn mul(a: &Mat4f, b: &Mat4f) -> Mat4f { - // Swap so that mul(a, b) computes standard a * b (was previously b * a). - let (a, b) = (&b.v, &a.v); - #[inline] - fn d(i: &[f32; 16], x: usize, y: usize) -> f32 { - i[x + 4 * y] - } - Mat4f { - v: [ - d(a, 0, 0) * d(b, 0, 0) - + d(a, 1, 0) * d(b, 0, 1) - + d(a, 2, 0) * d(b, 0, 2) - + d(a, 3, 0) * d(b, 0, 3), - d(a, 0, 0) * d(b, 1, 0) - + d(a, 1, 0) * d(b, 1, 1) - + d(a, 2, 0) * d(b, 1, 2) - + d(a, 3, 0) * d(b, 1, 3), - d(a, 0, 0) * d(b, 2, 0) - + d(a, 1, 0) * d(b, 2, 1) - + d(a, 2, 0) * d(b, 2, 2) - + d(a, 3, 0) * d(b, 2, 3), - d(a, 0, 0) * d(b, 3, 0) - + d(a, 1, 0) * d(b, 3, 1) - + d(a, 2, 0) * d(b, 3, 2) - + d(a, 3, 0) * d(b, 3, 3), - d(a, 0, 1) * d(b, 0, 0) - + d(a, 1, 1) * d(b, 0, 1) - + d(a, 2, 1) * d(b, 0, 2) - + d(a, 3, 1) * d(b, 0, 3), - d(a, 0, 1) * d(b, 1, 0) - + d(a, 1, 1) * d(b, 1, 1) - + d(a, 2, 1) * d(b, 1, 2) - + d(a, 3, 1) * d(b, 1, 3), - d(a, 0, 1) * d(b, 2, 0) - + d(a, 1, 1) * d(b, 2, 1) - + d(a, 2, 1) * d(b, 2, 2) - + d(a, 3, 1) * d(b, 2, 3), - d(a, 0, 1) * d(b, 3, 0) - + d(a, 1, 1) * d(b, 3, 1) - + d(a, 2, 1) * d(b, 3, 2) - + d(a, 3, 1) * d(b, 3, 3), - d(a, 0, 2) * d(b, 0, 0) - + d(a, 1, 2) * d(b, 0, 1) - + d(a, 2, 2) * d(b, 0, 2) - + d(a, 3, 2) * d(b, 0, 3), - d(a, 0, 2) * d(b, 1, 0) - + d(a, 1, 2) * d(b, 1, 1) - + d(a, 2, 2) * d(b, 1, 2) - + d(a, 3, 2) * d(b, 1, 3), - d(a, 0, 2) * d(b, 2, 0) - + d(a, 1, 2) * d(b, 2, 1) - + d(a, 2, 2) * d(b, 2, 2) - + d(a, 3, 2) * d(b, 2, 3), - d(a, 0, 2) * d(b, 3, 0) - + d(a, 1, 2) * d(b, 3, 1) - + d(a, 2, 2) * d(b, 3, 2) - + d(a, 3, 2) * d(b, 3, 3), - d(a, 0, 3) * d(b, 0, 0) - + d(a, 1, 3) * d(b, 0, 1) - + d(a, 2, 3) * d(b, 0, 2) - + d(a, 3, 3) * d(b, 0, 3), - d(a, 0, 3) * d(b, 1, 0) - + d(a, 1, 3) * d(b, 1, 1) - + d(a, 2, 3) * d(b, 1, 2) - + d(a, 3, 3) * d(b, 1, 3), - d(a, 0, 3) * d(b, 2, 0) - + d(a, 1, 3) * d(b, 2, 1) - + d(a, 2, 3) * d(b, 2, 2) - + d(a, 3, 3) * d(b, 2, 3), - d(a, 0, 3) * d(b, 3, 0) - + d(a, 1, 3) * d(b, 3, 1) - + d(a, 2, 3) * d(b, 3, 2) - + d(a, 3, 3) * d(b, 3, 3), - ], - } - } - - pub fn invert(&self) -> Mat4f { - let a = &self.v; - let a00 = a[0]; - let a01 = a[1]; - let a02 = a[2]; - let a03 = a[3]; - let a10 = a[4]; - let a11 = a[5]; - let a12 = a[6]; - let a13 = a[7]; - let a20 = a[8]; - let a21 = a[9]; - let a22 = a[10]; - let a23 = a[11]; - let a30 = a[12]; - let a31 = a[13]; - let a32 = a[14]; - let a33 = a[15]; - - let b00 = a00 * a11 - a01 * a10; - let b01 = a00 * a12 - a02 * a10; - let b02 = a00 * a13 - a03 * a10; - let b03 = a01 * a12 - a02 * a11; - let b04 = a01 * a13 - a03 * a11; - let b05 = a02 * a13 - a03 * a12; - let b06 = a20 * a31 - a21 * a30; - let b07 = a20 * a32 - a22 * a30; - let b08 = a20 * a33 - a23 * a30; - let b09 = a21 * a32 - a22 * a31; - let b10 = a21 * a33 - a23 * a31; - let b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if det == 0.0 { - return Mat4f::identity(); - } - - let idet = 1.0 / det; - Mat4f { - v: [ - (a11 * b11 - a12 * b10 + a13 * b09) * idet, - (a02 * b10 - a01 * b11 - a03 * b09) * idet, - (a31 * b05 - a32 * b04 + a33 * b03) * idet, - (a22 * b04 - a21 * b05 - a23 * b03) * idet, - (a12 * b08 - a10 * b11 - a13 * b07) * idet, - (a00 * b11 - a02 * b08 + a03 * b07) * idet, - (a32 * b02 - a30 * b05 - a33 * b01) * idet, - (a20 * b05 - a22 * b02 + a23 * b01) * idet, - (a10 * b10 - a11 * b08 + a13 * b06) * idet, - (a01 * b08 - a00 * b10 - a03 * b06) * idet, - (a30 * b04 - a31 * b02 + a33 * b00) * idet, - (a21 * b02 - a20 * b04 - a23 * b00) * idet, - (a11 * b07 - a10 * b09 - a12 * b06) * idet, - (a00 * b09 - a01 * b07 + a02 * b06) * idet, - (a31 * b01 - a30 * b03 - a32 * b00) * idet, - (a20 * b03 - a21 * b01 + a22 * b00) * idet, - ], - } - } -} - -//------ Vec2f operators - -impl ops::Add for Vec2f { - type Output = Vec2f; - fn add(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self.x + rhs.x, - y: self.y + rhs.y, - } - } -} - -impl ops::Sub for Vec2f { - type Output = Vec2f; - fn sub(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self.x - rhs.x, - y: self.y - rhs.y, - } - } -} - -impl ops::Mul for Vec2f { - type Output = Vec2f; - fn mul(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self.x * rhs.x, - y: self.y * rhs.y, - } - } -} - -impl ops::Div for Vec2f { - type Output = Vec2f; - fn div(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self.x / rhs.x, - y: self.y / rhs.y, - } - } -} - -impl ops::Add for f32 { - type Output = Vec2f; - fn add(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self + rhs.x, - y: self + rhs.y, - } - } -} - -impl ops::Sub for f32 { - type Output = Vec2f; - fn sub(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self - rhs.x, - y: self - rhs.y, - } - } -} - -impl ops::Mul for f32 { - type Output = Vec2f; - fn mul(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self * rhs.x, - y: self * rhs.y, - } - } -} - -impl ops::Div for f32 { - type Output = Vec2f; - fn div(self, rhs: Vec2f) -> Vec2f { - Vec2f { - x: self / rhs.x, - y: self / rhs.y, - } - } -} - -impl ops::Add for Vec2f { - type Output = Vec2f; - fn add(self, rhs: f32) -> Vec2f { - Vec2f { - x: self.x + rhs, - y: self.y + rhs, - } - } -} - -impl ops::Sub for Vec2f { - type Output = Vec2f; - fn sub(self, rhs: f32) -> Vec2f { - Vec2f { - x: self.x - rhs, - y: self.y - rhs, - } - } -} - -impl ops::Mul for Vec2f { - type Output = Vec2f; - fn mul(self, rhs: f32) -> Vec2f { - Vec2f { - x: self.x * rhs, - y: self.y * rhs, - } - } -} - -impl ops::Div for Vec2f { - type Output = Vec2f; - fn div(self, rhs: f32) -> Vec2f { - Vec2f { - x: self.x / rhs, - y: self.y / rhs, - } - } -} - -impl ops::AddAssign for Vec2f { - fn add_assign(&mut self, rhs: Vec2f) { - self.x = self.x + rhs.x; - self.y = self.y + rhs.y; - } -} - -impl ops::SubAssign for Vec2f { - fn sub_assign(&mut self, rhs: Vec2f) { - self.x = self.x - rhs.x; - self.y = self.y - rhs.y; - } -} - -impl ops::MulAssign for Vec2f { - fn mul_assign(&mut self, rhs: Vec2f) { - self.x = self.x * rhs.x; - self.y = self.y * rhs.y; - } -} - -impl ops::DivAssign for Vec2f { - fn div_assign(&mut self, rhs: Vec2f) { - self.x = self.x / rhs.x; - self.y = self.y / rhs.y; - } -} - -impl ops::AddAssign for Vec2f { - fn add_assign(&mut self, rhs: f32) { - self.x = self.x + rhs; - self.y = self.y + rhs; - } -} - -impl ops::SubAssign for Vec2f { - fn sub_assign(&mut self, rhs: f32) { - self.x = self.x - rhs; - self.y = self.y - rhs; - } -} - -impl ops::MulAssign for Vec2f { - fn mul_assign(&mut self, rhs: f32) { - self.x = self.x * rhs; - self.y = self.y * rhs; - } -} - -impl ops::DivAssign for Vec2f { - fn div_assign(&mut self, rhs: f32) { - self.x = self.x / rhs; - self.y = self.y / rhs; - } -} - -impl ops::Neg for Vec2f { - type Output = Vec2f; - fn neg(self) -> Self { - Vec2f { - x: -self.x, - y: -self.y, - } - } -} - -impl ops::Neg for Vec3f { - type Output = Vec3f; - fn neg(self) -> Self { - Vec3f { - x: -self.x, - y: -self.y, - z: -self.z, - } - } -} - -impl ops::Neg for Vec4f { - type Output = Vec4f; - fn neg(self) -> Self { - Vec4f { - x: -self.x, - y: -self.y, - z: -self.z, - w: -self.w, - } - } -} - -//------ Vec3f operators - -impl ops::Add for Vec3f { - type Output = Vec3f; - fn add(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } -} - -impl ops::Sub for Vec3f { - type Output = Vec3f; - fn sub(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self.x - rhs.x, - y: self.y - rhs.y, - z: self.z - rhs.z, - } - } -} - -impl ops::Mul for Vec3f { - type Output = Vec3f; - fn mul(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self.x * rhs.x, - y: self.y * rhs.y, - z: self.z * rhs.z, - } - } -} - -impl ops::Div for Vec3f { - type Output = Vec3f; - fn div(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self.x / rhs.x, - y: self.y / rhs.y, - z: self.z / rhs.z, - } - } -} - -impl ops::Add for f32 { - type Output = Vec3f; - fn add(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self + rhs.x, - y: self + rhs.y, - z: self + rhs.z, - } - } -} - -impl ops::Sub for f32 { - type Output = Vec3f; - fn sub(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self - rhs.x, - y: self - rhs.y, - z: self - rhs.z, - } - } -} - -impl ops::Mul for f32 { - type Output = Vec3f; - fn mul(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self * rhs.x, - y: self * rhs.y, - z: self * rhs.z, - } - } -} - -impl ops::Div for f32 { - type Output = Vec3f; - fn div(self, rhs: Vec3f) -> Vec3f { - Vec3f { - x: self / rhs.x, - y: self / rhs.y, - z: self / rhs.z, - } - } -} - -impl ops::Add for Vec3f { - type Output = Vec3f; - fn add(self, rhs: f32) -> Vec3f { - Vec3f { - x: self.x + rhs, - y: self.y + rhs, - z: self.z + rhs, - } - } -} - -impl ops::Sub for Vec3f { - type Output = Vec3f; - fn sub(self, rhs: f32) -> Vec3f { - Vec3f { - x: self.x - rhs, - y: self.y - rhs, - z: self.z - rhs, - } - } -} - -impl ops::Mul for Vec3f { - type Output = Vec3f; - fn mul(self, rhs: f32) -> Vec3f { - Vec3f { - x: self.x * rhs, - y: self.y * rhs, - z: self.z * rhs, - } - } -} - -impl ops::Div for Vec3f { - type Output = Vec3f; - fn div(self, rhs: f32) -> Vec3f { - Vec3f { - x: self.x / rhs, - y: self.y / rhs, - z: self.z / rhs, - } - } -} - -impl ops::AddAssign for Vec3f { - fn add_assign(&mut self, rhs: Vec3f) { - self.x = self.x + rhs.x; - self.y = self.y + rhs.y; - self.z = self.z + rhs.z; - } -} - -impl ops::SubAssign for Vec3f { - fn sub_assign(&mut self, rhs: Vec3f) { - self.x = self.x - rhs.x; - self.y = self.y - rhs.y; - self.z = self.z - rhs.z; - } -} - -impl ops::MulAssign for Vec3f { - fn mul_assign(&mut self, rhs: Vec3f) { - self.x = self.x * rhs.x; - self.y = self.y * rhs.y; - self.z = self.z * rhs.z; - } -} - -impl ops::DivAssign for Vec3f { - fn div_assign(&mut self, rhs: Vec3f) { - self.x = self.x / rhs.x; - self.y = self.y / rhs.y; - self.z = self.z / rhs.z; - } -} - -impl ops::AddAssign for Vec3f { - fn add_assign(&mut self, rhs: f32) { - self.x = self.x + rhs; - self.y = self.y + rhs; - self.z = self.z + rhs; - } -} - -impl ops::SubAssign for Vec3f { - fn sub_assign(&mut self, rhs: f32) { - self.x = self.x - rhs; - self.y = self.y - rhs; - self.z = self.z - rhs; - } -} - -impl ops::MulAssign for Vec3f { - fn mul_assign(&mut self, rhs: f32) { - self.x = self.x * rhs; - self.y = self.y * rhs; - self.z = self.z * rhs; - } -} - -impl ops::DivAssign for Vec3f { - fn div_assign(&mut self, rhs: f32) { - self.x = self.x / rhs; - self.y = self.y / rhs; - self.z = self.z / rhs; - } -} - -//------ Vec4f operators - -impl ops::Add for Vec4f { - type Output = Vec4f; - fn add(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - w: self.w + rhs.w, - } - } -} - -impl ops::Sub for Vec4f { - type Output = Vec4f; - fn sub(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self.x - rhs.x, - y: self.y - rhs.y, - z: self.z - rhs.z, - w: self.w - rhs.w, - } - } -} - -impl ops::Mul for Vec4f { - type Output = Vec4f; - fn mul(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self.x * rhs.x, - y: self.y * rhs.y, - z: self.z * rhs.z, - w: self.w * rhs.w, - } - } -} - -impl ops::Div for Vec4f { - type Output = Vec4f; - fn div(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self.x / rhs.x, - y: self.y / rhs.y, - z: self.z / rhs.z, - w: self.w / rhs.w, - } - } -} - -impl ops::Add for f32 { - type Output = Vec4f; - fn add(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self + rhs.x, - y: self + rhs.y, - z: self + rhs.z, - w: self + rhs.z, - } - } -} - -impl ops::Sub for f32 { - type Output = Vec4f; - fn sub(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self - rhs.x, - y: self - rhs.y, - z: self - rhs.z, - w: self - rhs.z, - } - } -} - -impl ops::Mul for f32 { - type Output = Vec4f; - fn mul(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self * rhs.x, - y: self * rhs.y, - z: self * rhs.z, - w: self * rhs.z, - } - } -} - -impl ops::Div for f32 { - type Output = Vec4f; - fn div(self, rhs: Vec4f) -> Vec4f { - Vec4f { - x: self / rhs.x, - y: self / rhs.y, - z: self / rhs.z, - w: self / rhs.z, - } - } -} - -impl ops::Add for Vec4f { - type Output = Vec4f; - fn add(self, rhs: f32) -> Vec4f { - Vec4f { - x: self.x + rhs, - y: self.y + rhs, - z: self.z + rhs, - w: self.w + rhs, - } - } -} - -impl ops::Sub for Vec4f { - type Output = Vec4f; - fn sub(self, rhs: f32) -> Vec4f { - Vec4f { - x: self.x - rhs, - y: self.y - rhs, - z: self.z - rhs, - w: self.w - rhs, - } - } -} - -impl ops::Mul for Vec4f { - type Output = Vec4f; - fn mul(self, rhs: f32) -> Vec4f { - Vec4f { - x: self.x * rhs, - y: self.y * rhs, - z: self.z * rhs, - w: self.w * rhs, - } - } -} - -impl ops::Div for Vec4f { - type Output = Vec4f; - fn div(self, rhs: f32) -> Vec4f { - Vec4f { - x: self.x / rhs, - y: self.y / rhs, - z: self.z / rhs, - w: self.w / rhs, - } - } -} - -impl ops::AddAssign for Vec4f { - fn add_assign(&mut self, rhs: Vec4f) { - self.x = self.x + rhs.x; - self.y = self.y + rhs.y; - self.z = self.z + rhs.z; - self.w = self.w + rhs.w; - } -} - -impl ops::SubAssign for Vec4f { - fn sub_assign(&mut self, rhs: Vec4f) { - self.x = self.x - rhs.x; - self.y = self.y - rhs.y; - self.z = self.z - rhs.z; - self.w = self.w - rhs.w; - } -} - -impl ops::MulAssign for Vec4f { - fn mul_assign(&mut self, rhs: Vec4f) { - self.x = self.x * rhs.x; - self.y = self.y * rhs.y; - self.z = self.z * rhs.z; - self.w = self.w * rhs.w; - } -} - -impl ops::DivAssign for Vec4f { - fn div_assign(&mut self, rhs: Vec4f) { - self.x = self.x / rhs.x; - self.y = self.y / rhs.y; - self.z = self.z / rhs.z; - self.w = self.w / rhs.w; - } -} - -impl ops::AddAssign for Vec4f { - fn add_assign(&mut self, rhs: f32) { - self.x = self.x + rhs; - self.y = self.y + rhs; - self.z = self.z + rhs; - self.w = self.w + rhs; - } -} - -impl ops::SubAssign for Vec4f { - fn sub_assign(&mut self, rhs: f32) { - self.x = self.x - rhs; - self.y = self.y - rhs; - self.z = self.z - rhs; - self.w = self.w - rhs; - } -} - -impl ops::MulAssign for Vec4f { - fn mul_assign(&mut self, rhs: f32) { - self.x = self.x * rhs; - self.y = self.y * rhs; - self.z = self.z * rhs; - self.w = self.w * rhs; - } -} - -impl ops::DivAssign for Vec4f { - fn div_assign(&mut self, rhs: f32) { - self.x = self.x / rhs; - self.y = self.y / rhs; - self.z = self.z / rhs; - self.w = self.w / rhs; - } -} - -// ---- Mat3f: column-major 3x3 matrix ---- - -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Mat3f { - pub c0: Vec3f, // column 0 - pub c1: Vec3f, // column 1 - pub c2: Vec3f, // column 2 -} - -impl Default for Mat3f { - fn default() -> Self { - Self::identity() - } -} - -impl Mat3f { - pub const fn identity() -> Self { - Mat3f { - c0: Vec3f { - x: 1.0, - y: 0.0, - z: 0.0, - }, - c1: Vec3f { - x: 0.0, - y: 1.0, - z: 0.0, - }, - c2: Vec3f { - x: 0.0, - y: 0.0, - z: 1.0, - }, - } - } - - pub const fn zero() -> Self { - Mat3f { - c0: Vec3f { - x: 0.0, - y: 0.0, - z: 0.0, - }, - c1: Vec3f { - x: 0.0, - y: 0.0, - z: 0.0, - }, - c2: Vec3f { - x: 0.0, - y: 0.0, - z: 0.0, - }, - } - } - - /// Diagonal matrix — used for cuboid inertia tensors. - pub const fn from_diagonal(d: Vec3f) -> Self { - Mat3f { - c0: Vec3f { - x: d.x, - y: 0.0, - z: 0.0, - }, - c1: Vec3f { - x: 0.0, - y: d.y, - z: 0.0, - }, - c2: Vec3f { - x: 0.0, - y: 0.0, - z: d.z, - }, - } - } - - /// Build rotation matrix from unit quaternion. - pub fn from_quat(q: Quat) -> Self { - let x2 = q.x + q.x; - let y2 = q.y + q.y; - let z2 = q.z + q.z; - let xx = q.x * x2; - let xy = q.x * y2; - let xz = q.x * z2; - let yy = q.y * y2; - let yz = q.y * z2; - let zz = q.z * z2; - let wx = q.w * x2; - let wy = q.w * y2; - let wz = q.w * z2; - Mat3f { - c0: Vec3f { - x: 1.0 - yy - zz, - y: xy + wz, - z: xz - wy, - }, - c1: Vec3f { - x: xy - wz, - y: 1.0 - xx - zz, - z: yz + wx, - }, - c2: Vec3f { - x: xz + wy, - y: yz - wx, - z: 1.0 - xx - yy, - }, - } - } - - pub fn transpose(&self) -> Self { - Mat3f { - c0: Vec3f { - x: self.c0.x, - y: self.c1.x, - z: self.c2.x, - }, - c1: Vec3f { - x: self.c0.y, - y: self.c1.y, - z: self.c2.y, - }, - c2: Vec3f { - x: self.c0.z, - y: self.c1.z, - z: self.c2.z, - }, - } - } - - pub fn mul_vec3(&self, v: Vec3f) -> Vec3f { - Vec3f { - x: self.c0.x * v.x + self.c1.x * v.y + self.c2.x * v.z, - y: self.c0.y * v.x + self.c1.y * v.y + self.c2.y * v.z, - z: self.c0.z * v.x + self.c1.z * v.y + self.c2.z * v.z, - } - } - - pub fn mul_mat3(&self, rhs: &Mat3f) -> Mat3f { - Mat3f { - c0: self.mul_vec3(rhs.c0), - c1: self.mul_vec3(rhs.c1), - c2: self.mul_vec3(rhs.c2), - } - } - - /// Scale each column by a scalar (equivalent to self * diag(s)). - pub fn scale(&self, s: f32) -> Self { - Mat3f { - c0: self.c0 * s, - c1: self.c1 * s, - c2: self.c2 * s, - } - } -} - -// ---- Aabb: axis-aligned bounding box ---- - -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Aabb { - pub min: Vec3f, - pub max: Vec3f, -} - -impl Aabb { - pub fn overlaps(&self, other: &Aabb) -> bool { - self.min.x <= other.max.x - && self.max.x >= other.min.x - && self.min.y <= other.max.y - && self.max.y >= other.min.y - && self.min.z <= other.max.z - && self.max.z >= other.min.z - } - - /// Compute AABB of a cuboid at the given pose. - /// Uses the abs-rotation-matrix trick: for each axis, the extent - /// is the dot product of half_extents with the abs of the corresponding - /// row of the rotation matrix. - pub fn from_cuboid(half_extents: Vec3f, pose: &Pose) -> Self { - let rot = Mat3f::from_quat(pose.orientation); - // Absolute value of each element — gives the extent contribution per axis - let abs_r = Mat3f { - c0: rot.c0.abs(), - c1: rot.c1.abs(), - c2: rot.c2.abs(), - }; - let extent = abs_r.mul_vec3(half_extents); - Aabb { - min: pose.position - extent, - max: pose.position + extent, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn mat4_mul_order() { - // Column-major layout: columns are contiguous in memory. - // Scale(2): diag(2,2,2,1) - let scale = Mat4f { - v: [ - 2.0, 0.0, 0.0, 0.0, // column 0 - 0.0, 2.0, 0.0, 0.0, // column 1 - 0.0, 0.0, 2.0, 0.0, // column 2 - 0.0, 0.0, 0.0, 1.0, // column 3 - ], - }; - - // Translate(5,7,0): identity with tx=5, ty=7 in column 3 - let translate = Mat4f { - v: [ - 1.0, 0.0, 0.0, 0.0, // column 0 - 0.0, 1.0, 0.0, 0.0, // column 1 - 0.0, 0.0, 1.0, 0.0, // column 2 - 5.0, 7.0, 0.0, 1.0, // column 3 - ], - }; - - // Standard linear algebra: Scale * Translate should scale the - // translation components, giving tx=10, ty=14. - // If mul(a,b) = a*b then result.v[12] == 10.0 - // If mul(a,b) = b*a then result.v[12] == 5.0 - - let result = Mat4f::mul(&scale, &translate); - let tx = result.v[12]; - let ty = result.v[13]; - - eprintln!("mul(&scale, &translate): tx={tx}, ty={ty}"); - eprintln!("result matrix: {:?}", result.v); - - // Check which convention mul uses: - if tx == 10.0 { - eprintln!("Mat4f::mul(a, b) computes a * b (standard order)"); - } else if tx == 5.0 { - eprintln!("Mat4f::mul(a, b) computes b * a (reversed order)"); - } else { - panic!("Unexpected tx={tx}; neither a*b nor b*a"); - } - - // Verify with transform_vec4 on the result applied to point (1,1,0,1). - // Standard Scale*Translate*(1,1,0,1): - // Translate*(1,1,0,1) = (6,8,0,1) - // Scale*(6,8,0,1) = (12,16,0,1) - // Reversed Translate*Scale*(1,1,0,1): - // Scale*(1,1,0,1) = (2,2,0,1) - // Translate*(2,2,0,1) = (7,9,0,1) - - let p = Vec4f { - x: 1.0, - y: 1.0, - z: 0.0, - w: 1.0, - }; - let out = result.transform_vec4(p); - eprintln!( - "transform_vec4 result: ({}, {}, {}, {})", - out.x, out.y, out.z, out.w - ); - - if out.x == 12.0 && out.y == 16.0 { - eprintln!("Confirmed: mul(a,b) = a*b, transform_vec4 is standard M*v"); - } else if out.x == 7.0 && out.y == 9.0 { - eprintln!("Confirmed: mul(a,b) = b*a (reversed)"); - } else { - panic!("Unexpected transform result: ({}, {})", out.x, out.y); - } - } -} diff --git a/vendor/makepad/libs/math/src/math_f64.rs b/vendor/makepad/libs/math/src/math_f64.rs deleted file mode 100644 index 0d3fb22..0000000 --- a/vendor/makepad/libs/math/src/math_f64.rs +++ /dev/null @@ -1,576 +0,0 @@ -//use std::f64::consts::PI; - -use { - crate::math_f32::*, - // makepad_microserde::*, - // crate::colorhex::* - std::{fmt, ops}, -}; - -pub struct PrettyPrintedF64(pub f64); - -impl fmt::Display for PrettyPrintedF64 { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.0.abs().fract() < 0.00000001 { - write!(f, "{}.0", self.0) - } else { - write!(f, "{}", self.0) - } - } -} - -#[derive(Clone, Copy, Default, Debug, PartialEq)] -pub struct Rect { - pub pos: Vec2d, - pub size: Vec2d, -} - -impl Rect { - pub fn translate(self, pos: Vec2d) -> Rect { - Rect { - pos: self.pos + pos, - size: self.size, - } - } - - pub fn contains(&self, pos: Vec2d) -> bool { - pos.x >= self.pos.x - && pos.x <= self.pos.x + self.size.x - && pos.y >= self.pos.y - && pos.y <= self.pos.y + self.size.y - } - - pub fn center(&self) -> Vec2d { - Vec2d { - x: self.pos.x + self.size.x * 0.5, - y: self.pos.y + self.size.y * 0.5, - } - } - - pub fn scale_and_shift(&self, center: Vec2d, scale: f64, shift: Vec2d) -> Rect { - Rect { - pos: (self.pos - center) * scale + center + shift, - size: self.size * scale, - } - } - - pub fn is_inside_of(&self, r: Rect) -> bool { - self.pos.x >= r.pos.x - && self.pos.y >= r.pos.y - && self.pos.x + self.size.x <= r.pos.x + r.size.x - && self.pos.y + self.size.y <= r.pos.y + r.size.y - } - - pub fn intersects(&self, r: Rect) -> bool { - r.pos.x < self.pos.x + self.size.x - && r.pos.x + r.size.x > self.pos.x - && r.pos.y < self.pos.y + self.size.y - && r.pos.y + r.size.y > self.pos.y - } - - pub fn add_margin(self, size: Vec2d) -> Rect { - Rect { - pos: self.pos - size, - size: self.size + 2.0 * size, - } - } - - pub fn contain(&self, other: Rect) -> Rect { - let mut pos = other.pos; - if pos.x < self.pos.x { - pos.x = self.pos.x - }; - if pos.y < self.pos.y { - pos.y = self.pos.y - }; - if pos.x + other.size.x > self.pos.x + self.size.x { - pos.x = self.pos.x + self.size.x - other.size.x - } - if pos.y + other.size.y > self.pos.y + self.size.y { - pos.y = self.pos.y + self.size.y - other.size.y - } - Rect { - pos, - size: other.size, - } - } - - pub fn hull(&self, other: Rect) -> Rect { - let otherpos = other.pos; - let otherfarside = other.pos + other.size; - let farside = self.pos + self.size; - let mut finalpos = self.pos; - let mut finalfarside = farside; - if otherpos.x < finalpos.x { - finalpos.x = otherpos.x - }; - if otherpos.y < finalpos.y { - finalpos.y = otherpos.y - }; - - if otherfarside.x > finalfarside.x { - finalfarside.x = otherfarside.x - }; - if otherfarside.y > finalfarside.y { - finalfarside.y = otherfarside.y - }; - let finalsize = finalfarside - finalpos; - Rect { - pos: finalpos, - size: finalsize, - } - } - - pub fn clip(&self, clip: (Vec2d, Vec2d)) -> Rect { - let mut x1 = self.pos.x; - let mut y1 = self.pos.y; - let mut x2 = x1 + self.size.x; - let mut y2 = y1 + self.size.y; - x1 = x1.max(clip.0.x).min(clip.1.x); - y1 = y1.max(clip.0.y).min(clip.1.y); - x2 = x2.max(clip.0.x).min(clip.1.x); - y2 = y2.max(clip.0.y).min(clip.1.y); - Rect { - pos: dvec2(x1, y1), - size: dvec2(x2 - x1, y2 - y1), - } - } - - pub fn from_lerp(a: Rect, b: Rect, f: f64) -> Rect { - Rect { - pos: (b.pos - a.pos) * f + a.pos, - size: (b.size - a.size) * f + a.size, - } - } - - pub fn dpi_snap(&self, f: f64) -> Rect { - Rect { - pos: dvec2((self.pos.x / f).floor() * f, (self.pos.y / f).floor() * f), - size: dvec2((self.size.x / f).floor() * f, (self.size.y / f).floor() * f), - } - } - - pub fn grow(&mut self, amt: f64) { - self.pos.x = self.pos.x - amt; - self.pos.y = self.pos.y - amt; - self.size.x = self.size.x + amt * 2.; - self.size.y = self.size.y + amt * 2.; - } - - pub fn clip_y_between(&mut self, y1: f64, y2: f64) { - if self.pos.y < y1 { - let diff = y1 - self.pos.y; - self.pos.y = y1; - self.size.y = self.size.y - diff; - } - - if (self.pos.y + self.size.y) > y2 { - let diff = y2 - (self.pos.y + self.size.y); - self.size.y = self.size.y + diff; - } - } - - pub fn clip_x_between(&mut self, x1: f64, x2: f64) { - if self.pos.x < x1 { - let diff = x1 - self.pos.x; - self.pos.x = x1; - self.size.x = self.size.x - diff; - } - - if (self.pos.x + self.size.x) > x2 { - let diff = x2 - (self.pos.x + self.size.x); - self.size.x = self.size.x + diff; - } - } - - pub fn is_nan(&self) -> bool { - self.pos.is_nan() || self.size.is_nan() - } -} - -#[derive(Clone, Copy, Default, Debug, PartialEq)] -pub struct Vec4d { - pub x: f64, - pub y: f64, - pub z: f64, - pub w: f64, -} -pub type DVec4 = Vec4d; - -#[derive(Clone, Copy, Default, Debug, PartialEq)] -pub struct Vec3d { - pub x: f64, - pub y: f64, - pub z: f64, -} -pub type DVec3 = Vec3d; - -#[derive(Clone, Copy, Default, Debug, PartialEq)] -pub struct Vec2d { - pub x: f64, - pub y: f64, -} -pub type DVec2 = Vec2d; - -impl std::convert::From for Vec2d { - fn from(other: Vec2f) -> Vec2d { - Vec2d { - x: other.x as f64, - y: other.y as f64, - } - } -} - -impl std::convert::From for Vec2f { - fn from(other: Vec2d) -> Vec2f { - Vec2f { - x: other.x as f32, - y: other.y as f32, - } - } -} - -impl std::convert::From<(Vec2d, Vec2d)> for Rect { - fn from(o: (Vec2d, Vec2d)) -> Rect { - Rect { - pos: dvec2(o.0.x, o.0.y), - size: dvec2(o.1.x - o.0.x, o.1.y - o.0.y), - } - } -} - -impl Vec2d { - pub const fn new() -> Vec2d { - Vec2d { x: 0.0, y: 0.0 } - } - - pub fn zero(&mut self) { - self.x = 0.; - self.y = 0.; - } - - pub fn dpi_snap(&self, f: f64) -> Vec2d { - Vec2d { - x: (self.x * f).round() / f, - y: (self.y * f).round() / f, - } - } - - pub const fn all(x: f64) -> Vec2d { - Vec2d { x, y: x } - } - - pub const fn index(&self, index: Vec2Index) -> f64 { - match index { - Vec2Index::X => self.x, - Vec2Index::Y => self.y, - } - } - - pub fn set_index(&mut self, index: Vec2Index, v: f64) { - match index { - Vec2Index::X => self.x = v, - Vec2Index::Y => self.y = v, - } - } - - pub const fn from_index_pair(index: Vec2Index, a: f64, b: f64) -> Self { - match index { - Vec2Index::X => Self { x: a, y: b }, - Vec2Index::Y => Self { x: b, y: a }, - } - } - - pub const fn into_vec2(self) -> Vec2f { - Vec2f { - x: self.x as f32, - y: self.y as f32, - } - } - - pub fn from_lerp(a: Vec2d, b: Vec2d, f: f64) -> Vec2d { - let nf = 1.0 - f; - Vec2d { - x: nf * a.x + f * b.x, - y: nf * a.y + f * b.y, - } - } - - pub fn floor(self) -> Vec2d { - Vec2d { - x: self.x.floor(), - y: self.y.floor(), - } - } - - pub fn ceil(self) -> Vec2d { - Vec2d { - x: self.x.ceil(), - y: self.y.ceil(), - } - } - - pub fn distance(&self, other: &Vec2d) -> f64 { - let dx = self.x - other.x; - let dy = self.y - other.y; - (dx * dx + dy * dy).sqrt() - } - - pub fn angle_in_radians(&self) -> f64 { - self.y.atan2(self.x) - } - pub fn swapxy(&self) -> Vec2d { - dvec2(self.y, self.x) - } - pub fn angle_in_degrees(&self) -> f64 { - self.y.atan2(self.x) * (360.0 / (2. * std::f64::consts::PI)) - } - - pub fn length(&self) -> f64 { - (self.x * self.x + self.y * self.y).sqrt() - } - pub fn normalize(&self) -> Vec2d { - let l = self.length(); - if l == 0.0 { - return dvec2(0., 0.); - } - return dvec2(self.x / l, self.y / l); - } - - pub fn clockwise_tangent(&self) -> Vec2d { - return dvec2(-self.y, self.x); - } - - pub fn counterclockwise_tangent(&self) -> Vec2d { - return dvec2(self.y, -self.x); - } - - pub fn normalize_to_x(&self) -> Vec2d { - let l = self.x; - if l == 0.0 { - return dvec2(1., 0.); - } - return dvec2(1., self.y / l); - } - pub fn normalize_to_y(&self) -> Vec2d { - let l = self.y; - if l == 0.0 { - return dvec2(1., 0.); - } - return dvec2(self.x / l, 1.); - } - - pub fn lengthsquared(&self) -> f64 { - self.x * self.x + self.y * self.y - } - - pub fn is_nan(&self) -> bool { - self.x.is_nan() || self.y.is_nan() - } -} - -impl fmt::Display for Vec2d { - // This trait requires `fmt` with this exact signature. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "vec2f64({},{})", self.x, self.y) - } -} - -pub const fn dvec2(x: f64, y: f64) -> Vec2d { - Vec2d { x, y } -} - -pub const fn rect(x: f64, y: f64, w: f64, h: f64) -> Rect { - Rect { - pos: Vec2d { x, y }, - size: Vec2d { x: w, y: h }, - } -} - -//------ Vec2f operators - -impl ops::Add for Vec2d { - type Output = Vec2d; - fn add(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self.x + rhs.x, - y: self.y + rhs.y, - } - } -} - -impl ops::Sub for Vec2d { - type Output = Vec2d; - fn sub(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self.x - rhs.x, - y: self.y - rhs.y, - } - } -} - -impl ops::Mul for Vec2d { - type Output = Vec2d; - fn mul(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self.x * rhs.x, - y: self.y * rhs.y, - } - } -} - -impl ops::Div for Vec2d { - type Output = Vec2d; - fn div(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self.x / rhs.x, - y: self.y / rhs.y, - } - } -} - -impl ops::Add for f64 { - type Output = Vec2d; - fn add(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self + rhs.x, - y: self + rhs.y, - } - } -} - -impl ops::Sub for f64 { - type Output = Vec2d; - fn sub(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self - rhs.x, - y: self - rhs.y, - } - } -} - -impl ops::Mul for f64 { - type Output = Vec2d; - fn mul(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self * rhs.x, - y: self * rhs.y, - } - } -} - -impl ops::Div for f64 { - type Output = Vec2d; - fn div(self, rhs: Vec2d) -> Vec2d { - Vec2d { - x: self / rhs.x, - y: self / rhs.y, - } - } -} - -impl ops::Add for Vec2d { - type Output = Vec2d; - fn add(self, rhs: f64) -> Vec2d { - Vec2d { - x: self.x + rhs, - y: self.y + rhs, - } - } -} - -impl ops::Sub for Vec2d { - type Output = Vec2d; - fn sub(self, rhs: f64) -> Vec2d { - Vec2d { - x: self.x - rhs, - y: self.y - rhs, - } - } -} - -impl ops::Mul for Vec2d { - type Output = Vec2d; - fn mul(self, rhs: f64) -> Vec2d { - Vec2d { - x: self.x * rhs, - y: self.y * rhs, - } - } -} - -impl ops::Div for Vec2d { - type Output = Vec2d; - fn div(self, rhs: f64) -> Vec2d { - Vec2d { - x: self.x / rhs, - y: self.y / rhs, - } - } -} - -impl ops::AddAssign for Vec2d { - fn add_assign(&mut self, rhs: Vec2d) { - self.x = self.x + rhs.x; - self.y = self.y + rhs.y; - } -} - -impl ops::SubAssign for Vec2d { - fn sub_assign(&mut self, rhs: Vec2d) { - self.x = self.x - rhs.x; - self.y = self.y - rhs.y; - } -} - -impl ops::MulAssign for Vec2d { - fn mul_assign(&mut self, rhs: Vec2d) { - self.x = self.x * rhs.x; - self.y = self.y * rhs.y; - } -} - -impl ops::DivAssign for Vec2d { - fn div_assign(&mut self, rhs: Vec2d) { - self.x = self.x / rhs.x; - self.y = self.y / rhs.y; - } -} - -impl ops::AddAssign for Vec2d { - fn add_assign(&mut self, rhs: f64) { - self.x = self.x + rhs; - self.y = self.y + rhs; - } -} - -impl ops::SubAssign for Vec2d { - fn sub_assign(&mut self, rhs: f64) { - self.x = self.x - rhs; - self.y = self.y - rhs; - } -} - -impl ops::MulAssign for Vec2d { - fn mul_assign(&mut self, rhs: f64) { - self.x = self.x * rhs; - self.y = self.y * rhs; - } -} - -impl ops::DivAssign for Vec2d { - fn div_assign(&mut self, rhs: f64) { - self.x = self.x / rhs; - self.y = self.y / rhs; - } -} - -impl ops::Neg for Vec2d { - type Output = Vec2d; - fn neg(self) -> Self { - Vec2d { - x: -self.x, - y: -self.y, - } - } -} diff --git a/vendor/makepad/libs/math/src/math_usize.rs b/vendor/makepad/libs/math/src/math_usize.rs deleted file mode 100644 index bbcf203..0000000 --- a/vendor/makepad/libs/math/src/math_usize.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::ops::{Add, Sub}; - -#[derive(Clone, Copy, Debug)] -pub struct RectUsize { - pub origin: PointUsize, - pub size: SizeUsize, -} - -impl RectUsize { - pub const fn new(origin: PointUsize, size: SizeUsize) -> Self { - Self { origin, size } - } - - pub const fn min(self) -> PointUsize { - self.origin - } - - pub fn max(self) -> PointUsize { - self.origin + self.size - } - - pub fn union(self, other: Self) -> Self { - let min = self.min().min(other.min()); - let max = self.max().max(other.max()); - Self::new(min, max - min) - } -} - -#[derive(Clone, Copy, Debug)] -pub struct PointUsize { - pub x: usize, - pub y: usize, -} - -impl PointUsize { - pub const fn new(x: usize, y: usize) -> Self { - Self { x, y } - } - - pub fn min(self, other: Self) -> Self { - Self { - x: self.x.min(other.x), - y: self.y.min(other.y), - } - } - - pub fn max(self, other: Self) -> Self { - Self { - x: self.x.max(other.x), - y: self.y.max(other.y), - } - } -} - -impl Add for PointUsize { - type Output = Self; - - fn add(self, other: SizeUsize) -> Self::Output { - PointUsize::new(self.x + other.width, self.y + other.height) - } -} - -impl Sub for PointUsize { - type Output = SizeUsize; - - fn sub(self, other: Self) -> Self::Output { - SizeUsize::new(self.x - other.x, self.y - other.y) - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SizeUsize { - pub width: usize, - pub height: usize, -} - -impl SizeUsize { - pub const fn new(width: usize, height: usize) -> Self { - Self { width, height } - } -} diff --git a/vendor/makepad/libs/math/src/shader.rs b/vendor/makepad/libs/math/src/shader.rs deleted file mode 100644 index 1cecc65..0000000 --- a/vendor/makepad/libs/math/src/shader.rs +++ /dev/null @@ -1,316 +0,0 @@ -// shader math glue layer - -pub trait ShaderMath { - fn abs(self) -> Self; - - fn sin(self) -> Self; - fn cos(self) -> Self; - fn tan(self) -> Self; - fn asin(self) -> Self; - fn acos(self) -> Self; - fn atan(self) -> Self; - - fn sinh(self) -> Self; - fn cosh(self) -> Self; - fn tanh(self) -> Self; - fn asinh(self) -> Self; - fn acosh(self) -> Self; - fn atanh(self) -> Self; - - fn fract(self) -> Self; - fn ceil(self) -> Self; - fn floor(self) -> Self; - fn min(self, v: Self) -> Self; - fn max(self, v: Self) -> Self; - fn clamp(self, low: Self, high: Self) -> Self; - fn exp(self) -> Self; - fn exp2(self) -> Self; - fn ln(self) -> Self; - fn log2(self) -> Self; - fn log10(self) -> Self; - fn powf(self, v: Self) -> Self; - fn powi(self, p: i32) -> Self; -} - -impl ShaderMath for f32 { - fn abs(self) -> Self { - self.abs() - } - fn sin(self) -> Self { - self.sin() - } - fn cos(self) -> Self { - self.cos() - } - fn tan(self) -> Self { - self.tan() - } - fn asin(self) -> Self { - self.asin() - } - fn acos(self) -> Self { - self.acos() - } - fn atan(self) -> Self { - self.atan() - } - - fn sinh(self) -> Self { - self.sinh() - } - fn cosh(self) -> Self { - self.cosh() - } - fn tanh(self) -> Self { - self.tanh() - } - fn asinh(self) -> Self { - self.asinh() - } - fn acosh(self) -> Self { - self.acosh() - } - fn atanh(self) -> Self { - self.atanh() - } - - fn fract(self) -> Self { - self.fract() - } - fn ceil(self) -> Self { - self.ceil() - } - fn floor(self) -> Self { - self.floor() - } - fn min(self, v: Self) -> Self { - self.min(v) - } - fn max(self, v: Self) -> Self { - self.max(v) - } - fn clamp(self, low: Self, high: Self) -> Self { - self.max(low).min(high) - } - fn exp(self) -> Self { - self.exp() - } - fn exp2(self) -> Self { - self.exp2() - } - fn ln(self) -> Self { - self.ln() - } - fn log2(self) -> Self { - self.log2() - } - fn log10(self) -> Self { - self.log10() - } - fn powf(self, v: Self) -> Self { - self.powf(v) - } - fn powi(self, v: i32) -> Self { - self.powi(v) - } -} - -impl ShaderMath for f64 { - fn abs(self) -> Self { - self.abs() - } - - fn sin(self) -> Self { - self.sin() - } - fn cos(self) -> Self { - self.cos() - } - fn tan(self) -> Self { - self.tan() - } - fn asin(self) -> Self { - self.asin() - } - fn acos(self) -> Self { - self.acos() - } - fn atan(self) -> Self { - self.atan() - } - - fn sinh(self) -> Self { - self.sinh() - } - fn cosh(self) -> Self { - self.cosh() - } - fn tanh(self) -> Self { - self.tanh() - } - fn asinh(self) -> Self { - self.asinh() - } - fn acosh(self) -> Self { - self.acosh() - } - fn atanh(self) -> Self { - self.atanh() - } - - fn fract(self) -> Self { - self.fract() - } - fn ceil(self) -> Self { - self.ceil() - } - fn floor(self) -> Self { - self.floor() - } - fn min(self, v: Self) -> Self { - self.min(v) - } - fn max(self, v: Self) -> Self { - self.max(v) - } - fn clamp(self, low: Self, high: Self) -> Self { - self.max(low).min(high) - } - fn exp(self) -> Self { - self.exp() - } - fn exp2(self) -> Self { - self.exp2() - } - fn ln(self) -> Self { - self.ln() - } - fn log2(self) -> Self { - self.log2() - } - fn log10(self) -> Self { - self.log10() - } - fn powf(self, v: Self) -> Self { - self.powf(v) - } - fn powi(self, v: i32) -> Self { - self.powi(v) - } -} - -pub fn abs(v: T) -> T { - v.abs() -} - -pub fn sin(v: T) -> T { - v.sin() -} -pub fn cos(v: T) -> T { - v.cos() -} -pub fn tan(v: T) -> T { - v.tan() -} -pub fn asin(v: T) -> T { - v.asin() -} -pub fn acos(v: T) -> T { - v.acos() -} -pub fn atan(v: T) -> T { - v.atan() -} - -pub fn sinh(v: T) -> T { - v.sinh() -} -pub fn cosh(v: T) -> T { - v.cosh() -} -pub fn tanh(v: T) -> T { - v.tanh() -} -pub fn asinh(v: T) -> T { - v.asinh() -} -pub fn acosh(v: T) -> T { - v.acosh() -} -pub fn atanh(v: T) -> T { - v.atanh() -} - -pub fn fract(v: T) -> T { - v.fract() -} -pub fn ceil(v: T) -> T { - v.ceil() -} -pub fn floor(v: T) -> T { - v.floor() -} -pub fn min(v: T, l: T) -> T { - v.min(l) -} -pub fn max(v: T, l: T) -> T { - v.max(l) -} -pub fn clamp(v: T, l: T, h: T) -> T { - v.clamp(l, h) -} -pub fn exp(v: T) -> T { - v.exp() -} -pub fn exp2(v: T) -> T { - v.exp2() -} -pub fn ln(v: T) -> T { - v.ln() -} -pub fn log2(v: T) -> T { - v.log2() -} -pub fn log10(v: T) -> T { - v.log10() -} -pub fn pow(v: T, l: T) -> T { - v.powf(l) -} -pub fn powf(v: T, l: T) -> T { - v.powf(l) -} -pub fn powi(v: T, l: i32) -> T { - v.powi(l) -} - -/* -abs -asin -acos -atan -sin -cos -tan -ceil -floor -min -max -clamp - -exp -exp2 -log -log2 -ln -pow -tanh -fract - -cross -distance -dot -inverse -length -normalize -*/ diff --git a/vendor/makepad/libs/math/src/shader_runtime.rs b/vendor/makepad/libs/math/src/shader_runtime.rs deleted file mode 100644 index 0fbfb77..0000000 --- a/vendor/makepad/libs/math/src/shader_runtime.rs +++ /dev/null @@ -1,742 +0,0 @@ -// Shader runtime types for headless/JIT rendering -// These types mirror GPU shader primitives for CPU-side evaluation - -use crate::math_f32::*; - -// ============================================================ -// Swizzle methods for Vec2f, Vec3f, Vec4f -// Generated to match GLSL swizzle syntax: v.xy(), v.xyz(), etc. -// ============================================================ - -impl Vec2f { - // 2-component swizzles returning Vec2f - pub fn xx(&self) -> Vec2f { - vec2(self.x, self.x) - } - pub fn xy(&self) -> Vec2f { - vec2(self.x, self.y) - } - pub fn yx(&self) -> Vec2f { - vec2(self.y, self.x) - } - pub fn yy(&self) -> Vec2f { - vec2(self.y, self.y) - } - // 3-component swizzles returning Vec3f - pub fn xxx(&self) -> Vec3f { - vec3(self.x, self.x, self.x) - } - pub fn xxy(&self) -> Vec3f { - vec3(self.x, self.x, self.y) - } - pub fn xyx(&self) -> Vec3f { - vec3(self.x, self.y, self.x) - } - pub fn xyy(&self) -> Vec3f { - vec3(self.x, self.y, self.y) - } - pub fn yxx(&self) -> Vec3f { - vec3(self.y, self.x, self.x) - } - pub fn yxy(&self) -> Vec3f { - vec3(self.y, self.x, self.y) - } - pub fn yyx(&self) -> Vec3f { - vec3(self.y, self.y, self.x) - } - pub fn yyy(&self) -> Vec3f { - vec3(self.y, self.y, self.y) - } - // 4-component swizzles returning Vec4f - pub fn xxxx(&self) -> Vec4f { - vec4(self.x, self.x, self.x, self.x) - } - pub fn xxyy(&self) -> Vec4f { - vec4(self.x, self.x, self.y, self.y) - } - pub fn xyxy(&self) -> Vec4f { - vec4(self.x, self.y, self.x, self.y) - } - pub fn yyxx(&self) -> Vec4f { - vec4(self.y, self.y, self.x, self.x) - } -} - -impl Vec3f { - // 2-component swizzles returning Vec2f - pub fn xx(&self) -> Vec2f { - vec2(self.x, self.x) - } - pub fn xy(&self) -> Vec2f { - vec2(self.x, self.y) - } - pub fn xz(&self) -> Vec2f { - vec2(self.x, self.z) - } - pub fn yx(&self) -> Vec2f { - vec2(self.y, self.x) - } - pub fn yy(&self) -> Vec2f { - vec2(self.y, self.y) - } - pub fn yz(&self) -> Vec2f { - vec2(self.y, self.z) - } - pub fn zx(&self) -> Vec2f { - vec2(self.z, self.x) - } - pub fn zy(&self) -> Vec2f { - vec2(self.z, self.y) - } - pub fn zz(&self) -> Vec2f { - vec2(self.z, self.z) - } - // 3-component swizzles returning Vec3f - pub fn xxx(&self) -> Vec3f { - vec3(self.x, self.x, self.x) - } - pub fn xxy(&self) -> Vec3f { - vec3(self.x, self.x, self.y) - } - pub fn xxz(&self) -> Vec3f { - vec3(self.x, self.x, self.z) - } - pub fn xyz(&self) -> Vec3f { - vec3(self.x, self.y, self.z) - } - pub fn xzy(&self) -> Vec3f { - vec3(self.x, self.z, self.y) - } - pub fn yxz(&self) -> Vec3f { - vec3(self.y, self.x, self.z) - } - pub fn yzx(&self) -> Vec3f { - vec3(self.y, self.z, self.x) - } - pub fn zxy(&self) -> Vec3f { - vec3(self.z, self.x, self.y) - } - pub fn zyx(&self) -> Vec3f { - vec3(self.z, self.y, self.x) - } - pub fn zzz(&self) -> Vec3f { - vec3(self.z, self.z, self.z) - } - // 4-component swizzles returning Vec4f - pub fn xxxx(&self) -> Vec4f { - vec4(self.x, self.x, self.x, self.x) - } - pub fn xyzx(&self) -> Vec4f { - vec4(self.x, self.y, self.z, self.x) - } - pub fn xyzz(&self) -> Vec4f { - vec4(self.x, self.y, self.z, self.z) - } - // mix method - pub fn mix(&self, other: Vec3f, t: f32) -> Vec3f { - vec3( - self.x + (other.x - self.x) * t, - self.y + (other.y - self.y) * t, - self.z + (other.z - self.z) * t, - ) - } -} - -impl Vec4f { - // 2-component swizzles returning Vec2f - // Note: xy() and zw() are already defined in math_f32.rs - pub fn xx(&self) -> Vec2f { - vec2(self.x, self.x) - } - pub fn xz(&self) -> Vec2f { - vec2(self.x, self.z) - } - pub fn xw(&self) -> Vec2f { - vec2(self.x, self.w) - } - pub fn yx(&self) -> Vec2f { - vec2(self.y, self.x) - } - pub fn yy(&self) -> Vec2f { - vec2(self.y, self.y) - } - pub fn yz(&self) -> Vec2f { - vec2(self.y, self.z) - } - pub fn yw(&self) -> Vec2f { - vec2(self.y, self.w) - } - pub fn zx(&self) -> Vec2f { - vec2(self.z, self.x) - } - pub fn zy(&self) -> Vec2f { - vec2(self.z, self.y) - } - pub fn zz(&self) -> Vec2f { - vec2(self.z, self.z) - } - pub fn wx(&self) -> Vec2f { - vec2(self.w, self.x) - } - pub fn wy(&self) -> Vec2f { - vec2(self.w, self.y) - } - pub fn wz(&self) -> Vec2f { - vec2(self.w, self.z) - } - pub fn ww(&self) -> Vec2f { - vec2(self.w, self.w) - } - // 3-component swizzles returning Vec3f - pub fn xxx(&self) -> Vec3f { - vec3(self.x, self.x, self.x) - } - pub fn xyz(&self) -> Vec3f { - vec3(self.x, self.y, self.z) - } - pub fn xyw(&self) -> Vec3f { - vec3(self.x, self.y, self.w) - } - pub fn xzy(&self) -> Vec3f { - vec3(self.x, self.z, self.y) - } - pub fn yxz(&self) -> Vec3f { - vec3(self.y, self.x, self.z) - } - pub fn yzw(&self) -> Vec3f { - vec3(self.y, self.z, self.w) - } - pub fn zxy(&self) -> Vec3f { - vec3(self.z, self.x, self.y) - } - pub fn zyx(&self) -> Vec3f { - vec3(self.z, self.y, self.x) - } - pub fn zwx(&self) -> Vec3f { - vec3(self.z, self.w, self.x) - } - pub fn wxy(&self) -> Vec3f { - vec3(self.w, self.x, self.y) - } - pub fn wzx(&self) -> Vec3f { - vec3(self.w, self.z, self.x) - } - pub fn rgb(&self) -> Vec3f { - vec3(self.x, self.y, self.z) - } - // 4-component swizzles returning Vec4f - pub fn xyzw(&self) -> Vec4f { - vec4(self.x, self.y, self.z, self.w) - } - pub fn xxxx(&self) -> Vec4f { - vec4(self.x, self.x, self.x, self.x) - } - pub fn yyyy(&self) -> Vec4f { - vec4(self.y, self.y, self.y, self.y) - } - pub fn zzzz(&self) -> Vec4f { - vec4(self.z, self.z, self.z, self.z) - } - pub fn wwww(&self) -> Vec4f { - vec4(self.w, self.w, self.w, self.w) - } - pub fn wzyx(&self) -> Vec4f { - vec4(self.w, self.z, self.y, self.x) - } - pub fn zyxw(&self) -> Vec4f { - vec4(self.z, self.y, self.x, self.w) - } - pub fn rgba(&self) -> Vec4f { - vec4(self.x, self.y, self.z, self.w) - } -} - -impl Vec2f { - pub fn mix(&self, other: Vec2f, t: f32) -> Vec2f { - vec2( - self.x + (other.x - self.x) * t, - self.y + (other.y - self.y) * t, - ) - } -} - -// ============================================================ -// Texture2D - CPU-side texture sampling -// ============================================================ - -pub struct Texture2D { - pub width: usize, - pub height: usize, - pub data: Vec, // RGBA f32 pixels, row-major -} - -impl Default for Texture2D { - fn default() -> Self { - Self::new() - } -} - -impl Texture2D { - pub fn new() -> Self { - Self { - width: 0, - height: 0, - data: Vec::new(), - } - } - - pub fn from_rgba_f32(width: usize, height: usize, data: Vec) -> Self { - Self { - width, - height, - data, - } - } - - pub fn sample(&self, coord: Vec2f) -> Vec4f { - if self.width == 0 || self.height == 0 || self.data.is_empty() { - return Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }; - } - // Clamp coordinates to [0, 1] - let u = coord.x.max(0.0).min(1.0); - let v = coord.y.max(0.0).min(1.0); - - // Nearest-neighbor sampling - let px = ((u * self.width as f32) as usize).min(self.width - 1); - let py = ((v * self.height as f32) as usize).min(self.height - 1); - let idx = (py * self.width + px) * 4; - - if idx + 3 < self.data.len() { - Vec4f { - x: self.data[idx], - y: self.data[idx + 1], - z: self.data[idx + 2], - w: self.data[idx + 3], - } - } else { - Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - } - } - } - - pub fn sample_r8(&self, coord: Vec2f) -> Vec4f { - if self.width == 0 || self.height == 0 || self.data.is_empty() { - return Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }; - } - let u = coord.x.max(0.0).min(1.0); - let v = coord.y.max(0.0).min(1.0); - let px = ((u * self.width as f32) as usize).min(self.width - 1); - let py = ((v * self.height as f32) as usize).min(self.height - 1); - let idx = py * self.width + px; - if idx < self.data.len() { - let r = self.data[idx]; - Vec4f { - x: r, - y: 0.0, - z: 0.0, - w: 1.0, - } - } else { - Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - } - } - } -} - -// ============================================================ -// Vec4f mix method (shader-style linear interpolation) -// ============================================================ - -impl Vec4f { - pub fn mix(&self, other: Vec4f, t: f32) -> Vec4f { - Vec4f { - x: self.x + (other.x - self.x) * t, - y: self.y + (other.y - self.y) * t, - z: self.z + (other.z - self.z) * t, - w: self.w + (other.w - self.w) * t, - } - } -} - -impl Vec2f { - pub fn atan2(&self) -> f32 { - self.y.atan2(self.x) - } -} - -// ============================================================ -// Shader builtin free functions -// ============================================================ - -pub fn mix_f32(a: f32, b: f32, t: f32) -> f32 { - a + (b - a) * t -} - -pub fn step(edge: f32, x: f32) -> f32 { - if x < edge { - 0.0 - } else { - 1.0 - } -} - -pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 { - let t = ((x - edge0) / (edge1 - edge0)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) -} - -pub fn sign(x: f32) -> f32 { - if x > 0.0 { - 1.0 - } else if x < 0.0 { - -1.0 - } else { - 0.0 - } -} - -pub fn sqrt(x: f32) -> f32 { - x.sqrt() -} - -pub fn inverse_sqrt(x: f32) -> f32 { - 1.0 / x.sqrt() -} - -pub fn inverse(m: Mat4f) -> Mat4f { - m.invert() -} - -pub fn modf(x: f32, y: f32) -> f32 { - x - y * (x / y).floor() -} - -pub fn atan2(y: f32, x: f32) -> f32 { - y.atan2(x) -} - -pub fn distance_2f(a: Vec2f, b: Vec2f) -> f32 { - let dx = a.x - b.x; - let dy = a.y - b.y; - (dx * dx + dy * dy).sqrt() -} - -pub fn length_2f(v: Vec2f) -> f32 { - (v.x * v.x + v.y * v.y).sqrt() -} - -pub fn dot_2f(a: Vec2f, b: Vec2f) -> f32 { - a.x * b.x + a.y * b.y -} - -pub fn normalize_2f(v: Vec2f) -> Vec2f { - let len = length_2f(v); - if len > 0.0 { - Vec2f { - x: v.x / len, - y: v.y / len, - } - } else { - Vec2f { x: 0.0, y: 0.0 } - } -} - -pub fn dot_4f(a: Vec4f, b: Vec4f) -> f32 { - a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w -} - -pub fn length_4f(v: Vec4f) -> f32 { - (v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w).sqrt() -} - -// ============================================================ -// Color conversion functions -// ============================================================ - -pub fn hsv_to_rgb(hsv: Vec4f) -> Vec4f { - let h = hsv.x; - let s = hsv.y; - let v = hsv.z; - - let c = v * s; - let x = c * (1.0 - ((h * 6.0) % 2.0 - 1.0).abs()); - let m = v - c; - - let (r, g, b) = if h < 1.0 / 6.0 { - (c, x, 0.0) - } else if h < 2.0 / 6.0 { - (x, c, 0.0) - } else if h < 3.0 / 6.0 { - (0.0, c, x) - } else if h < 4.0 / 6.0 { - (0.0, x, c) - } else if h < 5.0 / 6.0 { - (x, 0.0, c) - } else { - (c, 0.0, x) - }; - - Vec4f { - x: r + m, - y: g + m, - z: b + m, - w: hsv.w, - } -} - -// ============================================================ -// Sdf2d - 2D signed distance field for CPU-side shape rendering -// ============================================================ - -pub struct Sdf2d { - pub pos: Vec2f, - pub result: Vec4f, - pub last_pos: Vec2f, - pub start_pos: Vec2f, - pub shape: f32, - pub clip: f32, - pub has_clip: bool, - pub old_shape: f32, - pub blur: f32, - pub aa: f32, - pub scale_factor: f32, - pub dist: f32, -} - -impl Sdf2d { - pub fn viewport_f2(pos: Vec2f) -> Self { - Self { - pos, - result: Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }, - last_pos: Vec2f { x: 0.0, y: 0.0 }, - start_pos: Vec2f { x: 0.0, y: 0.0 }, - shape: 1e+20f32, - clip: -1e+20f32, - has_clip: false, - old_shape: 1e+20f32, - blur: 0.00001, - aa: 1.5, - scale_factor: 1.0, - dist: 0.0, - } - } - - // --- Shape primitives --- - - pub fn circle_f3(&mut self, x: f32, y: f32, r: f32) { - let dx = self.pos.x - x; - let dy = self.pos.y - y; - let d = (dx * dx + dy * dy).sqrt() - r; - self.shape = d; - self.clip = d; - self.has_clip = false; - self.old_shape = d; - } - - pub fn box_f4(&mut self, x: f32, y: f32, w: f32, h: f32, r: f32) { - let cx = x + w * 0.5; - let cy = y + h * 0.5; - let dx = (self.pos.x - cx).abs() - w * 0.5; - let dy = (self.pos.y - cy).abs() - h * 0.5; - let d = dx.max(0.0).hypot(dy.max(0.0)) + dx.max(dy).min(0.0) - r; - self.shape = d; - self.clip = d; - self.has_clip = false; - self.old_shape = d; - } - - pub fn rect_f4(&mut self, x: f32, y: f32, w: f32, h: f32) { - let cx = x + w * 0.5; - let cy = y + h * 0.5; - let dx = (self.pos.x - cx).abs() - w * 0.5; - let dy = (self.pos.y - cy).abs() - h * 0.5; - let d = dx.max(0.0).hypot(dy.max(0.0)) + dx.max(dy).min(0.0); - self.shape = d; - self.clip = d; - self.has_clip = false; - self.old_shape = d; - } - - pub fn hexagon_f3(&mut self, x: f32, y: f32, r: f32) { - let dx = (self.pos.x - x).abs(); - let dy = (self.pos.y - y).abs(); - let d = (dx * 0.866025 + dy * 0.5).max(dy) - r; - self.shape = d; - self.clip = d; - self.has_clip = false; - self.old_shape = d; - } - - // --- Path operations --- - - pub fn move_to(&mut self, x: f32, y: f32) { - self.last_pos = Vec2f { x, y }; - self.start_pos = Vec2f { x, y }; - self.shape = 1e+20f32; - self.clip = -1e+20f32; - self.has_clip = false; - self.old_shape = 1e+20f32; - } - - pub fn move_to_f2(&mut self, x: f32, y: f32) { - self.move_to(x, y); - } - - pub fn line_to(&mut self, x: f32, y: f32) { - let target = Vec2f { x, y }; - let pa = Vec2f { - x: self.pos.x - self.last_pos.x, - y: self.pos.y - self.last_pos.y, - }; - let ba = Vec2f { - x: target.x - self.last_pos.x, - y: target.y - self.last_pos.y, - }; - let dot_ba = ba.x * ba.x + ba.y * ba.y; - let h = if dot_ba > 0.0 { - ((pa.x * ba.x + pa.y * ba.y) / dot_ba).max(0.0).min(1.0) - } else { - 0.0 - }; - let diff = Vec2f { - x: pa.x - ba.x * h, - y: pa.y - ba.y * h, - }; - let d = (diff.x * diff.x + diff.y * diff.y).sqrt(); - self.shape = self.shape.min(d); - self.old_shape = self.shape; - self.last_pos = target; - } - - pub fn close_path(&mut self) { - self.line_to(self.start_pos.x, self.start_pos.y); - } - - // --- Boolean operations --- - - pub fn union(&mut self) { - self.old_shape = self.old_shape.min(self.shape); - self.shape = self.old_shape; - } - - pub fn intersect(&mut self) { - self.old_shape = self.old_shape.max(self.shape); - self.shape = self.old_shape; - } - - pub fn subtract(&mut self) { - self.old_shape = (-self.shape).max(self.old_shape); - self.shape = self.old_shape; - } - - // --- Fill and stroke --- - - pub fn fill_keep(&mut self, color: Vec4f) -> Vec4f { - let d = self.shape; - let aa = self.aa; - let alpha = (-d / aa + 0.5).max(0.0).min(1.0); - let premul = Vec4f { - x: color.x * color.w * alpha, - y: color.y * color.w * alpha, - z: color.z * color.w * alpha, - w: color.w * alpha, - }; - let inv_a = 1.0 - premul.w; - self.result = Vec4f { - x: premul.x + self.result.x * inv_a, - y: premul.y + self.result.y * inv_a, - z: premul.z + self.result.z * inv_a, - w: premul.w + self.result.w * inv_a, - }; - self.result - } - - pub fn fill(&mut self, color: Vec4f) -> Vec4f { - let res = self.fill_keep(color); - self.old_shape = 1e+20f32; - self.shape = 1e+20f32; - self.clip = -1e+20f32; - self.has_clip = false; - res - } - - pub fn stroke_keep(&mut self, color: Vec4f, width: f32) -> Vec4f { - let d = (self.shape.abs() - width * 0.5).max(0.0); - let aa = self.aa; - let alpha = (-d / aa + 0.5).max(0.0).min(1.0); - let premul = Vec4f { - x: color.x * color.w * alpha, - y: color.y * color.w * alpha, - z: color.z * color.w * alpha, - w: color.w * alpha, - }; - let inv_a = 1.0 - premul.w; - self.result = Vec4f { - x: premul.x + self.result.x * inv_a, - y: premul.y + self.result.y * inv_a, - z: premul.z + self.result.z * inv_a, - w: premul.w + self.result.w * inv_a, - }; - self.result - } - - pub fn stroke(&mut self, color: Vec4f, width: f32) -> Vec4f { - let res = self.stroke_keep(color, width); - self.old_shape = 1e+20f32; - self.shape = 1e+20f32; - self.clip = -1e+20f32; - self.has_clip = false; - res - } - - pub fn glow_keep(&mut self, color: Vec4f, width: f32) -> Vec4f { - let d = self.shape.abs(); - let alpha = (-(d * d) / (width * width * 0.1)).exp(); - let premul = Vec4f { - x: color.x * color.w * alpha, - y: color.y * color.w * alpha, - z: color.z * color.w * alpha, - w: color.w * alpha, - }; - let inv_a = 1.0 - premul.w; - self.result = Vec4f { - x: premul.x + self.result.x * inv_a, - y: premul.y + self.result.y * inv_a, - z: premul.z + self.result.z * inv_a, - w: premul.w + self.result.w * inv_a, - }; - self.result - } - - pub fn glow(&mut self, color: Vec4f, width: f32) -> Vec4f { - let res = self.glow_keep(color, width); - self.old_shape = 1e+20f32; - self.shape = 1e+20f32; - self.clip = -1e+20f32; - self.has_clip = false; - res - } -} diff --git a/vendor/makepad/libs/micro_proc_macro/Cargo.toml b/vendor/makepad/libs/micro_proc_macro/Cargo.toml deleted file mode 100644 index 9634985..0000000 --- a/vendor/makepad/libs/micro_proc_macro/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "makepad-micro-proc-macro" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad micro proc macro util lib" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "2tKeN-afCtZGYbB_BxPOVxkh0W4=" diff --git a/vendor/makepad/libs/micro_proc_macro/src/lib.rs b/vendor/makepad/libs/micro_proc_macro/src/lib.rs deleted file mode 100644 index eb0fed8..0000000 --- a/vendor/makepad/libs/micro_proc_macro/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod macro_lib; -pub use macro_lib::*; diff --git a/vendor/makepad/libs/micro_proc_macro/src/macro_lib.rs b/vendor/makepad/libs/micro_proc_macro/src/macro_lib.rs deleted file mode 100644 index c64e806..0000000 --- a/vendor/makepad/libs/micro_proc_macro/src/macro_lib.rs +++ /dev/null @@ -1,962 +0,0 @@ -#![allow(dead_code)] -extern crate proc_macro; -use proc_macro::token_stream::IntoIter; -use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; - -#[derive(Clone, Default, Eq, Hash, Copy, Ord, PartialOrd, PartialEq)] -pub struct LiveId(pub u64); - -impl LiveId { - pub const SEED: u64 = 0xd6e8_feb8_6659_fd93; - pub const ARRAY: u64 = 0x0000_2000_0000_0000; - // from https://nullprogram.com/blog/2018/07/31/ - // i have no idea what im doing with start value and finalisation. - pub const fn from_bytes(seed: u64, id_bytes: &[u8], start: usize, end: usize, or: u64) -> Self { - let mut x = seed; - let mut i = start; - while i < end { - x = x.overflowing_add(id_bytes[i] as u64).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0; - x ^= x >> 32; - i += 1; - } - // truncate to 45 bits fitting in a NaN box - Self((x & 0x0000_3fff_ffff_ffff) | or) - } - - pub const fn from_str(id_str: &str) -> Self { - let bytes = id_str.as_bytes(); - if bytes.len() > 0 && bytes[0] == b'$' { - Self::from_bytes(Self::SEED, bytes, 0, bytes.len(), Self::ARRAY) - } else { - Self::from_bytes(Self::SEED, bytes, 0, bytes.len(), 0) - } - } -} - -// little macro utility lib - -pub fn error_span(err: &str, span: Span) -> TokenStream { - let mut tb = TokenBuilder::new(); - tb.ident_with_span("compile_error", span) - .add("! (") - .string(err) - .add(") ;"); - tb.end() -} - -pub fn error(err: &str) -> TokenStream { - let mut tb = TokenBuilder::new(); - tb.add("compile_error ! (").string(err).add(") ;"); - tb.end() -} - -pub fn error_result(err: &str) -> Result<(), TokenStream> { - let mut tb = TokenBuilder::new(); - tb.add("compile_error ! (").string(err).add(") ;"); - Err(tb.end()) -} - -pub fn unwrap_option(input: TokenStream) -> Result { - let mut ty_parser = TokenParser::new(input.clone()); - if ty_parser.eat_ident("Option") { - if !ty_parser.eat_punct_alone('<') { - panic!() - } - Ok(ty_parser.eat_level_or_punct('>')) - } else { - Err(input) - } -} - -pub struct TokenBuilder { - pub groups: Vec<(Delimiter, TokenStream)>, -} - -impl TokenBuilder { - pub fn new() -> Self { - Self { - groups: vec![(Delimiter::None, TokenStream::new())], - } - } - - pub fn is_empty(&self) -> bool { - self.groups.len() == 1 && self.groups[0].1.is_empty() - } - - pub fn end(mut self) -> TokenStream { - if self.groups.len() != 1 { - panic!("Groups not empty, you missed a pop_group") - } - self.groups.pop().unwrap().1 - } - - pub fn eprint(&self) { - eprintln!("{}", self.groups.last().unwrap().1.to_string()); - } - - pub fn extend(&mut self, tt: TokenTree) -> &mut Self { - self.groups.last_mut().unwrap().1.extend(Some(tt)); - self - } - - pub fn stream(&mut self, what: Option) -> &mut Self { - if let Some(what) = what { - for c in what.into_iter() { - self.extend(c); - } - self - } else { - self - } - } - - pub fn add(&mut self, what: &str) -> &mut Self { - let b = what.as_bytes(); - let mut o = 0; - while o < b.len() { - let c0 = b[o] as char; - let c1 = if o + 1 < b.len() { - b[o + 1] as char - } else { - '\0' - }; - match (c0, c1) { - ('\r', _) | ('\n', _) | (' ', _) | ('\t', _) => { - o += 1; - } - ('{', _) => { - self.push_group(Delimiter::Brace); - o += 1; - } - ('(', _) => { - self.push_group(Delimiter::Parenthesis); - o += 1; - } - ('[', _) => { - self.push_group(Delimiter::Bracket); - o += 1; - } - ('}', _) => { - self.pop_group(Delimiter::Brace); - o += 1; - } - (')', _) => { - self.pop_group(Delimiter::Parenthesis); - o += 1; - } - (']', _) => { - self.pop_group(Delimiter::Bracket); - o += 1; - } - ('<', '<') - | ('>', '>') - | ('&', '&') - | ('|', '|') - | ('-', '>') - | ('=', '>') - | ('<', '=') - | ('>', '=') - | ('=', '=') - | ('!', '=') - | (':', ':') - | ('+', '=') - | ('-', '=') - | ('*', '=') - | ('/', '=') - | ('.', '.') => { - self.punct(std::str::from_utf8(&b[o..o + 2]).unwrap()); - o += 2; - } - ('$', _) - | ('+', _) - | ('-', _) - | ('*', _) - | ('/', _) - | ('#', _) - | ('=', _) - | ('<', _) - | ('>', _) - | ('?', _) - | (';', _) - | ('&', _) - | ('^', _) - | (':', _) - | (',', _) - | ('!', _) - | ('.', _) - | ('|', _) => { - self.punct(std::str::from_utf8(&b[o..o + 1]).unwrap()); - o += 1; - } - ('0', 'x') => { - // this needs to be fancier but whatever. - let mut e = o + 2; - let mut out: u64 = 0; - while e < b.len() { - match b[e] { - b'0'..=b'9' => out = (out << 4) | (b[e] - b'0') as u64, - b'a'..=b'f' => out = (out << 4) | (b[e] - b'a' + 10) as u64, - b'A'..=b'F' => out = (out << 4) | (b[e] - b'A' + 10) as u64, - b'_' => (), - _ => break, - }; - e += 1; - } - self.suf_u64(out); - o = e; - } - ('0'..='9', _) => { - let mut e = o + 1; - while e < b.len() { - match b[e] { - b'0'..=b'9' => e += 1, - _ => break, - } - } - let num = std::str::from_utf8(&b[o..e]).unwrap(); - self.unsuf_usize( - num.parse() - .unwrap_or_else(|_| panic!("Can't parse usize number \"{}\"", what)), - ); - o = e; - } - ('"', _) => { - let mut e = o + 1; - while e < b.len() { - match b[e] { - b'"' => break, - _ => e += 1, - } - } - self.string(std::str::from_utf8(&b[o + 1..e]).unwrap()); - o = e + 1; - } - ('\'', _) => { - let mut e = o + 1; - while e < b.len() { - match b[e] { - b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' => e += 1, - _ => break, - } - } - if o == e { - panic!("Unexpected character {:?}", b[e] as char); - } - let ident = std::str::from_utf8(&b[o + 1..e]).unwrap(); - self.lifetime_mark(); - self.ident(ident); - o = e; - } - _ => { - let mut e = o; - while e < b.len() { - match b[e] { - b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' => e += 1, - _ => break, - } - } - if o == e { - panic!("Unexpected character {:?}", b[e] as char); - } - let ident = std::str::from_utf8(&b[o..e]).unwrap(); - self.ident(ident); - o = e; - } - } - } - self - } - - pub fn ident(&mut self, id: &str) -> &mut Self { - self.extend(TokenTree::from(Ident::new(id, Span::call_site()))) - } - - pub fn ident_with_span(&mut self, id: &str, span: Span) -> &mut Self { - self.extend(TokenTree::from(Ident::new(id, span))) - } - - pub fn punct(&mut self, s: &str) -> &mut Self { - for (last, c) in s.chars().identify_last() { - self.extend(TokenTree::from(Punct::new( - c, - if last { Spacing::Alone } else { Spacing::Joint }, - ))); - } - self - } - - pub fn lifetime_mark(&mut self) -> &mut Self { - self.extend(TokenTree::from(Punct::new('\'', Spacing::Joint))); - self - } - - pub fn sep(&mut self) -> &mut Self { - self.extend(TokenTree::from(Punct::new(':', Spacing::Joint))); - self.extend(TokenTree::from(Punct::new(':', Spacing::Alone))); - self - } - - pub fn string(&mut self, val: &str) -> &mut Self { - self.extend(TokenTree::from(Literal::string(val))) - } - pub fn unsuf_usize(&mut self, val: usize) -> &mut Self { - self.extend(TokenTree::from(Literal::usize_unsuffixed(val))) - } - pub fn suf_u16(&mut self, val: u16) -> &mut Self { - self.extend(TokenTree::from(Literal::u16_suffixed(val))) - } - pub fn suf_u32(&mut self, val: u32) -> &mut Self { - self.extend(TokenTree::from(Literal::u32_suffixed(val))) - } - pub fn suf_u64(&mut self, val: u64) -> &mut Self { - self.extend(TokenTree::from(Literal::u64_suffixed(val))) - } - pub fn unsuf_f32(&mut self, val: f32) -> &mut Self { - self.extend(TokenTree::from(Literal::f32_unsuffixed(val))) - } - pub fn unsuf_f64(&mut self, val: f64) -> &mut Self { - self.extend(TokenTree::from(Literal::f64_unsuffixed(val))) - } - pub fn unsuf_i64(&mut self, val: i64) -> &mut Self { - self.extend(TokenTree::from(Literal::i64_unsuffixed(val))) - } - - pub fn chr(&mut self, val: char) -> &mut Self { - self.extend(TokenTree::from(Literal::character(val))) - } - pub fn _lit(&mut self, lit: Literal) -> &mut Self { - self.extend(TokenTree::from(lit)) - } - - pub fn push_group(&mut self, delim: Delimiter) -> &mut Self { - self.groups.push((delim, TokenStream::new())); - self - } - - pub fn stack_as_string(&self) -> String { - let mut ret = String::new(); - for i in (0..self.groups.len() - 1).rev() { - ret.push_str(&format!("Level {}: {}", i, self.groups[i].1.to_string())); - } - ret - } - - pub fn pop_group(&mut self, delim: Delimiter) -> &mut Self { - if self.groups.len() < 2 { - eprintln!("Stack dump for error:\n{}", self.stack_as_string()); - panic!("pop_group stack is empty {}", self.groups.len()); - } - let ts = self.groups.pop().unwrap(); - if ts.0 != delim { - eprintln!("Stack dump for error:\n{}", self.stack_as_string()); - panic!( - "pop_group Delimiter mismatch, got {:?} expected {:?}", - ts.0, delim - ); - } - self.extend(TokenTree::from(Group::new(delim, ts.1))); - self - } -} - -impl Default for TokenBuilder { - fn default() -> Self { - Self::new() - } -} - -pub trait IdentifyLast: Iterator + Sized { - fn identify_last(self) -> Iter; -} - -impl IdentifyLast for It -where - It: Iterator, -{ - fn identify_last(mut self) -> Iter { - let e = self.next(); - Iter { - iter: self, - buffer: e, - } - } -} - -pub struct Iter -where - It: Iterator, -{ - iter: It, - buffer: Option, -} - -#[derive(Debug)] -pub struct Attribute { - pub name: String, - pub args: Option, -} - -pub struct StructField { - pub name: String, - pub ty: TokenStream, - pub attrs: Vec, -} - -impl Iterator for Iter -where - It: Iterator, -{ - type Item = (bool, It::Item); - - fn next(&mut self) -> Option { - match self.buffer.take() { - None => None, - Some(e) => match self.iter.next() { - None => Some((true, e)), - Some(f) => { - self.buffer = Some(f); - Some((false, e)) - } - }, - } - } -} - -pub struct TokenParser { - iter_stack: Vec, - pub current: Option, -} - -// this parser is optimized for parsing type definitions, not general Rust code - -impl TokenParser { - pub fn new(start: TokenStream) -> Self { - let mut ret = Self { - iter_stack: vec![start.into_iter()], - current: None, - }; - ret.advance(); - ret - } - - pub fn advance(&mut self) { - let last = self.iter_stack.last_mut().unwrap(); - let value = last.next(); - if let Some(tok) = value { - self.current = Some(tok); - } else { - self.current = None; - } - // skip over /// - } - - pub fn unexpected(&self) -> TokenStream { - error("Unexpected token") - } - - pub fn is_delim(&mut self, delim: Delimiter) -> bool { - if let Some(TokenTree::Group(group)) = &self.current { - group.delimiter() == delim - } else { - false - } - } - - pub fn is_brace(&mut self) -> bool { - self.is_delim(Delimiter::Brace) - } - - pub fn is_paren(&mut self) -> bool { - self.is_delim(Delimiter::Parenthesis) - } - - pub fn is_bracket(&mut self) -> bool { - self.is_delim(Delimiter::Bracket) - } - - pub fn open_delim(&mut self, delim: Delimiter) -> bool { - if let Some(TokenTree::Group(group)) = &self.current { - if group.delimiter() == delim { - self.iter_stack.push(group.stream().into_iter()); - self.advance(); - return true; - } - } - false - } - - pub fn is_group_with_delim(&mut self, delim: Delimiter) -> bool { - if let Some(TokenTree::Group(group)) = &self.current { - delim == group.delimiter() - } else { - false - } - } - - pub fn open_group(&mut self) -> Option { - if let Some(TokenTree::Group(group)) = &self.current { - let delim = group.delimiter(); - self.iter_stack.push(group.stream().into_iter()); - self.advance(); - return Some(delim); - } - None - } - - pub fn open_brace(&mut self) -> bool { - self.open_delim(Delimiter::Brace) - } - - pub fn open_paren(&mut self) -> bool { - self.open_delim(Delimiter::Parenthesis) - } - - pub fn open_bracket(&mut self) -> bool { - self.open_delim(Delimiter::Bracket) - } - - pub fn is_eot(&mut self) -> bool { - self.current.is_none() && !self.iter_stack.is_empty() - } - - pub fn eat_eot(&mut self) -> bool { - // current is None - if self.is_eot() { - self.iter_stack.pop(); - if !self.iter_stack.is_empty() { - self.advance() - } - return true; - } - false - } - - pub fn eat_level(&mut self) -> TokenStream { - let mut tb = TokenBuilder::new(); - while !self.eat_eot() { - tb.extend(self.current.clone().unwrap()); - self.advance(); - } - tb.end() - } - - pub fn eat_level_or_punct(&mut self, what: char) -> TokenStream { - let mut tb = TokenBuilder::new(); - while !self.eat_eot() { - if self.is_punct_alone(what) { - self.advance(); - return tb.end(); - } - tb.extend(self.current.clone().unwrap()); - self.advance(); - } - tb.end() - } - - pub fn eat_ident(&mut self, what: &str) -> bool { - // check if our current thing is an ident, ifso eat it. - if let Some(TokenTree::Ident(ident)) = &self.current { - if ident.to_string() == what { - self.advance(); - return true; - } - } - false - } - - pub fn is_literal(&mut self) -> bool { - // check if our current thing is an ident, ifso eat it. - if let Some(TokenTree::Literal(_)) = &self.current { - return true; - } - false - } - - pub fn eat_literal(&mut self) -> Option { - // check if our current thing is an ident, ifso eat it. - if let Some(TokenTree::Literal(lit)) = &self.current { - let ret = Some(lit.clone()); - self.advance(); - return ret; - } - None - } - - pub fn span(&self) -> Option { - self.current.as_ref().map(|current| current.span()) - } - - pub fn is_punct_alone(&mut self, what: char) -> bool { - // check if our punct is multichar. - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == what - && (current.as_char() == '>' || current.spacing() == Spacing::Alone) - { - return true; - } - } - false - } - - pub fn is_punct_any(&mut self, what: char) -> bool { - // check if our punct is multichar. - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == what { - return true; - } - } - false - } - - pub fn eat_double_colon_destruct(&mut self) -> bool { - // check if our punct is multichar. - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == ':' && current.spacing() == Spacing::Joint { - self.advance(); - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == ':' && current.spacing() == Spacing::Alone { - self.advance(); - return true; - } - } - } - } - false - } - - pub fn eat_sep(&mut self) -> bool { - // check if our punct is multichar. - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == ':' && current.spacing() == Spacing::Joint { - self.advance(); - if let Some(TokenTree::Punct(current)) = &self.current { - if current.as_char() == ':' && current.spacing() == Spacing::Alone { - self.advance(); - return true; - } - } - } - } - false - } - - pub fn eat_punct_alone(&mut self, what: char) -> bool { - if self.is_punct_alone(what) { - self.advance(); - return true; - } - false - } - - pub fn eat_punct_any(&mut self, what: char) -> bool { - if self.is_punct_any(what) { - self.advance(); - return true; - } - false - } - - pub fn eat_any_punct(&mut self) -> Option { - let mut out = String::new(); - while let Some(TokenTree::Punct(current)) = &self.current { - out.push(current.as_char()); - if current.spacing() == Spacing::Alone { - self.advance(); - return Some(out); - } - self.advance(); - } - None - } - - pub fn eat_any_ident(&mut self) -> Option { - if let Some(TokenTree::Ident(ident)) = &self.current { - let ret = Some(ident.to_string()); - self.advance(); - return ret; - } - None - } - - pub fn eat_any_ident_with_span(&mut self) -> Option<(String, Span)> { - if let Some(TokenTree::Ident(ident)) = &self.current { - let ret = Some((ident.to_string(), self.span().unwrap())); - self.advance(); - return ret; - } - None - } - - pub fn expect_any_ident(&mut self) -> Result { - if let Some(TokenTree::Ident(ident)) = &self.current { - let ret = ident.to_string(); - self.advance(); - return Ok(ret); - } - Err(error("Expected any ident")) - } - - pub fn expect_punct_alone(&mut self, what: char) -> Result<(), TokenStream> { - if self.is_punct_alone(what) { - self.advance(); - Ok(()) - } else { - Err(error(&format!("Expected punct {}", what))) - } - } - - pub fn expect_punct_any(&mut self, what: char) -> Result<(), TokenStream> { - if self.is_punct_any(what) { - self.advance(); - Ok(()) - } else { - Err(error(&format!("Expected punct {}", what))) - } - } - - pub fn eat_ident_path(&mut self) -> Option { - let mut tb = TokenBuilder::new(); - while let Some(ident) = self.eat_any_ident() { - tb.ident(&ident); - if !self.eat_sep() { - break; - } - tb.sep(); - } - - let ts = tb.end(); - if !ts.is_empty() { - return Some(ts); - } - None - } - - pub fn eat_where_clause(&mut self, add_where: Option<&str>) -> Option { - let mut tb = TokenBuilder::new(); - if self.eat_ident("where") { - tb.add("where"); - // ok now we parse an ident - loop { - if let Some(ident) = self.eat_any_ident() { - tb.ident(&ident); - tb.stream(self.eat_generic()); - - if !self.eat_punct_alone(':') { - return None; - } - tb.add(":"); - loop { - if let Some(ident) = self.eat_any_ident() { - tb.add(&ident); - tb.stream(self.eat_generic()); - // check if we have upnext - // {, + or , - if self.eat_punct_alone('+') { - tb.add("+"); - continue; - } - if self.eat_punct_alone(',') { - // next one - if let Some(add_where) = add_where { - tb.add("+"); - tb.ident(add_where); - } - tb.add(","); - break; - } - if self.is_brace() || self.is_punct_alone(';') { - // upnext is a brace.. we're done - if let Some(add_where) = add_where { - tb.add("+"); - tb.ident(add_where); - } - return Some(tb.end()); - } - } else { - return None; // unexpected - } - } - } else { - return None; // unexpected - } - } - } - None - } - - pub fn eat_struct_field(&mut self) -> Option { - // letsparse an ident - let attrs = self.eat_attributes(); - - self.eat_ident("pub"); - if let Some(field) = self.eat_any_ident() { - if self.eat_punct_alone(':') { - if let Some(ty) = self.eat_type() { - return Some(StructField { - name: field, - ty, - attrs, - }); - } - } - } - None - } - - pub fn eat_attributes(&mut self) -> Vec { - let mut results = Vec::new(); - while self.eat_punct_alone('#') { - // parse our attribute - if !self.open_bracket() { - break; - } - let mut assign_form = false; - while let Some(ident) = self.eat_any_ident() { - // we might have an = - if self.eat_punct_alone('=') { - let level = self.eat_level(); - results.push(Attribute { - name: ident, - args: Some(level), - }); - //eprintln!("{} {}", results.last().unwrap().name, results.last().as_ref().unwrap().args.as_ref().unwrap().to_string()); - assign_form = true; - break; - } - if !self.open_paren() && !self.open_brace() { - results.push(Attribute { - name: ident, - args: None, - }); - break; - } - // lets take the whole ts - results.push(Attribute { - name: ident, - args: Some(self.eat_level()), - }); - self.eat_punct_alone(','); - } - if !assign_form && !self.eat_eot() { - break; - } - } - results - } - - pub fn eat_all_struct_fields(&mut self) -> Option> { - if self.open_brace() { - let mut fields = Vec::new(); - while !self.eat_eot() { - // lets eat an attrib - if let Some(sf) = self.eat_struct_field() { - fields.push(sf); - self.eat_punct_alone(','); - } else { - return None; - } - } - return Some(fields); - } - None - } - - pub fn eat_generic(&mut self) -> Option { - let mut tb = TokenBuilder::new(); - // if we have a <, keep running and keep a < stack - - if self.eat_punct_alone('<') { - tb.add("<"); - let mut stack = 1; - // keep eating things till we are at stack 0 for a ">" - while stack > 0 { - if self.eat_punct_alone('<') { - tb.add("<"); - stack += 1; - } - if self.eat_punct_alone('>') { - tb.add(">"); - stack -= 1; - } else if self.eat_eot() { - // shits broken - return None; - } else { - // store info here in generics struct - if let Some(current) = &self.current { - tb.extend(current.clone()); - } - self.advance(); - } - } - - return Some(tb.end()); - } - None - } - - pub fn eat_all_types(&mut self) -> Option> { - if self.open_paren() { - let mut ret = Vec::new(); - while !self.eat_eot() { - self.eat_ident("pub"); - if let Some(tt) = self.eat_type() { - ret.push(tt); - self.eat_punct_alone(','); - } else { - return None; - } - } - Some(ret) - } else { - None - } - } - - pub fn eat_type(&mut self) -> Option { - let mut tb = TokenBuilder::new(); - if self.eat_punct_alone('&') { - tb.add("&"); - if self.eat_punct_any('\'') { - tb.lifetime_mark(); - if let Some((ty, span)) = self.eat_any_ident_with_span() { - tb.ident_with_span(&ty, span); - } - } - } - if self.open_bracket() { - // array type - tb.add("["); - while !self.eat_eot() { - if let Some(current) = &self.current { - tb.extend(current.clone()); - } - self.advance(); - } - tb.add("]"); - return Some(tb.end()); - } else if self.open_paren() { - // tuple type - tb.add("("); - while !self.eat_eot() { - tb.stream(self.eat_type()); - self.eat_punct_alone(','); - } - tb.add(")"); - return Some(tb.end()); - } else if let Some((ty, span)) = self.eat_any_ident_with_span() { - tb.ident_with_span(&ty, span); - if ty == "dyn" { - if let Some((ty, span)) = self.eat_any_ident_with_span() { - tb.ident_with_span(&ty, span); - } - } - tb.stream(self.eat_generic()); - return Some(tb.end()); - } - None - } -} diff --git a/vendor/makepad/libs/micro_serde/Cargo.toml b/vendor/makepad/libs/micro_serde/Cargo.toml deleted file mode 100644 index b3baad7..0000000 --- a/vendor/makepad/libs/micro_serde/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "makepad-micro-serde" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad micro replacement for serde" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "yK9xdn_D0D3EdqleI-WHLtjk4rk=" - -[dependencies] -makepad-micro-serde-derive = { path = "derive", version = "1.0.0" } -makepad-live-id = {path = "../live_id", version = "1.0.0" } diff --git a/vendor/makepad/libs/micro_serde/derive/Cargo.toml b/vendor/makepad/libs/micro_serde/derive/Cargo.toml deleted file mode 100644 index 301b538..0000000 --- a/vendor/makepad/libs/micro_serde/derive/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "makepad-micro-serde-derive" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad micro serde derive macro" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "tSPvEgfuhrUzpofjMUEzGZksHSo=" - -[lib] -proc-macro = true - -[dependencies] -makepad-micro-proc-macro = { path = "../../micro_proc_macro", version = "1.0.0" } - diff --git a/vendor/makepad/libs/micro_serde/derive/src/derive_bin.rs b/vendor/makepad/libs/micro_serde/derive/src/derive_bin.rs deleted file mode 100644 index 6617717..0000000 --- a/vendor/makepad/libs/micro_serde/derive/src/derive_bin.rs +++ /dev/null @@ -1,200 +0,0 @@ -use makepad_micro_proc_macro::*; -use proc_macro::TokenStream; - -pub fn derive_ser_bin_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("SerBin")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerBin for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn ser_bin ( & self , s : & mut Vec < u8 > ) {"); - - if let Some(types) = types { - for i in 0..types.len() { - tb.add("self .").unsuf_usize(i).add(". ser_bin ( s ) ;"); - } - } else if let Some(fields) = parser.eat_all_struct_fields() { - for field in fields { - tb.add("self .").ident(&field.name).add(". ser_bin ( s ) ;"); - } - } else { - return parser.unexpected(); - } - tb.add("} } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("SerBin")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerBin for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn ser_bin ( & self , s : & mut Vec < u8 > ) {"); - tb.add("match self {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - let mut index = 0; - while !parser.eat_eot() { - parser.eat_attributes(); - // parse ident - if let Some(variant) = parser.eat_any_ident() { - if let Some(types) = parser.eat_all_types() { - tb.add("Self ::").ident(&variant).add("("); - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(","); - } - tb.add(") => {").suf_u16(index).add(". ser_bin ( s ) ;"); - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(". ser_bin ( s ) ;"); - } - tb.add("}"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.add("Self ::").ident(&variant).add("{"); - for field in fields.iter() { - tb.ident(&field.name).add(","); - } - tb.add("} => {").suf_u16(index).add(". ser_bin ( s ) ;"); - for field in fields { - tb.ident(&field.name).add(". ser_bin ( s ) ;"); - } - tb.add("}"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.add("Self ::").ident(&variant).add("=> {"); - tb.suf_u16(index).add(". ser_bin ( s ) ; }"); - } else { - return parser.unexpected(); - } - index += 1; - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add("} } } ;"); - return tb.end(); - } - } - parser.unexpected() -} - -pub fn derive_de_bin_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("DeBin")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeBin for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_bin ( o : & mut usize , d : & [ u8 ] )"); - tb.add("-> std :: result :: Result < Self , DeBinErr > { "); - tb.add("std :: result :: Result :: Ok ( Self"); - - if let Some(types) = types { - tb.add("("); - for _ in 0..types.len() { - tb.add("DeBin :: de_bin ( o , d ) ? ,"); - } - tb.add(")"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - tb.add("{"); - for field in fields { - tb.ident(&field.name).add(": DeBin :: de_bin ( o , d ) ? ,"); - } - tb.add("}"); - } else { - return parser.unexpected(); - } - tb.add(") } } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("DeBin")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeBin for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_bin ( o : & mut usize , d : & [ u8 ] )"); - tb.add("-> std :: result :: Result < Self , DeBinErr > {"); - tb.add("let id : u16 = DeBin :: de_bin ( o , d ) ? ;"); - tb.add("match id {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - let mut index = 0; - while !parser.eat_eot() { - // parse ident - parser.eat_attributes(); - if let Some(variant) = parser.eat_any_ident() { - tb.suf_u16(index as u16).add("=> {"); - tb.add("std :: result :: Result :: Ok ( Self ::"); - if let Some(types) = parser.eat_all_types() { - tb.ident(&variant).add("("); - for _ in 0..types.len() { - tb.add("DeBin :: de_bin ( o , d ) ? ,"); - } - tb.add(")"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.ident(&variant).add("{"); - for field in fields.iter() { - tb.ident(&field.name).add(": DeBin :: de_bin ( o , d ) ? ,"); - } - tb.add("}"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.ident(&variant); - } else { - return parser.unexpected(); - } - - tb.add(") }"); - index += 1; - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add("_ => std :: result :: Result :: Err ( DeBinErr { o : * o , l :"); - tb.unsuf_usize(1) - .add(", s : d . len ( ) , msg : ") - .string(&name) - .add(". to_string ( ) } )"); - tb.add("} } } ;"); - return tb.end(); - } - } - parser.unexpected() -} diff --git a/vendor/makepad/libs/micro_serde/derive/src/derive_json.rs b/vendor/makepad/libs/micro_serde/derive/src/derive_json.rs deleted file mode 100644 index b436706..0000000 --- a/vendor/makepad/libs/micro_serde/derive/src/derive_json.rs +++ /dev/null @@ -1,345 +0,0 @@ -use makepad_micro_proc_macro::*; -use proc_macro::TokenStream; - -fn get_json_field_name(field: &StructField) -> String { - // Check for #[rename(OtherName)] attribute - for attr in &field.attrs { - if attr.name == "rename" { - if let Some(ref args) = attr.args { - // Parse the argument as an identifier - let mut parser = TokenParser::new(args.clone()); - if let Some(name) = parser.eat_any_ident() { - return name; - } - } - } - } - // Fall back to the field name, stripping leading underscore if present - if let Some(v) = field.name.strip_prefix("_") { - v.to_string() - } else { - field.name.clone() - } -} - -pub fn derive_ser_json_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("SerJson")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerJson for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn ser_json ( & self , d : usize , s : & mut SerJsonState ) {"); - - if let Some(types) = types { - tb.add("s . out . push (").chr('[').add(") ;"); - for i in 0..types.len() { - tb.add("self .") - .unsuf_usize(i) - .add(". ser_json ( d , s ) ;"); - if i != types.len() - 1 { - tb.add("s . out . push (").chr(',').add(") ;"); - } - } - tb.add("s . out . push (").chr(']').add(") ;"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - let fields_len = fields.len(); - tb.add("s . st_pre ( ) ;"); - // named struct - for (i, field) in fields.iter().enumerate() { - let json_name = get_json_field_name(field); - if field.ty.clone().into_iter().next().unwrap().to_string() == "Option" { - tb.add("if let Some ( t ) = ") - .add("& self .") - .ident(&field.name) - .add("{"); - tb.add("s . field ( d + 1 ,").string(&json_name).add(") ;"); - tb.add("t . ser_json ( d + 1 , s ) ;"); - if i != fields_len - 1 { - tb.add("s . conl ( ) ;"); - } - tb.add("} ;"); - } else { - tb.add("s . field ( d + 1 ,").string(&json_name).add(" ) ;"); - tb.add("self .") - .ident(&field.name) - .add(". ser_json ( d + 1 , s ) ;"); - if i != fields_len - 1 { - tb.add("s . conl ( ) ;"); - } - } - } - tb.add("s . st_post ( d ) ;"); - } else { - return parser.unexpected(); - } - tb.add("} } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("SerJson")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerJson for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn ser_json ( & self , d : usize , s : & mut SerJsonState ) {"); - tb.add("s . out . push (").chr('{').add(") ;"); - tb.add("match self {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - - while !parser.eat_eot() { - // parse ident - parser.eat_attributes(); - if let Some(variant) = parser.eat_any_ident() { - if let Some(types) = parser.eat_all_types() { - tb.add("Self ::").ident(&variant).add("("); - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(","); - } - tb.add(") => {"); - tb.add("s . label (").string(&variant).add(") ;"); - tb.add("s . out . push (").chr(':').add(") ;"); - tb.add("s . out . push (").chr('[').add(") ;"); - - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(". ser_json ( d , s ) ;"); - if i != types.len() - 1 { - tb.add("s . out . push (").chr(',').add(") ;"); - } - } - tb.add("s . out . push (").chr(']').add(") ;"); - tb.add("}"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.add("Self ::").ident(&variant).add("{"); - for field in fields.iter() { - tb.ident(&field.name).add(","); - } - tb.add("} => {"); - - tb.add("s . label (").string(&variant).add(") ;"); - tb.add("s . out . push (").chr(':').add(") ;"); - tb.add("s . st_pre ( ) ;"); - - let fields_len = fields.len(); - for (i, field) in fields.iter().enumerate() { - let json_name = get_json_field_name(field); - if field.ty.clone().into_iter().next().unwrap().to_string() == "Option" - { - tb.add("if let Some ( t ) = ").ident(&field.name).add("{"); - tb.add("s . field ( d + 1 ,").string(&json_name).add(") ;"); - tb.add("t . ser_json ( d + 1 , s ) ;"); - if i != fields_len - 1 { - tb.add("s . conl ( ) ;"); - } - tb.add("} ;"); - } else { - tb.add("s . field ( d + 1 ,").string(&json_name).add(" ) ;"); - tb.ident(&field.name).add(". ser_json ( d + 1 , s ) ;"); - if i != fields_len - 1 { - tb.add("s . conl ( ) ;"); - } - } - } - tb.add("s . st_post ( d ) ; }"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.add("Self ::").ident(&variant).add("=> {"); - tb.add("s . label (").string(&variant).add(") ;"); - tb.add("s . out . push_str (").string(":[]").add(") ; }"); - } else { - return parser.unexpected(); - } - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add("}"); - tb.add("s . out . push (").chr('}').add(") ;"); - tb.add("} } ;"); - return tb.end(); - } - } - parser.unexpected() -} - -pub fn derive_de_json_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("DeJson")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeJson for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_json ( s : & mut DeJsonState , i : & mut std :: str :: Chars )"); - tb.add("-> std :: result :: Result < Self , DeJsonErr > { "); - - if let Some(types) = types { - tb.add("s . block_open ( i ) ? ;"); - tb.add("let r = Self"); - tb.add("("); - for _ in 0..types.len() { - tb.add("{ let r = DeJson :: de_json ( s , i ) ? ; s . eat_comma_block ( i ) ? ; r } ,"); - } - tb.add(") ;"); - tb.add("s . block_close ( i ) ? ;"); - tb.add("std :: result :: Result :: Ok ( r )"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - tb.add("s . curly_open ( i ) ? ;"); - for field in &fields { - tb.add("let mut") - .ident(&format!("_{}", field.name)) - .add("= None ;"); - } - tb.add("while let Some ( _ ) = s . next_str ( ) {"); - tb.add("match s . strbuf . as_ref ( ) {"); - for field in &fields { - let json_name = get_json_field_name(field); - tb.string(&json_name).add("=> { s . next_colon ( i ) ? ;"); - tb.ident(&format!("_{}", field.name)) - .add("= Some (DeJson :: de_json ( s , i ) ? ) ; } ,"); - } - tb.add("_ => { if s . lenient { s . next_colon ( i ) ? ; s . skip_value ( i ) ? ; } else { return std :: result :: Result :: Err ( s . err_exp ( & s . strbuf ) ) } }"); - tb.add("} ; s . eat_comma_curly ( i ) ? ;"); - tb.add("} ; s . curly_close ( i ) ? ;"); - - tb.add("std :: result :: Result :: Ok ( Self {"); - for field in &fields { - let json_name = get_json_field_name(field); - tb.ident(&field.name).add(":"); - if field.ty.clone().into_iter().next().unwrap().to_string() == "Option" { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { None } ,"); - } else { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { return Err ( s . err_nf ("); - tb.string(&json_name).add(") ) } ,"); - } - } - tb.add("} )"); - } else { - return parser.unexpected(); - } - tb.add("} } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("DeJson")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeJson for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_json ( s : & mut DeJsonState , i : & mut std :: str :: Chars )"); - tb.add("-> std :: result :: Result < Self , DeJsonErr > { "); - tb.add("s . curly_open ( i ) ? ;"); - tb.add("let _ = s . string ( i ) ? ;"); - tb.add("s . colon ( i ) ? ;"); - tb.add("let r = std :: result :: Result :: Ok ( match s . strbuf . as_ref ( ) {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - while !parser.eat_eot() { - // parse ident - parser.eat_attributes(); - if let Some(variant) = parser.eat_any_ident() { - tb.string(&variant).add("=> {"); - if let Some(types) = parser.eat_all_types() { - tb.add("s . block_open ( i ) ? ;"); - tb.add("let r = Self ::").ident(&variant).add("("); - for _ in 0..types.len() { - tb.add("{ let r = DeJson :: de_json ( s , i ) ? ; s . eat_comma_block ( i ) ? ; r } ,"); - } - tb.add(") ;"); - tb.add("s . block_close ( i ) ? ; r"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.add("s . curly_open ( i ) ? ;"); - for field in &fields { - tb.add("let mut") - .ident(&format!("_{}", field.name)) - .add("= None ;"); - } - tb.add("while let Some ( _ ) = s . next_str ( ) {"); - tb.add("match s . strbuf . as_ref ( ) {"); - for field in &fields { - let json_name = get_json_field_name(field); - tb.string(&json_name).add("=> { s . next_colon ( i ) ? ;"); - tb.ident(&format!("_{}", field.name)) - .add("= Some (DeJson :: de_json ( s , i ) ? ) ; } ,"); - } - tb.add("_ => { if s . lenient { s . next_colon ( i ) ? ; s . skip_value ( i ) ? ; } else { return std :: result :: Result :: Err ( s . err_exp ( & s . strbuf ) ) } }"); - tb.add("} s . eat_comma_curly ( i ) ? ;"); - tb.add("} s . curly_close ( i ) ? ;"); - - tb.add("Self ::").ident(&variant).add("{"); - for field in &fields { - let json_name = get_json_field_name(field); - tb.ident(&field.name).add(":"); - if field.ty.clone().into_iter().next().unwrap().to_string() == "Option" - { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { None } ,"); - } else { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { return Err ( s . err_nf ("); - tb.string(&json_name).add(") ) } ,"); - } - } - tb.add("}"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.add("s . block_open ( i ) ? ; s . block_close ( i ) ? ; Self ::") - .ident(&variant); - } else { - return parser.unexpected(); - } - - tb.add("}"); - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add("_ => return std :: result :: Result :: Err ( s . err_exp ( & s . strbuf ) )"); - tb.add("} ) ; s . curly_close ( i ) ? ; r } }"); - return tb.end(); - } - } - parser.unexpected() -} diff --git a/vendor/makepad/libs/micro_serde/derive/src/derive_ron.rs b/vendor/makepad/libs/micro_serde/derive/src/derive_ron.rs deleted file mode 100644 index 1aaad34..0000000 --- a/vendor/makepad/libs/micro_serde/derive/src/derive_ron.rs +++ /dev/null @@ -1,301 +0,0 @@ -use makepad_micro_proc_macro::*; -use proc_macro::TokenStream; - -pub fn derive_ser_ron_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("SerRon")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerRon for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{"); - tb.add("fn ser_ron(&self, d: usize, s: &mut SerRonState){"); - - if let Some(types) = types { - tb.add("s.out.push(").chr('(').add(");"); - for i in 0..types.len() { - tb.add("self.").unsuf_usize(i).add(".ser_ron(d, s);"); - if i != types.len() - 1 { - tb.add("s.out.push_str(").string(", ").add(") ;"); - } - } - tb.add("s.out.push(").chr(')').add(");"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - tb.add("s.st_pre( ) ;"); - - // named struct - for field in fields { - if field.ty.into_iter().next().unwrap().to_string() == "Option" { - tb.add("if let Some ( t ) = ") - .add("& self .") - .ident(&field.name) - .add("{"); - tb.add("s.field ( d + 1 ,").string(&field.name).add(") ;"); - tb.add("t.ser_ron ( d + 1 , s ) ; s . conl ( ) ; } ;"); - } else { - tb.add("s . field ( d + 1 ,") - .string(&field.name) - .add(" ) ;"); - tb.add("self .") - .ident(&field.name) - .add(". ser_ron ( d + 1 , s ) ; s . conl ( ) ;"); - } - } - tb.add("s . st_post ( d ) ;"); - } else { - return parser.unexpected(); - } - tb.add("} } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("SerRon")); - - tb.add("impl").stream(generic.clone()); - tb.add("SerRon for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn ser_ron ( & self , d : usize , s : & mut SerRonState ) {"); - tb.add("match self {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - - while !parser.eat_eot() { - // parse ident - parser.eat_attributes(); - if let Some(variant) = parser.eat_any_ident() { - if let Some(types) = parser.eat_all_types() { - tb.add("Self ::").ident(&variant).add("("); - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(","); - } - tb.add(") => {"); - tb.add("s . out . push_str (").string(&variant).add(") ;"); - tb.add("s . out . push (").chr('(').add(") ;"); - - for i in 0..types.len() { - tb.ident(&format!("n{}", i)).add(". ser_ron ( d , s ) ;"); - if i != types.len() - 1 { - tb.add("s . out . push_str (").string(", ").add(") ;"); - } - } - tb.add("s . out . push (").chr(')').add(") ;"); - tb.add("}"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.add("Self ::").ident(&variant).add("{"); - for field in fields.iter() { - tb.ident(&field.name).add(","); - } - tb.add("} => {"); - - tb.add("s . out . push_str (").string(&variant).add(") ;"); - tb.add("s . st_pre ( ) ;"); - - for field in fields { - if field.ty.into_iter().next().unwrap().to_string() == "Option" { - tb.add("if ").ident(&field.name).add(". is_some ( ) {"); - tb.add("s . field ( d + 1 ,").string(&field.name).add(") ;"); - tb.ident(&field.name) - .add(" . ser_ron ( d + 1 , s ) ; s . conl ( ) ; } ;"); - } else { - tb.add("s . field ( d + 1 ,") - .string(&field.name) - .add(" ) ;"); - tb.ident(&field.name) - .add(". ser_ron ( d + 1 , s ) ; s . conl ( ) ;"); - } - } - tb.add("s . st_post ( d ) ; }"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.add("Self ::").ident(&variant).add("=> {"); - tb.add("s . out . push_str (").string(&variant).add(") ; }"); - } else { - return parser.unexpected(); - } - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add("}"); - tb.add("} } ;"); - return tb.end(); - } - } - parser.unexpected() -} - -pub fn derive_de_ron_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(Some("DeRon")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeRon for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_ron ( s : & mut DeRonState , i : & mut std :: str :: Chars )"); - tb.add("-> std :: result :: Result < Self , DeRonErr > { "); - - if let Some(types) = types { - tb.add("s . paren_open ( i ) ? ;"); - tb.add("let r = Self"); - tb.add("("); - for _ in 0..types.len() { - tb.add("{ let r = DeRon :: de_ron ( s , i ) ? ; s . eat_comma_paren ( i ) ? ; r } ,"); - } - tb.add(") ;"); - tb.add("s . paren_close ( i ) ? ;"); - tb.add("std :: result :: Result :: Ok ( r ) "); - } else if let Some(fields) = parser.eat_all_struct_fields() { - tb.add("s . paren_open ( i ) ? ;"); - for field in &fields { - tb.add("let mut") - .ident(&format!("_{}", field.name)) - .add("= None ;"); - } - tb.add("while let Some ( _ ) = s . next_ident ( ) {"); - tb.add("match s . identbuf . as_ref ( ) {"); - for field in &fields { - tb.string(&field.name).add("=> { s . next_colon ( i ) ? ;"); - tb.ident(&format!("_{}", field.name)) - .add("= Some ( DeRon :: de_ron ( s , i ) ? ) ; } ,"); - } - tb.add( - "_ => return std :: result :: Result :: Err ( s . err_exp ( & s . identbuf ) )", - ); - tb.add("} ; s . eat_comma_paren ( i ) ? ;"); - tb.add("} ; s . paren_close ( i ) ? ;"); - - tb.add("std :: result :: Result :: Ok ( Self {"); - for field in fields { - tb.ident(&field.name).add(":"); - if field.ty.into_iter().next().unwrap().to_string() == "Option" { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { None } ,"); - } else { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { return Err ( s . err_nf ("); - tb.string(&field.name).add(") ) } ,"); - } - } - tb.add("} )"); - } else { - return parser.unexpected(); - } - tb.add("} } ;"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(Some("DeRon")); - - tb.add("impl").stream(generic.clone()); - tb.add("DeRon for") - .ident(&name) - .stream(generic) - .stream(where_clause); - tb.add("{ fn de_ron ( s : & mut DeRonState , i : & mut std :: str :: Chars )"); - tb.add("-> std :: result :: Result < Self , DeRonErr > { "); - tb.add("s . ident ( i ) ? ;"); - tb.add("std :: result :: Result :: Ok ( match s . identbuf . as_ref ( ) {"); - - if !parser.open_brace() { - return parser.unexpected(); - } - while !parser.eat_eot() { - // parse ident - parser.eat_attributes(); - if let Some(variant) = parser.eat_any_ident() { - tb.string(&variant).add("=> {"); - if let Some(types) = parser.eat_all_types() { - tb.add("s . paren_open ( i ) ? ;"); - tb.add("let r = Self ::").ident(&variant).add("("); - for _ in 0..types.len() { - tb.add("{ let r = DeRon :: de_ron ( s , i ) ? ; s . eat_comma_paren ( i ) ? ; r } ,"); - } - tb.add(") ;"); - tb.add("s . paren_close ( i ) ? ; r"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - tb.add("s . paren_open ( i ) ? ;"); - for field in &fields { - tb.add("let mut") - .ident(&format!("_{}", field.name)) - .add("= None ;"); - } - tb.add("while let Some ( _ ) = s . next_ident ( ) {"); - tb.add("match s . identbuf . as_ref ( ) {"); - for field in &fields { - tb.string(&field.name).add("=> { s . next_colon ( i ) ? ;"); - tb.ident(&format!("_{}", field.name)) - .add("= Some ( DeRon :: de_ron ( s , i ) ? ) ; } ,"); - } - tb.add("_ => return std :: result :: Result :: Err ( s . err_exp ( & s . strbuf ) )"); - tb.add("} ; s . eat_comma_paren ( i ) ? ;"); - tb.add("} ; s . paren_close ( i ) ? ;"); - - tb.add("Self ::").ident(&variant).add("{"); - for field in fields { - tb.ident(&field.name).add(":"); - if field.ty.into_iter().next().unwrap().to_string() == "Option" { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { None } ,"); - } else { - tb.add("if let Some ( t ) =") - .ident(&format!("_{}", field.name)); - tb.add("{ t } else { return Err ( s . err_nf ("); - tb.string(&field.name).add(") ) } ,"); - } - } - tb.add("}"); - } else if parser.is_punct_alone(',') || parser.is_eot() { - // bare variant - tb.add("Self ::").ident(&variant); - } else { - return parser.unexpected(); - } - - tb.add("}"); - parser.eat_punct_alone(','); - } else { - return parser.unexpected(); - } - } - tb.add( - "_ => return std :: result :: Result :: Err ( s . err_enum ( & s . identbuf ) )", - ); - tb.add("} ) } }"); - return tb.end(); - } - } - parser.unexpected() -} diff --git a/vendor/makepad/libs/micro_serde/derive/src/lib.rs b/vendor/makepad/libs/micro_serde/derive/src/lib.rs deleted file mode 100644 index 4c4094d..0000000 --- a/vendor/makepad/libs/micro_serde/derive/src/lib.rs +++ /dev/null @@ -1,41 +0,0 @@ -extern crate proc_macro; -use proc_macro::TokenStream; - -mod derive_bin; -use crate::derive_bin::*; - -mod derive_ron; -use crate::derive_ron::*; - -mod derive_json; -use crate::derive_json::*; - -#[proc_macro_derive(SerBin)] -pub fn derive_ser_bin(input: TokenStream) -> TokenStream { - derive_ser_bin_impl(input) -} - -#[proc_macro_derive(DeBin)] -pub fn derive_de_bin(input: TokenStream) -> TokenStream { - derive_de_bin_impl(input) -} - -#[proc_macro_derive(SerJson, attributes(rename))] -pub fn derive_ser_json(input: TokenStream) -> TokenStream { - derive_ser_json_impl(input) -} - -#[proc_macro_derive(DeJson, attributes(rename))] -pub fn derive_de_json(input: TokenStream) -> TokenStream { - derive_de_json_impl(input) -} - -#[proc_macro_derive(SerRon)] -pub fn derive_ser_ron(input: TokenStream) -> TokenStream { - derive_ser_ron_impl(input) -} - -#[proc_macro_derive(DeRon)] -pub fn derive_de_ron(input: TokenStream) -> TokenStream { - derive_de_ron_impl(input) -} diff --git a/vendor/makepad/libs/micro_serde/example/Cargo.toml b/vendor/makepad/libs/micro_serde/example/Cargo.toml deleted file mode 100644 index 7fd52d3..0000000 --- a/vendor/makepad/libs/micro_serde/example/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "microserde_example" -version = "0.1.0" -edition = "2021" - -[workspace] - -[dependencies] - -[dependencies.makepad-micro-serde] -path="../" diff --git a/vendor/makepad/libs/micro_serde/example/src/main.rs b/vendor/makepad/libs/micro_serde/example/src/main.rs deleted file mode 100644 index 98eed55..0000000 --- a/vendor/makepad/libs/micro_serde/example/src/main.rs +++ /dev/null @@ -1,86 +0,0 @@ -// lets make tinyserde dep free too! - -use makepad_micro_serde::*; - -#[derive(SerBin, DeBin, SerJson, DeJson, SerRon, DeRon, PartialEq)] -struct MyStruct where T: Clone { - pub a: T, - b: u32, - c: Option>, - d: Option>, - e: MyEnum, - f: MyEnum, - g: MyEnum, - h: MyEnum, - i: MyEnum, - j: String, - k: [u32;2] -} - -// Test struct for #[rename] attribute -#[derive(SerJson, DeJson, PartialEq, Debug)] -struct RenamedStruct { - #[rename(firstName)] - first_name: String, - #[rename(lastName)] - last_name: String, - age: u32, // Not renamed -} - -#[derive(SerBin, DeBin, SerJson, DeJson, SerRon, DeRon, PartialEq)] -enum MyEnum where T: Clone { - One, - Two(T, u32), - Three {x: u32, y: T}, - Four {z: Option, w: T}, -} - -fn main() { - //let a = MyStruct{step1:1,step2:None}; - //let x = MyStruct2(1,2); - let x = MyStruct { - a: 1, - b: 2, - c: Some(vec![3]), - d: None, - e: MyEnum::One, - f: MyEnum::Two(4, 5), - g: MyEnum::Three {x: 6, y: 7}, - h: MyEnum::Four {z: None, w: 8}, - i: MyEnum::Four {z: Some(9), w: 8}, - j: "Hello".to_string(), - k: [10,11] - }; - let bin = x.serialize_bin(); - println!("Bin len: {}", bin.len()); - let y:MyStruct = DeBin::deserialize_bin(&bin).unwrap(); - println!("Bin roundtrip equality {}", x == y); - - let json = x.serialize_json(); - println!("JSON Output {}", json); - let y:MyStruct = DeJson::deserialize_json(&json).unwrap(); - println!("JSON roundtrip equality {}", x == y); - - let ron = x.serialize_ron(); - println!("RON Output {}", ron); - let y:MyStruct = DeRon::deserialize_ron(&ron).unwrap(); - println!("RON roundtrip equality {}", x == y); - - // Test #[rename] attribute - let renamed = RenamedStruct { - first_name: "John".to_string(), - last_name: "Doe".to_string(), - age: 30, - }; - let renamed_json = renamed.serialize_json(); - println!("\nRenamed JSON Output: {}", renamed_json); - // Should output: {"firstName":"John","lastName":"Doe","age":30} - - let renamed_back: RenamedStruct = DeJson::deserialize_json(&renamed_json).unwrap(); - println!("Renamed roundtrip equality: {}", renamed == renamed_back); - - // Test deserializing from external JSON with renamed fields - let external_json = r#"{"firstName":"Jane","lastName":"Smith","age":25}"#; - let from_external: RenamedStruct = DeJson::deserialize_json(external_json).unwrap(); - println!("Deserialized from external JSON: {:?}", from_external); -} diff --git a/vendor/makepad/libs/micro_serde/src/lib.rs b/vendor/makepad/libs/micro_serde/src/lib.rs deleted file mode 100644 index 9b73f5e..0000000 --- a/vendor/makepad/libs/micro_serde/src/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub use makepad_micro_serde_derive::*; - -mod serde_bin; -pub use crate::serde_bin::*; - -mod serde_json; -pub use crate::serde_json::*; - -mod serde_ron; -pub use crate::serde_ron::*; diff --git a/vendor/makepad/libs/micro_serde/src/serde_bin.rs b/vendor/makepad/libs/micro_serde/src/serde_bin.rs deleted file mode 100644 index 91590b5..0000000 --- a/vendor/makepad/libs/micro_serde/src/serde_bin.rs +++ /dev/null @@ -1,646 +0,0 @@ -use makepad_live_id::LiveId; -use std::{collections::HashMap, hash::Hash, str}; - -#[allow(unused_imports)] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "macos", - target_os = "ios" -))] -use std::{ - ffi::{OsStr, OsString}, - path::{Path, PathBuf}, -}; - -pub trait SerBin { - fn serialize_bin(&self) -> Vec { - let mut s = Vec::new(); - self.ser_bin(&mut s); - s - } - - fn ser_bin(&self, s: &mut Vec); -} - -pub trait DeBin: Sized { - fn deserialize_bin(d: &[u8]) -> Result { - DeBin::de_bin(&mut 0, d) - } - - fn de_bin(o: &mut usize, d: &[u8]) -> Result; -} - -pub struct DeBinErr { - pub msg: String, - pub o: usize, - pub l: usize, - pub s: usize, -} - -impl std::fmt::Display for DeBinErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Error deserializing {} ", self.msg)?; - if self.l != 0 { - write!(f, "while trying to read {} bytes ", self.l)? - } - write!(f, " at offset {} in buffer of size {}", self.o, self.s) - } -} - -impl std::fmt::Debug for DeBinErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self, f) - } -} - -macro_rules! impl_ser_de_bin_for { - ($ty:ident) => { - impl SerBin for $ty { - fn ser_bin(&self, s: &mut Vec) { - s.extend_from_slice(&self.to_le_bytes()); - } - } - - impl DeBin for $ty { - fn de_bin(o: &mut usize, d: &[u8]) -> Result<$ty, DeBinErr> { - let l = std::mem::size_of::<$ty>(); - if *o + l > d.len() { - return Err(DeBinErr { - o: *o, - l, - s: d.len(), - msg: format!("{}", stringify!($ty)), - }); - } - let ret = $ty::from_le_bytes(d[*o..*o + l].try_into().unwrap()); - *o += l; - Ok(ret) - } - } - }; -} - -impl_ser_de_bin_for!(f64); -impl_ser_de_bin_for!(f32); -impl_ser_de_bin_for!(u64); -impl_ser_de_bin_for!(i64); -impl_ser_de_bin_for!(u32); -impl_ser_de_bin_for!(i32); -impl_ser_de_bin_for!(u16); -impl_ser_de_bin_for!(i16); - -impl SerBin for usize { - fn ser_bin(&self, s: &mut Vec) { - s.extend_from_slice(&(*self as u64).to_le_bytes()); - } -} - -impl DeBin for usize { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - let l = std::mem::size_of::(); - if *o + l > d.len() { - return Err(DeBinErr { - o: *o, - l, - s: d.len(), - msg: "usize".to_string(), - }); - } - let ret = u64::from_le_bytes(d[*o..*o + l].try_into().unwrap()) as usize; - *o += l; - Ok(ret) - } -} - -impl SerBin for LiveId { - fn ser_bin(&self, s: &mut Vec) { - self.0.ser_bin(s); - } -} - -impl DeBin for LiveId { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - Ok(LiveId(u64::de_bin(o, d)?)) - } -} - -impl DeBin for u8 { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - if *o + 1 > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "u8".to_string(), - }); - } - let m = d[*o]; - *o += 1; - Ok(m) - } -} - -impl SerBin for u8 { - fn ser_bin(&self, s: &mut Vec) { - s.push(*self); - } -} - -impl DeBin for i8 { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - if *o + 1 > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "u8".to_string(), - }); - } - let m = d[*o]; - *o += 1; - Ok(m as i8) - } -} - -impl SerBin for i8 { - fn ser_bin(&self, s: &mut Vec) { - s.push(*self as u8); - } -} - -impl SerBin for bool { - fn ser_bin(&self, s: &mut Vec) { - s.push(if *self { 1 } else { 0 }); - } -} - -impl DeBin for bool { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - if *o + 1 > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "bool".to_string(), - }); - } - let m = d[*o]; - *o += 1; - if m == 0 { - Ok(false) - } else { - Ok(true) - } - } -} - -impl SerBin for String { - fn ser_bin(&self, s: &mut Vec) { - let len = self.len(); - len.ser_bin(s); - s.extend_from_slice(self.as_bytes()); - } -} - -impl DeBin for String { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - let len: u64 = DeBin::de_bin(o, d)?; - if *o + (len as usize) > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "String".to_string(), - }); - } - let r = std::str::from_utf8(&d[*o..(*o + (len as usize))]) - .unwrap() - .to_string(); - *o += len as usize; - Ok(r) - } -} - -impl SerBin for Vec -where - T: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - let len = self.len() as u64; - len.ser_bin(s); - for item in self { - item.ser_bin(s); - } - } -} - -impl DeBin for Vec -where - T: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result, DeBinErr> { - let len: u64 = DeBin::de_bin(o, d)?; - let mut out = Vec::new(); - for _ in 0..len { - out.push(DeBin::de_bin(o, d)?) - } - Ok(out) - } -} - -impl SerBin for Option -where - T: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - match self { - None => s.push(0), - Some(v) => { - s.push(1); - v.ser_bin(s); - } - } - } -} - -impl DeBin for Option -where - T: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result, DeBinErr> { - if *o + 1 > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "Option".to_string(), - }); - } - let m = d[*o]; - *o += 1; - Ok(match m { - 0 => None, - 1 => Some(DeBin::de_bin(o, d)?), - _ => { - return Err(DeBinErr { - o: *o, - l: 0, - s: d.len(), - msg: "Option".to_string(), - }) - } - }) - } -} - -impl SerBin for Result -where - T: SerBin, - E: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - match self { - Ok(v) => { - s.push(0); - v.ser_bin(s); - } - Err(e) => { - s.push(1); - e.ser_bin(s); - } - } - } -} - -impl DeBin for Result -where - T: DeBin, - E: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - if *o + 1 > d.len() { - return Err(DeBinErr { - o: *o, - l: 1, - s: d.len(), - msg: "Result".to_string(), - }); - } - let m = d[*o]; - *o += 1; - Ok(match m { - 0 => Ok(T::de_bin(o, d)?), - 1 => Err(E::de_bin(o, d)?), - _ => { - return Err(DeBinErr { - o: *o, - l: 0, - s: d.len(), - msg: "Result".to_string(), - }) - } - }) - } -} - -impl SerBin for [T] -where - T: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - for item in self { - item.ser_bin(s); - } - } -} - -unsafe fn de_bin_array_impl_inner( - top: *mut T, - count: usize, - o: &mut usize, - d: &[u8], -) -> Result<(), DeBinErr> -where - T: DeBin, -{ - for c in 0..count { - top.add(c).write(DeBin::de_bin(o, d)?); - } - Ok(()) -} - -impl DeBin for [T; N] -where - T: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - unsafe { - let mut to = std::mem::MaybeUninit::<[T; N]>::uninit(); - let top: *mut T = &mut to as *mut _ as *mut T; - de_bin_array_impl_inner(top, N, o, d)?; - Ok(to.assume_init()) - } - } -} - -impl SerBin for (A, B) -where - A: SerBin, - B: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - self.0.ser_bin(s); - self.1.ser_bin(s); - } -} - -impl DeBin for (A, B) -where - A: DeBin, - B: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B), DeBinErr> { - Ok((DeBin::de_bin(o, d)?, DeBin::de_bin(o, d)?)) - } -} - -impl SerBin for (A, B, C) -where - A: SerBin, - B: SerBin, - C: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - self.0.ser_bin(s); - self.1.ser_bin(s); - self.2.ser_bin(s); - } -} - -impl DeBin for (A, B, C) -where - A: DeBin, - B: DeBin, - C: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B, C), DeBinErr> { - Ok(( - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - )) - } -} - -impl SerBin for (A, B, C, D) -where - A: SerBin, - B: SerBin, - C: SerBin, - D: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - self.0.ser_bin(s); - self.1.ser_bin(s); - self.2.ser_bin(s); - self.3.ser_bin(s); - } -} - -impl DeBin for (A, B, C, D) -where - A: DeBin, - B: DeBin, - C: DeBin, - D: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B, C, D), DeBinErr> { - Ok(( - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - )) - } -} - -impl SerBin for (A, B, C, D, E) -where - A: SerBin, - B: SerBin, - C: SerBin, - D: SerBin, - E: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - self.0.ser_bin(s); - self.1.ser_bin(s); - self.2.ser_bin(s); - self.3.ser_bin(s); - self.4.ser_bin(s); - } -} - -impl DeBin for (A, B, C, D, E) -where - A: DeBin, - B: DeBin, - C: DeBin, - D: DeBin, - E: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B, C, D, E), DeBinErr> { - Ok(( - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - DeBin::de_bin(o, d)?, - )) - } -} - -impl SerBin for HashMap -where - K: SerBin, - V: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - let len = self.len() as u64; - len.ser_bin(s); - for (k, v) in self { - k.ser_bin(s); - v.ser_bin(s); - } - } -} - -impl DeBin for HashMap -where - K: DeBin + Eq + Hash, - V: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - let len: u64 = DeBin::de_bin(o, d)?; - let mut h = HashMap::new(); - for _ in 0..len { - let k = DeBin::de_bin(o, d)?; - let v = DeBin::de_bin(o, d)?; - h.insert(k, v); - } - Ok(h) - } -} - -impl SerBin for Box -where - T: SerBin, -{ - fn ser_bin(&self, s: &mut Vec) { - (**self).ser_bin(s) - } -} - -impl DeBin for Box -where - T: DeBin, -{ - fn de_bin(o: &mut usize, d: &[u8]) -> Result, DeBinErr> { - Ok(Box::new(DeBin::de_bin(o, d)?)) - } -} - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] -impl SerBin for PathBuf { - fn ser_bin(&self, s: &mut Vec) { - self.as_os_str().ser_bin(s) - } -} - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] -impl SerBin for Path { - fn ser_bin(&self, s: &mut Vec) { - self.as_os_str().ser_bin(s) - } -} - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] -impl SerBin for OsString { - fn ser_bin(&self, s: &mut Vec) { - self.as_os_str().ser_bin(s) - } -} - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] -impl SerBin for OsStr { - fn ser_bin(&self, s: &mut Vec) { - use std::os::unix::ffi::OsStrExt; - - self.as_bytes().ser_bin(s) - } -} - -impl SerBin for char { - fn ser_bin(&self, s: &mut Vec) { - let mut bytes = [0; 4]; - self.encode_utf8(&mut bytes).as_bytes().ser_bin(s); - } -} -/* -#[cfg(unix)] -impl DeBin for PathBuf { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - Ok(PathBuf::from(OsString::de_bin(o, d)?)) - } -} - -#[cfg(unix)] -impl DeBin for OsString { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - use std::os::unix::ffi::OsStringExt; - - Ok(OsString::from_vec(Vec::de_bin(o, d)?)) - } -}*/ - -impl DeBin for char { - fn de_bin(o: &mut usize, d: &[u8]) -> Result { - let mut bytes = [0; 4]; - bytes[0] = u8::de_bin(o, d)?; - let width = utf8_char_width(bytes[0]); - for byte in &mut bytes[1..width] { - *byte = u8::de_bin(o, d)?; - } - Ok(str::from_utf8(&bytes[..width]) - .unwrap() - .chars() - .next() - .unwrap()) - } -} - -// Given a first byte, determines how many bytes are in this UTF-8 character. -#[inline] -pub fn utf8_char_width(b: u8) -> usize { - static UTF8_CHAR_WIDTH: [u8; 256] = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, // 0x1F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, // 0x3F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, // 0x5F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, // 0x7F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, // 0x9F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, // 0xBF - 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, // 0xDF - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF - ]; - - UTF8_CHAR_WIDTH[b as usize] as usize -} diff --git a/vendor/makepad/libs/micro_serde/src/serde_json.rs b/vendor/makepad/libs/micro_serde/src/serde_json.rs deleted file mode 100644 index 438bf06..0000000 --- a/vendor/makepad/libs/micro_serde/src/serde_json.rs +++ /dev/null @@ -1,1253 +0,0 @@ -use makepad_live_id::LiveId; -use std::collections::HashMap; -use std::hash::Hash; -use std::str::Chars; - -pub struct SerJsonState { - pub out: String, -} - -impl SerJsonState { - pub fn indent(&mut self, _d: usize) { - //for _ in 0..d { - // self.out.push_str(" "); - //} - } - - pub fn field(&mut self, d: usize, field: &str) { - self.indent(d); - self.out.push('"'); - self.out.push_str(field); - self.out.push('"'); - self.out.push(':'); - } - - pub fn label(&mut self, label: &str) { - self.out.push('"'); - self.out.push_str(label); - self.out.push('"'); - } - - pub fn conl(&mut self) { - self.out.push(',') - } - - pub fn st_pre(&mut self) { - self.out.push('{'); - } - - pub fn st_post(&mut self, d: usize) { - self.indent(d); - self.out.push('}'); - } -} - -pub trait SerJson { - fn serialize_json(&self) -> String { - let mut s = SerJsonState { out: String::new() }; - self.ser_json(0, &mut s); - s.out - } - - fn ser_json(&self, d: usize, s: &mut SerJsonState); -} - -pub trait DeJson: Sized { - fn deserialize_json(input: &str) -> Result { - let mut state = DeJsonState::default(); - let mut chars = input.chars(); - state.next(&mut chars); - state.next_tok(&mut chars)?; - DeJson::de_json(&mut state, &mut chars) - } - - fn deserialize_json_lenient(input: &str) -> Result { - let mut state = DeJsonState::default(); - state.lenient = true; - let mut chars = input.chars(); - state.next(&mut chars); - state.next_tok(&mut chars)?; - DeJson::de_json(&mut state, &mut chars) - } - - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result; -} - -#[derive(PartialEq, Debug, Default)] -pub enum DeJsonTok { - Str, - Char(char), - U64(u64), - U128(u128), - I64(i64), - I128(i128), - F64(f64), - Bool(bool), - BareIdent, - Null, - Colon, - CurlyOpen, - CurlyClose, - BlockOpen, - BlockClose, - Comma, - #[default] - Bof, - Eof, -} - -#[derive(Default)] -pub struct DeJsonState { - pub cur: char, - pub tok: DeJsonTok, - pub strbuf: String, - pub numbuf: String, - pub identbuf: String, - pub line: usize, - pub col: usize, - pub lenient: bool, -} - -pub struct DeJsonErr { - pub msg: String, - pub line: usize, - pub col: usize, -} - -impl std::fmt::Debug for DeJsonErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Json Deserialize error: {}, line:{} col:{}", - self.msg, - self.line + 1, - self.col + 1 - ) - } -} - -impl DeJsonState { - pub fn next(&mut self, i: &mut Chars) { - if let Some(c) = i.next() { - self.cur = c; - if self.cur == '\n' { - self.line += 1; - self.col = 0; - } else { - self.col += 1; - } - } else { - self.cur = '\0'; - } - } - - pub fn err_exp(&self, name: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Unexpected key {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_msg(&self, msg: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("{}", msg), - line: self.line, - col: self.col, - } - } - - pub fn err_nf(&self, name: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Key not found {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_enum(&self, name: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Enum not defined {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_token(&self, what: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Unexpected token {:?} expected {} ", self.tok, what), - line: self.line, - col: self.col, - } - } - - pub fn err_range(&self, what: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Value out of range {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn err_type(&self, what: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Token wrong type {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn err_parse(&self, what: &str) -> DeJsonErr { - DeJsonErr { - msg: format!("Cannot parse {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn eat_comma_block(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - match self.tok { - DeJsonTok::Comma => { - self.next_tok(i)?; - Ok(()) - } - DeJsonTok::BlockClose => Ok(()), - _ => Err(self.err_token(", or ]")), - } - } - - pub fn eat_comma_curly(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - match self.tok { - DeJsonTok::Comma => { - self.next_tok(i)?; - Ok(()) - } - DeJsonTok::CurlyClose => Ok(()), - _ => Err(self.err_token(", or }")), - } - } - - pub fn colon(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - match self.tok { - DeJsonTok::Colon => { - self.next_tok(i)?; - Ok(()) - } - _ => Err(self.err_token(":")), - } - } - - pub fn string(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - match &mut self.tok { - DeJsonTok::Str => { - self.next_tok(i)?; - Ok(()) - } - _ => Err(self.err_token("String")), - } - } - - pub fn next_colon(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - self.next_tok(i)?; - self.colon(i)?; - Ok(()) - } - - pub fn next_str(&mut self) -> Option<()> { - if let DeJsonTok::Str = &mut self.tok { - //let mut s = String::new(); - //std::mem::swap(&mut s, name); - Some(()) - } else { - None - } - } - - pub fn block_open(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - if self.tok == DeJsonTok::BlockOpen { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("[")) - } - - pub fn block_close(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - if self.tok == DeJsonTok::BlockClose { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("]")) - } - - pub fn curly_open(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - if self.tok == DeJsonTok::CurlyOpen { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("{")) - } - - pub fn curly_close(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - if self.tok == DeJsonTok::CurlyClose { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("}")) - } - - pub fn u64_range(&mut self, max: u64) -> Result { - if let DeJsonTok::U64(value) = self.tok { - if value > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value); - } - if let DeJsonTok::U128(value) = self.tok { - if value > max as u128 { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as u64); - } - Err(self.err_token("unsigned integer")) - } - - pub fn u128_range(&mut self, max: u128) -> Result { - if let DeJsonTok::U128(value) = self.tok { - if value > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value); - } - if let DeJsonTok::U64(value) = self.tok { - return Ok(value as u128); - } - Err(self.err_token("unsigned integer")) - } - - pub fn i64_range(&mut self, min: i64, max: i64) -> Result { - if let DeJsonTok::I64(value) = self.tok { - if value < min { - return Err(self.err_range(&format!("{}<{}", value, min))); - } - return Ok(value); - } - if let DeJsonTok::I128(value) = self.tok { - if value < min as i128 { - return Err(self.err_range(&format!("{}<{}", value, min))); - } - if value > max as i128 { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as i64); - } - if let DeJsonTok::U64(value) = self.tok { - if value as i64 > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as i64); - } - if let DeJsonTok::U128(value) = self.tok { - if value > max as u128 { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as i64); - } - Err(self.err_token("signed integer")) - } - - pub fn i128_range(&mut self, min: i128, max: i128) -> Result { - if let DeJsonTok::I128(value) = self.tok { - if value < min { - return Err(self.err_range(&format!("{}<{}", value, min))); - } - if value > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value); - } - if let DeJsonTok::I64(value) = self.tok { - return Ok(value as i128); - } - if let DeJsonTok::U128(value) = self.tok { - if value > max as u128 { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as i128); - } - if let DeJsonTok::U64(value) = self.tok { - return Ok(value as i128); - } - Err(self.err_token("signed integer")) - } - - pub fn as_f64(&mut self) -> Result { - if let DeJsonTok::I128(value) = self.tok { - return Ok(value as f64); - } - if let DeJsonTok::U128(value) = self.tok { - return Ok(value as f64); - } - if let DeJsonTok::I64(value) = self.tok { - return Ok(value as f64); - } - if let DeJsonTok::U64(value) = self.tok { - return Ok(value as f64); - } - if let DeJsonTok::F64(value) = self.tok { - return Ok(value); - } - Err(self.err_token("floating point")) - } - - pub fn as_bool(&mut self) -> Result { - if let DeJsonTok::Bool(value) = self.tok { - return Ok(value); - } - Err(self.err_token("boolean")) - } - - pub fn as_string(&mut self) -> Result { - if let DeJsonTok::Str = &mut self.tok { - let mut val = String::new(); - std::mem::swap(&mut val, &mut self.strbuf); - return Ok(val); - } - Err(self.err_token("string")) - } - - pub fn as_ident(&mut self) -> Result { - if let DeJsonTok::BareIdent = &mut self.tok { - let mut val = String::new(); - std::mem::swap(&mut val, &mut self.identbuf); - return Ok(val); - } - Err(self.err_token("ident")) - } - - pub fn skip_value(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - match self.tok { - DeJsonTok::Str - | DeJsonTok::U64(_) - | DeJsonTok::U128(_) - | DeJsonTok::I64(_) - | DeJsonTok::I128(_) - | DeJsonTok::F64(_) - | DeJsonTok::Bool(_) - | DeJsonTok::Null => { - self.next_tok(i)?; - Ok(()) - } - DeJsonTok::CurlyOpen => { - self.curly_open(i)?; - while self.tok != DeJsonTok::CurlyClose { - self.string(i)?; - self.colon(i)?; - self.skip_value(i)?; - self.eat_comma_curly(i)?; - } - self.curly_close(i)?; - Ok(()) - } - DeJsonTok::BlockOpen => { - self.block_open(i)?; - while self.tok != DeJsonTok::BlockClose { - self.skip_value(i)?; - self.eat_comma_block(i)?; - } - self.block_close(i)?; - Ok(()) - } - _ => Err(self.err_token("value to skip")), - } - } - - pub fn next_tok(&mut self, i: &mut Chars) -> Result<(), DeJsonErr> { - while self.cur == '\n' || self.cur == '\r' || self.cur == '\t' || self.cur == ' ' { - self.next(i); - } - if self.cur == '\0' { - self.tok = DeJsonTok::Eof; - return Ok(()); - } - match self.cur { - ':' => { - self.next(i); - self.tok = DeJsonTok::Colon; - Ok(()) - } - ',' => { - self.next(i); - self.tok = DeJsonTok::Comma; - Ok(()) - } - '[' => { - self.next(i); - self.tok = DeJsonTok::BlockOpen; - Ok(()) - } - ']' => { - self.next(i); - self.tok = DeJsonTok::BlockClose; - Ok(()) - } - '{' => { - self.next(i); - self.tok = DeJsonTok::CurlyOpen; - Ok(()) - } - '}' => { - self.next(i); - self.tok = DeJsonTok::CurlyClose; - Ok(()) - } - '-' | '0'..='9' => { - self.numbuf.clear(); - let is_neg = if self.cur == '-' { - self.numbuf.push(self.cur); - self.next(i); - true - } else { - false - }; - let mut is_float = false; - while self.cur >= '0' && self.cur <= '9' { - self.numbuf.push(self.cur); - self.next(i); - } - if self.cur == '.' { - is_float = true; - self.numbuf.push(self.cur); - self.next(i); - while self.cur >= '0' && self.cur <= '9' { - self.numbuf.push(self.cur); - self.next(i); - } - } - if self.cur == 'e' || self.cur == 'E' { - is_float = true; - self.numbuf.push(self.cur); - self.next(i); - if self.cur == '+' || self.cur == '-' { - self.numbuf.push(self.cur); - self.next(i); - } - if !(self.cur >= '0' && self.cur <= '9') { - return Err(self.err_parse("number")); - } - while self.cur >= '0' && self.cur <= '9' { - self.numbuf.push(self.cur); - self.next(i); - } - } - if is_float { - if let Ok(num) = self.numbuf.parse() { - self.tok = DeJsonTok::F64(num); - Ok(()) - } else { - Err(self.err_parse("number")) - } - } else { - if is_neg { - if let Ok(num) = self.numbuf.parse() { - self.tok = DeJsonTok::I64(num); - return Ok(()); - } - if let Ok(num) = self.numbuf.parse() { - self.tok = DeJsonTok::I128(num); - return Ok(()); - } - return Err(self.err_parse("number")); - } - if let Ok(num) = self.numbuf.parse() { - self.tok = DeJsonTok::U64(num); - return Ok(()); - } - if let Ok(num) = self.numbuf.parse() { - self.tok = DeJsonTok::U128(num); - return Ok(()); - } - Err(self.err_parse("number")) - } - } - 'a'..='z' | 'A'..='Z' | '_' => { - self.identbuf.clear(); - while self.cur >= 'a' && self.cur <= 'z' - || self.cur >= 'A' && self.cur <= 'Z' - || self.cur == '_' - { - self.identbuf.push(self.cur); - self.next(i); - } - if self.identbuf == "true" { - self.tok = DeJsonTok::Bool(true); - return Ok(()); - } - if self.identbuf == "false" { - self.tok = DeJsonTok::Bool(false); - return Ok(()); - } - if self.identbuf == "null" { - self.tok = DeJsonTok::Null; - return Ok(()); - } - self.tok = DeJsonTok::BareIdent; - Err(self.err_token(&format!( - "Got ##{}## needed true, false, null", - self.identbuf - ))) - } - '"' => { - self.strbuf.clear(); - self.next(i); - while self.cur != '"' { - if self.cur == '\\' { - self.next(i); - match self.cur { - 'n' => self.strbuf.push('\n'), - 'r' => self.strbuf.push('\r'), - 't' => self.strbuf.push('\t'), - '0' => self.strbuf.push('\0'), - '\0' => { - return Err(self.err_parse("string")); - } - 'u' => { - // 4 digit hex unicode following - fn hex_char_to_u8(byte: char) -> u8 { - if byte >= '0' && byte <= '9' { - byte as u8 - '0' as u8 - } else if byte >= 'a' && byte <= 'f' { - byte as u8 - 'a' as u8 + 10 - } else if byte >= 'A' && byte <= 'F' { - byte as u8 - 'A' as u8 + 10 - } else { - 0 - } - } - let mut a = 0; - self.next(i); - a |= (hex_char_to_u8(self.cur) as u32) << 12; - self.next(i); - a |= (hex_char_to_u8(self.cur) as u32) << 8; - self.next(i); - a |= (hex_char_to_u8(self.cur) as u32) << 4; - self.next(i); - a |= (hex_char_to_u8(self.cur) as u32) << 0; - self.strbuf.push(std::char::from_u32(a).unwrap_or('?')); - } - _ => self.strbuf.push(self.cur), - } - self.next(i); - } else { - if self.cur == '\0' { - return Err(self.err_parse("string")); - } else { - self.strbuf.push(self.cur); - } - self.next(i); - } - } - self.next(i); - self.tok = DeJsonTok::Str; - Ok(()) - } - _ => Err(self.err_token("tokenizer")), - } - } -} - -macro_rules! impl_ser_de_json_unsigned { - ( $ ty: ident, $ max: expr) => { - impl SerJson for $ty { - fn ser_json(&self, _d: usize, s: &mut SerJsonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeJson for $ty { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<$ty, DeJsonErr> { - let val = s.u128_range($max as u128)?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -macro_rules! impl_ser_de_json_signed { - ( $ ty: ident, $ min: expr, $ max: expr) => { - impl SerJson for $ty { - fn ser_json(&self, _d: usize, s: &mut SerJsonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeJson for $ty { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<$ty, DeJsonErr> { - let val = s.i128_range($min as i128, $max as i128)?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -macro_rules! impl_ser_de_json_float { - ( $ ty: ident) => { - impl SerJson for $ty { - fn ser_json(&self, _d: usize, s: &mut SerJsonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeJson for $ty { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<$ty, DeJsonErr> { - //s.is_prefix(p, i) ?; - let val = s.as_f64()?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -impl_ser_de_json_unsigned!(usize, std::u64::MAX); -impl_ser_de_json_unsigned!(u64, std::u64::MAX); -impl_ser_de_json_unsigned!(u128, std::u128::MAX); -impl_ser_de_json_unsigned!(u32, std::u32::MAX); -impl_ser_de_json_unsigned!(u16, std::u16::MAX); -impl_ser_de_json_unsigned!(u8, std::u8::MAX); -impl_ser_de_json_signed!(i64, std::i64::MIN, std::i64::MAX); -impl_ser_de_json_signed!(i128, std::i128::MIN, std::i128::MAX); -impl_ser_de_json_signed!(i32, std::i64::MIN, std::i64::MAX); -impl_ser_de_json_signed!(i16, std::i64::MIN, std::i64::MAX); -impl_ser_de_json_signed!(i8, std::i64::MIN, std::i8::MAX); -impl_ser_de_json_float!(f64); -impl_ser_de_json_float!(f32); - -impl SerJson for LiveId { - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - self.0.ser_json(d, s); - } -} - -impl DeJson for LiveId { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - Ok(LiveId(u64::de_json(s, i)?)) - } -} - -impl SerJson for Option -where - T: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - if let Some(v) = self { - v.ser_json(d, s); - } else { - s.out.push_str("None"); - } - } -} - -impl DeJson for Option -where - T: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - if let DeJsonTok::Null = s.tok { - s.next_tok(i)?; - return Ok(None); - } - Ok(Some(DeJson::de_json(s, i)?)) - } -} - -impl SerJson for bool { - fn ser_json(&self, _d: usize, s: &mut SerJsonState) { - if *self { - s.out.push_str("true") - } else { - s.out.push_str("false") - } - } -} - -impl DeJson for bool { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - let val = s.as_bool()?; - s.next_tok(i)?; - Ok(val) - } -} - -impl SerJson for String { - fn ser_json(&self, _d: usize, s: &mut SerJsonState) { - s.out.push('"'); - for c in self.chars() { - match c { - '\n' => { - s.out.push('\\'); - s.out.push('n'); - } - '\r' => { - s.out.push('\\'); - s.out.push('r'); - } - '\t' => { - s.out.push('\\'); - s.out.push('t'); - } - '\0' => { - s.out.push('\\'); - s.out.push('0'); - } - '\\' => { - s.out.push('\\'); - s.out.push('\\'); - } - '"' => { - s.out.push('\\'); - s.out.push('"'); - } - _ => s.out.push(c), - } - } - s.out.push('"'); - } -} - -impl DeJson for String { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - let val = s.as_string()?; - s.next_tok(i)?; - Ok(val) - } -} - -impl SerJson for Vec -where - T: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('['); - if !self.is_empty() { - let last = self.len() - 1; - for (index, item) in self.iter().enumerate() { - s.indent(d + 1); - item.ser_json(d + 1, s); - if index != last { - s.out.push(','); - } - } - } - s.out.push(']'); - } -} - -impl DeJson for Vec -where - T: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result, DeJsonErr> { - let mut out = Vec::new(); - s.block_open(i)?; - - while s.tok != DeJsonTok::BlockClose { - out.push(DeJson::de_json(s, i)?); - s.eat_comma_block(i)?; - } - s.block_close(i)?; - Ok(out) - } -} - -#[derive(Clone, Debug)] -pub enum JsonValue { - String(String), - Char(char), - U64(u64), - U128(u128), - I64(i64), - I128(i128), - F64(f64), - Bool(bool), - BareIdent(String), - Null, - Undefined, - Object(HashMap), - Array(Vec), -} - -impl JsonValue { - pub fn object(&self) -> Option<&HashMap> { - if let JsonValue::Object(obj) = self { - return Some(obj); - } - None - } - pub fn string(&self) -> Option<&String> { - if let JsonValue::String(obj) = self { - return Some(obj); - } - None - } - pub fn key(&self, key: &str) -> Option<&JsonValue> { - if let JsonValue::Object(obj) = self { - return obj.get(key); - } - None - } -} - -impl SerJson for JsonValue { - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - match self { - JsonValue::String(v) => v.ser_json(d, s), - JsonValue::Char(v) => v.to_string().ser_json(d, s), - JsonValue::U64(v) => v.ser_json(d, s), - JsonValue::U128(v) => v.ser_json(d, s), - JsonValue::I64(v) => v.ser_json(d, s), - JsonValue::I128(v) => v.ser_json(d, s), - JsonValue::F64(v) => v.ser_json(d, s), - JsonValue::Bool(v) => v.ser_json(d, s), - JsonValue::BareIdent(v) => v.ser_json(d, s), - JsonValue::Null => s.out.push_str("null"), - JsonValue::Undefined => s.out.push_str("undefined"), - JsonValue::Object(v) => v.ser_json(d, s), - JsonValue::Array(v) => v.ser_json(d, s), - } - } -} - -impl DeJson for JsonValue { - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - // lets check what tokenm we have - match s.tok { - DeJsonTok::Str => { - let v = s.as_string()?; - s.next_tok(i)?; - Ok(JsonValue::String(v)) - } - DeJsonTok::Char(c) => { - s.next_tok(i)?; - Ok(JsonValue::Char(c)) - } - DeJsonTok::U64(v) => { - s.next_tok(i)?; - Ok(JsonValue::U64(v)) - } - DeJsonTok::U128(v) => { - s.next_tok(i)?; - Ok(JsonValue::U128(v)) - } - DeJsonTok::I64(v) => { - s.next_tok(i)?; - Ok(JsonValue::I64(v)) - } - DeJsonTok::I128(v) => { - s.next_tok(i)?; - Ok(JsonValue::I128(v)) - } - DeJsonTok::F64(v) => { - s.next_tok(i)?; - Ok(JsonValue::F64(v)) - } - DeJsonTok::Bool(v) => { - s.next_tok(i)?; - Ok(JsonValue::Bool(v)) - } - DeJsonTok::BareIdent => { - let v = s.as_ident()?; - s.next_tok(i)?; - Ok(JsonValue::BareIdent(v)) - } - DeJsonTok::Null => { - s.next_tok(i)?; - Ok(JsonValue::Null) - } - DeJsonTok::Colon => return Err(s.err_msg("Unexpected :")), - DeJsonTok::CurlyOpen => { - let mut h = HashMap::new(); - s.curly_open(i)?; - while s.tok != DeJsonTok::CurlyClose { - let k = String::de_json(s, i)?; - s.colon(i)?; - let v = JsonValue::de_json(s, i)?; - s.eat_comma_curly(i)?; - h.insert(k, v); - } - s.curly_close(i)?; - Ok(JsonValue::Object(h)) - } - DeJsonTok::CurlyClose => return Err(s.err_msg("Unexpected }")), - DeJsonTok::BlockOpen => { - let mut out = Vec::new(); - s.block_open(i)?; - - while s.tok != DeJsonTok::BlockClose { - out.push(JsonValue::de_json(s, i)?); - s.eat_comma_block(i)?; - } - s.block_close(i)?; - Ok(JsonValue::Array(out)) - } - DeJsonTok::BlockClose => return Err(s.err_msg("Unexpected ]")), - DeJsonTok::Comma => return Err(s.err_msg("Unexpected ,")), - DeJsonTok::Bof => return Err(s.err_msg("Unexpected Bof")), - DeJsonTok::Eof => return Err(s.err_msg("Unexpected Eof")), - } - } -} - -impl SerJson for [T] -where - T: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('['); - let last = self.len().saturating_sub(1); - for (index, item) in self.iter().enumerate() { - item.ser_json(d + 1, s); - if index != last { - s.out.push(','); - } - } - s.out.push(']'); - } -} - -unsafe fn de_json_array_impl_inner( - top: *mut T, - count: usize, - s: &mut DeJsonState, - i: &mut Chars, -) -> Result<(), DeJsonErr> -where - T: DeJson, -{ - s.block_open(i)?; - for c in 0..count { - top.add(c).write(DeJson::de_json(s, i)?); - s.eat_comma_block(i)?; - } - s.block_close(i)?; - Ok(()) -} - -impl DeJson for [T; N] -where - T: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - unsafe { - let mut to = std::mem::MaybeUninit::<[T; N]>::uninit(); - let top: *mut T = &mut to as *mut _ as *mut T; - de_json_array_impl_inner(top, N, s, i)?; - Ok(to.assume_init()) - } - } -} - -fn de_json_comma_block(s: &mut DeJsonState, i: &mut Chars) -> Result -where - T: DeJson, -{ - let t = DeJson::de_json(s, i); - s.eat_comma_block(i)?; - t -} - -impl SerJson for (A, B) -where - A: SerJson, - B: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('['); - self.0.ser_json(d, s); - s.out.push(','); - self.1.ser_json(d, s); - s.out.push(']'); - } -} - -impl DeJson for (A, B) -where - A: DeJson, - B: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<(A, B), DeJsonErr> { - s.block_open(i)?; - let r = (de_json_comma_block(s, i)?, de_json_comma_block(s, i)?); - s.block_close(i)?; - Ok(r) - } -} - -impl SerJson for (A, B, C) -where - A: SerJson, - B: SerJson, - C: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('['); - self.0.ser_json(d, s); - s.out.push(','); - self.1.ser_json(d, s); - s.out.push(','); - self.2.ser_json(d, s); - s.out.push(']'); - } -} - -impl DeJson for (A, B, C) -where - A: DeJson, - B: DeJson, - C: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<(A, B, C), DeJsonErr> { - s.block_open(i)?; - let r = ( - de_json_comma_block(s, i)?, - de_json_comma_block(s, i)?, - de_json_comma_block(s, i)?, - ); - s.block_close(i)?; - Ok(r) - } -} - -impl SerJson for (A, B, C, D) -where - A: SerJson, - B: SerJson, - C: SerJson, - D: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('['); - self.0.ser_json(d, s); - s.out.push(','); - self.1.ser_json(d, s); - s.out.push(','); - self.2.ser_json(d, s); - s.out.push(','); - self.3.ser_json(d, s); - s.out.push(']'); - } -} - -impl DeJson for (A, B, C, D) -where - A: DeJson, - B: DeJson, - C: DeJson, - D: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result<(A, B, C, D), DeJsonErr> { - s.block_open(i)?; - let r = ( - de_json_comma_block(s, i)?, - de_json_comma_block(s, i)?, - de_json_comma_block(s, i)?, - de_json_comma_block(s, i)?, - ); - s.block_close(i)?; - Ok(r) - } -} - -impl SerJson for HashMap -where - K: SerJson, - V: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - s.out.push('{'); - let last = self.len().saturating_sub(1); - for (index, (k, v)) in self.iter().enumerate() { - s.indent(d + 1); - k.ser_json(d + 1, s); - s.out.push(':'); - v.ser_json(d + 1, s); - if index != last { - s.conl(); - } - } - s.indent(d); - s.out.push('}'); - } -} - -impl DeJson for HashMap -where - K: DeJson + Eq + Hash, - V: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result { - let mut h = HashMap::new(); - s.curly_open(i)?; - while s.tok != DeJsonTok::CurlyClose { - let k = DeJson::de_json(s, i)?; - s.colon(i)?; - let v = DeJson::de_json(s, i)?; - s.eat_comma_curly(i)?; - h.insert(k, v); - } - s.curly_close(i)?; - Ok(h) - } -} - -impl SerJson for Box -where - T: SerJson, -{ - fn ser_json(&self, d: usize, s: &mut SerJsonState) { - (**self).ser_json(d, s) - } -} - -impl DeJson for Box -where - T: DeJson, -{ - fn de_json(s: &mut DeJsonState, i: &mut Chars) -> Result, DeJsonErr> { - Ok(Box::new(DeJson::de_json(s, i)?)) - } -} - -#[cfg(test)] -mod tests { - use super::{DeJson, SerJson}; - use std::collections::HashMap; - - #[test] - fn serialize_empty_hashmap_json() { - let map: HashMap = HashMap::new(); - assert_eq!(map.serialize_json(), "{}"); - } - - #[test] - fn deserialize_f64_scientific_notation() { - let v: f64 = DeJson::deserialize_json("1.25e-2").unwrap(); - assert!((v - 0.0125).abs() < 1e-12); - - let v: f64 = DeJson::deserialize_json("-3E+1").unwrap(); - assert!((v + 30.0).abs() < 1e-12); - } - - #[test] - fn deserialize_u128_integer() { - let value: u128 = DeJson::deserialize_json("1000000000000000019884624838656").unwrap(); - assert_eq!(value, 1000000000000000019884624838656u128); - } - - #[test] - fn deserialize_string_preserves_dollar_signs() { - let value: String = DeJson::deserialize_json("\"▁$($\"").unwrap(); - assert_eq!(value, "▁$($"); - } -} diff --git a/vendor/makepad/libs/micro_serde/src/serde_ron.rs b/vendor/makepad/libs/micro_serde/src/serde_ron.rs deleted file mode 100644 index 78f54ca..0000000 --- a/vendor/makepad/libs/micro_serde/src/serde_ron.rs +++ /dev/null @@ -1,987 +0,0 @@ -use makepad_live_id::LiveId; -use std::collections::HashMap; -use std::hash::Hash; -use std::str::Chars; - -pub struct SerRonState { - pub out: String, -} - -impl SerRonState { - pub fn indent(&mut self, d: usize) { - for _ in 0..d { - self.out.push_str(" "); - } - } - - pub fn field(&mut self, d: usize, field: &str) { - self.indent(d); - self.out.push_str(field); - self.out.push(':'); - } - - pub fn conl(&mut self) { - self.out.push_str(",\n") - } - - pub fn st_pre(&mut self) { - self.out.push_str("(\n"); - } - - pub fn st_post(&mut self, d: usize) { - self.indent(d); - self.out.push(')'); - } -} - -pub trait SerRon { - fn serialize_ron(&self) -> String { - let mut s = SerRonState { out: String::new() }; - self.ser_ron(0, &mut s); - s.out - } - - fn ser_ron(&self, d: usize, s: &mut SerRonState); -} - -pub trait DeRon: Sized { - fn deserialize_ron(input: &str) -> Result { - let mut state = DeRonState::default(); - let mut chars = input.chars(); - state.next(&mut chars); - state.next_tok(&mut chars)?; - DeRon::de_ron(&mut state, &mut chars) - } - - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result; -} - -#[derive(PartialEq, Debug, Default)] -pub enum DeRonTok { - Ident, - Str, - U64(u64), - I64(i64), - F64(f64), - Bool(bool), - Char(char), - Colon, - CurlyOpen, - CurlyClose, - ParenOpen, - ParenClose, - BlockOpen, - BlockClose, - Comma, - #[default] - Bof, - Eof, -} - -#[derive(Default)] -pub struct DeRonState { - pub cur: char, - pub tok: DeRonTok, - pub strbuf: String, - pub numbuf: String, - pub identbuf: String, - pub line: usize, - pub col: usize, -} - -pub struct DeRonErr { - pub msg: String, - pub line: usize, - pub col: usize, -} - -impl std::fmt::Debug for DeRonErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Ron Deserialize error: {}, line:{} col:{}", - self.msg, - self.line + 1, - self.col + 1 - ) - } -} - -impl DeRonState { - pub fn next(&mut self, i: &mut Chars) { - if let Some(c) = i.next() { - self.cur = c; - if self.cur == '\n' { - self.line += 1; - self.col = 0; - } else { - self.col = 0; - } - } else { - self.cur = '\0'; - } - } - - pub fn err_exp(&self, name: &str) -> DeRonErr { - DeRonErr { - msg: format!("Unexpected key {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_nf(&self, name: &str) -> DeRonErr { - DeRonErr { - msg: format!("Key not found {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_enum(&self, name: &str) -> DeRonErr { - DeRonErr { - msg: format!("Enum not defined {}", name), - line: self.line, - col: self.col, - } - } - - pub fn err_token(&self, what: &str) -> DeRonErr { - DeRonErr { - msg: format!("Unexpected token {:?} expected {} ", self.tok, what), - line: self.line, - col: self.col, - } - } - - pub fn err_range(&self, what: &str) -> DeRonErr { - DeRonErr { - msg: format!("Value out of range {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn err_type(&self, what: &str) -> DeRonErr { - DeRonErr { - msg: format!("Token wrong type {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn err_parse(&self, what: &str) -> DeRonErr { - DeRonErr { - msg: format!("Cannot parse {} ", what), - line: self.line, - col: self.col, - } - } - - pub fn eat_comma_paren(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - match self.tok { - DeRonTok::Comma => { - self.next_tok(i)?; - Ok(()) - } - DeRonTok::ParenClose => Ok(()), - _ => Err(self.err_token(", or )")), - } - } - - pub fn eat_comma_block(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - match self.tok { - DeRonTok::Comma => { - self.next_tok(i)?; - Ok(()) - } - DeRonTok::BlockClose => Ok(()), - _ => Err(self.err_token(", or ]")), - } - } - - pub fn eat_comma_curly(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - match self.tok { - DeRonTok::Comma => { - self.next_tok(i)?; - Ok(()) - } - DeRonTok::CurlyClose => Ok(()), - _ => Err(self.err_token(", or }")), - } - } - - pub fn colon(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - match self.tok { - DeRonTok::Colon => { - self.next_tok(i)?; - Ok(()) - } - _ => Err(self.err_token(":")), - } - } - - pub fn ident(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - match &mut self.tok { - DeRonTok::Ident => { - self.next_tok(i)?; - Ok(()) - } - _ => Err(self.err_token("Identifier")), - } - } - - pub fn next_colon(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - self.next_tok(i)?; - self.colon(i)?; - Ok(()) - } - - pub fn next_ident(&mut self) -> Option<()> { - if let DeRonTok::Ident = &mut self.tok { - Some(()) - } else { - None - } - } - - pub fn paren_open(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::ParenOpen { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("(")) - } - - pub fn paren_close(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::ParenClose { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token(")")) - } - - pub fn block_open(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::BlockOpen { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("[")) - } - - pub fn block_close(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::BlockClose { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("]")) - } - - pub fn curly_open(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::CurlyOpen { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("{")) - } - - pub fn curly_close(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - if self.tok == DeRonTok::CurlyClose { - self.next_tok(i)?; - return Ok(()); - } - Err(self.err_token("}")) - } - - pub fn u64_range(&mut self, max: u64) -> Result { - if let DeRonTok::U64(value) = self.tok { - if value > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value); - } - Err(self.err_token("unsigned integer")) - } - - pub fn i64_range(&mut self, min: i64, max: i64) -> Result { - if let DeRonTok::I64(value) = self.tok { - if value < min { - return Err(self.err_range(&format!("{}<{}", value, min))); - } - return Ok(value); - } - if let DeRonTok::U64(value) = self.tok { - if value as i64 > max { - return Err(self.err_range(&format!("{}>{}", value, max))); - } - return Ok(value as i64); - } - Err(self.err_token("signed integer")) - } - - pub fn as_f64(&mut self) -> Result { - if let DeRonTok::I64(value) = self.tok { - return Ok(value as f64); - } - if let DeRonTok::U64(value) = self.tok { - return Ok(value as f64); - } - if let DeRonTok::F64(value) = self.tok { - return Ok(value); - } - Err(self.err_token("floating point")) - } - - pub fn as_bool(&mut self) -> Result { - if let DeRonTok::Bool(value) = self.tok { - return Ok(value); - } - if let DeRonTok::U64(value) = self.tok { - return Ok(value != 0); - } - Err(self.err_token("boolean")) - } - - pub fn as_string(&mut self) -> Result { - if let DeRonTok::Str = &mut self.tok { - let mut val = String::new(); - std::mem::swap(&mut val, &mut self.strbuf); - return Ok(val); - } - Err(self.err_token("string")) - } - - pub fn next_tok(&mut self, i: &mut Chars) -> Result<(), DeRonErr> { - loop { - while self.cur == '\n' || self.cur == '\r' || self.cur == '\t' || self.cur == ' ' { - self.next(i); - } - match self.cur { - '\0' => { - self.tok = DeRonTok::Eof; - return Ok(()); - } - ':' => { - self.next(i); - self.tok = DeRonTok::Colon; - return Ok(()); - } - ',' => { - self.next(i); - self.tok = DeRonTok::Comma; - return Ok(()); - } - '[' => { - self.next(i); - self.tok = DeRonTok::BlockOpen; - return Ok(()); - } - ']' => { - self.next(i); - self.tok = DeRonTok::BlockClose; - return Ok(()); - } - '(' => { - self.next(i); - self.tok = DeRonTok::ParenOpen; - return Ok(()); - } - ')' => { - self.next(i); - self.tok = DeRonTok::ParenClose; - return Ok(()); - } - '{' => { - self.next(i); - self.tok = DeRonTok::CurlyOpen; - return Ok(()); - } - '}' => { - self.next(i); - self.tok = DeRonTok::CurlyClose; - return Ok(()); - } - '/' => { - self.next(i); - if self.cur == '/' { - // single line comment - while self.cur != '\0' { - if self.cur == '\n' { - self.next(i); - break; - } - self.next(i); - } - } else if self.cur == '*' { - // multline comment - let mut last_star = false; - while self.cur != '\0' { - if self.cur == '/' && last_star { - self.next(i); - break; - } - last_star = self.cur == '*'; - self.next(i); - } - } else { - return Err(self.err_parse("comment")); - } - } - '-' | '0'..='9' => { - self.numbuf.clear(); - let is_neg = if self.cur == '-' { - self.numbuf.push(self.cur); - self.next(i); - true - } else { - false - }; - while self.cur >= '0' && self.cur <= '9' { - self.numbuf.push(self.cur); - self.next(i); - } - if self.cur == '.' { - self.numbuf.push(self.cur); - self.next(i); - while self.cur >= '0' && self.cur <= '9' { - self.numbuf.push(self.cur); - self.next(i); - } - if let Ok(num) = self.numbuf.parse() { - self.tok = DeRonTok::F64(num); - return Ok(()); - } else { - return Err(self.err_parse("number")); - } - } else { - if is_neg { - if let Ok(num) = self.numbuf.parse() { - self.tok = DeRonTok::I64(num); - return Ok(()); - } else { - return Err(self.err_parse("number")); - } - } - if let Ok(num) = self.numbuf.parse() { - self.tok = DeRonTok::U64(num); - return Ok(()); - } else { - return Err(self.err_parse("number")); - } - } - } - 'a'..='z' | 'A'..='Z' | '_' | '$' => { - self.identbuf.clear(); - self.identbuf.push(self.cur); - self.next(i); - - while self.cur >= 'a' && self.cur <= 'z' - || self.cur >= 'A' && self.cur <= 'Z' - || self.cur == '_' - || self.cur == '$' - || self.cur >= '0' && self.cur <= '9' - { - self.identbuf.push(self.cur); - self.next(i); - } - if self.identbuf == "true" { - self.tok = DeRonTok::Bool(true); - return Ok(()); - } - if self.identbuf == "false" { - self.tok = DeRonTok::Bool(false); - return Ok(()); - } - self.tok = DeRonTok::Ident; - return Ok(()); - } - '\'' => { - self.next(i); - if self.cur == '\\' { - self.next(i); - } - let chr = self.cur; - self.next(i); - if self.cur != '\'' { - return Err(self.err_token("char")); - } - self.next(i); - self.tok = DeRonTok::Char(chr); - } - '"' => { - self.strbuf.clear(); - self.next(i); - while self.cur != '"' { - if self.cur == '\\' { - self.next(i); - match self.cur { - 'n' => self.strbuf.push('\n'), - 'r' => self.strbuf.push('\r'), - 't' => self.strbuf.push('\t'), - '0' => self.strbuf.push('\0'), - '\0' => { - return Err(self.err_parse("string")); - } - _ => self.strbuf.push(self.cur), - } - self.next(i); - } else { - if self.cur == '\0' { - return Err(self.err_parse("string")); - } - self.strbuf.push(self.cur); - self.next(i); - } - } - self.next(i); - self.tok = DeRonTok::Str; - return Ok(()); - } - _ => { - return Err(self.err_token("tokenizer")); - } - } - } - } -} - -macro_rules! impl_ser_de_ron_unsigned { - ( $ ty: ident, $ max: expr) => { - impl SerRon for $ty { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeRon for $ty { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<$ty, DeRonErr> { - //s.is_prefix(p, i) ?; - let val = s.u64_range($max as u64)?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -macro_rules! impl_ser_de_ron_signed { - ( $ ty: ident, $ min: expr, $ max: expr) => { - impl SerRon for $ty { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeRon for $ty { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<$ty, DeRonErr> { - //s.is_prefix(p, i) ?; - let val = s.i64_range($min as i64, $max as i64)?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -macro_rules! impl_ser_de_ron_float { - ( $ ty: ident) => { - impl SerRon for $ty { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - s.out.push_str(&self.to_string()); - } - } - - impl DeRon for $ty { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<$ty, DeRonErr> { - //s.is_prefix(p, i) ?; - let val = s.as_f64()?; - s.next_tok(i)?; - return Ok(val as $ty); - } - } - }; -} - -impl_ser_de_ron_unsigned!(usize, std::usize::MAX); -impl_ser_de_ron_unsigned!(u64, std::u64::MAX); -impl_ser_de_ron_unsigned!(u32, std::u32::MAX); -impl_ser_de_ron_unsigned!(u16, std::u16::MAX); -impl_ser_de_ron_unsigned!(u8, std::u8::MAX); -impl_ser_de_ron_signed!(i64, std::i64::MIN, std::i64::MAX); -impl_ser_de_ron_signed!(i32, std::i64::MIN, std::i64::MAX); -impl_ser_de_ron_signed!(i16, std::i64::MIN, std::i64::MAX); -impl_ser_de_ron_signed!(i8, std::i64::MIN, std::i8::MAX); -impl_ser_de_ron_float!(f64); -impl_ser_de_ron_float!(f32); - -impl SerRon for Option -where - T: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - if let Some(v) = self { - v.ser_ron(d, s); - } else { - s.out.push_str("None"); - } - } -} - -impl DeRon for Option -where - T: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - if let DeRonTok::Ident = &s.tok { - if s.identbuf == "None" { - s.next_tok(i)?; - return Ok(None); - } - } - Ok(Some(DeRon::de_ron(s, i)?)) - } -} - -impl SerRon for bool { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - if *self { - s.out.push_str("true") - } else { - s.out.push_str("false") - } - } -} - -impl DeRon for bool { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - let val = s.as_bool()?; - s.next_tok(i)?; - Ok(val) - } -} - -impl SerRon for String { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - s.out.push('"'); - for c in self.chars() { - match c { - '\n' => { - s.out.push('\\'); - s.out.push('n'); - } - '\r' => { - s.out.push('\\'); - s.out.push('r'); - } - '\t' => { - s.out.push('\\'); - s.out.push('t'); - } - '\0' => { - s.out.push('\\'); - s.out.push('0'); - } - '\\' => { - s.out.push('\\'); - s.out.push('\\'); - } - '"' => { - s.out.push('\\'); - s.out.push('"'); - } - _ => s.out.push(c), - } - } - s.out.push('"'); - } -} - -impl DeRon for String { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - let val = s.as_string()?; - s.next_tok(i)?; - Ok(val) - } -} - -impl SerRon for Vec -where - T: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push_str("[\n"); - for item in self { - s.indent(d + 1); - item.ser_ron(d + 1, s); - s.conl(); - } - s.indent(d); - s.out.push(']'); - } -} - -impl DeRon for Vec -where - T: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result, DeRonErr> { - let mut out = Vec::new(); - s.block_open(i)?; - - while s.tok != DeRonTok::BlockClose { - out.push(DeRon::de_ron(s, i)?); - s.eat_comma_block(i)?; - } - s.block_close(i)?; - Ok(out) - } -} - -impl SerRon for [T] -where - T: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push('('); - let last = self.len().saturating_sub(1); - for (index, item) in self.iter().enumerate() { - item.ser_ron(d + 1, s); - if index != last { - s.out.push_str(", "); - } - } - s.out.push(')'); - } -} - -unsafe fn de_ron_array_impl_inner( - top: *mut T, - count: usize, - s: &mut DeRonState, - i: &mut Chars, -) -> Result<(), DeRonErr> -where - T: DeRon, -{ - s.paren_open(i)?; - for c in 0..count { - top.add(c).write(DeRon::de_ron(s, i)?); - s.eat_comma_paren(i)?; - } - s.paren_close(i)?; - Ok(()) -} - -impl DeRon for [T; N] -where - T: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - unsafe { - let mut to = std::mem::MaybeUninit::<[T; N]>::uninit(); - let top: *mut T = &mut to as *mut _ as *mut T; - de_ron_array_impl_inner(top, N, s, i)?; - Ok(to.assume_init()) - } - } -} - -fn de_ron_comma_paren(s: &mut DeRonState, i: &mut Chars) -> Result -where - T: DeRon, -{ - let t = DeRon::de_ron(s, i); - s.eat_comma_paren(i)?; - t -} - -impl SerRon for (A, B) -where - A: SerRon, - B: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push('('); - self.0.ser_ron(d, s); - s.out.push_str(", "); - self.1.ser_ron(d, s); - s.out.push(')'); - } -} - -impl DeRon for (A, B) -where - A: DeRon, - B: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<(A, B), DeRonErr> { - s.paren_open(i)?; - let r = (de_ron_comma_paren(s, i)?, de_ron_comma_paren(s, i)?); - s.paren_close(i)?; - Ok(r) - } -} - -impl SerRon for (A, B, C) -where - A: SerRon, - B: SerRon, - C: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push('('); - self.0.ser_ron(d, s); - s.out.push_str(", "); - self.1.ser_ron(d, s); - s.out.push_str(", "); - self.2.ser_ron(d, s); - s.out.push(')'); - } -} - -impl DeRon for (A, B, C) -where - A: DeRon, - B: DeRon, - C: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<(A, B, C), DeRonErr> { - s.paren_open(i)?; - let r = ( - de_ron_comma_paren(s, i)?, - de_ron_comma_paren(s, i)?, - de_ron_comma_paren(s, i)?, - ); - s.paren_close(i)?; - Ok(r) - } -} - -impl SerRon for (A, B, C, D) -where - A: SerRon, - B: SerRon, - C: SerRon, - D: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push('('); - self.0.ser_ron(d, s); - s.out.push_str(", "); - self.1.ser_ron(d, s); - s.out.push_str(", "); - self.2.ser_ron(d, s); - s.out.push_str(", "); - self.3.ser_ron(d, s); - s.out.push(')'); - } -} - -impl DeRon for (A, B, C, D) -where - A: DeRon, - B: DeRon, - C: DeRon, - D: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result<(A, B, C, D), DeRonErr> { - s.paren_open(i)?; - let r = ( - de_ron_comma_paren(s, i)?, - de_ron_comma_paren(s, i)?, - de_ron_comma_paren(s, i)?, - de_ron_comma_paren(s, i)?, - ); - s.paren_close(i)?; - Ok(r) - } -} - -impl SerRon for HashMap -where - K: SerRon, - V: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - s.out.push_str("{\n"); - for (k, v) in self { - s.indent(d + 1); - k.ser_ron(d + 1, s); - s.out.push(':'); - v.ser_ron(d + 1, s); - s.conl(); - } - s.indent(d); - s.out.push('}'); - } -} - -impl DeRon for HashMap -where - K: DeRon + Eq + Hash, - V: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - let mut h = HashMap::new(); - s.curly_open(i)?; - while s.tok != DeRonTok::CurlyClose { - let k = DeRon::de_ron(s, i)?; - s.colon(i)?; - let v = DeRon::de_ron(s, i)?; - s.eat_comma_curly(i)?; - h.insert(k, v); - } - s.curly_close(i)?; - Ok(h) - } -} - -impl SerRon for Box -where - T: SerRon, -{ - fn ser_ron(&self, d: usize, s: &mut SerRonState) { - (**self).ser_ron(d, s) - } -} - -impl DeRon for Box -where - T: DeRon, -{ - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result, DeRonErr> { - Ok(Box::new(DeRon::de_ron(s, i)?)) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct LiveIdRon(pub LiveId); - -impl SerRon for LiveId { - fn ser_ron(&self, _d: usize, s: &mut SerRonState) { - self.as_string(|v| { - if let Some(v) = v { - s.out.push_str(v); - } else { - s.out.push_str(&self.0.to_string()); - } - }); - } -} - -impl DeRon for LiveId { - fn de_ron(s: &mut DeRonState, i: &mut Chars) -> Result { - let liveid = match s.tok { - DeRonTok::U64(value) => LiveId(value), - DeRonTok::I64(value) => LiveId(value as u64), - DeRonTok::F64(value) => LiveId(value as u64), - DeRonTok::Ident => LiveId::from_str_with_lut(&s.identbuf).unwrap(), - _ => { - // err - return Err(s.err_token("liveid")); - } - }; - s.next_tok(i)?; - Ok(liveid) - } -} diff --git a/vendor/makepad/libs/regex/Cargo.toml b/vendor/makepad/libs/regex/Cargo.toml deleted file mode 100644 index dd99dc6..0000000 --- a/vendor/makepad/libs/regex/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "makepad-regex" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/vendor/makepad/libs/regex/src/ast.rs b/vendor/makepad/libs/regex/src/ast.rs deleted file mode 100644 index 467951e..0000000 --- a/vendor/makepad/libs/regex/src/ast.rs +++ /dev/null @@ -1,147 +0,0 @@ -use { - super::{char_class::CharClass, prog::Pred}, - std::mem, -}; - -#[derive(Clone, Debug)] -pub enum Op { - Empty, - Cap(usize), - Alt, - Cat, - Ques(bool), - Star(bool), - Plus(bool), - Assert(Pred), - Char(char), - CharClass(CharClass), -} - -#[derive(Debug)] -pub struct Builder { - ops: Vec, - tmp_ops: Vec, - start_stack: Vec, -} - -impl Builder { - pub fn new() -> Self { - Self { - ops: Vec::new(), - tmp_ops: Vec::new(), - start_stack: Vec::new(), - } - } - - pub fn stack_depth(&self) -> usize { - self.start_stack.len() - } - - pub fn empty(&mut self) { - let start = self.ops.len(); - self.ops.push(Op::Empty); - self.start_stack.push(start); - } - - pub fn cap(&mut self, index: usize) { - self.ops.push(Op::Cap(index)); - } - - pub fn alt(&mut self) { - self.ops.push(Op::Alt); - self.start_stack.pop().unwrap(); - } - - pub fn cat(&mut self) { - self.ops.push(Op::Cat); - self.start_stack.pop().unwrap(); - } - - pub fn ques(&mut self, greedy: bool) { - self.ops.push(Op::Ques(greedy)); - } - - pub fn star(&mut self, greedy: bool) { - self.ops.push(Op::Star(greedy)); - } - - pub fn plus(&mut self, greedy: bool) { - self.ops.push(Op::Plus(greedy)); - } - - pub fn rep(&mut self, min: u32, max: Option, greedy: bool) { - let start = self.start_stack.last().unwrap(); - self.tmp_ops.extend(self.ops.drain(start..)); - match max { - Some(max) => { - if min == 0 && max == 0 { - self.ops.push(Op::Empty); - } else if min == 1 && max == 1 { - self.ops.extend(self.tmp_ops.iter().cloned()); - } else { - if min > 0 { - self.ops.extend(self.tmp_ops.iter().cloned()); - for _ in 1..min { - self.ops.extend(self.tmp_ops.iter().cloned()); - self.ops.push(Op::Cat); - } - } - if max > min { - for _ in min..max { - self.ops.extend(self.tmp_ops.iter().cloned()); - } - for _ in min + 1..max { - self.ops.push(Op::Ques(greedy)); - self.ops.push(Op::Cat); - } - self.ops.push(Op::Ques(greedy)); - if min > 0 { - self.ops.push(Op::Cat); - } - } - } - } - None => { - if min == 0 { - self.ops.extend(self.tmp_ops.iter().cloned()); - self.ops.push(Op::Star(greedy)); - } else if min == 1 { - self.ops.extend(self.tmp_ops.iter().cloned()); - self.ops.push(Op::Plus(greedy)); - } else { - self.ops.extend(self.tmp_ops.iter().cloned()); - for _ in 1..(min - 1) { - self.ops.extend(self.tmp_ops.iter().cloned()); - self.ops.push(Op::Cat); - } - self.ops.extend(self.tmp_ops.iter().cloned()); - self.ops.push(Op::Plus(greedy)); - self.ops.push(Op::Cat); - } - } - } - self.tmp_ops.clear(); - } - - pub fn assert(&mut self, pred: Pred) { - let start = self.ops.len(); - self.ops.push(Op::Assert(pred)); - self.start_stack.push(start); - } - - pub fn char(&mut self, c: char) { - let start = self.ops.len(); - self.ops.push(Op::Char(c)); - self.start_stack.push(start); - } - - pub fn char_class(&mut self, class: CharClass) { - let start = self.ops.len(); - self.ops.push(Op::CharClass(class)); - self.start_stack.push(start); - } - - pub fn build(&mut self) -> Vec { - mem::replace(&mut self.ops, Vec::new()) - } -} diff --git a/vendor/makepad/libs/regex/src/basic.dat b/vendor/makepad/libs/regex/src/basic.dat deleted file mode 100644 index 632e1bb..0000000 --- a/vendor/makepad/libs/regex/src/basic.dat +++ /dev/null @@ -1,221 +0,0 @@ -NOTE all standard compliant implementations should pass these : 2002-05-31 - -BE abracadabra$ abracadabracadabra (7,18) -BE a...b abababbb (2,7) -BE XXXXXX ..XXXXXX (2,8) -E \) () (1,2) -BE a] a]a (0,2) -B } } (0,1) -E \} } (0,1) -BE \] ] (0,1) -B ] ] (0,1) -E ] ] (0,1) -B { { (0,1) -B } } (0,1) -BE ^a ax (0,1) -BE \^a a^a (1,3) -BE a\^ a^ (0,2) -BE a$ aa (1,2) -BE a\$ a$ (0,2) -BE ^$ NULL (0,0) -E $^ NULL (0,0) -E a($) aa (1,2)(2,2) -E a*(^a) aa (0,1)(0,1) -E (..)*(...)* a (0,0) -E (..)*(...)* abcd (0,4)(2,4) -E (ab|a)(bc|c) abc (0,3)(0,2)(2,3) -E (ab)c|abc abc (0,3)(0,2) -E a{0}b ab (1,2) -E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) -E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) -E a{9876543210} NULL BADBR -E ((a|a)|a) a (0,1)(0,1)(0,1) -E (a*)(a|aa) aaaa (0,4)(0,3)(3,4) -E a*(a.|aa) aaaa (0,4)(2,4) -E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2) -E (a|b)?.* b (0,1)(0,1) -E (a|b)c|a(b|c) ac (0,2)(0,1) -E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2) -E (a|b)*c|(a|ab)*c abc (0,3)(1,2) -E (a|b)*c|(a|ab)*c xc (1,2) -E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2) -E a?(ab|ba)ab abab (0,4)(0,2) -E a?(ac{0}b|ba)ab abab (0,4)(0,2) -E ab|abab abbabab (0,2) -E aba|bab|bba baaabbbaba (5,8) -E aba|bab baaabbbaba (6,9) -E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2) -E (a.|.a.)*|(a|.a...) aa (0,2)(0,2) -E ab|a xabc (1,3) -E ab|a xxabc (2,4) -Ei (?-u)(Ab|cD)* aBcD (0,4)(2,4) -BE [^-] --a (2,3) -BE [a-]* --a (0,3) -BE [a-m-]* --amoma-- (0,4) -E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17) -E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17) -{E [[:upper:]] A (0,1) [[]] not supported -E [[:lower:]]+ `az{ (1,3) -E [[:upper:]]+ @AZ[ (1,3) -# No collation in Go -#BE [[-]] [[-]] (2,4) -#BE [[.NIL.]] NULL ECOLLATE -#BE [[=aleph=]] NULL ECOLLATE -} -BE$ \n \n (0,1) -BEn$ \n \n (0,1) -BE$ [^a] \n (0,1) -BE$ \na \na (0,2) -E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3) -BE xxx xxx (0,3) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11) -E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1) -E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2) -E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81) -E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25) -E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22) -E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11) -BE$ .* \x01\x7f (0,2) -E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57) -L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH -E a*a*a*a*a*b aaaaaaaaab (0,10) -BE ^ NULL (0,0) -BE $ NULL (0,0) -BE ^$ NULL (0,0) -BE ^a$ a (0,1) -BE abc abc (0,3) -BE abc xabcy (1,4) -BE abc ababc (2,5) -BE ab*c abc (0,3) -BE ab*bc abc (0,3) -BE ab*bc abbc (0,4) -BE ab*bc abbbbc (0,6) -E ab+bc abbc (0,4) -E ab+bc abbbbc (0,6) -E ab?bc abbc (0,4) -E ab?bc abc (0,3) -E ab?c abc (0,3) -BE ^abc$ abc (0,3) -BE ^abc abcc (0,3) -BE abc$ aabc (1,4) -BE ^ abc (0,0) -BE $ abc (3,3) -BE a.c abc (0,3) -BE a.c axc (0,3) -BE a.*c axyzc (0,5) -BE a[bc]d abd (0,3) -BE a[b-d]e ace (0,3) -BE a[b-d] aac (1,3) -BE a[-b] a- (0,2) -BE a[b-] a- (0,2) -BE a] a] (0,2) -BE a[]]b a]b (0,3) -BE a[^bc]d aed (0,3) -BE a[^-b]c adc (0,3) -BE a[^]b]c adc (0,3) -E ab|cd abc (0,2) -E ab|cd abcd (0,2) -E a\(b a(b (0,3) -E a\(*b ab (0,2) -E a\(*b a((b (0,4) -E ((a)) abc (0,1)(0,1)(0,1) -E (a)b(c) abc (0,3)(0,1)(2,3) -E a+b+c aabbabc (4,7) -E a* aaa (0,3) -#E (a*)* - (0,0)(0,0) -E (a*)* - (0,0)(?,?) RE2/Go -E (a*)+ - (0,0)(0,0) -#E (a*|b)* - (0,0)(0,0) -E (a*|b)* - (0,0)(?,?) RE2/Go -E (a+|b)* ab (0,2)(1,2) -E (a+|b)+ ab (0,2)(1,2) -E (a+|b)? ab (0,1)(0,1) -BE [^ab]* cde (0,3) -#E (^)* - (0,0)(0,0) -E (^)* - (0,0)(?,?) RE2/Go -BE a* NULL (0,0) -E ([abc])*d abbbcd (0,6)(4,5) -E ([abc])*bcd abcd (0,4)(0,1) -E a|b|c|d|e e (0,1) -E (a|b|c|d|e)f ef (0,2)(0,1) -#E ((a*|b))* - (0,0)(0,0)(0,0) -E ((a*|b))* - (0,0)(?,?)(?,?) RE2/Go -BE abcd*efg abcdefg (0,7) -BE ab* xabyabbbz (1,3) -BE ab* xayabbbz (1,2) -E (ab|cd)e abcde (2,5)(2,4) -BE [abhgefdc]ij hij (0,3) -E (a|b)c*d abcd (1,4)(1,2) -E (ab|ab*)bc abc (0,3)(0,1) -E a([bc]*)c* abc (0,3)(1,3) -E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4) -E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4) -E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4) -E a[bcd]*dcdcde adcdcde (0,7) -E (ab|a)b*c abc (0,3)(0,2) -E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4) -BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5) -E ^a(bc+|b[eh])g|.h$ abh (1,3) -E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5) -E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2) -E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6) -E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1) -BE multiple words multiple words yeah (0,14) -E (.*)c(.*) abcde (0,5)(0,2)(3,5) -BE abcd abcd (0,4) -E a(bc)d abcd (0,4)(1,3) -E a[-]?c ac (0,3) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12) -E a+(b|c)*d+ aabcdd (0,6)(3,4) -E ^.+$ vivi (0,4) -E ^(.+)$ vivi (0,4)(0,4) -E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19) -E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3) -E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7) -E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7) -E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11) -E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3) -E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7) -E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3) -E ((foo)|bar)!bas bar!bas (0,7)(0,3) -E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7) -E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3) -E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3) -E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7) -E (foo|(bar))!bas foo!bas (0,7)(0,3) -E (foo|bar)!bas bar!bas (0,7)(0,3) -E (foo|bar)!bas foo!bar!bas (4,11)(4,7) -E (foo|bar)!bas foo!bas (0,7)(0,3) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7) -E .*(/XXX).* /XXX (0,4)(0,4) -E .*(\\XXX).* \XXX (0,4)(0,4) -E \\XXX \XXX (0,4) -E .*(/000).* /000 (0,4)(0,4) -E .*(\\000).* \000 (0,4)(0,4) -E \\000 \000 (0,4) diff --git a/vendor/makepad/libs/regex/src/case_fold.rs b/vendor/makepad/libs/regex/src/case_fold.rs deleted file mode 100644 index 1bee5a3..0000000 --- a/vendor/makepad/libs/regex/src/case_fold.rs +++ /dev/null @@ -1,77 +0,0 @@ -use { - super::{range::Range, unicode::CASE_FOLDS}, - std::cmp::Ordering, -}; - -pub fn case_fold_range(range: Range, mut f: F) -where - F: FnMut(Range), -{ - if !contains_case_fold(range) { - // No entry in the unicode case fold table — add the original range - // plus simple upper/lowercase mappings for each character - f(range); - let start = range.start as u32; - let end = (range.end as u32) + 1; - for c in (start..end).filter_map(char::from_u32) { - for mapped in c.to_uppercase() { - if mapped != c { - f(Range::new(mapped, mapped)); - } - } - for mapped in c.to_lowercase() { - if mapped != c { - f(Range::new(mapped, mapped)); - } - } - } - return; - } - let start = range.start as u32; - let end = (range.end as u32) + 1; - let mut next_c = None; - for c in (start..end).filter_map(char::from_u32) { - if next_c.map_or(false, |next_c| c < next_c) { - f(Range::new(c, c)); - continue; - } - match find_case_fold(c) { - Ok(folding) => { - for &c in folding { - f(Range::new(c, c)) - } - } - Err(c) => { - next_c = c; - continue; - } - } - } -} - -fn contains_case_fold(range: Range) -> bool { - CASE_FOLDS - .binary_search_by(|&(c, _)| { - if c < range.start { - return Ordering::Less; - } - if c > range.end { - return Ordering::Greater; - } - return Ordering::Equal; - }) - .is_ok() -} - -fn find_case_fold(c: char) -> Result<&'static [char], Option> { - CASE_FOLDS - .binary_search_by_key(&c, |&(c, _)| c) - .map(|i| CASE_FOLDS[i].1) - .map_err(|i| { - if i < CASE_FOLDS.len() { - Some(CASE_FOLDS[i].0) - } else { - None - } - }) -} diff --git a/vendor/makepad/libs/regex/src/char.rs b/vendor/makepad/libs/regex/src/char.rs deleted file mode 100644 index bea2a97..0000000 --- a/vendor/makepad/libs/regex/src/char.rs +++ /dev/null @@ -1,48 +0,0 @@ -/// Extensions to `char`. -pub trait CharExt { - fn is_ascii_word(self) -> bool; - - fn is_word(self) -> bool; -} - -impl CharExt for char { - /// Returns `true` if the `char` is an ASCII word character: - /// - /// * U+0030 '0' ..= U+0039 '9', or - /// * U+0041 'A' ..= U+005A 'Z', or - /// * U+005F '_', or - /// * U+0061 'a' ..= U+007A 'z', or - fn is_ascii_word(self) -> bool { - match self { - '0'..='9' | 'A'..='Z' | '_' | 'a'..='z' => true, - _ => false, - } - } - - /// Returns `true` if the `char` has the `Word` compatibility property. - /// - /// `Word` is described in Annex C (Compatibility Properties) of the - /// [Unicode Technical Standard #18]. - /// - /// [Unicode Technical Standard #18]: https://unicode.org/reports/tr18/ - fn is_word(self) -> bool { - use super::unicode; - - if self.is_ascii() && self.is_ascii_word() { - return true; - } - unicode::WORD - .binary_search_by(|range| { - use std::cmp::Ordering; - - if range.end < self { - return Ordering::Less; - } - if range.start > self { - return Ordering::Greater; - } - Ordering::Equal - }) - .is_ok() - } -} diff --git a/vendor/makepad/libs/regex/src/char_class.rs b/vendor/makepad/libs/regex/src/char_class.rs deleted file mode 100644 index de706aa..0000000 --- a/vendor/makepad/libs/regex/src/char_class.rs +++ /dev/null @@ -1,213 +0,0 @@ -use { - super::{case_fold, range::Range}, - std::{cmp::Ordering, collections::BTreeMap, slice}, -}; - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct CharClass { - bounds: Vec, -} - -impl CharClass { - pub fn any() -> Self { - Self { - bounds: vec![0, char::MAX as u32 + 1], - } - } - - pub fn contains(&self, c: char) -> bool { - let c = c as u32; - match self.bounds.binary_search_by(|&bound| { - if bound < c { - return Ordering::Less; - } - if bound > c { - return Ordering::Greater; - } - Ordering::Equal - }) { - Ok(index) => index % 2 == 0, - Err(index) => index % 2 == 1, - } - } - - pub fn iter(&self) -> Iter<'_> { - Iter { - iter: self.bounds.iter(), - } - } -} - -impl<'a> IntoIterator for &'a CharClass { - type Item = Range; - type IntoIter = Iter<'a>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -#[derive(Clone, Debug)] -pub struct Iter<'a> { - iter: slice::Iter<'a, u32>, -} - -impl<'a> Iterator for Iter<'a> { - type Item = Range; - - fn next(&mut self) -> Option { - Some(Range { - start: char::from_u32(*self.iter.next()?).unwrap(), - end: char::from_u32(*self.iter.next()? - 1).unwrap(), - }) - } -} - -#[derive(Debug)] -pub struct Builder { - deltas: BTreeMap, -} - -impl Builder { - pub fn new() -> Self { - Self { - deltas: BTreeMap::new(), - } - } - - pub fn add_ranges(&mut self, negated: bool, folded: bool, ranges: &[Range]) { - if negated { - if folded { - let mut builder = Builder::new(); - for &range in ranges { - builder.add_range(true, range); - } - let class = builder.build(true); - for range in &class { - self.add_range_internal(Range::new(range.start as u32, range.end as u32)); - } - } else { - let mut add_range = |range: Range| { - if range.start <= 0xD7FF && range.end >= 0xE000 { - self.add_range_internal(Range::new(range.start, 0xD7FF)); - self.add_range_internal(Range::new(0xE000, range.end)); - return; - } - self.add_range_internal(Range::new(range.start, range.end)) - }; - if ranges.is_empty() { - return; - } - let first_range_start = ranges.first().unwrap().start as u32; - if first_range_start > 0 { - add_range(Range::new(0, first_range_start - 1)); - } - for window in ranges.windows(2) { - let previous_range_end = window[0].end as u32; - let next_range_start = window[1].start as u32; - assert!(previous_range_end + 1 < next_range_start); - add_range(Range::new(previous_range_end + 1, next_range_start - 1)); - } - let last_range_end = ranges.last().unwrap().end as u32; - if last_range_end < 0x10FFFF { - add_range(Range::new(last_range_end + 1, 0x10FFFF)); - } - } - } else { - for &range in ranges { - self.add_range(folded, range); - } - } - } - - pub fn add_range(&mut self, folded: bool, range: Range) { - if folded { - case_fold::case_fold_range(range, |folded_range| { - self.add_range_internal(Range::new( - folded_range.start as u32, - folded_range.end as u32, - )) - }) - } else { - self.add_range_internal(Range::new(range.start as u32, range.end as u32)) - } - } - - pub fn add_char(&mut self, folded: bool, c: char) { - self.add_range(folded, Range::new(c, c)); - } - - pub fn build(&mut self, negated: bool) -> CharClass { - let mut bounds = Vec::new(); - if negated { - if !self.deltas.contains_key(&0) { - bounds.push(0); - } - let mut count = 0; - for (&bound, &delta) in self.deltas.range(1..0xD800) { - let next_count = count + delta; - if (count != 0) != (next_count != 0) { - bounds.push(bound); - } - count = next_count; - } - if !self.deltas.contains_key(&0xD800) { - bounds.push(0xD800); - } - if !self.deltas.contains_key(&0xE000) { - bounds.push(0xE000); - } - let mut count = 0; - for (&bound, &delta) in self.deltas.range(0xE001..0x110000) { - let next_count = count + delta; - if (count != 0) != (next_count != 0) { - bounds.push(bound); - } - count = next_count; - } - if !self.deltas.contains_key(&0x110000) { - bounds.push(0x110000); - } - } else { - let mut count = 0; - for (&bound, &delta) in &self.deltas { - let next_count = count + delta; - if (count != 0) != (next_count != 0) { - bounds.push(bound); - } - count = next_count; - } - } - self.deltas.clear(); - CharClass { bounds } - } - - fn add_range_internal(&mut self, range: Range) { - use std::collections::btree_map::Entry; - - match self.deltas.entry(range.start) { - Entry::Occupied(mut entry) => { - if *entry.get() == -1 { - entry.remove(); - } else { - *entry.get_mut() += 1; - } - } - Entry::Vacant(entry) => { - entry.insert(1); - } - } - match self.deltas.entry(range.end + 1) { - Entry::Occupied(mut entry) => { - if *entry.get() == 1 { - entry.remove(); - } else { - *entry.get_mut() -= 1; - } - } - Entry::Vacant(entry) => { - entry.insert(-1); - } - } - } -} diff --git a/vendor/makepad/libs/regex/src/compile.rs b/vendor/makepad/libs/regex/src/compile.rs deleted file mode 100644 index 146058c..0000000 --- a/vendor/makepad/libs/regex/src/compile.rs +++ /dev/null @@ -1,574 +0,0 @@ -use { - super::{ - ast::Op, - char::CharExt, - char_class::CharClass, - prog::{Inst, InstPtr, Pred, Prog, NULL_INST}, - range::Range, - utf8::ByteRangeSeqsAllocs, - }, - std::collections::HashMap, -}; - -#[derive(Clone, Copy, Default)] -pub struct Options { - pub dot_star: bool, - pub ignore_caps: bool, - pub byte_based: bool, - pub reversed: bool, -} - -#[derive(Debug)] -pub struct Allocs { - frag_stack: Vec, - byte_range_seqs_allocs: ByteRangeSeqsAllocs, - class_compiler_allocs: ClassCompilerAllocs, -} - -impl Allocs { - pub fn new() -> Self { - Self { - frag_stack: Vec::new(), - byte_range_seqs_allocs: ByteRangeSeqsAllocs::new(), - class_compiler_allocs: ClassCompilerAllocs::new(), - } - } -} - -pub fn compile(ops: &Vec, options: Options, cache: &mut Allocs) -> Prog { - let mut compiler = Compiler::new(options, cache); - for op in ops { - match *op { - Op::Empty => compiler.empty(), - Op::Cap(index) => compiler.cap(index), - Op::Alt => compiler.alt(), - Op::Cat => compiler.cat(), - Op::Ques(greedy) => compiler.ques(greedy), - Op::Star(greedy) => compiler.star(greedy), - Op::Plus(greedy) => compiler.plus(greedy), - Op::Assert(pred) => compiler.assert(pred), - Op::Char(c) => compiler.char(c), - Op::CharClass(ref class) => compiler.char_class(class), - } - } - compiler.compile() -} - -#[derive(Debug)] -struct Compiler<'a> { - dot_star: bool, - ignore_caps: bool, - reversed: bool, - byte_based: bool, - emitter: Emitter, - frag_stack: &'a mut Vec, - has_word_boundary: bool, - slot_count: usize, - byte_classes_builder: ByteClassesBuilder, - byte_range_seqs_cache: &'a mut ByteRangeSeqsAllocs, - class_compiler_cache: &'a mut ClassCompilerAllocs, -} - -impl<'a> Compiler<'a> { - fn new(options: Options, cache: &'a mut Allocs) -> Self { - let mut compiler = Self { - dot_star: options.dot_star, - ignore_caps: options.ignore_caps, - byte_based: options.byte_based, - reversed: options.reversed, - emitter: Emitter { insts: Vec::new() }, - frag_stack: &mut cache.frag_stack, - has_word_boundary: false, - slot_count: 0, - byte_classes_builder: ByteClassesBuilder::new(), - byte_range_seqs_cache: &mut cache.byte_range_seqs_allocs, - class_compiler_cache: &mut cache.class_compiler_allocs, - }; - if compiler.dot_star { - let class = CharClass::any(); - compiler.char_class(&class); - compiler.star(false); - } - compiler - } - - fn empty(&mut self) { - let inst = self.emitter.emit(Inst::nop(NULL_INST)); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst)))); - } - - fn cap(&mut self, index: usize) { - if self.ignore_caps { - return; - } - let frag = self.frag_stack.pop().unwrap(); - let inst_0 = self.emitter.emit(Inst::save(frag.start, 2 * index)); - let inst_1 = self.emitter.emit(Inst::save(NULL_INST, 2 * index + 1)); - self.slot_count += 2; - frag.ends.fill(inst_1, &mut self.emitter.insts); - self.frag_stack - .push(Frag::new(inst_0, HolePtrList::unit(HolePtr::out_0(inst_1)))); - } - - fn alt(&mut self) { - let frag_1 = self.frag_stack.pop().unwrap(); - let frag_0 = self.frag_stack.pop().unwrap(); - let inst = self.emitter.emit(Inst::split(frag_0.start, frag_1.start)); - self.frag_stack.push(Frag::new( - inst, - frag_0.ends.concat(frag_1.ends, &mut self.emitter.insts), - )); - } - - fn cat(&mut self) { - let frag_1 = self.frag_stack.pop().unwrap(); - let frag_0 = self.frag_stack.pop().unwrap(); - let frag; - if self.reversed { - frag_1.ends.fill(frag_0.start, &mut self.emitter.insts); - frag = Frag::new(frag_1.start, frag_0.ends); - } else { - frag_0.ends.fill(frag_1.start, &mut self.emitter.insts); - frag = Frag::new(frag_0.start, frag_1.ends); - } - self.frag_stack.push(frag); - } - - fn ques(&mut self, greedy: bool) { - let frag = self.frag_stack.pop().unwrap(); - let inst; - let hole; - if greedy { - inst = self.emitter.emit(Inst::split(frag.start, NULL_INST)); - hole = HolePtr::out_1(inst); - } else { - inst = self.emitter.emit(Inst::split(NULL_INST, frag.start)); - hole = HolePtr::out_0(inst); - } - self.frag_stack.push(Frag::new( - inst, - frag.ends.append(hole, &mut self.emitter.insts), - )); - } - - fn star(&mut self, greedy: bool) { - let frag = self.frag_stack.pop().unwrap(); - let inst; - let hole; - if greedy { - inst = self.emitter.emit(Inst::split(frag.start, NULL_INST)); - hole = HolePtr::out_1(inst); - } else { - inst = self.emitter.emit(Inst::split(NULL_INST, frag.start)); - hole = HolePtr::out_0(inst); - } - frag.ends.fill(inst, &mut self.emitter.insts); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(hole))); - } - - fn plus(&mut self, greedy: bool) { - let frag = self.frag_stack.pop().unwrap(); - let inst; - let hole; - if greedy { - inst = self.emitter.emit(Inst::split(frag.start, NULL_INST)); - hole = HolePtr::out_1(inst); - } else { - inst = self.emitter.emit(Inst::split(NULL_INST, frag.start)); - hole = HolePtr::out_0(inst); - } - frag.ends.fill(inst, &mut self.emitter.insts); - self.frag_stack - .push(Frag::new(frag.start, HolePtrList::unit(hole))); - } - - fn assert(&mut self, pred: Pred) { - let pred = if self.reversed { - match pred { - Pred::TextStart => Pred::TextEnd, - Pred::TextEnd => Pred::TextStart, - Pred::LineStart => Pred::LineEnd, - Pred::LineEnd => Pred::LineStart, - Pred::WordBoundary => Pred::WordBoundary, - Pred::NotWordBoundary => Pred::NotWordBoundary, - } - } else { - pred - }; - let inst = self.emitter.emit(Inst::assert(NULL_INST, pred)); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst)))); - match pred { - Pred::LineStart | Pred::LineEnd => { - self.byte_classes_builder - .add_range(Range::new(b'\n', b'\n')); - } - Pred::WordBoundary | Pred::NotWordBoundary => { - self.has_word_boundary = true; - let mut start: u16 = 0; - while start <= 255 { - let mut end: u16 = start + 1; - while end <= 255 { - if (start as u8 as char).is_ascii_word() - != (end as u8 as char).is_ascii_word() - { - break; - } - end += 1; - } - self.byte_classes_builder - .add_range(Range::new(start as u8, (end - 1) as u8)); - start = end; - } - self.byte_classes_builder.add_range(Range::new(0x0, 0x7F)); - } - _ => {} - } - } - - fn byte_range(&mut self, range: Range) { - let inst = self.emitter.emit(Inst::byte_range(NULL_INST, range)); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst)))); - self.byte_classes_builder.add_range(range); - } - - fn char(&mut self, c: char) { - if self.byte_based { - let mut bytes = [0; 4]; - let mut bytes = c.encode_utf8(&mut bytes).bytes(); - let b = bytes.next().unwrap(); - self.byte_range(Range::new(b, b)); - while let Some(b) = bytes.next() { - self.byte_range(Range::new(b, b)); - self.cat(); - } - } else { - let inst = self.emitter.emit(Inst::char(NULL_INST, c)); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst)))); - } - } - - fn char_class(&mut self, class: &CharClass) { - use super::utf8; - - if self.byte_based { - let mut compiler = ClassCompiler::new( - self.reversed, - &mut self.emitter, - &mut self.byte_classes_builder, - &mut self.class_compiler_cache, - ); - for range in class { - for mut seq in utf8::byte_range_seqs(range, &mut self.byte_range_seqs_cache) { - if self.reversed { - seq.reverse(); - } - compiler.add_ranges(seq.as_slice()); - } - } - self.frag_stack.push(compiler.compile()); - } else { - let inst = self.emitter.emit(Inst::class(NULL_INST, class.clone())); - self.frag_stack - .push(Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst)))); - } - } - - fn compile(mut self) -> Prog { - if self.dot_star { - self.reversed = false; - self.cat(); - } - let frag = self.frag_stack.pop().unwrap(); - let inst = self.emitter.emit(Inst::Match); - frag.ends.fill(inst, &mut self.emitter.insts); - Prog { - insts: self.emitter.insts, - start: frag.start, - byte_classes: self.byte_classes_builder.build(), - has_word_boundary: self.has_word_boundary, - slot_count: self.slot_count, - } - } -} - -#[derive(Debug)] -struct ClassCompiler<'a> { - reversed: bool, - emitter: &'a mut Emitter, - compiled: &'a mut HashMap, - uncompiled: &'a mut Vec, - ends: HolePtrList, - byte_classes_builder: &'a mut ByteClassesBuilder, -} - -impl<'a> ClassCompiler<'a> { - fn new( - reversed: bool, - emitter: &'a mut Emitter, - byte_classes_builder: &'a mut ByteClassesBuilder, - allocs: &'a mut ClassCompilerAllocs, - ) -> Self { - Self { - reversed, - emitter, - byte_classes_builder, - compiled: &mut allocs.compiled, - uncompiled: &mut allocs.uncompiled, - ends: HolePtrList::empty(), - } - } - - fn add_ranges(&mut self, ranges: &[Range]) { - let prefix_len = self.prefix_len(ranges); - let inst = self.compile_suffix(prefix_len); - self.append_suffix(inst, &ranges[prefix_len..]); - } - - fn prefix_len(&mut self, ranges: &[Range]) -> usize { - if self.reversed { - 0 - } else { - ranges - .iter() - .zip(self.uncompiled.iter()) - .take_while(|&(&range, uncompiled)| range == uncompiled.range) - .count() - } - } - - fn compile_suffix(&mut self, start: usize) -> InstPtr { - use std::mem; - - let mut inst = NULL_INST; - while self.uncompiled.len() > start { - let uncompiled = self.uncompiled.pop().unwrap(); - let has_hole = inst == NULL_INST; - let (next_inst, is_new) = self.get_or_emit(Inst::byte_range(inst, uncompiled.range)); - inst = next_inst; - if is_new && has_hole { - let ends = mem::replace(&mut self.ends, HolePtrList::empty()); - self.ends = ends.append(HolePtr::out_0(inst), &mut self.emitter.insts); - } - if uncompiled.inst != NULL_INST { - let (next_inst, _) = self.get_or_emit(Inst::split(uncompiled.inst, inst)); - inst = next_inst; - } - } - inst - } - - fn append_suffix(&mut self, inst: InstPtr, ranges: &[Range]) { - self.uncompiled.push(Uncompiled { - inst, - range: ranges[0], - }); - self.byte_classes_builder.add_range(ranges[0]); - for &range in &ranges[1..] { - self.uncompiled.push(Uncompiled { - inst: NULL_INST, - range, - }); - self.byte_classes_builder.add_range(range); - } - } - - fn get_or_emit(&mut self, inst: Inst) -> (InstPtr, bool) { - match self.compiled.get(&inst) { - Some(&ptr) => (ptr, false), - None => { - let ptr = self.emitter.emit(inst.clone()); - self.compiled.insert(inst, ptr); - (ptr, true) - } - } - } - - fn compile(mut self) -> Frag { - let start = self.compile_suffix(0); - self.compiled.clear(); - if start == NULL_INST { - let inst = self.emitter.emit(Inst::nop(NULL_INST)); - Frag::new(inst, HolePtrList::unit(HolePtr::out_0(inst))) - } else { - Frag::new(start, self.ends) - } - } -} - -#[derive(Debug)] -struct ClassCompilerAllocs { - compiled: HashMap, - uncompiled: Vec, -} - -impl ClassCompilerAllocs { - fn new() -> Self { - Self { - compiled: HashMap::new(), - uncompiled: Vec::new(), - } - } -} - -#[derive(Debug)] -struct Uncompiled { - inst: InstPtr, - range: Range, -} - -impl Uncompiled { - fn new(inst: InstPtr, range: Range) -> Self { - Self { inst, range } - } -} - -#[derive(Debug)] -struct Emitter { - insts: Vec, -} - -impl Emitter { - fn emit(&mut self, inst: Inst) -> InstPtr { - let ptr = self.insts.len(); - self.insts.push(inst); - ptr - } -} - -#[derive(Debug)] -struct Frag { - start: InstPtr, - ends: HolePtrList, -} - -impl Frag { - fn new(start: InstPtr, ends: HolePtrList) -> Self { - Self { start, ends } - } -} - -#[derive(Debug)] -struct HolePtrList { - head: HolePtr, - tail: HolePtr, -} - -impl HolePtrList { - fn empty() -> Self { - Self { - head: HolePtr::null(), - tail: HolePtr::null(), - } - } - - fn unit(hole: HolePtr) -> Self { - Self { - head: hole, - tail: hole, - } - } - - fn append(self, hole: HolePtr, insts: &mut [Inst]) -> Self { - self.concat(Self::unit(hole), insts) - } - - fn concat(self, other: Self, insts: &mut [Inst]) -> Self { - if self.tail.is_null() { - return other; - } - if self.head.is_null() { - return self; - } - *self.tail.get_mut(insts) = other.head.0; - Self { - head: self.head, - tail: other.tail, - } - } - - fn fill(self, inst: InstPtr, insts: &mut [Inst]) { - let mut curr = self.head; - while curr.0 != NULL_INST { - let next = *curr.get(insts); - *curr.get_mut(insts) = inst; - curr = HolePtr(next); - } - } -} - -#[derive(Clone, Copy, Debug)] -struct HolePtr(usize); - -impl HolePtr { - fn null() -> Self { - Self(NULL_INST) - } - - fn out_0(inst: InstPtr) -> Self { - Self(inst << 1) - } - - fn out_1(inst: InstPtr) -> Self { - Self(inst << 1 | 1) - } - - fn is_null(self) -> bool { - self.0 == NULL_INST - } - - fn get(self, insts: &[Inst]) -> &InstPtr { - let inst_ref = &insts[self.0 >> 1]; - if self.0 & 1 == 0 { - inst_ref.out_0() - } else { - inst_ref.out_1() - } - } - - fn get_mut(self, insts: &mut [Inst]) -> &mut InstPtr { - let inst_ref = &mut insts[self.0 >> 1]; - if self.0 & 1 == 0 { - inst_ref.out_0_mut() - } else { - inst_ref.out_1_mut() - } - } -} - -#[derive(Debug)] -struct ByteClassesBuilder([bool; 256]); - -impl ByteClassesBuilder { - fn new() -> Self { - Self([false; 256]) - } - - fn add_range(&mut self, range: Range) { - if range.start > 0 { - self.0[range.start as usize - 1] = true; - } - self.0[range.end as usize] = true; - } - - fn build(&self) -> Box<[u8]> { - let mut classes = vec![0; 256]; - let mut class = 0u8; - let mut i = 0; - loop { - classes[i] = class as u8; - if i == 255 { - break; - } - if self.0[i] { - class += 1; - } - i += 1; - } - classes.into_boxed_slice() - } -} diff --git a/vendor/makepad/libs/regex/src/dfa.rs b/vendor/makepad/libs/regex/src/dfa.rs deleted file mode 100644 index f785181..0000000 --- a/vendor/makepad/libs/regex/src/dfa.rs +++ /dev/null @@ -1,537 +0,0 @@ -use { - super::{ - char::CharExt, - input::Cursor, - leb128, - prog::{Inst, InstPtr, Pred, Prog}, - sparse_set::SparseSet, - }, - std::{collections::HashMap, rc::Rc, result}, -}; - -pub type Result = result::Result; - -#[derive(Debug)] -pub struct Error; - -#[derive(Clone, Copy, Debug)] -pub struct Options { - pub want_first_match: bool, - pub want_last_match: bool, - pub max_heap_usage: usize, -} - -impl Default for Options { - fn default() -> Self { - Self { - want_first_match: false, - want_last_match: false, - max_heap_usage: 1 << 20, - } - } -} - -#[derive(Clone, Debug)] -pub struct Cache { - heap_usage: usize, - clear_count: usize, - states: States, - start_state_cache: Box<[StatePtr]>, - state_cache: HashMap, - curr_insts: SparseSet, - next_insts: SparseSet, - add_inst_stack: Vec, -} - -impl Cache { - pub fn new(prog: &Prog) -> Self { - Self { - heap_usage: 0, - clear_count: 0, - states: States::new(prog.byte_class_count() + 1), - start_state_cache: vec![UNKNOWN_STATE; 1 << 5].into_boxed_slice(), - state_cache: HashMap::new(), - curr_insts: SparseSet::new(prog.insts.len()), - next_insts: SparseSet::new(prog.insts.len()), - add_inst_stack: Vec::new(), - } - } -} - -pub fn run( - prog: &Prog, - cursor: C, - options: Options, - cache: &mut Cache, -) -> Result> { - Dfa { - prog, - cursor, - last_clear_pos: 0, - want_first_match: options.want_first_match, - want_last_match: options.want_last_match, - max_heap_usage: options.max_heap_usage, - heap_usage: &mut cache.heap_usage, - clear_count: &mut cache.clear_count, - states: &mut cache.states, - start_state_cache: &mut cache.start_state_cache, - state_cache: &mut cache.state_cache, - curr_insts: &mut cache.curr_insts, - next_insts: &mut cache.next_insts, - add_inst_stack: &mut cache.add_inst_stack, - } - .run() -} - -#[derive(Debug)] -struct Dfa<'a, C> { - prog: &'a Prog, - cursor: C, - last_clear_pos: usize, - want_first_match: bool, - want_last_match: bool, - max_heap_usage: usize, - heap_usage: &'a mut usize, - clear_count: &'a mut usize, - states: &'a mut States, - start_state_cache: &'a mut Box<[StatePtr]>, - state_cache: &'a mut HashMap, - curr_insts: &'a mut SparseSet, - next_insts: &'a mut SparseSet, - add_inst_stack: &'a mut Vec, -} - -impl<'a, C: Cursor> Dfa<'a, C> { - fn run(&mut self) -> Result> { - let mut matched = None; - let start_state = self.start_state()?; - let mut curr_state = start_state; - let mut next_state = start_state; - let mut b = self.cursor.current_byte(); - loop { - while next_state <= MAX_STATE && b.is_some() { - self.cursor.move_next_byte(); - curr_state = next_state; - let byte_class = self.prog.byte_classes[b.unwrap() as usize] as u16; - next_state = *self.states.next_state(curr_state, byte_class); - b = self.cursor.current_byte(); - } - if next_state & MATCH_STATE != 0 { - self.cursor.move_prev_byte(); - matched = Some(self.cursor.index()); - self.cursor.move_next_byte(); - if self.want_first_match { - return Ok(matched); - } - next_state &= !MATCH_STATE; - continue; - } - if next_state == UNKNOWN_STATE { - let b = self.cursor.prev_byte(); - next_state = self.next_state(&mut curr_state, b)?; - let byte_class = match b { - Some(b) => self.prog.byte_classes[b as usize] as u16, - None => self.prog.byte_class_count() as u16, - }; - *self.states.next_state_mut(curr_state, byte_class) = next_state; - continue; - } else if next_state == DEAD_STATE { - return Ok(matched); - } else if next_state == ERROR_STATE { - return Err(Error); - } - break; - } - next_state &= MAX_STATE; - curr_state = next_state; - next_state = self.next_state(&mut curr_state, None)?; - if next_state & MATCH_STATE != 0 { - matched = Some(self.cursor.index()); - } - Ok(matched) - } - - fn start_state(&mut self) -> Result { - let next_is_word = self - .cursor - .current_byte() - .map_or(false, |b| (b as char).is_ascii_word()); - let prev_is_word = self - .cursor - .prev_byte() - .map_or(false, |b| (b as char).is_ascii_word()); - let mut flags = StateFlags::default(); - if prev_is_word { - flags.set_word(); - } - let preds = Preds { - text_start: self.cursor.prev_byte().is_none(), - text_end: self.cursor.current_byte().is_none(), - line_start: self.cursor.prev_byte().map_or(true, |b| b == b'\n'), - line_end: self.cursor.current_byte().map_or(true, |b| b == b'\n'), - word_boundary: next_is_word != prev_is_word, - }; - let index = preds.bits() as usize; - match self.start_state_cache[index] { - UNKNOWN_STATE => {} - state => return Ok(state), - }; - AddInstView { - prog: &self.prog, - stack: &mut self.add_inst_stack, - } - .add_inst(self.curr_insts, self.prog.start, preds); - let key = CreateStateKeyView { prog: &self.prog } - .create_state_key(flags, self.curr_insts.as_slice()); - self.curr_insts.clear(); - let state = self.get_or_add_state(key, None)?; - self.start_state_cache[index] = state; - Ok(state) - } - - fn next_state(&mut self, state: &mut StatePtr, b: Option) -> Result { - use std::mem; - - for inst in self.states.key(*state).insts() { - self.curr_insts.insert(inst); - } - if self.states.key(*state).flags.assert() { - let next_is_word = b.map_or(false, |b| (b as char).is_ascii_word()); - let prev_is_word = self.states.key(*state).flags.word(); - let preds = Preds { - text_end: b.is_none(), - line_end: b.map_or(true, |b| b == b'\n'), - word_boundary: next_is_word != prev_is_word, - ..Preds::default() - }; - for &inst in self.curr_insts.as_slice() { - AddInstView { - prog: &self.prog, - stack: &mut self.add_inst_stack, - } - .add_inst(self.next_insts, inst, preds); - } - mem::swap(&mut self.curr_insts, &mut self.next_insts); - self.next_insts.clear(); - } - let mut flags = StateFlags::default(); - if b.map_or(false, |b| (b as char).is_ascii_word()) { - flags.set_word(); - } - let preds = Preds { - line_start: b.map_or(true, |b| b as char == '\n'), - ..Preds::default() - }; - for &inst in self.curr_insts.as_slice() { - match &self.prog.insts[inst] { - Inst::Match => { - flags.set_matched(); - if !self.want_last_match { - break; - } - } - Inst::ByteRange(inst_ref) => { - if b.map_or(false, |b| inst_ref.range.contains(&b)) { - AddInstView { - prog: &self.prog, - stack: &mut self.add_inst_stack, - } - .add_inst(self.next_insts, inst_ref.out, preds); - } - } - Inst::Char(_) | Inst::Class(_) => panic!(), - _ => {} - } - } - mem::swap(&mut self.curr_insts, &mut self.next_insts); - self.next_insts.clear(); - if !flags.matched() && self.curr_insts.is_empty() { - return Ok(DEAD_STATE); - } - let key = CreateStateKeyView { prog: &self.prog } - .create_state_key(flags, self.curr_insts.as_slice()); - self.curr_insts.clear(); - let mut next_state = self.get_or_add_state(key, Some(state))?; - if flags.matched() { - next_state |= MATCH_STATE; - } - Ok(next_state) - } - - fn get_or_add_state( - &mut self, - key: StateKey, - retained_state: Option<&mut StatePtr>, - ) -> Result { - if let Some(&state) = self.state_cache.get(&key) { - return Ok(state); - } - if *self.heap_usage > self.max_heap_usage { - match retained_state { - Some(retained_state) => { - let key = self.states.key(*retained_state).clone(); - self.clear()?; - *retained_state = self.add_state(key.clone()); - } - None => self.clear()?, - } - } - Ok(self.add_state(key)) - } - - fn add_state(&mut self, key: StateKey) -> StatePtr { - use std::mem; - - *self.heap_usage += mem::size_of::() - + self.states.byte_class_count * mem::size_of::() - + mem::size_of::() - + mem::size_of::() - + mem::size_of::() - + key.bytes.len(); - let state = self.states.add(key.clone()); - if self.prog.has_word_boundary { - for b in 128..256 { - *self.states.next_state_mut(state, b) = ERROR_STATE; - } - } - self.state_cache.insert(key, state); - state - } - - fn clear(&mut self) -> Result<()> { - let byte_count = self.cursor.index() - self.last_clear_pos; - if *self.clear_count >= 3 && byte_count <= 10 * self.prog.insts.len() { - return Err(Error); - } - self.last_clear_pos = self.cursor.index(); - *self.heap_usage = 0; - *self.clear_count += 1; - self.states.clear(); - for state in self.start_state_cache.iter_mut() { - *state = UNKNOWN_STATE; - } - self.state_cache.clear(); - Ok(()) - } -} - -#[derive(Clone, Debug)] -struct States { - key: Vec, - transitions: Vec, - byte_class_count: usize, -} - -impl States { - #[inline] - fn new(byte_class_count: usize) -> Self { - Self { - key: Vec::new(), - transitions: Vec::new(), - byte_class_count, - } - } - - fn key(&self, state: StatePtr) -> &StateKey { - &self.key[state] - } - - #[inline] - fn next_state(&self, state: StatePtr, b: u16) -> &StatePtr { - self.transitions - .get(self.byte_class_count * state + b as usize) - .unwrap() - } - - #[inline] - fn next_state_mut(&mut self, state: StatePtr, b: u16) -> &mut StatePtr { - self.transitions - .get_mut(self.byte_class_count * state + b as usize) - .unwrap() - } - - fn add(&mut self, key: StateKey) -> StatePtr { - use std::iter; - - let ptr = self.key.len(); - self.key.push(key); - self.transitions - .extend(iter::repeat(UNKNOWN_STATE).take(self.byte_class_count)); - ptr - } - - fn clear(&mut self) { - self.key.clear(); - self.transitions.clear(); - } -} - -type StatePtr = usize; - -const UNKNOWN_STATE: StatePtr = 1 << 31; -const DEAD_STATE: StatePtr = UNKNOWN_STATE + 1; -const ERROR_STATE: StatePtr = DEAD_STATE + 1; -const MATCH_STATE: StatePtr = 1 << 30; -const MAX_STATE: StatePtr = MATCH_STATE - 1; - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -struct StateKey { - flags: StateFlags, - bytes: Rc<[u8]>, -} - -impl StateKey { - fn insts(&self) -> Insts<'_> { - Insts { - prev_inst: 0, - bytes: self.bytes.as_ref(), - } - } -} - -struct Insts<'a> { - prev_inst: InstPtr, - bytes: &'a [u8], -} - -impl<'a> Iterator for Insts<'a> { - type Item = InstPtr; - - fn next(&mut self) -> Option { - if self.bytes.is_empty() { - return None; - } - let delta = leb128::decode_isize(&mut self.bytes); - let inst = (self.prev_inst as isize + delta) as usize; - self.prev_inst = inst as usize; - Some(inst) - } -} - -#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -struct StateFlags(u8); - -impl StateFlags { - fn matched(&self) -> bool { - self.0 & 1 << 0 != 0 - } - - fn set_matched(&mut self) { - self.0 |= 1 << 0 - } - - fn assert(&self) -> bool { - self.0 & 1 << 1 != 0 - } - - fn set_assert(&mut self) { - self.0 |= 1 << 1; - } - - fn word(&self) -> bool { - self.0 & 1 << 2 != 0 - } - - fn set_word(&mut self) { - self.0 |= 1 << 2; - } -} - -#[derive(Debug)] -struct CreateStateKeyView<'a> { - prog: &'a Prog, -} - -impl<'a> CreateStateKeyView<'a> { - fn create_state_key(&self, flags: StateFlags, insts: &[InstPtr]) -> StateKey { - let mut flags = flags; - let mut bytes = Vec::new(); - let mut prev_inst = 0; - for &inst in insts { - match self.prog.insts[inst] { - Inst::Assert(_) => { - flags.set_assert(); - } - _ => {} - } - let delta = (inst as isize) - (prev_inst as isize); - prev_inst = inst; - leb128::encode_isize(&mut bytes, delta); - } - StateKey { - flags, - bytes: Rc::from(bytes), - } - } -} - -struct AddInstView<'a> { - prog: &'a Prog, - stack: &'a mut Vec, -} - -impl<'a> AddInstView<'a> { - fn add_inst(&mut self, insts: &mut SparseSet, inst: InstPtr, preds: Preds) { - self.stack.push(inst); - while let Some(inst) = self.stack.pop() { - let mut inst = inst; - loop { - if !insts.insert(inst) { - break; - } - match &self.prog.insts[inst] { - Inst::Match | Inst::ByteRange(_) | Inst::Char(_) | Inst::Class(_) => {} - Inst::Nop(inst_ref) => { - inst = inst_ref.out; - continue; - } - Inst::Save(inst_ref) => { - inst = inst_ref.out; - continue; - } - Inst::Assert(inst_ref) => { - if match inst_ref.pred { - Pred::TextStart => preds.text_start, - Pred::TextEnd => preds.text_end, - Pred::LineStart => preds.line_start, - Pred::LineEnd => preds.line_end, - Pred::WordBoundary => preds.word_boundary, - Pred::NotWordBoundary => !preds.word_boundary, - } { - inst = inst_ref.out; - continue; - } - insts.insert(inst); - break; - } - Inst::Split(inst_ref) => { - self.stack.push(inst_ref.out_1); - inst = inst_ref.out_0; - continue; - } - } - } - } - } -} - -#[derive(Clone, Copy, Debug, Default)] -struct Preds { - text_start: bool, - text_end: bool, - line_start: bool, - line_end: bool, - word_boundary: bool, -} - -impl Preds { - fn bits(self) -> u8 { - let mut bits = 0; - bits |= (self.text_start as u8) << 0; - bits |= (self.text_end as u8) << 1; - bits |= (self.line_start as u8) << 2; - bits |= (self.line_end as u8) << 3; - bits |= (self.word_boundary as u8) << 4; - bits - } -} diff --git a/vendor/makepad/libs/regex/src/error.rs b/vendor/makepad/libs/regex/src/error.rs deleted file mode 100644 index 13e12d5..0000000 --- a/vendor/makepad/libs/regex/src/error.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::{error, fmt, result}; - -#[derive(Clone, Debug)] -pub struct Error { - pub message: String, - pub pos: usize, -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{} at position {}", self.message, self.pos) - } -} - -pub type Result = result::Result; diff --git a/vendor/makepad/libs/regex/src/fuzz/.gitignore b/vendor/makepad/libs/regex/src/fuzz/.gitignore deleted file mode 100644 index a092511..0000000 --- a/vendor/makepad/libs/regex/src/fuzz/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target -corpus -artifacts diff --git a/vendor/makepad/libs/regex/src/fuzz/Cargo.toml b/vendor/makepad/libs/regex/src/fuzz/Cargo.toml deleted file mode 100644 index 57d80c3..0000000 --- a/vendor/makepad/libs/regex/src/fuzz/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "regex-fuzz" -version = "0.0.0" -authors = ["Automatically generated"] -publish = false -edition = "2018" - -[package.metadata] -cargo-fuzz = true - -[dependencies] -libfuzzer-sys = "0.4" - -[dependencies.regex] -path = ".." - -# Prevent this from interfering with workspaces -[workspace] -members = ["."] - -[[bin]] -name = "regex" -path = "fuzz_targets/regex.rs" -test = false -doc = false diff --git a/vendor/makepad/libs/regex/src/fuzz/fuzz_targets/regex.rs b/vendor/makepad/libs/regex/src/fuzz/fuzz_targets/regex.rs deleted file mode 100644 index aa355ac..0000000 --- a/vendor/makepad/libs/regex/src/fuzz/fuzz_targets/regex.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![no_main] -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|data: &[u8]| { - use regex::Regex; - - if let Ok(pattern) = std::str::from_utf8(data) { - let _ = Regex::::new(pattern); - } -}); diff --git a/vendor/makepad/libs/regex/src/input.rs b/vendor/makepad/libs/regex/src/input.rs deleted file mode 100644 index 65c9ffb..0000000 --- a/vendor/makepad/libs/regex/src/input.rs +++ /dev/null @@ -1,105 +0,0 @@ -use {super::char::CharExt, std::ops::Range}; - -pub trait Input<'a> { - type Cursor: Cursor; - - fn slice(&self, range: Range) -> Self; - - fn cursor_start(&self) -> Self::Cursor; - - fn cursor_end(&self) -> Self::Cursor; -} - -pub trait Cursor: Clone { - fn is_start(&self) -> bool; - - fn is_end(&self) -> bool; - - fn index(&self) -> usize; - - fn current_byte(&mut self) -> Option; - - fn current_char(&mut self) -> Option; - - fn prev_byte(&mut self) -> Option; - - fn prev_char(&mut self) -> Option; - - fn move_next_byte(&mut self) -> bool; - - fn move_next_char(&mut self) -> bool; - - fn move_prev_byte(&mut self) -> bool; - - fn move_prev_char(&mut self) -> bool; - - fn is_line_start(&mut self) -> bool { - self.prev_char().map_or(true, |c| c == '\n') - } - - fn is_line_end(&mut self) -> bool { - self.current_char().map_or(true, |c| c == '\n') - } - - fn is_word_boundary(&mut self) -> bool { - self.prev_char().map(|c| c.is_word()) != self.current_char().map(|c| c.is_word()) - } - - fn rev(self) -> RevCursor - where - Self: Sized, - { - RevCursor { cursor: self } - } -} - -#[derive(Clone, Debug)] -pub struct RevCursor { - cursor: C, -} - -impl Cursor for RevCursor { - fn is_start(&self) -> bool { - self.cursor.is_end() - } - - fn is_end(&self) -> bool { - self.cursor.is_start() - } - - fn index(&self) -> usize { - self.cursor.index() - } - - fn current_byte(&mut self) -> Option { - self.cursor.prev_byte() - } - - fn current_char(&mut self) -> Option { - self.cursor.prev_char() - } - - fn prev_byte(&mut self) -> Option { - self.cursor.current_byte() - } - - fn prev_char(&mut self) -> Option { - self.cursor.current_char() - } - - fn move_next_byte(&mut self) -> bool { - self.cursor.move_prev_byte() - } - - fn move_next_char(&mut self) -> bool { - self.cursor.move_prev_char() - } - - fn move_prev_byte(&mut self) -> bool { - self.cursor.move_next_byte() - } - - fn move_prev_char(&mut self) -> bool { - self.cursor.move_next_char() - } -} diff --git a/vendor/makepad/libs/regex/src/leb128.rs b/vendor/makepad/libs/regex/src/leb128.rs deleted file mode 100644 index cc53ca6..0000000 --- a/vendor/makepad/libs/regex/src/leb128.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! Functions for encoding/decoding integers as LEB128. -//! -//! For more information, see: https://en.wikipedia.org/wiki/LEB128. - -/// Decodes an `isize` as LEB128 from `bytes`. -/// -/// # Panics -/// -/// Panics if `bytes` is not valid LEB128. -pub fn decode_isize(bytes: &mut &[u8]) -> isize { - let un = decode_usize(bytes); - - // Decodes `n` as a `usize`, shifted one bit to the left, with the sign in bit 0. - let mut n = (un >> 1) as isize; - if un & 1 != 0 { - n = !n; - } - n -} - -/// Decodes an `usize` as LEB128 from `bytes`. -/// -/// # Panics -/// -/// Panics if `bytes` is not valid LEB128. -pub fn decode_usize(bytes: &mut &[u8]) -> usize { - let mut n = 0; - let mut shift = 0; - while !bytes.is_empty() { - let b = bytes[0]; - *bytes = &bytes[1..]; - n |= ((b & 0x7F) as usize) << shift; - if b < 0x80 { - return n; - } - shift += 7; - } - panic!("invalid LEB128") -} - -/// Encodes an `isize` as LEB128 into `bytes`. -pub fn encode_isize(bytes: &mut Vec, n: isize) { - // Encodes `n` as a `usize`, shifted one bit to the left, with the sign in bit 0. - let mut un = (n as usize) << 1; - if n < 0 { - un = !un; - } - - encode_usize(bytes, un) -} - -/// Encodes an `usize` as LEB128 into `bytes`. -pub fn encode_usize(bytes: &mut Vec, n: usize) { - let mut n = n; - while n >= 0x80 { - bytes.push((n as u8) | 0x80); - n >>= 7; - } - bytes.push(n as u8); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn isize() { - let expected = -2_147_483_647isize; - let mut bytes = Vec::new(); - encode_isize(&mut bytes, expected); - let actual = decode_isize(&mut bytes.as_slice()); - assert_eq!(actual, expected); - } - - #[test] - fn usize() { - let expected = 2_147_483_647usize; - let mut bytes = Vec::new(); - encode_usize(&mut bytes, expected); - let actual = decode_usize(&mut bytes.as_slice()); - assert_eq!(actual, expected); - } -} diff --git a/vendor/makepad/libs/regex/src/lib.rs b/vendor/makepad/libs/regex/src/lib.rs deleted file mode 100644 index 9c2a137..0000000 --- a/vendor/makepad/libs/regex/src/lib.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![allow(dead_code)] - -mod ast; -mod case_fold; -mod char; -mod char_class; -mod compile; -mod dfa; -mod error; -mod input; -mod leb128; -mod nfa; -mod parse; -mod prog; -mod range; -mod regex; -mod sparse_set; -mod str; -mod unicode; -mod utf8; - -pub use self::{ - error::{Error, Result}, - input::{Cursor, Input}, - parse::Options as ParseOptions, - regex::Regex, -}; - -#[cfg(test)] -mod tests; diff --git a/vendor/makepad/libs/regex/src/make_fowler_tests.py b/vendor/makepad/libs/regex/src/make_fowler_tests.py deleted file mode 100755 index 4635f73..0000000 --- a/vendor/makepad/libs/regex/src/make_fowler_tests.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/python3 - -import os -import re -import sys - -def group_to_str(group): - if group is None: - return "None, None" - else: - return "Some(%d), Some(%d)" % (group[0], group[1]) - -def test_to_str(test): - name, pattern, text, groups = test - group_strs = ", ".join([group_to_str(group) for group in groups]) - return "macros::test_regex!(%s, r\"%s\", \"%s\", %s);" % (name, pattern, text, group_strs) - -def read_test_data(file): - basename, _ = os.path.splitext(os.path.basename(file)) - tests = [] - for index, line in enumerate(open(sys.argv[1], "rb")): - line = line.decode("utf-8") - - if line[0] == '#': - continue - - fields = [field.strip() for field in line.split('\t')] - fields = [field for field in fields if len(field) != 0] - if not 4 <= len(fields) <= 5: - continue - options, pattern, text, group_strs = fields[:4] - if 'E' not in options or 'i' in options: - continue - - name = "%s_%d" % (basename, index + 1) - if pattern == "SAME": - pattern = tests[-1][1] - text = "" if text == "NULL" else text - text = re.sub(r"\\(?![nx])", r"\\\\", text) - if '$' in options and "\\x" in text: - continue - groups = [] - if group_strs == "NOMATCH": - groups = [None] - elif ',' in group_strs: - group_strs = [group_str.strip("()") for group_str in group_strs.split(")(")] - for group_str in group_strs: - start, end = [bound_str.strip() for bound_str in group_str.split(",")] - if start == '?' and end == '?': - groups.append(None) - else: - groups.append((int(start), int(end))) - else: - continue - - tests.append((name, pattern, text, groups)) - return tests - -def main(): - print("//! Generated by make_fowler_tests.py") - print("") - print("mod macros;") - print("") - - tests = read_test_data(sys.argv[1]) - for test in tests: - print(test_to_str(test)) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/vendor/makepad/libs/regex/src/make_unicode.py b/vendor/makepad/libs/regex/src/make_unicode.py deleted file mode 100755 index 15dfa4e..0000000 --- a/vendor/makepad/libs/regex/src/make_unicode.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/python3 - -import re -import sys -import urllib.request - -UNICODE_BASE_URL = "https://www.unicode.org/Public/14.0.0/ucd" - -def parse_code_value(string): - try: - value = int(string, 16) - except ValueError: - raise Exception("invalid unicode value") - if value < 0 or value > 0x10FFFF: - raise Exception("invalid unicode value") - return value - -def parse_code_range(string): - bounds = string.split("..") - if len(bounds) == 1: - start = parse_code_value(bounds[0]) - end = start - elif len(bounds) == 2: - start = parse_code_value(bounds[0]) - end = parse_code_value(bounds[1]) - else: - raise Exception("invalid unicode range") - if start > end: - raise Exception("invalid unicode range") - return range(start, end + 1) - -def parse_char_name(string): - match = re.match("<(.*), (First|Last)>", string) - if match is None: - return (string[0], None) - return match.groups() - -def read_unicode_data(url): - if url.startswith("https://"): - stream = urllib.request.urlopen(url) - else: - stream = open(url, "rb") - - first = None - expect_last = None - for line in stream: - line = line.decode("utf-8") - - hash = line.find("#") - if hash >= 0: - line = line[:hash] - line = line.strip() - if not line: - continue - - fields = [field.strip() for field in line.split(";")] - codes = parse_code_range(fields[0]) - (name, cont) = parse_char_name(fields[1]) - if expect_last is not None: - if name != expect_last or cont != "Last": - raise Exception("expected last line for %s", expect_last) - if len(codes) != 1 or codes[0] < first: - raise Exception("invalid last line") - codes = range(first, codes[0] + 1) - first = None - expect_last = None - yield [codes] + fields[1:] - elif cont == "First": - if len(codes) != 1: - raise Exception("invalid first line") - first = codes[0] - expect_last = name - else: - yield [codes] + fields[1:] - -def read_categories(unicode_base_url): - categories = {} - for [codes, _, category, *_] in read_unicode_data(unicode_base_url + "/UnicodeData.txt"): - categories.setdefault(category, []).extend(codes) - if len(category) > 1: - short = category[0] - categories.setdefault(short, []).extend(codes) - return categories - -def read_aliases(unicode_base_url): - aliases = {} - for [codes, alias, *_] in read_unicode_data(unicode_base_url + "/NameAliases.txt"): - aliases.setdefault(alias, []).extend(codes) - return aliases - -def read_properties(unicode_base_url): - properties = {} - for [codes, property] in read_unicode_data(unicode_base_url + "/DerivedCoreProperties.txt"): - properties.setdefault(property, []).extend(codes) - return properties - -def read_other_properties(unicode_base_url): - other_properties = {} - for [codes, other_property] in read_unicode_data(unicode_base_url + "/PropList.txt"): - other_properties.setdefault(other_property, []).extend(codes) - return other_properties - -def read_case_folds(unicode_base_url): - case_folds = {} - for [codes, status, mapping, *_] in read_unicode_data(unicode_base_url + "/CaseFolding.txt"): - if status not in ("C", "S"): - continue - mapping = parse_code_value(mapping) - case_folds.setdefault(mapping, [mapping]).extend(codes) - case_folds = list(case_folds.values()) - for codes in case_folds: - codes.sort() - case_folds.sort() - return case_folds - -def generate_ranges(codes): - range = None - for code in codes: - if range is None: - range = [code, code] - else: - if code == range[1] + 1: - range[1] = code - else: - yield range - range = [code, code] - if range is not None: - yield range - -def print_group(name, codes): - ranges = list(generate_ranges(sorted(codes))) - print("pub static %s: [Range; %d] = [" % (name, len(ranges))) - for range in ranges: - print(" Range::new('\\u{%X}', '\\u{%X}')," % (range[0], range[1])) - print("];") - -def main(): - if len(sys.argv) > 1: - unicode_base_url = sys.argv[1] - else: - unicode_base_url = UNICODE_BASE_URL - - categories = read_categories(unicode_base_url) - aliases = read_aliases(unicode_base_url) - properties = read_properties(unicode_base_url) - other_properties = read_other_properties(unicode_base_url) - case_folds = read_case_folds(unicode_base_url) - - print("//! Generated by make_unicode.py") - print("") - print("use crate::range::Range;") - print("") - - alnum = set() - alnum.update(properties["Alphabetic"]) - alnum.update(categories["Nd"]) - print_group("ALNUM", alnum) - print() - - alpha = set() - alpha.update(properties["Alphabetic"]) - print_group("ALPHA", alpha) - print() - - blank = set() - blank.update(categories["Zs"]) - blank.update(aliases["CHARACTER TABULATION"]) - print_group("BLANK", blank) - print() - - cntrl = set() - cntrl.update(categories["Cc"]) - print_group("CNTRL", cntrl) - print() - - digit = set() - digit.update(categories["Nd"]) - print_group("DIGIT", digit) - print() - - graph = set() - graph.update(range(0, 0xD800)) - graph.update(range(0xE000, 0x110000)) - graph.difference_update(other_properties["White_Space"]) - graph.difference_update(categories["Cc"]) - graph.difference_update(categories["Cs"]) - print_group("GRAPH", graph) - print() - - lower = set() - lower.update(properties["Lowercase"]) - print_group("LOWER", lower) - print() - - print_ = set() - print_.update(range(0, 0xD800)) - print_.update(range(0xE000, 0x110000)) - print_.difference_update(other_properties["White_Space"]) - print_.difference_update(categories["Cc"]) - print_.difference_update(categories["Cs"]) - print_.update(categories["Zs"]) - print_.update(aliases["CHARACTER TABULATION"]) - print_.difference_update(categories["Cc"]) - print_group("PRINT", print_) - print() - - punct = set() - punct.update(categories["P"]) - print_group("PUNCT", punct) - print() - - space = set() - space.update(other_properties["White_Space"]) - print_group("SPACE", space) - print() - - upper = set() - upper.update(properties["Uppercase"]) - print_group("UPPER", upper) - print() - - word = set() - word.update(properties["Alphabetic"]) - word.update(categories["M"]) - word.update(categories["Nd"]) - word.update(categories["Pc"]) - word.update(other_properties["Join_Control"]) - print_group("WORD", word) - print() - - xdigit = set() - xdigit.update(categories["Nd"]) - xdigit.update(other_properties["Hex_Digit"]) - print_group("XDIGIT", xdigit) - print() - - case_folds_by_code = [] - for case_fold in case_folds: - for code in case_fold: - case_folds_by_code.append([case_fold[0], case_fold]) - case_folds_by_code.sort() - print("pub static CASE_FOLDS: [(char, &'static [char]); %d] = [" % len(case_folds_by_code)) - for [code, case_folds] in case_folds_by_code: - print(" ('\\u{%X}', &[" % code, end="") - for code in case_folds: - print("'\\u{%X}'" % code, end = ", ") - print("]),") - print("];") - -if __name__ == '__main__': - main() diff --git a/vendor/makepad/libs/regex/src/mod.rs b/vendor/makepad/libs/regex/src/mod.rs deleted file mode 100644 index 5b42381..0000000 --- a/vendor/makepad/libs/regex/src/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![allow(dead_code)] - -mod ast; -mod case_fold; -mod char; -mod char_class; -mod compile; -mod input; -mod dfa; -mod error; -mod leb128; -mod nfa; -mod parse; -mod prog; -mod range; -mod regex; -mod sparse_set; -mod str; -mod unicode; -mod utf8; - -pub use self::{error::{Error, Result}, input::{Cursor, Input}, regex::Regex}; - -#[cfg(test)] -mod tests; diff --git a/vendor/makepad/libs/regex/src/nfa.rs b/vendor/makepad/libs/regex/src/nfa.rs deleted file mode 100644 index f99f685..0000000 --- a/vendor/makepad/libs/regex/src/nfa.rs +++ /dev/null @@ -1,235 +0,0 @@ -use super::{ - input::Cursor, - prog::{InstPtr, Pred, Prog}, - sparse_set::SparseSet, -}; - -#[derive(Clone, Copy, Debug, Default)] -pub struct Options { - pub want_first_match: bool, -} - -#[derive(Clone, Debug)] -pub struct Allocs { - current_threads: Threads, - next_threads: Threads, - add_thread_stack: Vec, -} - -impl Allocs { - pub fn new(prog: &Prog) -> Self { - Self { - current_threads: Threads::new(prog.insts.len(), prog.slot_count), - next_threads: Threads::new(prog.insts.len(), prog.slot_count), - add_thread_stack: Vec::new(), - } - } -} - -pub fn run( - prog: &Prog, - cursor: C, - options: Options, - slots: &mut [Option], - allocs: &mut Allocs, -) -> bool { - Nfa { - prog, - cursor, - want_first_match: options.want_first_match, - curr_threads: &mut allocs.current_threads, - next_threads: &mut allocs.next_threads, - add_thread_stack: &mut allocs.add_thread_stack, - } - .run(slots) -} - -#[derive(Debug)] -struct Nfa<'a, C: Cursor> { - prog: &'a Prog, - cursor: C, - want_first_match: bool, - curr_threads: &'a mut Threads, - next_threads: &'a mut Threads, - add_thread_stack: &'a mut Vec, -} - -impl<'a, C: Cursor> Nfa<'a, C> { - fn run(&mut self, slots: &mut [Option]) -> bool { - use {super::prog::Inst, std::mem}; - - let mut matched = false; - loop { - if !matched { - AddThreadView { - prog: &self.prog, - cursor: &mut self.cursor, - stack: &mut self.add_thread_stack, - } - .add_thread(&mut self.next_threads, self.prog.start, slots); - } - mem::swap(&mut self.curr_threads, &mut self.next_threads); - self.next_threads.inst.clear(); - if self.curr_threads.inst.is_empty() { - break; - } - let c = self.cursor.current_char(); - if c.is_some() { - self.cursor.move_next_char(); - } - let mut view = AddThreadView { - prog: &self.prog, - cursor: &mut self.cursor, - stack: &mut self.add_thread_stack, - }; - for &inst in self.curr_threads.inst.as_slice() { - match &self.prog.insts[inst] { - Inst::Match => { - let len = slots.len().min(self.curr_threads.slots.get(inst).len()); - (&mut slots[..len]) - .copy_from_slice(&self.curr_threads.slots.get(inst)[..len]); - if self.want_first_match { - return true; - } - matched = true; - break; - } - Inst::ByteRange(_) => panic!(), - Inst::Char(inst_ref) => { - if c.map_or(false, |c| c == inst_ref.c) { - view.add_thread( - &mut self.next_threads, - inst_ref.out, - self.curr_threads.slots.get_mut(inst), - ); - } - } - Inst::Class(inst_ref) => { - if c.map_or(false, |c| inst_ref.class.contains(c)) { - view.add_thread( - &mut self.next_threads, - inst_ref.out, - self.curr_threads.slots.get_mut(inst), - ); - } - } - _ => {} - } - } - if c.is_none() { - break; - } - } - matched - } -} - -#[derive(Clone, Debug)] -struct Threads { - inst: SparseSet, - slots: Slots, -} - -impl Threads { - fn new(inst_count: usize, slot_count: usize) -> Self { - Self { - inst: SparseSet::new(inst_count), - slots: Slots { - slots: (0..inst_count * slot_count).map(|_| None).collect(), - slot_count, - }, - } - } -} - -#[derive(Clone, Debug)] -struct Slots { - slots: Vec>, - slot_count: usize, -} - -impl Slots { - fn get(&self, inst: InstPtr) -> &[Option] { - &self.slots[inst * self.slot_count..][..self.slot_count] - } - - fn get_mut(&mut self, inst: InstPtr) -> &mut [Option] { - &mut self.slots[inst * self.slot_count..][..self.slot_count] - } -} - -#[derive(Clone, Debug)] -enum AddThreadFrame { - AddThread(InstPtr), - UnsaveSlots(usize, Option), -} - -#[derive(Debug)] -struct AddThreadView<'a, C: Cursor> { - prog: &'a Prog, - cursor: &'a mut C, - stack: &'a mut Vec, -} - -impl<'a, C: Cursor> AddThreadView<'a, C> { - fn add_thread(&mut self, threads: &mut Threads, inst: InstPtr, slots: &mut [Option]) { - use super::prog::Inst; - - self.stack.push(AddThreadFrame::AddThread(inst)); - while let Some(frame) = self.stack.pop() { - match frame { - AddThreadFrame::AddThread(inst) => { - let mut inst = inst; - loop { - if !threads.inst.insert(inst) { - break; - } - match &self.prog.insts[inst] { - Inst::Match | Inst::ByteRange(_) | Inst::Char(_) | Inst::Class(_) => { - let len = threads.slots.get(inst).len().min(slots.len()); - (&mut threads.slots.get_mut(inst)[..len]) - .copy_from_slice(&slots[..len]); - break; - } - Inst::Nop(inst_ref) => { - inst = inst_ref.out; - continue; - } - Inst::Save(inst_ref) => { - if inst_ref.slot_index < slots.len() { - self.stack.push(AddThreadFrame::UnsaveSlots( - inst_ref.slot_index, - slots[inst_ref.slot_index], - )); - slots[inst_ref.slot_index] = Some(self.cursor.index()); - } - inst = inst_ref.out; - continue; - } - Inst::Assert(inst_ref) => { - if match inst_ref.pred { - Pred::TextStart => self.cursor.is_start(), - Pred::TextEnd => self.cursor.is_end(), - Pred::LineStart => self.cursor.is_line_start(), - Pred::LineEnd => self.cursor.is_line_end(), - Pred::WordBoundary => self.cursor.is_word_boundary(), - Pred::NotWordBoundary => !self.cursor.is_word_boundary(), - } { - inst = inst_ref.out; - continue; - } - break; - } - Inst::Split(inst_ref) => { - self.stack.push(AddThreadFrame::AddThread(inst_ref.out_1)); - inst = inst_ref.out_0; - continue; - } - } - } - } - AddThreadFrame::UnsaveSlots(slot_index, old_pos) => slots[slot_index] = old_pos, - } - } - } -} diff --git a/vendor/makepad/libs/regex/src/nullsubexpr.dat b/vendor/makepad/libs/regex/src/nullsubexpr.dat deleted file mode 100644 index 3e0d4dd..0000000 --- a/vendor/makepad/libs/regex/src/nullsubexpr.dat +++ /dev/null @@ -1,80 +0,0 @@ -NOTE null subexpression matches : 2002-06-06 - -E (a*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a*)+ a (0,1)(0,1) -E SAME x (0,0)(0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a+)* a (0,1)(0,1) -E SAME x (0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a+)+ a (0,1)(0,1) -E SAME x NOMATCH -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) - -E ([a]*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E ([a]*)+ a (0,1)(0,1) -E SAME x (0,0)(0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E ([^b]*)* a (0,1)(0,1) -#E SAME b (0,0)(0,0) -E SAME b (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaab (0,6)(0,6) -E ([ab]*)* a (0,1)(0,1) -E SAME aaaaaa (0,6)(0,6) -E SAME ababab (0,6)(0,6) -E SAME bababa (0,6)(0,6) -E SAME b (0,1)(0,1) -E SAME bbbbbb (0,6)(0,6) -E SAME aaaabcde (0,5)(0,5) -E ([^a]*)* b (0,1)(0,1) -E SAME bbbbbb (0,6)(0,6) -#E SAME aaaaaa (0,0)(0,0) -E SAME aaaaaa (0,0)(?,?) RE2/Go -E ([^ab]*)* ccccxx (0,6)(0,6) -#E SAME ababab (0,0)(0,0) -E SAME ababab (0,0)(?,?) RE2/Go - -E ((z)+|a)* zabcde (0,2)(1,2) - -#{E a+? aaaaaa (0,1) no *? +? mimimal match ops -#E (a) aaa (0,1)(0,1) -#E (a*?) aaa (0,0)(0,0) -#E (a)*? aaa (0,0) -#E (a*?)*? aaa (0,0) -#} - -B \(a*\)*\(x\) x (0,1)(0,0)(0,1) -B \(a*\)*\(x\) ax (0,2)(0,1)(1,2) -B \(a*\)*\(x\) axa (0,2)(0,1)(1,2) -B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1) -B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2) -B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3) -B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4) -B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3) - -#E (a*)*(x) x (0,1)(0,0)(0,1) -E (a*)*(x) x (0,1)(?,?)(0,1) RE2/Go -E (a*)*(x) ax (0,2)(0,1)(1,2) -E (a*)*(x) axa (0,2)(0,1)(1,2) - -E (a*)+(x) x (0,1)(0,0)(0,1) -E (a*)+(x) ax (0,2)(0,1)(1,2) -E (a*)+(x) axa (0,2)(0,1)(1,2) - -E (a*){2}(x) x (0,1)(0,0)(0,1) -E (a*){2}(x) ax (0,2)(1,1)(1,2) -E (a*){2}(x) axa (0,2)(1,1)(1,2) - diff --git a/vendor/makepad/libs/regex/src/parse.rs b/vendor/makepad/libs/regex/src/parse.rs deleted file mode 100644 index 0a8202c..0000000 --- a/vendor/makepad/libs/regex/src/parse.rs +++ /dev/null @@ -1,542 +0,0 @@ -use { - super::{ - ast, - ast::Op, - char::CharExt, - char_class, - char_class::CharClass, - error::{Error, Result}, - prog::Pred, - range::Range, - unicode, - }, - std::mem, -}; - -#[derive(Clone, Copy, Debug, Default)] -pub struct Options { - /// Allow '.' to match newline characters. - pub dot_all: bool, - /// Ignore case when matching. - pub ignore_case: bool, - /// Allow '^' and '$' to match next to newline characters. - pub multiline: bool, -} - -#[derive(Debug)] -pub struct Allocs { - expr_stack: Vec, - class_builder: char_class::Builder, - ast_builder: ast::Builder, -} - -impl Allocs { - pub fn new() -> Self { - Self { - expr_stack: Vec::new(), - class_builder: char_class::Builder::new(), - ast_builder: ast::Builder::new(), - } - } -} - -pub fn parse(pattern: &str, options: Options, allocs: &mut Allocs) -> Result> { - Parser { - pattern, - pos: 0, - dot_all: options.dot_all, - ignore_case: options.ignore_case, - multiline: options.multiline, - next_cap_index: 1, - expr_stack: &mut allocs.expr_stack, - expr: Expr::new(Some(0)), - char_class_builder: &mut allocs.class_builder, - ast_builder: &mut allocs.ast_builder, - } - .parse() -} - -#[derive(Debug)] -struct Parser<'a> { - pattern: &'a str, - pos: usize, - dot_all: bool, - ignore_case: bool, - multiline: bool, - next_cap_index: usize, - expr_stack: &'a mut Vec, - expr: Expr, - char_class_builder: &'a mut char_class::Builder, - ast_builder: &'a mut ast::Builder, -} - -impl<'a> Parser<'a> { - fn parse(&mut self) -> Result> { - loop { - match self.peek() { - Some('(') => { - self.skip(); - let cap_index = if !self.skip_2_if(|c0, c1| (c0, c1) == ('?', ':')) { - let cap_index = self.next_cap_index; - self.next_cap_index += 1; - Some(cap_index) - } else { - None - }; - self.push(cap_index); - } - Some(')') => { - self.skip(); - self.pop()?; - } - Some('|') => { - self.skip(); - self.alt(); - } - Some('?') => { - self.skip(); - let greedy = !self.skip_if(|c| c == '?'); - if self.ast_builder.stack_depth() == 0 { - return Err(self.error(format!("missing operand"))); - } - self.ast_builder.ques(greedy); - } - Some('*') => { - self.skip(); - let greedy = !self.skip_if(|c| c == '?'); - if self.ast_builder.stack_depth() == 0 { - return Err(self.error(format!("missing operand"))); - } - self.ast_builder.star(greedy); - } - Some('+') => { - self.skip(); - let greedy = !self.skip_if(|c| c == '?'); - if self.ast_builder.stack_depth() == 0 { - return Err(self.error(format!("missing operand"))); - } - self.ast_builder.plus(greedy); - } - Some('{') => { - if !self.maybe_parse_rep()? { - self.skip(); - self.char('{'); - } - } - Some('^') => { - self.skip(); - self.assert(if self.multiline { - Pred::LineStart - } else { - Pred::TextStart - }); - } - Some('$') => { - self.skip(); - self.assert(if self.multiline { - Pred::LineEnd - } else { - Pred::TextEnd - }); - } - Some('.') => { - self.skip(); - let class = if self.dot_all { - CharClass::any() - } else { - self.char_class_builder.add_char(self.ignore_case, '\n'); - self.char_class_builder.build(true) - }; - self.char_class(class); - } - Some('[') => self.parse_class()?, - Some('\\') => { - if self.maybe_parse_class_escape() { - let class = self.char_class_builder.build(false); - self.char_class(class); - } else { - let c = self.parse_char_escape()?; - if self.ignore_case { - self.char_class_builder.add_char(true, c); - let class = self.char_class_builder.build(false); - self.char_class(class); - } else { - self.char(c); - } - } - } - Some(c) => { - self.skip(); - if self.ignore_case { - self.char_class_builder.add_char(true, c); - let class = self.char_class_builder.build(false); - self.char_class(class); - } else { - self.char(c); - } - } - None => break, - } - } - self.alt(); - if !self.expr_stack.is_empty() { - return Err(self.error(format!("unmatched '('"))); - } - if self.expr.term_count == 0 { - self.ast_builder.empty(); - } - self.ast_builder.cap(self.expr.cap_index.unwrap()); - Ok(self.ast_builder.build()) - } - - fn maybe_parse_rep(&mut self) -> Result { - let pos = self.pos; - self.skip(); - let min = match self.parse_dec_int().ok() { - Some(min) => min, - None => { - self.pos = pos; - return Ok(false); - } - }; - let max = if self.skip_if(|c| c == ',') { - if self.peek() != Some('}') { - match self.parse_dec_int().ok() { - Some(max) => Some(max), - None => { - self.pos = pos; - return Ok(false); - } - } - } else { - None - } - } else { - Some(min) - }; - if self.peek() != Some('}') { - self.pos = pos; - return Ok(false); - } - self.skip(); - let greedy = !self.skip_if(|c| c == '?'); - if max.map_or(false, |max| max < min) { - return Err(self.error(format!("invalid max repetition count"))); - } - if self.ast_builder.stack_depth() == 0 { - return Err(self.error(format!("missing operand"))); - } - self.ast_builder.rep(min, max, greedy); - Ok(true) - } - - fn parse_class(&mut self) -> Result<()> { - self.skip(); - let negated = self.skip_if(|c| c == '^'); - let mut is_first = true; - loop { - match self.peek_2() { - (Some(']'), _) if !is_first => { - self.skip(); - break; - } - (Some('['), Some(':')) => { - self.parse_char_class_name()?; - } - (Some(_), _) => { - if !self.maybe_parse_class_escape() { - let range = self.parse_class_range()?; - self.char_class_builder.add_range(self.ignore_case, range); - } - } - (None, _) => return Err(self.error(format!("unmatched '['"))), - } - is_first = false; - } - let class = self.char_class_builder.build(negated); - self.char_class(class); - Ok(()) - } - - fn parse_char_class_name(&mut self) -> Result<()> { - self.skip_2(); - let negated = self.skip_if(|c| c == '^'); - let start = self.pos; - let end = loop { - match self.peek_2() { - (Some(':'), Some(']')) => { - let end = self.pos; - self.skip_2(); - break end; - } - (Some(_), _) => self.skip(), - (None, _) => return Err(self.error(format!("unmatched '[:'"))), - } - }; - if start == end { - return Err(self.error(format!("empty char class name"))); - } - let ranges = match &self.pattern[start..end] { - "alnum" => unicode::ALNUM.as_slice(), - "alpha" => unicode::ALPHA.as_slice(), - "blank" => unicode::BLANK.as_slice(), - "cntrl" => unicode::CNTRL.as_slice(), - "digit" => unicode::DIGIT.as_slice(), - "graph" => unicode::GRAPH.as_slice(), - "lower" => unicode::LOWER.as_slice(), - "print" => unicode::PRINT.as_slice(), - "punct" => unicode::PUNCT.as_slice(), - "space" => unicode::SPACE.as_slice(), - "upper" => unicode::UPPER.as_slice(), - "word" => unicode::WORD.as_slice(), - "xdigit" => unicode::XDIGIT.as_slice(), - _ => { - return Err(self.error(format!( - "invalid char class name {}", - &self.pattern[start..end] - ))) - } - }; - self.char_class_builder - .add_ranges(negated, self.ignore_case, ranges); - Ok(()) - } - - fn maybe_parse_class_escape(&mut self) -> bool { - match self.peek_2() { - (Some('\\'), Some(c)) => { - let group = match c { - 'D' => Some((true, unicode::DIGIT.as_slice())), - 'S' => Some((true, unicode::SPACE.as_slice())), - 'W' => Some((true, unicode::WORD.as_slice())), - 'd' => Some((false, unicode::DIGIT.as_slice())), - 's' => Some((false, unicode::SPACE.as_slice())), - 'w' => Some((false, unicode::WORD.as_slice())), - _ => None, - }; - match group { - Some((negated, ranges)) => { - self.skip_2(); - self.char_class_builder - .add_ranges(negated, self.ignore_case, ranges); - true - } - None => false, - } - } - _ => false, - } - } - - fn parse_class_range(&mut self) -> Result> { - let start = self.parse_class_char()?; - match self.peek_2() { - (Some('-'), c1) if c1 != Some(']') => { - self.skip(); - let end = self.parse_class_char()?; - return Ok(Range::new(start, end)); - } - _ => Ok(Range::new(start, start)), - } - } - - fn parse_class_char(&mut self) -> Result { - match self.peek() { - Some('\\') => self.parse_char_escape(), - Some(c) => { - self.skip(); - Ok(c) - } - _ => return Err(self.error(format!("expected character, got end of pattern"))), - } - } - - fn parse_char_escape(&mut self) -> Result { - self.skip(); - let c = match self.peek() { - Some('n') => '\n', - Some('r') => '\r', - Some('t') => '\t', - Some(c) if !c.is_word() => c, - Some(c) => return Err(self.error(format!("expected escape character, got `{}`", c))), - None => { - return Err(self.error(format!("expected escape character, got end of pattern"))) - } - }; - self.skip(); - Ok(c) - } - - fn parse_dec_int(&mut self) -> Result { - let c = match self.peek() { - Some(c) if c.is_digit(10) => c, - Some(c) => return Err(self.error(format!("expected decimal digit, got `{}`", c))), - None => return Err(self.error(format!("expected decimal digit, got end of pattern"))), - }; - self.skip(); - let mut value = c.to_digit(10).unwrap(); - loop { - let c = match self.peek() { - Some(c) if c.is_digit(10) => { - self.skip(); - c - } - _ => break, - }; - value = match value.checked_mul(10) { - Some(value) => value, - None => return Err(self.error(format!("integer overflow"))), - } + c.to_digit(10).unwrap(); - } - Ok(value) - } - - fn parse_hex_int(&mut self) -> Result { - let c = match self.peek() { - Some(c) if c.is_digit(16) => { - self.skip(); - c - } - Some(c) => return Err(self.error(format!("expected hexadecimal digit, got `{}`", c))), - None => { - return Err(self.error(format!("expected hexadecimal digit, got end of pattern"))) - } - }; - let mut value = c.to_digit(16).unwrap(); - loop { - let c = match self.peek() { - Some(c) if c.is_digit(16) => { - self.skip(); - c - } - _ => break, - }; - value = 16 * value + c.to_digit(16).unwrap(); - } - Ok(value) - } - - fn peek(&self) -> Option { - self.pattern[self.pos..].chars().next() - } - - fn peek_2(&self) -> (Option, Option) { - let mut chars = self.pattern[self.pos..].chars(); - (chars.next(), chars.next()) - } - - fn skip(&mut self) { - self.pos += self.peek().unwrap().len_utf8(); - } - - fn skip_if(&mut self, f: impl FnOnce(char) -> bool) -> bool { - if self.peek().map_or(false, f) { - self.skip(); - true - } else { - false - } - } - - fn skip_2(&mut self) { - let (c0, c1) = self.peek_2(); - self.pos += c0.unwrap().len_utf8(); - self.pos += c1.unwrap().len_utf8(); - } - - fn skip_2_if(&mut self, f: impl FnOnce(char, char) -> bool) -> bool { - let (c0, c1) = self.peek_2(); - if match (c0, c1) { - (Some(c0), Some(c1)) => f(c0, c1), - _ => false, - } { - self.skip_2(); - true - } else { - false - } - } - - fn push(&mut self, cap_index: Option) { - self.cat(); - let expr = mem::replace(&mut self.expr, Expr::new(cap_index)); - self.expr_stack.push(expr); - } - - fn pop(&mut self) -> Result<()> { - self.alt(); - if self.expr.term_count == 0 { - self.ast_builder.empty(); - } - if let Some(index) = self.expr.cap_index { - self.ast_builder.cap(index); - } - self.expr = match self.expr_stack.pop() { - Some(expr) => expr, - None => return Err(self.error(format!("unmatched '('"))), - }; - self.expr.fact_count += 1; - Ok(()) - } - - fn alt(&mut self) { - self.cat(); - if self.expr.fact_count != 0 { - self.expr.term_count += 1; - self.expr.fact_count = 0; - } - if self.expr.term_count == 2 { - self.ast_builder.alt(); - self.expr.term_count -= 1; - } - } - - fn cat(&mut self) { - if self.expr.fact_count == 2 { - self.ast_builder.cat(); - self.expr.fact_count -= 1; - } - } - - fn assert(&mut self, pred: Pred) { - self.cat(); - self.expr.fact_count += 1; - self.ast_builder.assert(pred); - } - - fn char(&mut self, c: char) { - self.cat(); - self.expr.fact_count += 1; - self.ast_builder.char(c); - } - - fn char_class(&mut self, class: CharClass) { - self.cat(); - self.expr.fact_count += 1; - self.ast_builder.char_class(class); - } - - fn error(&self, message: String) -> Error { - return Error { - message, - pos: self.pos, - }; - } -} - -#[derive(Debug)] -struct Expr { - cap_index: Option, - term_count: usize, - fact_count: usize, -} - -impl Expr { - fn new(cap_index: Option) -> Self { - Self { - cap_index, - term_count: 0, - fact_count: 0, - } - } -} diff --git a/vendor/makepad/libs/regex/src/prog.rs b/vendor/makepad/libs/regex/src/prog.rs deleted file mode 100644 index 83eaff7..0000000 --- a/vendor/makepad/libs/regex/src/prog.rs +++ /dev/null @@ -1,153 +0,0 @@ -use super::{char_class::CharClass, range::Range}; - -#[derive(Clone, Debug)] -pub struct Prog { - pub insts: Vec, - pub start: InstPtr, - pub byte_classes: Box<[u8]>, - pub has_word_boundary: bool, - pub slot_count: usize, -} - -impl Prog { - pub fn byte_class_count(&self) -> usize { - self.byte_classes[255] as usize + 1 - } -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub enum Inst { - Match, - ByteRange(ByteRangeInst), - Char(CharInst), - Class(ClassInst), - Nop(NopInst), - Save(SaveInst), - Assert(AssertInst), - Split(SplitInst), -} - -impl Inst { - pub fn byte_range(out: InstPtr, range: Range) -> Self { - Self::ByteRange(ByteRangeInst { out, range }) - } - - pub fn char(out: InstPtr, c: char) -> Self { - Self::Char(CharInst { out, c }) - } - - pub fn class(out: InstPtr, class: CharClass) -> Self { - Self::Class(ClassInst { out, class }) - } - - pub fn nop(out: InstPtr) -> Self { - Self::Nop(NopInst { out }) - } - - pub fn save(out: InstPtr, slot_index: usize) -> Self { - Self::Save(SaveInst { out, slot_index }) - } - - pub fn assert(out: InstPtr, pred: Pred) -> Self { - Self::Assert(AssertInst { out, pred }) - } - - pub fn split(out_0: InstPtr, out_1: InstPtr) -> Self { - Self::Split(SplitInst { out_0, out_1 }) - } - - pub fn out_0(&self) -> &InstPtr { - match self { - Self::ByteRange(inst) => &inst.out, - Self::Char(inst) => &inst.out, - Self::Class(inst) => &inst.out, - Self::Nop(inst) => &inst.out, - Self::Save(inst) => &inst.out, - Self::Assert(inst) => &inst.out, - Self::Split(inst) => &inst.out_0, - _ => panic!(), - } - } - - pub fn out_1(&self) -> &InstPtr { - match self { - Self::Split(inst) => &inst.out_1, - _ => panic!(), - } - } - - pub fn out_0_mut(&mut self) -> &mut InstPtr { - match self { - Self::ByteRange(inst) => &mut inst.out, - Self::Char(inst) => &mut inst.out, - Self::Class(inst) => &mut inst.out, - Self::Nop(inst) => &mut inst.out, - Self::Save(inst) => &mut inst.out, - Self::Assert(inst) => &mut inst.out, - Self::Split(inst) => &mut inst.out_0, - _ => panic!(), - } - } - - pub fn out_1_mut(&mut self) -> &mut InstPtr { - match self { - Self::Split(inst) => &mut inst.out_1, - _ => panic!(), - } - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct ByteRangeInst { - pub out: InstPtr, - pub range: Range, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct CharInst { - pub out: InstPtr, - pub c: char, -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct ClassInst { - pub out: InstPtr, - pub class: CharClass, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct NopInst { - pub out: InstPtr, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SaveInst { - pub out: InstPtr, - pub slot_index: usize, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct AssertInst { - pub out: InstPtr, - pub pred: Pred, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum Pred { - TextStart, - TextEnd, - LineStart, - LineEnd, - WordBoundary, - NotWordBoundary, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SplitInst { - pub out_0: InstPtr, - pub out_1: InstPtr, -} - -pub type InstPtr = usize; - -pub const NULL_INST: InstPtr = usize::MAX; diff --git a/vendor/makepad/libs/regex/src/range.rs b/vendor/makepad/libs/regex/src/range.rs deleted file mode 100644 index 4ad1efb..0000000 --- a/vendor/makepad/libs/regex/src/range.rs +++ /dev/null @@ -1,38 +0,0 @@ -/// A range bounded inclusively from below and above. -#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -pub struct Range { - /// The lower bound of the range (inclusive). - pub start: T, - /// The upper bound of the range (inclusive). - pub end: T, -} - -impl Range { - /// Creates a new inclusive range with the given `start` and `end` bounds. - pub const fn new(start: T, end: T) -> Self { - Self { start, end } - } - - /// Returns `true` if `value` is contained in the range. - pub fn contains(&self, value: &T) -> bool - where - T: Ord, - { - &self.start <= value && value <= &self.end - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn contains() { - let range = Range::new(10, 20); - assert!(!range.contains(&9)); - assert!(range.contains(&10)); - assert!(range.contains(&15)); - assert!(range.contains(&20)); - assert!(!range.contains(&21)); - } -} diff --git a/vendor/makepad/libs/regex/src/regex.rs b/vendor/makepad/libs/regex/src/regex.rs deleted file mode 100644 index a40daa3..0000000 --- a/vendor/makepad/libs/regex/src/regex.rs +++ /dev/null @@ -1,142 +0,0 @@ -use { - super::{ - compile, dfa, - error::Result, - input::{Cursor as _, Input}, - nfa, parse, - prog::Prog, - }, - std::{cell::RefCell, sync::Arc}, -}; - -#[derive(Clone, Debug)] -pub struct Regex { - shared: Arc, - dfa_cache: RefCell, - rev_dfa_cache: RefCell, - nfa_cache: RefCell, -} - -impl Regex { - pub fn new(pattern: &str) -> Result { - Self::new_with_options( - pattern, - parse::Options { - multiline: true, - dot_all: true, - ..parse::Options::default() - }, - ) - } - - pub fn new_with_options(pattern: &str, options: parse::Options) -> Result { - let mut parse_cache = parse::Allocs::new(); - let ast = parse::parse(pattern, options, &mut parse_cache)?; - let mut compile_cache = compile::Allocs::new(); - let dfa_prog = compile::compile( - &ast, - compile::Options { - dot_star: true, - ignore_caps: true, - byte_based: true, - ..compile::Options::default() - }, - &mut compile_cache, - ); - let rev_dfa_prog = compile::compile( - &ast, - compile::Options { - ignore_caps: true, - byte_based: true, - reversed: true, - ..compile::Options::default() - }, - &mut compile_cache, - ); - let nfa_prog = compile::compile(&ast, compile::Options::default(), &mut compile_cache); - let dfa_cache = dfa::Cache::new(&dfa_prog); - let rev_dfa_cache = dfa::Cache::new(&rev_dfa_prog); - let nfa_cache = nfa::Allocs::new(&nfa_prog); - Ok(Self { - shared: Arc::new(Shared { - dfa_prog, - rev_dfa_prog, - nfa_prog, - }), - dfa_cache: RefCell::new(dfa_cache), - rev_dfa_cache: RefCell::new(rev_dfa_cache), - nfa_cache: RefCell::new(nfa_cache), - }) - } - - pub fn run<'a, I: Input<'a>>(&self, input: I, slots: &mut [Option]) -> bool { - let mut dfa_cache = self.dfa_cache.borrow_mut(); - match dfa::run( - &self.shared.dfa_prog, - input.cursor_start(), - dfa::Options { - want_first_match: slots.is_empty(), - ..dfa::Options::default() - }, - &mut *dfa_cache, - ) { - Ok(Some(end)) => { - if slots.is_empty() { - return true; - } - let mut rev_dfa_cache = self.rev_dfa_cache.borrow_mut(); - let start = dfa::run( - &self.shared.rev_dfa_prog, - input.slice(0..end).cursor_end().rev(), - dfa::Options { - want_last_match: true, - ..dfa::Options::default() - }, - &mut *rev_dfa_cache, - ) - .unwrap() - .unwrap(); - if slots.len() == 2 { - slots[0] = Some(start); - slots[1] = Some(end); - } else if slots.len() > 2 { - let mut nfa_cache = self.nfa_cache.borrow_mut(); - nfa::run( - &self.shared.nfa_prog, - input.slice(start..end).cursor_start(), - nfa::Options::default(), - slots, - &mut *nfa_cache, - ); - for slot in slots { - if let Some(slot) = slot { - *slot += start; - } - } - } - true - } - Ok(None) => false, - Err(_) => { - let mut nfa_cache = self.nfa_cache.borrow_mut(); - nfa::run( - &self.shared.nfa_prog, - input.cursor_start(), - nfa::Options { - want_first_match: slots.is_empty(), - ..nfa::Options::default() - }, - slots, - &mut *nfa_cache, - ) - } - } - } -} - -#[derive(Debug)] -struct Shared { - dfa_prog: Prog, - rev_dfa_prog: Prog, - nfa_prog: Prog, -} diff --git a/vendor/makepad/libs/regex/src/repetitions.dat b/vendor/makepad/libs/regex/src/repetitions.dat deleted file mode 100644 index 3bb2121..0000000 --- a/vendor/makepad/libs/regex/src/repetitions.dat +++ /dev/null @@ -1,163 +0,0 @@ -NOTE implicit vs. explicit repetitions : 2009-02-02 - -# Glenn Fowler -# conforming matches (column 4) must match one of the following BREs -# NOMATCH -# (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)* -# (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)* -# i.e., each 3-tuple has two identical elements and one (?,?) - -E ((..)|(.)) NULL NOMATCH -E ((..)|(.))((..)|(.)) NULL NOMATCH -E ((..)|(.))((..)|(.))((..)|(.)) NULL NOMATCH - -E ((..)|(.)){1} NULL NOMATCH -E ((..)|(.)){2} NULL NOMATCH -E ((..)|(.)){3} NULL NOMATCH - -E ((..)|(.))* NULL (0,0) - -E ((..)|(.)) a (0,1)(0,1)(?,?)(0,1) -E ((..)|(.))((..)|(.)) a NOMATCH -E ((..)|(.))((..)|(.))((..)|(.)) a NOMATCH - -E ((..)|(.)){1} a (0,1)(0,1)(?,?)(0,1) -E ((..)|(.)){2} a NOMATCH -E ((..)|(.)){3} a NOMATCH - -E ((..)|(.))* a (0,1)(0,1)(?,?)(0,1) - -E ((..)|(.)) aa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aa (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2) -E ((..)|(.))((..)|(.))((..)|(.)) aa NOMATCH - -E ((..)|(.)){1} aa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aa (0,2)(1,2)(?,?)(1,2) -E ((..)|(.)){3} aa NOMATCH - -E ((..)|(.))* aa (0,2)(0,2)(0,2)(?,?) - -E ((..)|(.)) aaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaa (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3) -E ((..)|(.))((..)|(.))((..)|(.)) aaa (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3) - -E ((..)|(.)){1} aaa (0,2)(0,2)(0,2)(?,?) -#E ((..)|(.)){2} aaa (0,3)(2,3)(?,?)(2,3) -E ((..)|(.)){2} aaa (0,3)(2,3)(0,2)(2,3) RE2/Go -E ((..)|(.)){3} aaa (0,3)(2,3)(?,?)(2,3) - -#E ((..)|(.))* aaa (0,3)(2,3)(?,?)(2,3) -E ((..)|(.))* aaa (0,3)(2,3)(0,2)(2,3) RE2/Go - -E ((..)|(.)) aaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4) - -E ((..)|(.)){1} aaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaa (0,4)(2,4)(2,4)(?,?) -#E ((..)|(.)){3} aaaa (0,4)(3,4)(?,?)(3,4) -E ((..)|(.)){3} aaaa (0,4)(3,4)(0,2)(3,4) RE2/Go - -E ((..)|(.))* aaaa (0,4)(2,4)(2,4)(?,?) - -E ((..)|(.)) aaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaaa (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5) - -E ((..)|(.)){1} aaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaaa (0,4)(2,4)(2,4)(?,?) -#E ((..)|(.)){3} aaaaa (0,5)(4,5)(?,?)(4,5) -E ((..)|(.)){3} aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go - -#E ((..)|(.))* aaaaa (0,5)(4,5)(?,?)(4,5) -E ((..)|(.))* aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go - -E ((..)|(.)) aaaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaaaa (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?) - -E ((..)|(.)){1} aaaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaaaa (0,4)(2,4)(2,4)(?,?) -E ((..)|(.)){3} aaaaaa (0,6)(4,6)(4,6)(?,?) - -E ((..)|(.))* aaaaaa (0,6)(4,6)(4,6)(?,?) - -NOTE additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02 - -# These test a bug in OS X / FreeBSD / NetBSD, and libtree. -# Linux/GLIBC gets the {8,} and {8,8} wrong. - -:HA#100:E X(.?){0,}Y X1234567Y (0,9)(7,8) -:HA#101:E X(.?){1,}Y X1234567Y (0,9)(7,8) -:HA#102:E X(.?){2,}Y X1234567Y (0,9)(7,8) -:HA#103:E X(.?){3,}Y X1234567Y (0,9)(7,8) -:HA#104:E X(.?){4,}Y X1234567Y (0,9)(7,8) -:HA#105:E X(.?){5,}Y X1234567Y (0,9)(7,8) -:HA#106:E X(.?){6,}Y X1234567Y (0,9)(7,8) -:HA#107:E X(.?){7,}Y X1234567Y (0,9)(7,8) -:HA#108:E X(.?){8,}Y X1234567Y (0,9)(8,8) -#:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(7,8) -:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(7,8) -:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(7,8) -:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(7,8) -:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(7,8) -:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(7,8) -:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(7,8) -:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(7,8) -:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(8,8) RE2/Go -:HA#118:E X(.?){8,8}Y X1234567Y (0,9)(8,8) - -# These test a fixed bug in my regex-tdfa that did not keep the expanded -# form properly grouped, so right association did the wrong thing with -# these ambiguous patterns (crafted just to test my code when I became -# suspicious of my implementation). The first subexpression should use -# "ab" then "a" then "bcd". - -# OS X / FreeBSD / NetBSD badly fail many of these, with impossible -# results like (0,6)(4,5)(6,6). - -:HA#260:E (a|ab|c|bcd){0,}(d*) ababcd (0,1)(0,1)(1,1) -:HA#261:E (a|ab|c|bcd){1,}(d*) ababcd (0,1)(0,1)(1,1) -:HA#262:E (a|ab|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#263:E (a|ab|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#264:E (a|ab|c|bcd){4,}(d*) ababcd NOMATCH -:HA#265:E (a|ab|c|bcd){0,10}(d*) ababcd (0,1)(0,1)(1,1) -:HA#266:E (a|ab|c|bcd){1,10}(d*) ababcd (0,1)(0,1)(1,1) -:HA#267:E (a|ab|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#268:E (a|ab|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#269:E (a|ab|c|bcd){4,10}(d*) ababcd NOMATCH -:HA#270:E (a|ab|c|bcd)*(d*) ababcd (0,1)(0,1)(1,1) -:HA#271:E (a|ab|c|bcd)+(d*) ababcd (0,1)(0,1)(1,1) - -# The above worked on Linux/GLIBC but the following often fail. -# They also trip up OS X / FreeBSD / NetBSD: - -#:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -:HA#284:E (ab|a|c|bcd){4,}(d*) ababcd NOMATCH -#:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -:HA#289:E (ab|a|c|bcd){4,10}(d*) ababcd NOMATCH -#:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6) -:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6) -:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(4,5)(5,6) RE2/Go diff --git a/vendor/makepad/libs/regex/src/sparse_set.rs b/vendor/makepad/libs/regex/src/sparse_set.rs deleted file mode 100644 index 8f1c99e..0000000 --- a/vendor/makepad/libs/regex/src/sparse_set.rs +++ /dev/null @@ -1,96 +0,0 @@ -/// A sparse set of integers. -/// -/// The implementation is based on: https://research.swtch.com/sparse. -/// -/// The vector `dense` contains a list of integers in insertion order. The boxed slice `sparse` -/// contains a mapping from integers to their indices in `dense`. An integer is in the `SparseSet` -/// if `sparse` maps the integer to a valid index in `dense`, and the integer at that index in -/// `dense` has the same value. -/// -/// All methods on a `SparseSet` take *O*(1) time. -#[derive(Clone, Debug)] -pub struct SparseSet { - dense: Vec, - sparse: Box<[usize]>, -} - -impl SparseSet { - /// Returns a new `SparseSet` with space for all integers ranging from `0` to `max`. - pub fn new(max: usize) -> Self { - Self { - dense: Vec::with_capacity(max), - sparse: vec![0; max].into_boxed_slice(), - } - } - - /// Returns `true` if the `SparseSet` is empty. - pub fn is_empty(&self) -> bool { - self.dense.is_empty() - } - - /// Returns a slice of the integers in the `SparseSet`, in insertion order. - pub fn as_slice(&self) -> &[usize] { - self.dense.as_slice() - } - - /// Returns `true` if the `SparseSet` contains the integer `value`. - pub fn contains(&self, value: usize) -> bool { - self.dense.get(self.sparse[value]) == Some(&value) - } - - /// Adds the integer `value` to the `SparseSet`. - /// - /// Returns `true` if the `SparseSet` did not already contain `value`. - pub fn insert(&mut self, value: usize) -> bool { - if self.contains(value) { - return false; - } - let index = self.dense.len(); - self.dense.push(value); - self.sparse[value] = index; - true - } - - /// Removes all integers from the `SparseSet`. - pub fn clear(&mut self) { - self.dense.clear() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn is_empty() { - let mut set = SparseSet::new(8); - assert!(set.is_empty()); - set.insert(4); - assert!(!set.is_empty()); - set.clear(); - assert!(set.is_empty()); - } - - #[test] - fn as_slice() { - let mut set = SparseSet::new(8); - assert_eq!(set.as_slice(), &[]); - set.insert(6); - set.insert(4); - set.insert(4); - set.insert(2); - assert_eq!(set.as_slice(), &[6, 4, 2]); - set.clear(); - assert_eq!(set.as_slice(), &[]); - } - - #[test] - fn contains() { - let mut set = SparseSet::new(8); - assert!(!set.contains(4)); - set.insert(4); - assert!(set.contains(4)); - set.clear(); - assert!(!set.contains(4)); - } -} diff --git a/vendor/makepad/libs/regex/src/str.rs b/vendor/makepad/libs/regex/src/str.rs deleted file mode 100644 index 8788a07..0000000 --- a/vendor/makepad/libs/regex/src/str.rs +++ /dev/null @@ -1,100 +0,0 @@ -use { - super::{input, input::Input}, - std::ops::Range, -}; - -impl<'a> Input<'a> for &'a str { - type Cursor = Cursor<'a>; - - fn slice(&self, range: Range) -> &'a str { - &self[range] - } - - fn cursor_start(&self) -> Self::Cursor { - Cursor { - str: &self, - index: 0, - } - } - - fn cursor_end(&self) -> Self::Cursor { - Cursor { - str: self, - index: self.len(), - } - } -} - -#[derive(Clone, Debug)] -pub struct Cursor<'a> { - str: &'a str, - index: usize, -} - -impl<'a> input::Cursor for Cursor<'a> { - fn is_start(&self) -> bool { - self.index == 0 - } - - fn is_end(&self) -> bool { - self.index == self.str.len() - } - - fn index(&self) -> usize { - self.index - } - - fn current_byte(&mut self) -> Option { - self.str.as_bytes()[self.index..].first().copied() - } - - fn current_char(&mut self) -> Option { - self.str[self.index..].chars().next() - } - - fn prev_byte(&mut self) -> Option { - self.str.as_bytes()[..self.index].last().copied() - } - - fn prev_char(&mut self) -> Option { - self.str[..self.index].chars().next_back() - } - - fn move_next_byte(&mut self) -> bool { - if self.is_end() { - return false; - } - self.index += 1; - true - } - - fn move_next_char(&mut self) -> bool { - if self.move_next_byte() { - while !self.str.is_char_boundary(self.index) { - self.move_next_byte(); - } - true - } else { - false - } - } - - fn move_prev_byte(&mut self) -> bool { - if self.is_start() { - return false; - } - self.index -= 1; - true - } - - fn move_prev_char(&mut self) -> bool { - if self.move_prev_byte() { - while !self.str.is_char_boundary(self.index) { - self.move_prev_byte(); - } - true - } else { - false - } - } -} diff --git a/vendor/makepad/libs/regex/src/tests/basic.rs b/vendor/makepad/libs/regex/src/tests/basic.rs deleted file mode 100644 index 78fd484..0000000 --- a/vendor/makepad/libs/regex/src/tests/basic.rs +++ /dev/null @@ -1,1210 +0,0 @@ -//! Generated by make_fowler_tests.py - -test_regex!( - basic_3, - r"abracadabra$", - "abracadabracadabra", - Some(7), - Some(18) -); -test_regex!(basic_4, r"a...b", "abababbb", Some(2), Some(7)); -test_regex!(basic_5, r"XXXXXX", "..XXXXXX", Some(2), Some(8)); -test_regex!(basic_6, r"\)", "()", Some(1), Some(2)); -test_regex!(basic_7, r"a]", "a]a", Some(0), Some(2)); -test_regex!(basic_9, r"\}", "}", Some(0), Some(1)); -test_regex!(basic_10, r"\]", "]", Some(0), Some(1)); -test_regex!(basic_12, r"]", "]", Some(0), Some(1)); -test_regex!(basic_15, r"^a", "ax", Some(0), Some(1)); -test_regex!(basic_16, r"\^a", "a^a", Some(1), Some(3)); -test_regex!(basic_17, r"a\^", "a^", Some(0), Some(2)); -test_regex!(basic_18, r"a$", "aa", Some(1), Some(2)); -test_regex!(basic_19, r"a\$", "a$", Some(0), Some(2)); -test_regex!(basic_20, r"^$", "", Some(0), Some(0)); -test_regex!(basic_21, r"$^", "", Some(0), Some(0)); -test_regex!(basic_22, r"a($)", "aa", Some(1), Some(2), Some(2), Some(2)); -test_regex!( - basic_23, - r"a*(^a)", - "aa", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!(basic_24, r"(..)*(...)*", "a", Some(0), Some(0)); -test_regex!( - basic_25, - r"(..)*(...)*", - "abcd", - Some(0), - Some(4), - Some(2), - Some(4) -); -test_regex!( - basic_26, - r"(ab|a)(bc|c)", - "abc", - Some(0), - Some(3), - Some(0), - Some(2), - Some(2), - Some(3) -); -test_regex!( - basic_27, - r"(ab)c|abc", - "abc", - Some(0), - Some(3), - Some(0), - Some(2) -); -test_regex!(basic_28, r"a{0}b", "ab", Some(1), Some(2)); -test_regex!( - basic_29, - r"(a*)(b?)(b+)b{3}", - "aaabbbbbbb", - Some(0), - Some(10), - Some(0), - Some(3), - Some(3), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_30, - r"(a*)(b{0,1})(b{1,})b{3}", - "aaabbbbbbb", - Some(0), - Some(10), - Some(0), - Some(3), - Some(3), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_32, - r"((a|a)|a)", - "a", - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - basic_33, - r"(a*)(a|aa)", - "aaaa", - Some(0), - Some(4), - Some(0), - Some(3), - Some(3), - Some(4) -); -test_regex!( - basic_34, - r"a*(a.|aa)", - "aaaa", - Some(0), - Some(4), - Some(2), - Some(4) -); -test_regex!( - basic_35, - r"a(b)|c(d)|a(e)f", - "aef", - Some(0), - Some(3), - None, - None, - None, - None, - Some(1), - Some(2) -); -test_regex!( - basic_36, - r"(a|b)?.*", - "b", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - basic_37, - r"(a|b)c|a(b|c)", - "ac", - Some(0), - Some(2), - Some(0), - Some(1) -); -test_regex!( - basic_38, - r"(a|b)c|a(b|c)", - "ab", - Some(0), - Some(2), - None, - None, - Some(1), - Some(2) -); -test_regex!( - basic_39, - r"(a|b)*c|(a|ab)*c", - "abc", - Some(0), - Some(3), - Some(1), - Some(2) -); -test_regex!(basic_40, r"(a|b)*c|(a|ab)*c", "xc", Some(1), Some(2)); -test_regex!( - basic_41, - r"(.a|.b).*|.*(.a|.b)", - "xa", - Some(0), - Some(2), - Some(0), - Some(2) -); -test_regex!( - basic_42, - r"a?(ab|ba)ab", - "abab", - Some(0), - Some(4), - Some(0), - Some(2) -); -test_regex!( - basic_43, - r"a?(ac{0}b|ba)ab", - "abab", - Some(0), - Some(4), - Some(0), - Some(2) -); -test_regex!(basic_44, r"ab|abab", "abbabab", Some(0), Some(2)); -test_regex!(basic_45, r"aba|bab|bba", "baaabbbaba", Some(5), Some(8)); -test_regex!(basic_46, r"aba|bab", "baaabbbaba", Some(6), Some(9)); -test_regex!( - basic_47, - r"(aa|aaa)*|(a|aaaaa)", - "aa", - Some(0), - Some(2), - Some(0), - Some(2) -); -test_regex!( - basic_48, - r"(a.|.a.)*|(a|.a...)", - "aa", - Some(0), - Some(2), - Some(0), - Some(2) -); -test_regex!(basic_49, r"ab|a", "xabc", Some(1), Some(3)); -test_regex!(basic_50, r"ab|a", "xxabc", Some(2), Some(4)); -test_regex!(basic_52, r"[^-]", "--a", Some(2), Some(3)); -test_regex!(basic_53, r"[a-]*", "--a", Some(0), Some(3)); -test_regex!(basic_54, r"[a-m-]*", "--amoma--", Some(0), Some(4)); -test_regex!( - basic_55, - r":::1:::0:|:::1:1:0:", - ":::0:::1:::1:::0:", - Some(8), - Some(17) -); -test_regex!( - basic_56, - r":::1:::0:|:::1:1:1:", - ":::0:::1:::1:::0:", - Some(8), - Some(17) -); -test_regex!(basic_57, r"[[:upper:]]", "A", Some(0), Some(1)); -test_regex!(basic_58, r"[[:lower:]]+", "`az{", Some(1), Some(3)); -test_regex!(basic_59, r"[[:upper:]]+", "@AZ[", Some(1), Some(3)); -test_regex!(basic_65, r"\n", "\n", Some(0), Some(1)); -test_regex!(basic_66, r"\n", "\n", Some(0), Some(1)); -test_regex!(basic_67, r"[^a]", "\n", Some(0), Some(1)); -test_regex!(basic_68, r"\na", "\na", Some(0), Some(2)); -test_regex!( - basic_69, - r"(a)(b)(c)", - "abc", - Some(0), - Some(3), - Some(0), - Some(1), - Some(1), - Some(2), - Some(2), - Some(3) -); -test_regex!(basic_70, r"xxx", "xxx", Some(0), Some(3)); -test_regex!( - basic_71, - r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", - "feb 6,", - Some(0), - Some(6) -); -test_regex!( - basic_72, - r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", - "2/7", - Some(0), - Some(3) -); -test_regex!( - basic_73, - r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", - "feb 1,Feb 6", - Some(5), - Some(11) -); -test_regex!( - basic_74, - r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))", - "x", - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - basic_75, - r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*", - "xx", - Some(0), - Some(2), - Some(1), - Some(2), - Some(1), - Some(2) -); -test_regex!( - basic_76, - r"a?(ab|ba)*", - "ababababababababababababababababababababababababababababababababababababababababa", - Some(0), - Some(81), - Some(79), - Some(81) -); -test_regex!( - basic_77, - r"abaa|abbaa|abbbaa|abbbbaa", - "ababbabbbabbbabbbbabbbbaa", - Some(18), - Some(25) -); -test_regex!( - basic_78, - r"abaa|abbaa|abbbaa|abbbbaa", - "ababbabbbabbbabbbbabaa", - Some(18), - Some(22) -); -test_regex!( - basic_79, - r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc", - "baaabbbabac", - Some(7), - Some(11) -); -test_regex!( - basic_81, - r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll", - "XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa", - Some(53), - Some(57) -); -test_regex!(basic_83, r"a*a*a*a*a*b", "aaaaaaaaab", Some(0), Some(10)); -test_regex!(basic_84, r"^", "", Some(0), Some(0)); -test_regex!(basic_85, r"$", "", Some(0), Some(0)); -test_regex!(basic_86, r"^$", "", Some(0), Some(0)); -test_regex!(basic_87, r"^a$", "a", Some(0), Some(1)); -test_regex!(basic_88, r"abc", "abc", Some(0), Some(3)); -test_regex!(basic_89, r"abc", "xabcy", Some(1), Some(4)); -test_regex!(basic_90, r"abc", "ababc", Some(2), Some(5)); -test_regex!(basic_91, r"ab*c", "abc", Some(0), Some(3)); -test_regex!(basic_92, r"ab*bc", "abc", Some(0), Some(3)); -test_regex!(basic_93, r"ab*bc", "abbc", Some(0), Some(4)); -test_regex!(basic_94, r"ab*bc", "abbbbc", Some(0), Some(6)); -test_regex!(basic_95, r"ab+bc", "abbc", Some(0), Some(4)); -test_regex!(basic_96, r"ab+bc", "abbbbc", Some(0), Some(6)); -test_regex!(basic_97, r"ab?bc", "abbc", Some(0), Some(4)); -test_regex!(basic_98, r"ab?bc", "abc", Some(0), Some(3)); -test_regex!(basic_99, r"ab?c", "abc", Some(0), Some(3)); -test_regex!(basic_100, r"^abc$", "abc", Some(0), Some(3)); -test_regex!(basic_101, r"^abc", "abcc", Some(0), Some(3)); -test_regex!(basic_102, r"abc$", "aabc", Some(1), Some(4)); -test_regex!(basic_103, r"^", "abc", Some(0), Some(0)); -test_regex!(basic_104, r"$", "abc", Some(3), Some(3)); -test_regex!(basic_105, r"a.c", "abc", Some(0), Some(3)); -test_regex!(basic_106, r"a.c", "axc", Some(0), Some(3)); -test_regex!(basic_107, r"a.*c", "axyzc", Some(0), Some(5)); -test_regex!(basic_108, r"a[bc]d", "abd", Some(0), Some(3)); -test_regex!(basic_109, r"a[b-d]e", "ace", Some(0), Some(3)); -test_regex!(basic_110, r"a[b-d]", "aac", Some(1), Some(3)); -test_regex!(basic_111, r"a[-b]", "a-", Some(0), Some(2)); -test_regex!(basic_112, r"a[b-]", "a-", Some(0), Some(2)); -test_regex!(basic_113, r"a]", "a]", Some(0), Some(2)); -test_regex!(basic_114, r"a[]]b", "a]b", Some(0), Some(3)); -test_regex!(basic_115, r"a[^bc]d", "aed", Some(0), Some(3)); -test_regex!(basic_116, r"a[^-b]c", "adc", Some(0), Some(3)); -test_regex!(basic_117, r"a[^]b]c", "adc", Some(0), Some(3)); -test_regex!(basic_118, r"ab|cd", "abc", Some(0), Some(2)); -test_regex!(basic_119, r"ab|cd", "abcd", Some(0), Some(2)); -test_regex!(basic_120, r"a\(b", "a(b", Some(0), Some(3)); -test_regex!(basic_121, r"a\(*b", "ab", Some(0), Some(2)); -test_regex!(basic_122, r"a\(*b", "a((b", Some(0), Some(4)); -test_regex!( - basic_123, - r"((a))", - "abc", - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - basic_124, - r"(a)b(c)", - "abc", - Some(0), - Some(3), - Some(0), - Some(1), - Some(2), - Some(3) -); -test_regex!(basic_125, r"a+b+c", "aabbabc", Some(4), Some(7)); -test_regex!(basic_126, r"a*", "aaa", Some(0), Some(3)); -test_regex!(basic_128, r"(a*)*", "-", Some(0), Some(0), None, None); -test_regex!(basic_129, r"(a*)+", "-", Some(0), Some(0), Some(0), Some(0)); -test_regex!(basic_131, r"(a*|b)*", "-", Some(0), Some(0), None, None); -test_regex!( - basic_132, - r"(a+|b)*", - "ab", - Some(0), - Some(2), - Some(1), - Some(2) -); -test_regex!( - basic_133, - r"(a+|b)+", - "ab", - Some(0), - Some(2), - Some(1), - Some(2) -); -test_regex!( - basic_134, - r"(a+|b)?", - "ab", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!(basic_135, r"[^ab]*", "cde", Some(0), Some(3)); -test_regex!(basic_137, r"(^)*", "-", Some(0), Some(0), None, None); -test_regex!(basic_138, r"a*", "", Some(0), Some(0)); -test_regex!( - basic_139, - r"([abc])*d", - "abbbcd", - Some(0), - Some(6), - Some(4), - Some(5) -); -test_regex!( - basic_140, - r"([abc])*bcd", - "abcd", - Some(0), - Some(4), - Some(0), - Some(1) -); -test_regex!(basic_141, r"a|b|c|d|e", "e", Some(0), Some(1)); -test_regex!( - basic_142, - r"(a|b|c|d|e)f", - "ef", - Some(0), - Some(2), - Some(0), - Some(1) -); -test_regex!( - basic_144, - r"((a*|b))*", - "-", - Some(0), - Some(0), - None, - None, - None, - None -); -test_regex!(basic_145, r"abcd*efg", "abcdefg", Some(0), Some(7)); -test_regex!(basic_146, r"ab*", "xabyabbbz", Some(1), Some(3)); -test_regex!(basic_147, r"ab*", "xayabbbz", Some(1), Some(2)); -test_regex!( - basic_148, - r"(ab|cd)e", - "abcde", - Some(2), - Some(5), - Some(2), - Some(4) -); -test_regex!(basic_149, r"[abhgefdc]ij", "hij", Some(0), Some(3)); -test_regex!( - basic_150, - r"(a|b)c*d", - "abcd", - Some(1), - Some(4), - Some(1), - Some(2) -); -test_regex!( - basic_151, - r"(ab|ab*)bc", - "abc", - Some(0), - Some(3), - Some(0), - Some(1) -); -test_regex!( - basic_152, - r"a([bc]*)c*", - "abc", - Some(0), - Some(3), - Some(1), - Some(3) -); -test_regex!( - basic_153, - r"a([bc]*)(c*d)", - "abcd", - Some(0), - Some(4), - Some(1), - Some(3), - Some(3), - Some(4) -); -test_regex!( - basic_154, - r"a([bc]+)(c*d)", - "abcd", - Some(0), - Some(4), - Some(1), - Some(3), - Some(3), - Some(4) -); -test_regex!( - basic_155, - r"a([bc]*)(c+d)", - "abcd", - Some(0), - Some(4), - Some(1), - Some(2), - Some(2), - Some(4) -); -test_regex!(basic_156, r"a[bcd]*dcdcde", "adcdcde", Some(0), Some(7)); -test_regex!( - basic_157, - r"(ab|a)b*c", - "abc", - Some(0), - Some(3), - Some(0), - Some(2) -); -test_regex!( - basic_158, - r"((a)(b)c)(d)", - "abcd", - Some(0), - Some(4), - Some(0), - Some(3), - Some(0), - Some(1), - Some(1), - Some(2), - Some(3), - Some(4) -); -test_regex!( - basic_159, - r"[A-Za-z_][A-Za-z0-9_]*", - "alpha", - Some(0), - Some(5) -); -test_regex!(basic_160, r"^a(bc+|b[eh])g|.h$", "abh", Some(1), Some(3)); -test_regex!( - basic_161, - r"(bc+d$|ef*g.|h?i(j|k))", - "effgz", - Some(0), - Some(5), - Some(0), - Some(5) -); -test_regex!( - basic_162, - r"(bc+d$|ef*g.|h?i(j|k))", - "ij", - Some(0), - Some(2), - Some(0), - Some(2), - Some(1), - Some(2) -); -test_regex!( - basic_163, - r"(bc+d$|ef*g.|h?i(j|k))", - "reffgz", - Some(1), - Some(6), - Some(1), - Some(6) -); -test_regex!( - basic_164, - r"(((((((((a)))))))))", - "a", - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - basic_165, - r"multiple words", - "multiple words yeah", - Some(0), - Some(14) -); -test_regex!( - basic_166, - r"(.*)c(.*)", - "abcde", - Some(0), - Some(5), - Some(0), - Some(2), - Some(3), - Some(5) -); -test_regex!(basic_167, r"abcd", "abcd", Some(0), Some(4)); -test_regex!( - basic_168, - r"a(bc)d", - "abcd", - Some(0), - Some(4), - Some(1), - Some(3) -); -test_regex!(basic_169, r"a[-]?c", "ac", Some(0), Some(3)); -test_regex!( - basic_170, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Qaddafi", - Some(0), - Some(15), - None, - None, - Some(10), - Some(12) -); -test_regex!( - basic_171, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Mo'ammar Gadhafi", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_172, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Kaddafi", - Some(0), - Some(15), - None, - None, - Some(10), - Some(12) -); -test_regex!( - basic_173, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Qadhafi", - Some(0), - Some(15), - None, - None, - Some(10), - Some(12) -); -test_regex!( - basic_174, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Gadafi", - Some(0), - Some(14), - None, - None, - Some(10), - Some(11) -); -test_regex!( - basic_175, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Mu'ammar Qadafi", - Some(0), - Some(15), - None, - None, - Some(11), - Some(12) -); -test_regex!( - basic_176, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Moamar Gaddafi", - Some(0), - Some(14), - None, - None, - Some(9), - Some(11) -); -test_regex!( - basic_177, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Mu'ammar Qadhdhafi", - Some(0), - Some(18), - None, - None, - Some(13), - Some(15) -); -test_regex!( - basic_178, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Khaddafi", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_179, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Ghaddafy", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_180, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Ghadafi", - Some(0), - Some(15), - None, - None, - Some(11), - Some(12) -); -test_regex!( - basic_181, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Ghaddafi", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_182, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muamar Kaddafi", - Some(0), - Some(14), - None, - None, - Some(9), - Some(11) -); -test_regex!( - basic_183, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Quathafi", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_184, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Muammar Gheddafi", - Some(0), - Some(16), - None, - None, - Some(11), - Some(13) -); -test_regex!( - basic_185, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Moammar Khadafy", - Some(0), - Some(15), - None, - None, - Some(11), - Some(12) -); -test_regex!( - basic_186, - r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", - "Moammar Qudhafi", - Some(0), - Some(15), - None, - None, - Some(10), - Some(12) -); -test_regex!( - basic_187, - r"a+(b|c)*d+", - "aabcdd", - Some(0), - Some(6), - Some(3), - Some(4) -); -test_regex!(basic_188, r"^.+$", "vivi", Some(0), Some(4)); -test_regex!( - basic_189, - r"^(.+)$", - "vivi", - Some(0), - Some(4), - Some(0), - Some(4) -); -test_regex!( - basic_190, - r"^([^!.]+).att.com!(.+)$", - "gryphon.att.com!eby", - Some(0), - Some(19), - Some(0), - Some(7), - Some(16), - Some(19) -); -test_regex!( - basic_191, - r"^([^!]+!)?([^!]+)$", - "bas", - Some(0), - Some(3), - None, - None, - Some(0), - Some(3) -); -test_regex!( - basic_192, - r"^([^!]+!)?([^!]+)$", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_193, - r"^([^!]+!)?([^!]+)$", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_194, - r"^.+!([^!]+!)([^!]+)$", - "foo!bar!bas", - Some(0), - Some(11), - Some(4), - Some(8), - Some(8), - Some(11) -); -test_regex!( - basic_195, - r"((foo)|(bar))!bas", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(3), - None, - None, - Some(0), - Some(3) -); -test_regex!( - basic_196, - r"((foo)|(bar))!bas", - "foo!bar!bas", - Some(4), - Some(11), - Some(4), - Some(7), - None, - None, - Some(4), - Some(7) -); -test_regex!( - basic_197, - r"((foo)|(bar))!bas", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(3), - Some(0), - Some(3) -); -test_regex!( - basic_198, - r"((foo)|bar)!bas", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(3) -); -test_regex!( - basic_199, - r"((foo)|bar)!bas", - "foo!bar!bas", - Some(4), - Some(11), - Some(4), - Some(7) -); -test_regex!( - basic_200, - r"((foo)|bar)!bas", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(3), - Some(0), - Some(3) -); -test_regex!( - basic_201, - r"(foo|(bar))!bas", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(3), - Some(0), - Some(3) -); -test_regex!( - basic_202, - r"(foo|(bar))!bas", - "foo!bar!bas", - Some(4), - Some(11), - Some(4), - Some(7), - Some(4), - Some(7) -); -test_regex!( - basic_203, - r"(foo|(bar))!bas", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(3) -); -test_regex!( - basic_204, - r"(foo|bar)!bas", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(3) -); -test_regex!( - basic_205, - r"(foo|bar)!bas", - "foo!bar!bas", - Some(4), - Some(11), - Some(4), - Some(7) -); -test_regex!( - basic_206, - r"(foo|bar)!bas", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(3) -); -test_regex!( - basic_207, - r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", - "foo!bar!bas", - Some(0), - Some(11), - Some(0), - Some(11), - None, - None, - None, - None, - Some(4), - Some(8), - Some(8), - Some(11) -); -test_regex!( - basic_208, - r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", - "bas", - Some(0), - Some(3), - None, - None, - Some(0), - Some(3) -); -test_regex!( - basic_209, - r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_210, - r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", - "foo!bar!bas", - Some(0), - Some(11), - None, - None, - None, - None, - Some(4), - Some(8), - Some(8), - Some(11) -); -test_regex!( - basic_211, - r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_212, - r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", - "bas", - Some(0), - Some(3), - Some(0), - Some(3), - None, - None, - Some(0), - Some(3) -); -test_regex!( - basic_213, - r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", - "bar!bas", - Some(0), - Some(7), - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_214, - r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", - "foo!bar!bas", - Some(0), - Some(11), - Some(0), - Some(11), - None, - None, - None, - None, - Some(4), - Some(8), - Some(8), - Some(11) -); -test_regex!( - basic_215, - r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", - "foo!bas", - Some(0), - Some(7), - Some(0), - Some(7), - Some(0), - Some(4), - Some(4), - Some(7) -); -test_regex!( - basic_216, - r".*(/XXX).*", - "/XXX", - Some(0), - Some(4), - Some(0), - Some(4) -); -test_regex!( - basic_217, - r".*(\\XXX).*", - "\\XXX", - Some(0), - Some(4), - Some(0), - Some(4) -); -test_regex!(basic_218, r"\\XXX", "\\XXX", Some(0), Some(4)); -test_regex!( - basic_219, - r".*(/000).*", - "/000", - Some(0), - Some(4), - Some(0), - Some(4) -); -test_regex!( - basic_220, - r".*(\\000).*", - "\\000", - Some(0), - Some(4), - Some(0), - Some(4) -); -test_regex!(basic_221, r"\\000", "\\000", Some(0), Some(4)); diff --git a/vendor/makepad/libs/regex/src/tests/mod.rs b/vendor/makepad/libs/regex/src/tests/mod.rs deleted file mode 100644 index 4ed24ed..0000000 --- a/vendor/makepad/libs/regex/src/tests/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -macro_rules! test_regex { - ($name:ident, $pattern:expr, $str:expr, $($pos:tt)+) => ( - #[test] - fn $name() { - use crate::regex::Regex; - - let regex = Regex::new($pattern).unwrap(); - let str = $str; - let expected: Vec> = vec![$($pos)+]; - let mut actual = vec![None; expected.len()]; - regex.run(str, &mut actual); - assert_eq!(expected, actual); - } - ); -} - -mod basic; -mod nullsubexpr; -mod repetitions; diff --git a/vendor/makepad/libs/regex/src/tests/nullsubexpr.rs b/vendor/makepad/libs/regex/src/tests/nullsubexpr.rs deleted file mode 100644 index 06d239d..0000000 --- a/vendor/makepad/libs/regex/src/tests/nullsubexpr.rs +++ /dev/null @@ -1,446 +0,0 @@ -//! Generated by make_fowler_tests.py - -test_regex!( - nullsubexpr_3, - r"(a*)*", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!(nullsubexpr_5, r"(a*)*", "x", Some(0), Some(0), None, None); -test_regex!( - nullsubexpr_6, - r"(a*)*", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_7, - r"(a*)*", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_8, - r"(a*)+", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_9, - r"(a*)+", - "x", - Some(0), - Some(0), - Some(0), - Some(0) -); -test_regex!( - nullsubexpr_10, - r"(a*)+", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_11, - r"(a*)+", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_12, - r"(a+)*", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!(nullsubexpr_13, r"(a+)*", "x", Some(0), Some(0)); -test_regex!( - nullsubexpr_14, - r"(a+)*", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_15, - r"(a+)*", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_16, - r"(a+)+", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!(nullsubexpr_17, r"(a+)+", "x", None, None); -test_regex!( - nullsubexpr_18, - r"(a+)+", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_19, - r"(a+)+", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_21, - r"([a]*)*", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_23, - r"([a]*)*", - "x", - Some(0), - Some(0), - None, - None -); -test_regex!( - nullsubexpr_24, - r"([a]*)*", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_25, - r"([a]*)*", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_26, - r"([a]*)+", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_27, - r"([a]*)+", - "x", - Some(0), - Some(0), - Some(0), - Some(0) -); -test_regex!( - nullsubexpr_28, - r"([a]*)+", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_29, - r"([a]*)+", - "aaaaaax", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_30, - r"([^b]*)*", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_32, - r"([^b]*)*", - "b", - Some(0), - Some(0), - None, - None -); -test_regex!( - nullsubexpr_33, - r"([^b]*)*", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_34, - r"([^b]*)*", - "aaaaaab", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_35, - r"([ab]*)*", - "a", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_36, - r"([ab]*)*", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_37, - r"([ab]*)*", - "ababab", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_38, - r"([ab]*)*", - "bababa", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_39, - r"([ab]*)*", - "b", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_40, - r"([ab]*)*", - "bbbbbb", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_41, - r"([ab]*)*", - "aaaabcde", - Some(0), - Some(5), - Some(0), - Some(5) -); -test_regex!( - nullsubexpr_42, - r"([^a]*)*", - "b", - Some(0), - Some(1), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_43, - r"([^a]*)*", - "bbbbbb", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_45, - r"([^a]*)*", - "aaaaaa", - Some(0), - Some(0), - None, - None -); -test_regex!( - nullsubexpr_46, - r"([^ab]*)*", - "ccccxx", - Some(0), - Some(6), - Some(0), - Some(6) -); -test_regex!( - nullsubexpr_48, - r"([^ab]*)*", - "ababab", - Some(0), - Some(0), - None, - None -); -test_regex!( - nullsubexpr_50, - r"((z)+|a)*", - "zabcde", - Some(0), - Some(2), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_69, - r"(a*)*(x)", - "x", - Some(0), - Some(1), - None, - None, - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_70, - r"(a*)*(x)", - "ax", - Some(0), - Some(2), - Some(0), - Some(1), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_71, - r"(a*)*(x)", - "axa", - Some(0), - Some(2), - Some(0), - Some(1), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_73, - r"(a*)+(x)", - "x", - Some(0), - Some(1), - Some(0), - Some(0), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_74, - r"(a*)+(x)", - "ax", - Some(0), - Some(2), - Some(0), - Some(1), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_75, - r"(a*)+(x)", - "axa", - Some(0), - Some(2), - Some(0), - Some(1), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_77, - r"(a*){2}(x)", - "x", - Some(0), - Some(1), - Some(0), - Some(0), - Some(0), - Some(1) -); -test_regex!( - nullsubexpr_78, - r"(a*){2}(x)", - "ax", - Some(0), - Some(2), - Some(1), - Some(1), - Some(1), - Some(2) -); -test_regex!( - nullsubexpr_79, - r"(a*){2}(x)", - "axa", - Some(0), - Some(2), - Some(1), - Some(1), - Some(1), - Some(2) -); diff --git a/vendor/makepad/libs/regex/src/tests/repetitions.rs b/vendor/makepad/libs/regex/src/tests/repetitions.rs deleted file mode 100644 index 6ebd2f7..0000000 --- a/vendor/makepad/libs/regex/src/tests/repetitions.rs +++ /dev/null @@ -1,989 +0,0 @@ -//! Generated by make_fowler_tests.py - -test_regex!(repetitions_10, r"((..)|(.))", "", None, None); -test_regex!(repetitions_11, r"((..)|(.))((..)|(.))", "", None, None); -test_regex!( - repetitions_12, - r"((..)|(.))((..)|(.))((..)|(.))", - "", - None, - None -); -test_regex!(repetitions_14, r"((..)|(.)){1}", "", None, None); -test_regex!(repetitions_15, r"((..)|(.)){2}", "", None, None); -test_regex!(repetitions_16, r"((..)|(.)){3}", "", None, None); -test_regex!(repetitions_18, r"((..)|(.))*", "", Some(0), Some(0)); -test_regex!( - repetitions_20, - r"((..)|(.))", - "a", - Some(0), - Some(1), - Some(0), - Some(1), - None, - None, - Some(0), - Some(1) -); -test_regex!(repetitions_21, r"((..)|(.))((..)|(.))", "a", None, None); -test_regex!( - repetitions_22, - r"((..)|(.))((..)|(.))((..)|(.))", - "a", - None, - None -); -test_regex!( - repetitions_24, - r"((..)|(.)){1}", - "a", - Some(0), - Some(1), - Some(0), - Some(1), - None, - None, - Some(0), - Some(1) -); -test_regex!(repetitions_25, r"((..)|(.)){2}", "a", None, None); -test_regex!(repetitions_26, r"((..)|(.)){3}", "a", None, None); -test_regex!( - repetitions_28, - r"((..)|(.))*", - "a", - Some(0), - Some(1), - Some(0), - Some(1), - None, - None, - Some(0), - Some(1) -); -test_regex!( - repetitions_30, - r"((..)|(.))", - "aa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_31, - r"((..)|(.))((..)|(.))", - "aa", - Some(0), - Some(2), - Some(0), - Some(1), - None, - None, - Some(0), - Some(1), - Some(1), - Some(2), - None, - None, - Some(1), - Some(2) -); -test_regex!( - repetitions_32, - r"((..)|(.))((..)|(.))((..)|(.))", - "aa", - None, - None -); -test_regex!( - repetitions_34, - r"((..)|(.)){1}", - "aa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_35, - r"((..)|(.)){2}", - "aa", - Some(0), - Some(2), - Some(1), - Some(2), - None, - None, - Some(1), - Some(2) -); -test_regex!(repetitions_36, r"((..)|(.)){3}", "aa", None, None); -test_regex!( - repetitions_38, - r"((..)|(.))*", - "aa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_40, - r"((..)|(.))", - "aaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_41, - r"((..)|(.))((..)|(.))", - "aaa", - Some(0), - Some(3), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(3), - None, - None, - Some(2), - Some(3) -); -test_regex!( - repetitions_42, - r"((..)|(.))((..)|(.))((..)|(.))", - "aaa", - Some(0), - Some(3), - Some(0), - Some(1), - None, - None, - Some(0), - Some(1), - Some(1), - Some(2), - None, - None, - Some(1), - Some(2), - Some(2), - Some(3), - None, - None, - Some(2), - Some(3) -); -test_regex!( - repetitions_44, - r"((..)|(.)){1}", - "aaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_46, - r"((..)|(.)){2}", - "aaa", - Some(0), - Some(3), - Some(2), - Some(3), - Some(0), - Some(2), - Some(2), - Some(3) -); -test_regex!( - repetitions_47, - r"((..)|(.)){3}", - "aaa", - Some(0), - Some(3), - Some(2), - Some(3), - None, - None, - Some(2), - Some(3) -); -test_regex!( - repetitions_50, - r"((..)|(.))*", - "aaa", - Some(0), - Some(3), - Some(2), - Some(3), - Some(0), - Some(2), - Some(2), - Some(3) -); -test_regex!( - repetitions_52, - r"((..)|(.))", - "aaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_53, - r"((..)|(.))((..)|(.))", - "aaaa", - Some(0), - Some(4), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_54, - r"((..)|(.))((..)|(.))((..)|(.))", - "aaaa", - Some(0), - Some(4), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(3), - None, - None, - Some(2), - Some(3), - Some(3), - Some(4), - None, - None, - Some(3), - Some(4) -); -test_regex!( - repetitions_56, - r"((..)|(.)){1}", - "aaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_57, - r"((..)|(.)){2}", - "aaaa", - Some(0), - Some(4), - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_59, - r"((..)|(.)){3}", - "aaaa", - Some(0), - Some(4), - Some(3), - Some(4), - Some(0), - Some(2), - Some(3), - Some(4) -); -test_regex!( - repetitions_61, - r"((..)|(.))*", - "aaaa", - Some(0), - Some(4), - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_63, - r"((..)|(.))", - "aaaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_64, - r"((..)|(.))((..)|(.))", - "aaaaa", - Some(0), - Some(4), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_65, - r"((..)|(.))((..)|(.))((..)|(.))", - "aaaaa", - Some(0), - Some(5), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(4), - Some(2), - Some(4), - None, - None, - Some(4), - Some(5), - None, - None, - Some(4), - Some(5) -); -test_regex!( - repetitions_67, - r"((..)|(.)){1}", - "aaaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_68, - r"((..)|(.)){2}", - "aaaaa", - Some(0), - Some(4), - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_70, - r"((..)|(.)){3}", - "aaaaa", - Some(0), - Some(5), - Some(4), - Some(5), - Some(2), - Some(4), - Some(4), - Some(5) -); -test_regex!( - repetitions_73, - r"((..)|(.))*", - "aaaaa", - Some(0), - Some(5), - Some(4), - Some(5), - Some(2), - Some(4), - Some(4), - Some(5) -); -test_regex!( - repetitions_75, - r"((..)|(.))", - "aaaaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_76, - r"((..)|(.))((..)|(.))", - "aaaaaa", - Some(0), - Some(4), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_77, - r"((..)|(.))((..)|(.))((..)|(.))", - "aaaaaa", - Some(0), - Some(6), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None, - Some(2), - Some(4), - Some(2), - Some(4), - None, - None, - Some(4), - Some(6), - Some(4), - Some(6), - None, - None -); -test_regex!( - repetitions_79, - r"((..)|(.)){1}", - "aaaaaa", - Some(0), - Some(2), - Some(0), - Some(2), - Some(0), - Some(2), - None, - None -); -test_regex!( - repetitions_80, - r"((..)|(.)){2}", - "aaaaaa", - Some(0), - Some(4), - Some(2), - Some(4), - Some(2), - Some(4), - None, - None -); -test_regex!( - repetitions_81, - r"((..)|(.)){3}", - "aaaaaa", - Some(0), - Some(6), - Some(4), - Some(6), - Some(4), - Some(6), - None, - None -); -test_regex!( - repetitions_83, - r"((..)|(.))*", - "aaaaaa", - Some(0), - Some(6), - Some(4), - Some(6), - Some(4), - Some(6), - None, - None -); -test_regex!( - repetitions_90, - r"X(.?){0,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_91, - r"X(.?){1,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_92, - r"X(.?){2,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_93, - r"X(.?){3,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_94, - r"X(.?){4,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_95, - r"X(.?){5,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_96, - r"X(.?){6,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_97, - r"X(.?){7,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(7), - Some(8) -); -test_regex!( - repetitions_98, - r"X(.?){8,}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_100, - r"X(.?){0,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_102, - r"X(.?){1,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_104, - r"X(.?){2,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_106, - r"X(.?){3,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_108, - r"X(.?){4,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_110, - r"X(.?){5,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_112, - r"X(.?){6,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_114, - r"X(.?){7,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_115, - r"X(.?){8,8}Y", - "X1234567Y", - Some(0), - Some(9), - Some(8), - Some(8) -); -test_regex!( - repetitions_126, - r"(a|ab|c|bcd){0,}(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_127, - r"(a|ab|c|bcd){1,}(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_128, - r"(a|ab|c|bcd){2,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(3), - Some(6), - Some(6), - Some(6) -); -test_regex!( - repetitions_129, - r"(a|ab|c|bcd){3,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(3), - Some(6), - Some(6), - Some(6) -); -test_regex!( - repetitions_130, - r"(a|ab|c|bcd){4,}(d*)", - "ababcd", - None, - None -); -test_regex!( - repetitions_131, - r"(a|ab|c|bcd){0,10}(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_132, - r"(a|ab|c|bcd){1,10}(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_133, - r"(a|ab|c|bcd){2,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(3), - Some(6), - Some(6), - Some(6) -); -test_regex!( - repetitions_134, - r"(a|ab|c|bcd){3,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(3), - Some(6), - Some(6), - Some(6) -); -test_regex!( - repetitions_135, - r"(a|ab|c|bcd){4,10}(d*)", - "ababcd", - None, - None -); -test_regex!( - repetitions_136, - r"(a|ab|c|bcd)*(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_137, - r"(a|ab|c|bcd)+(d*)", - "ababcd", - Some(0), - Some(1), - Some(0), - Some(1), - Some(1), - Some(1) -); -test_regex!( - repetitions_143, - r"(ab|a|c|bcd){0,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_145, - r"(ab|a|c|bcd){1,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_147, - r"(ab|a|c|bcd){2,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_149, - r"(ab|a|c|bcd){3,}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_150, - r"(ab|a|c|bcd){4,}(d*)", - "ababcd", - None, - None -); -test_regex!( - repetitions_152, - r"(ab|a|c|bcd){0,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_154, - r"(ab|a|c|bcd){1,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_156, - r"(ab|a|c|bcd){2,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_158, - r"(ab|a|c|bcd){3,10}(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_159, - r"(ab|a|c|bcd){4,10}(d*)", - "ababcd", - None, - None -); -test_regex!( - repetitions_161, - r"(ab|a|c|bcd)*(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); -test_regex!( - repetitions_163, - r"(ab|a|c|bcd)+(d*)", - "ababcd", - Some(0), - Some(6), - Some(4), - Some(5), - Some(5), - Some(6) -); diff --git a/vendor/makepad/libs/regex/src/unicode.rs b/vendor/makepad/libs/regex/src/unicode.rs deleted file mode 100644 index 2fbd030..0000000 --- a/vendor/makepad/libs/regex/src/unicode.rs +++ /dev/null @@ -1,6833 +0,0 @@ -//! Generated by make_unicode.py - -use super::range::Range; - -pub static ALNUM: [Range; 760] = [ - Range::new('\u{30}', '\u{39}'), - Range::new('\u{41}', '\u{5A}'), - Range::new('\u{61}', '\u{7A}'), - Range::new('\u{AA}', '\u{AA}'), - Range::new('\u{B5}', '\u{B5}'), - Range::new('\u{BA}', '\u{BA}'), - Range::new('\u{C0}', '\u{D6}'), - Range::new('\u{D8}', '\u{F6}'), - Range::new('\u{F8}', '\u{2C1}'), - Range::new('\u{2C6}', '\u{2D1}'), - Range::new('\u{2E0}', '\u{2E4}'), - Range::new('\u{2EC}', '\u{2EC}'), - Range::new('\u{2EE}', '\u{2EE}'), - Range::new('\u{345}', '\u{345}'), - Range::new('\u{370}', '\u{374}'), - Range::new('\u{376}', '\u{377}'), - Range::new('\u{37A}', '\u{37D}'), - Range::new('\u{37F}', '\u{37F}'), - Range::new('\u{386}', '\u{386}'), - Range::new('\u{388}', '\u{38A}'), - Range::new('\u{38C}', '\u{38C}'), - Range::new('\u{38E}', '\u{3A1}'), - Range::new('\u{3A3}', '\u{3F5}'), - Range::new('\u{3F7}', '\u{481}'), - Range::new('\u{48A}', '\u{52F}'), - Range::new('\u{531}', '\u{556}'), - Range::new('\u{559}', '\u{559}'), - Range::new('\u{560}', '\u{588}'), - Range::new('\u{5B0}', '\u{5BD}'), - Range::new('\u{5BF}', '\u{5BF}'), - Range::new('\u{5C1}', '\u{5C2}'), - Range::new('\u{5C4}', '\u{5C5}'), - Range::new('\u{5C7}', '\u{5C7}'), - Range::new('\u{5D0}', '\u{5EA}'), - Range::new('\u{5EF}', '\u{5F2}'), - Range::new('\u{610}', '\u{61A}'), - Range::new('\u{620}', '\u{657}'), - Range::new('\u{659}', '\u{669}'), - Range::new('\u{66E}', '\u{6D3}'), - Range::new('\u{6D5}', '\u{6DC}'), - Range::new('\u{6E1}', '\u{6E8}'), - Range::new('\u{6ED}', '\u{6FC}'), - Range::new('\u{6FF}', '\u{6FF}'), - Range::new('\u{710}', '\u{73F}'), - Range::new('\u{74D}', '\u{7B1}'), - Range::new('\u{7C0}', '\u{7EA}'), - Range::new('\u{7F4}', '\u{7F5}'), - Range::new('\u{7FA}', '\u{7FA}'), - Range::new('\u{800}', '\u{817}'), - Range::new('\u{81A}', '\u{82C}'), - Range::new('\u{840}', '\u{858}'), - Range::new('\u{860}', '\u{86A}'), - Range::new('\u{870}', '\u{887}'), - Range::new('\u{889}', '\u{88E}'), - Range::new('\u{8A0}', '\u{8C9}'), - Range::new('\u{8D4}', '\u{8DF}'), - Range::new('\u{8E3}', '\u{8E9}'), - Range::new('\u{8F0}', '\u{93B}'), - Range::new('\u{93D}', '\u{94C}'), - Range::new('\u{94E}', '\u{950}'), - Range::new('\u{955}', '\u{963}'), - Range::new('\u{966}', '\u{96F}'), - Range::new('\u{971}', '\u{983}'), - Range::new('\u{985}', '\u{98C}'), - Range::new('\u{98F}', '\u{990}'), - Range::new('\u{993}', '\u{9A8}'), - Range::new('\u{9AA}', '\u{9B0}'), - Range::new('\u{9B2}', '\u{9B2}'), - Range::new('\u{9B6}', '\u{9B9}'), - Range::new('\u{9BD}', '\u{9C4}'), - Range::new('\u{9C7}', '\u{9C8}'), - Range::new('\u{9CB}', '\u{9CC}'), - Range::new('\u{9CE}', '\u{9CE}'), - Range::new('\u{9D7}', '\u{9D7}'), - Range::new('\u{9DC}', '\u{9DD}'), - Range::new('\u{9DF}', '\u{9E3}'), - Range::new('\u{9E6}', '\u{9F1}'), - Range::new('\u{9FC}', '\u{9FC}'), - Range::new('\u{A01}', '\u{A03}'), - Range::new('\u{A05}', '\u{A0A}'), - Range::new('\u{A0F}', '\u{A10}'), - Range::new('\u{A13}', '\u{A28}'), - Range::new('\u{A2A}', '\u{A30}'), - Range::new('\u{A32}', '\u{A33}'), - Range::new('\u{A35}', '\u{A36}'), - Range::new('\u{A38}', '\u{A39}'), - Range::new('\u{A3E}', '\u{A42}'), - Range::new('\u{A47}', '\u{A48}'), - Range::new('\u{A4B}', '\u{A4C}'), - Range::new('\u{A51}', '\u{A51}'), - Range::new('\u{A59}', '\u{A5C}'), - Range::new('\u{A5E}', '\u{A5E}'), - Range::new('\u{A66}', '\u{A75}'), - Range::new('\u{A81}', '\u{A83}'), - Range::new('\u{A85}', '\u{A8D}'), - Range::new('\u{A8F}', '\u{A91}'), - Range::new('\u{A93}', '\u{AA8}'), - Range::new('\u{AAA}', '\u{AB0}'), - Range::new('\u{AB2}', '\u{AB3}'), - Range::new('\u{AB5}', '\u{AB9}'), - Range::new('\u{ABD}', '\u{AC5}'), - Range::new('\u{AC7}', '\u{AC9}'), - Range::new('\u{ACB}', '\u{ACC}'), - Range::new('\u{AD0}', '\u{AD0}'), - Range::new('\u{AE0}', '\u{AE3}'), - Range::new('\u{AE6}', '\u{AEF}'), - Range::new('\u{AF9}', '\u{AFC}'), - Range::new('\u{B01}', '\u{B03}'), - Range::new('\u{B05}', '\u{B0C}'), - Range::new('\u{B0F}', '\u{B10}'), - Range::new('\u{B13}', '\u{B28}'), - Range::new('\u{B2A}', '\u{B30}'), - Range::new('\u{B32}', '\u{B33}'), - Range::new('\u{B35}', '\u{B39}'), - Range::new('\u{B3D}', '\u{B44}'), - Range::new('\u{B47}', '\u{B48}'), - Range::new('\u{B4B}', '\u{B4C}'), - Range::new('\u{B56}', '\u{B57}'), - Range::new('\u{B5C}', '\u{B5D}'), - Range::new('\u{B5F}', '\u{B63}'), - Range::new('\u{B66}', '\u{B6F}'), - Range::new('\u{B71}', '\u{B71}'), - Range::new('\u{B82}', '\u{B83}'), - Range::new('\u{B85}', '\u{B8A}'), - Range::new('\u{B8E}', '\u{B90}'), - Range::new('\u{B92}', '\u{B95}'), - Range::new('\u{B99}', '\u{B9A}'), - Range::new('\u{B9C}', '\u{B9C}'), - Range::new('\u{B9E}', '\u{B9F}'), - Range::new('\u{BA3}', '\u{BA4}'), - Range::new('\u{BA8}', '\u{BAA}'), - Range::new('\u{BAE}', '\u{BB9}'), - Range::new('\u{BBE}', '\u{BC2}'), - Range::new('\u{BC6}', '\u{BC8}'), - Range::new('\u{BCA}', '\u{BCC}'), - Range::new('\u{BD0}', '\u{BD0}'), - Range::new('\u{BD7}', '\u{BD7}'), - Range::new('\u{BE6}', '\u{BEF}'), - Range::new('\u{C00}', '\u{C03}'), - Range::new('\u{C05}', '\u{C0C}'), - Range::new('\u{C0E}', '\u{C10}'), - Range::new('\u{C12}', '\u{C28}'), - Range::new('\u{C2A}', '\u{C39}'), - Range::new('\u{C3D}', '\u{C44}'), - Range::new('\u{C46}', '\u{C48}'), - Range::new('\u{C4A}', '\u{C4C}'), - Range::new('\u{C55}', '\u{C56}'), - Range::new('\u{C58}', '\u{C5A}'), - Range::new('\u{C5D}', '\u{C5D}'), - Range::new('\u{C60}', '\u{C63}'), - Range::new('\u{C66}', '\u{C6F}'), - Range::new('\u{C80}', '\u{C83}'), - Range::new('\u{C85}', '\u{C8C}'), - Range::new('\u{C8E}', '\u{C90}'), - Range::new('\u{C92}', '\u{CA8}'), - Range::new('\u{CAA}', '\u{CB3}'), - Range::new('\u{CB5}', '\u{CB9}'), - Range::new('\u{CBD}', '\u{CC4}'), - Range::new('\u{CC6}', '\u{CC8}'), - Range::new('\u{CCA}', '\u{CCC}'), - Range::new('\u{CD5}', '\u{CD6}'), - Range::new('\u{CDD}', '\u{CDE}'), - Range::new('\u{CE0}', '\u{CE3}'), - Range::new('\u{CE6}', '\u{CEF}'), - Range::new('\u{CF1}', '\u{CF2}'), - Range::new('\u{D00}', '\u{D0C}'), - Range::new('\u{D0E}', '\u{D10}'), - Range::new('\u{D12}', '\u{D3A}'), - Range::new('\u{D3D}', '\u{D44}'), - Range::new('\u{D46}', '\u{D48}'), - Range::new('\u{D4A}', '\u{D4C}'), - Range::new('\u{D4E}', '\u{D4E}'), - Range::new('\u{D54}', '\u{D57}'), - Range::new('\u{D5F}', '\u{D63}'), - Range::new('\u{D66}', '\u{D6F}'), - Range::new('\u{D7A}', '\u{D7F}'), - Range::new('\u{D81}', '\u{D83}'), - Range::new('\u{D85}', '\u{D96}'), - Range::new('\u{D9A}', '\u{DB1}'), - Range::new('\u{DB3}', '\u{DBB}'), - Range::new('\u{DBD}', '\u{DBD}'), - Range::new('\u{DC0}', '\u{DC6}'), - Range::new('\u{DCF}', '\u{DD4}'), - Range::new('\u{DD6}', '\u{DD6}'), - Range::new('\u{DD8}', '\u{DDF}'), - Range::new('\u{DE6}', '\u{DEF}'), - Range::new('\u{DF2}', '\u{DF3}'), - Range::new('\u{E01}', '\u{E3A}'), - Range::new('\u{E40}', '\u{E46}'), - Range::new('\u{E4D}', '\u{E4D}'), - Range::new('\u{E50}', '\u{E59}'), - Range::new('\u{E81}', '\u{E82}'), - Range::new('\u{E84}', '\u{E84}'), - Range::new('\u{E86}', '\u{E8A}'), - Range::new('\u{E8C}', '\u{EA3}'), - Range::new('\u{EA5}', '\u{EA5}'), - Range::new('\u{EA7}', '\u{EB9}'), - Range::new('\u{EBB}', '\u{EBD}'), - Range::new('\u{EC0}', '\u{EC4}'), - Range::new('\u{EC6}', '\u{EC6}'), - Range::new('\u{ECD}', '\u{ECD}'), - Range::new('\u{ED0}', '\u{ED9}'), - Range::new('\u{EDC}', '\u{EDF}'), - Range::new('\u{F00}', '\u{F00}'), - Range::new('\u{F20}', '\u{F29}'), - Range::new('\u{F40}', '\u{F47}'), - Range::new('\u{F49}', '\u{F6C}'), - Range::new('\u{F71}', '\u{F81}'), - Range::new('\u{F88}', '\u{F97}'), - Range::new('\u{F99}', '\u{FBC}'), - Range::new('\u{1000}', '\u{1036}'), - Range::new('\u{1038}', '\u{1038}'), - Range::new('\u{103B}', '\u{1049}'), - Range::new('\u{1050}', '\u{109D}'), - Range::new('\u{10A0}', '\u{10C5}'), - Range::new('\u{10C7}', '\u{10C7}'), - Range::new('\u{10CD}', '\u{10CD}'), - Range::new('\u{10D0}', '\u{10FA}'), - Range::new('\u{10FC}', '\u{1248}'), - Range::new('\u{124A}', '\u{124D}'), - Range::new('\u{1250}', '\u{1256}'), - Range::new('\u{1258}', '\u{1258}'), - Range::new('\u{125A}', '\u{125D}'), - Range::new('\u{1260}', '\u{1288}'), - Range::new('\u{128A}', '\u{128D}'), - Range::new('\u{1290}', '\u{12B0}'), - Range::new('\u{12B2}', '\u{12B5}'), - Range::new('\u{12B8}', '\u{12BE}'), - Range::new('\u{12C0}', '\u{12C0}'), - Range::new('\u{12C2}', '\u{12C5}'), - Range::new('\u{12C8}', '\u{12D6}'), - Range::new('\u{12D8}', '\u{1310}'), - Range::new('\u{1312}', '\u{1315}'), - Range::new('\u{1318}', '\u{135A}'), - Range::new('\u{1380}', '\u{138F}'), - Range::new('\u{13A0}', '\u{13F5}'), - Range::new('\u{13F8}', '\u{13FD}'), - Range::new('\u{1401}', '\u{166C}'), - Range::new('\u{166F}', '\u{167F}'), - Range::new('\u{1681}', '\u{169A}'), - Range::new('\u{16A0}', '\u{16EA}'), - Range::new('\u{16EE}', '\u{16F8}'), - Range::new('\u{1700}', '\u{1713}'), - Range::new('\u{171F}', '\u{1733}'), - Range::new('\u{1740}', '\u{1753}'), - Range::new('\u{1760}', '\u{176C}'), - Range::new('\u{176E}', '\u{1770}'), - Range::new('\u{1772}', '\u{1773}'), - Range::new('\u{1780}', '\u{17B3}'), - Range::new('\u{17B6}', '\u{17C8}'), - Range::new('\u{17D7}', '\u{17D7}'), - Range::new('\u{17DC}', '\u{17DC}'), - Range::new('\u{17E0}', '\u{17E9}'), - Range::new('\u{1810}', '\u{1819}'), - Range::new('\u{1820}', '\u{1878}'), - Range::new('\u{1880}', '\u{18AA}'), - Range::new('\u{18B0}', '\u{18F5}'), - Range::new('\u{1900}', '\u{191E}'), - Range::new('\u{1920}', '\u{192B}'), - Range::new('\u{1930}', '\u{1938}'), - Range::new('\u{1946}', '\u{196D}'), - Range::new('\u{1970}', '\u{1974}'), - Range::new('\u{1980}', '\u{19AB}'), - Range::new('\u{19B0}', '\u{19C9}'), - Range::new('\u{19D0}', '\u{19D9}'), - Range::new('\u{1A00}', '\u{1A1B}'), - Range::new('\u{1A20}', '\u{1A5E}'), - Range::new('\u{1A61}', '\u{1A74}'), - Range::new('\u{1A80}', '\u{1A89}'), - Range::new('\u{1A90}', '\u{1A99}'), - Range::new('\u{1AA7}', '\u{1AA7}'), - Range::new('\u{1ABF}', '\u{1AC0}'), - Range::new('\u{1ACC}', '\u{1ACE}'), - Range::new('\u{1B00}', '\u{1B33}'), - Range::new('\u{1B35}', '\u{1B43}'), - Range::new('\u{1B45}', '\u{1B4C}'), - Range::new('\u{1B50}', '\u{1B59}'), - Range::new('\u{1B80}', '\u{1BA9}'), - Range::new('\u{1BAC}', '\u{1BE5}'), - Range::new('\u{1BE7}', '\u{1BF1}'), - Range::new('\u{1C00}', '\u{1C36}'), - Range::new('\u{1C40}', '\u{1C49}'), - Range::new('\u{1C4D}', '\u{1C7D}'), - Range::new('\u{1C80}', '\u{1C88}'), - Range::new('\u{1C90}', '\u{1CBA}'), - Range::new('\u{1CBD}', '\u{1CBF}'), - Range::new('\u{1CE9}', '\u{1CEC}'), - Range::new('\u{1CEE}', '\u{1CF3}'), - Range::new('\u{1CF5}', '\u{1CF6}'), - Range::new('\u{1CFA}', '\u{1CFA}'), - Range::new('\u{1D00}', '\u{1DBF}'), - Range::new('\u{1DE7}', '\u{1DF4}'), - Range::new('\u{1E00}', '\u{1F15}'), - Range::new('\u{1F18}', '\u{1F1D}'), - Range::new('\u{1F20}', '\u{1F45}'), - Range::new('\u{1F48}', '\u{1F4D}'), - Range::new('\u{1F50}', '\u{1F57}'), - Range::new('\u{1F59}', '\u{1F59}'), - Range::new('\u{1F5B}', '\u{1F5B}'), - Range::new('\u{1F5D}', '\u{1F5D}'), - Range::new('\u{1F5F}', '\u{1F7D}'), - Range::new('\u{1F80}', '\u{1FB4}'), - Range::new('\u{1FB6}', '\u{1FBC}'), - Range::new('\u{1FBE}', '\u{1FBE}'), - Range::new('\u{1FC2}', '\u{1FC4}'), - Range::new('\u{1FC6}', '\u{1FCC}'), - Range::new('\u{1FD0}', '\u{1FD3}'), - Range::new('\u{1FD6}', '\u{1FDB}'), - Range::new('\u{1FE0}', '\u{1FEC}'), - Range::new('\u{1FF2}', '\u{1FF4}'), - Range::new('\u{1FF6}', '\u{1FFC}'), - Range::new('\u{2071}', '\u{2071}'), - Range::new('\u{207F}', '\u{207F}'), - Range::new('\u{2090}', '\u{209C}'), - Range::new('\u{2102}', '\u{2102}'), - Range::new('\u{2107}', '\u{2107}'), - Range::new('\u{210A}', '\u{2113}'), - Range::new('\u{2115}', '\u{2115}'), - Range::new('\u{2119}', '\u{211D}'), - Range::new('\u{2124}', '\u{2124}'), - Range::new('\u{2126}', '\u{2126}'), - Range::new('\u{2128}', '\u{2128}'), - Range::new('\u{212A}', '\u{212D}'), - Range::new('\u{212F}', '\u{2139}'), - Range::new('\u{213C}', '\u{213F}'), - Range::new('\u{2145}', '\u{2149}'), - Range::new('\u{214E}', '\u{214E}'), - Range::new('\u{2160}', '\u{2188}'), - Range::new('\u{24B6}', '\u{24E9}'), - Range::new('\u{2C00}', '\u{2CE4}'), - Range::new('\u{2CEB}', '\u{2CEE}'), - Range::new('\u{2CF2}', '\u{2CF3}'), - Range::new('\u{2D00}', '\u{2D25}'), - Range::new('\u{2D27}', '\u{2D27}'), - Range::new('\u{2D2D}', '\u{2D2D}'), - Range::new('\u{2D30}', '\u{2D67}'), - Range::new('\u{2D6F}', '\u{2D6F}'), - Range::new('\u{2D80}', '\u{2D96}'), - Range::new('\u{2DA0}', '\u{2DA6}'), - Range::new('\u{2DA8}', '\u{2DAE}'), - Range::new('\u{2DB0}', '\u{2DB6}'), - Range::new('\u{2DB8}', '\u{2DBE}'), - Range::new('\u{2DC0}', '\u{2DC6}'), - Range::new('\u{2DC8}', '\u{2DCE}'), - Range::new('\u{2DD0}', '\u{2DD6}'), - Range::new('\u{2DD8}', '\u{2DDE}'), - Range::new('\u{2DE0}', '\u{2DFF}'), - Range::new('\u{2E2F}', '\u{2E2F}'), - Range::new('\u{3005}', '\u{3007}'), - Range::new('\u{3021}', '\u{3029}'), - Range::new('\u{3031}', '\u{3035}'), - Range::new('\u{3038}', '\u{303C}'), - Range::new('\u{3041}', '\u{3096}'), - Range::new('\u{309D}', '\u{309F}'), - Range::new('\u{30A1}', '\u{30FA}'), - Range::new('\u{30FC}', '\u{30FF}'), - Range::new('\u{3105}', '\u{312F}'), - Range::new('\u{3131}', '\u{318E}'), - Range::new('\u{31A0}', '\u{31BF}'), - Range::new('\u{31F0}', '\u{31FF}'), - Range::new('\u{3400}', '\u{4DBF}'), - Range::new('\u{4E00}', '\u{A48C}'), - Range::new('\u{A4D0}', '\u{A4FD}'), - Range::new('\u{A500}', '\u{A60C}'), - Range::new('\u{A610}', '\u{A62B}'), - Range::new('\u{A640}', '\u{A66E}'), - Range::new('\u{A674}', '\u{A67B}'), - Range::new('\u{A67F}', '\u{A6EF}'), - Range::new('\u{A717}', '\u{A71F}'), - Range::new('\u{A722}', '\u{A788}'), - Range::new('\u{A78B}', '\u{A7CA}'), - Range::new('\u{A7D0}', '\u{A7D1}'), - Range::new('\u{A7D3}', '\u{A7D3}'), - Range::new('\u{A7D5}', '\u{A7D9}'), - Range::new('\u{A7F2}', '\u{A805}'), - Range::new('\u{A807}', '\u{A827}'), - Range::new('\u{A840}', '\u{A873}'), - Range::new('\u{A880}', '\u{A8C3}'), - Range::new('\u{A8C5}', '\u{A8C5}'), - Range::new('\u{A8D0}', '\u{A8D9}'), - Range::new('\u{A8F2}', '\u{A8F7}'), - Range::new('\u{A8FB}', '\u{A8FB}'), - Range::new('\u{A8FD}', '\u{A92A}'), - Range::new('\u{A930}', '\u{A952}'), - Range::new('\u{A960}', '\u{A97C}'), - Range::new('\u{A980}', '\u{A9B2}'), - Range::new('\u{A9B4}', '\u{A9BF}'), - Range::new('\u{A9CF}', '\u{A9D9}'), - Range::new('\u{A9E0}', '\u{A9FE}'), - Range::new('\u{AA00}', '\u{AA36}'), - Range::new('\u{AA40}', '\u{AA4D}'), - Range::new('\u{AA50}', '\u{AA59}'), - Range::new('\u{AA60}', '\u{AA76}'), - Range::new('\u{AA7A}', '\u{AABE}'), - Range::new('\u{AAC0}', '\u{AAC0}'), - Range::new('\u{AAC2}', '\u{AAC2}'), - Range::new('\u{AADB}', '\u{AADD}'), - Range::new('\u{AAE0}', '\u{AAEF}'), - Range::new('\u{AAF2}', '\u{AAF5}'), - Range::new('\u{AB01}', '\u{AB06}'), - Range::new('\u{AB09}', '\u{AB0E}'), - Range::new('\u{AB11}', '\u{AB16}'), - Range::new('\u{AB20}', '\u{AB26}'), - Range::new('\u{AB28}', '\u{AB2E}'), - Range::new('\u{AB30}', '\u{AB5A}'), - Range::new('\u{AB5C}', '\u{AB69}'), - Range::new('\u{AB70}', '\u{ABEA}'), - Range::new('\u{ABF0}', '\u{ABF9}'), - Range::new('\u{AC00}', '\u{D7A3}'), - Range::new('\u{D7B0}', '\u{D7C6}'), - Range::new('\u{D7CB}', '\u{D7FB}'), - Range::new('\u{F900}', '\u{FA6D}'), - Range::new('\u{FA70}', '\u{FAD9}'), - Range::new('\u{FB00}', '\u{FB06}'), - Range::new('\u{FB13}', '\u{FB17}'), - Range::new('\u{FB1D}', '\u{FB28}'), - Range::new('\u{FB2A}', '\u{FB36}'), - Range::new('\u{FB38}', '\u{FB3C}'), - Range::new('\u{FB3E}', '\u{FB3E}'), - Range::new('\u{FB40}', '\u{FB41}'), - Range::new('\u{FB43}', '\u{FB44}'), - Range::new('\u{FB46}', '\u{FBB1}'), - Range::new('\u{FBD3}', '\u{FD3D}'), - Range::new('\u{FD50}', '\u{FD8F}'), - Range::new('\u{FD92}', '\u{FDC7}'), - Range::new('\u{FDF0}', '\u{FDFB}'), - Range::new('\u{FE70}', '\u{FE74}'), - Range::new('\u{FE76}', '\u{FEFC}'), - Range::new('\u{FF10}', '\u{FF19}'), - Range::new('\u{FF21}', '\u{FF3A}'), - Range::new('\u{FF41}', '\u{FF5A}'), - Range::new('\u{FF66}', '\u{FFBE}'), - Range::new('\u{FFC2}', '\u{FFC7}'), - Range::new('\u{FFCA}', '\u{FFCF}'), - Range::new('\u{FFD2}', '\u{FFD7}'), - Range::new('\u{FFDA}', '\u{FFDC}'), - Range::new('\u{10000}', '\u{1000B}'), - Range::new('\u{1000D}', '\u{10026}'), - Range::new('\u{10028}', '\u{1003A}'), - Range::new('\u{1003C}', '\u{1003D}'), - Range::new('\u{1003F}', '\u{1004D}'), - Range::new('\u{10050}', '\u{1005D}'), - Range::new('\u{10080}', '\u{100FA}'), - Range::new('\u{10140}', '\u{10174}'), - Range::new('\u{10280}', '\u{1029C}'), - Range::new('\u{102A0}', '\u{102D0}'), - Range::new('\u{10300}', '\u{1031F}'), - Range::new('\u{1032D}', '\u{1034A}'), - Range::new('\u{10350}', '\u{1037A}'), - Range::new('\u{10380}', '\u{1039D}'), - Range::new('\u{103A0}', '\u{103C3}'), - Range::new('\u{103C8}', '\u{103CF}'), - Range::new('\u{103D1}', '\u{103D5}'), - Range::new('\u{10400}', '\u{1049D}'), - Range::new('\u{104A0}', '\u{104A9}'), - Range::new('\u{104B0}', '\u{104D3}'), - Range::new('\u{104D8}', '\u{104FB}'), - Range::new('\u{10500}', '\u{10527}'), - Range::new('\u{10530}', '\u{10563}'), - Range::new('\u{10570}', '\u{1057A}'), - Range::new('\u{1057C}', '\u{1058A}'), - Range::new('\u{1058C}', '\u{10592}'), - Range::new('\u{10594}', '\u{10595}'), - Range::new('\u{10597}', '\u{105A1}'), - Range::new('\u{105A3}', '\u{105B1}'), - Range::new('\u{105B3}', '\u{105B9}'), - Range::new('\u{105BB}', '\u{105BC}'), - Range::new('\u{10600}', '\u{10736}'), - Range::new('\u{10740}', '\u{10755}'), - Range::new('\u{10760}', '\u{10767}'), - Range::new('\u{10780}', '\u{10785}'), - Range::new('\u{10787}', '\u{107B0}'), - Range::new('\u{107B2}', '\u{107BA}'), - Range::new('\u{10800}', '\u{10805}'), - Range::new('\u{10808}', '\u{10808}'), - Range::new('\u{1080A}', '\u{10835}'), - Range::new('\u{10837}', '\u{10838}'), - Range::new('\u{1083C}', '\u{1083C}'), - Range::new('\u{1083F}', '\u{10855}'), - Range::new('\u{10860}', '\u{10876}'), - Range::new('\u{10880}', '\u{1089E}'), - Range::new('\u{108E0}', '\u{108F2}'), - Range::new('\u{108F4}', '\u{108F5}'), - Range::new('\u{10900}', '\u{10915}'), - Range::new('\u{10920}', '\u{10939}'), - Range::new('\u{10980}', '\u{109B7}'), - Range::new('\u{109BE}', '\u{109BF}'), - Range::new('\u{10A00}', '\u{10A03}'), - Range::new('\u{10A05}', '\u{10A06}'), - Range::new('\u{10A0C}', '\u{10A13}'), - Range::new('\u{10A15}', '\u{10A17}'), - Range::new('\u{10A19}', '\u{10A35}'), - Range::new('\u{10A60}', '\u{10A7C}'), - Range::new('\u{10A80}', '\u{10A9C}'), - Range::new('\u{10AC0}', '\u{10AC7}'), - Range::new('\u{10AC9}', '\u{10AE4}'), - Range::new('\u{10B00}', '\u{10B35}'), - Range::new('\u{10B40}', '\u{10B55}'), - Range::new('\u{10B60}', '\u{10B72}'), - Range::new('\u{10B80}', '\u{10B91}'), - Range::new('\u{10C00}', '\u{10C48}'), - Range::new('\u{10C80}', '\u{10CB2}'), - Range::new('\u{10CC0}', '\u{10CF2}'), - Range::new('\u{10D00}', '\u{10D27}'), - Range::new('\u{10D30}', '\u{10D39}'), - Range::new('\u{10E80}', '\u{10EA9}'), - Range::new('\u{10EAB}', '\u{10EAC}'), - Range::new('\u{10EB0}', '\u{10EB1}'), - Range::new('\u{10F00}', '\u{10F1C}'), - Range::new('\u{10F27}', '\u{10F27}'), - Range::new('\u{10F30}', '\u{10F45}'), - Range::new('\u{10F70}', '\u{10F81}'), - Range::new('\u{10FB0}', '\u{10FC4}'), - Range::new('\u{10FE0}', '\u{10FF6}'), - Range::new('\u{11000}', '\u{11045}'), - Range::new('\u{11066}', '\u{1106F}'), - Range::new('\u{11071}', '\u{11075}'), - Range::new('\u{11082}', '\u{110B8}'), - Range::new('\u{110C2}', '\u{110C2}'), - Range::new('\u{110D0}', '\u{110E8}'), - Range::new('\u{110F0}', '\u{110F9}'), - Range::new('\u{11100}', '\u{11132}'), - Range::new('\u{11136}', '\u{1113F}'), - Range::new('\u{11144}', '\u{11147}'), - Range::new('\u{11150}', '\u{11172}'), - Range::new('\u{11176}', '\u{11176}'), - Range::new('\u{11180}', '\u{111BF}'), - Range::new('\u{111C1}', '\u{111C4}'), - Range::new('\u{111CE}', '\u{111DA}'), - Range::new('\u{111DC}', '\u{111DC}'), - Range::new('\u{11200}', '\u{11211}'), - Range::new('\u{11213}', '\u{11234}'), - Range::new('\u{11237}', '\u{11237}'), - Range::new('\u{1123E}', '\u{1123E}'), - Range::new('\u{11280}', '\u{11286}'), - Range::new('\u{11288}', '\u{11288}'), - Range::new('\u{1128A}', '\u{1128D}'), - Range::new('\u{1128F}', '\u{1129D}'), - Range::new('\u{1129F}', '\u{112A8}'), - Range::new('\u{112B0}', '\u{112E8}'), - Range::new('\u{112F0}', '\u{112F9}'), - Range::new('\u{11300}', '\u{11303}'), - Range::new('\u{11305}', '\u{1130C}'), - Range::new('\u{1130F}', '\u{11310}'), - Range::new('\u{11313}', '\u{11328}'), - Range::new('\u{1132A}', '\u{11330}'), - Range::new('\u{11332}', '\u{11333}'), - Range::new('\u{11335}', '\u{11339}'), - Range::new('\u{1133D}', '\u{11344}'), - Range::new('\u{11347}', '\u{11348}'), - Range::new('\u{1134B}', '\u{1134C}'), - Range::new('\u{11350}', '\u{11350}'), - Range::new('\u{11357}', '\u{11357}'), - Range::new('\u{1135D}', '\u{11363}'), - Range::new('\u{11400}', '\u{11441}'), - Range::new('\u{11443}', '\u{11445}'), - Range::new('\u{11447}', '\u{1144A}'), - Range::new('\u{11450}', '\u{11459}'), - Range::new('\u{1145F}', '\u{11461}'), - Range::new('\u{11480}', '\u{114C1}'), - Range::new('\u{114C4}', '\u{114C5}'), - Range::new('\u{114C7}', '\u{114C7}'), - Range::new('\u{114D0}', '\u{114D9}'), - Range::new('\u{11580}', '\u{115B5}'), - Range::new('\u{115B8}', '\u{115BE}'), - Range::new('\u{115D8}', '\u{115DD}'), - Range::new('\u{11600}', '\u{1163E}'), - Range::new('\u{11640}', '\u{11640}'), - Range::new('\u{11644}', '\u{11644}'), - Range::new('\u{11650}', '\u{11659}'), - Range::new('\u{11680}', '\u{116B5}'), - Range::new('\u{116B8}', '\u{116B8}'), - Range::new('\u{116C0}', '\u{116C9}'), - Range::new('\u{11700}', '\u{1171A}'), - Range::new('\u{1171D}', '\u{1172A}'), - Range::new('\u{11730}', '\u{11739}'), - Range::new('\u{11740}', '\u{11746}'), - Range::new('\u{11800}', '\u{11838}'), - Range::new('\u{118A0}', '\u{118E9}'), - Range::new('\u{118FF}', '\u{11906}'), - Range::new('\u{11909}', '\u{11909}'), - Range::new('\u{1190C}', '\u{11913}'), - Range::new('\u{11915}', '\u{11916}'), - Range::new('\u{11918}', '\u{11935}'), - Range::new('\u{11937}', '\u{11938}'), - Range::new('\u{1193B}', '\u{1193C}'), - Range::new('\u{1193F}', '\u{11942}'), - Range::new('\u{11950}', '\u{11959}'), - Range::new('\u{119A0}', '\u{119A7}'), - Range::new('\u{119AA}', '\u{119D7}'), - Range::new('\u{119DA}', '\u{119DF}'), - Range::new('\u{119E1}', '\u{119E1}'), - Range::new('\u{119E3}', '\u{119E4}'), - Range::new('\u{11A00}', '\u{11A32}'), - Range::new('\u{11A35}', '\u{11A3E}'), - Range::new('\u{11A50}', '\u{11A97}'), - Range::new('\u{11A9D}', '\u{11A9D}'), - Range::new('\u{11AB0}', '\u{11AF8}'), - Range::new('\u{11C00}', '\u{11C08}'), - Range::new('\u{11C0A}', '\u{11C36}'), - Range::new('\u{11C38}', '\u{11C3E}'), - Range::new('\u{11C40}', '\u{11C40}'), - Range::new('\u{11C50}', '\u{11C59}'), - Range::new('\u{11C72}', '\u{11C8F}'), - Range::new('\u{11C92}', '\u{11CA7}'), - Range::new('\u{11CA9}', '\u{11CB6}'), - Range::new('\u{11D00}', '\u{11D06}'), - Range::new('\u{11D08}', '\u{11D09}'), - Range::new('\u{11D0B}', '\u{11D36}'), - Range::new('\u{11D3A}', '\u{11D3A}'), - Range::new('\u{11D3C}', '\u{11D3D}'), - Range::new('\u{11D3F}', '\u{11D41}'), - Range::new('\u{11D43}', '\u{11D43}'), - Range::new('\u{11D46}', '\u{11D47}'), - Range::new('\u{11D50}', '\u{11D59}'), - Range::new('\u{11D60}', '\u{11D65}'), - Range::new('\u{11D67}', '\u{11D68}'), - Range::new('\u{11D6A}', '\u{11D8E}'), - Range::new('\u{11D90}', '\u{11D91}'), - Range::new('\u{11D93}', '\u{11D96}'), - Range::new('\u{11D98}', '\u{11D98}'), - Range::new('\u{11DA0}', '\u{11DA9}'), - Range::new('\u{11EE0}', '\u{11EF6}'), - Range::new('\u{11FB0}', '\u{11FB0}'), - Range::new('\u{12000}', '\u{12399}'), - Range::new('\u{12400}', '\u{1246E}'), - Range::new('\u{12480}', '\u{12543}'), - Range::new('\u{12F90}', '\u{12FF0}'), - Range::new('\u{13000}', '\u{1342E}'), - Range::new('\u{14400}', '\u{14646}'), - Range::new('\u{16800}', '\u{16A38}'), - Range::new('\u{16A40}', '\u{16A5E}'), - Range::new('\u{16A60}', '\u{16A69}'), - Range::new('\u{16A70}', '\u{16ABE}'), - Range::new('\u{16AC0}', '\u{16AC9}'), - Range::new('\u{16AD0}', '\u{16AED}'), - Range::new('\u{16B00}', '\u{16B2F}'), - Range::new('\u{16B40}', '\u{16B43}'), - Range::new('\u{16B50}', '\u{16B59}'), - Range::new('\u{16B63}', '\u{16B77}'), - Range::new('\u{16B7D}', '\u{16B8F}'), - Range::new('\u{16E40}', '\u{16E7F}'), - Range::new('\u{16F00}', '\u{16F4A}'), - Range::new('\u{16F4F}', '\u{16F87}'), - Range::new('\u{16F8F}', '\u{16F9F}'), - Range::new('\u{16FE0}', '\u{16FE1}'), - Range::new('\u{16FE3}', '\u{16FE3}'), - Range::new('\u{16FF0}', '\u{16FF1}'), - Range::new('\u{17000}', '\u{187F7}'), - Range::new('\u{18800}', '\u{18CD5}'), - Range::new('\u{18D00}', '\u{18D08}'), - Range::new('\u{1AFF0}', '\u{1AFF3}'), - Range::new('\u{1AFF5}', '\u{1AFFB}'), - Range::new('\u{1AFFD}', '\u{1AFFE}'), - Range::new('\u{1B000}', '\u{1B122}'), - Range::new('\u{1B150}', '\u{1B152}'), - Range::new('\u{1B164}', '\u{1B167}'), - Range::new('\u{1B170}', '\u{1B2FB}'), - Range::new('\u{1BC00}', '\u{1BC6A}'), - Range::new('\u{1BC70}', '\u{1BC7C}'), - Range::new('\u{1BC80}', '\u{1BC88}'), - Range::new('\u{1BC90}', '\u{1BC99}'), - Range::new('\u{1BC9E}', '\u{1BC9E}'), - Range::new('\u{1D400}', '\u{1D454}'), - Range::new('\u{1D456}', '\u{1D49C}'), - Range::new('\u{1D49E}', '\u{1D49F}'), - Range::new('\u{1D4A2}', '\u{1D4A2}'), - Range::new('\u{1D4A5}', '\u{1D4A6}'), - Range::new('\u{1D4A9}', '\u{1D4AC}'), - Range::new('\u{1D4AE}', '\u{1D4B9}'), - Range::new('\u{1D4BB}', '\u{1D4BB}'), - Range::new('\u{1D4BD}', '\u{1D4C3}'), - Range::new('\u{1D4C5}', '\u{1D505}'), - Range::new('\u{1D507}', '\u{1D50A}'), - Range::new('\u{1D50D}', '\u{1D514}'), - Range::new('\u{1D516}', '\u{1D51C}'), - Range::new('\u{1D51E}', '\u{1D539}'), - Range::new('\u{1D53B}', '\u{1D53E}'), - Range::new('\u{1D540}', '\u{1D544}'), - Range::new('\u{1D546}', '\u{1D546}'), - Range::new('\u{1D54A}', '\u{1D550}'), - Range::new('\u{1D552}', '\u{1D6A5}'), - Range::new('\u{1D6A8}', '\u{1D6C0}'), - Range::new('\u{1D6C2}', '\u{1D6DA}'), - Range::new('\u{1D6DC}', '\u{1D6FA}'), - Range::new('\u{1D6FC}', '\u{1D714}'), - Range::new('\u{1D716}', '\u{1D734}'), - Range::new('\u{1D736}', '\u{1D74E}'), - Range::new('\u{1D750}', '\u{1D76E}'), - Range::new('\u{1D770}', '\u{1D788}'), - Range::new('\u{1D78A}', '\u{1D7A8}'), - Range::new('\u{1D7AA}', '\u{1D7C2}'), - Range::new('\u{1D7C4}', '\u{1D7CB}'), - Range::new('\u{1D7CE}', '\u{1D7FF}'), - Range::new('\u{1DF00}', '\u{1DF1E}'), - Range::new('\u{1E000}', '\u{1E006}'), - Range::new('\u{1E008}', '\u{1E018}'), - Range::new('\u{1E01B}', '\u{1E021}'), - Range::new('\u{1E023}', '\u{1E024}'), - Range::new('\u{1E026}', '\u{1E02A}'), - Range::new('\u{1E100}', '\u{1E12C}'), - Range::new('\u{1E137}', '\u{1E13D}'), - Range::new('\u{1E140}', '\u{1E149}'), - Range::new('\u{1E14E}', '\u{1E14E}'), - Range::new('\u{1E290}', '\u{1E2AD}'), - Range::new('\u{1E2C0}', '\u{1E2EB}'), - Range::new('\u{1E2F0}', '\u{1E2F9}'), - Range::new('\u{1E7E0}', '\u{1E7E6}'), - Range::new('\u{1E7E8}', '\u{1E7EB}'), - Range::new('\u{1E7ED}', '\u{1E7EE}'), - Range::new('\u{1E7F0}', '\u{1E7FE}'), - Range::new('\u{1E800}', '\u{1E8C4}'), - Range::new('\u{1E900}', '\u{1E943}'), - Range::new('\u{1E947}', '\u{1E947}'), - Range::new('\u{1E94B}', '\u{1E94B}'), - Range::new('\u{1E950}', '\u{1E959}'), - Range::new('\u{1EE00}', '\u{1EE03}'), - Range::new('\u{1EE05}', '\u{1EE1F}'), - Range::new('\u{1EE21}', '\u{1EE22}'), - Range::new('\u{1EE24}', '\u{1EE24}'), - Range::new('\u{1EE27}', '\u{1EE27}'), - Range::new('\u{1EE29}', '\u{1EE32}'), - Range::new('\u{1EE34}', '\u{1EE37}'), - Range::new('\u{1EE39}', '\u{1EE39}'), - Range::new('\u{1EE3B}', '\u{1EE3B}'), - Range::new('\u{1EE42}', '\u{1EE42}'), - Range::new('\u{1EE47}', '\u{1EE47}'), - Range::new('\u{1EE49}', '\u{1EE49}'), - Range::new('\u{1EE4B}', '\u{1EE4B}'), - Range::new('\u{1EE4D}', '\u{1EE4F}'), - Range::new('\u{1EE51}', '\u{1EE52}'), - Range::new('\u{1EE54}', '\u{1EE54}'), - Range::new('\u{1EE57}', '\u{1EE57}'), - Range::new('\u{1EE59}', '\u{1EE59}'), - Range::new('\u{1EE5B}', '\u{1EE5B}'), - Range::new('\u{1EE5D}', '\u{1EE5D}'), - Range::new('\u{1EE5F}', '\u{1EE5F}'), - Range::new('\u{1EE61}', '\u{1EE62}'), - Range::new('\u{1EE64}', '\u{1EE64}'), - Range::new('\u{1EE67}', '\u{1EE6A}'), - Range::new('\u{1EE6C}', '\u{1EE72}'), - Range::new('\u{1EE74}', '\u{1EE77}'), - Range::new('\u{1EE79}', '\u{1EE7C}'), - Range::new('\u{1EE7E}', '\u{1EE7E}'), - Range::new('\u{1EE80}', '\u{1EE89}'), - Range::new('\u{1EE8B}', '\u{1EE9B}'), - Range::new('\u{1EEA1}', '\u{1EEA3}'), - Range::new('\u{1EEA5}', '\u{1EEA9}'), - Range::new('\u{1EEAB}', '\u{1EEBB}'), - Range::new('\u{1F130}', '\u{1F149}'), - Range::new('\u{1F150}', '\u{1F169}'), - Range::new('\u{1F170}', '\u{1F189}'), - Range::new('\u{1FBF0}', '\u{1FBF9}'), - Range::new('\u{20000}', '\u{2A6DF}'), - Range::new('\u{2A700}', '\u{2B738}'), - Range::new('\u{2B740}', '\u{2B81D}'), - Range::new('\u{2B820}', '\u{2CEA1}'), - Range::new('\u{2CEB0}', '\u{2EBE0}'), - Range::new('\u{2F800}', '\u{2FA1D}'), - Range::new('\u{30000}', '\u{3134A}'), -]; - -pub static ALPHA: [Range; 722] = [ - Range::new('\u{41}', '\u{5A}'), - Range::new('\u{61}', '\u{7A}'), - Range::new('\u{AA}', '\u{AA}'), - Range::new('\u{B5}', '\u{B5}'), - Range::new('\u{BA}', '\u{BA}'), - Range::new('\u{C0}', '\u{D6}'), - Range::new('\u{D8}', '\u{F6}'), - Range::new('\u{F8}', '\u{2C1}'), - Range::new('\u{2C6}', '\u{2D1}'), - Range::new('\u{2E0}', '\u{2E4}'), - Range::new('\u{2EC}', '\u{2EC}'), - Range::new('\u{2EE}', '\u{2EE}'), - Range::new('\u{345}', '\u{345}'), - Range::new('\u{370}', '\u{374}'), - Range::new('\u{376}', '\u{377}'), - Range::new('\u{37A}', '\u{37D}'), - Range::new('\u{37F}', '\u{37F}'), - Range::new('\u{386}', '\u{386}'), - Range::new('\u{388}', '\u{38A}'), - Range::new('\u{38C}', '\u{38C}'), - Range::new('\u{38E}', '\u{3A1}'), - Range::new('\u{3A3}', '\u{3F5}'), - Range::new('\u{3F7}', '\u{481}'), - Range::new('\u{48A}', '\u{52F}'), - Range::new('\u{531}', '\u{556}'), - Range::new('\u{559}', '\u{559}'), - Range::new('\u{560}', '\u{588}'), - Range::new('\u{5B0}', '\u{5BD}'), - Range::new('\u{5BF}', '\u{5BF}'), - Range::new('\u{5C1}', '\u{5C2}'), - Range::new('\u{5C4}', '\u{5C5}'), - Range::new('\u{5C7}', '\u{5C7}'), - Range::new('\u{5D0}', '\u{5EA}'), - Range::new('\u{5EF}', '\u{5F2}'), - Range::new('\u{610}', '\u{61A}'), - Range::new('\u{620}', '\u{657}'), - Range::new('\u{659}', '\u{65F}'), - Range::new('\u{66E}', '\u{6D3}'), - Range::new('\u{6D5}', '\u{6DC}'), - Range::new('\u{6E1}', '\u{6E8}'), - Range::new('\u{6ED}', '\u{6EF}'), - Range::new('\u{6FA}', '\u{6FC}'), - Range::new('\u{6FF}', '\u{6FF}'), - Range::new('\u{710}', '\u{73F}'), - Range::new('\u{74D}', '\u{7B1}'), - Range::new('\u{7CA}', '\u{7EA}'), - Range::new('\u{7F4}', '\u{7F5}'), - Range::new('\u{7FA}', '\u{7FA}'), - Range::new('\u{800}', '\u{817}'), - Range::new('\u{81A}', '\u{82C}'), - Range::new('\u{840}', '\u{858}'), - Range::new('\u{860}', '\u{86A}'), - Range::new('\u{870}', '\u{887}'), - Range::new('\u{889}', '\u{88E}'), - Range::new('\u{8A0}', '\u{8C9}'), - Range::new('\u{8D4}', '\u{8DF}'), - Range::new('\u{8E3}', '\u{8E9}'), - Range::new('\u{8F0}', '\u{93B}'), - Range::new('\u{93D}', '\u{94C}'), - Range::new('\u{94E}', '\u{950}'), - Range::new('\u{955}', '\u{963}'), - Range::new('\u{971}', '\u{983}'), - Range::new('\u{985}', '\u{98C}'), - Range::new('\u{98F}', '\u{990}'), - Range::new('\u{993}', '\u{9A8}'), - Range::new('\u{9AA}', '\u{9B0}'), - Range::new('\u{9B2}', '\u{9B2}'), - Range::new('\u{9B6}', '\u{9B9}'), - Range::new('\u{9BD}', '\u{9C4}'), - Range::new('\u{9C7}', '\u{9C8}'), - Range::new('\u{9CB}', '\u{9CC}'), - Range::new('\u{9CE}', '\u{9CE}'), - Range::new('\u{9D7}', '\u{9D7}'), - Range::new('\u{9DC}', '\u{9DD}'), - Range::new('\u{9DF}', '\u{9E3}'), - Range::new('\u{9F0}', '\u{9F1}'), - Range::new('\u{9FC}', '\u{9FC}'), - Range::new('\u{A01}', '\u{A03}'), - Range::new('\u{A05}', '\u{A0A}'), - Range::new('\u{A0F}', '\u{A10}'), - Range::new('\u{A13}', '\u{A28}'), - Range::new('\u{A2A}', '\u{A30}'), - Range::new('\u{A32}', '\u{A33}'), - Range::new('\u{A35}', '\u{A36}'), - Range::new('\u{A38}', '\u{A39}'), - Range::new('\u{A3E}', '\u{A42}'), - Range::new('\u{A47}', '\u{A48}'), - Range::new('\u{A4B}', '\u{A4C}'), - Range::new('\u{A51}', '\u{A51}'), - Range::new('\u{A59}', '\u{A5C}'), - Range::new('\u{A5E}', '\u{A5E}'), - Range::new('\u{A70}', '\u{A75}'), - Range::new('\u{A81}', '\u{A83}'), - Range::new('\u{A85}', '\u{A8D}'), - Range::new('\u{A8F}', '\u{A91}'), - Range::new('\u{A93}', '\u{AA8}'), - Range::new('\u{AAA}', '\u{AB0}'), - Range::new('\u{AB2}', '\u{AB3}'), - Range::new('\u{AB5}', '\u{AB9}'), - Range::new('\u{ABD}', '\u{AC5}'), - Range::new('\u{AC7}', '\u{AC9}'), - Range::new('\u{ACB}', '\u{ACC}'), - Range::new('\u{AD0}', '\u{AD0}'), - Range::new('\u{AE0}', '\u{AE3}'), - Range::new('\u{AF9}', '\u{AFC}'), - Range::new('\u{B01}', '\u{B03}'), - Range::new('\u{B05}', '\u{B0C}'), - Range::new('\u{B0F}', '\u{B10}'), - Range::new('\u{B13}', '\u{B28}'), - Range::new('\u{B2A}', '\u{B30}'), - Range::new('\u{B32}', '\u{B33}'), - Range::new('\u{B35}', '\u{B39}'), - Range::new('\u{B3D}', '\u{B44}'), - Range::new('\u{B47}', '\u{B48}'), - Range::new('\u{B4B}', '\u{B4C}'), - Range::new('\u{B56}', '\u{B57}'), - Range::new('\u{B5C}', '\u{B5D}'), - Range::new('\u{B5F}', '\u{B63}'), - Range::new('\u{B71}', '\u{B71}'), - Range::new('\u{B82}', '\u{B83}'), - Range::new('\u{B85}', '\u{B8A}'), - Range::new('\u{B8E}', '\u{B90}'), - Range::new('\u{B92}', '\u{B95}'), - Range::new('\u{B99}', '\u{B9A}'), - Range::new('\u{B9C}', '\u{B9C}'), - Range::new('\u{B9E}', '\u{B9F}'), - Range::new('\u{BA3}', '\u{BA4}'), - Range::new('\u{BA8}', '\u{BAA}'), - Range::new('\u{BAE}', '\u{BB9}'), - Range::new('\u{BBE}', '\u{BC2}'), - Range::new('\u{BC6}', '\u{BC8}'), - Range::new('\u{BCA}', '\u{BCC}'), - Range::new('\u{BD0}', '\u{BD0}'), - Range::new('\u{BD7}', '\u{BD7}'), - Range::new('\u{C00}', '\u{C03}'), - Range::new('\u{C05}', '\u{C0C}'), - Range::new('\u{C0E}', '\u{C10}'), - Range::new('\u{C12}', '\u{C28}'), - Range::new('\u{C2A}', '\u{C39}'), - Range::new('\u{C3D}', '\u{C44}'), - Range::new('\u{C46}', '\u{C48}'), - Range::new('\u{C4A}', '\u{C4C}'), - Range::new('\u{C55}', '\u{C56}'), - Range::new('\u{C58}', '\u{C5A}'), - Range::new('\u{C5D}', '\u{C5D}'), - Range::new('\u{C60}', '\u{C63}'), - Range::new('\u{C80}', '\u{C83}'), - Range::new('\u{C85}', '\u{C8C}'), - Range::new('\u{C8E}', '\u{C90}'), - Range::new('\u{C92}', '\u{CA8}'), - Range::new('\u{CAA}', '\u{CB3}'), - Range::new('\u{CB5}', '\u{CB9}'), - Range::new('\u{CBD}', '\u{CC4}'), - Range::new('\u{CC6}', '\u{CC8}'), - Range::new('\u{CCA}', '\u{CCC}'), - Range::new('\u{CD5}', '\u{CD6}'), - Range::new('\u{CDD}', '\u{CDE}'), - Range::new('\u{CE0}', '\u{CE3}'), - Range::new('\u{CF1}', '\u{CF2}'), - Range::new('\u{D00}', '\u{D0C}'), - Range::new('\u{D0E}', '\u{D10}'), - Range::new('\u{D12}', '\u{D3A}'), - Range::new('\u{D3D}', '\u{D44}'), - Range::new('\u{D46}', '\u{D48}'), - Range::new('\u{D4A}', '\u{D4C}'), - Range::new('\u{D4E}', '\u{D4E}'), - Range::new('\u{D54}', '\u{D57}'), - Range::new('\u{D5F}', '\u{D63}'), - Range::new('\u{D7A}', '\u{D7F}'), - Range::new('\u{D81}', '\u{D83}'), - Range::new('\u{D85}', '\u{D96}'), - Range::new('\u{D9A}', '\u{DB1}'), - Range::new('\u{DB3}', '\u{DBB}'), - Range::new('\u{DBD}', '\u{DBD}'), - Range::new('\u{DC0}', '\u{DC6}'), - Range::new('\u{DCF}', '\u{DD4}'), - Range::new('\u{DD6}', '\u{DD6}'), - Range::new('\u{DD8}', '\u{DDF}'), - Range::new('\u{DF2}', '\u{DF3}'), - Range::new('\u{E01}', '\u{E3A}'), - Range::new('\u{E40}', '\u{E46}'), - Range::new('\u{E4D}', '\u{E4D}'), - Range::new('\u{E81}', '\u{E82}'), - Range::new('\u{E84}', '\u{E84}'), - Range::new('\u{E86}', '\u{E8A}'), - Range::new('\u{E8C}', '\u{EA3}'), - Range::new('\u{EA5}', '\u{EA5}'), - Range::new('\u{EA7}', '\u{EB9}'), - Range::new('\u{EBB}', '\u{EBD}'), - Range::new('\u{EC0}', '\u{EC4}'), - Range::new('\u{EC6}', '\u{EC6}'), - Range::new('\u{ECD}', '\u{ECD}'), - Range::new('\u{EDC}', '\u{EDF}'), - Range::new('\u{F00}', '\u{F00}'), - Range::new('\u{F40}', '\u{F47}'), - Range::new('\u{F49}', '\u{F6C}'), - Range::new('\u{F71}', '\u{F81}'), - Range::new('\u{F88}', '\u{F97}'), - Range::new('\u{F99}', '\u{FBC}'), - Range::new('\u{1000}', '\u{1036}'), - Range::new('\u{1038}', '\u{1038}'), - Range::new('\u{103B}', '\u{103F}'), - Range::new('\u{1050}', '\u{108F}'), - Range::new('\u{109A}', '\u{109D}'), - Range::new('\u{10A0}', '\u{10C5}'), - Range::new('\u{10C7}', '\u{10C7}'), - Range::new('\u{10CD}', '\u{10CD}'), - Range::new('\u{10D0}', '\u{10FA}'), - Range::new('\u{10FC}', '\u{1248}'), - Range::new('\u{124A}', '\u{124D}'), - Range::new('\u{1250}', '\u{1256}'), - Range::new('\u{1258}', '\u{1258}'), - Range::new('\u{125A}', '\u{125D}'), - Range::new('\u{1260}', '\u{1288}'), - Range::new('\u{128A}', '\u{128D}'), - Range::new('\u{1290}', '\u{12B0}'), - Range::new('\u{12B2}', '\u{12B5}'), - Range::new('\u{12B8}', '\u{12BE}'), - Range::new('\u{12C0}', '\u{12C0}'), - Range::new('\u{12C2}', '\u{12C5}'), - Range::new('\u{12C8}', '\u{12D6}'), - Range::new('\u{12D8}', '\u{1310}'), - Range::new('\u{1312}', '\u{1315}'), - Range::new('\u{1318}', '\u{135A}'), - Range::new('\u{1380}', '\u{138F}'), - Range::new('\u{13A0}', '\u{13F5}'), - Range::new('\u{13F8}', '\u{13FD}'), - Range::new('\u{1401}', '\u{166C}'), - Range::new('\u{166F}', '\u{167F}'), - Range::new('\u{1681}', '\u{169A}'), - Range::new('\u{16A0}', '\u{16EA}'), - Range::new('\u{16EE}', '\u{16F8}'), - Range::new('\u{1700}', '\u{1713}'), - Range::new('\u{171F}', '\u{1733}'), - Range::new('\u{1740}', '\u{1753}'), - Range::new('\u{1760}', '\u{176C}'), - Range::new('\u{176E}', '\u{1770}'), - Range::new('\u{1772}', '\u{1773}'), - Range::new('\u{1780}', '\u{17B3}'), - Range::new('\u{17B6}', '\u{17C8}'), - Range::new('\u{17D7}', '\u{17D7}'), - Range::new('\u{17DC}', '\u{17DC}'), - Range::new('\u{1820}', '\u{1878}'), - Range::new('\u{1880}', '\u{18AA}'), - Range::new('\u{18B0}', '\u{18F5}'), - Range::new('\u{1900}', '\u{191E}'), - Range::new('\u{1920}', '\u{192B}'), - Range::new('\u{1930}', '\u{1938}'), - Range::new('\u{1950}', '\u{196D}'), - Range::new('\u{1970}', '\u{1974}'), - Range::new('\u{1980}', '\u{19AB}'), - Range::new('\u{19B0}', '\u{19C9}'), - Range::new('\u{1A00}', '\u{1A1B}'), - Range::new('\u{1A20}', '\u{1A5E}'), - Range::new('\u{1A61}', '\u{1A74}'), - Range::new('\u{1AA7}', '\u{1AA7}'), - Range::new('\u{1ABF}', '\u{1AC0}'), - Range::new('\u{1ACC}', '\u{1ACE}'), - Range::new('\u{1B00}', '\u{1B33}'), - Range::new('\u{1B35}', '\u{1B43}'), - Range::new('\u{1B45}', '\u{1B4C}'), - Range::new('\u{1B80}', '\u{1BA9}'), - Range::new('\u{1BAC}', '\u{1BAF}'), - Range::new('\u{1BBA}', '\u{1BE5}'), - Range::new('\u{1BE7}', '\u{1BF1}'), - Range::new('\u{1C00}', '\u{1C36}'), - Range::new('\u{1C4D}', '\u{1C4F}'), - Range::new('\u{1C5A}', '\u{1C7D}'), - Range::new('\u{1C80}', '\u{1C88}'), - Range::new('\u{1C90}', '\u{1CBA}'), - Range::new('\u{1CBD}', '\u{1CBF}'), - Range::new('\u{1CE9}', '\u{1CEC}'), - Range::new('\u{1CEE}', '\u{1CF3}'), - Range::new('\u{1CF5}', '\u{1CF6}'), - Range::new('\u{1CFA}', '\u{1CFA}'), - Range::new('\u{1D00}', '\u{1DBF}'), - Range::new('\u{1DE7}', '\u{1DF4}'), - Range::new('\u{1E00}', '\u{1F15}'), - Range::new('\u{1F18}', '\u{1F1D}'), - Range::new('\u{1F20}', '\u{1F45}'), - Range::new('\u{1F48}', '\u{1F4D}'), - Range::new('\u{1F50}', '\u{1F57}'), - Range::new('\u{1F59}', '\u{1F59}'), - Range::new('\u{1F5B}', '\u{1F5B}'), - Range::new('\u{1F5D}', '\u{1F5D}'), - Range::new('\u{1F5F}', '\u{1F7D}'), - Range::new('\u{1F80}', '\u{1FB4}'), - Range::new('\u{1FB6}', '\u{1FBC}'), - Range::new('\u{1FBE}', '\u{1FBE}'), - Range::new('\u{1FC2}', '\u{1FC4}'), - Range::new('\u{1FC6}', '\u{1FCC}'), - Range::new('\u{1FD0}', '\u{1FD3}'), - Range::new('\u{1FD6}', '\u{1FDB}'), - Range::new('\u{1FE0}', '\u{1FEC}'), - Range::new('\u{1FF2}', '\u{1FF4}'), - Range::new('\u{1FF6}', '\u{1FFC}'), - Range::new('\u{2071}', '\u{2071}'), - Range::new('\u{207F}', '\u{207F}'), - Range::new('\u{2090}', '\u{209C}'), - Range::new('\u{2102}', '\u{2102}'), - Range::new('\u{2107}', '\u{2107}'), - Range::new('\u{210A}', '\u{2113}'), - Range::new('\u{2115}', '\u{2115}'), - Range::new('\u{2119}', '\u{211D}'), - Range::new('\u{2124}', '\u{2124}'), - Range::new('\u{2126}', '\u{2126}'), - Range::new('\u{2128}', '\u{2128}'), - Range::new('\u{212A}', '\u{212D}'), - Range::new('\u{212F}', '\u{2139}'), - Range::new('\u{213C}', '\u{213F}'), - Range::new('\u{2145}', '\u{2149}'), - Range::new('\u{214E}', '\u{214E}'), - Range::new('\u{2160}', '\u{2188}'), - Range::new('\u{24B6}', '\u{24E9}'), - Range::new('\u{2C00}', '\u{2CE4}'), - Range::new('\u{2CEB}', '\u{2CEE}'), - Range::new('\u{2CF2}', '\u{2CF3}'), - Range::new('\u{2D00}', '\u{2D25}'), - Range::new('\u{2D27}', '\u{2D27}'), - Range::new('\u{2D2D}', '\u{2D2D}'), - Range::new('\u{2D30}', '\u{2D67}'), - Range::new('\u{2D6F}', '\u{2D6F}'), - Range::new('\u{2D80}', '\u{2D96}'), - Range::new('\u{2DA0}', '\u{2DA6}'), - Range::new('\u{2DA8}', '\u{2DAE}'), - Range::new('\u{2DB0}', '\u{2DB6}'), - Range::new('\u{2DB8}', '\u{2DBE}'), - Range::new('\u{2DC0}', '\u{2DC6}'), - Range::new('\u{2DC8}', '\u{2DCE}'), - Range::new('\u{2DD0}', '\u{2DD6}'), - Range::new('\u{2DD8}', '\u{2DDE}'), - Range::new('\u{2DE0}', '\u{2DFF}'), - Range::new('\u{2E2F}', '\u{2E2F}'), - Range::new('\u{3005}', '\u{3007}'), - Range::new('\u{3021}', '\u{3029}'), - Range::new('\u{3031}', '\u{3035}'), - Range::new('\u{3038}', '\u{303C}'), - Range::new('\u{3041}', '\u{3096}'), - Range::new('\u{309D}', '\u{309F}'), - Range::new('\u{30A1}', '\u{30FA}'), - Range::new('\u{30FC}', '\u{30FF}'), - Range::new('\u{3105}', '\u{312F}'), - Range::new('\u{3131}', '\u{318E}'), - Range::new('\u{31A0}', '\u{31BF}'), - Range::new('\u{31F0}', '\u{31FF}'), - Range::new('\u{3400}', '\u{4DBF}'), - Range::new('\u{4E00}', '\u{A48C}'), - Range::new('\u{A4D0}', '\u{A4FD}'), - Range::new('\u{A500}', '\u{A60C}'), - Range::new('\u{A610}', '\u{A61F}'), - Range::new('\u{A62A}', '\u{A62B}'), - Range::new('\u{A640}', '\u{A66E}'), - Range::new('\u{A674}', '\u{A67B}'), - Range::new('\u{A67F}', '\u{A6EF}'), - Range::new('\u{A717}', '\u{A71F}'), - Range::new('\u{A722}', '\u{A788}'), - Range::new('\u{A78B}', '\u{A7CA}'), - Range::new('\u{A7D0}', '\u{A7D1}'), - Range::new('\u{A7D3}', '\u{A7D3}'), - Range::new('\u{A7D5}', '\u{A7D9}'), - Range::new('\u{A7F2}', '\u{A805}'), - Range::new('\u{A807}', '\u{A827}'), - Range::new('\u{A840}', '\u{A873}'), - Range::new('\u{A880}', '\u{A8C3}'), - Range::new('\u{A8C5}', '\u{A8C5}'), - Range::new('\u{A8F2}', '\u{A8F7}'), - Range::new('\u{A8FB}', '\u{A8FB}'), - Range::new('\u{A8FD}', '\u{A8FF}'), - Range::new('\u{A90A}', '\u{A92A}'), - Range::new('\u{A930}', '\u{A952}'), - Range::new('\u{A960}', '\u{A97C}'), - Range::new('\u{A980}', '\u{A9B2}'), - Range::new('\u{A9B4}', '\u{A9BF}'), - Range::new('\u{A9CF}', '\u{A9CF}'), - Range::new('\u{A9E0}', '\u{A9EF}'), - Range::new('\u{A9FA}', '\u{A9FE}'), - Range::new('\u{AA00}', '\u{AA36}'), - Range::new('\u{AA40}', '\u{AA4D}'), - Range::new('\u{AA60}', '\u{AA76}'), - Range::new('\u{AA7A}', '\u{AABE}'), - Range::new('\u{AAC0}', '\u{AAC0}'), - Range::new('\u{AAC2}', '\u{AAC2}'), - Range::new('\u{AADB}', '\u{AADD}'), - Range::new('\u{AAE0}', '\u{AAEF}'), - Range::new('\u{AAF2}', '\u{AAF5}'), - Range::new('\u{AB01}', '\u{AB06}'), - Range::new('\u{AB09}', '\u{AB0E}'), - Range::new('\u{AB11}', '\u{AB16}'), - Range::new('\u{AB20}', '\u{AB26}'), - Range::new('\u{AB28}', '\u{AB2E}'), - Range::new('\u{AB30}', '\u{AB5A}'), - Range::new('\u{AB5C}', '\u{AB69}'), - Range::new('\u{AB70}', '\u{ABEA}'), - Range::new('\u{AC00}', '\u{D7A3}'), - Range::new('\u{D7B0}', '\u{D7C6}'), - Range::new('\u{D7CB}', '\u{D7FB}'), - Range::new('\u{F900}', '\u{FA6D}'), - Range::new('\u{FA70}', '\u{FAD9}'), - Range::new('\u{FB00}', '\u{FB06}'), - Range::new('\u{FB13}', '\u{FB17}'), - Range::new('\u{FB1D}', '\u{FB28}'), - Range::new('\u{FB2A}', '\u{FB36}'), - Range::new('\u{FB38}', '\u{FB3C}'), - Range::new('\u{FB3E}', '\u{FB3E}'), - Range::new('\u{FB40}', '\u{FB41}'), - Range::new('\u{FB43}', '\u{FB44}'), - Range::new('\u{FB46}', '\u{FBB1}'), - Range::new('\u{FBD3}', '\u{FD3D}'), - Range::new('\u{FD50}', '\u{FD8F}'), - Range::new('\u{FD92}', '\u{FDC7}'), - Range::new('\u{FDF0}', '\u{FDFB}'), - Range::new('\u{FE70}', '\u{FE74}'), - Range::new('\u{FE76}', '\u{FEFC}'), - Range::new('\u{FF21}', '\u{FF3A}'), - Range::new('\u{FF41}', '\u{FF5A}'), - Range::new('\u{FF66}', '\u{FFBE}'), - Range::new('\u{FFC2}', '\u{FFC7}'), - Range::new('\u{FFCA}', '\u{FFCF}'), - Range::new('\u{FFD2}', '\u{FFD7}'), - Range::new('\u{FFDA}', '\u{FFDC}'), - Range::new('\u{10000}', '\u{1000B}'), - Range::new('\u{1000D}', '\u{10026}'), - Range::new('\u{10028}', '\u{1003A}'), - Range::new('\u{1003C}', '\u{1003D}'), - Range::new('\u{1003F}', '\u{1004D}'), - Range::new('\u{10050}', '\u{1005D}'), - Range::new('\u{10080}', '\u{100FA}'), - Range::new('\u{10140}', '\u{10174}'), - Range::new('\u{10280}', '\u{1029C}'), - Range::new('\u{102A0}', '\u{102D0}'), - Range::new('\u{10300}', '\u{1031F}'), - Range::new('\u{1032D}', '\u{1034A}'), - Range::new('\u{10350}', '\u{1037A}'), - Range::new('\u{10380}', '\u{1039D}'), - Range::new('\u{103A0}', '\u{103C3}'), - Range::new('\u{103C8}', '\u{103CF}'), - Range::new('\u{103D1}', '\u{103D5}'), - Range::new('\u{10400}', '\u{1049D}'), - Range::new('\u{104B0}', '\u{104D3}'), - Range::new('\u{104D8}', '\u{104FB}'), - Range::new('\u{10500}', '\u{10527}'), - Range::new('\u{10530}', '\u{10563}'), - Range::new('\u{10570}', '\u{1057A}'), - Range::new('\u{1057C}', '\u{1058A}'), - Range::new('\u{1058C}', '\u{10592}'), - Range::new('\u{10594}', '\u{10595}'), - Range::new('\u{10597}', '\u{105A1}'), - Range::new('\u{105A3}', '\u{105B1}'), - Range::new('\u{105B3}', '\u{105B9}'), - Range::new('\u{105BB}', '\u{105BC}'), - Range::new('\u{10600}', '\u{10736}'), - Range::new('\u{10740}', '\u{10755}'), - Range::new('\u{10760}', '\u{10767}'), - Range::new('\u{10780}', '\u{10785}'), - Range::new('\u{10787}', '\u{107B0}'), - Range::new('\u{107B2}', '\u{107BA}'), - Range::new('\u{10800}', '\u{10805}'), - Range::new('\u{10808}', '\u{10808}'), - Range::new('\u{1080A}', '\u{10835}'), - Range::new('\u{10837}', '\u{10838}'), - Range::new('\u{1083C}', '\u{1083C}'), - Range::new('\u{1083F}', '\u{10855}'), - Range::new('\u{10860}', '\u{10876}'), - Range::new('\u{10880}', '\u{1089E}'), - Range::new('\u{108E0}', '\u{108F2}'), - Range::new('\u{108F4}', '\u{108F5}'), - Range::new('\u{10900}', '\u{10915}'), - Range::new('\u{10920}', '\u{10939}'), - Range::new('\u{10980}', '\u{109B7}'), - Range::new('\u{109BE}', '\u{109BF}'), - Range::new('\u{10A00}', '\u{10A03}'), - Range::new('\u{10A05}', '\u{10A06}'), - Range::new('\u{10A0C}', '\u{10A13}'), - Range::new('\u{10A15}', '\u{10A17}'), - Range::new('\u{10A19}', '\u{10A35}'), - Range::new('\u{10A60}', '\u{10A7C}'), - Range::new('\u{10A80}', '\u{10A9C}'), - Range::new('\u{10AC0}', '\u{10AC7}'), - Range::new('\u{10AC9}', '\u{10AE4}'), - Range::new('\u{10B00}', '\u{10B35}'), - Range::new('\u{10B40}', '\u{10B55}'), - Range::new('\u{10B60}', '\u{10B72}'), - Range::new('\u{10B80}', '\u{10B91}'), - Range::new('\u{10C00}', '\u{10C48}'), - Range::new('\u{10C80}', '\u{10CB2}'), - Range::new('\u{10CC0}', '\u{10CF2}'), - Range::new('\u{10D00}', '\u{10D27}'), - Range::new('\u{10E80}', '\u{10EA9}'), - Range::new('\u{10EAB}', '\u{10EAC}'), - Range::new('\u{10EB0}', '\u{10EB1}'), - Range::new('\u{10F00}', '\u{10F1C}'), - Range::new('\u{10F27}', '\u{10F27}'), - Range::new('\u{10F30}', '\u{10F45}'), - Range::new('\u{10F70}', '\u{10F81}'), - Range::new('\u{10FB0}', '\u{10FC4}'), - Range::new('\u{10FE0}', '\u{10FF6}'), - Range::new('\u{11000}', '\u{11045}'), - Range::new('\u{11071}', '\u{11075}'), - Range::new('\u{11082}', '\u{110B8}'), - Range::new('\u{110C2}', '\u{110C2}'), - Range::new('\u{110D0}', '\u{110E8}'), - Range::new('\u{11100}', '\u{11132}'), - Range::new('\u{11144}', '\u{11147}'), - Range::new('\u{11150}', '\u{11172}'), - Range::new('\u{11176}', '\u{11176}'), - Range::new('\u{11180}', '\u{111BF}'), - Range::new('\u{111C1}', '\u{111C4}'), - Range::new('\u{111CE}', '\u{111CF}'), - Range::new('\u{111DA}', '\u{111DA}'), - Range::new('\u{111DC}', '\u{111DC}'), - Range::new('\u{11200}', '\u{11211}'), - Range::new('\u{11213}', '\u{11234}'), - Range::new('\u{11237}', '\u{11237}'), - Range::new('\u{1123E}', '\u{1123E}'), - Range::new('\u{11280}', '\u{11286}'), - Range::new('\u{11288}', '\u{11288}'), - Range::new('\u{1128A}', '\u{1128D}'), - Range::new('\u{1128F}', '\u{1129D}'), - Range::new('\u{1129F}', '\u{112A8}'), - Range::new('\u{112B0}', '\u{112E8}'), - Range::new('\u{11300}', '\u{11303}'), - Range::new('\u{11305}', '\u{1130C}'), - Range::new('\u{1130F}', '\u{11310}'), - Range::new('\u{11313}', '\u{11328}'), - Range::new('\u{1132A}', '\u{11330}'), - Range::new('\u{11332}', '\u{11333}'), - Range::new('\u{11335}', '\u{11339}'), - Range::new('\u{1133D}', '\u{11344}'), - Range::new('\u{11347}', '\u{11348}'), - Range::new('\u{1134B}', '\u{1134C}'), - Range::new('\u{11350}', '\u{11350}'), - Range::new('\u{11357}', '\u{11357}'), - Range::new('\u{1135D}', '\u{11363}'), - Range::new('\u{11400}', '\u{11441}'), - Range::new('\u{11443}', '\u{11445}'), - Range::new('\u{11447}', '\u{1144A}'), - Range::new('\u{1145F}', '\u{11461}'), - Range::new('\u{11480}', '\u{114C1}'), - Range::new('\u{114C4}', '\u{114C5}'), - Range::new('\u{114C7}', '\u{114C7}'), - Range::new('\u{11580}', '\u{115B5}'), - Range::new('\u{115B8}', '\u{115BE}'), - Range::new('\u{115D8}', '\u{115DD}'), - Range::new('\u{11600}', '\u{1163E}'), - Range::new('\u{11640}', '\u{11640}'), - Range::new('\u{11644}', '\u{11644}'), - Range::new('\u{11680}', '\u{116B5}'), - Range::new('\u{116B8}', '\u{116B8}'), - Range::new('\u{11700}', '\u{1171A}'), - Range::new('\u{1171D}', '\u{1172A}'), - Range::new('\u{11740}', '\u{11746}'), - Range::new('\u{11800}', '\u{11838}'), - Range::new('\u{118A0}', '\u{118DF}'), - Range::new('\u{118FF}', '\u{11906}'), - Range::new('\u{11909}', '\u{11909}'), - Range::new('\u{1190C}', '\u{11913}'), - Range::new('\u{11915}', '\u{11916}'), - Range::new('\u{11918}', '\u{11935}'), - Range::new('\u{11937}', '\u{11938}'), - Range::new('\u{1193B}', '\u{1193C}'), - Range::new('\u{1193F}', '\u{11942}'), - Range::new('\u{119A0}', '\u{119A7}'), - Range::new('\u{119AA}', '\u{119D7}'), - Range::new('\u{119DA}', '\u{119DF}'), - Range::new('\u{119E1}', '\u{119E1}'), - Range::new('\u{119E3}', '\u{119E4}'), - Range::new('\u{11A00}', '\u{11A32}'), - Range::new('\u{11A35}', '\u{11A3E}'), - Range::new('\u{11A50}', '\u{11A97}'), - Range::new('\u{11A9D}', '\u{11A9D}'), - Range::new('\u{11AB0}', '\u{11AF8}'), - Range::new('\u{11C00}', '\u{11C08}'), - Range::new('\u{11C0A}', '\u{11C36}'), - Range::new('\u{11C38}', '\u{11C3E}'), - Range::new('\u{11C40}', '\u{11C40}'), - Range::new('\u{11C72}', '\u{11C8F}'), - Range::new('\u{11C92}', '\u{11CA7}'), - Range::new('\u{11CA9}', '\u{11CB6}'), - Range::new('\u{11D00}', '\u{11D06}'), - Range::new('\u{11D08}', '\u{11D09}'), - Range::new('\u{11D0B}', '\u{11D36}'), - Range::new('\u{11D3A}', '\u{11D3A}'), - Range::new('\u{11D3C}', '\u{11D3D}'), - Range::new('\u{11D3F}', '\u{11D41}'), - Range::new('\u{11D43}', '\u{11D43}'), - Range::new('\u{11D46}', '\u{11D47}'), - Range::new('\u{11D60}', '\u{11D65}'), - Range::new('\u{11D67}', '\u{11D68}'), - Range::new('\u{11D6A}', '\u{11D8E}'), - Range::new('\u{11D90}', '\u{11D91}'), - Range::new('\u{11D93}', '\u{11D96}'), - Range::new('\u{11D98}', '\u{11D98}'), - Range::new('\u{11EE0}', '\u{11EF6}'), - Range::new('\u{11FB0}', '\u{11FB0}'), - Range::new('\u{12000}', '\u{12399}'), - Range::new('\u{12400}', '\u{1246E}'), - Range::new('\u{12480}', '\u{12543}'), - Range::new('\u{12F90}', '\u{12FF0}'), - Range::new('\u{13000}', '\u{1342E}'), - Range::new('\u{14400}', '\u{14646}'), - Range::new('\u{16800}', '\u{16A38}'), - Range::new('\u{16A40}', '\u{16A5E}'), - Range::new('\u{16A70}', '\u{16ABE}'), - Range::new('\u{16AD0}', '\u{16AED}'), - Range::new('\u{16B00}', '\u{16B2F}'), - Range::new('\u{16B40}', '\u{16B43}'), - Range::new('\u{16B63}', '\u{16B77}'), - Range::new('\u{16B7D}', '\u{16B8F}'), - Range::new('\u{16E40}', '\u{16E7F}'), - Range::new('\u{16F00}', '\u{16F4A}'), - Range::new('\u{16F4F}', '\u{16F87}'), - Range::new('\u{16F8F}', '\u{16F9F}'), - Range::new('\u{16FE0}', '\u{16FE1}'), - Range::new('\u{16FE3}', '\u{16FE3}'), - Range::new('\u{16FF0}', '\u{16FF1}'), - Range::new('\u{17000}', '\u{187F7}'), - Range::new('\u{18800}', '\u{18CD5}'), - Range::new('\u{18D00}', '\u{18D08}'), - Range::new('\u{1AFF0}', '\u{1AFF3}'), - Range::new('\u{1AFF5}', '\u{1AFFB}'), - Range::new('\u{1AFFD}', '\u{1AFFE}'), - Range::new('\u{1B000}', '\u{1B122}'), - Range::new('\u{1B150}', '\u{1B152}'), - Range::new('\u{1B164}', '\u{1B167}'), - Range::new('\u{1B170}', '\u{1B2FB}'), - Range::new('\u{1BC00}', '\u{1BC6A}'), - Range::new('\u{1BC70}', '\u{1BC7C}'), - Range::new('\u{1BC80}', '\u{1BC88}'), - Range::new('\u{1BC90}', '\u{1BC99}'), - Range::new('\u{1BC9E}', '\u{1BC9E}'), - Range::new('\u{1D400}', '\u{1D454}'), - Range::new('\u{1D456}', '\u{1D49C}'), - Range::new('\u{1D49E}', '\u{1D49F}'), - Range::new('\u{1D4A2}', '\u{1D4A2}'), - Range::new('\u{1D4A5}', '\u{1D4A6}'), - Range::new('\u{1D4A9}', '\u{1D4AC}'), - Range::new('\u{1D4AE}', '\u{1D4B9}'), - Range::new('\u{1D4BB}', '\u{1D4BB}'), - Range::new('\u{1D4BD}', '\u{1D4C3}'), - Range::new('\u{1D4C5}', '\u{1D505}'), - Range::new('\u{1D507}', '\u{1D50A}'), - Range::new('\u{1D50D}', '\u{1D514}'), - Range::new('\u{1D516}', '\u{1D51C}'), - Range::new('\u{1D51E}', '\u{1D539}'), - Range::new('\u{1D53B}', '\u{1D53E}'), - Range::new('\u{1D540}', '\u{1D544}'), - Range::new('\u{1D546}', '\u{1D546}'), - Range::new('\u{1D54A}', '\u{1D550}'), - Range::new('\u{1D552}', '\u{1D6A5}'), - Range::new('\u{1D6A8}', '\u{1D6C0}'), - Range::new('\u{1D6C2}', '\u{1D6DA}'), - Range::new('\u{1D6DC}', '\u{1D6FA}'), - Range::new('\u{1D6FC}', '\u{1D714}'), - Range::new('\u{1D716}', '\u{1D734}'), - Range::new('\u{1D736}', '\u{1D74E}'), - Range::new('\u{1D750}', '\u{1D76E}'), - Range::new('\u{1D770}', '\u{1D788}'), - Range::new('\u{1D78A}', '\u{1D7A8}'), - Range::new('\u{1D7AA}', '\u{1D7C2}'), - Range::new('\u{1D7C4}', '\u{1D7CB}'), - Range::new('\u{1DF00}', '\u{1DF1E}'), - Range::new('\u{1E000}', '\u{1E006}'), - Range::new('\u{1E008}', '\u{1E018}'), - Range::new('\u{1E01B}', '\u{1E021}'), - Range::new('\u{1E023}', '\u{1E024}'), - Range::new('\u{1E026}', '\u{1E02A}'), - Range::new('\u{1E100}', '\u{1E12C}'), - Range::new('\u{1E137}', '\u{1E13D}'), - Range::new('\u{1E14E}', '\u{1E14E}'), - Range::new('\u{1E290}', '\u{1E2AD}'), - Range::new('\u{1E2C0}', '\u{1E2EB}'), - Range::new('\u{1E7E0}', '\u{1E7E6}'), - Range::new('\u{1E7E8}', '\u{1E7EB}'), - Range::new('\u{1E7ED}', '\u{1E7EE}'), - Range::new('\u{1E7F0}', '\u{1E7FE}'), - Range::new('\u{1E800}', '\u{1E8C4}'), - Range::new('\u{1E900}', '\u{1E943}'), - Range::new('\u{1E947}', '\u{1E947}'), - Range::new('\u{1E94B}', '\u{1E94B}'), - Range::new('\u{1EE00}', '\u{1EE03}'), - Range::new('\u{1EE05}', '\u{1EE1F}'), - Range::new('\u{1EE21}', '\u{1EE22}'), - Range::new('\u{1EE24}', '\u{1EE24}'), - Range::new('\u{1EE27}', '\u{1EE27}'), - Range::new('\u{1EE29}', '\u{1EE32}'), - Range::new('\u{1EE34}', '\u{1EE37}'), - Range::new('\u{1EE39}', '\u{1EE39}'), - Range::new('\u{1EE3B}', '\u{1EE3B}'), - Range::new('\u{1EE42}', '\u{1EE42}'), - Range::new('\u{1EE47}', '\u{1EE47}'), - Range::new('\u{1EE49}', '\u{1EE49}'), - Range::new('\u{1EE4B}', '\u{1EE4B}'), - Range::new('\u{1EE4D}', '\u{1EE4F}'), - Range::new('\u{1EE51}', '\u{1EE52}'), - Range::new('\u{1EE54}', '\u{1EE54}'), - Range::new('\u{1EE57}', '\u{1EE57}'), - Range::new('\u{1EE59}', '\u{1EE59}'), - Range::new('\u{1EE5B}', '\u{1EE5B}'), - Range::new('\u{1EE5D}', '\u{1EE5D}'), - Range::new('\u{1EE5F}', '\u{1EE5F}'), - Range::new('\u{1EE61}', '\u{1EE62}'), - Range::new('\u{1EE64}', '\u{1EE64}'), - Range::new('\u{1EE67}', '\u{1EE6A}'), - Range::new('\u{1EE6C}', '\u{1EE72}'), - Range::new('\u{1EE74}', '\u{1EE77}'), - Range::new('\u{1EE79}', '\u{1EE7C}'), - Range::new('\u{1EE7E}', '\u{1EE7E}'), - Range::new('\u{1EE80}', '\u{1EE89}'), - Range::new('\u{1EE8B}', '\u{1EE9B}'), - Range::new('\u{1EEA1}', '\u{1EEA3}'), - Range::new('\u{1EEA5}', '\u{1EEA9}'), - Range::new('\u{1EEAB}', '\u{1EEBB}'), - Range::new('\u{1F130}', '\u{1F149}'), - Range::new('\u{1F150}', '\u{1F169}'), - Range::new('\u{1F170}', '\u{1F189}'), - Range::new('\u{20000}', '\u{2A6DF}'), - Range::new('\u{2A700}', '\u{2B738}'), - Range::new('\u{2B740}', '\u{2B81D}'), - Range::new('\u{2B820}', '\u{2CEA1}'), - Range::new('\u{2CEB0}', '\u{2EBE0}'), - Range::new('\u{2F800}', '\u{2FA1D}'), - Range::new('\u{30000}', '\u{3134A}'), -]; - -pub static BLANK: [Range; 8] = [ - Range::new('\u{9}', '\u{9}'), - Range::new('\u{20}', '\u{20}'), - Range::new('\u{A0}', '\u{A0}'), - Range::new('\u{1680}', '\u{1680}'), - Range::new('\u{2000}', '\u{200A}'), - Range::new('\u{202F}', '\u{202F}'), - Range::new('\u{205F}', '\u{205F}'), - Range::new('\u{3000}', '\u{3000}'), -]; - -pub static CNTRL: [Range; 2] = [ - Range::new('\u{0}', '\u{1F}'), - Range::new('\u{7F}', '\u{9F}'), -]; - -pub static DIGIT: [Range; 62] = [ - Range::new('\u{30}', '\u{39}'), - Range::new('\u{660}', '\u{669}'), - Range::new('\u{6F0}', '\u{6F9}'), - Range::new('\u{7C0}', '\u{7C9}'), - Range::new('\u{966}', '\u{96F}'), - Range::new('\u{9E6}', '\u{9EF}'), - Range::new('\u{A66}', '\u{A6F}'), - Range::new('\u{AE6}', '\u{AEF}'), - Range::new('\u{B66}', '\u{B6F}'), - Range::new('\u{BE6}', '\u{BEF}'), - Range::new('\u{C66}', '\u{C6F}'), - Range::new('\u{CE6}', '\u{CEF}'), - Range::new('\u{D66}', '\u{D6F}'), - Range::new('\u{DE6}', '\u{DEF}'), - Range::new('\u{E50}', '\u{E59}'), - Range::new('\u{ED0}', '\u{ED9}'), - Range::new('\u{F20}', '\u{F29}'), - Range::new('\u{1040}', '\u{1049}'), - Range::new('\u{1090}', '\u{1099}'), - Range::new('\u{17E0}', '\u{17E9}'), - Range::new('\u{1810}', '\u{1819}'), - Range::new('\u{1946}', '\u{194F}'), - Range::new('\u{19D0}', '\u{19D9}'), - Range::new('\u{1A80}', '\u{1A89}'), - Range::new('\u{1A90}', '\u{1A99}'), - Range::new('\u{1B50}', '\u{1B59}'), - Range::new('\u{1BB0}', '\u{1BB9}'), - Range::new('\u{1C40}', '\u{1C49}'), - Range::new('\u{1C50}', '\u{1C59}'), - Range::new('\u{A620}', '\u{A629}'), - Range::new('\u{A8D0}', '\u{A8D9}'), - Range::new('\u{A900}', '\u{A909}'), - Range::new('\u{A9D0}', '\u{A9D9}'), - Range::new('\u{A9F0}', '\u{A9F9}'), - Range::new('\u{AA50}', '\u{AA59}'), - Range::new('\u{ABF0}', '\u{ABF9}'), - Range::new('\u{FF10}', '\u{FF19}'), - Range::new('\u{104A0}', '\u{104A9}'), - Range::new('\u{10D30}', '\u{10D39}'), - Range::new('\u{11066}', '\u{1106F}'), - Range::new('\u{110F0}', '\u{110F9}'), - Range::new('\u{11136}', '\u{1113F}'), - Range::new('\u{111D0}', '\u{111D9}'), - Range::new('\u{112F0}', '\u{112F9}'), - Range::new('\u{11450}', '\u{11459}'), - Range::new('\u{114D0}', '\u{114D9}'), - Range::new('\u{11650}', '\u{11659}'), - Range::new('\u{116C0}', '\u{116C9}'), - Range::new('\u{11730}', '\u{11739}'), - Range::new('\u{118E0}', '\u{118E9}'), - Range::new('\u{11950}', '\u{11959}'), - Range::new('\u{11C50}', '\u{11C59}'), - Range::new('\u{11D50}', '\u{11D59}'), - Range::new('\u{11DA0}', '\u{11DA9}'), - Range::new('\u{16A60}', '\u{16A69}'), - Range::new('\u{16AC0}', '\u{16AC9}'), - Range::new('\u{16B50}', '\u{16B59}'), - Range::new('\u{1D7CE}', '\u{1D7FF}'), - Range::new('\u{1E140}', '\u{1E149}'), - Range::new('\u{1E2F0}', '\u{1E2F9}'), - Range::new('\u{1E950}', '\u{1E959}'), - Range::new('\u{1FBF0}', '\u{1FBF9}'), -]; - -pub static GRAPH: [Range; 9] = [ - Range::new('\u{21}', '\u{7E}'), - Range::new('\u{A1}', '\u{167F}'), - Range::new('\u{1681}', '\u{1FFF}'), - Range::new('\u{200B}', '\u{2027}'), - Range::new('\u{202A}', '\u{202E}'), - Range::new('\u{2030}', '\u{205E}'), - Range::new('\u{2060}', '\u{2FFF}'), - Range::new('\u{3001}', '\u{D7FF}'), - Range::new('\u{E000}', '\u{10FFFF}'), -]; - -pub static LOWER: [Range; 668] = [ - Range::new('\u{61}', '\u{7A}'), - Range::new('\u{AA}', '\u{AA}'), - Range::new('\u{B5}', '\u{B5}'), - Range::new('\u{BA}', '\u{BA}'), - Range::new('\u{DF}', '\u{F6}'), - Range::new('\u{F8}', '\u{FF}'), - Range::new('\u{101}', '\u{101}'), - Range::new('\u{103}', '\u{103}'), - Range::new('\u{105}', '\u{105}'), - Range::new('\u{107}', '\u{107}'), - Range::new('\u{109}', '\u{109}'), - Range::new('\u{10B}', '\u{10B}'), - Range::new('\u{10D}', '\u{10D}'), - Range::new('\u{10F}', '\u{10F}'), - Range::new('\u{111}', '\u{111}'), - Range::new('\u{113}', '\u{113}'), - Range::new('\u{115}', '\u{115}'), - Range::new('\u{117}', '\u{117}'), - Range::new('\u{119}', '\u{119}'), - Range::new('\u{11B}', '\u{11B}'), - Range::new('\u{11D}', '\u{11D}'), - Range::new('\u{11F}', '\u{11F}'), - Range::new('\u{121}', '\u{121}'), - Range::new('\u{123}', '\u{123}'), - Range::new('\u{125}', '\u{125}'), - Range::new('\u{127}', '\u{127}'), - Range::new('\u{129}', '\u{129}'), - Range::new('\u{12B}', '\u{12B}'), - Range::new('\u{12D}', '\u{12D}'), - Range::new('\u{12F}', '\u{12F}'), - Range::new('\u{131}', '\u{131}'), - Range::new('\u{133}', '\u{133}'), - Range::new('\u{135}', '\u{135}'), - Range::new('\u{137}', '\u{138}'), - Range::new('\u{13A}', '\u{13A}'), - Range::new('\u{13C}', '\u{13C}'), - Range::new('\u{13E}', '\u{13E}'), - Range::new('\u{140}', '\u{140}'), - Range::new('\u{142}', '\u{142}'), - Range::new('\u{144}', '\u{144}'), - Range::new('\u{146}', '\u{146}'), - Range::new('\u{148}', '\u{149}'), - Range::new('\u{14B}', '\u{14B}'), - Range::new('\u{14D}', '\u{14D}'), - Range::new('\u{14F}', '\u{14F}'), - Range::new('\u{151}', '\u{151}'), - Range::new('\u{153}', '\u{153}'), - Range::new('\u{155}', '\u{155}'), - Range::new('\u{157}', '\u{157}'), - Range::new('\u{159}', '\u{159}'), - Range::new('\u{15B}', '\u{15B}'), - Range::new('\u{15D}', '\u{15D}'), - Range::new('\u{15F}', '\u{15F}'), - Range::new('\u{161}', '\u{161}'), - Range::new('\u{163}', '\u{163}'), - Range::new('\u{165}', '\u{165}'), - Range::new('\u{167}', '\u{167}'), - Range::new('\u{169}', '\u{169}'), - Range::new('\u{16B}', '\u{16B}'), - Range::new('\u{16D}', '\u{16D}'), - Range::new('\u{16F}', '\u{16F}'), - Range::new('\u{171}', '\u{171}'), - Range::new('\u{173}', '\u{173}'), - Range::new('\u{175}', '\u{175}'), - Range::new('\u{177}', '\u{177}'), - Range::new('\u{17A}', '\u{17A}'), - Range::new('\u{17C}', '\u{17C}'), - Range::new('\u{17E}', '\u{180}'), - Range::new('\u{183}', '\u{183}'), - Range::new('\u{185}', '\u{185}'), - Range::new('\u{188}', '\u{188}'), - Range::new('\u{18C}', '\u{18D}'), - Range::new('\u{192}', '\u{192}'), - Range::new('\u{195}', '\u{195}'), - Range::new('\u{199}', '\u{19B}'), - Range::new('\u{19E}', '\u{19E}'), - Range::new('\u{1A1}', '\u{1A1}'), - Range::new('\u{1A3}', '\u{1A3}'), - Range::new('\u{1A5}', '\u{1A5}'), - Range::new('\u{1A8}', '\u{1A8}'), - Range::new('\u{1AA}', '\u{1AB}'), - Range::new('\u{1AD}', '\u{1AD}'), - Range::new('\u{1B0}', '\u{1B0}'), - Range::new('\u{1B4}', '\u{1B4}'), - Range::new('\u{1B6}', '\u{1B6}'), - Range::new('\u{1B9}', '\u{1BA}'), - Range::new('\u{1BD}', '\u{1BF}'), - Range::new('\u{1C6}', '\u{1C6}'), - Range::new('\u{1C9}', '\u{1C9}'), - Range::new('\u{1CC}', '\u{1CC}'), - Range::new('\u{1CE}', '\u{1CE}'), - Range::new('\u{1D0}', '\u{1D0}'), - Range::new('\u{1D2}', '\u{1D2}'), - Range::new('\u{1D4}', '\u{1D4}'), - Range::new('\u{1D6}', '\u{1D6}'), - Range::new('\u{1D8}', '\u{1D8}'), - Range::new('\u{1DA}', '\u{1DA}'), - Range::new('\u{1DC}', '\u{1DD}'), - Range::new('\u{1DF}', '\u{1DF}'), - Range::new('\u{1E1}', '\u{1E1}'), - Range::new('\u{1E3}', '\u{1E3}'), - Range::new('\u{1E5}', '\u{1E5}'), - Range::new('\u{1E7}', '\u{1E7}'), - Range::new('\u{1E9}', '\u{1E9}'), - Range::new('\u{1EB}', '\u{1EB}'), - Range::new('\u{1ED}', '\u{1ED}'), - Range::new('\u{1EF}', '\u{1F0}'), - Range::new('\u{1F3}', '\u{1F3}'), - Range::new('\u{1F5}', '\u{1F5}'), - Range::new('\u{1F9}', '\u{1F9}'), - Range::new('\u{1FB}', '\u{1FB}'), - Range::new('\u{1FD}', '\u{1FD}'), - Range::new('\u{1FF}', '\u{1FF}'), - Range::new('\u{201}', '\u{201}'), - Range::new('\u{203}', '\u{203}'), - Range::new('\u{205}', '\u{205}'), - Range::new('\u{207}', '\u{207}'), - Range::new('\u{209}', '\u{209}'), - Range::new('\u{20B}', '\u{20B}'), - Range::new('\u{20D}', '\u{20D}'), - Range::new('\u{20F}', '\u{20F}'), - Range::new('\u{211}', '\u{211}'), - Range::new('\u{213}', '\u{213}'), - Range::new('\u{215}', '\u{215}'), - Range::new('\u{217}', '\u{217}'), - Range::new('\u{219}', '\u{219}'), - Range::new('\u{21B}', '\u{21B}'), - Range::new('\u{21D}', '\u{21D}'), - Range::new('\u{21F}', '\u{21F}'), - Range::new('\u{221}', '\u{221}'), - Range::new('\u{223}', '\u{223}'), - Range::new('\u{225}', '\u{225}'), - Range::new('\u{227}', '\u{227}'), - Range::new('\u{229}', '\u{229}'), - Range::new('\u{22B}', '\u{22B}'), - Range::new('\u{22D}', '\u{22D}'), - Range::new('\u{22F}', '\u{22F}'), - Range::new('\u{231}', '\u{231}'), - Range::new('\u{233}', '\u{239}'), - Range::new('\u{23C}', '\u{23C}'), - Range::new('\u{23F}', '\u{240}'), - Range::new('\u{242}', '\u{242}'), - Range::new('\u{247}', '\u{247}'), - Range::new('\u{249}', '\u{249}'), - Range::new('\u{24B}', '\u{24B}'), - Range::new('\u{24D}', '\u{24D}'), - Range::new('\u{24F}', '\u{293}'), - Range::new('\u{295}', '\u{2B8}'), - Range::new('\u{2C0}', '\u{2C1}'), - Range::new('\u{2E0}', '\u{2E4}'), - Range::new('\u{345}', '\u{345}'), - Range::new('\u{371}', '\u{371}'), - Range::new('\u{373}', '\u{373}'), - Range::new('\u{377}', '\u{377}'), - Range::new('\u{37A}', '\u{37D}'), - Range::new('\u{390}', '\u{390}'), - Range::new('\u{3AC}', '\u{3CE}'), - Range::new('\u{3D0}', '\u{3D1}'), - Range::new('\u{3D5}', '\u{3D7}'), - Range::new('\u{3D9}', '\u{3D9}'), - Range::new('\u{3DB}', '\u{3DB}'), - Range::new('\u{3DD}', '\u{3DD}'), - Range::new('\u{3DF}', '\u{3DF}'), - Range::new('\u{3E1}', '\u{3E1}'), - Range::new('\u{3E3}', '\u{3E3}'), - Range::new('\u{3E5}', '\u{3E5}'), - Range::new('\u{3E7}', '\u{3E7}'), - Range::new('\u{3E9}', '\u{3E9}'), - Range::new('\u{3EB}', '\u{3EB}'), - Range::new('\u{3ED}', '\u{3ED}'), - Range::new('\u{3EF}', '\u{3F3}'), - Range::new('\u{3F5}', '\u{3F5}'), - Range::new('\u{3F8}', '\u{3F8}'), - Range::new('\u{3FB}', '\u{3FC}'), - Range::new('\u{430}', '\u{45F}'), - Range::new('\u{461}', '\u{461}'), - Range::new('\u{463}', '\u{463}'), - Range::new('\u{465}', '\u{465}'), - Range::new('\u{467}', '\u{467}'), - Range::new('\u{469}', '\u{469}'), - Range::new('\u{46B}', '\u{46B}'), - Range::new('\u{46D}', '\u{46D}'), - Range::new('\u{46F}', '\u{46F}'), - Range::new('\u{471}', '\u{471}'), - Range::new('\u{473}', '\u{473}'), - Range::new('\u{475}', '\u{475}'), - Range::new('\u{477}', '\u{477}'), - Range::new('\u{479}', '\u{479}'), - Range::new('\u{47B}', '\u{47B}'), - Range::new('\u{47D}', '\u{47D}'), - Range::new('\u{47F}', '\u{47F}'), - Range::new('\u{481}', '\u{481}'), - Range::new('\u{48B}', '\u{48B}'), - Range::new('\u{48D}', '\u{48D}'), - Range::new('\u{48F}', '\u{48F}'), - Range::new('\u{491}', '\u{491}'), - Range::new('\u{493}', '\u{493}'), - Range::new('\u{495}', '\u{495}'), - Range::new('\u{497}', '\u{497}'), - Range::new('\u{499}', '\u{499}'), - Range::new('\u{49B}', '\u{49B}'), - Range::new('\u{49D}', '\u{49D}'), - Range::new('\u{49F}', '\u{49F}'), - Range::new('\u{4A1}', '\u{4A1}'), - Range::new('\u{4A3}', '\u{4A3}'), - Range::new('\u{4A5}', '\u{4A5}'), - Range::new('\u{4A7}', '\u{4A7}'), - Range::new('\u{4A9}', '\u{4A9}'), - Range::new('\u{4AB}', '\u{4AB}'), - Range::new('\u{4AD}', '\u{4AD}'), - Range::new('\u{4AF}', '\u{4AF}'), - Range::new('\u{4B1}', '\u{4B1}'), - Range::new('\u{4B3}', '\u{4B3}'), - Range::new('\u{4B5}', '\u{4B5}'), - Range::new('\u{4B7}', '\u{4B7}'), - Range::new('\u{4B9}', '\u{4B9}'), - Range::new('\u{4BB}', '\u{4BB}'), - Range::new('\u{4BD}', '\u{4BD}'), - Range::new('\u{4BF}', '\u{4BF}'), - Range::new('\u{4C2}', '\u{4C2}'), - Range::new('\u{4C4}', '\u{4C4}'), - Range::new('\u{4C6}', '\u{4C6}'), - Range::new('\u{4C8}', '\u{4C8}'), - Range::new('\u{4CA}', '\u{4CA}'), - Range::new('\u{4CC}', '\u{4CC}'), - Range::new('\u{4CE}', '\u{4CF}'), - Range::new('\u{4D1}', '\u{4D1}'), - Range::new('\u{4D3}', '\u{4D3}'), - Range::new('\u{4D5}', '\u{4D5}'), - Range::new('\u{4D7}', '\u{4D7}'), - Range::new('\u{4D9}', '\u{4D9}'), - Range::new('\u{4DB}', '\u{4DB}'), - Range::new('\u{4DD}', '\u{4DD}'), - Range::new('\u{4DF}', '\u{4DF}'), - Range::new('\u{4E1}', '\u{4E1}'), - Range::new('\u{4E3}', '\u{4E3}'), - Range::new('\u{4E5}', '\u{4E5}'), - Range::new('\u{4E7}', '\u{4E7}'), - Range::new('\u{4E9}', '\u{4E9}'), - Range::new('\u{4EB}', '\u{4EB}'), - Range::new('\u{4ED}', '\u{4ED}'), - Range::new('\u{4EF}', '\u{4EF}'), - Range::new('\u{4F1}', '\u{4F1}'), - Range::new('\u{4F3}', '\u{4F3}'), - Range::new('\u{4F5}', '\u{4F5}'), - Range::new('\u{4F7}', '\u{4F7}'), - Range::new('\u{4F9}', '\u{4F9}'), - Range::new('\u{4FB}', '\u{4FB}'), - Range::new('\u{4FD}', '\u{4FD}'), - Range::new('\u{4FF}', '\u{4FF}'), - Range::new('\u{501}', '\u{501}'), - Range::new('\u{503}', '\u{503}'), - Range::new('\u{505}', '\u{505}'), - Range::new('\u{507}', '\u{507}'), - Range::new('\u{509}', '\u{509}'), - Range::new('\u{50B}', '\u{50B}'), - Range::new('\u{50D}', '\u{50D}'), - Range::new('\u{50F}', '\u{50F}'), - Range::new('\u{511}', '\u{511}'), - Range::new('\u{513}', '\u{513}'), - Range::new('\u{515}', '\u{515}'), - Range::new('\u{517}', '\u{517}'), - Range::new('\u{519}', '\u{519}'), - Range::new('\u{51B}', '\u{51B}'), - Range::new('\u{51D}', '\u{51D}'), - Range::new('\u{51F}', '\u{51F}'), - Range::new('\u{521}', '\u{521}'), - Range::new('\u{523}', '\u{523}'), - Range::new('\u{525}', '\u{525}'), - Range::new('\u{527}', '\u{527}'), - Range::new('\u{529}', '\u{529}'), - Range::new('\u{52B}', '\u{52B}'), - Range::new('\u{52D}', '\u{52D}'), - Range::new('\u{52F}', '\u{52F}'), - Range::new('\u{560}', '\u{588}'), - Range::new('\u{10D0}', '\u{10FA}'), - Range::new('\u{10FD}', '\u{10FF}'), - Range::new('\u{13F8}', '\u{13FD}'), - Range::new('\u{1C80}', '\u{1C88}'), - Range::new('\u{1D00}', '\u{1DBF}'), - Range::new('\u{1E01}', '\u{1E01}'), - Range::new('\u{1E03}', '\u{1E03}'), - Range::new('\u{1E05}', '\u{1E05}'), - Range::new('\u{1E07}', '\u{1E07}'), - Range::new('\u{1E09}', '\u{1E09}'), - Range::new('\u{1E0B}', '\u{1E0B}'), - Range::new('\u{1E0D}', '\u{1E0D}'), - Range::new('\u{1E0F}', '\u{1E0F}'), - Range::new('\u{1E11}', '\u{1E11}'), - Range::new('\u{1E13}', '\u{1E13}'), - Range::new('\u{1E15}', '\u{1E15}'), - Range::new('\u{1E17}', '\u{1E17}'), - Range::new('\u{1E19}', '\u{1E19}'), - Range::new('\u{1E1B}', '\u{1E1B}'), - Range::new('\u{1E1D}', '\u{1E1D}'), - Range::new('\u{1E1F}', '\u{1E1F}'), - Range::new('\u{1E21}', '\u{1E21}'), - Range::new('\u{1E23}', '\u{1E23}'), - Range::new('\u{1E25}', '\u{1E25}'), - Range::new('\u{1E27}', '\u{1E27}'), - Range::new('\u{1E29}', '\u{1E29}'), - Range::new('\u{1E2B}', '\u{1E2B}'), - Range::new('\u{1E2D}', '\u{1E2D}'), - Range::new('\u{1E2F}', '\u{1E2F}'), - Range::new('\u{1E31}', '\u{1E31}'), - Range::new('\u{1E33}', '\u{1E33}'), - Range::new('\u{1E35}', '\u{1E35}'), - Range::new('\u{1E37}', '\u{1E37}'), - Range::new('\u{1E39}', '\u{1E39}'), - Range::new('\u{1E3B}', '\u{1E3B}'), - Range::new('\u{1E3D}', '\u{1E3D}'), - Range::new('\u{1E3F}', '\u{1E3F}'), - Range::new('\u{1E41}', '\u{1E41}'), - Range::new('\u{1E43}', '\u{1E43}'), - Range::new('\u{1E45}', '\u{1E45}'), - Range::new('\u{1E47}', '\u{1E47}'), - Range::new('\u{1E49}', '\u{1E49}'), - Range::new('\u{1E4B}', '\u{1E4B}'), - Range::new('\u{1E4D}', '\u{1E4D}'), - Range::new('\u{1E4F}', '\u{1E4F}'), - Range::new('\u{1E51}', '\u{1E51}'), - Range::new('\u{1E53}', '\u{1E53}'), - Range::new('\u{1E55}', '\u{1E55}'), - Range::new('\u{1E57}', '\u{1E57}'), - Range::new('\u{1E59}', '\u{1E59}'), - Range::new('\u{1E5B}', '\u{1E5B}'), - Range::new('\u{1E5D}', '\u{1E5D}'), - Range::new('\u{1E5F}', '\u{1E5F}'), - Range::new('\u{1E61}', '\u{1E61}'), - Range::new('\u{1E63}', '\u{1E63}'), - Range::new('\u{1E65}', '\u{1E65}'), - Range::new('\u{1E67}', '\u{1E67}'), - Range::new('\u{1E69}', '\u{1E69}'), - Range::new('\u{1E6B}', '\u{1E6B}'), - Range::new('\u{1E6D}', '\u{1E6D}'), - Range::new('\u{1E6F}', '\u{1E6F}'), - Range::new('\u{1E71}', '\u{1E71}'), - Range::new('\u{1E73}', '\u{1E73}'), - Range::new('\u{1E75}', '\u{1E75}'), - Range::new('\u{1E77}', '\u{1E77}'), - Range::new('\u{1E79}', '\u{1E79}'), - Range::new('\u{1E7B}', '\u{1E7B}'), - Range::new('\u{1E7D}', '\u{1E7D}'), - Range::new('\u{1E7F}', '\u{1E7F}'), - Range::new('\u{1E81}', '\u{1E81}'), - Range::new('\u{1E83}', '\u{1E83}'), - Range::new('\u{1E85}', '\u{1E85}'), - Range::new('\u{1E87}', '\u{1E87}'), - Range::new('\u{1E89}', '\u{1E89}'), - Range::new('\u{1E8B}', '\u{1E8B}'), - Range::new('\u{1E8D}', '\u{1E8D}'), - Range::new('\u{1E8F}', '\u{1E8F}'), - Range::new('\u{1E91}', '\u{1E91}'), - Range::new('\u{1E93}', '\u{1E93}'), - Range::new('\u{1E95}', '\u{1E9D}'), - Range::new('\u{1E9F}', '\u{1E9F}'), - Range::new('\u{1EA1}', '\u{1EA1}'), - Range::new('\u{1EA3}', '\u{1EA3}'), - Range::new('\u{1EA5}', '\u{1EA5}'), - Range::new('\u{1EA7}', '\u{1EA7}'), - Range::new('\u{1EA9}', '\u{1EA9}'), - Range::new('\u{1EAB}', '\u{1EAB}'), - Range::new('\u{1EAD}', '\u{1EAD}'), - Range::new('\u{1EAF}', '\u{1EAF}'), - Range::new('\u{1EB1}', '\u{1EB1}'), - Range::new('\u{1EB3}', '\u{1EB3}'), - Range::new('\u{1EB5}', '\u{1EB5}'), - Range::new('\u{1EB7}', '\u{1EB7}'), - Range::new('\u{1EB9}', '\u{1EB9}'), - Range::new('\u{1EBB}', '\u{1EBB}'), - Range::new('\u{1EBD}', '\u{1EBD}'), - Range::new('\u{1EBF}', '\u{1EBF}'), - Range::new('\u{1EC1}', '\u{1EC1}'), - Range::new('\u{1EC3}', '\u{1EC3}'), - Range::new('\u{1EC5}', '\u{1EC5}'), - Range::new('\u{1EC7}', '\u{1EC7}'), - Range::new('\u{1EC9}', '\u{1EC9}'), - Range::new('\u{1ECB}', '\u{1ECB}'), - Range::new('\u{1ECD}', '\u{1ECD}'), - Range::new('\u{1ECF}', '\u{1ECF}'), - Range::new('\u{1ED1}', '\u{1ED1}'), - Range::new('\u{1ED3}', '\u{1ED3}'), - Range::new('\u{1ED5}', '\u{1ED5}'), - Range::new('\u{1ED7}', '\u{1ED7}'), - Range::new('\u{1ED9}', '\u{1ED9}'), - Range::new('\u{1EDB}', '\u{1EDB}'), - Range::new('\u{1EDD}', '\u{1EDD}'), - Range::new('\u{1EDF}', '\u{1EDF}'), - Range::new('\u{1EE1}', '\u{1EE1}'), - Range::new('\u{1EE3}', '\u{1EE3}'), - Range::new('\u{1EE5}', '\u{1EE5}'), - Range::new('\u{1EE7}', '\u{1EE7}'), - Range::new('\u{1EE9}', '\u{1EE9}'), - Range::new('\u{1EEB}', '\u{1EEB}'), - Range::new('\u{1EED}', '\u{1EED}'), - Range::new('\u{1EEF}', '\u{1EEF}'), - Range::new('\u{1EF1}', '\u{1EF1}'), - Range::new('\u{1EF3}', '\u{1EF3}'), - Range::new('\u{1EF5}', '\u{1EF5}'), - Range::new('\u{1EF7}', '\u{1EF7}'), - Range::new('\u{1EF9}', '\u{1EF9}'), - Range::new('\u{1EFB}', '\u{1EFB}'), - Range::new('\u{1EFD}', '\u{1EFD}'), - Range::new('\u{1EFF}', '\u{1F07}'), - Range::new('\u{1F10}', '\u{1F15}'), - Range::new('\u{1F20}', '\u{1F27}'), - Range::new('\u{1F30}', '\u{1F37}'), - Range::new('\u{1F40}', '\u{1F45}'), - Range::new('\u{1F50}', '\u{1F57}'), - Range::new('\u{1F60}', '\u{1F67}'), - Range::new('\u{1F70}', '\u{1F7D}'), - Range::new('\u{1F80}', '\u{1F87}'), - Range::new('\u{1F90}', '\u{1F97}'), - Range::new('\u{1FA0}', '\u{1FA7}'), - Range::new('\u{1FB0}', '\u{1FB4}'), - Range::new('\u{1FB6}', '\u{1FB7}'), - Range::new('\u{1FBE}', '\u{1FBE}'), - Range::new('\u{1FC2}', '\u{1FC4}'), - Range::new('\u{1FC6}', '\u{1FC7}'), - Range::new('\u{1FD0}', '\u{1FD3}'), - Range::new('\u{1FD6}', '\u{1FD7}'), - Range::new('\u{1FE0}', '\u{1FE7}'), - Range::new('\u{1FF2}', '\u{1FF4}'), - Range::new('\u{1FF6}', '\u{1FF7}'), - Range::new('\u{2071}', '\u{2071}'), - Range::new('\u{207F}', '\u{207F}'), - Range::new('\u{2090}', '\u{209C}'), - Range::new('\u{210A}', '\u{210A}'), - Range::new('\u{210E}', '\u{210F}'), - Range::new('\u{2113}', '\u{2113}'), - Range::new('\u{212F}', '\u{212F}'), - Range::new('\u{2134}', '\u{2134}'), - Range::new('\u{2139}', '\u{2139}'), - Range::new('\u{213C}', '\u{213D}'), - Range::new('\u{2146}', '\u{2149}'), - Range::new('\u{214E}', '\u{214E}'), - Range::new('\u{2170}', '\u{217F}'), - Range::new('\u{2184}', '\u{2184}'), - Range::new('\u{24D0}', '\u{24E9}'), - Range::new('\u{2C30}', '\u{2C5F}'), - Range::new('\u{2C61}', '\u{2C61}'), - Range::new('\u{2C65}', '\u{2C66}'), - Range::new('\u{2C68}', '\u{2C68}'), - Range::new('\u{2C6A}', '\u{2C6A}'), - Range::new('\u{2C6C}', '\u{2C6C}'), - Range::new('\u{2C71}', '\u{2C71}'), - Range::new('\u{2C73}', '\u{2C74}'), - Range::new('\u{2C76}', '\u{2C7D}'), - Range::new('\u{2C81}', '\u{2C81}'), - Range::new('\u{2C83}', '\u{2C83}'), - Range::new('\u{2C85}', '\u{2C85}'), - Range::new('\u{2C87}', '\u{2C87}'), - Range::new('\u{2C89}', '\u{2C89}'), - Range::new('\u{2C8B}', '\u{2C8B}'), - Range::new('\u{2C8D}', '\u{2C8D}'), - Range::new('\u{2C8F}', '\u{2C8F}'), - Range::new('\u{2C91}', '\u{2C91}'), - Range::new('\u{2C93}', '\u{2C93}'), - Range::new('\u{2C95}', '\u{2C95}'), - Range::new('\u{2C97}', '\u{2C97}'), - Range::new('\u{2C99}', '\u{2C99}'), - Range::new('\u{2C9B}', '\u{2C9B}'), - Range::new('\u{2C9D}', '\u{2C9D}'), - Range::new('\u{2C9F}', '\u{2C9F}'), - Range::new('\u{2CA1}', '\u{2CA1}'), - Range::new('\u{2CA3}', '\u{2CA3}'), - Range::new('\u{2CA5}', '\u{2CA5}'), - Range::new('\u{2CA7}', '\u{2CA7}'), - Range::new('\u{2CA9}', '\u{2CA9}'), - Range::new('\u{2CAB}', '\u{2CAB}'), - Range::new('\u{2CAD}', '\u{2CAD}'), - Range::new('\u{2CAF}', '\u{2CAF}'), - Range::new('\u{2CB1}', '\u{2CB1}'), - Range::new('\u{2CB3}', '\u{2CB3}'), - Range::new('\u{2CB5}', '\u{2CB5}'), - Range::new('\u{2CB7}', '\u{2CB7}'), - Range::new('\u{2CB9}', '\u{2CB9}'), - Range::new('\u{2CBB}', '\u{2CBB}'), - Range::new('\u{2CBD}', '\u{2CBD}'), - Range::new('\u{2CBF}', '\u{2CBF}'), - Range::new('\u{2CC1}', '\u{2CC1}'), - Range::new('\u{2CC3}', '\u{2CC3}'), - Range::new('\u{2CC5}', '\u{2CC5}'), - Range::new('\u{2CC7}', '\u{2CC7}'), - Range::new('\u{2CC9}', '\u{2CC9}'), - Range::new('\u{2CCB}', '\u{2CCB}'), - Range::new('\u{2CCD}', '\u{2CCD}'), - Range::new('\u{2CCF}', '\u{2CCF}'), - Range::new('\u{2CD1}', '\u{2CD1}'), - Range::new('\u{2CD3}', '\u{2CD3}'), - Range::new('\u{2CD5}', '\u{2CD5}'), - Range::new('\u{2CD7}', '\u{2CD7}'), - Range::new('\u{2CD9}', '\u{2CD9}'), - Range::new('\u{2CDB}', '\u{2CDB}'), - Range::new('\u{2CDD}', '\u{2CDD}'), - Range::new('\u{2CDF}', '\u{2CDF}'), - Range::new('\u{2CE1}', '\u{2CE1}'), - Range::new('\u{2CE3}', '\u{2CE4}'), - Range::new('\u{2CEC}', '\u{2CEC}'), - Range::new('\u{2CEE}', '\u{2CEE}'), - Range::new('\u{2CF3}', '\u{2CF3}'), - Range::new('\u{2D00}', '\u{2D25}'), - Range::new('\u{2D27}', '\u{2D27}'), - Range::new('\u{2D2D}', '\u{2D2D}'), - Range::new('\u{A641}', '\u{A641}'), - Range::new('\u{A643}', '\u{A643}'), - Range::new('\u{A645}', '\u{A645}'), - Range::new('\u{A647}', '\u{A647}'), - Range::new('\u{A649}', '\u{A649}'), - Range::new('\u{A64B}', '\u{A64B}'), - Range::new('\u{A64D}', '\u{A64D}'), - Range::new('\u{A64F}', '\u{A64F}'), - Range::new('\u{A651}', '\u{A651}'), - Range::new('\u{A653}', '\u{A653}'), - Range::new('\u{A655}', '\u{A655}'), - Range::new('\u{A657}', '\u{A657}'), - Range::new('\u{A659}', '\u{A659}'), - Range::new('\u{A65B}', '\u{A65B}'), - Range::new('\u{A65D}', '\u{A65D}'), - Range::new('\u{A65F}', '\u{A65F}'), - Range::new('\u{A661}', '\u{A661}'), - Range::new('\u{A663}', '\u{A663}'), - Range::new('\u{A665}', '\u{A665}'), - Range::new('\u{A667}', '\u{A667}'), - Range::new('\u{A669}', '\u{A669}'), - Range::new('\u{A66B}', '\u{A66B}'), - Range::new('\u{A66D}', '\u{A66D}'), - Range::new('\u{A681}', '\u{A681}'), - Range::new('\u{A683}', '\u{A683}'), - Range::new('\u{A685}', '\u{A685}'), - Range::new('\u{A687}', '\u{A687}'), - Range::new('\u{A689}', '\u{A689}'), - Range::new('\u{A68B}', '\u{A68B}'), - Range::new('\u{A68D}', '\u{A68D}'), - Range::new('\u{A68F}', '\u{A68F}'), - Range::new('\u{A691}', '\u{A691}'), - Range::new('\u{A693}', '\u{A693}'), - Range::new('\u{A695}', '\u{A695}'), - Range::new('\u{A697}', '\u{A697}'), - Range::new('\u{A699}', '\u{A699}'), - Range::new('\u{A69B}', '\u{A69D}'), - Range::new('\u{A723}', '\u{A723}'), - Range::new('\u{A725}', '\u{A725}'), - Range::new('\u{A727}', '\u{A727}'), - Range::new('\u{A729}', '\u{A729}'), - Range::new('\u{A72B}', '\u{A72B}'), - Range::new('\u{A72D}', '\u{A72D}'), - Range::new('\u{A72F}', '\u{A731}'), - Range::new('\u{A733}', '\u{A733}'), - Range::new('\u{A735}', '\u{A735}'), - Range::new('\u{A737}', '\u{A737}'), - Range::new('\u{A739}', '\u{A739}'), - Range::new('\u{A73B}', '\u{A73B}'), - Range::new('\u{A73D}', '\u{A73D}'), - Range::new('\u{A73F}', '\u{A73F}'), - Range::new('\u{A741}', '\u{A741}'), - Range::new('\u{A743}', '\u{A743}'), - Range::new('\u{A745}', '\u{A745}'), - Range::new('\u{A747}', '\u{A747}'), - Range::new('\u{A749}', '\u{A749}'), - Range::new('\u{A74B}', '\u{A74B}'), - Range::new('\u{A74D}', '\u{A74D}'), - Range::new('\u{A74F}', '\u{A74F}'), - Range::new('\u{A751}', '\u{A751}'), - Range::new('\u{A753}', '\u{A753}'), - Range::new('\u{A755}', '\u{A755}'), - Range::new('\u{A757}', '\u{A757}'), - Range::new('\u{A759}', '\u{A759}'), - Range::new('\u{A75B}', '\u{A75B}'), - Range::new('\u{A75D}', '\u{A75D}'), - Range::new('\u{A75F}', '\u{A75F}'), - Range::new('\u{A761}', '\u{A761}'), - Range::new('\u{A763}', '\u{A763}'), - Range::new('\u{A765}', '\u{A765}'), - Range::new('\u{A767}', '\u{A767}'), - Range::new('\u{A769}', '\u{A769}'), - Range::new('\u{A76B}', '\u{A76B}'), - Range::new('\u{A76D}', '\u{A76D}'), - Range::new('\u{A76F}', '\u{A778}'), - Range::new('\u{A77A}', '\u{A77A}'), - Range::new('\u{A77C}', '\u{A77C}'), - Range::new('\u{A77F}', '\u{A77F}'), - Range::new('\u{A781}', '\u{A781}'), - Range::new('\u{A783}', '\u{A783}'), - Range::new('\u{A785}', '\u{A785}'), - Range::new('\u{A787}', '\u{A787}'), - Range::new('\u{A78C}', '\u{A78C}'), - Range::new('\u{A78E}', '\u{A78E}'), - Range::new('\u{A791}', '\u{A791}'), - Range::new('\u{A793}', '\u{A795}'), - Range::new('\u{A797}', '\u{A797}'), - Range::new('\u{A799}', '\u{A799}'), - Range::new('\u{A79B}', '\u{A79B}'), - Range::new('\u{A79D}', '\u{A79D}'), - Range::new('\u{A79F}', '\u{A79F}'), - Range::new('\u{A7A1}', '\u{A7A1}'), - Range::new('\u{A7A3}', '\u{A7A3}'), - Range::new('\u{A7A5}', '\u{A7A5}'), - Range::new('\u{A7A7}', '\u{A7A7}'), - Range::new('\u{A7A9}', '\u{A7A9}'), - Range::new('\u{A7AF}', '\u{A7AF}'), - Range::new('\u{A7B5}', '\u{A7B5}'), - Range::new('\u{A7B7}', '\u{A7B7}'), - Range::new('\u{A7B9}', '\u{A7B9}'), - Range::new('\u{A7BB}', '\u{A7BB}'), - Range::new('\u{A7BD}', '\u{A7BD}'), - Range::new('\u{A7BF}', '\u{A7BF}'), - Range::new('\u{A7C1}', '\u{A7C1}'), - Range::new('\u{A7C3}', '\u{A7C3}'), - Range::new('\u{A7C8}', '\u{A7C8}'), - Range::new('\u{A7CA}', '\u{A7CA}'), - Range::new('\u{A7D1}', '\u{A7D1}'), - Range::new('\u{A7D3}', '\u{A7D3}'), - Range::new('\u{A7D5}', '\u{A7D5}'), - Range::new('\u{A7D7}', '\u{A7D7}'), - Range::new('\u{A7D9}', '\u{A7D9}'), - Range::new('\u{A7F6}', '\u{A7F6}'), - Range::new('\u{A7F8}', '\u{A7FA}'), - Range::new('\u{AB30}', '\u{AB5A}'), - Range::new('\u{AB5C}', '\u{AB68}'), - Range::new('\u{AB70}', '\u{ABBF}'), - Range::new('\u{FB00}', '\u{FB06}'), - Range::new('\u{FB13}', '\u{FB17}'), - Range::new('\u{FF41}', '\u{FF5A}'), - Range::new('\u{10428}', '\u{1044F}'), - Range::new('\u{104D8}', '\u{104FB}'), - Range::new('\u{10597}', '\u{105A1}'), - Range::new('\u{105A3}', '\u{105B1}'), - Range::new('\u{105B3}', '\u{105B9}'), - Range::new('\u{105BB}', '\u{105BC}'), - Range::new('\u{10780}', '\u{10780}'), - Range::new('\u{10783}', '\u{10785}'), - Range::new('\u{10787}', '\u{107B0}'), - Range::new('\u{107B2}', '\u{107BA}'), - Range::new('\u{10CC0}', '\u{10CF2}'), - Range::new('\u{118C0}', '\u{118DF}'), - Range::new('\u{16E60}', '\u{16E7F}'), - Range::new('\u{1D41A}', '\u{1D433}'), - Range::new('\u{1D44E}', '\u{1D454}'), - Range::new('\u{1D456}', '\u{1D467}'), - Range::new('\u{1D482}', '\u{1D49B}'), - Range::new('\u{1D4B6}', '\u{1D4B9}'), - Range::new('\u{1D4BB}', '\u{1D4BB}'), - Range::new('\u{1D4BD}', '\u{1D4C3}'), - Range::new('\u{1D4C5}', '\u{1D4CF}'), - Range::new('\u{1D4EA}', '\u{1D503}'), - Range::new('\u{1D51E}', '\u{1D537}'), - Range::new('\u{1D552}', '\u{1D56B}'), - Range::new('\u{1D586}', '\u{1D59F}'), - Range::new('\u{1D5BA}', '\u{1D5D3}'), - Range::new('\u{1D5EE}', '\u{1D607}'), - Range::new('\u{1D622}', '\u{1D63B}'), - Range::new('\u{1D656}', '\u{1D66F}'), - Range::new('\u{1D68A}', '\u{1D6A5}'), - Range::new('\u{1D6C2}', '\u{1D6DA}'), - Range::new('\u{1D6DC}', '\u{1D6E1}'), - Range::new('\u{1D6FC}', '\u{1D714}'), - Range::new('\u{1D716}', '\u{1D71B}'), - Range::new('\u{1D736}', '\u{1D74E}'), - Range::new('\u{1D750}', '\u{1D755}'), - Range::new('\u{1D770}', '\u{1D788}'), - Range::new('\u{1D78A}', '\u{1D78F}'), - Range::new('\u{1D7AA}', '\u{1D7C2}'), - Range::new('\u{1D7C4}', '\u{1D7C9}'), - Range::new('\u{1D7CB}', '\u{1D7CB}'), - Range::new('\u{1DF00}', '\u{1DF09}'), - Range::new('\u{1DF0B}', '\u{1DF1E}'), - Range::new('\u{1E922}', '\u{1E943}'), -]; - -pub static PRINT: [Range; 4] = [ - Range::new('\u{20}', '\u{7E}'), - Range::new('\u{A0}', '\u{2027}'), - Range::new('\u{202A}', '\u{D7FF}'), - Range::new('\u{E000}', '\u{10FFFF}'), -]; - -pub static PUNCT: [Range; 189] = [ - Range::new('\u{21}', '\u{23}'), - Range::new('\u{25}', '\u{2A}'), - Range::new('\u{2C}', '\u{2F}'), - Range::new('\u{3A}', '\u{3B}'), - Range::new('\u{3F}', '\u{40}'), - Range::new('\u{5B}', '\u{5D}'), - Range::new('\u{5F}', '\u{5F}'), - Range::new('\u{7B}', '\u{7B}'), - Range::new('\u{7D}', '\u{7D}'), - Range::new('\u{A1}', '\u{A1}'), - Range::new('\u{A7}', '\u{A7}'), - Range::new('\u{AB}', '\u{AB}'), - Range::new('\u{B6}', '\u{B7}'), - Range::new('\u{BB}', '\u{BB}'), - Range::new('\u{BF}', '\u{BF}'), - Range::new('\u{37E}', '\u{37E}'), - Range::new('\u{387}', '\u{387}'), - Range::new('\u{55A}', '\u{55F}'), - Range::new('\u{589}', '\u{58A}'), - Range::new('\u{5BE}', '\u{5BE}'), - Range::new('\u{5C0}', '\u{5C0}'), - Range::new('\u{5C3}', '\u{5C3}'), - Range::new('\u{5C6}', '\u{5C6}'), - Range::new('\u{5F3}', '\u{5F4}'), - Range::new('\u{609}', '\u{60A}'), - Range::new('\u{60C}', '\u{60D}'), - Range::new('\u{61B}', '\u{61B}'), - Range::new('\u{61D}', '\u{61F}'), - Range::new('\u{66A}', '\u{66D}'), - Range::new('\u{6D4}', '\u{6D4}'), - Range::new('\u{700}', '\u{70D}'), - Range::new('\u{7F7}', '\u{7F9}'), - Range::new('\u{830}', '\u{83E}'), - Range::new('\u{85E}', '\u{85E}'), - Range::new('\u{964}', '\u{965}'), - Range::new('\u{970}', '\u{970}'), - Range::new('\u{9FD}', '\u{9FD}'), - Range::new('\u{A76}', '\u{A76}'), - Range::new('\u{AF0}', '\u{AF0}'), - Range::new('\u{C77}', '\u{C77}'), - Range::new('\u{C84}', '\u{C84}'), - Range::new('\u{DF4}', '\u{DF4}'), - Range::new('\u{E4F}', '\u{E4F}'), - Range::new('\u{E5A}', '\u{E5B}'), - Range::new('\u{F04}', '\u{F12}'), - Range::new('\u{F14}', '\u{F14}'), - Range::new('\u{F3A}', '\u{F3D}'), - Range::new('\u{F85}', '\u{F85}'), - Range::new('\u{FD0}', '\u{FD4}'), - Range::new('\u{FD9}', '\u{FDA}'), - Range::new('\u{104A}', '\u{104F}'), - Range::new('\u{10FB}', '\u{10FB}'), - Range::new('\u{1360}', '\u{1368}'), - Range::new('\u{1400}', '\u{1400}'), - Range::new('\u{166E}', '\u{166E}'), - Range::new('\u{169B}', '\u{169C}'), - Range::new('\u{16EB}', '\u{16ED}'), - Range::new('\u{1735}', '\u{1736}'), - Range::new('\u{17D4}', '\u{17D6}'), - Range::new('\u{17D8}', '\u{17DA}'), - Range::new('\u{1800}', '\u{180A}'), - Range::new('\u{1944}', '\u{1945}'), - Range::new('\u{1A1E}', '\u{1A1F}'), - Range::new('\u{1AA0}', '\u{1AA6}'), - Range::new('\u{1AA8}', '\u{1AAD}'), - Range::new('\u{1B5A}', '\u{1B60}'), - Range::new('\u{1B7D}', '\u{1B7E}'), - Range::new('\u{1BFC}', '\u{1BFF}'), - Range::new('\u{1C3B}', '\u{1C3F}'), - Range::new('\u{1C7E}', '\u{1C7F}'), - Range::new('\u{1CC0}', '\u{1CC7}'), - Range::new('\u{1CD3}', '\u{1CD3}'), - Range::new('\u{2010}', '\u{2027}'), - Range::new('\u{2030}', '\u{2043}'), - Range::new('\u{2045}', '\u{2051}'), - Range::new('\u{2053}', '\u{205E}'), - Range::new('\u{207D}', '\u{207E}'), - Range::new('\u{208D}', '\u{208E}'), - Range::new('\u{2308}', '\u{230B}'), - Range::new('\u{2329}', '\u{232A}'), - Range::new('\u{2768}', '\u{2775}'), - Range::new('\u{27C5}', '\u{27C6}'), - Range::new('\u{27E6}', '\u{27EF}'), - Range::new('\u{2983}', '\u{2998}'), - Range::new('\u{29D8}', '\u{29DB}'), - Range::new('\u{29FC}', '\u{29FD}'), - Range::new('\u{2CF9}', '\u{2CFC}'), - Range::new('\u{2CFE}', '\u{2CFF}'), - Range::new('\u{2D70}', '\u{2D70}'), - Range::new('\u{2E00}', '\u{2E2E}'), - Range::new('\u{2E30}', '\u{2E4F}'), - Range::new('\u{2E52}', '\u{2E5D}'), - Range::new('\u{3001}', '\u{3003}'), - Range::new('\u{3008}', '\u{3011}'), - Range::new('\u{3014}', '\u{301F}'), - Range::new('\u{3030}', '\u{3030}'), - Range::new('\u{303D}', '\u{303D}'), - Range::new('\u{30A0}', '\u{30A0}'), - Range::new('\u{30FB}', '\u{30FB}'), - Range::new('\u{A4FE}', '\u{A4FF}'), - Range::new('\u{A60D}', '\u{A60F}'), - Range::new('\u{A673}', '\u{A673}'), - Range::new('\u{A67E}', '\u{A67E}'), - Range::new('\u{A6F2}', '\u{A6F7}'), - Range::new('\u{A874}', '\u{A877}'), - Range::new('\u{A8CE}', '\u{A8CF}'), - Range::new('\u{A8F8}', '\u{A8FA}'), - Range::new('\u{A8FC}', '\u{A8FC}'), - Range::new('\u{A92E}', '\u{A92F}'), - Range::new('\u{A95F}', '\u{A95F}'), - Range::new('\u{A9C1}', '\u{A9CD}'), - Range::new('\u{A9DE}', '\u{A9DF}'), - Range::new('\u{AA5C}', '\u{AA5F}'), - Range::new('\u{AADE}', '\u{AADF}'), - Range::new('\u{AAF0}', '\u{AAF1}'), - Range::new('\u{ABEB}', '\u{ABEB}'), - Range::new('\u{FD3E}', '\u{FD3F}'), - Range::new('\u{FE10}', '\u{FE19}'), - Range::new('\u{FE30}', '\u{FE52}'), - Range::new('\u{FE54}', '\u{FE61}'), - Range::new('\u{FE63}', '\u{FE63}'), - Range::new('\u{FE68}', '\u{FE68}'), - Range::new('\u{FE6A}', '\u{FE6B}'), - Range::new('\u{FF01}', '\u{FF03}'), - Range::new('\u{FF05}', '\u{FF0A}'), - Range::new('\u{FF0C}', '\u{FF0F}'), - Range::new('\u{FF1A}', '\u{FF1B}'), - Range::new('\u{FF1F}', '\u{FF20}'), - Range::new('\u{FF3B}', '\u{FF3D}'), - Range::new('\u{FF3F}', '\u{FF3F}'), - Range::new('\u{FF5B}', '\u{FF5B}'), - Range::new('\u{FF5D}', '\u{FF5D}'), - Range::new('\u{FF5F}', '\u{FF65}'), - Range::new('\u{10100}', '\u{10102}'), - Range::new('\u{1039F}', '\u{1039F}'), - Range::new('\u{103D0}', '\u{103D0}'), - Range::new('\u{1056F}', '\u{1056F}'), - Range::new('\u{10857}', '\u{10857}'), - Range::new('\u{1091F}', '\u{1091F}'), - Range::new('\u{1093F}', '\u{1093F}'), - Range::new('\u{10A50}', '\u{10A58}'), - Range::new('\u{10A7F}', '\u{10A7F}'), - Range::new('\u{10AF0}', '\u{10AF6}'), - Range::new('\u{10B39}', '\u{10B3F}'), - Range::new('\u{10B99}', '\u{10B9C}'), - Range::new('\u{10EAD}', '\u{10EAD}'), - Range::new('\u{10F55}', '\u{10F59}'), - Range::new('\u{10F86}', '\u{10F89}'), - Range::new('\u{11047}', '\u{1104D}'), - Range::new('\u{110BB}', '\u{110BC}'), - Range::new('\u{110BE}', '\u{110C1}'), - Range::new('\u{11140}', '\u{11143}'), - Range::new('\u{11174}', '\u{11175}'), - Range::new('\u{111C5}', '\u{111C8}'), - Range::new('\u{111CD}', '\u{111CD}'), - Range::new('\u{111DB}', '\u{111DB}'), - Range::new('\u{111DD}', '\u{111DF}'), - Range::new('\u{11238}', '\u{1123D}'), - Range::new('\u{112A9}', '\u{112A9}'), - Range::new('\u{1144B}', '\u{1144F}'), - Range::new('\u{1145A}', '\u{1145B}'), - Range::new('\u{1145D}', '\u{1145D}'), - Range::new('\u{114C6}', '\u{114C6}'), - Range::new('\u{115C1}', '\u{115D7}'), - Range::new('\u{11641}', '\u{11643}'), - Range::new('\u{11660}', '\u{1166C}'), - Range::new('\u{116B9}', '\u{116B9}'), - Range::new('\u{1173C}', '\u{1173E}'), - Range::new('\u{1183B}', '\u{1183B}'), - Range::new('\u{11944}', '\u{11946}'), - Range::new('\u{119E2}', '\u{119E2}'), - Range::new('\u{11A3F}', '\u{11A46}'), - Range::new('\u{11A9A}', '\u{11A9C}'), - Range::new('\u{11A9E}', '\u{11AA2}'), - Range::new('\u{11C41}', '\u{11C45}'), - Range::new('\u{11C70}', '\u{11C71}'), - Range::new('\u{11EF7}', '\u{11EF8}'), - Range::new('\u{11FFF}', '\u{11FFF}'), - Range::new('\u{12470}', '\u{12474}'), - Range::new('\u{12FF1}', '\u{12FF2}'), - Range::new('\u{16A6E}', '\u{16A6F}'), - Range::new('\u{16AF5}', '\u{16AF5}'), - Range::new('\u{16B37}', '\u{16B3B}'), - Range::new('\u{16B44}', '\u{16B44}'), - Range::new('\u{16E97}', '\u{16E9A}'), - Range::new('\u{16FE2}', '\u{16FE2}'), - Range::new('\u{1BC9F}', '\u{1BC9F}'), - Range::new('\u{1DA87}', '\u{1DA8B}'), - Range::new('\u{1E95E}', '\u{1E95F}'), -]; - -pub static SPACE: [Range; 10] = [ - Range::new('\u{9}', '\u{D}'), - Range::new('\u{20}', '\u{20}'), - Range::new('\u{85}', '\u{85}'), - Range::new('\u{A0}', '\u{A0}'), - Range::new('\u{1680}', '\u{1680}'), - Range::new('\u{2000}', '\u{200A}'), - Range::new('\u{2028}', '\u{2029}'), - Range::new('\u{202F}', '\u{202F}'), - Range::new('\u{205F}', '\u{205F}'), - Range::new('\u{3000}', '\u{3000}'), -]; - -pub static UPPER: [Range; 651] = [ - Range::new('\u{41}', '\u{5A}'), - Range::new('\u{C0}', '\u{D6}'), - Range::new('\u{D8}', '\u{DE}'), - Range::new('\u{100}', '\u{100}'), - Range::new('\u{102}', '\u{102}'), - Range::new('\u{104}', '\u{104}'), - Range::new('\u{106}', '\u{106}'), - Range::new('\u{108}', '\u{108}'), - Range::new('\u{10A}', '\u{10A}'), - Range::new('\u{10C}', '\u{10C}'), - Range::new('\u{10E}', '\u{10E}'), - Range::new('\u{110}', '\u{110}'), - Range::new('\u{112}', '\u{112}'), - Range::new('\u{114}', '\u{114}'), - Range::new('\u{116}', '\u{116}'), - Range::new('\u{118}', '\u{118}'), - Range::new('\u{11A}', '\u{11A}'), - Range::new('\u{11C}', '\u{11C}'), - Range::new('\u{11E}', '\u{11E}'), - Range::new('\u{120}', '\u{120}'), - Range::new('\u{122}', '\u{122}'), - Range::new('\u{124}', '\u{124}'), - Range::new('\u{126}', '\u{126}'), - Range::new('\u{128}', '\u{128}'), - Range::new('\u{12A}', '\u{12A}'), - Range::new('\u{12C}', '\u{12C}'), - Range::new('\u{12E}', '\u{12E}'), - Range::new('\u{130}', '\u{130}'), - Range::new('\u{132}', '\u{132}'), - Range::new('\u{134}', '\u{134}'), - Range::new('\u{136}', '\u{136}'), - Range::new('\u{139}', '\u{139}'), - Range::new('\u{13B}', '\u{13B}'), - Range::new('\u{13D}', '\u{13D}'), - Range::new('\u{13F}', '\u{13F}'), - Range::new('\u{141}', '\u{141}'), - Range::new('\u{143}', '\u{143}'), - Range::new('\u{145}', '\u{145}'), - Range::new('\u{147}', '\u{147}'), - Range::new('\u{14A}', '\u{14A}'), - Range::new('\u{14C}', '\u{14C}'), - Range::new('\u{14E}', '\u{14E}'), - Range::new('\u{150}', '\u{150}'), - Range::new('\u{152}', '\u{152}'), - Range::new('\u{154}', '\u{154}'), - Range::new('\u{156}', '\u{156}'), - Range::new('\u{158}', '\u{158}'), - Range::new('\u{15A}', '\u{15A}'), - Range::new('\u{15C}', '\u{15C}'), - Range::new('\u{15E}', '\u{15E}'), - Range::new('\u{160}', '\u{160}'), - Range::new('\u{162}', '\u{162}'), - Range::new('\u{164}', '\u{164}'), - Range::new('\u{166}', '\u{166}'), - Range::new('\u{168}', '\u{168}'), - Range::new('\u{16A}', '\u{16A}'), - Range::new('\u{16C}', '\u{16C}'), - Range::new('\u{16E}', '\u{16E}'), - Range::new('\u{170}', '\u{170}'), - Range::new('\u{172}', '\u{172}'), - Range::new('\u{174}', '\u{174}'), - Range::new('\u{176}', '\u{176}'), - Range::new('\u{178}', '\u{179}'), - Range::new('\u{17B}', '\u{17B}'), - Range::new('\u{17D}', '\u{17D}'), - Range::new('\u{181}', '\u{182}'), - Range::new('\u{184}', '\u{184}'), - Range::new('\u{186}', '\u{187}'), - Range::new('\u{189}', '\u{18B}'), - Range::new('\u{18E}', '\u{191}'), - Range::new('\u{193}', '\u{194}'), - Range::new('\u{196}', '\u{198}'), - Range::new('\u{19C}', '\u{19D}'), - Range::new('\u{19F}', '\u{1A0}'), - Range::new('\u{1A2}', '\u{1A2}'), - Range::new('\u{1A4}', '\u{1A4}'), - Range::new('\u{1A6}', '\u{1A7}'), - Range::new('\u{1A9}', '\u{1A9}'), - Range::new('\u{1AC}', '\u{1AC}'), - Range::new('\u{1AE}', '\u{1AF}'), - Range::new('\u{1B1}', '\u{1B3}'), - Range::new('\u{1B5}', '\u{1B5}'), - Range::new('\u{1B7}', '\u{1B8}'), - Range::new('\u{1BC}', '\u{1BC}'), - Range::new('\u{1C4}', '\u{1C4}'), - Range::new('\u{1C7}', '\u{1C7}'), - Range::new('\u{1CA}', '\u{1CA}'), - Range::new('\u{1CD}', '\u{1CD}'), - Range::new('\u{1CF}', '\u{1CF}'), - Range::new('\u{1D1}', '\u{1D1}'), - Range::new('\u{1D3}', '\u{1D3}'), - Range::new('\u{1D5}', '\u{1D5}'), - Range::new('\u{1D7}', '\u{1D7}'), - Range::new('\u{1D9}', '\u{1D9}'), - Range::new('\u{1DB}', '\u{1DB}'), - Range::new('\u{1DE}', '\u{1DE}'), - Range::new('\u{1E0}', '\u{1E0}'), - Range::new('\u{1E2}', '\u{1E2}'), - Range::new('\u{1E4}', '\u{1E4}'), - Range::new('\u{1E6}', '\u{1E6}'), - Range::new('\u{1E8}', '\u{1E8}'), - Range::new('\u{1EA}', '\u{1EA}'), - Range::new('\u{1EC}', '\u{1EC}'), - Range::new('\u{1EE}', '\u{1EE}'), - Range::new('\u{1F1}', '\u{1F1}'), - Range::new('\u{1F4}', '\u{1F4}'), - Range::new('\u{1F6}', '\u{1F8}'), - Range::new('\u{1FA}', '\u{1FA}'), - Range::new('\u{1FC}', '\u{1FC}'), - Range::new('\u{1FE}', '\u{1FE}'), - Range::new('\u{200}', '\u{200}'), - Range::new('\u{202}', '\u{202}'), - Range::new('\u{204}', '\u{204}'), - Range::new('\u{206}', '\u{206}'), - Range::new('\u{208}', '\u{208}'), - Range::new('\u{20A}', '\u{20A}'), - Range::new('\u{20C}', '\u{20C}'), - Range::new('\u{20E}', '\u{20E}'), - Range::new('\u{210}', '\u{210}'), - Range::new('\u{212}', '\u{212}'), - Range::new('\u{214}', '\u{214}'), - Range::new('\u{216}', '\u{216}'), - Range::new('\u{218}', '\u{218}'), - Range::new('\u{21A}', '\u{21A}'), - Range::new('\u{21C}', '\u{21C}'), - Range::new('\u{21E}', '\u{21E}'), - Range::new('\u{220}', '\u{220}'), - Range::new('\u{222}', '\u{222}'), - Range::new('\u{224}', '\u{224}'), - Range::new('\u{226}', '\u{226}'), - Range::new('\u{228}', '\u{228}'), - Range::new('\u{22A}', '\u{22A}'), - Range::new('\u{22C}', '\u{22C}'), - Range::new('\u{22E}', '\u{22E}'), - Range::new('\u{230}', '\u{230}'), - Range::new('\u{232}', '\u{232}'), - Range::new('\u{23A}', '\u{23B}'), - Range::new('\u{23D}', '\u{23E}'), - Range::new('\u{241}', '\u{241}'), - Range::new('\u{243}', '\u{246}'), - Range::new('\u{248}', '\u{248}'), - Range::new('\u{24A}', '\u{24A}'), - Range::new('\u{24C}', '\u{24C}'), - Range::new('\u{24E}', '\u{24E}'), - Range::new('\u{370}', '\u{370}'), - Range::new('\u{372}', '\u{372}'), - Range::new('\u{376}', '\u{376}'), - Range::new('\u{37F}', '\u{37F}'), - Range::new('\u{386}', '\u{386}'), - Range::new('\u{388}', '\u{38A}'), - Range::new('\u{38C}', '\u{38C}'), - Range::new('\u{38E}', '\u{38F}'), - Range::new('\u{391}', '\u{3A1}'), - Range::new('\u{3A3}', '\u{3AB}'), - Range::new('\u{3CF}', '\u{3CF}'), - Range::new('\u{3D2}', '\u{3D4}'), - Range::new('\u{3D8}', '\u{3D8}'), - Range::new('\u{3DA}', '\u{3DA}'), - Range::new('\u{3DC}', '\u{3DC}'), - Range::new('\u{3DE}', '\u{3DE}'), - Range::new('\u{3E0}', '\u{3E0}'), - Range::new('\u{3E2}', '\u{3E2}'), - Range::new('\u{3E4}', '\u{3E4}'), - Range::new('\u{3E6}', '\u{3E6}'), - Range::new('\u{3E8}', '\u{3E8}'), - Range::new('\u{3EA}', '\u{3EA}'), - Range::new('\u{3EC}', '\u{3EC}'), - Range::new('\u{3EE}', '\u{3EE}'), - Range::new('\u{3F4}', '\u{3F4}'), - Range::new('\u{3F7}', '\u{3F7}'), - Range::new('\u{3F9}', '\u{3FA}'), - Range::new('\u{3FD}', '\u{42F}'), - Range::new('\u{460}', '\u{460}'), - Range::new('\u{462}', '\u{462}'), - Range::new('\u{464}', '\u{464}'), - Range::new('\u{466}', '\u{466}'), - Range::new('\u{468}', '\u{468}'), - Range::new('\u{46A}', '\u{46A}'), - Range::new('\u{46C}', '\u{46C}'), - Range::new('\u{46E}', '\u{46E}'), - Range::new('\u{470}', '\u{470}'), - Range::new('\u{472}', '\u{472}'), - Range::new('\u{474}', '\u{474}'), - Range::new('\u{476}', '\u{476}'), - Range::new('\u{478}', '\u{478}'), - Range::new('\u{47A}', '\u{47A}'), - Range::new('\u{47C}', '\u{47C}'), - Range::new('\u{47E}', '\u{47E}'), - Range::new('\u{480}', '\u{480}'), - Range::new('\u{48A}', '\u{48A}'), - Range::new('\u{48C}', '\u{48C}'), - Range::new('\u{48E}', '\u{48E}'), - Range::new('\u{490}', '\u{490}'), - Range::new('\u{492}', '\u{492}'), - Range::new('\u{494}', '\u{494}'), - Range::new('\u{496}', '\u{496}'), - Range::new('\u{498}', '\u{498}'), - Range::new('\u{49A}', '\u{49A}'), - Range::new('\u{49C}', '\u{49C}'), - Range::new('\u{49E}', '\u{49E}'), - Range::new('\u{4A0}', '\u{4A0}'), - Range::new('\u{4A2}', '\u{4A2}'), - Range::new('\u{4A4}', '\u{4A4}'), - Range::new('\u{4A6}', '\u{4A6}'), - Range::new('\u{4A8}', '\u{4A8}'), - Range::new('\u{4AA}', '\u{4AA}'), - Range::new('\u{4AC}', '\u{4AC}'), - Range::new('\u{4AE}', '\u{4AE}'), - Range::new('\u{4B0}', '\u{4B0}'), - Range::new('\u{4B2}', '\u{4B2}'), - Range::new('\u{4B4}', '\u{4B4}'), - Range::new('\u{4B6}', '\u{4B6}'), - Range::new('\u{4B8}', '\u{4B8}'), - Range::new('\u{4BA}', '\u{4BA}'), - Range::new('\u{4BC}', '\u{4BC}'), - Range::new('\u{4BE}', '\u{4BE}'), - Range::new('\u{4C0}', '\u{4C1}'), - Range::new('\u{4C3}', '\u{4C3}'), - Range::new('\u{4C5}', '\u{4C5}'), - Range::new('\u{4C7}', '\u{4C7}'), - Range::new('\u{4C9}', '\u{4C9}'), - Range::new('\u{4CB}', '\u{4CB}'), - Range::new('\u{4CD}', '\u{4CD}'), - Range::new('\u{4D0}', '\u{4D0}'), - Range::new('\u{4D2}', '\u{4D2}'), - Range::new('\u{4D4}', '\u{4D4}'), - Range::new('\u{4D6}', '\u{4D6}'), - Range::new('\u{4D8}', '\u{4D8}'), - Range::new('\u{4DA}', '\u{4DA}'), - Range::new('\u{4DC}', '\u{4DC}'), - Range::new('\u{4DE}', '\u{4DE}'), - Range::new('\u{4E0}', '\u{4E0}'), - Range::new('\u{4E2}', '\u{4E2}'), - Range::new('\u{4E4}', '\u{4E4}'), - Range::new('\u{4E6}', '\u{4E6}'), - Range::new('\u{4E8}', '\u{4E8}'), - Range::new('\u{4EA}', '\u{4EA}'), - Range::new('\u{4EC}', '\u{4EC}'), - Range::new('\u{4EE}', '\u{4EE}'), - Range::new('\u{4F0}', '\u{4F0}'), - Range::new('\u{4F2}', '\u{4F2}'), - Range::new('\u{4F4}', '\u{4F4}'), - Range::new('\u{4F6}', '\u{4F6}'), - Range::new('\u{4F8}', '\u{4F8}'), - Range::new('\u{4FA}', '\u{4FA}'), - Range::new('\u{4FC}', '\u{4FC}'), - Range::new('\u{4FE}', '\u{4FE}'), - Range::new('\u{500}', '\u{500}'), - Range::new('\u{502}', '\u{502}'), - Range::new('\u{504}', '\u{504}'), - Range::new('\u{506}', '\u{506}'), - Range::new('\u{508}', '\u{508}'), - Range::new('\u{50A}', '\u{50A}'), - Range::new('\u{50C}', '\u{50C}'), - Range::new('\u{50E}', '\u{50E}'), - Range::new('\u{510}', '\u{510}'), - Range::new('\u{512}', '\u{512}'), - Range::new('\u{514}', '\u{514}'), - Range::new('\u{516}', '\u{516}'), - Range::new('\u{518}', '\u{518}'), - Range::new('\u{51A}', '\u{51A}'), - Range::new('\u{51C}', '\u{51C}'), - Range::new('\u{51E}', '\u{51E}'), - Range::new('\u{520}', '\u{520}'), - Range::new('\u{522}', '\u{522}'), - Range::new('\u{524}', '\u{524}'), - Range::new('\u{526}', '\u{526}'), - Range::new('\u{528}', '\u{528}'), - Range::new('\u{52A}', '\u{52A}'), - Range::new('\u{52C}', '\u{52C}'), - Range::new('\u{52E}', '\u{52E}'), - Range::new('\u{531}', '\u{556}'), - Range::new('\u{10A0}', '\u{10C5}'), - Range::new('\u{10C7}', '\u{10C7}'), - Range::new('\u{10CD}', '\u{10CD}'), - Range::new('\u{13A0}', '\u{13F5}'), - Range::new('\u{1C90}', '\u{1CBA}'), - Range::new('\u{1CBD}', '\u{1CBF}'), - Range::new('\u{1E00}', '\u{1E00}'), - Range::new('\u{1E02}', '\u{1E02}'), - Range::new('\u{1E04}', '\u{1E04}'), - Range::new('\u{1E06}', '\u{1E06}'), - Range::new('\u{1E08}', '\u{1E08}'), - Range::new('\u{1E0A}', '\u{1E0A}'), - Range::new('\u{1E0C}', '\u{1E0C}'), - Range::new('\u{1E0E}', '\u{1E0E}'), - Range::new('\u{1E10}', '\u{1E10}'), - Range::new('\u{1E12}', '\u{1E12}'), - Range::new('\u{1E14}', '\u{1E14}'), - Range::new('\u{1E16}', '\u{1E16}'), - Range::new('\u{1E18}', '\u{1E18}'), - Range::new('\u{1E1A}', '\u{1E1A}'), - Range::new('\u{1E1C}', '\u{1E1C}'), - Range::new('\u{1E1E}', '\u{1E1E}'), - Range::new('\u{1E20}', '\u{1E20}'), - Range::new('\u{1E22}', '\u{1E22}'), - Range::new('\u{1E24}', '\u{1E24}'), - Range::new('\u{1E26}', '\u{1E26}'), - Range::new('\u{1E28}', '\u{1E28}'), - Range::new('\u{1E2A}', '\u{1E2A}'), - Range::new('\u{1E2C}', '\u{1E2C}'), - Range::new('\u{1E2E}', '\u{1E2E}'), - Range::new('\u{1E30}', '\u{1E30}'), - Range::new('\u{1E32}', '\u{1E32}'), - Range::new('\u{1E34}', '\u{1E34}'), - Range::new('\u{1E36}', '\u{1E36}'), - Range::new('\u{1E38}', '\u{1E38}'), - Range::new('\u{1E3A}', '\u{1E3A}'), - Range::new('\u{1E3C}', '\u{1E3C}'), - Range::new('\u{1E3E}', '\u{1E3E}'), - Range::new('\u{1E40}', '\u{1E40}'), - Range::new('\u{1E42}', '\u{1E42}'), - Range::new('\u{1E44}', '\u{1E44}'), - Range::new('\u{1E46}', '\u{1E46}'), - Range::new('\u{1E48}', '\u{1E48}'), - Range::new('\u{1E4A}', '\u{1E4A}'), - Range::new('\u{1E4C}', '\u{1E4C}'), - Range::new('\u{1E4E}', '\u{1E4E}'), - Range::new('\u{1E50}', '\u{1E50}'), - Range::new('\u{1E52}', '\u{1E52}'), - Range::new('\u{1E54}', '\u{1E54}'), - Range::new('\u{1E56}', '\u{1E56}'), - Range::new('\u{1E58}', '\u{1E58}'), - Range::new('\u{1E5A}', '\u{1E5A}'), - Range::new('\u{1E5C}', '\u{1E5C}'), - Range::new('\u{1E5E}', '\u{1E5E}'), - Range::new('\u{1E60}', '\u{1E60}'), - Range::new('\u{1E62}', '\u{1E62}'), - Range::new('\u{1E64}', '\u{1E64}'), - Range::new('\u{1E66}', '\u{1E66}'), - Range::new('\u{1E68}', '\u{1E68}'), - Range::new('\u{1E6A}', '\u{1E6A}'), - Range::new('\u{1E6C}', '\u{1E6C}'), - Range::new('\u{1E6E}', '\u{1E6E}'), - Range::new('\u{1E70}', '\u{1E70}'), - Range::new('\u{1E72}', '\u{1E72}'), - Range::new('\u{1E74}', '\u{1E74}'), - Range::new('\u{1E76}', '\u{1E76}'), - Range::new('\u{1E78}', '\u{1E78}'), - Range::new('\u{1E7A}', '\u{1E7A}'), - Range::new('\u{1E7C}', '\u{1E7C}'), - Range::new('\u{1E7E}', '\u{1E7E}'), - Range::new('\u{1E80}', '\u{1E80}'), - Range::new('\u{1E82}', '\u{1E82}'), - Range::new('\u{1E84}', '\u{1E84}'), - Range::new('\u{1E86}', '\u{1E86}'), - Range::new('\u{1E88}', '\u{1E88}'), - Range::new('\u{1E8A}', '\u{1E8A}'), - Range::new('\u{1E8C}', '\u{1E8C}'), - Range::new('\u{1E8E}', '\u{1E8E}'), - Range::new('\u{1E90}', '\u{1E90}'), - Range::new('\u{1E92}', '\u{1E92}'), - Range::new('\u{1E94}', '\u{1E94}'), - Range::new('\u{1E9E}', '\u{1E9E}'), - Range::new('\u{1EA0}', '\u{1EA0}'), - Range::new('\u{1EA2}', '\u{1EA2}'), - Range::new('\u{1EA4}', '\u{1EA4}'), - Range::new('\u{1EA6}', '\u{1EA6}'), - Range::new('\u{1EA8}', '\u{1EA8}'), - Range::new('\u{1EAA}', '\u{1EAA}'), - Range::new('\u{1EAC}', '\u{1EAC}'), - Range::new('\u{1EAE}', '\u{1EAE}'), - Range::new('\u{1EB0}', '\u{1EB0}'), - Range::new('\u{1EB2}', '\u{1EB2}'), - Range::new('\u{1EB4}', '\u{1EB4}'), - Range::new('\u{1EB6}', '\u{1EB6}'), - Range::new('\u{1EB8}', '\u{1EB8}'), - Range::new('\u{1EBA}', '\u{1EBA}'), - Range::new('\u{1EBC}', '\u{1EBC}'), - Range::new('\u{1EBE}', '\u{1EBE}'), - Range::new('\u{1EC0}', '\u{1EC0}'), - Range::new('\u{1EC2}', '\u{1EC2}'), - Range::new('\u{1EC4}', '\u{1EC4}'), - Range::new('\u{1EC6}', '\u{1EC6}'), - Range::new('\u{1EC8}', '\u{1EC8}'), - Range::new('\u{1ECA}', '\u{1ECA}'), - Range::new('\u{1ECC}', '\u{1ECC}'), - Range::new('\u{1ECE}', '\u{1ECE}'), - Range::new('\u{1ED0}', '\u{1ED0}'), - Range::new('\u{1ED2}', '\u{1ED2}'), - Range::new('\u{1ED4}', '\u{1ED4}'), - Range::new('\u{1ED6}', '\u{1ED6}'), - Range::new('\u{1ED8}', '\u{1ED8}'), - Range::new('\u{1EDA}', '\u{1EDA}'), - Range::new('\u{1EDC}', '\u{1EDC}'), - Range::new('\u{1EDE}', '\u{1EDE}'), - Range::new('\u{1EE0}', '\u{1EE0}'), - Range::new('\u{1EE2}', '\u{1EE2}'), - Range::new('\u{1EE4}', '\u{1EE4}'), - Range::new('\u{1EE6}', '\u{1EE6}'), - Range::new('\u{1EE8}', '\u{1EE8}'), - Range::new('\u{1EEA}', '\u{1EEA}'), - Range::new('\u{1EEC}', '\u{1EEC}'), - Range::new('\u{1EEE}', '\u{1EEE}'), - Range::new('\u{1EF0}', '\u{1EF0}'), - Range::new('\u{1EF2}', '\u{1EF2}'), - Range::new('\u{1EF4}', '\u{1EF4}'), - Range::new('\u{1EF6}', '\u{1EF6}'), - Range::new('\u{1EF8}', '\u{1EF8}'), - Range::new('\u{1EFA}', '\u{1EFA}'), - Range::new('\u{1EFC}', '\u{1EFC}'), - Range::new('\u{1EFE}', '\u{1EFE}'), - Range::new('\u{1F08}', '\u{1F0F}'), - Range::new('\u{1F18}', '\u{1F1D}'), - Range::new('\u{1F28}', '\u{1F2F}'), - Range::new('\u{1F38}', '\u{1F3F}'), - Range::new('\u{1F48}', '\u{1F4D}'), - Range::new('\u{1F59}', '\u{1F59}'), - Range::new('\u{1F5B}', '\u{1F5B}'), - Range::new('\u{1F5D}', '\u{1F5D}'), - Range::new('\u{1F5F}', '\u{1F5F}'), - Range::new('\u{1F68}', '\u{1F6F}'), - Range::new('\u{1FB8}', '\u{1FBB}'), - Range::new('\u{1FC8}', '\u{1FCB}'), - Range::new('\u{1FD8}', '\u{1FDB}'), - Range::new('\u{1FE8}', '\u{1FEC}'), - Range::new('\u{1FF8}', '\u{1FFB}'), - Range::new('\u{2102}', '\u{2102}'), - Range::new('\u{2107}', '\u{2107}'), - Range::new('\u{210B}', '\u{210D}'), - Range::new('\u{2110}', '\u{2112}'), - Range::new('\u{2115}', '\u{2115}'), - Range::new('\u{2119}', '\u{211D}'), - Range::new('\u{2124}', '\u{2124}'), - Range::new('\u{2126}', '\u{2126}'), - Range::new('\u{2128}', '\u{2128}'), - Range::new('\u{212A}', '\u{212D}'), - Range::new('\u{2130}', '\u{2133}'), - Range::new('\u{213E}', '\u{213F}'), - Range::new('\u{2145}', '\u{2145}'), - Range::new('\u{2160}', '\u{216F}'), - Range::new('\u{2183}', '\u{2183}'), - Range::new('\u{24B6}', '\u{24CF}'), - Range::new('\u{2C00}', '\u{2C2F}'), - Range::new('\u{2C60}', '\u{2C60}'), - Range::new('\u{2C62}', '\u{2C64}'), - Range::new('\u{2C67}', '\u{2C67}'), - Range::new('\u{2C69}', '\u{2C69}'), - Range::new('\u{2C6B}', '\u{2C6B}'), - Range::new('\u{2C6D}', '\u{2C70}'), - Range::new('\u{2C72}', '\u{2C72}'), - Range::new('\u{2C75}', '\u{2C75}'), - Range::new('\u{2C7E}', '\u{2C80}'), - Range::new('\u{2C82}', '\u{2C82}'), - Range::new('\u{2C84}', '\u{2C84}'), - Range::new('\u{2C86}', '\u{2C86}'), - Range::new('\u{2C88}', '\u{2C88}'), - Range::new('\u{2C8A}', '\u{2C8A}'), - Range::new('\u{2C8C}', '\u{2C8C}'), - Range::new('\u{2C8E}', '\u{2C8E}'), - Range::new('\u{2C90}', '\u{2C90}'), - Range::new('\u{2C92}', '\u{2C92}'), - Range::new('\u{2C94}', '\u{2C94}'), - Range::new('\u{2C96}', '\u{2C96}'), - Range::new('\u{2C98}', '\u{2C98}'), - Range::new('\u{2C9A}', '\u{2C9A}'), - Range::new('\u{2C9C}', '\u{2C9C}'), - Range::new('\u{2C9E}', '\u{2C9E}'), - Range::new('\u{2CA0}', '\u{2CA0}'), - Range::new('\u{2CA2}', '\u{2CA2}'), - Range::new('\u{2CA4}', '\u{2CA4}'), - Range::new('\u{2CA6}', '\u{2CA6}'), - Range::new('\u{2CA8}', '\u{2CA8}'), - Range::new('\u{2CAA}', '\u{2CAA}'), - Range::new('\u{2CAC}', '\u{2CAC}'), - Range::new('\u{2CAE}', '\u{2CAE}'), - Range::new('\u{2CB0}', '\u{2CB0}'), - Range::new('\u{2CB2}', '\u{2CB2}'), - Range::new('\u{2CB4}', '\u{2CB4}'), - Range::new('\u{2CB6}', '\u{2CB6}'), - Range::new('\u{2CB8}', '\u{2CB8}'), - Range::new('\u{2CBA}', '\u{2CBA}'), - Range::new('\u{2CBC}', '\u{2CBC}'), - Range::new('\u{2CBE}', '\u{2CBE}'), - Range::new('\u{2CC0}', '\u{2CC0}'), - Range::new('\u{2CC2}', '\u{2CC2}'), - Range::new('\u{2CC4}', '\u{2CC4}'), - Range::new('\u{2CC6}', '\u{2CC6}'), - Range::new('\u{2CC8}', '\u{2CC8}'), - Range::new('\u{2CCA}', '\u{2CCA}'), - Range::new('\u{2CCC}', '\u{2CCC}'), - Range::new('\u{2CCE}', '\u{2CCE}'), - Range::new('\u{2CD0}', '\u{2CD0}'), - Range::new('\u{2CD2}', '\u{2CD2}'), - Range::new('\u{2CD4}', '\u{2CD4}'), - Range::new('\u{2CD6}', '\u{2CD6}'), - Range::new('\u{2CD8}', '\u{2CD8}'), - Range::new('\u{2CDA}', '\u{2CDA}'), - Range::new('\u{2CDC}', '\u{2CDC}'), - Range::new('\u{2CDE}', '\u{2CDE}'), - Range::new('\u{2CE0}', '\u{2CE0}'), - Range::new('\u{2CE2}', '\u{2CE2}'), - Range::new('\u{2CEB}', '\u{2CEB}'), - Range::new('\u{2CED}', '\u{2CED}'), - Range::new('\u{2CF2}', '\u{2CF2}'), - Range::new('\u{A640}', '\u{A640}'), - Range::new('\u{A642}', '\u{A642}'), - Range::new('\u{A644}', '\u{A644}'), - Range::new('\u{A646}', '\u{A646}'), - Range::new('\u{A648}', '\u{A648}'), - Range::new('\u{A64A}', '\u{A64A}'), - Range::new('\u{A64C}', '\u{A64C}'), - Range::new('\u{A64E}', '\u{A64E}'), - Range::new('\u{A650}', '\u{A650}'), - Range::new('\u{A652}', '\u{A652}'), - Range::new('\u{A654}', '\u{A654}'), - Range::new('\u{A656}', '\u{A656}'), - Range::new('\u{A658}', '\u{A658}'), - Range::new('\u{A65A}', '\u{A65A}'), - Range::new('\u{A65C}', '\u{A65C}'), - Range::new('\u{A65E}', '\u{A65E}'), - Range::new('\u{A660}', '\u{A660}'), - Range::new('\u{A662}', '\u{A662}'), - Range::new('\u{A664}', '\u{A664}'), - Range::new('\u{A666}', '\u{A666}'), - Range::new('\u{A668}', '\u{A668}'), - Range::new('\u{A66A}', '\u{A66A}'), - Range::new('\u{A66C}', '\u{A66C}'), - Range::new('\u{A680}', '\u{A680}'), - Range::new('\u{A682}', '\u{A682}'), - Range::new('\u{A684}', '\u{A684}'), - Range::new('\u{A686}', '\u{A686}'), - Range::new('\u{A688}', '\u{A688}'), - Range::new('\u{A68A}', '\u{A68A}'), - Range::new('\u{A68C}', '\u{A68C}'), - Range::new('\u{A68E}', '\u{A68E}'), - Range::new('\u{A690}', '\u{A690}'), - Range::new('\u{A692}', '\u{A692}'), - Range::new('\u{A694}', '\u{A694}'), - Range::new('\u{A696}', '\u{A696}'), - Range::new('\u{A698}', '\u{A698}'), - Range::new('\u{A69A}', '\u{A69A}'), - Range::new('\u{A722}', '\u{A722}'), - Range::new('\u{A724}', '\u{A724}'), - Range::new('\u{A726}', '\u{A726}'), - Range::new('\u{A728}', '\u{A728}'), - Range::new('\u{A72A}', '\u{A72A}'), - Range::new('\u{A72C}', '\u{A72C}'), - Range::new('\u{A72E}', '\u{A72E}'), - Range::new('\u{A732}', '\u{A732}'), - Range::new('\u{A734}', '\u{A734}'), - Range::new('\u{A736}', '\u{A736}'), - Range::new('\u{A738}', '\u{A738}'), - Range::new('\u{A73A}', '\u{A73A}'), - Range::new('\u{A73C}', '\u{A73C}'), - Range::new('\u{A73E}', '\u{A73E}'), - Range::new('\u{A740}', '\u{A740}'), - Range::new('\u{A742}', '\u{A742}'), - Range::new('\u{A744}', '\u{A744}'), - Range::new('\u{A746}', '\u{A746}'), - Range::new('\u{A748}', '\u{A748}'), - Range::new('\u{A74A}', '\u{A74A}'), - Range::new('\u{A74C}', '\u{A74C}'), - Range::new('\u{A74E}', '\u{A74E}'), - Range::new('\u{A750}', '\u{A750}'), - Range::new('\u{A752}', '\u{A752}'), - Range::new('\u{A754}', '\u{A754}'), - Range::new('\u{A756}', '\u{A756}'), - Range::new('\u{A758}', '\u{A758}'), - Range::new('\u{A75A}', '\u{A75A}'), - Range::new('\u{A75C}', '\u{A75C}'), - Range::new('\u{A75E}', '\u{A75E}'), - Range::new('\u{A760}', '\u{A760}'), - Range::new('\u{A762}', '\u{A762}'), - Range::new('\u{A764}', '\u{A764}'), - Range::new('\u{A766}', '\u{A766}'), - Range::new('\u{A768}', '\u{A768}'), - Range::new('\u{A76A}', '\u{A76A}'), - Range::new('\u{A76C}', '\u{A76C}'), - Range::new('\u{A76E}', '\u{A76E}'), - Range::new('\u{A779}', '\u{A779}'), - Range::new('\u{A77B}', '\u{A77B}'), - Range::new('\u{A77D}', '\u{A77E}'), - Range::new('\u{A780}', '\u{A780}'), - Range::new('\u{A782}', '\u{A782}'), - Range::new('\u{A784}', '\u{A784}'), - Range::new('\u{A786}', '\u{A786}'), - Range::new('\u{A78B}', '\u{A78B}'), - Range::new('\u{A78D}', '\u{A78D}'), - Range::new('\u{A790}', '\u{A790}'), - Range::new('\u{A792}', '\u{A792}'), - Range::new('\u{A796}', '\u{A796}'), - Range::new('\u{A798}', '\u{A798}'), - Range::new('\u{A79A}', '\u{A79A}'), - Range::new('\u{A79C}', '\u{A79C}'), - Range::new('\u{A79E}', '\u{A79E}'), - Range::new('\u{A7A0}', '\u{A7A0}'), - Range::new('\u{A7A2}', '\u{A7A2}'), - Range::new('\u{A7A4}', '\u{A7A4}'), - Range::new('\u{A7A6}', '\u{A7A6}'), - Range::new('\u{A7A8}', '\u{A7A8}'), - Range::new('\u{A7AA}', '\u{A7AE}'), - Range::new('\u{A7B0}', '\u{A7B4}'), - Range::new('\u{A7B6}', '\u{A7B6}'), - Range::new('\u{A7B8}', '\u{A7B8}'), - Range::new('\u{A7BA}', '\u{A7BA}'), - Range::new('\u{A7BC}', '\u{A7BC}'), - Range::new('\u{A7BE}', '\u{A7BE}'), - Range::new('\u{A7C0}', '\u{A7C0}'), - Range::new('\u{A7C2}', '\u{A7C2}'), - Range::new('\u{A7C4}', '\u{A7C7}'), - Range::new('\u{A7C9}', '\u{A7C9}'), - Range::new('\u{A7D0}', '\u{A7D0}'), - Range::new('\u{A7D6}', '\u{A7D6}'), - Range::new('\u{A7D8}', '\u{A7D8}'), - Range::new('\u{A7F5}', '\u{A7F5}'), - Range::new('\u{FF21}', '\u{FF3A}'), - Range::new('\u{10400}', '\u{10427}'), - Range::new('\u{104B0}', '\u{104D3}'), - Range::new('\u{10570}', '\u{1057A}'), - Range::new('\u{1057C}', '\u{1058A}'), - Range::new('\u{1058C}', '\u{10592}'), - Range::new('\u{10594}', '\u{10595}'), - Range::new('\u{10C80}', '\u{10CB2}'), - Range::new('\u{118A0}', '\u{118BF}'), - Range::new('\u{16E40}', '\u{16E5F}'), - Range::new('\u{1D400}', '\u{1D419}'), - Range::new('\u{1D434}', '\u{1D44D}'), - Range::new('\u{1D468}', '\u{1D481}'), - Range::new('\u{1D49C}', '\u{1D49C}'), - Range::new('\u{1D49E}', '\u{1D49F}'), - Range::new('\u{1D4A2}', '\u{1D4A2}'), - Range::new('\u{1D4A5}', '\u{1D4A6}'), - Range::new('\u{1D4A9}', '\u{1D4AC}'), - Range::new('\u{1D4AE}', '\u{1D4B5}'), - Range::new('\u{1D4D0}', '\u{1D4E9}'), - Range::new('\u{1D504}', '\u{1D505}'), - Range::new('\u{1D507}', '\u{1D50A}'), - Range::new('\u{1D50D}', '\u{1D514}'), - Range::new('\u{1D516}', '\u{1D51C}'), - Range::new('\u{1D538}', '\u{1D539}'), - Range::new('\u{1D53B}', '\u{1D53E}'), - Range::new('\u{1D540}', '\u{1D544}'), - Range::new('\u{1D546}', '\u{1D546}'), - Range::new('\u{1D54A}', '\u{1D550}'), - Range::new('\u{1D56C}', '\u{1D585}'), - Range::new('\u{1D5A0}', '\u{1D5B9}'), - Range::new('\u{1D5D4}', '\u{1D5ED}'), - Range::new('\u{1D608}', '\u{1D621}'), - Range::new('\u{1D63C}', '\u{1D655}'), - Range::new('\u{1D670}', '\u{1D689}'), - Range::new('\u{1D6A8}', '\u{1D6C0}'), - Range::new('\u{1D6E2}', '\u{1D6FA}'), - Range::new('\u{1D71C}', '\u{1D734}'), - Range::new('\u{1D756}', '\u{1D76E}'), - Range::new('\u{1D790}', '\u{1D7A8}'), - Range::new('\u{1D7CA}', '\u{1D7CA}'), - Range::new('\u{1E900}', '\u{1E921}'), - Range::new('\u{1F130}', '\u{1F149}'), - Range::new('\u{1F150}', '\u{1F169}'), - Range::new('\u{1F170}', '\u{1F189}'), -]; - -pub static WORD: [Range; 759] = [ - Range::new('\u{30}', '\u{39}'), - Range::new('\u{41}', '\u{5A}'), - Range::new('\u{5F}', '\u{5F}'), - Range::new('\u{61}', '\u{7A}'), - Range::new('\u{AA}', '\u{AA}'), - Range::new('\u{B5}', '\u{B5}'), - Range::new('\u{BA}', '\u{BA}'), - Range::new('\u{C0}', '\u{D6}'), - Range::new('\u{D8}', '\u{F6}'), - Range::new('\u{F8}', '\u{2C1}'), - Range::new('\u{2C6}', '\u{2D1}'), - Range::new('\u{2E0}', '\u{2E4}'), - Range::new('\u{2EC}', '\u{2EC}'), - Range::new('\u{2EE}', '\u{2EE}'), - Range::new('\u{300}', '\u{374}'), - Range::new('\u{376}', '\u{377}'), - Range::new('\u{37A}', '\u{37D}'), - Range::new('\u{37F}', '\u{37F}'), - Range::new('\u{386}', '\u{386}'), - Range::new('\u{388}', '\u{38A}'), - Range::new('\u{38C}', '\u{38C}'), - Range::new('\u{38E}', '\u{3A1}'), - Range::new('\u{3A3}', '\u{3F5}'), - Range::new('\u{3F7}', '\u{481}'), - Range::new('\u{483}', '\u{52F}'), - Range::new('\u{531}', '\u{556}'), - Range::new('\u{559}', '\u{559}'), - Range::new('\u{560}', '\u{588}'), - Range::new('\u{591}', '\u{5BD}'), - Range::new('\u{5BF}', '\u{5BF}'), - Range::new('\u{5C1}', '\u{5C2}'), - Range::new('\u{5C4}', '\u{5C5}'), - Range::new('\u{5C7}', '\u{5C7}'), - Range::new('\u{5D0}', '\u{5EA}'), - Range::new('\u{5EF}', '\u{5F2}'), - Range::new('\u{610}', '\u{61A}'), - Range::new('\u{620}', '\u{669}'), - Range::new('\u{66E}', '\u{6D3}'), - Range::new('\u{6D5}', '\u{6DC}'), - Range::new('\u{6DF}', '\u{6E8}'), - Range::new('\u{6EA}', '\u{6FC}'), - Range::new('\u{6FF}', '\u{6FF}'), - Range::new('\u{710}', '\u{74A}'), - Range::new('\u{74D}', '\u{7B1}'), - Range::new('\u{7C0}', '\u{7F5}'), - Range::new('\u{7FA}', '\u{7FA}'), - Range::new('\u{7FD}', '\u{7FD}'), - Range::new('\u{800}', '\u{82D}'), - Range::new('\u{840}', '\u{85B}'), - Range::new('\u{860}', '\u{86A}'), - Range::new('\u{870}', '\u{887}'), - Range::new('\u{889}', '\u{88E}'), - Range::new('\u{898}', '\u{8E1}'), - Range::new('\u{8E3}', '\u{963}'), - Range::new('\u{966}', '\u{96F}'), - Range::new('\u{971}', '\u{983}'), - Range::new('\u{985}', '\u{98C}'), - Range::new('\u{98F}', '\u{990}'), - Range::new('\u{993}', '\u{9A8}'), - Range::new('\u{9AA}', '\u{9B0}'), - Range::new('\u{9B2}', '\u{9B2}'), - Range::new('\u{9B6}', '\u{9B9}'), - Range::new('\u{9BC}', '\u{9C4}'), - Range::new('\u{9C7}', '\u{9C8}'), - Range::new('\u{9CB}', '\u{9CE}'), - Range::new('\u{9D7}', '\u{9D7}'), - Range::new('\u{9DC}', '\u{9DD}'), - Range::new('\u{9DF}', '\u{9E3}'), - Range::new('\u{9E6}', '\u{9F1}'), - Range::new('\u{9FC}', '\u{9FC}'), - Range::new('\u{9FE}', '\u{9FE}'), - Range::new('\u{A01}', '\u{A03}'), - Range::new('\u{A05}', '\u{A0A}'), - Range::new('\u{A0F}', '\u{A10}'), - Range::new('\u{A13}', '\u{A28}'), - Range::new('\u{A2A}', '\u{A30}'), - Range::new('\u{A32}', '\u{A33}'), - Range::new('\u{A35}', '\u{A36}'), - Range::new('\u{A38}', '\u{A39}'), - Range::new('\u{A3C}', '\u{A3C}'), - Range::new('\u{A3E}', '\u{A42}'), - Range::new('\u{A47}', '\u{A48}'), - Range::new('\u{A4B}', '\u{A4D}'), - Range::new('\u{A51}', '\u{A51}'), - Range::new('\u{A59}', '\u{A5C}'), - Range::new('\u{A5E}', '\u{A5E}'), - Range::new('\u{A66}', '\u{A75}'), - Range::new('\u{A81}', '\u{A83}'), - Range::new('\u{A85}', '\u{A8D}'), - Range::new('\u{A8F}', '\u{A91}'), - Range::new('\u{A93}', '\u{AA8}'), - Range::new('\u{AAA}', '\u{AB0}'), - Range::new('\u{AB2}', '\u{AB3}'), - Range::new('\u{AB5}', '\u{AB9}'), - Range::new('\u{ABC}', '\u{AC5}'), - Range::new('\u{AC7}', '\u{AC9}'), - Range::new('\u{ACB}', '\u{ACD}'), - Range::new('\u{AD0}', '\u{AD0}'), - Range::new('\u{AE0}', '\u{AE3}'), - Range::new('\u{AE6}', '\u{AEF}'), - Range::new('\u{AF9}', '\u{AFF}'), - Range::new('\u{B01}', '\u{B03}'), - Range::new('\u{B05}', '\u{B0C}'), - Range::new('\u{B0F}', '\u{B10}'), - Range::new('\u{B13}', '\u{B28}'), - Range::new('\u{B2A}', '\u{B30}'), - Range::new('\u{B32}', '\u{B33}'), - Range::new('\u{B35}', '\u{B39}'), - Range::new('\u{B3C}', '\u{B44}'), - Range::new('\u{B47}', '\u{B48}'), - Range::new('\u{B4B}', '\u{B4D}'), - Range::new('\u{B55}', '\u{B57}'), - Range::new('\u{B5C}', '\u{B5D}'), - Range::new('\u{B5F}', '\u{B63}'), - Range::new('\u{B66}', '\u{B6F}'), - Range::new('\u{B71}', '\u{B71}'), - Range::new('\u{B82}', '\u{B83}'), - Range::new('\u{B85}', '\u{B8A}'), - Range::new('\u{B8E}', '\u{B90}'), - Range::new('\u{B92}', '\u{B95}'), - Range::new('\u{B99}', '\u{B9A}'), - Range::new('\u{B9C}', '\u{B9C}'), - Range::new('\u{B9E}', '\u{B9F}'), - Range::new('\u{BA3}', '\u{BA4}'), - Range::new('\u{BA8}', '\u{BAA}'), - Range::new('\u{BAE}', '\u{BB9}'), - Range::new('\u{BBE}', '\u{BC2}'), - Range::new('\u{BC6}', '\u{BC8}'), - Range::new('\u{BCA}', '\u{BCD}'), - Range::new('\u{BD0}', '\u{BD0}'), - Range::new('\u{BD7}', '\u{BD7}'), - Range::new('\u{BE6}', '\u{BEF}'), - Range::new('\u{C00}', '\u{C0C}'), - Range::new('\u{C0E}', '\u{C10}'), - Range::new('\u{C12}', '\u{C28}'), - Range::new('\u{C2A}', '\u{C39}'), - Range::new('\u{C3C}', '\u{C44}'), - Range::new('\u{C46}', '\u{C48}'), - Range::new('\u{C4A}', '\u{C4D}'), - Range::new('\u{C55}', '\u{C56}'), - Range::new('\u{C58}', '\u{C5A}'), - Range::new('\u{C5D}', '\u{C5D}'), - Range::new('\u{C60}', '\u{C63}'), - Range::new('\u{C66}', '\u{C6F}'), - Range::new('\u{C80}', '\u{C83}'), - Range::new('\u{C85}', '\u{C8C}'), - Range::new('\u{C8E}', '\u{C90}'), - Range::new('\u{C92}', '\u{CA8}'), - Range::new('\u{CAA}', '\u{CB3}'), - Range::new('\u{CB5}', '\u{CB9}'), - Range::new('\u{CBC}', '\u{CC4}'), - Range::new('\u{CC6}', '\u{CC8}'), - Range::new('\u{CCA}', '\u{CCD}'), - Range::new('\u{CD5}', '\u{CD6}'), - Range::new('\u{CDD}', '\u{CDE}'), - Range::new('\u{CE0}', '\u{CE3}'), - Range::new('\u{CE6}', '\u{CEF}'), - Range::new('\u{CF1}', '\u{CF2}'), - Range::new('\u{D00}', '\u{D0C}'), - Range::new('\u{D0E}', '\u{D10}'), - Range::new('\u{D12}', '\u{D44}'), - Range::new('\u{D46}', '\u{D48}'), - Range::new('\u{D4A}', '\u{D4E}'), - Range::new('\u{D54}', '\u{D57}'), - Range::new('\u{D5F}', '\u{D63}'), - Range::new('\u{D66}', '\u{D6F}'), - Range::new('\u{D7A}', '\u{D7F}'), - Range::new('\u{D81}', '\u{D83}'), - Range::new('\u{D85}', '\u{D96}'), - Range::new('\u{D9A}', '\u{DB1}'), - Range::new('\u{DB3}', '\u{DBB}'), - Range::new('\u{DBD}', '\u{DBD}'), - Range::new('\u{DC0}', '\u{DC6}'), - Range::new('\u{DCA}', '\u{DCA}'), - Range::new('\u{DCF}', '\u{DD4}'), - Range::new('\u{DD6}', '\u{DD6}'), - Range::new('\u{DD8}', '\u{DDF}'), - Range::new('\u{DE6}', '\u{DEF}'), - Range::new('\u{DF2}', '\u{DF3}'), - Range::new('\u{E01}', '\u{E3A}'), - Range::new('\u{E40}', '\u{E4E}'), - Range::new('\u{E50}', '\u{E59}'), - Range::new('\u{E81}', '\u{E82}'), - Range::new('\u{E84}', '\u{E84}'), - Range::new('\u{E86}', '\u{E8A}'), - Range::new('\u{E8C}', '\u{EA3}'), - Range::new('\u{EA5}', '\u{EA5}'), - Range::new('\u{EA7}', '\u{EBD}'), - Range::new('\u{EC0}', '\u{EC4}'), - Range::new('\u{EC6}', '\u{EC6}'), - Range::new('\u{EC8}', '\u{ECD}'), - Range::new('\u{ED0}', '\u{ED9}'), - Range::new('\u{EDC}', '\u{EDF}'), - Range::new('\u{F00}', '\u{F00}'), - Range::new('\u{F18}', '\u{F19}'), - Range::new('\u{F20}', '\u{F29}'), - Range::new('\u{F35}', '\u{F35}'), - Range::new('\u{F37}', '\u{F37}'), - Range::new('\u{F39}', '\u{F39}'), - Range::new('\u{F3E}', '\u{F47}'), - Range::new('\u{F49}', '\u{F6C}'), - Range::new('\u{F71}', '\u{F84}'), - Range::new('\u{F86}', '\u{F97}'), - Range::new('\u{F99}', '\u{FBC}'), - Range::new('\u{FC6}', '\u{FC6}'), - Range::new('\u{1000}', '\u{1049}'), - Range::new('\u{1050}', '\u{109D}'), - Range::new('\u{10A0}', '\u{10C5}'), - Range::new('\u{10C7}', '\u{10C7}'), - Range::new('\u{10CD}', '\u{10CD}'), - Range::new('\u{10D0}', '\u{10FA}'), - Range::new('\u{10FC}', '\u{1248}'), - Range::new('\u{124A}', '\u{124D}'), - Range::new('\u{1250}', '\u{1256}'), - Range::new('\u{1258}', '\u{1258}'), - Range::new('\u{125A}', '\u{125D}'), - Range::new('\u{1260}', '\u{1288}'), - Range::new('\u{128A}', '\u{128D}'), - Range::new('\u{1290}', '\u{12B0}'), - Range::new('\u{12B2}', '\u{12B5}'), - Range::new('\u{12B8}', '\u{12BE}'), - Range::new('\u{12C0}', '\u{12C0}'), - Range::new('\u{12C2}', '\u{12C5}'), - Range::new('\u{12C8}', '\u{12D6}'), - Range::new('\u{12D8}', '\u{1310}'), - Range::new('\u{1312}', '\u{1315}'), - Range::new('\u{1318}', '\u{135A}'), - Range::new('\u{135D}', '\u{135F}'), - Range::new('\u{1380}', '\u{138F}'), - Range::new('\u{13A0}', '\u{13F5}'), - Range::new('\u{13F8}', '\u{13FD}'), - Range::new('\u{1401}', '\u{166C}'), - Range::new('\u{166F}', '\u{167F}'), - Range::new('\u{1681}', '\u{169A}'), - Range::new('\u{16A0}', '\u{16EA}'), - Range::new('\u{16EE}', '\u{16F8}'), - Range::new('\u{1700}', '\u{1715}'), - Range::new('\u{171F}', '\u{1734}'), - Range::new('\u{1740}', '\u{1753}'), - Range::new('\u{1760}', '\u{176C}'), - Range::new('\u{176E}', '\u{1770}'), - Range::new('\u{1772}', '\u{1773}'), - Range::new('\u{1780}', '\u{17D3}'), - Range::new('\u{17D7}', '\u{17D7}'), - Range::new('\u{17DC}', '\u{17DD}'), - Range::new('\u{17E0}', '\u{17E9}'), - Range::new('\u{180B}', '\u{180D}'), - Range::new('\u{180F}', '\u{1819}'), - Range::new('\u{1820}', '\u{1878}'), - Range::new('\u{1880}', '\u{18AA}'), - Range::new('\u{18B0}', '\u{18F5}'), - Range::new('\u{1900}', '\u{191E}'), - Range::new('\u{1920}', '\u{192B}'), - Range::new('\u{1930}', '\u{193B}'), - Range::new('\u{1946}', '\u{196D}'), - Range::new('\u{1970}', '\u{1974}'), - Range::new('\u{1980}', '\u{19AB}'), - Range::new('\u{19B0}', '\u{19C9}'), - Range::new('\u{19D0}', '\u{19D9}'), - Range::new('\u{1A00}', '\u{1A1B}'), - Range::new('\u{1A20}', '\u{1A5E}'), - Range::new('\u{1A60}', '\u{1A7C}'), - Range::new('\u{1A7F}', '\u{1A89}'), - Range::new('\u{1A90}', '\u{1A99}'), - Range::new('\u{1AA7}', '\u{1AA7}'), - Range::new('\u{1AB0}', '\u{1ACE}'), - Range::new('\u{1B00}', '\u{1B4C}'), - Range::new('\u{1B50}', '\u{1B59}'), - Range::new('\u{1B6B}', '\u{1B73}'), - Range::new('\u{1B80}', '\u{1BF3}'), - Range::new('\u{1C00}', '\u{1C37}'), - Range::new('\u{1C40}', '\u{1C49}'), - Range::new('\u{1C4D}', '\u{1C7D}'), - Range::new('\u{1C80}', '\u{1C88}'), - Range::new('\u{1C90}', '\u{1CBA}'), - Range::new('\u{1CBD}', '\u{1CBF}'), - Range::new('\u{1CD0}', '\u{1CD2}'), - Range::new('\u{1CD4}', '\u{1CFA}'), - Range::new('\u{1D00}', '\u{1F15}'), - Range::new('\u{1F18}', '\u{1F1D}'), - Range::new('\u{1F20}', '\u{1F45}'), - Range::new('\u{1F48}', '\u{1F4D}'), - Range::new('\u{1F50}', '\u{1F57}'), - Range::new('\u{1F59}', '\u{1F59}'), - Range::new('\u{1F5B}', '\u{1F5B}'), - Range::new('\u{1F5D}', '\u{1F5D}'), - Range::new('\u{1F5F}', '\u{1F7D}'), - Range::new('\u{1F80}', '\u{1FB4}'), - Range::new('\u{1FB6}', '\u{1FBC}'), - Range::new('\u{1FBE}', '\u{1FBE}'), - Range::new('\u{1FC2}', '\u{1FC4}'), - Range::new('\u{1FC6}', '\u{1FCC}'), - Range::new('\u{1FD0}', '\u{1FD3}'), - Range::new('\u{1FD6}', '\u{1FDB}'), - Range::new('\u{1FE0}', '\u{1FEC}'), - Range::new('\u{1FF2}', '\u{1FF4}'), - Range::new('\u{1FF6}', '\u{1FFC}'), - Range::new('\u{200C}', '\u{200D}'), - Range::new('\u{203F}', '\u{2040}'), - Range::new('\u{2054}', '\u{2054}'), - Range::new('\u{2071}', '\u{2071}'), - Range::new('\u{207F}', '\u{207F}'), - Range::new('\u{2090}', '\u{209C}'), - Range::new('\u{20D0}', '\u{20F0}'), - Range::new('\u{2102}', '\u{2102}'), - Range::new('\u{2107}', '\u{2107}'), - Range::new('\u{210A}', '\u{2113}'), - Range::new('\u{2115}', '\u{2115}'), - Range::new('\u{2119}', '\u{211D}'), - Range::new('\u{2124}', '\u{2124}'), - Range::new('\u{2126}', '\u{2126}'), - Range::new('\u{2128}', '\u{2128}'), - Range::new('\u{212A}', '\u{212D}'), - Range::new('\u{212F}', '\u{2139}'), - Range::new('\u{213C}', '\u{213F}'), - Range::new('\u{2145}', '\u{2149}'), - Range::new('\u{214E}', '\u{214E}'), - Range::new('\u{2160}', '\u{2188}'), - Range::new('\u{24B6}', '\u{24E9}'), - Range::new('\u{2C00}', '\u{2CE4}'), - Range::new('\u{2CEB}', '\u{2CF3}'), - Range::new('\u{2D00}', '\u{2D25}'), - Range::new('\u{2D27}', '\u{2D27}'), - Range::new('\u{2D2D}', '\u{2D2D}'), - Range::new('\u{2D30}', '\u{2D67}'), - Range::new('\u{2D6F}', '\u{2D6F}'), - Range::new('\u{2D7F}', '\u{2D96}'), - Range::new('\u{2DA0}', '\u{2DA6}'), - Range::new('\u{2DA8}', '\u{2DAE}'), - Range::new('\u{2DB0}', '\u{2DB6}'), - Range::new('\u{2DB8}', '\u{2DBE}'), - Range::new('\u{2DC0}', '\u{2DC6}'), - Range::new('\u{2DC8}', '\u{2DCE}'), - Range::new('\u{2DD0}', '\u{2DD6}'), - Range::new('\u{2DD8}', '\u{2DDE}'), - Range::new('\u{2DE0}', '\u{2DFF}'), - Range::new('\u{2E2F}', '\u{2E2F}'), - Range::new('\u{3005}', '\u{3007}'), - Range::new('\u{3021}', '\u{302F}'), - Range::new('\u{3031}', '\u{3035}'), - Range::new('\u{3038}', '\u{303C}'), - Range::new('\u{3041}', '\u{3096}'), - Range::new('\u{3099}', '\u{309A}'), - Range::new('\u{309D}', '\u{309F}'), - Range::new('\u{30A1}', '\u{30FA}'), - Range::new('\u{30FC}', '\u{30FF}'), - Range::new('\u{3105}', '\u{312F}'), - Range::new('\u{3131}', '\u{318E}'), - Range::new('\u{31A0}', '\u{31BF}'), - Range::new('\u{31F0}', '\u{31FF}'), - Range::new('\u{3400}', '\u{4DBF}'), - Range::new('\u{4E00}', '\u{A48C}'), - Range::new('\u{A4D0}', '\u{A4FD}'), - Range::new('\u{A500}', '\u{A60C}'), - Range::new('\u{A610}', '\u{A62B}'), - Range::new('\u{A640}', '\u{A672}'), - Range::new('\u{A674}', '\u{A67D}'), - Range::new('\u{A67F}', '\u{A6F1}'), - Range::new('\u{A717}', '\u{A71F}'), - Range::new('\u{A722}', '\u{A788}'), - Range::new('\u{A78B}', '\u{A7CA}'), - Range::new('\u{A7D0}', '\u{A7D1}'), - Range::new('\u{A7D3}', '\u{A7D3}'), - Range::new('\u{A7D5}', '\u{A7D9}'), - Range::new('\u{A7F2}', '\u{A827}'), - Range::new('\u{A82C}', '\u{A82C}'), - Range::new('\u{A840}', '\u{A873}'), - Range::new('\u{A880}', '\u{A8C5}'), - Range::new('\u{A8D0}', '\u{A8D9}'), - Range::new('\u{A8E0}', '\u{A8F7}'), - Range::new('\u{A8FB}', '\u{A8FB}'), - Range::new('\u{A8FD}', '\u{A92D}'), - Range::new('\u{A930}', '\u{A953}'), - Range::new('\u{A960}', '\u{A97C}'), - Range::new('\u{A980}', '\u{A9C0}'), - Range::new('\u{A9CF}', '\u{A9D9}'), - Range::new('\u{A9E0}', '\u{A9FE}'), - Range::new('\u{AA00}', '\u{AA36}'), - Range::new('\u{AA40}', '\u{AA4D}'), - Range::new('\u{AA50}', '\u{AA59}'), - Range::new('\u{AA60}', '\u{AA76}'), - Range::new('\u{AA7A}', '\u{AAC2}'), - Range::new('\u{AADB}', '\u{AADD}'), - Range::new('\u{AAE0}', '\u{AAEF}'), - Range::new('\u{AAF2}', '\u{AAF6}'), - Range::new('\u{AB01}', '\u{AB06}'), - Range::new('\u{AB09}', '\u{AB0E}'), - Range::new('\u{AB11}', '\u{AB16}'), - Range::new('\u{AB20}', '\u{AB26}'), - Range::new('\u{AB28}', '\u{AB2E}'), - Range::new('\u{AB30}', '\u{AB5A}'), - Range::new('\u{AB5C}', '\u{AB69}'), - Range::new('\u{AB70}', '\u{ABEA}'), - Range::new('\u{ABEC}', '\u{ABED}'), - Range::new('\u{ABF0}', '\u{ABF9}'), - Range::new('\u{AC00}', '\u{D7A3}'), - Range::new('\u{D7B0}', '\u{D7C6}'), - Range::new('\u{D7CB}', '\u{D7FB}'), - Range::new('\u{F900}', '\u{FA6D}'), - Range::new('\u{FA70}', '\u{FAD9}'), - Range::new('\u{FB00}', '\u{FB06}'), - Range::new('\u{FB13}', '\u{FB17}'), - Range::new('\u{FB1D}', '\u{FB28}'), - Range::new('\u{FB2A}', '\u{FB36}'), - Range::new('\u{FB38}', '\u{FB3C}'), - Range::new('\u{FB3E}', '\u{FB3E}'), - Range::new('\u{FB40}', '\u{FB41}'), - Range::new('\u{FB43}', '\u{FB44}'), - Range::new('\u{FB46}', '\u{FBB1}'), - Range::new('\u{FBD3}', '\u{FD3D}'), - Range::new('\u{FD50}', '\u{FD8F}'), - Range::new('\u{FD92}', '\u{FDC7}'), - Range::new('\u{FDF0}', '\u{FDFB}'), - Range::new('\u{FE00}', '\u{FE0F}'), - Range::new('\u{FE20}', '\u{FE2F}'), - Range::new('\u{FE33}', '\u{FE34}'), - Range::new('\u{FE4D}', '\u{FE4F}'), - Range::new('\u{FE70}', '\u{FE74}'), - Range::new('\u{FE76}', '\u{FEFC}'), - Range::new('\u{FF10}', '\u{FF19}'), - Range::new('\u{FF21}', '\u{FF3A}'), - Range::new('\u{FF3F}', '\u{FF3F}'), - Range::new('\u{FF41}', '\u{FF5A}'), - Range::new('\u{FF66}', '\u{FFBE}'), - Range::new('\u{FFC2}', '\u{FFC7}'), - Range::new('\u{FFCA}', '\u{FFCF}'), - Range::new('\u{FFD2}', '\u{FFD7}'), - Range::new('\u{FFDA}', '\u{FFDC}'), - Range::new('\u{10000}', '\u{1000B}'), - Range::new('\u{1000D}', '\u{10026}'), - Range::new('\u{10028}', '\u{1003A}'), - Range::new('\u{1003C}', '\u{1003D}'), - Range::new('\u{1003F}', '\u{1004D}'), - Range::new('\u{10050}', '\u{1005D}'), - Range::new('\u{10080}', '\u{100FA}'), - Range::new('\u{10140}', '\u{10174}'), - Range::new('\u{101FD}', '\u{101FD}'), - Range::new('\u{10280}', '\u{1029C}'), - Range::new('\u{102A0}', '\u{102D0}'), - Range::new('\u{102E0}', '\u{102E0}'), - Range::new('\u{10300}', '\u{1031F}'), - Range::new('\u{1032D}', '\u{1034A}'), - Range::new('\u{10350}', '\u{1037A}'), - Range::new('\u{10380}', '\u{1039D}'), - Range::new('\u{103A0}', '\u{103C3}'), - Range::new('\u{103C8}', '\u{103CF}'), - Range::new('\u{103D1}', '\u{103D5}'), - Range::new('\u{10400}', '\u{1049D}'), - Range::new('\u{104A0}', '\u{104A9}'), - Range::new('\u{104B0}', '\u{104D3}'), - Range::new('\u{104D8}', '\u{104FB}'), - Range::new('\u{10500}', '\u{10527}'), - Range::new('\u{10530}', '\u{10563}'), - Range::new('\u{10570}', '\u{1057A}'), - Range::new('\u{1057C}', '\u{1058A}'), - Range::new('\u{1058C}', '\u{10592}'), - Range::new('\u{10594}', '\u{10595}'), - Range::new('\u{10597}', '\u{105A1}'), - Range::new('\u{105A3}', '\u{105B1}'), - Range::new('\u{105B3}', '\u{105B9}'), - Range::new('\u{105BB}', '\u{105BC}'), - Range::new('\u{10600}', '\u{10736}'), - Range::new('\u{10740}', '\u{10755}'), - Range::new('\u{10760}', '\u{10767}'), - Range::new('\u{10780}', '\u{10785}'), - Range::new('\u{10787}', '\u{107B0}'), - Range::new('\u{107B2}', '\u{107BA}'), - Range::new('\u{10800}', '\u{10805}'), - Range::new('\u{10808}', '\u{10808}'), - Range::new('\u{1080A}', '\u{10835}'), - Range::new('\u{10837}', '\u{10838}'), - Range::new('\u{1083C}', '\u{1083C}'), - Range::new('\u{1083F}', '\u{10855}'), - Range::new('\u{10860}', '\u{10876}'), - Range::new('\u{10880}', '\u{1089E}'), - Range::new('\u{108E0}', '\u{108F2}'), - Range::new('\u{108F4}', '\u{108F5}'), - Range::new('\u{10900}', '\u{10915}'), - Range::new('\u{10920}', '\u{10939}'), - Range::new('\u{10980}', '\u{109B7}'), - Range::new('\u{109BE}', '\u{109BF}'), - Range::new('\u{10A00}', '\u{10A03}'), - Range::new('\u{10A05}', '\u{10A06}'), - Range::new('\u{10A0C}', '\u{10A13}'), - Range::new('\u{10A15}', '\u{10A17}'), - Range::new('\u{10A19}', '\u{10A35}'), - Range::new('\u{10A38}', '\u{10A3A}'), - Range::new('\u{10A3F}', '\u{10A3F}'), - Range::new('\u{10A60}', '\u{10A7C}'), - Range::new('\u{10A80}', '\u{10A9C}'), - Range::new('\u{10AC0}', '\u{10AC7}'), - Range::new('\u{10AC9}', '\u{10AE6}'), - Range::new('\u{10B00}', '\u{10B35}'), - Range::new('\u{10B40}', '\u{10B55}'), - Range::new('\u{10B60}', '\u{10B72}'), - Range::new('\u{10B80}', '\u{10B91}'), - Range::new('\u{10C00}', '\u{10C48}'), - Range::new('\u{10C80}', '\u{10CB2}'), - Range::new('\u{10CC0}', '\u{10CF2}'), - Range::new('\u{10D00}', '\u{10D27}'), - Range::new('\u{10D30}', '\u{10D39}'), - Range::new('\u{10E80}', '\u{10EA9}'), - Range::new('\u{10EAB}', '\u{10EAC}'), - Range::new('\u{10EB0}', '\u{10EB1}'), - Range::new('\u{10F00}', '\u{10F1C}'), - Range::new('\u{10F27}', '\u{10F27}'), - Range::new('\u{10F30}', '\u{10F50}'), - Range::new('\u{10F70}', '\u{10F85}'), - Range::new('\u{10FB0}', '\u{10FC4}'), - Range::new('\u{10FE0}', '\u{10FF6}'), - Range::new('\u{11000}', '\u{11046}'), - Range::new('\u{11066}', '\u{11075}'), - Range::new('\u{1107F}', '\u{110BA}'), - Range::new('\u{110C2}', '\u{110C2}'), - Range::new('\u{110D0}', '\u{110E8}'), - Range::new('\u{110F0}', '\u{110F9}'), - Range::new('\u{11100}', '\u{11134}'), - Range::new('\u{11136}', '\u{1113F}'), - Range::new('\u{11144}', '\u{11147}'), - Range::new('\u{11150}', '\u{11173}'), - Range::new('\u{11176}', '\u{11176}'), - Range::new('\u{11180}', '\u{111C4}'), - Range::new('\u{111C9}', '\u{111CC}'), - Range::new('\u{111CE}', '\u{111DA}'), - Range::new('\u{111DC}', '\u{111DC}'), - Range::new('\u{11200}', '\u{11211}'), - Range::new('\u{11213}', '\u{11237}'), - Range::new('\u{1123E}', '\u{1123E}'), - Range::new('\u{11280}', '\u{11286}'), - Range::new('\u{11288}', '\u{11288}'), - Range::new('\u{1128A}', '\u{1128D}'), - Range::new('\u{1128F}', '\u{1129D}'), - Range::new('\u{1129F}', '\u{112A8}'), - Range::new('\u{112B0}', '\u{112EA}'), - Range::new('\u{112F0}', '\u{112F9}'), - Range::new('\u{11300}', '\u{11303}'), - Range::new('\u{11305}', '\u{1130C}'), - Range::new('\u{1130F}', '\u{11310}'), - Range::new('\u{11313}', '\u{11328}'), - Range::new('\u{1132A}', '\u{11330}'), - Range::new('\u{11332}', '\u{11333}'), - Range::new('\u{11335}', '\u{11339}'), - Range::new('\u{1133B}', '\u{11344}'), - Range::new('\u{11347}', '\u{11348}'), - Range::new('\u{1134B}', '\u{1134D}'), - Range::new('\u{11350}', '\u{11350}'), - Range::new('\u{11357}', '\u{11357}'), - Range::new('\u{1135D}', '\u{11363}'), - Range::new('\u{11366}', '\u{1136C}'), - Range::new('\u{11370}', '\u{11374}'), - Range::new('\u{11400}', '\u{1144A}'), - Range::new('\u{11450}', '\u{11459}'), - Range::new('\u{1145E}', '\u{11461}'), - Range::new('\u{11480}', '\u{114C5}'), - Range::new('\u{114C7}', '\u{114C7}'), - Range::new('\u{114D0}', '\u{114D9}'), - Range::new('\u{11580}', '\u{115B5}'), - Range::new('\u{115B8}', '\u{115C0}'), - Range::new('\u{115D8}', '\u{115DD}'), - Range::new('\u{11600}', '\u{11640}'), - Range::new('\u{11644}', '\u{11644}'), - Range::new('\u{11650}', '\u{11659}'), - Range::new('\u{11680}', '\u{116B8}'), - Range::new('\u{116C0}', '\u{116C9}'), - Range::new('\u{11700}', '\u{1171A}'), - Range::new('\u{1171D}', '\u{1172B}'), - Range::new('\u{11730}', '\u{11739}'), - Range::new('\u{11740}', '\u{11746}'), - Range::new('\u{11800}', '\u{1183A}'), - Range::new('\u{118A0}', '\u{118E9}'), - Range::new('\u{118FF}', '\u{11906}'), - Range::new('\u{11909}', '\u{11909}'), - Range::new('\u{1190C}', '\u{11913}'), - Range::new('\u{11915}', '\u{11916}'), - Range::new('\u{11918}', '\u{11935}'), - Range::new('\u{11937}', '\u{11938}'), - Range::new('\u{1193B}', '\u{11943}'), - Range::new('\u{11950}', '\u{11959}'), - Range::new('\u{119A0}', '\u{119A7}'), - Range::new('\u{119AA}', '\u{119D7}'), - Range::new('\u{119DA}', '\u{119E1}'), - Range::new('\u{119E3}', '\u{119E4}'), - Range::new('\u{11A00}', '\u{11A3E}'), - Range::new('\u{11A47}', '\u{11A47}'), - Range::new('\u{11A50}', '\u{11A99}'), - Range::new('\u{11A9D}', '\u{11A9D}'), - Range::new('\u{11AB0}', '\u{11AF8}'), - Range::new('\u{11C00}', '\u{11C08}'), - Range::new('\u{11C0A}', '\u{11C36}'), - Range::new('\u{11C38}', '\u{11C40}'), - Range::new('\u{11C50}', '\u{11C59}'), - Range::new('\u{11C72}', '\u{11C8F}'), - Range::new('\u{11C92}', '\u{11CA7}'), - Range::new('\u{11CA9}', '\u{11CB6}'), - Range::new('\u{11D00}', '\u{11D06}'), - Range::new('\u{11D08}', '\u{11D09}'), - Range::new('\u{11D0B}', '\u{11D36}'), - Range::new('\u{11D3A}', '\u{11D3A}'), - Range::new('\u{11D3C}', '\u{11D3D}'), - Range::new('\u{11D3F}', '\u{11D47}'), - Range::new('\u{11D50}', '\u{11D59}'), - Range::new('\u{11D60}', '\u{11D65}'), - Range::new('\u{11D67}', '\u{11D68}'), - Range::new('\u{11D6A}', '\u{11D8E}'), - Range::new('\u{11D90}', '\u{11D91}'), - Range::new('\u{11D93}', '\u{11D98}'), - Range::new('\u{11DA0}', '\u{11DA9}'), - Range::new('\u{11EE0}', '\u{11EF6}'), - Range::new('\u{11FB0}', '\u{11FB0}'), - Range::new('\u{12000}', '\u{12399}'), - Range::new('\u{12400}', '\u{1246E}'), - Range::new('\u{12480}', '\u{12543}'), - Range::new('\u{12F90}', '\u{12FF0}'), - Range::new('\u{13000}', '\u{1342E}'), - Range::new('\u{14400}', '\u{14646}'), - Range::new('\u{16800}', '\u{16A38}'), - Range::new('\u{16A40}', '\u{16A5E}'), - Range::new('\u{16A60}', '\u{16A69}'), - Range::new('\u{16A70}', '\u{16ABE}'), - Range::new('\u{16AC0}', '\u{16AC9}'), - Range::new('\u{16AD0}', '\u{16AED}'), - Range::new('\u{16AF0}', '\u{16AF4}'), - Range::new('\u{16B00}', '\u{16B36}'), - Range::new('\u{16B40}', '\u{16B43}'), - Range::new('\u{16B50}', '\u{16B59}'), - Range::new('\u{16B63}', '\u{16B77}'), - Range::new('\u{16B7D}', '\u{16B8F}'), - Range::new('\u{16E40}', '\u{16E7F}'), - Range::new('\u{16F00}', '\u{16F4A}'), - Range::new('\u{16F4F}', '\u{16F87}'), - Range::new('\u{16F8F}', '\u{16F9F}'), - Range::new('\u{16FE0}', '\u{16FE1}'), - Range::new('\u{16FE3}', '\u{16FE4}'), - Range::new('\u{16FF0}', '\u{16FF1}'), - Range::new('\u{17000}', '\u{187F7}'), - Range::new('\u{18800}', '\u{18CD5}'), - Range::new('\u{18D00}', '\u{18D08}'), - Range::new('\u{1AFF0}', '\u{1AFF3}'), - Range::new('\u{1AFF5}', '\u{1AFFB}'), - Range::new('\u{1AFFD}', '\u{1AFFE}'), - Range::new('\u{1B000}', '\u{1B122}'), - Range::new('\u{1B150}', '\u{1B152}'), - Range::new('\u{1B164}', '\u{1B167}'), - Range::new('\u{1B170}', '\u{1B2FB}'), - Range::new('\u{1BC00}', '\u{1BC6A}'), - Range::new('\u{1BC70}', '\u{1BC7C}'), - Range::new('\u{1BC80}', '\u{1BC88}'), - Range::new('\u{1BC90}', '\u{1BC99}'), - Range::new('\u{1BC9D}', '\u{1BC9E}'), - Range::new('\u{1CF00}', '\u{1CF2D}'), - Range::new('\u{1CF30}', '\u{1CF46}'), - Range::new('\u{1D165}', '\u{1D169}'), - Range::new('\u{1D16D}', '\u{1D172}'), - Range::new('\u{1D17B}', '\u{1D182}'), - Range::new('\u{1D185}', '\u{1D18B}'), - Range::new('\u{1D1AA}', '\u{1D1AD}'), - Range::new('\u{1D242}', '\u{1D244}'), - Range::new('\u{1D400}', '\u{1D454}'), - Range::new('\u{1D456}', '\u{1D49C}'), - Range::new('\u{1D49E}', '\u{1D49F}'), - Range::new('\u{1D4A2}', '\u{1D4A2}'), - Range::new('\u{1D4A5}', '\u{1D4A6}'), - Range::new('\u{1D4A9}', '\u{1D4AC}'), - Range::new('\u{1D4AE}', '\u{1D4B9}'), - Range::new('\u{1D4BB}', '\u{1D4BB}'), - Range::new('\u{1D4BD}', '\u{1D4C3}'), - Range::new('\u{1D4C5}', '\u{1D505}'), - Range::new('\u{1D507}', '\u{1D50A}'), - Range::new('\u{1D50D}', '\u{1D514}'), - Range::new('\u{1D516}', '\u{1D51C}'), - Range::new('\u{1D51E}', '\u{1D539}'), - Range::new('\u{1D53B}', '\u{1D53E}'), - Range::new('\u{1D540}', '\u{1D544}'), - Range::new('\u{1D546}', '\u{1D546}'), - Range::new('\u{1D54A}', '\u{1D550}'), - Range::new('\u{1D552}', '\u{1D6A5}'), - Range::new('\u{1D6A8}', '\u{1D6C0}'), - Range::new('\u{1D6C2}', '\u{1D6DA}'), - Range::new('\u{1D6DC}', '\u{1D6FA}'), - Range::new('\u{1D6FC}', '\u{1D714}'), - Range::new('\u{1D716}', '\u{1D734}'), - Range::new('\u{1D736}', '\u{1D74E}'), - Range::new('\u{1D750}', '\u{1D76E}'), - Range::new('\u{1D770}', '\u{1D788}'), - Range::new('\u{1D78A}', '\u{1D7A8}'), - Range::new('\u{1D7AA}', '\u{1D7C2}'), - Range::new('\u{1D7C4}', '\u{1D7CB}'), - Range::new('\u{1D7CE}', '\u{1D7FF}'), - Range::new('\u{1DA00}', '\u{1DA36}'), - Range::new('\u{1DA3B}', '\u{1DA6C}'), - Range::new('\u{1DA75}', '\u{1DA75}'), - Range::new('\u{1DA84}', '\u{1DA84}'), - Range::new('\u{1DA9B}', '\u{1DA9F}'), - Range::new('\u{1DAA1}', '\u{1DAAF}'), - Range::new('\u{1DF00}', '\u{1DF1E}'), - Range::new('\u{1E000}', '\u{1E006}'), - Range::new('\u{1E008}', '\u{1E018}'), - Range::new('\u{1E01B}', '\u{1E021}'), - Range::new('\u{1E023}', '\u{1E024}'), - Range::new('\u{1E026}', '\u{1E02A}'), - Range::new('\u{1E100}', '\u{1E12C}'), - Range::new('\u{1E130}', '\u{1E13D}'), - Range::new('\u{1E140}', '\u{1E149}'), - Range::new('\u{1E14E}', '\u{1E14E}'), - Range::new('\u{1E290}', '\u{1E2AE}'), - Range::new('\u{1E2C0}', '\u{1E2F9}'), - Range::new('\u{1E7E0}', '\u{1E7E6}'), - Range::new('\u{1E7E8}', '\u{1E7EB}'), - Range::new('\u{1E7ED}', '\u{1E7EE}'), - Range::new('\u{1E7F0}', '\u{1E7FE}'), - Range::new('\u{1E800}', '\u{1E8C4}'), - Range::new('\u{1E8D0}', '\u{1E8D6}'), - Range::new('\u{1E900}', '\u{1E94B}'), - Range::new('\u{1E950}', '\u{1E959}'), - Range::new('\u{1EE00}', '\u{1EE03}'), - Range::new('\u{1EE05}', '\u{1EE1F}'), - Range::new('\u{1EE21}', '\u{1EE22}'), - Range::new('\u{1EE24}', '\u{1EE24}'), - Range::new('\u{1EE27}', '\u{1EE27}'), - Range::new('\u{1EE29}', '\u{1EE32}'), - Range::new('\u{1EE34}', '\u{1EE37}'), - Range::new('\u{1EE39}', '\u{1EE39}'), - Range::new('\u{1EE3B}', '\u{1EE3B}'), - Range::new('\u{1EE42}', '\u{1EE42}'), - Range::new('\u{1EE47}', '\u{1EE47}'), - Range::new('\u{1EE49}', '\u{1EE49}'), - Range::new('\u{1EE4B}', '\u{1EE4B}'), - Range::new('\u{1EE4D}', '\u{1EE4F}'), - Range::new('\u{1EE51}', '\u{1EE52}'), - Range::new('\u{1EE54}', '\u{1EE54}'), - Range::new('\u{1EE57}', '\u{1EE57}'), - Range::new('\u{1EE59}', '\u{1EE59}'), - Range::new('\u{1EE5B}', '\u{1EE5B}'), - Range::new('\u{1EE5D}', '\u{1EE5D}'), - Range::new('\u{1EE5F}', '\u{1EE5F}'), - Range::new('\u{1EE61}', '\u{1EE62}'), - Range::new('\u{1EE64}', '\u{1EE64}'), - Range::new('\u{1EE67}', '\u{1EE6A}'), - Range::new('\u{1EE6C}', '\u{1EE72}'), - Range::new('\u{1EE74}', '\u{1EE77}'), - Range::new('\u{1EE79}', '\u{1EE7C}'), - Range::new('\u{1EE7E}', '\u{1EE7E}'), - Range::new('\u{1EE80}', '\u{1EE89}'), - Range::new('\u{1EE8B}', '\u{1EE9B}'), - Range::new('\u{1EEA1}', '\u{1EEA3}'), - Range::new('\u{1EEA5}', '\u{1EEA9}'), - Range::new('\u{1EEAB}', '\u{1EEBB}'), - Range::new('\u{1F130}', '\u{1F149}'), - Range::new('\u{1F150}', '\u{1F169}'), - Range::new('\u{1F170}', '\u{1F189}'), - Range::new('\u{1FBF0}', '\u{1FBF9}'), - Range::new('\u{20000}', '\u{2A6DF}'), - Range::new('\u{2A700}', '\u{2B738}'), - Range::new('\u{2B740}', '\u{2B81D}'), - Range::new('\u{2B820}', '\u{2CEA1}'), - Range::new('\u{2CEB0}', '\u{2EBE0}'), - Range::new('\u{2F800}', '\u{2FA1D}'), - Range::new('\u{30000}', '\u{3134A}'), - Range::new('\u{E0100}', '\u{E01EF}'), -]; - -pub static XDIGIT: [Range; 66] = [ - Range::new('\u{30}', '\u{39}'), - Range::new('\u{41}', '\u{46}'), - Range::new('\u{61}', '\u{66}'), - Range::new('\u{660}', '\u{669}'), - Range::new('\u{6F0}', '\u{6F9}'), - Range::new('\u{7C0}', '\u{7C9}'), - Range::new('\u{966}', '\u{96F}'), - Range::new('\u{9E6}', '\u{9EF}'), - Range::new('\u{A66}', '\u{A6F}'), - Range::new('\u{AE6}', '\u{AEF}'), - Range::new('\u{B66}', '\u{B6F}'), - Range::new('\u{BE6}', '\u{BEF}'), - Range::new('\u{C66}', '\u{C6F}'), - Range::new('\u{CE6}', '\u{CEF}'), - Range::new('\u{D66}', '\u{D6F}'), - Range::new('\u{DE6}', '\u{DEF}'), - Range::new('\u{E50}', '\u{E59}'), - Range::new('\u{ED0}', '\u{ED9}'), - Range::new('\u{F20}', '\u{F29}'), - Range::new('\u{1040}', '\u{1049}'), - Range::new('\u{1090}', '\u{1099}'), - Range::new('\u{17E0}', '\u{17E9}'), - Range::new('\u{1810}', '\u{1819}'), - Range::new('\u{1946}', '\u{194F}'), - Range::new('\u{19D0}', '\u{19D9}'), - Range::new('\u{1A80}', '\u{1A89}'), - Range::new('\u{1A90}', '\u{1A99}'), - Range::new('\u{1B50}', '\u{1B59}'), - Range::new('\u{1BB0}', '\u{1BB9}'), - Range::new('\u{1C40}', '\u{1C49}'), - Range::new('\u{1C50}', '\u{1C59}'), - Range::new('\u{A620}', '\u{A629}'), - Range::new('\u{A8D0}', '\u{A8D9}'), - Range::new('\u{A900}', '\u{A909}'), - Range::new('\u{A9D0}', '\u{A9D9}'), - Range::new('\u{A9F0}', '\u{A9F9}'), - Range::new('\u{AA50}', '\u{AA59}'), - Range::new('\u{ABF0}', '\u{ABF9}'), - Range::new('\u{FF10}', '\u{FF19}'), - Range::new('\u{FF21}', '\u{FF26}'), - Range::new('\u{FF41}', '\u{FF46}'), - Range::new('\u{104A0}', '\u{104A9}'), - Range::new('\u{10D30}', '\u{10D39}'), - Range::new('\u{11066}', '\u{1106F}'), - Range::new('\u{110F0}', '\u{110F9}'), - Range::new('\u{11136}', '\u{1113F}'), - Range::new('\u{111D0}', '\u{111D9}'), - Range::new('\u{112F0}', '\u{112F9}'), - Range::new('\u{11450}', '\u{11459}'), - Range::new('\u{114D0}', '\u{114D9}'), - Range::new('\u{11650}', '\u{11659}'), - Range::new('\u{116C0}', '\u{116C9}'), - Range::new('\u{11730}', '\u{11739}'), - Range::new('\u{118E0}', '\u{118E9}'), - Range::new('\u{11950}', '\u{11959}'), - Range::new('\u{11C50}', '\u{11C59}'), - Range::new('\u{11D50}', '\u{11D59}'), - Range::new('\u{11DA0}', '\u{11DA9}'), - Range::new('\u{16A60}', '\u{16A69}'), - Range::new('\u{16AC0}', '\u{16AC9}'), - Range::new('\u{16B50}', '\u{16B59}'), - Range::new('\u{1D7CE}', '\u{1D7FF}'), - Range::new('\u{1E140}', '\u{1E149}'), - Range::new('\u{1E2F0}', '\u{1E2F9}'), - Range::new('\u{1E950}', '\u{1E959}'), - Range::new('\u{1FBF0}', '\u{1FBF9}'), -]; - -pub static CASE_FOLDS: [(char, &'static [char]); 2878] = [ - ('\u{41}', &['\u{41}', '\u{61}']), - ('\u{41}', &['\u{41}', '\u{61}']), - ('\u{42}', &['\u{42}', '\u{62}']), - ('\u{42}', &['\u{42}', '\u{62}']), - ('\u{43}', &['\u{43}', '\u{63}']), - ('\u{43}', &['\u{43}', '\u{63}']), - ('\u{44}', &['\u{44}', '\u{64}']), - ('\u{44}', &['\u{44}', '\u{64}']), - ('\u{45}', &['\u{45}', '\u{65}']), - ('\u{45}', &['\u{45}', '\u{65}']), - ('\u{46}', &['\u{46}', '\u{66}']), - ('\u{46}', &['\u{46}', '\u{66}']), - ('\u{47}', &['\u{47}', '\u{67}']), - ('\u{47}', &['\u{47}', '\u{67}']), - ('\u{48}', &['\u{48}', '\u{68}']), - ('\u{48}', &['\u{48}', '\u{68}']), - ('\u{49}', &['\u{49}', '\u{69}']), - ('\u{49}', &['\u{49}', '\u{69}']), - ('\u{4A}', &['\u{4A}', '\u{6A}']), - ('\u{4A}', &['\u{4A}', '\u{6A}']), - ('\u{4B}', &['\u{4B}', '\u{6B}', '\u{212A}']), - ('\u{4B}', &['\u{4B}', '\u{6B}', '\u{212A}']), - ('\u{4B}', &['\u{4B}', '\u{6B}', '\u{212A}']), - ('\u{4C}', &['\u{4C}', '\u{6C}']), - ('\u{4C}', &['\u{4C}', '\u{6C}']), - ('\u{4D}', &['\u{4D}', '\u{6D}']), - ('\u{4D}', &['\u{4D}', '\u{6D}']), - ('\u{4E}', &['\u{4E}', '\u{6E}']), - ('\u{4E}', &['\u{4E}', '\u{6E}']), - ('\u{4F}', &['\u{4F}', '\u{6F}']), - ('\u{4F}', &['\u{4F}', '\u{6F}']), - ('\u{50}', &['\u{50}', '\u{70}']), - ('\u{50}', &['\u{50}', '\u{70}']), - ('\u{51}', &['\u{51}', '\u{71}']), - ('\u{51}', &['\u{51}', '\u{71}']), - ('\u{52}', &['\u{52}', '\u{72}']), - ('\u{52}', &['\u{52}', '\u{72}']), - ('\u{53}', &['\u{53}', '\u{73}', '\u{17F}']), - ('\u{53}', &['\u{53}', '\u{73}', '\u{17F}']), - ('\u{53}', &['\u{53}', '\u{73}', '\u{17F}']), - ('\u{54}', &['\u{54}', '\u{74}']), - ('\u{54}', &['\u{54}', '\u{74}']), - ('\u{55}', &['\u{55}', '\u{75}']), - ('\u{55}', &['\u{55}', '\u{75}']), - ('\u{56}', &['\u{56}', '\u{76}']), - ('\u{56}', &['\u{56}', '\u{76}']), - ('\u{57}', &['\u{57}', '\u{77}']), - ('\u{57}', &['\u{57}', '\u{77}']), - ('\u{58}', &['\u{58}', '\u{78}']), - ('\u{58}', &['\u{58}', '\u{78}']), - ('\u{59}', &['\u{59}', '\u{79}']), - ('\u{59}', &['\u{59}', '\u{79}']), - ('\u{5A}', &['\u{5A}', '\u{7A}']), - ('\u{5A}', &['\u{5A}', '\u{7A}']), - ('\u{B5}', &['\u{B5}', '\u{39C}', '\u{3BC}']), - ('\u{B5}', &['\u{B5}', '\u{39C}', '\u{3BC}']), - ('\u{B5}', &['\u{B5}', '\u{39C}', '\u{3BC}']), - ('\u{C0}', &['\u{C0}', '\u{E0}']), - ('\u{C0}', &['\u{C0}', '\u{E0}']), - ('\u{C1}', &['\u{C1}', '\u{E1}']), - ('\u{C1}', &['\u{C1}', '\u{E1}']), - ('\u{C2}', &['\u{C2}', '\u{E2}']), - ('\u{C2}', &['\u{C2}', '\u{E2}']), - ('\u{C3}', &['\u{C3}', '\u{E3}']), - ('\u{C3}', &['\u{C3}', '\u{E3}']), - ('\u{C4}', &['\u{C4}', '\u{E4}']), - ('\u{C4}', &['\u{C4}', '\u{E4}']), - ('\u{C5}', &['\u{C5}', '\u{E5}', '\u{212B}']), - ('\u{C5}', &['\u{C5}', '\u{E5}', '\u{212B}']), - ('\u{C5}', &['\u{C5}', '\u{E5}', '\u{212B}']), - ('\u{C6}', &['\u{C6}', '\u{E6}']), - ('\u{C6}', &['\u{C6}', '\u{E6}']), - ('\u{C7}', &['\u{C7}', '\u{E7}']), - ('\u{C7}', &['\u{C7}', '\u{E7}']), - ('\u{C8}', &['\u{C8}', '\u{E8}']), - ('\u{C8}', &['\u{C8}', '\u{E8}']), - ('\u{C9}', &['\u{C9}', '\u{E9}']), - ('\u{C9}', &['\u{C9}', '\u{E9}']), - ('\u{CA}', &['\u{CA}', '\u{EA}']), - ('\u{CA}', &['\u{CA}', '\u{EA}']), - ('\u{CB}', &['\u{CB}', '\u{EB}']), - ('\u{CB}', &['\u{CB}', '\u{EB}']), - ('\u{CC}', &['\u{CC}', '\u{EC}']), - ('\u{CC}', &['\u{CC}', '\u{EC}']), - ('\u{CD}', &['\u{CD}', '\u{ED}']), - ('\u{CD}', &['\u{CD}', '\u{ED}']), - ('\u{CE}', &['\u{CE}', '\u{EE}']), - ('\u{CE}', &['\u{CE}', '\u{EE}']), - ('\u{CF}', &['\u{CF}', '\u{EF}']), - ('\u{CF}', &['\u{CF}', '\u{EF}']), - ('\u{D0}', &['\u{D0}', '\u{F0}']), - ('\u{D0}', &['\u{D0}', '\u{F0}']), - ('\u{D1}', &['\u{D1}', '\u{F1}']), - ('\u{D1}', &['\u{D1}', '\u{F1}']), - ('\u{D2}', &['\u{D2}', '\u{F2}']), - ('\u{D2}', &['\u{D2}', '\u{F2}']), - ('\u{D3}', &['\u{D3}', '\u{F3}']), - ('\u{D3}', &['\u{D3}', '\u{F3}']), - ('\u{D4}', &['\u{D4}', '\u{F4}']), - ('\u{D4}', &['\u{D4}', '\u{F4}']), - ('\u{D5}', &['\u{D5}', '\u{F5}']), - ('\u{D5}', &['\u{D5}', '\u{F5}']), - ('\u{D6}', &['\u{D6}', '\u{F6}']), - ('\u{D6}', &['\u{D6}', '\u{F6}']), - ('\u{D8}', &['\u{D8}', '\u{F8}']), - ('\u{D8}', &['\u{D8}', '\u{F8}']), - ('\u{D9}', &['\u{D9}', '\u{F9}']), - ('\u{D9}', &['\u{D9}', '\u{F9}']), - ('\u{DA}', &['\u{DA}', '\u{FA}']), - ('\u{DA}', &['\u{DA}', '\u{FA}']), - ('\u{DB}', &['\u{DB}', '\u{FB}']), - ('\u{DB}', &['\u{DB}', '\u{FB}']), - ('\u{DC}', &['\u{DC}', '\u{FC}']), - ('\u{DC}', &['\u{DC}', '\u{FC}']), - ('\u{DD}', &['\u{DD}', '\u{FD}']), - ('\u{DD}', &['\u{DD}', '\u{FD}']), - ('\u{DE}', &['\u{DE}', '\u{FE}']), - ('\u{DE}', &['\u{DE}', '\u{FE}']), - ('\u{DF}', &['\u{DF}', '\u{1E9E}']), - ('\u{DF}', &['\u{DF}', '\u{1E9E}']), - ('\u{FF}', &['\u{FF}', '\u{178}']), - ('\u{FF}', &['\u{FF}', '\u{178}']), - ('\u{100}', &['\u{100}', '\u{101}']), - ('\u{100}', &['\u{100}', '\u{101}']), - ('\u{102}', &['\u{102}', '\u{103}']), - ('\u{102}', &['\u{102}', '\u{103}']), - ('\u{104}', &['\u{104}', '\u{105}']), - ('\u{104}', &['\u{104}', '\u{105}']), - ('\u{106}', &['\u{106}', '\u{107}']), - ('\u{106}', &['\u{106}', '\u{107}']), - ('\u{108}', &['\u{108}', '\u{109}']), - ('\u{108}', &['\u{108}', '\u{109}']), - ('\u{10A}', &['\u{10A}', '\u{10B}']), - ('\u{10A}', &['\u{10A}', '\u{10B}']), - ('\u{10C}', &['\u{10C}', '\u{10D}']), - ('\u{10C}', &['\u{10C}', '\u{10D}']), - ('\u{10E}', &['\u{10E}', '\u{10F}']), - ('\u{10E}', &['\u{10E}', '\u{10F}']), - ('\u{110}', &['\u{110}', '\u{111}']), - ('\u{110}', &['\u{110}', '\u{111}']), - ('\u{112}', &['\u{112}', '\u{113}']), - ('\u{112}', &['\u{112}', '\u{113}']), - ('\u{114}', &['\u{114}', '\u{115}']), - ('\u{114}', &['\u{114}', '\u{115}']), - ('\u{116}', &['\u{116}', '\u{117}']), - ('\u{116}', &['\u{116}', '\u{117}']), - ('\u{118}', &['\u{118}', '\u{119}']), - ('\u{118}', &['\u{118}', '\u{119}']), - ('\u{11A}', &['\u{11A}', '\u{11B}']), - ('\u{11A}', &['\u{11A}', '\u{11B}']), - ('\u{11C}', &['\u{11C}', '\u{11D}']), - ('\u{11C}', &['\u{11C}', '\u{11D}']), - ('\u{11E}', &['\u{11E}', '\u{11F}']), - ('\u{11E}', &['\u{11E}', '\u{11F}']), - ('\u{120}', &['\u{120}', '\u{121}']), - ('\u{120}', &['\u{120}', '\u{121}']), - ('\u{122}', &['\u{122}', '\u{123}']), - ('\u{122}', &['\u{122}', '\u{123}']), - ('\u{124}', &['\u{124}', '\u{125}']), - ('\u{124}', &['\u{124}', '\u{125}']), - ('\u{126}', &['\u{126}', '\u{127}']), - ('\u{126}', &['\u{126}', '\u{127}']), - ('\u{128}', &['\u{128}', '\u{129}']), - ('\u{128}', &['\u{128}', '\u{129}']), - ('\u{12A}', &['\u{12A}', '\u{12B}']), - ('\u{12A}', &['\u{12A}', '\u{12B}']), - ('\u{12C}', &['\u{12C}', '\u{12D}']), - ('\u{12C}', &['\u{12C}', '\u{12D}']), - ('\u{12E}', &['\u{12E}', '\u{12F}']), - ('\u{12E}', &['\u{12E}', '\u{12F}']), - ('\u{132}', &['\u{132}', '\u{133}']), - ('\u{132}', &['\u{132}', '\u{133}']), - ('\u{134}', &['\u{134}', '\u{135}']), - ('\u{134}', &['\u{134}', '\u{135}']), - ('\u{136}', &['\u{136}', '\u{137}']), - ('\u{136}', &['\u{136}', '\u{137}']), - ('\u{139}', &['\u{139}', '\u{13A}']), - ('\u{139}', &['\u{139}', '\u{13A}']), - ('\u{13B}', &['\u{13B}', '\u{13C}']), - ('\u{13B}', &['\u{13B}', '\u{13C}']), - ('\u{13D}', &['\u{13D}', '\u{13E}']), - ('\u{13D}', &['\u{13D}', '\u{13E}']), - ('\u{13F}', &['\u{13F}', '\u{140}']), - ('\u{13F}', &['\u{13F}', '\u{140}']), - ('\u{141}', &['\u{141}', '\u{142}']), - ('\u{141}', &['\u{141}', '\u{142}']), - ('\u{143}', &['\u{143}', '\u{144}']), - ('\u{143}', &['\u{143}', '\u{144}']), - ('\u{145}', &['\u{145}', '\u{146}']), - ('\u{145}', &['\u{145}', '\u{146}']), - ('\u{147}', &['\u{147}', '\u{148}']), - ('\u{147}', &['\u{147}', '\u{148}']), - ('\u{14A}', &['\u{14A}', '\u{14B}']), - ('\u{14A}', &['\u{14A}', '\u{14B}']), - ('\u{14C}', &['\u{14C}', '\u{14D}']), - ('\u{14C}', &['\u{14C}', '\u{14D}']), - ('\u{14E}', &['\u{14E}', '\u{14F}']), - ('\u{14E}', &['\u{14E}', '\u{14F}']), - ('\u{150}', &['\u{150}', '\u{151}']), - ('\u{150}', &['\u{150}', '\u{151}']), - ('\u{152}', &['\u{152}', '\u{153}']), - ('\u{152}', &['\u{152}', '\u{153}']), - ('\u{154}', &['\u{154}', '\u{155}']), - ('\u{154}', &['\u{154}', '\u{155}']), - ('\u{156}', &['\u{156}', '\u{157}']), - ('\u{156}', &['\u{156}', '\u{157}']), - ('\u{158}', &['\u{158}', '\u{159}']), - ('\u{158}', &['\u{158}', '\u{159}']), - ('\u{15A}', &['\u{15A}', '\u{15B}']), - ('\u{15A}', &['\u{15A}', '\u{15B}']), - ('\u{15C}', &['\u{15C}', '\u{15D}']), - ('\u{15C}', &['\u{15C}', '\u{15D}']), - ('\u{15E}', &['\u{15E}', '\u{15F}']), - ('\u{15E}', &['\u{15E}', '\u{15F}']), - ('\u{160}', &['\u{160}', '\u{161}']), - ('\u{160}', &['\u{160}', '\u{161}']), - ('\u{162}', &['\u{162}', '\u{163}']), - ('\u{162}', &['\u{162}', '\u{163}']), - ('\u{164}', &['\u{164}', '\u{165}']), - ('\u{164}', &['\u{164}', '\u{165}']), - ('\u{166}', &['\u{166}', '\u{167}']), - ('\u{166}', &['\u{166}', '\u{167}']), - ('\u{168}', &['\u{168}', '\u{169}']), - ('\u{168}', &['\u{168}', '\u{169}']), - ('\u{16A}', &['\u{16A}', '\u{16B}']), - ('\u{16A}', &['\u{16A}', '\u{16B}']), - ('\u{16C}', &['\u{16C}', '\u{16D}']), - ('\u{16C}', &['\u{16C}', '\u{16D}']), - ('\u{16E}', &['\u{16E}', '\u{16F}']), - ('\u{16E}', &['\u{16E}', '\u{16F}']), - ('\u{170}', &['\u{170}', '\u{171}']), - ('\u{170}', &['\u{170}', '\u{171}']), - ('\u{172}', &['\u{172}', '\u{173}']), - ('\u{172}', &['\u{172}', '\u{173}']), - ('\u{174}', &['\u{174}', '\u{175}']), - ('\u{174}', &['\u{174}', '\u{175}']), - ('\u{176}', &['\u{176}', '\u{177}']), - ('\u{176}', &['\u{176}', '\u{177}']), - ('\u{179}', &['\u{179}', '\u{17A}']), - ('\u{179}', &['\u{179}', '\u{17A}']), - ('\u{17B}', &['\u{17B}', '\u{17C}']), - ('\u{17B}', &['\u{17B}', '\u{17C}']), - ('\u{17D}', &['\u{17D}', '\u{17E}']), - ('\u{17D}', &['\u{17D}', '\u{17E}']), - ('\u{180}', &['\u{180}', '\u{243}']), - ('\u{180}', &['\u{180}', '\u{243}']), - ('\u{181}', &['\u{181}', '\u{253}']), - ('\u{181}', &['\u{181}', '\u{253}']), - ('\u{182}', &['\u{182}', '\u{183}']), - ('\u{182}', &['\u{182}', '\u{183}']), - ('\u{184}', &['\u{184}', '\u{185}']), - ('\u{184}', &['\u{184}', '\u{185}']), - ('\u{186}', &['\u{186}', '\u{254}']), - ('\u{186}', &['\u{186}', '\u{254}']), - ('\u{187}', &['\u{187}', '\u{188}']), - ('\u{187}', &['\u{187}', '\u{188}']), - ('\u{189}', &['\u{189}', '\u{256}']), - ('\u{189}', &['\u{189}', '\u{256}']), - ('\u{18A}', &['\u{18A}', '\u{257}']), - ('\u{18A}', &['\u{18A}', '\u{257}']), - ('\u{18B}', &['\u{18B}', '\u{18C}']), - ('\u{18B}', &['\u{18B}', '\u{18C}']), - ('\u{18E}', &['\u{18E}', '\u{1DD}']), - ('\u{18E}', &['\u{18E}', '\u{1DD}']), - ('\u{18F}', &['\u{18F}', '\u{259}']), - ('\u{18F}', &['\u{18F}', '\u{259}']), - ('\u{190}', &['\u{190}', '\u{25B}']), - ('\u{190}', &['\u{190}', '\u{25B}']), - ('\u{191}', &['\u{191}', '\u{192}']), - ('\u{191}', &['\u{191}', '\u{192}']), - ('\u{193}', &['\u{193}', '\u{260}']), - ('\u{193}', &['\u{193}', '\u{260}']), - ('\u{194}', &['\u{194}', '\u{263}']), - ('\u{194}', &['\u{194}', '\u{263}']), - ('\u{195}', &['\u{195}', '\u{1F6}']), - ('\u{195}', &['\u{195}', '\u{1F6}']), - ('\u{196}', &['\u{196}', '\u{269}']), - ('\u{196}', &['\u{196}', '\u{269}']), - ('\u{197}', &['\u{197}', '\u{268}']), - ('\u{197}', &['\u{197}', '\u{268}']), - ('\u{198}', &['\u{198}', '\u{199}']), - ('\u{198}', &['\u{198}', '\u{199}']), - ('\u{19A}', &['\u{19A}', '\u{23D}']), - ('\u{19A}', &['\u{19A}', '\u{23D}']), - ('\u{19C}', &['\u{19C}', '\u{26F}']), - ('\u{19C}', &['\u{19C}', '\u{26F}']), - ('\u{19D}', &['\u{19D}', '\u{272}']), - ('\u{19D}', &['\u{19D}', '\u{272}']), - ('\u{19E}', &['\u{19E}', '\u{220}']), - ('\u{19E}', &['\u{19E}', '\u{220}']), - ('\u{19F}', &['\u{19F}', '\u{275}']), - ('\u{19F}', &['\u{19F}', '\u{275}']), - ('\u{1A0}', &['\u{1A0}', '\u{1A1}']), - ('\u{1A0}', &['\u{1A0}', '\u{1A1}']), - ('\u{1A2}', &['\u{1A2}', '\u{1A3}']), - ('\u{1A2}', &['\u{1A2}', '\u{1A3}']), - ('\u{1A4}', &['\u{1A4}', '\u{1A5}']), - ('\u{1A4}', &['\u{1A4}', '\u{1A5}']), - ('\u{1A6}', &['\u{1A6}', '\u{280}']), - ('\u{1A6}', &['\u{1A6}', '\u{280}']), - ('\u{1A7}', &['\u{1A7}', '\u{1A8}']), - ('\u{1A7}', &['\u{1A7}', '\u{1A8}']), - ('\u{1A9}', &['\u{1A9}', '\u{283}']), - ('\u{1A9}', &['\u{1A9}', '\u{283}']), - ('\u{1AC}', &['\u{1AC}', '\u{1AD}']), - ('\u{1AC}', &['\u{1AC}', '\u{1AD}']), - ('\u{1AE}', &['\u{1AE}', '\u{288}']), - ('\u{1AE}', &['\u{1AE}', '\u{288}']), - ('\u{1AF}', &['\u{1AF}', '\u{1B0}']), - ('\u{1AF}', &['\u{1AF}', '\u{1B0}']), - ('\u{1B1}', &['\u{1B1}', '\u{28A}']), - ('\u{1B1}', &['\u{1B1}', '\u{28A}']), - ('\u{1B2}', &['\u{1B2}', '\u{28B}']), - ('\u{1B2}', &['\u{1B2}', '\u{28B}']), - ('\u{1B3}', &['\u{1B3}', '\u{1B4}']), - ('\u{1B3}', &['\u{1B3}', '\u{1B4}']), - ('\u{1B5}', &['\u{1B5}', '\u{1B6}']), - ('\u{1B5}', &['\u{1B5}', '\u{1B6}']), - ('\u{1B7}', &['\u{1B7}', '\u{292}']), - ('\u{1B7}', &['\u{1B7}', '\u{292}']), - ('\u{1B8}', &['\u{1B8}', '\u{1B9}']), - ('\u{1B8}', &['\u{1B8}', '\u{1B9}']), - ('\u{1BC}', &['\u{1BC}', '\u{1BD}']), - ('\u{1BC}', &['\u{1BC}', '\u{1BD}']), - ('\u{1BF}', &['\u{1BF}', '\u{1F7}']), - ('\u{1BF}', &['\u{1BF}', '\u{1F7}']), - ('\u{1C4}', &['\u{1C4}', '\u{1C5}', '\u{1C6}']), - ('\u{1C4}', &['\u{1C4}', '\u{1C5}', '\u{1C6}']), - ('\u{1C4}', &['\u{1C4}', '\u{1C5}', '\u{1C6}']), - ('\u{1C7}', &['\u{1C7}', '\u{1C8}', '\u{1C9}']), - ('\u{1C7}', &['\u{1C7}', '\u{1C8}', '\u{1C9}']), - ('\u{1C7}', &['\u{1C7}', '\u{1C8}', '\u{1C9}']), - ('\u{1CA}', &['\u{1CA}', '\u{1CB}', '\u{1CC}']), - ('\u{1CA}', &['\u{1CA}', '\u{1CB}', '\u{1CC}']), - ('\u{1CA}', &['\u{1CA}', '\u{1CB}', '\u{1CC}']), - ('\u{1CD}', &['\u{1CD}', '\u{1CE}']), - ('\u{1CD}', &['\u{1CD}', '\u{1CE}']), - ('\u{1CF}', &['\u{1CF}', '\u{1D0}']), - ('\u{1CF}', &['\u{1CF}', '\u{1D0}']), - ('\u{1D1}', &['\u{1D1}', '\u{1D2}']), - ('\u{1D1}', &['\u{1D1}', '\u{1D2}']), - ('\u{1D3}', &['\u{1D3}', '\u{1D4}']), - ('\u{1D3}', &['\u{1D3}', '\u{1D4}']), - ('\u{1D5}', &['\u{1D5}', '\u{1D6}']), - ('\u{1D5}', &['\u{1D5}', '\u{1D6}']), - ('\u{1D7}', &['\u{1D7}', '\u{1D8}']), - ('\u{1D7}', &['\u{1D7}', '\u{1D8}']), - ('\u{1D9}', &['\u{1D9}', '\u{1DA}']), - ('\u{1D9}', &['\u{1D9}', '\u{1DA}']), - ('\u{1DB}', &['\u{1DB}', '\u{1DC}']), - ('\u{1DB}', &['\u{1DB}', '\u{1DC}']), - ('\u{1DE}', &['\u{1DE}', '\u{1DF}']), - ('\u{1DE}', &['\u{1DE}', '\u{1DF}']), - ('\u{1E0}', &['\u{1E0}', '\u{1E1}']), - ('\u{1E0}', &['\u{1E0}', '\u{1E1}']), - ('\u{1E2}', &['\u{1E2}', '\u{1E3}']), - ('\u{1E2}', &['\u{1E2}', '\u{1E3}']), - ('\u{1E4}', &['\u{1E4}', '\u{1E5}']), - ('\u{1E4}', &['\u{1E4}', '\u{1E5}']), - ('\u{1E6}', &['\u{1E6}', '\u{1E7}']), - ('\u{1E6}', &['\u{1E6}', '\u{1E7}']), - ('\u{1E8}', &['\u{1E8}', '\u{1E9}']), - ('\u{1E8}', &['\u{1E8}', '\u{1E9}']), - ('\u{1EA}', &['\u{1EA}', '\u{1EB}']), - ('\u{1EA}', &['\u{1EA}', '\u{1EB}']), - ('\u{1EC}', &['\u{1EC}', '\u{1ED}']), - ('\u{1EC}', &['\u{1EC}', '\u{1ED}']), - ('\u{1EE}', &['\u{1EE}', '\u{1EF}']), - ('\u{1EE}', &['\u{1EE}', '\u{1EF}']), - ('\u{1F1}', &['\u{1F1}', '\u{1F2}', '\u{1F3}']), - ('\u{1F1}', &['\u{1F1}', '\u{1F2}', '\u{1F3}']), - ('\u{1F1}', &['\u{1F1}', '\u{1F2}', '\u{1F3}']), - ('\u{1F4}', &['\u{1F4}', '\u{1F5}']), - ('\u{1F4}', &['\u{1F4}', '\u{1F5}']), - ('\u{1F8}', &['\u{1F8}', '\u{1F9}']), - ('\u{1F8}', &['\u{1F8}', '\u{1F9}']), - ('\u{1FA}', &['\u{1FA}', '\u{1FB}']), - ('\u{1FA}', &['\u{1FA}', '\u{1FB}']), - ('\u{1FC}', &['\u{1FC}', '\u{1FD}']), - ('\u{1FC}', &['\u{1FC}', '\u{1FD}']), - ('\u{1FE}', &['\u{1FE}', '\u{1FF}']), - ('\u{1FE}', &['\u{1FE}', '\u{1FF}']), - ('\u{200}', &['\u{200}', '\u{201}']), - ('\u{200}', &['\u{200}', '\u{201}']), - ('\u{202}', &['\u{202}', '\u{203}']), - ('\u{202}', &['\u{202}', '\u{203}']), - ('\u{204}', &['\u{204}', '\u{205}']), - ('\u{204}', &['\u{204}', '\u{205}']), - ('\u{206}', &['\u{206}', '\u{207}']), - ('\u{206}', &['\u{206}', '\u{207}']), - ('\u{208}', &['\u{208}', '\u{209}']), - ('\u{208}', &['\u{208}', '\u{209}']), - ('\u{20A}', &['\u{20A}', '\u{20B}']), - ('\u{20A}', &['\u{20A}', '\u{20B}']), - ('\u{20C}', &['\u{20C}', '\u{20D}']), - ('\u{20C}', &['\u{20C}', '\u{20D}']), - ('\u{20E}', &['\u{20E}', '\u{20F}']), - ('\u{20E}', &['\u{20E}', '\u{20F}']), - ('\u{210}', &['\u{210}', '\u{211}']), - ('\u{210}', &['\u{210}', '\u{211}']), - ('\u{212}', &['\u{212}', '\u{213}']), - ('\u{212}', &['\u{212}', '\u{213}']), - ('\u{214}', &['\u{214}', '\u{215}']), - ('\u{214}', &['\u{214}', '\u{215}']), - ('\u{216}', &['\u{216}', '\u{217}']), - ('\u{216}', &['\u{216}', '\u{217}']), - ('\u{218}', &['\u{218}', '\u{219}']), - ('\u{218}', &['\u{218}', '\u{219}']), - ('\u{21A}', &['\u{21A}', '\u{21B}']), - ('\u{21A}', &['\u{21A}', '\u{21B}']), - ('\u{21C}', &['\u{21C}', '\u{21D}']), - ('\u{21C}', &['\u{21C}', '\u{21D}']), - ('\u{21E}', &['\u{21E}', '\u{21F}']), - ('\u{21E}', &['\u{21E}', '\u{21F}']), - ('\u{222}', &['\u{222}', '\u{223}']), - ('\u{222}', &['\u{222}', '\u{223}']), - ('\u{224}', &['\u{224}', '\u{225}']), - ('\u{224}', &['\u{224}', '\u{225}']), - ('\u{226}', &['\u{226}', '\u{227}']), - ('\u{226}', &['\u{226}', '\u{227}']), - ('\u{228}', &['\u{228}', '\u{229}']), - ('\u{228}', &['\u{228}', '\u{229}']), - ('\u{22A}', &['\u{22A}', '\u{22B}']), - ('\u{22A}', &['\u{22A}', '\u{22B}']), - ('\u{22C}', &['\u{22C}', '\u{22D}']), - ('\u{22C}', &['\u{22C}', '\u{22D}']), - ('\u{22E}', &['\u{22E}', '\u{22F}']), - ('\u{22E}', &['\u{22E}', '\u{22F}']), - ('\u{230}', &['\u{230}', '\u{231}']), - ('\u{230}', &['\u{230}', '\u{231}']), - ('\u{232}', &['\u{232}', '\u{233}']), - ('\u{232}', &['\u{232}', '\u{233}']), - ('\u{23A}', &['\u{23A}', '\u{2C65}']), - ('\u{23A}', &['\u{23A}', '\u{2C65}']), - ('\u{23B}', &['\u{23B}', '\u{23C}']), - ('\u{23B}', &['\u{23B}', '\u{23C}']), - ('\u{23E}', &['\u{23E}', '\u{2C66}']), - ('\u{23E}', &['\u{23E}', '\u{2C66}']), - ('\u{23F}', &['\u{23F}', '\u{2C7E}']), - ('\u{23F}', &['\u{23F}', '\u{2C7E}']), - ('\u{240}', &['\u{240}', '\u{2C7F}']), - ('\u{240}', &['\u{240}', '\u{2C7F}']), - ('\u{241}', &['\u{241}', '\u{242}']), - ('\u{241}', &['\u{241}', '\u{242}']), - ('\u{244}', &['\u{244}', '\u{289}']), - ('\u{244}', &['\u{244}', '\u{289}']), - ('\u{245}', &['\u{245}', '\u{28C}']), - ('\u{245}', &['\u{245}', '\u{28C}']), - ('\u{246}', &['\u{246}', '\u{247}']), - ('\u{246}', &['\u{246}', '\u{247}']), - ('\u{248}', &['\u{248}', '\u{249}']), - ('\u{248}', &['\u{248}', '\u{249}']), - ('\u{24A}', &['\u{24A}', '\u{24B}']), - ('\u{24A}', &['\u{24A}', '\u{24B}']), - ('\u{24C}', &['\u{24C}', '\u{24D}']), - ('\u{24C}', &['\u{24C}', '\u{24D}']), - ('\u{24E}', &['\u{24E}', '\u{24F}']), - ('\u{24E}', &['\u{24E}', '\u{24F}']), - ('\u{250}', &['\u{250}', '\u{2C6F}']), - ('\u{250}', &['\u{250}', '\u{2C6F}']), - ('\u{251}', &['\u{251}', '\u{2C6D}']), - ('\u{251}', &['\u{251}', '\u{2C6D}']), - ('\u{252}', &['\u{252}', '\u{2C70}']), - ('\u{252}', &['\u{252}', '\u{2C70}']), - ('\u{25C}', &['\u{25C}', '\u{A7AB}']), - ('\u{25C}', &['\u{25C}', '\u{A7AB}']), - ('\u{261}', &['\u{261}', '\u{A7AC}']), - ('\u{261}', &['\u{261}', '\u{A7AC}']), - ('\u{265}', &['\u{265}', '\u{A78D}']), - ('\u{265}', &['\u{265}', '\u{A78D}']), - ('\u{266}', &['\u{266}', '\u{A7AA}']), - ('\u{266}', &['\u{266}', '\u{A7AA}']), - ('\u{26A}', &['\u{26A}', '\u{A7AE}']), - ('\u{26A}', &['\u{26A}', '\u{A7AE}']), - ('\u{26B}', &['\u{26B}', '\u{2C62}']), - ('\u{26B}', &['\u{26B}', '\u{2C62}']), - ('\u{26C}', &['\u{26C}', '\u{A7AD}']), - ('\u{26C}', &['\u{26C}', '\u{A7AD}']), - ('\u{271}', &['\u{271}', '\u{2C6E}']), - ('\u{271}', &['\u{271}', '\u{2C6E}']), - ('\u{27D}', &['\u{27D}', '\u{2C64}']), - ('\u{27D}', &['\u{27D}', '\u{2C64}']), - ('\u{282}', &['\u{282}', '\u{A7C5}']), - ('\u{282}', &['\u{282}', '\u{A7C5}']), - ('\u{287}', &['\u{287}', '\u{A7B1}']), - ('\u{287}', &['\u{287}', '\u{A7B1}']), - ('\u{29D}', &['\u{29D}', '\u{A7B2}']), - ('\u{29D}', &['\u{29D}', '\u{A7B2}']), - ('\u{29E}', &['\u{29E}', '\u{A7B0}']), - ('\u{29E}', &['\u{29E}', '\u{A7B0}']), - ('\u{345}', &['\u{345}', '\u{399}', '\u{3B9}', '\u{1FBE}']), - ('\u{345}', &['\u{345}', '\u{399}', '\u{3B9}', '\u{1FBE}']), - ('\u{345}', &['\u{345}', '\u{399}', '\u{3B9}', '\u{1FBE}']), - ('\u{345}', &['\u{345}', '\u{399}', '\u{3B9}', '\u{1FBE}']), - ('\u{370}', &['\u{370}', '\u{371}']), - ('\u{370}', &['\u{370}', '\u{371}']), - ('\u{372}', &['\u{372}', '\u{373}']), - ('\u{372}', &['\u{372}', '\u{373}']), - ('\u{376}', &['\u{376}', '\u{377}']), - ('\u{376}', &['\u{376}', '\u{377}']), - ('\u{37B}', &['\u{37B}', '\u{3FD}']), - ('\u{37B}', &['\u{37B}', '\u{3FD}']), - ('\u{37C}', &['\u{37C}', '\u{3FE}']), - ('\u{37C}', &['\u{37C}', '\u{3FE}']), - ('\u{37D}', &['\u{37D}', '\u{3FF}']), - ('\u{37D}', &['\u{37D}', '\u{3FF}']), - ('\u{37F}', &['\u{37F}', '\u{3F3}']), - ('\u{37F}', &['\u{37F}', '\u{3F3}']), - ('\u{386}', &['\u{386}', '\u{3AC}']), - ('\u{386}', &['\u{386}', '\u{3AC}']), - ('\u{388}', &['\u{388}', '\u{3AD}']), - ('\u{388}', &['\u{388}', '\u{3AD}']), - ('\u{389}', &['\u{389}', '\u{3AE}']), - ('\u{389}', &['\u{389}', '\u{3AE}']), - ('\u{38A}', &['\u{38A}', '\u{3AF}']), - ('\u{38A}', &['\u{38A}', '\u{3AF}']), - ('\u{38C}', &['\u{38C}', '\u{3CC}']), - ('\u{38C}', &['\u{38C}', '\u{3CC}']), - ('\u{38E}', &['\u{38E}', '\u{3CD}']), - ('\u{38E}', &['\u{38E}', '\u{3CD}']), - ('\u{38F}', &['\u{38F}', '\u{3CE}']), - ('\u{38F}', &['\u{38F}', '\u{3CE}']), - ('\u{391}', &['\u{391}', '\u{3B1}']), - ('\u{391}', &['\u{391}', '\u{3B1}']), - ('\u{392}', &['\u{392}', '\u{3B2}', '\u{3D0}']), - ('\u{392}', &['\u{392}', '\u{3B2}', '\u{3D0}']), - ('\u{392}', &['\u{392}', '\u{3B2}', '\u{3D0}']), - ('\u{393}', &['\u{393}', '\u{3B3}']), - ('\u{393}', &['\u{393}', '\u{3B3}']), - ('\u{394}', &['\u{394}', '\u{3B4}']), - ('\u{394}', &['\u{394}', '\u{3B4}']), - ('\u{395}', &['\u{395}', '\u{3B5}', '\u{3F5}']), - ('\u{395}', &['\u{395}', '\u{3B5}', '\u{3F5}']), - ('\u{395}', &['\u{395}', '\u{3B5}', '\u{3F5}']), - ('\u{396}', &['\u{396}', '\u{3B6}']), - ('\u{396}', &['\u{396}', '\u{3B6}']), - ('\u{397}', &['\u{397}', '\u{3B7}']), - ('\u{397}', &['\u{397}', '\u{3B7}']), - ('\u{398}', &['\u{398}', '\u{3B8}', '\u{3D1}', '\u{3F4}']), - ('\u{398}', &['\u{398}', '\u{3B8}', '\u{3D1}', '\u{3F4}']), - ('\u{398}', &['\u{398}', '\u{3B8}', '\u{3D1}', '\u{3F4}']), - ('\u{398}', &['\u{398}', '\u{3B8}', '\u{3D1}', '\u{3F4}']), - ('\u{39A}', &['\u{39A}', '\u{3BA}', '\u{3F0}']), - ('\u{39A}', &['\u{39A}', '\u{3BA}', '\u{3F0}']), - ('\u{39A}', &['\u{39A}', '\u{3BA}', '\u{3F0}']), - ('\u{39B}', &['\u{39B}', '\u{3BB}']), - ('\u{39B}', &['\u{39B}', '\u{3BB}']), - ('\u{39D}', &['\u{39D}', '\u{3BD}']), - ('\u{39D}', &['\u{39D}', '\u{3BD}']), - ('\u{39E}', &['\u{39E}', '\u{3BE}']), - ('\u{39E}', &['\u{39E}', '\u{3BE}']), - ('\u{39F}', &['\u{39F}', '\u{3BF}']), - ('\u{39F}', &['\u{39F}', '\u{3BF}']), - ('\u{3A0}', &['\u{3A0}', '\u{3C0}', '\u{3D6}']), - ('\u{3A0}', &['\u{3A0}', '\u{3C0}', '\u{3D6}']), - ('\u{3A0}', &['\u{3A0}', '\u{3C0}', '\u{3D6}']), - ('\u{3A1}', &['\u{3A1}', '\u{3C1}', '\u{3F1}']), - ('\u{3A1}', &['\u{3A1}', '\u{3C1}', '\u{3F1}']), - ('\u{3A1}', &['\u{3A1}', '\u{3C1}', '\u{3F1}']), - ('\u{3A3}', &['\u{3A3}', '\u{3C2}', '\u{3C3}']), - ('\u{3A3}', &['\u{3A3}', '\u{3C2}', '\u{3C3}']), - ('\u{3A3}', &['\u{3A3}', '\u{3C2}', '\u{3C3}']), - ('\u{3A4}', &['\u{3A4}', '\u{3C4}']), - ('\u{3A4}', &['\u{3A4}', '\u{3C4}']), - ('\u{3A5}', &['\u{3A5}', '\u{3C5}']), - ('\u{3A5}', &['\u{3A5}', '\u{3C5}']), - ('\u{3A6}', &['\u{3A6}', '\u{3C6}', '\u{3D5}']), - ('\u{3A6}', &['\u{3A6}', '\u{3C6}', '\u{3D5}']), - ('\u{3A6}', &['\u{3A6}', '\u{3C6}', '\u{3D5}']), - ('\u{3A7}', &['\u{3A7}', '\u{3C7}']), - ('\u{3A7}', &['\u{3A7}', '\u{3C7}']), - ('\u{3A8}', &['\u{3A8}', '\u{3C8}']), - ('\u{3A8}', &['\u{3A8}', '\u{3C8}']), - ('\u{3A9}', &['\u{3A9}', '\u{3C9}', '\u{2126}']), - ('\u{3A9}', &['\u{3A9}', '\u{3C9}', '\u{2126}']), - ('\u{3A9}', &['\u{3A9}', '\u{3C9}', '\u{2126}']), - ('\u{3AA}', &['\u{3AA}', '\u{3CA}']), - ('\u{3AA}', &['\u{3AA}', '\u{3CA}']), - ('\u{3AB}', &['\u{3AB}', '\u{3CB}']), - ('\u{3AB}', &['\u{3AB}', '\u{3CB}']), - ('\u{3CF}', &['\u{3CF}', '\u{3D7}']), - ('\u{3CF}', &['\u{3CF}', '\u{3D7}']), - ('\u{3D8}', &['\u{3D8}', '\u{3D9}']), - ('\u{3D8}', &['\u{3D8}', '\u{3D9}']), - ('\u{3DA}', &['\u{3DA}', '\u{3DB}']), - ('\u{3DA}', &['\u{3DA}', '\u{3DB}']), - ('\u{3DC}', &['\u{3DC}', '\u{3DD}']), - ('\u{3DC}', &['\u{3DC}', '\u{3DD}']), - ('\u{3DE}', &['\u{3DE}', '\u{3DF}']), - ('\u{3DE}', &['\u{3DE}', '\u{3DF}']), - ('\u{3E0}', &['\u{3E0}', '\u{3E1}']), - ('\u{3E0}', &['\u{3E0}', '\u{3E1}']), - ('\u{3E2}', &['\u{3E2}', '\u{3E3}']), - ('\u{3E2}', &['\u{3E2}', '\u{3E3}']), - ('\u{3E4}', &['\u{3E4}', '\u{3E5}']), - ('\u{3E4}', &['\u{3E4}', '\u{3E5}']), - ('\u{3E6}', &['\u{3E6}', '\u{3E7}']), - ('\u{3E6}', &['\u{3E6}', '\u{3E7}']), - ('\u{3E8}', &['\u{3E8}', '\u{3E9}']), - ('\u{3E8}', &['\u{3E8}', '\u{3E9}']), - ('\u{3EA}', &['\u{3EA}', '\u{3EB}']), - ('\u{3EA}', &['\u{3EA}', '\u{3EB}']), - ('\u{3EC}', &['\u{3EC}', '\u{3ED}']), - ('\u{3EC}', &['\u{3EC}', '\u{3ED}']), - ('\u{3EE}', &['\u{3EE}', '\u{3EF}']), - ('\u{3EE}', &['\u{3EE}', '\u{3EF}']), - ('\u{3F2}', &['\u{3F2}', '\u{3F9}']), - ('\u{3F2}', &['\u{3F2}', '\u{3F9}']), - ('\u{3F7}', &['\u{3F7}', '\u{3F8}']), - ('\u{3F7}', &['\u{3F7}', '\u{3F8}']), - ('\u{3FA}', &['\u{3FA}', '\u{3FB}']), - ('\u{3FA}', &['\u{3FA}', '\u{3FB}']), - ('\u{400}', &['\u{400}', '\u{450}']), - ('\u{400}', &['\u{400}', '\u{450}']), - ('\u{401}', &['\u{401}', '\u{451}']), - ('\u{401}', &['\u{401}', '\u{451}']), - ('\u{402}', &['\u{402}', '\u{452}']), - ('\u{402}', &['\u{402}', '\u{452}']), - ('\u{403}', &['\u{403}', '\u{453}']), - ('\u{403}', &['\u{403}', '\u{453}']), - ('\u{404}', &['\u{404}', '\u{454}']), - ('\u{404}', &['\u{404}', '\u{454}']), - ('\u{405}', &['\u{405}', '\u{455}']), - ('\u{405}', &['\u{405}', '\u{455}']), - ('\u{406}', &['\u{406}', '\u{456}']), - ('\u{406}', &['\u{406}', '\u{456}']), - ('\u{407}', &['\u{407}', '\u{457}']), - ('\u{407}', &['\u{407}', '\u{457}']), - ('\u{408}', &['\u{408}', '\u{458}']), - ('\u{408}', &['\u{408}', '\u{458}']), - ('\u{409}', &['\u{409}', '\u{459}']), - ('\u{409}', &['\u{409}', '\u{459}']), - ('\u{40A}', &['\u{40A}', '\u{45A}']), - ('\u{40A}', &['\u{40A}', '\u{45A}']), - ('\u{40B}', &['\u{40B}', '\u{45B}']), - ('\u{40B}', &['\u{40B}', '\u{45B}']), - ('\u{40C}', &['\u{40C}', '\u{45C}']), - ('\u{40C}', &['\u{40C}', '\u{45C}']), - ('\u{40D}', &['\u{40D}', '\u{45D}']), - ('\u{40D}', &['\u{40D}', '\u{45D}']), - ('\u{40E}', &['\u{40E}', '\u{45E}']), - ('\u{40E}', &['\u{40E}', '\u{45E}']), - ('\u{40F}', &['\u{40F}', '\u{45F}']), - ('\u{40F}', &['\u{40F}', '\u{45F}']), - ('\u{410}', &['\u{410}', '\u{430}']), - ('\u{410}', &['\u{410}', '\u{430}']), - ('\u{411}', &['\u{411}', '\u{431}']), - ('\u{411}', &['\u{411}', '\u{431}']), - ('\u{412}', &['\u{412}', '\u{432}', '\u{1C80}']), - ('\u{412}', &['\u{412}', '\u{432}', '\u{1C80}']), - ('\u{412}', &['\u{412}', '\u{432}', '\u{1C80}']), - ('\u{413}', &['\u{413}', '\u{433}']), - ('\u{413}', &['\u{413}', '\u{433}']), - ('\u{414}', &['\u{414}', '\u{434}', '\u{1C81}']), - ('\u{414}', &['\u{414}', '\u{434}', '\u{1C81}']), - ('\u{414}', &['\u{414}', '\u{434}', '\u{1C81}']), - ('\u{415}', &['\u{415}', '\u{435}']), - ('\u{415}', &['\u{415}', '\u{435}']), - ('\u{416}', &['\u{416}', '\u{436}']), - ('\u{416}', &['\u{416}', '\u{436}']), - ('\u{417}', &['\u{417}', '\u{437}']), - ('\u{417}', &['\u{417}', '\u{437}']), - ('\u{418}', &['\u{418}', '\u{438}']), - ('\u{418}', &['\u{418}', '\u{438}']), - ('\u{419}', &['\u{419}', '\u{439}']), - ('\u{419}', &['\u{419}', '\u{439}']), - ('\u{41A}', &['\u{41A}', '\u{43A}']), - ('\u{41A}', &['\u{41A}', '\u{43A}']), - ('\u{41B}', &['\u{41B}', '\u{43B}']), - ('\u{41B}', &['\u{41B}', '\u{43B}']), - ('\u{41C}', &['\u{41C}', '\u{43C}']), - ('\u{41C}', &['\u{41C}', '\u{43C}']), - ('\u{41D}', &['\u{41D}', '\u{43D}']), - ('\u{41D}', &['\u{41D}', '\u{43D}']), - ('\u{41E}', &['\u{41E}', '\u{43E}', '\u{1C82}']), - ('\u{41E}', &['\u{41E}', '\u{43E}', '\u{1C82}']), - ('\u{41E}', &['\u{41E}', '\u{43E}', '\u{1C82}']), - ('\u{41F}', &['\u{41F}', '\u{43F}']), - ('\u{41F}', &['\u{41F}', '\u{43F}']), - ('\u{420}', &['\u{420}', '\u{440}']), - ('\u{420}', &['\u{420}', '\u{440}']), - ('\u{421}', &['\u{421}', '\u{441}', '\u{1C83}']), - ('\u{421}', &['\u{421}', '\u{441}', '\u{1C83}']), - ('\u{421}', &['\u{421}', '\u{441}', '\u{1C83}']), - ('\u{422}', &['\u{422}', '\u{442}', '\u{1C84}', '\u{1C85}']), - ('\u{422}', &['\u{422}', '\u{442}', '\u{1C84}', '\u{1C85}']), - ('\u{422}', &['\u{422}', '\u{442}', '\u{1C84}', '\u{1C85}']), - ('\u{422}', &['\u{422}', '\u{442}', '\u{1C84}', '\u{1C85}']), - ('\u{423}', &['\u{423}', '\u{443}']), - ('\u{423}', &['\u{423}', '\u{443}']), - ('\u{424}', &['\u{424}', '\u{444}']), - ('\u{424}', &['\u{424}', '\u{444}']), - ('\u{425}', &['\u{425}', '\u{445}']), - ('\u{425}', &['\u{425}', '\u{445}']), - ('\u{426}', &['\u{426}', '\u{446}']), - ('\u{426}', &['\u{426}', '\u{446}']), - ('\u{427}', &['\u{427}', '\u{447}']), - ('\u{427}', &['\u{427}', '\u{447}']), - ('\u{428}', &['\u{428}', '\u{448}']), - ('\u{428}', &['\u{428}', '\u{448}']), - ('\u{429}', &['\u{429}', '\u{449}']), - ('\u{429}', &['\u{429}', '\u{449}']), - ('\u{42A}', &['\u{42A}', '\u{44A}', '\u{1C86}']), - ('\u{42A}', &['\u{42A}', '\u{44A}', '\u{1C86}']), - ('\u{42A}', &['\u{42A}', '\u{44A}', '\u{1C86}']), - ('\u{42B}', &['\u{42B}', '\u{44B}']), - ('\u{42B}', &['\u{42B}', '\u{44B}']), - ('\u{42C}', &['\u{42C}', '\u{44C}']), - ('\u{42C}', &['\u{42C}', '\u{44C}']), - ('\u{42D}', &['\u{42D}', '\u{44D}']), - ('\u{42D}', &['\u{42D}', '\u{44D}']), - ('\u{42E}', &['\u{42E}', '\u{44E}']), - ('\u{42E}', &['\u{42E}', '\u{44E}']), - ('\u{42F}', &['\u{42F}', '\u{44F}']), - ('\u{42F}', &['\u{42F}', '\u{44F}']), - ('\u{460}', &['\u{460}', '\u{461}']), - ('\u{460}', &['\u{460}', '\u{461}']), - ('\u{462}', &['\u{462}', '\u{463}', '\u{1C87}']), - ('\u{462}', &['\u{462}', '\u{463}', '\u{1C87}']), - ('\u{462}', &['\u{462}', '\u{463}', '\u{1C87}']), - ('\u{464}', &['\u{464}', '\u{465}']), - ('\u{464}', &['\u{464}', '\u{465}']), - ('\u{466}', &['\u{466}', '\u{467}']), - ('\u{466}', &['\u{466}', '\u{467}']), - ('\u{468}', &['\u{468}', '\u{469}']), - ('\u{468}', &['\u{468}', '\u{469}']), - ('\u{46A}', &['\u{46A}', '\u{46B}']), - ('\u{46A}', &['\u{46A}', '\u{46B}']), - ('\u{46C}', &['\u{46C}', '\u{46D}']), - ('\u{46C}', &['\u{46C}', '\u{46D}']), - ('\u{46E}', &['\u{46E}', '\u{46F}']), - ('\u{46E}', &['\u{46E}', '\u{46F}']), - ('\u{470}', &['\u{470}', '\u{471}']), - ('\u{470}', &['\u{470}', '\u{471}']), - ('\u{472}', &['\u{472}', '\u{473}']), - ('\u{472}', &['\u{472}', '\u{473}']), - ('\u{474}', &['\u{474}', '\u{475}']), - ('\u{474}', &['\u{474}', '\u{475}']), - ('\u{476}', &['\u{476}', '\u{477}']), - ('\u{476}', &['\u{476}', '\u{477}']), - ('\u{478}', &['\u{478}', '\u{479}']), - ('\u{478}', &['\u{478}', '\u{479}']), - ('\u{47A}', &['\u{47A}', '\u{47B}']), - ('\u{47A}', &['\u{47A}', '\u{47B}']), - ('\u{47C}', &['\u{47C}', '\u{47D}']), - ('\u{47C}', &['\u{47C}', '\u{47D}']), - ('\u{47E}', &['\u{47E}', '\u{47F}']), - ('\u{47E}', &['\u{47E}', '\u{47F}']), - ('\u{480}', &['\u{480}', '\u{481}']), - ('\u{480}', &['\u{480}', '\u{481}']), - ('\u{48A}', &['\u{48A}', '\u{48B}']), - ('\u{48A}', &['\u{48A}', '\u{48B}']), - ('\u{48C}', &['\u{48C}', '\u{48D}']), - ('\u{48C}', &['\u{48C}', '\u{48D}']), - ('\u{48E}', &['\u{48E}', '\u{48F}']), - ('\u{48E}', &['\u{48E}', '\u{48F}']), - ('\u{490}', &['\u{490}', '\u{491}']), - ('\u{490}', &['\u{490}', '\u{491}']), - ('\u{492}', &['\u{492}', '\u{493}']), - ('\u{492}', &['\u{492}', '\u{493}']), - ('\u{494}', &['\u{494}', '\u{495}']), - ('\u{494}', &['\u{494}', '\u{495}']), - ('\u{496}', &['\u{496}', '\u{497}']), - ('\u{496}', &['\u{496}', '\u{497}']), - ('\u{498}', &['\u{498}', '\u{499}']), - ('\u{498}', &['\u{498}', '\u{499}']), - ('\u{49A}', &['\u{49A}', '\u{49B}']), - ('\u{49A}', &['\u{49A}', '\u{49B}']), - ('\u{49C}', &['\u{49C}', '\u{49D}']), - ('\u{49C}', &['\u{49C}', '\u{49D}']), - ('\u{49E}', &['\u{49E}', '\u{49F}']), - ('\u{49E}', &['\u{49E}', '\u{49F}']), - ('\u{4A0}', &['\u{4A0}', '\u{4A1}']), - ('\u{4A0}', &['\u{4A0}', '\u{4A1}']), - ('\u{4A2}', &['\u{4A2}', '\u{4A3}']), - ('\u{4A2}', &['\u{4A2}', '\u{4A3}']), - ('\u{4A4}', &['\u{4A4}', '\u{4A5}']), - ('\u{4A4}', &['\u{4A4}', '\u{4A5}']), - ('\u{4A6}', &['\u{4A6}', '\u{4A7}']), - ('\u{4A6}', &['\u{4A6}', '\u{4A7}']), - ('\u{4A8}', &['\u{4A8}', '\u{4A9}']), - ('\u{4A8}', &['\u{4A8}', '\u{4A9}']), - ('\u{4AA}', &['\u{4AA}', '\u{4AB}']), - ('\u{4AA}', &['\u{4AA}', '\u{4AB}']), - ('\u{4AC}', &['\u{4AC}', '\u{4AD}']), - ('\u{4AC}', &['\u{4AC}', '\u{4AD}']), - ('\u{4AE}', &['\u{4AE}', '\u{4AF}']), - ('\u{4AE}', &['\u{4AE}', '\u{4AF}']), - ('\u{4B0}', &['\u{4B0}', '\u{4B1}']), - ('\u{4B0}', &['\u{4B0}', '\u{4B1}']), - ('\u{4B2}', &['\u{4B2}', '\u{4B3}']), - ('\u{4B2}', &['\u{4B2}', '\u{4B3}']), - ('\u{4B4}', &['\u{4B4}', '\u{4B5}']), - ('\u{4B4}', &['\u{4B4}', '\u{4B5}']), - ('\u{4B6}', &['\u{4B6}', '\u{4B7}']), - ('\u{4B6}', &['\u{4B6}', '\u{4B7}']), - ('\u{4B8}', &['\u{4B8}', '\u{4B9}']), - ('\u{4B8}', &['\u{4B8}', '\u{4B9}']), - ('\u{4BA}', &['\u{4BA}', '\u{4BB}']), - ('\u{4BA}', &['\u{4BA}', '\u{4BB}']), - ('\u{4BC}', &['\u{4BC}', '\u{4BD}']), - ('\u{4BC}', &['\u{4BC}', '\u{4BD}']), - ('\u{4BE}', &['\u{4BE}', '\u{4BF}']), - ('\u{4BE}', &['\u{4BE}', '\u{4BF}']), - ('\u{4C0}', &['\u{4C0}', '\u{4CF}']), - ('\u{4C0}', &['\u{4C0}', '\u{4CF}']), - ('\u{4C1}', &['\u{4C1}', '\u{4C2}']), - ('\u{4C1}', &['\u{4C1}', '\u{4C2}']), - ('\u{4C3}', &['\u{4C3}', '\u{4C4}']), - ('\u{4C3}', &['\u{4C3}', '\u{4C4}']), - ('\u{4C5}', &['\u{4C5}', '\u{4C6}']), - ('\u{4C5}', &['\u{4C5}', '\u{4C6}']), - ('\u{4C7}', &['\u{4C7}', '\u{4C8}']), - ('\u{4C7}', &['\u{4C7}', '\u{4C8}']), - ('\u{4C9}', &['\u{4C9}', '\u{4CA}']), - ('\u{4C9}', &['\u{4C9}', '\u{4CA}']), - ('\u{4CB}', &['\u{4CB}', '\u{4CC}']), - ('\u{4CB}', &['\u{4CB}', '\u{4CC}']), - ('\u{4CD}', &['\u{4CD}', '\u{4CE}']), - ('\u{4CD}', &['\u{4CD}', '\u{4CE}']), - ('\u{4D0}', &['\u{4D0}', '\u{4D1}']), - ('\u{4D0}', &['\u{4D0}', '\u{4D1}']), - ('\u{4D2}', &['\u{4D2}', '\u{4D3}']), - ('\u{4D2}', &['\u{4D2}', '\u{4D3}']), - ('\u{4D4}', &['\u{4D4}', '\u{4D5}']), - ('\u{4D4}', &['\u{4D4}', '\u{4D5}']), - ('\u{4D6}', &['\u{4D6}', '\u{4D7}']), - ('\u{4D6}', &['\u{4D6}', '\u{4D7}']), - ('\u{4D8}', &['\u{4D8}', '\u{4D9}']), - ('\u{4D8}', &['\u{4D8}', '\u{4D9}']), - ('\u{4DA}', &['\u{4DA}', '\u{4DB}']), - ('\u{4DA}', &['\u{4DA}', '\u{4DB}']), - ('\u{4DC}', &['\u{4DC}', '\u{4DD}']), - ('\u{4DC}', &['\u{4DC}', '\u{4DD}']), - ('\u{4DE}', &['\u{4DE}', '\u{4DF}']), - ('\u{4DE}', &['\u{4DE}', '\u{4DF}']), - ('\u{4E0}', &['\u{4E0}', '\u{4E1}']), - ('\u{4E0}', &['\u{4E0}', '\u{4E1}']), - ('\u{4E2}', &['\u{4E2}', '\u{4E3}']), - ('\u{4E2}', &['\u{4E2}', '\u{4E3}']), - ('\u{4E4}', &['\u{4E4}', '\u{4E5}']), - ('\u{4E4}', &['\u{4E4}', '\u{4E5}']), - ('\u{4E6}', &['\u{4E6}', '\u{4E7}']), - ('\u{4E6}', &['\u{4E6}', '\u{4E7}']), - ('\u{4E8}', &['\u{4E8}', '\u{4E9}']), - ('\u{4E8}', &['\u{4E8}', '\u{4E9}']), - ('\u{4EA}', &['\u{4EA}', '\u{4EB}']), - ('\u{4EA}', &['\u{4EA}', '\u{4EB}']), - ('\u{4EC}', &['\u{4EC}', '\u{4ED}']), - ('\u{4EC}', &['\u{4EC}', '\u{4ED}']), - ('\u{4EE}', &['\u{4EE}', '\u{4EF}']), - ('\u{4EE}', &['\u{4EE}', '\u{4EF}']), - ('\u{4F0}', &['\u{4F0}', '\u{4F1}']), - ('\u{4F0}', &['\u{4F0}', '\u{4F1}']), - ('\u{4F2}', &['\u{4F2}', '\u{4F3}']), - ('\u{4F2}', &['\u{4F2}', '\u{4F3}']), - ('\u{4F4}', &['\u{4F4}', '\u{4F5}']), - ('\u{4F4}', &['\u{4F4}', '\u{4F5}']), - ('\u{4F6}', &['\u{4F6}', '\u{4F7}']), - ('\u{4F6}', &['\u{4F6}', '\u{4F7}']), - ('\u{4F8}', &['\u{4F8}', '\u{4F9}']), - ('\u{4F8}', &['\u{4F8}', '\u{4F9}']), - ('\u{4FA}', &['\u{4FA}', '\u{4FB}']), - ('\u{4FA}', &['\u{4FA}', '\u{4FB}']), - ('\u{4FC}', &['\u{4FC}', '\u{4FD}']), - ('\u{4FC}', &['\u{4FC}', '\u{4FD}']), - ('\u{4FE}', &['\u{4FE}', '\u{4FF}']), - ('\u{4FE}', &['\u{4FE}', '\u{4FF}']), - ('\u{500}', &['\u{500}', '\u{501}']), - ('\u{500}', &['\u{500}', '\u{501}']), - ('\u{502}', &['\u{502}', '\u{503}']), - ('\u{502}', &['\u{502}', '\u{503}']), - ('\u{504}', &['\u{504}', '\u{505}']), - ('\u{504}', &['\u{504}', '\u{505}']), - ('\u{506}', &['\u{506}', '\u{507}']), - ('\u{506}', &['\u{506}', '\u{507}']), - ('\u{508}', &['\u{508}', '\u{509}']), - ('\u{508}', &['\u{508}', '\u{509}']), - ('\u{50A}', &['\u{50A}', '\u{50B}']), - ('\u{50A}', &['\u{50A}', '\u{50B}']), - ('\u{50C}', &['\u{50C}', '\u{50D}']), - ('\u{50C}', &['\u{50C}', '\u{50D}']), - ('\u{50E}', &['\u{50E}', '\u{50F}']), - ('\u{50E}', &['\u{50E}', '\u{50F}']), - ('\u{510}', &['\u{510}', '\u{511}']), - ('\u{510}', &['\u{510}', '\u{511}']), - ('\u{512}', &['\u{512}', '\u{513}']), - ('\u{512}', &['\u{512}', '\u{513}']), - ('\u{514}', &['\u{514}', '\u{515}']), - ('\u{514}', &['\u{514}', '\u{515}']), - ('\u{516}', &['\u{516}', '\u{517}']), - ('\u{516}', &['\u{516}', '\u{517}']), - ('\u{518}', &['\u{518}', '\u{519}']), - ('\u{518}', &['\u{518}', '\u{519}']), - ('\u{51A}', &['\u{51A}', '\u{51B}']), - ('\u{51A}', &['\u{51A}', '\u{51B}']), - ('\u{51C}', &['\u{51C}', '\u{51D}']), - ('\u{51C}', &['\u{51C}', '\u{51D}']), - ('\u{51E}', &['\u{51E}', '\u{51F}']), - ('\u{51E}', &['\u{51E}', '\u{51F}']), - ('\u{520}', &['\u{520}', '\u{521}']), - ('\u{520}', &['\u{520}', '\u{521}']), - ('\u{522}', &['\u{522}', '\u{523}']), - ('\u{522}', &['\u{522}', '\u{523}']), - ('\u{524}', &['\u{524}', '\u{525}']), - ('\u{524}', &['\u{524}', '\u{525}']), - ('\u{526}', &['\u{526}', '\u{527}']), - ('\u{526}', &['\u{526}', '\u{527}']), - ('\u{528}', &['\u{528}', '\u{529}']), - ('\u{528}', &['\u{528}', '\u{529}']), - ('\u{52A}', &['\u{52A}', '\u{52B}']), - ('\u{52A}', &['\u{52A}', '\u{52B}']), - ('\u{52C}', &['\u{52C}', '\u{52D}']), - ('\u{52C}', &['\u{52C}', '\u{52D}']), - ('\u{52E}', &['\u{52E}', '\u{52F}']), - ('\u{52E}', &['\u{52E}', '\u{52F}']), - ('\u{531}', &['\u{531}', '\u{561}']), - ('\u{531}', &['\u{531}', '\u{561}']), - ('\u{532}', &['\u{532}', '\u{562}']), - ('\u{532}', &['\u{532}', '\u{562}']), - ('\u{533}', &['\u{533}', '\u{563}']), - ('\u{533}', &['\u{533}', '\u{563}']), - ('\u{534}', &['\u{534}', '\u{564}']), - ('\u{534}', &['\u{534}', '\u{564}']), - ('\u{535}', &['\u{535}', '\u{565}']), - ('\u{535}', &['\u{535}', '\u{565}']), - ('\u{536}', &['\u{536}', '\u{566}']), - ('\u{536}', &['\u{536}', '\u{566}']), - ('\u{537}', &['\u{537}', '\u{567}']), - ('\u{537}', &['\u{537}', '\u{567}']), - ('\u{538}', &['\u{538}', '\u{568}']), - ('\u{538}', &['\u{538}', '\u{568}']), - ('\u{539}', &['\u{539}', '\u{569}']), - ('\u{539}', &['\u{539}', '\u{569}']), - ('\u{53A}', &['\u{53A}', '\u{56A}']), - ('\u{53A}', &['\u{53A}', '\u{56A}']), - ('\u{53B}', &['\u{53B}', '\u{56B}']), - ('\u{53B}', &['\u{53B}', '\u{56B}']), - ('\u{53C}', &['\u{53C}', '\u{56C}']), - ('\u{53C}', &['\u{53C}', '\u{56C}']), - ('\u{53D}', &['\u{53D}', '\u{56D}']), - ('\u{53D}', &['\u{53D}', '\u{56D}']), - ('\u{53E}', &['\u{53E}', '\u{56E}']), - ('\u{53E}', &['\u{53E}', '\u{56E}']), - ('\u{53F}', &['\u{53F}', '\u{56F}']), - ('\u{53F}', &['\u{53F}', '\u{56F}']), - ('\u{540}', &['\u{540}', '\u{570}']), - ('\u{540}', &['\u{540}', '\u{570}']), - ('\u{541}', &['\u{541}', '\u{571}']), - ('\u{541}', &['\u{541}', '\u{571}']), - ('\u{542}', &['\u{542}', '\u{572}']), - ('\u{542}', &['\u{542}', '\u{572}']), - ('\u{543}', &['\u{543}', '\u{573}']), - ('\u{543}', &['\u{543}', '\u{573}']), - ('\u{544}', &['\u{544}', '\u{574}']), - ('\u{544}', &['\u{544}', '\u{574}']), - ('\u{545}', &['\u{545}', '\u{575}']), - ('\u{545}', &['\u{545}', '\u{575}']), - ('\u{546}', &['\u{546}', '\u{576}']), - ('\u{546}', &['\u{546}', '\u{576}']), - ('\u{547}', &['\u{547}', '\u{577}']), - ('\u{547}', &['\u{547}', '\u{577}']), - ('\u{548}', &['\u{548}', '\u{578}']), - ('\u{548}', &['\u{548}', '\u{578}']), - ('\u{549}', &['\u{549}', '\u{579}']), - ('\u{549}', &['\u{549}', '\u{579}']), - ('\u{54A}', &['\u{54A}', '\u{57A}']), - ('\u{54A}', &['\u{54A}', '\u{57A}']), - ('\u{54B}', &['\u{54B}', '\u{57B}']), - ('\u{54B}', &['\u{54B}', '\u{57B}']), - ('\u{54C}', &['\u{54C}', '\u{57C}']), - ('\u{54C}', &['\u{54C}', '\u{57C}']), - ('\u{54D}', &['\u{54D}', '\u{57D}']), - ('\u{54D}', &['\u{54D}', '\u{57D}']), - ('\u{54E}', &['\u{54E}', '\u{57E}']), - ('\u{54E}', &['\u{54E}', '\u{57E}']), - ('\u{54F}', &['\u{54F}', '\u{57F}']), - ('\u{54F}', &['\u{54F}', '\u{57F}']), - ('\u{550}', &['\u{550}', '\u{580}']), - ('\u{550}', &['\u{550}', '\u{580}']), - ('\u{551}', &['\u{551}', '\u{581}']), - ('\u{551}', &['\u{551}', '\u{581}']), - ('\u{552}', &['\u{552}', '\u{582}']), - ('\u{552}', &['\u{552}', '\u{582}']), - ('\u{553}', &['\u{553}', '\u{583}']), - ('\u{553}', &['\u{553}', '\u{583}']), - ('\u{554}', &['\u{554}', '\u{584}']), - ('\u{554}', &['\u{554}', '\u{584}']), - ('\u{555}', &['\u{555}', '\u{585}']), - ('\u{555}', &['\u{555}', '\u{585}']), - ('\u{556}', &['\u{556}', '\u{586}']), - ('\u{556}', &['\u{556}', '\u{586}']), - ('\u{10A0}', &['\u{10A0}', '\u{2D00}']), - ('\u{10A0}', &['\u{10A0}', '\u{2D00}']), - ('\u{10A1}', &['\u{10A1}', '\u{2D01}']), - ('\u{10A1}', &['\u{10A1}', '\u{2D01}']), - ('\u{10A2}', &['\u{10A2}', '\u{2D02}']), - ('\u{10A2}', &['\u{10A2}', '\u{2D02}']), - ('\u{10A3}', &['\u{10A3}', '\u{2D03}']), - ('\u{10A3}', &['\u{10A3}', '\u{2D03}']), - ('\u{10A4}', &['\u{10A4}', '\u{2D04}']), - ('\u{10A4}', &['\u{10A4}', '\u{2D04}']), - ('\u{10A5}', &['\u{10A5}', '\u{2D05}']), - ('\u{10A5}', &['\u{10A5}', '\u{2D05}']), - ('\u{10A6}', &['\u{10A6}', '\u{2D06}']), - ('\u{10A6}', &['\u{10A6}', '\u{2D06}']), - ('\u{10A7}', &['\u{10A7}', '\u{2D07}']), - ('\u{10A7}', &['\u{10A7}', '\u{2D07}']), - ('\u{10A8}', &['\u{10A8}', '\u{2D08}']), - ('\u{10A8}', &['\u{10A8}', '\u{2D08}']), - ('\u{10A9}', &['\u{10A9}', '\u{2D09}']), - ('\u{10A9}', &['\u{10A9}', '\u{2D09}']), - ('\u{10AA}', &['\u{10AA}', '\u{2D0A}']), - ('\u{10AA}', &['\u{10AA}', '\u{2D0A}']), - ('\u{10AB}', &['\u{10AB}', '\u{2D0B}']), - ('\u{10AB}', &['\u{10AB}', '\u{2D0B}']), - ('\u{10AC}', &['\u{10AC}', '\u{2D0C}']), - ('\u{10AC}', &['\u{10AC}', '\u{2D0C}']), - ('\u{10AD}', &['\u{10AD}', '\u{2D0D}']), - ('\u{10AD}', &['\u{10AD}', '\u{2D0D}']), - ('\u{10AE}', &['\u{10AE}', '\u{2D0E}']), - ('\u{10AE}', &['\u{10AE}', '\u{2D0E}']), - ('\u{10AF}', &['\u{10AF}', '\u{2D0F}']), - ('\u{10AF}', &['\u{10AF}', '\u{2D0F}']), - ('\u{10B0}', &['\u{10B0}', '\u{2D10}']), - ('\u{10B0}', &['\u{10B0}', '\u{2D10}']), - ('\u{10B1}', &['\u{10B1}', '\u{2D11}']), - ('\u{10B1}', &['\u{10B1}', '\u{2D11}']), - ('\u{10B2}', &['\u{10B2}', '\u{2D12}']), - ('\u{10B2}', &['\u{10B2}', '\u{2D12}']), - ('\u{10B3}', &['\u{10B3}', '\u{2D13}']), - ('\u{10B3}', &['\u{10B3}', '\u{2D13}']), - ('\u{10B4}', &['\u{10B4}', '\u{2D14}']), - ('\u{10B4}', &['\u{10B4}', '\u{2D14}']), - ('\u{10B5}', &['\u{10B5}', '\u{2D15}']), - ('\u{10B5}', &['\u{10B5}', '\u{2D15}']), - ('\u{10B6}', &['\u{10B6}', '\u{2D16}']), - ('\u{10B6}', &['\u{10B6}', '\u{2D16}']), - ('\u{10B7}', &['\u{10B7}', '\u{2D17}']), - ('\u{10B7}', &['\u{10B7}', '\u{2D17}']), - ('\u{10B8}', &['\u{10B8}', '\u{2D18}']), - ('\u{10B8}', &['\u{10B8}', '\u{2D18}']), - ('\u{10B9}', &['\u{10B9}', '\u{2D19}']), - ('\u{10B9}', &['\u{10B9}', '\u{2D19}']), - ('\u{10BA}', &['\u{10BA}', '\u{2D1A}']), - ('\u{10BA}', &['\u{10BA}', '\u{2D1A}']), - ('\u{10BB}', &['\u{10BB}', '\u{2D1B}']), - ('\u{10BB}', &['\u{10BB}', '\u{2D1B}']), - ('\u{10BC}', &['\u{10BC}', '\u{2D1C}']), - ('\u{10BC}', &['\u{10BC}', '\u{2D1C}']), - ('\u{10BD}', &['\u{10BD}', '\u{2D1D}']), - ('\u{10BD}', &['\u{10BD}', '\u{2D1D}']), - ('\u{10BE}', &['\u{10BE}', '\u{2D1E}']), - ('\u{10BE}', &['\u{10BE}', '\u{2D1E}']), - ('\u{10BF}', &['\u{10BF}', '\u{2D1F}']), - ('\u{10BF}', &['\u{10BF}', '\u{2D1F}']), - ('\u{10C0}', &['\u{10C0}', '\u{2D20}']), - ('\u{10C0}', &['\u{10C0}', '\u{2D20}']), - ('\u{10C1}', &['\u{10C1}', '\u{2D21}']), - ('\u{10C1}', &['\u{10C1}', '\u{2D21}']), - ('\u{10C2}', &['\u{10C2}', '\u{2D22}']), - ('\u{10C2}', &['\u{10C2}', '\u{2D22}']), - ('\u{10C3}', &['\u{10C3}', '\u{2D23}']), - ('\u{10C3}', &['\u{10C3}', '\u{2D23}']), - ('\u{10C4}', &['\u{10C4}', '\u{2D24}']), - ('\u{10C4}', &['\u{10C4}', '\u{2D24}']), - ('\u{10C5}', &['\u{10C5}', '\u{2D25}']), - ('\u{10C5}', &['\u{10C5}', '\u{2D25}']), - ('\u{10C7}', &['\u{10C7}', '\u{2D27}']), - ('\u{10C7}', &['\u{10C7}', '\u{2D27}']), - ('\u{10CD}', &['\u{10CD}', '\u{2D2D}']), - ('\u{10CD}', &['\u{10CD}', '\u{2D2D}']), - ('\u{10D0}', &['\u{10D0}', '\u{1C90}']), - ('\u{10D0}', &['\u{10D0}', '\u{1C90}']), - ('\u{10D1}', &['\u{10D1}', '\u{1C91}']), - ('\u{10D1}', &['\u{10D1}', '\u{1C91}']), - ('\u{10D2}', &['\u{10D2}', '\u{1C92}']), - ('\u{10D2}', &['\u{10D2}', '\u{1C92}']), - ('\u{10D3}', &['\u{10D3}', '\u{1C93}']), - ('\u{10D3}', &['\u{10D3}', '\u{1C93}']), - ('\u{10D4}', &['\u{10D4}', '\u{1C94}']), - ('\u{10D4}', &['\u{10D4}', '\u{1C94}']), - ('\u{10D5}', &['\u{10D5}', '\u{1C95}']), - ('\u{10D5}', &['\u{10D5}', '\u{1C95}']), - ('\u{10D6}', &['\u{10D6}', '\u{1C96}']), - ('\u{10D6}', &['\u{10D6}', '\u{1C96}']), - ('\u{10D7}', &['\u{10D7}', '\u{1C97}']), - ('\u{10D7}', &['\u{10D7}', '\u{1C97}']), - ('\u{10D8}', &['\u{10D8}', '\u{1C98}']), - ('\u{10D8}', &['\u{10D8}', '\u{1C98}']), - ('\u{10D9}', &['\u{10D9}', '\u{1C99}']), - ('\u{10D9}', &['\u{10D9}', '\u{1C99}']), - ('\u{10DA}', &['\u{10DA}', '\u{1C9A}']), - ('\u{10DA}', &['\u{10DA}', '\u{1C9A}']), - ('\u{10DB}', &['\u{10DB}', '\u{1C9B}']), - ('\u{10DB}', &['\u{10DB}', '\u{1C9B}']), - ('\u{10DC}', &['\u{10DC}', '\u{1C9C}']), - ('\u{10DC}', &['\u{10DC}', '\u{1C9C}']), - ('\u{10DD}', &['\u{10DD}', '\u{1C9D}']), - ('\u{10DD}', &['\u{10DD}', '\u{1C9D}']), - ('\u{10DE}', &['\u{10DE}', '\u{1C9E}']), - ('\u{10DE}', &['\u{10DE}', '\u{1C9E}']), - ('\u{10DF}', &['\u{10DF}', '\u{1C9F}']), - ('\u{10DF}', &['\u{10DF}', '\u{1C9F}']), - ('\u{10E0}', &['\u{10E0}', '\u{1CA0}']), - ('\u{10E0}', &['\u{10E0}', '\u{1CA0}']), - ('\u{10E1}', &['\u{10E1}', '\u{1CA1}']), - ('\u{10E1}', &['\u{10E1}', '\u{1CA1}']), - ('\u{10E2}', &['\u{10E2}', '\u{1CA2}']), - ('\u{10E2}', &['\u{10E2}', '\u{1CA2}']), - ('\u{10E3}', &['\u{10E3}', '\u{1CA3}']), - ('\u{10E3}', &['\u{10E3}', '\u{1CA3}']), - ('\u{10E4}', &['\u{10E4}', '\u{1CA4}']), - ('\u{10E4}', &['\u{10E4}', '\u{1CA4}']), - ('\u{10E5}', &['\u{10E5}', '\u{1CA5}']), - ('\u{10E5}', &['\u{10E5}', '\u{1CA5}']), - ('\u{10E6}', &['\u{10E6}', '\u{1CA6}']), - ('\u{10E6}', &['\u{10E6}', '\u{1CA6}']), - ('\u{10E7}', &['\u{10E7}', '\u{1CA7}']), - ('\u{10E7}', &['\u{10E7}', '\u{1CA7}']), - ('\u{10E8}', &['\u{10E8}', '\u{1CA8}']), - ('\u{10E8}', &['\u{10E8}', '\u{1CA8}']), - ('\u{10E9}', &['\u{10E9}', '\u{1CA9}']), - ('\u{10E9}', &['\u{10E9}', '\u{1CA9}']), - ('\u{10EA}', &['\u{10EA}', '\u{1CAA}']), - ('\u{10EA}', &['\u{10EA}', '\u{1CAA}']), - ('\u{10EB}', &['\u{10EB}', '\u{1CAB}']), - ('\u{10EB}', &['\u{10EB}', '\u{1CAB}']), - ('\u{10EC}', &['\u{10EC}', '\u{1CAC}']), - ('\u{10EC}', &['\u{10EC}', '\u{1CAC}']), - ('\u{10ED}', &['\u{10ED}', '\u{1CAD}']), - ('\u{10ED}', &['\u{10ED}', '\u{1CAD}']), - ('\u{10EE}', &['\u{10EE}', '\u{1CAE}']), - ('\u{10EE}', &['\u{10EE}', '\u{1CAE}']), - ('\u{10EF}', &['\u{10EF}', '\u{1CAF}']), - ('\u{10EF}', &['\u{10EF}', '\u{1CAF}']), - ('\u{10F0}', &['\u{10F0}', '\u{1CB0}']), - ('\u{10F0}', &['\u{10F0}', '\u{1CB0}']), - ('\u{10F1}', &['\u{10F1}', '\u{1CB1}']), - ('\u{10F1}', &['\u{10F1}', '\u{1CB1}']), - ('\u{10F2}', &['\u{10F2}', '\u{1CB2}']), - ('\u{10F2}', &['\u{10F2}', '\u{1CB2}']), - ('\u{10F3}', &['\u{10F3}', '\u{1CB3}']), - ('\u{10F3}', &['\u{10F3}', '\u{1CB3}']), - ('\u{10F4}', &['\u{10F4}', '\u{1CB4}']), - ('\u{10F4}', &['\u{10F4}', '\u{1CB4}']), - ('\u{10F5}', &['\u{10F5}', '\u{1CB5}']), - ('\u{10F5}', &['\u{10F5}', '\u{1CB5}']), - ('\u{10F6}', &['\u{10F6}', '\u{1CB6}']), - ('\u{10F6}', &['\u{10F6}', '\u{1CB6}']), - ('\u{10F7}', &['\u{10F7}', '\u{1CB7}']), - ('\u{10F7}', &['\u{10F7}', '\u{1CB7}']), - ('\u{10F8}', &['\u{10F8}', '\u{1CB8}']), - ('\u{10F8}', &['\u{10F8}', '\u{1CB8}']), - ('\u{10F9}', &['\u{10F9}', '\u{1CB9}']), - ('\u{10F9}', &['\u{10F9}', '\u{1CB9}']), - ('\u{10FA}', &['\u{10FA}', '\u{1CBA}']), - ('\u{10FA}', &['\u{10FA}', '\u{1CBA}']), - ('\u{10FD}', &['\u{10FD}', '\u{1CBD}']), - ('\u{10FD}', &['\u{10FD}', '\u{1CBD}']), - ('\u{10FE}', &['\u{10FE}', '\u{1CBE}']), - ('\u{10FE}', &['\u{10FE}', '\u{1CBE}']), - ('\u{10FF}', &['\u{10FF}', '\u{1CBF}']), - ('\u{10FF}', &['\u{10FF}', '\u{1CBF}']), - ('\u{13A0}', &['\u{13A0}', '\u{AB70}']), - ('\u{13A0}', &['\u{13A0}', '\u{AB70}']), - ('\u{13A1}', &['\u{13A1}', '\u{AB71}']), - ('\u{13A1}', &['\u{13A1}', '\u{AB71}']), - ('\u{13A2}', &['\u{13A2}', '\u{AB72}']), - ('\u{13A2}', &['\u{13A2}', '\u{AB72}']), - ('\u{13A3}', &['\u{13A3}', '\u{AB73}']), - ('\u{13A3}', &['\u{13A3}', '\u{AB73}']), - ('\u{13A4}', &['\u{13A4}', '\u{AB74}']), - ('\u{13A4}', &['\u{13A4}', '\u{AB74}']), - ('\u{13A5}', &['\u{13A5}', '\u{AB75}']), - ('\u{13A5}', &['\u{13A5}', '\u{AB75}']), - ('\u{13A6}', &['\u{13A6}', '\u{AB76}']), - ('\u{13A6}', &['\u{13A6}', '\u{AB76}']), - ('\u{13A7}', &['\u{13A7}', '\u{AB77}']), - ('\u{13A7}', &['\u{13A7}', '\u{AB77}']), - ('\u{13A8}', &['\u{13A8}', '\u{AB78}']), - ('\u{13A8}', &['\u{13A8}', '\u{AB78}']), - ('\u{13A9}', &['\u{13A9}', '\u{AB79}']), - ('\u{13A9}', &['\u{13A9}', '\u{AB79}']), - ('\u{13AA}', &['\u{13AA}', '\u{AB7A}']), - ('\u{13AA}', &['\u{13AA}', '\u{AB7A}']), - ('\u{13AB}', &['\u{13AB}', '\u{AB7B}']), - ('\u{13AB}', &['\u{13AB}', '\u{AB7B}']), - ('\u{13AC}', &['\u{13AC}', '\u{AB7C}']), - ('\u{13AC}', &['\u{13AC}', '\u{AB7C}']), - ('\u{13AD}', &['\u{13AD}', '\u{AB7D}']), - ('\u{13AD}', &['\u{13AD}', '\u{AB7D}']), - ('\u{13AE}', &['\u{13AE}', '\u{AB7E}']), - ('\u{13AE}', &['\u{13AE}', '\u{AB7E}']), - ('\u{13AF}', &['\u{13AF}', '\u{AB7F}']), - ('\u{13AF}', &['\u{13AF}', '\u{AB7F}']), - ('\u{13B0}', &['\u{13B0}', '\u{AB80}']), - ('\u{13B0}', &['\u{13B0}', '\u{AB80}']), - ('\u{13B1}', &['\u{13B1}', '\u{AB81}']), - ('\u{13B1}', &['\u{13B1}', '\u{AB81}']), - ('\u{13B2}', &['\u{13B2}', '\u{AB82}']), - ('\u{13B2}', &['\u{13B2}', '\u{AB82}']), - ('\u{13B3}', &['\u{13B3}', '\u{AB83}']), - ('\u{13B3}', &['\u{13B3}', '\u{AB83}']), - ('\u{13B4}', &['\u{13B4}', '\u{AB84}']), - ('\u{13B4}', &['\u{13B4}', '\u{AB84}']), - ('\u{13B5}', &['\u{13B5}', '\u{AB85}']), - ('\u{13B5}', &['\u{13B5}', '\u{AB85}']), - ('\u{13B6}', &['\u{13B6}', '\u{AB86}']), - ('\u{13B6}', &['\u{13B6}', '\u{AB86}']), - ('\u{13B7}', &['\u{13B7}', '\u{AB87}']), - ('\u{13B7}', &['\u{13B7}', '\u{AB87}']), - ('\u{13B8}', &['\u{13B8}', '\u{AB88}']), - ('\u{13B8}', &['\u{13B8}', '\u{AB88}']), - ('\u{13B9}', &['\u{13B9}', '\u{AB89}']), - ('\u{13B9}', &['\u{13B9}', '\u{AB89}']), - ('\u{13BA}', &['\u{13BA}', '\u{AB8A}']), - ('\u{13BA}', &['\u{13BA}', '\u{AB8A}']), - ('\u{13BB}', &['\u{13BB}', '\u{AB8B}']), - ('\u{13BB}', &['\u{13BB}', '\u{AB8B}']), - ('\u{13BC}', &['\u{13BC}', '\u{AB8C}']), - ('\u{13BC}', &['\u{13BC}', '\u{AB8C}']), - ('\u{13BD}', &['\u{13BD}', '\u{AB8D}']), - ('\u{13BD}', &['\u{13BD}', '\u{AB8D}']), - ('\u{13BE}', &['\u{13BE}', '\u{AB8E}']), - ('\u{13BE}', &['\u{13BE}', '\u{AB8E}']), - ('\u{13BF}', &['\u{13BF}', '\u{AB8F}']), - ('\u{13BF}', &['\u{13BF}', '\u{AB8F}']), - ('\u{13C0}', &['\u{13C0}', '\u{AB90}']), - ('\u{13C0}', &['\u{13C0}', '\u{AB90}']), - ('\u{13C1}', &['\u{13C1}', '\u{AB91}']), - ('\u{13C1}', &['\u{13C1}', '\u{AB91}']), - ('\u{13C2}', &['\u{13C2}', '\u{AB92}']), - ('\u{13C2}', &['\u{13C2}', '\u{AB92}']), - ('\u{13C3}', &['\u{13C3}', '\u{AB93}']), - ('\u{13C3}', &['\u{13C3}', '\u{AB93}']), - ('\u{13C4}', &['\u{13C4}', '\u{AB94}']), - ('\u{13C4}', &['\u{13C4}', '\u{AB94}']), - ('\u{13C5}', &['\u{13C5}', '\u{AB95}']), - ('\u{13C5}', &['\u{13C5}', '\u{AB95}']), - ('\u{13C6}', &['\u{13C6}', '\u{AB96}']), - ('\u{13C6}', &['\u{13C6}', '\u{AB96}']), - ('\u{13C7}', &['\u{13C7}', '\u{AB97}']), - ('\u{13C7}', &['\u{13C7}', '\u{AB97}']), - ('\u{13C8}', &['\u{13C8}', '\u{AB98}']), - ('\u{13C8}', &['\u{13C8}', '\u{AB98}']), - ('\u{13C9}', &['\u{13C9}', '\u{AB99}']), - ('\u{13C9}', &['\u{13C9}', '\u{AB99}']), - ('\u{13CA}', &['\u{13CA}', '\u{AB9A}']), - ('\u{13CA}', &['\u{13CA}', '\u{AB9A}']), - ('\u{13CB}', &['\u{13CB}', '\u{AB9B}']), - ('\u{13CB}', &['\u{13CB}', '\u{AB9B}']), - ('\u{13CC}', &['\u{13CC}', '\u{AB9C}']), - ('\u{13CC}', &['\u{13CC}', '\u{AB9C}']), - ('\u{13CD}', &['\u{13CD}', '\u{AB9D}']), - ('\u{13CD}', &['\u{13CD}', '\u{AB9D}']), - ('\u{13CE}', &['\u{13CE}', '\u{AB9E}']), - ('\u{13CE}', &['\u{13CE}', '\u{AB9E}']), - ('\u{13CF}', &['\u{13CF}', '\u{AB9F}']), - ('\u{13CF}', &['\u{13CF}', '\u{AB9F}']), - ('\u{13D0}', &['\u{13D0}', '\u{ABA0}']), - ('\u{13D0}', &['\u{13D0}', '\u{ABA0}']), - ('\u{13D1}', &['\u{13D1}', '\u{ABA1}']), - ('\u{13D1}', &['\u{13D1}', '\u{ABA1}']), - ('\u{13D2}', &['\u{13D2}', '\u{ABA2}']), - ('\u{13D2}', &['\u{13D2}', '\u{ABA2}']), - ('\u{13D3}', &['\u{13D3}', '\u{ABA3}']), - ('\u{13D3}', &['\u{13D3}', '\u{ABA3}']), - ('\u{13D4}', &['\u{13D4}', '\u{ABA4}']), - ('\u{13D4}', &['\u{13D4}', '\u{ABA4}']), - ('\u{13D5}', &['\u{13D5}', '\u{ABA5}']), - ('\u{13D5}', &['\u{13D5}', '\u{ABA5}']), - ('\u{13D6}', &['\u{13D6}', '\u{ABA6}']), - ('\u{13D6}', &['\u{13D6}', '\u{ABA6}']), - ('\u{13D7}', &['\u{13D7}', '\u{ABA7}']), - ('\u{13D7}', &['\u{13D7}', '\u{ABA7}']), - ('\u{13D8}', &['\u{13D8}', '\u{ABA8}']), - ('\u{13D8}', &['\u{13D8}', '\u{ABA8}']), - ('\u{13D9}', &['\u{13D9}', '\u{ABA9}']), - ('\u{13D9}', &['\u{13D9}', '\u{ABA9}']), - ('\u{13DA}', &['\u{13DA}', '\u{ABAA}']), - ('\u{13DA}', &['\u{13DA}', '\u{ABAA}']), - ('\u{13DB}', &['\u{13DB}', '\u{ABAB}']), - ('\u{13DB}', &['\u{13DB}', '\u{ABAB}']), - ('\u{13DC}', &['\u{13DC}', '\u{ABAC}']), - ('\u{13DC}', &['\u{13DC}', '\u{ABAC}']), - ('\u{13DD}', &['\u{13DD}', '\u{ABAD}']), - ('\u{13DD}', &['\u{13DD}', '\u{ABAD}']), - ('\u{13DE}', &['\u{13DE}', '\u{ABAE}']), - ('\u{13DE}', &['\u{13DE}', '\u{ABAE}']), - ('\u{13DF}', &['\u{13DF}', '\u{ABAF}']), - ('\u{13DF}', &['\u{13DF}', '\u{ABAF}']), - ('\u{13E0}', &['\u{13E0}', '\u{ABB0}']), - ('\u{13E0}', &['\u{13E0}', '\u{ABB0}']), - ('\u{13E1}', &['\u{13E1}', '\u{ABB1}']), - ('\u{13E1}', &['\u{13E1}', '\u{ABB1}']), - ('\u{13E2}', &['\u{13E2}', '\u{ABB2}']), - ('\u{13E2}', &['\u{13E2}', '\u{ABB2}']), - ('\u{13E3}', &['\u{13E3}', '\u{ABB3}']), - ('\u{13E3}', &['\u{13E3}', '\u{ABB3}']), - ('\u{13E4}', &['\u{13E4}', '\u{ABB4}']), - ('\u{13E4}', &['\u{13E4}', '\u{ABB4}']), - ('\u{13E5}', &['\u{13E5}', '\u{ABB5}']), - ('\u{13E5}', &['\u{13E5}', '\u{ABB5}']), - ('\u{13E6}', &['\u{13E6}', '\u{ABB6}']), - ('\u{13E6}', &['\u{13E6}', '\u{ABB6}']), - ('\u{13E7}', &['\u{13E7}', '\u{ABB7}']), - ('\u{13E7}', &['\u{13E7}', '\u{ABB7}']), - ('\u{13E8}', &['\u{13E8}', '\u{ABB8}']), - ('\u{13E8}', &['\u{13E8}', '\u{ABB8}']), - ('\u{13E9}', &['\u{13E9}', '\u{ABB9}']), - ('\u{13E9}', &['\u{13E9}', '\u{ABB9}']), - ('\u{13EA}', &['\u{13EA}', '\u{ABBA}']), - ('\u{13EA}', &['\u{13EA}', '\u{ABBA}']), - ('\u{13EB}', &['\u{13EB}', '\u{ABBB}']), - ('\u{13EB}', &['\u{13EB}', '\u{ABBB}']), - ('\u{13EC}', &['\u{13EC}', '\u{ABBC}']), - ('\u{13EC}', &['\u{13EC}', '\u{ABBC}']), - ('\u{13ED}', &['\u{13ED}', '\u{ABBD}']), - ('\u{13ED}', &['\u{13ED}', '\u{ABBD}']), - ('\u{13EE}', &['\u{13EE}', '\u{ABBE}']), - ('\u{13EE}', &['\u{13EE}', '\u{ABBE}']), - ('\u{13EF}', &['\u{13EF}', '\u{ABBF}']), - ('\u{13EF}', &['\u{13EF}', '\u{ABBF}']), - ('\u{13F0}', &['\u{13F0}', '\u{13F8}']), - ('\u{13F0}', &['\u{13F0}', '\u{13F8}']), - ('\u{13F1}', &['\u{13F1}', '\u{13F9}']), - ('\u{13F1}', &['\u{13F1}', '\u{13F9}']), - ('\u{13F2}', &['\u{13F2}', '\u{13FA}']), - ('\u{13F2}', &['\u{13F2}', '\u{13FA}']), - ('\u{13F3}', &['\u{13F3}', '\u{13FB}']), - ('\u{13F3}', &['\u{13F3}', '\u{13FB}']), - ('\u{13F4}', &['\u{13F4}', '\u{13FC}']), - ('\u{13F4}', &['\u{13F4}', '\u{13FC}']), - ('\u{13F5}', &['\u{13F5}', '\u{13FD}']), - ('\u{13F5}', &['\u{13F5}', '\u{13FD}']), - ('\u{1C88}', &['\u{1C88}', '\u{A64A}', '\u{A64B}']), - ('\u{1C88}', &['\u{1C88}', '\u{A64A}', '\u{A64B}']), - ('\u{1C88}', &['\u{1C88}', '\u{A64A}', '\u{A64B}']), - ('\u{1D79}', &['\u{1D79}', '\u{A77D}']), - ('\u{1D79}', &['\u{1D79}', '\u{A77D}']), - ('\u{1D7D}', &['\u{1D7D}', '\u{2C63}']), - ('\u{1D7D}', &['\u{1D7D}', '\u{2C63}']), - ('\u{1D8E}', &['\u{1D8E}', '\u{A7C6}']), - ('\u{1D8E}', &['\u{1D8E}', '\u{A7C6}']), - ('\u{1E00}', &['\u{1E00}', '\u{1E01}']), - ('\u{1E00}', &['\u{1E00}', '\u{1E01}']), - ('\u{1E02}', &['\u{1E02}', '\u{1E03}']), - ('\u{1E02}', &['\u{1E02}', '\u{1E03}']), - ('\u{1E04}', &['\u{1E04}', '\u{1E05}']), - ('\u{1E04}', &['\u{1E04}', '\u{1E05}']), - ('\u{1E06}', &['\u{1E06}', '\u{1E07}']), - ('\u{1E06}', &['\u{1E06}', '\u{1E07}']), - ('\u{1E08}', &['\u{1E08}', '\u{1E09}']), - ('\u{1E08}', &['\u{1E08}', '\u{1E09}']), - ('\u{1E0A}', &['\u{1E0A}', '\u{1E0B}']), - ('\u{1E0A}', &['\u{1E0A}', '\u{1E0B}']), - ('\u{1E0C}', &['\u{1E0C}', '\u{1E0D}']), - ('\u{1E0C}', &['\u{1E0C}', '\u{1E0D}']), - ('\u{1E0E}', &['\u{1E0E}', '\u{1E0F}']), - ('\u{1E0E}', &['\u{1E0E}', '\u{1E0F}']), - ('\u{1E10}', &['\u{1E10}', '\u{1E11}']), - ('\u{1E10}', &['\u{1E10}', '\u{1E11}']), - ('\u{1E12}', &['\u{1E12}', '\u{1E13}']), - ('\u{1E12}', &['\u{1E12}', '\u{1E13}']), - ('\u{1E14}', &['\u{1E14}', '\u{1E15}']), - ('\u{1E14}', &['\u{1E14}', '\u{1E15}']), - ('\u{1E16}', &['\u{1E16}', '\u{1E17}']), - ('\u{1E16}', &['\u{1E16}', '\u{1E17}']), - ('\u{1E18}', &['\u{1E18}', '\u{1E19}']), - ('\u{1E18}', &['\u{1E18}', '\u{1E19}']), - ('\u{1E1A}', &['\u{1E1A}', '\u{1E1B}']), - ('\u{1E1A}', &['\u{1E1A}', '\u{1E1B}']), - ('\u{1E1C}', &['\u{1E1C}', '\u{1E1D}']), - ('\u{1E1C}', &['\u{1E1C}', '\u{1E1D}']), - ('\u{1E1E}', &['\u{1E1E}', '\u{1E1F}']), - ('\u{1E1E}', &['\u{1E1E}', '\u{1E1F}']), - ('\u{1E20}', &['\u{1E20}', '\u{1E21}']), - ('\u{1E20}', &['\u{1E20}', '\u{1E21}']), - ('\u{1E22}', &['\u{1E22}', '\u{1E23}']), - ('\u{1E22}', &['\u{1E22}', '\u{1E23}']), - ('\u{1E24}', &['\u{1E24}', '\u{1E25}']), - ('\u{1E24}', &['\u{1E24}', '\u{1E25}']), - ('\u{1E26}', &['\u{1E26}', '\u{1E27}']), - ('\u{1E26}', &['\u{1E26}', '\u{1E27}']), - ('\u{1E28}', &['\u{1E28}', '\u{1E29}']), - ('\u{1E28}', &['\u{1E28}', '\u{1E29}']), - ('\u{1E2A}', &['\u{1E2A}', '\u{1E2B}']), - ('\u{1E2A}', &['\u{1E2A}', '\u{1E2B}']), - ('\u{1E2C}', &['\u{1E2C}', '\u{1E2D}']), - ('\u{1E2C}', &['\u{1E2C}', '\u{1E2D}']), - ('\u{1E2E}', &['\u{1E2E}', '\u{1E2F}']), - ('\u{1E2E}', &['\u{1E2E}', '\u{1E2F}']), - ('\u{1E30}', &['\u{1E30}', '\u{1E31}']), - ('\u{1E30}', &['\u{1E30}', '\u{1E31}']), - ('\u{1E32}', &['\u{1E32}', '\u{1E33}']), - ('\u{1E32}', &['\u{1E32}', '\u{1E33}']), - ('\u{1E34}', &['\u{1E34}', '\u{1E35}']), - ('\u{1E34}', &['\u{1E34}', '\u{1E35}']), - ('\u{1E36}', &['\u{1E36}', '\u{1E37}']), - ('\u{1E36}', &['\u{1E36}', '\u{1E37}']), - ('\u{1E38}', &['\u{1E38}', '\u{1E39}']), - ('\u{1E38}', &['\u{1E38}', '\u{1E39}']), - ('\u{1E3A}', &['\u{1E3A}', '\u{1E3B}']), - ('\u{1E3A}', &['\u{1E3A}', '\u{1E3B}']), - ('\u{1E3C}', &['\u{1E3C}', '\u{1E3D}']), - ('\u{1E3C}', &['\u{1E3C}', '\u{1E3D}']), - ('\u{1E3E}', &['\u{1E3E}', '\u{1E3F}']), - ('\u{1E3E}', &['\u{1E3E}', '\u{1E3F}']), - ('\u{1E40}', &['\u{1E40}', '\u{1E41}']), - ('\u{1E40}', &['\u{1E40}', '\u{1E41}']), - ('\u{1E42}', &['\u{1E42}', '\u{1E43}']), - ('\u{1E42}', &['\u{1E42}', '\u{1E43}']), - ('\u{1E44}', &['\u{1E44}', '\u{1E45}']), - ('\u{1E44}', &['\u{1E44}', '\u{1E45}']), - ('\u{1E46}', &['\u{1E46}', '\u{1E47}']), - ('\u{1E46}', &['\u{1E46}', '\u{1E47}']), - ('\u{1E48}', &['\u{1E48}', '\u{1E49}']), - ('\u{1E48}', &['\u{1E48}', '\u{1E49}']), - ('\u{1E4A}', &['\u{1E4A}', '\u{1E4B}']), - ('\u{1E4A}', &['\u{1E4A}', '\u{1E4B}']), - ('\u{1E4C}', &['\u{1E4C}', '\u{1E4D}']), - ('\u{1E4C}', &['\u{1E4C}', '\u{1E4D}']), - ('\u{1E4E}', &['\u{1E4E}', '\u{1E4F}']), - ('\u{1E4E}', &['\u{1E4E}', '\u{1E4F}']), - ('\u{1E50}', &['\u{1E50}', '\u{1E51}']), - ('\u{1E50}', &['\u{1E50}', '\u{1E51}']), - ('\u{1E52}', &['\u{1E52}', '\u{1E53}']), - ('\u{1E52}', &['\u{1E52}', '\u{1E53}']), - ('\u{1E54}', &['\u{1E54}', '\u{1E55}']), - ('\u{1E54}', &['\u{1E54}', '\u{1E55}']), - ('\u{1E56}', &['\u{1E56}', '\u{1E57}']), - ('\u{1E56}', &['\u{1E56}', '\u{1E57}']), - ('\u{1E58}', &['\u{1E58}', '\u{1E59}']), - ('\u{1E58}', &['\u{1E58}', '\u{1E59}']), - ('\u{1E5A}', &['\u{1E5A}', '\u{1E5B}']), - ('\u{1E5A}', &['\u{1E5A}', '\u{1E5B}']), - ('\u{1E5C}', &['\u{1E5C}', '\u{1E5D}']), - ('\u{1E5C}', &['\u{1E5C}', '\u{1E5D}']), - ('\u{1E5E}', &['\u{1E5E}', '\u{1E5F}']), - ('\u{1E5E}', &['\u{1E5E}', '\u{1E5F}']), - ('\u{1E60}', &['\u{1E60}', '\u{1E61}', '\u{1E9B}']), - ('\u{1E60}', &['\u{1E60}', '\u{1E61}', '\u{1E9B}']), - ('\u{1E60}', &['\u{1E60}', '\u{1E61}', '\u{1E9B}']), - ('\u{1E62}', &['\u{1E62}', '\u{1E63}']), - ('\u{1E62}', &['\u{1E62}', '\u{1E63}']), - ('\u{1E64}', &['\u{1E64}', '\u{1E65}']), - ('\u{1E64}', &['\u{1E64}', '\u{1E65}']), - ('\u{1E66}', &['\u{1E66}', '\u{1E67}']), - ('\u{1E66}', &['\u{1E66}', '\u{1E67}']), - ('\u{1E68}', &['\u{1E68}', '\u{1E69}']), - ('\u{1E68}', &['\u{1E68}', '\u{1E69}']), - ('\u{1E6A}', &['\u{1E6A}', '\u{1E6B}']), - ('\u{1E6A}', &['\u{1E6A}', '\u{1E6B}']), - ('\u{1E6C}', &['\u{1E6C}', '\u{1E6D}']), - ('\u{1E6C}', &['\u{1E6C}', '\u{1E6D}']), - ('\u{1E6E}', &['\u{1E6E}', '\u{1E6F}']), - ('\u{1E6E}', &['\u{1E6E}', '\u{1E6F}']), - ('\u{1E70}', &['\u{1E70}', '\u{1E71}']), - ('\u{1E70}', &['\u{1E70}', '\u{1E71}']), - ('\u{1E72}', &['\u{1E72}', '\u{1E73}']), - ('\u{1E72}', &['\u{1E72}', '\u{1E73}']), - ('\u{1E74}', &['\u{1E74}', '\u{1E75}']), - ('\u{1E74}', &['\u{1E74}', '\u{1E75}']), - ('\u{1E76}', &['\u{1E76}', '\u{1E77}']), - ('\u{1E76}', &['\u{1E76}', '\u{1E77}']), - ('\u{1E78}', &['\u{1E78}', '\u{1E79}']), - ('\u{1E78}', &['\u{1E78}', '\u{1E79}']), - ('\u{1E7A}', &['\u{1E7A}', '\u{1E7B}']), - ('\u{1E7A}', &['\u{1E7A}', '\u{1E7B}']), - ('\u{1E7C}', &['\u{1E7C}', '\u{1E7D}']), - ('\u{1E7C}', &['\u{1E7C}', '\u{1E7D}']), - ('\u{1E7E}', &['\u{1E7E}', '\u{1E7F}']), - ('\u{1E7E}', &['\u{1E7E}', '\u{1E7F}']), - ('\u{1E80}', &['\u{1E80}', '\u{1E81}']), - ('\u{1E80}', &['\u{1E80}', '\u{1E81}']), - ('\u{1E82}', &['\u{1E82}', '\u{1E83}']), - ('\u{1E82}', &['\u{1E82}', '\u{1E83}']), - ('\u{1E84}', &['\u{1E84}', '\u{1E85}']), - ('\u{1E84}', &['\u{1E84}', '\u{1E85}']), - ('\u{1E86}', &['\u{1E86}', '\u{1E87}']), - ('\u{1E86}', &['\u{1E86}', '\u{1E87}']), - ('\u{1E88}', &['\u{1E88}', '\u{1E89}']), - ('\u{1E88}', &['\u{1E88}', '\u{1E89}']), - ('\u{1E8A}', &['\u{1E8A}', '\u{1E8B}']), - ('\u{1E8A}', &['\u{1E8A}', '\u{1E8B}']), - ('\u{1E8C}', &['\u{1E8C}', '\u{1E8D}']), - ('\u{1E8C}', &['\u{1E8C}', '\u{1E8D}']), - ('\u{1E8E}', &['\u{1E8E}', '\u{1E8F}']), - ('\u{1E8E}', &['\u{1E8E}', '\u{1E8F}']), - ('\u{1E90}', &['\u{1E90}', '\u{1E91}']), - ('\u{1E90}', &['\u{1E90}', '\u{1E91}']), - ('\u{1E92}', &['\u{1E92}', '\u{1E93}']), - ('\u{1E92}', &['\u{1E92}', '\u{1E93}']), - ('\u{1E94}', &['\u{1E94}', '\u{1E95}']), - ('\u{1E94}', &['\u{1E94}', '\u{1E95}']), - ('\u{1EA0}', &['\u{1EA0}', '\u{1EA1}']), - ('\u{1EA0}', &['\u{1EA0}', '\u{1EA1}']), - ('\u{1EA2}', &['\u{1EA2}', '\u{1EA3}']), - ('\u{1EA2}', &['\u{1EA2}', '\u{1EA3}']), - ('\u{1EA4}', &['\u{1EA4}', '\u{1EA5}']), - ('\u{1EA4}', &['\u{1EA4}', '\u{1EA5}']), - ('\u{1EA6}', &['\u{1EA6}', '\u{1EA7}']), - ('\u{1EA6}', &['\u{1EA6}', '\u{1EA7}']), - ('\u{1EA8}', &['\u{1EA8}', '\u{1EA9}']), - ('\u{1EA8}', &['\u{1EA8}', '\u{1EA9}']), - ('\u{1EAA}', &['\u{1EAA}', '\u{1EAB}']), - ('\u{1EAA}', &['\u{1EAA}', '\u{1EAB}']), - ('\u{1EAC}', &['\u{1EAC}', '\u{1EAD}']), - ('\u{1EAC}', &['\u{1EAC}', '\u{1EAD}']), - ('\u{1EAE}', &['\u{1EAE}', '\u{1EAF}']), - ('\u{1EAE}', &['\u{1EAE}', '\u{1EAF}']), - ('\u{1EB0}', &['\u{1EB0}', '\u{1EB1}']), - ('\u{1EB0}', &['\u{1EB0}', '\u{1EB1}']), - ('\u{1EB2}', &['\u{1EB2}', '\u{1EB3}']), - ('\u{1EB2}', &['\u{1EB2}', '\u{1EB3}']), - ('\u{1EB4}', &['\u{1EB4}', '\u{1EB5}']), - ('\u{1EB4}', &['\u{1EB4}', '\u{1EB5}']), - ('\u{1EB6}', &['\u{1EB6}', '\u{1EB7}']), - ('\u{1EB6}', &['\u{1EB6}', '\u{1EB7}']), - ('\u{1EB8}', &['\u{1EB8}', '\u{1EB9}']), - ('\u{1EB8}', &['\u{1EB8}', '\u{1EB9}']), - ('\u{1EBA}', &['\u{1EBA}', '\u{1EBB}']), - ('\u{1EBA}', &['\u{1EBA}', '\u{1EBB}']), - ('\u{1EBC}', &['\u{1EBC}', '\u{1EBD}']), - ('\u{1EBC}', &['\u{1EBC}', '\u{1EBD}']), - ('\u{1EBE}', &['\u{1EBE}', '\u{1EBF}']), - ('\u{1EBE}', &['\u{1EBE}', '\u{1EBF}']), - ('\u{1EC0}', &['\u{1EC0}', '\u{1EC1}']), - ('\u{1EC0}', &['\u{1EC0}', '\u{1EC1}']), - ('\u{1EC2}', &['\u{1EC2}', '\u{1EC3}']), - ('\u{1EC2}', &['\u{1EC2}', '\u{1EC3}']), - ('\u{1EC4}', &['\u{1EC4}', '\u{1EC5}']), - ('\u{1EC4}', &['\u{1EC4}', '\u{1EC5}']), - ('\u{1EC6}', &['\u{1EC6}', '\u{1EC7}']), - ('\u{1EC6}', &['\u{1EC6}', '\u{1EC7}']), - ('\u{1EC8}', &['\u{1EC8}', '\u{1EC9}']), - ('\u{1EC8}', &['\u{1EC8}', '\u{1EC9}']), - ('\u{1ECA}', &['\u{1ECA}', '\u{1ECB}']), - ('\u{1ECA}', &['\u{1ECA}', '\u{1ECB}']), - ('\u{1ECC}', &['\u{1ECC}', '\u{1ECD}']), - ('\u{1ECC}', &['\u{1ECC}', '\u{1ECD}']), - ('\u{1ECE}', &['\u{1ECE}', '\u{1ECF}']), - ('\u{1ECE}', &['\u{1ECE}', '\u{1ECF}']), - ('\u{1ED0}', &['\u{1ED0}', '\u{1ED1}']), - ('\u{1ED0}', &['\u{1ED0}', '\u{1ED1}']), - ('\u{1ED2}', &['\u{1ED2}', '\u{1ED3}']), - ('\u{1ED2}', &['\u{1ED2}', '\u{1ED3}']), - ('\u{1ED4}', &['\u{1ED4}', '\u{1ED5}']), - ('\u{1ED4}', &['\u{1ED4}', '\u{1ED5}']), - ('\u{1ED6}', &['\u{1ED6}', '\u{1ED7}']), - ('\u{1ED6}', &['\u{1ED6}', '\u{1ED7}']), - ('\u{1ED8}', &['\u{1ED8}', '\u{1ED9}']), - ('\u{1ED8}', &['\u{1ED8}', '\u{1ED9}']), - ('\u{1EDA}', &['\u{1EDA}', '\u{1EDB}']), - ('\u{1EDA}', &['\u{1EDA}', '\u{1EDB}']), - ('\u{1EDC}', &['\u{1EDC}', '\u{1EDD}']), - ('\u{1EDC}', &['\u{1EDC}', '\u{1EDD}']), - ('\u{1EDE}', &['\u{1EDE}', '\u{1EDF}']), - ('\u{1EDE}', &['\u{1EDE}', '\u{1EDF}']), - ('\u{1EE0}', &['\u{1EE0}', '\u{1EE1}']), - ('\u{1EE0}', &['\u{1EE0}', '\u{1EE1}']), - ('\u{1EE2}', &['\u{1EE2}', '\u{1EE3}']), - ('\u{1EE2}', &['\u{1EE2}', '\u{1EE3}']), - ('\u{1EE4}', &['\u{1EE4}', '\u{1EE5}']), - ('\u{1EE4}', &['\u{1EE4}', '\u{1EE5}']), - ('\u{1EE6}', &['\u{1EE6}', '\u{1EE7}']), - ('\u{1EE6}', &['\u{1EE6}', '\u{1EE7}']), - ('\u{1EE8}', &['\u{1EE8}', '\u{1EE9}']), - ('\u{1EE8}', &['\u{1EE8}', '\u{1EE9}']), - ('\u{1EEA}', &['\u{1EEA}', '\u{1EEB}']), - ('\u{1EEA}', &['\u{1EEA}', '\u{1EEB}']), - ('\u{1EEC}', &['\u{1EEC}', '\u{1EED}']), - ('\u{1EEC}', &['\u{1EEC}', '\u{1EED}']), - ('\u{1EEE}', &['\u{1EEE}', '\u{1EEF}']), - ('\u{1EEE}', &['\u{1EEE}', '\u{1EEF}']), - ('\u{1EF0}', &['\u{1EF0}', '\u{1EF1}']), - ('\u{1EF0}', &['\u{1EF0}', '\u{1EF1}']), - ('\u{1EF2}', &['\u{1EF2}', '\u{1EF3}']), - ('\u{1EF2}', &['\u{1EF2}', '\u{1EF3}']), - ('\u{1EF4}', &['\u{1EF4}', '\u{1EF5}']), - ('\u{1EF4}', &['\u{1EF4}', '\u{1EF5}']), - ('\u{1EF6}', &['\u{1EF6}', '\u{1EF7}']), - ('\u{1EF6}', &['\u{1EF6}', '\u{1EF7}']), - ('\u{1EF8}', &['\u{1EF8}', '\u{1EF9}']), - ('\u{1EF8}', &['\u{1EF8}', '\u{1EF9}']), - ('\u{1EFA}', &['\u{1EFA}', '\u{1EFB}']), - ('\u{1EFA}', &['\u{1EFA}', '\u{1EFB}']), - ('\u{1EFC}', &['\u{1EFC}', '\u{1EFD}']), - ('\u{1EFC}', &['\u{1EFC}', '\u{1EFD}']), - ('\u{1EFE}', &['\u{1EFE}', '\u{1EFF}']), - ('\u{1EFE}', &['\u{1EFE}', '\u{1EFF}']), - ('\u{1F00}', &['\u{1F00}', '\u{1F08}']), - ('\u{1F00}', &['\u{1F00}', '\u{1F08}']), - ('\u{1F01}', &['\u{1F01}', '\u{1F09}']), - ('\u{1F01}', &['\u{1F01}', '\u{1F09}']), - ('\u{1F02}', &['\u{1F02}', '\u{1F0A}']), - ('\u{1F02}', &['\u{1F02}', '\u{1F0A}']), - ('\u{1F03}', &['\u{1F03}', '\u{1F0B}']), - ('\u{1F03}', &['\u{1F03}', '\u{1F0B}']), - ('\u{1F04}', &['\u{1F04}', '\u{1F0C}']), - ('\u{1F04}', &['\u{1F04}', '\u{1F0C}']), - ('\u{1F05}', &['\u{1F05}', '\u{1F0D}']), - ('\u{1F05}', &['\u{1F05}', '\u{1F0D}']), - ('\u{1F06}', &['\u{1F06}', '\u{1F0E}']), - ('\u{1F06}', &['\u{1F06}', '\u{1F0E}']), - ('\u{1F07}', &['\u{1F07}', '\u{1F0F}']), - ('\u{1F07}', &['\u{1F07}', '\u{1F0F}']), - ('\u{1F10}', &['\u{1F10}', '\u{1F18}']), - ('\u{1F10}', &['\u{1F10}', '\u{1F18}']), - ('\u{1F11}', &['\u{1F11}', '\u{1F19}']), - ('\u{1F11}', &['\u{1F11}', '\u{1F19}']), - ('\u{1F12}', &['\u{1F12}', '\u{1F1A}']), - ('\u{1F12}', &['\u{1F12}', '\u{1F1A}']), - ('\u{1F13}', &['\u{1F13}', '\u{1F1B}']), - ('\u{1F13}', &['\u{1F13}', '\u{1F1B}']), - ('\u{1F14}', &['\u{1F14}', '\u{1F1C}']), - ('\u{1F14}', &['\u{1F14}', '\u{1F1C}']), - ('\u{1F15}', &['\u{1F15}', '\u{1F1D}']), - ('\u{1F15}', &['\u{1F15}', '\u{1F1D}']), - ('\u{1F20}', &['\u{1F20}', '\u{1F28}']), - ('\u{1F20}', &['\u{1F20}', '\u{1F28}']), - ('\u{1F21}', &['\u{1F21}', '\u{1F29}']), - ('\u{1F21}', &['\u{1F21}', '\u{1F29}']), - ('\u{1F22}', &['\u{1F22}', '\u{1F2A}']), - ('\u{1F22}', &['\u{1F22}', '\u{1F2A}']), - ('\u{1F23}', &['\u{1F23}', '\u{1F2B}']), - ('\u{1F23}', &['\u{1F23}', '\u{1F2B}']), - ('\u{1F24}', &['\u{1F24}', '\u{1F2C}']), - ('\u{1F24}', &['\u{1F24}', '\u{1F2C}']), - ('\u{1F25}', &['\u{1F25}', '\u{1F2D}']), - ('\u{1F25}', &['\u{1F25}', '\u{1F2D}']), - ('\u{1F26}', &['\u{1F26}', '\u{1F2E}']), - ('\u{1F26}', &['\u{1F26}', '\u{1F2E}']), - ('\u{1F27}', &['\u{1F27}', '\u{1F2F}']), - ('\u{1F27}', &['\u{1F27}', '\u{1F2F}']), - ('\u{1F30}', &['\u{1F30}', '\u{1F38}']), - ('\u{1F30}', &['\u{1F30}', '\u{1F38}']), - ('\u{1F31}', &['\u{1F31}', '\u{1F39}']), - ('\u{1F31}', &['\u{1F31}', '\u{1F39}']), - ('\u{1F32}', &['\u{1F32}', '\u{1F3A}']), - ('\u{1F32}', &['\u{1F32}', '\u{1F3A}']), - ('\u{1F33}', &['\u{1F33}', '\u{1F3B}']), - ('\u{1F33}', &['\u{1F33}', '\u{1F3B}']), - ('\u{1F34}', &['\u{1F34}', '\u{1F3C}']), - ('\u{1F34}', &['\u{1F34}', '\u{1F3C}']), - ('\u{1F35}', &['\u{1F35}', '\u{1F3D}']), - ('\u{1F35}', &['\u{1F35}', '\u{1F3D}']), - ('\u{1F36}', &['\u{1F36}', '\u{1F3E}']), - ('\u{1F36}', &['\u{1F36}', '\u{1F3E}']), - ('\u{1F37}', &['\u{1F37}', '\u{1F3F}']), - ('\u{1F37}', &['\u{1F37}', '\u{1F3F}']), - ('\u{1F40}', &['\u{1F40}', '\u{1F48}']), - ('\u{1F40}', &['\u{1F40}', '\u{1F48}']), - ('\u{1F41}', &['\u{1F41}', '\u{1F49}']), - ('\u{1F41}', &['\u{1F41}', '\u{1F49}']), - ('\u{1F42}', &['\u{1F42}', '\u{1F4A}']), - ('\u{1F42}', &['\u{1F42}', '\u{1F4A}']), - ('\u{1F43}', &['\u{1F43}', '\u{1F4B}']), - ('\u{1F43}', &['\u{1F43}', '\u{1F4B}']), - ('\u{1F44}', &['\u{1F44}', '\u{1F4C}']), - ('\u{1F44}', &['\u{1F44}', '\u{1F4C}']), - ('\u{1F45}', &['\u{1F45}', '\u{1F4D}']), - ('\u{1F45}', &['\u{1F45}', '\u{1F4D}']), - ('\u{1F51}', &['\u{1F51}', '\u{1F59}']), - ('\u{1F51}', &['\u{1F51}', '\u{1F59}']), - ('\u{1F53}', &['\u{1F53}', '\u{1F5B}']), - ('\u{1F53}', &['\u{1F53}', '\u{1F5B}']), - ('\u{1F55}', &['\u{1F55}', '\u{1F5D}']), - ('\u{1F55}', &['\u{1F55}', '\u{1F5D}']), - ('\u{1F57}', &['\u{1F57}', '\u{1F5F}']), - ('\u{1F57}', &['\u{1F57}', '\u{1F5F}']), - ('\u{1F60}', &['\u{1F60}', '\u{1F68}']), - ('\u{1F60}', &['\u{1F60}', '\u{1F68}']), - ('\u{1F61}', &['\u{1F61}', '\u{1F69}']), - ('\u{1F61}', &['\u{1F61}', '\u{1F69}']), - ('\u{1F62}', &['\u{1F62}', '\u{1F6A}']), - ('\u{1F62}', &['\u{1F62}', '\u{1F6A}']), - ('\u{1F63}', &['\u{1F63}', '\u{1F6B}']), - ('\u{1F63}', &['\u{1F63}', '\u{1F6B}']), - ('\u{1F64}', &['\u{1F64}', '\u{1F6C}']), - ('\u{1F64}', &['\u{1F64}', '\u{1F6C}']), - ('\u{1F65}', &['\u{1F65}', '\u{1F6D}']), - ('\u{1F65}', &['\u{1F65}', '\u{1F6D}']), - ('\u{1F66}', &['\u{1F66}', '\u{1F6E}']), - ('\u{1F66}', &['\u{1F66}', '\u{1F6E}']), - ('\u{1F67}', &['\u{1F67}', '\u{1F6F}']), - ('\u{1F67}', &['\u{1F67}', '\u{1F6F}']), - ('\u{1F70}', &['\u{1F70}', '\u{1FBA}']), - ('\u{1F70}', &['\u{1F70}', '\u{1FBA}']), - ('\u{1F71}', &['\u{1F71}', '\u{1FBB}']), - ('\u{1F71}', &['\u{1F71}', '\u{1FBB}']), - ('\u{1F72}', &['\u{1F72}', '\u{1FC8}']), - ('\u{1F72}', &['\u{1F72}', '\u{1FC8}']), - ('\u{1F73}', &['\u{1F73}', '\u{1FC9}']), - ('\u{1F73}', &['\u{1F73}', '\u{1FC9}']), - ('\u{1F74}', &['\u{1F74}', '\u{1FCA}']), - ('\u{1F74}', &['\u{1F74}', '\u{1FCA}']), - ('\u{1F75}', &['\u{1F75}', '\u{1FCB}']), - ('\u{1F75}', &['\u{1F75}', '\u{1FCB}']), - ('\u{1F76}', &['\u{1F76}', '\u{1FDA}']), - ('\u{1F76}', &['\u{1F76}', '\u{1FDA}']), - ('\u{1F77}', &['\u{1F77}', '\u{1FDB}']), - ('\u{1F77}', &['\u{1F77}', '\u{1FDB}']), - ('\u{1F78}', &['\u{1F78}', '\u{1FF8}']), - ('\u{1F78}', &['\u{1F78}', '\u{1FF8}']), - ('\u{1F79}', &['\u{1F79}', '\u{1FF9}']), - ('\u{1F79}', &['\u{1F79}', '\u{1FF9}']), - ('\u{1F7A}', &['\u{1F7A}', '\u{1FEA}']), - ('\u{1F7A}', &['\u{1F7A}', '\u{1FEA}']), - ('\u{1F7B}', &['\u{1F7B}', '\u{1FEB}']), - ('\u{1F7B}', &['\u{1F7B}', '\u{1FEB}']), - ('\u{1F7C}', &['\u{1F7C}', '\u{1FFA}']), - ('\u{1F7C}', &['\u{1F7C}', '\u{1FFA}']), - ('\u{1F7D}', &['\u{1F7D}', '\u{1FFB}']), - ('\u{1F7D}', &['\u{1F7D}', '\u{1FFB}']), - ('\u{1F80}', &['\u{1F80}', '\u{1F88}']), - ('\u{1F80}', &['\u{1F80}', '\u{1F88}']), - ('\u{1F81}', &['\u{1F81}', '\u{1F89}']), - ('\u{1F81}', &['\u{1F81}', '\u{1F89}']), - ('\u{1F82}', &['\u{1F82}', '\u{1F8A}']), - ('\u{1F82}', &['\u{1F82}', '\u{1F8A}']), - ('\u{1F83}', &['\u{1F83}', '\u{1F8B}']), - ('\u{1F83}', &['\u{1F83}', '\u{1F8B}']), - ('\u{1F84}', &['\u{1F84}', '\u{1F8C}']), - ('\u{1F84}', &['\u{1F84}', '\u{1F8C}']), - ('\u{1F85}', &['\u{1F85}', '\u{1F8D}']), - ('\u{1F85}', &['\u{1F85}', '\u{1F8D}']), - ('\u{1F86}', &['\u{1F86}', '\u{1F8E}']), - ('\u{1F86}', &['\u{1F86}', '\u{1F8E}']), - ('\u{1F87}', &['\u{1F87}', '\u{1F8F}']), - ('\u{1F87}', &['\u{1F87}', '\u{1F8F}']), - ('\u{1F90}', &['\u{1F90}', '\u{1F98}']), - ('\u{1F90}', &['\u{1F90}', '\u{1F98}']), - ('\u{1F91}', &['\u{1F91}', '\u{1F99}']), - ('\u{1F91}', &['\u{1F91}', '\u{1F99}']), - ('\u{1F92}', &['\u{1F92}', '\u{1F9A}']), - ('\u{1F92}', &['\u{1F92}', '\u{1F9A}']), - ('\u{1F93}', &['\u{1F93}', '\u{1F9B}']), - ('\u{1F93}', &['\u{1F93}', '\u{1F9B}']), - ('\u{1F94}', &['\u{1F94}', '\u{1F9C}']), - ('\u{1F94}', &['\u{1F94}', '\u{1F9C}']), - ('\u{1F95}', &['\u{1F95}', '\u{1F9D}']), - ('\u{1F95}', &['\u{1F95}', '\u{1F9D}']), - ('\u{1F96}', &['\u{1F96}', '\u{1F9E}']), - ('\u{1F96}', &['\u{1F96}', '\u{1F9E}']), - ('\u{1F97}', &['\u{1F97}', '\u{1F9F}']), - ('\u{1F97}', &['\u{1F97}', '\u{1F9F}']), - ('\u{1FA0}', &['\u{1FA0}', '\u{1FA8}']), - ('\u{1FA0}', &['\u{1FA0}', '\u{1FA8}']), - ('\u{1FA1}', &['\u{1FA1}', '\u{1FA9}']), - ('\u{1FA1}', &['\u{1FA1}', '\u{1FA9}']), - ('\u{1FA2}', &['\u{1FA2}', '\u{1FAA}']), - ('\u{1FA2}', &['\u{1FA2}', '\u{1FAA}']), - ('\u{1FA3}', &['\u{1FA3}', '\u{1FAB}']), - ('\u{1FA3}', &['\u{1FA3}', '\u{1FAB}']), - ('\u{1FA4}', &['\u{1FA4}', '\u{1FAC}']), - ('\u{1FA4}', &['\u{1FA4}', '\u{1FAC}']), - ('\u{1FA5}', &['\u{1FA5}', '\u{1FAD}']), - ('\u{1FA5}', &['\u{1FA5}', '\u{1FAD}']), - ('\u{1FA6}', &['\u{1FA6}', '\u{1FAE}']), - ('\u{1FA6}', &['\u{1FA6}', '\u{1FAE}']), - ('\u{1FA7}', &['\u{1FA7}', '\u{1FAF}']), - ('\u{1FA7}', &['\u{1FA7}', '\u{1FAF}']), - ('\u{1FB0}', &['\u{1FB0}', '\u{1FB8}']), - ('\u{1FB0}', &['\u{1FB0}', '\u{1FB8}']), - ('\u{1FB1}', &['\u{1FB1}', '\u{1FB9}']), - ('\u{1FB1}', &['\u{1FB1}', '\u{1FB9}']), - ('\u{1FB3}', &['\u{1FB3}', '\u{1FBC}']), - ('\u{1FB3}', &['\u{1FB3}', '\u{1FBC}']), - ('\u{1FC3}', &['\u{1FC3}', '\u{1FCC}']), - ('\u{1FC3}', &['\u{1FC3}', '\u{1FCC}']), - ('\u{1FD0}', &['\u{1FD0}', '\u{1FD8}']), - ('\u{1FD0}', &['\u{1FD0}', '\u{1FD8}']), - ('\u{1FD1}', &['\u{1FD1}', '\u{1FD9}']), - ('\u{1FD1}', &['\u{1FD1}', '\u{1FD9}']), - ('\u{1FE0}', &['\u{1FE0}', '\u{1FE8}']), - ('\u{1FE0}', &['\u{1FE0}', '\u{1FE8}']), - ('\u{1FE1}', &['\u{1FE1}', '\u{1FE9}']), - ('\u{1FE1}', &['\u{1FE1}', '\u{1FE9}']), - ('\u{1FE5}', &['\u{1FE5}', '\u{1FEC}']), - ('\u{1FE5}', &['\u{1FE5}', '\u{1FEC}']), - ('\u{1FF3}', &['\u{1FF3}', '\u{1FFC}']), - ('\u{1FF3}', &['\u{1FF3}', '\u{1FFC}']), - ('\u{2132}', &['\u{2132}', '\u{214E}']), - ('\u{2132}', &['\u{2132}', '\u{214E}']), - ('\u{2160}', &['\u{2160}', '\u{2170}']), - ('\u{2160}', &['\u{2160}', '\u{2170}']), - ('\u{2161}', &['\u{2161}', '\u{2171}']), - ('\u{2161}', &['\u{2161}', '\u{2171}']), - ('\u{2162}', &['\u{2162}', '\u{2172}']), - ('\u{2162}', &['\u{2162}', '\u{2172}']), - ('\u{2163}', &['\u{2163}', '\u{2173}']), - ('\u{2163}', &['\u{2163}', '\u{2173}']), - ('\u{2164}', &['\u{2164}', '\u{2174}']), - ('\u{2164}', &['\u{2164}', '\u{2174}']), - ('\u{2165}', &['\u{2165}', '\u{2175}']), - ('\u{2165}', &['\u{2165}', '\u{2175}']), - ('\u{2166}', &['\u{2166}', '\u{2176}']), - ('\u{2166}', &['\u{2166}', '\u{2176}']), - ('\u{2167}', &['\u{2167}', '\u{2177}']), - ('\u{2167}', &['\u{2167}', '\u{2177}']), - ('\u{2168}', &['\u{2168}', '\u{2178}']), - ('\u{2168}', &['\u{2168}', '\u{2178}']), - ('\u{2169}', &['\u{2169}', '\u{2179}']), - ('\u{2169}', &['\u{2169}', '\u{2179}']), - ('\u{216A}', &['\u{216A}', '\u{217A}']), - ('\u{216A}', &['\u{216A}', '\u{217A}']), - ('\u{216B}', &['\u{216B}', '\u{217B}']), - ('\u{216B}', &['\u{216B}', '\u{217B}']), - ('\u{216C}', &['\u{216C}', '\u{217C}']), - ('\u{216C}', &['\u{216C}', '\u{217C}']), - ('\u{216D}', &['\u{216D}', '\u{217D}']), - ('\u{216D}', &['\u{216D}', '\u{217D}']), - ('\u{216E}', &['\u{216E}', '\u{217E}']), - ('\u{216E}', &['\u{216E}', '\u{217E}']), - ('\u{216F}', &['\u{216F}', '\u{217F}']), - ('\u{216F}', &['\u{216F}', '\u{217F}']), - ('\u{2183}', &['\u{2183}', '\u{2184}']), - ('\u{2183}', &['\u{2183}', '\u{2184}']), - ('\u{24B6}', &['\u{24B6}', '\u{24D0}']), - ('\u{24B6}', &['\u{24B6}', '\u{24D0}']), - ('\u{24B7}', &['\u{24B7}', '\u{24D1}']), - ('\u{24B7}', &['\u{24B7}', '\u{24D1}']), - ('\u{24B8}', &['\u{24B8}', '\u{24D2}']), - ('\u{24B8}', &['\u{24B8}', '\u{24D2}']), - ('\u{24B9}', &['\u{24B9}', '\u{24D3}']), - ('\u{24B9}', &['\u{24B9}', '\u{24D3}']), - ('\u{24BA}', &['\u{24BA}', '\u{24D4}']), - ('\u{24BA}', &['\u{24BA}', '\u{24D4}']), - ('\u{24BB}', &['\u{24BB}', '\u{24D5}']), - ('\u{24BB}', &['\u{24BB}', '\u{24D5}']), - ('\u{24BC}', &['\u{24BC}', '\u{24D6}']), - ('\u{24BC}', &['\u{24BC}', '\u{24D6}']), - ('\u{24BD}', &['\u{24BD}', '\u{24D7}']), - ('\u{24BD}', &['\u{24BD}', '\u{24D7}']), - ('\u{24BE}', &['\u{24BE}', '\u{24D8}']), - ('\u{24BE}', &['\u{24BE}', '\u{24D8}']), - ('\u{24BF}', &['\u{24BF}', '\u{24D9}']), - ('\u{24BF}', &['\u{24BF}', '\u{24D9}']), - ('\u{24C0}', &['\u{24C0}', '\u{24DA}']), - ('\u{24C0}', &['\u{24C0}', '\u{24DA}']), - ('\u{24C1}', &['\u{24C1}', '\u{24DB}']), - ('\u{24C1}', &['\u{24C1}', '\u{24DB}']), - ('\u{24C2}', &['\u{24C2}', '\u{24DC}']), - ('\u{24C2}', &['\u{24C2}', '\u{24DC}']), - ('\u{24C3}', &['\u{24C3}', '\u{24DD}']), - ('\u{24C3}', &['\u{24C3}', '\u{24DD}']), - ('\u{24C4}', &['\u{24C4}', '\u{24DE}']), - ('\u{24C4}', &['\u{24C4}', '\u{24DE}']), - ('\u{24C5}', &['\u{24C5}', '\u{24DF}']), - ('\u{24C5}', &['\u{24C5}', '\u{24DF}']), - ('\u{24C6}', &['\u{24C6}', '\u{24E0}']), - ('\u{24C6}', &['\u{24C6}', '\u{24E0}']), - ('\u{24C7}', &['\u{24C7}', '\u{24E1}']), - ('\u{24C7}', &['\u{24C7}', '\u{24E1}']), - ('\u{24C8}', &['\u{24C8}', '\u{24E2}']), - ('\u{24C8}', &['\u{24C8}', '\u{24E2}']), - ('\u{24C9}', &['\u{24C9}', '\u{24E3}']), - ('\u{24C9}', &['\u{24C9}', '\u{24E3}']), - ('\u{24CA}', &['\u{24CA}', '\u{24E4}']), - ('\u{24CA}', &['\u{24CA}', '\u{24E4}']), - ('\u{24CB}', &['\u{24CB}', '\u{24E5}']), - ('\u{24CB}', &['\u{24CB}', '\u{24E5}']), - ('\u{24CC}', &['\u{24CC}', '\u{24E6}']), - ('\u{24CC}', &['\u{24CC}', '\u{24E6}']), - ('\u{24CD}', &['\u{24CD}', '\u{24E7}']), - ('\u{24CD}', &['\u{24CD}', '\u{24E7}']), - ('\u{24CE}', &['\u{24CE}', '\u{24E8}']), - ('\u{24CE}', &['\u{24CE}', '\u{24E8}']), - ('\u{24CF}', &['\u{24CF}', '\u{24E9}']), - ('\u{24CF}', &['\u{24CF}', '\u{24E9}']), - ('\u{2C00}', &['\u{2C00}', '\u{2C30}']), - ('\u{2C00}', &['\u{2C00}', '\u{2C30}']), - ('\u{2C01}', &['\u{2C01}', '\u{2C31}']), - ('\u{2C01}', &['\u{2C01}', '\u{2C31}']), - ('\u{2C02}', &['\u{2C02}', '\u{2C32}']), - ('\u{2C02}', &['\u{2C02}', '\u{2C32}']), - ('\u{2C03}', &['\u{2C03}', '\u{2C33}']), - ('\u{2C03}', &['\u{2C03}', '\u{2C33}']), - ('\u{2C04}', &['\u{2C04}', '\u{2C34}']), - ('\u{2C04}', &['\u{2C04}', '\u{2C34}']), - ('\u{2C05}', &['\u{2C05}', '\u{2C35}']), - ('\u{2C05}', &['\u{2C05}', '\u{2C35}']), - ('\u{2C06}', &['\u{2C06}', '\u{2C36}']), - ('\u{2C06}', &['\u{2C06}', '\u{2C36}']), - ('\u{2C07}', &['\u{2C07}', '\u{2C37}']), - ('\u{2C07}', &['\u{2C07}', '\u{2C37}']), - ('\u{2C08}', &['\u{2C08}', '\u{2C38}']), - ('\u{2C08}', &['\u{2C08}', '\u{2C38}']), - ('\u{2C09}', &['\u{2C09}', '\u{2C39}']), - ('\u{2C09}', &['\u{2C09}', '\u{2C39}']), - ('\u{2C0A}', &['\u{2C0A}', '\u{2C3A}']), - ('\u{2C0A}', &['\u{2C0A}', '\u{2C3A}']), - ('\u{2C0B}', &['\u{2C0B}', '\u{2C3B}']), - ('\u{2C0B}', &['\u{2C0B}', '\u{2C3B}']), - ('\u{2C0C}', &['\u{2C0C}', '\u{2C3C}']), - ('\u{2C0C}', &['\u{2C0C}', '\u{2C3C}']), - ('\u{2C0D}', &['\u{2C0D}', '\u{2C3D}']), - ('\u{2C0D}', &['\u{2C0D}', '\u{2C3D}']), - ('\u{2C0E}', &['\u{2C0E}', '\u{2C3E}']), - ('\u{2C0E}', &['\u{2C0E}', '\u{2C3E}']), - ('\u{2C0F}', &['\u{2C0F}', '\u{2C3F}']), - ('\u{2C0F}', &['\u{2C0F}', '\u{2C3F}']), - ('\u{2C10}', &['\u{2C10}', '\u{2C40}']), - ('\u{2C10}', &['\u{2C10}', '\u{2C40}']), - ('\u{2C11}', &['\u{2C11}', '\u{2C41}']), - ('\u{2C11}', &['\u{2C11}', '\u{2C41}']), - ('\u{2C12}', &['\u{2C12}', '\u{2C42}']), - ('\u{2C12}', &['\u{2C12}', '\u{2C42}']), - ('\u{2C13}', &['\u{2C13}', '\u{2C43}']), - ('\u{2C13}', &['\u{2C13}', '\u{2C43}']), - ('\u{2C14}', &['\u{2C14}', '\u{2C44}']), - ('\u{2C14}', &['\u{2C14}', '\u{2C44}']), - ('\u{2C15}', &['\u{2C15}', '\u{2C45}']), - ('\u{2C15}', &['\u{2C15}', '\u{2C45}']), - ('\u{2C16}', &['\u{2C16}', '\u{2C46}']), - ('\u{2C16}', &['\u{2C16}', '\u{2C46}']), - ('\u{2C17}', &['\u{2C17}', '\u{2C47}']), - ('\u{2C17}', &['\u{2C17}', '\u{2C47}']), - ('\u{2C18}', &['\u{2C18}', '\u{2C48}']), - ('\u{2C18}', &['\u{2C18}', '\u{2C48}']), - ('\u{2C19}', &['\u{2C19}', '\u{2C49}']), - ('\u{2C19}', &['\u{2C19}', '\u{2C49}']), - ('\u{2C1A}', &['\u{2C1A}', '\u{2C4A}']), - ('\u{2C1A}', &['\u{2C1A}', '\u{2C4A}']), - ('\u{2C1B}', &['\u{2C1B}', '\u{2C4B}']), - ('\u{2C1B}', &['\u{2C1B}', '\u{2C4B}']), - ('\u{2C1C}', &['\u{2C1C}', '\u{2C4C}']), - ('\u{2C1C}', &['\u{2C1C}', '\u{2C4C}']), - ('\u{2C1D}', &['\u{2C1D}', '\u{2C4D}']), - ('\u{2C1D}', &['\u{2C1D}', '\u{2C4D}']), - ('\u{2C1E}', &['\u{2C1E}', '\u{2C4E}']), - ('\u{2C1E}', &['\u{2C1E}', '\u{2C4E}']), - ('\u{2C1F}', &['\u{2C1F}', '\u{2C4F}']), - ('\u{2C1F}', &['\u{2C1F}', '\u{2C4F}']), - ('\u{2C20}', &['\u{2C20}', '\u{2C50}']), - ('\u{2C20}', &['\u{2C20}', '\u{2C50}']), - ('\u{2C21}', &['\u{2C21}', '\u{2C51}']), - ('\u{2C21}', &['\u{2C21}', '\u{2C51}']), - ('\u{2C22}', &['\u{2C22}', '\u{2C52}']), - ('\u{2C22}', &['\u{2C22}', '\u{2C52}']), - ('\u{2C23}', &['\u{2C23}', '\u{2C53}']), - ('\u{2C23}', &['\u{2C23}', '\u{2C53}']), - ('\u{2C24}', &['\u{2C24}', '\u{2C54}']), - ('\u{2C24}', &['\u{2C24}', '\u{2C54}']), - ('\u{2C25}', &['\u{2C25}', '\u{2C55}']), - ('\u{2C25}', &['\u{2C25}', '\u{2C55}']), - ('\u{2C26}', &['\u{2C26}', '\u{2C56}']), - ('\u{2C26}', &['\u{2C26}', '\u{2C56}']), - ('\u{2C27}', &['\u{2C27}', '\u{2C57}']), - ('\u{2C27}', &['\u{2C27}', '\u{2C57}']), - ('\u{2C28}', &['\u{2C28}', '\u{2C58}']), - ('\u{2C28}', &['\u{2C28}', '\u{2C58}']), - ('\u{2C29}', &['\u{2C29}', '\u{2C59}']), - ('\u{2C29}', &['\u{2C29}', '\u{2C59}']), - ('\u{2C2A}', &['\u{2C2A}', '\u{2C5A}']), - ('\u{2C2A}', &['\u{2C2A}', '\u{2C5A}']), - ('\u{2C2B}', &['\u{2C2B}', '\u{2C5B}']), - ('\u{2C2B}', &['\u{2C2B}', '\u{2C5B}']), - ('\u{2C2C}', &['\u{2C2C}', '\u{2C5C}']), - ('\u{2C2C}', &['\u{2C2C}', '\u{2C5C}']), - ('\u{2C2D}', &['\u{2C2D}', '\u{2C5D}']), - ('\u{2C2D}', &['\u{2C2D}', '\u{2C5D}']), - ('\u{2C2E}', &['\u{2C2E}', '\u{2C5E}']), - ('\u{2C2E}', &['\u{2C2E}', '\u{2C5E}']), - ('\u{2C2F}', &['\u{2C2F}', '\u{2C5F}']), - ('\u{2C2F}', &['\u{2C2F}', '\u{2C5F}']), - ('\u{2C60}', &['\u{2C60}', '\u{2C61}']), - ('\u{2C60}', &['\u{2C60}', '\u{2C61}']), - ('\u{2C67}', &['\u{2C67}', '\u{2C68}']), - ('\u{2C67}', &['\u{2C67}', '\u{2C68}']), - ('\u{2C69}', &['\u{2C69}', '\u{2C6A}']), - ('\u{2C69}', &['\u{2C69}', '\u{2C6A}']), - ('\u{2C6B}', &['\u{2C6B}', '\u{2C6C}']), - ('\u{2C6B}', &['\u{2C6B}', '\u{2C6C}']), - ('\u{2C72}', &['\u{2C72}', '\u{2C73}']), - ('\u{2C72}', &['\u{2C72}', '\u{2C73}']), - ('\u{2C75}', &['\u{2C75}', '\u{2C76}']), - ('\u{2C75}', &['\u{2C75}', '\u{2C76}']), - ('\u{2C80}', &['\u{2C80}', '\u{2C81}']), - ('\u{2C80}', &['\u{2C80}', '\u{2C81}']), - ('\u{2C82}', &['\u{2C82}', '\u{2C83}']), - ('\u{2C82}', &['\u{2C82}', '\u{2C83}']), - ('\u{2C84}', &['\u{2C84}', '\u{2C85}']), - ('\u{2C84}', &['\u{2C84}', '\u{2C85}']), - ('\u{2C86}', &['\u{2C86}', '\u{2C87}']), - ('\u{2C86}', &['\u{2C86}', '\u{2C87}']), - ('\u{2C88}', &['\u{2C88}', '\u{2C89}']), - ('\u{2C88}', &['\u{2C88}', '\u{2C89}']), - ('\u{2C8A}', &['\u{2C8A}', '\u{2C8B}']), - ('\u{2C8A}', &['\u{2C8A}', '\u{2C8B}']), - ('\u{2C8C}', &['\u{2C8C}', '\u{2C8D}']), - ('\u{2C8C}', &['\u{2C8C}', '\u{2C8D}']), - ('\u{2C8E}', &['\u{2C8E}', '\u{2C8F}']), - ('\u{2C8E}', &['\u{2C8E}', '\u{2C8F}']), - ('\u{2C90}', &['\u{2C90}', '\u{2C91}']), - ('\u{2C90}', &['\u{2C90}', '\u{2C91}']), - ('\u{2C92}', &['\u{2C92}', '\u{2C93}']), - ('\u{2C92}', &['\u{2C92}', '\u{2C93}']), - ('\u{2C94}', &['\u{2C94}', '\u{2C95}']), - ('\u{2C94}', &['\u{2C94}', '\u{2C95}']), - ('\u{2C96}', &['\u{2C96}', '\u{2C97}']), - ('\u{2C96}', &['\u{2C96}', '\u{2C97}']), - ('\u{2C98}', &['\u{2C98}', '\u{2C99}']), - ('\u{2C98}', &['\u{2C98}', '\u{2C99}']), - ('\u{2C9A}', &['\u{2C9A}', '\u{2C9B}']), - ('\u{2C9A}', &['\u{2C9A}', '\u{2C9B}']), - ('\u{2C9C}', &['\u{2C9C}', '\u{2C9D}']), - ('\u{2C9C}', &['\u{2C9C}', '\u{2C9D}']), - ('\u{2C9E}', &['\u{2C9E}', '\u{2C9F}']), - ('\u{2C9E}', &['\u{2C9E}', '\u{2C9F}']), - ('\u{2CA0}', &['\u{2CA0}', '\u{2CA1}']), - ('\u{2CA0}', &['\u{2CA0}', '\u{2CA1}']), - ('\u{2CA2}', &['\u{2CA2}', '\u{2CA3}']), - ('\u{2CA2}', &['\u{2CA2}', '\u{2CA3}']), - ('\u{2CA4}', &['\u{2CA4}', '\u{2CA5}']), - ('\u{2CA4}', &['\u{2CA4}', '\u{2CA5}']), - ('\u{2CA6}', &['\u{2CA6}', '\u{2CA7}']), - ('\u{2CA6}', &['\u{2CA6}', '\u{2CA7}']), - ('\u{2CA8}', &['\u{2CA8}', '\u{2CA9}']), - ('\u{2CA8}', &['\u{2CA8}', '\u{2CA9}']), - ('\u{2CAA}', &['\u{2CAA}', '\u{2CAB}']), - ('\u{2CAA}', &['\u{2CAA}', '\u{2CAB}']), - ('\u{2CAC}', &['\u{2CAC}', '\u{2CAD}']), - ('\u{2CAC}', &['\u{2CAC}', '\u{2CAD}']), - ('\u{2CAE}', &['\u{2CAE}', '\u{2CAF}']), - ('\u{2CAE}', &['\u{2CAE}', '\u{2CAF}']), - ('\u{2CB0}', &['\u{2CB0}', '\u{2CB1}']), - ('\u{2CB0}', &['\u{2CB0}', '\u{2CB1}']), - ('\u{2CB2}', &['\u{2CB2}', '\u{2CB3}']), - ('\u{2CB2}', &['\u{2CB2}', '\u{2CB3}']), - ('\u{2CB4}', &['\u{2CB4}', '\u{2CB5}']), - ('\u{2CB4}', &['\u{2CB4}', '\u{2CB5}']), - ('\u{2CB6}', &['\u{2CB6}', '\u{2CB7}']), - ('\u{2CB6}', &['\u{2CB6}', '\u{2CB7}']), - ('\u{2CB8}', &['\u{2CB8}', '\u{2CB9}']), - ('\u{2CB8}', &['\u{2CB8}', '\u{2CB9}']), - ('\u{2CBA}', &['\u{2CBA}', '\u{2CBB}']), - ('\u{2CBA}', &['\u{2CBA}', '\u{2CBB}']), - ('\u{2CBC}', &['\u{2CBC}', '\u{2CBD}']), - ('\u{2CBC}', &['\u{2CBC}', '\u{2CBD}']), - ('\u{2CBE}', &['\u{2CBE}', '\u{2CBF}']), - ('\u{2CBE}', &['\u{2CBE}', '\u{2CBF}']), - ('\u{2CC0}', &['\u{2CC0}', '\u{2CC1}']), - ('\u{2CC0}', &['\u{2CC0}', '\u{2CC1}']), - ('\u{2CC2}', &['\u{2CC2}', '\u{2CC3}']), - ('\u{2CC2}', &['\u{2CC2}', '\u{2CC3}']), - ('\u{2CC4}', &['\u{2CC4}', '\u{2CC5}']), - ('\u{2CC4}', &['\u{2CC4}', '\u{2CC5}']), - ('\u{2CC6}', &['\u{2CC6}', '\u{2CC7}']), - ('\u{2CC6}', &['\u{2CC6}', '\u{2CC7}']), - ('\u{2CC8}', &['\u{2CC8}', '\u{2CC9}']), - ('\u{2CC8}', &['\u{2CC8}', '\u{2CC9}']), - ('\u{2CCA}', &['\u{2CCA}', '\u{2CCB}']), - ('\u{2CCA}', &['\u{2CCA}', '\u{2CCB}']), - ('\u{2CCC}', &['\u{2CCC}', '\u{2CCD}']), - ('\u{2CCC}', &['\u{2CCC}', '\u{2CCD}']), - ('\u{2CCE}', &['\u{2CCE}', '\u{2CCF}']), - ('\u{2CCE}', &['\u{2CCE}', '\u{2CCF}']), - ('\u{2CD0}', &['\u{2CD0}', '\u{2CD1}']), - ('\u{2CD0}', &['\u{2CD0}', '\u{2CD1}']), - ('\u{2CD2}', &['\u{2CD2}', '\u{2CD3}']), - ('\u{2CD2}', &['\u{2CD2}', '\u{2CD3}']), - ('\u{2CD4}', &['\u{2CD4}', '\u{2CD5}']), - ('\u{2CD4}', &['\u{2CD4}', '\u{2CD5}']), - ('\u{2CD6}', &['\u{2CD6}', '\u{2CD7}']), - ('\u{2CD6}', &['\u{2CD6}', '\u{2CD7}']), - ('\u{2CD8}', &['\u{2CD8}', '\u{2CD9}']), - ('\u{2CD8}', &['\u{2CD8}', '\u{2CD9}']), - ('\u{2CDA}', &['\u{2CDA}', '\u{2CDB}']), - ('\u{2CDA}', &['\u{2CDA}', '\u{2CDB}']), - ('\u{2CDC}', &['\u{2CDC}', '\u{2CDD}']), - ('\u{2CDC}', &['\u{2CDC}', '\u{2CDD}']), - ('\u{2CDE}', &['\u{2CDE}', '\u{2CDF}']), - ('\u{2CDE}', &['\u{2CDE}', '\u{2CDF}']), - ('\u{2CE0}', &['\u{2CE0}', '\u{2CE1}']), - ('\u{2CE0}', &['\u{2CE0}', '\u{2CE1}']), - ('\u{2CE2}', &['\u{2CE2}', '\u{2CE3}']), - ('\u{2CE2}', &['\u{2CE2}', '\u{2CE3}']), - ('\u{2CEB}', &['\u{2CEB}', '\u{2CEC}']), - ('\u{2CEB}', &['\u{2CEB}', '\u{2CEC}']), - ('\u{2CED}', &['\u{2CED}', '\u{2CEE}']), - ('\u{2CED}', &['\u{2CED}', '\u{2CEE}']), - ('\u{2CF2}', &['\u{2CF2}', '\u{2CF3}']), - ('\u{2CF2}', &['\u{2CF2}', '\u{2CF3}']), - ('\u{A640}', &['\u{A640}', '\u{A641}']), - ('\u{A640}', &['\u{A640}', '\u{A641}']), - ('\u{A642}', &['\u{A642}', '\u{A643}']), - ('\u{A642}', &['\u{A642}', '\u{A643}']), - ('\u{A644}', &['\u{A644}', '\u{A645}']), - ('\u{A644}', &['\u{A644}', '\u{A645}']), - ('\u{A646}', &['\u{A646}', '\u{A647}']), - ('\u{A646}', &['\u{A646}', '\u{A647}']), - ('\u{A648}', &['\u{A648}', '\u{A649}']), - ('\u{A648}', &['\u{A648}', '\u{A649}']), - ('\u{A64C}', &['\u{A64C}', '\u{A64D}']), - ('\u{A64C}', &['\u{A64C}', '\u{A64D}']), - ('\u{A64E}', &['\u{A64E}', '\u{A64F}']), - ('\u{A64E}', &['\u{A64E}', '\u{A64F}']), - ('\u{A650}', &['\u{A650}', '\u{A651}']), - ('\u{A650}', &['\u{A650}', '\u{A651}']), - ('\u{A652}', &['\u{A652}', '\u{A653}']), - ('\u{A652}', &['\u{A652}', '\u{A653}']), - ('\u{A654}', &['\u{A654}', '\u{A655}']), - ('\u{A654}', &['\u{A654}', '\u{A655}']), - ('\u{A656}', &['\u{A656}', '\u{A657}']), - ('\u{A656}', &['\u{A656}', '\u{A657}']), - ('\u{A658}', &['\u{A658}', '\u{A659}']), - ('\u{A658}', &['\u{A658}', '\u{A659}']), - ('\u{A65A}', &['\u{A65A}', '\u{A65B}']), - ('\u{A65A}', &['\u{A65A}', '\u{A65B}']), - ('\u{A65C}', &['\u{A65C}', '\u{A65D}']), - ('\u{A65C}', &['\u{A65C}', '\u{A65D}']), - ('\u{A65E}', &['\u{A65E}', '\u{A65F}']), - ('\u{A65E}', &['\u{A65E}', '\u{A65F}']), - ('\u{A660}', &['\u{A660}', '\u{A661}']), - ('\u{A660}', &['\u{A660}', '\u{A661}']), - ('\u{A662}', &['\u{A662}', '\u{A663}']), - ('\u{A662}', &['\u{A662}', '\u{A663}']), - ('\u{A664}', &['\u{A664}', '\u{A665}']), - ('\u{A664}', &['\u{A664}', '\u{A665}']), - ('\u{A666}', &['\u{A666}', '\u{A667}']), - ('\u{A666}', &['\u{A666}', '\u{A667}']), - ('\u{A668}', &['\u{A668}', '\u{A669}']), - ('\u{A668}', &['\u{A668}', '\u{A669}']), - ('\u{A66A}', &['\u{A66A}', '\u{A66B}']), - ('\u{A66A}', &['\u{A66A}', '\u{A66B}']), - ('\u{A66C}', &['\u{A66C}', '\u{A66D}']), - ('\u{A66C}', &['\u{A66C}', '\u{A66D}']), - ('\u{A680}', &['\u{A680}', '\u{A681}']), - ('\u{A680}', &['\u{A680}', '\u{A681}']), - ('\u{A682}', &['\u{A682}', '\u{A683}']), - ('\u{A682}', &['\u{A682}', '\u{A683}']), - ('\u{A684}', &['\u{A684}', '\u{A685}']), - ('\u{A684}', &['\u{A684}', '\u{A685}']), - ('\u{A686}', &['\u{A686}', '\u{A687}']), - ('\u{A686}', &['\u{A686}', '\u{A687}']), - ('\u{A688}', &['\u{A688}', '\u{A689}']), - ('\u{A688}', &['\u{A688}', '\u{A689}']), - ('\u{A68A}', &['\u{A68A}', '\u{A68B}']), - ('\u{A68A}', &['\u{A68A}', '\u{A68B}']), - ('\u{A68C}', &['\u{A68C}', '\u{A68D}']), - ('\u{A68C}', &['\u{A68C}', '\u{A68D}']), - ('\u{A68E}', &['\u{A68E}', '\u{A68F}']), - ('\u{A68E}', &['\u{A68E}', '\u{A68F}']), - ('\u{A690}', &['\u{A690}', '\u{A691}']), - ('\u{A690}', &['\u{A690}', '\u{A691}']), - ('\u{A692}', &['\u{A692}', '\u{A693}']), - ('\u{A692}', &['\u{A692}', '\u{A693}']), - ('\u{A694}', &['\u{A694}', '\u{A695}']), - ('\u{A694}', &['\u{A694}', '\u{A695}']), - ('\u{A696}', &['\u{A696}', '\u{A697}']), - ('\u{A696}', &['\u{A696}', '\u{A697}']), - ('\u{A698}', &['\u{A698}', '\u{A699}']), - ('\u{A698}', &['\u{A698}', '\u{A699}']), - ('\u{A69A}', &['\u{A69A}', '\u{A69B}']), - ('\u{A69A}', &['\u{A69A}', '\u{A69B}']), - ('\u{A722}', &['\u{A722}', '\u{A723}']), - ('\u{A722}', &['\u{A722}', '\u{A723}']), - ('\u{A724}', &['\u{A724}', '\u{A725}']), - ('\u{A724}', &['\u{A724}', '\u{A725}']), - ('\u{A726}', &['\u{A726}', '\u{A727}']), - ('\u{A726}', &['\u{A726}', '\u{A727}']), - ('\u{A728}', &['\u{A728}', '\u{A729}']), - ('\u{A728}', &['\u{A728}', '\u{A729}']), - ('\u{A72A}', &['\u{A72A}', '\u{A72B}']), - ('\u{A72A}', &['\u{A72A}', '\u{A72B}']), - ('\u{A72C}', &['\u{A72C}', '\u{A72D}']), - ('\u{A72C}', &['\u{A72C}', '\u{A72D}']), - ('\u{A72E}', &['\u{A72E}', '\u{A72F}']), - ('\u{A72E}', &['\u{A72E}', '\u{A72F}']), - ('\u{A732}', &['\u{A732}', '\u{A733}']), - ('\u{A732}', &['\u{A732}', '\u{A733}']), - ('\u{A734}', &['\u{A734}', '\u{A735}']), - ('\u{A734}', &['\u{A734}', '\u{A735}']), - ('\u{A736}', &['\u{A736}', '\u{A737}']), - ('\u{A736}', &['\u{A736}', '\u{A737}']), - ('\u{A738}', &['\u{A738}', '\u{A739}']), - ('\u{A738}', &['\u{A738}', '\u{A739}']), - ('\u{A73A}', &['\u{A73A}', '\u{A73B}']), - ('\u{A73A}', &['\u{A73A}', '\u{A73B}']), - ('\u{A73C}', &['\u{A73C}', '\u{A73D}']), - ('\u{A73C}', &['\u{A73C}', '\u{A73D}']), - ('\u{A73E}', &['\u{A73E}', '\u{A73F}']), - ('\u{A73E}', &['\u{A73E}', '\u{A73F}']), - ('\u{A740}', &['\u{A740}', '\u{A741}']), - ('\u{A740}', &['\u{A740}', '\u{A741}']), - ('\u{A742}', &['\u{A742}', '\u{A743}']), - ('\u{A742}', &['\u{A742}', '\u{A743}']), - ('\u{A744}', &['\u{A744}', '\u{A745}']), - ('\u{A744}', &['\u{A744}', '\u{A745}']), - ('\u{A746}', &['\u{A746}', '\u{A747}']), - ('\u{A746}', &['\u{A746}', '\u{A747}']), - ('\u{A748}', &['\u{A748}', '\u{A749}']), - ('\u{A748}', &['\u{A748}', '\u{A749}']), - ('\u{A74A}', &['\u{A74A}', '\u{A74B}']), - ('\u{A74A}', &['\u{A74A}', '\u{A74B}']), - ('\u{A74C}', &['\u{A74C}', '\u{A74D}']), - ('\u{A74C}', &['\u{A74C}', '\u{A74D}']), - ('\u{A74E}', &['\u{A74E}', '\u{A74F}']), - ('\u{A74E}', &['\u{A74E}', '\u{A74F}']), - ('\u{A750}', &['\u{A750}', '\u{A751}']), - ('\u{A750}', &['\u{A750}', '\u{A751}']), - ('\u{A752}', &['\u{A752}', '\u{A753}']), - ('\u{A752}', &['\u{A752}', '\u{A753}']), - ('\u{A754}', &['\u{A754}', '\u{A755}']), - ('\u{A754}', &['\u{A754}', '\u{A755}']), - ('\u{A756}', &['\u{A756}', '\u{A757}']), - ('\u{A756}', &['\u{A756}', '\u{A757}']), - ('\u{A758}', &['\u{A758}', '\u{A759}']), - ('\u{A758}', &['\u{A758}', '\u{A759}']), - ('\u{A75A}', &['\u{A75A}', '\u{A75B}']), - ('\u{A75A}', &['\u{A75A}', '\u{A75B}']), - ('\u{A75C}', &['\u{A75C}', '\u{A75D}']), - ('\u{A75C}', &['\u{A75C}', '\u{A75D}']), - ('\u{A75E}', &['\u{A75E}', '\u{A75F}']), - ('\u{A75E}', &['\u{A75E}', '\u{A75F}']), - ('\u{A760}', &['\u{A760}', '\u{A761}']), - ('\u{A760}', &['\u{A760}', '\u{A761}']), - ('\u{A762}', &['\u{A762}', '\u{A763}']), - ('\u{A762}', &['\u{A762}', '\u{A763}']), - ('\u{A764}', &['\u{A764}', '\u{A765}']), - ('\u{A764}', &['\u{A764}', '\u{A765}']), - ('\u{A766}', &['\u{A766}', '\u{A767}']), - ('\u{A766}', &['\u{A766}', '\u{A767}']), - ('\u{A768}', &['\u{A768}', '\u{A769}']), - ('\u{A768}', &['\u{A768}', '\u{A769}']), - ('\u{A76A}', &['\u{A76A}', '\u{A76B}']), - ('\u{A76A}', &['\u{A76A}', '\u{A76B}']), - ('\u{A76C}', &['\u{A76C}', '\u{A76D}']), - ('\u{A76C}', &['\u{A76C}', '\u{A76D}']), - ('\u{A76E}', &['\u{A76E}', '\u{A76F}']), - ('\u{A76E}', &['\u{A76E}', '\u{A76F}']), - ('\u{A779}', &['\u{A779}', '\u{A77A}']), - ('\u{A779}', &['\u{A779}', '\u{A77A}']), - ('\u{A77B}', &['\u{A77B}', '\u{A77C}']), - ('\u{A77B}', &['\u{A77B}', '\u{A77C}']), - ('\u{A77E}', &['\u{A77E}', '\u{A77F}']), - ('\u{A77E}', &['\u{A77E}', '\u{A77F}']), - ('\u{A780}', &['\u{A780}', '\u{A781}']), - ('\u{A780}', &['\u{A780}', '\u{A781}']), - ('\u{A782}', &['\u{A782}', '\u{A783}']), - ('\u{A782}', &['\u{A782}', '\u{A783}']), - ('\u{A784}', &['\u{A784}', '\u{A785}']), - ('\u{A784}', &['\u{A784}', '\u{A785}']), - ('\u{A786}', &['\u{A786}', '\u{A787}']), - ('\u{A786}', &['\u{A786}', '\u{A787}']), - ('\u{A78B}', &['\u{A78B}', '\u{A78C}']), - ('\u{A78B}', &['\u{A78B}', '\u{A78C}']), - ('\u{A790}', &['\u{A790}', '\u{A791}']), - ('\u{A790}', &['\u{A790}', '\u{A791}']), - ('\u{A792}', &['\u{A792}', '\u{A793}']), - ('\u{A792}', &['\u{A792}', '\u{A793}']), - ('\u{A794}', &['\u{A794}', '\u{A7C4}']), - ('\u{A794}', &['\u{A794}', '\u{A7C4}']), - ('\u{A796}', &['\u{A796}', '\u{A797}']), - ('\u{A796}', &['\u{A796}', '\u{A797}']), - ('\u{A798}', &['\u{A798}', '\u{A799}']), - ('\u{A798}', &['\u{A798}', '\u{A799}']), - ('\u{A79A}', &['\u{A79A}', '\u{A79B}']), - ('\u{A79A}', &['\u{A79A}', '\u{A79B}']), - ('\u{A79C}', &['\u{A79C}', '\u{A79D}']), - ('\u{A79C}', &['\u{A79C}', '\u{A79D}']), - ('\u{A79E}', &['\u{A79E}', '\u{A79F}']), - ('\u{A79E}', &['\u{A79E}', '\u{A79F}']), - ('\u{A7A0}', &['\u{A7A0}', '\u{A7A1}']), - ('\u{A7A0}', &['\u{A7A0}', '\u{A7A1}']), - ('\u{A7A2}', &['\u{A7A2}', '\u{A7A3}']), - ('\u{A7A2}', &['\u{A7A2}', '\u{A7A3}']), - ('\u{A7A4}', &['\u{A7A4}', '\u{A7A5}']), - ('\u{A7A4}', &['\u{A7A4}', '\u{A7A5}']), - ('\u{A7A6}', &['\u{A7A6}', '\u{A7A7}']), - ('\u{A7A6}', &['\u{A7A6}', '\u{A7A7}']), - ('\u{A7A8}', &['\u{A7A8}', '\u{A7A9}']), - ('\u{A7A8}', &['\u{A7A8}', '\u{A7A9}']), - ('\u{A7B3}', &['\u{A7B3}', '\u{AB53}']), - ('\u{A7B3}', &['\u{A7B3}', '\u{AB53}']), - ('\u{A7B4}', &['\u{A7B4}', '\u{A7B5}']), - ('\u{A7B4}', &['\u{A7B4}', '\u{A7B5}']), - ('\u{A7B6}', &['\u{A7B6}', '\u{A7B7}']), - ('\u{A7B6}', &['\u{A7B6}', '\u{A7B7}']), - ('\u{A7B8}', &['\u{A7B8}', '\u{A7B9}']), - ('\u{A7B8}', &['\u{A7B8}', '\u{A7B9}']), - ('\u{A7BA}', &['\u{A7BA}', '\u{A7BB}']), - ('\u{A7BA}', &['\u{A7BA}', '\u{A7BB}']), - ('\u{A7BC}', &['\u{A7BC}', '\u{A7BD}']), - ('\u{A7BC}', &['\u{A7BC}', '\u{A7BD}']), - ('\u{A7BE}', &['\u{A7BE}', '\u{A7BF}']), - ('\u{A7BE}', &['\u{A7BE}', '\u{A7BF}']), - ('\u{A7C0}', &['\u{A7C0}', '\u{A7C1}']), - ('\u{A7C0}', &['\u{A7C0}', '\u{A7C1}']), - ('\u{A7C2}', &['\u{A7C2}', '\u{A7C3}']), - ('\u{A7C2}', &['\u{A7C2}', '\u{A7C3}']), - ('\u{A7C7}', &['\u{A7C7}', '\u{A7C8}']), - ('\u{A7C7}', &['\u{A7C7}', '\u{A7C8}']), - ('\u{A7C9}', &['\u{A7C9}', '\u{A7CA}']), - ('\u{A7C9}', &['\u{A7C9}', '\u{A7CA}']), - ('\u{A7D0}', &['\u{A7D0}', '\u{A7D1}']), - ('\u{A7D0}', &['\u{A7D0}', '\u{A7D1}']), - ('\u{A7D6}', &['\u{A7D6}', '\u{A7D7}']), - ('\u{A7D6}', &['\u{A7D6}', '\u{A7D7}']), - ('\u{A7D8}', &['\u{A7D8}', '\u{A7D9}']), - ('\u{A7D8}', &['\u{A7D8}', '\u{A7D9}']), - ('\u{A7F5}', &['\u{A7F5}', '\u{A7F6}']), - ('\u{A7F5}', &['\u{A7F5}', '\u{A7F6}']), - ('\u{FF21}', &['\u{FF21}', '\u{FF41}']), - ('\u{FF21}', &['\u{FF21}', '\u{FF41}']), - ('\u{FF22}', &['\u{FF22}', '\u{FF42}']), - ('\u{FF22}', &['\u{FF22}', '\u{FF42}']), - ('\u{FF23}', &['\u{FF23}', '\u{FF43}']), - ('\u{FF23}', &['\u{FF23}', '\u{FF43}']), - ('\u{FF24}', &['\u{FF24}', '\u{FF44}']), - ('\u{FF24}', &['\u{FF24}', '\u{FF44}']), - ('\u{FF25}', &['\u{FF25}', '\u{FF45}']), - ('\u{FF25}', &['\u{FF25}', '\u{FF45}']), - ('\u{FF26}', &['\u{FF26}', '\u{FF46}']), - ('\u{FF26}', &['\u{FF26}', '\u{FF46}']), - ('\u{FF27}', &['\u{FF27}', '\u{FF47}']), - ('\u{FF27}', &['\u{FF27}', '\u{FF47}']), - ('\u{FF28}', &['\u{FF28}', '\u{FF48}']), - ('\u{FF28}', &['\u{FF28}', '\u{FF48}']), - ('\u{FF29}', &['\u{FF29}', '\u{FF49}']), - ('\u{FF29}', &['\u{FF29}', '\u{FF49}']), - ('\u{FF2A}', &['\u{FF2A}', '\u{FF4A}']), - ('\u{FF2A}', &['\u{FF2A}', '\u{FF4A}']), - ('\u{FF2B}', &['\u{FF2B}', '\u{FF4B}']), - ('\u{FF2B}', &['\u{FF2B}', '\u{FF4B}']), - ('\u{FF2C}', &['\u{FF2C}', '\u{FF4C}']), - ('\u{FF2C}', &['\u{FF2C}', '\u{FF4C}']), - ('\u{FF2D}', &['\u{FF2D}', '\u{FF4D}']), - ('\u{FF2D}', &['\u{FF2D}', '\u{FF4D}']), - ('\u{FF2E}', &['\u{FF2E}', '\u{FF4E}']), - ('\u{FF2E}', &['\u{FF2E}', '\u{FF4E}']), - ('\u{FF2F}', &['\u{FF2F}', '\u{FF4F}']), - ('\u{FF2F}', &['\u{FF2F}', '\u{FF4F}']), - ('\u{FF30}', &['\u{FF30}', '\u{FF50}']), - ('\u{FF30}', &['\u{FF30}', '\u{FF50}']), - ('\u{FF31}', &['\u{FF31}', '\u{FF51}']), - ('\u{FF31}', &['\u{FF31}', '\u{FF51}']), - ('\u{FF32}', &['\u{FF32}', '\u{FF52}']), - ('\u{FF32}', &['\u{FF32}', '\u{FF52}']), - ('\u{FF33}', &['\u{FF33}', '\u{FF53}']), - ('\u{FF33}', &['\u{FF33}', '\u{FF53}']), - ('\u{FF34}', &['\u{FF34}', '\u{FF54}']), - ('\u{FF34}', &['\u{FF34}', '\u{FF54}']), - ('\u{FF35}', &['\u{FF35}', '\u{FF55}']), - ('\u{FF35}', &['\u{FF35}', '\u{FF55}']), - ('\u{FF36}', &['\u{FF36}', '\u{FF56}']), - ('\u{FF36}', &['\u{FF36}', '\u{FF56}']), - ('\u{FF37}', &['\u{FF37}', '\u{FF57}']), - ('\u{FF37}', &['\u{FF37}', '\u{FF57}']), - ('\u{FF38}', &['\u{FF38}', '\u{FF58}']), - ('\u{FF38}', &['\u{FF38}', '\u{FF58}']), - ('\u{FF39}', &['\u{FF39}', '\u{FF59}']), - ('\u{FF39}', &['\u{FF39}', '\u{FF59}']), - ('\u{FF3A}', &['\u{FF3A}', '\u{FF5A}']), - ('\u{FF3A}', &['\u{FF3A}', '\u{FF5A}']), - ('\u{10400}', &['\u{10400}', '\u{10428}']), - ('\u{10400}', &['\u{10400}', '\u{10428}']), - ('\u{10401}', &['\u{10401}', '\u{10429}']), - ('\u{10401}', &['\u{10401}', '\u{10429}']), - ('\u{10402}', &['\u{10402}', '\u{1042A}']), - ('\u{10402}', &['\u{10402}', '\u{1042A}']), - ('\u{10403}', &['\u{10403}', '\u{1042B}']), - ('\u{10403}', &['\u{10403}', '\u{1042B}']), - ('\u{10404}', &['\u{10404}', '\u{1042C}']), - ('\u{10404}', &['\u{10404}', '\u{1042C}']), - ('\u{10405}', &['\u{10405}', '\u{1042D}']), - ('\u{10405}', &['\u{10405}', '\u{1042D}']), - ('\u{10406}', &['\u{10406}', '\u{1042E}']), - ('\u{10406}', &['\u{10406}', '\u{1042E}']), - ('\u{10407}', &['\u{10407}', '\u{1042F}']), - ('\u{10407}', &['\u{10407}', '\u{1042F}']), - ('\u{10408}', &['\u{10408}', '\u{10430}']), - ('\u{10408}', &['\u{10408}', '\u{10430}']), - ('\u{10409}', &['\u{10409}', '\u{10431}']), - ('\u{10409}', &['\u{10409}', '\u{10431}']), - ('\u{1040A}', &['\u{1040A}', '\u{10432}']), - ('\u{1040A}', &['\u{1040A}', '\u{10432}']), - ('\u{1040B}', &['\u{1040B}', '\u{10433}']), - ('\u{1040B}', &['\u{1040B}', '\u{10433}']), - ('\u{1040C}', &['\u{1040C}', '\u{10434}']), - ('\u{1040C}', &['\u{1040C}', '\u{10434}']), - ('\u{1040D}', &['\u{1040D}', '\u{10435}']), - ('\u{1040D}', &['\u{1040D}', '\u{10435}']), - ('\u{1040E}', &['\u{1040E}', '\u{10436}']), - ('\u{1040E}', &['\u{1040E}', '\u{10436}']), - ('\u{1040F}', &['\u{1040F}', '\u{10437}']), - ('\u{1040F}', &['\u{1040F}', '\u{10437}']), - ('\u{10410}', &['\u{10410}', '\u{10438}']), - ('\u{10410}', &['\u{10410}', '\u{10438}']), - ('\u{10411}', &['\u{10411}', '\u{10439}']), - ('\u{10411}', &['\u{10411}', '\u{10439}']), - ('\u{10412}', &['\u{10412}', '\u{1043A}']), - ('\u{10412}', &['\u{10412}', '\u{1043A}']), - ('\u{10413}', &['\u{10413}', '\u{1043B}']), - ('\u{10413}', &['\u{10413}', '\u{1043B}']), - ('\u{10414}', &['\u{10414}', '\u{1043C}']), - ('\u{10414}', &['\u{10414}', '\u{1043C}']), - ('\u{10415}', &['\u{10415}', '\u{1043D}']), - ('\u{10415}', &['\u{10415}', '\u{1043D}']), - ('\u{10416}', &['\u{10416}', '\u{1043E}']), - ('\u{10416}', &['\u{10416}', '\u{1043E}']), - ('\u{10417}', &['\u{10417}', '\u{1043F}']), - ('\u{10417}', &['\u{10417}', '\u{1043F}']), - ('\u{10418}', &['\u{10418}', '\u{10440}']), - ('\u{10418}', &['\u{10418}', '\u{10440}']), - ('\u{10419}', &['\u{10419}', '\u{10441}']), - ('\u{10419}', &['\u{10419}', '\u{10441}']), - ('\u{1041A}', &['\u{1041A}', '\u{10442}']), - ('\u{1041A}', &['\u{1041A}', '\u{10442}']), - ('\u{1041B}', &['\u{1041B}', '\u{10443}']), - ('\u{1041B}', &['\u{1041B}', '\u{10443}']), - ('\u{1041C}', &['\u{1041C}', '\u{10444}']), - ('\u{1041C}', &['\u{1041C}', '\u{10444}']), - ('\u{1041D}', &['\u{1041D}', '\u{10445}']), - ('\u{1041D}', &['\u{1041D}', '\u{10445}']), - ('\u{1041E}', &['\u{1041E}', '\u{10446}']), - ('\u{1041E}', &['\u{1041E}', '\u{10446}']), - ('\u{1041F}', &['\u{1041F}', '\u{10447}']), - ('\u{1041F}', &['\u{1041F}', '\u{10447}']), - ('\u{10420}', &['\u{10420}', '\u{10448}']), - ('\u{10420}', &['\u{10420}', '\u{10448}']), - ('\u{10421}', &['\u{10421}', '\u{10449}']), - ('\u{10421}', &['\u{10421}', '\u{10449}']), - ('\u{10422}', &['\u{10422}', '\u{1044A}']), - ('\u{10422}', &['\u{10422}', '\u{1044A}']), - ('\u{10423}', &['\u{10423}', '\u{1044B}']), - ('\u{10423}', &['\u{10423}', '\u{1044B}']), - ('\u{10424}', &['\u{10424}', '\u{1044C}']), - ('\u{10424}', &['\u{10424}', '\u{1044C}']), - ('\u{10425}', &['\u{10425}', '\u{1044D}']), - ('\u{10425}', &['\u{10425}', '\u{1044D}']), - ('\u{10426}', &['\u{10426}', '\u{1044E}']), - ('\u{10426}', &['\u{10426}', '\u{1044E}']), - ('\u{10427}', &['\u{10427}', '\u{1044F}']), - ('\u{10427}', &['\u{10427}', '\u{1044F}']), - ('\u{104B0}', &['\u{104B0}', '\u{104D8}']), - ('\u{104B0}', &['\u{104B0}', '\u{104D8}']), - ('\u{104B1}', &['\u{104B1}', '\u{104D9}']), - ('\u{104B1}', &['\u{104B1}', '\u{104D9}']), - ('\u{104B2}', &['\u{104B2}', '\u{104DA}']), - ('\u{104B2}', &['\u{104B2}', '\u{104DA}']), - ('\u{104B3}', &['\u{104B3}', '\u{104DB}']), - ('\u{104B3}', &['\u{104B3}', '\u{104DB}']), - ('\u{104B4}', &['\u{104B4}', '\u{104DC}']), - ('\u{104B4}', &['\u{104B4}', '\u{104DC}']), - ('\u{104B5}', &['\u{104B5}', '\u{104DD}']), - ('\u{104B5}', &['\u{104B5}', '\u{104DD}']), - ('\u{104B6}', &['\u{104B6}', '\u{104DE}']), - ('\u{104B6}', &['\u{104B6}', '\u{104DE}']), - ('\u{104B7}', &['\u{104B7}', '\u{104DF}']), - ('\u{104B7}', &['\u{104B7}', '\u{104DF}']), - ('\u{104B8}', &['\u{104B8}', '\u{104E0}']), - ('\u{104B8}', &['\u{104B8}', '\u{104E0}']), - ('\u{104B9}', &['\u{104B9}', '\u{104E1}']), - ('\u{104B9}', &['\u{104B9}', '\u{104E1}']), - ('\u{104BA}', &['\u{104BA}', '\u{104E2}']), - ('\u{104BA}', &['\u{104BA}', '\u{104E2}']), - ('\u{104BB}', &['\u{104BB}', '\u{104E3}']), - ('\u{104BB}', &['\u{104BB}', '\u{104E3}']), - ('\u{104BC}', &['\u{104BC}', '\u{104E4}']), - ('\u{104BC}', &['\u{104BC}', '\u{104E4}']), - ('\u{104BD}', &['\u{104BD}', '\u{104E5}']), - ('\u{104BD}', &['\u{104BD}', '\u{104E5}']), - ('\u{104BE}', &['\u{104BE}', '\u{104E6}']), - ('\u{104BE}', &['\u{104BE}', '\u{104E6}']), - ('\u{104BF}', &['\u{104BF}', '\u{104E7}']), - ('\u{104BF}', &['\u{104BF}', '\u{104E7}']), - ('\u{104C0}', &['\u{104C0}', '\u{104E8}']), - ('\u{104C0}', &['\u{104C0}', '\u{104E8}']), - ('\u{104C1}', &['\u{104C1}', '\u{104E9}']), - ('\u{104C1}', &['\u{104C1}', '\u{104E9}']), - ('\u{104C2}', &['\u{104C2}', '\u{104EA}']), - ('\u{104C2}', &['\u{104C2}', '\u{104EA}']), - ('\u{104C3}', &['\u{104C3}', '\u{104EB}']), - ('\u{104C3}', &['\u{104C3}', '\u{104EB}']), - ('\u{104C4}', &['\u{104C4}', '\u{104EC}']), - ('\u{104C4}', &['\u{104C4}', '\u{104EC}']), - ('\u{104C5}', &['\u{104C5}', '\u{104ED}']), - ('\u{104C5}', &['\u{104C5}', '\u{104ED}']), - ('\u{104C6}', &['\u{104C6}', '\u{104EE}']), - ('\u{104C6}', &['\u{104C6}', '\u{104EE}']), - ('\u{104C7}', &['\u{104C7}', '\u{104EF}']), - ('\u{104C7}', &['\u{104C7}', '\u{104EF}']), - ('\u{104C8}', &['\u{104C8}', '\u{104F0}']), - ('\u{104C8}', &['\u{104C8}', '\u{104F0}']), - ('\u{104C9}', &['\u{104C9}', '\u{104F1}']), - ('\u{104C9}', &['\u{104C9}', '\u{104F1}']), - ('\u{104CA}', &['\u{104CA}', '\u{104F2}']), - ('\u{104CA}', &['\u{104CA}', '\u{104F2}']), - ('\u{104CB}', &['\u{104CB}', '\u{104F3}']), - ('\u{104CB}', &['\u{104CB}', '\u{104F3}']), - ('\u{104CC}', &['\u{104CC}', '\u{104F4}']), - ('\u{104CC}', &['\u{104CC}', '\u{104F4}']), - ('\u{104CD}', &['\u{104CD}', '\u{104F5}']), - ('\u{104CD}', &['\u{104CD}', '\u{104F5}']), - ('\u{104CE}', &['\u{104CE}', '\u{104F6}']), - ('\u{104CE}', &['\u{104CE}', '\u{104F6}']), - ('\u{104CF}', &['\u{104CF}', '\u{104F7}']), - ('\u{104CF}', &['\u{104CF}', '\u{104F7}']), - ('\u{104D0}', &['\u{104D0}', '\u{104F8}']), - ('\u{104D0}', &['\u{104D0}', '\u{104F8}']), - ('\u{104D1}', &['\u{104D1}', '\u{104F9}']), - ('\u{104D1}', &['\u{104D1}', '\u{104F9}']), - ('\u{104D2}', &['\u{104D2}', '\u{104FA}']), - ('\u{104D2}', &['\u{104D2}', '\u{104FA}']), - ('\u{104D3}', &['\u{104D3}', '\u{104FB}']), - ('\u{104D3}', &['\u{104D3}', '\u{104FB}']), - ('\u{10570}', &['\u{10570}', '\u{10597}']), - ('\u{10570}', &['\u{10570}', '\u{10597}']), - ('\u{10571}', &['\u{10571}', '\u{10598}']), - ('\u{10571}', &['\u{10571}', '\u{10598}']), - ('\u{10572}', &['\u{10572}', '\u{10599}']), - ('\u{10572}', &['\u{10572}', '\u{10599}']), - ('\u{10573}', &['\u{10573}', '\u{1059A}']), - ('\u{10573}', &['\u{10573}', '\u{1059A}']), - ('\u{10574}', &['\u{10574}', '\u{1059B}']), - ('\u{10574}', &['\u{10574}', '\u{1059B}']), - ('\u{10575}', &['\u{10575}', '\u{1059C}']), - ('\u{10575}', &['\u{10575}', '\u{1059C}']), - ('\u{10576}', &['\u{10576}', '\u{1059D}']), - ('\u{10576}', &['\u{10576}', '\u{1059D}']), - ('\u{10577}', &['\u{10577}', '\u{1059E}']), - ('\u{10577}', &['\u{10577}', '\u{1059E}']), - ('\u{10578}', &['\u{10578}', '\u{1059F}']), - ('\u{10578}', &['\u{10578}', '\u{1059F}']), - ('\u{10579}', &['\u{10579}', '\u{105A0}']), - ('\u{10579}', &['\u{10579}', '\u{105A0}']), - ('\u{1057A}', &['\u{1057A}', '\u{105A1}']), - ('\u{1057A}', &['\u{1057A}', '\u{105A1}']), - ('\u{1057C}', &['\u{1057C}', '\u{105A3}']), - ('\u{1057C}', &['\u{1057C}', '\u{105A3}']), - ('\u{1057D}', &['\u{1057D}', '\u{105A4}']), - ('\u{1057D}', &['\u{1057D}', '\u{105A4}']), - ('\u{1057E}', &['\u{1057E}', '\u{105A5}']), - ('\u{1057E}', &['\u{1057E}', '\u{105A5}']), - ('\u{1057F}', &['\u{1057F}', '\u{105A6}']), - ('\u{1057F}', &['\u{1057F}', '\u{105A6}']), - ('\u{10580}', &['\u{10580}', '\u{105A7}']), - ('\u{10580}', &['\u{10580}', '\u{105A7}']), - ('\u{10581}', &['\u{10581}', '\u{105A8}']), - ('\u{10581}', &['\u{10581}', '\u{105A8}']), - ('\u{10582}', &['\u{10582}', '\u{105A9}']), - ('\u{10582}', &['\u{10582}', '\u{105A9}']), - ('\u{10583}', &['\u{10583}', '\u{105AA}']), - ('\u{10583}', &['\u{10583}', '\u{105AA}']), - ('\u{10584}', &['\u{10584}', '\u{105AB}']), - ('\u{10584}', &['\u{10584}', '\u{105AB}']), - ('\u{10585}', &['\u{10585}', '\u{105AC}']), - ('\u{10585}', &['\u{10585}', '\u{105AC}']), - ('\u{10586}', &['\u{10586}', '\u{105AD}']), - ('\u{10586}', &['\u{10586}', '\u{105AD}']), - ('\u{10587}', &['\u{10587}', '\u{105AE}']), - ('\u{10587}', &['\u{10587}', '\u{105AE}']), - ('\u{10588}', &['\u{10588}', '\u{105AF}']), - ('\u{10588}', &['\u{10588}', '\u{105AF}']), - ('\u{10589}', &['\u{10589}', '\u{105B0}']), - ('\u{10589}', &['\u{10589}', '\u{105B0}']), - ('\u{1058A}', &['\u{1058A}', '\u{105B1}']), - ('\u{1058A}', &['\u{1058A}', '\u{105B1}']), - ('\u{1058C}', &['\u{1058C}', '\u{105B3}']), - ('\u{1058C}', &['\u{1058C}', '\u{105B3}']), - ('\u{1058D}', &['\u{1058D}', '\u{105B4}']), - ('\u{1058D}', &['\u{1058D}', '\u{105B4}']), - ('\u{1058E}', &['\u{1058E}', '\u{105B5}']), - ('\u{1058E}', &['\u{1058E}', '\u{105B5}']), - ('\u{1058F}', &['\u{1058F}', '\u{105B6}']), - ('\u{1058F}', &['\u{1058F}', '\u{105B6}']), - ('\u{10590}', &['\u{10590}', '\u{105B7}']), - ('\u{10590}', &['\u{10590}', '\u{105B7}']), - ('\u{10591}', &['\u{10591}', '\u{105B8}']), - ('\u{10591}', &['\u{10591}', '\u{105B8}']), - ('\u{10592}', &['\u{10592}', '\u{105B9}']), - ('\u{10592}', &['\u{10592}', '\u{105B9}']), - ('\u{10594}', &['\u{10594}', '\u{105BB}']), - ('\u{10594}', &['\u{10594}', '\u{105BB}']), - ('\u{10595}', &['\u{10595}', '\u{105BC}']), - ('\u{10595}', &['\u{10595}', '\u{105BC}']), - ('\u{10C80}', &['\u{10C80}', '\u{10CC0}']), - ('\u{10C80}', &['\u{10C80}', '\u{10CC0}']), - ('\u{10C81}', &['\u{10C81}', '\u{10CC1}']), - ('\u{10C81}', &['\u{10C81}', '\u{10CC1}']), - ('\u{10C82}', &['\u{10C82}', '\u{10CC2}']), - ('\u{10C82}', &['\u{10C82}', '\u{10CC2}']), - ('\u{10C83}', &['\u{10C83}', '\u{10CC3}']), - ('\u{10C83}', &['\u{10C83}', '\u{10CC3}']), - ('\u{10C84}', &['\u{10C84}', '\u{10CC4}']), - ('\u{10C84}', &['\u{10C84}', '\u{10CC4}']), - ('\u{10C85}', &['\u{10C85}', '\u{10CC5}']), - ('\u{10C85}', &['\u{10C85}', '\u{10CC5}']), - ('\u{10C86}', &['\u{10C86}', '\u{10CC6}']), - ('\u{10C86}', &['\u{10C86}', '\u{10CC6}']), - ('\u{10C87}', &['\u{10C87}', '\u{10CC7}']), - ('\u{10C87}', &['\u{10C87}', '\u{10CC7}']), - ('\u{10C88}', &['\u{10C88}', '\u{10CC8}']), - ('\u{10C88}', &['\u{10C88}', '\u{10CC8}']), - ('\u{10C89}', &['\u{10C89}', '\u{10CC9}']), - ('\u{10C89}', &['\u{10C89}', '\u{10CC9}']), - ('\u{10C8A}', &['\u{10C8A}', '\u{10CCA}']), - ('\u{10C8A}', &['\u{10C8A}', '\u{10CCA}']), - ('\u{10C8B}', &['\u{10C8B}', '\u{10CCB}']), - ('\u{10C8B}', &['\u{10C8B}', '\u{10CCB}']), - ('\u{10C8C}', &['\u{10C8C}', '\u{10CCC}']), - ('\u{10C8C}', &['\u{10C8C}', '\u{10CCC}']), - ('\u{10C8D}', &['\u{10C8D}', '\u{10CCD}']), - ('\u{10C8D}', &['\u{10C8D}', '\u{10CCD}']), - ('\u{10C8E}', &['\u{10C8E}', '\u{10CCE}']), - ('\u{10C8E}', &['\u{10C8E}', '\u{10CCE}']), - ('\u{10C8F}', &['\u{10C8F}', '\u{10CCF}']), - ('\u{10C8F}', &['\u{10C8F}', '\u{10CCF}']), - ('\u{10C90}', &['\u{10C90}', '\u{10CD0}']), - ('\u{10C90}', &['\u{10C90}', '\u{10CD0}']), - ('\u{10C91}', &['\u{10C91}', '\u{10CD1}']), - ('\u{10C91}', &['\u{10C91}', '\u{10CD1}']), - ('\u{10C92}', &['\u{10C92}', '\u{10CD2}']), - ('\u{10C92}', &['\u{10C92}', '\u{10CD2}']), - ('\u{10C93}', &['\u{10C93}', '\u{10CD3}']), - ('\u{10C93}', &['\u{10C93}', '\u{10CD3}']), - ('\u{10C94}', &['\u{10C94}', '\u{10CD4}']), - ('\u{10C94}', &['\u{10C94}', '\u{10CD4}']), - ('\u{10C95}', &['\u{10C95}', '\u{10CD5}']), - ('\u{10C95}', &['\u{10C95}', '\u{10CD5}']), - ('\u{10C96}', &['\u{10C96}', '\u{10CD6}']), - ('\u{10C96}', &['\u{10C96}', '\u{10CD6}']), - ('\u{10C97}', &['\u{10C97}', '\u{10CD7}']), - ('\u{10C97}', &['\u{10C97}', '\u{10CD7}']), - ('\u{10C98}', &['\u{10C98}', '\u{10CD8}']), - ('\u{10C98}', &['\u{10C98}', '\u{10CD8}']), - ('\u{10C99}', &['\u{10C99}', '\u{10CD9}']), - ('\u{10C99}', &['\u{10C99}', '\u{10CD9}']), - ('\u{10C9A}', &['\u{10C9A}', '\u{10CDA}']), - ('\u{10C9A}', &['\u{10C9A}', '\u{10CDA}']), - ('\u{10C9B}', &['\u{10C9B}', '\u{10CDB}']), - ('\u{10C9B}', &['\u{10C9B}', '\u{10CDB}']), - ('\u{10C9C}', &['\u{10C9C}', '\u{10CDC}']), - ('\u{10C9C}', &['\u{10C9C}', '\u{10CDC}']), - ('\u{10C9D}', &['\u{10C9D}', '\u{10CDD}']), - ('\u{10C9D}', &['\u{10C9D}', '\u{10CDD}']), - ('\u{10C9E}', &['\u{10C9E}', '\u{10CDE}']), - ('\u{10C9E}', &['\u{10C9E}', '\u{10CDE}']), - ('\u{10C9F}', &['\u{10C9F}', '\u{10CDF}']), - ('\u{10C9F}', &['\u{10C9F}', '\u{10CDF}']), - ('\u{10CA0}', &['\u{10CA0}', '\u{10CE0}']), - ('\u{10CA0}', &['\u{10CA0}', '\u{10CE0}']), - ('\u{10CA1}', &['\u{10CA1}', '\u{10CE1}']), - ('\u{10CA1}', &['\u{10CA1}', '\u{10CE1}']), - ('\u{10CA2}', &['\u{10CA2}', '\u{10CE2}']), - ('\u{10CA2}', &['\u{10CA2}', '\u{10CE2}']), - ('\u{10CA3}', &['\u{10CA3}', '\u{10CE3}']), - ('\u{10CA3}', &['\u{10CA3}', '\u{10CE3}']), - ('\u{10CA4}', &['\u{10CA4}', '\u{10CE4}']), - ('\u{10CA4}', &['\u{10CA4}', '\u{10CE4}']), - ('\u{10CA5}', &['\u{10CA5}', '\u{10CE5}']), - ('\u{10CA5}', &['\u{10CA5}', '\u{10CE5}']), - ('\u{10CA6}', &['\u{10CA6}', '\u{10CE6}']), - ('\u{10CA6}', &['\u{10CA6}', '\u{10CE6}']), - ('\u{10CA7}', &['\u{10CA7}', '\u{10CE7}']), - ('\u{10CA7}', &['\u{10CA7}', '\u{10CE7}']), - ('\u{10CA8}', &['\u{10CA8}', '\u{10CE8}']), - ('\u{10CA8}', &['\u{10CA8}', '\u{10CE8}']), - ('\u{10CA9}', &['\u{10CA9}', '\u{10CE9}']), - ('\u{10CA9}', &['\u{10CA9}', '\u{10CE9}']), - ('\u{10CAA}', &['\u{10CAA}', '\u{10CEA}']), - ('\u{10CAA}', &['\u{10CAA}', '\u{10CEA}']), - ('\u{10CAB}', &['\u{10CAB}', '\u{10CEB}']), - ('\u{10CAB}', &['\u{10CAB}', '\u{10CEB}']), - ('\u{10CAC}', &['\u{10CAC}', '\u{10CEC}']), - ('\u{10CAC}', &['\u{10CAC}', '\u{10CEC}']), - ('\u{10CAD}', &['\u{10CAD}', '\u{10CED}']), - ('\u{10CAD}', &['\u{10CAD}', '\u{10CED}']), - ('\u{10CAE}', &['\u{10CAE}', '\u{10CEE}']), - ('\u{10CAE}', &['\u{10CAE}', '\u{10CEE}']), - ('\u{10CAF}', &['\u{10CAF}', '\u{10CEF}']), - ('\u{10CAF}', &['\u{10CAF}', '\u{10CEF}']), - ('\u{10CB0}', &['\u{10CB0}', '\u{10CF0}']), - ('\u{10CB0}', &['\u{10CB0}', '\u{10CF0}']), - ('\u{10CB1}', &['\u{10CB1}', '\u{10CF1}']), - ('\u{10CB1}', &['\u{10CB1}', '\u{10CF1}']), - ('\u{10CB2}', &['\u{10CB2}', '\u{10CF2}']), - ('\u{10CB2}', &['\u{10CB2}', '\u{10CF2}']), - ('\u{118A0}', &['\u{118A0}', '\u{118C0}']), - ('\u{118A0}', &['\u{118A0}', '\u{118C0}']), - ('\u{118A1}', &['\u{118A1}', '\u{118C1}']), - ('\u{118A1}', &['\u{118A1}', '\u{118C1}']), - ('\u{118A2}', &['\u{118A2}', '\u{118C2}']), - ('\u{118A2}', &['\u{118A2}', '\u{118C2}']), - ('\u{118A3}', &['\u{118A3}', '\u{118C3}']), - ('\u{118A3}', &['\u{118A3}', '\u{118C3}']), - ('\u{118A4}', &['\u{118A4}', '\u{118C4}']), - ('\u{118A4}', &['\u{118A4}', '\u{118C4}']), - ('\u{118A5}', &['\u{118A5}', '\u{118C5}']), - ('\u{118A5}', &['\u{118A5}', '\u{118C5}']), - ('\u{118A6}', &['\u{118A6}', '\u{118C6}']), - ('\u{118A6}', &['\u{118A6}', '\u{118C6}']), - ('\u{118A7}', &['\u{118A7}', '\u{118C7}']), - ('\u{118A7}', &['\u{118A7}', '\u{118C7}']), - ('\u{118A8}', &['\u{118A8}', '\u{118C8}']), - ('\u{118A8}', &['\u{118A8}', '\u{118C8}']), - ('\u{118A9}', &['\u{118A9}', '\u{118C9}']), - ('\u{118A9}', &['\u{118A9}', '\u{118C9}']), - ('\u{118AA}', &['\u{118AA}', '\u{118CA}']), - ('\u{118AA}', &['\u{118AA}', '\u{118CA}']), - ('\u{118AB}', &['\u{118AB}', '\u{118CB}']), - ('\u{118AB}', &['\u{118AB}', '\u{118CB}']), - ('\u{118AC}', &['\u{118AC}', '\u{118CC}']), - ('\u{118AC}', &['\u{118AC}', '\u{118CC}']), - ('\u{118AD}', &['\u{118AD}', '\u{118CD}']), - ('\u{118AD}', &['\u{118AD}', '\u{118CD}']), - ('\u{118AE}', &['\u{118AE}', '\u{118CE}']), - ('\u{118AE}', &['\u{118AE}', '\u{118CE}']), - ('\u{118AF}', &['\u{118AF}', '\u{118CF}']), - ('\u{118AF}', &['\u{118AF}', '\u{118CF}']), - ('\u{118B0}', &['\u{118B0}', '\u{118D0}']), - ('\u{118B0}', &['\u{118B0}', '\u{118D0}']), - ('\u{118B1}', &['\u{118B1}', '\u{118D1}']), - ('\u{118B1}', &['\u{118B1}', '\u{118D1}']), - ('\u{118B2}', &['\u{118B2}', '\u{118D2}']), - ('\u{118B2}', &['\u{118B2}', '\u{118D2}']), - ('\u{118B3}', &['\u{118B3}', '\u{118D3}']), - ('\u{118B3}', &['\u{118B3}', '\u{118D3}']), - ('\u{118B4}', &['\u{118B4}', '\u{118D4}']), - ('\u{118B4}', &['\u{118B4}', '\u{118D4}']), - ('\u{118B5}', &['\u{118B5}', '\u{118D5}']), - ('\u{118B5}', &['\u{118B5}', '\u{118D5}']), - ('\u{118B6}', &['\u{118B6}', '\u{118D6}']), - ('\u{118B6}', &['\u{118B6}', '\u{118D6}']), - ('\u{118B7}', &['\u{118B7}', '\u{118D7}']), - ('\u{118B7}', &['\u{118B7}', '\u{118D7}']), - ('\u{118B8}', &['\u{118B8}', '\u{118D8}']), - ('\u{118B8}', &['\u{118B8}', '\u{118D8}']), - ('\u{118B9}', &['\u{118B9}', '\u{118D9}']), - ('\u{118B9}', &['\u{118B9}', '\u{118D9}']), - ('\u{118BA}', &['\u{118BA}', '\u{118DA}']), - ('\u{118BA}', &['\u{118BA}', '\u{118DA}']), - ('\u{118BB}', &['\u{118BB}', '\u{118DB}']), - ('\u{118BB}', &['\u{118BB}', '\u{118DB}']), - ('\u{118BC}', &['\u{118BC}', '\u{118DC}']), - ('\u{118BC}', &['\u{118BC}', '\u{118DC}']), - ('\u{118BD}', &['\u{118BD}', '\u{118DD}']), - ('\u{118BD}', &['\u{118BD}', '\u{118DD}']), - ('\u{118BE}', &['\u{118BE}', '\u{118DE}']), - ('\u{118BE}', &['\u{118BE}', '\u{118DE}']), - ('\u{118BF}', &['\u{118BF}', '\u{118DF}']), - ('\u{118BF}', &['\u{118BF}', '\u{118DF}']), - ('\u{16E40}', &['\u{16E40}', '\u{16E60}']), - ('\u{16E40}', &['\u{16E40}', '\u{16E60}']), - ('\u{16E41}', &['\u{16E41}', '\u{16E61}']), - ('\u{16E41}', &['\u{16E41}', '\u{16E61}']), - ('\u{16E42}', &['\u{16E42}', '\u{16E62}']), - ('\u{16E42}', &['\u{16E42}', '\u{16E62}']), - ('\u{16E43}', &['\u{16E43}', '\u{16E63}']), - ('\u{16E43}', &['\u{16E43}', '\u{16E63}']), - ('\u{16E44}', &['\u{16E44}', '\u{16E64}']), - ('\u{16E44}', &['\u{16E44}', '\u{16E64}']), - ('\u{16E45}', &['\u{16E45}', '\u{16E65}']), - ('\u{16E45}', &['\u{16E45}', '\u{16E65}']), - ('\u{16E46}', &['\u{16E46}', '\u{16E66}']), - ('\u{16E46}', &['\u{16E46}', '\u{16E66}']), - ('\u{16E47}', &['\u{16E47}', '\u{16E67}']), - ('\u{16E47}', &['\u{16E47}', '\u{16E67}']), - ('\u{16E48}', &['\u{16E48}', '\u{16E68}']), - ('\u{16E48}', &['\u{16E48}', '\u{16E68}']), - ('\u{16E49}', &['\u{16E49}', '\u{16E69}']), - ('\u{16E49}', &['\u{16E49}', '\u{16E69}']), - ('\u{16E4A}', &['\u{16E4A}', '\u{16E6A}']), - ('\u{16E4A}', &['\u{16E4A}', '\u{16E6A}']), - ('\u{16E4B}', &['\u{16E4B}', '\u{16E6B}']), - ('\u{16E4B}', &['\u{16E4B}', '\u{16E6B}']), - ('\u{16E4C}', &['\u{16E4C}', '\u{16E6C}']), - ('\u{16E4C}', &['\u{16E4C}', '\u{16E6C}']), - ('\u{16E4D}', &['\u{16E4D}', '\u{16E6D}']), - ('\u{16E4D}', &['\u{16E4D}', '\u{16E6D}']), - ('\u{16E4E}', &['\u{16E4E}', '\u{16E6E}']), - ('\u{16E4E}', &['\u{16E4E}', '\u{16E6E}']), - ('\u{16E4F}', &['\u{16E4F}', '\u{16E6F}']), - ('\u{16E4F}', &['\u{16E4F}', '\u{16E6F}']), - ('\u{16E50}', &['\u{16E50}', '\u{16E70}']), - ('\u{16E50}', &['\u{16E50}', '\u{16E70}']), - ('\u{16E51}', &['\u{16E51}', '\u{16E71}']), - ('\u{16E51}', &['\u{16E51}', '\u{16E71}']), - ('\u{16E52}', &['\u{16E52}', '\u{16E72}']), - ('\u{16E52}', &['\u{16E52}', '\u{16E72}']), - ('\u{16E53}', &['\u{16E53}', '\u{16E73}']), - ('\u{16E53}', &['\u{16E53}', '\u{16E73}']), - ('\u{16E54}', &['\u{16E54}', '\u{16E74}']), - ('\u{16E54}', &['\u{16E54}', '\u{16E74}']), - ('\u{16E55}', &['\u{16E55}', '\u{16E75}']), - ('\u{16E55}', &['\u{16E55}', '\u{16E75}']), - ('\u{16E56}', &['\u{16E56}', '\u{16E76}']), - ('\u{16E56}', &['\u{16E56}', '\u{16E76}']), - ('\u{16E57}', &['\u{16E57}', '\u{16E77}']), - ('\u{16E57}', &['\u{16E57}', '\u{16E77}']), - ('\u{16E58}', &['\u{16E58}', '\u{16E78}']), - ('\u{16E58}', &['\u{16E58}', '\u{16E78}']), - ('\u{16E59}', &['\u{16E59}', '\u{16E79}']), - ('\u{16E59}', &['\u{16E59}', '\u{16E79}']), - ('\u{16E5A}', &['\u{16E5A}', '\u{16E7A}']), - ('\u{16E5A}', &['\u{16E5A}', '\u{16E7A}']), - ('\u{16E5B}', &['\u{16E5B}', '\u{16E7B}']), - ('\u{16E5B}', &['\u{16E5B}', '\u{16E7B}']), - ('\u{16E5C}', &['\u{16E5C}', '\u{16E7C}']), - ('\u{16E5C}', &['\u{16E5C}', '\u{16E7C}']), - ('\u{16E5D}', &['\u{16E5D}', '\u{16E7D}']), - ('\u{16E5D}', &['\u{16E5D}', '\u{16E7D}']), - ('\u{16E5E}', &['\u{16E5E}', '\u{16E7E}']), - ('\u{16E5E}', &['\u{16E5E}', '\u{16E7E}']), - ('\u{16E5F}', &['\u{16E5F}', '\u{16E7F}']), - ('\u{16E5F}', &['\u{16E5F}', '\u{16E7F}']), - ('\u{1E900}', &['\u{1E900}', '\u{1E922}']), - ('\u{1E900}', &['\u{1E900}', '\u{1E922}']), - ('\u{1E901}', &['\u{1E901}', '\u{1E923}']), - ('\u{1E901}', &['\u{1E901}', '\u{1E923}']), - ('\u{1E902}', &['\u{1E902}', '\u{1E924}']), - ('\u{1E902}', &['\u{1E902}', '\u{1E924}']), - ('\u{1E903}', &['\u{1E903}', '\u{1E925}']), - ('\u{1E903}', &['\u{1E903}', '\u{1E925}']), - ('\u{1E904}', &['\u{1E904}', '\u{1E926}']), - ('\u{1E904}', &['\u{1E904}', '\u{1E926}']), - ('\u{1E905}', &['\u{1E905}', '\u{1E927}']), - ('\u{1E905}', &['\u{1E905}', '\u{1E927}']), - ('\u{1E906}', &['\u{1E906}', '\u{1E928}']), - ('\u{1E906}', &['\u{1E906}', '\u{1E928}']), - ('\u{1E907}', &['\u{1E907}', '\u{1E929}']), - ('\u{1E907}', &['\u{1E907}', '\u{1E929}']), - ('\u{1E908}', &['\u{1E908}', '\u{1E92A}']), - ('\u{1E908}', &['\u{1E908}', '\u{1E92A}']), - ('\u{1E909}', &['\u{1E909}', '\u{1E92B}']), - ('\u{1E909}', &['\u{1E909}', '\u{1E92B}']), - ('\u{1E90A}', &['\u{1E90A}', '\u{1E92C}']), - ('\u{1E90A}', &['\u{1E90A}', '\u{1E92C}']), - ('\u{1E90B}', &['\u{1E90B}', '\u{1E92D}']), - ('\u{1E90B}', &['\u{1E90B}', '\u{1E92D}']), - ('\u{1E90C}', &['\u{1E90C}', '\u{1E92E}']), - ('\u{1E90C}', &['\u{1E90C}', '\u{1E92E}']), - ('\u{1E90D}', &['\u{1E90D}', '\u{1E92F}']), - ('\u{1E90D}', &['\u{1E90D}', '\u{1E92F}']), - ('\u{1E90E}', &['\u{1E90E}', '\u{1E930}']), - ('\u{1E90E}', &['\u{1E90E}', '\u{1E930}']), - ('\u{1E90F}', &['\u{1E90F}', '\u{1E931}']), - ('\u{1E90F}', &['\u{1E90F}', '\u{1E931}']), - ('\u{1E910}', &['\u{1E910}', '\u{1E932}']), - ('\u{1E910}', &['\u{1E910}', '\u{1E932}']), - ('\u{1E911}', &['\u{1E911}', '\u{1E933}']), - ('\u{1E911}', &['\u{1E911}', '\u{1E933}']), - ('\u{1E912}', &['\u{1E912}', '\u{1E934}']), - ('\u{1E912}', &['\u{1E912}', '\u{1E934}']), - ('\u{1E913}', &['\u{1E913}', '\u{1E935}']), - ('\u{1E913}', &['\u{1E913}', '\u{1E935}']), - ('\u{1E914}', &['\u{1E914}', '\u{1E936}']), - ('\u{1E914}', &['\u{1E914}', '\u{1E936}']), - ('\u{1E915}', &['\u{1E915}', '\u{1E937}']), - ('\u{1E915}', &['\u{1E915}', '\u{1E937}']), - ('\u{1E916}', &['\u{1E916}', '\u{1E938}']), - ('\u{1E916}', &['\u{1E916}', '\u{1E938}']), - ('\u{1E917}', &['\u{1E917}', '\u{1E939}']), - ('\u{1E917}', &['\u{1E917}', '\u{1E939}']), - ('\u{1E918}', &['\u{1E918}', '\u{1E93A}']), - ('\u{1E918}', &['\u{1E918}', '\u{1E93A}']), - ('\u{1E919}', &['\u{1E919}', '\u{1E93B}']), - ('\u{1E919}', &['\u{1E919}', '\u{1E93B}']), - ('\u{1E91A}', &['\u{1E91A}', '\u{1E93C}']), - ('\u{1E91A}', &['\u{1E91A}', '\u{1E93C}']), - ('\u{1E91B}', &['\u{1E91B}', '\u{1E93D}']), - ('\u{1E91B}', &['\u{1E91B}', '\u{1E93D}']), - ('\u{1E91C}', &['\u{1E91C}', '\u{1E93E}']), - ('\u{1E91C}', &['\u{1E91C}', '\u{1E93E}']), - ('\u{1E91D}', &['\u{1E91D}', '\u{1E93F}']), - ('\u{1E91D}', &['\u{1E91D}', '\u{1E93F}']), - ('\u{1E91E}', &['\u{1E91E}', '\u{1E940}']), - ('\u{1E91E}', &['\u{1E91E}', '\u{1E940}']), - ('\u{1E91F}', &['\u{1E91F}', '\u{1E941}']), - ('\u{1E91F}', &['\u{1E91F}', '\u{1E941}']), - ('\u{1E920}', &['\u{1E920}', '\u{1E942}']), - ('\u{1E920}', &['\u{1E920}', '\u{1E942}']), - ('\u{1E921}', &['\u{1E921}', '\u{1E943}']), - ('\u{1E921}', &['\u{1E921}', '\u{1E943}']), -]; diff --git a/vendor/makepad/libs/regex/src/utf8.rs b/vendor/makepad/libs/regex/src/utf8.rs deleted file mode 100644 index f3878fc..0000000 --- a/vendor/makepad/libs/regex/src/utf8.rs +++ /dev/null @@ -1,217 +0,0 @@ -use super::range::Range; - -const MAX_LEN: usize = 4; - -#[derive(Debug)] -pub struct ByteRangeSeqsAllocs { - range_stack: Vec>, -} - -impl ByteRangeSeqsAllocs { - pub fn new() -> Self { - Self { - range_stack: Vec::new(), - } - } -} - -// An iterator over the sequences of UTF-8 byte ranges that are equivalent to a given range of -// Unicode scalar values. -// -// This struct is returned by the `byte_range_seqs` function. See its documentation for more. -#[derive(Debug)] -pub struct ByteRangeSeqs<'a> { - range_stack: &'a mut Vec>, -} - -impl<'a> Iterator for ByteRangeSeqs<'a> { - type Item = ByteRangeSeq; - - fn next(&mut self) -> Option { - let mut range = self.range_stack.pop()?; - 'LOOP: loop { - // Step 1: If the range contains only ASCII code points, return early. - if range.end <= 0x7F { - return Some(ByteRangeSeq::One([Range::new( - range.start as u8, - range.end as u8, - )])); - } - - // Step 2: Ensure that the range does not contain any surrogate code points. - if range.start < 0xE000 && range.end > 0xD7FF { - self.range_stack.push(Range::new(0xE000, range.end)); - range.end = 0xD7FF; - continue 'LOOP; - } - - // Step 3: Ensure that all scalar values in the range can be encoded as a sequence - // of UTF-8 bytes with the same length. - for index in 1..MAX_LEN { - let max = max_scalar(index); - if range.start <= max && max < range.end { - self.range_stack.push(Range::new(max + 1, range.end)); - range.end = max; - continue 'LOOP; - } - } - - // Step 4: Ensure that all scalar values in the range can be encoded as a single - // sequence of UTF-8 byte ranges. - for index in 1..MAX_LEN { - let mask = (1 << (6 * index)) - 1; - if range.start & !mask != range.end & !mask { - if range.start & mask != 0 { - self.range_stack - .push(Range::new((range.start | mask) + 1, range.end)); - range.end = range.start | mask; - continue 'LOOP; - } - if range.end & mask != mask { - self.range_stack - .push(Range::new(range.end & !mask, range.end)); - range.end = (range.end & !mask) - 1; - continue 'LOOP; - } - } - } - - // Step 5: Encode all scalar values in the range as a sequence of UTF-8 bytes. - let mut start = [0; MAX_LEN]; - let start = char::from_u32(range.start) - .unwrap() - .encode_utf8(&mut start) - .as_bytes(); - let mut end = [0; MAX_LEN]; - let end = char::from_u32(range.end) - .unwrap() - .encode_utf8(&mut end) - .as_bytes(); - assert_eq!(start.len(), end.len()); - return Some(match start.len() { - 2 => { - ByteRangeSeq::Two([Range::new(start[0], end[0]), Range::new(start[1], end[1])]) - } - 3 => ByteRangeSeq::Three([ - Range::new(start[0], end[0]), - Range::new(start[1], end[1]), - Range::new(start[2], end[2]), - ]), - 4 => ByteRangeSeq::Four([ - Range::new(start[0], end[0]), - Range::new(start[1], end[1]), - Range::new(start[2], end[2]), - Range::new(start[3], end[3]), - ]), - _ => panic!(), - }); - } - } -} - -/// A sequence of UTF-8 byte ranges. -#[derive(Debug, Eq, PartialEq)] -pub enum ByteRangeSeq { - One([Range; 1]), - Two([Range; 2]), - Three([Range; 3]), - Four([Range; 4]), -} - -impl ByteRangeSeq { - /// Returns a slice of the ranges in the `ByteRangeSeq`. - pub fn as_slice(&self) -> &[Range] { - match self { - Self::One(seq) => seq.as_slice(), - Self::Two(seq) => seq.as_slice(), - Self::Three(seq) => seq.as_slice(), - Self::Four(seq) => seq.as_slice(), - } - } - - /// Reverses the order of the ranges in the `ByteRangeSeq`, in place. - pub fn reverse(&mut self) { - match self { - Self::One(_) => {} - Self::Two(seq) => seq.reverse(), - Self::Three(seq) => seq.reverse(), - Self::Four(seq) => seq.reverse(), - } - } -} - -/// Returns an iterator over the sequences of UTF-8 byte ranges that are equivalent to the given -/// range of Unicode scalar values. -pub fn byte_range_seqs(range: Range, allocs: &mut ByteRangeSeqsAllocs) -> ByteRangeSeqs<'_> { - let range_stack = &mut allocs.range_stack; - range_stack.clear(); - range_stack.push(Range::new(range.start as u32, range.end as u32)); - ByteRangeSeqs { range_stack } -} - -/// Returns the maximum scalar value that can be encoded with `len` UTF-8 bytes. -fn max_scalar(len: usize) -> u32 { - match len { - 1 => 0x7F, - 2 => 0x7FF, - 3 => 0xFFFF, - 4 => 0x10FFFF, - _ => panic!("invalid number of bytes"), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn any() { - let mut cache = ByteRangeSeqsAllocs::new(); - assert_eq!( - super::byte_range_seqs(Range::new('\u{0}', '\u{10FFFF}'), &mut cache) - .collect::>(), - vec![ - ByteRangeSeq::One([Range::new(0x00, 0x7F)]), - ByteRangeSeq::Two([Range::new(0xC2, 0xDF), Range::new(0x80, 0xBF)]), - ByteRangeSeq::Three([ - Range::new(0xE0, 0xE0), - Range::new(0xA0, 0xBF), - Range::new(0x80, 0xBF) - ]), - ByteRangeSeq::Three([ - Range::new(0xE1, 0xEC), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF) - ]), - ByteRangeSeq::Three([ - Range::new(0xED, 0xED), - Range::new(0x80, 0x9F), - Range::new(0x80, 0xBF) - ]), - ByteRangeSeq::Three([ - Range::new(0xEE, 0xEF), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF) - ]), - ByteRangeSeq::Four([ - Range::new(0xF0, 0xF0), - Range::new(0x90, 0xBF), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF), - ]), - ByteRangeSeq::Four([ - Range::new(0xF1, 0xF3), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF), - ]), - ByteRangeSeq::Four([ - Range::new(0xF4, 0xF4), - Range::new(0x80, 0x8F), - Range::new(0x80, 0xBF), - Range::new(0x80, 0xBF), - ]) - ] - ); - } -} diff --git a/vendor/makepad/libs/smallvec/Cargo.toml b/vendor/makepad/libs/smallvec/Cargo.toml deleted file mode 100644 index d8de79c..0000000 --- a/vendor/makepad/libs/smallvec/Cargo.toml +++ /dev/null @@ -1,67 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -name = "smallvec" -version = "1.15.1" -authors = ["The Servo Project Developers"] -build = false -autolib = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "'Small vector' optimization: store up to a small number of items on the stack" -documentation = "https://docs.rs/smallvec/" -readme = "README.md" -keywords = [ - "small", - "vec", - "vector", - "stack", - "no_std", -] -categories = ["data-structures"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/servo/rust-smallvec" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", - "--generate-link-to-definition", -] - -[features] -const_generics = [] -const_new = ["const_generics"] -debugger_visualizer = [] -drain_filter = [] -drain_keep_rest = ["drain_filter"] - -may_dangle = [] -specialization = [] -union = [] -write = [] - -[lints.rust.unexpected_cfgs] -level = "allow" - -[lib] -name = "smallvec" -path = "src/lib.rs" - -[dependencies.serde] -version = "1" -optional = true -default-features = false diff --git a/vendor/makepad/libs/smallvec/LICENSE-APACHE b/vendor/makepad/libs/smallvec/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/vendor/makepad/libs/smallvec/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/makepad/libs/smallvec/LICENSE-MIT b/vendor/makepad/libs/smallvec/LICENSE-MIT deleted file mode 100644 index 9729c12..0000000 --- a/vendor/makepad/libs/smallvec/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2018 The Servo Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/makepad/libs/smallvec/debug_metadata/smallvec.natvis b/vendor/makepad/libs/smallvec/debug_metadata/smallvec.natvis deleted file mode 100644 index 8731860..0000000 --- a/vendor/makepad/libs/smallvec/debug_metadata/smallvec.natvis +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - {{ len={len()} is_inline={is_inline()} }} - - is_inline() ? $T2 : capacity - len() - data_ptr() - - - len() - data_ptr() - - - - - - - - - {{ len={len()} is_inline={is_inline()} }} - - is_inline() ? $T2 : capacity - len() - - - len() - data_ptr() - - - - \ No newline at end of file diff --git a/vendor/makepad/libs/smallvec/src/arbitrary.rs b/vendor/makepad/libs/smallvec/src/arbitrary.rs deleted file mode 100644 index cbdfcb0..0000000 --- a/vendor/makepad/libs/smallvec/src/arbitrary.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{Array, SmallVec}; -use arbitrary::{Arbitrary, Unstructured}; - -impl<'a, A: Array> Arbitrary<'a> for SmallVec -where - ::Item: Arbitrary<'a>, -{ - fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { - u.arbitrary_iter()?.collect() - } - - fn arbitrary_take_rest(u: Unstructured<'a>) -> arbitrary::Result { - u.arbitrary_take_rest_iter()?.collect() - } - - fn size_hint(depth: usize) -> (usize, Option) { - arbitrary::size_hint::and(::size_hint(depth), (0, None)) - } -} diff --git a/vendor/makepad/libs/smallvec/src/lib.rs b/vendor/makepad/libs/smallvec/src/lib.rs deleted file mode 100644 index efca8a6..0000000 --- a/vendor/makepad/libs/smallvec/src/lib.rs +++ /dev/null @@ -1,2619 +0,0 @@ -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Small vectors in various sizes. These store a certain number of elements inline, and fall back -//! to the heap for larger allocations. This can be a useful optimization for improving cache -//! locality and reducing allocator traffic for workloads that fit within the inline buffer. -//! -//! ## `no_std` support -//! -//! By default, `smallvec` does not depend on `std`. However, the optional -//! `write` feature implements the `std::io::Write` trait for vectors of `u8`. -//! When this feature is enabled, `smallvec` depends on `std`. -//! -//! ## Optional features -//! -//! ### `serde` -//! -//! When this optional dependency is enabled, `SmallVec` implements the `serde::Serialize` and -//! `serde::Deserialize` traits. -//! -//! ### `write` -//! -//! When this feature is enabled, `SmallVec<[u8; _]>` implements the `std::io::Write` trait. -//! This feature is not compatible with `#![no_std]` programs. -//! -//! ### `union` -//! -//! **This feature requires Rust 1.49.** -//! -//! When the `union` feature is enabled `smallvec` will track its state (inline or spilled) -//! without the use of an enum tag, reducing the size of the `smallvec` by one machine word. -//! This means that there is potentially no space overhead compared to `Vec`. -//! Note that `smallvec` can still be larger than `Vec` if the inline buffer is larger than two -//! machine words. -//! -//! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml. -//! Note that this feature requires Rust 1.49. -//! -//! Tracking issue: [rust-lang/rust#55149](https://github.com/rust-lang/rust/issues/55149) -//! -//! ### `const_generics` -//! -//! **This feature requires Rust 1.51.** -//! -//! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed -//! list of sizes. -//! -//! ### `const_new` -//! -//! **This feature requires Rust 1.51.** -//! -//! This feature exposes the functions [`SmallVec::new_const`], [`SmallVec::from_const`], and [`smallvec_inline`] which enables the `SmallVec` to be initialized from a const context. -//! For details, see the -//! [Rust Reference](https://doc.rust-lang.org/reference/const_eval.html#const-functions). -//! -//! ### `drain_filter` -//! -//! **This feature is unstable.** It may change to match the unstable `drain_filter` method in libstd. -//! -//! Enables the `drain_filter` method, which produces an iterator that calls a user-provided -//! closure to determine which elements of the vector to remove and yield from the iterator. -//! -//! ### `drain_keep_rest` -//! -//! **This feature is unstable.** It may change to match the unstable `drain_keep_rest` method in libstd. -//! -//! Enables the `DrainFilter::keep_rest` method. -//! -//! ### `specialization` -//! -//! **This feature is unstable and requires a nightly build of the Rust toolchain.** -//! -//! When this feature is enabled, `SmallVec::from(slice)` has improved performance for slices -//! of `Copy` types. (Without this feature, you can use `SmallVec::from_slice` to get optimal -//! performance for `Copy` types.) -//! -//! Tracking issue: [rust-lang/rust#31844](https://github.com/rust-lang/rust/issues/31844) -//! -//! ### `may_dangle` -//! -//! **This feature is unstable and requires a nightly build of the Rust toolchain.** -//! -//! This feature makes the Rust compiler less strict about use of vectors that contain borrowed -//! references. For details, see the -//! [Rustonomicon](https://doc.rust-lang.org/1.42.0/nomicon/dropck.html#an-escape-hatch). -//! -//! Tracking issue: [rust-lang/rust#34761](https://github.com/rust-lang/rust/issues/34761) - -#![no_std] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![cfg_attr(feature = "specialization", allow(incomplete_features))] -#![cfg_attr(feature = "specialization", feature(specialization))] -#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))] -#![cfg_attr( - feature = "debugger_visualizer", - feature(debugger_visualizer), - debugger_visualizer(natvis_file = "../debug_metadata/smallvec.natvis") -)] -#![deny(missing_docs)] - -#[doc(hidden)] -pub extern crate alloc; - -#[cfg(any(test, feature = "write"))] -extern crate std; - -#[cfg(test)] -mod tests; - -#[allow(deprecated)] -use alloc::alloc::{Layout, LayoutErr}; -use alloc::boxed::Box; -use alloc::{vec, vec::Vec}; -use core::borrow::{Borrow, BorrowMut}; -use core::cmp; -use core::fmt; -use core::hash::{Hash, Hasher}; -use core::hint::unreachable_unchecked; -use core::iter::{repeat, FromIterator, FusedIterator, IntoIterator}; -use core::mem; -use core::mem::MaybeUninit; -use core::ops::{self, Range, RangeBounds}; -use core::ptr::{self, NonNull}; -use core::slice::{self, SliceIndex}; - -#[cfg(feature = "malloc_size_of")] -use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps}; - -#[cfg(feature = "serde")] -use serde::{ - de::{Deserialize, Deserializer, SeqAccess, Visitor}, - ser::{Serialize, SerializeSeq, Serializer}, -}; - -#[cfg(feature = "serde")] -use core::marker::PhantomData; - -#[cfg(feature = "write")] -use std::io; - -#[cfg(feature = "drain_keep_rest")] -use core::mem::ManuallyDrop; - -/// Creates a [`SmallVec`] containing the arguments. -/// -/// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions. -/// There are two forms of this macro: -/// -/// - Create a [`SmallVec`] containing a given list of elements: -/// -/// ``` -/// # use smallvec::{smallvec, SmallVec}; -/// # fn main() { -/// let v: SmallVec<[_; 128]> = smallvec![1, 2, 3]; -/// assert_eq!(v[0], 1); -/// assert_eq!(v[1], 2); -/// assert_eq!(v[2], 3); -/// # } -/// ``` -/// -/// - Create a [`SmallVec`] from a given element and size: -/// -/// ``` -/// # use smallvec::{smallvec, SmallVec}; -/// # fn main() { -/// let v: SmallVec<[_; 0x8000]> = smallvec![1; 3]; -/// assert_eq!(v, SmallVec::from_buf([1, 1, 1])); -/// # } -/// ``` -/// -/// Note that unlike array expressions this syntax supports all elements -/// which implement [`Clone`] and the number of elements doesn't have to be -/// a constant. -/// -/// This will use `clone` to duplicate an expression, so one should be careful -/// using this with types having a nonstandard `Clone` implementation. For -/// example, `smallvec![Rc::new(1); 5]` will create a vector of five references -/// to the same boxed integer value, not five references pointing to independently -/// boxed integers. -#[macro_export] -macro_rules! smallvec { - // count helper: transform any expression into 1 - (@one $x:expr) => (1usize); - () => ( - $crate::SmallVec::new() - ); - ($elem:expr; $n:expr) => ({ - $crate::SmallVec::from_elem($elem, $n) - }); - ($($x:expr),+$(,)?) => ({ - let count = 0usize $(+ $crate::smallvec!(@one $x))+; - let mut vec = $crate::SmallVec::new(); - if count <= vec.inline_size() { - $(vec.push($x);)* - vec - } else { - $crate::SmallVec::from_vec($crate::alloc::vec![$($x,)+]) - } - }); -} - -/// Creates an inline [`SmallVec`] containing the arguments. This macro is enabled by the feature `const_new`. -/// -/// `smallvec_inline!` allows `SmallVec`s to be defined with the same syntax as array expressions in `const` contexts. -/// The inline storage `A` will always be an array of the size specified by the arguments. -/// There are two forms of this macro: -/// -/// - Create a [`SmallVec`] containing a given list of elements: -/// -/// ``` -/// # use smallvec::{smallvec_inline, SmallVec}; -/// # fn main() { -/// const V: SmallVec<[i32; 3]> = smallvec_inline![1, 2, 3]; -/// assert_eq!(V[0], 1); -/// assert_eq!(V[1], 2); -/// assert_eq!(V[2], 3); -/// # } -/// ``` -/// -/// - Create a [`SmallVec`] from a given element and size: -/// -/// ``` -/// # use smallvec::{smallvec_inline, SmallVec}; -/// # fn main() { -/// const V: SmallVec<[i32; 3]> = smallvec_inline![1; 3]; -/// assert_eq!(V, SmallVec::from_buf([1, 1, 1])); -/// # } -/// ``` -/// -/// Note that the behavior mimics that of array expressions, in contrast to [`smallvec`]. -#[cfg(feature = "const_new")] -#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] -#[macro_export] -macro_rules! smallvec_inline { - // count helper: transform any expression into 1 - (@one $x:expr) => (1usize); - ($elem:expr; $n:expr) => ({ - $crate::SmallVec::<[_; $n]>::from_const([$elem; $n]) - }); - ($($x:expr),+ $(,)?) => ({ - const N: usize = 0usize $(+ $crate::smallvec_inline!(@one $x))*; - $crate::SmallVec::<[_; N]>::from_const([$($x,)*]) - }); -} - -/// `panic!()` in debug builds, optimization hint in release. -#[cfg(not(feature = "union"))] -macro_rules! debug_unreachable { - () => { - debug_unreachable!("entered unreachable code") - }; - ($e:expr) => { - if cfg!(debug_assertions) { - panic!($e); - } else { - unreachable_unchecked(); - } - }; -} - -/// Trait to be implemented by a collection that can be extended from a slice -/// -/// ## Example -/// -/// ```rust -/// use smallvec::{ExtendFromSlice, SmallVec}; -/// -/// fn initialize>(v: &mut V) { -/// v.extend_from_slice(b"Test!"); -/// } -/// -/// let mut vec = Vec::new(); -/// initialize(&mut vec); -/// assert_eq!(&vec, b"Test!"); -/// -/// let mut small_vec = SmallVec::<[u8; 8]>::new(); -/// initialize(&mut small_vec); -/// assert_eq!(&small_vec as &[_], b"Test!"); -/// ``` -#[doc(hidden)] -#[deprecated] -pub trait ExtendFromSlice { - /// Extends a collection from a slice of its element type - fn extend_from_slice(&mut self, other: &[T]); -} - -#[allow(deprecated)] -impl ExtendFromSlice for Vec { - fn extend_from_slice(&mut self, other: &[T]) { - Vec::extend_from_slice(self, other) - } -} - -/// Error type for APIs with fallible heap allocation -#[derive(Debug)] -pub enum CollectionAllocErr { - /// Overflow `usize::MAX` or other error during size computation - CapacityOverflow, - /// The allocator return an error - AllocErr { - /// The layout that was passed to the allocator - layout: Layout, - }, -} - -impl fmt::Display for CollectionAllocErr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Allocation error: {:?}", self) - } -} - -#[allow(deprecated)] -impl From for CollectionAllocErr { - fn from(_: LayoutErr) -> Self { - CollectionAllocErr::CapacityOverflow - } -} - -fn infallible(result: Result) -> T { - match result { - Ok(x) => x, - Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), - Err(CollectionAllocErr::AllocErr { layout }) => alloc::alloc::handle_alloc_error(layout), - } -} - -/// FIXME: use `Layout::array` when we require a Rust version where it’s stable -/// -fn layout_array(n: usize) -> Result { - let size = mem::size_of::() - .checked_mul(n) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - let align = mem::align_of::(); - Layout::from_size_align(size, align).map_err(|_| CollectionAllocErr::CapacityOverflow) -} - -unsafe fn deallocate(ptr: NonNull, capacity: usize) { - // This unwrap should succeed since the same did when allocating. - let layout = layout_array::(capacity).unwrap(); - alloc::alloc::dealloc(ptr.as_ptr() as *mut u8, layout) -} - -/// An iterator that removes the items from a `SmallVec` and yields them by value. -/// -/// Returned from [`SmallVec::drain`][1]. -/// -/// [1]: struct.SmallVec.html#method.drain -pub struct Drain<'a, T: 'a + Array> { - tail_start: usize, - tail_len: usize, - iter: slice::Iter<'a, T::Item>, - vec: NonNull>, -} - -impl<'a, T: 'a + Array> fmt::Debug for Drain<'a, T> -where - T::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() - } -} - -unsafe impl<'a, T: Sync + Array> Sync for Drain<'a, T> {} -unsafe impl<'a, T: Send + Array> Send for Drain<'a, T> {} - -impl<'a, T: 'a + Array> Iterator for Drain<'a, T> { - type Item = T::Item; - - #[inline] - fn next(&mut self) -> Option { - self.iter - .next() - .map(|reference| unsafe { ptr::read(reference) }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter - .next_back() - .map(|reference| unsafe { ptr::read(reference) }) - } -} - -impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> { - #[inline] - fn len(&self) -> usize { - self.iter.len() - } -} - -impl<'a, T: Array> FusedIterator for Drain<'a, T> {} - -impl<'a, T: 'a + Array> Drop for Drain<'a, T> { - fn drop(&mut self) { - self.for_each(drop); - - if self.tail_len > 0 { - unsafe { - let source_vec = self.vec.as_mut(); - - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.tail_start; - if tail != start { - // as_mut_ptr creates a &mut, invalidating other pointers. - // This pattern avoids calling it with a pointer already present. - let ptr = source_vec.as_mut_ptr(); - let src = ptr.add(tail); - let dst = ptr.add(start); - ptr::copy(src, dst, self.tail_len); - } - source_vec.set_len(start + self.tail_len); - } - } - } -} - -#[cfg(feature = "drain_filter")] -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// Returned from [`SmallVec::drain_filter`][1]. -/// -/// [1]: struct.SmallVec.html#method.drain_filter -pub struct DrainFilter<'a, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - vec: &'a mut SmallVec, - /// The index of the item that will be inspected by the next call to `next`. - idx: usize, - /// The number of items that have been drained (removed) thus far. - del: usize, - /// The original length of `vec` prior to draining. - old_len: usize, - /// The filter test predicate. - pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `DrainFilter`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - panic_flag: bool, -} - -#[cfg(feature = "drain_filter")] -impl fmt::Debug for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, - T::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("DrainFilter") - .field(&self.vec.as_slice()) - .finish() - } -} - -#[cfg(feature = "drain_filter")] -impl Iterator for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - type Item = T::Item; - - fn next(&mut self) -> Option { - unsafe { - while self.idx < self.old_len { - let i = self.idx; - let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; - let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const Self::Item = &v[i]; - let dst: *mut Self::Item = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); - } - } - None - } - } - - fn size_hint(&self) -> (usize, Option) { - (0, Some(self.old_len - self.idx)) - } -} - -#[cfg(feature = "drain_filter")] -impl Drop for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F> - where - F: FnMut(&mut T::Item) -> bool, - T: Array, - { - drain: &'b mut DrainFilter<'a, T, F>, - } - - impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F> - where - F: FnMut(&mut T::Item) -> bool, - T: Array, - { - fn drop(&mut self) { - unsafe { - if self.drain.idx < self.drain.old_len && self.drain.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. - let ptr = self.drain.vec.as_mut_ptr(); - let src = ptr.add(self.drain.idx); - let dst = src.sub(self.drain.del); - let tail_len = self.drain.old_len - self.drain.idx; - src.copy_to(dst, tail_len); - } - self.drain.vec.set_len(self.drain.old_len - self.drain.del); - } - } - } - - let backshift = BackshiftOnDrop { drain: self }; - - // Attempt to consume any remaining elements if the filter predicate - // has not yet panicked. We'll backshift any remaining elements - // whether we've already panicked or if the consumption here panics. - if !backshift.drain.panic_flag { - backshift.drain.for_each(drop); - } - } -} - -#[cfg(feature = "drain_keep_rest")] -impl DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - /// Keep unyielded elements in the source `Vec`. - /// - /// # Examples - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// - /// let mut vec: SmallVec<[char; 2]> = smallvec!['a', 'b', 'c']; - /// let mut drain = vec.drain_filter(|_| true); - /// - /// assert_eq!(drain.next().unwrap(), 'a'); - /// - /// // This call keeps 'b' and 'c' in the vec. - /// drain.keep_rest(); - /// - /// // If we wouldn't call `keep_rest()`, - /// // `vec` would be empty. - /// assert_eq!(vec, SmallVec::<[char; 2]>::from_slice(&['b', 'c'])); - /// ``` - pub fn keep_rest(self) { - // At this moment layout looks like this: - // - // _____________________/-- old_len - // / \ - // [kept] [yielded] [tail] - // \_______/ ^-- idx - // \-- del - // - // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`) - // - // 1. Move [tail] after [kept] - // 2. Update length of the original vec to `old_len - del` - // a. In case of ZST, this is the only thing we want to do - // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do - let mut this = ManuallyDrop::new(self); - - unsafe { - // ZSTs have no identity, so we don't need to move them around. - let needs_move = mem::size_of::() != 0; - - if needs_move && this.idx < this.old_len && this.del > 0 { - let ptr = this.vec.as_mut_ptr(); - let src = ptr.add(this.idx); - let dst = src.sub(this.del); - let tail_len = this.old_len - this.idx; - src.copy_to(dst, tail_len); - } - - let new_len = this.old_len - this.del; - this.vec.set_len(new_len); - } - } -} - -#[cfg(feature = "union")] -union SmallVecData { - inline: core::mem::ManuallyDrop>, - heap: (NonNull, usize), -} - -#[cfg(all(feature = "union", feature = "const_new"))] -impl SmallVecData<[T; N]> { - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - const fn from_const(inline: MaybeUninit<[T; N]>) -> Self { - SmallVecData { - inline: core::mem::ManuallyDrop::new(inline), - } - } -} - -#[cfg(feature = "union")] -impl SmallVecData { - #[inline] - unsafe fn inline(&self) -> ConstNonNull { - ConstNonNull::new(self.inline.as_ptr() as *const A::Item).unwrap() - } - #[inline] - unsafe fn inline_mut(&mut self) -> NonNull { - NonNull::new(self.inline.as_mut_ptr() as *mut A::Item).unwrap() - } - #[inline] - fn from_inline(inline: MaybeUninit) -> SmallVecData { - SmallVecData { - inline: core::mem::ManuallyDrop::new(inline), - } - } - #[inline] - unsafe fn into_inline(self) -> MaybeUninit { - core::mem::ManuallyDrop::into_inner(self.inline) - } - #[inline] - unsafe fn heap(&self) -> (ConstNonNull, usize) { - (ConstNonNull(self.heap.0), self.heap.1) - } - #[inline] - unsafe fn heap_mut(&mut self) -> (NonNull, &mut usize) { - let h = &mut self.heap; - (h.0, &mut h.1) - } - #[inline] - fn from_heap(ptr: NonNull, len: usize) -> SmallVecData { - SmallVecData { heap: (ptr, len) } - } -} - -#[cfg(not(feature = "union"))] -enum SmallVecData { - Inline(MaybeUninit), - // Using NonNull and NonZero here allows to reduce size of `SmallVec`. - Heap { - // Since we never allocate on heap - // unless our capacity is bigger than inline capacity - // heap capacity cannot be less than 1. - // Therefore, pointer cannot be null too. - ptr: NonNull, - len: usize, - }, -} - -#[cfg(all(not(feature = "union"), feature = "const_new"))] -impl SmallVecData<[T; N]> { - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - const fn from_const(inline: MaybeUninit<[T; N]>) -> Self { - SmallVecData::Inline(inline) - } -} - -#[cfg(not(feature = "union"))] -impl SmallVecData { - #[inline] - unsafe fn inline(&self) -> ConstNonNull { - match self { - SmallVecData::Inline(a) => ConstNonNull::new(a.as_ptr() as *const A::Item).unwrap(), - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn inline_mut(&mut self) -> NonNull { - match self { - SmallVecData::Inline(a) => NonNull::new(a.as_mut_ptr() as *mut A::Item).unwrap(), - _ => debug_unreachable!(), - } - } - #[inline] - fn from_inline(inline: MaybeUninit) -> SmallVecData { - SmallVecData::Inline(inline) - } - #[inline] - unsafe fn into_inline(self) -> MaybeUninit { - match self { - SmallVecData::Inline(a) => a, - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn heap(&self) -> (ConstNonNull, usize) { - match self { - SmallVecData::Heap { ptr, len } => (ConstNonNull(*ptr), *len), - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn heap_mut(&mut self) -> (NonNull, &mut usize) { - match self { - SmallVecData::Heap { ptr, len } => (*ptr, len), - _ => debug_unreachable!(), - } - } - #[inline] - fn from_heap(ptr: NonNull, len: usize) -> SmallVecData { - SmallVecData::Heap { ptr, len } - } -} - -unsafe impl Send for SmallVecData {} -unsafe impl Sync for SmallVecData {} - -/// A `Vec`-like container that can store a small number of elements inline. -/// -/// `SmallVec` acts like a vector, but can store a limited amount of data inline within the -/// `SmallVec` struct rather than in a separate allocation. If the data exceeds this limit, the -/// `SmallVec` will "spill" its data onto the heap, allocating a new buffer to hold it. -/// -/// The amount of data that a `SmallVec` can store inline depends on its backing store. The backing -/// store can be any type that implements the `Array` trait; usually it is a small fixed-sized -/// array. For example a `SmallVec<[u64; 8]>` can hold up to eight 64-bit integers inline. -/// -/// ## Example -/// -/// ```rust -/// use smallvec::SmallVec; -/// let mut v = SmallVec::<[u8; 4]>::new(); // initialize an empty vector -/// -/// // The vector can hold up to 4 items without spilling onto the heap. -/// v.extend(0..4); -/// assert_eq!(v.len(), 4); -/// assert!(!v.spilled()); -/// -/// // Pushing another element will force the buffer to spill: -/// v.push(4); -/// assert_eq!(v.len(), 5); -/// assert!(v.spilled()); -/// ``` -pub struct SmallVec { - // The capacity field is used to determine which of the storage variants is active: - // If capacity <= Self::inline_capacity() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use). - // If capacity > Self::inline_capacity() then the heap variant is used and capacity holds the size of the memory allocation. - capacity: usize, - data: SmallVecData, -} - -impl SmallVec { - /// Construct an empty vector - #[inline] - pub fn new() -> SmallVec { - // Try to detect invalid custom implementations of `Array`. Hopefully, - // this check should be optimized away entirely for valid ones. - assert!( - mem::size_of::() == A::size() * mem::size_of::() - && mem::align_of::() >= mem::align_of::() - ); - SmallVec { - capacity: 0, - data: SmallVecData::from_inline(MaybeUninit::uninit()), - } - } - - /// Construct an empty vector with enough capacity pre-allocated to store at least `n` - /// elements. - /// - /// Will create a heap allocation only if `n` is larger than the inline capacity. - /// - /// ``` - /// # use smallvec::SmallVec; - /// - /// let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(100); - /// - /// assert!(v.is_empty()); - /// assert!(v.capacity() >= 100); - /// ``` - #[inline] - pub fn with_capacity(n: usize) -> Self { - let mut v = SmallVec::new(); - v.reserve_exact(n); - v - } - - /// Construct a new `SmallVec` from a `Vec`. - /// - /// Elements will be copied to the inline buffer if `vec.capacity() <= Self::inline_capacity()`. - /// - /// ```rust - /// use smallvec::SmallVec; - /// - /// let vec = vec![1, 2, 3, 4, 5]; - /// let small_vec: SmallVec<[_; 3]> = SmallVec::from_vec(vec); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_vec(mut vec: Vec) -> SmallVec { - if vec.capacity() <= Self::inline_capacity() { - // Cannot use Vec with smaller capacity - // because we use value of `Self::capacity` field as indicator. - unsafe { - let mut data = SmallVecData::::from_inline(MaybeUninit::uninit()); - let len = vec.len(); - vec.set_len(0); - ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().as_ptr(), len); - - SmallVec { - capacity: len, - data, - } - } - } else { - let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); - mem::forget(vec); - let ptr = NonNull::new(ptr) - // See docs: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_ptr - .expect("Cannot be null by `Vec` invariant"); - - SmallVec { - capacity: cap, - data: SmallVecData::from_heap(ptr, len), - } - } - } - - /// Constructs a new `SmallVec` on the stack from an `A` without - /// copying elements. - /// - /// ```rust - /// use smallvec::SmallVec; - /// - /// let buf = [1, 2, 3, 4, 5]; - /// let small_vec: SmallVec<_> = SmallVec::from_buf(buf); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_buf(buf: A) -> SmallVec { - SmallVec { - capacity: A::size(), - data: SmallVecData::from_inline(MaybeUninit::new(buf)), - } - } - - /// Constructs a new `SmallVec` on the stack from an `A` without - /// copying elements. Also sets the length, which must be less or - /// equal to the size of `buf`. - /// - /// ```rust - /// use smallvec::SmallVec; - /// - /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let small_vec: SmallVec<_> = SmallVec::from_buf_and_len(buf, 5); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec { - assert!(len <= A::size()); - unsafe { SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), len) } - } - - /// Constructs a new `SmallVec` on the stack from an `A` without - /// copying elements. Also sets the length. The user is responsible - /// for ensuring that `len <= A::size()`. - /// - /// ```rust - /// use smallvec::SmallVec; - /// use std::mem::MaybeUninit; - /// - /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let small_vec: SmallVec<_> = unsafe { - /// SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), 5) - /// }; - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit, len: usize) -> SmallVec { - SmallVec { - capacity: len, - data: SmallVecData::from_inline(buf), - } - } - - /// Sets the length of a vector. - /// - /// This will explicitly set the size of the vector, without actually - /// modifying its buffers, so it is up to the caller to ensure that the - /// vector is actually the specified size. - pub unsafe fn set_len(&mut self, new_len: usize) { - let (_, len_ptr, _) = self.triple_mut(); - *len_ptr = new_len; - } - - /// The maximum number of elements this vector can hold inline - #[inline] - fn inline_capacity() -> usize { - if mem::size_of::() > 0 { - A::size() - } else { - // For zero-size items code like `ptr.add(offset)` always returns the same pointer. - // Therefore all items are at the same address, - // and any array size has capacity for infinitely many items. - // The capacity is limited by the bit width of the length field. - // - // `Vec` also does this: - // https://github.com/rust-lang/rust/blob/1.44.0/src/liballoc/raw_vec.rs#L186 - // - // In our case, this also ensures that a smallvec of zero-size items never spills, - // and we never try to allocate zero bytes which `std::alloc::alloc` disallows. - core::usize::MAX - } - } - - /// The maximum number of elements this vector can hold inline - #[inline] - pub fn inline_size(&self) -> usize { - Self::inline_capacity() - } - - /// The number of elements stored in the vector - #[inline] - pub fn len(&self) -> usize { - self.triple().1 - } - - /// Returns `true` if the vector is empty - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// The number of items the vector can hold without reallocating - #[inline] - pub fn capacity(&self) -> usize { - self.triple().2 - } - - /// Returns a tuple with (data ptr, len, capacity) - /// Useful to get all `SmallVec` properties with a single check of the current storage variant. - #[inline] - fn triple(&self) -> (ConstNonNull, usize, usize) { - unsafe { - if self.spilled() { - let (ptr, len) = self.data.heap(); - (ptr, len, self.capacity) - } else { - (self.data.inline(), self.capacity, Self::inline_capacity()) - } - } - } - - /// Returns a tuple with (data ptr, len ptr, capacity) - #[inline] - fn triple_mut(&mut self) -> (NonNull, &mut usize, usize) { - unsafe { - if self.spilled() { - let (ptr, len_ptr) = self.data.heap_mut(); - (ptr, len_ptr, self.capacity) - } else { - ( - self.data.inline_mut(), - &mut self.capacity, - Self::inline_capacity(), - ) - } - } - } - - /// Returns `true` if the data has spilled into a separate heap-allocated buffer. - #[inline] - pub fn spilled(&self) -> bool { - self.capacity > Self::inline_capacity() - } - - /// Creates a draining iterator that removes the specified range in the vector - /// and yields the removed items. - /// - /// Note 1: The element range is removed even if the iterator is only - /// partially consumed or not consumed at all. - /// - /// Note 2: It is unspecified how many elements are removed from the vector - /// if the `Drain` value is leaked. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - pub fn drain(&mut self, range: R) -> Drain<'_, A> - where - R: RangeBounds, - { - use core::ops::Bound::*; - - let len = self.len(); - let start = match range.start_bound() { - Included(&n) => n, - Excluded(&n) => n.checked_add(1).expect("Range start out of bounds"), - Unbounded => 0, - }; - let end = match range.end_bound() { - Included(&n) => n.checked_add(1).expect("Range end out of bounds"), - Excluded(&n) => n, - Unbounded => len, - }; - - assert!(start <= end); - assert!(end <= len); - - unsafe { - self.set_len(start); - - let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start); - - Drain { - tail_start: end, - tail_len: len - end, - iter: range_slice.iter(), - // Since self is a &mut, passing it to a function would invalidate the slice iterator. - vec: NonNull::new_unchecked(self as *mut _), - } - } - } - - #[cfg(feature = "drain_filter")] - /// Creates an iterator which uses a closure to determine if an element should be removed. - /// - /// If the closure returns true, the element is removed and yielded. If the closure returns - /// false, the element will remain in the vector and will not be yielded by the iterator. - /// - /// Using this method is equivalent to the following code: - /// ``` - /// # use smallvec::SmallVec; - /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; - /// # let mut vec: SmallVec<[i32; 8]> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6]); - /// let mut i = 0; - /// while i < vec.len() { - /// if some_predicate(&mut vec[i]) { - /// let val = vec.remove(i); - /// // your code here - /// } else { - /// i += 1; - /// } - /// } - /// - /// # assert_eq!(vec, SmallVec::<[i32; 8]>::from_slice(&[1i32, 4, 5])); - /// ``` - /// /// - /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, - /// because it can backshift the elements of the array in bulk. - /// - /// Note that `drain_filter` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original allocation: - /// - /// ``` - /// # use smallvec::SmallVec; - /// let mut numbers: SmallVec<[i32; 16]> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); - /// - /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); - /// let odds = numbers; - /// - /// assert_eq!(evens, SmallVec::<[i32; 16]>::from_slice(&[2i32, 4, 6, 8, 14])); - /// assert_eq!(odds, SmallVec::<[i32; 16]>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15])); - /// ``` - pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, A, F> - where - F: FnMut(&mut A::Item) -> bool, - { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - DrainFilter { - vec: self, - idx: 0, - del: 0, - old_len, - pred: filter, - panic_flag: false, - } - } - - /// Append an item to the vector. - #[inline] - pub fn push(&mut self, value: A::Item) { - unsafe { - let (mut ptr, mut len, cap) = self.triple_mut(); - if *len == cap { - self.reserve_one_unchecked(); - let (heap_ptr, heap_len) = self.data.heap_mut(); - ptr = heap_ptr; - len = heap_len; - } - ptr::write(ptr.as_ptr().add(*len), value); - *len += 1; - } - } - - /// Remove an item from the end of the vector and return it, or None if empty. - #[inline] - pub fn pop(&mut self) -> Option { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let ptr: *const _ = ptr.as_ptr(); - if *len_ptr == 0 { - return None; - } - let last_index = *len_ptr - 1; - *len_ptr = last_index; - Some(ptr::read(ptr.add(last_index))) - } - } - - /// Moves all the elements of `other` into `self`, leaving `other` empty. - /// - /// # Example - /// - /// ``` - /// # use smallvec::{SmallVec, smallvec}; - /// let mut v0: SmallVec<[u8; 16]> = smallvec![1, 2, 3]; - /// let mut v1: SmallVec<[u8; 32]> = smallvec![4, 5, 6]; - /// v0.append(&mut v1); - /// assert_eq!(*v0, [1, 2, 3, 4, 5, 6]); - /// assert_eq!(*v1, []); - /// ``` - pub fn append(&mut self, other: &mut SmallVec) - where - B: Array, - { - self.extend(other.drain(..)) - } - - /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. - /// - /// Panics if `new_cap` is less than the vector's length - /// or if the capacity computation overflows `usize`. - pub fn grow(&mut self, new_cap: usize) { - infallible(self.try_grow(new_cap)) - } - - /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. - /// - /// Panics if `new_cap` is less than the vector's length - pub fn try_grow(&mut self, new_cap: usize) -> Result<(), CollectionAllocErr> { - unsafe { - let unspilled = !self.spilled(); - let (ptr, &mut len, cap) = self.triple_mut(); - assert!(new_cap >= len); - if new_cap <= Self::inline_capacity() { - if unspilled { - return Ok(()); - } - self.data = SmallVecData::from_inline(MaybeUninit::uninit()); - ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len); - self.capacity = len; - deallocate(ptr, cap); - } else if new_cap != cap { - let layout = layout_array::(new_cap)?; - debug_assert!(layout.size() > 0); - let new_alloc; - if unspilled { - new_alloc = NonNull::new(alloc::alloc::alloc(layout)) - .ok_or(CollectionAllocErr::AllocErr { layout })? - .cast(); - ptr::copy_nonoverlapping(ptr.as_ptr(), new_alloc.as_ptr(), len); - } else { - // This should never fail since the same succeeded - // when previously allocating `ptr`. - let old_layout = layout_array::(cap)?; - - let new_ptr = - alloc::alloc::realloc(ptr.as_ptr() as *mut u8, old_layout, layout.size()); - new_alloc = NonNull::new(new_ptr) - .ok_or(CollectionAllocErr::AllocErr { layout })? - .cast(); - } - self.data = SmallVecData::from_heap(new_alloc, len); - self.capacity = new_cap; - } - Ok(()) - } - } - - /// Reserve capacity for `additional` more elements to be inserted. - /// - /// May reserve more space to avoid frequent reallocations. - /// - /// Panics if the capacity computation overflows `usize`. - #[inline] - pub fn reserve(&mut self, additional: usize) { - infallible(self.try_reserve(additional)) - } - - /// Internal method used to grow in push() and insert(), where we know already we have to grow. - #[cold] - fn reserve_one_unchecked(&mut self) { - debug_assert_eq!(self.len(), self.capacity()); - let new_cap = self - .len() - .checked_add(1) - .and_then(usize::checked_next_power_of_two) - .expect("capacity overflow"); - infallible(self.try_grow(new_cap)) - } - - /// Reserve capacity for `additional` more elements to be inserted. - /// - /// May reserve more space to avoid frequent reallocations. - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - // prefer triple_mut() even if triple() would work so that the optimizer removes duplicated - // calls to it from callers. - let (_, &mut len, cap) = self.triple_mut(); - if cap - len >= additional { - return Ok(()); - } - let new_cap = len - .checked_add(additional) - .and_then(usize::checked_next_power_of_two) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - self.try_grow(new_cap) - } - - /// Reserve the minimum capacity for `additional` more elements to be inserted. - /// - /// Panics if the new capacity overflows `usize`. - pub fn reserve_exact(&mut self, additional: usize) { - infallible(self.try_reserve_exact(additional)) - } - - /// Reserve the minimum capacity for `additional` more elements to be inserted. - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - let (_, &mut len, cap) = self.triple_mut(); - if cap - len >= additional { - return Ok(()); - } - let new_cap = len - .checked_add(additional) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - self.try_grow(new_cap) - } - - /// Shrink the capacity of the vector as much as possible. - /// - /// When possible, this will move data from an external heap buffer to the vector's inline - /// storage. - pub fn shrink_to_fit(&mut self) { - if !self.spilled() { - return; - } - let len = self.len(); - if self.inline_size() >= len { - unsafe { - let (ptr, len) = self.data.heap(); - self.data = SmallVecData::from_inline(MaybeUninit::uninit()); - ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len); - deallocate(ptr.0, self.capacity); - self.capacity = len; - } - } else if self.capacity() > len { - self.grow(len); - } - } - - /// Shorten the vector, keeping the first `len` elements and dropping the rest. - /// - /// If `len` is greater than or equal to the vector's current length, this has no - /// effect. - /// - /// This does not re-allocate. If you want the vector's capacity to shrink, call - /// `shrink_to_fit` after truncating. - pub fn truncate(&mut self, len: usize) { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let ptr = ptr.as_ptr(); - while len < *len_ptr { - let last_index = *len_ptr - 1; - *len_ptr = last_index; - ptr::drop_in_place(ptr.add(last_index)); - } - } - } - - /// Extracts a slice containing the entire vector. - /// - /// Equivalent to `&s[..]`. - pub fn as_slice(&self) -> &[A::Item] { - self - } - - /// Extracts a mutable slice of the entire vector. - /// - /// Equivalent to `&mut s[..]`. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - self - } - - /// Remove the element at position `index`, replacing it with the last element. - /// - /// This does not preserve ordering, but is O(1). - /// - /// Panics if `index` is out of bounds. - #[inline] - pub fn swap_remove(&mut self, index: usize) -> A::Item { - let len = self.len(); - self.swap(len - 1, index); - self.pop() - .unwrap_or_else(|| unsafe { unreachable_unchecked() }) - } - - /// Remove all elements from the vector. - #[inline] - pub fn clear(&mut self) { - self.truncate(0); - } - - /// Remove and return the element at position `index`, shifting all elements after it to the - /// left. - /// - /// Panics if `index` is out of bounds. - pub fn remove(&mut self, index: usize) -> A::Item { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let len = *len_ptr; - assert!(index < len); - *len_ptr = len - 1; - let ptr = ptr.as_ptr().add(index); - let item = ptr::read(ptr); - ptr::copy(ptr.add(1), ptr, len - index - 1); - item - } - } - - /// Insert an element at position `index`, shifting all elements after it to the right. - /// - /// Panics if `index > len`. - pub fn insert(&mut self, index: usize, element: A::Item) { - unsafe { - let (mut ptr, mut len_ptr, cap) = self.triple_mut(); - if *len_ptr == cap { - self.reserve_one_unchecked(); - let (heap_ptr, heap_len_ptr) = self.data.heap_mut(); - ptr = heap_ptr; - len_ptr = heap_len_ptr; - } - let mut ptr = ptr.as_ptr(); - let len = *len_ptr; - if index > len { - panic!("index exceeds length"); - } - // SAFETY: add is UB if index > len, but we panicked first - ptr = ptr.add(index); - if index < len { - // Shift element to the right of `index`. - ptr::copy(ptr, ptr.add(1), len - index); - } - *len_ptr = len + 1; - ptr::write(ptr, element); - } - } - - /// Insert multiple elements at position `index`, shifting all following elements toward the - /// back. - pub fn insert_many>(&mut self, index: usize, iterable: I) { - let mut iter = iterable.into_iter(); - if index == self.len() { - return self.extend(iter); - } - - let (lower_size_bound, _) = iter.size_hint(); - assert!(lower_size_bound <= core::isize::MAX as usize); // Ensure offset is indexable - assert!(index + lower_size_bound >= index); // Protect against overflow - - let mut num_added = 0; - let old_len = self.len(); - assert!(index <= old_len); - - unsafe { - // Reserve space for `lower_size_bound` elements. - self.reserve(lower_size_bound); - let start = self.as_mut_ptr(); - let ptr = start.add(index); - - // Move the trailing elements. - ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index); - - // In case the iterator panics, don't double-drop the items we just copied above. - self.set_len(0); - let mut guard = DropOnPanic { - start, - skip: index..(index + lower_size_bound), - len: old_len + lower_size_bound, - }; - - // The set_len above invalidates the previous pointers, so we must re-create them. - let start = self.as_mut_ptr(); - let ptr = start.add(index); - - while num_added < lower_size_bound { - let element = match iter.next() { - Some(x) => x, - None => break, - }; - let cur = ptr.add(num_added); - ptr::write(cur, element); - guard.skip.start += 1; - num_added += 1; - } - - if num_added < lower_size_bound { - // Iterator provided fewer elements than the hint. Move the tail backward. - ptr::copy( - ptr.add(lower_size_bound), - ptr.add(num_added), - old_len - index, - ); - } - // There are no more duplicate or uninitialized slots, so the guard is not needed. - self.set_len(old_len + num_added); - mem::forget(guard); - } - - // Insert any remaining elements one-by-one. - for element in iter { - self.insert(index + num_added, element); - num_added += 1; - } - - struct DropOnPanic { - start: *mut T, - skip: Range, // Space we copied-out-of, but haven't written-to yet. - len: usize, - } - - impl Drop for DropOnPanic { - fn drop(&mut self) { - for i in 0..self.len { - if !self.skip.contains(&i) { - unsafe { - ptr::drop_in_place(self.start.add(i)); - } - } - } - } - } - } - - /// Convert a `SmallVec` to a `Vec`, without reallocating if the `SmallVec` has already spilled onto - /// the heap. - pub fn into_vec(mut self) -> Vec { - if self.spilled() { - unsafe { - let (ptr, &mut len) = self.data.heap_mut(); - let v = Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity); - mem::forget(self); - v - } - } else { - self.into_iter().collect() - } - } - - /// Converts a `SmallVec` into a `Box<[T]>` without reallocating if the `SmallVec` has already spilled - /// onto the heap. - /// - /// Note that this will drop any excess capacity. - pub fn into_boxed_slice(self) -> Box<[A::Item]> { - self.into_vec().into_boxed_slice() - } - - /// Convert the `SmallVec` into an `A` if possible. Otherwise return `Err(Self)`. - /// - /// This method returns `Err(Self)` if the `SmallVec` is too short (and the `A` contains uninitialized elements), - /// or if the `SmallVec` is too long (and all the elements were spilled to the heap). - pub fn into_inner(self) -> Result { - if self.spilled() || self.len() != A::size() { - // Note: A::size, not Self::inline_capacity - Err(self) - } else { - unsafe { - let data = ptr::read(&self.data); - mem::forget(self); - Ok(data.into_inline().assume_init()) - } - } - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// This method operates in place and preserves the order of the retained - /// elements. - pub fn retain bool>(&mut self, mut f: F) { - let mut del = 0; - let len = self.len(); - for i in 0..len { - if !f(&mut self[i]) { - del += 1; - } else if del > 0 { - self.swap(i - del, i); - } - } - self.truncate(len - del); - } - - /// Retains only the elements specified by the predicate. - /// - /// This method is identical in behaviour to [`retain`]; it is included only - /// to maintain api-compatibility with `std::Vec`, where the methods are - /// separate for historical reasons. - pub fn retain_mut bool>(&mut self, f: F) { - self.retain(f) - } - - /// Removes consecutive duplicate elements. - pub fn dedup(&mut self) - where - A::Item: PartialEq, - { - self.dedup_by(|a, b| a == b); - } - - /// Removes consecutive duplicate elements using the given equality relation. - pub fn dedup_by(&mut self, mut same_bucket: F) - where - F: FnMut(&mut A::Item, &mut A::Item) -> bool, - { - // See the implementation of Vec::dedup_by in the - // standard library for an explanation of this algorithm. - let len = self.len(); - if len <= 1 { - return; - } - - let ptr = self.as_mut_ptr(); - let mut w: usize = 1; - - unsafe { - for r in 1..len { - let p_r = ptr.add(r); - let p_wm1 = ptr.add(w - 1); - if !same_bucket(&mut *p_r, &mut *p_wm1) { - if r != w { - let p_w = p_wm1.add(1); - mem::swap(&mut *p_r, &mut *p_w); - } - w += 1; - } - } - } - - self.truncate(w); - } - - /// Removes consecutive elements that map to the same key. - pub fn dedup_by_key(&mut self, mut key: F) - where - F: FnMut(&mut A::Item) -> K, - K: PartialEq, - { - self.dedup_by(|a, b| key(a) == key(b)); - } - - /// Resizes the `SmallVec` in-place so that `len` is equal to `new_len`. - /// - /// If `new_len` is greater than `len`, the `SmallVec` is extended by the difference, with each - /// additional slot filled with the result of calling the closure `f`. The return values from `f` - /// will end up in the `SmallVec` in the order they have been generated. - /// - /// If `new_len` is less than `len`, the `SmallVec` is simply truncated. - /// - /// This method uses a closure to create new values on every push. If you'd rather `Clone` a given - /// value, use `resize`. If you want to use the `Default` trait to generate values, you can pass - /// `Default::default()` as the second argument. - /// - /// Added for `std::vec::Vec` compatibility (added in Rust 1.33.0) - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// let mut vec : SmallVec<[_; 4]> = smallvec![1, 2, 3]; - /// vec.resize_with(5, Default::default); - /// assert_eq!(&*vec, &[1, 2, 3, 0, 0]); - /// - /// let mut vec : SmallVec<[_; 4]> = smallvec![]; - /// let mut p = 1; - /// vec.resize_with(4, || { p *= 2; p }); - /// assert_eq!(&*vec, &[2, 4, 8, 16]); - /// ``` - pub fn resize_with(&mut self, new_len: usize, f: F) - where - F: FnMut() -> A::Item, - { - let old_len = self.len(); - if old_len < new_len { - let mut f = f; - let additional = new_len - old_len; - self.reserve(additional); - for _ in 0..additional { - self.push(f()); - } - } else if old_len > new_len { - self.truncate(new_len); - } - } - - /// Creates a `SmallVec` directly from the raw components of another - /// `SmallVec`. - /// - /// # Safety - /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` needs to have been previously allocated via `SmallVec` for its - /// spilled storage (at least, it's highly likely to be incorrect if it - /// wasn't). - /// * `ptr`'s `A::Item` type needs to be the same size and alignment that - /// it was allocated with - /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated - /// with. - /// - /// Violating these may cause problems like corrupting the allocator's - /// internal data structures. - /// - /// Additionally, `capacity` must be greater than the amount of inline - /// storage `A` has; that is, the new `SmallVec` must need to spill over - /// into heap allocated storage. This condition is asserted against. - /// - /// The ownership of `ptr` is effectively transferred to the - /// `SmallVec` which may then deallocate, reallocate or change the - /// contents of memory pointed to by the pointer at will. Ensure - /// that nothing else uses the pointer after calling this - /// function. - /// - /// # Examples - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// use std::mem; - /// use std::ptr; - /// - /// fn main() { - /// let mut v: SmallVec<[_; 1]> = smallvec![1, 2, 3]; - /// - /// // Pull out the important parts of `v`. - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); - /// let spilled = v.spilled(); - /// - /// unsafe { - /// // Forget all about `v`. The heap allocation that stored the - /// // three values won't be deallocated. - /// mem::forget(v); - /// - /// // Overwrite memory with [4, 5, 6]. - /// // - /// // This is only safe if `spilled` is true! Otherwise, we are - /// // writing into the old `SmallVec`'s inline storage on the - /// // stack. - /// assert!(spilled); - /// for i in 0..len { - /// ptr::write(p.add(i), 4 + i); - /// } - /// - /// // Put everything back together into a SmallVec with a different - /// // amount of inline storage, but which is still less than `cap`. - /// let rebuilt = SmallVec::<[_; 2]>::from_raw_parts(p, len, cap); - /// assert_eq!(&*rebuilt, &[4, 5, 6]); - /// } - /// } - #[inline] - pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec { - // SAFETY: We require caller to provide same ptr as we alloc - // and we never alloc null pointer. - let ptr = unsafe { - debug_assert!(!ptr.is_null(), "Called `from_raw_parts` with null pointer."); - NonNull::new_unchecked(ptr) - }; - assert!(capacity > Self::inline_capacity()); - SmallVec { - capacity, - data: SmallVecData::from_heap(ptr, length), - } - } - - /// Returns a raw pointer to the vector's buffer. - pub fn as_ptr(&self) -> *const A::Item { - // We shadow the slice method of the same name to avoid going through - // `deref`, which creates an intermediate reference that may place - // additional safety constraints on the contents of the slice. - self.triple().0.as_ptr() - } - - /// Returns a raw mutable pointer to the vector's buffer. - pub fn as_mut_ptr(&mut self) -> *mut A::Item { - // We shadow the slice method of the same name to avoid going through - // `deref_mut`, which creates an intermediate reference that may place - // additional safety constraints on the contents of the slice. - self.triple_mut().0.as_ptr() - } -} - -impl SmallVec -where - A::Item: Copy, -{ - /// Copy the elements from a slice into a new `SmallVec`. - /// - /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`. - pub fn from_slice(slice: &[A::Item]) -> Self { - let len = slice.len(); - if len <= Self::inline_capacity() { - SmallVec { - capacity: len, - data: SmallVecData::from_inline(unsafe { - let mut data: MaybeUninit = MaybeUninit::uninit(); - ptr::copy_nonoverlapping( - slice.as_ptr(), - data.as_mut_ptr() as *mut A::Item, - len, - ); - data - }), - } - } else { - let mut b = slice.to_vec(); - let cap = b.capacity(); - let ptr = NonNull::new(b.as_mut_ptr()).expect("Vec always contain non null pointers."); - mem::forget(b); - SmallVec { - capacity: cap, - data: SmallVecData::from_heap(ptr, len), - } - } - } - - /// Copy elements from a slice into the vector at position `index`, shifting any following - /// elements toward the back. - /// - /// For slices of `Copy` types, this is more efficient than `insert`. - #[inline] - pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { - self.reserve(slice.len()); - - let len = self.len(); - assert!(index <= len); - - unsafe { - let slice_ptr = slice.as_ptr(); - let ptr = self.as_mut_ptr().add(index); - ptr::copy(ptr, ptr.add(slice.len()), len - index); - ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len()); - self.set_len(len + slice.len()); - } - } - - /// Copy elements from a slice and append them to the vector. - /// - /// For slices of `Copy` types, this is more efficient than `extend`. - #[inline] - pub fn extend_from_slice(&mut self, slice: &[A::Item]) { - let len = self.len(); - self.insert_from_slice(len, slice); - } -} - -impl SmallVec -where - A::Item: Clone, -{ - /// Resizes the vector so that its length is equal to `len`. - /// - /// If `len` is less than the current length, the vector simply truncated. - /// - /// If `len` is greater than the current length, `value` is appended to the - /// vector until its length equals `len`. - pub fn resize(&mut self, len: usize, value: A::Item) { - let old_len = self.len(); - - if len > old_len { - self.extend(repeat(value).take(len - old_len)); - } else { - self.truncate(len); - } - } - - /// Creates a `SmallVec` with `n` copies of `elem`. - /// ``` - /// use smallvec::SmallVec; - /// - /// let v = SmallVec::<[char; 128]>::from_elem('d', 2); - /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); - /// ``` - pub fn from_elem(elem: A::Item, n: usize) -> Self { - if n > Self::inline_capacity() { - vec![elem; n].into() - } else { - let mut v = SmallVec::::new(); - unsafe { - let (ptr, len_ptr, _) = v.triple_mut(); - let ptr = ptr.as_ptr(); - let mut local_len = SetLenOnDrop::new(len_ptr); - - for i in 0..n { - ::core::ptr::write(ptr.add(i), elem.clone()); - local_len.increment_len(1); - } - } - v - } - } -} - -impl ops::Deref for SmallVec { - type Target = [A::Item]; - #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - let (ptr, len, _) = self.triple(); - slice::from_raw_parts(ptr.as_ptr(), len) - } - } -} - -impl ops::DerefMut for SmallVec { - #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { - unsafe { - let (ptr, &mut len, _) = self.triple_mut(); - slice::from_raw_parts_mut(ptr.as_ptr(), len) - } - } -} - -impl AsRef<[A::Item]> for SmallVec { - #[inline] - fn as_ref(&self) -> &[A::Item] { - self - } -} - -impl AsMut<[A::Item]> for SmallVec { - #[inline] - fn as_mut(&mut self) -> &mut [A::Item] { - self - } -} - -impl Borrow<[A::Item]> for SmallVec { - #[inline] - fn borrow(&self) -> &[A::Item] { - self - } -} - -impl BorrowMut<[A::Item]> for SmallVec { - #[inline] - fn borrow_mut(&mut self) -> &mut [A::Item] { - self - } -} - -#[cfg(feature = "write")] -#[cfg_attr(docsrs, doc(cfg(feature = "write")))] -impl> io::Write for SmallVec { - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result { - self.extend_from_slice(buf); - Ok(buf.len()) - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - self.extend_from_slice(buf); - Ok(()) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[cfg(feature = "serde")] -#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] -impl Serialize for SmallVec -where - A::Item: Serialize, -{ - fn serialize(&self, serializer: S) -> Result { - let mut state = serializer.serialize_seq(Some(self.len()))?; - for item in self { - state.serialize_element(&item)?; - } - state.end() - } -} - -#[cfg(feature = "serde")] -#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] -impl<'de, A: Array> Deserialize<'de> for SmallVec -where - A::Item: Deserialize<'de>, -{ - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(SmallVecVisitor { - phantom: PhantomData, - }) - } -} - -#[cfg(feature = "serde")] -struct SmallVecVisitor { - phantom: PhantomData, -} - -#[cfg(feature = "serde")] -impl<'de, A: Array> Visitor<'de> for SmallVecVisitor -where - A::Item: Deserialize<'de>, -{ - type Value = SmallVec; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - fn visit_seq(self, mut seq: B) -> Result - where - B: SeqAccess<'de>, - { - use serde::de::Error; - let len = seq.size_hint().unwrap_or(0); - let mut values = SmallVec::new(); - values.try_reserve(len).map_err(B::Error::custom)?; - - while let Some(value) = seq.next_element()? { - values.push(value); - } - - Ok(values) - } -} - -#[cfg(feature = "malloc_size_of")] -impl MallocShallowSizeOf for SmallVec { - fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - if self.spilled() { - unsafe { ops.malloc_size_of(self.as_ptr()) } - } else { - 0 - } - } -} - -#[cfg(feature = "malloc_size_of")] -impl MallocSizeOf for SmallVec -where - A: Array, - A::Item: MallocSizeOf, -{ - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - let mut n = self.shallow_size_of(ops); - for elem in self.iter() { - n += elem.size_of(ops); - } - n - } -} - -#[cfg(feature = "specialization")] -trait SpecFrom { - fn spec_from(slice: S) -> SmallVec; -} - -#[cfg(feature = "specialization")] -mod specialization; - -#[cfg(feature = "arbitrary")] -mod arbitrary; - -#[cfg(feature = "specialization")] -impl<'a, A: Array> SpecFrom for SmallVec -where - A::Item: Copy, -{ - #[inline] - fn spec_from(slice: &'a [A::Item]) -> SmallVec { - SmallVec::from_slice(slice) - } -} - -impl<'a, A: Array> From<&'a [A::Item]> for SmallVec -where - A::Item: Clone, -{ - #[cfg(not(feature = "specialization"))] - #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec { - slice.iter().cloned().collect() - } - - #[cfg(feature = "specialization")] - #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec { - SmallVec::spec_from(slice) - } -} - -impl From> for SmallVec { - #[inline] - fn from(vec: Vec) -> SmallVec { - SmallVec::from_vec(vec) - } -} - -impl From for SmallVec { - #[inline] - fn from(array: A) -> SmallVec { - SmallVec::from_buf(array) - } -} - -impl> ops::Index for SmallVec { - type Output = I::Output; - - fn index(&self, index: I) -> &I::Output { - &(**self)[index] - } -} - -impl> ops::IndexMut for SmallVec { - fn index_mut(&mut self, index: I) -> &mut I::Output { - &mut (&mut **self)[index] - } -} - -#[allow(deprecated)] -impl ExtendFromSlice for SmallVec -where - A::Item: Copy, -{ - fn extend_from_slice(&mut self, other: &[A::Item]) { - SmallVec::extend_from_slice(self, other) - } -} - -impl FromIterator for SmallVec { - #[inline] - fn from_iter>(iterable: I) -> SmallVec { - let mut v = SmallVec::new(); - v.extend(iterable); - v - } -} - -impl Extend for SmallVec { - fn extend>(&mut self, iterable: I) { - let mut iter = iterable.into_iter(); - let (lower_size_bound, _) = iter.size_hint(); - self.reserve(lower_size_bound); - - unsafe { - let (ptr, len_ptr, cap) = self.triple_mut(); - let ptr = ptr.as_ptr(); - let mut len = SetLenOnDrop::new(len_ptr); - while len.get() < cap { - if let Some(out) = iter.next() { - ptr::write(ptr.add(len.get()), out); - len.increment_len(1); - } else { - return; - } - } - } - - for elem in iter { - self.push(elem); - } - } -} - -impl fmt::Debug for SmallVec -where - A::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl Default for SmallVec { - #[inline] - fn default() -> SmallVec { - SmallVec::new() - } -} - -#[cfg(feature = "may_dangle")] -unsafe impl<#[may_dangle] A: Array> Drop for SmallVec { - fn drop(&mut self) { - unsafe { - if self.spilled() { - let (ptr, &mut len) = self.data.heap_mut(); - Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity); - } else { - ptr::drop_in_place(&mut self[..]); - } - } - } -} - -#[cfg(not(feature = "may_dangle"))] -impl Drop for SmallVec { - fn drop(&mut self) { - unsafe { - if self.spilled() { - let (ptr, &mut len) = self.data.heap_mut(); - drop(Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity)); - } else { - ptr::drop_in_place(&mut self[..]); - } - } - } -} - -impl Clone for SmallVec -where - A::Item: Clone, -{ - #[inline] - fn clone(&self) -> SmallVec { - SmallVec::from(self.as_slice()) - } - - fn clone_from(&mut self, source: &Self) { - // Inspired from `impl Clone for Vec`. - - // drop anything that will not be overwritten - self.truncate(source.len()); - - // self.len <= other.len due to the truncate above, so the - // slices here are always in-bounds. - let (init, tail) = source.split_at(self.len()); - - // reuse the contained values' allocations/resources. - self.clone_from_slice(init); - self.extend(tail.iter().cloned()); - } -} - -impl PartialEq> for SmallVec -where - A::Item: PartialEq, -{ - #[inline] - fn eq(&self, other: &SmallVec) -> bool { - self[..] == other[..] - } -} - -impl Eq for SmallVec where A::Item: Eq {} - -impl PartialOrd for SmallVec -where - A::Item: PartialOrd, -{ - #[inline] - fn partial_cmp(&self, other: &SmallVec) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -impl Ord for SmallVec -where - A::Item: Ord, -{ - #[inline] - fn cmp(&self, other: &SmallVec) -> cmp::Ordering { - Ord::cmp(&**self, &**other) - } -} - -impl Hash for SmallVec -where - A::Item: Hash, -{ - fn hash(&self, state: &mut H) { - (**self).hash(state) - } -} - -unsafe impl Send for SmallVec where A::Item: Send {} - -/// An iterator that consumes a `SmallVec` and yields its items by value. -/// -/// Returned from [`SmallVec::into_iter`][1]. -/// -/// [1]: struct.SmallVec.html#method.into_iter -pub struct IntoIter { - data: SmallVec, - current: usize, - end: usize, -} - -impl fmt::Debug for IntoIter -where - A::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() - } -} - -impl Clone for IntoIter -where - A::Item: Clone, -{ - fn clone(&self) -> IntoIter { - SmallVec::from(self.as_slice()).into_iter() - } -} - -impl Drop for IntoIter { - fn drop(&mut self) { - for _ in self {} - } -} - -impl Iterator for IntoIter { - type Item = A::Item; - - #[inline] - fn next(&mut self) -> Option { - if self.current == self.end { - None - } else { - unsafe { - let current = self.current; - self.current += 1; - Some(ptr::read(self.data.as_ptr().add(current))) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let size = self.end - self.current; - (size, Some(size)) - } -} - -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - if self.current == self.end { - None - } else { - unsafe { - self.end -= 1; - Some(ptr::read(self.data.as_ptr().add(self.end))) - } - } - } -} - -impl ExactSizeIterator for IntoIter {} -impl FusedIterator for IntoIter {} - -impl IntoIter { - /// Returns the remaining items of this iterator as a slice. - pub fn as_slice(&self) -> &[A::Item] { - let len = self.end - self.current; - unsafe { core::slice::from_raw_parts(self.data.as_ptr().add(self.current), len) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - let len = self.end - self.current; - unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().add(self.current), len) } - } -} - -impl IntoIterator for SmallVec { - type IntoIter = IntoIter; - type Item = A::Item; - fn into_iter(mut self) -> Self::IntoIter { - unsafe { - // Set SmallVec len to zero as `IntoIter` drop handles dropping of the elements - let len = self.len(); - self.set_len(0); - IntoIter { - data: self, - current: 0, - end: len, - } - } - } -} - -impl<'a, A: Array> IntoIterator for &'a SmallVec { - type IntoIter = slice::Iter<'a, A::Item>; - type Item = &'a A::Item; - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, A: Array> IntoIterator for &'a mut SmallVec { - type IntoIter = slice::IterMut<'a, A::Item>; - type Item = &'a mut A::Item; - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -/// Types that can be used as the backing store for a [`SmallVec`]. -pub unsafe trait Array { - /// The type of the array's elements. - type Item; - /// Returns the number of items the array can hold. - fn size() -> usize; -} - -/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. -/// -/// Copied from -struct SetLenOnDrop<'a> { - len: &'a mut usize, - local_len: usize, -} - -impl<'a> SetLenOnDrop<'a> { - #[inline] - fn new(len: &'a mut usize) -> Self { - SetLenOnDrop { - local_len: *len, - len, - } - } - - #[inline] - fn get(&self) -> usize { - self.local_len - } - - #[inline] - fn increment_len(&mut self, increment: usize) { - self.local_len += increment; - } -} - -impl<'a> Drop for SetLenOnDrop<'a> { - #[inline] - fn drop(&mut self) { - *self.len = self.local_len; - } -} - -#[cfg(feature = "const_new")] -impl SmallVec<[T; N]> { - /// Construct an empty vector. - /// - /// This is a `const` version of [`SmallVec::new`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays. - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - pub const fn new_const() -> Self { - SmallVec { - capacity: 0, - data: SmallVecData::from_const(MaybeUninit::uninit()), - } - } - - /// The array passed as an argument is moved to be an inline version of `SmallVec`. - /// - /// This is a `const` version of [`SmallVec::from_buf`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays. - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - pub const fn from_const(items: [T; N]) -> Self { - SmallVec { - capacity: N, - data: SmallVecData::from_const(MaybeUninit::new(items)), - } - } - - /// Constructs a new `SmallVec` on the stack from an array without - /// copying elements. Also sets the length. The user is responsible - /// for ensuring that `len <= N`. - /// - /// This is a `const` version of [`SmallVec::from_buf_and_len_unchecked`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays. - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - pub const unsafe fn from_const_with_len_unchecked(items: [T; N], len: usize) -> Self { - SmallVec { - capacity: len, - data: SmallVecData::from_const(MaybeUninit::new(items)), - } - } -} - -#[cfg(feature = "const_generics")] -#[cfg_attr(docsrs, doc(cfg(feature = "const_generics")))] -unsafe impl Array for [T; N] { - type Item = T; - #[inline] - fn size() -> usize { - N - } -} - -#[cfg(not(feature = "const_generics"))] -macro_rules! impl_array( - ($($size:expr),+) => { - $( - unsafe impl Array for [T; $size] { - type Item = T; - #[inline] - fn size() -> usize { $size } - } - )+ - } -); - -#[cfg(not(feature = "const_generics"))] -impl_array!( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 36, 0x40, 0x60, 0x80, 0x100, 0x200, 0x400, 0x600, 0x800, 0x1000, - 0x2000, 0x4000, 0x6000, 0x8000, 0x10000, 0x20000, 0x40000, 0x60000, 0x80000, 0x10_0000 -); - -/// Convenience trait for constructing a `SmallVec` -pub trait ToSmallVec { - /// Construct a new `SmallVec` from a slice. - fn to_smallvec(&self) -> SmallVec; -} - -impl ToSmallVec for [A::Item] -where - A::Item: Copy, -{ - #[inline] - fn to_smallvec(&self) -> SmallVec { - SmallVec::from_slice(self) - } -} - -// Immutable counterpart for `NonNull`. -#[repr(transparent)] -struct ConstNonNull(NonNull); - -impl ConstNonNull { - #[inline] - fn new(ptr: *const T) -> Option { - NonNull::new(ptr as *mut T).map(Self) - } - #[inline] - fn as_ptr(self) -> *const T { - self.0.as_ptr() - } -} - -impl Clone for ConstNonNull { - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl Copy for ConstNonNull {} - -#[cfg(feature = "impl_bincode")] -use bincode::{ - de::{read::Reader, BorrowDecoder, Decode, Decoder}, - enc::{write::Writer, Encode, Encoder}, - error::{DecodeError, EncodeError}, - BorrowDecode, -}; - -#[cfg(feature = "impl_bincode")] -impl Decode for SmallVec -where - A: Array, - A::Item: Decode, -{ - fn decode>(decoder: &mut D) -> Result { - use core::convert::TryInto; - let len = u64::decode(decoder)?; - let len = len - .try_into() - .map_err(|_| DecodeError::OutsideUsizeRange(len))?; - decoder.claim_container_read::(len)?; - - let mut vec = SmallVec::with_capacity(len); - if unty::type_equal::() { - // Initialize the smallvec's buffer. Note that we need to do this through - // the raw pointer as we cannot name the type [u8; N] even though A::Item is u8. - let ptr = vec.as_mut_ptr(); - // SAFETY: A::Item is u8 and the smallvec has been allocated with enough capacity - unsafe { - core::ptr::write_bytes(ptr, 0, len); - vec.set_len(len); - } - // Read the data into the smallvec's buffer. - let slice = vec.as_mut_slice(); - // SAFETY: A::Item is u8 - let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) }; - decoder.reader().read(slice)?; - } else { - for _ in 0..len { - decoder.unclaim_bytes_read(core::mem::size_of::()); - vec.push(A::Item::decode(decoder)?); - } - } - Ok(vec) - } -} - -#[cfg(feature = "impl_bincode")] -impl<'de, A, Context> BorrowDecode<'de, Context> for SmallVec -where - A: Array, - A::Item: BorrowDecode<'de, Context>, -{ - fn borrow_decode>( - decoder: &mut D, - ) -> Result { - use core::convert::TryInto; - let len = u64::decode(decoder)?; - let len = len - .try_into() - .map_err(|_| DecodeError::OutsideUsizeRange(len))?; - decoder.claim_container_read::(len)?; - - let mut vec = SmallVec::with_capacity(len); - if unty::type_equal::() { - // Initialize the smallvec's buffer. Note that we need to do this through - // the raw pointer as we cannot name the type [u8; N] even though A::Item is u8. - let ptr = vec.as_mut_ptr(); - // SAFETY: A::Item is u8 and the smallvec has been allocated with enough capacity - unsafe { - core::ptr::write_bytes(ptr, 0, len); - vec.set_len(len); - } - // Read the data into the smallvec's buffer. - let slice = vec.as_mut_slice(); - // SAFETY: A::Item is u8 - let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) }; - decoder.reader().read(slice)?; - } else { - for _ in 0..len { - decoder.unclaim_bytes_read(core::mem::size_of::()); - vec.push(A::Item::borrow_decode(decoder)?); - } - } - Ok(vec) - } -} - -#[cfg(feature = "impl_bincode")] -impl Encode for SmallVec -where - A: Array, - A::Item: Encode, -{ - fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { - (self.len() as u64).encode(encoder)?; - if unty::type_equal::() { - // Safety: A::Item is u8 - let slice: &[u8] = unsafe { core::mem::transmute(self.as_slice()) }; - encoder.writer().write(slice)?; - } else { - for item in self.iter() { - item.encode(encoder)?; - } - } - Ok(()) - } -} diff --git a/vendor/makepad/libs/smallvec/src/specialization.rs b/vendor/makepad/libs/smallvec/src/specialization.rs deleted file mode 100644 index 658fa77..0000000 --- a/vendor/makepad/libs/smallvec/src/specialization.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementations that require `default fn`. - -use super::{Array, SmallVec, SpecFrom}; - -impl<'a, A: Array> SpecFrom for SmallVec -where - A::Item: Clone, -{ - #[inline] - default fn spec_from(slice: &'a [A::Item]) -> SmallVec { - slice.into_iter().cloned().collect() - } -} diff --git a/vendor/makepad/libs/smallvec/src/tests.rs b/vendor/makepad/libs/smallvec/src/tests.rs deleted file mode 100644 index a4298cd..0000000 --- a/vendor/makepad/libs/smallvec/src/tests.rs +++ /dev/null @@ -1,1134 +0,0 @@ -use crate::{smallvec, SmallVec}; - -use std::iter::FromIterator; - -use alloc::borrow::ToOwned; -use alloc::boxed::Box; -use alloc::rc::Rc; -use alloc::{vec, vec::Vec}; - -#[test] -pub fn test_zero() { - let mut v = SmallVec::<[_; 0]>::new(); - assert!(!v.spilled()); - v.push(0usize); - assert!(v.spilled()); - assert_eq!(&*v, &[0]); -} - -// We heap allocate all these strings so that double frees will show up under valgrind. - -#[test] -pub fn test_inline() { - let mut v = SmallVec::<[_; 16]>::new(); - v.push("hello".to_owned()); - v.push("there".to_owned()); - assert_eq!(&*v, &["hello".to_owned(), "there".to_owned(),][..]); -} - -#[test] -pub fn test_spill() { - let mut v = SmallVec::<[_; 2]>::new(); - v.push("hello".to_owned()); - assert_eq!(v[0], "hello"); - v.push("there".to_owned()); - v.push("burma".to_owned()); - assert_eq!(v[0], "hello"); - v.push("shave".to_owned()); - assert_eq!( - &*v, - &[ - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - ][..] - ); -} - -#[test] -pub fn test_double_spill() { - let mut v = SmallVec::<[_; 2]>::new(); - v.push("hello".to_owned()); - v.push("there".to_owned()); - v.push("burma".to_owned()); - v.push("shave".to_owned()); - v.push("hello".to_owned()); - v.push("there".to_owned()); - v.push("burma".to_owned()); - v.push("shave".to_owned()); - assert_eq!( - &*v, - &[ - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - ][..] - ); -} - -// https://github.com/servo/rust-smallvec/issues/4 -#[test] -fn issue_4() { - SmallVec::<[Box; 2]>::new(); -} - -// https://github.com/servo/rust-smallvec/issues/5 -#[test] -fn issue_5() { - assert!(Some(SmallVec::<[&u32; 2]>::new()).is_some()); -} - -#[test] -fn test_with_capacity() { - let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(1); - assert!(v.is_empty()); - assert!(!v.spilled()); - assert_eq!(v.capacity(), 3); - - let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(10); - assert!(v.is_empty()); - assert!(v.spilled()); - assert_eq!(v.capacity(), 10); -} - -#[test] -fn drain() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.drain(..).collect::>(), &[3]); - - // spilling the vec - v.push(3); - v.push(4); - v.push(5); - let old_capacity = v.capacity(); - assert_eq!(v.drain(1..).collect::>(), &[4, 5]); - // drain should not change the capacity - assert_eq!(v.capacity(), old_capacity); - - // Exercise the tail-shifting code when in the inline state - // This has the potential to produce UB due to aliasing - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(1); - v.push(2); - assert_eq!(v.drain(..1).collect::>(), &[1]); -} - -#[test] -fn drain_rev() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.drain(..).rev().collect::>(), &[3]); - - // spilling the vec - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.drain(..).rev().collect::>(), &[5, 4, 3]); -} - -#[test] -fn drain_forget() { - let mut v: SmallVec<[u8; 1]> = smallvec![0, 1, 2, 3, 4, 5, 6, 7]; - std::mem::forget(v.drain(2..5)); - assert_eq!(v.len(), 2); -} - -#[test] -fn into_iter() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.into_iter().collect::>(), &[3]); - - // spilling the vec - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.into_iter().collect::>(), &[3, 4, 5]); -} - -#[test] -fn into_iter_rev() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.into_iter().rev().collect::>(), &[3]); - - // spilling the vec - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.into_iter().rev().collect::>(), &[5, 4, 3]); -} - -#[test] -fn into_iter_drop() { - use std::cell::Cell; - - struct DropCounter<'a>(&'a Cell); - - impl<'a> Drop for DropCounter<'a> { - fn drop(&mut self) { - self.0.set(self.0.get() + 1); - } - } - - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.into_iter(); - assert_eq!(cell.get(), 1); - } - - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - assert!(v.into_iter().next().is_some()); - assert_eq!(cell.get(), 2); - } - - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - assert!(v.into_iter().next().is_some()); - assert_eq!(cell.get(), 3); - } - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - { - let mut it = v.into_iter(); - assert!(it.next().is_some()); - assert!(it.next_back().is_some()); - } - assert_eq!(cell.get(), 3); - } -} - -#[test] -fn test_capacity() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.reserve(1); - assert_eq!(v.capacity(), 2); - assert!(!v.spilled()); - - v.reserve_exact(0x100); - assert!(v.capacity() >= 0x100); - - v.push(0); - v.push(1); - v.push(2); - v.push(3); - - v.shrink_to_fit(); - assert!(v.capacity() < 0x100); -} - -#[test] -fn test_truncate() { - let mut v: SmallVec<[Box; 8]> = SmallVec::new(); - - for x in 0..8 { - v.push(Box::new(x)); - } - v.truncate(4); - - assert_eq!(v.len(), 4); - assert!(!v.spilled()); - - assert_eq!(*v.swap_remove(1), 1); - assert_eq!(*v.remove(1), 3); - v.insert(1, Box::new(3)); - - assert_eq!(&v.iter().map(|v| **v).collect::>(), &[0, 3, 2]); -} - -#[test] -fn test_insert_many() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_many(1, [5, 6].iter().cloned()); - assert_eq!( - &v.iter().map(|v| *v).collect::>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -struct MockHintIter { - x: T, - hint: usize, -} -impl Iterator for MockHintIter { - type Item = T::Item; - fn next(&mut self) -> Option { - self.x.next() - } - fn size_hint(&self) -> (usize, Option) { - (self.hint, None) - } -} - -#[test] -fn test_insert_many_short_hint() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_many( - 1, - MockHintIter { - x: [5, 6].iter().cloned(), - hint: 5, - }, - ); - assert_eq!( - &v.iter().map(|v| *v).collect::>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -#[test] -fn test_insert_many_long_hint() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_many( - 1, - MockHintIter { - x: [5, 6].iter().cloned(), - hint: 1, - }, - ); - assert_eq!( - &v.iter().map(|v| *v).collect::>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -// https://github.com/servo/rust-smallvec/issues/96 -mod insert_many_panic { - use crate::{smallvec, SmallVec}; - use alloc::boxed::Box; - - struct PanicOnDoubleDrop { - dropped: Box, - } - - impl PanicOnDoubleDrop { - fn new() -> Self { - Self { - dropped: Box::new(false), - } - } - } - - impl Drop for PanicOnDoubleDrop { - fn drop(&mut self) { - assert!(!*self.dropped, "already dropped"); - *self.dropped = true; - } - } - - /// Claims to yield `hint` items, but actually yields `count`, then panics. - struct BadIter { - hint: usize, - count: usize, - } - - impl Iterator for BadIter { - type Item = PanicOnDoubleDrop; - fn size_hint(&self) -> (usize, Option) { - (self.hint, None) - } - fn next(&mut self) -> Option { - if self.count == 0 { - panic!() - } - self.count -= 1; - Some(PanicOnDoubleDrop::new()) - } - } - - #[test] - fn panic_early_at_start() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(0, BadIter { hint: 1, count: 0 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_early_in_middle() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(1, BadIter { hint: 4, count: 2 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_early_at_end() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(2, BadIter { hint: 3, count: 1 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_late_at_start() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(0, BadIter { hint: 3, count: 5 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_late_at_end() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(2, BadIter { hint: 3, count: 5 }); - }); - assert!(result.is_err()); - } -} - -#[test] -#[should_panic] -fn test_invalid_grow() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - v.extend(0..8); - v.grow(5); -} - -#[test] -#[should_panic] -fn drain_overflow() { - let mut v: SmallVec<[u8; 8]> = smallvec![0]; - v.drain(..=std::usize::MAX); -} - -#[test] -fn test_insert_from_slice() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_from_slice(1, &[5, 6]); - assert_eq!( - &v.iter().map(|v| *v).collect::>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -#[test] -fn test_extend_from_slice() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.extend_from_slice(&[5, 6]); - assert_eq!( - &v.iter().map(|v| *v).collect::>(), - &[0, 1, 2, 3, 5, 6] - ); -} - -#[test] -#[should_panic] -fn test_drop_panic_smallvec() { - // This test should only panic once, and not double panic, - // which would mean a double drop - struct DropPanic; - - impl Drop for DropPanic { - fn drop(&mut self) { - panic!("drop"); - } - } - - let mut v = SmallVec::<[_; 1]>::new(); - v.push(DropPanic); -} - -#[test] -fn test_eq() { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - let mut b: SmallVec<[u32; 2]> = SmallVec::new(); - let mut c: SmallVec<[u32; 2]> = SmallVec::new(); - // a = [1, 2] - a.push(1); - a.push(2); - // b = [1, 2] - b.push(1); - b.push(2); - // c = [3, 4] - c.push(3); - c.push(4); - - assert!(a == b); - assert!(a != c); -} - -#[test] -fn test_ord() { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - let mut b: SmallVec<[u32; 2]> = SmallVec::new(); - let mut c: SmallVec<[u32; 2]> = SmallVec::new(); - // a = [1] - a.push(1); - // b = [1, 1] - b.push(1); - b.push(1); - // c = [1, 2] - c.push(1); - c.push(2); - - assert!(a < b); - assert!(b > a); - assert!(b < c); - assert!(c > b); -} - -#[test] -fn test_hash() { - use std::collections::hash_map::DefaultHasher; - use std::hash::Hash; - - { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - let b = [1, 2]; - a.extend(b.iter().cloned()); - let mut hasher = DefaultHasher::new(); - assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher)); - } - { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - let b = [1, 2, 11, 12]; - a.extend(b.iter().cloned()); - let mut hasher = DefaultHasher::new(); - assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher)); - } -} - -#[test] -fn test_as_ref() { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - a.push(1); - assert_eq!(a.as_ref(), [1]); - a.push(2); - assert_eq!(a.as_ref(), [1, 2]); - a.push(3); - assert_eq!(a.as_ref(), [1, 2, 3]); -} - -#[test] -fn test_as_mut() { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - a.push(1); - assert_eq!(a.as_mut(), [1]); - a.push(2); - assert_eq!(a.as_mut(), [1, 2]); - a.push(3); - assert_eq!(a.as_mut(), [1, 2, 3]); - a.as_mut()[1] = 4; - assert_eq!(a.as_mut(), [1, 4, 3]); -} - -#[test] -fn test_borrow() { - use std::borrow::Borrow; - - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - a.push(1); - assert_eq!(a.borrow(), [1]); - a.push(2); - assert_eq!(a.borrow(), [1, 2]); - a.push(3); - assert_eq!(a.borrow(), [1, 2, 3]); -} - -#[test] -fn test_borrow_mut() { - use std::borrow::BorrowMut; - - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - a.push(1); - assert_eq!(a.borrow_mut(), [1]); - a.push(2); - assert_eq!(a.borrow_mut(), [1, 2]); - a.push(3); - assert_eq!(a.borrow_mut(), [1, 2, 3]); - BorrowMut::<[u32]>::borrow_mut(&mut a)[1] = 4; - assert_eq!(a.borrow_mut(), [1, 4, 3]); -} - -#[test] -fn test_from() { - assert_eq!(&SmallVec::<[u32; 2]>::from(&[1][..])[..], [1]); - assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]); - - let vec = vec![]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let array = [1]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from(array); - assert_eq!(&*small_vec, &[1]); - drop(small_vec); - - let array = [99; 128]; - let small_vec: SmallVec<[u8; 128]> = SmallVec::from(array); - assert_eq!(&*small_vec, vec![99u8; 128].as_slice()); - drop(small_vec); -} - -#[test] -fn test_from_slice() { - assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]); - assert_eq!( - &SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], - [1, 2, 3] - ); -} - -#[test] -fn test_exact_size_iterator() { - let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]); - assert_eq!(vec.clone().into_iter().len(), 3); - assert_eq!(vec.drain(..2).len(), 2); - assert_eq!(vec.into_iter().len(), 1); -} - -#[test] -fn test_into_iter_as_slice() { - let vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]); - let mut iter = vec.clone().into_iter(); - assert_eq!(iter.as_slice(), &[1, 2, 3]); - assert_eq!(iter.as_mut_slice(), &[1, 2, 3]); - iter.next(); - assert_eq!(iter.as_slice(), &[2, 3]); - assert_eq!(iter.as_mut_slice(), &[2, 3]); - iter.next_back(); - assert_eq!(iter.as_slice(), &[2]); - assert_eq!(iter.as_mut_slice(), &[2]); -} - -#[test] -fn test_into_iter_clone() { - // Test that the cloned iterator yields identical elements and that it owns its own copy - // (i.e. no use after move errors). - let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter(); - let mut clone_iter = iter.clone(); - while let Some(x) = iter.next() { - assert_eq!(x, clone_iter.next().unwrap()); - } - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn test_into_iter_clone_partially_consumed_iterator() { - // Test that the cloned iterator only contains the remaining elements of the original iterator. - let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter().skip(1); - let mut clone_iter = iter.clone(); - while let Some(x) = iter.next() { - assert_eq!(x, clone_iter.next().unwrap()); - } - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn test_into_iter_clone_empty_smallvec() { - let mut iter = SmallVec::<[u8; 2]>::new().into_iter(); - let mut clone_iter = iter.clone(); - assert_eq!(iter.next(), None); - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn shrink_to_fit_unspill() { - let mut vec = SmallVec::<[u8; 2]>::from_iter(0..3); - vec.pop(); - assert!(vec.spilled()); - vec.shrink_to_fit(); - assert!(!vec.spilled(), "shrink_to_fit will un-spill if possible"); -} - -#[test] -fn test_into_vec() { - let vec = SmallVec::<[u8; 2]>::from_iter(0..2); - assert_eq!(vec.into_vec(), vec![0, 1]); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..3); - assert_eq!(vec.into_vec(), vec![0, 1, 2]); -} - -#[test] -fn test_into_inner() { - let vec = SmallVec::<[u8; 2]>::from_iter(0..2); - assert_eq!(vec.into_inner(), Ok([0, 1])); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..1); - assert_eq!(vec.clone().into_inner(), Err(vec)); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..3); - assert_eq!(vec.clone().into_inner(), Err(vec)); -} - -#[test] -fn test_from_vec() { - let vec = vec![]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![1]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1]); - drop(small_vec); - - let vec = vec![1, 2, 3]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); -} - -#[test] -fn test_retain() { - // Test inline data storage - let mut sv: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]); - sv.retain(|&mut i| i != 3); - assert_eq!(sv.pop(), Some(4)); - assert_eq!(sv.pop(), Some(2)); - assert_eq!(sv.pop(), Some(1)); - assert_eq!(sv.pop(), None); - - // Test spilled data storage - let mut sv: SmallVec<[i32; 3]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]); - sv.retain(|&mut i| i != 3); - assert_eq!(sv.pop(), Some(4)); - assert_eq!(sv.pop(), Some(2)); - assert_eq!(sv.pop(), Some(1)); - assert_eq!(sv.pop(), None); - - // Test that drop implementations are called for inline. - let one = Rc::new(1); - let mut sv: SmallVec<[Rc; 3]> = SmallVec::new(); - sv.push(Rc::clone(&one)); - assert_eq!(Rc::strong_count(&one), 2); - sv.retain(|_| false); - assert_eq!(Rc::strong_count(&one), 1); - - // Test that drop implementations are called for spilled data. - let mut sv: SmallVec<[Rc; 1]> = SmallVec::new(); - sv.push(Rc::clone(&one)); - sv.push(Rc::new(2)); - assert_eq!(Rc::strong_count(&one), 2); - sv.retain(|_| false); - assert_eq!(Rc::strong_count(&one), 1); -} - -#[test] -fn test_dedup() { - let mut dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 2, 3, 3]); - dupes.dedup(); - assert_eq!(&*dupes, &[1, 2, 3]); - - let mut empty: SmallVec<[i32; 5]> = SmallVec::new(); - empty.dedup(); - assert!(empty.is_empty()); - - let mut all_ones: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 1, 1, 1]); - all_ones.dedup(); - assert_eq!(all_ones.len(), 1); - - let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]); - no_dupes.dedup(); - assert_eq!(no_dupes.len(), 5); -} - -#[test] -fn test_resize() { - let mut v: SmallVec<[i32; 8]> = SmallVec::new(); - v.push(1); - v.resize(5, 0); - assert_eq!(v[..], [1, 0, 0, 0, 0][..]); - - v.resize(2, -1); - assert_eq!(v[..], [1, 0][..]); -} - -#[cfg(feature = "write")] -#[test] -fn test_write() { - use std::io::Write; - - let data = [1, 2, 3, 4, 5]; - - let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new(); - let len = small_vec.write(&data[..]).unwrap(); - assert_eq!(len, 5); - assert_eq!(small_vec.as_ref(), data.as_ref()); - - let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new(); - small_vec.write_all(&data[..]).unwrap(); - assert_eq!(small_vec.as_ref(), data.as_ref()); -} - -#[cfg(feature = "serde")] -#[test] -fn test_serde() { - use bincode1::{config, deserialize}; - let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); - small_vec.push(1); - let encoded = config().limit(100).serialize(&small_vec).unwrap(); - let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); - assert_eq!(small_vec, decoded); - small_vec.push(2); - // Spill the vec - small_vec.push(3); - small_vec.push(4); - // Check again after spilling. - let encoded = config().limit(100).serialize(&small_vec).unwrap(); - let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); - assert_eq!(small_vec, decoded); -} - -#[test] -fn grow_to_shrink() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(1); - v.push(2); - v.push(3); - assert!(v.spilled()); - v.clear(); - // Shrink to inline. - v.grow(2); - assert!(!v.spilled()); - assert_eq!(v.capacity(), 2); - assert_eq!(v.len(), 0); - v.push(4); - assert_eq!(v[..], [4]); -} - -#[test] -fn resumable_extend() { - let s = "a b c"; - // This iterator yields: (Some('a'), None, Some('b'), None, Some('c')), None - let it = s - .chars() - .scan(0, |_, ch| if ch.is_whitespace() { None } else { Some(ch) }); - let mut v: SmallVec<[char; 4]> = SmallVec::new(); - v.extend(it); - assert_eq!(v[..], ['a']); -} - -// #139 -#[test] -fn uninhabited() { - enum Void {} - let _sv = SmallVec::<[Void; 8]>::new(); -} - -#[test] -fn grow_spilled_same_size() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(0); - v.push(1); - v.push(2); - assert!(v.spilled()); - assert_eq!(v.capacity(), 4); - // grow with the same capacity - v.grow(4); - assert_eq!(v.capacity(), 4); - assert_eq!(v[..], [0, 1, 2]); -} - -#[cfg(feature = "const_generics")] -#[test] -fn const_generics() { - let _v = SmallVec::<[i32; 987]>::default(); -} - -#[cfg(feature = "const_new")] -#[test] -fn const_new() { - let v = const_new_inner(); - assert_eq!(v.capacity(), 4); - assert_eq!(v.len(), 0); - let v = const_new_inline_sized(); - assert_eq!(v.capacity(), 4); - assert_eq!(v.len(), 4); - assert_eq!(v[0], 1); - let v = const_new_inline_args(); - assert_eq!(v.capacity(), 2); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 1); - assert_eq!(v[1], 4); - let v = const_new_with_len(); - assert_eq!(v.capacity(), 4); - assert_eq!(v.len(), 3); - assert_eq!(v[0], 2); - assert_eq!(v[1], 5); - assert_eq!(v[2], 7); -} -#[cfg(feature = "const_new")] -const fn const_new_inner() -> SmallVec<[i32; 4]> { - SmallVec::<[i32; 4]>::new_const() -} -#[cfg(feature = "const_new")] -const fn const_new_inline_sized() -> SmallVec<[i32; 4]> { - crate::smallvec_inline![1; 4] -} -#[cfg(feature = "const_new")] -const fn const_new_inline_args() -> SmallVec<[i32; 2]> { - crate::smallvec_inline![1, 4] -} -#[cfg(feature = "const_new")] -const fn const_new_with_len() -> SmallVec<[i32; 4]> { - unsafe { SmallVec::<[i32; 4]>::from_const_with_len_unchecked([2, 5, 7, 0], 3) } -} - -#[test] -fn empty_macro() { - let _v: SmallVec<[u8; 1]> = smallvec![]; -} - -#[test] -fn zero_size_items() { - SmallVec::<[(); 0]>::new().push(()); -} - -#[test] -fn test_insert_many_overflow() { - let mut v: SmallVec<[u8; 1]> = SmallVec::new(); - v.push(123); - - // Prepare an iterator with small lower bound - let iter = (0u8..5).filter(|n| n % 2 == 0); - assert_eq!(iter.size_hint().0, 0); - - v.insert_many(0, iter); - assert_eq!(&*v, &[0, 2, 4, 123]); -} - -#[test] -fn test_clone_from() { - let mut a: SmallVec<[u8; 2]> = SmallVec::new(); - a.push(1); - a.push(2); - a.push(3); - - let mut b: SmallVec<[u8; 2]> = SmallVec::new(); - b.push(10); - - let mut c: SmallVec<[u8; 2]> = SmallVec::new(); - c.push(20); - c.push(21); - c.push(22); - - a.clone_from(&b); - assert_eq!(&*a, &[10]); - - b.clone_from(&c); - assert_eq!(&*b, &[20, 21, 22]); -} - -#[test] -fn test_size() { - use core::mem::size_of; - const PTR_SIZE: usize = size_of::(); - #[cfg(feature = "union")] - { - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(4 * PTR_SIZE, size_of::>()); - } - #[cfg(not(feature = "union"))] - { - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(3 * PTR_SIZE, size_of::>()); - assert_eq!(4 * PTR_SIZE, size_of::>()); - } -} - -#[cfg(feature = "drain_filter")] -#[test] -fn drain_filter() { - let mut a: SmallVec<[u8; 2]> = smallvec![1u8, 2, 3, 4, 5, 6, 7, 8]; - - let b: SmallVec<[u8; 2]> = a.drain_filter(|x| *x % 3 == 0).collect(); - - assert_eq!(a, SmallVec::<[u8; 2]>::from_slice(&[1u8, 2, 4, 5, 7, 8])); - assert_eq!(b, SmallVec::<[u8; 2]>::from_slice(&[3u8, 6])); -} - -#[cfg(feature = "drain_keep_rest")] -#[test] -fn drain_keep_rest() { - let mut a: SmallVec<[i32; 3]> = smallvec![1i32, 2, 3, 4, 5, 6, 7, 8]; - let mut df = a.drain_filter(|x| *x % 2 == 0); - - assert_eq!(df.next().unwrap(), 2); - assert_eq!(df.next().unwrap(), 4); - - df.keep_rest(); - - assert_eq!(a, SmallVec::<[i32; 3]>::from_slice(&[1i32, 3, 5, 6, 7, 8])); -} - -/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments -/// given to SmallVec. Draining and extending the allocation are fairly well-tested earlier, but -/// `smallvec.insert(usize::MAX, val)` once slipped by! -/// -/// All code that indexes into SmallVecs should be tested with such "trivially wrong" args. -#[test] -fn max_dont_panic() { - let mut sv: SmallVec<[i32; 2]> = smallvec![0]; - let _ = sv.get(usize::MAX); - sv.truncate(usize::MAX); -} - -#[test] -#[should_panic] -fn max_remove() { - let mut sv: SmallVec<[i32; 2]> = smallvec![0]; - sv.remove(usize::MAX); -} - -#[test] -#[should_panic] -fn max_swap_remove() { - let mut sv: SmallVec<[i32; 2]> = smallvec![0]; - sv.swap_remove(usize::MAX); -} - -#[test] -#[should_panic] -fn test_insert_out_of_bounds() { - let mut v: SmallVec<[i32; 4]> = SmallVec::new(); - v.insert(10, 6); -} - -#[cfg(feature = "impl_bincode")] -#[test] -fn test_bincode() { - let config = bincode::config::standard(); - let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); - let mut buffer = [0u8; 128]; - small_vec.push(1); - let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); - let (decoded, bytes_read) = - bincode::decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - let (decoded, bytes_read) = - bincode::borrow_decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - // Spill the vec - small_vec.push(2); - small_vec.push(3); - small_vec.push(4); - // Check again after spilling. - let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); - let (decoded, bytes_read) = - bincode::decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - let (decoded, bytes_read) = - bincode::borrow_decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); -} - -#[cfg(feature = "impl_bincode")] -#[test] -fn test_bincode_u8() { - let config = bincode::config::standard(); - let mut small_vec: SmallVec<[u8; 16]> = SmallVec::new(); - let mut buffer = [0u8; 128]; - small_vec.extend_from_slice(b"testing test"); - let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); - let (decoded, bytes_read) = - bincode::decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - let (decoded, bytes_read) = - bincode::borrow_decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - // Spill the vec - small_vec.extend_from_slice(b"some more testing"); - // Check again after spilling. - let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); - let (decoded, bytes_read) = - bincode::decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); - let (decoded, bytes_read) = - bincode::borrow_decode_from_slice::, _>(&buffer, config).unwrap(); - assert_eq!(bytes_written, bytes_read); - assert_eq!(small_vec, decoded); -} diff --git a/vendor/makepad/platform/script/Cargo.toml b/vendor/makepad/platform/script/Cargo.toml deleted file mode 100644 index 1b41a6e..0000000 --- a/vendor/makepad/platform/script/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "makepad-script" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad script (octoscript)" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "yK9xdn_D0D3EdqleI-WHLtjk4rk=" - -[features] -default = ["check_gen"] -check_gen = [] - -[dependencies] -makepad-error-log = {path = "../../libs/error_log", version = "1.0.0" } -makepad-math = {path = "../../libs/math", version = "1.0.0" } -makepad-live-id = {path = "../../libs/live_id", version = "1.0.0" } -makepad-script-derive = {path = "./derive", version = "1.0.0" } -smallvec = { version = "1.15", path = "../../libs/smallvec" } -makepad-regex = {path = "../../libs/regex", version = "0.1.0" } -makepad-html = {path = "../../libs/html", version = "1.0.0" } diff --git a/vendor/makepad/platform/script/build.rs b/vendor/makepad/platform/script/build.rs deleted file mode 100644 index f328e4d..0000000 --- a/vendor/makepad/platform/script/build.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/vendor/makepad/platform/script/derive/Cargo.toml b/vendor/makepad/platform/script/derive/Cargo.toml deleted file mode 100644 index ad4357e..0000000 --- a/vendor/makepad/platform/script/derive/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "makepad-script-derive" -version = "1.0.0" -authors = ["Makepad "] -edition = "2021" -description = "Makepad octoscript derive macro" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/makepad/makepad/" -repository = "https://github.com/makepad/makepad/" -metadata.makepad-auto-version = "tSPvEgfuhrUzpofjMUEzGZksHSo=" - -[lib] -proc-macro = true - -[dependencies] -makepad-micro-proc-macro = { path = "../../../libs/micro_proc_macro", version = "1.0.0" } - diff --git a/vendor/makepad/platform/script/derive/src/derive_scriptable.rs b/vendor/makepad/platform/script/derive/src/derive_scriptable.rs deleted file mode 100644 index 64b9d5f..0000000 --- a/vendor/makepad/platform/script/derive/src/derive_scriptable.rs +++ /dev/null @@ -1,1042 +0,0 @@ -use proc_macro::TokenStream; - -use makepad_micro_proc_macro::{error_result, Attribute, StructField, TokenBuilder, TokenParser}; - -pub fn derive_script_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - if let Err(err) = derive_script_impl_inner(&mut parser, &mut tb) { - err - } else { - tb.end() - } -} - -fn derive_script_impl_inner( - parser: &mut TokenParser, - tb: &mut TokenBuilder, -) -> Result<(), TokenStream> { - let main_attribs = parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - let struct_name = parser.expect_any_ident()?; - let generic = parser.eat_generic(); - let types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(None); - - let mut fields = if let Some(_types) = types { - return error_result("Unexpected type form"); - } else if let Some(fields) = parser.eat_all_struct_fields() { - fields - } else { - return error_result("Unexpected field form"); - }; - - for field in &mut fields { - if field.attrs.is_empty() { - // need field def - return error_result("Please annotate the field type with #[rust] for rust-only fields, #[live] for scriptable mapped fields, #[apply_default] for scriptable fields with default application, #[deref] for a base class, #[script] to call script_new, or #[self] for a ScriptObjectRef to the object being applied"); - } - } - - // Deref - - let deref_field = fields - .iter() - .find(|field| field.attrs.iter().any(|a| a.name == "deref")); - - if let Some(deref_field) = deref_field { - tb.add("impl").stream(generic.clone()); - tb.add("std::ops::Deref for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - tb.add(" type Target = ") - .stream(Some(deref_field.ty.clone())) - .add(";"); - tb.add(" fn deref(&self) -> &Self::Target {&self.") - .ident(&deref_field.name) - .add("}"); - tb.add("}"); - tb.add("impl").stream(generic.clone()); - - tb.add("std::ops::DerefMut for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - tb.add(" fn deref_mut(&mut self) -> &mut Self::Target {&mut self.") - .ident(&deref_field.name) - .add("}"); - tb.add("}"); - } - - // marker - tb.add("impl").stream(generic.clone()); - tb.add("ScriptDeriveMarker for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{}"); - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptHookDeref for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - tb.add(" fn on_deref_before_apply(&mut self, vm:&mut ScriptVm, apply:&Apply, scope:&mut Scope, value:ScriptValue){"); - tb.add(" ::on_before_apply(self, vm, apply, scope, value);"); - tb.add(" ::on_before_dispatch(self, vm, apply, scope, value);"); - tb.add(" }"); - - tb.add(" fn on_deref_after_apply(&mut self,vm: &mut ScriptVm, apply:&Apply, scope:&mut Scope, value:ScriptValue){"); - - tb.add(" ::on_after_apply(self, vm, apply, scope, value);"); - tb.add(" ::on_after_dispatch(self, vm, apply, scope, value);"); - tb.add(" }"); - tb.add("}"); - - // ScriptApply - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptApply for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - - tb.add(" fn script_type_id(&self)->ScriptTypeId{ ScriptTypeId::of::()}"); - - tb.add(" fn script_apply(&mut self, vm:&mut ScriptVm, apply:&Apply, scope:&mut Scope, value:ScriptValue) {"); - tb.add(" if ::on_custom_apply(self, vm, apply, scope, value) || value.is_nil(){return};"); - tb.add(" ::on_deref_before_apply(self, vm, apply, scope, value);"); - - let ui_root_field = fields.iter().find_map(|field| { - let ty = field.ty.to_string().replace(' ', ""); - if field.name == "ui" && (ty == "WidgetRef" || ty.ends_with("::WidgetRef")) { - Some(field.name.clone()) - } else { - None - } - }); - - // Declare variables for apply_default fields to store their dirty values - - for field in &fields { - // Handle #[source] field specially - only update during New/Reload, NOT during Eval - // Eval creates temporary prototype objects that shouldn't become the permanent source - if field.attrs.iter().any(|a| a.name == "source") { - tb.add("if !apply.is_eval() && apply.is_from_script() {"); - tb.add(" if let Some(obj) = value.as_object() {"); - tb.add(" self.") - .ident(&field.name) - .add(" = vm.bx.heap.new_object_ref(obj);"); - tb.add(" }"); - tb.add("}"); - } else if field - .attrs - .iter() - .any(|a| a.name == "live" || a.name == "apply_default") - { - tb.add("{ let mut __field_value = vm.bx.heap.value_for_apply(value, id!(") - .ident(&field.name) - .add(").into(), apply);"); - tb.add("if __field_value.is_none() && apply.is_reload(){"); - tb.add(" let default_value = <") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_reload_default(vm);"); - tb.add(" if !default_value.is_nil(){"); - tb.add(" __field_value = Some(default_value);"); - tb.add(" }"); - tb.add("}"); - tb.add("if let Some(v) = __field_value {"); - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_apply(&mut self.") - .ident(&field.name) - .add(",vm, apply, scope, v);"); - tb.add("}"); - tb.add("}"); - } - if field - .attrs - .iter() - .any(|a| a.name == "splat" || a.name == "walk" || a.name == "layout") - { - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_apply(&mut self.") - .ident(&field.name) - .add(", vm, apply, scope, value);"); - } - } - - if let Some(field_name) = &ui_root_field { - tb.add("self.") - .ident(field_name) - .add(".register_as_ui_root(vm);"); - } - - // Deref'd fields are applied BEFORE apply_default's recursive apply. - // - // Why this order matters: an `#[apply_default]` field (always an - // `Animator` in practice) returns an apply block describing how the - // widget's runtime fields should look in its current state — e.g. - // `{ height: 0 }` for a "hidden" state. The recursive call then - // re-walks the widget with that block as the value, setting the - // matching widget fields. If the deref'd field's `script_apply` - // (which reapplies the widget's *template* defaults via the inner - // base widget) ran AFTER this, it would overwrite the animator's - // state-driven values with the template defaults, leaving the - // widget visually in its template state for the rest of the apply - // pass. On `Apply::ScriptReapply` that produces the "flicker to - // defaults" most users notice when a preference change forces a - // tree-wide re-walk: every animator-driven widget briefly drops - // back to its template visual until the next event handler patches - // it up. Running deref first and apply_default's recursive last - // means the animator's apply block wins, the widget never visibly - // touches its template default, and `Animator::script_apply_default` - // can return the *current* state's apply on `ScriptReapply` to - // restore the runtime visual state in a single pass. - for field in &fields { - if field.attrs.iter().any(|a| a.name == "deref") { - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_apply(&mut self.") - .ident(&field.name) - .add(", vm, apply, scope, value);"); - } - } - - for field in &fields { - if field.attrs.iter().any(|a| a.name == "apply_default") { - tb.add(" if let Some(default_value) = <") - .stream(Some(field.ty.clone())) - .add(" as ScriptApplyDefault>::script_apply_default(&mut self.") - .ident(&field.name) - .add(",vm, apply, scope, value){"); - tb.add(" self.script_apply(vm, &Apply::Default(apply.as_default().map_or(0, |x| x + 1)), scope, default_value);"); - tb.add(" }"); - } - } - - tb.add(" ::on_deref_after_apply(self, vm, apply, scope, value);"); - tb.add(" }"); - - tb.add(" fn script_to_value(&self, vm: &mut ScriptVm)->ScriptValue {"); - - tb.add(" let proto = Self::script_proto(vm).into();"); - tb.add(" let obj = vm.bx.heap.new_with_proto(proto);"); - tb.add(" self.script_to_value_props(vm, obj);"); - tb.add(" obj.into()"); - tb.add(" }"); - - tb.add(" fn script_to_value_props(&self, vm: &mut ScriptVm, obj:ScriptObject) {"); - - for field in &fields { - if field.attrs.iter().find(|a| a.name == "deref").is_some() { - tb.add("self.") - .ident(&field.name) - .add(".script_to_value_props(vm, obj);"); - } - // Also cascade walk/layout/splat fields' properties to the object - if field - .attrs - .iter() - .find(|a| a.name == "walk" || a.name == "layout" || a.name == "splat") - .is_some() - { - tb.add("self.") - .ident(&field.name) - .add(".script_to_value_props(vm, obj);"); - } - if let Some(_) = field - .attrs - .iter() - .find(|a| a.name == "live" || a.name == "apply_default") - { - tb.add("let value:ScriptValue = <") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_to_value( &self.") - .ident(&field.name) - .add(", vm); "); - tb.add("vm.bx.heap.set_value(obj, ScriptValue::from_id(id_lut!(") - .ident(&field.name) - .add(")), value, vm.bx.threads.cur().trap.pass());"); - } - } - - tb.add(" }"); - - // Generate script_source if there's a #[source] field - let source_field = fields - .iter() - .find(|field| field.attrs.iter().any(|a| a.name == "source")); - if let Some(source_field) = source_field { - tb.add(" fn script_source(&self) -> ScriptObject {self.") - .ident(&source_field.name) - .add(".as_object()"); - tb.add(" }"); - } - - tb.add("}"); - - // ScriptNew - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptNew for") - .ident(&struct_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - - tb.add(" fn script_type_id_static()->ScriptTypeId{ ScriptTypeId::of::()}"); - tb.add(" fn script_type_name()->Option{ Some(id_lut!(") - .ident(&struct_name) - .add(")) }"); - - tb.add(" fn script_new(vm: &mut ScriptVm) -> Self {"); - tb.add(" Self {"); - for field in &fields { - tb.ident(&field.name).add(":"); - - if let Some(attr) = field.attrs.iter().find(|a| { - a.name == "new" - || a.name == "live" - || a.name == "apply_default" - || a.name == "deref" - || a.name == "rust" - || a.name == "source" - || a.name == "uid" - }) { - if attr.args.is_none() || attr.args.as_ref().unwrap().is_empty() { - if attr.name == "live" - || attr.name == "apply_default" - || attr.name == "new" - || attr.name == "deref" - { - tb.add("ScriptNew::script_new_with_default(vm)"); - } else if attr.name == "uid" { - tb.add("WidgetUid::new()"); - } else { - tb.add("Default::default()"); - } - } else { - tb.add("(").stream(attr.args.clone()).add(").into()"); - } - } else { - tb.add("Default::default()"); - } - tb.add(","); - } - tb.add(" }"); - tb.add(" }"); - - tb.add(" fn script_proto_props(vm: &mut ScriptVm, obj:ScriptObject, props:&mut ScriptTypeProps) {"); - - for (_, field) in fields.iter().enumerate() { - // Process deref field - mark rust_instance_start before adding parent fields - // This marks where the actual Rust instance data begins (excluding config fields above) - if field.attrs.iter().find(|a| a.name == "deref").is_some() { - tb.add("props.mark_rust_instance_start();"); - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_proto_props(vm, obj, props);"); - } - - // Process walk and layout fields - cascade their props like deref but without marking rust_instance_start - if field - .attrs - .iter() - .find(|a| a.name == "walk" || a.name == "layout" || a.name == "splat") - .is_some() - { - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_proto_props(vm, obj, props);"); - } - - // Process live and apply_default fields after deref (or when no deref exists) - if let Some(_attr) = field - .attrs - .iter() - .find(|a| a.name == "live" || a.name == "apply_default") - { - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_proto(vm);"); - tb.add("props.insert(id_lut!(") - .ident(&field.name) - .add("),<") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_type_id_static());"); - } - } - - tb.add(" }"); - tb.add("}"); - - if main_attribs.iter().any(|attr| attr.name == "debug_print") { - tb.eprint(); - } - - return Ok(()); - } else if parser.eat_ident("enum") { - let enum_name = parser.expect_any_ident()?; - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(None); - - if !parser.open_brace() { - return error_result("cant find open brace for enum"); - } - - struct EnumItem { - name: String, - attributes: Vec, - kind: EnumKind, - discriminant: Option, // For repr(u32) enums - can be any expression - } - - enum EnumKind { - Bare, - Named(Vec), - Tuple(Vec), - } - let mut items = Vec::new(); - - impl EnumItem { - fn gen_new(&self, tb: &mut TokenBuilder) -> Result<(), TokenStream> { - tb.add("Self::").ident(&self.name); - match &self.kind { - EnumKind::Bare => (), - EnumKind::Named(_) => { - if self.attributes.len() != 1 { - return error_result( - "For named and typle enums please provide default values", - ); - } - tb.add("{").stream(self.attributes[0].args.clone()).add("}"); - } - EnumKind::Tuple(_) => { - if self.attributes.len() != 1 { - return error_result( - "For named and typle enums please provide default values", - ); - } - tb.add("(").stream(self.attributes[0].args.clone()).add(")"); - } - } - Ok(()) - } - } - - let mut pick = None; - while !parser.eat_eot() { - let attributes = parser.eat_attributes(); - // check if we have a default attribute - if let Some(name) = parser.eat_any_ident() { - if attributes - .iter() - .any(|a| a.name == "pick" || a.name == "default") - { - if pick.is_some() { - return error_result("Enum can only have a single field marked pick"); - } - pick = Some(items.len()) - } - if let Some(types) = parser.eat_all_types() { - items.push(EnumItem { - name, - attributes, - kind: EnumKind::Tuple(types), - discriminant: None, - }); - parser.eat_level_or_punct(','); - } else if let Some(fields) = parser.eat_all_struct_fields() { - // named variant - items.push(EnumItem { - name, - attributes, - kind: EnumKind::Named(fields), - discriminant: None, - }); - parser.eat_level_or_punct(','); - } else { - // Check for discriminant value (= expr) for bare variants - let discriminant = if parser.eat_punct_alone('=') { - // Capture everything until comma as the discriminant expression - // Note: eat_level_or_punct already consumes the comma - Some(parser.eat_level_or_punct(',')) - } else { - parser.eat_level_or_punct(','); - None - }; - items.push(EnumItem { - name, - attributes, - kind: EnumKind::Bare, - discriminant, - }) - } - } else { - parser.eat_level_or_punct(','); - } - } - - if pick.is_none() { - return error_result("Enum needs atleast one field marked pick"); - } - - // marker - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptDeriveMarker for") - .ident(&enum_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{}"); - - // ScriptNew - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptNew for") - .ident(&enum_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - - tb.add(" fn script_type_id_static()->ScriptTypeId{ScriptTypeId::of::()}"); - tb.add(" fn script_type_name()->Option{ Some(id_lut!(") - .ident(&enum_name) - .add(")) }"); - tb.add(" fn script_new(vm:&mut ScriptVm)->Self{"); - tb.add(" "); - items[pick.unwrap()].gen_new(tb)?; - tb.add(" "); - tb.add(" }"); - - tb.add(" fn script_default(vm:&mut ScriptVm)->ScriptValue{"); - tb.add(" Self::script_proto(vm);"); - tb.add(" Self::script_new(vm).script_to_value(vm)"); - tb.add(" }"); - - // For enums, script_new_with_default should always return the #[pick] variant, - // not use the type default (which is the enum API object with all variants) - tb.add(" fn script_new_with_default(vm:&mut ScriptVm)->Self{"); - tb.add(" Self::script_new(vm)"); - tb.add(" }"); - - tb.add(" fn script_reload_default(vm:&mut ScriptVm)->ScriptValue{"); - tb.add( - " if vm.bx.heap.type_default_for_id(Self::script_type_id_static()).is_some(){", - ); - tb.add(" Self::script_new_with_default(vm).script_to_value(vm)"); - tb.add(" } else {"); - tb.add(" NIL"); - tb.add(" }"); - tb.add(" }"); - - tb.add(" fn script_type_check(heap:&ScriptHeap, value:ScriptValue)->bool{"); - tb.add(" if ::on_type_check(heap, value){"); - tb.add(" return true"); - tb.add(" }"); - tb.add(" if let Some(o) = value.as_object(){"); - tb.add(" let root_proto = heap.root_proto(o);"); - tb.add(" if let Some(id) = root_proto.as_id(){"); - tb.add(" return match id{"); - for item in &items { - tb.add(" id!(") - .ident(&item.name) - .add(")=>true,"); - } - tb.add(" _=>false"); - tb.add(" }"); - tb.add(" }"); - tb.add(" }"); - tb.add(" false"); - tb.add(" }"); - - // Check if any variant has a discriminant (indicating repr(u32) enum) - let has_discriminant = items.iter().any(|item| item.discriminant.is_some()); - if has_discriminant { - tb.add(" fn is_repr_u32_enum() -> bool { true }"); - } - - tb.add(" fn script_proto_build(vm:&mut ScriptVm, _props:&mut ScriptTypeProps)->ScriptValue{"); - tb.add(" let enum_object = vm.bx.heap.new_object();"); - - for item in &items { - match &item.kind { - EnumKind::Bare => { - tb.add("let bare = vm.bx.heap.new_with_proto(id_lut!(") - .ident(&item.name) - .add(").into());"); - // If this is a repr(u32) enum, store the discriminant value as f64 - if let Some(disc) = &item.discriminant { - tb.add("vm.bx.heap.set_value(bare, id!(_repr_u32_enum_value).into(), ScriptValue::from((").stream(Some(disc.clone())).add(") as f64), vm.bx.threads.cur().trap.pass());"); - } - tb.add("vm.bx.heap.set_value(enum_object, id!(") - .ident(&item.name) - .add(").into(), bare.into(), vm.bx.threads.cur().trap.pass());"); - tb.add("vm.bx.heap.freeze(bare);"); - } - EnumKind::Tuple(args) => { - for arg in args.iter() { - tb.add("<") - .stream(Some(arg.clone())) - .add(" as ScriptNew>::script_proto(vm);"); - } - tb.add("vm.add_method(enum_object, id_lut!(") - .ident(&item.name) - .add("), &[], |vm, args|{"); - tb.add(" let tuple = vm.bx.heap.new_with_proto(id!(") - .ident(&item.name) - .add(").into());"); - tb.add(" if vm.bx.heap.vec_len(args) != ") - .unsuf_usize(args.len()) - .add("{"); - tb.add(" makepad_script::script_err_invalid_args!(vm.bx.threads.cur().trap, \"wrong argument count\");"); - tb.add(" }"); - for (i, arg) in args.iter().enumerate() { - tb.add("if let Some(a) = vm.bx.heap.vec_value_if_exist(args, ") - .unsuf_usize(i) - .add("){"); - tb.add(" if!<") - .stream(Some(arg.clone())) - .add(" as ScriptNew>::script_type_check(&vm.bx.heap, a){"); - tb.add(" makepad_script::script_err_type_mismatch!(vm.bx.threads.cur().trap, \"argument type mismatch\");"); - tb.add(" }"); - tb.add("}"); - } - tb.add(" vm.bx.heap.vec_push_vec(tuple, args, vm.bx.threads.cur().trap.pass());"); - tb.add(" tuple.into()"); - tb.add("});"); - } - EnumKind::Named(fields) => { - tb.add("let def ="); - item.gen_new(tb)?; - tb.add(";"); - tb.add("let named = vm.bx.heap.new_with_proto(id_lut!(") - .ident(&item.name) - .add(").into());"); - tb.add("let mut props = ScriptTypeProps::default();"); - tb.add("if let Self::").ident(&item.name).add("{"); - for (i, field) in fields.iter().enumerate() { - tb.ident(&field.name) - .add(":") - .ident(&format!("v{i}")) - .add(","); - } - tb.add("} = def{"); - for (i, field) in fields.iter().enumerate() { - tb.add("let value = ") - .ident(&format!("v{i}")) - .add(".script_to_value(vm);"); - // Register the field type first (like structs do) so type checking works - tb.add("<") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_proto(vm);"); - tb.add("props.insert(id_lut!(") - .ident(&field.name) - .add("), <") - .stream(Some(field.ty.clone())) - .add(" as ScriptNew>::script_type_id_static());"); - tb.add(" vm.bx.heap.set_value(named, id!(") - .ident(&field.name) - .add(").into(), value, vm.bx.threads.cur().trap.pass());"); - } - tb.add("}"); - tb.add("let ty_check = ScriptTypeCheck{props, object: None, is_repr_u32_enum: false};"); - tb.add("let ty_index = vm.bx.heap.register_type(None, ty_check);"); - tb.add("vm.bx.heap.set_type(named, ty_index);"); - tb.add("vm.bx.heap.freeze_component(named);"); - tb.add("vm.bx.heap.set_value(enum_object, id!(") - .ident(&item.name) - .add(").into(), named.into(), vm.bx.threads.cur().trap.pass());"); - // uh oh crap. we need to get the default value out of the unparsed defaults - } - } - } - tb.add(" enum_object.into()"); - tb.add(" }"); - tb.add("}"); - - // ScriptApply - - tb.add("impl").stream(generic.clone()); - tb.add("ScriptApply for") - .ident(&enum_name) - .stream(generic.clone()) - .stream(where_clause.clone()) - .add("{"); - - tb.add(" fn script_type_id(&self)->ScriptTypeId{ScriptTypeId::of::()}"); - tb.add(" fn script_apply(&mut self, vm:&mut ScriptVm, apply:&Apply, scope:&mut Scope, value:ScriptValue){"); - tb.add(" if self.on_custom_apply(vm, apply, scope, value){"); - tb.add(" return"); - tb.add(" }"); - tb.add(" if let Some(object) = value.as_object(){"); - tb.add(" let root_proto = vm.bx.heap.root_proto(object);"); - tb.add(" if let Some(id) = root_proto.as_id(){"); - tb.add(" match id{"); - for item in &items { - match &item.kind { - EnumKind::Bare => { - tb.add(" id!(").ident(&item.name).add(")=>{"); - tb.add(" *self = Self::") - .ident(&item.name) - .add(";"); - tb.add(" return;"); - tb.add(" }"); - } - EnumKind::Tuple(args) => { - tb.add(" id!(").ident(&item.name).add(")=>{"); - tb.add(" if let Self::") - .ident(&item.name) - .add("(..) = self{}else{"); - tb.add(" *self = "); - item.gen_new(tb)?; - tb.add(";"); - tb.add(" }"); - tb.add(" if let Self::") - .ident(&item.name) - .add("("); - for i in 0..args.len() { - tb.ident(&format!("v{i}")).add(","); - } - tb.add(") = self{"); - for (i, arg) in args.iter().enumerate() { - tb.add( - " if let Some(v) = vm.bx.heap.vec_value_if_exist(object, ", - ) - .unsuf_usize(i) - .add("){"); - tb.add(" <") - .stream(Some(arg.clone())) - .add(" as ScriptApply>::script_apply(") - .ident(&format!("v{i}")) - .add(", vm, apply, scope, v);"); - tb.add(" }"); - } - tb.add(" }"); - tb.add(" return;"); - tb.add(" }"); - } - EnumKind::Named(fields) => { - tb.add(" id!(").ident(&item.name).add(")=>{"); - tb.add(" if let Self::") - .ident(&item.name) - .add("{..} = self{}else{"); - tb.add(" *self = "); - item.gen_new(tb)?; - tb.add(";"); - tb.add(" }"); - tb.add(" if let Self::") - .ident(&item.name) - .add("{"); - for (i, field) in fields.iter().enumerate() { - tb.ident(&field.name) - .add(":") - .ident(&format!("v{i}")) - .add(","); - } - tb.add("} = self{"); - for (i, field) in fields.iter().enumerate() { - tb.add("if let Some(v) = vm.bx.heap.value_for_apply(value, ScriptValue::from_id(id!(").ident(&field.name).add(")), apply){"); - tb.add(" <") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_apply(") - .ident(&format!("v{i}")) - .add(", vm, apply, scope, v);"); - tb.add("}"); - } - tb.add(" }"); - tb.add(" return;"); - tb.add(" }"); - } - } - } - tb.add(" other=>{"); - tb.add(" let obj_desc = vm.format_object_for_error(object);"); - tb.add(" makepad_script::script_err_unknown_type!(vm.bx.threads.cur().trap,").string(&format!("unknown variant '{{}}' for enum {}, object: {{}}", enum_name)).add(", other, obj_desc);"); - tb.add(" return;"); - tb.add(" }"); - tb.add(" }"); - tb.add(" }"); - tb.add(" else{"); - tb.add(" let obj_desc = vm.format_object_for_error(object);"); - tb.add( - " makepad_script::script_err_unknown_type!(vm.bx.threads.cur().trap,", - ) - .string(&format!( - "expected variant id for enum {}, got object: {{}}", - enum_name - )) - .add(", obj_desc);"); - tb.add(" return;"); - tb.add(" }"); - tb.add(" }"); - tb.add(" let value_desc = vm.format_enum_variant_error(value);"); - tb.add(" makepad_script::script_err_unknown_type!(vm.bx.threads.cur().trap,") - .string(&format!( - "expected variant for enum {}, got {{}}", - enum_name - )) - .add(", value_desc);"); - tb.add(" }"); - - tb.add(" fn script_to_value(&self, vm:&mut ScriptVm)->ScriptValue{"); - tb.add(" match self{"); - for item in &items { - match &item.kind { - EnumKind::Bare => { - tb.add("Self::").ident(&item.name).add("=>{"); - tb.add(" Self::script_enum_lookup_variant(vm,id!(") - .ident(&item.name) - .add("))"); - tb.add("}"); - } - EnumKind::Tuple(args) => { - tb.add("Self::").ident(&item.name).add("("); - for i in 0..args.len() { - tb.ident(&format!("v{i}")).add(","); - } - tb.add(")=>{"); - tb.add(" let tuple = vm.bx.heap.new_with_proto(id!(") - .ident(&item.name) - .add(").into());"); - for (i, arg) in args.iter().enumerate() { - tb.add("let value = <") - .stream(Some(arg.clone())) - .add(" as ScriptApply>::script_to_value(") - .ident(&format!("v{i}")) - .add(",vm);"); - tb.add("vm.bx.heap.vec_push(tuple, NIL, value, vm.bx.threads.cur().trap.pass());"); - } - tb.add(" tuple.into()"); - tb.add("}"); - } - EnumKind::Named(fields) => { - tb.add("Self::").ident(&item.name).add("{"); - for (i, field) in fields.iter().enumerate() { - tb.ident(&field.name) - .add(":") - .ident(&format!("v{i}")) - .add(","); - } - tb.add("}=>{"); - tb.add(" let proto = Self::script_enum_lookup_variant(vm,id!(") - .ident(&item.name) - .add("));"); - tb.add(" let named = vm.bx.heap.new_with_proto(proto);"); - for (i, field) in fields.iter().enumerate() { - tb.add("let value = <") - .stream(Some(field.ty.clone())) - .add(" as ScriptApply>::script_to_value(") - .ident(&format!("v{i}")) - .add(", vm);"); - tb.add("vm.bx.heap.set_value(named, id!(") - .ident(&field.name) - .add(").into(), value, vm.bx.threads.cur().trap.pass());"); - } - tb.add(" named.into()"); - tb.add("}"); - } - } - } - tb.add(" }"); - tb.add(" }"); - - tb.add("}"); - - Ok(()) - } else { - error_result("Not enum or struct") - } -} - -pub fn derive_script_hook_impl(input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let mut parser = TokenParser::new(input); - let _main_attribs = parser.eat_attributes(); - parser.eat_ident("pub"); - if parser.eat_ident("struct") { - if let Some(struct_name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let _types = parser.eat_all_types(); - let where_clause = parser.eat_where_clause(None); //Some("LiveUpdateHooks")); - tb.add("impl").stream(generic.clone()); - tb.add("ScriptHook for") - .ident(&struct_name) - .stream(generic) - .stream(where_clause) - .add("{}"); - return tb.end(); - } - } else if parser.eat_ident("enum") { - if let Some(enum_name) = parser.eat_any_ident() { - let generic = parser.eat_generic(); - let where_clause = parser.eat_where_clause(None); - tb.add("impl").stream(generic.clone()); - tb.add("ScriptHook for") - .ident(&enum_name) - .stream(generic) - .stream(where_clause) - .add("{}"); - return tb.end(); - } - } - parser.unexpected() -} -/* - -//#[derive(Script)] -#[allow(unused)] -pub enum EnumTest{ - // #[pick] - Bare, - Tuple(f64), - Named{named_field:f64} -} - -impl ScriptHook for EnumTest{ -} - -impl ScriptNew for EnumTest{ - fn script_type_id_static()->ScriptTypeId{ScriptTypeId::of::()} - fn script_new(vm:&mut ScriptVm)->Self{let mut ret = Self::Bare; ret.on_new(vm);ret} - - fn script_default(vm:&mut ScriptVm)->ScriptValue{ - Self::script_proto(vm); - Self::script_new(vm).script_to_value(vm) - } - - fn script_type_check(heap:&ScriptHeap, value:ScriptValue)->bool{ - if Self::on_type_check(heap, value){ - return true - } - if let Some(o) = value.as_object(){ - let root_proto = heap.root_proto(o); - if let Some(id) = root_proto.as_id(){ - return match id{ - id!(Bare)=>true, - id!(Tuple)=>true, - id!(Named)=>true, - _=>false - } - } - } - false - } - - fn script_proto_build(vm:&mut ScriptVm, _props:&mut ScriptTypeProps)->ScriptValue{ - let enum_object = vm.bx.heap.new(); - - // how do we typecheck an enum type eh - let bare = vm.bx.heap.new_with_proto(id!(Bare).into()); - vm.bx.heap.set_value(enum_object, id_lut!(Bare).into(), bare.into(), vm.bx.threads.cur().trap.pass()); - vm.bx.heap.freeze(bare); - - // alright next one the tuple - vm.add_method(enum_object, id!(Tuple), &[], |vm, args|{ - let tuple = vm.bx.heap.new_with_proto(id!(Tuple).into()); - if vm.bx.heap.vec_len(args) != 1 { - script_err_invalid_args!(vm.bx.threads.cur().trap, "EnumTest::Tuple requires 1 arg"); - } - if let Some(a) = vm.bx.heap.vec_value_if_exist(args, 0){ - if !f64::script_type_check(&vm.bx.heap, a){ - script_err_type_mismatch!(vm.bx.threads.cur().trap, "EnumTest::Tuple arg must be f64"); - } - } - vm.bx.heap.vec_push_vec(tuple, args, vm.bx.threads.cur().trap.pass()); - tuple.into() - }); - - // we can make a type index prop check for sself thing - let def = Self::Named{named_field: 1.0}; - let named = vm.bx.heap.new_with_proto(id_lut!(Named).into()); - let mut props = ScriptTypeProps::default(); - if let Self::Named{named_field:v0} = def{ - - let value = v0.script_to_value(vm); - props.insert(id_lut!(named_field), f64::script_type_id_static()); - vm.bx.heap.set_value(named, id!(named_field).into(), value, vm.bx.threads.cur().trap.pass()); - - } - - let ty_check = ScriptTypeCheck{props, object: None, is_repr_u32_enum: false}; - let ty_index = vm.bx.heap.register_type(None, ty_check); - vm.bx.heap.freeze_with_type(named, ty_index); - vm.bx.heap.set_value(enum_object, id!(Named).into(), named.into(), vm.bx.threads.cur().trap.pass()); - - enum_object.into() - } -} - -impl ScriptToValue for EnumTest{ - fn script_to_value(&self, vm:&mut ScriptVm)->ScriptValue{ - match self{ - Self::Bare=>{ - Self::script_enum_lookup_variant(vm, id!(Bare)) - } - Self::Tuple(x)=>{ - let tuple = vm.bx.heap.new_with_proto(id!(Tuple).into()); - let value = x.script_to_value(vm); - vm.bx.heap.vec_push(tuple, NIL, value, vm.bx.threads.cur().trap.pass()); - tuple.into() - } - Self::Named{named_field}=>{ - let proto = Self::script_enum_lookup_variant(vm, id!(Named)); - let named = vm.bx.heap.new_with_proto(proto); - let value = named_field.script_to_value(vm); - vm.bx.heap.set_value(named, id_lut!(named_field).into(), value, vm.bx.threads.cur().trap.pass()); - named.into() - } - } - } -} - -impl ScriptApply for EnumTest{ - fn script_type_id(&self)->ScriptTypeId{ScriptTypeId::of::()} - fn script_apply(&mut self, vm:&mut ScriptVm, apply:&Apply, value:ScriptValue){ - if self.on_skip_apply(vm, apply, value){ - return - } - if let Some(object) = value.as_object(){ - let root_proto = vm.bx.heap.root_proto(object); - // we now have to fetch the proto LiveId of the object - if let Some(id) = root_proto.as_id(){ - match id{ - id!(Bare)=>{ - *self = Self::Bare; - return; - } - id!(Tuple)=>{ - if let Self::Tuple(..) = self{} else {*self = Self::Tuple(1.0)}; - if let Self::Tuple(a1) = self{ - if let Some(v) = vm.bx.heap.vec_value_if_exist(object, 0){ - a1.script_apply(vm, apply, v); - } - return - } - return - } - id!(Named)=>{ - if let Self::Named{..} = self{} else { *self = Self::Named{named_field:1.0}}; - if let Self::Named{named_field} = self{ - if let Some(v) = vm.bx.heap.value_apply_if_dirty(value, ScriptValue::from_id(id!(named_field))){ - named_field.script_apply(vm, apply, v); - } - return - } - } - _=>{ - } - } - } - } - script_err_unknown_type!(vm.bx.threads.cur().trap, "unknown EnumTest variant"); - } -}*/ diff --git a/vendor/makepad/platform/script/derive/src/error.rs b/vendor/makepad/platform/script/derive/src/error.rs deleted file mode 100644 index ca82409..0000000 --- a/vendor/makepad/platform/script/derive/src/error.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![allow(unstable_name_collisions)] - -use { - makepad_micro_proc_macro::{TokenBuilder, TokenParser}, - proc_macro::TokenStream, -}; - -pub fn script_err_gen_impl(input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - // lets get the argument name - let mut parser = TokenParser::new(input); - fn parse(parser: &mut TokenParser, tb: &mut TokenBuilder) -> Result<(), TokenStream> { - let ident = parser.expect_any_ident()?; - tb.add("#[macro_export] macro_rules!") - .ident(&ident) - .add("{"); - tb.add(" ($trap:expr) => {"); - tb.add(" if let $crate::trap::ScriptTrap::Inner(trap) = $trap.pass(){"); - tb.add(" trap.push_err(ScriptValue::") - .ident(&ident) - .add("(trap.ip), stringify!($trap).into(), file!().into(), line!())"); - tb.add(" }else{"); - tb.add(" ScriptValue::") - .ident(&ident) - .add("(ScriptIp::default())"); - tb.add(" }"); - tb.add(" };"); - tb.add(" ($trap:expr, $($arg:tt)*) => {"); - tb.add(" if let $crate::trap::ScriptTrap::Inner(trap) = $trap.pass(){"); - tb.add(" trap.push_err(ScriptValue::") - .ident(&ident) - .add("(trap.ip), format!($($arg)*), file!().into(), line!())"); - tb.add(" }else{"); - tb.add(" ScriptValue::") - .ident(&ident) - .add("(ScriptIp::default())"); - tb.add(" }"); - tb.add(" }"); - tb.add("}"); - Ok(()) - } - if let Err(e) = parse(&mut parser, &mut tb) { - return e; - }; - tb.end() -} diff --git a/vendor/makepad/platform/script/derive/src/lib.rs b/vendor/makepad/platform/script/derive/src/lib.rs deleted file mode 100644 index 808e0ef..0000000 --- a/vendor/makepad/platform/script/derive/src/lib.rs +++ /dev/null @@ -1,66 +0,0 @@ -use proc_macro::TokenStream; - -mod derive_scriptable; -mod error; -mod script; -mod swizzle; -use derive_scriptable::*; -use error::*; -use script::*; -use swizzle::*; - -#[proc_macro] -pub fn script(input: TokenStream) -> TokenStream { - script_impl(input) -} - -#[proc_macro] -pub fn script_mod(input: TokenStream) -> TokenStream { - script_mod_impl(input) -} - -#[proc_macro] -pub fn script_apply_eval(input: TokenStream) -> TokenStream { - script_apply_eval_impl(input) -} - -#[proc_macro] -pub fn script_err_gen(input: TokenStream) -> TokenStream { - script_err_gen_impl(input) -} - -#[proc_macro_derive( - Script, - attributes( - apply_default, - source, - new, - live, - rust, - pick, - splat, - walk, - layout, - deref, - uid, - ) -)] - -pub fn derive_script(input: TokenStream) -> TokenStream { - derive_script_impl(input) -} - -#[proc_macro_derive(ScriptHook, attributes())] -pub fn derive_script_hook(input: TokenStream) -> TokenStream { - derive_script_hook_impl(input) -} - -#[proc_macro] -pub fn pod_swizzle_vec_match(input: TokenStream) -> TokenStream { - pod_swizzle_vec_match_impl(input) -} - -#[proc_macro] -pub fn pod_swizzle_vec_type(input: TokenStream) -> TokenStream { - pod_swizzle_vec_type_impl(input) -} diff --git a/vendor/makepad/platform/script/derive/src/script.rs b/vendor/makepad/platform/script/derive/src/script.rs deleted file mode 100644 index e976147..0000000 --- a/vendor/makepad/platform/script/derive/src/script.rs +++ /dev/null @@ -1,232 +0,0 @@ -#![allow(unstable_name_collisions)] - -use { - makepad_micro_proc_macro::{TokenBuilder, TokenParser}, - proc_macro::{Delimiter, Span, TokenStream}, - std::fmt::Write, -}; - -pub fn script_mod_impl(input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - let ts = script_impl(input); - tb.add("pub fn script_mod(vm:&mut ScriptVm)->ScriptValue{"); - tb.add(" let sb=").stream(Some(ts)).add(";"); - tb.add(" vm.eval(sb)"); - tb.add("}"); - tb.end() -} - -pub fn script_apply_eval_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - // Parse: cx, target, { script code } - // First get the cx expression - let cx_expr = parser.eat_any_ident().expect("Expected cx identifier"); - parser.eat_punct_alone(','); - - // Get the target expression (could be self.draw_bg or similar) - let mut target_tb = TokenBuilder::new(); - while !parser.eat_punct_alone(',') { - if let Some(tt) = parser.current.clone() { - target_tb.extend(tt); - parser.advance(); - } else { - break; - } - } - let target_stream = target_tb.end(); - - // The rest is the script code (already includes braces from eat_level) - // Prepend __script_source__ to make it __script_source__{...} - let script_code: TokenStream = { - let mut tb = TokenBuilder::new(); - tb.add("__script_source__"); - tb.stream(Some(parser.eat_level())); - tb.end() - }; - - // Generate the script_impl output (the ScriptMod struct) - // Use script_impl_expr to NOT add semicolon - we want to return the expression value - let script_mod = script_impl(script_code); - - // Build: cx.with_vm(|vm| { let script = ScriptMod{...}; target.script_apply_eval(vm, script) }) - tb.ident(&cx_expr).add(".with_vm(|vm|{"); - tb.add("let script =").stream(Some(script_mod)).add(";"); - tb.stream(Some(target_stream)); - tb.add(".script_apply_eval(vm, script)"); - tb.add("})"); - - tb.end() -} - -pub fn script_impl(input: TokenStream) -> TokenStream { - let mut parser = TokenParser::new(input); - let mut tb = TokenBuilder::new(); - - if let Some(span) = parser.span() { - let (s, values) = token_parser_to_whitespace_matching_string(&mut parser, span); - - tb.add("ScriptMod {"); - tb.add(" cargo_manifest_path: env!(") - .string("CARGO_MANIFEST_DIR") - .add(").trim_start_matches(") - .string("\\\\?\\") - .add(").to_string(),"); - tb.add(" module_path :") - .ident_with_span("module_path", span) - .add("!().to_string(),"); - tb.add(" file:") - .ident_with_span("file", span) - .add("!().to_string().replace(") - .string("\\") - .add(",") - .string("/") - .add("),"); - tb.add(" line:line!() as usize,"); - tb.add(" column:column!() as usize,"); - - tb.add(" code:").string(&s).add(".to_string(),"); - tb.add(" values:{"); - tb.add(" let mut v = Vec::new();"); - for value in &values { - tb.add("v.push( {") - .stream(Some(value.clone())) - .add("}.script_to_value(vm) );"); - } - tb.add(" v}"); - tb.add("}"); - } else { - tb.add("ScriptMod::default()"); - } - tb.end() -} - -// sself function parses tokens into a source-equal whitespaced output string -fn token_parser_to_whitespace_matching_string( - parser: &mut TokenParser, - span: Span, -) -> (String, Vec) { - let mut s = String::new(); - let mut values = Vec::new(); - - tp_to_str(parser, span, &mut s, &mut values, &mut None); - s.push(';'); - return (s, values); - - #[derive(Clone, Copy)] - struct Lc { - line: usize, - column: usize, - } - - impl Lc { - fn _next_char(self) -> Self { - Self { - line: self.line, - column: self.column + 1, - } - } - } - - fn delim_to_pair(delim: Delimiter) -> (char, char) { - match delim { - Delimiter::Brace => ('{', '}'), - Delimiter::Parenthesis => ('(', ')'), - Delimiter::Bracket => ('[', ']'), - Delimiter::None => (' ', ' '), - } - } - - fn tp_to_str( - parser: &mut TokenParser, - span: Span, - out: &mut String, - values: &mut Vec, - last_end: &mut Option, - ) { - fn lc_from_start(span: Span) -> Lc { - Lc { - line: span.start().line(), - column: span.start().column(), - } - } - - fn lc_from_end(span: Span) -> Lc { - Lc { - line: span.end().line(), - column: span.end().column(), - } - } - - fn delta_whitespace(now: Lc, needed: Lc, out: &mut String) { - if now.line == needed.line { - for _ in now.column..needed.column { - out.push(' '); - } - } else { - for _ in now.line..needed.line { - out.push('\n'); - } - for _ in 1..needed.column { - out.push(' '); - } - } - } - - if last_end.is_none() { - *last_end = Some(lc_from_start(span)); - } - - let mut last_tt = None; - - while !parser.eat_eot() { - let span = parser.span().unwrap(); - if let Some(delim) = parser.open_group() { - if let Some(TokenTree::Punct(last_punct)) = &last_tt { - if last_punct.as_char() == '#' { - last_tt = None; - out.pop(); - let index = values.len(); - write!(out, "#({index})").unwrap(); - values.push(parser.eat_level()); - continue; - } - } - - let (gs, ge) = delim_to_pair(delim); - let start = lc_from_start(span); - let end = lc_from_end(span); - delta_whitespace(last_end.unwrap(), start, out); - out.push(gs); - *last_end = Some(start._next_char()); - tp_to_str(parser, span, out, values, last_end); - delta_whitespace( - last_end.unwrap(), - Lc { - line: end.line, - column: end.column - 1, - }, - out, - ); - *last_end = Some(end); - out.push(ge); - } else { - if let Some(tt) = &parser.current { - { - last_tt = Some(tt.clone()); - let start = lc_from_start(span); - delta_whitespace(last_end.unwrap(), start, out); - } - - out.push_str(&tt.to_string()); - - *last_end = Some(lc_from_end(span)); - } - parser.advance(); - } - } - } -} - -use proc_macro::TokenTree; diff --git a/vendor/makepad/platform/script/derive/src/swizzle.rs b/vendor/makepad/platform/script/derive/src/swizzle.rs deleted file mode 100644 index 4b16ecd..0000000 --- a/vendor/makepad/platform/script/derive/src/swizzle.rs +++ /dev/null @@ -1,117 +0,0 @@ -#![allow(unstable_name_collisions)] - -use {makepad_micro_proc_macro::TokenBuilder, proc_macro::TokenStream}; - -pub fn pod_swizzle_vec_type_impl(_input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - - tb.add("match field_name {"); - do_fields(&mut tb, &["x", "y", "z", "w"]); - do_fields(&mut tb, &["r", "g", "b", "a"]); - fn do_fields(tb: &mut TokenBuilder, fields: &[&str]) { - // lets generate the vec1 permutations - for (_x, xfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(xfield) - .add(")=>Some(vt.swizzle_type(1, builtins)),"); - } - // lets generate the vec2 permutations - for (_x, xfield) in fields.iter().enumerate() { - for (_y, yfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}", xfield, yfield)) - .add(")=>Some(vt.swizzle_type(2, builtins)),"); - } - } - for (_x, xfield) in fields.iter().enumerate() { - for (_y, yfield) in fields.iter().enumerate() { - for (_z, zfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}{}", xfield, yfield, zfield)) - .add(")=>Some(vt.swizzle_type(3, builtins)),"); - } - } - } - for (_x, xfield) in fields.iter().enumerate() { - for (_y, yfield) in fields.iter().enumerate() { - for (_z, zfield) in fields.iter().enumerate() { - for (_w, wfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}{}{}", xfield, yfield, zfield, wfield)) - .add(")=>Some(vt.swizzle_type(4, builtins)),"); - } - } - } - } - } - tb.add(" _=>None"); - tb.add("}"); - tb.end() -} - -pub fn pod_swizzle_vec_match_impl(_input: TokenStream) -> TokenStream { - let mut tb = TokenBuilder::new(); - - tb.add("match field_name {"); - do_fields(&mut tb, &["x", "y", "z", "w"]); - do_fields(&mut tb, &["r", "g", "b", "a"]); - fn do_fields(tb: &mut TokenBuilder, fields: &[&str]) { - // lets generate the vec1 permutations - for (x, xfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(xfield) - .add(")=>self.pod_swizzle_vec1(*vt, data,") - .unsuf_usize(x) - .add(", trap),"); - } - // lets generate the vec2 permutations - for (x, xfield) in fields.iter().enumerate() { - for (y, yfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}", xfield, yfield)) - .add(")=>self.pod_swizzle_vec(*vt, data,[") - .unsuf_usize(x) - .add(",") - .unsuf_usize(y) - .add("], builtins, trap),"); - } - } - for (x, xfield) in fields.iter().enumerate() { - for (y, yfield) in fields.iter().enumerate() { - for (z, zfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}{}", xfield, yfield, zfield)) - .add(")=>self.pod_swizzle_vec(*vt, data,[") - .unsuf_usize(x) - .add(",") - .unsuf_usize(y) - .add(",") - .unsuf_usize(z) - .add("], builtins, trap),"); - } - } - } - for (x, xfield) in fields.iter().enumerate() { - for (y, yfield) in fields.iter().enumerate() { - for (z, zfield) in fields.iter().enumerate() { - for (w, wfield) in fields.iter().enumerate() { - tb.add(" id!(") - .ident(&format!("{}{}{}{}", xfield, yfield, zfield, wfield)) - .add(")=>self.pod_swizzle_vec(*vt, data,[") - .unsuf_usize(x) - .add(",") - .unsuf_usize(y) - .add(",") - .unsuf_usize(z) - .add(",") - .unsuf_usize(w) - .add("], builtins, trap),"); - } - } - } - } - } - tb.add(" _=>script_err_pod!(trap, \"unknown swizzle field\")"); - tb.add("}"); - tb.end() -} diff --git a/vendor/makepad/platform/script/src/apply.rs b/vendor/makepad/platform/script/src/apply.rs deleted file mode 100644 index a39e184..0000000 --- a/vendor/makepad/platform/script/src/apply.rs +++ /dev/null @@ -1,251 +0,0 @@ -use std::any::Any; - -// ============================================================================ -// ScopeDataRef / ScopeDataMut - Type-erased data containers for scope -// ============================================================================ - -#[derive(Default)] -pub struct ScopeDataRef<'a>(Option<&'a dyn Any>); - -#[derive(Default)] -pub struct ScopeDataMut<'a>(Option<&'a mut dyn Any>); - -impl<'a> ScopeDataRef<'a> { - pub fn get(&self) -> Option<&T> { - self.0.as_ref().and_then(|r| r.downcast_ref()) - } -} - -impl<'a> ScopeDataMut<'a> { - pub fn get(&mut self) -> Option<&T> { - self.0.as_ref().and_then(|r| r.downcast_ref()) - } - - pub fn get_mut(&mut self) -> Option<&mut T> { - self.0.as_mut().and_then(|r| r.downcast_mut()) - } -} - -// ============================================================================ -// Scope - Context passed during apply operations -// ============================================================================ - -#[derive(Default)] -pub struct Scope<'a, 'b> { - pub data: ScopeDataMut<'a>, - pub props: ScopeDataRef<'b>, - pub index: usize, -} - -impl<'a, 'b> Scope<'a, 'b> { - pub fn with_data(v: &'a mut T) -> Self { - Self { - data: ScopeDataMut(Some(v)), - props: ScopeDataRef(None), - index: 0, - } - } - - pub fn with_data_props(v: &'a mut T, w: &'b U) -> Self { - Self { - data: ScopeDataMut(Some(v)), - props: ScopeDataRef(Some(w)), - index: 0, - } - } - - pub fn with_props(w: &'b T) -> Self { - Self { - data: ScopeDataMut(None), - props: ScopeDataRef(Some(w)), - index: 0, - } - } - - pub fn with_data_index(v: &'a mut T, index: usize) -> Self { - Self { - data: ScopeDataMut(Some(v)), - props: ScopeDataRef(None), - index, - } - } - - pub fn with_data_props_index(v: &'a mut T, w: &'b T, index: usize) -> Self { - Self { - data: ScopeDataMut(Some(v)), - props: ScopeDataRef(Some(w)), - index, - } - } - - pub fn with_props_index(w: &'b T, index: usize) -> Self { - Self { - data: ScopeDataMut(None), - props: ScopeDataRef(Some(w)), - index, - } - } - - pub fn empty() -> Self { - Self { - data: ScopeDataMut(None), - props: ScopeDataRef(None), - index: 0, - } - } - - pub fn override_props(&mut self, props: &'b T, f: F) -> R - where - F: FnOnce(&mut Scope) -> R, - { - let mut props = ScopeDataRef(Some(props)); - std::mem::swap(&mut self.props, &mut props); - let r = f(self); - std::mem::swap(&mut self.props, &mut props); - r - } - - pub fn override_props_index(&mut self, props: &'b T, index: usize, f: F) -> R - where - F: FnOnce(&mut Scope) -> R, - { - let mut props = ScopeDataRef(Some(props)); - let old_index = self.index; - self.index = index; - std::mem::swap(&mut self.props, &mut props); - let r = f(self); - std::mem::swap(&mut self.props, &mut props); - self.index = old_index; - r - } -} - -// ============================================================================ -// Apply - Source of apply operation -// ============================================================================ - -#[derive(Debug, Clone, Default)] -pub enum Apply { - #[default] - New, - /// LiveEdit-driven hot-reload. The DSL itself changed; the template - /// is the new source of truth and template values should override - /// any prior runtime state. - Reload, - /// Heap-mutation broadcast triggered by `cx.request_script_reapply()` - /// (e.g. preference change, safe-area inset change). The template has - /// NOT changed — the same cached `app_value` is being re-walked so - /// shared-heap-object references (`(mod.widgets.X.field)` lookups) - /// pick up their new values. Field types whose canonical mutation - /// path is an imperative setter (e.g. `Label::set_text`) should - /// early-return on this variant so runtime state survives. - ScriptReapply, - Animate, - Eval, - Default(usize), -} - -impl Apply { - pub fn is_from_script(&self) -> bool { - match self { - Self::New => true, - Self::Reload => true, - Self::ScriptReapply => true, - Self::Eval => true, - _ => false, - } - } - - /// Returns true if this is a template apply (New or Reload) where - /// the #[source] field should be updated. Excludes Eval since eval - /// creates temporary objects that would become dangling after GC. - /// Excludes ScriptReapply because the template hasn't changed — - /// the same source object is being re-walked, so re-binding it is - /// unnecessary work. - pub fn is_template_apply(&self) -> bool { - match self { - Self::New => true, - Self::Reload => true, - _ => false, - } - } - - pub fn is_new(&self) -> bool { - match self { - Self::New => true, - _ => false, - } - } - - /// True for any re-application after the initial `New` — i.e. either a - /// LiveEdit hot-reload (`Apply::Reload`) or a `request_script_reapply`-driven - /// walk (`Apply::ScriptReapply`). - /// - /// Most widgets that branch on this method want to handle "the template - /// is being re-applied for whatever reason" uniformly (re-attach - /// listeners, re-resolve heap-ref-driven dimensions, refresh derived - /// state). They should NOT need to differentiate between the two - /// triggers, so we keep `is_reload` as the broad predicate. - /// - /// Use `is_live_edit_reload()` if you specifically want only LiveEdit, - /// or `is_script_reapply()` for only the heap-mutation-broadcast case. - pub fn is_reload(&self) -> bool { - match self { - Self::Reload => true, - Self::ScriptReapply => true, - _ => false, - } - } - - /// True only for `Apply::Reload` — a LiveEdit-driven hot-reload where - /// the DSL itself changed. Excludes `Apply::ScriptReapply`. Use this - /// (rather than `is_reload`) when behavior should fire only when the - /// template source has actually changed (e.g. re-running script_mod - /// scaffolding, invalidating template-derived caches). - pub fn is_live_edit_reload(&self) -> bool { - match self { - Self::Reload => true, - _ => false, - } - } - - /// True only for `Apply::ScriptReapply` — a `request_script_reapply`-driven - /// re-walk where the template has NOT changed. Field impls whose value - /// should not be clobbered by template defaults on this kind of re-walk - /// should early-return when this is true (canonical example: - /// `ArcStringMut::script_apply`). - pub fn is_script_reapply(&self) -> bool { - match self { - Self::ScriptReapply => true, - _ => false, - } - } - - pub fn is_animate(&self) -> bool { - match self { - Self::Animate => true, - _ => false, - } - } - - pub fn is_eval(&self) -> bool { - match self { - Self::Eval => true, - _ => false, - } - } - - pub fn as_default(&self) -> Option { - match self { - Self::Default(u) => Some(*u), - _ => None, - } - } - - pub fn is_default(&self) -> bool { - match self { - Self::Default(_) => true, - _ => false, - } - } -} diff --git a/vendor/makepad/platform/script/src/array.rs b/vendor/makepad/platform/script/src/array.rs deleted file mode 100644 index 0c05ef4..0000000 --- a/vendor/makepad/platform/script/src/array.rs +++ /dev/null @@ -1,771 +0,0 @@ -use crate::function::*; -use crate::heap::*; -use crate::makepad_live_id::*; -use crate::native::*; -use crate::object::*; -use crate::value::*; -use crate::*; - -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::HashMap; -use std::collections::VecDeque; -use std::mem::size_of; -use std::rc::Rc; - -/// Appends `bytes` with the same replacement behavior as -/// `String::from_utf8_lossy` without materializing an unbounded intermediate -/// string before the destination sink can apply its limit. -fn append_utf8_lossy(mut bytes: &[u8], out: &mut S) { - while !bytes.is_empty() && !out.is_full() { - match std::str::from_utf8(bytes) { - Ok(valid) => { - out.append_str(valid); - break; - } - Err(error) => { - let valid_up_to = error.valid_up_to(); - if valid_up_to != 0 { - let valid = std::str::from_utf8(&bytes[..valid_up_to]) - .expect("UTF-8 errors report valid prefixes"); - out.append_str(valid); - if out.is_full() { - break; - } - } - - out.append_char('\u{FFFD}'); - if out.is_full() { - break; - } - - let invalid_len = error.error_len().unwrap_or(bytes.len() - valid_up_to); - bytes = &bytes[valid_up_to + invalid_len..]; - } - } - } -} - -#[derive(Debug)] -pub struct ScriptArrayRef { - pub(crate) roots: Rc>>, - pub(crate) array: ScriptArray, -} - -impl From for ScriptValue { - fn from(v: ScriptArrayRef) -> Self { - ScriptValue::from_array(v.as_array()) - } -} - -impl Clone for ScriptArrayRef { - fn clone(&self) -> Self { - let mut roots = self.roots.borrow_mut(); - match roots.entry(self.array) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - *value += 1; - } - Entry::Vacant(_vac) => { - eprintln!("ScriptObjectRef root is vacant!"); - } - } - Self { - roots: self.roots.clone(), - array: self.array.clone(), - } - } -} - -impl ScriptArrayRef { - pub fn as_array(&self) -> ScriptArray { - self.array - } -} - -impl Drop for ScriptArrayRef { - fn drop(&mut self) { - let mut roots = self.roots.borrow_mut(); - match roots.entry(self.array) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - if *value >= 1 { - *value -= 1; - } else { - eprintln!("ScriptObjectRef is 0!"); - } - if *value == 0 { - occ.remove(); - } - } - Entry::Vacant(_vac) => { - eprintln!("ScriptObjectRef root is vacant!"); - } - } - } -} - -#[derive(Default)] -pub struct ScriptArrayTag(u64); - -impl ScriptArrayTag { - pub const MARK: u64 = 0x1 << 40; - pub const ALLOCED: u64 = 0x2 << 40; - pub const STATIC: u64 = 0x4 << 40; - pub const DIRTY: u64 = 0x40 << 40; - pub const FROZEN: u64 = 0x100 << 40; - - pub const REF_DATA_MASK: u64 = 0xFF_FFFF_FFFF; - pub const REF_KIND_MASK: u64 = 0xF << 58; - pub const REF_KIND_APPLY_TRANSFORM: u64 = 0x6 << 58; - pub const IMMUTABLE_MASK: u64 = Self::FROZEN | Self::STATIC; - - pub fn is_alloced(&self) -> bool { - return self.0 & Self::ALLOCED != 0; - } - - pub fn set_apply_transform(&mut self, ni: NativeId) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - self.0 |= (ni.index as u64) | Self::REF_KIND_APPLY_TRANSFORM; - } - - pub fn as_apply_transform(&self) -> Option { - if self.0 & Self::REF_KIND_MASK == Self::REF_KIND_APPLY_TRANSFORM { - Some(NativeId { - index: self.0 as u32, - }) - } else { - None - } - } - - pub fn is_apply_transform(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_APPLY_TRANSFORM - } - - pub fn set_alloced(&mut self) { - self.0 |= Self::ALLOCED - } - - pub fn clear(&mut self) { - self.0 = 0; - } - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - pub fn freeze(&mut self) { - self.0 |= Self::FROZEN - } - - pub fn is_frozen(&self) -> bool { - self.0 & Self::FROZEN != 0 - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } - - #[inline(always)] - pub fn is_immutable(&self) -> bool { - self.0 & Self::IMMUTABLE_MASK != 0 - } - - pub fn set_dirty(&mut self) { - self.0 |= Self::DIRTY - } - - pub fn check_and_clear_dirty(&mut self) -> bool { - if self.0 & Self::DIRTY != 0 { - self.0 &= !Self::DIRTY; - true - } else { - false - } - } -} - -#[derive(PartialEq)] -pub enum ScriptArrayStorage { - ScriptValue(VecDeque), - F32(Vec), - U32(Vec), - U16(Vec), - U8(Vec), -} - -impl ScriptArrayStorage { - /// Backing allocation retained by this storage, excluding the enum itself. - /// - /// The heap budget uses retained capacity instead of logical length so a - /// cleared or sparsely written collection cannot hide already-reserved - /// memory from the host's accounting boundary. - pub(crate) fn retained_bytes(&self) -> usize { - match self { - Self::ScriptValue(values) => values.capacity().saturating_mul(size_of::()), - Self::F32(values) => values.capacity().saturating_mul(size_of::()), - Self::U32(values) => values.capacity().saturating_mul(size_of::()), - Self::U16(values) => values.capacity().saturating_mul(size_of::()), - Self::U8(values) => values.capacity(), - } - } - - /// Minimum backing bytes needed to represent `length` values before any - /// allocator growth policy is applied. Callers use this before sparse - /// indexed writes so a hostile index cannot request an unbounded resize. - pub(crate) fn minimum_bytes_for_len(&self, length: usize) -> Option { - let element_bytes = match self { - Self::ScriptValue(_) => size_of::(), - Self::F32(_) => size_of::(), - Self::U32(_) => size_of::(), - Self::U16(_) => size_of::(), - Self::U8(_) => size_of::(), - }; - length.checked_mul(element_bytes) - } - - pub fn clear(&mut self) { - match self { - Self::ScriptValue(v) => v.clear(), - Self::F32(v) => v.clear(), - Self::U32(v) => v.clear(), - Self::U16(v) => v.clear(), - Self::U8(v) => v.clear(), - } - } - pub fn len(&self) -> usize { - match self { - Self::ScriptValue(v) => v.len(), - Self::F32(v) => v.len(), - Self::U32(v) => v.len(), - Self::U16(v) => v.len(), - Self::U8(v) => v.len(), - } - } - pub fn index(&self, index: usize) -> Option { - match self { - Self::ScriptValue(v) => { - if let Some(v) = v.get(index) { - (*v).into() - } else { - None - } - } - Self::F32(v) => { - if let Some(v) = v.get(index) { - Some((*v).into()) - } else { - None - } - } - Self::U32(v) => { - if let Some(v) = v.get(index) { - Some((*v).into()) - } else { - None - } - } - Self::U16(v) => { - if let Some(v) = v.get(index) { - Some((*v).into()) - } else { - None - } - } - Self::U8(v) => { - if let Some(v) = v.get(index) { - Some((*v).into()) - } else { - None - } - } - } - } - pub fn set_index(&mut self, index: usize, value: ScriptValue) { - match self { - Self::ScriptValue(v) => { - if index >= v.len() { - v.resize(index + 1, NIL); - } - v[index] = value; - } - Self::F32(v) => { - if index >= v.len() { - v.resize(index + 1, 0.0); - } - v[index] = value.as_f64().unwrap_or(0.0) as f32; - } - Self::U32(v) => { - if index >= v.len() { - v.resize(index + 1, 0); - } - v[index] = value.as_f64().unwrap_or(0.0) as u32; - } - Self::U16(v) => { - if index >= v.len() { - v.resize(index + 1, 0); - } - v[index] = value.as_f64().unwrap_or(0.0) as u16; - } - Self::U8(v) => { - if index >= v.len() { - v.resize(index + 1, 0); - } - v[index] = value.as_f64().unwrap_or(0.0) as u8; - } - } - } - pub fn push(&mut self, value: ScriptValue) { - match self { - Self::ScriptValue(v) => v.push_back(value), - Self::F32(v) => v.push(value.as_f64().unwrap_or(0.0) as f32), - Self::U32(v) => v.push(value.as_f64().unwrap_or(0.0) as u32), - Self::U16(v) => v.push(value.as_f64().unwrap_or(0.0) as u16), - Self::U8(v) => v.push(value.as_f64().unwrap_or(0.0) as u8), - } - } - pub fn push_vec(&mut self, vec: &[ScriptVecValue]) { - match self { - Self::ScriptValue(v) => { - for a in vec { - v.push_back(a.value) - } - } - Self::F32(v) => { - for a in vec { - v.push(a.value.as_f64().unwrap_or(0.0) as f32) - } - } - Self::U32(v) => { - for a in vec { - v.push(a.value.as_f64().unwrap_or(0.0) as u32) - } - } - Self::U16(v) => { - for a in vec { - v.push(a.value.as_f64().unwrap_or(0.0) as u16) - } - } - Self::U8(v) => { - for a in vec { - v.push(a.value.as_f64().unwrap_or(0.0) as u8) - } - } - } - } - pub fn pop(&mut self) -> Option { - match self { - Self::ScriptValue(v) => { - if let Some(v) = v.pop_back() { - Some(v.into()) - } else { - None - } - } - Self::F32(v) => { - if let Some(v) = v.pop() { - Some(v.into()) - } else { - None - } - } - Self::U32(v) => { - if let Some(v) = v.pop() { - Some(v.into()) - } else { - None - } - } - Self::U16(v) => { - if let Some(v) = v.pop() { - Some(v.into()) - } else { - None - } - } - Self::U8(v) => { - if let Some(v) = v.pop() { - Some(v.into()) - } else { - None - } - } - } - } - - pub fn pop_front(&mut self) -> Option { - match self { - Self::ScriptValue(v) => { - if let Some(v) = v.pop_front() { - Some(v.into()) - } else { - None - } - } - Self::F32(v) => { - if v.len() > 0 { - Some(v.remove(0).into()) - } else { - None - } - } - Self::U32(v) => { - if v.len() > 0 { - Some(v.remove(0).into()) - } else { - None - } - } - Self::U16(v) => { - if v.len() > 0 { - Some(v.remove(0).into()) - } else { - None - } - } - Self::U8(v) => { - if v.len() > 0 { - Some(v.remove(0).into()) - } else { - None - } - } - } - } - pub fn remove(&mut self, index: usize) -> ScriptValue { - match self { - Self::ScriptValue(v) => { - if let Some(value) = v.remove(index) { - value - } else { - NIL - } - } - Self::F32(v) => v.remove(index).into(), - Self::U32(v) => v.remove(index).into(), - Self::U16(v) => v.remove(index).into(), - Self::U8(v) => v.remove(index).into(), - } - } - pub fn to_string(&self, heap: &ScriptHeap, out: &mut S) { - match self { - Self::U8(bytes) => append_utf8_lossy(bytes, out), - Self::ScriptValue(vec) => { - for v in vec { - heap.cast_to_string(*v, out); - if out.is_full() { - break; - } - } - } - Self::F32(v) => { - for v in v { - if let Some(c) = std::char::from_u32(*v as _) { - out.append_char(c) - } - if out.is_full() { - break; - } - } - } - Self::U32(v) => { - for v in v { - if let Some(c) = std::char::from_u32(*v) { - out.append_char(c) - } - if out.is_full() { - break; - } - } - } - Self::U16(v) => { - for v in v { - if let Some(c) = std::char::from_u32(*v as _) { - out.append_char(c) - } - if out.is_full() { - break; - } - } - } - } - } -} - -pub struct ScriptArrayData { - pub tag: ScriptArrayTag, - pub storage: ScriptArrayStorage, -} - -impl Default for ScriptArrayData { - fn default() -> Self { - Self { - tag: ScriptArrayTag::default(), - storage: ScriptArrayStorage::ScriptValue(Default::default()), - } - } -} - -impl ScriptArrayData { - pub fn add_type_methods(native: &mut ScriptNative, heap: &mut ScriptHeap) { - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(to_string), - &[], - |vm, args| { - if let Some(arr) = script_value!(vm, args.self).as_array() { - return vm - .bx - .heap - .new_bounded_string_with(|heap, s| { - heap.array_storage(arr).to_string(heap, s); - }) - .into(); - } - script_err_unexpected!(vm.bx.threads.cur_ref().trap, "unexpected array type") - }, - ); - - native.add_type_method(heap, ScriptValueType::REDUX_ARRAY, id!(parse_json), &[], |vm, args|{ - if let Some(array) = script_value!(vm, args.self).as_array(){ - // Take json_parser out to avoid borrow conflict - let mut json_parser = std::mem::take(&mut vm.bx.threads.cur().json_parser); - let result = vm.bx.heap.temp_bounded_string_with(|heap, temp| { - let is_byte_array = match heap.array_storage(array) { - ScriptArrayStorage::U8(bytes) => { - append_utf8_lossy(bytes, temp); - true - } - _ => false, - }; - if is_byte_array && !temp.is_full() { - json_parser.read_json(temp.as_str(), heap) - } else { - NIL - } - }); - vm.bx.threads.cur().json_parser = json_parser; - if result == NIL { - // Check if it was due to wrong storage type - let storage = vm.bx.heap.array_storage(array); - if !matches!(storage, ScriptArrayStorage::U8(_)) { - return script_err_type_mismatch!(vm.bx.threads.cur_ref().trap, "parse_json requires U8 byte array, got different array storage type"); - } - } - return result.into() - } - script_err_unexpected!(vm.bx.threads.cur_ref().trap, "parse_json called on non-array value") - }); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(parse_json), - &[], - |vm, args| { - if let Some(arr) = script_value!(vm, args.self).as_array() { - // Take json_parser out to avoid borrow conflict - let mut json_parser = std::mem::take(&mut vm.bx.threads.cur().json_parser); - let result = vm.bx.heap.temp_bounded_string_with(|heap, temp| { - let storage = heap.array_storage(arr); - storage.to_string(heap, temp); - if temp.is_full() { - NIL - } else { - json_parser.read_json(temp.as_str(), heap) - } - }); - vm.bx.threads.cur().json_parser = json_parser; - return result; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "to_string called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(push), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx.heap.array_push_vec(sself, args, trap); - return NIL; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "push called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(pop), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.array_pop(sself, trap); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "pop called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(clear), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx.heap.array_clear(sself, trap); - return NIL; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "clear called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(len), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - return vm.bx.heap.array_len(sself).into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "len called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(remove), - script_args!(index = NIL), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - let index = script_value!(vm, args.index); - let idx = index.as_index(); - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.array_remove(sself, idx, trap); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "remove called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(freeze), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - vm.bx.heap.freeze_array(sself); - return sself.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "freeze called on non-array value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_ARRAY, - id!(retain), - script_args!(cb = NIL), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_array() { - let fnptr = script_value!(vm, args.cb); - let mut i = 0; - while i < vm.bx.heap.array_len(sself) { - let value = script_array_index!(vm, sself[i]); - let ret = vm.call(fnptr, &[value]); - if ret.is_err() { - return ret; - } - if !vm.bx.heap.cast_to_bool(ret) { - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx.heap.array_remove(sself, i, trap); - } else { - i += 1 - } - } - return NIL; - } - script_err_not_impl!( - vm.bx.threads.cur_ref().trap, - "retain called on non-array value" - ) - }, - ); - } - - pub fn clear(&mut self) { - self.storage.clear(); - self.tag.clear() - } - - pub fn is_value_array(&self) -> bool { - if let ScriptArrayStorage::ScriptValue(_) = &self.storage { - true - } else { - false - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn incremental_utf8_lossy_matches_std() { - for bytes in [ - b"valid".as_slice(), - b"prefix\xFFsuffix".as_slice(), - b"\xF0\x9F\x92".as_slice(), - b"\xC3\xA9\xFF\x80".as_slice(), - ] { - let mut out = String::new(); - append_utf8_lossy(bytes, &mut out); - assert_eq!(out, String::from_utf8_lossy(bytes).as_ref()); - } - } -} diff --git a/vendor/makepad/platform/script/src/array_heap.rs b/vendor/makepad/platform/script/src/array_heap.rs deleted file mode 100644 index db51654..0000000 --- a/vendor/makepad/platform/script/src/array_heap.rs +++ /dev/null @@ -1,404 +0,0 @@ -use crate::heap::*; -use crate::trap::*; -use crate::value::*; -use crate::*; -use std::mem::size_of; - -impl ScriptHeap { - // Arrays - - fn prepare_array_storage_growth( - &mut self, - array: ScriptArray, - requested_len: usize, - ) -> Option { - let storage = &self.arrays[array].storage; - let before = storage.retained_bytes(); - if self.max_heap_bytes.is_none() { - return Some(before); - } - let growth = storage - .minimum_bytes_for_len(requested_len) - .map(|required| required.saturating_sub(before)); - if self.can_grow_heap_by(growth) { - Some(before) - } else { - None - } - } - - pub(crate) fn note_array_storage_growth(&mut self, array: ScriptArray, before: usize) { - let after = self.arrays[array].storage.retained_bytes(); - self.note_heap_capacity_change(before, after); - } - - pub fn freeze_array(&mut self, array: ScriptArray) { - self.arrays[array].tag.freeze() - } - - pub fn new_array(&mut self) -> ScriptArray { - let capacity = self.arrays.capacity(); - let (array, previous_storage) = if let Some(arr) = self.arrays_free.pop() { - // arr already has the correct generation from gc.rs sweep - let array = &mut self.arrays[arr]; - let previous_storage = array.storage.retained_bytes(); - // Reused array slots may come from typed buffers (U8/U16/U32/F32). - // New arrays must start as generic ScriptValue storage. - if !matches!(array.storage, ScriptArrayStorage::ScriptValue(_)) { - array.storage = ScriptArrayStorage::ScriptValue(Default::default()); - } else { - array.storage.clear(); - } - array.tag.set_alloced(); - (arr, previous_storage) - } else { - let index = self.arrays.len(); - let mut array = ScriptArrayData::default(); - array.tag.set_alloced(); - self.arrays.push(array); - // New slot starts at generation 0 - (ScriptArray::new(index as _, crate::value::GENERATION_ZERO), 0) - }; - self.note_heap_growth( - self.arrays - .capacity() - .saturating_sub(capacity) - .saturating_mul(size_of::>()), - ); - self.note_heap_capacity_change( - previous_storage, - self.arrays[array].storage.retained_bytes(), - ); - array - } - - pub fn array_len(&self, array: ScriptArray) -> usize { - self.arrays[array].storage.len() - } - - pub fn array_push(&mut self, array: ScriptArray, value: ScriptValue, trap: ScriptTrap) { - if self.arrays[array].tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return; - } - let Some(requested_len) = self.arrays[array].storage.len().checked_add(1) else { - self.can_grow_heap_by(None); - return; - }; - let Some(before) = self.prepare_array_storage_growth(array, requested_len) else { - return; - }; - { - let array_data = &mut self.arrays[array]; - array_data.tag.set_dirty(); - array_data.storage.push(value); - } - self.note_array_storage_growth(array, before); - } - - pub fn array_pop_front_option(&mut self, array: ScriptArray) -> Option { - let array = &mut self.arrays[array]; - if array.tag.is_immutable() { - return None; - } - array.tag.set_dirty(); - array.storage.pop_front() - } - - pub fn array_push_vec(&mut self, array: ScriptArray, object: ScriptObject, trap: ScriptTrap) { - if self.arrays[array].tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return; - } - let Some(requested_len) = self.arrays[array] - .storage - .len() - .checked_add(self.objects[object].vec.len()) - else { - self.can_grow_heap_by(None); - return; - }; - let Some(before) = self.prepare_array_storage_growth(array, requested_len) else { - return; - }; - let values = self.objects[object] - .vec - .iter() - .map(|entry| entry.value) - .collect::>(); - { - let array_data = &mut self.arrays[array]; - array_data.tag.set_dirty(); - for value in values { - array_data.storage.push(value); - } - } - self.note_array_storage_growth(array, before); - } - - /// Merges all elements from source array into target array. - /// Used by the splat operator (..) to spread one array into another. - pub fn merge_array(&mut self, target: ScriptArray, source: ScriptArray, trap: ScriptTrap) { - if self.arrays[target].tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return; - } - // Get the storage from source first - let source_storage = &self.arrays[source].storage; - let values: Vec = match source_storage { - ScriptArrayStorage::ScriptValue(v) => v.iter().copied().collect(), - ScriptArrayStorage::U8(v) => { - v.iter().map(|x| ScriptValue::from_f64(*x as f64)).collect() - } - ScriptArrayStorage::U16(v) => { - v.iter().map(|x| ScriptValue::from_f64(*x as f64)).collect() - } - ScriptArrayStorage::U32(v) => { - v.iter().map(|x| ScriptValue::from_f64(*x as f64)).collect() - } - ScriptArrayStorage::F32(v) => { - v.iter().map(|x| ScriptValue::from_f64(*x as f64)).collect() - } - }; - - let Some(requested_len) = self.arrays[target].storage.len().checked_add(values.len()) else { - self.can_grow_heap_by(None); - return; - }; - let Some(before) = self.prepare_array_storage_growth(target, requested_len) else { - return; - }; - let target_arr = &mut self.arrays[target]; - target_arr.tag.set_dirty(); - for v in values { - target_arr.storage.push(v); - } - self.note_array_storage_growth(target, before); - } - - pub fn array_push_unchecked(&mut self, array: ScriptArray, value: ScriptValue) { - let Some(requested_len) = self.arrays[array].storage.len().checked_add(1) else { - self.can_grow_heap_by(None); - return; - }; - let Some(before) = self.prepare_array_storage_growth(array, requested_len) else { - return; - }; - { - let array_data = &mut self.arrays[array]; - array_data.tag.set_dirty(); - array_data.storage.push(value); - } - self.note_array_storage_growth(array, before); - } - - pub fn array_storage(&self, array: ScriptArray) -> &ScriptArrayStorage { - let array = &self.arrays[array]; - &array.storage - } - - pub fn new_array_from_vec_u8(&mut self, data: Vec) -> ScriptArray { - let ptr = self.new_array(); - let before = self.arrays[ptr].storage.retained_bytes(); - { - let array_data = &mut self.arrays[ptr]; - array_data.tag.set_dirty(); - array_data.storage = ScriptArrayStorage::U8(data); - } - self.note_array_storage_growth(ptr, before); - ptr - } - - /// Mutates one array storage value while preserving aggregate heap - /// accounting. Normal VM and adapter conversion paths should prefer this - /// over [`Self::array_mut`]. - pub(crate) fn array_mut_with R>( - &mut self, - array: ScriptArray, - trap: ScriptTrap, - cb: F, - ) -> Option { - let before = self.arrays[array].storage.retained_bytes(); - let result = { - let array_data = &mut self.arrays[array]; - if array_data.tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return None; - } - array_data.tag.set_dirty(); - cb(&mut array_data.storage) - }; - self.note_array_storage_growth(array, before); - Some(result) - } - - /// Returns direct mutable access for trusted raw VM hosts. - /// - /// This cannot observe capacity changes after the borrow escapes. A host - /// that uses it while a heap cap is active must call - /// [`Self::reconcile_heap_bytes`] before it re-enters untrusted script. - /// Octoscript's normal VM paths use accounting-aware helpers instead. - pub fn array_mut( - &mut self, - array: ScriptArray, - trap: ScriptTrap, - ) -> Option<&mut ScriptArrayStorage> { - let array = &mut self.arrays[array]; - if array.tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return None; - } - array.tag.set_dirty(); - Some(&mut array.storage) - } - - pub fn array_mut_self_with R>( - &mut self, - array: ScriptArray, - cb: F, - ) -> R { - let mut storage = ScriptArrayStorage::ScriptValue(Default::default()); - std::mem::swap(&mut self.arrays[array].storage, &mut storage); - let r = cb(self, &storage); - std::mem::swap(&mut self.arrays[array].storage, &mut storage); - r - } - - pub fn array_mut_mut_self_with R>( - &mut self, - array: ScriptArray, - cb: F, - ) -> R { - let before = self.arrays[array].storage.retained_bytes(); - let mut storage = ScriptArrayStorage::ScriptValue(Default::default()); - std::mem::swap(&mut self.arrays[array].storage, &mut storage); - let r = cb(self, &mut storage); - std::mem::swap(&mut self.arrays[array].storage, &mut storage); - self.note_array_storage_growth(array, before); - r - } - - pub fn array_remove( - &mut self, - array: ScriptArray, - index: usize, - trap: ScriptTrap, - ) -> ScriptValue { - let array = &mut self.arrays[array]; - if array.tag.is_immutable() { - return script_err_immutable!(trap, "array is immutable"); - } - array.tag.set_dirty(); - if index >= array.storage.len() { - return script_err_out_of_bounds!( - trap, - "array remove index {} out of bounds (len={})", - index, - array.storage.len() - ); - } - array.storage.remove(index) - } - - pub fn array_pop(&mut self, array: ScriptArray, trap: ScriptTrap) -> ScriptValue { - let array = &mut self.arrays[array]; - if array.tag.is_immutable() { - return script_err_immutable!(trap, "array is immutable"); - } - if let Some(value) = array.storage.pop() { - array.tag.set_dirty(); - value - } else { - script_err_out_of_bounds!(trap, "array pop on empty array") - } - } - - pub fn array_clear(&mut self, array: ScriptArray, trap: ScriptTrap) { - let array = &mut self.arrays[array]; - if array.tag.is_immutable() { - script_err_immutable!(trap, "array is immutable"); - return; - } - if array.storage.len() != 0 { - array.storage.clear(); - array.tag.set_dirty(); - } - } - - pub fn array_index(&self, array: ScriptArray, index: usize, trap: ScriptTrap) -> ScriptValue { - let storage = &self.arrays[array].storage; - if let Some(value) = storage.index(index) { - return value; - } else { - script_err_out_of_bounds!( - trap, - "array index {} out of bounds (len={})", - index, - storage.len() - ) - } - } - - pub fn array_index_unchecked(&self, array: ScriptArray, index: usize) -> ScriptValue { - if let Some(value) = self.arrays[array].storage.index(index) { - return value; - } else { - NIL - } - } - - pub fn set_array_index( - &mut self, - array: ScriptArray, - index: usize, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - if self.arrays[array].tag.is_immutable() { - return script_err_immutable!(trap, "array is immutable"); - } - let Some(requested_len) = index.checked_add(1) else { - self.can_grow_heap_by(None); - return NIL; - }; - let Some(before) = self.prepare_array_storage_growth(array, requested_len) else { - return NIL; - }; - { - let array_data = &mut self.arrays[array]; - array_data.tag.set_dirty(); - array_data.storage.set_index(index, value); - } - self.note_array_storage_growth(array, before); - NIL - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::array::ScriptArrayStorage; - - #[test] - fn reused_array_slot_resets_to_script_value_storage() { - let mut heap = ScriptHeap::default(); - - let typed_array = heap.new_array_from_vec_u8(vec![1, 2, 3, 4]); - let index = typed_array.index() as usize; - - // Simulate GC sweep/free for this slot. - heap.arrays[typed_array].clear(); - heap.arrays.free_slot(typed_array.index()); - let new_gen = heap.arrays.generation(index); - heap.arrays_free - .push(ScriptArray::new(typed_array.index(), new_gen)); - - let reused = heap.new_array(); - assert_eq!(reused.index(), typed_array.index()); - assert!(matches!( - heap.arrays[reused].storage, - ScriptArrayStorage::ScriptValue(_) - )); - assert_eq!(heap.array_len(reused), 0); - } -} diff --git a/vendor/makepad/platform/script/src/colorhex.rs b/vendor/makepad/platform/script/src/colorhex.rs deleted file mode 100644 index 7746774..0000000 --- a/vendor/makepad/platform/script/src/colorhex.rs +++ /dev/null @@ -1,92 +0,0 @@ -/* -pub fn from_hex_str(hex: &str) -> Result { - Self::from_hex_bytes(hex.as_bytes()) -}*/ -/* -pub fn from_hex_bytes(bytes: &[u8]) -> Result { - let color = if bytes.len()>2 && bytes[0] == '#' as u8 { - hex_bytes_to_u32(&bytes[1..])? - } - else { - hex_bytes_to_u32(bytes)? - }; - Ok(Vec4f { - x: (((color >> 24)&0xff) as f32) / 255.0, - y: (((color >> 16)&0xff) as f32) / 255.0, - z: (((color >> 8)&0xff) as f32) / 255.0, - w: (((color >> 0)&0xff) as f32) / 255.0, - }) -}*/ - -pub fn hex_bytes_to_u32(buf: &[u8]) -> Result { - fn hex_to_int(c: u8) -> Result { - if (48..=57).contains(&c) { - return Ok((c - 48) as u32); - } - if (65..=70).contains(&c) { - return Ok((c - 65 + 10) as u32); - } - if (97..=102).contains(&c) { - return Ok((c - 97 + 10) as u32); - } - Err(()) - } - - match buf.len() { - 1 => { - // #w - let val = hex_to_int(buf[0])?; - return Ok((val << 28) - | (val << 24) - | (val << 20) - | (val << 16) - | (val << 12) - | (val << 8) - | 0xff); - } - 2 => { - //#ww - let val = (hex_to_int(buf[0])? << 4) + hex_to_int(buf[1])?; - return Ok((val << 24) | (val << 16) | (val << 8) | 0xff); - } - 3 => { - // #rgb - let r = hex_to_int(buf[0])?; - let g = hex_to_int(buf[1])?; - let b = hex_to_int(buf[2])?; - return Ok((r << 28) | (r << 24) | (g << 20) | (g << 16) | (b << 12) | (b << 8) | 0xff); - } - 4 => { - // #rgba - let r = hex_to_int(buf[0])?; - let g = hex_to_int(buf[1])?; - let b = hex_to_int(buf[2])?; - let a = hex_to_int(buf[3])?; - return Ok((r << 28) - | (r << 24) - | (g << 20) - | (g << 16) - | (b << 12) - | (b << 8) - | (a << 4) - | a); - } - 6 => { - // #rrggbb - let r = (hex_to_int(buf[0])? << 4) + hex_to_int(buf[1])?; - let g = (hex_to_int(buf[2])? << 4) + hex_to_int(buf[3])?; - let b = (hex_to_int(buf[4])? << 4) + hex_to_int(buf[5])?; - return Ok((r << 24) | (g << 16) | (b << 8) | 0xff); - } - 8 => { - // #rrggbbaa - let r = (hex_to_int(buf[0])? << 4) + hex_to_int(buf[1])?; - let g = (hex_to_int(buf[2])? << 4) + hex_to_int(buf[3])?; - let b = (hex_to_int(buf[4])? << 4) + hex_to_int(buf[5])?; - let a = (hex_to_int(buf[6])? << 4) + hex_to_int(buf[7])?; - return Ok((r << 24) | (g << 16) | (b << 8) | a); - } - _ => (), - } - Err(()) -} diff --git a/vendor/makepad/platform/script/src/equality.rs b/vendor/makepad/platform/script/src/equality.rs deleted file mode 100644 index 6c4dab9..0000000 --- a/vendor/makepad/platform/script/src/equality.rs +++ /dev/null @@ -1,158 +0,0 @@ -//! Iterative structural equality. Container pairs are visited once, including -//! cyclic graphs and shared DAGs. Language opcodes supply fuel/deadline checks. - -use crate::makepad_live_id::LiveId; -use crate::{array::ScriptArrayStorage, heap::ScriptHeap, value::ScriptValue}; -use std::collections::HashSet; - -/// Independent ceiling on native comparison work and its temporary storage. -pub const MAX_EQUALITY_WORK: usize = 65_536; - -impl ScriptHeap { - /// Trusted host comparison without VM fuel. Still iterative and cycle-safe. - pub fn deep_eq(&self, a: ScriptValue, b: ScriptValue) -> bool { - self.deep_eq_bounded(a, b, usize::MAX, || true) - .unwrap_or(false) - } - - /// `None` is resource exhaustion, never a comparison result. Every queued - /// edge and processed pair consumes work before allocation or traversal. - pub fn deep_eq_bounded( - &self, - a: ScriptValue, - b: ScriptValue, - maximum_work: usize, - mut charge_host: impl FnMut() -> bool, - ) -> Option { - let mut remaining = maximum_work; - let mut charge = || { - remaining = remaining.checked_sub(1)?; - charge_host().then_some(()) - }; - let mut pending = vec![(a, b)]; - let mut visited = HashSet::new(); - while let Some((a, b)) = pending.pop() { - charge()?; - if a.is_nan() || b.is_nan() { - return Some(false); - } - if a == b { - continue; - } - if let Some(a) = a.as_number() { - if b.as_number() != Some(a) { - return Some(false); - } - continue; - } - if a.is_string_like() || b.is_string_like() { - let equal = self - .string_with(a, |heap, a| { - heap.string_with(b, |_, b| { - if a.len() != b.len() { - return Some(false); - } - for (a, b) in a.as_bytes().chunks(256).zip(b.as_bytes().chunks(256)) { - charge()?; - if a != b { - return Some(false); - } - } - Some(true) - }) - .unwrap_or(Some(false)) - }) - .unwrap_or(Some(false))?; - if !equal { - return Some(false); - } - continue; - } - if let (Some(pa), Some(pb)) = (a.as_object(), b.as_object()) { - if !visited.insert((a, b)) { - continue; - } - let oa = &self.objects[pa]; - let ob = &self.objects[pb]; - if oa.vec.len() != ob.vec.len() || oa.map_len() != ob.map_len() { - return Some(false); - } - charge()?; - pending.push((oa.proto, ob.proto)); - for (a, b) in oa.vec.iter().zip(&ob.vec) { - charge()?; - pending.push((a.key, b.key)); - charge()?; - pending.push((a.value, b.value)); - } - if let Some(result) = oa.map_iter_ret(|key, value| { - if charge().is_none() { - return Some(None); - } - let other = ob.map_get(&key).or_else(|| { - // JSON string keys and source identifier keys name the - // same fields without changing either object. - if let Some(id) = key.as_id().filter(|_| ob.tag.is_string_keys()) { - id.as_string(|s| { - s.and_then(|s| self.check_intern_string(s)) - .and_then(|key| ob.map_get(&key)) - }) - } else if key.is_string_like() && !ob.tag.is_string_keys() { - self.string_with(key, |_, s| ob.map_get(&LiveId::from_str(s).into())) - .flatten() - } else { - None - } - }); - let Some(other) = other else { - return Some(Some(false)); - }; - pending.push((value, other)); - None - }) { - return result; - } - continue; - } - if let (Some(pa), Some(pb)) = (a.as_array(), b.as_array()) { - if !visited.insert((a, b)) { - continue; - } - let a = &self.arrays[pa].storage; - let b = &self.arrays[pb].storage; - macro_rules! scalar_array { - ($a:expr, $b:expr) => {{ - if $a.len() != $b.len() { - return Some(false); - } - for (a, b) in $a.iter().zip($b) { - charge()?; - if a != b { - return Some(false); - } - } - }}; - } - match (a, b) { - (ScriptArrayStorage::ScriptValue(a), ScriptArrayStorage::ScriptValue(b)) => { - if a.len() != b.len() { - return Some(false); - } - for (&a, &b) in a.iter().zip(b) { - charge()?; - pending.push((a, b)); - } - } - (ScriptArrayStorage::F32(a), ScriptArrayStorage::F32(b)) => scalar_array!(a, b), - (ScriptArrayStorage::U32(a), ScriptArrayStorage::U32(b)) => scalar_array!(a, b), - (ScriptArrayStorage::U16(a), ScriptArrayStorage::U16(b)) => scalar_array!(a, b), - (ScriptArrayStorage::U8(a), ScriptArrayStorage::U8(b)) => scalar_array!(a, b), - _ => return Some(false), - } - continue; - } - return Some(false); - } - Some(true) - } -} diff --git a/vendor/makepad/platform/script/src/function.rs b/vendor/makepad/platform/script/src/function.rs deleted file mode 100644 index 9390ab0..0000000 --- a/vendor/makepad/platform/script/src/function.rs +++ /dev/null @@ -1,184 +0,0 @@ -use crate::suggest::format_value_type; -use crate::trap::*; -use crate::value::*; -use crate::*; - -#[derive(Debug, Clone, Copy)] -pub struct NativeId { - pub index: u32, -} - -#[derive(Clone)] -pub struct ScriptFnRef(pub(crate) ScriptObjectRef); - -impl From for ScriptValue { - fn from(v: ScriptFnRef) -> Self { - ScriptValue::from_object(v.as_object()) - } -} - -impl ScriptFnRef { - pub fn as_object(&self) -> ScriptObject { - self.0.as_object() - } -} - -#[derive(Debug, Clone, Copy)] -pub enum ScriptFnPtr { - Script(ScriptIp), - Native(NativeId), -} - -impl ScriptRefOptionExt for Option { - fn as_object(&self) -> Option { - if let Some(x) = self { - Some(x.as_object()) - } else { - None - } - } -} - -impl ScriptHeap { - // Functions - - pub fn set_fn(&mut self, ptr: ScriptObject, fnptr: ScriptFnPtr) { - let object = &mut self.objects[ptr]; - object.tag.set_fn(fnptr); - } - - pub fn as_fn(&self, ptr: ScriptObject) -> Option { - let object = &self.objects[ptr]; - object.tag.as_fn() - } - - pub fn is_fn(&self, ptr: ScriptObject) -> bool { - let object = &self.objects[ptr]; - object.tag.is_fn() - } - - pub fn set_reffed(&mut self, ptr: ScriptObject) { - let object = &mut self.objects[ptr]; - object.tag.set_reffed(); - } - - pub fn parent_as_fn(&self, ptr: ScriptObject) -> Option { - let object = &self.objects[ptr]; - if let Some(ptr) = object.proto.as_object() { - let fn_object = &self.objects[ptr]; - fn_object.tag.as_fn() - } else { - None - } - } - - pub fn unnamed_fn_arg( - &mut self, - top_ptr: ScriptObject, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let object = &self.objects[top_ptr]; - - // which arg number? - let index = object.map_len(); - - if let Some(ptr) = object.proto.as_object() { - let proto_object = &self.objects[ptr]; - if let Some(kv) = proto_object.vec.get(index) { - let key = kv.key; - if let Some(def) = object.vec.get(index) { - if !def.value.is_nil() - && def.value.value_type().to_redux() != value.value_type().to_redux() - { - return script_err_type_mismatch!( - trap, - "arg {} type mismatch: expected {}, got {}", - index, - format_value_type(self, def.value), - format_value_type(self, value) - ); - } - } - self.insert_object_map(top_ptr, key, value); - return NIL; - } - } - // only allow if we are varargs - self.push_object_vec(top_ptr, ScriptVecValue { key: NIL, value }); - return NIL; - } - - pub fn named_fn_arg( - &mut self, - top_ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let object = &self.objects[top_ptr]; - - if let Some(ptr) = object.proto.as_object() { - let object = &self.objects[ptr]; - for kv in object.vec.iter() { - if kv.key == key { - if !kv.value.is_nil() - && kv.value.value_type().to_redux() != value.value_type().to_redux() - { - return script_err_type_mismatch!( - trap, - "named arg {:?} type mismatch: expected {}, got {}", - key, - format_value_type(self, kv.value), - format_value_type(self, value) - ); - } - self.insert_object_map(top_ptr, key, value); - return NIL; - } - } - return script_err_not_found!(trap, "unknown named arg {:?}", key); - } - script_err_unexpected!(trap, "named_fn_arg called without prototype object") - } - - pub fn push_all_fn_args( - &mut self, - top_ptr: ScriptObject, - args: &[ScriptValue], - trap: ScriptTrap, - ) -> ScriptValue { - let object = &self.objects[top_ptr]; - if let Some(ptr) = object.proto.as_object() { - for (index, value) in args.iter().enumerate() { - let object = &self.objects[ptr]; - if let Some(v1) = object.vec.get(index) { - let key = v1.key; - // typecheck against default arg - if let Some(def) = object.vec.get(index) { - if !def.value.is_nil() - && def.value.value_type().to_redux() != value.value_type().to_redux() - { - return script_err_type_mismatch!( - trap, - "arg {} ({:?}) type mismatch: expected {}, got {}", - index, - key, - format_value_type(self, def.value), - format_value_type(self, *value) - ); - } - } - self.insert_object_map(top_ptr, key, *value); - } else { - self.push_object_vec(top_ptr, ScriptVecValue { - key: NIL, - value: *value, - }); - } - } - return NIL; - } - script_err_unexpected!(trap, "push_all_fn_args called without prototype object") - } -} diff --git a/vendor/makepad/platform/script/src/gc.rs b/vendor/makepad/platform/script/src/gc.rs deleted file mode 100644 index 6272cc8..0000000 --- a/vendor/makepad/platform/script/src/gc.rs +++ /dev/null @@ -1,776 +0,0 @@ -use crate::array::*; -use crate::function::*; -use crate::handle::*; -use crate::heap::*; -use crate::makepad_error_log::*; - -use crate::object::*; -use crate::regex::*; -use crate::thread::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; - -use std::collections::hash_map::Entry; -use std::sync::Arc; - -/// Tracks heap statistics from the last garbage collection run. -/// Used to determine when to trigger the next GC cycle. -#[derive(Default, Clone, Copy)] -pub struct ScriptHeapGcLast { - pub objects: usize, - pub strings: usize, - pub arrays: usize, - pub pods: usize, - pub handles: usize, - pub regexes: usize, -} - -/// Lightweight mark item for GC work list - just the reference, no debug info -#[derive(Copy, Clone)] -pub enum ScriptGcMark { - Object(ScriptObject), - Array(ScriptArray), -} - -// Queue values for static marking - used inside map_iter closures where we can't check is_static -macro_rules! queue_static_val { - ($self:ident, $val:expr) => { - if let Some(ptr) = $val.as_object() { - $self.mark_vec.push(ScriptGcMark::Object(ptr)); - } else if let Some(ptr) = $val.as_string() { - if let Some(str_data) = $self.strings[ptr].as_mut() { - str_data.tag.set_static(); - } - } else if let Some(ptr) = $val.as_array() { - $self.mark_vec.push(ScriptGcMark::Array(ptr)); - } else if let Some(ptr) = $val.as_pod() { - $self.pods[ptr].tag.set_static(); - } else if let Some(ptr) = $val.as_handle() { - if let Some(handle_data) = $self.handles[ptr].as_mut() { - handle_data.tag.set_static(); - } - } else if let Some(ptr) = $val.as_regex() { - if let Some(regex_data) = $self.regexes[ptr].as_mut() { - regex_data.tag.set_static(); - } - } - }; -} - -// Set static with check - used outside closures where we can check is_static -macro_rules! set_static_val { - ($self:ident, $val:expr) => { - if let Some(ptr) = $val.as_object() { - if !$self.objects[ptr].tag.is_static() { - $self.mark_vec.push(ScriptGcMark::Object(ptr)); - } - } else if let Some(ptr) = $val.as_string() { - if let Some(str_data) = $self.strings[ptr].as_mut() { - str_data.tag.set_static(); - } - } else if let Some(ptr) = $val.as_array() { - if !$self.arrays[ptr].tag.is_static() { - $self.mark_vec.push(ScriptGcMark::Array(ptr)); - } - } else if let Some(ptr) = $val.as_pod() { - $self.pods[ptr].tag.set_static(); - } else if let Some(ptr) = $val.as_handle() { - if let Some(handle_data) = $self.handles[ptr].as_mut() { - handle_data.tag.set_static(); - } - } else if let Some(ptr) = $val.as_regex() { - if let Some(regex_data) = $self.regexes[ptr].as_mut() { - regex_data.tag.set_static(); - } - } - }; -} - -// Mark a value using split field borrows (so callers can iterate maps without snapshot Vecs) -macro_rules! mark_value_fields { - ($objects:expr, $arrays:expr, $strings:expr, $pods:expr, $handles:expr, $regexes:expr, $mark_vec:expr, $val:expr) => { - if let Some(ptr) = $val.as_object() { - let object = &$objects[ptr]; - if !object.tag.is_static() && object.tag.is_alloced() { - $mark_vec.push(ScriptGcMark::Object(ptr)); - } - } else if let Some(ptr) = $val.as_string() { - if let Some(str_data) = $strings[ptr].as_mut() { - if !str_data.tag.is_static() { - str_data.tag.set_mark(); - } - } - } else if let Some(ptr) = $val.as_array() { - let array = &$arrays[ptr]; - if !array.tag.is_static() && array.tag.is_alloced() { - $mark_vec.push(ScriptGcMark::Array(ptr)); - } - } else if let Some(ptr) = $val.as_pod() { - let pod = &mut $pods[ptr]; - if !pod.tag.is_static() && pod.tag.is_alloced() { - pod.tag.set_mark(); - } - } else if let Some(ptr) = $val.as_handle() { - // Skip handle index 0 - it's the "null" handle (ScriptHandle::ZERO) - if ptr.index != 0 { - if let Some(handle_data) = $handles[ptr].as_mut() { - if !handle_data.tag.is_static() { - handle_data.tag.set_mark(); - } - } - } - } else if let Some(ptr) = $val.as_regex() { - if let Some(regex_data) = $regexes[ptr].as_mut() { - if !regex_data.tag.is_static() { - regex_data.tag.set_mark(); - } - } - } - }; -} - -impl ScriptHeap { - /// Recursively mark a value and all reachable values as static (permanent). - /// This walks the object graph similar to GC marking but sets the static flag instead. - pub fn set_static(&mut self, value: ScriptValue) { - self.mark_vec.clear(); - - // Initial value - set_static_val!(self, value); - - // Process the work list - use while loop since set_static_inner adds to mark_vec - let mut i = 0; - while i < self.mark_vec.len() { - let mark = self.mark_vec[i]; - self.set_static_inner(mark); - i += 1; - } - } - - fn set_static_inner(&mut self, value: ScriptGcMark) { - match value { - ScriptGcMark::Object(obj) => { - let object = &mut self.objects[obj]; - // Skip if already static or not allocated - if object.tag.is_static() || !object.tag.is_alloced() { - return; - } - object.tag.set_static(); - - // Queue all referenced values using macro (no is_static check inside closure) - // Also queues proto chain - let proto = object.proto; - queue_static_val!(self, proto); - object.map_iter(|key, val| { - queue_static_val!(self, key); - queue_static_val!(self, val); - }); - let len = object.vec.len(); - for j in 0..len { - let object = &self.objects[obj]; - let key = object.vec[j].key; - let val = object.vec[j].value; - set_static_val!(self, key); - set_static_val!(self, val); - } - } - ScriptGcMark::Array(arr) => { - let array = &mut self.arrays[arr]; - // Skip if already static or not allocated - if array.tag.is_static() || !array.tag.is_alloced() { - return; - } - array.tag.set_static(); - - // Queue all referenced values - if let ScriptArrayStorage::ScriptValue(values) = &self.arrays[arr].storage { - for v in values { - set_static_val!(self, v); - } - } - } - } - } - - pub fn new_object_ref(&mut self, obj: ScriptObject) -> ScriptObjectRef { - // Mark as reffed so free_object_if_unreffed won't free it - self.objects[obj].tag.set_reffed(); - - let mut roots = self.root_objects.borrow_mut(); - match roots.entry(obj) { - Entry::Occupied(mut occ) => { - *occ.get_mut() += 1; - ScriptObjectRef { - roots: Some(self.root_objects.clone()), - obj: obj, - } - } - Entry::Vacant(vac) => { - vac.insert(1); - ScriptObjectRef { - roots: Some(self.root_objects.clone()), - obj: obj, - } - } - } - } - - pub fn new_array_ref(&mut self, array: ScriptArray) -> ScriptArrayRef { - let mut roots = self.root_arrays.borrow_mut(); - match roots.entry(array) { - Entry::Occupied(mut occ) => { - *occ.get_mut() += 1; - ScriptArrayRef { - roots: self.root_arrays.clone(), - array: array, - } - } - Entry::Vacant(vac) => { - vac.insert(1); - ScriptArrayRef { - roots: self.root_arrays.clone(), - array: array, - } - } - } - } - - pub fn new_fn_ref(&mut self, obj: ScriptObject) -> ScriptFnRef { - ScriptFnRef(self.new_object_ref(obj)) - } - - pub fn new_handle_ref(&mut self, handle: ScriptHandle) -> ScriptHandleRef { - let mut roots = self.root_handles.borrow_mut(); - match roots.entry(handle) { - Entry::Occupied(mut occ) => { - *occ.get_mut() += 1; - ScriptHandleRef { - roots: self.root_handles.clone(), - handle: handle, - } - } - Entry::Vacant(vac) => { - vac.insert(1); - ScriptHandleRef { - roots: self.root_handles.clone(), - handle: handle, - } - } - } - } - - pub fn mark_inner(&mut self, mark: ScriptGcMark) { - match mark { - ScriptGcMark::Object(obj) => { - // Check flags and set mark - let object = &mut self.objects[obj]; - // Static objects are assumed to only reference static values, so - // they do not need traversal during normal GC marking. - if object.tag.is_static() || object.tag.is_marked() || !object.tag.is_alloced() { - return; - } - object.tag.set_mark(); - - // Mark proto/map/vec entries directly without temporary Vec snapshots. - let (objects, arrays, strings, pods, handles, regexes, mark_vec) = ( - &self.objects, - &self.arrays, - &mut self.strings, - &mut self.pods, - &mut self.handles, - &mut self.regexes, - &mut self.mark_vec, - ); - let object = &objects[obj]; - mark_value_fields!( - objects, - arrays, - strings, - pods, - handles, - regexes, - mark_vec, - object.proto - ); - for (key, val) in object.map.iter() { - mark_value_fields!( - objects, arrays, strings, pods, handles, regexes, mark_vec, *key - ); - mark_value_fields!( - objects, arrays, strings, pods, handles, regexes, mark_vec, val.value - ); - } - for kv in object.vec.iter() { - mark_value_fields!( - objects, arrays, strings, pods, handles, regexes, mark_vec, kv.key - ); - mark_value_fields!( - objects, arrays, strings, pods, handles, regexes, mark_vec, kv.value - ); - } - } - ScriptGcMark::Array(arr) => { - let tag = &self.arrays[arr].tag; - if tag.is_static() || tag.is_marked() || !tag.is_alloced() { - return; - } - self.arrays[arr].tag.set_mark(); - - if let ScriptArrayStorage::ScriptValue(values) = &self.arrays[arr].storage { - let (objects, arrays, strings, pods, handles, regexes, mark_vec) = ( - &self.objects, - &self.arrays, - &mut self.strings, - &mut self.pods, - &mut self.handles, - &mut self.regexes, - &mut self.mark_vec, - ); - for v in values.iter() { - mark_value_fields!( - objects, arrays, strings, pods, handles, regexes, mark_vec, *v - ); - } - } - } - } - } - - /// Mark a single value - adds objects/arrays to work list, marks primitives directly - #[inline] - fn mark_value(&mut self, val: ScriptValue) { - let (objects, arrays, strings, pods, handles, regexes, mark_vec) = ( - &self.objects, - &self.arrays, - &mut self.strings, - &mut self.pods, - &mut self.handles, - &mut self.regexes, - &mut self.mark_vec, - ); - mark_value_fields!(objects, arrays, strings, pods, handles, regexes, mark_vec, val); - } - - pub fn mark(&mut self, threads: &ScriptThreads, code: &ScriptCode) { - self.mark_vec.clear(); - - // Mark type_check protos - for i in 0..self.type_check.len() { - if let Some(object) = &self.type_check[i].object { - self.mark_value(object.proto); - } - } - - // Mark type_defaults objects - { - let (type_defaults, mark_vec) = (&self.type_defaults, &mut self.mark_vec); - for obj in type_defaults.values().copied() { - mark_vec.push(ScriptGcMark::Object(obj)); - } - } - - // Mark pod_types default values and objects - for i in 0..self.pod_types.len() { - let (default, pod_obj) = { - let pod_type = &self.pod_types[i]; - (pod_type.default, pod_type.object) - }; - self.mark_value(default); - if pod_obj != ScriptObject::ZERO { - self.mark_value(pod_obj.into()); - } - } - - // Mark root_objects - { - let roots = self.root_objects.borrow(); - let mark_vec = &mut self.mark_vec; - for item in roots.keys().copied() { - mark_vec.push(ScriptGcMark::Object(item)); - } - } - - // Mark root_arrays - { - let roots = self.root_arrays.borrow(); - let mark_vec = &mut self.mark_vec; - for item in roots.keys().copied() { - mark_vec.push(ScriptGcMark::Array(item)); - } - } - - // Mark root_handles directly - { - let roots = self.root_handles.borrow(); - let handles = &mut self.handles; - for item in roots.keys().copied() { - if let Some(handle_data) = handles[item].as_mut() { - handle_data.tag.set_mark(); - } - } - } - - // Mark thread stacks - for thread_idx in 0..threads.len() { - if let Some(thread) = threads.get(thread_idx) { - // Stack values - for value in thread.stack.iter() { - self.mark_value(*value); - } - // Scopes - for scope in thread.scopes.iter() { - self.mark_value((*scope).into()); - } - // Method call contexts - for me in thread.mes.iter() { - match me { - ScriptMe::Object(obj) => { - self.mark_value((*obj).into()); - } - ScriptMe::Call { sself, args, .. } => { - if let Some(s) = sself { - self.mark_value(*s); - } - self.mark_value((*args).into()); - } - ScriptMe::Pod { pod, .. } => { - self.pods[*pod].tag.set_mark(); - } - ScriptMe::Array(arr) => { - self.mark_value((*arr).into()); - } - } - } - // Loop sources - for loop_frame in thread.loops.iter() { - if let Some(loop_values) = &loop_frame.values { - self.mark_value(loop_values.source); - } - } - // Trap error values - for err in thread.trap.err.borrow().iter() { - self.mark_value(err.value); - } - // Trap return/bail values - match thread.trap.on.get() { - Some(ScriptTrapOn::Return(v)) | Some(ScriptTrapOn::Bail(v)) => { - self.mark_value(v); - } - _ => {} - } - } - } - - // Mark ScriptBody scope and me objects - for body in code.bodies.borrow().iter() { - if let ScriptSource::Mod(script_mod) = &body.source { - for v in script_mod.values.iter() { - self.mark_value(*v); - } - } - - // Mark tokenizer string literals as roots - for str_val in body.tokenizer.iter_strings() { - if let Some(ptr) = str_val.as_string() { - if let Some(str_data) = self.strings[ptr].as_mut() { - if !str_data.tag.is_static() { - str_data.tag.set_mark(); - } - } - } - } - } - - // Mark ScriptNative type_table objects - for type_map in code.native.borrow().type_table.iter() { - for (_, obj) in type_map.iter() { - self.mark_value((*obj).into()); - } - } - - // Process the work list - use while loop since mark_inner adds to mark_vec - let mut i = 0; - while i < self.mark_vec.len() { - let mark = self.mark_vec[i]; - self.mark_inner(mark); - i += 1; - } - } - - pub fn sweep(&mut self, log_stats: bool) { - #[cfg(not(target_arch = "wasm32"))] - let start = std::time::Instant::now(); - - // GC stats: (static, alive, removed) - let (mut obj_static, mut obj_alive, mut obj_removed) = (0usize, 0usize, 0usize); - let (mut arr_static, mut arr_alive, mut arr_removed) = (0usize, 0usize, 0usize); - let (mut str_static, mut str_alive, mut str_removed) = (0usize, 0usize, 0usize); - let (mut hdl_static, mut hdl_alive, mut hdl_removed) = (0usize, 0usize, 0usize); - let (mut pod_static, mut pod_alive, mut pod_removed) = (0usize, 0usize, 0usize); - let (mut rex_static, mut rex_alive, mut rex_removed) = (0usize, 0usize, 0usize); - - for i in 1..self.objects.len() { - let obj = &mut self.objects.get_at_mut(i); - // Skip static objects - they are permanent - if obj.tag.is_static() { - obj_static += 1; - obj.tag.clear_mark(); - continue; - } - if !obj.tag.is_marked() && obj.tag.is_alloced() { - if let Some(pod_ty) = obj.tag.as_pod_type() { - self.pod_types_free.push(pod_ty); - } - obj.clear(); - // Increment generation so stale references will be detected - self.objects.free_slot(i as u32); - // Push ref with NEW generation to free list - ready to reuse - let new_gen = self.objects.generation(i); - self.objects_free.push(ScriptObject::new(i as u32, new_gen)); - obj_removed += 1; - } else { - if obj.tag.is_alloced() { - obj_alive += 1; - } - obj.tag.clear_mark(); - } - } - if obj_removed != 0 { - self.bump_object_reuse_epoch(); - } - for i in 1..self.arrays.len() { - let array = &mut self.arrays.get_at_mut(i); - // Skip static arrays - they are permanent - if array.tag.is_static() { - arr_static += 1; - array.tag.clear_mark(); - continue; - } - if !array.tag.is_marked() && array.tag.is_alloced() { - array.clear(); - // Increment generation, then push ref with new generation - self.arrays.free_slot(i as u32); - let new_gen = self.arrays.generation(i); - self.arrays_free.push(ScriptArray::new(i as u32, new_gen)); - arr_removed += 1; - } else { - if array.tag.is_alloced() { - arr_alive += 1; - } - array.tag.clear_mark(); - } - } - // always leave the empty null string at 0 - for i in 1..self.strings.len() { - if let Some(str) = &mut self.strings.get_at_mut(i) { - // Skip static strings - they are permanent - if str.tag.is_static() { - str_static += 1; - continue; - } - if !str.tag.is_marked() { - if let Some((k, _)) = self.string_intern.remove_entry(&str.string) { - self.strings.set_at(i, None); - if let Some(mut s) = Arc::into_inner(k.0) { - s.clear(); - if self.max_heap_bytes.is_none() { - self.strings_reuse.push(s); - } - } - // Increment generation, then push ref with new generation - self.strings.free_slot(i as u32); - let new_gen = self.strings.generation(i); - self.strings_free.push(ScriptString::new(i as u32, new_gen)); - str_removed += 1; - } - } else { - str_alive += 1; - str.tag.clear_mark(); - } - } - } - for i in 1..self.handles.len() { - if let Some(handle) = &mut self.handles.get_at_mut(i) { - // Skip static handles - they are permanent - if handle.tag.is_static() { - hdl_static += 1; - continue; - } - if !handle.tag.is_marked() { - let handle_data = self.handles.get_at_mut(i).take().unwrap(); - handle_data.gc(); - // Increment generation, then push ref with new generation - self.handles.free_slot(i as u32); - let new_gen = self.handles.generation(i); - // Note: ScriptHandle also needs a type, but for free list we use type 0 - self.handles_free.push(ScriptHandle::new( - ScriptHandleType(0), - i as u32, - new_gen, - )); - hdl_removed += 1; - } else { - hdl_alive += 1; - handle.tag.clear_mark(); - } - } - } - for i in 1..self.pods.len() { - let pod = &mut self.pods.get_at_mut(i); - // Skip static pods - they are permanent - if pod.tag.is_static() { - pod_static += 1; - continue; - } - if !pod.tag.is_marked() && pod.tag.is_alloced() { - pod.clear(); - // Increment generation, then push ref with new generation - self.pods.free_slot(i as u32); - let new_gen = self.pods.generation(i); - self.pods_free.push(ScriptPod::new(i as u32, new_gen)); - pod_removed += 1; - } else { - if pod.tag.is_alloced() { - pod_alive += 1; - } - pod.tag.clear_mark(); - } - } - - for i in 1..self.regexes.len() { - if let Some(re) = &mut self.regexes.get_at_mut(i) { - if re.tag.is_static() { - rex_static += 1; - continue; - } - if !re.tag.is_marked() { - // Build the intern key to remove from intern table - let key = RegexInternKey { - pattern: re.pattern.clone(), - flags: re.flags, - }; - self.regex_intern.remove(&key); - self.regexes.set_at(i, None); - self.regexes.free_slot(i as u32); - let new_gen = self.regexes.generation(i); - self.regexes_free.push(ScriptRegex::new(i as u32, new_gen)); - rex_removed += 1; - } else { - rex_alive += 1; - re.tag.clear_mark(); - } - } - } - - // Print compact GC stats: S=static A=alive R=removed - #[cfg(not(target_arch = "wasm32"))] - let elapsed_us = start.elapsed().as_micros(); - #[cfg(target_arch = "wasm32")] - let elapsed_us = 0u128; - if log_stats { - log!("GC {}us: obj[S:{} A:{} R:{}] arr[S:{} A:{} R:{}] str[S:{} A:{} R:{}] hdl[S:{} A:{} R:{}] pod[S:{} A:{} R:{}] rex[S:{} A:{} R:{}]", - elapsed_us, - obj_static, obj_alive, obj_removed, - arr_static, arr_alive, arr_removed, - str_static, str_alive, str_removed, - hdl_static, hdl_alive, hdl_removed, - pod_static, pod_alive, pod_removed, - rex_static, rex_alive, rex_removed); - } - - // Record heap statistics after GC for triggering next cycle - self.gc_last = ScriptHeapGcLast { - objects: self.objects.len() - self.objects_free.len(), - strings: self.strings.len() - self.strings_free.len(), - arrays: self.arrays.len() - self.arrays_free.len(), - pods: self.pods.len() - self.pods_free.len(), - handles: self.handles.len() - self.handles_free.len(), - regexes: self.regexes.len() - self.regexes_free.len(), - }; - self.reconcile_heap_bytes(); - } - - /// Check if garbage collection should be triggered. - /// - /// Uses a growth-based heuristic similar to Lua and V8: - /// - Trigger when any heap category has grown by 2x since last GC - /// - Use minimum thresholds to avoid GC thrashing on small heaps - /// - Objects are weighted more heavily as they're the primary allocation type - - pub fn needs_gc(&self) -> bool { - // Minimum thresholds before GC can trigger (avoid thrashing on small heaps) - const MIN_OBJECTS: usize = 1024; - const MIN_STRINGS: usize = 256; - const MIN_ARRAYS: usize = 128; - const MIN_PODS: usize = 128; - const MIN_HANDLES: usize = 64; - - // Growth factor - trigger GC when heap doubles (2x) - // This is similar to Lua's default and V8's heuristics - const GROWTH_FACTOR: usize = 2; - - let objects = self.objects.len() - self.objects_free.len(); - let strings = self.strings.len() - self.strings_free.len(); - let arrays = self.arrays.len() - self.arrays_free.len(); - let pods = self.pods.len() - self.pods_free.len(); - let handles = self.handles.len() - self.handles_free.len(); - - // Check each category: must exceed minimum AND have grown by factor - if objects >= MIN_OBJECTS && objects >= self.gc_last.objects * GROWTH_FACTOR { - return true; - } - if strings >= MIN_STRINGS && strings >= self.gc_last.strings * GROWTH_FACTOR { - return true; - } - if arrays >= MIN_ARRAYS && arrays >= self.gc_last.arrays * GROWTH_FACTOR { - return true; - } - if pods >= MIN_PODS && pods >= self.gc_last.pods * GROWTH_FACTOR { - return true; - } - if handles >= MIN_HANDLES && handles >= self.gc_last.handles * GROWTH_FACTOR { - return true; - } - - // Regexes are interned so unlikely to grow fast, but check anyway - let regexes = self.regexes.len() - self.regexes_free.len(); - if regexes >= MIN_HANDLES && regexes >= self.gc_last.regexes * GROWTH_FACTOR { - return true; - } - - false - } - - pub fn gc_live_len(&self) -> usize { - let objects = self.objects.len() - self.objects_free.len(); - let strings = self.strings.len() - self.strings_free.len(); - let arrays = self.arrays.len() - self.arrays_free.len(); - let pods = self.pods.len() - self.pods_free.len(); - let handles = self.handles.len() - self.handles_free.len(); - let regexes = self.regexes.len() - self.regexes_free.len(); - objects + strings + arrays + pods + handles + regexes - } - - pub fn free_object_if_unreffed(&mut self, ptr: ScriptObject) { - // Check if reference is still valid (may have been freed by GC) - if !self.objects.is_valid(ptr) { - return; - } - let obj = &mut self.objects[ptr]; - // Must check is_alloced to avoid double-freeing - if obj.tag.is_alloced() && !obj.tag.is_reffed() { - if let Some(pod_ty) = obj.tag.as_pod_type() { - self.pod_types_free.push(pod_ty); - } - obj.clear(); - // Increment generation so stale references will be detected - self.objects.free_slot(ptr.index); - // Push ref with NEW generation to free list - ready to reuse - let new_gen = self.objects.generation(ptr.index as usize); - self.objects_free - .push(ScriptObject::new(ptr.index, new_gen)); - self.bump_object_reuse_epoch(); - } - } -} diff --git a/vendor/makepad/platform/script/src/gen_index.rs b/vendor/makepad/platform/script/src/gen_index.rs deleted file mode 100644 index 5e4aebc..0000000 --- a/vendor/makepad/platform/script/src/gen_index.rs +++ /dev/null @@ -1,298 +0,0 @@ -/// Generational index system for detecting use-after-free bugs. -/// -/// A GenVec stores data along with a generation counter per slot. When an item is freed -/// and its slot reused, the generation is incremented. Any stale references will -/// have a mismatched generation and can be detected. -/// -/// For release builds, generation checking can be disabled via feature flag. -use crate::value::Generation; - -/// Trait for types that can be used as generational indices into a GenVec. -/// The type must provide an index and a generation. -pub trait GenRef: Copy { - fn index(&self) -> u32; - fn generation(&self) -> Generation; - fn new(index: u32, generation: Generation) -> Self; -} - -/// Metadata stored per slot in a GenVec -#[derive(Debug, Clone)] -pub struct GenSlot { - #[cfg(feature = "check_gen")] - pub generation: Generation, - pub data: T, -} - -impl Default for GenSlot { - #[cfg(feature = "check_gen")] - fn default() -> Self { - Self { - generation: 0, - data: T::default(), - } - } - #[cfg(not(feature = "check_gen"))] - fn default() -> Self { - Self { data: T::default() } - } -} - -impl GenSlot { - #[cfg(feature = "check_gen")] - pub fn new(data: T) -> Self { - Self { - generation: 0, - data, - } - } - #[cfg(not(feature = "check_gen"))] - pub fn new(data: T) -> Self { - Self { data } - } - - /// Increment the generation counter (called when freeing a slot) - #[cfg(feature = "check_gen")] - #[inline] - pub fn increment_generation(&mut self) { - self.generation = self.generation.wrapping_add(1); - } - #[cfg(not(feature = "check_gen"))] - #[inline] - pub fn increment_generation(&mut self) { - // No-op when check_gen is disabled - } -} - -/// A Vec wrapper that tracks generations for each slot. -/// Provides checked access that validates generation on each lookup. -/// -/// Use `Index` where R implements `GenRef` for checked access. -/// Use `Index` for unchecked access (iteration, etc). -#[derive(Debug)] -pub struct GenVec { - slots: Vec>, -} - -impl Default for GenVec { - fn default() -> Self { - Self { slots: Vec::new() } - } -} - -impl GenVec { - pub fn new() -> Self { - Self { slots: Vec::new() } - } - - pub fn with_capacity(capacity: usize) -> Self { - Self { - slots: Vec::with_capacity(capacity), - } - } - - /// Push a new item and return (index, generation) - #[cfg(feature = "check_gen")] - pub fn push(&mut self, data: T) -> (u32, Generation) { - let index = self.slots.len() as u32; - self.slots.push(GenSlot::new(data)); - (index, 0) - } - #[cfg(not(feature = "check_gen"))] - pub fn push(&mut self, data: T) -> (u32, Generation) { - let index = self.slots.len() as u32; - self.slots.push(GenSlot::new(data)); - (index, ()) - } - - /// Get the length of the underlying vec - #[inline] - pub fn len(&self) -> usize { - self.slots.len() - } - - /// Reclaim over-allocated backing capacity. This only shrinks spare capacity (it never - /// changes `len`), so every existing raw index / `GenRef` remains valid. Useful after a - /// large allocation spike followed by a GC: the slot count stays at its high-water mark - /// (slots are reused via the free list), but the Vec's doubling overhead is returned. - #[inline] - pub fn shrink_to_fit(&mut self) { - self.slots.shrink_to_fit(); - } - - /// Backing capacity, for deciding whether a `shrink_to_fit` is worthwhile. - #[inline] - pub fn capacity(&self) -> usize { - self.slots.capacity() - } - - /// Check if empty - #[inline] - pub fn is_empty(&self) -> bool { - self.slots.is_empty() - } - - /// Get the current generation for a slot by raw index - #[cfg(feature = "check_gen")] - #[inline] - pub fn generation(&self, index: usize) -> Generation { - self.slots[index].generation - } - #[cfg(not(feature = "check_gen"))] - #[inline] - pub fn generation(&self, _index: usize) -> Generation { - () - } - - /// Check if a reference is still valid (generation matches) - #[cfg(feature = "check_gen")] - #[inline] - pub fn is_valid(&self, r: R) -> bool { - let index = r.index() as usize; - if index >= self.slots.len() { - return false; - } - self.slots[index].generation == r.generation() - } - #[cfg(not(feature = "check_gen"))] - #[inline] - pub fn is_valid(&self, r: R) -> bool { - let index = r.index() as usize; - index < self.slots.len() - } - - /// Increment the generation for a slot (call this when freeing) - #[inline] - pub fn free_slot(&mut self, index: u32) { - if let Some(slot) = self.slots.get_mut(index as usize) { - slot.increment_generation(); - } - } - - /// Iter over the data items - pub fn iter(&self) -> impl Iterator { - self.slots.iter().map(|s| &s.data) - } - - /// Iter mutably over the data items - pub fn iter_mut(&mut self) -> impl Iterator { - self.slots.iter_mut().map(|s| &mut s.data) - } - - /// Split the underlying slots at a given index for simultaneous mutable access. - /// Returns references to GenSlot (with .data field) to allow accessing both data and generation. - pub fn slots_split_at_mut(&mut self, mid: usize) -> (&mut [GenSlot], &mut [GenSlot]) { - self.slots.split_at_mut(mid) - } - - /// Get a reference to an item by raw index. - /// INTERNAL USE ONLY - bypasses generation check. Use for GC iteration. - #[inline] - pub fn get_at(&self, index: usize) -> &T { - &self.slots[index].data - } - - /// Get a mutable reference to an item by raw index. - /// INTERNAL USE ONLY - bypasses generation check. Use for GC iteration. - #[inline] - pub fn get_at_mut(&mut self, index: usize) -> &mut T { - &mut self.slots[index].data - } - - /// Set an item by raw index. - /// INTERNAL USE ONLY - bypasses generation check. Use for GC sweep. - #[inline] - pub fn set_at(&mut self, index: usize, value: T) { - self.slots[index].data = value; - } -} - -impl GenVec { - /// Allocate a slot, either reusing from free list or growing. - /// Returns a reference type R with the correct generation. - #[cfg(feature = "check_gen")] - pub fn allocate(&mut self, free_list: &mut Vec) -> R { - if let Some(index) = free_list.pop() { - // Reuse freed slot - generation was already incremented when freed - let gen = self.slots[index as usize].generation; - R::new(index, gen) - } else { - // Grow the vec - let index = self.slots.len() as u32; - self.slots.push(GenSlot::default()); - R::new(index, crate::value::GENERATION_ZERO) - } - } - #[cfg(not(feature = "check_gen"))] - pub fn allocate(&mut self, free_list: &mut Vec) -> R { - if let Some(index) = free_list.pop() { - R::new(index, ()) - } else { - let index = self.slots.len() as u32; - self.slots.push(GenSlot::default()); - R::new(index, ()) - } - } -} - -/// Check generation and panic on mismatch -#[cfg(feature = "check_gen")] -#[inline] -fn check_generation( - slots_gen: Generation, - ref_gen: Generation, - index: u32, - type_name: &str, -) { - if slots_gen != ref_gen { - panic!( - "GenVec<{}> use-after-free detected! index={} ref_gen={} slot_gen={}", - type_name, index, ref_gen, slots_gen - ); - } -} - -/// Index by a GenRef type - checked access -impl std::ops::Index for GenVec { - type Output = T; - - #[cfg(feature = "check_gen")] - #[inline] - fn index(&self, r: R) -> &Self::Output { - let slot = &self.slots[r.index() as usize]; - check_generation::( - slot.generation, - r.generation(), - r.index(), - std::any::type_name::(), - ); - &slot.data - } - - #[cfg(not(feature = "check_gen"))] - #[inline] - fn index(&self, r: R) -> &Self::Output { - &self.slots[r.index() as usize].data - } -} - -/// IndexMut by a GenRef type - checked access -impl std::ops::IndexMut for GenVec { - #[cfg(feature = "check_gen")] - #[inline] - fn index_mut(&mut self, r: R) -> &mut Self::Output { - let slot = &mut self.slots[r.index() as usize]; - check_generation::( - slot.generation, - r.generation(), - r.index(), - std::any::type_name::(), - ); - &mut slot.data - } - - #[cfg(not(feature = "check_gen"))] - #[inline] - fn index_mut(&mut self, r: R) -> &mut Self::Output { - &mut self.slots[r.index() as usize].data - } -} diff --git a/vendor/makepad/platform/script/src/handle.rs b/vendor/makepad/platform/script/src/handle.rs deleted file mode 100644 index 753d35d..0000000 --- a/vendor/makepad/platform/script/src/handle.rs +++ /dev/null @@ -1,213 +0,0 @@ -use crate::heap::*; -use crate::value::*; -use std::any::{Any, TypeId}; -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::HashMap; -use std::fmt; -use std::fmt::Debug; -use std::rc::Rc; - -#[derive(Debug)] -pub struct ScriptHandleRef { - pub(crate) roots: Rc>>, - pub(crate) handle: ScriptHandle, -} - -impl From for ScriptValue { - fn from(v: ScriptHandleRef) -> Self { - ScriptValue::from_handle(v.as_handle()) - } -} - -impl Clone for ScriptHandleRef { - fn clone(&self) -> Self { - let mut roots = self.roots.borrow_mut(); - match roots.entry(self.handle) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - *value += 1; - } - Entry::Vacant(_vac) => { - eprintln!("ScriptHandleRef root is vacant!"); - } - } - Self { - roots: self.roots.clone(), - handle: self.handle.clone(), - } - } -} - -impl ScriptHandleRef { - pub fn as_handle(&self) -> ScriptHandle { - self.handle - } -} - -impl Drop for ScriptHandleRef { - fn drop(&mut self) { - let mut roots = self.roots.borrow_mut(); - match roots.entry(self.handle) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - if *value >= 1 { - *value -= 1; - } else { - eprintln!("ScriptHandleRef is 0!"); - } - if *value == 0 { - occ.remove(); - } - } - Entry::Vacant(_vac) => { - eprintln!("ScriptHandleRef root is vacant!"); - } - } - } -} - -impl ScriptHeap { - pub fn new_handle( - &mut self, - ty: ScriptHandleType, - mut hgc: Box, - ) -> ScriptHandle { - if let Some(mut handle) = self.handles_free.pop() { - // handle already has the correct generation from gc.rs sweep - handle.ty = ty; - hgc.set_handle(handle); - self.handles[handle] = Some(ScriptHandleData { - tag: Default::default(), - handle: hgc, - }); - handle - } else { - let index = self.handles.len(); - // New slot starts at generation 0 - let handle = ScriptHandle::new(ty, index as _, crate::value::GENERATION_ZERO); - hgc.set_handle(handle); - self.handles.push(Some(ScriptHandleData { - tag: Default::default(), - handle: hgc, - })); - handle - } - } - - pub fn handle_ref(&self, handle: ScriptHandle) -> Option<&T> { - self.handles[handle] - .as_ref() - .and_then(|h| h.handle.downcast_ref::()) - } - - pub fn handle_mut( - &mut self, - handle: ScriptHandle, - ) -> Option<&mut T> { - self.handles[handle] - .as_mut() - .and_then(|h| h.handle.downcast_mut::()) - } -} - -#[derive(Default)] -pub struct HandleTag(u64); - -impl HandleTag { - const MARK: u64 = 0x1; - const STATIC: u64 = 0x2; - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } -} - -pub struct ScriptHandleData { - pub tag: HandleTag, - pub handle: Box, -} - -impl ScriptHandleData { - pub fn gc(mut self) { - self.handle.gc() - } -} - -pub trait ScriptHandleGc: Any { - fn gc(&mut self); - fn set_handle(&mut self, _handle: ScriptHandle) {} - fn debug_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ScriptHandleGc: No debug format") - } -} - -impl Debug for dyn ScriptHandleGc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.debug_fmt(f) - } -} - -impl dyn ScriptHandleGc { - pub fn is(&self) -> bool { - Any::type_id(self) == TypeId::of::() - } - pub fn downcast_ref(&self) -> Option<&T> { - if self.is::() { - Some(unsafe { &*(self as *const dyn ScriptHandleGc as *const T) }) - } else { - None - } - } - pub fn downcast_mut(&mut self) -> Option<&mut T> { - if self.is::() { - Some(unsafe { &mut *(self as *const dyn ScriptHandleGc as *mut T) }) - } else { - None - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - struct FirstHandle; - struct SecondHandle; - - impl ScriptHandleGc for FirstHandle { - fn gc(&mut self) {} - } - - impl ScriptHandleGc for SecondHandle { - fn gc(&mut self) {} - } - - #[test] - fn handle_downcasts_use_the_concrete_any_type() { - let mut handle: Box = Box::new(FirstHandle); - - assert!(handle.is::()); - assert!(!handle.is::()); - assert!(handle.downcast_ref::().is_some()); - assert!(handle.downcast_ref::().is_none()); - assert!(handle.downcast_mut::().is_some()); - assert!(handle.downcast_mut::().is_none()); - } -} diff --git a/vendor/makepad/platform/script/src/heap.rs b/vendor/makepad/platform/script/src/heap.rs deleted file mode 100644 index 2c44db6..0000000 --- a/vendor/makepad/platform/script/src/heap.rs +++ /dev/null @@ -1,949 +0,0 @@ -use crate::array::*; -use crate::gc::*; -use crate::gen_index::{GenSlot, GenVec}; -use crate::handle::*; -use crate::makepad_live_id::*; -use crate::object::*; -use crate::pod::*; -use crate::regex::*; -use crate::string::*; -use crate::string_heap::ScriptStringSink; -use crate::traits::*; -use crate::trap::*; -use crate::value::*; - -use std::cell::RefCell; -use std::collections::HashMap; -use std::fmt::Write; -use std::mem::size_of; -use std::rc::Rc; - -#[derive(Default)] -pub struct ScriptHeap { - pub modules: ScriptObject, - pub(crate) gc_last: ScriptHeapGcLast, - pub(crate) mark_vec: Vec, - pub(crate) object_reuse_epoch: u64, - - pub(crate) root_objects: Rc>>, - pub(crate) root_arrays: Rc>>, - pub(crate) root_handles: Rc>>, - - pub(crate) type_defaults: HashMap, - - // GenVec provides generation-checked access via Index etc. - // Use index[obj] for checked access, index[i as usize] for unchecked iteration - pub(crate) objects: GenVec, - pub(crate) objects_free: Vec, // Stores refs with incremented generation, ready to reuse - - pub(crate) string_intern: HashMap, - pub(crate) strings_reuse: Vec, - pub(crate) strings: GenVec>, - pub(crate) strings_free: Vec, - pub(crate) max_string_bytes: Option, - pub(crate) string_limit_exceeded: bool, - pub(crate) max_heap_bytes: Option, - pub(crate) heap_limit_exceeded: bool, - // Cached retained-capacity accounting while an aggregate heap limit is - // active. Allocation paths update it by observed backing-capacity growth; - // hosts can reconcile it after trusted raw-VM configuration or collection. - pub(crate) accounted_heap_bytes: usize, - - pub(crate) arrays: GenVec, - pub(crate) arrays_free: Vec, - - pub(crate) pod_types: Vec, - pub(crate) pod_types_free: Vec, - pub(crate) pods: GenVec, - pub(crate) pods_free: Vec, - - pub(crate) type_check: Vec, - pub(crate) type_index: HashMap, - - pub(crate) handles: GenVec>, - pub(crate) handles_free: Vec, - - pub(crate) regex_intern: HashMap, - pub(crate) regexes: GenVec>, - pub(crate) regexes_free: Vec, -} - -impl ScriptHeap { - /// A stable, unique identity for this heap for its lifetime, matching - /// [`ScriptObjectRef::heap_key`] for every ref minted here. Used to map a - /// heap to its owning script VM so a widget's objects are always resolved - /// against the heap that created them. - pub fn heap_key(&self) -> usize { - Rc::as_ptr(&self.root_objects) as *const () as usize - } - - /// Cap on the number of cleared `String` buffers kept around for reuse. Each one holds a - /// heap allocation; a big script burst can stash thousands of them in `strings_reuse`, - /// which would otherwise never be released. - const MAX_STRINGS_REUSE: usize = 1024; - - /// Applies an aggregate cap to the Octoscript-owned heap data structures. - /// - /// `None` preserves the inherited Makepad VM behavior. The accounting - /// tracks retained capacity of script strings, arrays, objects, slots, and - /// intern tables. It intentionally cannot account for opaque host handles, - /// adapter-owned Rust allocations, or the process allocator's metadata. - pub fn set_max_heap_bytes(&mut self, maximum_bytes: Option) { - self.max_heap_bytes = maximum_bytes; - self.heap_limit_exceeded = false; - - // A pooled buffer is retained process memory but does not represent a - // live script value. Drop it when enabling the cap so later string - // accounting has one clear ownership path. - if maximum_bytes.is_some() { - self.strings_reuse = Vec::new(); - } - self.reconcile_heap_bytes(); - } - - /// Returns the configured aggregate Octoscript heap cap, if any. - pub fn max_heap_bytes(&self) -> Option { - self.max_heap_bytes - } - - /// Returns the current tracked retained-capacity amount used for the - /// aggregate heap limit. - pub fn accounted_heap_bytes(&self) -> usize { - self.accounted_heap_bytes - } - - /// Recomputes retained-capacity accounting from the current heap state. - /// - /// This is appropriate after trusted raw VM configuration or garbage - /// collection. Normal script allocation paths update the cached value in - /// constant time instead of scanning the heap on every instruction. - pub fn reconcile_heap_bytes(&mut self) { - self.accounted_heap_bytes = self.estimated_heap_bytes(); - if self - .max_heap_bytes - .is_some_and(|maximum| self.accounted_heap_bytes > maximum) - { - self.heap_limit_exceeded = true; - } - } - - /// Recomputes accounting for uncommon allocation paths whose backing - /// storage is owned by a lower-level helper. - pub(crate) fn reconcile_heap_bytes_if_limited(&mut self) { - if self.max_heap_bytes.is_some() { - self.reconcile_heap_bytes(); - } - } - - /// Returns and clears an aggregate heap-cap failure raised by a script - /// allocation path. - pub fn take_heap_limit_exceeded(&mut self) -> bool { - std::mem::take(&mut self.heap_limit_exceeded) - } - - /// Records observed retained-capacity growth from a normal script-owned - /// allocation path. This remains a no-op for an unbounded raw VM. - pub(crate) fn note_heap_growth(&mut self, growth_bytes: usize) { - if self.max_heap_bytes.is_none() || growth_bytes == 0 { - return; - } - self.accounted_heap_bytes = self.accounted_heap_bytes.saturating_add(growth_bytes); - if self - .max_heap_bytes - .is_some_and(|maximum| self.accounted_heap_bytes > maximum) - { - self.heap_limit_exceeded = true; - } - } - - /// Applies an observed retained-capacity replacement. A shrink makes the - /// cached amount accurate for later sparse-growth preflights, but never - /// clears a failure already raised by this execution. - pub(crate) fn note_heap_capacity_change(&mut self, before: usize, after: usize) { - if self.max_heap_bytes.is_none() || before == after { - return; - } - if after > before { - self.note_heap_growth(after - before); - } else { - self.accounted_heap_bytes = self.accounted_heap_bytes.saturating_sub(before - after); - } - } - - /// Rejects a sparse collection resize before it asks Rust to allocate the - /// requested backing storage. Ordinary capacity growth is observed after - /// the operation; this preflight closes the one-operation allocation gap - /// for attacker-controlled indexes. - pub(crate) fn can_grow_heap_by(&mut self, growth_bytes: Option) -> bool { - let Some(maximum) = self.max_heap_bytes else { - return true; - }; - let Some(growth_bytes) = growth_bytes else { - self.heap_limit_exceeded = true; - return false; - }; - if growth_bytes > maximum.saturating_sub(self.accounted_heap_bytes) { - self.heap_limit_exceeded = true; - return false; - } - true - } - - fn estimated_heap_bytes(&self) -> usize { - fn bytes_for(capacity: usize) -> usize { - capacity.saturating_mul(size_of::()) - } - - fn map_bytes(map: &HashMap) -> usize { - // HashMap keeps bucket control data in addition to key/value - // payload. Charge two machine words plus one control byte per - // usable bucket to avoid treating map capacity as free. - let entry_bytes = size_of::<(K, V)>() - .saturating_add(size_of::().saturating_mul(2)) - .saturating_add(1); - map.capacity().saturating_mul(entry_bytes) - } - - let mut bytes = size_of::(); - - bytes = bytes.saturating_add(bytes_for::(self.mark_vec.capacity())); - bytes = bytes.saturating_add(map_bytes(&*self.root_objects.borrow())); - bytes = bytes.saturating_add(map_bytes(&*self.root_arrays.borrow())); - bytes = bytes.saturating_add(map_bytes(&*self.root_handles.borrow())); - bytes = bytes.saturating_add(map_bytes(&self.type_defaults)); - - bytes = bytes.saturating_add(bytes_for::>( - self.objects.capacity(), - )); - bytes = bytes.saturating_add(bytes_for::(self.objects_free.capacity())); - for object in self.objects.iter() { - bytes = bytes.saturating_add(object.retained_bytes()); - } - - bytes = bytes.saturating_add(map_bytes(&self.string_intern)); - bytes = bytes.saturating_add(bytes_for::(self.strings_reuse.capacity())); - for string in &self.strings_reuse { - bytes = bytes.saturating_add(string.capacity()); - } - bytes = bytes.saturating_add(bytes_for::>>( - self.strings.capacity(), - )); - bytes = bytes.saturating_add(bytes_for::(self.strings_free.capacity())); - for string in self.strings.iter().flatten() { - bytes = bytes.saturating_add(string.string.0.capacity()); - } - - bytes = bytes.saturating_add(bytes_for::>( - self.arrays.capacity(), - )); - bytes = bytes.saturating_add(bytes_for::(self.arrays_free.capacity())); - for array in self.arrays.iter() { - bytes = bytes.saturating_add(array.storage.retained_bytes()); - } - - bytes = bytes.saturating_add(bytes_for::(self.pod_types.capacity())); - bytes = bytes.saturating_add(bytes_for::(self.pod_types_free.capacity())); - bytes = bytes.saturating_add(bytes_for::>(self.pods.capacity())); - bytes = bytes.saturating_add(bytes_for::(self.pods_free.capacity())); - for pod in self.pods.iter() { - bytes = bytes.saturating_add(bytes_for::(pod.data.capacity())); - } - - bytes = bytes.saturating_add(bytes_for::(self.type_check.capacity())); - bytes = bytes.saturating_add(map_bytes(&self.type_index)); - - // Handle payloads are intentionally opaque Rust-owned allocations; - // count their slot bookkeeping but not the adapter's object graph. - bytes = bytes.saturating_add(bytes_for::>>( - self.handles.capacity(), - )); - bytes = bytes.saturating_add(bytes_for::(self.handles_free.capacity())); - - bytes = bytes.saturating_add(map_bytes(&self.regex_intern)); - bytes = bytes.saturating_add(bytes_for::>>( - self.regexes.capacity(), - )); - bytes = bytes.saturating_add(bytes_for::(self.regexes_free.capacity())); - for regex in self.regexes.iter().flatten() { - // The compiled regex engine is opaque, but the pattern's retained - // bytes and all VM-level indexes are charged here. - bytes = bytes.saturating_add(regex.pattern.capacity()); - } - for key in self.regex_intern.keys() { - bytes = bytes.saturating_add(key.pattern.capacity()); - } - - bytes - } - - /// Release memory the heap is holding purely for reuse / over-allocation, called after a - /// GC sweep. This is safe because it never removes or moves any live slot — it only: - /// - drops excess pooled-for-reuse `String` buffers beyond a cap (re-allocated lazily), - /// - returns over-allocated spare capacity in the slot arrays and free lists. - /// The slot arrays keep their high-water `len` (slots are reused via the free lists), so - /// every existing index / reference stays valid. - pub fn shrink_to_fit(&mut self) { - if self.strings_reuse.len() > Self::MAX_STRINGS_REUSE { - self.strings_reuse.truncate(Self::MAX_STRINGS_REUSE); - } - self.strings_reuse.shrink_to_fit(); - - self.objects.shrink_to_fit(); - self.strings.shrink_to_fit(); - self.arrays.shrink_to_fit(); - self.pods.shrink_to_fit(); - self.handles.shrink_to_fit(); - self.regexes.shrink_to_fit(); - - self.objects_free.shrink_to_fit(); - self.strings_free.shrink_to_fit(); - self.arrays_free.shrink_to_fit(); - self.pods_free.shrink_to_fit(); - self.pod_types_free.shrink_to_fit(); - self.handles_free.shrink_to_fit(); - self.regexes_free.shrink_to_fit(); - self.reconcile_heap_bytes_if_limited(); - } - - pub fn empty() -> Self { - let mut objects = GenVec::new(); - let mut arrays = GenVec::new(); - let mut pods = GenVec::new(); - let mut handles = GenVec::new(); - let mut strings = GenVec::new(); - let mut regexes = GenVec::new(); - - // Push slot 0 for each (reserved/null slot) - objects.push(Default::default()); - arrays.push(Default::default()); - pods.push(Default::default()); - handles.push(None); - strings.push(None); // slot 0 for strings too - regexes.push(None); // slot 0 for regexes too - - let mut v = Self { - root_objects: Default::default(), - modules: ScriptObject::ZERO, - objects, - arrays, - pods, - handles, - strings, - regexes, - ..Default::default() - }; - // Initialize slot 0 (reserved null slot) - use get_at_mut for internal init - v.objects.get_at_mut(0).tag.set_alloced(); - v.objects.get_at_mut(0).tag.set_static(); - v.objects.get_at_mut(0).tag.freeze(); - v.arrays.get_at_mut(0).tag.set_alloced(); - v.arrays.get_at_mut(0).tag.freeze(); - - v.modules = v.new_with_proto(id!(mod).into()); - v.root_objects.borrow_mut().insert(v.modules, 1); - - v - } - - pub fn registered_type(&self, id: ScriptTypeId) -> Option<&ScriptTypeCheck> { - if let Some(index) = self.type_index.get(&id) { - Some(&self.type_check[index.0 as usize]) - } else { - None - } - } - - pub fn register_type( - &mut self, - type_id: Option, - ty_check: ScriptTypeCheck, - ) -> ScriptTypeIndex { - let index = ScriptTypeIndex(self.type_check.len() as _); - if let Some(type_id) = type_id { - self.type_index.insert(type_id, index); - } - self.type_check.push(ty_check); - index - } - - pub fn type_matches_id(&self, ptr: ScriptObject, type_id: ScriptTypeId) -> bool { - let obj = &self.objects[ptr]; - if let Some(ti) = obj.tag.as_type_index() { - if let Some(object) = &self.type_check[ti.0 as usize].object { - return object.type_id == type_id; - } - } - false - } - - /// Returns the TypeId for an object if it has a registered type. - pub fn object_type_id(&self, ptr: ScriptObject) -> Option { - let obj = &self.objects[ptr]; - if let Some(ti) = obj.tag.as_type_index() { - if let Some(object) = &self.type_check[ti.0 as usize].object { - return Some(object.type_id); - } - } - None - } - - /// Returns the registered script name for a given TypeId, if any. - pub fn type_name_by_id(&self, type_id: ScriptTypeId) -> Option { - if let Some(index) = self.type_index.get(&type_id) { - if let Some(object) = &self.type_check[index.0 as usize].object { - return object.name; - } - } - None - } - - pub fn new_module(&mut self, id: LiveId) -> ScriptObject { - let md = self.new_with_proto(id.into()); - self.set_value_def(self.modules, id.into(), md.into()); - md - } - - pub fn module(&mut self, id: LiveId) -> ScriptObject { - self.value(self.modules, id.into(), NoTrap).into() - } - - // Accessors - - pub fn has_proto(&mut self, ptr: ScriptObject, rhs: ScriptValue) -> bool { - let mut ptr = ptr; - loop { - let object = &mut self.objects[ptr]; - if object.proto == rhs { - return true; - } - if let Some(object) = object.proto.as_object() { - ptr = object - } else { - return false; - } - } - } - - pub fn proto(&self, ptr: ScriptObject) -> ScriptValue { - self.objects[ptr].proto - } - - pub fn root_proto(&self, ptr: ScriptObject) -> ScriptValue { - let mut ptr = ptr; - loop { - let object = &self.objects[ptr]; - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - return object.proto; - } - } - } - - pub fn object_data(&self, ptr: ScriptObject) -> &ScriptObjectData { - &self.objects[ptr] - } - - /// Monotonic counter bumped when object slots are freed/reused. - /// Used by higher layers to evict caches keyed by ScriptObject identity. - pub fn object_reuse_epoch(&self) -> u64 { - self.object_reuse_epoch - } - - pub(crate) fn bump_object_reuse_epoch(&mut self) { - self.object_reuse_epoch = self.object_reuse_epoch.wrapping_add(1); - } - - pub fn type_check(&self, index: ScriptTypeIndex) -> &ScriptTypeCheck { - &self.type_check[index.0 as usize] - } - - pub fn set_type_default(&mut self, obj: ScriptObject) -> bool { - let object = &self.objects[obj]; - if let Some(ty_index) = object.tag.as_type_index() { - // Add to type_defaults mapping (GC will scan this table) - self.type_defaults.insert(ty_index, obj); - true - } else { - false - } - } - - pub fn type_default(&self, ty_index: ScriptTypeIndex) -> Option { - self.type_defaults.get(&ty_index).copied() - } - - pub fn type_default_for_id(&self, type_id: ScriptTypeId) -> Option { - if let Some(ty_index) = self.type_index.get(&type_id) { - self.type_defaults.get(ty_index).copied() - } else { - None - } - } - - /// Look up a field's ScriptTypeId from the type-check structure of an object. - /// This is used when the field value isn't on the prototype but the type is registered. - pub fn field_type_from_type_check( - &self, - obj: ScriptObject, - field_id: LiveId, - ) -> Option { - let object = &self.objects[obj]; - if let Some(ty_index) = object.tag.as_type_index() { - let type_check = &self.type_check[ty_index.0 as usize]; - if let Some(prop) = type_check.props.props.get(&field_id) { - return Some(prop.ty); - } - } - // Also check the prototype chain - if let Some(proto_obj) = object.proto.as_object() { - return self.field_type_from_type_check(proto_obj, field_id); - } - None - } - - #[inline] - pub fn cast_to_f64(&self, v: ScriptValue, ip: ScriptIp) -> f64 { - if let Some(v) = v.as_f64() { - return v; - } - if let Some(v) = v.as_u40() { - return v as _; - } - if let Some(number) = self.string_with(v, |_, text| text.parse::()) { - return number.unwrap_or_else(|_| { - ScriptValue::from_f64_traced_nan(f64::NAN, ip) - .as_f64() - .unwrap() - }); - } - if let Some(v) = v.as_bool() { - return if v { 1.0 } else { 0.0 }; - } - if let Some(v) = v.as_f32() { - return v as f64; - } - if let Some(v) = v.as_f16() { - return v as f64; - } - if let Some(v) = v.as_u32() { - return v as f64; - } - if let Some(v) = v.as_i32() { - return v as f64; - } - if let Some(v) = v.as_color() { - return v as f64; - } - if v.is_nil() { - return 0.0; - } - ScriptValue::from_f64_traced_nan(f64::NAN, ip) - .as_f64() - .unwrap() - } - - pub fn cast_to_bool(&self, v: ScriptValue) -> bool { - if let Some(b) = v.as_bool() { - return b; - } - if v.is_nil() { - return false; - } - if let Some(v) = v.as_f64() { - return v != 0.0; - } - if let Some(v) = v.as_u40() { - return v != 0; - } - if let Some(v) = v.as_f32() { - return v != 0.0; - } - if let Some(v) = v.as_f16() { - return v != 0.0; - } - if let Some(v) = v.as_u32() { - return v != 0; - } - if let Some(v) = v.as_i32() { - return v != 0; - } - if let Some(_v) = v.as_object() { - return true; - } - if v.inline_string_not_empty() { - return true; - } - if let Some(v) = v.as_string() { - return self.string(v).len() != 0; - } - if let Some(_v) = v.as_id() { - return true; - } - if let Some(_v) = v.as_color() { - return true; - } - if v.is_opcode() { - return true; - } - false - } - - // Debug and utility - - pub fn println(&self, value: ScriptValue) { - let mut out = String::new(); - let mut recur = Vec::new(); - self.to_debug_string(value, &mut recur, &mut out, true, 0); - println!("{out}"); - } - - pub fn to_debug_string( - &self, - value: ScriptValue, - recur: &mut Vec, - out: &mut String, - formatted: bool, - depth: usize, - ) { - fn write_indent(out: &mut String, depth: usize) { - for _ in 0..depth { - out.push_str("- - "); - } - } - - fn write_separator(out: &mut String, formatted: bool, depth: usize, first: bool) { - if !first { - if formatted { - out.push_str(",\n"); - write_indent(out, depth); - } else { - out.push_str(", "); - } - } - } - - if let Some(obj) = value.as_object() { - if self.is_fn(obj) { - write!(out, "", obj.index()).ok(); - return; - } - if recur.iter().any(|v| *v == value) { - write!(out, "").ok(); - return; - } - recur.push(value); - - let object = &self.objects[obj]; - if object.tag.is_script_fn() { - write!(out, "Fn").ok(); - } else if object.tag.is_native_fn() { - write!(out, "Native").ok(); - } - let mut ptr = obj; - // scan up the chain to set the proto value - write!(out, "<{}>{{", obj.index()).ok(); - - // Check if object has any content (for formatted output) - let has_content = { - let obj_data = &self.objects[obj]; - obj_data.map_len() > 0 - || !obj_data.vec.is_empty() - || obj_data.tag.as_type_index().is_some() - }; - - if formatted && has_content { - out.push('\n'); - write_indent(out, depth + 1); - } - - let mut first = true; - - // if we have a type index, output type checked base properties first - if let Some(ty_index) = object.tag.as_type_index() { - write!(out, "").ok(); - if formatted { - out.push('\n'); - write_indent(out, depth + 1); - } - first = true; - } - - loop { - let object = &self.objects[ptr]; - - object.map_iter_ordered(|key, value| { - write_separator(out, formatted, depth + 1, first); - if key != NIL { - self.to_debug_string(key, recur, out, formatted, depth + 1); - write!(out, ": ").ok(); - } - self.to_debug_string(value, recur, out, formatted, depth + 1); - first = false; - }); - for kv in object.vec.iter() { - write_separator(out, formatted, depth + 1, first); - if kv.key != NIL { - write!(out, "{}: ", kv.key).ok(); - } - self.to_debug_string(kv.value, recur, out, formatted, depth + 1); - first = false; - } - if let Some(next_ptr) = object.proto.as_object() { - if formatted { - if !first { - out.push_str(",\n"); - write_indent(out, depth + 1); - } - write!(out, "^<{}>", next_ptr.index()).ok(); - } else { - if !first { - write!(out, ",").ok(); - } - write!(out, "^<{}>", next_ptr.index()).ok(); - } - ptr = next_ptr - } else { - if formatted && has_content { - out.push('\n'); - write_indent(out, depth); - } - write!(out, "/{}", object.proto).ok(); - break; - } - } - write!(out, "}}").ok(); - recur.pop(); - } else if let Some(arr) = value.as_array() { - if recur.iter().any(|v| *v == value) { - write!(out, "").ok(); - return; - } - recur.push(value); - let array = &self.arrays[arr]; - let len = array.storage.len(); - write!(out, "<{}>[", arr.index()).ok(); - - if formatted && len > 0 { - out.push('\n'); - write_indent(out, depth + 1); - } - - for i in 0..len { - if i != 0 { - if formatted { - out.push_str(",\n"); - write_indent(out, depth + 1); - } else { - out.push_str(", "); - } - } - self.to_debug_string( - array.storage.index(i).unwrap(), - recur, - out, - formatted, - depth + 1, - ); - } - - if formatted && len > 0 { - out.push('\n'); - write_indent(out, depth); - } - - write!(out, "]").ok(); - recur.pop(); - } else if let Some(s) = value.as_string() { - let s = if let Some(s) = &self.strings[s] { - &s.string.0 - } else { - "" - }; - write!(out, "\"").ok(); - write!(out, "{}", s).ok(); - write!(out, "\"").ok(); - } else if value - .as_inline_string(|s| { - write!(out, "\"").ok(); - write!(out, "{}", s).ok(); - write!(out, "\"").ok(); - }) - .is_some() - { - } else if let Some(pod) = value.as_pod() { - let pod = &self.pods[pod]; - let pod_type = &self.pod_types[pod.ty.index as usize]; - self.pod_debug(out, pod_type, 0, &pod.data); - } else { - write!(out, "{}", value).ok(); - } - } - - pub fn to_json(&mut self, value: ScriptValue) -> ScriptValue { - self.new_bounded_string_with(|heap, s| { - heap.to_json_inner(value, s); - }) - } - - pub fn to_json_inner(&self, value: ScriptValue, out: &mut S) { - fn escape_str(inp: &str, out: &mut S) { - for c in inp.chars() { - match c { - '\x08' => out.append_str("\\b"), - '\x0c' => out.append_str("\\f"), - '\n' => out.append_str("\\n"), - '\r' => out.append_str("\\r"), - '"' => out.append_str("\\\""), - '\\' => out.append_str("\\"), - c => { - out.append_char(c); - } - } - if out.is_full() { - break; - } - } - } - if out.is_full() { - return; - } - if let Some(obj) = value.as_object() { - let mut ptr = obj; - // scan up the chain to set the proto value - out.append_char('{'); - let mut first = true; - loop { - let object = &self.objects[ptr]; - object.map_iter(|key, value| { - if out.is_full() { - return; - } - if !first { - out.append_char(',') - } - self.to_json_inner(key, out); - out.append_char(':'); - self.to_json_inner(value, out); - first = false; - }); - if out.is_full() { - break; - } - for kv in object.vec.iter() { - if out.is_full() { - break; - } - if !first { - out.append_char(',') - } - first = false; - self.to_json_inner(kv.key, out); - out.append_char(':'); - self.to_json_inner(kv.value, out); - } - if out.is_full() { - break; - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - break; - } - } - if !out.is_full() { - out.append_char('}'); - } - } else if let Some(arr) = value.as_array() { - let array = &self.arrays[arr]; - let len = array.storage.len(); - let mut first = true; - out.append_char('['); - for i in 0..len { - if let Some(value) = array.storage.index(i) { - if !first { - out.append_char(',') - } - first = false; - self.to_json_inner(value, out); - if out.is_full() { - break; - } - } - } - if !out.is_full() { - out.append_char(']'); - } - } else if let Some(id) = value.as_id() { - out.append_char('"'); - id.as_string(|s| { - if let Some(s) = s { - escape_str(s, out); - } - }); - if !out.is_full() { - out.append_char('"'); - } - // alright. sself is json eh. so. - } else if let Some(s) = value.as_string() { - let s = if let Some(s) = &self.strings[s] { - &s.string.0 - } else { - "" - }; - out.append_char('"'); - escape_str(s, out); - if !out.is_full() { - out.append_char('"'); - } - } else if value - .as_inline_string(|s| { - out.append_char('"'); - escape_str(s, out); - if !out.is_full() { - out.append_char('"'); - } - }) - .is_some() - { - } else if let Some(v) = value.as_bool() { - if v { - out.append_str("true") - } else { - out.append_str("false") - } - } else if let Some(v) = value.as_number() { - write!(out, "{}", v).ok(); - } else if let Some(v) = value.as_handle() { - write!(out, "Handle{:?}", v).ok(); - } else { - out.append_str("null"); - } - } - - // memory usage - pub fn objects_len(&self) -> usize { - self.objects.len() - } - - /// Checks if a value has an apply transform without calling it. - /// Used by type_check to be permissive when a transform exists. - pub fn has_apply_transform(&self, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - return self.objects[obj].tag.as_apply_transform().is_some(); - } - if let Some(arr) = value.as_array() { - return self.arrays[arr].tag.as_apply_transform().is_some(); - } - false - } -} diff --git a/vendor/makepad/platform/script/src/json.rs b/vendor/makepad/platform/script/src/json.rs deleted file mode 100644 index 9bcf1cb..0000000 --- a/vendor/makepad/platform/script/src/json.rs +++ /dev/null @@ -1,351 +0,0 @@ -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id::makepad_live_id_macros::*; -use crate::tokenizer::*; -use crate::value::*; - -#[derive(Debug)] -pub(crate) enum State { - Root, - RootMaybeObject, - ObjectKey(ScriptObject), - ObjectColon(ScriptObject, ScriptValue), - ObjectValue(ScriptObject, ScriptValue), - Array(ScriptArray), -} - -#[derive(Default)] -pub struct JsonParser { - index: u32, - pub root: ScriptValue, - pub(crate) state: Vec, - pub errors: Vec<(u32, String)>, -} - -impl JsonParser { - pub fn clear(&mut self) { - self.index = 0; - self.root = NIL; - self.state.clear(); - self.state.push(State::Root); - self.errors.clear(); - } -} - -impl JsonParser { - fn parse_step(&mut self, tok: ScriptToken, heap: &mut ScriptHeap) { - match self.state.pop().unwrap() { - State::RootMaybeObject => { - let key = self.root; - let new_obj = heap.new_object(); - heap.set_string_keys(new_obj); - self.root = new_obj.into(); - match tok { - ScriptToken::Operator(id) => match id { - id!(:) => { - self.state.push(State::ObjectValue(new_obj, key)); - } - x => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected token in json root {:?}", x), - )); - } - }, - x => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected token in json root {:?}", x), - )); - } - } - } - State::Root => { - match tok { - ScriptToken::Identifier(id) => match id { - id!(true) => self.root = TRUE.into(), - id!(false) => self.root = FALSE.into(), - id!(null) => self.root = NIL.into(), - x => { - self.root = ScriptValue::from_escaped_id(x); - self.state.push(State::RootMaybeObject) - } - }, - ScriptToken::String(v) => { - self.root = v; - self.state.push(State::RootMaybeObject); - } - ScriptToken::U40(v) => { - self.root = (v as f64).into(); - self.state.push(State::RootMaybeObject); - } - ScriptToken::F64(v) => { - self.root = v.into(); - self.state.push(State::RootMaybeObject); - } - ScriptToken::Color(v) => { - self.root = v.into(); - self.state.push(State::RootMaybeObject); - } - ScriptToken::OpenCurly => { - // object - let new_obj = heap.new_object(); - heap.set_string_keys(new_obj); - self.root = new_obj.into(); - self.state.push(State::ObjectKey(new_obj)); - } - ScriptToken::OpenSquare => { - // - let new_arr = heap.new_array(); - self.root = new_arr.into(); - self.state.push(State::Array(new_arr)); - } - ScriptToken::CloseSquare - | ScriptToken::CloseRound - | ScriptToken::CloseCurly => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected ] or }} or ) in json root"), - )); - } - x => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected token in json root {:?}", x), - )); - } - } - } - State::ObjectKey(obj) => { - // we require a string or identifier - match tok { - ScriptToken::Identifier(id) => { - self.state.push(State::ObjectColon(obj, id.into())); - } - ScriptToken::String(v) => { - self.state.push(State::ObjectColon(obj, v.into())); - } - ScriptToken::F64(v) => { - self.state.push(State::ObjectColon(obj, v.into())); - } - ScriptToken::Color(v) => { - self.state.push(State::ObjectColon(obj, v.into())); - } - // nonstandard, allow objects and arrays as keys - ScriptToken::OpenCurly => { - // object - let new_obj = heap.new_object(); - heap.set_string_keys(new_obj); - self.state.push(State::ObjectColon(obj, new_obj.into())); - self.state.push(State::ObjectKey(new_obj)); - } - ScriptToken::OpenSquare => { - // - let new_arr = heap.new_array(); - self.state.push(State::ObjectColon(obj, new_arr.into())); - self.state.push(State::Array(new_arr)); - } - ScriptToken::CloseCurly => {} - ScriptToken::CloseRound | ScriptToken::CloseSquare => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected ] or ) in object"), - )); - } - ScriptToken::Operator(id) => { - self.state.push(State::ObjectKey(obj)); - match id { - id!(,) => {} - x => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected operator in object {}", x), - )); - } - } - } - x => { - self.state.push(State::ObjectKey(obj)); - self.errors.push(( - self.index, - format!("JsonParser: Unexpected token in object {:?}", x), - )); - } - } - } - State::ObjectColon(obj, key) => match tok { - ScriptToken::Operator(id) => match id { - id!(:) => { - self.state.push(State::ObjectValue(obj, key)); - } - x => { - self.state.push(State::ObjectKey(obj)); - self.errors.push(( - self.index, - format!("JsonParser: Unexpected operator expecting ':' {}", x), - )); - } - }, - x => { - self.state.push(State::ObjectKey(obj)); - self.errors.push(( - self.index, - format!( - "JsonParser: Unexpected token waiting for object ':' {:?}", - x - ), - )); - } - }, - State::ObjectValue(obj, key) => { - self.state.push(State::ObjectKey(obj)); - match tok { - ScriptToken::Identifier(id) => match id { - id!(true) => heap.set_value_def(obj, key, TRUE), - id!(false) => heap.set_value_def(obj, key, FALSE), - id!(null) => heap.set_value_def(obj, key, NIL), - x => heap.set_value_def(obj, key, x.into()), - }, - ScriptToken::String(v) => { - heap.set_value_def(obj, key, v); - } - ScriptToken::U40(v) => { - heap.set_value_def(obj, key, (v as f64).into()); - } - ScriptToken::F64(v) => { - heap.set_value_def(obj, key, v.into()); - } - ScriptToken::Color(v) => { - heap.set_value_def(obj, key, v.into()); - } - ScriptToken::OpenCurly => { - // object - let new_obj = heap.new_object(); - heap.set_string_keys(new_obj); - heap.set_value_def(obj, key, new_obj.into()); - self.state.push(State::ObjectKey(new_obj)); - } - ScriptToken::OpenSquare => { - // - let new_arr = heap.new_array(); - heap.set_value_def(obj, key, new_arr.into()); - self.state.push(State::Array(new_arr)); - } - ScriptToken::CloseCurly => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected }} expecting object value"), - )); - self.state.pop(); - // end of array - } - ScriptToken::CloseRound | ScriptToken::CloseSquare => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected ] or ) in array"), - )); - } - ScriptToken::Operator(op) => { - if op != id!(,) { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected operator expecting ',' {}", op), - )); - } - } - x => { - self.errors - .push((self.index, format!("JsonParser: Unexpected token {:?}", x))); - } - } - } - State::Array(arr) => { - self.state.push(State::Array(arr)); - // alright we can parse a value or ] - match tok { - ScriptToken::Identifier(id) => match id { - id!(true) => heap.array_push_unchecked(arr, TRUE), - id!(false) => heap.array_push_unchecked(arr, FALSE), - id!(null) => heap.array_push_unchecked(arr, NIL), - x => heap.array_push_unchecked(arr, x.into()), - }, - ScriptToken::String(v) => { - heap.array_push_unchecked(arr, v); - } - ScriptToken::U40(v) => { - heap.array_push_unchecked(arr, (v as f64).into()); - } - ScriptToken::F64(v) => { - heap.array_push_unchecked(arr, v.into()); - } - ScriptToken::Color(v) => { - heap.array_push_unchecked(arr, ScriptValue::from_color(v)); - } - ScriptToken::OpenCurly => { - // object - let new_obj = heap.new_object(); - heap.set_string_keys(new_obj); - heap.array_push_unchecked(arr, new_obj.into()); - self.state.push(State::ObjectKey(new_obj)); - } - ScriptToken::OpenSquare => { - // - let new_arr = heap.new_array(); - heap.array_push_unchecked(arr, new_arr.into()); - self.state.push(State::Array(new_arr)); - } - ScriptToken::CloseSquare => { - // end of array - self.state.pop(); - } - ScriptToken::CloseRound | ScriptToken::CloseCurly => { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected }} or ) in array"), - )); - } - ScriptToken::Operator(op) => { - if op != id!(,) { - self.errors.push(( - self.index, - format!("JsonParser: Unexpected operator expecting ',' {}", op), - )); - } - } - x => { - self.errors - .push((self.index, format!("JsonParser: Unexpected token {:?}", x))); - } - } - } - } - } - - pub fn parse(&mut self, tokens: &[ScriptTokenPos], heap: &mut ScriptHeap) { - while self.index < tokens.len() as u32 && self.state.len() > 0 { - let tok = if let Some(tok) = tokens.get(self.index as usize) { - tok.token.clone() - } else { - ScriptToken::StreamEnd - }; - self.parse_step(tok, heap); - self.index += 1; - } - } -} - -#[derive(Default)] -pub struct JsonParserThread { - pub tokenizer: ScriptTokenizer, - pub parser: JsonParser, -} - -impl JsonParserThread { - pub fn read_json(&mut self, json: &str, heap: &mut ScriptHeap) -> ScriptValue { - self.tokenizer.clear(); - self.parser.clear(); - self.tokenizer.tokenize(json, heap); - self.parser.parse(&self.tokenizer.tokens, heap); - return self.parser.root; - } -} diff --git a/vendor/makepad/platform/script/src/lib.rs b/vendor/makepad/platform/script/src/lib.rs deleted file mode 100644 index 34ac6e7..0000000 --- a/vendor/makepad/platform/script/src/lib.rs +++ /dev/null @@ -1,94 +0,0 @@ -pub use makepad_error_log; -pub use makepad_live_id; -pub use makepad_live_id::makepad_live_id_macros; -pub use makepad_math; -pub use makepad_math::makepad_micro_serde; -pub use makepad_regex; -pub use makepad_script_derive; - -#[macro_export] -macro_rules! script_eval { - ($vm:expr, { $($tt:tt)* } $(,)?) => {{ - ($vm).with_vm(|vm|{let b = $crate::script! { $($tt)* };vm.eval(b)}) - }}; -} - -pub mod colorhex; -pub mod equality; -pub mod gen_index; -pub mod heap; -pub mod mod_gc; -pub mod mod_html; -pub mod mod_math; -pub mod mod_pod; -pub mod mod_regex; -pub mod mod_shader; -pub mod mod_std; -pub mod object; -pub mod object_heap; -pub mod parser; -pub mod regex; -pub mod regex_heap; -pub mod string; -pub mod string_heap; -pub mod tokenizer; -#[macro_use] -pub mod native; -pub mod apply; -pub mod array; -pub mod array_heap; -pub mod function; -pub mod gc; -pub mod handle; -pub mod json; -pub mod numeric; -pub mod opcode; -pub mod opcodes; -pub mod opcodes_assign; -pub mod opcodes_calls; -pub mod opcodes_control; -pub mod opcodes_loops; -pub mod opcodes_ops; -pub mod opcodes_vars; -pub mod pod; -pub mod pod_heap; -pub mod prims; -pub mod shader; -pub mod shader_backend; -pub mod shader_builtins; -pub mod shader_calls; -pub mod shader_control; -pub mod shader_glsl; -pub mod shader_hlsl; -pub mod shader_metal; -pub mod shader_ops; -pub mod shader_output; -pub mod shader_tables; -pub mod shader_vars; -pub mod shader_wgsl; -pub mod suggest; -pub mod test; -pub mod thread; -pub mod traits; -pub mod trap; -pub mod value; -pub mod value_map; -pub mod vec_prims; -pub mod vm; - -pub use apply::*; -pub use array::*; -pub use function::*; -pub use gc::*; -pub use handle::*; -pub use heap::*; -pub use makepad_live_id::*; -pub use makepad_script_derive::*; -pub use object::*; -pub use string::*; -pub use string_heap::*; -pub use thread::*; -pub use traits::*; -pub use trap::*; -pub use value::*; -pub use vm::*; diff --git a/vendor/makepad/platform/script/src/mod_gc.rs b/vendor/makepad/platform/script/src/mod_gc.rs deleted file mode 100644 index 79705b2..0000000 --- a/vendor/makepad/platform/script/src/mod_gc.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::heap::*; -use crate::makepad_error_log::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::native::*; -use crate::value::*; -use crate::*; - -pub fn define_gc_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let gc = heap.new_module(id!(gc)); - - native.add_method( - heap, - gc, - id_lut!(set_static), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - vm.bx.heap.set_static(value); - value - }, - ); - - native.add_method(heap, gc, id_lut!(run), script_args!(), |vm, _args| { - vm.gc(); - ScriptValue::NIL - }); - - native.add_method( - heap, - gc, - id_lut!(run_status), - script_args!(), - |vm, _args| { - vm.gc_with_status(); - ScriptValue::NIL - }, - ); - - native.add_method( - heap, - gc, - id_lut!(dump_tag), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - if let Some(obj) = value.as_object() { - let object = &vm.bx.heap.objects[obj]; - let tag = &object.tag; - let type_index = tag.as_type_index().map(|t| t.0); - let is_static = tag.is_static(); - let proto = object.proto; - let proto_obj_index = proto.as_object().map(|p| p.index); - let proto_type_index = if let Some(p) = proto.as_object() { - vm.bx.heap.objects[p] - .tag - .as_type_index() - .map(|t| t.0) - } else { - None - }; - let type_props = if let Some(ty) = tag.as_type_index() { - let check = &vm.bx.heap.type_check[ty.0 as usize]; - check - .props - .props - .keys() - .map(|k| format!("{:?}", k)) - .collect::>() - .join(", ") - } else { - String::new() - }; - log!( - "obj {} type_index={:?} is_static={} proto={:?} proto_type_index={:?} props=[{}]", - obj.index, - type_index, - is_static, - proto_obj_index, - proto_type_index, - type_props - ); - } - value - }, - ); -} diff --git a/vendor/makepad/platform/script/src/mod_html.rs b/vendor/makepad/platform/script/src/mod_html.rs deleted file mode 100644 index 010533c..0000000 --- a/vendor/makepad/platform/script/src/mod_html.rs +++ /dev/null @@ -1,813 +0,0 @@ -use crate::handle::*; -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::native::*; -use crate::value::*; -use crate::*; -use makepad_html::{parse_html, HtmlNode}; -use makepad_live_id::live_id::InternLiveId; -use std::rc::Rc; - -// Shared backing store — the parsed HTML data is Rc'd so query results -// just reference ranges into it without copying strings or nodes. -struct HtmlBacking { - decoded: String, - nodes: Vec, -} - -pub struct ScriptHtmlDoc { - backing: Rc, - // Element ranges as (open_tag_index, close_tag_index) into backing.nodes. - ranges: Vec<(u32, u32)>, - // true = root document (empty ranges means whole doc), false = query result (empty = no matches) - is_root: bool, - handle: ScriptHandle, -} - -impl ScriptHandleGc for ScriptHtmlDoc { - fn gc(&mut self) {} - fn set_handle(&mut self, handle: ScriptHandle) { - self.handle = handle; - } -} - -impl ScriptHtmlDoc { - fn decoded(&self) -> &str { - &self.backing.decoded - } - - fn nodes(&self) -> &[HtmlNode] { - &self.backing.nodes - } -} - -// ---- Query parsing ---- - -enum Combinator { - Descendant, - Child, -} - -enum Terminal { - None, - Attr(LiveId), - Text, - Index(usize), -} - -struct QueryStep { - tag: Option, - id_filter: Option, - class_filter: Option, - combinator: Combinator, -} - -struct ParsedQuery { - steps: Vec, - terminal: Terminal, -} - -fn parse_query(sel: &str) -> ParsedQuery { - let sel = sel.trim(); - let mut steps = Vec::new(); - let mut terminal = Terminal::None; - let mut next_combinator = Combinator::Descendant; - - let mut i = 0; - let bytes = sel.as_bytes(); - - while i < bytes.len() { - // Skip whitespace - while i < bytes.len() && bytes[i] == b' ' { - i += 1; - } - if i >= bytes.len() { - break; - } - - if bytes[i] == b'>' { - next_combinator = Combinator::Child; - i += 1; - continue; - } - - // Read a token (until whitespace or >) - let tok_start = i; - while i < bytes.len() && bytes[i] != b' ' && bytes[i] != b'>' { - i += 1; - } - let token = &sel[tok_start..i]; - - let mut tag_part = token; - let mut id_filter = None; - let mut class_filter = None; - - // @attr terminal - if let Some(at) = tag_part.find('@') { - terminal = Terminal::Attr(LiveId::from_str_lc(&tag_part[at + 1..])); - tag_part = &tag_part[..at]; - if tag_part.is_empty() { - tag_part = "*"; - } - } - - // [N] index terminal - if let Some(b) = tag_part.find('[') { - if let Some(e) = tag_part.find(']') { - if let Ok(idx) = tag_part[b + 1..e].parse::() { - terminal = Terminal::Index(idx); - } - tag_part = &tag_part[..b]; - } - } - - // #id filter - if let Some(h) = tag_part.find('#') { - id_filter = Some(LiveId::from_str_lc(&tag_part[h + 1..])); - tag_part = &tag_part[..h]; - if tag_part.is_empty() { - tag_part = "*"; - } - } - - // .class or .text - if let Some(d) = tag_part.find('.') { - let suffix = &tag_part[d + 1..]; - if suffix == "text" { - terminal = Terminal::Text; - } else { - class_filter = Some(LiveId::from_str_lc(suffix)); - } - tag_part = &tag_part[..d]; - if tag_part.is_empty() { - tag_part = "*"; - } - } - - let tag = if tag_part == "*" { - None - } else { - Some(LiveId::from_str_lc(tag_part)) - }; - - steps.push(QueryStep { - tag, - id_filter, - class_filter, - combinator: std::mem::replace(&mut next_combinator, Combinator::Descendant), - }); - } - - ParsedQuery { steps, terminal } -} - -// ---- Query execution (zero-copy, operates on backing) ---- - -fn find_close_tag(nodes: &[HtmlNode], open_idx: usize) -> usize { - let mut depth = 0u32; - for i in (open_idx + 1)..nodes.len() { - match &nodes[i] { - HtmlNode::OpenTag { .. } => depth += 1, - HtmlNode::CloseTag { .. } => { - if depth == 0 { - return i; - } - depth -= 1; - } - _ => {} - } - } - nodes.len().saturating_sub(1) -} - -fn element_matches(decoded: &str, nodes: &[HtmlNode], idx: usize, step: &QueryStep) -> bool { - let lc = match &nodes[idx] { - HtmlNode::OpenTag { lc, .. } => *lc, - _ => return false, - }; - if let Some(tag_id) = step.tag { - if lc != tag_id { - return false; - } - } - if step.id_filter.is_none() && step.class_filter.is_none() { - return true; - } - - // Scan attributes (they immediately follow the open tag) - let mut id_ok = step.id_filter.is_none(); - let mut class_ok = step.class_filter.is_none(); - for j in (idx + 1)..nodes.len() { - match &nodes[j] { - HtmlNode::Attribute { lc, start, end, .. } => { - if !id_ok && *lc == live_id!(id) { - if let Some(ref want) = step.id_filter { - id_ok = LiveId::from_str_lc(&decoded[*start..*end]) == *want; - } - } - if !class_ok && *lc == live_id!(class) { - if let Some(ref want) = step.class_filter { - let cls = &decoded[*start..*end]; - class_ok = cls - .split_whitespace() - .any(|c| LiveId::from_str_lc(c) == *want); - } - } - } - _ => break, - } - } - id_ok && class_ok -} - -fn find_elements( - decoded: &str, - nodes: &[HtmlNode], - step: &QueryStep, - range_start: usize, - range_end: usize, - recurse: bool, - out: &mut Vec<(u32, u32)>, -) { - let mut i = range_start; - let mut depth = 0u32; - while i < range_end { - match &nodes[i] { - HtmlNode::OpenTag { .. } => { - if (recurse || depth == 0) && element_matches(decoded, nodes, i, step) { - let close = find_close_tag(nodes, i); - out.push((i as u32, close as u32)); - if !recurse { - i = close + 1; - continue; - } - } - depth += 1; - } - HtmlNode::CloseTag { .. } => { - if depth > 0 { - depth -= 1; - } - } - _ => {} - } - i += 1; - } -} - -fn execute_query( - decoded: &str, - nodes: &[HtmlNode], - ranges: &[(u32, u32)], - steps: &[QueryStep], -) -> Vec<(u32, u32)> { - if steps.is_empty() { - return ranges.to_vec(); - } - - // First step: search within provided ranges - let mut matches = Vec::new(); - if ranges.is_empty() { - // Whole document - find_elements( - decoded, - nodes, - &steps[0], - 0, - nodes.len(), - true, - &mut matches, - ); - } else { - for &(s, e) in ranges { - find_elements( - decoded, - nodes, - &steps[0], - s as usize, - e as usize, - true, - &mut matches, - ); - } - } - - // Subsequent steps - for step in &steps[1..] { - let prev = std::mem::take(&mut matches); - let is_child = matches!(step.combinator, Combinator::Child); - for &(s, e) in &prev { - let child_start = s as usize + 1; - if child_start < e as usize { - find_elements( - decoded, - nodes, - step, - child_start, - e as usize, - !is_child, - &mut matches, - ); - } - } - } - - // Deduplicate (same element can be found via multiple ancestor paths) - matches.sort_unstable(); - matches.dedup(); - - matches -} - -fn collect_text<'a>(decoded: &'a str, nodes: &[HtmlNode], start: usize, end: usize) -> &'a str { - // Fast path: if there's exactly one text node, return a slice (no alloc) - let mut first_text: Option<(usize, usize)> = None; - let mut count = 0; - for i in start..=end.min(nodes.len().saturating_sub(1)) { - if let HtmlNode::Text { - start: s, - end: e, - all_ws, - } = &nodes[i] - { - if !all_ws { - count += 1; - if count == 1 { - first_text = Some((*s, *e)); - } - } - } - } - if count == 1 { - if let Some((s, e)) = first_text { - return &decoded[s..e]; - } - } - // For zero or multiple text nodes we'll need the caller to handle it - "" -} - -fn collect_text_owned(decoded: &str, nodes: &[HtmlNode], start: usize, end: usize) -> String { - let mut text = String::new(); - for i in start..=end.min(nodes.len().saturating_sub(1)) { - if let HtmlNode::Text { - start: s, - end: e, - all_ws, - } = &nodes[i] - { - if !all_ws || (text.is_empty() && *all_ws) { - if !text.is_empty() { - text.push(' '); - } - text.push_str(&decoded[*s..*e]); - } - } - } - text -} - -fn get_attr<'a>( - decoded: &'a str, - nodes: &[HtmlNode], - open_idx: usize, - attr_id: LiveId, -) -> Option<&'a str> { - for j in (open_idx + 1)..nodes.len() { - match &nodes[j] { - HtmlNode::Attribute { lc, start, end, .. } if *lc == attr_id => { - return Some(&decoded[*start..*end]); - } - HtmlNode::OpenTag { .. } | HtmlNode::CloseTag { .. } | HtmlNode::Text { .. } => break, - _ => {} - } - } - None -} - -fn count_top_level_elements(nodes: &[HtmlNode]) -> usize { - let mut count = 0; - let mut depth = 0u32; - for node in nodes { - match node { - HtmlNode::OpenTag { .. } => { - if depth == 0 { - count += 1; - } - depth += 1; - } - HtmlNode::CloseTag { .. } => { - depth = depth.saturating_sub(1); - } - _ => {} - } - } - count -} - -fn top_level_ranges(nodes: &[HtmlNode]) -> Vec<(u32, u32)> { - let mut out = Vec::new(); - let mut i = 0; - while i < nodes.len() { - if let HtmlNode::OpenTag { .. } = &nodes[i] { - let close = find_close_tag(nodes, i); - out.push((i as u32, close as u32)); - i = close + 1; - } else { - i += 1; - } - } - out -} - -pub fn define_html_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let html_type = native.new_handle_type(heap, id!(html)); - - // "string".parse_html() -> html handle - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(parse_html), - &[], - move |vm, args| { - let sself = script_value!(vm, args.self); - let doc = - if let Some(d) = vm.bx.heap.string_mut_self_with(sself, |_heap, s| { - parse_html(s, &mut None, InternLiveId::No) - }) { - d - } else { - return script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "parse_html called on non-string value" - ); - }; - let backing = Rc::new(HtmlBacking { - decoded: doc.decoded, - nodes: doc.nodes, - }); - let html_doc = ScriptHtmlDoc { - backing, - ranges: Vec::new(), - is_root: true, - handle: ScriptHandle::ZERO, - }; - vm.bx.heap.new_handle(html_type, Box::new(html_doc)).into() - }, - ); - - // html.query(selector) -> html handle, string, or array - native.add_type_method( - heap, - html_type.to_redux(), - id!(query), - &[(id!(sel), NIL)], - move |vm, args| { - let sself = script_value!(vm, args.self); - let sel_val = script_value!(vm, args.sel); - - let sel_str = if let Some(r) = vm.bx.heap.string_with(sel_val, |_, s| s.to_string()) { - r - } else { - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "query() selector must be a string" - ); - }; - - let handle = if let Some(h) = sself.as_handle() { - h - } else { - return NIL; - }; - - let parsed = parse_query(&sel_str); - - // Extract Rc backing + ranges (cheap clone of Rc + small vec) - let (backing, ranges, is_root) = - if let Some(doc) = vm.bx.heap.handle_ref::(handle) { - (doc.backing.clone(), doc.ranges.clone(), doc.is_root) - } else { - return NIL; - }; - - // Empty non-root = no matches from previous query, skip - if !is_root && ranges.is_empty() { - let sub = ScriptHtmlDoc { - backing: backing.clone(), - ranges: Vec::new(), - is_root: false, - handle: ScriptHandle::ZERO, - }; - return vm.bx.heap.new_handle(html_type, Box::new(sub)).into(); - } - - let matches = execute_query(&backing.decoded, &backing.nodes, &ranges, &parsed.steps); - - match parsed.terminal { - Terminal::Attr(attr_id) => { - if matches.len() == 1 { - if let Some(val) = get_attr( - &backing.decoded, - &backing.nodes, - matches[0].0 as usize, - attr_id, - ) { - return vm.bx.heap.new_string_from_str(val); - } - return NIL; - } - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur_ref().trap.pass(); - for &(s, _e) in &matches { - if let Some(val) = - get_attr(&backing.decoded, &backing.nodes, s as usize, attr_id) - { - let sv = vm.bx.heap.new_string_from_str(val); - vm.bx.heap.array_push(arr, sv, trap); - } else { - vm.bx.heap.array_push(arr, NIL, trap); - } - } - arr.into() - } - Terminal::Text => { - if matches.len() == 1 { - let slice = collect_text( - &backing.decoded, - &backing.nodes, - matches[0].0 as usize, - matches[0].1 as usize, - ); - if !slice.is_empty() { - return vm.bx.heap.new_string_from_str(slice); - } - let owned = collect_text_owned( - &backing.decoded, - &backing.nodes, - matches[0].0 as usize, - matches[0].1 as usize, - ); - return vm.bx.heap.new_string_from_str(&owned); - } - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur_ref().trap.pass(); - for &(s, e) in &matches { - let slice = - collect_text(&backing.decoded, &backing.nodes, s as usize, e as usize); - let sv = if !slice.is_empty() { - vm.bx.heap.new_string_from_str(slice) - } else { - let owned = collect_text_owned( - &backing.decoded, - &backing.nodes, - s as usize, - e as usize, - ); - vm.bx.heap.new_string_from_str(&owned) - }; - vm.bx.heap.array_push(arr, sv, trap); - } - arr.into() - } - Terminal::Index(idx) => { - if idx < matches.len() { - let sub = ScriptHtmlDoc { - backing: backing.clone(), - ranges: vec![matches[idx]], - is_root: false, - handle: ScriptHandle::ZERO, - }; - vm.bx.heap.new_handle(html_type, Box::new(sub)).into() - } else { - NIL - } - } - Terminal::None => { - let sub = ScriptHtmlDoc { - backing: backing.clone(), - ranges: matches, - is_root: false, - handle: ScriptHandle::ZERO, - }; - vm.bx.heap.new_handle(html_type, Box::new(sub)).into() - } - } - }, - ); - - // html.attr(name) -> string or nil - native.add_type_method( - heap, - html_type.to_redux(), - id!(attr), - &[(id!(name), NIL)], - move |vm, args| { - let sself = script_value!(vm, args.self); - let name_val = script_value!(vm, args.name); - let attr_name = if let Some(r) = vm.bx.heap.string_with(name_val, |_, s| s.to_string()) - { - r - } else { - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "attr() name must be a string" - ); - }; - let handle = if let Some(h) = sself.as_handle() { - h - } else { - return NIL; - }; - let attr_id = LiveId::from_str_lc(&attr_name); - let result = if let Some(doc) = vm.bx.heap.handle_ref::(handle) { - let open_idx = if doc.is_root && doc.ranges.is_empty() { - doc.nodes() - .iter() - .position(|n| matches!(n, HtmlNode::OpenTag { .. })) - } else if !doc.ranges.is_empty() { - Some(doc.ranges[0].0 as usize) - } else { - None - }; - open_idx.and_then(|idx| { - get_attr(doc.decoded(), doc.nodes(), idx, attr_id).map(|v| v.to_string()) - }) - } else { - None - }; - if let Some(val) = result { - return vm.bx.heap.new_string_from_str(&val); - } - NIL - }, - ); - - // html.array() -> array of html handles (one per top-level element) - native.add_type_method( - heap, - html_type.to_redux(), - id!(array), - &[], - move |vm, args| { - let sself = script_value!(vm, args.self); - let handle = if let Some(h) = sself.as_handle() { - h - } else { - return NIL; - }; - - let (backing, ranges) = - if let Some(doc) = vm.bx.heap.handle_ref::(handle) { - let r = if doc.is_root && doc.ranges.is_empty() { - top_level_ranges(doc.nodes()) - } else if !doc.ranges.is_empty() { - doc.ranges.clone() - } else { - Vec::new() - }; - (doc.backing.clone(), r) - } else { - return NIL; - }; - - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur_ref().trap.pass(); - for range in &ranges { - let sub = ScriptHtmlDoc { - backing: backing.clone(), - ranges: vec![*range], - is_root: false, - handle: ScriptHandle::ZERO, - }; - let h = vm.bx.heap.new_handle(html_type, Box::new(sub)); - vm.bx.heap.array_push(arr, h.into(), trap); - } - arr.into() - }, - ); - - // Getters: length, text, html - native.set_type_getter(html_type.to_redux(), |vm, value, field| { - let handle = if let Some(h) = value.as_handle() { - h - } else { - return NIL; - }; - - if field == id!(length) { - if let Some(doc) = vm.bx.heap.handle_ref::(handle) { - if !doc.is_root || !doc.ranges.is_empty() { - return ScriptValue::from_f64(doc.ranges.len() as f64); - } - return ScriptValue::from_f64(count_top_level_elements(doc.nodes()) as f64); - } - return NIL; - } - - // For text and html we extract the string, drop the borrow, then allocate - let result = if let Some(doc) = vm.bx.heap.handle_ref::(handle) { - if field == id!(text) { - let mut text = String::new(); - if doc.is_root && doc.ranges.is_empty() { - text = collect_text_owned( - doc.decoded(), - doc.nodes(), - 0, - doc.nodes().len().saturating_sub(1), - ); - } else { - for &(s, e) in &doc.ranges { - let t = - collect_text_owned(doc.decoded(), doc.nodes(), s as usize, e as usize); - if !t.is_empty() { - if !text.is_empty() { - text.push(' '); - } - text.push_str(&t); - } - } - } - Some(text) - } else if field == id!(html) { - let html = if doc.is_root && doc.ranges.is_empty() { - reconstruct_html(doc.decoded(), doc.nodes(), 0, doc.nodes().len()) - } else { - let mut out = String::new(); - for &(s, e) in &doc.ranges { - reconstruct_html_into( - &mut out, - doc.decoded(), - doc.nodes(), - s as usize, - e as usize + 1, - ); - } - out - }; - Some(html) - } else { - None - } - } else { - None - }; - - if let Some(s) = result { - return vm.bx.heap.new_string_from_str(&s); - } - NIL - }); -} - -fn reconstruct_html(decoded: &str, nodes: &[HtmlNode], start: usize, end: usize) -> String { - let mut out = String::new(); - reconstruct_html_into(&mut out, decoded, nodes, start, end); - out -} - -fn reconstruct_html_into( - out: &mut String, - decoded: &str, - nodes: &[HtmlNode], - start: usize, - end: usize, -) { - let mut i = start; - while i < end && i < nodes.len() { - match &nodes[i] { - HtmlNode::OpenTag { nc, .. } => { - out.push('<'); - out.push_str(&format!("{}", nc)); - let mut j = i + 1; - while j < end && j < nodes.len() { - if let HtmlNode::Attribute { nc, start, end, .. } = &nodes[j] { - out.push(' '); - out.push_str(&format!("{}", nc)); - let val = &decoded[*start..*end]; - if !val.is_empty() { - out.push_str("=\""); - out.push_str(val); - out.push('"'); - } - j += 1; - } else { - break; - } - } - out.push('>'); - } - HtmlNode::CloseTag { nc, .. } => { - out.push_str("'); - } - HtmlNode::Text { start, end, .. } => { - out.push_str(&decoded[*start..*end]); - } - HtmlNode::Attribute { .. } => {} - } - i += 1; - } -} diff --git a/vendor/makepad/platform/script/src/mod_math.rs b/vendor/makepad/platform/script/src/mod_math.rs deleted file mode 100644 index 9222e85..0000000 --- a/vendor/makepad/platform/script/src/mod_math.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::native::*; -use crate::shader_builtins::*; - -pub fn define_math_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let math = heap.new_module(id!(math)); - define_shader_builtins(heap, math, native); -} diff --git a/vendor/makepad/platform/script/src/mod_pod.rs b/vendor/makepad/platform/script/src/mod_pod.rs deleted file mode 100644 index 1526b62..0000000 --- a/vendor/makepad/platform/script/src/mod_pod.rs +++ /dev/null @@ -1,365 +0,0 @@ -#![allow(unused)] -use crate::heap::*; -use crate::native::*; -use crate::numeric::NumericValue; -use crate::pod::*; -use crate::value::*; -use crate::*; -use makepad_live_id::*; - -#[macro_export] -macro_rules! script_pod_def { - ($heap:expr, $pod: expr, $ty: ident, $id:ident, $pod_ty:expr, $pod_def:expr ) => {{ - let pod_obj = $heap.new_with_proto(id_lut!($ty).into()); - let pt = $heap.new_pod_type($pod_ty, $pod_def); - $heap.set_object_storage_vec2(pod_obj); - $heap.set_object_pod_type(pod_obj, pt); - $heap.set_value_def($pod, id!($id).into(), pod_obj.into()); - pt - }}; -} - -#[derive(Default)] -pub struct ScriptPodBuiltins { - pub pod_void: ScriptPodType, - pub pod_struct: ScriptPodType, - pub pod_array: ScriptPodType, - pub pod_bool: ScriptPodType, - pub pod_f32: ScriptPodType, - pub pod_f16: ScriptPodType, - pub pod_u32: ScriptPodType, - pub pod_i32: ScriptPodType, - pub pod_atomic_u32: ScriptPodType, - pub pod_atomic_i32: ScriptPodType, - pub pod_vec2f: ScriptPodType, - pub pod_vec3f: ScriptPodType, - pub pod_vec4f: ScriptPodType, - pub pod_vec2h: ScriptPodType, - pub pod_vec3h: ScriptPodType, - pub pod_vec4h: ScriptPodType, - pub pod_vec2u: ScriptPodType, - pub pod_vec3u: ScriptPodType, - pub pod_vec4u: ScriptPodType, - pub pod_vec2i: ScriptPodType, - pub pod_vec3i: ScriptPodType, - pub pod_vec4i: ScriptPodType, - pub pod_vec2b: ScriptPodType, - pub pod_vec3b: ScriptPodType, - pub pod_vec4b: ScriptPodType, - pub pod_mat2x2f: ScriptPodType, - pub pod_mat2x3f: ScriptPodType, - pub pod_mat2x4f: ScriptPodType, - pub pod_mat3x2f: ScriptPodType, - pub pod_mat3x3f: ScriptPodType, - pub pod_mat3x4f: ScriptPodType, - pub pod_mat4x2f: ScriptPodType, - pub pod_mat4x3f: ScriptPodType, - pub pod_mat4x4f: ScriptPodType, -} - -impl ScriptPodBuiltins { - pub fn value_to_exact_type(&self, val: ScriptValue) -> Option { - if val.is_f64() { - return Some(self.pod_f32); - } - if val.is_f32() { - return Some(self.pod_f32); - } - if val.is_u40() { - return Some(self.pod_u32); - } - if val.is_u32() { - return Some(self.pod_u32); - } - if val.is_i32() { - return Some(self.pod_i32); - } - if val.is_f16() { - return Some(self.pod_f16); - } - if val.is_bool() { - return Some(self.pod_bool); - } - None - } -} - -pub fn define_pod_module(heap: &mut ScriptHeap, native: &mut ScriptNative) -> ScriptPodBuiltins { - let pod = heap.new_module(id!(pod)); - - let pod_void = heap.pod_def_atom( - pod, - id_lut!(void), - None, - ScriptPodTy::Void, - id_lut!(pod_void), - ScriptValue::NIL, - ); - assert!(pod_void == ScriptPodType::VOID); - - let pod_struct = heap.pod_def_atom( - pod, - id_lut!(struct), - None, - ScriptPodTy::UndefinedStruct, - id_lut!(pod_struct), - ScriptValue::NIL, - ); - - let pod_array = heap.pod_def_atom( - pod, - id_lut!(array), - None, - ScriptPodTy::ArrayBuilder, - id_lut!(pod_array), - ScriptValue::NIL, - ); - - let pod_bool = heap.pod_def_atom( - pod, - id_lut!(bool), - None, - ScriptPodTy::Bool, - id_lut!(pod_bool), - ScriptValue::from_bool(false), - ); - - let pod_f32 = heap.pod_def_atom( - pod, - id_lut!(f32), - Some(id_lut!(float)), - ScriptPodTy::F32, - id_lut!(pod_f32), - ScriptValue::from_f32(0.0), - ); - - let pod_f16 = heap.pod_def_atom( - pod, - id_lut!(f16), - None, - ScriptPodTy::F16, - id_lut!(pod_f16), - ScriptValue::from_f16(0.0), - ); - - let pod_u32 = heap.pod_def_atom( - pod, - id_lut!(u32), - Some(id_lut!(uint)), - ScriptPodTy::U32, - id_lut!(pod_u32), - ScriptValue::from_u32(0), - ); - - let pod_i32 = heap.pod_def_atom( - pod, - id_lut!(i32), - Some(id_lut!(int)), - ScriptPodTy::I32, - id_lut!(pod_i32), - ScriptValue::from_i32(0), - ); - - let pod_atomic_u32 = heap.pod_def_atom( - pod, - id_lut!(atomic_u32), - None, - ScriptPodTy::AtomicU32, - id_lut!(pod_atomic_u32), - ScriptValue::from_u32(0), - ); - - let pod_atomic_i32 = heap.pod_def_atom( - pod, - id_lut!(pod_atomic_i32), - None, - ScriptPodTy::AtomicI32, - id_lut!(pod_atomic_i32), - ScriptValue::from_i32(0), - ); - - let pod_vec2f = heap.pod_def_vec( - pod, - id_lut!(vec2f), - Some(id_lut!(vec2)), - ScriptPodVec::Vec2f, - ); - let pod_vec3f = heap.pod_def_vec( - pod, - id_lut!(vec3f), - Some(id_lut!(vec3)), - ScriptPodVec::Vec3f, - ); - let pod_vec4f = heap.pod_def_vec( - pod, - id_lut!(vec4f), - Some(id_lut!(vec4)), - ScriptPodVec::Vec4f, - ); - let pod_vec2u = heap.pod_def_vec(pod, id_lut!(vec2u), None, ScriptPodVec::Vec2u); - let pod_vec3u = heap.pod_def_vec(pod, id_lut!(vec3u), None, ScriptPodVec::Vec3u); - let pod_vec4u = heap.pod_def_vec(pod, id_lut!(vec4u), None, ScriptPodVec::Vec4u); - let pod_vec2i = heap.pod_def_vec(pod, id_lut!(vec2i), None, ScriptPodVec::Vec2i); - let pod_vec3i = heap.pod_def_vec(pod, id_lut!(vec3i), None, ScriptPodVec::Vec3i); - let pod_vec4i = heap.pod_def_vec(pod, id_lut!(vec4i), None, ScriptPodVec::Vec4i); - let pod_vec2h = heap.pod_def_vec(pod, id_lut!(vec2h), None, ScriptPodVec::Vec2h); - let pod_vec3h = heap.pod_def_vec(pod, id_lut!(vec3h), None, ScriptPodVec::Vec3h); - let pod_vec4h = heap.pod_def_vec(pod, id_lut!(vec4h), None, ScriptPodVec::Vec4h); - let pod_vec2b = heap.pod_def_vec(pod, id_lut!(vec2b), None, ScriptPodVec::Vec2b); - let pod_vec3b = heap.pod_def_vec(pod, id_lut!(vec3b), None, ScriptPodVec::Vec3b); - let pod_vec4b = heap.pod_def_vec(pod, id_lut!(vec4b), None, ScriptPodVec::Vec4b); - - let pod_mat2x2f = heap.pod_def_mat(pod, id_lut!(mat2x2f), ScriptPodMat::Mat2x2f); - let pod_mat2x3f = heap.pod_def_mat(pod, id_lut!(mat2x3f), ScriptPodMat::Mat2x3f); - let pod_mat2x4f = heap.pod_def_mat(pod, id_lut!(mat2x4f), ScriptPodMat::Mat2x4f); - let pod_mat3x2f = heap.pod_def_mat(pod, id_lut!(mat3x2f), ScriptPodMat::Mat3x2f); - let pod_mat3x3f = heap.pod_def_mat(pod, id_lut!(mat3x3f), ScriptPodMat::Mat3x3f); - let pod_mat3x4f = heap.pod_def_mat(pod, id_lut!(mat3x4f), ScriptPodMat::Mat3x4f); - let pod_mat4x2f = heap.pod_def_mat(pod, id_lut!(mat4x2f), ScriptPodMat::Mat4x2f); - let pod_mat4x3f = heap.pod_def_mat(pod, id_lut!(mat4x3f), ScriptPodMat::Mat4x3f); - let pod_mat4x4f = heap.pod_def_mat(pod, id_lut!(mat4x4f), ScriptPodMat::Mat4x4f); - - // Add mix method for all pod types (f32, vec2f, vec3f, vec4f, etc.) - // self.mix(other, alpha) -> mix(self, other, alpha) - native.add_type_method( - heap, - ScriptValueType::REDUX_POD, - id!(mix), - script_args!(other = 0.0, a = 0.0), - |vm, args| { - let sself = - vm.bx - .heap - .value(args, id!(self).into(), vm.bx.threads.cur_ref().trap.pass()); - let other = - vm.bx - .heap - .value(args, id!(other).into(), vm.bx.threads.cur_ref().trap.pass()); - let a_val = vm - .bx - .heap - .value(args, id!(a).into(), vm.bx.threads.cur_ref().trap.pass()); - - let self_nv = NumericValue::from_script_value_heap( - &vm.bx.heap, - sself, - vm.bx.threads.cur_ref().trap.ip, - ); - let other_nv = NumericValue::from_script_value_heap( - &vm.bx.heap, - other, - vm.bx.threads.cur_ref().trap.ip, - ); - - // mix typically has scalar alpha, but can also have matching type alpha - if let Some(a_f) = a_val.as_f64() { - self_nv - .mix_scalar(other_nv, a_f) - .to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - } else { - let a_nv = NumericValue::from_script_value_heap( - &vm.bx.heap, - a_val, - vm.bx.threads.cur_ref().trap.ip, - ); - self_nv - .mix_componentwise(other_nv, a_nv) - .to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - } - }, - ); - - // Vector convenience methods, GDScript-style: v.length(), v.normalized(), - // a.dot(b), a.cross(b). The DSL guides teach these idioms; without them - // every steering AI has to hand-roll sqrt(dx*dx + ...). Registered under - // BOTH pod reduxes: runtime vec values dispatch as REDUX_POD_TYPE (13), - // heap pods as REDUX_POD (12). - for redux in [ScriptValueType::REDUX_POD, ScriptValueType::REDUX_POD_TYPE] { - native.add_type_method(heap, redux, id!(length), script_args!(), |vm, args| { - let trap = vm.bx.threads.cur_ref().trap.pass(); - let sself = vm.bx.heap.value(args, id!(self).into(), trap); - let ip = vm.bx.threads.cur_ref().trap.ip; - let nv = NumericValue::from_script_value_heap(&vm.bx.heap, sself, ip); - ScriptValue::from_f64(nv.length()) - }); - for method in [id!(normalized), id!(normalize)] { - native.add_type_method(heap, redux, method, script_args!(), |vm, args| { - let trap = vm.bx.threads.cur_ref().trap.pass(); - let sself = vm.bx.heap.value(args, id!(self).into(), trap); - let ip = vm.bx.threads.cur_ref().trap.ip; - let nv = NumericValue::from_script_value_heap(&vm.bx.heap, sself, ip); - nv.normalize() - .to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - }); - } - native.add_type_method( - heap, - redux, - id!(dot), - script_args!(other = 0.0), - |vm, args| { - let trap = vm.bx.threads.cur_ref().trap.pass(); - let sself = vm.bx.heap.value(args, id!(self).into(), trap); - let other = vm.bx.heap.value(args, id!(other).into(), trap); - let ip = vm.bx.threads.cur_ref().trap.ip; - let a = NumericValue::from_script_value_heap(&vm.bx.heap, sself, ip); - let b = NumericValue::from_script_value_heap(&vm.bx.heap, other, ip); - ScriptValue::from_f64(a.dot(b)) - }, - ); - native.add_type_method( - heap, - redux, - id!(cross), - script_args!(other = 0.0), - |vm, args| { - let trap = vm.bx.threads.cur_ref().trap.pass(); - let sself = vm.bx.heap.value(args, id!(self).into(), trap); - let other = vm.bx.heap.value(args, id!(other).into(), trap); - let ip = vm.bx.threads.cur_ref().trap.ip; - let a = NumericValue::from_script_value_heap(&vm.bx.heap, sself, ip); - let b = NumericValue::from_script_value_heap(&vm.bx.heap, other, ip); - a.cross(b) - .to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - }, - ); - } - - let ps = ScriptPodBuiltins { - pod_void, - pod_struct, - pod_array, - pod_bool, - pod_f32, - pod_f16, - pod_u32, - pod_i32, - pod_atomic_u32, - pod_atomic_i32, - pod_vec2f, - pod_vec3f, - pod_vec4f, - pod_vec2h, - pod_vec3h, - pod_vec4h, - pod_vec2u, - pod_vec3u, - pod_vec4u, - pod_vec2i, - pod_vec3i, - pod_vec4i, - pod_vec2b, - pod_vec3b, - pod_vec4b, - pod_mat2x2f, - pod_mat2x3f, - pod_mat2x4f, - pod_mat3x2f, - pod_mat3x3f, - pod_mat3x4f, - pod_mat4x2f, - pod_mat4x3f, - pod_mat4x4f, - }; - ps -} diff --git a/vendor/makepad/platform/script/src/mod_regex.rs b/vendor/makepad/platform/script/src/mod_regex.rs deleted file mode 100644 index 925db42..0000000 --- a/vendor/makepad/platform/script/src/mod_regex.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::array::*; -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::native::*; -use crate::value::*; -use crate::*; - -pub fn define_regex_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let std = heap.module(id!(std)); - - // regex(pattern, flags) -> ScriptRegex - native.add_method( - heap, - std, - id_lut!(regex), - script_args_def!(pattern = NIL, flags = NIL), - |vm, args| { - let pattern_val = script_value!(vm, args.pattern); - let flags_val = script_value!(vm, args.flags); - - let pattern_str; - let mut flags_str = String::new(); - - // Extract pattern string - if let Some(r) = vm.bx.heap.string_with(pattern_val, |_, s| s.to_string()) { - pattern_str = r; - } else { - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "regex() pattern must be a string" - ); - } - - // Extract flags string (default to empty) - if !flags_val.is_nil() { - if let Some(r) = vm.bx.heap.string_with(flags_val, |_, s| s.to_string()) { - flags_str = r; - } else { - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "regex() flags must be a string" - ); - } - } - - match vm.bx.heap.new_regex(&pattern_str, &flags_str) { - Ok(val) => val, - Err(e) => { - script_err_invalid_args!( - vm.bx.threads.cur_ref().trap, - "regex compile error: {}", - e - ) - } - } - }, - ); - - // Type methods on regex values - - // regex.test(str) -> bool - native.add_type_method( - heap, - ScriptValueType::REDUX_REGEX, - id!(test), - script_args_def!(str = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let str_val = script_value!(vm, args.str); - - if let Some(re_ptr) = sself.as_regex() { - if let Some(result) = vm.bx.heap.string_with(str_val, |heap, s| { - heap.regex(re_ptr).map(|re| re.inner.run(s, &mut [])) - }) { - if let Some(matched) = result { - return matched.into(); - } - } - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "regex.test() argument must be a string" - ); - } - script_err_unexpected!(vm.bx.threads.cur_ref().trap, "test called on non-regex") - }, - ); - - // regex.exec(str) -> object {value, index, captures} or nil - native.add_type_method( - heap, - ScriptValueType::REDUX_REGEX, - id!(exec), - script_args_def!(str = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let str_val = script_value!(vm, args.str); - - if let Some(re_ptr) = sself.as_regex() { - // We need to get num_captures first, then run - let num_captures = if let Some(re) = vm.bx.heap.regex(re_ptr) { - re.num_captures - } else { - return NIL; - }; - - let num_slots = (num_captures + 1) * 2; - let mut slots = vec![None; num_slots]; - - let matched = vm.bx.heap.string_with(str_val, |heap, s| { - if let Some(re) = heap.regex(re_ptr) { - if re.inner.run(s, &mut slots) { - Some(s.to_string()) - } else { - None - } - } else { - None - } - }); - - match matched { - Some(Some(input)) => { - let match_start = slots[0].unwrap_or(0); - let match_end = slots[1].unwrap_or(0); - let value = &input[match_start..match_end]; - - // Build result object - let obj = vm.bx.heap.new_with_proto(NIL); - let value_sv = vm.bx.heap.new_string_from_str(value); - let trap = vm.bx.threads.cur_ref().trap.pass(); - vm.bx.heap.set_value(obj, id!(value).into(), value_sv, trap); - vm.bx.heap.set_value( - obj, - id!(index).into(), - ScriptValue::from_f64(match_start as f64), - trap, - ); - - // Build captures array - let captures = vm.bx.heap.new_array(); - vm.bx - .heap - .array_mut_mut_self_with(captures, |heap, storage| { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(vec) = storage { - // Group 0 = whole match - vec.push_back(heap.new_string_from_str(value)); - // Groups 1..N - for i in 1..=num_captures { - let s = slots.get(i * 2).copied().flatten(); - let e = slots.get(i * 2 + 1).copied().flatten(); - match (s, e) { - (Some(s), Some(e)) => { - vec.push_back( - heap.new_string_from_str(&input[s..e]), - ); - } - _ => vec.push_back(NIL), - } - } - } - }); - - vm.bx - .heap - .set_value(obj, id!(captures).into(), captures.into(), trap); - return obj.into(); - } - _ => return NIL, - } - } - script_err_unexpected!(vm.bx.threads.cur_ref().trap, "exec called on non-regex") - }, - ); - - // Property getters: regex.source, regex.global - native.set_type_getter(ScriptValueType::REDUX_REGEX, |vm, value, field| { - if let Some(re_ptr) = value.as_regex() { - if let Some(re) = vm.bx.heap.regex(re_ptr) { - if field == id!(source) { - let pat = re.pattern.clone(); - return vm.bx.heap.new_string_from_str(&pat); - } else if field == id!(global) { - return re.flags.global.into(); - } - } - } - NIL - }); -} diff --git a/vendor/makepad/platform/script/src/mod_shader.rs b/vendor/makepad/platform/script/src/mod_shader.rs deleted file mode 100644 index 4a89f12..0000000 --- a/vendor/makepad/platform/script/src/mod_shader.rs +++ /dev/null @@ -1,565 +0,0 @@ -use crate::heap::*; -use crate::native::*; -use crate::shader::*; -use crate::shader_backend::*; -use crate::trap::NoTrap; -use crate::value::*; -#[allow(unused)] -use crate::*; -use makepad_live_id::*; - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ShaderIoType(pub(crate) u32); - -pub const SHADER_IO_RUST_INSTANCE: ShaderIoType = ShaderIoType(0); -pub const SHADER_IO_DYN_INSTANCE: ShaderIoType = ShaderIoType(1); -pub const SHADER_IO_DYN_UNIFORM: ShaderIoType = ShaderIoType(2); -pub const SHADER_IO_UNIFORM_BUFFER: ShaderIoType = ShaderIoType(3); -pub const SHADER_IO_VERTEX_BUFFER: ShaderIoType = ShaderIoType(4); -pub const SHADER_IO_VARYING: ShaderIoType = ShaderIoType(5); -pub const SHADER_IO_VERTEX_POSITION: ShaderIoType = ShaderIoType(6); -pub const SHADER_IO_TEXTURE_1D: ShaderIoType = ShaderIoType(7); -pub const SHADER_IO_TEXTURE_VIDEO: ShaderIoType = ShaderIoType(8); -pub const SHADER_IO_TEXTURE_1D_ARRAY: ShaderIoType = ShaderIoType(9); -pub const SHADER_IO_TEXTURE_2D: ShaderIoType = ShaderIoType(10); -pub const SHADER_IO_TEXTURE_2D_ARRAY: ShaderIoType = ShaderIoType(11); -pub const SHADER_IO_TEXTURE_3D: ShaderIoType = ShaderIoType(12); -pub const SHADER_IO_TEXTURE_3D_ARRAY: ShaderIoType = ShaderIoType(13); -pub const SHADER_IO_TEXTURE_CUBE: ShaderIoType = ShaderIoType(14); -pub const SHADER_IO_TEXTURE_CUBE_ARRAY: ShaderIoType = ShaderIoType(15); -pub const SHADER_IO_TEXTURE_DEPTH: ShaderIoType = ShaderIoType(16); -pub const SHADER_IO_TEXTURE_DEPTH_ARRAY: ShaderIoType = ShaderIoType(17); -pub const SHADER_IO_SAMPLER: ShaderIoType = ShaderIoType(18); -pub const SHADER_IO_BUFFER_R: ShaderIoType = ShaderIoType(19); -pub const SHADER_IO_BUFFER_W: ShaderIoType = ShaderIoType(20); -pub const SHADER_IO_BUFFER_RW: ShaderIoType = ShaderIoType(21); -pub const SHADER_IO_SCOPE_UNIFORM: ShaderIoType = ShaderIoType(22); -pub const SHADER_IO_FRAGMENT_OUTPUT_0: ShaderIoType = ShaderIoType(23); -pub const SHADER_IO_FRAGMENT_OUTPUT_MAX: ShaderIoType = - ShaderIoType(SHADER_IO_FRAGMENT_OUTPUT_0.0 + 7); - -pub fn define_shader_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let shader = heap.new_module(id!(shader)); - - native.add_method( - heap, - shader, - id_lut!(depth_clip), - script_args!(world = NIL, color = NIL, clip = 0.0), - |vm, args| { - vm.bx - .heap - .value(args, id!(color).into(), vm.bx.threads.cur_ref().trap.pass()) - }, - ); - - native.add_method( - heap, - shader, - id_lut!(instance), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_DYN_INSTANCE); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(uniform), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_DYN_UNIFORM); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(uniform_buffer), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_UNIFORM_BUFFER); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(vertex_buffer), - script_args!(value = NIL, buf = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let buffer = script_value!(vm, args.buf); - let obj = vm.bx.heap.new_with_proto(value); - set_script_value!(vm, obj.buffer = buffer); - vm.bx.heap.set_shader_io(obj, SHADER_IO_VERTEX_BUFFER); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(varying), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_VARYING); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(vertex_position), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_VERTEX_POSITION); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_1d), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_1D); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_1d_array), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_1D_ARRAY); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_2d), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_2D); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_2d_array), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_2D_ARRAY); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_3d), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_3D); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_3d_array), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_3D_ARRAY); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_cube), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_CUBE); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_cube_array), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_CUBE_ARRAY); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_depth), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_DEPTH); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_depth_array), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_DEPTH_ARRAY); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(texture_video), - script_args!(value = NIL), - |vm, args| { - let value = script_value!(vm, args.value); - let obj = vm.bx.heap.new_with_proto(value); - vm.bx.heap.set_shader_io(obj, SHADER_IO_TEXTURE_VIDEO); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(fragment_output), - script_args!(index = NIL, ty = NIL), - |vm, args| { - let index = script_value!(vm, args.index); - let ty = script_value!(vm, args.ty); - let obj = vm.bx.heap.new_with_proto(ty); - let index = index.as_index().min(7) as u32; - vm.bx - .heap - .set_shader_io(obj, ShaderIoType(SHADER_IO_FRAGMENT_OUTPUT_0.0 + index)); - obj.into() - }, - ); - - native.add_method( - heap, - shader, - id_lut!(test_compile_draw), - script_args!(io_self = NIL), - |vm, args| { - // lets fetch the code - let io_self = script_value!(vm, args.io_self); - - // ok we're going to take a function, and then call it to generate/typetrace it out - // for every function we make a 'shadercompiler' - if let Some(io_self) = io_self.as_object() { - let mut output = ShaderOutput::default(); - output.backend = ShaderBackend::Metal; - output.use_vulkan = false; - - output.pre_collect_rust_instance_io(vm, io_self); - output.pre_collect_shader_io(vm, io_self); - - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(vertex).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Vertex; - // Entry point shaders don't have script-level arguments to validate, use NoTrap - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(vertex), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(fragment).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Fragment; - // Entry point shaders don't have script-level arguments to validate, use NoTrap - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(fragment), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - - output.assign_uniform_buffer_indices(&vm.bx.heap, 3); - - let mut out = String::new(); - output.create_struct_defs(vm, &mut out); - output.metal_create_instance_struct(vm, &mut out); - output.metal_create_uniform_struct(vm, &mut out); - output.metal_create_scope_uniform_struct(vm, &mut out); - output.metal_create_io_struct(vm, &mut out); - output.metal_create_varying_struct(vm, &mut out); - output.metal_create_vertex_buffer_struct(vm, &mut out); - output.metal_create_sampler_decls(&mut out); - output.metal_create_helpers(&mut out); - output.metal_create_io_vertex_struct(vm, &mut out); - output.metal_create_vertex_fn(vm, &mut out); - output.metal_create_io_fragment_struct(vm, &mut out); - /* - output.metal_create_fragment_main_fn(vm, &mut out); - println!("Structs:\n{}", out); - for fns in &output.functions{ - println!("{}{{\n{}}}\n",fns.call_sig, fns.out); - } - - // Print scope uniforms for debugging - if !output.scope_uniforms.is_empty() { - println!("\nScope Uniforms ({} entries):", output.scope_uniforms.len()); - for su in &output.scope_uniforms { - println!(" - source_obj: {}, key: {}, shader_name: {}", - su.source_obj.index, su.key, su.shader_name); - } - }*/ - - return NIL; - } - // trap error - NIL - }, - ); - - native.add_method( - heap, - shader, - id_lut!(test_compile_draw_contains), - script_args!(io_self = NIL, needle = NIL), - |vm, args| { - let io_self = script_value!(vm, args.io_self); - let needle_val = script_value!(vm, args.needle); - let Some(needle) = vm.bx.heap.string_with(needle_val, |_heap, s| s.to_string()) else { - return ScriptValue::from_bool(false); - }; - - if let Some(io_self) = io_self.as_object() { - let mut output = ShaderOutput::default(); - output.backend = ShaderBackend::Metal; - output.use_vulkan = false; - - output.pre_collect_rust_instance_io(vm, io_self); - output.pre_collect_shader_io(vm, io_self); - - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(vertex).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Vertex; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(vertex), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(fragment).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Fragment; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(fragment), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - - output.assign_uniform_buffer_indices(&vm.bx.heap, 3); - - let mut out = String::new(); - output.create_struct_defs(vm, &mut out); - output.metal_create_instance_struct(vm, &mut out); - output.metal_create_uniform_struct(vm, &mut out); - output.metal_create_scope_uniform_struct(vm, &mut out); - output.metal_create_io_struct(vm, &mut out); - output.metal_create_varying_struct(vm, &mut out); - output.metal_create_vertex_buffer_struct(vm, &mut out); - output.metal_create_sampler_decls(&mut out); - output.metal_create_helpers(&mut out); - output.create_functions(&mut out); - output.metal_create_io_vertex_struct(vm, &mut out); - output.metal_create_io_framebuffer_struct(vm, &mut out); - output.metal_create_io_fragment_struct(vm, &mut out); - output.metal_create_vertex_fn(vm, &mut out); - output.metal_create_fragment_main_fn(vm, &mut out); - - return ScriptValue::from_bool(out.contains(&needle)); - } - - ScriptValue::from_bool(false) - }, - ); - - native.add_method( - heap, - shader, - id_lut!(test_compile_draw_rust_contains), - script_args!(io_self = NIL, needle = NIL), - |vm, args| { - let io_self = script_value!(vm, args.io_self); - let needle_val = script_value!(vm, args.needle); - let Some(needle) = vm.bx.heap.string_with(needle_val, |_heap, s| s.to_string()) else { - return ScriptValue::from_bool(false); - }; - - if let Some(io_self) = io_self.as_object() { - let mut output = ShaderOutput::default(); - output.backend = ShaderBackend::Rust; - output.use_vulkan = false; - - output.pre_collect_rust_instance_io(vm, io_self); - output.pre_collect_shader_io(vm, io_self); - - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(vertex).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Vertex; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(vertex), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - if let Some(fnobj) = vm - .bx - .heap - .object_method( - io_self, - id!(fragment).into(), - vm.bx.threads.cur_ref().trap.pass(), - ) - .as_object() - { - output.mode = ShaderMode::Fragment; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(fragment), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - - output.assign_uniform_buffer_indices(&vm.bx.heap, 3); - - // The Rust backend has no monolithic module emitter here (the - // headless runtime owns that); struct defs plus the compiled - // function bodies cover everything expression codegen produces. - let mut out = String::new(); - output.create_struct_defs(vm, &mut out); - output.create_functions(&mut out); - - return ScriptValue::from_bool(out.contains(&needle)); - } - - ScriptValue::from_bool(false) - }, - ); -} diff --git a/vendor/makepad/platform/script/src/mod_std.rs b/vendor/makepad/platform/script/src/mod_std.rs deleted file mode 100644 index 8a57602..0000000 --- a/vendor/makepad/platform/script/src/mod_std.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::native::*; -use crate::value::*; -use crate::*; - -pub fn define_std_module(heap: &mut ScriptHeap, native: &mut ScriptNative) { - let std = heap.new_module(id!(std)); - - native.add_method( - heap, - std, - id_lut!(assert), - script_args!(v = NIL), - |vm, args| { - if let Some(x) = script_value!(vm, args.v).as_bool() { - if x == true { - return NIL; - } - } - script_err_assert_fail!(vm.bx.threads.cur_ref().trap, "assertion failed") - }, - ); - - //native.add_method(heap, std, id!(err), script_args!(), |vm, _args|{ - // return vm.thread.last_err - //}); - - let range = heap.new_with_proto(id!(range).into()); - heap.set_value_def(std, id!(Range).into(), range.into()); - - native.add_method( - heap, - range, - id_lut!(step), - script_args!(x = 0.0), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - if let Some(x) = script_value!(vm, args.x).as_f64() { - set_script_value!(vm, sself.step = x); - } - return sself.into(); - } - NIL - }, - ); - - native.add_method( - heap, - std, - id_lut!(log), - script_args_def!(what = NIL), - |vm, args| { - let what = script_value!(vm, args.what); - vm.log(what); - NIL - }, - ); - - native.add_method( - heap, - std, - id_lut!(print), - script_args_def!(what = NIL), - |vm, args| { - let what = script_value!(vm, args.what); - if vm - .string_with(what, |_vm, str| { - print!("{}", str); - }) - .is_none() - { - vm.bx.heap.temp_bounded_string_with(|heap, temp| { - heap.cast_to_string(what, temp); - print!("{}", temp.as_str()) - }); - } - NIL - }, - ); - - native.add_method( - heap, - std, - id_lut!(println), - script_args_def!(what = NIL), - |vm, args| { - let what = script_value!(vm, args.what); - if vm - .string_with(what, |_vm, str| { - println!("{}", str); - }) - .is_none() - { - let is_empty = vm.bx.heap.temp_bounded_string_with(|heap, temp| { - heap.cast_to_string(what, temp); - if temp.is_empty() { - return true; - } - println!("{}", temp.as_str()); - false - }); - if is_empty { - return script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "println called with empty converted string, value: {:?}", - what - ); - } - } - NIL - }, - ); - - //native.add_method(heap, std, id!(to_metal_shader), script_args!(entry=NIL), |vm, _args|{ - - // return vm.thread.last_err - //}); - - native.add_method( - heap, - std, - id_lut!(set_type_default), - script_args!(obj = NIL), - |vm, args| { - if let Some(obj) = script_value!(vm, args.obj).as_object() { - if vm.bx.heap.set_type_default(obj) { - return obj.into(); - } - } - NIL - }, - ); -} diff --git a/vendor/makepad/platform/script/src/native.rs b/vendor/makepad/platform/script/src/native.rs deleted file mode 100644 index d88fca8..0000000 --- a/vendor/makepad/platform/script/src/native.rs +++ /dev/null @@ -1,495 +0,0 @@ -use crate::array::*; -use crate::function::*; -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id::*; -use crate::object::*; -use crate::string::*; -use crate::value::*; -use crate::vm::*; -use crate::*; - -#[macro_export] -macro_rules! script_value_f64 { - ($ctx:ident, $args:ident.$id: ident) => { - $ctx.heap.cast_to_f64( - $ctx.heap.value($args, id!($id).into(), &$ctx.thread.trap), - $ctx.thread.trap.ip, - ) - }; - ($ctx:ident, $obj:ident[$index: expr]) => { - $ctx.heap.cast_to_f64( - $ctx.heap.vec_value($obj, ($index) as usize), - $ctx.thread.ip(), - ) - }; -} - -#[macro_export] -macro_rules! script_value_bool { - ($ctx:ident, $args:ident.$id: ident) => { - $ctx.heap.cast_to_bool( - $ctx.heap.value($args, id!($id).into(), NIL), - $ctx.thread.ip(), - ) - }; - ($ctx:ident, $obj:ident[$index: expr]) => { - $ctx.heap.cast_to_bool( - $ctx.heap.vec_value($obj, ($index) as usize), - $ctx.thread.ip(), - ) - }; -} - -#[macro_export] -macro_rules! script_value { - ($vm:ident, $obj:ident.$id: ident) => { - $vm.bx.heap.value( - ($obj).into(), - id!($id).into(), - $vm.bx.threads.cur_ref().trap.pass(), - ) - }; - ($vm:ident, $obj:ident.$id:ident.$id2:ident) => { - $vm.bx.heap.value( - $vm.bx - .heap - .value( - ($obj).into(), - id!($id).into(), - $vm.bx.threads.cur_ref().trap.pass(), - ) - .into(), - id!($id2).into(), - $vm.bx.threads.cur_ref().trap.pass(), - ) - }; - ($vm:ident, $obj:ident[$index: expr]) => { - $vm.bx.heap.vec_value( - ($obj).into(), - ($index) as usize, - $vm.bx.threads.cur_ref().trap.pass(), - ) - }; - ($vm:ident, $obj:ident as array[$index: expr]) => { - $vm.bx.heap.array_index( - ($obj).into(), - ($index) as usize, - $vm.bx.threads.cur_ref().trap.pass(), - ) - }; -} - -#[macro_export] -macro_rules! script_has_proto { - ($vm:ident, $what:ident, $obj:ident.$id: ident) => {{ - let proto = $vm.bx.heap.value( - ($obj).into(), - id!($id).into(), - $vm.bx.threads.cur_ref().trap.pass(), - ); - $vm.bx.heap.has_proto(($what).into(), proto) - }}; -} - -#[macro_export] -macro_rules! script_is_fn { - ($vm:ident, $what:ident, $obj:expr) => {{ - $vm.bx.heap.is_fn(($obj).into()) - }}; -} - -#[macro_export] -macro_rules! script_array_index { - ($vm:ident, $obj:ident[$index: expr]) => {{ - let trap = $vm.bx.threads.cur().trap.pass(); - $vm.bx - .heap - .array_index(($obj).into(), ($index) as usize, trap) - }}; -} - -#[macro_export] -macro_rules! set_script_value { - ($vm:ident, $obj:ident.$id: ident=$value:expr) => {{ - let trap = $vm.bx.threads.cur().trap.pass(); - $vm.bx - .heap - .set_value($obj, id!($id).into(), ($value).into(), trap) - }}; - ($vm:ident, $obj:ident[$index: expr]=$value:expr) => {{ - let trap = $vm.bx.threads.cur().trap.pass(); - $vm.bx - .heap - .set_vec_value($obj, ($index) as usize, ($value).into(), trap) - }}; -} - -#[macro_export] -macro_rules! set_script_value_to_api { - ($vm:ident, $obj:ident.$id: ident=$val:expr) => {{ - let v = $val::script_api($vm); - let trap = $vm.bx.threads.cur().trap.pass(); - $vm.bx - .heap - .set_value(($obj).into(), id_lut!($id).into(), v, trap); - }}; - ($vm:ident, $obj:ident.$id: ident) => {{ - let v = $id::script_api($vm); - let trap = $vm.bx.threads.cur().trap.pass(); - $vm.bx - .heap - .set_value(($obj).into(), id_lut!($id).into(), v, trap); - }}; -} - -#[macro_export] -macro_rules! set_script_value_to_pod { - ($vm:ident, $obj:ident.$id: ident=$val:expr) => {{ - let v = $val::script_pod($vm).expect("Cant make a pod type"); - $vm.bx.heap.pod_type_name_set(v, id_lut!($id)); - $vm.bx.heap.set_value( - ($obj).into(), - id_lut!($id).into(), - v.into(), - $vm.bx.threads.cur_ref().trap.pass(), - ); - }}; - ($vm:ident, $obj:ident.$id: ident) => {{ - let v = $id::script_pod($vm).expect("Cant make a pod type"); - $vm.bx.heap.pod_type_name_set(v, id_lut!($id)); - $vm.bx.heap.set_value( - ($obj).into(), - id_lut!($id).into(), - v.into(), - $vm.bx.threads.cur_ref().trap.pass(), - ); - }}; -} - -#[macro_export] -macro_rules! script_args{ - ($($id:ident=$val:expr),*)=>{ - &[$((id!($id), ($val).into()),)*] - } -} - -#[macro_export] -macro_rules! script_args_def{ - ($($id:ident=$val:expr),*)=>{ - &[$((id_lut!($id), ($val).into()),)*] - } -} - -pub type NativeGetterFn = Box ScriptValue + 'static>; -pub type NativeSetterFn = - Box ScriptValue + 'static>; -/// Generic method dispatch: called with (vm, args_object, method). -/// The args object has `self` set and all call arguments collected. -/// Used when a type has no specific method registered but has a catch-all call handler. -pub type NativeCallFn = Box ScriptValue + 'static>; -pub type NativeFn = Box ScriptValue + 'static>; - -#[derive(Default)] -pub struct ScriptNative { - pub(crate) functions: Vec, - pub(crate) type_table: Vec>, - pub(crate) handle_type: LiveIdMap, - pub(crate) getters: Vec, - pub(crate) setters: Vec, - pub(crate) calls: Vec>, -} - -impl ScriptNative { - pub fn new(h: &mut ScriptHeap) -> Self { - let mut native = Self::default(); - native.add_shared(h); - ScriptObjectData::add_type_methods(&mut native, h); - ScriptArrayData::add_type_methods(&mut native, h); - ScriptStringData::add_type_methods(&mut native, h); - native - } - - /// Generic entry point - only boxes the closure, delegates to non-generic helper - #[inline(always)] - pub fn add_fn( - &mut self, - heap: &mut ScriptHeap, - args: &[(LiveId, ScriptValue)], - f: F, - ) -> ScriptObject - where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - let boxed: NativeFn = Box::new(f); - self.add_fn_boxed(heap, args, boxed) - } - - /// Non-generic helper that does the actual work - reduces monomorphization - #[inline(never)] - fn add_fn_boxed( - &mut self, - heap: &mut ScriptHeap, - args: &[(LiveId, ScriptValue)], - f: NativeFn, - ) -> ScriptObject { - let fn_index = self.functions.len(); - let fn_obj = heap.new_with_proto(id!(native).into()); - heap.set_object_storage_vec2(fn_obj); - heap.set_fn( - fn_obj, - ScriptFnPtr::Native(NativeId { - index: fn_index as u32, - }), - ); - - for (arg, def) in args { - heap.set_value_def(fn_obj, (*arg).into(), *def); - } - - self.functions.push(f); - - fn_obj - } - - /// Registers a native function to be used as an apply_transform and returns its NativeId. - /// This is used for creating objects that transform to a computed value when applied. - pub fn add_apply_transform_fn(&mut self, f: F) -> NativeId - where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - let fn_index = self.functions.len(); - self.functions.push(Box::new(f)); - NativeId { - index: fn_index as u32, - } - } - - pub fn add_method( - &mut self, - heap: &mut ScriptHeap, - module: ScriptObject, - method: LiveId, - args: &[(LiveId, ScriptValue)], - f: F, - ) where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - // lets get the - let fn_obj = self.add_fn(heap, args, f); - heap.set_value_def(module, method.into(), fn_obj.into()); - } - - pub fn new_handle_type(&mut self, heap: &mut ScriptHeap, id: LiveId) -> ScriptHandleType { - let ht = self.type_table.len() - ScriptValueType::REDUX_HANDLE_FIRST.to_index(); - if ht >= ScriptValueType::REDUX_HANDLE_MAX as usize { - panic!( - "Too many handle types (max {})", - ScriptValueType::REDUX_HANDLE_MAX - ); - } - let ty = ScriptHandleType(ht as u8); - self.handle_type.insert(id, ty); - self.add_type_method(heap, ty.to_redux(), id!(ty), &[], move |_, _| id.escape()); - ty - } - - pub fn set_type_getter(&mut self, ty_redux: ScriptTypeRedux, f: F) - where - F: Fn(&mut ScriptVm, ScriptValue, LiveId) -> ScriptValue + 'static, - { - self.getters[ty_redux.to_index()] = Box::new(f) - } - - pub fn set_type_setter(&mut self, ty_redux: ScriptTypeRedux, f: F) - where - F: Fn(&mut ScriptVm, ScriptValue, LiveId, ScriptValue) -> ScriptValue + 'static, - { - self.setters[ty_redux.to_index()] = Box::new(f) - } - - pub fn set_type_call(&mut self, ty_redux: ScriptTypeRedux, f: F) - where - F: Fn(&mut ScriptVm, ScriptObject, LiveId) -> ScriptValue + 'static, - { - self.ensure_type_table_capacity(ty_redux); - self.calls[ty_redux.to_index()] = Some(Box::new(f)); - } - - /// Ensures capacity for type tables - non-generic to reduce monomorphization - #[inline(never)] - fn ensure_type_table_capacity(&mut self, ty_redux: ScriptTypeRedux) { - if ty_redux.to_index() as usize >= self.type_table.len() { - self.type_table - .resize_with(ty_redux.to_index() + 1, || Default::default()); - self.getters.resize_with(ty_redux.to_index() + 1, || { - Box::new(|vm, value, field| { - script_err_not_found!( - vm.bx.threads.cur_ref().trap, - "no getter for field {:?} on type {:?}", - field, - value.value_type() - ) - }) - }); - self.setters.resize_with(ty_redux.to_index() + 1, || { - Box::new(|vm, value, field, _| { - script_err_not_found!( - vm.bx.threads.cur_ref().trap, - "no setter for field {:?} on type {:?}", - field, - value.value_type() - ) - }) - }); - self.calls.resize_with(ty_redux.to_index() + 1, || None); - } - } - - pub fn add_type_method( - &mut self, - heap: &mut ScriptHeap, - ty_redux: ScriptTypeRedux, - method: LiveId, - args: &[(LiveId, ScriptValue)], - f: F, - ) where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - let fn_obj = self.add_fn(heap, args, f); - self.ensure_type_table_capacity(ty_redux); - self.type_table[ty_redux.to_index()].insert(method, fn_obj); - } - - /// Removes every native method registered for one value type. - /// - /// A host that embeds the raw VM normally leaves this surface intact. A - /// restricted embedding can clear it during trusted setup, then install a - /// smaller owned method surface before any script is evaluated. - pub fn clear_type_methods(&mut self, ty_redux: ScriptTypeRedux) -> usize { - let Some(methods) = self.type_table.get_mut(ty_redux.to_index()) else { - return 0; - }; - let removed = methods.len(); - methods.clear(); - removed - } - - pub fn add_shared(&mut self, heap: &mut ScriptHeap) { - self.add_type_method(heap, ScriptValueType::REDUX_NUMBER, id!(ty), &[], |_, _| { - id!(number).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_NAN, id!(ty), &[], |_, _| { - id!(nan).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_BOOL, id!(ty), &[], |_, _| { - id!(bool).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_NIL, id!(ty), &[], |_, _| { - id!(nil).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_COLOR, id!(ty), &[], |_, _| { - id!(color).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_STRING, id!(ty), &[], |_, _| { - id!(string).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_OBJECT, id!(ty), &[], |_, _| { - id!(object).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ARRAY, id!(ty), &[], |_, _| { - id!(rsid).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_REGEX, id!(ty), &[], |_, _| { - id!(regex).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_OPCODE, id!(ty), &[], |_, _| { - id!(opcode).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ERR, id!(ty), &[], |_, _| { - id!(err).escape() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ID, id!(ty), &[], |_, _| { - id!(id).escape() - }); - - let types = [ - (ScriptValueType::REDUX_NUMBER, id!(is_number)), - (ScriptValueType::REDUX_NAN, id!(is_nan)), - (ScriptValueType::REDUX_BOOL, id!(is_bool)), - (ScriptValueType::REDUX_NIL, id!(is_nil)), - (ScriptValueType::REDUX_COLOR, id!(is_color)), - (ScriptValueType::REDUX_STRING, id!(is_string)), - (ScriptValueType::REDUX_OBJECT, id!(is_object)), - (ScriptValueType::REDUX_ARRAY, id!(is_array)), - (ScriptValueType::REDUX_REGEX, id!(is_regex)), - (ScriptValueType::REDUX_OPCODE, id!(is_opcode)), - (ScriptValueType::REDUX_ERR, id!(is_err)), - (ScriptValueType::REDUX_ID, id!(is_id)), - ]; - - for (ty, _) in types { - self.add_type_method(heap, ty, id!(to_json), &[], |vm, args| { - let sself = script_value!(vm, args.self); - vm.bx.heap.to_json(sself) - }); - self.add_type_method(heap, ty, id!(to_number), &[], |vm, args| { - let sself = script_value!(vm, args.self); - vm.bx - .heap - .cast_to_f64(sself, vm.bx.threads.cur_ref().trap.ip) - .into() - }); - if ty != ScriptValueType::REDUX_ARRAY { - self.add_type_method(heap, ty, id!(to_string), &[], |vm, args| { - let sself = script_value!(vm, args.self); - if sself.is_string_like() { - return sself; - } - vm.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(sself, out); - }) - }); - } - } - - for (ty, id) in types { - self.add_type_method(heap, ScriptValueType::REDUX_NUMBER, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_NUMBER).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_NAN, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_NAN).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_BOOL, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_BOOL).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_NIL, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_NIL).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_COLOR, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_COLOR).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_STRING, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_STRING).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_OBJECT, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_OBJECT).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ARRAY, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_ARRAY).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_REGEX, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_REGEX).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_OPCODE, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_OPCODE).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ERR, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_ERR).into() - }); - self.add_type_method(heap, ScriptValueType::REDUX_ID, id, &[], move |_, _| { - (ty == ScriptValueType::REDUX_ID).into() - }); - } - } -} diff --git a/vendor/makepad/platform/script/src/numeric.rs b/vendor/makepad/platform/script/src/numeric.rs deleted file mode 100644 index a1e9fa5..0000000 --- a/vendor/makepad/platform/script/src/numeric.rs +++ /dev/null @@ -1,732 +0,0 @@ -//! Numeric value types for type-preserving arithmetic operations -//! -//! This module provides the `NumericValue` enum which can hold f64, Vec2f, Vec3f, Vec4f, -//! Color, or Mat4x4f values and supports component-wise operations with proper type promotion. - -use crate::heap::*; -use crate::pod::*; -use crate::value::*; -use crate::vm::ScriptCode; -use makepad_math::{Vec2f, Vec3f, Vec4f}; - -/// Represents a numeric value that can be f64, Vec2f, Vec3f, Vec4f, Color, or Mat4x4f -/// Used for type-preserving arithmetic operations -#[derive(Clone, Copy)] -pub enum NumericValue { - F64(f64), - Vec2(Vec2f), - Vec3(Vec3f), - Vec4(Vec4f), - Color(Vec4f), // Color stored as Vec4f internally - Mat4([f32; 16]), // 4x4 matrix in column-major order -} - -impl NumericValue { - /// Extract a numeric value from ScriptValue (heap-only version, no vm needed) - pub fn from_script_value_heap(heap: &ScriptHeap, value: ScriptValue, ip: ScriptIp) -> Self { - // Check for Color first (u32 encoded) - if let Some(c) = value.as_color() { - return NumericValue::Color(Vec4f::from_u32(c)); - } - - // Check for f64 - if let Some(f) = value.as_f64() { - return NumericValue::F64(f); - } - - // Check for other number types - if let Some(f) = value.as_f32() { - return NumericValue::F64(f as f64); - } - if let Some(f) = value.as_u32() { - return NumericValue::F64(f as f64); - } - if let Some(f) = value.as_i32() { - return NumericValue::F64(f as f64); - } - - // Check for Pod (Vec and Mat types) - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - match &pod_type.ty { - ScriptPodTy::Vec(v) => { - match v { - ScriptPodVec::Vec2f => { - return NumericValue::Vec2(Vec2f { - x: f32::from_bits(pod_data.data[0]), - y: f32::from_bits(pod_data.data[1]), - }); - } - ScriptPodVec::Vec3f => { - return NumericValue::Vec3(Vec3f { - x: f32::from_bits(pod_data.data[0]), - y: f32::from_bits(pod_data.data[1]), - z: f32::from_bits(pod_data.data[2]), - }); - } - ScriptPodVec::Vec4f => { - return NumericValue::Vec4(Vec4f { - x: f32::from_bits(pod_data.data[0]), - y: f32::from_bits(pod_data.data[1]), - z: f32::from_bits(pod_data.data[2]), - w: f32::from_bits(pod_data.data[3]), - }); - } - // Handle integer vectors by converting to float - ScriptPodVec::Vec2i | ScriptPodVec::Vec2u => { - return NumericValue::Vec2(Vec2f { - x: pod_data.data[0] as f32, - y: pod_data.data[1] as f32, - }); - } - ScriptPodVec::Vec3i | ScriptPodVec::Vec3u => { - return NumericValue::Vec3(Vec3f { - x: pod_data.data[0] as f32, - y: pod_data.data[1] as f32, - z: pod_data.data[2] as f32, - }); - } - ScriptPodVec::Vec4i | ScriptPodVec::Vec4u => { - return NumericValue::Vec4(Vec4f { - x: pod_data.data[0] as f32, - y: pod_data.data[1] as f32, - z: pod_data.data[2] as f32, - w: pod_data.data[3] as f32, - }); - } - _ => {} - } - } - ScriptPodTy::Mat(m) => { - if let ScriptPodMat::Mat4x4f = m { - let mut mat = [0.0f32; 16]; - for i in 0..16 { - mat[i] = f32::from_bits(pod_data.data[i]); - } - return NumericValue::Mat4(mat); - } - } - _ => {} - } - } - - // Fallback: cast to f64 - NumericValue::F64(heap.cast_to_f64(value, ip)) - } - - /// Convert back to ScriptValue (heap + code version) - pub fn to_script_value_heap(self, heap: &mut ScriptHeap, code: &ScriptCode) -> ScriptValue { - match self { - NumericValue::F64(f) => ScriptValue::from_f64(f), - NumericValue::Vec2(v) => { - let pod = heap.new_pod(code.builtins.pod.pod_vec2f); - let pod_data = &mut heap.pods[pod]; - pod_data.data[0] = v.x.to_bits(); - pod_data.data[1] = v.y.to_bits(); - pod.into() - } - NumericValue::Vec3(v) => { - let pod = heap.new_pod(code.builtins.pod.pod_vec3f); - let pod_data = &mut heap.pods[pod]; - pod_data.data[0] = v.x.to_bits(); - pod_data.data[1] = v.y.to_bits(); - pod_data.data[2] = v.z.to_bits(); - pod.into() - } - NumericValue::Vec4(v) => { - let pod = heap.new_pod(code.builtins.pod.pod_vec4f); - let pod_data = &mut heap.pods[pod]; - pod_data.data[0] = v.x.to_bits(); - pod_data.data[1] = v.y.to_bits(); - pod_data.data[2] = v.z.to_bits(); - pod_data.data[3] = v.w.to_bits(); - pod.into() - } - NumericValue::Color(v) => ScriptValue::from_color(v.to_u32()), - NumericValue::Mat4(m) => { - let pod = heap.new_pod(code.builtins.pod.pod_mat4x4f); - let pod_data = &mut heap.pods[pod]; - for i in 0..16 { - pod_data.data[i] = m[i].to_bits(); - } - pod.into() - } - } - } - - /// Apply a unary f32 operation component-wise - pub fn map_f32 f32>(self, f: F) -> Self { - match self { - NumericValue::F64(v) => NumericValue::F64(f(v as f32) as f64), - NumericValue::Vec2(v) => NumericValue::Vec2(Vec2f { - x: f(v.x), - y: f(v.y), - }), - NumericValue::Vec3(v) => NumericValue::Vec3(Vec3f { - x: f(v.x), - y: f(v.y), - z: f(v.z), - }), - NumericValue::Vec4(v) => NumericValue::Vec4(Vec4f { - x: f(v.x), - y: f(v.y), - z: f(v.z), - w: f(v.w), - }), - NumericValue::Color(v) => NumericValue::Color(Vec4f { - x: f(v.x), - y: f(v.y), - z: f(v.z), - w: f(v.w), - }), - NumericValue::Mat4(m) => { - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = f(m[i]); - } - NumericValue::Mat4(result) - } - } - } - - /// Apply a binary f32 operation component-wise with proper type promotion - /// This handles +, -, and component-wise * and / - pub fn zip_f32 f32>(self, other: Self, f: F) -> Self { - match (self, other) { - // Same types - (NumericValue::F64(a), NumericValue::F64(b)) => { - NumericValue::F64(f(a as f32, b as f32) as f64) - } - (NumericValue::Vec2(a), NumericValue::Vec2(b)) => NumericValue::Vec2(Vec2f { - x: f(a.x, b.x), - y: f(a.y, b.y), - }), - (NumericValue::Vec3(a), NumericValue::Vec3(b)) => NumericValue::Vec3(Vec3f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - }), - (NumericValue::Vec4(a), NumericValue::Vec4(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, b.w), - }), - (NumericValue::Color(a), NumericValue::Color(b)) => NumericValue::Color(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, b.w), - }), - (NumericValue::Mat4(a), NumericValue::Mat4(b)) => { - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = f(a[i], b[i]); - } - NumericValue::Mat4(result) - } - - // Scalar * Vec -> Vec (broadcast) - (NumericValue::F64(a), NumericValue::Vec2(b)) => { - let a = a as f32; - NumericValue::Vec2(Vec2f { - x: f(a, b.x), - y: f(a, b.y), - }) - } - (NumericValue::Vec2(a), NumericValue::F64(b)) => { - let b = b as f32; - NumericValue::Vec2(Vec2f { - x: f(a.x, b), - y: f(a.y, b), - }) - } - (NumericValue::F64(a), NumericValue::Vec3(b)) => { - let a = a as f32; - NumericValue::Vec3(Vec3f { - x: f(a, b.x), - y: f(a, b.y), - z: f(a, b.z), - }) - } - (NumericValue::Vec3(a), NumericValue::F64(b)) => { - let b = b as f32; - NumericValue::Vec3(Vec3f { - x: f(a.x, b), - y: f(a.y, b), - z: f(a.z, b), - }) - } - (NumericValue::F64(a), NumericValue::Vec4(b)) => { - let a = a as f32; - NumericValue::Vec4(Vec4f { - x: f(a, b.x), - y: f(a, b.y), - z: f(a, b.z), - w: f(a, b.w), - }) - } - (NumericValue::Vec4(a), NumericValue::F64(b)) => { - let b = b as f32; - NumericValue::Vec4(Vec4f { - x: f(a.x, b), - y: f(a.y, b), - z: f(a.z, b), - w: f(a.w, b), - }) - } - - // Scalar * Color -> Color (broadcast) - (NumericValue::F64(a), NumericValue::Color(b)) => { - let a = a as f32; - NumericValue::Color(Vec4f { - x: f(a, b.x), - y: f(a, b.y), - z: f(a, b.z), - w: f(a, b.w), - }) - } - (NumericValue::Color(a), NumericValue::F64(b)) => { - let b = b as f32; - NumericValue::Color(Vec4f { - x: f(a.x, b), - y: f(a.y, b), - z: f(a.z, b), - w: f(a.w, b), - }) - } - - // Scalar * Mat -> Mat (broadcast) - (NumericValue::F64(a), NumericValue::Mat4(b)) => { - let a = a as f32; - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = f(a, b[i]); - } - NumericValue::Mat4(result) - } - (NumericValue::Mat4(a), NumericValue::F64(b)) => { - let b = b as f32; - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = f(a[i], b); - } - NumericValue::Mat4(result) - } - - // Vec4 <-> Color operations preserve the first operand's type - (NumericValue::Vec4(a), NumericValue::Color(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, b.w), - }), - (NumericValue::Color(a), NumericValue::Vec4(b)) => NumericValue::Color(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, b.w), - }), - - // Mixed Vec sizes - use larger type - (NumericValue::Vec2(a), NumericValue::Vec3(b)) => NumericValue::Vec3(Vec3f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(0.0, b.z), - }), - (NumericValue::Vec3(a), NumericValue::Vec2(b)) => NumericValue::Vec3(Vec3f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, 0.0), - }), - (NumericValue::Vec2(a), NumericValue::Vec4(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(0.0, b.z), - w: f(0.0, b.w), - }), - (NumericValue::Vec4(a), NumericValue::Vec2(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, 0.0), - w: f(a.w, 0.0), - }), - (NumericValue::Vec3(a), NumericValue::Vec4(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(0.0, b.w), - }), - (NumericValue::Vec4(a), NumericValue::Vec3(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, 0.0), - }), - - // Vec <-> Color mixed - convert to vec4 style operation - (NumericValue::Vec2(a), NumericValue::Color(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(0.0, b.z), - w: f(0.0, b.w), - }), - (NumericValue::Color(a), NumericValue::Vec2(b)) => NumericValue::Color(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, 0.0), - w: f(a.w, 0.0), - }), - (NumericValue::Vec3(a), NumericValue::Color(b)) => NumericValue::Vec4(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(0.0, b.w), - }), - (NumericValue::Color(a), NumericValue::Vec3(b)) => NumericValue::Color(Vec4f { - x: f(a.x, b.x), - y: f(a.y, b.y), - z: f(a.z, b.z), - w: f(a.w, 0.0), - }), - - // Mat * Vec or Vec * Mat - for non-multiply ops, just return first operand - (NumericValue::Mat4(_), NumericValue::Vec4(_)) - | (NumericValue::Vec4(_), NumericValue::Mat4(_)) - | (NumericValue::Mat4(_), NumericValue::Vec3(_)) - | (NumericValue::Vec3(_), NumericValue::Mat4(_)) - | (NumericValue::Mat4(_), NumericValue::Vec2(_)) - | (NumericValue::Vec2(_), NumericValue::Mat4(_)) - | (NumericValue::Mat4(_), NumericValue::Color(_)) - | (NumericValue::Color(_), NumericValue::Mat4(_)) => self, - } - } - - /// Multiply operation with proper matrix-vector semantics - pub fn multiply(self, other: Self) -> Self { - match (self, other) { - // Mat4 * Vec4 -> Vec4 (matrix-vector multiplication) - (NumericValue::Mat4(m), NumericValue::Vec4(v)) => { - NumericValue::Vec4(mat4_mul_vec4(&m, &v)) - } - // Vec4 * Mat4 -> Vec4 (vector-matrix multiplication, treats vector as row) - (NumericValue::Vec4(v), NumericValue::Mat4(m)) => { - NumericValue::Vec4(vec4_mul_mat4(&v, &m)) - } - // Mat4 * Mat4 -> Mat4 (matrix multiplication) - (NumericValue::Mat4(a), NumericValue::Mat4(b)) => { - NumericValue::Mat4(mat4_mul_mat4(&a, &b)) - } - // Mat4 * Vec3 -> Vec3 (treat as Vec4 with w=1, return xyz) - (NumericValue::Mat4(m), NumericValue::Vec3(v)) => { - let v4 = Vec4f { - x: v.x, - y: v.y, - z: v.z, - w: 1.0, - }; - let result = mat4_mul_vec4(&m, &v4); - NumericValue::Vec3(Vec3f { - x: result.x, - y: result.y, - z: result.z, - }) - } - // Vec3 * Mat4 -> Vec3 - (NumericValue::Vec3(v), NumericValue::Mat4(m)) => { - let v4 = Vec4f { - x: v.x, - y: v.y, - z: v.z, - w: 1.0, - }; - let result = vec4_mul_mat4(&v4, &m); - NumericValue::Vec3(Vec3f { - x: result.x, - y: result.y, - z: result.z, - }) - } - // Mat4 * Color -> Color (treat as Vec4) - (NumericValue::Mat4(m), NumericValue::Color(c)) => { - NumericValue::Color(mat4_mul_vec4(&m, &c)) - } - // Color * Mat4 -> Color - (NumericValue::Color(c), NumericValue::Mat4(m)) => { - NumericValue::Color(vec4_mul_mat4(&c, &m)) - } - // Mat4 * scalar -> Mat4 (component-wise) - (NumericValue::Mat4(m), NumericValue::F64(s)) => { - let s = s as f32; - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = m[i] * s; - } - NumericValue::Mat4(result) - } - // scalar * Mat4 -> Mat4 - (NumericValue::F64(s), NumericValue::Mat4(m)) => { - let s = s as f32; - let mut result = [0.0f32; 16]; - for i in 0..16 { - result[i] = s * m[i]; - } - NumericValue::Mat4(result) - } - // All other cases: component-wise multiplication - _ => self.zip_f32(other, |a, b| a * b), - } - } - - /// Mix two values with a scalar alpha - pub fn mix_scalar(self, other: Self, alpha: f64) -> Self { - let a = alpha as f32; - let one_minus_a = 1.0 - a; - match (self, other) { - (NumericValue::F64(x), NumericValue::F64(y)) => { - NumericValue::F64((x as f32 * one_minus_a + y as f32 * a) as f64) - } - (NumericValue::Vec2(x), NumericValue::Vec2(y)) => NumericValue::Vec2(Vec2f { - x: x.x * one_minus_a + y.x * a, - y: x.y * one_minus_a + y.y * a, - }), - (NumericValue::Vec3(x), NumericValue::Vec3(y)) => NumericValue::Vec3(Vec3f { - x: x.x * one_minus_a + y.x * a, - y: x.y * one_minus_a + y.y * a, - z: x.z * one_minus_a + y.z * a, - }), - (NumericValue::Vec4(x), NumericValue::Vec4(y)) => NumericValue::Vec4(Vec4f { - x: x.x * one_minus_a + y.x * a, - y: x.y * one_minus_a + y.y * a, - z: x.z * one_minus_a + y.z * a, - w: x.w * one_minus_a + y.w * a, - }), - (NumericValue::Color(x), NumericValue::Color(y)) => NumericValue::Color(Vec4f { - x: x.x * one_minus_a + y.x * a, - y: x.y * one_minus_a + y.y * a, - z: x.z * one_minus_a + y.z * a, - w: x.w * one_minus_a + y.w * a, - }), - // Fallback - _ => self, - } - } - - /// Mix two values with component-wise alpha (alpha has same type as self/other) - pub fn mix_componentwise(self, other: Self, alpha: Self) -> Self { - match (self, other, alpha) { - (NumericValue::F64(x), NumericValue::F64(y), NumericValue::F64(a)) => { - let a = a as f32; - NumericValue::F64((x as f32 * (1.0 - a) + y as f32 * a) as f64) - } - (NumericValue::Vec2(x), NumericValue::Vec2(y), NumericValue::Vec2(a)) => { - NumericValue::Vec2(Vec2f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - }) - } - (NumericValue::Vec3(x), NumericValue::Vec3(y), NumericValue::Vec3(a)) => { - NumericValue::Vec3(Vec3f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - }) - } - (NumericValue::Vec4(x), NumericValue::Vec4(y), NumericValue::Vec4(a)) => { - NumericValue::Vec4(Vec4f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - w: x.w * (1.0 - a.w) + y.w * a.w, - }) - } - (NumericValue::Color(x), NumericValue::Color(y), NumericValue::Color(a)) => { - NumericValue::Color(Vec4f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - w: x.w * (1.0 - a.w) + y.w * a.w, - }) - } - // Fallback: treat alpha as scalar using its first component - _ => { - let a_f = match alpha { - NumericValue::F64(v) => v, - NumericValue::Vec2(v) => v.x as f64, - NumericValue::Vec3(v) => v.x as f64, - NumericValue::Vec4(v) => v.x as f64, - NumericValue::Color(v) => v.x as f64, - NumericValue::Mat4(_) => 0.5, - }; - self.mix_scalar(other, a_f) - } - } - } - - /// Clamp with scalar min/max - pub fn clamp_scalar(self, min_val: f64, max_val: f64) -> Self { - let min_f = min_val as f32; - let max_f = max_val as f32; - self.map_f32(|v| v.max(min_f).min(max_f)) - } - - /// Step function with scalar edge - pub fn step_scalar(edge: f64, self_val: Self) -> Self { - let edge_f = edge as f32; - self_val.map_f32(|v| if v < edge_f { 0.0 } else { 1.0 }) - } - - /// Smoothstep with scalar edges - pub fn smoothstep_scalar(e0: f64, e1: f64, self_val: Self) -> Self { - let e0_f = e0 as f32; - let e1_f = e1 as f32; - self_val.map_f32(|x| { - let t = ((x - e0_f) / (e1_f - e0_f)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) - }) - } - - /// Get the length (magnitude) of a vector, or absolute value for scalar - pub fn length(&self) -> f64 { - match self { - NumericValue::F64(v) => v.abs(), - NumericValue::Vec2(v) => (v.x * v.x + v.y * v.y).sqrt() as f64, - NumericValue::Vec3(v) => (v.x * v.x + v.y * v.y + v.z * v.z).sqrt() as f64, - NumericValue::Vec4(v) => (v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w).sqrt() as f64, - NumericValue::Color(v) => (v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w).sqrt() as f64, - NumericValue::Mat4(_) => 0.0, // undefined for matrices - } - } - - /// Dot product (returns scalar) - pub fn dot(self, other: Self) -> f64 { - match (self, other) { - (NumericValue::F64(a), NumericValue::F64(b)) => a * b, - (NumericValue::Vec2(a), NumericValue::Vec2(b)) => (a.x * b.x + a.y * b.y) as f64, - (NumericValue::Vec3(a), NumericValue::Vec3(b)) => { - (a.x * b.x + a.y * b.y + a.z * b.z) as f64 - } - (NumericValue::Vec4(a), NumericValue::Vec4(b)) => { - (a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w) as f64 - } - (NumericValue::Color(a), NumericValue::Color(b)) => { - (a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w) as f64 - } - _ => 0.0, // Mismatched types - } - } - - /// Normalize a vector (returns unit vector in same direction) - pub fn normalize(self) -> Self { - let len = self.length() as f32; - if len == 0.0 { - return self; - } - let inv_len = 1.0 / len; - match self { - NumericValue::F64(v) => NumericValue::F64(if v >= 0.0 { 1.0 } else { -1.0 }), - NumericValue::Vec2(v) => NumericValue::Vec2(Vec2f { - x: v.x * inv_len, - y: v.y * inv_len, - }), - NumericValue::Vec3(v) => NumericValue::Vec3(Vec3f { - x: v.x * inv_len, - y: v.y * inv_len, - z: v.z * inv_len, - }), - NumericValue::Vec4(v) => NumericValue::Vec4(Vec4f { - x: v.x * inv_len, - y: v.y * inv_len, - z: v.z * inv_len, - w: v.w * inv_len, - }), - NumericValue::Color(v) => NumericValue::Color(Vec4f { - x: v.x * inv_len, - y: v.y * inv_len, - z: v.z * inv_len, - w: v.w * inv_len, - }), - NumericValue::Mat4(m) => NumericValue::Mat4(m), // undefined for matrices - } - } - - /// Cross product (only defined for Vec3) - pub fn cross(self, other: Self) -> Self { - match (self, other) { - (NumericValue::Vec3(a), NumericValue::Vec3(b)) => NumericValue::Vec3(Vec3f { - x: a.y * b.z - a.z * b.y, - y: a.z * b.x - a.x * b.z, - z: a.x * b.y - a.y * b.x, - }), - _ => self.zero_like(), // Undefined for other types - } - } - - /// Create a zero value of the same type - pub fn zero_like(&self) -> Self { - match self { - NumericValue::F64(_) => NumericValue::F64(0.0), - NumericValue::Vec2(_) => NumericValue::Vec2(Vec2f { x: 0.0, y: 0.0 }), - NumericValue::Vec3(_) => NumericValue::Vec3(Vec3f { - x: 0.0, - y: 0.0, - z: 0.0, - }), - NumericValue::Vec4(_) => NumericValue::Vec4(Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }), - NumericValue::Color(_) => NumericValue::Color(Vec4f { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }), - NumericValue::Mat4(_) => NumericValue::Mat4([0.0; 16]), - } - } -} - -/// Matrix-vector multiplication: M * v (column vector) -/// Matrix is in column-major order -#[inline] -pub fn mat4_mul_vec4(m: &[f32; 16], v: &Vec4f) -> Vec4f { - Vec4f { - x: m[0] * v.x + m[4] * v.y + m[8] * v.z + m[12] * v.w, - y: m[1] * v.x + m[5] * v.y + m[9] * v.z + m[13] * v.w, - z: m[2] * v.x + m[6] * v.y + m[10] * v.z + m[14] * v.w, - w: m[3] * v.x + m[7] * v.y + m[11] * v.z + m[15] * v.w, - } -} - -/// Vector-matrix multiplication: v * M (row vector) -/// Matrix is in column-major order -#[inline] -pub fn vec4_mul_mat4(v: &Vec4f, m: &[f32; 16]) -> Vec4f { - Vec4f { - x: v.x * m[0] + v.y * m[1] + v.z * m[2] + v.w * m[3], - y: v.x * m[4] + v.y * m[5] + v.z * m[6] + v.w * m[7], - z: v.x * m[8] + v.y * m[9] + v.z * m[10] + v.w * m[11], - w: v.x * m[12] + v.y * m[13] + v.z * m[14] + v.w * m[15], - } -} - -/// Matrix-matrix multiplication: A * B -/// Both matrices in column-major order -#[inline] -pub fn mat4_mul_mat4(a: &[f32; 16], b: &[f32; 16]) -> [f32; 16] { - let mut result = [0.0f32; 16]; - for col in 0..4 { - for row in 0..4 { - let mut sum = 0.0f32; - for k in 0..4 { - sum += a[k * 4 + row] * b[col * 4 + k]; - } - result[col * 4 + row] = sum; - } - } - result -} diff --git a/vendor/makepad/platform/script/src/object.rs b/vendor/makepad/platform/script/src/object.rs deleted file mode 100644 index 2be30a4..0000000 --- a/vendor/makepad/platform/script/src/object.rs +++ /dev/null @@ -1,1165 +0,0 @@ -use crate::function::*; -use crate::heap::*; -use crate::makepad_live_id::*; -use crate::mod_shader::ShaderIoType; -use crate::native::*; -use crate::traits::*; -use crate::value::*; -use crate::value_map::*; -use crate::*; -use ::std::cell::RefCell; -use ::std::collections::hash_map::Entry; -use ::std::collections::HashMap; -use ::std::fmt; -use ::std::mem::size_of; -use ::std::rc::Rc; -//use std::collections::btree_map::BTreeMap; - -#[derive(Default)] -pub struct ScriptObjectTag(u64); - -pub type ScriptObjectMap = ValueMap; - -pub struct ScriptObjectRef { - pub(crate) roots: Option>>>, - pub(crate) obj: ScriptObject, -} - -impl ScriptObjectRef { - pub fn is_zero(&self) -> bool { - self.obj == ScriptObject::ZERO - } -} - -impl Default for ScriptObjectRef { - fn default() -> Self { - Self { - roots: None, - obj: ScriptObject::ZERO, - } - } -} - -impl Clone for ScriptObjectRef { - fn clone(&self) -> Self { - if let Some(roots) = &self.roots { - let mut roots = roots.borrow_mut(); - match roots.entry(self.obj) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - *value += 1; - } - Entry::Vacant(_vac) => { - eprintln!("ScriptObjectRef root is vacant!"); - } - } - } - Self { - roots: self.roots.clone(), - obj: self.obj.clone(), - } - } -} - -impl From for ScriptValue { - fn from(v: ScriptObjectRef) -> Self { - ScriptValue::from_object(v.as_object()) - } -} - -impl ScriptObjectRef { - pub fn as_object(&self) -> ScriptObject { - self.obj - } - - /// A stable, unique identity for the heap that minted this ref. All refs from - /// the same heap share one `root_objects` `Rc`, so its pointer identifies the - /// heap for the heap's lifetime. Returns 0 for a heap-less (empty) ref. Use - /// this to route a widget's script objects back to their owning VM instead of - /// dereferencing them against the wrong heap. - pub fn heap_key(&self) -> usize { - self.roots - .as_ref() - .map_or(0, |rc| Rc::as_ptr(rc) as *const () as usize) - } -} - -pub trait ScriptRefOptionExt { - fn as_object(&self) -> Option; -} -impl ScriptRefOptionExt for Option { - fn as_object(&self) -> Option { - if let Some(x) = self { - Some(x.as_object()) - } else { - None - } - } -} - -impl Drop for ScriptObjectRef { - fn drop(&mut self) { - if let Some(roots) = &self.roots { - let mut roots = roots.borrow_mut(); - match roots.entry(self.obj) { - Entry::Occupied(mut occ) => { - let value = occ.get_mut(); - if *value >= 1 { - *value -= 1; - } else { - eprintln!("ScriptObjectRef is 0!"); - } - if *value == 0 { - occ.remove(); - } - } - Entry::Vacant(_vac) => { - eprintln!("ScriptObjectRef root is vacant!"); - } - } - } - } -} - -impl ScriptObjectTag { - // marked in the mark-sweep gc - pub const MARK: u64 = 0x1 << 40; - // object is not 'free' - pub const ALLOCED: u64 = 0x2 << 40; - // object is 'deep' aka writes to protochain - pub const DEEP: u64 = 0x4 << 40; - // make the map tracked - pub const TRACKED: u64 = 0x8 << 40; - // used to quick-free objects if not set - pub const REFFED: u64 = 0x10 << 40; - // object is skipped in gc passes - pub const STATIC: u64 = 0x20 << 40; - // object dirty - pub const DIRTY: u64 = 0x40 << 40; - - // set when the object has been first applied - pub const FIRST_APPLIED: u64 = 0x80 << 40; - // marks object readonly - pub const FROZEN: u64 = 0x100 << 40; - // checks base types against prototype - pub const VALIDATED: u64 = 0x200 << 40; - // for read only allow writes only if map item doesnt exist - pub const MAP_ADD: u64 = 0x400 << 40; - // vec is frozen - pub const VEC_FROZEN: u64 = 0x800 << 40; - // type checked - pub const TYPE_CHECKED: u64 = 0x1000 << 40; - // cant be a prototype - pub const NOTPROTO: u64 = 0x2000 << 40; - // automatically convert between id and string keys when looking up - pub const STRING_KEYS: u64 = 0x4000 << 40; - - pub const FROM_EVAL: u64 = 0x8000 << 40; - - pub const FREEZE_MASK: u64 = Self::FROZEN | Self::VALIDATED | Self::MAP_ADD | Self::VEC_FROZEN; - - const PROTO_FWD: u64 = Self::ALLOCED - | Self::DEEP - | Self::STORAGE_MASK - | Self::VALIDATED - | Self::MAP_ADD - | Self::VEC_FROZEN - | Self::TRACKED - | Self::REF_KIND_MASK - | Self::REF_DATA_MASK - | Self::TYPE_CHECKED; - - pub const NEED_CHECK_MASK: u64 = Self::FREEZE_MASK | Self::TYPE_CHECKED; - - pub const FLAG_MASK: u64 = 0x3FFFF << 40; - - pub const REF_KIND_SCRIPT_FN: u64 = 0x1 << 58; - pub const REF_KIND_NATIVE_FN: u64 = 0x2 << 58; - pub const REF_KIND_TYPE_INDEX: u64 = 0x3 << 58; - pub const REF_KIND_POD_TYPE: u64 = 0x4 << 58; - pub const REF_KIND_SHADER_IO: u64 = 0x5 << 58; - pub const REF_KIND_APPLY_TRANSFORM: u64 = 0x6 << 58; - pub const REF_KIND_MASK: u64 = 0xF << 58; - pub const REF_DATA_MASK: u64 = 0xFF_FFFF_FFFF; - - pub const STORAGE_SHIFT: u64 = 62; - pub const STORAGE_MASK: u64 = 0x3 << Self::STORAGE_SHIFT; - - pub const STORAGE_AUTO: u64 = 0 << Self::STORAGE_SHIFT; - pub const STORAGE_VEC2: u64 = 1 << Self::STORAGE_SHIFT; - pub const STORAGE_MAP: u64 = 2 << Self::STORAGE_SHIFT; - - pub fn proto_fwd(&self) -> u64 { - self.0 & Self::PROTO_FWD - } - - pub fn set_proto_fwd(&mut self, fwd: u64) { - self.0 = (self.0 & !Self::PROTO_FWD) | (fwd & Self::PROTO_FWD) - } - - // STORAGE - - pub fn is_auto(&self) -> bool { - self.0 & Self::STORAGE_MASK == Self::STORAGE_AUTO - } - - pub fn is_vec2(&self) -> bool { - self.0 & Self::STORAGE_MASK == Self::STORAGE_VEC2 - } - - pub fn is_map(&self) -> bool { - self.0 & Self::STORAGE_MASK == Self::STORAGE_MAP - } - - pub fn set_vec2(&mut self) { - self.0 &= !Self::STORAGE_MASK; - self.0 |= Self::STORAGE_VEC2; - } - - pub fn set_auto(&mut self) { - self.0 &= !Self::STORAGE_MASK; - } - - pub fn set_map(&mut self) { - self.0 &= !Self::STORAGE_MASK; - self.0 |= Self::STORAGE_MAP; - } - - // FLAGS - - pub fn set_first_applied_and_clean(&mut self) { - self.0 &= !Self::DIRTY; - self.0 |= Self::FIRST_APPLIED; - } - - pub fn is_first_applied(&self) -> bool { - self.0 & Self::FIRST_APPLIED != 0 - } - - pub fn set_tracked(&mut self) { - self.0 |= Self::TRACKED - } - - pub fn is_tracked(&self) -> bool { - self.0 & Self::TRACKED != 0 - } - - pub fn set_dirty(&mut self) { - self.0 |= Self::DIRTY - } - - pub fn check_and_clear_dirty(&mut self) -> bool { - if self.0 & Self::DIRTY != 0 { - self.0 &= !Self::DIRTY; - true - } else { - false - } - } - - pub fn set_string_keys(&mut self) { - self.0 |= Self::STRING_KEYS - } - - pub fn is_string_keys(&self) -> bool { - self.0 & Self::STRING_KEYS != 0 - } - - pub fn set_from_eval(&mut self) { - self.0 |= Self::FROM_EVAL - } - - pub fn is_from_eval(&self) -> bool { - self.0 & Self::FROM_EVAL != 0 - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } - - pub fn is_notproto(&self) -> bool { - self.0 & Self::NOTPROTO != 0 - } - - pub fn set_notproto(&mut self) { - self.0 |= Self::NOTPROTO - } - - pub fn is_frozen(&self) -> bool { - self.0 & Self::FROZEN != 0 - } - - /// Check if object is immutable (either frozen or static) - /// Static objects are GC-permanent and should not be modified - #[inline(always)] - pub fn is_immutable(&self) -> bool { - self.0 & (Self::FROZEN | Self::STATIC) != 0 - } - - pub fn is_validated(&self) -> bool { - self.0 & Self::VALIDATED != 0 - } - - pub fn is_map_add(&self) -> bool { - self.0 & Self::MAP_ADD != 0 - } - - pub fn set_reffed(&mut self) { - self.0 |= Self::REFFED - } - - pub fn is_reffed(&self) -> bool { - self.0 & Self::REFFED != 0 - } - - pub fn set_deep(&mut self) { - self.0 |= Self::DEEP - } - - pub fn clear_deep(&mut self) { - self.0 &= !Self::DEEP - } - - pub fn is_deep(&self) -> bool { - self.0 & Self::DEEP != 0 - } - - pub fn is_alloced(&self) -> bool { - return self.0 & Self::ALLOCED != 0; - } - - pub fn set_alloced(&mut self) { - self.0 |= Self::ALLOCED - } - - pub fn clear(&mut self) { - self.0 = 0; - } - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - // FREEZE - - pub fn freeze(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN - } - - pub fn freeze_type(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN | Self::VEC_FROZEN - } - - pub fn freeze_api(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN | Self::VALIDATED | Self::VEC_FROZEN - } - - pub fn freeze_module(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::MAP_ADD | Self::VEC_FROZEN | Self::NOTPROTO - } - - pub fn freeze_component(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN | Self::VALIDATED - } - - pub fn freeze_shader(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN | Self::VALIDATED | Self::MAP_ADD | Self::VEC_FROZEN - } - - pub fn freeze_ext(&mut self) { - self.0 &= !(Self::FREEZE_MASK); - self.0 |= Self::FROZEN | Self::VALIDATED | Self::MAP_ADD - } - - pub fn needs_checking(&self) -> bool { - self.0 & (Self::NEED_CHECK_MASK) != 0 - } - - pub fn is_vec_frozen(&self) -> bool { - self.0 & (Self::VEC_FROZEN | Self::FROZEN | Self::STATIC) != 0 - } - - // REF - - pub fn set_type_index(&mut self, ty: ScriptTypeIndex) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - self.0 |= ty.0 as u64 | Self::REF_KIND_TYPE_INDEX | Self::TYPE_CHECKED; - } - - pub fn as_type_index(&self) -> Option { - if self.is_type_index() { - Some(ScriptTypeIndex(self.0 as u32)) - } else { - None - } - } - - pub fn is_type_index(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_TYPE_INDEX - } - - pub fn set_apply_transform(&mut self, ni: NativeId) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - self.0 |= (ni.index as u64) | Self::REF_KIND_APPLY_TRANSFORM; - } - - pub fn as_apply_transform(&self) -> Option { - if self.0 & Self::REF_KIND_MASK == Self::REF_KIND_APPLY_TRANSFORM { - Some(NativeId { - index: self.0 as u32, - }) - } else { - None - } - } - - pub fn is_apply_transform(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_APPLY_TRANSFORM - } - - pub fn set_fn(&mut self, ptr: ScriptFnPtr) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - match ptr { - ScriptFnPtr::Script(ip) => self.0 |= ip.to_u40() | Self::REF_KIND_SCRIPT_FN, - ScriptFnPtr::Native(ni) => self.0 |= (ni.index as u64) | Self::REF_KIND_NATIVE_FN, - } - } - - pub fn as_fn(&self) -> Option { - if self.0 & Self::REF_KIND_MASK == Self::REF_KIND_SCRIPT_FN { - Some(ScriptFnPtr::Script(ScriptIp::from_u40(self.0))) - } else if self.0 & Self::REF_KIND_MASK == Self::REF_KIND_NATIVE_FN { - Some(ScriptFnPtr::Native(NativeId { - index: self.0 as u32, - })) - } else { - None - } - } - - pub fn is_script_fn(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_SCRIPT_FN - } - - pub fn is_native_fn(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_NATIVE_FN - } - - pub fn is_fn(&self) -> bool { - self.is_script_fn() || self.is_native_fn() - } - - pub fn set_pod_type(&mut self, ty: ScriptPodType) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - self.0 |= ty.index as u64 | Self::REF_KIND_POD_TYPE - } - - pub fn as_pod_type(&self) -> Option { - if self.is_pod_type() { - Some(ScriptPodType { - index: self.0 as u32, - }) - } else { - None - } - } - - pub fn is_pod_type(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_POD_TYPE - } - - pub fn set_shader_io(&mut self, ty: ShaderIoType) { - self.0 &= !(Self::REF_DATA_MASK); - self.0 &= !(Self::REF_KIND_MASK); - self.0 |= ty.0 as u64 | Self::REF_KIND_SHADER_IO - } - - pub fn as_shader_io(&self) -> Option { - if self.is_shader_io() { - Some(ShaderIoType(self.0 as u32)) - } else { - None - } - } - - pub fn is_shader_io(&self) -> bool { - self.0 & Self::REF_KIND_MASK == Self::REF_KIND_SHADER_IO - } -} - -impl fmt::Debug for ScriptObjectTag { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for ScriptObjectTag { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ObjectType(").ok(); - if self.is_vec2() { - write!(f, "STORAGE_VEC2|").ok(); - } - if self.is_auto() { - write!(f, "STORAGE_AUTO|").ok(); - } - if self.is_map() { - write!(f, "STORAGE_MAP|").ok(); - } - if self.is_marked() { - write!(f, "MARK|").ok(); - } - if self.is_alloced() { - write!(f, "ALLOCED|").ok(); - } - if self.is_deep() { - write!(f, "DEEP|").ok(); - } - if self.is_script_fn() { - write!(f, "SCRIPT_FN({:?})|", self.as_fn().unwrap()).ok(); - } - if self.is_native_fn() { - write!(f, "NATIVE_FN({:?})|", self.as_fn().unwrap()).ok(); - } - if self.is_reffed() { - write!(f, "REFFED|").ok(); - } - if self.is_frozen() { - write!(f, "FROZEN|").ok(); - } - if self.is_vec_frozen() { - write!(f, "VEC_FROZEN|").ok(); - } - if self.is_validated() { - write!(f, "VALIDATED|").ok(); - } - if self.is_map_add() { - write!(f, "MAP_ADD|").ok(); - } - if self.is_script_fn() { - write!(f, "SCRIPT_FN|").ok(); - } - if self.is_native_fn() { - write!(f, "NATIVE_FN|").ok(); - } - - write!(f, ")") - } -} - -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] -pub struct ScriptMapTag(u64); - -impl ScriptMapTag { - // Lower 32 bits store insertion order - const ORDER_MASK: u64 = 0xFFFF_FFFF; - // Bit 33 (index 32) stores the dirty flag - const DIRTY: u64 = 1 << 32; - - #[allow(dead_code)] - fn dirty() -> Self { - Self(Self::DIRTY) - } - - fn dirty_with_order(order: u32) -> Self { - Self(Self::DIRTY | (order as u64)) - } - - fn get_and_clear_dirty(&mut self) -> bool { - let ret = self.0 & Self::DIRTY != 0; - self.0 &= !Self::DIRTY; - ret - } - - fn set_dirty(&mut self) { - self.0 |= Self::DIRTY; - } - - pub fn order(&self) -> u32 { - (self.0 & Self::ORDER_MASK) as u32 - } - - #[allow(dead_code)] - fn set_order(&mut self, order: u32) { - self.0 = (self.0 & !Self::ORDER_MASK) | (order as u64); - } - - fn with_order_offset(self, offset: u32) -> Self { - let new_order = self.order() + offset; - Self((self.0 & !Self::ORDER_MASK) | (new_order as u64)) - } -} - -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] -pub struct ScriptMapValue { - pub tag: ScriptMapTag, - pub value: ScriptValue, -} - -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] -pub struct ScriptVecValue { - pub key: ScriptValue, - pub value: ScriptValue, -} - -#[derive(Default, Debug)] -pub struct ScriptObjectData { - pub tag: ScriptObjectTag, - pub proto: ScriptValue, - pub map: ScriptObjectMap, - pub vec: Vec, -} - -impl ScriptObjectData { - const MAP_GROWTH_CAPACITY_FLOOR: usize = 8; - const MAP_GROWTH_CAPACITY_MULTIPLIER: usize = 4; - - fn map_entry_bytes() -> usize { - size_of::<(ScriptValue, ScriptMapValue)>() - .saturating_add(size_of::().saturating_mul(2)) - .saturating_add(1) - } - - /// Backing allocation retained by this object's dynamic property storage. - /// - /// HashMap's public API does not expose allocator bytes, so the accounting - /// model charges a conservative per-bucket control allowance in addition - /// to the key/value payload. - pub(crate) fn retained_bytes(&self) -> usize { - self.map - .capacity() - .saturating_mul(Self::map_entry_bytes()) - .saturating_add( - self.vec - .capacity() - .saturating_mul(size_of::()), - ) - } - - /// Conservative retained capacity needed before inserting a new map key. - /// - /// `HashMap` does not expose the exact size of its next rehash. When the - /// current table is full, reserve four times the visible capacity (with a - /// small initial floor) before allowing the insertion. That is deliberately - /// larger than the standard table's geometric growth so a generated key - /// cannot request a rehash after the heap cap has already rejected it. - /// Post-insert accounting remains in place as a backstop for implementation - /// changes in the underlying map. - pub(crate) fn anticipated_retained_bytes_after_map_insert( - &self, - key: ScriptValue, - ) -> Option { - let map_capacity = if self.map.contains_key(&key) || self.map.len() < self.map.capacity() { - self.map.capacity() - } else { - self.map - .capacity() - .checked_mul(Self::MAP_GROWTH_CAPACITY_MULTIPLIER)? - .max(Self::MAP_GROWTH_CAPACITY_FLOOR) - }; - let map_bytes = map_capacity.checked_mul(Self::map_entry_bytes())?; - let vec_bytes = self - .vec - .capacity() - .checked_mul(size_of::())?; - map_bytes.checked_add(vec_bytes) - } - - /// Minimum bytes needed to represent a vector-style object through the - /// requested logical length. This deliberately uses length rather than a - /// guessed Vec growth factor so callers can reject impossible sparse - /// indexes before a resize attempts an allocation. - pub(crate) fn minimum_vec_bytes_for_len(length: usize) -> Option { - length.checked_mul(size_of::()) - } - - pub fn add_type_methods(native: &mut ScriptNative, heap: &mut ScriptHeap) { - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(proto), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - return vm.bx.heap.proto(sself); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "proto called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(push), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.vec_push_vec(sself, args, trap); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "push called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(pop), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.vec_pop(sself, trap).value; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "pop called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(len), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - return vm.bx.heap.vec_len(sself).into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "len called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(vec_len), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - return vm.bx.heap.vec_len(sself).into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "vec_len called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(map_len), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - return vm.bx.heap.map_len(sself).into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "map_len called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(delete), - script_args!(key = NIL), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - if vm.bx.heap.objects[sself].tag.is_immutable() { - return script_err_immutable!( - vm.bx.threads.cur_ref().trap, - "cannot delete from immutable object" - ); - } - let key = script_value!(vm, args.key); - if let Some(val) = vm.bx.heap.map_delete(sself, &key) { - return val; - } - return NIL; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "delete called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(vec_key), - script_args!(index = NIL), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let index = script_value!(vm, args.index); - let idx = index.as_index(); - let kv = vm - .bx - .heap - .vec_key_value(sself, idx, vm.bx.threads.cur().trap.pass()); - if let Some(id) = kv.key.as_id() { - return id.escape(); - } - return kv.key; - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "vec_key called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(gc_id), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - return sself.index().into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "gc_id called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(extend), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.vec_push_vec_of_vec(sself, args, false, trap); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "extend called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(splat), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let trap = vm.bx.threads.cur().trap.pass(); - return vm.bx.heap.vec_push_vec_of_vec(sself, args, true, trap); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "import called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(freeze), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - vm.bx.heap.freeze(sself); - return sself.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "freeze called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(freeze_api), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - vm.bx.heap.freeze_api(sself); - return sself.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "freeze_api called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(freeze_module), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - vm.bx.heap.freeze_module(sself); - return sself.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "freeze_module called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(freeze_component), - &[], - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - vm.bx.heap.freeze_component(sself); - return sself.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "freeze_component called on non-object value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_OBJECT, - id!(retain), - script_args!(cb = NIL), - |vm, args| { - if let Some(sself) = script_value!(vm, args.self).as_object() { - let fnptr = script_value!(vm, args.cb); - let mut i = 0; - while i < vm.bx.heap.vec_len(sself) { - let value = script_value!(vm, sself[i]); - let ret = vm.call(fnptr, &[value]); - if ret.is_err() { - return ret; - } - if !vm.bx.heap.cast_to_bool(ret) { - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx.heap.vec_remove(sself, i, trap); - } else { - i += 1 - } - } - return NIL; - } - script_err_not_impl!( - vm.bx.threads.cur_ref().trap, - "retain called on non-object value" - ) - }, - ); - } - - pub fn map_insert(&mut self, key: ScriptValue, value: ScriptValue) { - if self.tag.is_tracked() { - let order = self.map.len() as u32; - match self.map.entry(key) { - Entry::Occupied(mut occ) => { - let old = occ.get_mut(); - if old.value != value { - old.tag.set_dirty(); - self.tag.set_dirty(); - old.value = value; - } - return; - } - Entry::Vacant(vac) => { - vac.insert(ScriptMapValue { - value, - tag: ScriptMapTag::dirty_with_order(order), - }); - return; - } - } - } else { - if let Some(existing) = self.map.get_mut(&key) { - existing.value = value; - return; - } - let order = self.map.len() as u32; - self.map.insert( - key, - ScriptMapValue { - value, - tag: ScriptMapTag::dirty_with_order(order), - }, - ); - } - } - - pub fn map_set_if_exist(&mut self, key: ScriptValue, value: ScriptValue) -> bool { - if self.tag.is_tracked() { - match self.map.entry(key) { - Entry::Occupied(mut occ) => { - let old = occ.get_mut(); - if old.value != value { - old.tag.set_dirty(); - self.tag.set_dirty(); - old.value = value; - } - return true; - } - Entry::Vacant(_) => {} - } - } - if let Some(val) = self.map.get_mut(&key) { - val.value = value; - return true; - } - false - } - - pub fn map_get(&self, key: &ScriptValue) -> Option { - if let Some(val) = self.map.get(key) { - Some(val.value) - } else { - None - } - } - - pub fn map_get_if_dirty(&mut self, key: &ScriptValue) -> Option { - if self.tag.is_tracked() { - match self.map.entry(*key) { - Entry::Occupied(mut occ) => { - let val = occ.get_mut(); - if val.tag.get_and_clear_dirty() { - return Some(val.value); - } - return None; - } - Entry::Vacant(_) => return None, - }; - } - self.map_get(key) - } - - pub fn map_delete(&mut self, key: &ScriptValue) -> Option { - self.map.remove(key).map(|v| v.value) - } - - pub fn map_len(&self) -> usize { - self.map.len() - } - - pub fn map_iter_ret Option>( - &self, - mut f: F, - ) -> Option { - for (key, val) in self.map.iter() { - let r = f(*key, val.value); - if r.is_some() { - return r; - } - } - None - } - - pub fn map_iter(&self, mut f: F) { - for (key, val) in self.map.iter() { - f(*key, val.value); - } - } - - pub fn map_iter_ordered(&self, mut f: F) { - let mut ordered: Vec<_> = self.map.iter().collect(); - ordered.sort_by_key(|(_, val)| val.tag.order()); - for (key, val) in ordered { - f(*key, val.value); - } - } - - pub fn merge_map_from_other(&mut self, other: &ScriptObjectData) { - let offset = self.map.len() as u32; - for (k, v) in other.map.iter() { - self.map.insert( - *k, - ScriptMapValue { - value: v.value, - tag: v.tag.with_order_offset(offset), - }, - ); - } - } - - /// Merge map entries from other, but only if the key doesn't already exist in self. - /// Used by the splat operator to not overwrite existing values. - pub fn merge_map_from_other_no_overwrite(&mut self, other: &ScriptObjectData) { - let offset = self.map.len() as u32; - for (k, v) in other.map.iter() { - if !self.map.contains_key(k) { - self.map.insert( - *k, - ScriptMapValue { - value: v.value, - tag: v.tag.with_order_offset(offset), - }, - ); - } - } - } - - pub fn push_vec_from_other(&mut self, other: &ScriptObjectData) { - self.vec.extend_from_slice(&other.vec); - } - - //const DONT_RECYCLE_WHEN: usize = 1000; - pub fn with_proto(proto: ScriptValue) -> Self { - Self { - proto, - ..Default::default() - } - } - - pub fn clear(&mut self) { - self.proto = NIL; - self.tag.clear(); - self.map.clear(); - self.vec.clear(); - // Debug: verify clear worked - debug_assert!(self.map.is_empty(), "map.clear() didn't work!"); - } -} diff --git a/vendor/makepad/platform/script/src/object_heap.rs b/vendor/makepad/platform/script/src/object_heap.rs deleted file mode 100644 index c0eebdb..0000000 --- a/vendor/makepad/platform/script/src/object_heap.rs +++ /dev/null @@ -1,1365 +0,0 @@ -use crate::apply::Apply; -use crate::heap::*; -use crate::makepad_live_id::*; -use crate::mod_shader::ShaderIoType; -use crate::suggest::*; -use crate::traits::*; -use crate::trap::*; -use crate::value::*; -use crate::*; -use std::mem::size_of; - -impl ScriptHeap { - // New objects - - fn prepare_object_vec_growth( - &mut self, - object: ScriptObject, - requested_len: usize, - ) -> Option { - let before = self.objects[object] - .vec - .capacity() - .saturating_mul(size_of::()); - if self.max_heap_bytes.is_none() { - return Some(before); - } - let growth = ScriptObjectData::minimum_vec_bytes_for_len(requested_len) - .map(|required| required.saturating_sub(before)); - if self.can_grow_heap_by(growth) { - Some(before) - } else { - None - } - } - - fn prepare_object_map_growth( - &mut self, - object: ScriptObject, - key: ScriptValue, - ) -> Option { - let storage = &self.objects[object]; - let before = storage.retained_bytes(); - if self.max_heap_bytes.is_none() { - return Some(before); - } - let growth = storage - .anticipated_retained_bytes_after_map_insert(key) - .map(|required| required.saturating_sub(before)); - if self.can_grow_heap_by(growth) { - Some(before) - } else { - None - } - } - - pub(crate) fn note_object_storage_growth(&mut self, object: ScriptObject, before: usize) { - let after = self.objects[object].retained_bytes(); - self.note_heap_capacity_change(before, after); - } - - pub(crate) fn insert_object_map( - &mut self, - object: ScriptObject, - key: ScriptValue, - value: ScriptValue, - ) { - let Some(before) = self.prepare_object_map_growth(object, key) else { - return; - }; - self.objects[object].map_insert(key, value); - self.note_object_storage_growth(object, before); - } - - pub(crate) fn push_object_vec( - &mut self, - object: ScriptObject, - value: ScriptVecValue, - ) { - let Some(requested_len) = self.objects[object].vec.len().checked_add(1) else { - self.can_grow_heap_by(None); - return; - }; - let Some(before) = self.prepare_object_vec_growth(object, requested_len) else { - return; - }; - self.objects[object].vec.push(value); - self.note_object_storage_growth(object, before); - } - - pub fn new_object(&mut self) -> ScriptObject { - let capacity = self.objects.capacity(); - let object = if let Some(obj) = self.objects_free.pop() { - // obj already has the correct generation from gc.rs sweep - let object = &mut self.objects[obj]; - debug_assert!( - object.map.is_empty() && object.vec.is_empty() && object.proto.is_nil(), - "reused object slot was not fully cleared before reuse" - ); - object.tag.set_alloced(); - object.proto = id!(object).into(); - obj - } else { - let index = self.objects.len() as u32; - let mut object = ScriptObjectData::default(); - object.tag.set_alloced(); - object.proto = id!(object).into(); - let (_, generation) = self.objects.push(object); - ScriptObject::new(index, generation) - }; - self.note_heap_growth( - self.objects - .capacity() - .saturating_sub(capacity) - .saturating_mul(size_of::>()), - ); - object - } - - pub fn new_with_proto_checked(&mut self, proto: ScriptValue, trap: ScriptTrap) -> ScriptObject { - if let Some(ptr) = proto.as_object() { - let object = &mut self.objects[ptr]; - if object.tag.is_notproto() { - script_err_wrong_value!(trap, "object marked as not usable as prototype"); - return ScriptObject::ZERO; - } - } - self.new_with_proto(proto) - } - - pub fn new_with_proto(&mut self, proto: ScriptValue) -> ScriptObject { - self.new_with_proto_impl(proto, true) - } - - pub fn new_with_proto_no_vec(&mut self, proto: ScriptValue) -> ScriptObject { - self.new_with_proto_impl(proto, false) - } - - fn new_with_proto_impl( - &mut self, - proto: ScriptValue, - copy_vec_from_auto_proto: bool, - ) -> ScriptObject { - let (proto_fwd, proto_ptr) = if let Some(ptr) = proto.as_object() { - // Use checked access via ScriptObject - let object = &mut self.objects[ptr]; - object.tag.set_reffed(); - (object.tag.proto_fwd(), ptr) - } else { - let ptr = self.new_object(); - self.objects[ptr].proto = proto; - return ptr; - }; - - let objects_capacity = self.objects.capacity(); - let (object, previous_storage) = if let Some(obj) = self.objects_free.pop() { - // obj already has the correct generation from gc.rs sweep - let index = obj.index; - let previous_storage = self.objects[obj].retained_bytes(); - - // Use raw index for split_at_mut (internal operation) - let (object, proto_object) = if index > proto_ptr.index { - let (o1, o2) = self.objects.slots_split_at_mut(index as usize); - (&mut o2[0].data, &mut o1[proto_ptr.index as usize].data) - } else { - let (o1, o2) = self.objects.slots_split_at_mut(proto_ptr.index as usize); - (&mut o1[index as usize].data, &mut o2[0].data) - }; - debug_assert!( - object.map.is_empty() && object.vec.is_empty() && object.proto.is_nil(), - "reused object slot was not fully cleared before proto allocation" - ); - object.tag.set_alloced(); - object.tag.set_proto_fwd(proto_fwd); - object.proto = proto; - // only copy vec if we are 'auto' otherwise we proto inherit normally - if copy_vec_from_auto_proto && proto_object.tag.is_auto() { - object.vec.extend_from_slice(&proto_object.vec); - } - (obj, previous_storage) - } else { - let index = self.objects.len() as u32; - let mut object = ScriptObjectData::with_proto(proto); - object.tag.set_alloced(); - object.tag.set_proto_fwd(proto_fwd); - let proto_object = &self.objects[proto_ptr]; - if copy_vec_from_auto_proto && proto_object.tag.is_auto() { - object.vec.extend_from_slice(&proto_object.vec); - } - let (_, generation) = self.objects.push(object); - (ScriptObject::new(index, generation), 0) - }; - let slot_growth = self - .objects - .capacity() - .saturating_sub(objects_capacity) - .saturating_mul(size_of::>()); - self.note_heap_growth(slot_growth); - self.note_heap_capacity_change(previous_storage, self.objects[object].retained_bytes()); - object - } - - pub fn new_if_reffed(&mut self, ptr: ScriptObject) -> ScriptObject { - let obj = &self.objects[ptr]; - if obj.tag.is_reffed() { - let proto = obj.proto; - return self.new_with_proto(proto); - } - return ptr; - } - - // Object flagv - - pub fn set_object_deep(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_deep() - } - - pub fn set_object_storage_vec2(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_vec2() - } - - pub fn set_object_storage_auto(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_auto() - } - - pub fn set_object_pod_type(&mut self, ptr: ScriptObject, pt: ScriptPodType) { - self.objects[ptr].tag.set_pod_type(pt) - } - - pub fn set_first_applied_and_clean(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_first_applied_and_clean() - } - - pub fn clear_object_deep(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.clear_deep() - } - - pub fn freeze(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze() - } - - pub fn set_notproto(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_notproto() - } - - pub fn set_from_eval(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.set_from_eval() - } - - pub fn is_from_eval(&self, ptr: ScriptObject) -> bool { - self.objects[ptr].tag.is_from_eval() - } - - pub fn freeze_module(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze_module() - } - - pub fn freeze_component(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze_component() - } - - pub fn freeze_shader(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze_shader() - } - - pub fn freeze_ext(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze_ext() - } - - pub fn freeze_api(&mut self, ptr: ScriptObject) { - self.objects[ptr].tag.freeze_api() - } - - pub fn set_object_apply_transform(&mut self, ptr: ScriptObject, ni: NativeId) { - self.objects[ptr].tag.set_apply_transform(ni) - } - - pub fn set_type(&mut self, obj: ScriptObject, ty: ScriptTypeIndex) { - self.objects[obj].tag.set_type_index(ty); - } - - pub fn set_string_keys(&mut self, obj: ScriptObject) { - let object = &mut self.objects[obj]; - object.tag.set_string_keys(); - } - - pub fn set_shader_io(&mut self, obj: ScriptObject, io: ShaderIoType) { - let object = &mut self.objects[obj]; - object.tag.set_shader_io(io); - } - - pub fn as_shader_io(&self, obj: ScriptObject) -> Option { - let object = &self.objects[obj]; - object.tag.as_shader_io() - } - - // Writing object values - - pub(crate) fn force_value_in_map( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - sself: ScriptValue, - ) { - self.insert_object_map(ptr, key, sself); - } - - fn set_value_index( - &mut self, - ptr: ScriptObject, - index: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - // alright so. now what. - if self.objects[ptr].tag.is_vec_frozen() { - // has rw flags - return script_err_immutable!(trap, "cannot set index on frozen vec"); - } - - let index = index.as_index(); - let Some(requested_len) = index.checked_add(1) else { - self.can_grow_heap_by(None); - return NIL; - }; - let Some(before) = self.prepare_object_vec_growth(ptr, requested_len) else { - return NIL; - }; - { - let object = &mut self.objects[ptr]; - if index >= object.vec.len() { - object.vec.resize(requested_len, ScriptVecValue::default()); - } - object.vec[index].value = value; - } - self.note_object_storage_growth(ptr, before); - NIL - } - - pub fn set_value_vec( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - if self.objects[ptr].tag.is_vec_frozen() { - return script_err_immutable!(trap, "cannot set vec key on frozen vec"); - } - { - let object = &mut self.objects[ptr]; - for kv in object.vec.iter_mut().rev() { - if kv.key == key { - kv.value = value; - return NIL; - } - } - } - self.push_object_vec(ptr, ScriptVecValue { key, value }); - NIL - } - - fn set_value_deep( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let mut ptr = ptr; - loop { - let object = &mut self.objects[ptr]; - let is_immutable = object.tag.is_immutable(); - // Check vec for key - for kv in object.vec.iter_mut().rev() { - if kv.key == key { - if is_immutable { - return script_err_immutable!(trap, "cannot modify immutable object"); - } - kv.value = value; - return NIL; - } - } - // Check map for key - if object.map_get(&key).is_some() { - if is_immutable { - return script_err_immutable!(trap, "cannot modify immutable object"); - } - object.map_set_if_exist(key, value); - return NIL; - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - break; - } - } - // alright nothing found - if self.objects[ptr].tag.is_immutable() { - return script_err_immutable!(trap, "cannot modify immutable object"); - } - if self.objects[ptr].tag.is_vec2() { - self.push_object_vec(ptr, ScriptVecValue { key, value }); - } else { - self.insert_object_map(ptr, key, value); - } - NIL - } - - fn validate_type(&self, lhs: ScriptValue, rhs: ScriptValue) -> bool { - lhs.value_type().to_redux() == rhs.value_type().to_redux() - } - - fn set_value_shallow_checked( - &mut self, - top_ptr: ScriptObject, - key: ScriptValue, - key_id: LiveId, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let object = &self.objects[top_ptr]; - if object.tag.is_immutable() { - return script_err_immutable!(trap, "cannot set property on immutable object"); - } - - if let Some(ty) = object.tag.as_type_index() { - let check = &self.type_check[ty.0 as usize]; - if let Some(type_prop) = check.props.props.get(&key_id) { - if let Some(ty_index) = self.type_index.get(&type_prop.ty) { - let check_prop = &self.type_check[ty_index.0 as usize]; - if let Some(type_object) = &check_prop.object { - if !(type_object.check)(self, value) { - let expected = format_expected_type(self, type_object); - return script_err_type_mismatch!( - trap, - "type mismatch for property {:?}: expected {}, got {}", - key_id, - expected, - format_value_type(self, value) - ); - } - } - } else { - println!( - "Trying to check a type that hasnt been registered yet for {} {}", - key, value - ); - return script_err_unknown_type!( - trap, - "type not registered for property {:?}", - key_id - ); - } - } else if !object.tag.is_map_add() { - // check if the key exists in the vec (for := defined properties) - let mut found_in_vec = false; - let mut ptr = top_ptr; - loop { - let obj = &self.objects[ptr]; - for kv in obj.vec.iter().rev() { - if kv.key == key { - found_in_vec = true; - break; - } - } - if found_in_vec { - break; - } - if let Some(next_ptr) = obj.proto.as_object() { - ptr = next_ptr; - } else { - break; - } - } - if found_in_vec { - return self.set_value_vec(top_ptr, key, value, trap); - } - return script_err_not_found!( - trap, - "property {:?} not defined on type{}", - key_id, - suggest_property(self, top_ptr, key) - ); - } - self.insert_object_map(top_ptr, key, value); - return NIL; - } - // check against prototype or type - if object.tag.is_validated() { - let mut ptr = top_ptr; - loop { - let object = &self.objects[ptr]; - if object.tag.is_vec2() { - for kv in object.vec.iter().rev() { - if kv.key == key { - if !self.validate_type(kv.value, value) { - return script_err_type_mismatch!( - trap, - "type mismatch assigning to property {:?}: expected {}, got {}", - key, - format_value_type(self, kv.value), - format_value_type(self, value) - ); - } - return self.set_value_shallow(top_ptr, key, value, trap); - } - } - } - if let Some(set_value) = object.map_get(&key) { - if !self.validate_type(set_value, value) { - return script_err_type_mismatch!( - trap, - "type mismatch assigning to property {:?}: expected {}, got {}", - key, - format_value_type(self, set_value), - format_value_type(self, value) - ); - } - return self.set_value_shallow(top_ptr, key, value, trap); - } - // also check vec for := defined properties on non-vec2 objects - if !object.tag.is_vec2() { - for kv in object.vec.iter().rev() { - if kv.key == key { - return self.set_value_vec(top_ptr, key, value, trap); - } - } - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else if !object.tag.is_map_add() { - // not found - return script_err_not_found!( - trap, - "property {:?} not found and object does not allow adding", - key_id - ); - } - } - } - let object = &self.objects[top_ptr]; - if object.tag.is_map_add() { - if object.tag.is_vec2() { - for kv in object.vec.iter().rev() { - if kv.key == key { - return script_err_duplicate!(trap, "key {:?} already exists in vec", key); - } - } - self.push_object_vec(top_ptr, ScriptVecValue { key, value }); - return NIL; - } - if let Some(_) = object.map_get(&key) { - return script_err_duplicate!(trap, "key {:?} already exists in map", key); - } else { - self.insert_object_map(top_ptr, key, value); - return NIL; - } - } - script_err_unexpected!(trap, "unexpected state in set_value_shallow_checked") - } - - fn set_value_shallow( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - if self.objects[ptr].tag.is_immutable() { - return script_err_immutable!(trap, "cannot set property on immutable object"); - } - if self.objects[ptr].tag.is_vec2() { - for kv in self.objects[ptr].vec.iter_mut().rev() { - if kv.key == key { - kv.value = value; - return NIL; - } - } - self.push_object_vec(ptr, ScriptVecValue { key, value }); - return NIL; - } - self.insert_object_map(ptr, key, value); - NIL - } - - pub fn set_value_def(&mut self, ptr: ScriptObject, key: ScriptValue, value: ScriptValue) { - self.set_value(ptr, key, value, NoTrap); - } - - pub fn set_value( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - if let Some(key_id) = key.as_id() { - let object = &self.objects[ptr]; - if !object.tag.is_deep() { - if object.tag.needs_checking() { - return self.set_value_shallow_checked(ptr, key, key_id, value, trap); - } - if object.tag.is_string_keys() { - if let Some(skey) = key_id.as_string(|s| { - if let Some(s) = s { - // Try to get existing interned string - if let Some(existing) = self.check_intern_string(s) { - Some(existing) - } else { - // Not interned yet - intern it now to maintain consistency - Some(self.new_string_from_str(s)) - } - } else { - None - } - }) { - return self.set_value_shallow(ptr, skey, value, trap); - } - // LiveId couldn't be converted to string - fall through to use LiveId - // This happens for hashed IDs that lost their string representation - } - return self.set_value_shallow(ptr, key, value, trap); - } else { - return self.set_value_deep(ptr, key, value, trap); - } - } - if key.is_index() { - // use vector - return self.set_value_index(ptr, key, value, trap); - } - if key.is_string_like() || key.is_object() || key.is_color() || key.is_bool() { - // scan protochain for object - let object = &mut self.objects[ptr]; - if !object.tag.is_deep() { - if object.tag.needs_checking() { - return script_err_type_mismatch!(trap, "invalid key type for checked object"); - } - return self.set_value_shallow(ptr, key, value, trap); - } else { - return self.set_value_deep(ptr, key, value, trap); - } - } - script_err_type_mismatch!(trap, "unsupported key type for set_value") - } - - // scope specific value get/set - - pub fn set_scope_value( - &mut self, - ptr: ScriptObject, - key: LiveId, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let root_ptr = ptr; - let mut ptr = ptr; - loop { - let object = &mut self.objects[ptr]; - if let Some(set) = object.map.get_mut(&key.into()) { - if object.tag.is_immutable() { - return script_err_immutable!(trap, "cannot modify immutable object"); - } - set.value = value; - return NIL; - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - break; - } - } - // alright nothing found - script_err_not_found!( - trap, - "variable {} not found in scope{}", - key, - suggest_scope_var(self, root_ptr, key) - ) - } - - pub fn scope_value(&self, ptr: ScriptObject, key: LiveId, trap: ScriptTrap) -> ScriptValue { - let root_ptr = ptr; - let mut ptr = ptr; - let key_sv = key.into(); - loop { - let object = &self.objects[ptr]; - if let Some(set) = object.map.get(&key_sv) { - return set.value; - } - if object.tag.is_vec2() { - for kv in object.vec.iter().rev() { - if kv.key == key_sv { - return kv.value; - } - } - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - break; - } - } - // alright nothing found - script_err_not_found!( - trap, - "variable {} not found in scope{}", - key, - suggest_scope_var(self, root_ptr, key) - ) - } - - pub fn def_scope_value( - &mut self, - ptr: ScriptObject, - key: LiveId, - value: ScriptValue, - ) -> Option { - // if we already have sself value we have to shadow the scope - let key = key.into(); - if self.objects[ptr].map.contains_key(&key) { - let new_scope = self.new_with_proto(ptr.into()); - self.insert_object_map(new_scope, key, value); - return Some(new_scope); - } - self.insert_object_map(ptr, key, value); - None - } - - // Reading object values - - fn value_index(&self, ptr: ScriptObject, index: ScriptValue, trap: ScriptTrap) -> ScriptValue { - let object = &self.objects[ptr]; - // most used path - let index = index.as_index(); - if let Some(kv) = object.vec.get(index) { - return kv.value; - } - script_err_not_found!( - trap, - "index {} out of bounds (len={})", - index, - object.vec.len() - ) - } - - fn value_deep_map( - &self, - obj_ptr: ScriptObject, - key: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - let mut ptr = obj_ptr; - loop { - let object = &self.objects[ptr]; - if let Some(value) = object.map_get(&key) { - return value; - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - break; - } - } - script_err_not_found!( - trap, - "key {:?} not found in prototype chain{}", - key, - suggest_property(self, obj_ptr, key) - ) - } - - fn value_deep(&self, obj_ptr: ScriptObject, key: ScriptValue, trap: ScriptTrap) -> ScriptValue { - let mut ptr = obj_ptr; - loop { - let object = &self.objects[ptr]; - if let Some(value) = object.map_get(&key) { - return value; - } - // handle auto conversion from string to id and back for json interop - if object.tag.is_string_keys() { - if let Some(id) = key.as_id() { - if let Some(value) = id.as_string(|s| { - if let Some(s) = s { - if let Some(idx) = self.check_intern_string(s) { - object.map_get(&idx) - } else { - None - } - } else { - None - } - }) { - return value; - } - } else if key.is_string_like() { - // string key on string_keys object: resolve via intern to canonical ScriptValue - if let Some(Some(value)) = self.string_with(key, |heap, s| { - if let Some(idx) = heap.check_intern_string(s) { - if idx != key { - object.map_get(&idx) - } else { - None - } - } else { - None - } - }) { - return value; - } - } - } else if key.is_string_like() { - let id = if let Some(s) = key.as_string() { - if let Some(s) = &self.strings[s] { - LiveId::from_str(&s.string.0) - } else { - LiveId(0) - } - } else { - key.as_inline_string(|s| LiveId::from_str(s)).unwrap() - }; - if let Some(value) = object.map_get(&id.into()) { - return value; - } - } - for kv in object.vec.iter().rev() { - if kv.key == key { - return kv.value; - } - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr; - } else { - break; - } - } - script_err_not_found!( - trap, - "property {:?} not found in prototype chain{}", - key, - suggest_property(self, obj_ptr, key) - ) - } - - pub fn object_method( - &self, - ptr: ScriptObject, - key: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - return self.value_deep_map(ptr, key, trap); - } - - pub fn value_path(&self, ptr: ScriptObject, keys: &[LiveId], trap: ScriptTrap) -> ScriptValue { - let mut value: ScriptValue = ptr.into(); - for key in keys { - if let Some(obj) = value.as_object() { - value = self.value(obj, (*key).into(), trap); - } else { - return script_err_not_found!( - trap, - "path segment {:?} requires object but got {:?}", - key, - value.value_type() - ); - } - } - value - } - - pub fn value(&self, ptr: ScriptObject, key: ScriptValue, trap: ScriptTrap) -> ScriptValue { - if key.is_id() { - return self.value_deep(ptr, key, trap); - } - if key.is_index() { - return self.value_index(ptr, key, trap); - } - if key.is_string_like() || key.is_object() || key.is_color() || key.is_bool() { - // scan protochain for object - return self.value_deep(ptr, key, trap); - } - // TODO implement string lookup - script_err_not_found!( - trap, - "unsupported key type {:?} for value lookup", - key.value_type() - ) - } - - /// Create a default instance for a type-checked field that doesn't exist on the prototype. - /// This is used for deep prototypical inheritance - when accessing obj.field where field - /// only exists in the type-check structure, we create a new instance and set it on obj. - pub fn proto_field_from_type_check( - &mut self, - obj: ScriptObject, - field_id: LiveId, - trap: ScriptTrap, - ) -> ScriptValue { - // Get the field's type_id from the type-check structure - if let Some(field_type_id) = self.field_type_from_type_check(obj, field_id) { - // Look up the type_default for this type - if let Some(default_obj) = self.type_default_for_id(field_type_id) { - // Create a new object with the default as prototype - let new_obj = self.new_with_proto(default_obj.into()); - // Set it on the parent object - self.set_value(obj, field_id.into(), new_obj.into(), trap); - return new_obj.into(); - } - } - script_err_not_found!( - trap, - "field {:?} not found in type-check and has no default{}", - field_id, - suggest_scope_var(self, obj, field_id) - ) - } - - /// Handle proto_field access for a value that exists on the prototype chain. - /// If the value is an object that comes from a prototype (not directly on obj), - /// create a new object with it as prototype and set it on obj. - pub fn proto_field_from_value( - &mut self, - obj: ScriptObject, - field: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - // First check if the field exists directly on this object - let obj_data = &self.objects[obj]; - if let Some(value) = obj_data.map_get(&field) { - // Field exists directly on object, return as-is - return value; - } - // Handle is_string_keys: convert LiveId to string key - if obj_data.tag.is_string_keys() { - if let Some(id) = field.as_id() { - if let Some(value) = id.as_string(|s| { - if let Some(s) = s { - if let Some(idx) = self.check_intern_string(s) { - self.objects[obj].map_get(&idx) - } else { - None - } - } else { - None - } - }) { - return value; - } - } - } - - // Field doesn't exist directly - get from prototype chain - let value = self.value(obj, field, trap); - - // If it's an object from prototype, create a new instance - if let Some(value_obj) = value.as_object() { - // Create a new object with the prototype value as its proto - // Note: new_with_proto automatically copies type_index from prototype chain - let new_obj = self.new_with_proto(value_obj.into()); - // Set it on the current object - self.set_value(obj, field, new_obj.into(), trap); - return new_obj.into(); - } - - // Not an object (primitive or nil) - return as-is - value - } - - pub fn value_for_apply( - &mut self, - obj: ScriptValue, - key: ScriptValue, - apply: &Apply, - ) -> Option { - if let Some(ptr) = obj.as_object() { - // only do top level if dirty - let object = &mut self.objects[ptr]; - if let Some(value) = object.map_get(&key) { - return Some(value); - } - // For eval, only check the object's own map (no prototype chain) - if apply.is_eval() { - return None; - } - // if we havent been applied before apply prototype chain too - let mut ptr = if let Some(next_ptr) = object.proto.as_object() { - next_ptr - } else { - return None; - }; - loop { - let object = &self.objects[ptr]; - if let Some(value) = object.map_get(&key) { - return Some(value); - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr - } else { - return None; - } - } - } - None - } - - pub fn map_ref(&self, object: ScriptObject) -> &ScriptObjectMap { - let object = &self.objects[object]; - &object.map - } - - pub fn map_mut_with R>( - &mut self, - s: S, - object: ScriptObject, - f: F, - ) -> R { - let before = self.objects[object].retained_bytes(); - let mut map = ScriptObjectMap::default(); - std::mem::swap(&mut map, &mut self.objects[object].map); - let r = f(s, &mut map); - std::mem::swap(&mut map, &mut self.objects[object].map); - self.note_object_storage_growth(object, before); - r - } - - // Vec Reading - - pub fn vec_key_value( - &self, - ptr: ScriptObject, - index: usize, - trap: ScriptTrap, - ) -> ScriptVecValue { - let object = &self.objects[ptr]; - - if let Some(value) = object.vec.get(index) { - return *value; - } - ScriptVecValue { - key: NIL, - value: script_err_out_of_bounds!( - trap, - "vec index {} out of bounds (len={})", - index, - object.vec.len() - ), - } - } - - pub fn vec_value(&self, ptr: ScriptObject, index: usize, trap: ScriptTrap) -> ScriptValue { - let object = &self.objects[ptr]; - if let Some(kv) = object.vec.get(index) { - return kv.value; - } - script_err_out_of_bounds!( - trap, - "vec index {} out of bounds (len={})", - index, - object.vec.len() - ) - } - - pub fn vec_value_if_exist(&self, ptr: ScriptObject, index: usize) -> Option { - let object = &self.objects[ptr]; - if let Some(kv) = object.vec.get(index) { - Some(kv.value) - } else { - None - } - } - - pub fn vec_len(&self, ptr: ScriptObject) -> usize { - let object = &self.objects[ptr]; - object.vec.len() - } - - pub fn map_delete(&mut self, ptr: ScriptObject, key: &ScriptValue) -> Option { - let object = &mut self.objects[ptr]; - object.map_delete(key) - } - - pub fn map_len(&self, ptr: ScriptObject) -> usize { - let object = &self.objects[ptr]; - object.map_len() - } - - /// Total number of iterable entries: vec entries + map entries. - /// Used by `for k, v in obj` to iterate all entries. - pub fn iter_len(&self, ptr: ScriptObject) -> usize { - let object = &self.objects[ptr]; - object.vec.len() + object.map_len() - } - - /// Get key-value at an iteration index spanning both vec and map. - /// Indices 0..vec_len come from vec, indices vec_len..vec_len+map_len come from map. - pub fn iter_key_value( - &self, - ptr: ScriptObject, - index: usize, - trap: ScriptTrap, - ) -> ScriptVecValue { - let object = &self.objects[ptr]; - let vec_len = object.vec.len(); - if index < vec_len { - return object.vec[index]; - } - let map_index = index - vec_len; - if let Some((key, map_val)) = object.map.iter().nth(map_index) { - return ScriptVecValue { - key: *key, - value: map_val.value, - }; - } - ScriptVecValue { - key: NIL, - value: script_err_out_of_bounds!( - trap, - "iter index {} out of bounds (vec_len={}, map_len={})", - index, - vec_len, - object.map_len() - ), - } - } - - pub fn vec_ref(&self, ptr: ScriptObject) -> &[ScriptVecValue] { - let object = &self.objects[ptr]; - &object.vec - } - - // Vec Writing - - pub fn vec_insert_value_at( - &mut self, - _ptr: ScriptObject, - _key: ScriptValue, - _value: ScriptValue, - _before: bool, - _ip: ScriptTrap, - ) -> ScriptValue { - NIL - } - - pub fn vec_insert_value_begin( - &mut self, - _ptr: ScriptObject, - _key: ScriptValue, - _value: ScriptValue, - _ip: ScriptTrap, - ) -> ScriptValue { - NIL - } - - pub fn vec_push_vec( - &mut self, - target: ScriptObject, - source: ScriptObject, - trap: ScriptTrap, - ) -> ScriptValue { - if target == source { - return script_err_invalid_args!( - trap, - "cannot push object vec onto itself (object gc_id={})", - target.index - ); - } - if self.objects[target].tag.is_vec_frozen() { - return script_err_immutable!(trap, "cannot push to frozen vec"); - } - let source_len = self.objects[source].vec.len(); - let Some(requested_len) = self.objects[target].vec.len().checked_add(source_len) else { - self.can_grow_heap_by(None); - return NIL; - }; - let Some(_) = self.prepare_object_vec_growth(target, requested_len) else { - return NIL; - }; - let before = self.objects[target].retained_bytes(); - let (target_obj, source_obj) = if target.index > source.index { - let (o1, o2) = self.objects.slots_split_at_mut(target.index as usize); - (&mut o2[0].data, &mut o1[source.index as usize].data) - } else { - let (o1, o2) = self.objects.slots_split_at_mut(source.index as usize); - (&mut o1[target.index as usize].data, &mut o2[0].data) - }; - target_obj.push_vec_from_other(source_obj); - self.note_object_storage_growth(target, before); - NIL - } - - pub fn vec_push_vec_of_vec( - &mut self, - target: ScriptObject, - source: ScriptObject, - map: bool, - trap: ScriptTrap, - ) -> ScriptValue { - let len = self.objects[source].vec.len(); - for i in 0..len { - if let Some(source) = self.objects[source].vec[i].value.as_object() { - if target == source { - return script_err_invalid_args!( - trap, - "cannot push object vec onto itself in nested push (object gc_id={})", - target.index - ); - } - if self.objects[target].tag.is_vec_frozen() { - return script_err_immutable!( - trap, - "cannot push to frozen vec in nested push" - ); - } - let source_len = self.objects[source].vec.len(); - let Some(requested_len) = self.objects[target].vec.len().checked_add(source_len) - else { - self.can_grow_heap_by(None); - return NIL; - }; - let Some(_) = self.prepare_object_vec_growth(target, requested_len) else { - return NIL; - }; - let before = self.objects[target].retained_bytes(); - let (target_obj, source_obj) = if target.index > source.index { - let (o1, o2) = self.objects.slots_split_at_mut(target.index as usize); - (&mut o2[0].data, &mut o1[source.index as usize].data) - } else { - let (o1, o2) = self.objects.slots_split_at_mut(source.index as usize); - (&mut o1[target.index as usize].data, &mut o2[0].data) - }; - target_obj.push_vec_from_other(source_obj); - if map { - target_obj.merge_map_from_other(source_obj); - } - self.note_object_storage_growth(target, before); - } - } - NIL - } - - /// Merges the vec and map parts of a source object into a target object. - /// Used by the splat operator (..) to spread one object into another. - /// Map entries from source are only added if they don't already exist in target. - pub fn merge_object( - &mut self, - target: ScriptObject, - source: ScriptObject, - trap: ScriptTrap, - ) -> ScriptValue { - if target == source { - return script_err_invalid_args!( - trap, - "cannot merge object into itself (object gc_id={})", - target.index - ); - } - if self.objects[target].tag.is_immutable() { - return script_err_immutable!(trap, "cannot merge into immutable object"); - } - let source_len = self.objects[source].vec.len(); - let copy_vec = !self.objects[target].tag.is_vec_frozen(); - if copy_vec { - let Some(requested_len) = self.objects[target].vec.len().checked_add(source_len) - else { - self.can_grow_heap_by(None); - return NIL; - }; - let Some(_) = self.prepare_object_vec_growth(target, requested_len) else { - return NIL; - }; - } - let before = self.objects[target].retained_bytes(); - let (target_obj, source_obj) = if target.index > source.index { - let (o1, o2) = self.objects.slots_split_at_mut(target.index as usize); - (&mut o2[0].data, &mut o1[source.index as usize].data) - } else { - let (o1, o2) = self.objects.slots_split_at_mut(source.index as usize); - (&mut o1[target.index as usize].data, &mut o2[0].data) - }; - if !target_obj.tag.is_vec_frozen() { - target_obj.push_vec_from_other(source_obj); - } - // Only add map entries that don't already exist in target - target_obj.merge_map_from_other_no_overwrite(source_obj); - self.note_object_storage_growth(target, before); - NIL - } - - pub fn vec_push( - &mut self, - ptr: ScriptObject, - key: ScriptValue, - value: ScriptValue, - trap: ScriptTrap, - ) -> ScriptValue { - if self.objects[ptr].tag.is_vec_frozen() { - return script_err_immutable!(trap, "cannot push to frozen vec"); - } - self.push_object_vec(ptr, ScriptVecValue { key, value }); - NIL - } - - pub fn vec_push_unchecked(&mut self, ptr: ScriptObject, key: ScriptValue, value: ScriptValue) { - self.push_object_vec(ptr, ScriptVecValue { key, value }); - } - - pub fn vec_remove( - &mut self, - ptr: ScriptObject, - index: usize, - trap: ScriptTrap, - ) -> ScriptVecValue { - let object = &mut self.objects[ptr]; - if object.tag.is_vec_frozen() { - return ScriptVecValue { - key: NIL, - value: script_err_immutable!(trap, "cannot remove from frozen vec"), - }; - } - if index >= object.vec.len() { - return ScriptVecValue { - key: NIL, - value: script_err_out_of_bounds!( - trap, - "vec remove index {} out of bounds (len={})", - index, - object.vec.len() - ), - }; - } - object.vec.remove(index) - } - - pub fn vec_pop(&mut self, ptr: ScriptObject, trap: ScriptTrap) -> ScriptVecValue { - let object = &mut self.objects[ptr]; - if object.tag.is_vec_frozen() { - return ScriptVecValue { - key: NIL, - value: script_err_immutable!(trap, "cannot pop from frozen vec"), - }; - } - object.vec.pop().unwrap_or_else(|| ScriptVecValue { - key: NIL, - value: script_err_out_of_bounds!(trap, "cannot pop from empty vec"), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn bounded_map_insert_rejects_rehash_before_mutation() { - let mut heap = ScriptHeap::empty(); - let object = heap.new_object(); - heap.set_max_heap_bytes(Some(usize::MAX)); - let baseline = heap.accounted_heap_bytes(); - heap.set_max_heap_bytes(Some(baseline.checked_add(1).unwrap())); - - heap.insert_object_map(object, id!(entry).into(), NIL); - - assert!(heap.take_heap_limit_exceeded()); - assert!(heap.objects[object].map.is_empty()); - } -} diff --git a/vendor/makepad/platform/script/src/opcode.rs b/vendor/makepad/platform/script/src/opcode.rs deleted file mode 100644 index 6f8f1d6..0000000 --- a/vendor/makepad/platform/script/src/opcode.rs +++ /dev/null @@ -1,407 +0,0 @@ -use std::fmt; - -#[derive(Copy, Clone, PartialEq, Eq, Default)] -pub struct OpcodeArgs(pub(crate) u32); - -impl OpcodeArgs { - pub const TYPE_NONE: u32 = 0; - pub const TYPE_NIL: u32 = 1 << 28; - pub const TYPE_NUMBER: u32 = 2 << 28; - pub const TYPE_MASK: u32 = 3 << 28; - pub const NEED_NIL_FLAG: u32 = 1 << 31; - pub const POP_TO_ME_FLAG: u32 = 1 << 30; - pub const MAX_U32: u32 = (1 << 28) - 1; - - pub const NONE: Self = Self(0); - pub const NIL: Self = Self(Self::TYPE_NIL); - - pub fn raw(&self) -> u32 { - self.0 - } - - pub fn from_u32(jump_to_next: u32) -> Self { - Self(Self::TYPE_NUMBER | (jump_to_next & 0x0fff_ffff)) - } - - pub fn set_need_nil(self) -> Self { - Self(self.0 | Self::NEED_NIL_FLAG) - } - - pub fn to_u32(&self) -> u32 { - self.0 & 0x1fff_ffff - } - - pub fn arg_type(&self) -> u32 { - self.0 & Self::TYPE_MASK - } - - // pub fn is_statement(&self)->bool{ - // self.0 & Self::STATEMENT_FLAG != 0 - // } - - pub fn is_need_nil(&self) -> bool { - self.0 & Self::NEED_NIL_FLAG != 0 - } - - pub fn is_pop_to_me(&self) -> bool { - self.0 & Self::POP_TO_ME_FLAG != 0 - } - - pub fn is_nil(&self) -> bool { - self.0 & Self::TYPE_MASK == Self::TYPE_NIL - } - - pub fn is_u32(&self) -> bool { - self.0 & Self::TYPE_MASK == Self::TYPE_NUMBER - } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Opcode(pub u8); -impl Opcode { - pub fn raw(&self) -> u8 { - self.0 - } - - pub const NOP: Self = Self(0); - pub const NOT: Self = Self(1); - pub const NEG: Self = Self(2); - pub const MUL: Self = Self(3); - pub const DIV: Self = Self(4); - pub const MOD: Self = Self(5); - pub const ADD: Self = Self(6); - pub const SUB: Self = Self(7); - pub const SHL: Self = Self(8); - pub const SHR: Self = Self(9); - pub const AND: Self = Self(10); - pub const OR: Self = Self(11); - pub const XOR: Self = Self(12); - - pub const CONCAT: Self = Self(13); - pub const EQ: Self = Self(14); - pub const NEQ: Self = Self(15); - pub const LT: Self = Self(16); - pub const GT: Self = Self(17); - pub const LEQ: Self = Self(18); - pub const GEQ: Self = Self(19); - // Short-circuit evaluation opcodes (these replace simple binary ops) - pub const LOGIC_AND_TEST: Self = Self(20); // If falsy, skip and keep value; else pop and continue - pub const LOGIC_OR_TEST: Self = Self(21); // If truthy, skip and keep value; else pop and continue - pub const NIL_OR_TEST: Self = Self(22); // If not nil, skip and keep value; else pop and continue - pub const SHALLOW_EQ: Self = Self(23); - pub const SHALLOW_NEQ: Self = Self(24); - - pub const fn is_assign(self) -> bool { - self.0 >= Opcode::ASSIGN_ME.0 && self.0 <= Opcode::ASSIGN_INDEX_IFNIL.0 - } - - pub const ASSIGN_ME: Self = Self(25); - pub const ASSIGN_ME_BEFORE: Self = Self(26); - pub const ASSIGN_ME_AFTER: Self = Self(27); - pub const ASSIGN_ME_BEGIN: Self = Self(28); - pub const ASSIGN_ME_VEC: Self = Self(29); - - pub const ASSIGN: Self = Self(30); - pub const ASSIGN_ADD: Self = Self(31); - pub const ASSIGN_SUB: Self = Self(32); - pub const ASSIGN_MUL: Self = Self(33); - pub const ASSIGN_DIV: Self = Self(34); - pub const ASSIGN_MOD: Self = Self(35); - pub const ASSIGN_AND: Self = Self(36); - pub const ASSIGN_OR: Self = Self(37); - pub const ASSIGN_XOR: Self = Self(38); - pub const ASSIGN_SHL: Self = Self(39); - pub const ASSIGN_SHR: Self = Self(40); - pub const ASSIGN_IFNIL: Self = Self(41); - - pub const ASSIGN_FIELD: Self = Self(42); - pub const ASSIGN_FIELD_ADD: Self = Self(43); - pub const ASSIGN_FIELD_SUB: Self = Self(44); - pub const ASSIGN_FIELD_MUL: Self = Self(45); - pub const ASSIGN_FIELD_DIV: Self = Self(46); - pub const ASSIGN_FIELD_MOD: Self = Self(47); - pub const ASSIGN_FIELD_AND: Self = Self(48); - pub const ASSIGN_FIELD_OR: Self = Self(49); - pub const ASSIGN_FIELD_XOR: Self = Self(50); - pub const ASSIGN_FIELD_SHL: Self = Self(51); - pub const ASSIGN_FIELD_SHR: Self = Self(52); - - pub const ASSIGN_FIELD_IFNIL: Self = Self(53); - - pub const ASSIGN_INDEX: Self = Self(54); - pub const ASSIGN_INDEX_ADD: Self = Self(55); - pub const ASSIGN_INDEX_SUB: Self = Self(56); - pub const ASSIGN_INDEX_MUL: Self = Self(57); - pub const ASSIGN_INDEX_DIV: Self = Self(58); - pub const ASSIGN_INDEX_MOD: Self = Self(59); - pub const ASSIGN_INDEX_AND: Self = Self(60); - pub const ASSIGN_INDEX_OR: Self = Self(61); - pub const ASSIGN_INDEX_XOR: Self = Self(62); - pub const ASSIGN_INDEX_SHL: Self = Self(63); - pub const ASSIGN_INDEX_SHR: Self = Self(64); - pub const ASSIGN_INDEX_IFNIL: Self = Self(65); - - pub const BEGIN_PROTO: Self = Self(66); - pub const PROTO_INHERIT_READ: Self = Self(67); - pub const END_PROTO: Self = Self(68); - pub const BEGIN_BARE: Self = Self(69); - pub const END_BARE: Self = Self(70); - pub const BEGIN_ARRAY: Self = Self(71); - pub const END_ARRAY: Self = Self(72); - - pub const CALL_ARGS: Self = Self(73); - pub const CALL_EXEC: Self = Self(74); - pub const METHOD_CALL_ARGS: Self = Self(75); - pub const METHOD_CALL_EXEC: Self = Self(76); - - pub const FN_ARGS: Self = Self(77); - pub const FN_LET_ARGS: Self = Self(78); - pub const FN_ARG_DYN: Self = Self(79); - pub const FN_ARG_TYPED: Self = Self(80); - pub const FN_BODY_DYN: Self = Self(81); - pub const FN_BODY_TYPED: Self = Self(82); - pub const RETURN: Self = Self(83); - - pub const IF_TEST: Self = Self(84); - pub const IF_ELSE: Self = Self(85); - - pub const FIELD: Self = Self(86); - pub const FIELD_NIL: Self = Self(87); - pub const ME_FIELD: Self = Self(88); - pub const ARRAY_INDEX: Self = Self(89); - pub const PROTO_FIELD: Self = Self(90); - pub const POP_TO_ME: Self = Self(91); - - pub const LET_TYPED: Self = Self(92); - pub const LET_DYN: Self = Self(93); - - pub const SEARCH_TREE: Self = Self(94); - pub const STRING_STREAM: Self = Self(95); - pub const LOG: Self = Self(96); - - pub const ME: Self = Self(97); - pub const SCOPE: Self = Self(98); - - pub const FOR_1: Self = Self(99); - pub const FOR_2: Self = Self(100); - pub const FOR_3: Self = Self(101); - pub const LOOP: Self = Self(102); - pub const BREAKIFNOT: Self = Self(103); - pub const FOR_END: Self = Self(104); - pub const BREAK: Self = Self(105); - pub const CONTINUE: Self = Self(106); - pub const RANGE: Self = Self(107); - pub const IS: Self = Self(108); - pub const RETURN_IF_ERR: Self = Self(109); - pub const TRY_TEST: Self = Self(110); - pub const TRY_ERR: Self = Self(111); - pub const TRY_OK: Self = Self(112); - pub const OK_TEST: Self = Self(113); - pub const OK_END: Self = Self(114); - pub const USE: Self = Self(115); - pub const VAR_TYPED: Self = Self(116); - pub const VAR_DYN: Self = Self(117); - - // Inherit opcodes - pub const PROTO_INHERIT_WRITE: Self = Self(118); - pub const SCOPE_INHERIT_READ: Self = Self(119); - pub const SCOPE_INHERIT_WRITE: Self = Self(120); - pub const FIELD_INHERIT_READ: Self = Self(121); - pub const FIELD_INHERIT_WRITE: Self = Self(122); - pub const INDEX_INHERIT_READ: Self = Self(123); - pub const INDEX_INHERIT_WRITE: Self = Self(124); - pub const ME_SPLAT: Self = Self(125); - - // Destructuring opcodes - pub const DUP: Self = Self(126); - pub const DROP: Self = Self(127); - pub const LET_DESTRUCT_ARRAY_EL: Self = Self(128); // arg = index; stack: [source, id] -> [source], binds id = source[index] - pub const LET_DESTRUCT_OBJECT_EL: Self = Self(129); // stack: [source, id] -> [source], binds id = source[id] - pub const ARRAY_INDEX_NIL: Self = Self(130); -} - -impl fmt::Debug for OpcodeArgs { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for OpcodeArgs { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.arg_type() { - Self::TYPE_NONE => { - write!(f, "").ok(); - } - Self::TYPE_NIL => { - write!(f, "(nil)").ok(); - } - Self::TYPE_NUMBER => { - write!(f, "({})", self.to_u32()).ok(); - } - _ => {} - }; - //if self.is_statement(){ - // write!(f,"").ok(); - //} - if self.is_pop_to_me() { - write!(f, "").ok(); - } - write!(f, "") - } -} - -impl fmt::Debug for Opcode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for Opcode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Self::NOP => return write!(f, "nop"), - Self::NOT => return write!(f, "!"), - Self::NEG => return write!(f, "neg"), - Self::MUL => return write!(f, "*"), - Self::DIV => return write!(f, "/"), - Self::MOD => return write!(f, "%"), - Self::ADD => return write!(f, "+"), - Self::SUB => return write!(f, "-"), - Self::SHL => return write!(f, "<<"), - Self::SHR => return write!(f, ">>"), - Self::AND => return write!(f, "&"), - Self::XOR => return write!(f, "^"), - Self::OR => return write!(f, "|"), - Self::EQ => return write!(f, "=="), - Self::NEQ => return write!(f, "!="), - Self::LT => return write!(f, "<"), - Self::GT => return write!(f, ">"), - Self::LEQ => return write!(f, "<="), - Self::GEQ => return write!(f, ">="), - Self::LOGIC_AND_TEST => return write!(f, "&&?"), - Self::LOGIC_OR_TEST => return write!(f, "||?"), - Self::NIL_OR_TEST => return write!(f, "|??"), - Self::SHALLOW_EQ => return write!(f, "==="), - Self::SHALLOW_NEQ => return write!(f, "!=="), - - Self::ASSIGN => return write!(f, "="), - Self::ASSIGN_ME => return write!(f, ":"), - Self::ASSIGN_ME_VEC => return write!(f, ":="), - Self::ASSIGN_ADD => return write!(f, "+="), - Self::ASSIGN_SUB => return write!(f, "-="), - Self::ASSIGN_MUL => return write!(f, "*="), - Self::ASSIGN_DIV => return write!(f, "/="), - Self::ASSIGN_MOD => return write!(f, "%="), - Self::ASSIGN_AND => return write!(f, "&="), - Self::ASSIGN_OR => return write!(f, "|="), - Self::ASSIGN_XOR => return write!(f, "^="), - Self::ASSIGN_SHL => return write!(f, "<<="), - Self::ASSIGN_SHR => return write!(f, ">>="), - Self::ASSIGN_IFNIL => return write!(f, "?="), - - Self::ASSIGN_FIELD => return write!(f, ".="), - Self::ASSIGN_FIELD_ADD => return write!(f, ".+="), - Self::ASSIGN_FIELD_SUB => return write!(f, ".-="), - Self::ASSIGN_FIELD_MUL => return write!(f, ".*="), - Self::ASSIGN_FIELD_DIV => return write!(f, "./="), - Self::ASSIGN_FIELD_MOD => return write!(f, ".%="), - Self::ASSIGN_FIELD_AND => return write!(f, ".&="), - Self::ASSIGN_FIELD_OR => return write!(f, ".|="), - Self::ASSIGN_FIELD_XOR => return write!(f, ".^="), - Self::ASSIGN_FIELD_SHL => return write!(f, ".<<="), - Self::ASSIGN_FIELD_SHR => return write!(f, ".>>="), - Self::ASSIGN_FIELD_IFNIL => return write!(f, ".?="), - - Self::ASSIGN_INDEX => return write!(f, "[]="), - Self::ASSIGN_INDEX_ADD => return write!(f, "[]+="), - Self::ASSIGN_INDEX_SUB => return write!(f, "[]-="), - Self::ASSIGN_INDEX_MUL => return write!(f, "[]*="), - Self::ASSIGN_INDEX_DIV => return write!(f, "[]/="), - Self::ASSIGN_INDEX_MOD => return write!(f, "[]%="), - Self::ASSIGN_INDEX_AND => return write!(f, "[]&="), - Self::ASSIGN_INDEX_OR => return write!(f, "[]|="), - Self::ASSIGN_INDEX_XOR => return write!(f, "[]^="), - Self::ASSIGN_INDEX_SHL => return write!(f, "[]<<="), - Self::ASSIGN_INDEX_SHR => return write!(f, "[]>>="), - Self::ASSIGN_INDEX_IFNIL => return write!(f, "[]?="), - - Self::BEGIN_PROTO => return write!(f, "{{"), - Self::PROTO_INHERIT_READ => return write!(f, ""), - Self::END_PROTO => return write!(f, "}}"), - Self::PROTO_INHERIT_WRITE => return write!(f, ""), - Self::SCOPE_INHERIT_READ => return write!(f, ""), - Self::SCOPE_INHERIT_WRITE => return write!(f, ""), - Self::FIELD_INHERIT_READ => return write!(f, ""), - Self::FIELD_INHERIT_WRITE => return write!(f, ""), - Self::INDEX_INHERIT_READ => return write!(f, ""), - Self::INDEX_INHERIT_WRITE => return write!(f, ""), - Self::BEGIN_BARE => return write!(f, "{{"), - Self::END_BARE => return write!(f, "}}"), - - Self::METHOD_CALL_ARGS => return write!(f, "("), - Self::METHOD_CALL_EXEC => return write!(f, ")"), - Self::CALL_ARGS => return write!(f, "("), - Self::CALL_EXEC => return write!(f, ")"), - - Self::BEGIN_ARRAY => return write!(f, "["), - Self::END_ARRAY => return write!(f, "]"), - - Self::FN_ARGS => return write!(f, "|"), - Self::FN_LET_ARGS => return write!(f, "|"), - Self::FN_ARG_DYN => return write!(f, "fnarg"), - Self::FN_ARG_TYPED => return write!(f, "fnarg_ty"), - Self::FN_BODY_DYN => return write!(f, "|"), - Self::FN_BODY_TYPED => return write!(f, "|"), - Self::RETURN => return write!(f, "return"), - - Self::IF_TEST => return write!(f, "if"), - Self::IF_ELSE => return write!(f, "else"), - - Self::FIELD => return write!(f, "."), - Self::FIELD_NIL => return write!(f, ".?"), - Self::ME_FIELD => return write!(f, "me."), - Self::ARRAY_INDEX => return write!(f, "[]"), - - Self::PROTO_FIELD => return write!(f, "."), - Self::POP_TO_ME => return write!(f, ""), - - Self::LET_TYPED => return write!(f, "let_ty"), - Self::LET_DYN => return write!(f, "let"), - Self::VAR_TYPED => return write!(f, "var_ty"), - Self::VAR_DYN => return write!(f, "var"), - - Self::SEARCH_TREE => return write!(f, "$"), - Self::STRING_STREAM => return write!(f, ""), - Self::LOG => return write!(f, "log()"), - Self::ME => return write!(f, "me"), - Self::SCOPE => return write!(f, "scope"), - - Self::FOR_1 => return write!(f, "for1"), - Self::FOR_2 => return write!(f, "for2"), - Self::FOR_3 => return write!(f, "for2"), - Self::FOR_END => return write!(f, "forend"), - Self::LOOP => return write!(f, "loop"), - Self::BREAKIFNOT => return write!(f, "breakifnot"), - - Self::BREAK => return write!(f, "break"), - Self::CONTINUE => return write!(f, "continue"), - - Self::RANGE => return write!(f, ".."), - Self::IS => return write!(f, "is"), - Self::RETURN_IF_ERR => return write!(f, "?"), - Self::TRY_TEST => return write!(f, "try_test"), - Self::TRY_ERR => return write!(f, "try_err"), - Self::TRY_OK => return write!(f, "try_ok"), - Self::USE => return write!(f, "use"), - Self::OK_TEST => return write!(f, "ok_test"), - Self::OK_END => return write!(f, "ok_end"), - Self::ME_SPLAT => return write!(f, "..splat"), - Self::DUP => return write!(f, "dup"), - Self::DROP => return write!(f, "drop"), - Self::LET_DESTRUCT_ARRAY_EL => return write!(f, "let_arr_el"), - Self::LET_DESTRUCT_OBJECT_EL => return write!(f, "let_obj_el"), - Self::ARRAY_INDEX_NIL => return write!(f, "?[]"), - _ => return write!(f, "OP{}", self.0), - } - } -} diff --git a/vendor/makepad/platform/script/src/opcodes.rs b/vendor/makepad/platform/script/src/opcodes.rs deleted file mode 100644 index a295409..0000000 --- a/vendor/makepad/platform/script/src/opcodes.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! Opcode execution for the script virtual machine -//! -//! This module contains the main opcode dispatch function and re-exports -//! the handler implementations from the split modules: -//! - `opcodes_ops` - Arithmetic and comparison operations -//! - `opcodes_assign` - Assignment operations -//! - `opcodes_calls` - Function and method calls -//! - `opcodes_control` - Control flow (if, for, return, try/ok) -//! - `opcodes_vars` - Variables, fields, and object operations -//! - `opcodes_loops` - For loop helper functions - -use crate::opcode::*; -use crate::vm::ScriptVm; - -impl<'a> ScriptVm<'a> { - #[inline] - pub fn opcode(&mut self, opcode: Opcode, opargs: OpcodeArgs) { - match opcode { - // NOP placeholder emitted by parser rewrite passes (for markers / unary +). - // It intentionally performs no stack mutation and just advances IP. - Opcode::NOP => self.bx.threads.cur().trap.goto_next(), - - // ARITHMETIC - Opcode::NOT => self.handle_not(), - Opcode::NEG => self.handle_neg(), - Opcode::MUL => self.handle_mul(opargs), - Opcode::DIV => self.handle_div(opargs), - Opcode::MOD => self.handle_f64_op(opargs, |a, b| a % b), - Opcode::ADD => self.handle_add(opargs), - Opcode::SUB => self.handle_sub(opargs), - Opcode::SHL => self.handle_fu64_op(opargs, |a, b| a << b), - Opcode::SHR => self.handle_fu64_op(opargs, |a, b| a >> b), - Opcode::AND => self.handle_fu64_op(opargs, |a, b| a & b), - Opcode::OR => self.handle_fu64_op(opargs, |a, b| a | b), - Opcode::XOR => self.handle_fu64_op(opargs, |a, b| a ^ b), - - // ASSIGN - Opcode::ASSIGN => self.handle_assign(), - Opcode::ASSIGN_ADD => self.handle_assign_add(), - Opcode::ASSIGN_SUB => self.handle_f64_scope_assign_op(|a, b| a - b), - Opcode::ASSIGN_MUL => self.handle_f64_scope_assign_op(|a, b| a * b), - Opcode::ASSIGN_DIV => self.handle_f64_scope_assign_op(|a, b| a / b), - Opcode::ASSIGN_MOD => self.handle_f64_scope_assign_op(|a, b| a % b), - Opcode::ASSIGN_AND => self.handle_fu64_scope_assign_op(|a, b| a & b), - Opcode::ASSIGN_OR => self.handle_fu64_scope_assign_op(|a, b| a | b), - Opcode::ASSIGN_XOR => self.handle_fu64_scope_assign_op(|a, b| a ^ b), - Opcode::ASSIGN_SHL => self.handle_fu64_scope_assign_op(|a, b| a << b), - Opcode::ASSIGN_SHR => self.handle_fu64_scope_assign_op(|a, b| a >> b), - Opcode::ASSIGN_IFNIL => self.handle_assign_ifnil(opargs), - - // ASSIGN FIELD - Opcode::ASSIGN_FIELD => self.handle_assign_field(), - Opcode::ASSIGN_FIELD_ADD => self.handle_assign_field_add(), - Opcode::ASSIGN_FIELD_SUB => self.handle_f64_field_assign_op(|a, b| a - b), - Opcode::ASSIGN_FIELD_MUL => self.handle_f64_field_assign_op(|a, b| a * b), - Opcode::ASSIGN_FIELD_DIV => self.handle_f64_field_assign_op(|a, b| a / b), - Opcode::ASSIGN_FIELD_MOD => self.handle_f64_field_assign_op(|a, b| a % b), - Opcode::ASSIGN_FIELD_AND => self.handle_fu64_field_assign_op(|a, b| a & b), - Opcode::ASSIGN_FIELD_OR => self.handle_fu64_field_assign_op(|a, b| a | b), - Opcode::ASSIGN_FIELD_XOR => self.handle_fu64_field_assign_op(|a, b| a ^ b), - Opcode::ASSIGN_FIELD_SHL => self.handle_fu64_field_assign_op(|a, b| a << b), - Opcode::ASSIGN_FIELD_SHR => self.handle_fu64_field_assign_op(|a, b| a >> b), - Opcode::ASSIGN_FIELD_IFNIL => self.handle_assign_field_ifnil(), - - Opcode::ASSIGN_INDEX => self.handle_assign_index(), - Opcode::ASSIGN_INDEX_ADD => self.handle_assign_index_add(), - Opcode::ASSIGN_INDEX_SUB => self.handle_f64_index_assign_op(|a, b| a - b), - Opcode::ASSIGN_INDEX_MUL => self.handle_f64_index_assign_op(|a, b| a * b), - Opcode::ASSIGN_INDEX_DIV => self.handle_f64_index_assign_op(|a, b| a / b), - Opcode::ASSIGN_INDEX_MOD => self.handle_f64_index_assign_op(|a, b| a % b), - Opcode::ASSIGN_INDEX_AND => self.handle_fu64_index_assign_op(|a, b| a & b), - Opcode::ASSIGN_INDEX_OR => self.handle_fu64_index_assign_op(|a, b| a | b), - Opcode::ASSIGN_INDEX_XOR => self.handle_fu64_index_assign_op(|a, b| a ^ b), - Opcode::ASSIGN_INDEX_SHL => self.handle_fu64_index_assign_op(|a, b| a << b), - Opcode::ASSIGN_INDEX_SHR => self.handle_fu64_index_assign_op(|a, b| a >> b), - Opcode::ASSIGN_INDEX_IFNIL => self.handle_assign_index_ifnil(), - - // ASSIGN ME - Opcode::ASSIGN_ME => self.handle_assign_me(), - Opcode::ASSIGN_ME_VEC => self.handle_assign_me_vec(), - Opcode::ASSIGN_ME_BEFORE | Opcode::ASSIGN_ME_AFTER => { - self.handle_assign_me_before_after(opcode) - } - Opcode::ASSIGN_ME_BEGIN => self.handle_assign_me_begin(), - - // CONCAT - Opcode::CONCAT => self.handle_concat(), - - // EQUALITY - Opcode::EQ => self.handle_eq(), - Opcode::NEQ => self.handle_neq(), - Opcode::LT => self.handle_f64_cmp_op(opargs, |a, b| a < b), - Opcode::GT => self.handle_f64_cmp_op(opargs, |a, b| a > b), - Opcode::LEQ => self.handle_f64_cmp_op(opargs, |a, b| a <= b), - Opcode::GEQ => self.handle_f64_cmp_op(opargs, |a, b| a >= b), - - Opcode::LOGIC_AND_TEST => self.handle_logic_and_test(opargs), - Opcode::LOGIC_OR_TEST => self.handle_logic_or_test(opargs), - Opcode::NIL_OR_TEST => self.handle_nil_or_test(opargs), - Opcode::SHALLOW_EQ => self.handle_shallow_eq(), - Opcode::SHALLOW_NEQ => self.handle_shallow_neq(), - - // Object/Array begin - Opcode::BEGIN_PROTO => self.handle_begin_proto(), - Opcode::PROTO_INHERIT_READ => self.handle_proto_inherit_read(), - Opcode::PROTO_INHERIT_WRITE => self.handle_proto_inherit_write(), - Opcode::SCOPE_INHERIT_READ => self.handle_scope_inherit_read(), - Opcode::SCOPE_INHERIT_WRITE => self.handle_scope_inherit_write(), - Opcode::FIELD_INHERIT_READ => self.handle_field_inherit_read(), - Opcode::FIELD_INHERIT_WRITE => self.handle_field_inherit_write(), - Opcode::INDEX_INHERIT_READ => self.handle_index_inherit_read(), - Opcode::INDEX_INHERIT_WRITE => self.handle_index_inherit_write(), - Opcode::END_PROTO => self.handle_end_proto(), - Opcode::BEGIN_BARE => self.handle_begin_bare(), - Opcode::END_BARE => self.handle_end_bare(), - Opcode::BEGIN_ARRAY => self.handle_begin_array(), - Opcode::END_ARRAY => self.handle_end_array(), - - // Calling - Opcode::CALL_ARGS => self.handle_call_args(), - Opcode::CALL_EXEC | Opcode::METHOD_CALL_EXEC => { - let should_pop_to_me = self.handle_call_exec(opargs); - if self.bx.threads.cur_ref().has_execution_limit_exceeded() { - return; - } - if should_pop_to_me && opargs.is_pop_to_me() { - self.pop_to_me(); - } - return; - } - Opcode::METHOD_CALL_ARGS => { - if self.handle_method_call_args() { - // Pod case: return early, skip pop_to_me (original returned before end) - return; - } - // Normal case: falls through to end-of-function pop_to_me check - } - - // Fn def - Opcode::FN_ARGS => self.handle_fn_args(), - Opcode::FN_LET_ARGS => self.handle_fn_let_args(), - Opcode::FN_ARG_DYN => self.handle_fn_arg_dyn(opargs), - Opcode::FN_ARG_TYPED => self.handle_fn_arg_typed(opargs), - Opcode::FN_BODY_DYN => self.handle_fn_body_dyn(opargs), - Opcode::FN_BODY_TYPED => self.handle_fn_body_typed(opargs), - Opcode::RETURN => { - self.handle_return(opargs); - if self.bx.threads.cur_ref().has_execution_limit_exceeded() { - return; - } - if opargs.is_pop_to_me() { - self.pop_to_me(); - } - return; - } - Opcode::RETURN_IF_ERR => { - if self.handle_return_if_err(opargs) { - // Error case: original fell through to end-of-function check - if self.bx.threads.cur_ref().has_execution_limit_exceeded() { - return; - } - if opargs.is_pop_to_me() { - self.pop_to_me(); - } - return; - } - // Non-error case: falls through to end-of-function pop_to_me check - } - - // IF - Opcode::IF_TEST => self.handle_if_test(opargs), - Opcode::IF_ELSE => self.handle_if_else(opargs), - - // Use - Opcode::USE => { - self.handle_use(); - // Original returned early, skipping pop_to_me - return; - } - - // Field - Opcode::FIELD => self.handle_field(), - Opcode::FIELD_NIL => self.handle_field_nil(), - Opcode::ME_FIELD => self.handle_me_field(), - Opcode::PROTO_FIELD => self.handle_proto_field(), - Opcode::POP_TO_ME => self.handle_pop_to_me(), - Opcode::ME_SPLAT => self.handle_me_splat(), - - // Array index - Opcode::ARRAY_INDEX => self.handle_array_index(), - - // Let - Opcode::LET_DYN => self.handle_let_dyn(opargs), - Opcode::LET_TYPED => self.handle_let_typed(opargs), - Opcode::VAR_DYN => self.handle_var_dyn(opargs), - Opcode::VAR_TYPED => self.handle_var_typed(opargs), - - // Tree search - Opcode::SEARCH_TREE => self.handle_search_tree(), - - // Log - Opcode::LOG => self.handle_log(), - - // Me/Scope - Opcode::ME => self.handle_me(), - Opcode::SCOPE => self.handle_scope(), - - // For - Opcode::FOR_1 => self.handle_for_1(opargs), - Opcode::FOR_2 => self.handle_for_2(opargs), - Opcode::FOR_3 => self.handle_for_3(opargs), - Opcode::LOOP => self.handle_loop(opargs), - Opcode::FOR_END => self.handle_for_end(), - Opcode::BREAK => self.handle_break(), - Opcode::BREAKIFNOT => self.handle_breakifnot(), - Opcode::CONTINUE => self.handle_continue(), - - // Range - Opcode::RANGE => self.handle_range(), - - // Is - Opcode::IS => self.handle_is(), - - // Try / OK - Opcode::OK_TEST => self.handle_ok_test(opargs), - Opcode::OK_END => self.handle_ok_end(), - Opcode::TRY_TEST => self.handle_try_test(opargs), - Opcode::TRY_ERR => self.handle_try_err(opargs), - Opcode::TRY_OK => self.handle_try_ok(opargs), - - // Destructuring - Opcode::DUP => self.handle_dup(), - Opcode::DROP => self.handle_drop(), - Opcode::ARRAY_INDEX_NIL => self.handle_array_index_nil(), - Opcode::LET_DESTRUCT_ARRAY_EL => self.handle_let_destruct_array_el(opargs), - Opcode::LET_DESTRUCT_OBJECT_EL => self.handle_let_destruct_object_el(), - - _ => self.bail("undefined VM opcode"), - } - if self.bx.threads.cur_ref().has_execution_limit_exceeded() { - return; - } - if opargs.is_pop_to_me() { - self.pop_to_me(); - } - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_assign.rs b/vendor/makepad/platform/script/src/opcodes_assign.rs deleted file mode 100644 index d023ce3..0000000 --- a/vendor/makepad/platform/script/src/opcodes_assign.rs +++ /dev/null @@ -1,775 +0,0 @@ -//! Opcode assignment operations -//! -//! This module contains handle functions for assignment operations: -//! ASSIGN, ASSIGN_FIELD, ASSIGN_INDEX, and ASSIGN_ME variants. - -use crate::opcode::*; -use crate::thread::*; -use crate::value::*; -use crate::vm::ScriptVm; -use crate::*; - -impl<'a> ScriptVm<'a> { - // ASSIGN handlers - - pub(crate) fn handle_assign(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self.bx.threads.cur().pop_stack_value(); - if let Some(id) = id.as_id() { - let value = self - .bx - .threads - .cur() - .set_scope_value(&mut self.bx.heap, id, value); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "assign target is not an identifier, got {:?}", - id.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_add(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self.bx.threads.cur().pop_stack_value(); - if let Some(id) = id.as_id() { - let old_value = self.bx.threads.cur().scope_value(&self.bx.heap, id); - if old_value.is_err() { - self.bx.threads.cur().push_stack_unchecked(old_value); - } else if old_value.is_string_like() || value.is_string_like() { - let str = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(old_value, out); - heap.cast_to_string(value, out); - }); - self.bx - .threads - .cur() - .set_scope_value(&mut self.bx.heap, id, str.into()); - self.bx.threads.cur().push_stack_unchecked(NIL); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.threads.cur().set_scope_value( - &mut self.bx.heap, - id, - ScriptValue::from_f64_traced_nan(fa + fb, ip), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "+= target is not an identifier, got {:?}", - id.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - /// ASSIGN_IFNIL - lazy evaluation: checks if scope var is nil - /// Stack: [id] -> [id] (continue) or [] (jump) - /// If scope[id] is NOT nil: pop id, push nil, jump to skip RHS - /// If scope[id] IS nil: leave id on stack, continue to evaluate RHS then ASSIGN - pub(crate) fn handle_assign_ifnil(&mut self, opargs: OpcodeArgs) { - let id = self.bx.threads.cur().peek_stack_value(); - if let Some(id_val) = id.as_id() { - let va = self.bx.threads.cur().scope_value(&self.bx.heap, id_val); - if !va.is_err() && !va.is_nil() { - // Value is NOT nil - skip the RHS evaluation - // Pop the id from stack and push nil as result - self.bx.threads.cur().pop_stack_value(); - self.bx.threads.cur().push_stack_unchecked(NIL); - // Jump past the RHS and ASSIGN - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } else { - // Value IS nil - continue to evaluate RHS - // Leave id on stack for ASSIGN to use later - self.bx.threads.cur().trap.goto_next(); - } - } else { - // Not an identifier - error - self.bx.threads.cur().pop_stack_value(); - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "?= target is not an identifier, got {:?}", - id.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - } - } - - // ASSIGN FIELD handlers - - pub(crate) fn handle_assign_field(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let value = - self.bx - .heap - .set_value(obj, field, value, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "cannot assign field {:?} on {:?} (not an object)", - field, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_field_add(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - if old_value.is_string_like() || value.is_string_like() { - let str = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(old_value, out); - heap.cast_to_string(value, out); - }); - let value = self.bx.heap.set_value( - obj, - field, - str.into(), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_value( - obj, - field, - ScriptValue::from_f64_traced_nan(fa + fb, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "cannot += field {:?} on {:?} (not an object)", - field, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_field_ifnil(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - if old_value.is_err() || old_value.is_nil() { - let value = - self.bx - .heap - .set_value(obj, field, value, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - self.bx.threads.cur().push_stack_unchecked(NIL); - } - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "cannot ?= field {:?} on {:?} (not an object)", - field, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - // ASSIGN INDEX handlers - - pub(crate) fn handle_assign_index(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - // Escaped ids (@x) from variables need to be unescaped for use as property keys - let index = if index.is_escaped_id() { - ScriptValue::from_id(index.as_id().unwrap()) - } else { - index - }; - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let value = - self.bx - .heap - .set_value(obj, index, value, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - self.bx - .heap - .set_array_index(arr, index, value, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "cannot assign index {:?} on {:?} (not an object/array)", - index, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_index_add(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - if old_value.is_string_like() || value.is_string_like() { - let str = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(old_value, out); - heap.cast_to_string(value, out); - }); - let value = self.bx.heap.set_value( - obj, - index, - str.into(), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_value( - obj, - index, - ScriptValue::from_f64_traced_nan(fa + fb, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let old_value = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - if old_value.is_string_like() || value.is_string_like() { - let str = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(old_value, out); - heap.cast_to_string(value, out); - }); - let value = self.bx.heap.set_array_index( - arr, - index, - str.into(), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_array_index( - arr, - index, - ScriptValue::from_f64_traced_nan(fa + fb, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "cannot += index {:?} on {:?} (not an object/array)", - index, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_index_ifnil(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - if old_value.is_err() || old_value.is_nil() { - let value = - self.bx - .heap - .set_value(obj, index, value, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - self.bx.threads.cur().push_stack_unchecked(NIL); - } - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let old_value = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - if old_value.is_err() || old_value.is_nil() { - let value = self.bx.heap.set_array_index( - arr, - index, - value, - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - self.bx.threads.cur().push_stack_unchecked(NIL); - } - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "cannot ?= index {:?} on {:?} (not an object/array)", - index, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - // ASSIGN ME handlers - - pub(crate) fn handle_assign_me(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - if self.bx.threads.cur_ref().call_has_me() { - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_assign_me"); - return; - }; - match me { - ScriptMe::Call { args, .. } => { - let args = *args; - self.bx.heap.named_fn_arg( - args, - field, - value, - self.bx.threads.cur().trap.pass(), - ); - } - ScriptMe::Object(obj) => { - let obj = *obj; - if field.is_string_like() { - self.bx.heap.set_string_keys(obj); - } - self.bx - .heap - .set_value(obj, field, value, self.bx.threads.cur().trap.pass()); - } - ScriptMe::Pod { pod, .. } => { - let pod = *pod; - self.bx.heap.set_pod_field( - pod, - field, - value, - self.bx.threads.cur().trap.pass(), - ); - } - ScriptMe::Array(_arr) => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "named assign {:?} not allowed in array literal context", - field - ); - } - } - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_me_vec(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - if self.bx.threads.cur_ref().call_has_me() { - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_assign_me_vec"); - return; - }; - match me { - ScriptMe::Call { args, .. } => { - let args = *args; - self.bx.heap.named_fn_arg( - args, - field, - value, - self.bx.threads.cur().trap.pass(), - ); - } - ScriptMe::Object(obj) => { - let obj = *obj; - self.bx.heap.set_value_vec( - obj, - field, - value, - self.bx.threads.cur().trap.pass(), - ); - } - ScriptMe::Pod { pod, .. } => { - let pod = *pod; - self.bx.heap.set_pod_field( - pod, - field, - value, - self.bx.threads.cur().trap.pass(), - ); - } - ScriptMe::Array(_arr) => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "vec assign {:?} not allowed in array literal context", - field - ); - } - } - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_me_before_after(&mut self, opcode: Opcode) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_assign_me_before_after"); - return; - }; - let value = match me { - ScriptMe::Call { .. } | ScriptMe::Pod { .. } => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "before/after {:?} not allowed in function call arguments", - field - ) - } - ScriptMe::Object(obj) => { - let obj = *obj; - self.bx.heap.vec_insert_value_at( - obj, - field, - value, - opcode == Opcode::ASSIGN_ME_BEFORE, - self.bx.threads.cur().trap.pass(), - ) - } - ScriptMe::Array(_arr) => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "before/after {:?} not allowed in array literal context", - field - ) - } - }; - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_assign_me_begin(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_assign_me_begin"); - return; - }; - let value = match me { - ScriptMe::Call { .. } | ScriptMe::Pod { .. } => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "begin {:?} not allowed in function call arguments", - field - ) - } - ScriptMe::Object(obj) => { - let obj = *obj; - self.bx.heap.vec_insert_value_begin( - obj, - field, - value, - self.bx.threads.cur().trap.pass(), - ) - } - ScriptMe::Array(_arr) => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "begin {:?} not allowed in array literal context", - field - ) - } - }; - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - } - - // Generic assignment operation handlers - - pub fn handle_f64_scope_assign_op(&mut self, f: F) - where - F: FnOnce(f64, f64) -> f64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self.bx.threads.cur().pop_stack_value(); - if let Some(id) = id.as_id() { - let va = self.bx.threads.cur().scope_value(&self.bx.heap, id); - if va.is_err() { - self.bx.threads.cur().push_stack_unchecked(va); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(va, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.threads.cur().set_scope_value( - &mut self.bx.heap, - id, - ScriptValue::from_f64_traced_nan(f(fa, fb), ip), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "compound assignment target is not an identifier, got {:?}", - id.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_fu64_scope_assign_op(&mut self, f: F) - where - F: FnOnce(u64, u64) -> u64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self.bx.threads.cur().pop_stack_value(); - if let Some(id) = id.as_id() { - let old_value = self.bx.threads.cur().scope_value(&self.bx.heap, id); - if old_value.is_err() { - self.bx.threads.cur().push_stack_unchecked(old_value); - } else { - let ip = self.bx.threads.cur_ref().trap.ip; - let ua = self.bx.heap.cast_to_f64(old_value, ip) as u64; - let ub = self.bx.heap.cast_to_f64(value, ip) as u64; - let value = self.bx.threads.cur().set_scope_value( - &mut self.bx.heap, - id, - ScriptValue::from_f64_traced_nan(f(ua, ub) as f64, ip), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "bitwise compound assignment target is not an identifier, got {:?}", - id.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_f64_field_assign_op(&mut self, f: F) - where - F: FnOnce(f64, f64) -> f64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_value( - obj, - field, - ScriptValue::from_f64_traced_nan(f(fa, fb), ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "field compound assignment on {:?} (not an object)", - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_fu64_field_assign_op(&mut self, f: F) - where - F: FnOnce(u64, u64) -> u64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip) as u64; - let fb = self.bx.heap.cast_to_f64(value, ip) as u64; - let value = self.bx.heap.set_value( - obj, - field, - ScriptValue::from_f64_traced_nan(f(fa, fb) as f64, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "field bitwise compound assignment on {:?} (not an object)", - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_f64_index_assign_op(&mut self, f: F) - where - F: FnOnce(f64, f64) -> f64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_value( - obj, - index, - ScriptValue::from_f64_traced_nan(f(fa, fb), ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let old_value = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip); - let fb = self.bx.heap.cast_to_f64(value, ip); - let value = self.bx.heap.set_array_index( - arr, - index, - ScriptValue::from_f64_traced_nan(f(fa, fb), ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "index compound assignment on {:?} (not an object/array)", - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_fu64_index_assign_op(&mut self, f: F) - where - F: FnOnce(u64, u64) -> u64, - { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let old_value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip) as u64; - let fb = self.bx.heap.cast_to_f64(value, ip) as u64; - let value = self.bx.heap.set_value( - obj, - index, - ScriptValue::from_f64_traced_nan(f(fa, fb) as f64, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let old_value = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - let ip = self.bx.threads.cur_ref().trap.ip; - let fa = self.bx.heap.cast_to_f64(old_value, ip) as u64; - let fb = self.bx.heap.cast_to_f64(value, ip) as u64; - let value = self.bx.heap.set_array_index( - arr, - index, - ScriptValue::from_f64_traced_nan(f(fa, fb) as f64, ip), - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_immutable!( - self.bx.threads.cur_ref().trap, - "index bitwise compound assignment on {:?} (not an object/array)", - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_calls.rs b/vendor/makepad/platform/script/src/opcodes_calls.rs deleted file mode 100644 index 2a4b870..0000000 --- a/vendor/makepad/platform/script/src/opcodes_calls.rs +++ /dev/null @@ -1,443 +0,0 @@ -//! Opcode function and method call operations -//! -//! This module contains handle functions for function calls, method calls, -//! function definitions, and related operations. - -use crate::function::*; -use crate::makepad_live_id::*; -use crate::opcode::*; -use crate::pod::ScriptPodOffset; -use crate::thread::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; -use crate::*; - -impl<'a> ScriptVm<'a> { - // Calling handlers - - pub(crate) fn handle_call_args(&mut self) { - let fnobj = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(ty) = self.bx.heap.pod_type(fnobj) { - let pod = self.bx.heap.new_pod(ty); - self.bx.threads.cur().mes.push(ScriptMe::Pod { - pod, - offset: ScriptPodOffset::default(), - }); - } else { - let scope = self.bx.heap.new_with_proto(fnobj); - self.bx.heap.clear_object_deep(scope); - self.bx.threads.cur().mes.push(ScriptMe::Call { - args: scope, - sself: None, - method: None, - }); - } - self.bx.threads.cur().trap.goto_next(); - } - - // Returns true if caller should call pop_to_me, false if it should be skipped - pub(crate) fn handle_call_exec(&mut self, opargs: OpcodeArgs) -> bool { - let Some(me) = self.bx.threads.cur().mes.pop() else { - self.bail("mes empty in handle_call_exec"); - return false; - }; - - let (args, sself, method) = match me { - ScriptMe::Call { - args, - sself, - method, - } => (args, sself, method), - ScriptMe::Pod { pod, offset } => { - self.bx - .heap - .pod_check_arg_total(pod, offset, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(pod.into()); - self.bx.threads.cur().trap.goto_next(); - return true; // Pod: caller should handle pop_to_me - } - _ => { - self.bail("unexpected me type in handle_call_exec"); - return false; - } - }; - - if let Some(sself) = sself { - self.bx - .heap - .force_value_in_map(args, id!(self).into(), sself); - } - self.bx.heap.set_object_deep(args); - self.bx.heap.set_object_storage_auto(args); - - // Dynamic dispatch via call: when handle_method_call_args set - // method, there is no fn proto — dispatch through the type's - // registered call function instead. - if let Some(method) = method { - let sself = sself.unwrap_or(NIL); - let type_index = sself.value_type().to_redux(); - let call_ptr: Option< - *const dyn Fn(&mut ScriptVm, ScriptObject, LiveId) -> ScriptValue, - > = { - let native = self.bx.code.native.borrow(); - native - .calls - .get(type_index.to_index()) - .and_then(|c| c.as_ref().map(|f| &**f as *const _)) - }; - if let Some(call_ptr) = call_ptr { - let ip = self.bx.threads.cur_ref().trap.ip; - // Pause thread before native call so re-entrant calls get a different thread - self.bx.threads.cur().is_paused = true; - // SAFETY: The call pointer is valid as long as native calls aren't removed during execution - let ret = unsafe { (*call_ptr)(self, args, method) }; - - // Check if call explicitly paused (via pause() which sets trap.on to Pause) - if matches!( - self.bx.threads.cur().trap.on.get(), - Some(ScriptTrapOn::Pause) - ) { - // Re-push the me so it can be re-executed on resume - self.bx.threads.cur().mes.push(ScriptMe::Call { - args, - sself: Some(sself), - method: Some(method), - }); - return false; // Paused: skip pop_to_me, function not complete - } - - // Call didn't explicitly pause, unpause the thread - self.bx.threads.cur().is_paused = false; - - self.bx.threads.cur().trap.ip = ip; - self.bx.threads.cur().push_stack_value(ret); - self.bx.heap.free_object_if_unreffed(args); - self.bx.threads.cur().trap.goto_next(); - return true; // Call complete - } - // No call handler registered - fall through to error - let value = script_err_not_found!( - self.bx.threads.cur_ref().trap, - "no call handler for method {:?} on type {:?}", - method, - type_index - ); - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - return true; - } - - if let Some(fnptr) = self.bx.heap.parent_as_fn(args) { - match fnptr { - ScriptFnPtr::Native(ni) => { - let ip = self.bx.threads.cur_ref().trap.ip; - // Get the function pointer and drop the borrow before calling - let func_ptr: *const dyn Fn(&mut ScriptVm, ScriptObject) -> ScriptValue = { - let native = self.bx.code.native.borrow(); - &*native.functions[ni.index as usize] as *const _ - }; - // Pause thread before native call so re-entrant calls get a different thread - self.bx.threads.cur().is_paused = true; - // SAFETY: The function pointer is valid as long as native functions aren't removed during execution - let ret = unsafe { (*func_ptr)(self, args) }; - - // Check if native explicitly paused (via pause() which sets trap.on to Pause) - if matches!( - self.bx.threads.cur().trap.on.get(), - Some(ScriptTrapOn::Pause) - ) { - // Native explicitly paused, leave is_paused = true - self.bx.threads.cur().mes.push(ScriptMe::Call { - args, - sself, - method: None, - }); - return false; // Paused: skip pop_to_me, function not complete - } - - // Native didn't explicitly pause, unpause the thread - self.bx.threads.cur().is_paused = false; - - self.bx.threads.cur().trap.ip = ip; - self.bx.threads.cur().push_stack_value(ret); - self.bx.heap.free_object_if_unreffed(args); // DISABLED: investigating RootObject already freed - self.bx.threads.cur().trap.goto_next(); - return true; // Native complete: caller should handle pop_to_me - } - ScriptFnPtr::Script(sip) => { - let call = CallFrame { - bases: self.bx.threads.cur_ref().new_bases(), - args: opargs, - return_ip: Some(ScriptIp { - index: self.bx.threads.cur_ref().trap.ip.index + 1, - body: self.bx.threads.cur_ref().trap.ip.body, - }), - }; - if !self.bx.threads.cur().push_call_frame(call) { - return false; - } - self.bx.threads.cur().scopes.push(args); - self.bx.threads.cur().trap.ip = sip; - return false; // Script: skip pop_to_me, RETURN will handle it via call.args - } - } - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "call target is not a function (got {:?})", - self.bx.heap.proto(args).value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - return true; // Error: caller should handle pop_to_me - } - } - - pub(crate) fn handle_method_call_args(&mut self) -> bool { - let method = self.bx.threads.cur().pop_stack_value(); - let sself = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let fnobj = if let Some(obj) = sself.as_object() { - self.bx.heap.object_method(obj, method, NoTrap) - } else if let Some(pod) = sself.as_pod() { - self.bx.heap.pod_method(pod, method, NoTrap) - } else { - NIL - }; - - let args = if fnobj.is_err() || fnobj == NIL { - let method = method.as_id().unwrap_or(id!()); - let type_index = sself.value_type().to_redux(); - let (found_method, has_call) = { - let native = self.bx.code.native.borrow(); - let type_entry = &native.type_table[type_index.to_index()]; - let found = type_entry.get(&method).copied(); - let has_call = native - .calls - .get(type_index.to_index()) - .map(|c| c.is_some()) - .unwrap_or(false); - (found, has_call) - }; - if let Some(method_ptr) = found_method { - self.bx.heap.new_with_proto(method_ptr.into()) - } else if has_call { - // Dynamic dispatch via call: create an empty vec2 args object. - // The call function will be invoked in handle_call_exec with - // the method name and collected arguments. - let args = self.bx.heap.new_with_proto(NIL); - self.bx.heap.set_object_storage_vec2(args); - self.bx.heap.clear_object_deep(args); - - self.bx.threads.cur().mes.push(ScriptMe::Call { - args, - sself: Some(sself), - method: Some(method), - }); - self.bx.threads.cur().trap.goto_next(); - return false; - } else { - script_err_not_found!( - self.bx.threads.cur_ref().trap, - "method {:?} not found on {}", - method, - type_index - ); - self.bx.heap.new_with_proto(id!(undefined_function).into()) - } - } else { - if let Some(ty) = self.bx.heap.pod_type(fnobj) { - let pod = self.bx.heap.new_pod(ty); - self.bx.threads.cur().mes.push(ScriptMe::Pod { - pod, - offset: ScriptPodOffset::default(), - }); - self.bx.threads.cur().trap.goto_next(); - return true; // Pod: caller should return early, skip pop_to_me - } - self.bx.heap.new_with_proto(fnobj) - }; - self.bx.heap.clear_object_deep(args); - - self.bx.threads.cur().mes.push(ScriptMe::Call { - args, - sself: Some(sself), - method: None, - }); - self.bx.threads.cur().trap.goto_next(); - false - } - - // Fn def handlers - - pub(crate) fn handle_fn_args(&mut self) { - let Some(&scope) = self.bx.threads.cur_ref().scopes.last() else { - self.bail("scopes empty in handle_fn_args"); - return; - }; - let me = self.bx.heap.new_with_proto(scope.into()); - self.bx.heap.set_object_storage_vec2(me); - self.bx.heap.clear_object_deep(me); - self.bx.threads.cur().mes.push(ScriptMe::Object(me)); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_fn_let_args(&mut self) { - let id = self - .bx - .threads - .cur() - .pop_stack_value() - .as_id() - .unwrap_or(id!()); - let Some(&scope) = self.bx.threads.cur_ref().scopes.last() else { - self.bail("scopes empty in handle_fn_let_args"); - return; - }; - let me = self.bx.heap.new_with_proto(scope.into()); - self.bx.heap.set_object_storage_vec2(me); - self.bx.heap.clear_object_deep(me); - self.bx.threads.cur().mes.push(ScriptMe::Object(me)); - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, me.into()); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_fn_arg_dyn(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let id = self - .bx - .threads - .cur() - .pop_stack_value() - .as_id() - .unwrap_or(id!()); - - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_fn_arg_dyn"); - return; - }; - match me { - ScriptMe::Call { .. } | ScriptMe::Array(_) | ScriptMe::Pod { .. } => { - script_err_unexpected!( - self.bx.threads.cur_ref().trap, - "FN_ARG_DYN for {:?}: expected Object context on stack", - id - ); - } - ScriptMe::Object(obj) => { - if id == id!(self) && self.bx.heap.vec_len(*obj) == 0 { - // ignore self as first argument - } else { - self.bx.heap.set_value(*obj, id.into(), value, NoTrap); - } - } - }; - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_fn_arg_typed(&mut self, opargs: OpcodeArgs) { - let _value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let ty = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self - .bx - .threads - .cur() - .pop_stack_value() - .as_id() - .unwrap_or(id!()); - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in handle_fn_arg_typed"); - return; - }; - match me { - ScriptMe::Call { .. } | ScriptMe::Array(_) | ScriptMe::Pod { .. } => { - script_err_unexpected!( - self.bx.threads.cur_ref().trap, - "FN_ARG_TYPED for {:?}: expected Object context on stack", - id - ); - } - ScriptMe::Object(obj) => { - self.bx.heap.set_value(*obj, id.into(), ty, NoTrap); - } - }; - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_fn_body_dyn(&mut self, opargs: OpcodeArgs) { - let jump_over_fn = opargs.to_u32(); - if let Some(me) = self.bx.threads.cur().mes.pop() { - match me { - ScriptMe::Call { .. } | ScriptMe::Array(_) | ScriptMe::Pod { .. } => { - script_err_unexpected!( - self.bx.threads.cur_ref().trap, - "FN_BODY_DYN: expected Object context for function body, got {:?}", - me - ); - self.bx.threads.cur().push_stack_unchecked(NIL); - } - ScriptMe::Object(obj) => { - self.bx.heap.set_fn( - obj, - ScriptFnPtr::Script(ScriptIp { - body: self.bx.threads.cur_ref().trap.ip.body, - index: (self.bx.threads.cur_ref().trap.ip() + 1), - }), - ); - self.bx.threads.cur().push_stack_unchecked(obj.into()); - } - }; - self.bx.threads.cur().trap.goto_rel(jump_over_fn); - } else { - script_err_unexpected!( - self.bx.threads.cur_ref().trap, - "FN_BODY_DYN: me stack is empty (function definition without arguments block)" - ); - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - } - - pub(crate) fn handle_fn_body_typed(&mut self, opargs: OpcodeArgs) { - let jump_over_fn = opargs.to_u32(); - let _return_type = self.bx.threads.cur().pop_stack_value(); - if let Some(me) = self.bx.threads.cur().mes.pop() { - match me { - ScriptMe::Call { .. } | ScriptMe::Array(_) | ScriptMe::Pod { .. } => { - script_err_unexpected!( - self.bx.threads.cur_ref().trap, - "FN_BODY_TYPED: expected Object context for typed function body, got {:?}", - me - ); - self.bx.threads.cur().push_stack_unchecked(NIL); - } - ScriptMe::Object(obj) => { - self.bx.heap.set_fn( - obj, - ScriptFnPtr::Script(ScriptIp { - body: self.bx.threads.cur_ref().trap.ip.body, - index: (self.bx.threads.cur_ref().trap.ip() + 1), - }), - ); - self.bx.threads.cur().push_stack_unchecked(obj.into()); - } - }; - self.bx.threads.cur().trap.goto_rel(jump_over_fn); - } else { - script_err_unexpected!(self.bx.threads.cur_ref().trap, "FN_BODY_TYPED: me stack is empty (typed function definition without arguments block)"); - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_control.rs b/vendor/makepad/platform/script/src/opcodes_control.rs deleted file mode 100644 index bfd10c5..0000000 --- a/vendor/makepad/platform/script/src/opcodes_control.rs +++ /dev/null @@ -1,354 +0,0 @@ -//! Opcode control flow operations -//! -//! This module contains handle functions for control flow: if/else statements, -//! for loops, return statements, range, is, and try/ok operations. - -use crate::makepad_live_id::*; -use crate::opcode::*; -use crate::thread::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::ScriptVm; -use crate::*; - -impl<'a> ScriptVm<'a> { - // IF handlers - - pub(crate) fn handle_if_test(&mut self, opargs: OpcodeArgs) { - let test = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let test = self.bx.heap.cast_to_bool(test); - if test { - self.bx.threads.cur().trap.goto_next() - } else { - if opargs.is_need_nil() { - self.bx.threads.cur().push_stack_unchecked(NIL); - } - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } - } - - pub(crate) fn handle_if_else(&mut self, opargs: OpcodeArgs) { - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } - - // RETURN handlers - - pub(crate) fn handle_return(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let Some(call) = self.bx.threads.cur().calls.pop() else { - self.bail("calls empty in handle_return"); - return; - }; - self.bx - .threads - .cur() - .truncate_bases(call.bases, &mut self.bx.heap); - - if let Some(ret) = call.return_ip { - self.bx.threads.cur().trap.ip = ret; - self.bx.threads.cur().push_stack_unchecked(value); - if !self.bx.threads.cur_ref().has_execution_limit_exceeded() && call.args.is_pop_to_me() - { - self.pop_to_me(); - } - } else { - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Return(value))); - } - } - - pub(crate) fn handle_return_if_err(&mut self, _opargs: OpcodeArgs) -> bool { - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - if value.is_err() { - let Some(call) = self.bx.threads.cur().calls.pop() else { - self.bail("calls empty in handle_return_if_err"); - return true; - }; - self.bx - .threads - .cur() - .truncate_bases(call.bases, &mut self.bx.heap); - if let Some(ret) = call.return_ip { - self.bx.threads.cur().trap.ip = ret; - self.bx.threads.cur().push_stack_unchecked(value); - if !self.bx.threads.cur_ref().has_execution_limit_exceeded() - && call.args.is_pop_to_me() - { - self.pop_to_me(); - } - } else { - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Return(value))); - } - true - } else { - self.bx.threads.cur().trap.goto_next(); - false - } - } - - // For loop handlers - - pub(crate) fn handle_for_1(&mut self, opargs: OpcodeArgs) { - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let Some(value_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_1 value_id not an id"); - return; - }; - self.begin_for_loop(opargs.to_u32() as _, source, value_id, None, None); - } - - pub(crate) fn handle_for_2(&mut self, opargs: OpcodeArgs) { - // for k v in source: k = key (obj) or index (array/range), v = value - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let Some(value_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_2 value_id not an id"); - return; - }; - let Some(first_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_2 first_id not an id"); - return; - }; - // Pass first_id as key_id - for objects it gets key, for arrays/ranges it gets index - self.begin_for_loop(opargs.to_u32() as _, source, value_id, None, Some(first_id)); - } - - pub(crate) fn handle_for_3(&mut self, opargs: OpcodeArgs) { - // for i k v in source: i = index, k = key, v = value (objects only) - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let Some(value_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_3 value_id not an id"); - return; - }; - let Some(key_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_3 key_id not an id"); - return; - }; - let Some(index_id) = self.bx.threads.cur().pop_stack_value().as_id() else { - self.bail("for_3 index_id not an id"); - return; - }; - self.begin_for_loop( - opargs.to_u32() as _, - source, - value_id, - Some(index_id), - Some(key_id), - ); - } - - pub(crate) fn handle_loop(&mut self, opargs: OpcodeArgs) { - self.begin_loop(opargs.to_u32() as _); - } - - pub(crate) fn handle_for_end(&mut self) { - self.end_for_loop(); - } - - pub(crate) fn handle_break(&mut self) { - self.break_for_loop(); - } - - pub(crate) fn handle_breakifnot(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if !self.bx.heap.cast_to_bool(value) { - self.break_for_loop(); - } else { - self.bx.threads.cur().trap.goto_next(); - } - } - - pub(crate) fn handle_continue(&mut self) { - self.end_for_loop(); - } - - // Range handler - - pub(crate) fn handle_range(&mut self) { - let end = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let start = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if !start.is_number() { - let err = script_err_type_mismatch!( - self.bx.threads.cur().trap, - "range must start with a number, did you forget a , before a splat operator?" - ); - self.bx.threads.cur().push_stack_unchecked(err); - self.bx.threads.cur().trap.goto_next(); - return; - } - if !end.is_number() { - let err = - script_err_type_mismatch!(self.bx.threads.cur().trap, "range end must be a number"); - self.bx.threads.cur().push_stack_unchecked(err); - self.bx.threads.cur().trap.goto_next(); - return; - } - let range = self - .bx - .heap - .new_with_proto(self.bx.code.builtins.range.into()); - self.bx.heap.set_value_def(range, id!(start).into(), start); - self.bx.heap.set_value_def(range, id!(end).into(), end); - self.bx.threads.cur().push_stack_unchecked(range.into()); - self.bx.threads.cur().trap.goto_next(); - } - - // Is handler - - pub(crate) fn handle_is(&mut self) { - let rhs = self.bx.threads.cur().pop_stack_value(); - let lhs = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let cmp = if let Some(id) = rhs.as_id() { - let ty = lhs.value_type(); - let is_number = id == id!(number).into(); - match ty { - // All numeric types match "is number" - ScriptValueType::F64 - | ScriptValueType::F32 - | ScriptValueType::F16 - | ScriptValueType::U32 - | ScriptValueType::I32 - | ScriptValueType::U40 => is_number, - ScriptValueType::NAN => is_number || id == id!(nan).into(), - ScriptValueType::BOOL => id == id!(bool).into(), - ScriptValueType::NIL => id == id!(nil).into(), - ScriptValueType::COLOR => id == id!(color).into(), - ScriptValueType::OBJECT => { - id == id!(object).into() || { - if let Some(rhs) = self - .bx - .threads - .cur() - .scope_value(&self.bx.heap, id) - .as_object() - { - if let Some(obj) = lhs.as_object() { - self.bx.heap.has_proto(obj, rhs.into()) - } else { - false - } - } else { - false - } - } - } - ScriptValueType::ARRAY => id == id!(array).into(), - ScriptValueType::REGEX => id == id!(regex).into(), - _ if ty.to_redux() == ScriptValueType::REDUX_STRING => id == id!(string).into(), - _ if ty.to_redux() == ScriptValueType::REDUX_ID => id == id!(id).into(), - _ => false, - } - } else if rhs.is_nil() { - // `x is nil` where nil is the actual value - lhs.is_nil() - } else if let Some(obj) = lhs.as_object() { - self.bx.heap.has_proto(obj, rhs) - } else { - false - }; - self.bx.threads.cur().push_stack_unchecked(cmp.into()); - self.bx.threads.cur().trap.goto_next(); - } - - // Short-circuit evaluation handlers - - /// || short-circuit: if first operand is truthy, skip second operand and keep value - pub(crate) fn handle_logic_or_test(&mut self, opargs: OpcodeArgs) { - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - let test = self.bx.heap.cast_to_bool(value); - if test { - // First operand is truthy - skip second operand, keep value on stack - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } else { - // First operand is falsy - pop it and evaluate second operand - self.bx.threads.cur().pop_stack_value(); - self.bx.threads.cur().trap.goto_next(); - } - } - - /// && short-circuit: if first operand is falsy, skip second operand and keep value - pub(crate) fn handle_logic_and_test(&mut self, opargs: OpcodeArgs) { - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - let test = self.bx.heap.cast_to_bool(value); - if !test { - // First operand is falsy - skip second operand, keep value on stack - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } else { - // First operand is truthy - pop it and evaluate second operand - self.bx.threads.cur().pop_stack_value(); - self.bx.threads.cur().trap.goto_next(); - } - } - - /// |? short-circuit: if first operand is not nil, skip second operand and keep value - pub(crate) fn handle_nil_or_test(&mut self, opargs: OpcodeArgs) { - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - if !value.is_nil() { - // First operand is not nil - skip second operand, keep value on stack - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } else { - // First operand is nil - pop it and evaluate second operand - self.bx.threads.cur().pop_stack_value(); - self.bx.threads.cur().trap.goto_next(); - } - } - - // Try / OK handlers - - pub(crate) fn handle_ok_test(&mut self, opargs: OpcodeArgs) { - let ip = self.bx.threads.cur_ref().trap.ip(); - let bases = self.bx.threads.cur_ref().new_bases(); - self.bx.threads.cur().tries.push(TryFrame { - push_nil: true, - start_ip: ip, - jump: opargs.to_u32() + 1, - bases, - }); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_ok_end(&mut self) { - if self.bx.threads.cur().tries.pop().is_none() { - self.bail("tries empty in handle_ok_end"); - return; - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_try_test(&mut self, opargs: OpcodeArgs) { - let ip = self.bx.threads.cur_ref().trap.ip(); - let bases = self.bx.threads.cur_ref().new_bases(); - self.bx.threads.cur().tries.push(TryFrame { - push_nil: false, - start_ip: ip, - jump: opargs.to_u32() + 1, - bases, - }); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_try_err(&mut self, opargs: OpcodeArgs) { - if self.bx.threads.cur().tries.pop().is_none() { - self.bail("tries empty in handle_try_err"); - return; - } - // The parser includes the optional legacy OK guard in this distance. - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } - - pub(crate) fn handle_try_ok(&mut self, opargs: OpcodeArgs) { - self.bx.threads.cur().trap.goto_rel(opargs.to_u32()); - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_loops.rs b/vendor/makepad/platform/script/src/opcodes_loops.rs deleted file mode 100644 index bc8d258..0000000 --- a/vendor/makepad/platform/script/src/opcodes_loops.rs +++ /dev/null @@ -1,455 +0,0 @@ -//! Opcode for loop helper functions -//! -//! This module contains the implementation of for loop iteration, -//! including begin_for_loop, end_for_loop, break_for_loop, and related helpers. - -use crate::makepad_live_id::*; -use crate::thread::*; -use crate::value::*; -use crate::vm::ScriptVm; -use crate::*; - -impl<'a> ScriptVm<'a> { - fn reset_loop_iteration(&mut self, bases: StackBases) -> Option { - self.bx - .threads - .cur() - .truncate_loop_iteration_bases(bases, &mut self.bx.heap); - let Some(&parent) = self.bx.threads.cur_ref().scopes.last() else { - self.bail("scopes empty while resetting a loop iteration"); - return None; - }; - let scope = self.bx.heap.new_with_proto(parent.into()); - self.bx.heap.clear_object_deep(scope); - self.bx.threads.cur().scopes.push(scope); - Some(scope) - } - - pub fn begin_for_loop_inner( - &mut self, - jump: u32, - source: ScriptValue, - value_id: LiveId, - index_id: Option, - key_id: Option, - first_value: ScriptValue, - first_index: f64, - first_key: ScriptValue, - ) { - self.bx.threads.cur().trap.goto_next(); - let bases = self.bx.threads.cur_ref().new_bases(); - let start_ip = self.bx.threads.cur_ref().trap.ip(); - self.bx.threads.cur().loops.push(LoopFrame { - bases, - start_ip, - values: Some(LoopValues { - value_id, - key_id, - index_id, - source, - index: first_index, - }), - jump, - }); - let Some(&scope) = self.bx.threads.cur_ref().scopes.last() else { - self.bail("scopes empty in begin_for_loop_inner"); - return; - }; - let new_scope = self.bx.heap.new_with_proto(scope.into()); - self.bx.heap.clear_object_deep(new_scope); - - self.bx.threads.cur().scopes.push(new_scope); - self.bx - .heap - .set_value_def(new_scope, value_id.into(), first_value); - if let Some(key_id) = key_id { - // For arrays (first_key is NIL), assign index to key_id (FOR_2 semantics: k=index, v=value) - if first_key.is_nil() { - self.bx - .heap - .set_value_def(new_scope, key_id.into(), first_index.into()); - } else { - self.bx - .heap - .set_value_def(new_scope, key_id.into(), first_key); - } - } - if let Some(index_id) = index_id { - self.bx - .heap - .set_value_def(new_scope, index_id.into(), first_index.into()); - } - } - - pub fn begin_loop(&mut self, jump: u32) { - self.bx.threads.cur().trap.goto_next(); - let bases = self.bx.threads.cur_ref().new_bases(); - let start_ip = self.bx.threads.cur_ref().trap.ip.index; - self.bx.threads.cur().loops.push(LoopFrame { - bases, - start_ip, - values: None, - jump, - }); - let Some(&scope) = self.bx.threads.cur_ref().scopes.last() else { - self.bail("scopes empty in begin_loop"); - return; - }; - let new_scope = self.bx.heap.new_with_proto(scope.into()); - self.bx.heap.clear_object_deep(new_scope); - self.bx.threads.cur().scopes.push(new_scope); - } - - pub fn begin_for_loop( - &mut self, - jump: u32, - source: ScriptValue, - value_id: LiveId, - index_id: Option, - key_id: Option, - ) { - let v0 = ScriptValue::from_f64(0.0); - if let Some(s) = source.as_number() { - if s >= 1.0 { - self.begin_for_loop_inner(jump, source, value_id, key_id, index_id, v0, 0.0, v0); - return; - } - } else if let Some(obj) = source.as_object() { - let has_range_proto = self - .bx - .heap - .has_proto(obj, self.bx.code.builtins.range.into()); - if has_range_proto { - // range object - // Use as_number() to handle both f64 and integer types (u40, u32, i32, etc) - let start = self - .bx - .heap - .value(obj, id!(start).into(), self.bx.threads.cur().trap.pass()) - .as_number() - .unwrap_or(0.0); - let end = self - .bx - .heap - .value(obj, id!(end).into(), self.bx.threads.cur().trap.pass()) - .as_number() - .unwrap_or(0.0); - let v = start.into(); - if (start - end).abs() >= 1.0 { - self.begin_for_loop_inner( - jump, source, value_id, index_id, key_id, v, start, v, - ); - return; - } - } else { - if self.bx.heap.iter_len(obj) > 0 { - let kv = self - .bx - .heap - .iter_key_value(obj, 0, self.bx.threads.cur().trap.pass()); - self.begin_for_loop_inner( - jump, source, value_id, index_id, key_id, kv.value, 0.0, kv.key, - ); - return; - } - } - } else if let Some(arr) = source.as_array() { - // FOR_3 (index_id + key_id) not supported for arrays - if index_id.is_some() && key_id.is_some() { - let err = script_err_type_mismatch!( - self.bx.threads.cur().trap, - "for i k v in array is not supported, use for i v in array instead" - ); - self.bx.threads.cur().push_stack_unchecked(err); - self.bx.threads.cur().trap.goto_rel(jump); - return; - } - if self.bx.heap.array_len(arr) > 0 { - let value = self - .bx - .heap - .array_index(arr, 0, self.bx.threads.cur().trap.pass()); - self.begin_for_loop_inner( - jump, source, value_id, index_id, key_id, value, 0.0, NIL, - ); - return; - } - } - self.bx.threads.cur().trap.goto_rel(jump); - } - - pub fn end_for_loop(&mut self) { - let Some(lf) = self.bx.threads.cur().loops.last_mut() else { - self.bail("loops empty in end_for_loop"); - return; - }; - if let Some(values) = &mut lf.values { - if let Some(end) = values.source.as_number() { - values.index += 1.0; - if values.index >= end { - self.break_for_loop(); - return; - } - let start_ip = lf.start_ip; - let bases = lf.bases; - let value_id = values.value_id; - let index = values.index; - let Some(scope) = self.reset_loop_iteration(bases) else { - return; - }; - self.bx - .heap - .set_value_def(scope, value_id.into(), index.into()); - self.bx.threads.cur().trap.goto(start_ip); - return; - } else if let Some(obj) = values.source.as_object() { - if self - .bx - .heap - .has_proto(obj, self.bx.code.builtins.range.into()) - { - // Use as_number() to handle both f64 and integer types - let end = self - .bx - .heap - .value(obj, id!(end).into(), self.bx.threads.cur().trap.pass()) - .as_number() - .unwrap_or(0.0); - let step = self - .bx - .heap - .value(obj, id!(step).into(), self.bx.threads.cur().trap.pass()) - .as_number() - .unwrap_or(1.0); - let Some(lf) = self.bx.threads.cur().loops.last_mut() else { - self.bail("loops empty in end_for_loop/range"); - return; - }; - let Some(values) = lf.values.as_mut() else { - self.bail("loop values empty in end_for_loop/range"); - return; - }; - values.index += step; - if values.index >= end { - self.break_for_loop(); - return; - } - let start_ip = lf.start_ip; - let bases = lf.bases; - let value_id = values.value_id; - let key_id = values.key_id; - let index = values.index; - let Some(scope) = self.reset_loop_iteration(bases) else { - return; - }; - self.bx - .heap - .set_value_def(scope, value_id.into(), index.into()); - // For FOR_2 on ranges, key_id gets the index (same as value for simple ranges) - if let Some(key_id) = key_id { - self.bx - .heap - .set_value_def(scope, key_id.into(), index.into()); - } - self.bx.threads.cur().trap.goto(start_ip); - return; - } else { - let Some(lf) = self.bx.threads.cur().loops.last_mut() else { - self.bail("loops empty in end_for_loop/object"); - return; - }; - let Some(values) = lf.values.as_mut() else { - self.bail("loop values empty in end_for_loop/object"); - return; - }; - values.index += 1.0; - let index = values.index; - let source = values.source; - let Some(obj) = source.as_object() else { - self.bail("source not object in end_for_loop/object"); - return; - }; - if index >= self.bx.heap.iter_len(obj) as f64 { - self.break_for_loop(); - return; - } - let kv = self.bx.heap.iter_key_value( - obj, - index as usize, - self.bx.threads.cur().trap.pass(), - ); - - let Some(lf) = self.bx.threads.cur().loops.last_mut() else { - self.bail("loops empty in end_for_loop/object re-borrow"); - return; - }; - let Some(values) = lf.values.as_ref() else { - self.bail("loop values empty in end_for_loop/object re-borrow"); - return; - }; - let start_ip = lf.start_ip; - let bases = lf.bases; - let value_id = values.value_id; - let index_id = values.index_id; - let key_id = values.key_id; - let index = values.index; - - let Some(scope) = self.reset_loop_iteration(bases) else { - return; - }; - self.bx - .heap - .set_value_def(scope, value_id.into(), kv.value.into()); - if let Some(index_id) = index_id { - self.bx - .heap - .set_value_def(scope, index_id.into(), index.into()); - } - if let Some(key_id) = key_id { - self.bx.heap.set_value_def(scope, key_id.into(), kv.key); - } - - self.bx.threads.cur().trap.goto(start_ip); - return; - } - } else if let Some(arr) = values.source.as_array() { - values.index += 1.0; - let index = values.index; - if index >= self.bx.heap.array_len(arr) as f64 { - self.break_for_loop(); - return; - } - let value = self.bx.heap.array_index( - arr, - index as usize, - self.bx.threads.cur().trap.pass(), - ); - - let Some(lf) = self.bx.threads.cur().loops.last_mut() else { - self.bail("loops empty in end_for_loop/array re-borrow"); - return; - }; - let Some(values) = lf.values.as_ref() else { - self.bail("loop values empty in end_for_loop/array re-borrow"); - return; - }; - let start_ip = lf.start_ip; - let bases = lf.bases; - let value_id = values.value_id; - let index_id = values.index_id; - let key_id = values.key_id; - let index = values.index; - - let Some(scope) = self.reset_loop_iteration(bases) else { - return; - }; - - self.bx - .heap - .set_value_def(scope, value_id.into(), value.into()); - if let Some(index_id) = index_id { - self.bx - .heap - .set_value_def(scope, index_id.into(), index.into()); - } - // For FOR_2 on arrays, key_id gets the index (arrays don't have keys) - if let Some(key_id) = key_id { - self.bx - .heap - .set_value_def(scope, key_id.into(), index.into()); - } - - self.bx.threads.cur().trap.goto(start_ip); - return; - } - } else { - let Some(lf) = self.bx.threads.cur_ref().loops.last() else { - self.bail("loops empty in end_for_loop/plain"); - return; - }; - let start_ip = lf.start_ip; - let mut bases = lf.bases; - // Plain `loop` keeps its iteration scope across back-edges. Only - // nested scopes and iteration-local interpreter state are reset. - bases.scope += 1; - self.bx - .threads - .cur() - .truncate_loop_iteration_bases(bases, &mut self.bx.heap); - self.bx.threads.cur().trap.goto(start_ip); - return; - } - self.bail("unknown loop state"); - } - - pub fn break_for_loop(&mut self) { - let Some(lp) = self.bx.threads.cur().loops.pop() else { - self.bail("loops empty in break_for_loop"); - return; - }; - self.bx - .threads - .cur() - .truncate_bases(lp.bases, &mut self.bx.heap); - self.bx.threads.cur().trap.goto(lp.start_ip + lp.jump - 1); - } - - pub fn pop_to_me(&mut self) { - let value = self.bx.threads.cur().pop_stack_value(); - if self.bx.threads.cur_ref().call_has_me() { - let (key, value) = if let Some(id) = value.as_id() { - if value.is_escaped_id() { - (NIL, value) - } else { - (value, self.bx.threads.cur().scope_value(&self.bx.heap, id)) - } - } else { - (NIL, value) - }; - - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in pop_to_me"); - return; - }; - match me { - ScriptMe::Call { args, .. } => { - let args = *args; - self.bx - .heap - .unnamed_fn_arg(args, value, self.bx.threads.cur().trap.pass()); - } - ScriptMe::Object(obj) => { - let obj = *obj; - if !value.is_nil() && !value.is_err() { - self.bx - .heap - .vec_push(obj, key, value, self.bx.threads.cur().trap.pass()); - } - } - ScriptMe::Pod { pod, offset } => { - let pod = *pod; - let mut offset_copy = *offset; - self.bx.heap.pod_pop_to_me( - pod, - &mut offset_copy, - key, - value, - &self.bx.code.builtins.pod, - self.bx.threads.cur().trap.pass(), - ); - // Write the updated offset back - if let Some(ScriptMe::Pod { offset, .. }) = self.bx.threads.cur().mes.last_mut() - { - *offset = offset_copy; - } - } - ScriptMe::Array(arr) => { - let arr = *arr; - self.bx - .heap - .array_push(arr, value, self.bx.threads.cur().trap.pass()) - } - } - } - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_ops.rs b/vendor/makepad/platform/script/src/opcodes_ops.rs deleted file mode 100644 index bafb523..0000000 --- a/vendor/makepad/platform/script/src/opcodes_ops.rs +++ /dev/null @@ -1,309 +0,0 @@ -//! Opcode arithmetic and comparison operations -//! -//! This module contains handle functions for arithmetic operations (+, -, *, /, etc.), -//! comparison operations (==, !=, <, >, etc.), and logical operations (&&, ||). - -use crate::numeric::NumericValue; -use crate::opcode::*; -use crate::value::*; -use crate::vm::ScriptVm; -use crate::*; - -impl<'a> ScriptVm<'a> { - // ARITHMETIC handlers - - pub(crate) fn handle_not(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let v = self.bx.heap.cast_to_bool(value); - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_bool(!v)); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_neg(&mut self) { - let value = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(f) = value.as_number() { - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64(-f)); - self.bx.threads.cur().trap.goto_next(); - return; - } - let ip = self.bx.threads.cur_ref().trap.ip; - let num = NumericValue::from_script_value_heap(&self.bx.heap, value, ip); - let result = num.zip_f32(NumericValue::F64(-1.0), |a, b| a * b); - self.bx - .threads - .cur() - .push_stack_unchecked(result.to_script_value_heap(&mut self.bx.heap, &self.bx.code)); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_add(&mut self, opargs: OpcodeArgs) { - let b = if opargs.is_u32() { - (opargs.to_u32()).into() - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - if a.is_string_like() || b.is_string_like() { - let ptr = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(a, out); - heap.cast_to_string(b, out); - }); - self.bx.threads.cur().push_stack_unchecked(ptr.into()); - self.bx.threads.cur().trap.goto_next(); - return; - } - - if let (Some(fa), Some(fb)) = (a.as_number(), b.as_number()) { - let ip = self.bx.threads.cur_ref().trap.ip; - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(fa + fb, ip)); - self.bx.threads.cur().trap.goto_next(); - return; - } - - let ip = self.bx.threads.cur_ref().trap.ip; - let na = NumericValue::from_script_value_heap(&self.bx.heap, a, ip); - let nb = NumericValue::from_script_value_heap(&self.bx.heap, b, ip); - let result = na.zip_f32(nb, |x, y| x + y); - self.bx - .threads - .cur() - .push_stack_unchecked(result.to_script_value_heap(&mut self.bx.heap, &self.bx.code)); - self.bx.threads.cur().trap.goto_next(); - } - - // CONCAT handler - - pub(crate) fn handle_concat(&mut self) { - let op1 = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let op2 = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let ptr = self.bx.heap.new_bounded_string_with(|heap, out| { - heap.cast_to_string(op1, out); - heap.cast_to_string(op2, out); - }); - self.bx.threads.cur().push_stack_unchecked(ptr.into()); - self.bx.threads.cur().trap.goto_next(); - } - - // EQUALITY handlers - - pub(crate) fn handle_eq(&mut self) { - self.handle_structural_equality(false); - } - - pub(crate) fn handle_neq(&mut self) { - self.handle_structural_equality(true); - } - - fn handle_structural_equality(&mut self, negate: bool) { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let deadline = self.bx.run_budget.as_ref().map(|b| b.hard_deadline); - let thread = self.bx.threads.cur(); - let result = self - .bx - .heap - .deep_eq_bounded(a, b, crate::equality::MAX_EQUALITY_WORK, || { - if let Some(remaining) = thread.instruction_limit_remaining.as_mut() { - if *remaining == 0 { - return false; - } - *remaining -= 1; - } - deadline.is_none_or(|deadline| std::time::Instant::now() < deadline) - }); - match result { - Some(equal) => { - self.bx - .threads - .cur() - .push_stack_unchecked((equal != negate).into()); - self.bx.threads.cur().trap.goto_next(); - } - None => { - let error = script_err_limit!( - self.bx.threads.cur_ref().trap, - "script equality work, instruction, or time limit exceeded" - ); - // Native work exhaustion is uncatchable just like VM fuel. - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(crate::trap::ScriptTrapOn::Bail(error))); - } - } - } - - pub(crate) fn handle_shallow_eq(&mut self) { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - self.bx.threads.cur().push_stack_value((a == b).into()); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_shallow_neq(&mut self) { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - self.bx.threads.cur().push_stack_unchecked((a != b).into()); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_f64_op(&mut self, args: OpcodeArgs, f: F) - where - F: FnOnce(f64, f64) -> f64, - { - let ip = self.bx.threads.cur_ref().trap.ip; - let fb = if args.is_u32() { - args.to_u32() as f64 - } else { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - self.bx.heap.cast_to_f64(b, ip) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let fa = self.bx.heap.cast_to_f64(a, ip); - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(f(fa, fb), ip)); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_fu64_op(&mut self, args: OpcodeArgs, f: F) - where - F: FnOnce(u64, u64) -> u64, - { - let ip = self.bx.threads.cur_ref().trap.ip; - let ub = if args.is_u32() { - args.to_u32() as u64 - } else { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - self.bx.heap.cast_to_f64(b, ip) as u64 - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let ua = self.bx.heap.cast_to_f64(a, ip) as u64; - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(f(ua, ub) as f64, ip)); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_f64_cmp_op(&mut self, args: OpcodeArgs, f: F) - where - F: FnOnce(f64, f64) -> bool, - { - let ip = self.bx.threads.cur_ref().trap.ip; - let fb = if args.is_u32() { - args.to_u32() as f64 - } else { - let b = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - self.bx.heap.cast_to_f64(b, ip) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let fa = self.bx.heap.cast_to_f64(a, ip); - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_bool(f(fa, fb))); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_mul(&mut self, args: OpcodeArgs) { - let b = if args.is_u32() { - ScriptValue::from_f64(args.to_u32() as f64) - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - if let (Some(fa), Some(fb)) = (a.as_number(), b.as_number()) { - let ip = self.bx.threads.cur_ref().trap.ip; - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(fa * fb, ip)); - self.bx.threads.cur().trap.goto_next(); - return; - } - - let ip = self.bx.threads.cur_ref().trap.ip; - let na = NumericValue::from_script_value_heap(&self.bx.heap, a, ip); - let nb = NumericValue::from_script_value_heap(&self.bx.heap, b, ip); - let result = na.multiply(nb); - self.bx - .threads - .cur() - .push_stack_unchecked(result.to_script_value_heap(&mut self.bx.heap, &self.bx.code)); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_div(&mut self, args: OpcodeArgs) { - let b = if args.is_u32() { - ScriptValue::from_f64(args.to_u32() as f64) - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - if let (Some(fa), Some(fb)) = (a.as_number(), b.as_number()) { - let ip = self.bx.threads.cur_ref().trap.ip; - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(fa / fb, ip)); - self.bx.threads.cur().trap.goto_next(); - return; - } - - let ip = self.bx.threads.cur_ref().trap.ip; - let na = NumericValue::from_script_value_heap(&self.bx.heap, a, ip); - let nb = NumericValue::from_script_value_heap(&self.bx.heap, b, ip); - let result = na.zip_f32(nb, |x, y| if y != 0.0 { x / y } else { 0.0 }); - self.bx - .threads - .cur() - .push_stack_unchecked(result.to_script_value_heap(&mut self.bx.heap, &self.bx.code)); - self.bx.threads.cur().trap.goto_next(); - } - - pub fn handle_sub(&mut self, args: OpcodeArgs) { - let b = if args.is_u32() { - ScriptValue::from_f64(args.to_u32() as f64) - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let a = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - if let (Some(fa), Some(fb)) = (a.as_number(), b.as_number()) { - let ip = self.bx.threads.cur_ref().trap.ip; - self.bx - .threads - .cur() - .push_stack_unchecked(ScriptValue::from_f64_traced_nan(fa - fb, ip)); - self.bx.threads.cur().trap.goto_next(); - return; - } - - let ip = self.bx.threads.cur_ref().trap.ip; - let na = NumericValue::from_script_value_heap(&self.bx.heap, a, ip); - let nb = NumericValue::from_script_value_heap(&self.bx.heap, b, ip); - let result = na.zip_f32(nb, |x, y| x - y); - self.bx - .threads - .cur() - .push_stack_unchecked(result.to_script_value_heap(&mut self.bx.heap, &self.bx.code)); - self.bx.threads.cur().trap.goto_next(); - } -} diff --git a/vendor/makepad/platform/script/src/opcodes_vars.rs b/vendor/makepad/platform/script/src/opcodes_vars.rs deleted file mode 100644 index f7073bb..0000000 --- a/vendor/makepad/platform/script/src/opcodes_vars.rs +++ /dev/null @@ -1,939 +0,0 @@ -//! Opcode variable and field operations -//! -//! This module contains handle functions for variable declarations (let, var), -//! field access, use statements, object/array construction, logging, and related operations. - -use crate::makepad_error_log::*; -use crate::makepad_live_id::*; -use crate::opcode::*; -use crate::thread::*; -use crate::value::*; -use crate::vm::*; -use crate::*; - -impl<'a> ScriptVm<'a> { - // Object/Array begin handlers - - pub(crate) fn handle_begin_proto(&mut self) { - let proto = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let me = self - .bx - .heap - .new_with_proto_checked(proto, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().mes.push(ScriptMe::Object(me)); - self.bx.threads.cur().trap.goto_next(); - } - - /// Part 1 of proto-inherit (+:) operator. - pub(crate) fn handle_proto_inherit_read(&mut self) { - let field = self.bx.threads.cur().peek_stack_value(); - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in proto_inherit_read"); - return; - }; - let proto = if let ScriptMe::Object(object) = me { - let object = *object; - let value = self.bx.heap.proto_field_from_value( - object, - field, - self.bx.threads.cur().trap.pass(), - ); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - if let Some(field_id) = field.as_id() { - self.bx.heap.proto_field_from_type_check( - object, - field_id, - self.bx.threads.cur().trap.pass(), - ) - } else { - NIL - } - } else { - value - } - } else { - NIL - }; - self.bx.threads.cur().push_stack_unchecked(proto); - self.bx.threads.cur().trap.goto_next(); - } - - /// Part 2 of proto-inherit (+:) operator. - pub(crate) fn handle_proto_inherit_write(&mut self) { - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - if let Some(me) = self.bx.threads.cur_ref().mes.last() { - if let ScriptMe::Object(me_obj) = me { - let me_obj = *me_obj; - if field.is_string_like() { - self.bx.heap.set_string_keys(me_obj); - } - self.bx - .heap - .set_value(me_obj, field, object, self.bx.threads.cur().trap.pass()); - } - } - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_scope_inherit_read(&mut self) { - let id = self.bx.threads.cur().peek_stack_value(); - let proto = if let Some(id) = id.as_id() { - let value = self.bx.threads.cur().scope_value(&self.bx.heap, id); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - value - } - } else { - NIL - }; - self.bx.threads.cur().push_stack_unchecked(proto); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_scope_inherit_write(&mut self) { - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let id = self.bx.threads.cur().pop_stack_value(); - if let Some(id) = id.as_id() { - self.bx - .threads - .cur() - .set_scope_value(&mut self.bx.heap, id, object); - } - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_field_inherit_read(&mut self) { - let field = self.bx.threads.cur().peek_stack_value(); - let object = self.bx.threads.cur().peek_stack_value_at(1); - let object = if let Some(id) = object.as_id() { - if !object.is_escaped_id() { - self.bx.threads.cur().scope_value(&self.bx.heap, id) - } else { - object - } - } else { - object - }; - let proto = if let Some(obj) = object.as_object() { - let value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - value - } - } else { - NIL - }; - self.bx.threads.cur().push_stack_unchecked(proto); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_field_inherit_write(&mut self) { - let built_object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - if field.is_string_like() { - self.bx.heap.set_string_keys(obj); - } - self.bx - .heap - .set_value(obj, field, built_object, self.bx.threads.cur().trap.pass()); - } - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_index_inherit_read(&mut self) { - let index = self.bx.threads.cur().peek_stack_value(); - let object = self.bx.threads.cur().peek_stack_value_at(1); - let object = if let Some(id) = object.as_id() { - if !object.is_escaped_id() { - self.bx.threads.cur().scope_value(&self.bx.heap, id) - } else { - object - } - } else { - object - }; - let proto = if let Some(obj) = object.as_object() { - let value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - value - } - } else if let Some(arr) = object.as_array() { - let Some(idx) = self.checked_array_index(index) else { - return; - }; - let value = self - .bx - .heap - .array_index(arr, idx, self.bx.threads.cur().trap.pass()); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - value - } - } else { - NIL - }; - self.bx.threads.cur().push_stack_unchecked(proto); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_index_inherit_write(&mut self) { - let built_object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let index = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - self.bx - .heap - .set_value(obj, index, built_object, self.bx.threads.cur().trap.pass()); - } else if let Some(arr) = object.as_array() { - let Some(idx) = self.checked_array_index(index) else { - return; - }; - self.bx - .heap - .set_array_index(arr, idx, built_object, self.bx.threads.cur().trap.pass()); - } - self.bx.threads.cur().push_stack_unchecked(NIL); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_end_proto(&mut self) { - let Some(me) = self.bx.threads.cur().mes.pop() else { - self.bail("mes empty in end_proto"); - return; - }; - if let ScriptMe::Object(me) = me { - self.bx.heap.finalize_maybe_pod_type( - me, - &self.bx.code.builtins.pod, - self.bx.threads.cur().trap.pass(), - ); - } - self.bx.threads.cur().push_stack_unchecked(me.into()); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_begin_bare(&mut self) { - let me = self.bx.heap.new_object(); - self.bx.threads.cur().mes.push(ScriptMe::Object(me)); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_end_bare(&mut self) { - let Some(me) = self.bx.threads.cur().mes.pop() else { - self.bail("mes empty in end_bare"); - return; - }; - self.bx.threads.cur().push_stack_unchecked(me.into()); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_begin_array(&mut self) { - let me = self.bx.heap.new_array(); - self.bx.threads.cur().mes.push(ScriptMe::Array(me)); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_end_array(&mut self) { - let Some(me) = self.bx.threads.cur().mes.pop() else { - self.bail("mes empty in end_array"); - return; - }; - self.bx.threads.cur().push_stack_unchecked(me.into()); - self.bx.threads.cur().trap.goto_next(); - } - - // Use handler - - pub(crate) fn handle_use(&mut self) { - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - if field.as_id() == Some(id!(*)) { - let mut items = Vec::new(); - let obj_data = &self.bx.heap.objects[obj]; - for (k, v) in obj_data.map.iter() { - items.push((*k, v.value)); - } - for item in &obj_data.vec { - items.push((item.key, item.value)); - } - for (k, v) in items { - if let Some(id) = k.as_id() { - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, v); - } - } - } else { - let value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - if !value.is_nil() { - if let Some(field) = field.as_id() { - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, field, value); - } - } - } - } - self.bx.threads.cur().trap.goto_next(); - } - - // Field handlers - - pub(crate) fn handle_field(&mut self) { - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else if let Some(pod) = object.as_pod() { - let value = self.bx.heap.pod_read_field( - pod, - field, - &self.bx.code.builtins.pod, - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let field = field.as_id().unwrap_or(id!()); - let type_index = object.value_type().to_redux(); - // Get the getter pointer and drop the borrow before calling - let getter_ptr: *const dyn Fn(&mut ScriptVm, ScriptValue, LiveId) -> ScriptValue = { - let native = self.bx.code.native.borrow(); - &*native.getters[type_index.to_index()] as *const _ - }; - // SAFETY: The getter pointer is valid as long as native getters aren't removed during execution - let ret = unsafe { (*getter_ptr)(self, object, field) }; - self.bx.threads.cur().push_stack_unchecked(ret); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_field_nil(&mut self) { - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let value = self - .bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - self.bx.threads.cur().push_stack_unchecked(NIL); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_me_field(&mut self) { - let field = self.bx.threads.cur().pop_stack_value(); - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in me_field"); - return; - }; - let value = match me { - ScriptMe::Array(_) => { - script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "field access {:?} not allowed in array literal context", - field - ) - } - ScriptMe::Call { args, .. } => { - let args = *args; - self.bx - .heap - .value(args, field, self.bx.threads.cur().trap.pass()) - } - ScriptMe::Pod { pod, .. } => { - let pod = *pod; - self.bx.heap.pod_read_field( - pod, - field, - &self.bx.code.builtins.pod, - self.bx.threads.cur().trap.pass(), - ) - } - ScriptMe::Object(obj) => { - let obj = *obj; - self.bx - .heap - .value(obj, field, self.bx.threads.cur().trap.pass()) - } - }; - self.bx.threads.cur().push_stack_value(value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_proto_field(&mut self) { - let field = self.bx.threads.cur().pop_stack_value(); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if let Some(obj) = object.as_object() { - let value = - self.bx - .heap - .proto_field_from_value(obj, field, self.bx.threads.cur().trap.pass()); - if value.is_nil() || value.is_err() { - self.bx.threads.cur().trap.err.take(); - if let Some(field_id) = field.as_id() { - let value = self.bx.heap.proto_field_from_type_check( - obj, - field_id, - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value); - } else { - let value = script_err_not_found!( - self.bx.threads.cur_ref().trap, - "proto field lookup requires identifier, got {:?}", - field.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - } else { - self.bx.threads.cur().push_stack_unchecked(value) - } - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "proto_field {:?} target is not an object (got {:?})", - field, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_pop_to_me(&mut self) { - self.pop_to_me(); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_me_splat(&mut self) { - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - if !self.bx.threads.cur_ref().call_has_me() { - self.bx.threads.cur().trap.goto_next(); - return; - } - - let Some(me) = self.bx.threads.cur_ref().mes.last() else { - self.bail("mes empty in me_splat"); - return; - }; - match me { - ScriptMe::Object(obj) => { - let obj = *obj; - if let Some(source_obj) = source.as_object() { - self.bx - .heap - .merge_object(obj, source_obj, self.bx.threads.cur().trap.pass()); - } else if let Some(source_arr) = source.as_array() { - let len = self.bx.heap.array_len(source_arr); - for i in 0..len { - let v = self.bx.heap.array_index( - source_arr, - i, - self.bx.threads.cur().trap.pass(), - ); - self.bx - .heap - .vec_push(obj, NIL, v, self.bx.threads.cur().trap.pass()); - } - } - } - ScriptMe::Array(arr) => { - let arr = *arr; - if let Some(source_arr) = source.as_array() { - self.bx - .heap - .merge_array(arr, source_arr, self.bx.threads.cur().trap.pass()); - } else if let Some(source_obj) = source.as_object() { - self.bx - .heap - .array_push_vec(arr, source_obj, self.bx.threads.cur().trap.pass()); - } - } - ScriptMe::Call { args, .. } => { - let args = *args; - if let Some(source_obj) = source.as_object() { - let len = self.bx.heap.vec_len(source_obj); - for i in 0..len { - let kv = self.bx.heap.vec_key_value( - source_obj, - i, - self.bx.threads.cur().trap.pass(), - ); - self.bx.heap.unnamed_fn_arg( - args, - kv.value, - self.bx.threads.cur().trap.pass(), - ); - } - } else if let Some(source_arr) = source.as_array() { - let len = self.bx.heap.array_len(source_arr); - for i in 0..len { - let v = self.bx.heap.array_index( - source_arr, - i, - self.bx.threads.cur().trap.pass(), - ); - self.bx - .heap - .unnamed_fn_arg(args, v, self.bx.threads.cur().trap.pass()); - } - } - } - ScriptMe::Pod { .. } => { - script_err_not_impl!( - self.bx.threads.cur_ref().trap, - "splat operator (..) not supported for pod types" - ); - } - } - self.bx.threads.cur().trap.goto_next(); - } - - /// Validate before touching storage, so rejected writes are atomic. - pub(crate) fn checked_array_index(&mut self, index: ScriptValue) -> Option { - if let Some(index) = index.checked_index() { - return Some(index); - } - let error = script_err_invalid_args!( - self.bx.threads.cur_ref().trap, - "array index must be a finite nonnegative integer" - ); - self.bx.threads.cur().push_stack_unchecked(error); - self.bx.threads.cur().trap.goto_next(); - None - } - - // Array index handler - - pub(crate) fn handle_array_index(&mut self) { - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let object = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - if let Some(obj) = object.as_object() { - let value = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - // A map lookup with a missing string/object key yields nil (not an error), - // matching dynamic-map semantics (e.g. `map[key] != nil` membership checks). - // Integer indexing keeps erroring so index-based iteration still terminates. - let value = if value.is_err() - && (index.is_string_like() || index.is_object() || index.is_color()) - { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - value - }; - self.bx.threads.cur().push_stack_unchecked(value) - } else if let Some(arr) = object.as_array() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let value = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - self.bx.threads.cur().push_stack_unchecked(value) - } else if let Some(pod) = object.as_pod() { - let Some(index) = self.checked_array_index(index) else { - return; - }; - let value = self.bx.heap.pod_array_index( - pod, - index, - &self.bx.code.builtins.pod, - self.bx.threads.cur().trap.pass(), - ); - self.bx.threads.cur().push_stack_unchecked(value) - } else { - let value = script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "cannot index {:?} on {:?} (not an object/array/pod)", - index, - object.value_type() - ); - self.bx.threads.cur().push_stack_unchecked(value); - } - self.bx.threads.cur().trap.goto_next(); - } - - // Let handlers - - pub(crate) fn handle_let_dyn(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let id = self.bx.threads.cur().pop_stack_value(); - let id = id.as_id().unwrap_or(id!()); - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_let_typed(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let _ty = self.bx.threads.cur().pop_stack_value(); - let id = self - .bx - .threads - .cur() - .pop_stack_value() - .as_id() - .unwrap_or(id!()); - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_var_dyn(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let id = self.bx.threads.cur().pop_stack_value(); - let id = id.as_id().unwrap_or(id!()); - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_var_typed(&mut self, opargs: OpcodeArgs) { - let value = if opargs.is_nil() { - NIL - } else { - self.bx.threads.cur().pop_stack_resolved(&self.bx.heap) - }; - let _ty = self.bx.threads.cur().pop_stack_value(); - let id = self - .bx - .threads - .cur() - .pop_stack_value() - .as_id() - .unwrap_or(id!()); - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - self.bx.threads.cur().trap.goto_next(); - } - - // Tree search handler - - pub(crate) fn handle_search_tree(&mut self) { - self.bx.threads.cur().trap.goto_next(); - } - - // Log handler - - pub(crate) fn handle_log(&mut self) { - if !self.bx.allow_debug_output { - let error = script_err_not_allowed!( - self.bx.threads.cur_ref().trap, - "direct script logging is disabled by this host" - ); - self.bx.threads.cur().push_stack_unchecked(error); - self.bx.threads.cur().trap.goto_next(); - return; - } - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - self.log(value); - self.bx.threads.cur().trap.goto_next(); - } - - // Me/Scope handlers - - pub(crate) fn handle_me(&mut self) { - let value = if self.bx.threads.cur_ref().call_has_me() { - match self.bx.threads.cur_ref().mes.last() { - Some(ScriptMe::Array(arr)) => (*arr).into(), - Some(ScriptMe::Call { args, .. }) => (*args).into(), - Some(ScriptMe::Pod { pod, .. }) => (*pod).into(), - Some(ScriptMe::Object(obj)) => (*obj).into(), - None => { - self.bail("mes empty in me"); - return; - } - } - } else { - NIL - }; - self.bx.threads.cur().push_stack_value(value); - self.bx.threads.cur().trap.goto_next(); - } - - pub(crate) fn handle_scope(&mut self) { - let Some(&scope) = self.bx.threads.cur().scopes.last() else { - self.bail("scopes empty in scope"); - return; - }; - self.bx.threads.cur().push_stack_value(scope.into()); - self.bx.threads.cur().trap.goto_next(); - } - - // Log implementation - - pub fn log(&self, value: ScriptValue) { - if !self.bx.allow_debug_output { - return; - } - if let Some(loc) = self.bx.code.ip_to_loc(self.bx.threads.cur_ref().trap.ip) { - if value != NIL { - if let Some(err_ptr) = value.as_err() { - if let Some(loc2) = self.bx.code.ip_to_loc(err_ptr.ip) { - let err_queue = self.bx.threads.cur_ref().trap.err.borrow(); - if let Some(err) = err_queue.iter().find(|e| e.value == value) { - log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!( - "{} ({}:{}) {}", - err.message, err.origin_file, err.origin_line, loc2 - ), - LogLevel::Log, - ); - } else { - log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!("{} {}", value, loc2), - LogLevel::Log, - ); - } - } - } else if let Some(nanip) = value.as_f64_traced_nan() { - if let Some(loc2) = self.bx.code.ip_to_loc(nanip) { - log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!("{} NaN Traced to {}", value, loc2), - LogLevel::Log, - ); - } - } else { - let mut out = String::new(); - let mut recur = Vec::new(); - self.bx - .heap - .to_debug_string(value, &mut recur, &mut out, true, 0); - log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!("{:?}:{out}", value.value_type()), - LogLevel::Log, - ); - } - } else { - log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!("nil"), - LogLevel::Log, - ); - } - } - } - - // Destructuring handlers - - /// DUP - duplicate top of stack - pub(crate) fn handle_dup(&mut self) { - let value = self.bx.threads.cur().peek_stack_resolved(&self.bx.heap); - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - } - - /// DROP - discard top of stack - pub(crate) fn handle_drop(&mut self) { - self.bx.threads.cur().pop_stack_value(); - self.bx.threads.cur().trap.goto_next(); - } - - /// ARRAY_INDEX_NIL - like ARRAY_INDEX but returns nil instead of error - /// Stack: [source, index] -> [value_or_nil] - pub(crate) fn handle_array_index_nil(&mut self) { - let index = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - let value = if let Some(arr) = source.as_array() { - let Some(idx) = self.checked_array_index(index) else { - return; - }; - // Try to get, return NIL if out of bounds or error - let result = self - .bx - .heap - .array_index(arr, idx, self.bx.threads.cur().trap.pass()); - if result.is_err() { - self.bx.threads.cur().trap.err.take(); // Clear the error - NIL - } else { - result - } - } else if let Some(obj) = source.as_object() { - let result = self - .bx - .heap - .value(obj, index, self.bx.threads.cur().trap.pass()); - if result.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - result - } - } else { - NIL - }; - - self.bx.threads.cur().push_stack_unchecked(value); - self.bx.threads.cur().trap.goto_next(); - } - - /// LET_DESTRUCT_ARRAY_EL(index) - destructure array element - /// Stack: [source, id] -> [source] - /// Binds: id = source[index] (nil-safe extraction) - pub(crate) fn handle_let_destruct_array_el(&mut self, opargs: OpcodeArgs) { - let index = opargs.to_u32() as usize; - let id = self.bx.threads.cur().pop_stack_value(); - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - // Extract value from source array at index (nil-safe) - let value = if let Some(arr) = source.as_array() { - let result = self - .bx - .heap - .array_index(arr, index, self.bx.threads.cur().trap.pass()); - if result.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - result - } - } else if let Some(obj) = source.as_object() { - let result = self.bx.heap.value( - obj, - ScriptValue::from_u32(index as u32), - self.bx.threads.cur().trap.pass(), - ); - if result.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - result - } - } else { - NIL - }; - - // Bind the value to the identifier - if let Some(id) = id.as_id() { - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - } - - // Push source back on stack for next element - self.bx.threads.cur().push_stack_unchecked(source); - self.bx.threads.cur().trap.goto_next(); - } - - /// LET_DESTRUCT_OBJECT_EL - destructure object element - /// Stack: [source, id] -> [source] - /// Binds: id = source[id] (nil-safe extraction) - pub(crate) fn handle_let_destruct_object_el(&mut self) { - let id = self.bx.threads.cur().pop_stack_value(); - let source = self.bx.threads.cur().pop_stack_resolved(&self.bx.heap); - - // Extract value from source object using id as key (nil-safe) - let value = if let Some(obj) = source.as_object() { - let result = self - .bx - .heap - .value(obj, id, self.bx.threads.cur().trap.pass()); - if result.is_err() { - self.bx.threads.cur().trap.err.take(); - NIL - } else { - result - } - } else { - NIL - }; - - // Bind the value to the identifier - if let Some(id) = id.as_id() { - self.bx - .threads - .cur() - .def_scope_value(&mut self.bx.heap, id, value); - } - - // Push source back on stack for next element - self.bx.threads.cur().push_stack_unchecked(source); - self.bx.threads.cur().trap.goto_next(); - } -} diff --git a/vendor/makepad/platform/script/src/parser.rs b/vendor/makepad/platform/script/src/parser.rs deleted file mode 100644 index 564ee8e..0000000 --- a/vendor/makepad/platform/script/src/parser.rs +++ /dev/null @@ -1,4520 +0,0 @@ -use crate::makepad_error_log::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id::makepad_live_id_macros::*; -use crate::opcode::*; -use crate::tokenizer::*; -use crate::value::*; - -macro_rules! error { - ($self:expr, $tokenizer:expr, $($arg:tt)*) => { - $self.report_error($tokenizer, format!("{} (from: {}:{})", format!($($arg)*), file!(), line!())) - } -} - -/// Structured parser feedback retained for hosts that need to validate source -/// without executing it. Positions are zero-based and relative to the parser's -/// configured source offsets. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ScriptParserDiagnostic { - pub line: u32, - pub column: u32, - pub message: String, -} - -/// Maximum retained diagnostics for one parser instance. -/// -/// The parser still marks `had_error` after this limit so callers cannot treat -/// a malformed source as valid just because feedback was bounded. -pub const MAX_PARSER_DIAGNOSTICS: usize = 64; - -#[derive(Clone, Debug, Eq, PartialEq)] -enum State { - BeginStmt { - last_was_sep: bool, - }, - BeginExpr { - required: bool, - }, - EndExpr, - EndStmt { - last: u32, - }, - - EscapedId, - - ForIdent { - idents: u32, - index: u32, - }, - ForBody { - idents: u32, - index: u32, - }, - ForExpr { - code_start: u32, - }, - ForBlock { - code_start: u32, - }, - Loop { - index: u32, - }, - While { - index: u32, - }, - WhileTest { - code_start: u32, - }, - - IfTest { - index: u32, - }, - IfTrueExpr { - if_start: u32, - }, - IfTrueBlock { - if_start: u32, - last_was_sep: bool, - }, - IfMaybeElse { - if_start: u32, - was_block: bool, - }, - IfElse { - else_start: u32, - }, - IfElseExpr { - else_start: u32, - }, - IfElseBlock { - else_start: u32, - last_was_sep: bool, - }, - - OkTest { - index: u32, - }, - OkTestBlock { - ok_start: u32, - last_was_sep: bool, - }, - OkTestExpr { - ok_start: u32, - }, - - TryTest { - index: u32, - }, - TryTestBlock { - try_start: u32, - last_was_sep: bool, - }, - TryTestExpr { - try_start: u32, - }, - TryErrBlockOrExpr { - allow_catch: bool, - canonical_catch: bool, - protected_was_block: bool, - try_start: u32, - }, - TryErrBlock { - canonical_catch: bool, - err_start: u32, - last_was_sep: bool, - }, - TryErrExpr { - err_start: u32, - }, - TryOk { - err_start: u32, - was_block: bool, - }, - TryOkBlockOrExpr, - TryOkBlock { - ok_start: u32, - last_was_sep: bool, - }, - TryOkExpr { - ok_start: u32, - }, - - FnMaybeLet { - index: u32, - }, - FnLetMaybeArgs, - FnArgList { - lambda: bool, - }, - FnArgMaybeType { - lambda: bool, - index: u32, - }, - FnArgType { - lambda: bool, - index: u32, - }, - FnArgTypeAssign { - lambda: bool, - index: u32, - }, - - FnBody { - lambda: bool, - }, - FnReturnType { - lambda: bool, - }, - FnBodyTyped { - lambda: bool, - }, - EndFnBlock { - fn_slot: u32, - last_was_sep: bool, - index: u32, - }, - EndFnExpr { - fn_slot: u32, - index: u32, - }, - EmitFnArgTyped { - index: u32, - }, - EmitFnArgDyn { - index: u32, - }, - - EmitUnary { - what_op: LiveId, - index: u32, - }, - EmitSplat { - index: u32, - }, - EmitOp { - what_op: LiveId, - index: u32, - }, - EmitFieldAssign { - what_op: LiveId, - index: u32, - }, - EmitIndexAssign { - what_op: LiveId, - index: u32, - }, - - EndBare, - EndBareSquare, - EndProto, - EndProtoInherit, - EndScopeInherit, - EndFieldInherit, - EndIndexInherit, - EndRound, - - CallMaybeDo { - is_method: bool, - index: u32, - }, - EmitCallFromDo { - is_method: bool, - index: u32, - }, - EndCall { - is_method: bool, - index: u32, - }, - ArrayIndex, - - EmitReturn { - index: u32, - code_len_before: u32, - }, - EmitBreak { - index: u32, - }, - EmitContinue { - index: u32, - }, - - Use { - index: u32, - }, - Let { - index: u32, - }, - LetDynOrTyped { - index: u32, - }, - LetType { - index: u32, - }, - LetTypedAssign { - index: u32, - }, - EmitLetDyn { - index: u32, - }, - EmitLetTyped { - index: u32, - }, - - // Destructuring patterns - // We collect binding ids in the code stream, then after RHS we emit extraction opcodes - // Defaults are stored separately and ?= is emitted after extraction - LetArrayDestruct { - index: u32, - count: u32, - ids_start: u32, - }, // parsing [x, y, ...] pattern - LetArrayDestructEl { - index: u32, - count: u32, - binding_id: LiveId, - ids_start: u32, - }, // after identifier, maybe = default - LetArrayDestructDefault { - index: u32, - count: u32, - binding_id: LiveId, - ids_start: u32, - default_start: u32, - }, // parsing default expr - LetArrayDestructRhs { - index: u32, - count: u32, - ids_start: u32, - defaults_start: u32, - }, // after ], before = - EmitLetArrayDestruct { - index: u32, - count: u32, - ids_start: u32, - defaults_start: u32, - }, // after RHS, emit opcodes - - // Nested object pattern inside array: let [{x}] = ... - LetArrayDestructNestedObject { - index: u32, - outer_count: u32, - outer_ids_start: u32, - nested_count: u32, - }, - LetArrayDestructNestedObjectEl { - index: u32, - outer_count: u32, - outer_ids_start: u32, - nested_count: u32, - binding_id: LiveId, - }, - - // Nested array pattern inside array: let [[x]] = ... - LetArrayDestructNestedArray { - index: u32, - outer_count: u32, - outer_ids_start: u32, - nested_count: u32, - }, - LetArrayDestructNestedArrayEl { - index: u32, - outer_count: u32, - outer_ids_start: u32, - nested_count: u32, - binding_id: LiveId, - }, - - LetObjectDestruct { - index: u32, - count: u32, - ids_start: u32, - }, // parsing {x, y, ...} pattern - LetObjectDestructEl { - index: u32, - count: u32, - binding_id: LiveId, - ids_start: u32, - }, // after identifier, maybe = default - LetObjectDestructDefault { - index: u32, - count: u32, - binding_id: LiveId, - ids_start: u32, - default_start: u32, - }, // parsing default expr - LetObjectDestructRhs { - index: u32, - count: u32, - ids_start: u32, - defaults_start: u32, - }, // after }, before = - EmitLetObjectDestruct { - index: u32, - count: u32, - ids_start: u32, - defaults_start: u32, - }, // after RHS, emit opcodes - - // Nested array pattern inside object: let {a: [x]} = ... - LetObjectDestructNestedArray { - index: u32, - outer_count: u32, - outer_ids_start: u32, - key: LiveId, - nested_count: u32, - }, - LetObjectDestructNestedArrayEl { - index: u32, - outer_count: u32, - outer_ids_start: u32, - key: LiveId, - nested_count: u32, - binding_id: LiveId, - }, - - // Nested object pattern inside object: let {a: {x}} = ... - LetObjectDestructNestedObject { - index: u32, - outer_count: u32, - outer_ids_start: u32, - key: LiveId, - nested_count: u32, - }, - LetObjectDestructNestedObjectEl { - index: u32, - outer_count: u32, - outer_ids_start: u32, - key: LiveId, - nested_count: u32, - binding_id: LiveId, - }, - Var { - index: u32, - }, - VarDynOrTyped { - index: u32, - }, - VarType { - index: u32, - }, - VarTypedAssign { - index: u32, - }, - EmitVarDyn { - index: u32, - }, - EmitVarTyped { - index: u32, - }, - - MatchSubject { - temp_id: LiveId, - index: u32, - }, - MatchBlock { - temp_id: LiveId, - index: u32, - }, - MatchArmPattern { - temp_id: LiveId, - first: bool, - prev_else_start: u32, - index: u32, - }, - MatchArmArrow { - temp_id: LiveId, - prev_else_start: u32, - index: u32, - }, - MatchArmBody { - temp_id: LiveId, - if_start: u32, - prev_else_start: u32, - index: u32, - }, - MatchArmBlock { - temp_id: LiveId, - if_start: u32, - prev_else_start: u32, - last_was_sep: bool, - index: u32, - }, - MatchWildcardArrow { - prev_else_start: u32, - index: u32, - }, - MatchWildcardBody { - prev_else_start: u32, - index: u32, - }, - MatchWildcardBlock { - prev_else_start: u32, - last_was_sep: bool, - index: u32, - }, - MatchMaybeArm { - temp_id: LiveId, - if_start: u32, - prev_else_start: u32, - index: u32, - }, - MatchWildcardEnd { - prev_else_start: u32, - index: u32, - }, - - // Short-circuit evaluation - patches TEST opcode jump after second operand - ShortCircuitEnd { - test_slot: u32, - what_op: LiveId, - }, - // Short-circuit ?= - emits ASSIGN after RHS, then patches jump - ShortCircuitAssignEnd { - test_slot: u32, - index: u32, - }, -} - -impl State { - fn is_short_circuit_op(op: LiveId) -> bool { - op == id!(&&) || op == id!(||) || op == id!(|?) - } - - fn short_circuit_opcode(op: LiveId) -> Opcode { - match op { - id!(&&) => Opcode::LOGIC_AND_TEST, - id!(||) => Opcode::LOGIC_OR_TEST, - id!(|?) => Opcode::NIL_OR_TEST, - _ => Opcode::NOP, - } - } -} - -// we have a stack, and we have operations -// operators: -/* -Order list from highest prio to lowest -1 Identifierpath -2 Method calls -3 Field expression -4 Functioncall, array index -5 ? -6 unary - ! * borrow -7 as -8 * / % -9 + - -10 << >> -11 & -12 ^ -13 | -14 == != < > <= >= -15 && -16 || -17 = += -= *= /= %= -18 &= |= ^= <<= >>= -19 return break -*/ - -impl State { - fn operator_order(op: LiveId) -> usize { - match op { - id!(.) => 3, - id!(.?) => 3, - id!(*) | id!(/) | id!(%) => 8, - id!(+) | id!(-) => 9, - id!(<<) | id!(>>) => 10, - id!(&) => 11, - id!(^) => 12, - id!(|) => 13, - id!(-:) => 14, - id!(++) => 14, - id!(<) | id!(>) | id!(<=) | id!(>=) => 14, - id!(===) | id!(!==) | id!(==) | id!(!=) => 15, - id!(is) => 15, - id!(&&) => 16, - id!(||) | id!(|?) => 17, - id!(..) => 18, - id!(:) - | id!(:=) - | id!(=) - | id!(>:) - | id!(<:) - | id!(^:) - | id!(+:) - | id!(+=) - | id!(-=) - | id!(*=) - | id!(/=) - | id!(%=) => 19, - id!(&=) | id!(|=) | id!(^=) | id!(<<=) | id!(>>=) | id!(?=) => 20, - _ => 0, - } - } - - fn is_assign_operator(op: LiveId) -> bool { - match op { - id!(=) - | id!(:) - | id!(:=) - | id!(+=) - | id!(<:) - | id!(+:) - | id!(+=) - | id!(-=) - | id!(*=) - | id!(/=) - | id!(%=) - | id!(&=) - | id!(|=) - | id!(^=) - | id!(<<=) - | id!(>>=) - | id!(?=) => true, - _ => false, - } - } - - fn operator_supports_inline_number(op: LiveId) -> bool { - match op { - id!(*) - | id!(/) - | id!(%) - | id!(+) - | id!(-) - | id!(<<) - | id!(>>) - | id!(&) - | id!(^) - | id!(|) - | id!(<) - | id!(>) - | id!(<=) - | id!(>=) => true, - _ => false, - } - } - - fn operator_to_field_assign(op: LiveId) -> ScriptValue { - match op { - id!(=) | id!(:) => Opcode::ASSIGN_FIELD, - id!(+=) => Opcode::ASSIGN_FIELD_ADD, - id!(-=) => Opcode::ASSIGN_FIELD_SUB, - id!(*=) => Opcode::ASSIGN_FIELD_MUL, - id!(/=) => Opcode::ASSIGN_FIELD_DIV, - id!(%=) => Opcode::ASSIGN_FIELD_MOD, - id!(&=) => Opcode::ASSIGN_FIELD_AND, - id!(|=) => Opcode::ASSIGN_FIELD_OR, - id!(^=) => Opcode::ASSIGN_FIELD_XOR, - id!(<<=) => Opcode::ASSIGN_FIELD_SHL, - id!(>>=) => Opcode::ASSIGN_FIELD_SHR, - id!(?=) => Opcode::ASSIGN_FIELD_IFNIL, - _ => Opcode::NOP, - } - .into() - } - - fn operator_to_index_assign(op: LiveId) -> ScriptValue { - match op { - id!(=) => Opcode::ASSIGN_INDEX, - id!(+=) => Opcode::ASSIGN_INDEX_ADD, - id!(-=) => Opcode::ASSIGN_INDEX_SUB, - id!(*=) => Opcode::ASSIGN_INDEX_MUL, - id!(/=) => Opcode::ASSIGN_INDEX_DIV, - id!(%=) => Opcode::ASSIGN_INDEX_MOD, - id!(&=) => Opcode::ASSIGN_INDEX_AND, - id!(|=) => Opcode::ASSIGN_INDEX_OR, - id!(^=) => Opcode::ASSIGN_INDEX_XOR, - id!(<<=) => Opcode::ASSIGN_INDEX_SHL, - id!(>>=) => Opcode::ASSIGN_INDEX_SHR, - id!(?=) => Opcode::ASSIGN_INDEX_IFNIL, - _ => Opcode::NOP, - } - .into() - } - - fn operator_to_unary(op: LiveId) -> ScriptValue { - match op { - id!(~) => Opcode::LOG, - id!(!) => Opcode::NOT, - id!(-) => Opcode::NEG, - id!(+) => Opcode::NOP, - _ => Opcode::NOP, - } - .into() - } - - fn operator_to_opcode(op: LiveId) -> ScriptValue { - match op { - id!(*) => Opcode::MUL, - id!(/) => Opcode::DIV, - id!(%) => Opcode::MOD, - id!(+) => Opcode::ADD, - id!(-) => Opcode::SUB, - id!(<<) => Opcode::SHL, - id!(>>) => Opcode::SHR, - id!(&) => Opcode::AND, - id!(^) => Opcode::XOR, - id!(|) => Opcode::OR, - id!(++) => Opcode::CONCAT, - id!(is) => Opcode::IS, - id!(==) => Opcode::EQ, - id!(!=) => Opcode::NEQ, - id!(<) => Opcode::LT, - id!(>) => Opcode::GT, - id!(<=) => Opcode::LEQ, - id!(>=) => Opcode::GEQ, - id!(===) => Opcode::SHALLOW_EQ, - id!(!==) => Opcode::SHALLOW_NEQ, - - // &&, ||, |? are handled specially for short-circuit evaluation - id!(&&) => Opcode::LOGIC_AND_TEST, - id!(||) => Opcode::LOGIC_OR_TEST, - id!(|?) => Opcode::NIL_OR_TEST, - id!(:) => Opcode::ASSIGN_ME, - id!(:=) => Opcode::ASSIGN_ME_VEC, - id!(<:) => Opcode::ASSIGN_ME_BEFORE, - id!(>:) => Opcode::ASSIGN_ME_AFTER, - id!(^:) => Opcode::ASSIGN_ME_BEGIN, - id!(=) => Opcode::ASSIGN, - id!(+=) => Opcode::ASSIGN_ADD, - id!(-=) => Opcode::ASSIGN_SUB, - id!(*=) => Opcode::ASSIGN_MUL, - id!(/=) => Opcode::ASSIGN_DIV, - id!(%=) => Opcode::ASSIGN_MOD, - id!(&=) => Opcode::ASSIGN_AND, - id!(|=) => Opcode::ASSIGN_OR, - id!(^=) => Opcode::ASSIGN_XOR, - id!(<<=) => Opcode::ASSIGN_SHL, - id!(>>=) => Opcode::ASSIGN_SHR, - id!(?=) => Opcode::ASSIGN_IFNIL, - id!(..) => Opcode::RANGE, - id!(.) => Opcode::FIELD, - id!(.?) => Opcode::FIELD_NIL, - id!(me.) => Opcode::ME_FIELD, - id!(?) => Opcode::RETURN_IF_ERR, - _ => Opcode::NOP, - } - .into() - } - - fn is_heq_prio(&self, other: State) -> bool { - match self { - Self::EmitOp { what_op: op1, .. } => match other { - Self::EmitOp { what_op: op2, .. } => { - if Self::is_assign_operator(*op1) && Self::is_assign_operator(op2) { - return false; - } - Self::operator_order(*op1) <= Self::operator_order(op2) - } - _ => false, - }, - _ => false, - } - } -} - -/// Represents a nested destructuring pattern (one level deep for now) -#[derive(Clone, Debug)] -pub enum NestedPattern { - /// Nested object pattern like {x, y} - stores binding ids - Object(Vec), - /// Nested array pattern like [x, y] - stores binding ids - Array(Vec), -} - -pub struct ScriptParser { - pub index: u32, - pub opcodes: Vec, - pub source_map: Vec>, - pub had_error: bool, - pub diagnostics: Vec, - pub diagnostics_truncated: bool, - - state: Vec, - emit_errors: bool, - pub file: String, - pub line_offset: usize, - pub col_offset: usize, - - // Temporary storage for destructuring defaults (binding_id, value_code, value_map) - pub(crate) destruct_defaults: Vec<(LiveId, Vec, Vec>)>, - - // Storage for nested patterns during parsing - // Each entry is (pattern_info). The index into this vec is encoded in the ids list. - nested_patterns: Vec, -} - -impl Default for ScriptParser { - fn default() -> Self { - Self { - index: 0, - opcodes: Default::default(), - source_map: Default::default(), - had_error: false, - diagnostics: Default::default(), - diagnostics_truncated: false, - state: vec![State::BeginStmt { - last_was_sep: false, - }], - emit_errors: true, - file: String::new(), - line_offset: 0, - col_offset: 0, - destruct_defaults: Default::default(), - nested_patterns: Default::default(), - } - } -} - -/// Snapshot of parser state that can be restored for incremental parsing. -/// Captures the state before auto-close so we can undo those synthetic closings -/// when more source arrives. -pub struct ParserCheckpoint { - pub opcodes_len: usize, - pub source_map_len: usize, - pub token_index: u32, - state: Vec, - destruct_defaults_len: usize, - nested_patterns_len: usize, - /// The last opcode before the checkpoint, saved because auto-close's - /// set_pop_to_me() mutates it in place. Must be restored on continuation. - last_opcode: Option, - /// Auto-close patches pending logical jumps in place, not just the tail. - short_circuit_opcodes: Vec<(u32, ScriptValue)>, -} - -impl ScriptParser { - /// Controls whether parser errors are forwarded to Makepad's global log. - /// Diagnostics remain available through [`Self::diagnostics`] either way. - pub fn set_emit_errors(&mut self, emit_errors: bool) { - self.emit_errors = emit_errors; - } - - pub fn report_error(&mut self, tokenizer: &ScriptTokenizer, msg: String) { - self.had_error = true; - let (line, col) = tokenizer - .token_index_to_row_col(self.index) - .unwrap_or((0, 0)); - let line = line + self.line_offset as u32; - let column = col + self.col_offset as u32; - if self.diagnostics.len() < MAX_PARSER_DIAGNOSTICS { - let message = msg - .split_once(" (from: ") - .map_or_else(|| msg.clone(), |(message, _)| message.to_owned()); - self.diagnostics.push(ScriptParserDiagnostic { - line, - column, - message, - }); - } else { - self.diagnostics_truncated = true; - } - if self.emit_errors { - log_with_level(&self.file, line, column, line, column, msg, LogLevel::Error); - } - } - - fn code_len(&self) -> u32 { - self.opcodes.len() as _ - } - - fn code_last(&self) -> Option<&ScriptValue> { - self.opcodes.last() - } - - fn pop_code(&mut self) { - self.opcodes.pop(); - self.source_map.pop(); - } - - fn push_code(&mut self, code: ScriptValue, index: u32) { - self.opcodes.push(code); - self.source_map.push(Some(index)); - } - - fn push_code_none(&mut self, code: ScriptValue) { - self.opcodes.push(code); - self.source_map.push(None); - } - - fn insert_code_with_source(&mut self, index: usize, code: ScriptValue, source: Option) { - debug_assert!(index <= self.opcodes.len()); - - // Entries beyond the opcode stream cannot describe an executable opcode. - // Fill missing entries as synthetic before inserting a paired opcode. - self.source_map.truncate(self.opcodes.len()); - self.source_map.resize(self.opcodes.len(), None); - self.opcodes.insert(index, code); - self.source_map.insert(index, source); - } - - fn set_pop_to_me(&mut self) { - if let Some(code) = self.opcodes.last_mut() { - if let Some((opcode, _args)) = code.as_opcode() { - if opcode == Opcode::RETURN { - self.push_code(Opcode::POP_TO_ME.into(), self.index) - } else { - code.set_opcode_args_pop_to_me(); - } - } else { - self.push_code(Opcode::POP_TO_ME.into(), self.index) - } - } - } - - fn has_pop_to_me(&self) -> bool { - if let Some(code) = self.opcodes.last() { - if let Some((opcode, args)) = code.as_opcode() { - if opcode == Opcode::POP_TO_ME { - return true; - } - return args.0 & OpcodeArgs::POP_TO_ME_FLAG != 0; - } - } - false - } - - fn clear_pop_to_me(&mut self) { - if let Some(code) = self.opcodes.last_mut() { - if let Some((opcode, _)) = code.as_opcode() { - if opcode == Opcode::POP_TO_ME { - self.pop_code(); - return; - } - } - code.clear_opcode_args_pop_to_me(); - } - } - - fn set_opcode_args(&mut self, index: u32, args: OpcodeArgs) { - self.opcodes[index as usize].set_opcode_args(args); - } - - fn parse_step( - &mut self, - tokenizer: &ScriptTokenizer, - tok: ScriptToken, - values: &[ScriptValue], - ) -> u32 { - let op = tok.operator(); - let sep = tok.separator(); - let id = tok.identifier(); - match self.state.pop().unwrap() { - State::ForIdent { idents, index } => { - // we push k and v - // allow optional parens: `for (x, y) in z` is identical to `for x, y in z` - if tok.is_open_round() || tok.is_close_round() { - self.state.push(State::ForIdent { idents, index }); - return 1; - } - if id.not_empty() { - if id == id!(in) { - // alright we move on to parsing the range expr - self.state.push(State::ForBody { idents, index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else if idents < 3 { - self.push_code(id.into(), self.index); - self.state.push(State::ForIdent { - idents: idents + 1, - index, - }); - return 1; - } else { - error!(self, tokenizer, "Too many identifiers in for"); - return 0; - } - } - if sep == id!(,) { - // eat the commas - self.state.push(State::ForIdent { idents, index }); - return 1; - } - error!(self, tokenizer, "Unexpected state in parsing for"); - } - State::ForBody { idents, index } => { - // alright lets emit a for instruction - - let code_start = self.code_len(); - if idents == 1 { - self.push_code(Opcode::FOR_1.into(), index); - } else if idents == 2 { - self.push_code(Opcode::FOR_2.into(), index); - } else if idents == 3 { - self.push_code(Opcode::FOR_3.into(), index); - } else { - error!( - self, - tokenizer, "Wrong number of identifiers for for loop {idents}" - ); - return 0; - } - if tok.is_open_curly() { - self.state.push(State::ForBlock { code_start }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else { - self.state.push(State::ForExpr { code_start }); - self.state.push(State::BeginExpr { required: true }); - } - } - State::Loop { index } => { - let code_start = self.code_len(); - self.push_code(Opcode::LOOP.into(), index); - if tok.is_open_curly() { - self.state.push(State::ForBlock { code_start }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else { - self.state.push(State::ForExpr { code_start }); - self.state.push(State::BeginExpr { required: true }); - } - } - State::While { index } => { - let code_start = self.code_len(); - self.push_code(Opcode::LOOP.into(), index); - self.state.push(State::WhileTest { code_start }); - self.state.push(State::BeginExpr { required: true }); - } - State::WhileTest { code_start } => { - self.push_code(Opcode::BREAKIFNOT.into(), self.index); - if tok.is_open_curly() { - self.state.push(State::ForBlock { code_start }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else { - self.state.push(State::ForExpr { code_start }); - self.state.push(State::BeginExpr { required: true }); - } - } - // Match expression desugaring: - // match x { 1 => true, 2 => {false} } - // becomes: - // let $mN = x - // if $mN == 1 true else if $mN == 2 {false} - State::MatchSubject { temp_id, index } => { - // Subject expression has been parsed - // Order is now: [temp_id, subject_value] - emit LET_DYN - self.push_code(Opcode::LET_DYN.into(), index); - self.state.push(State::MatchBlock { temp_id, index }); - } - State::MatchBlock { temp_id, index } => { - if tok.is_open_curly() { - self.state.push(State::MatchArmPattern { - temp_id, - first: true, - prev_else_start: 0, - index, - }); - return 1; - } else { - error!(self, tokenizer, "Expected {{ after match expression"); - } - } - State::MatchArmPattern { - temp_id, - first: _, - prev_else_start, - index, - } => { - if tok.is_close_curly() { - // Empty match - patch any pending IF_ELSE and push nil - if prev_else_start > 0 { - self.set_opcode_args( - prev_else_start, - OpcodeArgs::from_u32(self.code_len() as u32 - prev_else_start), - ); - } - self.push_code(NIL, index); - self.state.push(State::EndExpr); - return 1; - } - // Check for wildcard pattern `_` - if id == id!(_) { - // Wildcard pattern - just expect => and body - self.state.push(State::MatchWildcardArrow { - prev_else_start, - index, - }); - return 1; - } - // Emit temp_id to push the match subject value - self.push_code(ScriptValue::from_id(temp_id), index); - // Parse the pattern expression - self.state.push(State::MatchArmArrow { - temp_id, - prev_else_start, - index, - }); - self.state.push(State::BeginExpr { required: true }); - } - State::MatchArmArrow { - temp_id, - prev_else_start, - index, - } => { - // Pattern expression done, emit EQ and IF_TEST - self.push_code(Opcode::EQ.into(), index); - let if_start = self.code_len(); - self.push_code(Opcode::IF_TEST.into(), index); - // Expect => - if op == id!(=>) { - // Parse arm body - check for block or expression - self.state.push(State::MatchArmBody { - temp_id, - if_start, - prev_else_start, - index, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected => after match pattern, got {:?}", tok - ); - } - } - State::MatchArmBody { - temp_id, - if_start, - prev_else_start, - index, - } => { - // Check if arm body is a block or expression (like IfTest does) - if tok.is_open_curly() { - // Block body - use BeginStmt like if blocks - self.state.push(State::MatchArmBlock { - temp_id, - if_start, - prev_else_start, - last_was_sep: false, - index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // Expression body - self.state.push(State::MatchMaybeArm { - temp_id, - if_start, - prev_else_start, - index, - }); - self.state.push(State::BeginExpr { required: true }); - } - State::MatchArmBlock { - temp_id, - if_start, - prev_else_start, - last_was_sep, - index, - } => { - // Block body done, expect } - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.state.push(State::MatchMaybeArm { - temp_id, - if_start, - prev_else_start, - index, - }); - return 1; - } else { - error!(self, tokenizer, "Expected }} in match arm block"); - } - } - State::MatchWildcardArrow { - prev_else_start, - index, - } => { - // Wildcard pattern done, expect => - if op == id!(=>) { - // Parse wildcard arm body - check for block or expression - self.state.push(State::MatchWildcardBody { - prev_else_start, - index, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected => after _ wildcard pattern, got {:?}", tok - ); - } - } - State::MatchWildcardBody { - prev_else_start, - index, - } => { - // Check if wildcard body is a block or expression - if tok.is_open_curly() { - // Block body - self.state.push(State::MatchWildcardBlock { - prev_else_start, - last_was_sep: false, - index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // Expression body - self.state.push(State::MatchWildcardEnd { - prev_else_start, - index, - }); - self.state.push(State::BeginExpr { required: true }); - } - State::MatchWildcardBlock { - prev_else_start, - last_was_sep, - index, - } => { - // Wildcard block body done, expect } - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.state.push(State::MatchWildcardEnd { - prev_else_start, - index, - }); - return 1; - } else { - error!(self, tokenizer, "Expected }} in wildcard arm block"); - } - } - State::MatchWildcardEnd { - prev_else_start, - index: _, - } => { - // Wildcard body done - patch any pending IF_ELSE to jump here - if prev_else_start > 0 { - self.set_opcode_args( - prev_else_start, - OpcodeArgs::from_u32(self.code_len() as u32 - prev_else_start), - ); - } - // Expect } - if tok.is_close_curly() { - self.state.push(State::EndExpr); - return 1; - } else { - error!( - self, - tokenizer, "Expected }} after wildcard arm (no more arms allowed after _)" - ); - } - } - State::MatchMaybeArm { - temp_id, - if_start, - prev_else_start, - index, - } => { - // Arm body parsed. Now emit IF_ELSE and patch IF_TEST. - - // First, patch any previous arm's IF_ELSE to jump here (to current position) - if prev_else_start > 0 { - self.set_opcode_args( - prev_else_start, - OpcodeArgs::from_u32(self.code_len() as u32 - prev_else_start), - ); - } - - if tok.is_close_curly() { - // End of match - no more arms, patch IF_TEST with need_nil flag - self.set_opcode_args( - if_start, - OpcodeArgs::from_u32(self.code_len() as u32 - if_start).set_need_nil(), - ); - self.state.push(State::EndExpr); - return 1; - } - - // More arms coming - emit IF_ELSE to skip remaining arms after this arm's body - let else_start = self.code_len(); - self.push_code(Opcode::IF_ELSE.into(), index); - - // Patch IF_TEST to jump here (after arm body and IF_ELSE) to next arm - self.set_opcode_args( - if_start, - OpcodeArgs::from_u32(self.code_len() as u32 - if_start), - ); - - // Check for wildcard or regular arm - if id == id!(_) { - // Next arm is wildcard - it's the final else body - self.state.push(State::MatchWildcardArrow { - prev_else_start: else_start, - index, - }); - return 1; - } - - // Continue with next regular arm, passing this arm's else_start - self.state.push(State::MatchArmPattern { - temp_id, - first: false, - prev_else_start: else_start, - index, - }); - } - State::ForExpr { code_start } => { - self.set_pop_to_me(); - //self.push_code_none(Opcode::POP_TO_ME.into()); - self.push_code_none(Opcode::FOR_END.into()); - let jump_to = (self.code_len() - code_start) as _; - self.set_opcode_args(code_start, OpcodeArgs::from_u32(jump_to)); - return 0; - } - State::ForBlock { code_start } => { - if tok.is_close_curly() { - self.push_code_none(Opcode::FOR_END.into()); - let jump_to = (self.code_len() - code_start) as _; - self.set_opcode_args(code_start, OpcodeArgs::from_u32(jump_to)); - return 1; - } else { - error!(self, tokenizer, "Expected }} not found in for"); - return 0; - } - } - State::Use { index } => { - if let Some(code) = self.opcodes.last() { - if let Some((Opcode::FIELD, _)) = code.as_opcode() { - self.pop_code(); - self.push_code(Opcode::USE.into(), index) - } else { - error!(self, tokenizer, "Error use expected field operation") - } - } - } - State::Let { index } => { - if id == id!(mut) { - // "let mut" is treated as "var" - self.state.push(State::Var { index }); - return 1; - } else if tok.is_open_square() { - // Array destructuring: let [x, y] = ... - let ids_start = self.code_len(); - self.state.push(State::LetArrayDestruct { - index, - count: 0, - ids_start, - }); - return 1; - } else if tok.is_open_curly() { - // Object destructuring: let {x, y} = ... - let ids_start = self.code_len(); - self.state.push(State::LetObjectDestruct { - index, - count: 0, - ids_start, - }); - return 1; - } else if id.not_empty() { - // lets expect an assignment expression - // push the id on to the stack - self.push_code(id.into(), self.index); - self.state.push(State::LetDynOrTyped { index }); - return 1; - } else { - // unknown - error!(self, tokenizer, "Let expected identifier"); - } - } - State::LetDynOrTyped { index } => { - if op == id!(=) { - // assignment following - self.state.push(State::EmitLetDyn { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else if op == id!(:) { - // type following - self.state.push(State::LetType { index }); - return 1; - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::LET_DYN, OpcodeArgs::NIL), - index, - ); - } - } - State::LetType { index } => { - if id.not_empty() { - // lets expect an assignment expression - // push the id on to the stack - self.push_code(id.into(), self.index); - self.state.push(State::LetTypedAssign { index }); - return 1; - } else { - // unknown - error!(self, tokenizer, "Let type expected"); - } - } - State::LetTypedAssign { index } => { - if op == id!(=) { - // assignment following - self.state.push(State::EmitLetTyped { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::LET_TYPED, OpcodeArgs::NIL), - index, - ); - } - } - State::EmitLetDyn { index } => { - self.push_code(Opcode::LET_DYN.into(), index); - } - State::EmitLetTyped { index } => { - self.push_code(Opcode::LET_TYPED.into(), index); - } - - // ====== Array Destructuring: let [x, y = default, ...] = expr ====== - // Layout during parsing: [ids..., defaults_with_ifnil..., rhs] - // Final generated code: [rhs, id_0, EXTRACT(0), id_1, EXTRACT(1), ..., DROP, defaults_with_ifnil] - State::LetArrayDestruct { - index, - count, - ids_start, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestruct { - index, - count, - ids_start, - }); - return 1; - } - if id.not_empty() { - // Just push the identifier - self.push_code(id.into(), self.index); - self.state.push(State::LetArrayDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_open_curly() { - // Nested object pattern: let [{x, y}] = ... - // Push a marker that will be replaced with the nested pattern index - self.push_code(Opcode::NOP.into(), self.index); // placeholder - self.state.push(State::LetArrayDestructNestedObject { - index, - outer_count: count + 1, - outer_ids_start: ids_start, - nested_count: 0, - }); - return 1; - } else if tok.is_open_square() { - // Nested array pattern: let [[x, y]] = ... - self.push_code(Opcode::NOP.into(), self.index); // placeholder - self.state.push(State::LetArrayDestructNestedArray { - index, - outer_count: count + 1, - outer_ids_start: ids_start, - nested_count: 0, - }); - return 1; - } else if tok.is_close_square() { - let defaults_start = self.code_len(); - self.state.push(State::LetArrayDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in array destructuring pattern" - ); - } - } - State::LetArrayDestructEl { - index, - count, - binding_id, - ids_start, - } => { - if op == id!(=) { - // Default value follows - parse it - let default_start = self.code_len(); - self.state.push(State::LetArrayDestructDefault { - index, - count, - binding_id, - ids_start, - default_start, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestruct { - index, - count, - ids_start, - }); - return 1; - } else if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::LetArrayDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_close_square() { - let defaults_start = self.code_len(); - self.state.push(State::LetArrayDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected '=' or identifier in array destructuring pattern" - ); - } - } - State::LetArrayDestructDefault { - index, - count, - binding_id, - ids_start, - default_start, - } => { - // Default was parsed (value is in code stream at default_start..current) - // Store it for later emission, don't emit inline - let default_start = default_start as usize; - let value_code: Vec<_> = self.opcodes[default_start..].to_vec(); - let value_map: Vec<_> = self.source_map[default_start..].to_vec(); - self.opcodes.truncate(default_start); - self.source_map.truncate(default_start); - - // Store the default for later - self.destruct_defaults - .push((binding_id, value_code, value_map)); - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestruct { - index, - count, - ids_start, - }); - return 1; - } else if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::LetArrayDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_close_square() { - let defaults_start = self.code_len(); - self.state.push(State::LetArrayDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - self.state.push(State::LetArrayDestruct { - index, - count, - ids_start, - }); - return 0; - } - } - // Nested object pattern inside array: let [{x, y}] = ... - State::LetArrayDestructNestedObject { - index, - outer_count, - outer_ids_start, - nested_count, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestructNestedObject { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 1; - } - if id.not_empty() { - self.state.push(State::LetArrayDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_curly() { - // Nested pattern complete - bindings were collected in NestedObjectEl - if let Some(NestedPattern::Object(ref bindings)) = self.nested_patterns.last() { - if bindings.len() == nested_count as usize { - // Pattern is complete, update the placeholder with the pattern index - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = - outer_ids_start as usize + outer_count as usize - 1; - // Encode the nested pattern as a special marker: NOP with args = pattern_index + 1 (so 0 means "not nested") - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - } - } - self.state.push(State::LetArrayDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in nested object pattern" - ); - } - } - State::LetArrayDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - nested_count, - binding_id, - } => { - // Store the binding in the nested pattern - if nested_count == 1 { - // First binding - create new pattern - self.nested_patterns - .push(NestedPattern::Object(vec![binding_id])); - } else { - // Add to existing pattern - if let Some(NestedPattern::Object(ref mut bindings)) = - self.nested_patterns.last_mut() - { - bindings.push(binding_id); - } - } - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestructNestedObject { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 1; - } else if id.not_empty() { - self.state.push(State::LetArrayDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_curly() { - // Pattern complete - update placeholder - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - self.state.push(State::LetArrayDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - self.state.push(State::LetArrayDestructNestedObject { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 0; - } - } - - // Nested array pattern inside array: let [[x, y]] = ... - State::LetArrayDestructNestedArray { - index, - outer_count, - outer_ids_start, - nested_count, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestructNestedArray { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 1; - } - if id.not_empty() { - self.state.push(State::LetArrayDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_square() { - // Nested pattern complete - if let Some(NestedPattern::Array(ref bindings)) = self.nested_patterns.last() { - if bindings.len() == nested_count as usize { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = - outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - } - } - self.state.push(State::LetArrayDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in nested array pattern" - ); - } - } - State::LetArrayDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - nested_count, - binding_id, - } => { - // Store the binding - if nested_count == 1 { - self.nested_patterns - .push(NestedPattern::Array(vec![binding_id])); - } else { - if let Some(NestedPattern::Array(ref mut bindings)) = - self.nested_patterns.last_mut() - { - bindings.push(binding_id); - } - } - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetArrayDestructNestedArray { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 1; - } else if id.not_empty() { - self.state.push(State::LetArrayDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_square() { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - self.state.push(State::LetArrayDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - self.state.push(State::LetArrayDestructNestedArray { - index, - outer_count, - outer_ids_start, - nested_count, - }); - return 0; - } - } - - State::LetArrayDestructRhs { - index, - count, - ids_start, - defaults_start, - } => { - if op == id!(=) { - self.state.push(State::EmitLetArrayDestruct { - index, - count, - ids_start, - defaults_start, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - error!(self, tokenizer, "Expected '=' after destructuring pattern"); - } - } - State::EmitLetArrayDestruct { - index, - count, - ids_start, - defaults_start, - } => { - // Layout: [ids..., rhs_code], defaults stored in destruct_defaults - // Generate: [rhs, id_0, EXTRACT(0), ..., DROP, defaults_code...] - // For nested patterns: [rhs, DUP, idx, ARRAY_INDEX_NIL, nested_bindings..., DROP, ...] - - let ids_start = ids_start as usize; - let defaults_start = defaults_start as usize; - let count = count as usize; - - let ids: Vec<_> = self.opcodes[ids_start..ids_start + count].to_vec(); - let ids_map: Vec<_> = self.source_map[ids_start..ids_start + count].to_vec(); - let rhs: Vec<_> = self.opcodes[defaults_start..].to_vec(); - let rhs_map: Vec<_> = self.source_map[defaults_start..].to_vec(); - - self.opcodes.truncate(ids_start); - self.source_map.truncate(ids_start); - - // RHS first - self.opcodes.extend(rhs); - self.source_map.extend(rhs_map); - - // Process each element - check for nested patterns - for (i, (id_code, id_map)) in ids.into_iter().zip(ids_map).enumerate() { - // Check if this is a nested pattern marker (NOP with non-zero args) - if let Some((opcode, args)) = id_code.as_opcode() { - if opcode == Opcode::NOP && args.to_u32() > 0 { - // This is a nested pattern - let pattern_idx = (args.to_u32() - 1) as usize; - if let Some(pattern) = self.nested_patterns.get(pattern_idx).cloned() { - // Emit: DUP, index, ARRAY_INDEX_NIL, nested extraction, DROP - self.push_code(Opcode::DUP.into(), index); - self.push_code(i.into(), index); - self.push_code(Opcode::ARRAY_INDEX_NIL.into(), index); - - match pattern { - NestedPattern::Object(bindings) => { - // For nested object: id, LET_DESTRUCT_OBJECT_EL for each binding - for binding_id in bindings { - self.push_code(binding_id.into(), index); - self.push_code( - Opcode::LET_DESTRUCT_OBJECT_EL.into(), - index, - ); - } - } - NestedPattern::Array(bindings) => { - // For nested array: id, LET_DESTRUCT_ARRAY_EL(j) for each binding - for (j, binding_id) in bindings.into_iter().enumerate() { - self.push_code(binding_id.into(), index); - self.push_code( - ScriptValue::from_opcode_args( - Opcode::LET_DESTRUCT_ARRAY_EL, - OpcodeArgs::from_u32(j as u32), - ), - index, - ); - } - } - } - - // DROP the nested source - self.push_code(Opcode::DROP.into(), index); - continue; - } - } - } - - // Simple identifier - emit normally - self.opcodes.push(id_code); - self.source_map.push(id_map); - self.push_code( - ScriptValue::from_opcode_args( - Opcode::LET_DESTRUCT_ARRAY_EL, - OpcodeArgs::from_u32(i as u32), - ), - index, - ); - } - - // DROP outer source - self.push_code(Opcode::DROP.into(), index); - - // Emit stored defaults with lazy evaluation: [id, ASSIGN_IFNIL(jump), value, ASSIGN] - // jump_dist = value_code.len() + 2 to skip past value_code AND the ASSIGN opcode - let defaults = std::mem::take(&mut self.destruct_defaults); - for (binding_id, value_code, value_map) in defaults { - let jump_dist = (value_code.len() + 2) as u32; - self.push_code(binding_id.into(), index); - self.push_code( - ScriptValue::from_opcode_args( - Opcode::ASSIGN_IFNIL, - OpcodeArgs::from_u32(jump_dist), - ), - index, - ); - self.opcodes.extend(value_code); - self.source_map.extend(value_map); - self.push_code(Opcode::ASSIGN.into(), index); - } - - // Clear nested patterns for next destructuring - self.nested_patterns.clear(); - - // This is a let statement, go directly to BeginStmt to avoid pop_to_me being set on DROP - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - - // ====== Object Destructuring: let {x, y = default, ...} = expr ====== - State::LetObjectDestruct { - index, - count, - ids_start, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestruct { - index, - count, - ids_start, - }); - return 1; - } - if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::LetObjectDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_close_curly() { - let defaults_start = self.code_len(); - self.state.push(State::LetObjectDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in object destructuring pattern" - ); - } - } - State::LetObjectDestructEl { - index, - count, - binding_id, - ids_start, - } => { - if op == id!(=) { - // Default value follows - parse it - let default_start = self.code_len(); - self.state.push(State::LetObjectDestructDefault { - index, - count, - binding_id, - ids_start, - default_start, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestruct { - index, - count, - ids_start, - }); - return 1; - } else if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::LetObjectDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_close_curly() { - let defaults_start = self.code_len(); - self.state.push(State::LetObjectDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected '=' or identifier in object destructuring pattern" - ); - } - } - State::LetObjectDestructDefault { - index, - count, - binding_id, - ids_start, - default_start, - } => { - // Default was parsed - store it for later emission, don't emit inline - let default_start = default_start as usize; - let value_code: Vec<_> = self.opcodes[default_start..].to_vec(); - let value_map: Vec<_> = self.source_map[default_start..].to_vec(); - self.opcodes.truncate(default_start); - self.source_map.truncate(default_start); - - // Store the default for later - self.destruct_defaults - .push((binding_id, value_code, value_map)); - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestruct { - index, - count, - ids_start, - }); - return 1; - } else if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::LetObjectDestructEl { - index, - count: count + 1, - binding_id: id, - ids_start, - }); - return 1; - } else if tok.is_close_curly() { - let defaults_start = self.code_len(); - self.state.push(State::LetObjectDestructRhs { - index, - count, - ids_start, - defaults_start, - }); - return 1; - } else { - self.state.push(State::LetObjectDestruct { - index, - count, - ids_start, - }); - return 0; - } - } - // Nested array pattern inside object: let {a: [x, y]} = ... - State::LetObjectDestructNestedArray { - index, - outer_count, - outer_ids_start, - key, - nested_count, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestructNestedArray { - index, - outer_count, - outer_ids_start, - key, - nested_count, - }); - return 1; - } - if id.not_empty() { - self.state.push(State::LetObjectDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - key, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_square() { - // Pattern complete - if let Some(NestedPattern::Array(ref bindings)) = self.nested_patterns.last() { - if bindings.len() == nested_count as usize { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = - outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - } - } - self.state.push(State::LetObjectDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in nested array pattern" - ); - } - } - State::LetObjectDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - key: _, - nested_count, - binding_id, - } => { - if nested_count == 1 { - self.nested_patterns - .push(NestedPattern::Array(vec![binding_id])); - } else { - if let Some(NestedPattern::Array(ref mut bindings)) = - self.nested_patterns.last_mut() - { - bindings.push(binding_id); - } - } - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestructNestedArray { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count, - }); - return 1; - } else if id.not_empty() { - self.state.push(State::LetObjectDestructNestedArrayEl { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_square() { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - self.state.push(State::LetObjectDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - self.state.push(State::LetObjectDestructNestedArray { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count, - }); - return 0; - } - } - - // Nested object pattern inside object: let {a: {x, y}} = ... - State::LetObjectDestructNestedObject { - index, - outer_count, - outer_ids_start, - key, - nested_count, - } => { - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestructNestedObject { - index, - outer_count, - outer_ids_start, - key, - nested_count, - }); - return 1; - } - if id.not_empty() { - self.state.push(State::LetObjectDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - key, - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_curly() { - // Pattern complete - if let Some(NestedPattern::Object(ref bindings)) = self.nested_patterns.last() { - if bindings.len() == nested_count as usize { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = - outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - } - } - self.state.push(State::LetObjectDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - error!( - self, - tokenizer, "Expected identifier in nested object pattern" - ); - } - } - State::LetObjectDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - key: _, - nested_count, - binding_id, - } => { - if nested_count == 1 { - self.nested_patterns - .push(NestedPattern::Object(vec![binding_id])); - } else { - if let Some(NestedPattern::Object(ref mut bindings)) = - self.nested_patterns.last_mut() - { - bindings.push(binding_id); - } - } - - if sep == id!(,) || sep == id!(;) { - self.state.push(State::LetObjectDestructNestedObject { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count, - }); - return 1; - } else if id.not_empty() { - self.state.push(State::LetObjectDestructNestedObjectEl { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count: nested_count + 1, - binding_id: id, - }); - return 1; - } else if tok.is_close_curly() { - let pattern_idx = self.nested_patterns.len() - 1; - let placeholder_pos = outer_ids_start as usize + outer_count as usize - 1; - self.opcodes[placeholder_pos] = ScriptValue::from_opcode_args( - Opcode::NOP, - OpcodeArgs::from_u32((pattern_idx + 1) as u32), - ); - self.state.push(State::LetObjectDestruct { - index, - count: outer_count, - ids_start: outer_ids_start, - }); - return 1; - } else { - self.state.push(State::LetObjectDestructNestedObject { - index, - outer_count, - outer_ids_start, - key: LiveId::empty(), - nested_count, - }); - return 0; - } - } - - State::LetObjectDestructRhs { - index, - count, - ids_start, - defaults_start, - } => { - if op == id!(=) { - self.state.push(State::EmitLetObjectDestruct { - index, - count, - ids_start, - defaults_start, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - error!(self, tokenizer, "Expected '=' after destructuring pattern"); - } - } - State::EmitLetObjectDestruct { - index, - count, - ids_start, - defaults_start, - } => { - // Layout: [ids..., rhs_code], defaults stored in destruct_defaults - // Generate: [rhs, id_0, EXTRACT, ..., DROP, defaults_code...] - - let ids_start = ids_start as usize; - let defaults_start = defaults_start as usize; - let count = count as usize; - - let ids: Vec<_> = self.opcodes[ids_start..ids_start + count].to_vec(); - let ids_map: Vec<_> = self.source_map[ids_start..ids_start + count].to_vec(); - let rhs: Vec<_> = self.opcodes[defaults_start..].to_vec(); - let rhs_map: Vec<_> = self.source_map[defaults_start..].to_vec(); - - self.opcodes.truncate(ids_start); - self.source_map.truncate(ids_start); - - // RHS first - self.opcodes.extend(rhs); - self.source_map.extend(rhs_map); - - // id, EXTRACT for each - for (id_code, id_map) in ids.into_iter().zip(ids_map) { - self.opcodes.push(id_code); - self.source_map.push(id_map); - self.push_code(Opcode::LET_DESTRUCT_OBJECT_EL.into(), index); - } - - // DROP source - self.push_code(Opcode::DROP.into(), index); - - // Emit stored defaults with lazy evaluation: [id, ASSIGN_IFNIL(jump), value, ASSIGN] - // jump_dist = value_code.len() + 2 to skip past value_code AND the ASSIGN opcode - let defaults = std::mem::take(&mut self.destruct_defaults); - for (binding_id, value_code, value_map) in defaults { - let jump_dist = (value_code.len() + 2) as u32; - self.push_code(binding_id.into(), index); - self.push_code( - ScriptValue::from_opcode_args( - Opcode::ASSIGN_IFNIL, - OpcodeArgs::from_u32(jump_dist), - ), - index, - ); - self.opcodes.extend(value_code); - self.source_map.extend(value_map); - self.push_code(Opcode::ASSIGN.into(), index); - } - - // This is a let statement, go directly to BeginStmt to avoid pop_to_me being set on DROP - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - - State::Var { index } => { - if id.not_empty() { - // lets expect an assignment expression - // push the id on to the stack - self.push_code(id.into(), self.index); - self.state.push(State::VarDynOrTyped { index }); - return 1; - } else { - // unknown - error!(self, tokenizer, "Var expected identifier"); - } - } - State::VarDynOrTyped { index } => { - if op == id!(=) { - // assignment following - self.state.push(State::EmitVarDyn { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else if op == id!(:) { - // type following - self.state.push(State::VarType { index }); - return 1; - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::VAR_DYN, OpcodeArgs::NIL), - index, - ); - } - } - State::VarType { index } => { - if id.not_empty() { - // lets expect an assignment expression - // push the id on to the stack - self.push_code(id.into(), self.index); - self.state.push(State::VarTypedAssign { index }); - return 1; - } else { - // unknown - error!(self, tokenizer, "Var type expected"); - } - } - State::VarTypedAssign { index } => { - if op == id!(=) { - // assignment following - self.state.push(State::EmitVarTyped { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::VAR_TYPED, OpcodeArgs::NIL), - index, - ); - } - } - State::EmitVarDyn { index } => { - self.push_code(Opcode::VAR_DYN.into(), index); - } - State::EmitVarTyped { index } => { - self.push_code(Opcode::VAR_TYPED.into(), index); - } - State::EndRound => { - // we expect a ) here - //self.code.push(Opcode::END_FRAG.into()); - if tok.is_close_round() { - self.state.push(State::EndExpr); - return 1; - } else { - error!(self, tokenizer, "Expected )") - } - } - State::EmitFnArgTyped { index } => { - self.push_code(Opcode::FN_ARG_TYPED.into(), index); - } - State::EmitFnArgDyn { index } => { - self.push_code(Opcode::FN_ARG_DYN.into(), index); - } - State::FnMaybeLet { index } => { - if id.not_empty() { - // ok we did fn id - self.push_code(id.into(), self.index); - self.push_code(Opcode::FN_LET_ARGS.into(), self.index); - self.state.push(State::FnLetMaybeArgs); - return 1; - } else if tok.is_open_curly() { - // zero args function - self.push_code(Opcode::FN_ARGS.into(), self.index); - let fn_slot = self.code_len(); - self.push_code(Opcode::FN_BODY_DYN.into(), self.index); - self.state.push(State::EndFnBlock { - fn_slot, - last_was_sep: false, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // immediate args - else if tok.is_open_round() { - self.push_code(Opcode::FN_ARGS.into(), self.index); - self.state.push(State::FnArgList { lambda: false }); - return 1; - } else { - self.state.push(State::EmitFnArgDyn { index }); - error!(self, tokenizer, "Argument type expected in function"); - } - } - State::FnLetMaybeArgs => { - // no args - if tok.is_open_curly() { - let fn_slot = self.code_len(); - self.push_code(Opcode::FN_BODY_DYN.into(), self.index); - self.state.push(State::EndFnBlock { - fn_slot, - last_was_sep: false, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if tok.is_open_round() { - self.state.push(State::FnArgList { lambda: false }); - return 1; - } else { - error!( - self, - tokenizer, "Expected either {{ or ( in function definition" - ); - } - } - State::FnArgType { lambda, index } => { - if id.not_empty() { - self.push_code(id.into(), self.index); - self.state.push(State::FnArgTypeAssign { lambda, index }); - return 1; - } else { - self.state.push(State::EmitFnArgDyn { index }); - error!(self, tokenizer, "Argument type expected in function") - } - } - State::FnArgTypeAssign { lambda, index } => { - if !lambda && op == id!(=) { - // assignment following - self.state.push(State::EmitFnArgTyped { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::FN_ARG_TYPED, OpcodeArgs::NIL), - index, - ); - } - } - State::FnArgMaybeType { lambda, index } => { - if !lambda && op == id!(=) { - // assignment following - self.state.push(State::EmitFnArgDyn { index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if op == id!(:) { - self.state.push(State::FnArgType { lambda, index }); - return 1; - } - self.push_code( - ScriptValue::from_opcode_args(Opcode::FN_ARG_DYN, OpcodeArgs::NIL), - index, - ); - } - State::FnArgList { lambda } => { - if id.not_empty() { - // ident - self.push_code(id.into(), self.index); - self.state.push(State::FnArgList { lambda }); - self.state.push(State::FnArgMaybeType { - lambda, - index: self.index, - }); - return 1; - } - if lambda && op == id!(|) { - self.state.push(State::FnBody { lambda }); - return 1; - } else if !lambda && tok.is_close_round() { - self.state.push(State::FnBody { lambda }); - return 1; - } - if sep == id!(,) { - self.state.push(State::FnArgList { lambda }); - return 1; - } - // unexpected token, but just stay in the arg list mode - error!( - self, - tokenizer, "Unexpected token in function argument list {:?}", tok - ); - self.state.push(State::FnArgList { lambda }); - return 1; - } - State::FnBody { lambda } => { - // Check for return type annotation with -> - if op == id!(->) { - self.state.push(State::FnReturnType { lambda }); - return 1; - } - let fn_slot = self.code_len() as _; - self.push_code(Opcode::FN_BODY_DYN.into(), self.index); - if tok.is_open_curly() { - // function body - self.state.push(State::EndFnBlock { - fn_slot, - last_was_sep: false, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if lambda { - // function body can be expression expression - self.state.push(State::EndFnExpr { - fn_slot, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - } else { - error!( - self, - tokenizer, "Unexpected token in function definition, expected {{ {:?}", tok - ); - } - } - State::FnReturnType { lambda } => { - if id.not_empty() { - // we have a return type identifier - self.push_code(id.into(), self.index); - self.state.push(State::FnBodyTyped { lambda }); - return 1; - } else { - error!(self, tokenizer, "Expected return type after ->"); - } - } - State::FnBodyTyped { lambda } => { - let fn_slot = self.code_len() as _; - self.push_code(Opcode::FN_BODY_TYPED.into(), self.index); - if tok.is_open_curly() { - // function body - self.state.push(State::EndFnBlock { - fn_slot, - last_was_sep: false, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if lambda { - // function body can be expression expression - self.state.push(State::EndFnExpr { - fn_slot, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - } else { - error!( - self, - tokenizer, "Unexpected token in function definition, expected {{ {:?}", tok - ); - } - } - State::EscapedId => { - if id.not_empty() { - // ident - self.push_code(id.escape(), self.index); - return 1; - } else { - error!(self, tokenizer, "Expected identifier after @"); - } - } - State::EndFnExpr { fn_slot, index } => { - self.push_code(Opcode::RETURN.into(), index); - self.set_opcode_args( - fn_slot as _, - OpcodeArgs::from_u32(self.code_len() as u32 - fn_slot), - ); - } - State::EndFnBlock { - fn_slot, - last_was_sep, - index, - } => { - /* if !last_was_sep && Some(&Opcode::POP_TO_ME.into()) == self.code_last(){ - self.pop_code(); - self.push_code(Opcode::RETURN.into(), index); - }*/ - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - self.push_code(Opcode::RETURN.into(), index); - } else { - self.push_code( - ScriptValue::from_opcode_args(Opcode::RETURN, OpcodeArgs::NIL), - index, - ); - } - self.set_opcode_args( - fn_slot as _, - OpcodeArgs::from_u32(self.code_len() as u32 - fn_slot), - ); - - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // alright we parsed a + b * c - State::EmitFieldAssign { what_op, index } => { - self.push_code(State::operator_to_field_assign(what_op), index); - } - State::EmitIndexAssign { what_op, index } => { - self.push_code(State::operator_to_index_assign(what_op), index); - } - State::EmitOp { what_op, index } => { - if State::operator_supports_inline_number(what_op) { - if let Some(code) = self.code_last() { - if let Some(vf64) = code.as_f64() { - let num = vf64 as u64; - if vf64.fract() == 0.0 && num <= OpcodeArgs::MAX_U32 as u64 { - self.pop_code(); - let mut value = State::operator_to_opcode(what_op); - value.set_opcode_args(OpcodeArgs::from_u32(num as u32)); - self.push_code(value, index); - return 0; - } - } - } - } - self.push_code(State::operator_to_opcode(what_op), index); - return 0; - } - State::EmitUnary { what_op, index } => { - self.push_code(State::operator_to_unary(what_op), index); - return 0; - } - State::EmitSplat { index } => { - self.push_code(Opcode::ME_SPLAT.into(), index); - return 0; - } - State::ShortCircuitEnd { test_slot, .. } => { - // Patch the TEST opcode's jump to skip to current position (after second operand) - self.set_opcode_args(test_slot, OpcodeArgs::from_u32(self.code_len() - test_slot)); - return 0; - } - State::ShortCircuitAssignEnd { test_slot, index } => { - // Emit ASSIGN after RHS, then patch the jump - self.push_code(Opcode::ASSIGN.into(), index); - self.set_opcode_args(test_slot, OpcodeArgs::from_u32(self.code_len() - test_slot)); - return 0; - } - State::EmitReturn { - index, - code_len_before, - } => { - if self.code_len() as u32 == code_len_before { - // No expression was parsed after `return` — bare void return - self.push_code( - ScriptValue::from_opcode_args(Opcode::RETURN, OpcodeArgs::NIL), - index, - ); - } else { - // Expression was parsed — return with value - self.push_code(Opcode::RETURN.into(), index); - } - return 0; - } - State::EmitBreak { index } => { - self.push_code(Opcode::BREAK.into(), index); - return 0; - } - State::EmitContinue { index } => { - self.push_code(Opcode::CONTINUE.into(), index); - return 0; - } - State::EndBareSquare => { - self.push_code(Opcode::END_ARRAY.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_square() { - return 1; - } else { - error!(self, tokenizer, "Expected ] not found"); - return 0; - } - } - State::EndBare => { - self.push_code(Opcode::END_BARE.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // emit the create prototype instruction - State::EndProto => { - self.push_code(Opcode::END_PROTO.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // emit prototype instruction + proto inherit write (for +: operator) - State::EndProtoInherit => { - self.push_code(Opcode::END_PROTO.into(), self.index); - self.push_code(Opcode::PROTO_INHERIT_WRITE.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // emit prototype instruction + scope inherit write (for value += {} operator) - State::EndScopeInherit => { - self.push_code(Opcode::END_PROTO.into(), self.index); - self.push_code(Opcode::SCOPE_INHERIT_WRITE.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // emit prototype instruction + field inherit write (for obj.field += {} operator) - State::EndFieldInherit => { - self.push_code(Opcode::END_PROTO.into(), self.index); - self.push_code(Opcode::FIELD_INHERIT_WRITE.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - // emit prototype instruction + index inherit write (for obj[index] += {} operator) - State::EndIndexInherit => { - self.push_code(Opcode::END_PROTO.into(), self.index); - self.push_code(Opcode::INDEX_INHERIT_WRITE.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_curly() { - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - State::EmitCallFromDo { is_method, index } => { - self.set_pop_to_me(); - if is_method { - self.push_code(Opcode::METHOD_CALL_EXEC.into(), index); - } else { - self.push_code(Opcode::CALL_EXEC.into(), index); - } - self.state.push(State::EndExpr); - } - State::CallMaybeDo { is_method, index } => { - if id == id!(do) { - self.state.push(State::EmitCallFromDo { is_method, index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } else { - if is_method { - self.push_code(Opcode::METHOD_CALL_EXEC.into(), index); - } else { - self.push_code(Opcode::CALL_EXEC.into(), index); - } - self.state.push(State::EndExpr); - return 0; - } - } - State::EndCall { is_method, index } => { - // expect ) - self.state.push(State::CallMaybeDo { is_method, index }); - if tok.is_close_round() { - return 1; - } else { - error!(self, tokenizer, "Expected ) not found"); - return 0; - } - } - State::ArrayIndex => { - self.push_code(Opcode::ARRAY_INDEX.into(), self.index); - self.state.push(State::EndExpr); - if tok.is_close_square() { - return 1; - } else { - error!(self, tokenizer, "AT TOK {:?}", tok); - error!(self, tokenizer, "Expected ] not found"); - return 0; - } - } - - State::TryTest { index } => { - let try_start = self.code_len() as _; - self.push_code(Opcode::TRY_TEST.into(), index); - if tok.is_open_curly() { - self.state.push(State::TryTestBlock { - try_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.state.push(State::TryTestExpr { try_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::OkTest { index } => { - let ok_start = self.code_len() as _; - self.push_code(Opcode::OK_TEST.into(), index); - if tok.is_open_curly() { - self.state.push(State::OkTestBlock { - ok_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.state.push(State::OkTestExpr { ok_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::OkTestExpr { ok_start } => { - self.set_opcode_args( - ok_start, - OpcodeArgs::from_u32(self.code_len() as u32 - ok_start), - ); - self.push_code(Opcode::OK_END.into(), self.index); - return 0; - } - State::OkTestBlock { - ok_start, - last_was_sep, - } => { - self.set_opcode_args( - ok_start, - OpcodeArgs::from_u32(self.code_len() as u32 - ok_start), - ); - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.push_code(Opcode::OK_END.into(), self.index); - self.state.push(State::EndExpr); - return 1; - } else { - self.push_code(Opcode::OK_END.into(), self.index); - return 0; - } - } - State::TryTestExpr { try_start } => { - self.set_opcode_args( - try_start, - OpcodeArgs::from_u32(self.code_len() as u32 - try_start), - ); - self.state.push(State::TryErrBlockOrExpr { - allow_catch: true, - canonical_catch: false, - protected_was_block: false, - try_start, - }); - return 0; - } - State::TryTestBlock { - try_start, - last_was_sep, - } => { - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.set_opcode_args( - try_start, - OpcodeArgs::from_u32(self.code_len() as u32 - try_start), - ); - self.state.push(State::TryErrBlockOrExpr { - allow_catch: true, - canonical_catch: false, - protected_was_block: true, - try_start, - }); - return 1; - } else { - self.set_opcode_args( - try_start, - OpcodeArgs::from_u32(self.code_len() as u32 - try_start), - ); - self.state.push(State::TryErrBlockOrExpr { - allow_catch: true, - canonical_catch: false, - protected_was_block: true, - try_start, - }); - return 0; - } - } - State::TryErrBlockOrExpr { - allow_catch, - canonical_catch, - protected_was_block, - try_start, - } => { - if allow_catch && id == id!(catch) { - // Canonical blocks end in a separator. Retain their tail - // value, then repatch the jump after removing pop-to-me. - if protected_was_block && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.set_opcode_args( - try_start, - OpcodeArgs::from_u32(self.code_len() as u32 - try_start), - ); - self.state.push(State::TryErrBlockOrExpr { - allow_catch: false, - canonical_catch: true, - protected_was_block, - try_start, - }); - return 1; - } - let err_start = self.code_len() as _; - self.push_code(Opcode::TRY_ERR.into(), self.index); - if tok.is_open_curly() { - self.state.push(State::TryErrBlock { - canonical_catch, - err_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.state.push(State::TryErrExpr { err_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::TryErrExpr { err_start } => { - self.set_opcode_args( - err_start, - OpcodeArgs::from_u32(self.code_len() as u32 - err_start), - ); - self.state.push(State::TryOk { - err_start, - was_block: false, - }); - } - State::TryErrBlock { - canonical_catch, - err_start, - last_was_sep, - } => { - if tok.is_close_curly() { - if (canonical_catch || !last_was_sep) && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.set_opcode_args( - err_start, - OpcodeArgs::from_u32(self.code_len() as u32 - err_start), - ); - self.state.push(State::TryOk { - err_start, - was_block: true, - }); - return 1; - } else { - self.set_opcode_args( - err_start, - OpcodeArgs::from_u32(self.code_len() as u32 - err_start), - ); - error!(self, tokenizer, "Expected }} not found"); - self.state.push(State::TryOk { - err_start, - was_block: false, - }); - return 0; - } - } - State::TryOk { - err_start, - was_block, - } => { - if id == id!(ok) { - // A successful legacy try skips TRY_OK itself so it enters - // the ok branch; without ok, TRY_ERR lands on its parent. - self.set_opcode_args( - err_start, - OpcodeArgs::from_u32(self.code_len() as u32 - err_start + 1), - ); - self.state.push(State::TryOkBlockOrExpr); - return 1; - } - if was_block { - self.state.push(State::EndExpr) - } - return 0; - } - State::TryOkBlockOrExpr => { - let ok_start = self.code_len() as _; - self.push_code(Opcode::TRY_OK.into(), self.index); - if tok.is_open_curly() { - self.state.push(State::TryOkBlock { - ok_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.state.push(State::TryOkExpr { ok_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::TryOkExpr { ok_start } => { - self.set_opcode_args( - ok_start, - OpcodeArgs::from_u32(self.code_len() as u32 - ok_start), - ); - } - State::TryOkBlock { - ok_start, - last_was_sep, - } => { - self.set_opcode_args( - ok_start, - OpcodeArgs::from_u32(self.code_len() as u32 - ok_start), - ); - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.state.push(State::EndExpr); - return 1; - } else { - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - State::IfTest { index } => { - let if_start = self.code_len() as _; - self.push_code(Opcode::IF_TEST.into(), index); - if tok.is_open_curly() { - self.state.push(State::IfTrueBlock { - if_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - if id == id!(else) { - error!(self, tokenizer, "Unexpected else, use {{}} to disambiguate"); - return 1; - } - self.state.push(State::IfTrueExpr { if_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::IfTrueExpr { if_start } => { - self.state.push(State::IfMaybeElse { - if_start, - was_block: false, - }); - return 0; - } - State::IfTrueBlock { - if_start, - last_was_sep, - } => { - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - self.state.push(State::IfMaybeElse { - if_start, - was_block: true, - }); - return 1; - } else { - self.state.push(State::EndExpr); - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - State::IfMaybeElse { - if_start, - was_block, - } => { - if id == id!(elif) { - self.push_code(Opcode::IF_ELSE.into(), self.index); - self.set_opcode_args( - if_start, - OpcodeArgs::from_u32(self.code_len() as u32 - if_start), - ); - - self.state.push(State::IfMaybeElse { - if_start, - was_block, - }); - self.state.push(State::IfTest { index: self.index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if id == id!(else) { - let else_start = self.code_len() as u32; - self.push_code(Opcode::IF_ELSE.into(), self.index); - self.set_opcode_args( - if_start, - OpcodeArgs::from_u32(self.code_len() as u32 - if_start), - ); - self.state.push(State::IfElse { else_start }); - return 1; - } - self.set_opcode_args( - if_start, - OpcodeArgs::from_u32(self.code_len() as u32 - if_start).set_need_nil(), - ); - // self.push_code_none(NIL); - if was_block { - // allow expression to chain - self.state.push(State::EndExpr) - } - } - State::IfElse { else_start } => { - if tok.is_open_curly() { - self.state.push(State::IfElseBlock { - else_start, - last_was_sep: false, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.state.push(State::IfElseExpr { else_start }); - self.state.push(State::BeginExpr { required: true }); - return 0; - } - State::IfElseExpr { else_start } => { - self.set_opcode_args( - else_start, - OpcodeArgs::from_u32(self.code_len() as u32 - else_start), - ); - return 0; - } - State::IfElseBlock { - else_start, - last_was_sep, - } => { - if tok.is_close_curly() { - if !last_was_sep && self.has_pop_to_me() { - self.clear_pop_to_me(); - } - /* - if !last_was_sep{ - if Some(&Opcode::POP_TO_ME.into()) == self.code_last(){ - self.pop_code(); - } - }*/ - self.set_opcode_args( - else_start, - OpcodeArgs::from_u32(self.code_len() as u32 - else_start), - ); - self.state.push(State::EndExpr); - return 1; - } else { - self.state.push(State::EndExpr); - error!(self, tokenizer, "Expected }} not found"); - return 0; - } - } - State::BeginExpr { required } => { - if !required - && matches!( - self.state.last(), - Some(State::EmitReturn { .. } | State::EmitBreak { .. }) - ) - && (id == id!(let) - || id == id!(var) - || id == id!(use) - || id == id!(return) - || id == id!(break) - || id == id!(continue)) - { - return 0; - } - if let Some(index) = tok.as_rust_value() { - let Some(value) = values.get(index as usize).copied() else { - error!(self, tokenizer, "Rust value index {index} is unavailable"); - self.state.push(State::EndExpr); - return 1; - }; - self.push_code(value, self.index); - self.state.push(State::EndExpr); - return 1; - } - if tok.is_open_curly() { - // Check if there's a pending +: operator for proto-inherit - if let Some(State::EmitOp { - what_op: id!(+:), .. - }) = self.state.last() - { - self.state.pop(); - // Proto-inherit operator: field +: { ... } - // Emit PROTO_INHERIT_READ to read field and push proto value - self.push_code(Opcode::PROTO_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndProtoInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // Check if there's a pending += operator for scope-inherit - if let Some(State::EmitOp { - what_op: id!(+=), .. - }) = self.state.last() - { - self.state.pop(); - // Scope-inherit operator: value += { ... } - // Emit SCOPE_INHERIT_READ to read variable and push proto value - self.push_code(Opcode::SCOPE_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndScopeInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // Check if there's a pending field += for field-inherit - if let Some(State::EmitFieldAssign { - what_op: id!(+=), .. - }) = self.state.last() - { - self.state.pop(); - // Field-inherit operator: obj.field += { ... } - // Emit FIELD_INHERIT_READ to read field and push proto value - self.push_code(Opcode::FIELD_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndFieldInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // Check if there's a pending index += for index-inherit - if let Some(State::EmitIndexAssign { - what_op: id!(+=), .. - }) = self.state.last() - { - self.state.pop(); - // Index-inherit operator: obj[index] += { ... } - // Emit INDEX_INHERIT_READ to read index and push proto value - self.push_code(Opcode::INDEX_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndIndexInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - self.push_code(Opcode::BEGIN_BARE.into(), self.index); - self.state.push(State::EndBare); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - if tok.is_open_square() { - self.push_code(Opcode::BEGIN_ARRAY.into(), self.index); - self.state.push(State::EndBareSquare); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - if tok.is_open_round() { - //self.code.push(Opcode::BEGIN_FRAG.into()); - self.state.push(State::EndRound); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if let Some(v) = tok.as_f64() { - self.push_code(ScriptValue::from_f64(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_u40() { - self.push_code(ScriptValue::from_u40(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_f32() { - self.push_code(ScriptValue::from_f32(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_u32() { - self.push_code(ScriptValue::from_u32(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_i32() { - self.push_code(ScriptValue::from_i32(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_f16() { - self.push_code(ScriptValue::from_f16(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if id == id!(if) { - // do if as an expression - self.state.push(State::IfTest { index: self.index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if id == id!(try) { - // do if as an expression - self.state.push(State::TryTest { index: self.index }); - return 1; - } - if id == id!(ok) { - // do if as an expression - self.state.push(State::OkTest { index: self.index }); - return 1; - } - if id == id!(for) { - self.state.push(State::ForIdent { - idents: 0, - index: self.index, - }); - return 1; - } - if id == id!(loop) { - self.state.push(State::Loop { index: self.index }); - return 1; - } - if id == id!(while) { - self.state.push(State::While { index: self.index }); - return 1; - } - if id == id!(match) { - // Generate temp variable name based on code position - // Avoid double-underscore identifiers in generated GLSL locals. - // The shader backend prefixes locals with `l_`, so `_match_*` would - // become `l__match_*`, which is reserved in GLSL ES. - let temp_name = format!("match_{}", self.code_len()); - // Use from_str_with_lut to register the temp name in the LUT for lookup - let temp_id = LiveId::from_str_with_lut(&temp_name) - .unwrap_or_else(|_| LiveId::from_str(&temp_name)); - // Emit temp_id FIRST, then parse subject expression, then LET_DYN - self.push_code(ScriptValue::from_id(temp_id), self.index); - self.state.push(State::MatchSubject { - temp_id, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if id == id!(use) { - self.state.push(State::Use { index: self.index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if id == id!(fn) { - self.state.push(State::FnMaybeLet { index: self.index }); - return 1; - } - if id == id!(let) { - // we have to have an identifier after let - self.state.push(State::Let { index: self.index }); - return 1; - } - if id == id!(var) { - // we have to have an identifier after var - self.state.push(State::Var { index: self.index }); - return 1; - } - if id == id!(return) { - let code_len_before = self.code_len() as u32; - self.state.push(State::EmitReturn { - index: self.index, - code_len_before, - }); - self.state.push(State::BeginExpr { required: false }); - return 1; - } - if id == id!(break) { - self.state.push(State::EmitBreak { index: self.index }); - self.state.push(State::BeginExpr { required: false }); - return 1; - } - if id == id!(continue) { - self.state.push(State::EmitContinue { index: self.index }); - return 1; - } - if id == id!(true) { - self.push_code(ScriptValue::from_bool(true), self.index); - self.state.push(State::EndExpr); - return 1; - } - if id == id!(false) { - self.push_code(ScriptValue::from_bool(false), self.index); - self.state.push(State::EndExpr); - return 1; - } - if id == id!(me) { - self.push_code(Opcode::ME.into(), self.index); - self.state.push(State::EndExpr); - return 1; - } - if id == id!(scope) { - self.push_code(Opcode::SCOPE.into(), self.index); - self.state.push(State::EndExpr); - return 1; - } - if id == id!(nil) { - self.push_code(NIL, self.index); - self.state.push(State::EndExpr); - return 1; - } - if id.not_empty() { - self.push_code(ScriptValue::from_id(id), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(v) = tok.as_color() { - self.push_code(ScriptValue::from_color(v), self.index); - self.state.push(State::EndExpr); - return 1; - } - if let Some(value) = tok.as_string() { - self.push_code(value, self.index); - self.state.push(State::EndExpr); - return 1; - } - if op == id!(*) { - self.push_code(ScriptValue::from_id(id!(*)), self.index); - self.state.push(State::EndExpr); - return 1; - } - if op == id!(-) || op == id!(+) || op == id!(!) || op == id!(~) { - self.state.push(State::EmitUnary { - what_op: op, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if op == id!(@) { - self.state.push(State::EndExpr); - self.state.push(State::EscapedId); - return 1; - } - if op == id!(||) { - self.push_code(Opcode::FN_ARGS.into(), self.index); - self.state.push(State::FnBody { lambda: true }); - return 1; - } - if op == id!(|) { - self.push_code(Opcode::FN_ARGS.into(), self.index); - self.state.push(State::FnArgList { lambda: true }); - return 1; - } - if op == id!(.) { - self.state.push(State::EmitOp { - what_op: id!(me.), - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if op == id!(..) { - // Prefix .. is the splat operator - self.state.push(State::EmitSplat { index: self.index }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - if !required && (sep == id!(;) || sep == id!(,)) { - // self.push_code(NIL, self.index); - } - if required { - error!( - self, - tokenizer, "Expected expression after {:?} found {:?}", self.state, tok - ); - self.push_code_none(NIL); - } - } - - State::EndExpr => { - if op == id!(~) { - return 0; - } - if op == id!(?) { - // we have a post op return if err - if let Some(State::EmitOp { what_op, index }) = self.state.last() { - if *what_op == id!(.) || *what_op == id!(.?) { - self.push_code(State::operator_to_opcode(*what_op), *index); - self.state.pop(); - } - } - self.push_code(State::operator_to_opcode(id!(?)), self.index); - return 1; - } - // named operators - let op = if id == id!(is) { - id!(is) - } else if id == id!(and) { - id!(&&) - } else if id == id!(or) { - id!(||) - } else { - op - }; - - // Handle short-circuit operators (&&, ||, |?) specially - // These need the TEST opcode emitted BEFORE the second operand - if State::is_short_circuit_op(op) { - // Emit any pending unary operators first - they bind tighter than all binary ops - loop { - if let Some(State::EmitUnary { what_op, index }) = self.state.last() { - let (what_op, index) = (*what_op, *index); - self.state.pop(); - self.push_code(State::operator_to_unary(what_op), index); - } else { - break; - } - } - - let op_order = State::operator_order(op); - - // First, process any pending EmitOp with higher or equal precedence - // (this ensures proper operator precedence) - while let Some(last) = self.state.last() { - if let State::EmitOp { what_op, index } = last { - if State::operator_order(*what_op) <= op_order { - let what_op = *what_op; - let index = *index; - self.state.pop(); - self.push_code(State::operator_to_opcode(what_op), index); - } else { - break; - } - } else if let State::ShortCircuitEnd { test_slot, what_op } = last { - // Keep a lower-precedence left operator open until - // its entire right-hand expression has been emitted. - if State::operator_order(*what_op) > op_order { - break; - } - // Patch higher or equal precedence short-circuit ops - let test_slot = *test_slot; - self.state.pop(); - self.set_opcode_args( - test_slot, - OpcodeArgs::from_u32(self.code_len() - test_slot), - ); - } else { - break; - } - } - - // Emit the TEST opcode with placeholder jump - let test_slot = self.code_len(); - self.push_code(State::short_circuit_opcode(op).into(), self.index); - - // Push state to patch the jump after second operand is parsed - self.state.push(State::ShortCircuitEnd { - test_slot, - what_op: op, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - - // Handle ?= with lazy evaluation for SIMPLE variable assignments only - // Field/index assignments (x.f?=, x[i]?=) use their own opcodes with eager evaluation - // Emits: [id, ASSIGN_IFNIL(jump), rhs_code, ASSIGN] - if op == id!(?=) { - // Only use lazy eval for simple variable assignment (last code is an identifier) - // For field/index assignments, fall through to normal operator handling - let is_simple_var_assign = self.code_last().map(|c| c.is_id()).unwrap_or(false) - && self - .state - .last() - .map(|s| { - !matches!( - s, - State::EmitOp { - what_op: id!(.) | id!(.?), - .. - } - ) - }) - .unwrap_or(true) - && self.code_last() != Some(&Opcode::ARRAY_INDEX.into()); - - if is_simple_var_assign { - // Emit any pending unary operators first - loop { - if let Some(State::EmitUnary { what_op, index }) = self.state.last() { - let (what_op, index) = (*what_op, *index); - self.state.pop(); - self.push_code(State::operator_to_unary(what_op), index); - } else { - break; - } - } - - // Emit ASSIGN_IFNIL with placeholder jump - let test_slot = self.code_len(); - self.push_code(Opcode::ASSIGN_IFNIL.into(), self.index); - - // Push state to emit ASSIGN and patch jump after RHS is parsed - self.state.push(State::ShortCircuitAssignEnd { - test_slot, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - // else: fall through to normal operator handling for field/index ?= - } - - if State::operator_order(op) != 0 { - // Emit any pending unary operators, but only if this binary op has lower - // precedence than unary (order >= 6). Field access (order 3) has higher - // precedence than unary, so -x.y should parse as -(x.y), not (-x).y - if State::operator_order(op) >= 6 { - loop { - if let Some(State::EmitUnary { what_op, index }) = self.state.last() { - let (what_op, index) = (*what_op, *index); - self.state.pop(); - self.push_code(State::operator_to_unary(what_op), index); - } else { - break; - } - } - } - - let next_state = State::EmitOp { - what_op: op, - index: self.index, - }; - // check if we have a ..[] = - if Some(&Opcode::ARRAY_INDEX.into()) == self.code_last() { - if State::is_assign_operator(op) { - self.pop_code(); - self.state.push(State::EmitIndexAssign { - what_op: op, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - } - // check if we need to generate proto_field ops - if let Some(last) = self.state.pop() { - if let State::EmitOp { - what_op: id!(.) | id!(.?), - .. - } = last - { - if State::is_assign_operator(op) { - // For : operator with field chain like field.sub: value - // transform to me.field.sub = value - if op == id!(:) { - // Find the start of the field chain by walking backwards - // The chain structure is: [id, id, (FIELD, id)*] - // e.g. field.sub -> [id(field), id(sub)] - // e.g. field.sub.sub2 -> [id(field), id(sub), FIELD, id(sub2)] - let mut chain_start = self.opcodes.len(); - - // Walk backwards through ids and FIELDs - while chain_start > 0 { - let prev = chain_start - 1; - if self.opcodes[prev].is_id() - || self.opcodes[prev] == Opcode::FIELD.into() - { - chain_start = prev; - } else { - break; - } - } - - let Some(proto_field_index) = chain_start.checked_add(2) else { - error!( - self, - tokenizer, "Malformed prototype field assignment" - ); - self.state.push(State::BeginExpr { required: true }); - return 1; - }; - let chain_starts_with_id = self - .opcodes - .get(chain_start) - .is_some_and(ScriptValue::is_id); - let proto_field_slot_is_valid = - proto_field_index <= self.opcodes.len().saturating_add(1); - if !chain_starts_with_id || !proto_field_slot_is_valid { - error!( - self, - tokenizer, "Malformed prototype field assignment" - ); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - self.insert_code_with_source( - chain_start, - Opcode::ME.into(), - Some(self.index), - ); - self.insert_code_with_source( - proto_field_index, - Opcode::PROTO_FIELD.into(), - Some(self.index), - ); - } - - // Patch remaining FIELD to PROTO_FIELD - for pair in self.opcodes.rchunks_mut(2) { - if pair.len() != 2 { - break; - } - if pair[0].is_id() && pair[1] == Opcode::FIELD.into() { - pair[1] = Opcode::PROTO_FIELD.into() - } else if pair[1].is_id() && pair[0] == Opcode::FIELD.into() { - pair[0] = Opcode::PROTO_FIELD.into() - } else { - break; - } - } - self.state.push(State::EmitFieldAssign { - what_op: op, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - } - if last.is_heq_prio(next_state) { - // Push `last` back first - self.state.push(last); - - // Find the correct position to insert the new operator. - // It should be inserted below ALL EmitOp states that have higher or equal priority. - // This ensures correct operator precedence for expressions like t.x*t.y + t.z*t.w - let op_order = State::operator_order(op); - let is_assign = State::is_assign_operator(op); - let mut insert_pos = self.state.len(); - for i in (0..self.state.len()).rev() { - if let State::EmitOp { what_op, .. } = &self.state[i] { - // If both are assignment operators, don't treat as heq_prio (right-to-left associativity) - let pending_is_assign = State::is_assign_operator(*what_op); - if pending_is_assign && is_assign { - break; - } - if State::operator_order(*what_op) <= op_order { - insert_pos = i; - } else { - break; - } - } else { - break; - } - } - - // Insert new operator and BeginExpr at the found position - self.state - .insert(insert_pos, State::BeginExpr { required: true }); - self.state.insert( - insert_pos, - State::EmitOp { - what_op: op, - index: self.index, - }, - ); - return 1; - } else { - self.state.push(last); - } - } - self.state.push(State::EmitOp { - what_op: op, - index: self.index, - }); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - - if tok.is_open_curly() { - for state in self.state.iter().rev() { - if let State::EmitOp { .. } = state { - } else if let State::EmitUnary { .. } = state { - } else if let State::ShortCircuitEnd { .. } = state { - } else if let State::IfTest { .. } = state { - return 0; - } else if let State::TryTestExpr { .. } = state { - return 0; - } else if let State::WhileTest { .. } = state { - return 0; - } else if let State::ForBody { .. } = state { - return 0; - } else if let State::MatchSubject { .. } = state { - return 0; - } else { - break; - } - } - if let Some(last) = self.state.pop() { - if let State::EmitOp { - what_op: id!(.), - index, - } = last - { - self.push_code(State::operator_to_opcode(id!(.)), index); - } else if let State::EmitOp { - what_op: id!(.?), - index, - } = last - { - self.push_code(State::operator_to_opcode(id!(.?)), index); - } else if let State::EmitOp { - what_op: id!(+:), .. - } = last - { - // Proto-inherit operator: field +: Proto { ... } - // Emit PROTO_INHERIT_READ to read field and push proto value - self.push_code(Opcode::PROTO_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndProtoInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if let State::EmitOp { - what_op: id!(+=), .. - } = last - { - // Scope-inherit operator: value += Proto { ... } - // Emit SCOPE_INHERIT_READ to read variable and push proto value - self.push_code(Opcode::SCOPE_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndScopeInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if let State::EmitFieldAssign { - what_op: id!(+=), .. - } = last - { - // Field-inherit operator: obj.field += Proto { ... } - // Emit FIELD_INHERIT_READ to read field and push proto value - self.push_code(Opcode::FIELD_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndFieldInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else if let State::EmitIndexAssign { - what_op: id!(+=), .. - } = last - { - // Index-inherit operator: obj[index] += Proto { ... } - // Emit INDEX_INHERIT_READ to read index and push proto value - self.push_code(Opcode::INDEX_INHERIT_READ.into(), self.index); - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndIndexInherit); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } else { - self.state.push(last); - } - } - // `{...}{...}` is NOT object-inherits-from-object. If the value we just - // finished is a bare object literal (last opcode END_BARE), a following - // `{` begins a NEW value separated by an implicit ("magic") comma - not a - // proto-inherit. EndExpr was already popped, so returning 0 without - // consuming `{` lets the enclosing collection/argument/block loop (where - // commas are optional) parse it as the next element. This makes comma-less - // `[{a} {b}]`, `f({a} {b})` and `{ {a} {b} }` parse as separate items - // instead of silently collapsing into one. `Ident{...}` instantiation ends - // in END_PROTO / an id (not END_BARE), so it is unaffected and still protos. - if self.code_last() == Some(&Opcode::END_BARE.into()) { - return 0; - } - self.push_code(Opcode::BEGIN_PROTO.into(), self.index); - self.state.push(State::EndProto); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - if tok.is_open_round() { - if let Some(last) = self.state.pop() { - if let State::EmitOp { - what_op: id!(.) | id!(.?), - .. - } = last - { - self.push_code(Opcode::METHOD_CALL_ARGS.into(), self.index); - self.state.push(State::EndCall { - is_method: true, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - } else { - self.state.push(last); - self.push_code(Opcode::CALL_ARGS.into(), self.index); - self.state.push(State::EndCall { - is_method: false, - index: self.index, - }); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - } - } - return 1; - } - if tok.is_open_square() { - if let Some(last) = self.state.pop() { - if let State::EmitOp { - what_op: id!(.), - index, - } = last - { - self.push_code(State::operator_to_opcode(id!(.)), index); - } else if let State::EmitOp { - what_op: id!(.?), - index, - } = last - { - self.push_code(State::operator_to_opcode(id!(.?)), index); - } else { - self.state.push(last); - } - } - self.state.push(State::ArrayIndex); - self.state.push(State::BeginExpr { required: true }); - return 1; - } - return 0; - } - State::BeginStmt { last_was_sep } => { - if sep == id!(;) || sep == id!(,) { - // just eat it - // we can pop all operator emits - self.state.push(State::BeginStmt { last_was_sep: true }); - // we should also force a 'nil' in if/else/fn calls just like Rust - return 1; - } - if tok.is_close_round() || tok.is_close_curly() || tok.is_close_square() { - if last_was_sep { - if let Some(State::TryTestBlock { last_was_sep, .. }) = - self.state.last_mut() - { - *last_was_sep = true - } - if let Some(State::TryErrBlock { last_was_sep, .. }) = self.state.last_mut() - { - *last_was_sep = true - } - if let Some(State::TryOkBlock { last_was_sep, .. }) = self.state.last_mut() - { - *last_was_sep = true - } - if let Some(State::IfTrueBlock { last_was_sep, .. }) = self.state.last_mut() - { - *last_was_sep = true - } - if let Some(State::IfElseBlock { last_was_sep, .. }) = self.state.last_mut() - { - *last_was_sep = true - } - if let Some(State::EndFnBlock { last_was_sep, .. }) = self.state.last_mut() - { - *last_was_sep = true - } - } - // pop and let the stack handle it - return 0; - } - // lets do an expression statement as fallthrough - self.state.push(State::EndStmt { last: self.index }); - self.state.push(State::BeginExpr { required: false }); - return 0; - } - State::EndStmt { last } => { - if last == self.index { - error!( - self, - tokenizer, "Parser stuck on character {:?}, skipping", tok - ); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 1; - } - // in a function call we need the - - if let Some(code) = self.opcodes.last_mut() { - if let Some((opcode, _)) = code.as_opcode() { - if opcode == Opcode::FOR_END { - //code.set_opcode_is_statement(); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - if opcode == Opcode::ASSIGN_ME || opcode == Opcode::ASSIGN_ME_VEC { - //code.set_opcode_is_statement(); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - if opcode == Opcode::BREAK || opcode == Opcode::CONTINUE { - //code.set_opcode_is_statement(); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - if opcode == Opcode::ME_SPLAT { - // ME_SPLAT already handles merging into me, no pop_to_me needed - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - if code.is_let_opcode() { - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - } - } - // otherwise pop to me - self.set_pop_to_me(); - //self.push_code_none(Opcode::POP_TO_ME.into()); - self.state.push(State::BeginStmt { - last_was_sep: false, - }); - return 0; - } - } - 0 - } - - pub fn parse( - &mut self, - tokenizer: &ScriptTokenizer, - file: &str, - offsets: (usize, usize), - values: &[ScriptValue], - ) { - self.file = file.to_string(); - self.line_offset = offsets.0; - self.col_offset = offsets.1; - // wait for the tokens to be consumed - let mut steps_zero = 0; - let tokens = &tokenizer.tokens; - while self.index < tokens.len() as u32 && self.state.len() > 0 { - let tok = if let Some(tok) = tokens.get(self.index as usize) { - tok.token.clone() - } else { - ScriptToken::StreamEnd - }; - - let step = self.parse_step(tokenizer, tok, values); - if step == 0 { - steps_zero += 1; - } else { - steps_zero = 0; - } - // println!("{:?} {:?}", self.code, self.state); - if steps_zero > 1000 { - error!( - self, - tokenizer, - "Parser stuck {:?} {} {:?}", - self.state, - step, - tokens[self.index as usize] - ); - break; - } - self.index += step; - } - - // Auto-close any unclosed proto/object states left on the stack - // This happens when input is truncated mid-object (e.g. streaming) - let last_index = self.index.saturating_sub(1); - // set_pop_to_me() reads self.index for source map entries, so point it - // at the last valid token rather than one-past-end. - self.index = last_index; - while self.state.len() > 0 { - match self.state.pop().unwrap() { - State::EndProto => { - self.push_code(Opcode::END_PROTO.into(), last_index); - } - State::EndProtoInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::PROTO_INHERIT_WRITE.into(), last_index); - } - State::EndScopeInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::SCOPE_INHERIT_WRITE.into(), last_index); - } - State::EndFieldInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::FIELD_INHERIT_WRITE.into(), last_index); - } - State::EndIndexInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::INDEX_INHERIT_WRITE.into(), last_index); - } - State::EndStmt { .. } => { - self.set_pop_to_me(); - } - State::EmitOp { what_op, index } => { - self.push_code(State::operator_to_opcode(what_op), index); - } - State::EmitUnary { what_op, index } => { - self.push_code(State::operator_to_unary(what_op), index); - } - _ => { - // Other states (EndExpr, BeginStmt, etc.) - just drop them - } - } - } - - // Handle the last value as the script's return value, similar to function blocks - if self.has_pop_to_me() { - self.clear_pop_to_me(); - self.push_code(Opcode::RETURN.into(), self.index.saturating_sub(1)); - } else if self.opcodes.len() > 0 { - // Check if last opcode already returns or is a statement that doesn't produce a value - let needs_nil_return = if let Some(code) = self.code_last() { - if let Some((opcode, _)) = code.as_opcode() { - opcode != Opcode::RETURN - } else { - true - } - } else { - true - }; - if needs_nil_return { - self.push_code( - ScriptValue::from_opcode_args(Opcode::RETURN, OpcodeArgs::NIL), - self.index.saturating_sub(1), - ); - } - } - - //println!("{:?}", self.opcodes) - } - - /// Save parser state before auto-close, returning a checkpoint that can be - /// used to restore state for continuation when more source arrives. - /// Call this after the main parse loop but BEFORE auto-close runs. - pub fn save_checkpoint(&self) -> ParserCheckpoint { - ParserCheckpoint { - opcodes_len: self.opcodes.len(), - source_map_len: self.source_map.len(), - token_index: self.index, - state: self.state.clone(), - destruct_defaults_len: self.destruct_defaults.len(), - nested_patterns_len: self.nested_patterns.len(), - last_opcode: self.opcodes.last().copied(), - short_circuit_opcodes: self - .state - .iter() - .filter_map(|state| { - if let State::ShortCircuitEnd { test_slot, .. } = state { - Some((*test_slot, self.opcodes[*test_slot as usize])) - } else { - None - } - }) - .collect(), - } - } - - /// Restore parser state from a checkpoint, undoing any auto-close opcodes - /// that were appended after the checkpoint was taken. - pub fn restore_checkpoint(&mut self, cp: ParserCheckpoint) { - self.opcodes.truncate(cp.opcodes_len); - self.source_map.truncate(cp.source_map_len); - // Restore the last opcode in case auto-close mutated its POP_TO_ME flag - if let Some(saved) = cp.last_opcode { - if let Some(last) = self.opcodes.last_mut() { - *last = saved; - } - } - for (slot, opcode) in cp.short_circuit_opcodes { - self.opcodes[slot as usize] = opcode; - } - self.index = cp.token_index; - self.state = cp.state; - self.destruct_defaults.truncate(cp.destruct_defaults_len); - self.nested_patterns.truncate(cp.nested_patterns_len); - } - - /// Parse tokens incrementally: run the main parse loop, then save a checkpoint, - /// then auto-close for execution. Returns the checkpoint for later restoration. - /// - /// `unfinished_string`: if the tokenizer's last token is `StringUnfinished`, - /// pass the interned value here so the parser emits the real partial string - /// into opcodes (for incremental UI rendering). The tokenizer token is NOT - /// modified, preserving its state machine for the next `tokenize()` call. - pub fn parse_streaming( - &mut self, - tokenizer: &ScriptTokenizer, - file: &str, - offsets: (usize, usize), - values: &[ScriptValue], - unfinished_string: Option, - ) -> ParserCheckpoint { - self.file = file.to_string(); - self.line_offset = offsets.0; - self.col_offset = offsets.1; - let mut steps_zero = 0; - let tokens = &tokenizer.tokens; - let max_token_index = if tokens.is_empty() { - 0 - } else { - (tokens.len() - 1) as u32 - }; - while self.index < tokens.len() as u32 && self.state.len() > 0 { - let tok = if let Some(tok) = tokens.get(self.index as usize) { - tok.token.clone() - } else { - ScriptToken::StreamEnd - }; - // When we hit StringUnfinished: save checkpoint BEFORE it so the - // parser re-processes this token next time (with updated content). - // Substitute the interned value for the current execution, then - // consume remaining tokens and auto-close. - if let ScriptToken::StringUnfinished = &tok { - let checkpoint_before = self.save_checkpoint(); - let tok = if let Some(v) = unfinished_string { - ScriptToken::String(v) - } else { - tok - }; - let step = self.parse_step(tokenizer, tok, values); - self.index += step; - // Continue parsing any remaining tokens after the string - while self.index < tokens.len() as u32 && self.state.len() > 0 { - let tok2 = if let Some(tok2) = tokens.get(self.index as usize) { - tok2.token.clone() - } else { - ScriptToken::StreamEnd - }; - let step2 = self.parse_step(tokenizer, tok2, values); - self.index += step2; - } - return self.auto_close(checkpoint_before, max_token_index); - } - - let step = self.parse_step(tokenizer, tok, values); - if step == 0 { - steps_zero += 1; - } else { - steps_zero = 0; - } - if steps_zero > 1000 { - error!( - self, - tokenizer, - "Parser stuck {:?} {} {:?}", - self.state, - step, - tokens[self.index as usize] - ); - break; - } - self.index += step; - } - - // Save checkpoint BEFORE auto-close - let checkpoint = self.save_checkpoint(); - self.auto_close(checkpoint, max_token_index) - } - - /// Auto-close any open states for execution, then append a RETURN. - /// `max_token_index` is the last valid token index in the tokenizer, - /// used to clamp source map entries for synthetic opcodes. - /// Returns the checkpoint that was passed in (taken before auto-close). - fn auto_close( - &mut self, - checkpoint: ParserCheckpoint, - max_token_index: u32, - ) -> ParserCheckpoint { - // Use the last consumed token index for synthetic auto-close source map entries, - // same as the regular parse() method. Clamp to max_token_index for safety. - let last_index = self.index.saturating_sub(1).min(max_token_index); - // set_pop_to_me() reads self.index for source map entries, so point it - // at the last valid token rather than one-past-end. - self.index = last_index; - while self.state.len() > 0 { - match self.state.pop().unwrap() { - State::EndProto => { - self.push_code(Opcode::END_PROTO.into(), last_index); - } - State::EndProtoInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::PROTO_INHERIT_WRITE.into(), last_index); - } - State::EndScopeInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::SCOPE_INHERIT_WRITE.into(), last_index); - } - State::EndFieldInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::FIELD_INHERIT_WRITE.into(), last_index); - } - State::EndIndexInherit => { - self.push_code(Opcode::END_PROTO.into(), last_index); - self.push_code(Opcode::INDEX_INHERIT_WRITE.into(), last_index); - } - State::EndStmt { .. } => { - self.set_pop_to_me(); - } - State::EmitOp { what_op, index } => { - self.push_code(State::operator_to_opcode(what_op), index); - } - State::EmitUnary { what_op, index } => { - self.push_code(State::operator_to_unary(what_op), index); - } - State::ShortCircuitEnd { test_slot, .. } => { - self.set_opcode_args( - test_slot, - OpcodeArgs::from_u32(self.code_len() - test_slot), - ); - } - _ => {} - } - } - - if self.has_pop_to_me() { - self.clear_pop_to_me(); - self.push_code(Opcode::RETURN.into(), last_index); - } else if self.opcodes.len() > 0 { - let needs_nil_return = if let Some(code) = self.code_last() { - if let Some((opcode, _)) = code.as_opcode() { - opcode != Opcode::RETURN - } else { - true - } - } else { - true - }; - if needs_nil_return { - self.push_code( - ScriptValue::from_opcode_args(Opcode::RETURN, OpcodeArgs::NIL), - last_index, - ); - } - } - - checkpoint - } - - pub fn dump_opcodes(&self) { - println!("=== OPCODES ({} total) ===", self.opcodes.len()); - for (i, op) in self.opcodes.iter().enumerate() { - println!("{:3}: {:?}", i, op); - } - println!("=== END OPCODES ==="); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn malformed_proto_field_assignment_keeps_opcode_metadata_in_lockstep() { - let source = concat!( - "H.-", - "\x17\x17\x17\x17\x0e", - "\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17", - "m: ", - "\x17\x17\x17\x17\x17\x17\x17\x17\x17", - "return ", - "\x17\x17\x17\x17\x17\x17\x17\x17\x17\x17", - "=!" - ); - let mut heap = crate::heap::ScriptHeap::default(); - let mut tokenizer = ScriptTokenizer::default(); - tokenizer.tokenize(source, &mut heap); - tokenizer.tokenize("\n;", &mut heap); - let mut parser = ScriptParser::default(); - parser.set_emit_errors(false); - - parser.parse(&tokenizer, "fuzz.octoscript", (0, 0), &[]); - - assert!(parser.had_error); - assert_eq!(parser.opcodes.len(), parser.source_map.len()); - assert!(parser.state.is_empty()); - assert_eq!(parser.index as usize, tokenizer.tokens.len() - 1); - } - - #[test] - fn proto_field_assignment_accepts_an_identifier_chain() { - let mut heap = crate::heap::ScriptHeap::default(); - let mut tokenizer = ScriptTokenizer::default(); - tokenizer.tokenize("draw_bg.color: 1\n;", &mut heap); - let mut parser = ScriptParser::default(); - parser.set_emit_errors(false); - - parser.parse(&tokenizer, "valid.octoscript", (0, 0), &[]); - - assert!(!parser.had_error, "{:?}", parser.diagnostics); - assert_eq!(parser.opcodes.len(), parser.source_map.len()); - } -} diff --git a/vendor/makepad/platform/script/src/pod.rs b/vendor/makepad/platform/script/src/pod.rs deleted file mode 100644 index c429675..0000000 --- a/vendor/makepad/platform/script/src/pod.rs +++ /dev/null @@ -1,583 +0,0 @@ -#![allow(unused)] -use crate::heap::*; -use crate::mod_pod::*; -use crate::trap::*; -use crate::value::*; -use crate::value::*; -use makepad_live_id::*; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScriptPodField { - pub name: LiveId, - pub default: ScriptValue, - pub ty: ScriptPodTypeInline, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScriptPodEnum { - pub name: LiveId, - pub variant: ScriptPodEnumVariant, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ScriptPodEnumVariant { - Bare, - Tuple { items: Vec }, - Named { fields: Vec }, -} - -// we're going to try to follow std140 datamapping for wgsl -#[derive(Default, Clone, Debug, PartialEq, Eq)] -pub struct ScriptPodTypeData { - pub name: Option, - pub object: ScriptObject, - pub default: ScriptValue, - //pub cached_align_of2: usize, - pub ty: ScriptPodTy, -} - -#[derive(Default, Clone, Debug, PartialEq, Eq)] -pub struct ScriptPodTypeInline { - pub self_ref: ScriptPodType, - pub data: ScriptPodTypeData, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ScriptPodVec { - Vec2f, - Vec3f, - Vec4f, - Vec2h, - Vec3h, - Vec4h, - Vec2u, - Vec3u, - Vec4u, - Vec2i, - Vec3i, - Vec4i, - Vec2b, - Vec3b, - Vec4b, -} -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ScriptPodMat { - Mat2x2f, - Mat3x2f, - Mat4x2f, - Mat2x3f, - Mat3x3f, - Mat4x3f, - Mat2x4f, - Mat3x4f, - Mat4x4f, -} - -impl ScriptPodVec { - pub fn elem_size(&self) -> usize { - match self { - Self::Vec2h | Self::Vec3h | Self::Vec4h => 2, - _ => 4, - } - } - - pub fn elem_ty(&self) -> ScriptPodTy { - match self { - Self::Vec2f | Self::Vec3f | Self::Vec4f => ScriptPodTy::F32, - Self::Vec2h | Self::Vec3h | Self::Vec4h => ScriptPodTy::F16, - Self::Vec2u | Self::Vec3u | Self::Vec4u => ScriptPodTy::U32, - Self::Vec2i | Self::Vec3i | Self::Vec4i => ScriptPodTy::I32, - Self::Vec2b | Self::Vec3b | Self::Vec4b => ScriptPodTy::Bool, - } - } - - pub fn name(&self) -> LiveId { - match self { - Self::Vec2f => id!(vec2f), - Self::Vec3f => id!(vec3f), - Self::Vec4f => id!(vec4f), - Self::Vec2h => id!(vec2h), - Self::Vec3h => id!(vec3h), - Self::Vec4h => id!(vec4h), - Self::Vec2u => id!(vec2u), - Self::Vec3u => id!(vec3u), - Self::Vec4u => id!(vec4u), - Self::Vec2i => id!(vec2i), - Self::Vec3i => id!(vec3i), - Self::Vec4i => id!(vec4i), - Self::Vec2b => id!(vec2b), - Self::Vec3b => id!(vec3b), - Self::Vec4b => id!(vec4b), - } - } - - pub fn swizzle_type(&self, lanes: usize, builtin: &ScriptPodBuiltins) -> ScriptPodType { - match self { - Self::Vec2f => match lanes { - 2 => builtin.pod_vec2f, - 3 => builtin.pod_vec3f, - 4 => builtin.pod_vec4f, - _ => builtin.pod_f32, - }, - Self::Vec3f => match lanes { - 2 => builtin.pod_vec2f, - 3 => builtin.pod_vec3f, - 4 => builtin.pod_vec4f, - _ => builtin.pod_f32, - }, - Self::Vec4f => match lanes { - 2 => builtin.pod_vec2f, - 3 => builtin.pod_vec3f, - 4 => builtin.pod_vec4f, - _ => builtin.pod_f32, - }, - Self::Vec2h => match lanes { - 2 => builtin.pod_vec2h, - 3 => builtin.pod_vec3h, - 4 => builtin.pod_vec4h, - _ => builtin.pod_f16, - }, - Self::Vec3h => match lanes { - 2 => builtin.pod_vec2h, - 3 => builtin.pod_vec3h, - 4 => builtin.pod_vec4h, - _ => builtin.pod_f16, - }, - Self::Vec4h => match lanes { - 2 => builtin.pod_vec2h, - 3 => builtin.pod_vec3h, - 4 => builtin.pod_vec4h, - _ => builtin.pod_f16, - }, - Self::Vec2u => match lanes { - 2 => builtin.pod_vec2u, - 3 => builtin.pod_vec3u, - 4 => builtin.pod_vec4u, - _ => builtin.pod_u32, - }, - Self::Vec3u => match lanes { - 2 => builtin.pod_vec2u, - 3 => builtin.pod_vec3u, - 4 => builtin.pod_vec4u, - _ => builtin.pod_u32, - }, - Self::Vec4u => match lanes { - 2 => builtin.pod_vec2u, - 3 => builtin.pod_vec3u, - 4 => builtin.pod_vec4u, - _ => builtin.pod_u32, - }, - Self::Vec2i => match lanes { - 2 => builtin.pod_vec2i, - 3 => builtin.pod_vec3i, - 4 => builtin.pod_vec4i, - _ => builtin.pod_i32, - }, - Self::Vec3i => match lanes { - 2 => builtin.pod_vec2i, - 3 => builtin.pod_vec3i, - 4 => builtin.pod_vec4i, - _ => builtin.pod_i32, - }, - Self::Vec4i => match lanes { - 2 => builtin.pod_vec2i, - 3 => builtin.pod_vec3i, - 4 => builtin.pod_vec4i, - _ => builtin.pod_i32, - }, - Self::Vec2b => match lanes { - 2 => builtin.pod_vec2b, - 3 => builtin.pod_vec3b, - 4 => builtin.pod_vec4b, - _ => builtin.pod_bool, - }, - Self::Vec3b => match lanes { - 2 => builtin.pod_vec2b, - 3 => builtin.pod_vec3b, - 4 => builtin.pod_vec4b, - _ => builtin.pod_bool, - }, - Self::Vec4b => match lanes { - 2 => builtin.pod_vec2b, - 3 => builtin.pod_vec3b, - 4 => builtin.pod_vec4b, - _ => builtin.pod_bool, - }, - } - } - - pub fn builtin(&self, builtin: &ScriptPodBuiltins) -> ScriptPodType { - match self { - Self::Vec2f => builtin.pod_vec2f, - Self::Vec3f => builtin.pod_vec3f, - Self::Vec4f => builtin.pod_vec4f, - Self::Vec2h => builtin.pod_vec2h, - Self::Vec3h => builtin.pod_vec3h, - Self::Vec4h => builtin.pod_vec4h, - Self::Vec2u => builtin.pod_vec2u, - Self::Vec3u => builtin.pod_vec3u, - Self::Vec4u => builtin.pod_vec4u, - Self::Vec2i => builtin.pod_vec2i, - Self::Vec3i => builtin.pod_vec3i, - Self::Vec4i => builtin.pod_vec4i, - Self::Vec2b => builtin.pod_vec2b, - Self::Vec3b => builtin.pod_vec3b, - Self::Vec4b => builtin.pod_vec4b, - } - } - - pub fn dims(&self) -> usize { - match self { - Self::Vec2f | Self::Vec2h | Self::Vec2u | Self::Vec2i | Self::Vec2b => 2, - Self::Vec3f | Self::Vec3h | Self::Vec3u | Self::Vec3i | Self::Vec3b => 3, - Self::Vec4f | Self::Vec4h | Self::Vec4u | Self::Vec4i | Self::Vec4b => 4, - } - } - pub fn align_of(&self) -> usize { - match self { - Self::Vec2f => 8, - Self::Vec3f => 16, - Self::Vec4f => 8, - Self::Vec2h => 4, - Self::Vec3h => 8, - Self::Vec4h => 16, - Self::Vec2u => 8, - Self::Vec3u => 16, - Self::Vec4u => 16, - Self::Vec2i => 8, - Self::Vec3i => 16, - Self::Vec4i => 16, - Self::Vec2b => 8, - Self::Vec3b => 16, - Self::Vec4b => 16, - } - } - pub fn size_of(&self) -> usize { - match self { - Self::Vec2f => 8, - Self::Vec3f => 12, - Self::Vec4f => 16, - Self::Vec2h => 4, - Self::Vec3h => 6, - Self::Vec4h => 8, - Self::Vec2u => 8, - Self::Vec3u => 12, - Self::Vec4u => 16, - Self::Vec2i => 8, - Self::Vec3i => 12, - Self::Vec4i => 16, - Self::Vec2b => 8, - Self::Vec3b => 12, - Self::Vec4b => 16, - } - } -} -impl ScriptPodMat { - pub fn elem_size(&self) -> usize { - match self { - _ => 4, - } - } - pub fn name(&self) -> LiveId { - match self { - Self::Mat2x2f => id!(mat2x2f), - Self::Mat3x2f => id!(mat3x2f), - Self::Mat4x2f => id!(mat4x2f), - Self::Mat2x3f => id!(mat2x3f), - Self::Mat3x3f => id!(mat3x3f), - Self::Mat4x3f => id!(mat4x3f), - Self::Mat2x4f => id!(mat2x4f), - Self::Mat3x4f => id!(mat3x4f), - Self::Mat4x4f => id!(mat4x4f), - } - } - - pub fn builtin(&self, builtin: &ScriptPodBuiltins) -> ScriptPodType { - match self { - Self::Mat2x2f => builtin.pod_mat2x2f, - Self::Mat3x2f => builtin.pod_mat3x2f, - Self::Mat4x2f => builtin.pod_mat4x2f, - Self::Mat2x3f => builtin.pod_mat2x3f, - Self::Mat3x3f => builtin.pod_mat3x3f, - Self::Mat4x3f => builtin.pod_mat4x3f, - Self::Mat2x4f => builtin.pod_mat2x4f, - Self::Mat3x4f => builtin.pod_mat3x4f, - Self::Mat4x4f => builtin.pod_mat4x4f, - } - } - - pub fn dim(&self) -> usize { - let (x, y) = self.dims(); - x * y - } - - pub fn dims(&self) -> (usize, usize) { - match self { - Self::Mat2x2f => (2, 2), - Self::Mat3x2f => (3, 2), - Self::Mat4x2f => (4, 2), - Self::Mat2x3f => (2, 3), - Self::Mat3x3f => (3, 3), - Self::Mat4x3f => (4, 3), - Self::Mat2x4f => (2, 4), - Self::Mat3x4f => (3, 4), - Self::Mat4x4f => (4, 4), - } - } - - pub fn align_of(&self) -> usize { - match self { - Self::Mat2x2f => 8, - Self::Mat3x2f => 8, - Self::Mat4x2f => 8, - Self::Mat2x3f => 16, - Self::Mat3x3f => 16, - Self::Mat4x3f => 16, - Self::Mat2x4f => 16, - Self::Mat3x4f => 16, - Self::Mat4x4f => 16, - } - } - pub fn size_of(&self) -> usize { - match self { - Self::Mat2x2f => 16, - Self::Mat3x2f => 24, - Self::Mat4x2f => 32, - Self::Mat2x3f => 32, - Self::Mat3x3f => 48, - Self::Mat4x3f => 64, - Self::Mat2x4f => 32, - Self::Mat3x4f => 48, - Self::Mat4x4f => 64, - } - } -} - -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub enum ScriptPodTy { - #[default] - Void, - ArrayBuilder, - UndefinedStruct, - // limited to the types WGSL supports - F32, - F16, - U32, - I32, - Bool, - AtomicU32, - AtomicI32, - Vec(ScriptPodVec), - Mat(ScriptPodMat), - Struct { - align_of: usize, - size_of: usize, - fields: Vec, - }, - Enum { - align_of: usize, - size_of: usize, - variants: Vec, - }, - FixedArray { - align_of: usize, - size_of: usize, - len: usize, - ty: Box, - }, - VariableArray { - align_of: usize, - ty: Box, - }, -} - -impl ScriptPodTy { - pub fn is_number(&self) -> bool { - match self { - Self::F32 | Self::F16 | Self::U32 | Self::I32 => true, - _ => false, - } - } - - pub fn is_float_type(&self) -> bool { - match self { - Self::F32 | Self::F16 => true, - Self::Vec(v) => matches!(v.elem_ty(), ScriptPodTy::F32 | ScriptPodTy::F16), - Self::Mat(_) => true, // Matrices are float-based - _ => false, - } - } - - /// Calculates the struct layout (align_of and size_of) from a slice of fields. - /// Returns (align_of, size_of) tuple. - /// - /// The alignment is the maximum alignment of all fields. - /// The size is calculated by walking through fields with proper alignment, - /// then aligning the final size to the struct alignment. - pub fn calculate_struct_layout(fields: &[ScriptPodField]) -> (usize, usize) { - // Calculate max alignment from all field types - let mut align_of = 0usize; - for field in fields { - align_of = align_of.max(field.ty.data.ty.align_of()); - } - - // Calculate size by walking through fields with proper alignment - let mut offset_of = 0usize; - for field in fields { - let field_align = field.ty.data.ty.align_of(); - let field_size = field.ty.data.ty.size_of(); - - // Align the offset to field alignment - let rem = offset_of % field_align; - if rem != 0 { - offset_of += field_align - rem; - } - - offset_of += field_size; - } - - // Align final size to struct alignment - if align_of > 0 { - let rem = offset_of % align_of; - if rem != 0 { - offset_of += align_of - rem; - } - } - - (align_of, offset_of) - } - - /// Creates a new Struct variant with layout calculated from fields. - pub fn new_struct(fields: Vec) -> Self { - let (align_of, size_of) = Self::calculate_struct_layout(&fields); - Self::Struct { - align_of, - size_of, - fields, - } - } -} - -#[derive(Debug, Default, Copy, Clone)] -pub struct ScriptPodOffset { - pub offset_of: usize, - pub field_index: usize, -} - -impl ScriptPodTy { - pub fn align_of(&self) -> usize { - match self { - Self::Void | Self::ArrayBuilder | Self::UndefinedStruct => 0, - Self::F32 => 4, - Self::F16 => 2, - Self::U32 => 4, - Self::I32 => 4, - Self::Bool => 4, - Self::AtomicU32 => 4, - Self::AtomicI32 => 4, - Self::Vec(bt) => bt.align_of(), - Self::Mat(bt) => bt.align_of(), - Self::Struct { align_of, .. } => *align_of, - Self::Enum { align_of, .. } => *align_of, - Self::FixedArray { align_of, .. } => *align_of, - Self::VariableArray { align_of, .. } => *align_of, - } - } - - pub fn size_of(&self) -> usize { - match self { - Self::Void | Self::ArrayBuilder | Self::UndefinedStruct => 0, - Self::F32 => 4, - Self::F16 => 2, - Self::U32 => 4, - Self::I32 => 4, - Self::Bool => 4, - Self::AtomicU32 => 4, - Self::AtomicI32 => 4, - Self::Vec(bt) => bt.size_of(), - Self::Mat(bt) => bt.size_of(), - Self::Struct { size_of, .. } => *size_of, - Self::Enum { size_of, .. } => *size_of, - Self::FixedArray { size_of, .. } => *size_of, - Self::VariableArray { .. } => 0, - } - } - - /// Returns the number of float32-sized slots this type occupies. - /// This is used for shader attribute/uniform layout calculations. - pub fn slots(&self) -> usize { - // Each slot is 4 bytes (size of f32) - // For f16, we round up to 1 slot - let size = self.size_of(); - (size + 3) / 4 - } -} - -#[derive(Default, Debug)] -pub struct ScriptPodTag(u64); - -impl ScriptPodTag { - const MARK: u64 = 0x1 << 60; - const ALLOCED: u64 = 0x2 << 60; - const STATIC: u64 = 0x8 << 60; - const ARRAY_BUILDER: u64 = 0x4 << 60; - pub fn set_array_builder(&mut self, ty: ScriptPodType) { - self.0 |= Self::ARRAY_BUILDER; - self.0 |= (ty.index as u64); - } - - pub fn as_array_builder(&self) -> Option { - if self.0 & Self::ARRAY_BUILDER != 0 { - return Some(ScriptPodType { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - pub fn is_alloced(&self) -> bool { - return self.0 & Self::ALLOCED != 0; - } - - pub fn set_alloced(&mut self) { - self.0 |= Self::ALLOCED - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } - - pub fn clear(&mut self) { - self.0 = 0; - } -} - -#[derive(Default)] -pub struct ScriptPodData { - pub tag: ScriptPodTag, - pub ty: ScriptPodType, - pub data: Vec, -} - -impl ScriptPodData { - pub fn clear(&mut self) { - self.tag.clear(); - self.data.clear(); - } -} diff --git a/vendor/makepad/platform/script/src/pod_heap.rs b/vendor/makepad/platform/script/src/pod_heap.rs deleted file mode 100644 index bd5f6d6..0000000 --- a/vendor/makepad/platform/script/src/pod_heap.rs +++ /dev/null @@ -1,2361 +0,0 @@ -use crate::heap::*; -use crate::mod_pod::*; -use crate::pod::*; -use crate::trap::*; -use crate::value::*; -use crate::*; -use makepad_live_id::*; -use std::fmt::Write; - -impl ScriptHeap { - // POD TYPES - - pub fn pod_method(&self, ptr: ScriptPod, key: ScriptValue, trap: ScriptTrap) -> ScriptValue { - let pod = &self.pods[ptr]; - let pod_ty = &self.pod_types[pod.ty.index as usize]; - self.value(pod_ty.object, key, trap) - } - - pub fn new_pod_type( - &mut self, - object: ScriptObject, - name: Option, - ty: ScriptPodTy, - default: ScriptValue, - ) -> ScriptPodType { - let pod_type = if let Some(ptr) = self.pod_types_free.pop() { - let pod_type = &mut self.pod_types[ptr.index as usize]; - pod_type.object = object; - pod_type.name = name; - pod_type.ty = ty; - pod_type.default = default; - ptr - } else { - let ptr = ScriptPodType { - index: self.pod_types.len() as u32, - }; - self.pod_types.push(ScriptPodTypeData { - name, - object, - ty, - default, - }); - ptr - }; - self.reconcile_heap_bytes_if_limited(); - pod_type - } - - pub fn new_pod_array_type(&mut self, ty: ScriptPodTy, default: ScriptValue) -> ScriptPodType { - for (i, pod_type) in self.pod_types.iter().enumerate() { - if pod_type.ty == ty { - return ScriptPodType { index: i as u32 }; - } - } - - let dummy_obj = self.new_object(); - self.new_pod_type(dummy_obj, None, ty, default) - } - - pub fn pod_type(&self, ty: ScriptValue) -> Option { - if let Some(obj) = ty.as_object() { - let object = &self.objects[obj]; - return object.tag.as_pod_type(); - } - None - } - - pub fn pod_type_ref(&self, ty: ScriptPodType) -> &ScriptPodTypeData { - &self.pod_types[ty.index as usize] - } - - /// Get pod data for a ScriptPod value. - /// Returns the pod type and data slice for extracting values. - pub fn pod_data(&self, pod: ScriptPod) -> (&ScriptPodTypeData, &[u32]) { - let pod_data = &self.pods[pod]; - let pod_type = &self.pod_types[pod_data.ty.index as usize]; - (pod_type, &pod_data.data) - } - - pub fn pod_type_name(&self, ty: ScriptPodType) -> Option { - let ty = &self.pod_types[ty.index as usize]; - ty.name - } - - pub fn pod_type_name_set(&mut self, ty: ScriptPodType, name: LiveId) { - let ty = &mut self.pod_types[ty.index as usize]; - ty.name = Some(name); - } - - pub fn pod_type_name_if_not_set(&mut self, ty: ScriptPodType, name: LiveId) { - let ty = &mut self.pod_types[ty.index as usize]; - if ty.name.is_none() { - ty.name = Some(name); - } - } - - /// Maps a Rust TypeId to its corresponding ScriptPodType. - /// This handles primitive types (f32, u32, i32, bool, f64), - /// vector types (Vec2f, Vec3f, Vec4f), matrix types (Mat4f), - /// and looks up registered struct types that have pod representations. - pub fn type_id_to_pod_type( - &self, - type_id: crate::traits::ScriptTypeId, - builtins: &ScriptPodBuiltins, - ) -> Option { - use makepad_math::{Mat4f, Quat, Vec2f, Vec3f, Vec4f}; - use std::any::TypeId; - - // Check primitive types - if type_id == TypeId::of::() { - return Some(builtins.pod_f32); - } - if type_id == TypeId::of::() { - return Some(builtins.pod_f32); // f64 maps to f32 in pod - } - if type_id == TypeId::of::() { - return Some(builtins.pod_u32); - } - if type_id == TypeId::of::() { - return Some(builtins.pod_i32); - } - if type_id == TypeId::of::() { - return Some(builtins.pod_bool); - } - - // Check vector types (f32) - if type_id == TypeId::of::() { - return Some(builtins.pod_vec2f); - } - if type_id == TypeId::of::() { - return Some(builtins.pod_vec3f); - } - if type_id == TypeId::of::() { - return Some(builtins.pod_vec4f); - } - - // Check matrix types (f32) - if type_id == TypeId::of::() { - return Some(builtins.pod_mat4x4f); - } - - // Quat has same layout as Vec4f (x, y, z, w) - if type_id == TypeId::of::() { - return Some(builtins.pod_vec4f); - } - - // Check if this type has a registered ScriptTypeCheck with a pod type - if let Some(type_index) = self.type_index.get(&type_id) { - let type_check = &self.type_check[type_index.0 as usize]; - - // Check if this is a repr(u32) enum - treat as u32 in shaders - if type_check.is_repr_u32_enum { - return Some(builtins.pod_u32); - } - - if let Some(ref object) = type_check.object { - // Check if the proto object has a pod type - if let Some(proto_obj) = object.proto.as_object() { - let obj_data = &self.objects[proto_obj]; - if let Some(pod_type) = obj_data.tag.as_pod_type() { - return Some(pod_type); - } - } - } - } - - None - } - - fn pod_type_inline( - &self, - val: ScriptValue, - builtins: &ScriptPodBuiltins, - ) -> Option { - if let Some(obj) = val.as_object() { - let object = &self.objects[obj]; - if let Some(pt) = object.tag.as_pod_type() { - return Some(ScriptPodTypeInline { - self_ref: pt, - data: self.pod_types[pt.index as usize].clone(), - }); - } - } - if let Some(pod_ptr) = val.as_pod() { - let pod = &self.pods[pod_ptr]; - let pod_type_obj = self.pod_types[pod.ty.index as usize].object; - let object = &self.objects[pod_type_obj]; - if let Some(pt) = object.tag.as_pod_type() { - return Some(ScriptPodTypeInline { - self_ref: pt, - data: self.pod_types[pt.index as usize].clone(), - }); - } - } - if let Some(_f) = val.as_f64() { - let pod_type = &self.pod_types[builtins.pod_f32.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_f32, - data: pod_type.clone(), - }); - } - if val.is_f32() { - let pod_type = &self.pod_types[builtins.pod_f32.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_f32, - data: pod_type.clone(), - }); - } - if val.is_u32() { - let pod_type = &self.pod_types[builtins.pod_u32.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_u32, - data: pod_type.clone(), - }); - } - if val.is_i32() { - let pod_type = &self.pod_types[builtins.pod_i32.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_i32, - data: pod_type.clone(), - }); - } - if val.is_f16() { - let pod_type = &self.pod_types[builtins.pod_f16.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_f16, - data: pod_type.clone(), - }); - } - if val.is_bool() { - let pod_type = &self.pod_types[builtins.pod_bool.index as usize]; - return Some(ScriptPodTypeInline { - self_ref: builtins.pod_bool, - data: pod_type.clone(), - }); - } - None - } - pub fn finalize_maybe_pod_type( - &mut self, - ptr: ScriptObject, - builtins: &ScriptPodBuiltins, - trap: ScriptTrap, - ) { - let object = &self.objects[ptr]; - if object.tag.is_pod_type() { - let mut kvs = Vec::new(); - let mut pod_type = id!(pod_unknown); - let mut walk = ptr; - loop { - let object = &self.objects[walk]; - if object.tag.is_vec2() { - for kv in object.vec.iter().rev() { - kvs.push(kv); - } - } - if let Some(next_ptr) = object.proto.as_object() { - walk = next_ptr - } else { - pod_type = object.proto.as_id().unwrap_or(pod_type); - break; - } - } - // alright we have our properties - // now lets build a pod_type from it - match pod_type { - id!(pod_array) => { - if kvs.len() == 1 { - if let Some(ty) = self.pod_type_inline(kvs[0].value, builtins) { - let pt = self.new_pod_type( - ptr, - None, - ScriptPodTy::VariableArray { - align_of: ty.data.ty.align_of(), - ty: Box::new(ty), - }, - NIL, - ); - self.set_object_pod_type(ptr, pt); - self.set_notproto(ptr); - self.freeze(ptr); - return; - } - } else if kvs.len() == 2 { - if let Some(ty) = self.pod_type_inline(kvs[1].value, builtins) { - if let Some(len) = kvs[0].value.as_number() { - let len = len as usize; - let align_of = ty.data.ty.align_of(); - let size_of = align_of * len; - let rem = size_of % align_of; - let size_of = if rem != 0 { - size_of + (align_of - rem) - } else { - size_of - }; - - let pt = self.new_pod_type( - ptr, - None, - ScriptPodTy::FixedArray { - ty: Box::new(ty), - align_of, - size_of, - len, - }, - NIL, - ); - self.set_object_pod_type(ptr, pt); - self.set_notproto(ptr); - self.freeze(ptr); - return; - } - } - } - script_err_pod!(trap, "pod array definition requires [element_type] or [length, element_type], got {} elements", kvs.len()); - return; - } - id!(pod_struct) => { - // alright lets build a struct - let mut fields = Vec::new(); - let mut methods = Vec::new(); - for kv in kvs.iter().rev() { - if let Some(ty) = self.pod_type_inline(kv.value, builtins) { - if let Some(name) = kv.key.as_id() { - fields.push(ScriptPodField { - name, - ty, - default: kv.value, - }); - continue; - } - } - if let Some(obj) = kv.value.as_object() { - if self.is_fn(obj) { - // functions are methods - methods.push(obj); - continue; - } - } - - script_err_pod!(trap, "pod struct field {:?} is not a pod type", kv.key); - } - - // Use centralized layout calculation - let pt = self.new_pod_type(ptr, None, ScriptPodTy::new_struct(fields), NIL); - self.set_object_pod_type(ptr, pt); - self.set_notproto(ptr); - self.freeze(ptr); - } - _x => { - script_err_pod!(trap, "pod type {:?} cannot be extended (only pod_array and pod_struct are extendable)", pod_type); - return; - } - } - } - } - - pub fn pod_def_atom( - &mut self, - pod_module: ScriptObject, - name: LiveId, - alias: Option, - ty: ScriptPodTy, - helper_name: LiveId, - default: ScriptValue, - ) -> ScriptPodType { - let pod_obj = self.new_with_proto(helper_name.into()); - if ty != ScriptPodTy::UndefinedStruct && ty != ScriptPodTy::ArrayBuilder { - self.set_notproto(pod_obj); - } - let pt = self.new_pod_type(pod_obj, Some(name), ty, default); - self.set_object_storage_vec2(pod_obj); - self.set_object_pod_type(pod_obj, pt); - self.set_value_def(pod_module, name.into(), pod_obj.into()); - if let Some(alias) = alias { - self.set_value_def(pod_module, alias.into(), pod_obj.into()); - } - pt - } - - pub fn pod_def_vec( - &mut self, - pod_module: ScriptObject, - name: LiveId, - alias: Option, - builtin: ScriptPodVec, - ) -> ScriptPodType { - let pod_obj = self.new_with_proto(name.into()); - let vec_ty = self.new_pod_type(pod_obj, Some(name), ScriptPodTy::Vec(builtin), NIL); - self.set_object_pod_type(pod_obj, vec_ty); - self.set_notproto(pod_obj); - self.freeze(pod_obj); - self.set_value_def(pod_module, name.into(), pod_obj.into()); - if let Some(alias) = alias { - self.set_value_def(pod_module, alias.into(), pod_obj.into()); - } - return vec_ty; - } - - pub fn pod_def_mat( - &mut self, - pod_module: ScriptObject, - name: LiveId, - builtin: ScriptPodMat, - ) -> ScriptPodType { - let pod_obj = self.new_with_proto(name.into()); - let mat_ty = self.new_pod_type(pod_obj, Some(name), ScriptPodTy::Mat(builtin), NIL); - self.set_object_pod_type(pod_obj, mat_ty); - self.set_notproto(pod_obj); - self.freeze(pod_obj); - self.set_value_def(pod_module, name.into(), pod_obj.into()); - return mat_ty; - } - - // PODS - - pub fn new_pod(&mut self, ty: ScriptPodType) -> ScriptPod { - let pod_ty = &self.pod_types[ty.index as usize]; - let pod = if let Some(ptr) = self.pods_free.pop() { - let pod = &mut self.pods[ptr]; - pod.ty = ty; - pod.tag.set_alloced(); - pod.data - .resize(pod_ty.ty.size_of().next_multiple_of(4) >> 2, 0); - // Reused slots keep existing words when size stays equal. - // Always zero so old pod contents cannot leak into a fresh allocation. - pod.data.fill(0); - ptr - } else { - let index = self.pods.len() as u32; - self.pods.push(ScriptPodData { - ty, - ..Default::default() - }); - // New slot starts at generation 0 - let ptr = ScriptPod::new(index, crate::value::GENERATION_ZERO); - let pod = &mut self.pods[ptr]; - pod.tag.set_alloced(); - pod.data - .resize(pod_ty.ty.size_of().next_multiple_of(4) >> 2, 0); - ptr - }; - self.reconcile_heap_bytes_if_limited(); - pod - } - - // POD writing - - pub fn set_pod_field( - &self, - pod: ScriptPod, - field: ScriptValue, - _value: ScriptValue, - _trap: ScriptTrap, - ) -> ScriptValue { - let _pod = &self.pods[pod]; - println!( - "pod_heap::set_pod_field - Want to set pod field {}, but not impplemented", - field - ); - NIL - } - - pub fn pod_pop_to_me( - &mut self, - pod_ptr: ScriptPod, - offset: &mut ScriptPodOffset, - _field: ScriptValue, - value: ScriptValue, - builtins: &ScriptPodBuiltins, - trap: ScriptTrap, - ) { - let pod_ty_index = self.pods[pod_ptr].ty.index as usize; - - // if we are constructing an array, set the type here - if let ScriptPodTy::ArrayBuilder = &self.pod_types[pod_ty_index].ty { - let ty = if let Some(ty) = self.pod_type_inline(value, builtins) { - ty - } else { - script_err_pod!( - trap, - "pod type mismatch: value {:?} is not a valid pod element", - value.value_type() - ); - return; - }; - if let Some(last_ty) = self.pods[pod_ptr].tag.as_array_builder() { - if last_ty != ty.self_ref { - script_err_pod!(trap, "pod array element type mismatch: array expects element type index {}, got {}", last_ty.index, ty.self_ref.index); - return; - } - } else { - self.pods[pod_ptr].tag.set_array_builder(ty.self_ref); - } - } - - let pod = &mut self.pods[pod_ptr]; - let mut out_data = Vec::new(); - std::mem::swap(&mut out_data, &mut pod.data); - let pod_ty = pod.ty; - let pod_type = &self.pod_types[pod_ty.index as usize]; - // alright lets write 'value' into our current offset slot - // our current offset slot is - match &pod_type.ty { - ScriptPodTy::Struct { - align_of, fields, .. - } => { - // struct. ok so we are at field - if let Some(field) = fields.get(offset.field_index) { - // align the field offset - let align_bytes = field.ty.data.ty.align_of(); - let rem = offset.offset_of % align_of; - if rem != 0 { - offset.offset_of += align_bytes - rem - } - - self.pod_write_field(&field.ty, offset.offset_of, &mut out_data, value, trap); - // alright lets do the align and all that - offset.field_index += 1; - offset.offset_of += field.ty.data.ty.size_of(); - } else { - script_err_pod!( - trap, - "pod struct has too many fields: field index {} >= field count {}", - offset.field_index, - fields.len() - ); - } - } - ScriptPodTy::ArrayBuilder => { - if let Some(ty) = self.pods[pod_ptr].tag.as_array_builder() { - let pod_type = &self.pod_types[ty.index as usize]; - let align_of = pod_type.ty.align_of(); - let rem = offset.offset_of % align_of; - if rem != 0 { - offset.offset_of += align_of - rem - } - - let no_u32 = (offset.offset_of + align_of) >> 2; - if (offset.offset_of + align_of) & 3 > 0 { - out_data.resize(no_u32 + 1, 0); - } else { - out_data.resize(no_u32, 0); - } - let element_ty = ScriptPodTypeInline { - self_ref: ty, - data: pod_type.clone(), - }; - self.pod_write_field(&element_ty, offset.offset_of, &mut out_data, value, trap); - offset.offset_of += align_of; - } - } - ScriptPodTy::FixedArray { - align_of: _, - size_of: _, - len: _, - ty: _, - } => {} - ScriptPodTy::VariableArray { align_of: _, ty: _ } => {} - ScriptPodTy::Vec(ot) => { - offset.offset_of += - self.pod_write_vec(ot, offset.offset_of, &mut out_data, value, trap); - } - ScriptPodTy::Mat(mt) => { - if let Some(value) = value.as_number() { - if offset.offset_of >= mt.elem_size() * mt.dim() { - script_err_pod!( - trap, - "pod matrix has too many elements: offset {} >= size {}", - offset.offset_of, - mt.elem_size() * mt.dim() - ); - } else { - out_data[offset.offset_of >> 2] = (value as f32).to_bits(); - offset.offset_of += mt.elem_size() - } - } else if let Some(_in_pod) = value.as_pod() { - script_err_pod!(trap, "pod matrix expects scalar values, got pod"); - } else { - script_err_pod!( - trap, - "pod matrix expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::F32 => { - if offset.field_index > 0 { - script_err_pod!(trap, "f32 constructor takes exactly 1 arg, got more"); - } else if let Some(v) = value.as_number() { - out_data.resize(1, 0); - out_data[0] = (v as f32).to_bits(); - offset.field_index = 1; - offset.offset_of = 4; - } else { - script_err_pod!( - trap, - "f32 constructor expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::F16 => { - if offset.field_index > 0 { - script_err_pod!(trap, "f16 constructor takes exactly 1 arg, got more"); - } else if let Some(v) = value.as_number() { - out_data.resize(1, 0); - out_data[0] = f32_to_f16(v as f32) as u32; - offset.field_index = 1; - offset.offset_of = 2; - } else { - script_err_pod!( - trap, - "f16 constructor expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::U32 => { - if offset.field_index > 0 { - script_err_pod!(trap, "u32 constructor takes exactly 1 arg, got more"); - } else if let Some(v) = value.as_number() { - out_data.resize(1, 0); - out_data[0] = v as u32; - offset.field_index = 1; - offset.offset_of = 4; - } else { - script_err_pod!( - trap, - "u32 constructor expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::I32 => { - if offset.field_index > 0 { - script_err_pod!(trap, "i32 constructor takes exactly 1 arg, got more"); - } else if let Some(v) = value.as_number() { - out_data.resize(1, 0); - out_data[0] = (v as i32) as u32; - offset.field_index = 1; - offset.offset_of = 4; - } else { - script_err_pod!( - trap, - "i32 constructor expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::Bool => { - if offset.field_index > 0 { - script_err_pod!(trap, "bool constructor takes exactly 1 arg, got more"); - } else if let Some(v) = value.as_bool() { - out_data.resize(1, 0); - out_data[0] = if v { 1 } else { 0 }; - offset.field_index = 1; - offset.offset_of = 4; - } else { - script_err_pod!( - trap, - "bool constructor expects bool, got {:?}", - value.value_type() - ); - } - } - _ => { - script_err_unexpected!(trap, "unexpected pod type {:?} in pop_to_me", pod_type.ty); - } - } - std::mem::swap(&mut out_data, &mut self.pods[pod_ptr].data); - } - - pub fn pod_check_arg_total( - &mut self, - pod: ScriptPod, - offset: ScriptPodOffset, - trap: ScriptTrap, - ) { - let pod = &mut self.pods[pod]; - let pod_type = &self.pod_types[pod.ty.index as usize]; - let size_of = pod_type.ty.size_of(); - if offset.offset_of == 0 { - // empty. lets do it zero'ed - return; - } - // not enough - - if size_of != offset.offset_of { - match &pod_type.ty { - ScriptPodTy::ArrayBuilder => return, - ScriptPodTy::Vec(vt) => { - if offset.offset_of == vt.elem_size() { - if vt.elem_size() == 2 { - let fill = pod.data[0] & 0xffff; - for i in 0..pod_type.ty.size_of() >> 2 { - pod.data[i] = (fill) | (fill << 16) - } - } else { - let fill = pod.data[0]; - for i in 1..pod_type.ty.size_of() >> 2 { - pod.data[i] = fill - } - } - return; - } - } - ScriptPodTy::Mat(mt) => { - if offset.offset_of == mt.elem_size() { - if mt.elem_size() == 2 { - let fill = pod.data[0] & 0xffff; - for i in 0..pod_type.ty.size_of() >> 2 { - pod.data[i] = (fill) | (fill << 16) - } - } else { - let fill = pod.data[0]; - for i in 1..pod_type.ty.size_of() >> 2 { - pod.data[i] = fill - } - } - return; - } - } - _ => {} - } - } else { - return; - } - script_err_pod!( - trap, - "pod constructor incomplete: provided {} bytes, expected {}", - offset.offset_of, - size_of - ); - } - - fn pod_write_vec( - &self, - ot: &ScriptPodVec, - offset_of: usize, - out_data: &mut [u32], - value: ScriptValue, - trap: ScriptTrap, - ) -> usize { - if let Some(value) = value.as_number() { - if offset_of >= ot.elem_size() * ot.dims() { - script_err_pod!( - trap, - "pod {} has too many components: offset {} >= size {}", - ot.name(), - offset_of, - ot.elem_size() * ot.dims() - ); - return 0; - } else { - let o = offset_of; - let o2 = o >> 2; - match ot { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - out_data[o2] = (value as f32).to_bits(); - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - let u = f32_to_f16(value as f32); - if o & 3 >= 2 { - out_data[o >> 2] |= (u as u32) << 16; - } else { - out_data[o >> 2] = u as u32; - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - out_data[o2] = value as u32; - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - out_data[o2] = value as i32 as u32; - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - out_data[o2] = value as i32 as u32; - } - } - return ot.elem_size(); - } - } else if let Some(value) = value.as_bool() { - if offset_of >= ot.elem_size() * ot.dims() { - script_err_pod!( - trap, - "pod {} has too many components: offset {} >= size {}", - ot.name(), - offset_of, - ot.elem_size() * ot.dims() - ); - return 0; - } else { - let o = offset_of; - let o2 = o >> 2; - match ot { - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - out_data[o2] = if value { 1 } else { 0 } - } - _ => { - script_err_pod!(trap, "pod {} does not accept bool values", ot.name()); - } - } - return ot.elem_size(); - } - } else if let Some(in_pod) = value.as_pod() { - let in_pod = &self.pods[in_pod]; - let in_pod_ty = &self.pod_types[in_pod.ty.index as usize]; - if let ScriptPodTy::Vec(it) = &in_pod_ty.ty { - if offset_of + it.dims() * ot.elem_size() > ot.elem_size() * ot.dims() { - script_err_pod!( - trap, - "pod {} + {} exceeds {} capacity: {} + {} > {}", - ot.name(), - it.name(), - ot.name(), - offset_of, - it.dims() * ot.elem_size(), - ot.elem_size() * ot.dims() - ); - return 0; - } else { - // output type - let o = offset_of; - let o2 = o >> 2; - match ot { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => match it - { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i]; - } - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - for i in 0..it.dims() { - if i & 1 == 1 { - out_data[o2 + i] = - f16_to_f32((in_pod.data[i >> 1] >> 16) as u16) - .to_bits(); - } else { - out_data[o2 + i] = - f16_to_f32(in_pod.data[i >> 1] as u16).to_bits() - } - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - for i in 0..it.dims() { - out_data[o2 + i] = (in_pod.data[i] as f32).to_bits(); - } - } - ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b - | ScriptPodVec::Vec2i - | ScriptPodVec::Vec3i - | ScriptPodVec::Vec4i => { - for i in 0..it.dims() { - out_data[o2 + i] = (in_pod.data[i] as i32 as f32).to_bits(); - } - } - }, - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => match it - { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - for i in 0..it.dims() { - let u = f32_to_f16(f32::from_bits(in_pod.data[i])); - let op = o + (i << 1); - if op & 3 >= 2 { - out_data[op >> 2] |= (u as u32) << 16; - } else { - out_data[op >> 2] = u as u32; - } - } - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - for i in (0..it.dims()).step_by(2) { - out_data[o + i >> 1] = in_pod.data[i >> 1]; - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - for i in 0..it.dims() { - let u = f32_to_f16(in_pod.data[i] as f32); - let op = o + (i << 1); - if op & 3 >= 2 { - out_data[op >> 2] |= (u as u32) << 16; - } else { - out_data[op >> 2] = u as u32; - } - } - } - ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b - | ScriptPodVec::Vec2i - | ScriptPodVec::Vec3i - | ScriptPodVec::Vec4i => { - for i in 0..it.dims() { - let u = f32_to_f16(in_pod.data[i] as i32 as f32); - let op = o + (i << 1); - if op & 3 >= 2 { - out_data[op >> 2] |= (u as u32) << 16; - } else { - out_data[op >> 2] = u as u32; - } - } - } - }, - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => match it - { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - for i in 0..it.dims() { - out_data[o2 + i] = f32::from_bits(in_pod.data[i]) as u32; - } - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - for i in 0..it.dims() { - if i & 1 == 1 { - out_data[o2 + i] = - f16_to_f32((in_pod.data[i >> 1] >> 16) as u16) as u32; - } else { - out_data[o2 + i] = - f16_to_f32(in_pod.data[i >> 1] as u16) as u32; - } - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i]; - } - } - ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b - | ScriptPodVec::Vec2i - | ScriptPodVec::Vec3i - | ScriptPodVec::Vec4i => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i] as i32 as u32; - } - } - }, - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => match it - { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - for i in 0..it.dims() { - out_data[o2 + i] = f32::from_bits(in_pod.data[i]) as i32 as u32; - } - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - for i in 0..it.dims() { - if i & 1 == 1 { - out_data[o2 + i] = - f16_to_f32((in_pod.data[i >> 1] >> 16) as u16) as i32 - as u32 - } else { - out_data[o2 + i] = - f16_to_f32(in_pod.data[i >> 1] as u16) as i32 as u32 - } - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i] as i32 as u32; - } - } - ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b - | ScriptPodVec::Vec2i - | ScriptPodVec::Vec3i - | ScriptPodVec::Vec4i => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i]; - } - } - }, - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => match it - { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - for i in 0..it.dims() { - out_data[o2 + i] = if f32::from_bits(in_pod.data[i]) as u32 != 0 - { - 1 - } else { - 0 - }; - } - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - for i in 0..it.dims() { - if i & 1 == 1 { - out_data[o2 + i] = - if f16_to_f32((in_pod.data[i >> 1] >> 16) as u16) as i32 - as u32 - != 0 - { - 1 - } else { - 0 - } - } else { - out_data[o2 + i] = - if f16_to_f32(in_pod.data[i >> 1] as u16) as i32 as u32 - != 0 - { - 1 - } else { - 0 - } - } - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - for i in 0..it.dims() { - out_data[o2 + i] = if in_pod.data[i] as i32 as u32 != 0 { - 1 - } else { - 0 - }; - } - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - for i in 0..it.dims() { - out_data[o2 + i] = if in_pod.data[i] != 0 { 1 } else { 0 }; - } - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - for i in 0..it.dims() { - out_data[o2 + i] = in_pod.data[i]; - } - } - }, - } - return it.dims() * ot.elem_size(); - } - } else { - script_err_pod!( - trap, - "pod {} expects vector input, got {:?}", - ot.name(), - in_pod_ty.ty - ); - } - } else { - script_err_pod!( - trap, - "pod {} expects number, bool or vector, got {:?}", - ot.name(), - value.value_type() - ); - } - 0 - } - - fn pod_write_field( - &self, - field_ty: &ScriptPodTypeInline, - offset_of: usize, - out_data: &mut Vec, - value: ScriptValue, - trap: ScriptTrap, - ) { - match &field_ty.data.ty { - ScriptPodTy::Void | ScriptPodTy::ArrayBuilder | ScriptPodTy::UndefinedStruct => { - script_err_unexpected!(trap, "cannot write to pod type {:?}", field_ty.data.ty); - return; - } - ScriptPodTy::Bool => { - if let Some(value) = value.as_bool() { - out_data[offset_of >> 2] = if value { 1 } else { 0 } - } else { - script_err_pod!( - trap, - "pod bool field expects bool, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => { - if let Some(value) = value.as_number() { - out_data[offset_of >> 2] = value as u32; - } else { - script_err_pod!( - trap, - "pod u32 field expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => { - if let Some(value) = value.as_number() { - out_data[offset_of >> 2] = (value as i32) as u32; - } else { - script_err_pod!( - trap, - "pod i32 field expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::F32 => { - if let Some(value) = value.as_number() { - out_data[offset_of >> 2] = (value as f32).to_bits(); - } else if let Some(other_pod) = value.as_pod() { - let other_pod = &self.pods[other_pod]; - let _other_pod_ty = &self.pod_types[other_pod.ty.index as usize]; - // we should only allow splatting vecs into vecs - // how do we figure out we are a vec - } else { - script_err_pod!( - trap, - "pod f32 field expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::Vec(_vt) => { - if let Some(other_pod) = value.as_pod() { - let other_pod = &self.pods[other_pod]; - if other_pod.ty == field_ty.self_ref { - let o = offset_of >> 2; - for i in 0..other_pod.data.len() { - out_data[o + i] = other_pod.data[i] - } - return; - } - } - script_err_pod!( - trap, - "pod vec field expects matching vec type (type index {}), got {:?}", - field_ty.self_ref.index, - value.value_type() - ); - } - ScriptPodTy::Mat(_mt) => { - if let Some(other_pod) = value.as_pod() { - let other_pod = &self.pods[other_pod]; - if other_pod.ty == field_ty.self_ref { - let o = offset_of >> 2; - for i in 0..other_pod.data.len() { - out_data[o + i] = other_pod.data[i] - } - return; - } - } - script_err_pod!( - trap, - "pod mat field expects matching mat type (type index {}), got {:?}", - field_ty.self_ref.index, - value.value_type() - ); - } - ScriptPodTy::F16 => { - if let Some(value) = value.as_number() { - let u = f32_to_f16(value as f32); - if offset_of & 3 >= 2 { - out_data[offset_of >> 2] |= (u as u32) << 16; - } else { - out_data[offset_of >> 2] = u as u32; - } - } else { - script_err_pod!( - trap, - "pod f16 field expects number, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::Struct { .. } => { - if let Some(other_pod) = value.as_pod() { - let other_pod = &self.pods[other_pod]; - if other_pod.ty == field_ty.self_ref { - let o = offset_of >> 2; - for i in 0..other_pod.data.len() { - out_data[o + i] = other_pod.data[i] - } - } else { - script_err_pod!( - trap, - "pod struct field expects type index {}, got type index {}", - field_ty.self_ref.index, - other_pod.ty.index - ); - } - } else { - script_err_pod!( - trap, - "pod struct field expects struct, got {:?}", - value.value_type() - ); - } - } - ScriptPodTy::Enum { .. } => { - todo!() - } - ScriptPodTy::FixedArray { - ty, len, size_of, .. - } => { - // alright we're writing to 'fixed array'. - // lets accept an ArrayBuilder, check if the type fits and the length of the array - // ifso write it in. - if let Some(other_pod_ptr) = value.as_pod() { - let other_pod = &self.pods[other_pod_ptr]; - let other_pod_ty = &self.pod_types[other_pod.ty.index as usize]; - - if let ScriptPodTy::ArrayBuilder = &other_pod_ty.ty { - // Check element type - if let Some(elem_ty) = other_pod.tag.as_array_builder() { - if elem_ty != ty.self_ref { - script_err_pod!(trap, "pod fixed array element type mismatch: expected type index {}, got {}", ty.self_ref.index, elem_ty.index); - return; - } - } else if *len > 0 { - script_err_pod!( - trap, - "pod fixed array expects ArrayBuilder with {} elements", - len - ); - return; - } - - // Check size match - // heuristic check based on ArrayBuilder implementation - if other_pod.data.len() * 4 < *size_of { - script_err_pod!( - trap, - "pod fixed array has not enough data: got {} bytes, need {}", - other_pod.data.len() * 4, - size_of - ); - return; - } - let elem_align = ty.data.ty.align_of(); - if other_pod.data.len() > *size_of + elem_align { - script_err_pod!( - trap, - "pod fixed array has too much data: got {} u32s, max {}", - other_pod.data.len(), - *size_of + elem_align - ); - return; - } - - // Copy data - let u32_count = *size_of >> 2; - let start = offset_of >> 2; - if start + u32_count > out_data.len() { - script_err_pod!( - trap, - "pod fixed array write would exceed buffer: {} + {} > {}", - start, - u32_count, - out_data.len() - ); - return; - } - for i in 0..u32_count { - out_data[start + i] = other_pod.data[i]; - } - return; - } - } - script_err_pod!( - trap, - "pod fixed array field expects ArrayBuilder, got {:?}", - value.value_type() - ); - } - ScriptPodTy::VariableArray { ty, .. } => { - if let Some(other_pod_ptr) = value.as_pod() { - let other_pod = &self.pods[other_pod_ptr]; - let other_pod_ty = &self.pod_types[other_pod.ty.index as usize]; - - if let ScriptPodTy::ArrayBuilder = &other_pod_ty.ty { - if let Some(elem_ty) = other_pod.tag.as_array_builder() { - if elem_ty != ty.self_ref { - script_err_pod!(trap, "pod variable array element type mismatch: expected type index {}, got {}", ty.self_ref.index, elem_ty.index); - return; - } - } else if other_pod.data.len() > 0 { - script_err_pod!(trap, "pod variable array expects ArrayBuilder with matching element type"); - return; - } - - let elem_count_u32 = other_pod.data.len(); - let start_u32 = offset_of >> 2; - - out_data.resize(start_u32 + elem_count_u32, 0); - - for i in 0..elem_count_u32 { - out_data[start_u32 + i] = other_pod.data[i]; - } - return; - } - } - script_err_pod!( - trap, - "pod variable array field expects ArrayBuilder, got {:?}", - value.value_type() - ); - } - } - } - - // POD Reading - - pub fn pod_array_index( - &mut self, - pod_ptr: ScriptPod, - index: usize, - builtins: &ScriptPodBuiltins, - trap: ScriptTrap, - ) -> ScriptValue { - let pod = &mut self.pods[pod_ptr]; - let pod_ty = pod.ty; - let pod_type = &self.pod_types[pod_ty.index as usize]; - - let (elem_ty, align_of) = match &pod_type.ty { - ScriptPodTy::ArrayBuilder => { - if let Some(ty) = pod.tag.as_array_builder() { - let pod_type = &self.pod_types[ty.index as usize]; - (Some(ty), pod_type.ty.align_of()) - } else { - (None, 0) - } - } - ScriptPodTy::FixedArray { ty, align_of, .. } - | ScriptPodTy::VariableArray { ty, align_of, .. } => (Some(ty.self_ref), *align_of), - _ => { - script_err_wrong_value!( - trap, - "cannot index into pod type {:?} (not an array)", - pod_type.ty - ); - return NIL; - } - }; - - if let Some(elem_ty) = elem_ty { - let offset_of = index * align_of; - // bounds check - let pod = &self.pods[pod_ptr]; - if offset_of + align_of > pod.data.len() * 4 { - script_err_out_of_bounds!( - trap, - "pod array index {} out of bounds (max index={})", - index, - (pod.data.len() * 4 / align_of).saturating_sub(1) - ); - return NIL; - } - - let elem_pod_type = &self.pod_types[elem_ty.index as usize]; - match &elem_pod_type.ty { - ScriptPodTy::Bool => { - if pod.data[offset_of >> 2] == 1 { - return TRUE; - } else { - return FALSE; - } - } - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => { - return ScriptValue::from_u32(pod.data[offset_of >> 2]) - } - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => { - return ScriptValue::from_i32(pod.data[offset_of >> 2] as i32) - } - ScriptPodTy::F32 => { - return ScriptValue::from_f32(f32::from_bits(pod.data[offset_of >> 2])) - } - ScriptPodTy::F16 => { - if offset_of & 3 >= 2 { - return ScriptValue::from_f16(f16_to_f32( - (pod.data[offset_of >> 2] >> 16) as u16, - )); - } else { - return ScriptValue::from_f16(f16_to_f32(pod.data[offset_of >> 2] as u16)); - } - } - ScriptPodTy::Vec(vt) => { - let range = (offset_of >> 2)..((offset_of + vt.align_of()) >> 2); - let pod_type = vt.builtin(builtins); - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - ScriptPodTy::Mat(mt) => { - let range = (offset_of >> 2)..((offset_of + mt.size_of()) >> 2); - let pod_type = mt.builtin(builtins); - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - ScriptPodTy::FixedArray { size_of, .. } | ScriptPodTy::Struct { size_of, .. } => { - let range = (offset_of >> 2)..((offset_of + size_of) >> 2); - let pod_type = elem_ty; - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - _ => {} - } - } - - NIL - } - - pub fn pod_field_type( - &self, - pod_ty: ScriptPodType, - field_name: LiveId, - builtins: &ScriptPodBuiltins, - ) -> Option { - let pod_ty = &self.pod_types[pod_ty.index as usize]; - match &pod_ty.ty { - ScriptPodTy::Struct { fields, .. } => { - for field in fields { - if field.name == field_name { - return Some(field.ty.self_ref); - } - } - None - } - ScriptPodTy::Vec(vt) => { - return makepad_script_derive::pod_swizzle_vec_type!(); - } - _ => None, - } - } - - pub fn pod_read_field( - &mut self, - pod_ptr: ScriptPod, - field: ScriptValue, - builtins: &ScriptPodBuiltins, - trap: ScriptTrap, - ) -> ScriptValue { - // alright lets get a field - let field_name = if let Some(id) = field.as_id() { - id - } else { - return script_err_pod!( - trap, - "pod field name must be identifier, got {:?}", - field.value_type() - ); - }; - let pod = &mut self.pods[pod_ptr]; - let pod_ty = pod.ty; - let pod_type = &self.pod_types[pod_ty.index as usize]; - - // alright lets write 'value' into our current offset slot - // our current offset slot is - match &pod_type.ty { - ScriptPodTy::Struct { - align_of, fields, .. - } => { - let mut offset_of = 0; - // alright we have to return a field now - // what do we do - // do we 'new' pod types? or provide a 'window' - for field in fields { - let align_bytes = field.ty.data.ty.align_of(); - let rem = offset_of % align_of; - if rem != 0 { - offset_of += align_bytes - rem - } - if field.name == field_name { - match &field.ty.data.ty { - ScriptPodTy::Void - | ScriptPodTy::ArrayBuilder - | ScriptPodTy::UndefinedStruct => { - script_err_unexpected!( - trap, - "cannot read pod field {:?} with type {:?}", - field_name, - field.ty.data.ty - ); - return NIL; - } - ScriptPodTy::Bool => { - if pod.data[offset_of >> 2] == 1 { - return TRUE; - } else { - return FALSE; - } - } - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => { - return ScriptValue::from_u32(pod.data[offset_of >> 2]) - } - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => { - return ScriptValue::from_i32(pod.data[offset_of >> 2] as i32) - } - ScriptPodTy::F32 => { - return ScriptValue::from_f32(f32::from_bits( - pod.data[offset_of >> 2], - )) - } - ScriptPodTy::F16 => { - if offset_of & 3 >= 2 { - return ScriptValue::from_f16(f16_to_f32( - (pod.data[offset_of >> 2] >> 16) as u16, - )); - } else { - return ScriptValue::from_f16(f16_to_f32( - pod.data[offset_of >> 2] as u16, - )); - } - } - ScriptPodTy::Vec(vt) => { - let range = (offset_of >> 2)..((offset_of + vt.align_of()) >> 2); - let pod_type = vt.builtin(builtins); - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - ScriptPodTy::Mat(mt) => { - let range = (offset_of >> 2)..((offset_of + mt.size_of()) >> 2); - let pod_type = mt.builtin(builtins); - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - ScriptPodTy::FixedArray { size_of, .. } - | ScriptPodTy::Struct { size_of, .. } => { - let range = (offset_of >> 2)..((offset_of + size_of) >> 2); - let pod_type = field.ty.self_ref; - let out_pod_ptr = self.new_pod(pod_type); - let mut out_data = Vec::new(); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - out_data.clear(); - out_data.extend(&self.pods[pod_ptr].data[range]); - std::mem::swap(&mut self.pods[out_pod_ptr].data, &mut out_data); - return out_pod_ptr.into(); - } - ScriptPodTy::Enum { .. } => { - todo!() - } - ScriptPodTy::VariableArray { .. } => { - todo!() - } - } - } - offset_of += field.ty.data.ty.size_of(); - } - return script_err_pod!(trap, "pod struct has no field {:?}", field_name); - } - ScriptPodTy::Vec(vt) => { - // we support reading fields and swizzles - let mut data = [0u32; 4]; - let data_in = &pod.data; - for i in 0..data.len().min(data_in.len()) { - data[i] = data_in[i] - } - return makepad_script_derive::pod_swizzle_vec_match!(); - } - ScriptPodTy::Mat(_mt) => {} - _ => {} - } - NIL - } - - // Swizzle reading - - pub fn pod_swizzle_vec1( - &self, - vec: ScriptPodVec, - data: [u32; 4], - x: usize, - trap: ScriptTrap, - ) -> ScriptValue { - if x >= vec.dims() { - return script_err_pod!( - trap, - "pod {} swizzle component {} out of range (max={})", - vec.name(), - x, - vec.dims() - 1 - ); - } - match vec { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - return ScriptValue::from_f32(f32::from_bits(data[x])) - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - if x & 1 == 1 { - return ScriptValue::from_f16(f16_to_f32((data[x >> 1] >> 16) as u16)); - } else { - return ScriptValue::from_f16(f16_to_f32(data[x >> 1] as u16)); - } - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - return ScriptValue::from_u32(data[x]) - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - return ScriptValue::from_i32(data[x] as i32) - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - return ScriptValue::from_bool(data[x] as i32 != 0) - } - } - } - - pub fn pod_swizzle_vec( - &mut self, - vec: ScriptPodVec, - data: [u32; 4], - swiz: [usize; N], - builtins: &ScriptPodBuiltins, - _trap: ScriptTrap, - ) -> ScriptValue { - let pod_type = match N { - 2 => match vec { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - builtins.pod_vec2f - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - builtins.pod_vec2h - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - builtins.pod_vec2u - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - builtins.pod_vec2i - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - builtins.pod_vec2b - } - }, - 3 => match vec { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - builtins.pod_vec3f - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - builtins.pod_vec3h - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - builtins.pod_vec3u - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - builtins.pod_vec3i - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - builtins.pod_vec3b - } - }, - 4 => match vec { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - builtins.pod_vec4f - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - builtins.pod_vec4h - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - builtins.pod_vec4u - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - builtins.pod_vec4i - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - builtins.pod_vec4b - } - }, - _ => panic!(), - }; - // lets create a pod with type_name - let pod_ptr = self.new_pod(pod_type); - let pod = &mut self.pods[pod_ptr]; - let pod_data = &mut pod.data; - - match vec { - ScriptPodVec::Vec2f - | ScriptPodVec::Vec3f - | ScriptPodVec::Vec4f - | ScriptPodVec::Vec2u - | ScriptPodVec::Vec3u - | ScriptPodVec::Vec4u - | ScriptPodVec::Vec2i - | ScriptPodVec::Vec3i - | ScriptPodVec::Vec4i - | ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b => { - for (i, swiz) in swiz.iter().enumerate() { - pod_data[i] = data[*swiz]; - } - pod_ptr.into() - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - // alright lets swizzle a half float into u32 - pod_ptr.into() - } - } - } - - // Shader compiler use - - pub fn pod_check_abstract_constructor_arg( - &self, - pod_ty: ScriptPodType, - offset: &mut ScriptPodOffset, - trap: ScriptTrap, - ) { - let pod_ty_data = &self.pod_types[pod_ty.index as usize]; - match &pod_ty_data.ty { - // cross casting numbers - ScriptPodTy::F32 | ScriptPodTy::F16 | ScriptPodTy::U32 | ScriptPodTy::I32 => { - if offset.field_index > 0 { - script_err_pod!(trap, "scalar pod constructor takes exactly 1 arg, got more"); - return; - } - offset.field_index += 1; - return; - } - ScriptPodTy::Vec(v1) => { - // what do we - // check field counter - if offset.field_index + 1 > v1.dims() { - script_err_pod!( - trap, - "pod {} constructor: arg {} exceeds {} components", - v1.name(), - offset.field_index + 1, - v1.dims() - ); - } - offset.field_index += 1; - return; - } - ScriptPodTy::Mat(m) => { - // what do we - // check field counter - if offset.field_index + 1 > m.dim() { - script_err_pod!( - trap, - "pod {} constructor: arg {} exceeds {} elements", - m.name(), - offset.field_index + 1, - m.dim() - ); - } - offset.field_index += 1; - return; - } - ScriptPodTy::Struct { fields, .. } => { - if offset.field_index >= fields.len() { - script_err_pod!( - trap, - "pod struct constructor: arg {} exceeds {} fields", - offset.field_index, - fields.len() - ); - return; - } - if !fields[offset.field_index].ty.data.ty.is_number() { - script_err_type_mismatch!( - trap, - "pod struct field {:?} at index {} is not a number type", - fields[offset.field_index].name, - offset.field_index - ); - return; - } - offset.field_index += 1; - } - ScriptPodTy::FixedArray { ty, len, .. } => { - if offset.field_index >= *len { - script_err_pod!( - trap, - "pod fixed array constructor: arg {} exceeds length {}", - offset.field_index, - len - ); - return; - } - if ty.data.ty.is_number() { - script_err_type_mismatch!( - trap, - "pod fixed array element is number type, use scalar constructor" - ); - return; - } - offset.field_index += 1; - } - ScriptPodTy::VariableArray { ty, .. } => { - if ty.data.ty.is_number() { - script_err_type_mismatch!( - trap, - "pod variable array element is number type, use scalar constructor" - ); - return; - } - offset.field_index += 1; - } - _ => { - script_err_type_mismatch!( - trap, - "pod type {:?} does not support abstract constructor args", - pod_ty_data.ty - ); - } - } - } - - pub fn pod_check_constructor_arg_count( - &self, - pod_ty: ScriptPodType, - offset: &ScriptPodOffset, - trap: ScriptTrap, - ) { - let pod_ty_data = &self.pod_types[pod_ty.index as usize]; - match &pod_ty_data.ty { - ScriptPodTy::F32 - | ScriptPodTy::F16 - | ScriptPodTy::U32 - | ScriptPodTy::I32 - | ScriptPodTy::Bool => { - if offset.field_index != 1 { - script_err_pod!( - trap, - "scalar pod constructor requires exactly 1 arg, got {}", - offset.field_index - ); - } - } - ScriptPodTy::Vec(v1) => { - if offset.field_index != 1 && offset.field_index < v1.dims() { - script_err_pod!( - trap, - "pod {} constructor requires 1 or {} args, got {}", - v1.name(), - v1.dims(), - offset.field_index - ); - } - } - ScriptPodTy::Struct { fields, .. } => { - if offset.field_index < fields.len() { - script_err_pod!( - trap, - "pod struct constructor requires {} args, got {}", - fields.len(), - offset.field_index - ); - } - } - ScriptPodTy::FixedArray { len, .. } => { - if offset.field_index < *len { - script_err_pod!( - trap, - "pod fixed array constructor requires {} args, got {}", - len, - offset.field_index - ); - } - } - ScriptPodTy::Mat(m) => { - if offset.field_index != 1 && offset.field_index < m.dim() { - script_err_pod!( - trap, - "pod {} constructor requires 1 or {} args, got {}", - m.name(), - m.dim(), - offset.field_index - ); - } - } - _ => (), - } - } - - pub fn pod_check_constructor_arg( - &self, - pod_ty: ScriptPodType, - pod_ty_arg: ScriptPodType, - offset: &mut ScriptPodOffset, - trap: ScriptTrap, - ) { - let pod_ty_data = &self.pod_types[pod_ty.index as usize]; - let pod_ty_arg_data = &self.pod_types[pod_ty_arg.index as usize]; - match &pod_ty_data.ty { - // cross casting numbers - ScriptPodTy::F32 | ScriptPodTy::F16 | ScriptPodTy::U32 | ScriptPodTy::I32 => { - // were casting to f32 - if offset.field_index > 0 { - script_err_pod!( - trap, - "scalar pod constructor takes exactly 1 arg, already have {}", - offset.field_index - ); - return; - } - offset.field_index += 1; - match &pod_ty_arg_data.ty { - ScriptPodTy::F32 | ScriptPodTy::F16 | ScriptPodTy::U32 | ScriptPodTy::I32 => { - return; - } - _ => { - script_err_type_mismatch!( - trap, - "scalar pod constructor expects number type, got {:?}", - pod_ty_arg_data.ty - ); - } - } - } - ScriptPodTy::Bool => { - // were casting to f32 - if offset.field_index > 0 { - script_err_pod!( - trap, - "bool pod constructor takes exactly 1 arg, already have {}", - offset.field_index - ); - return; - } - offset.field_index += 1; - match &pod_ty_arg_data.ty { - ScriptPodTy::Bool => { - return; - } - _ => { - script_err_type_mismatch!( - trap, - "bool pod constructor expects bool, got {:?}", - pod_ty_arg_data.ty - ); - } - } - } - ScriptPodTy::AtomicU32 => { - script_err_type_mismatch!(trap, "AtomicU32 cannot be constructed directly"); - } - ScriptPodTy::AtomicI32 => { - script_err_type_mismatch!(trap, "AtomicI32 cannot be constructed directly"); - } - ScriptPodTy::Vec(v1) => { - // what do we - match pod_ty_arg_data.ty { - // single component - ScriptPodTy::F32 - | ScriptPodTy::F16 - | ScriptPodTy::U32 - | ScriptPodTy::I32 - | ScriptPodTy::Bool => { - if v1.elem_ty() != pod_ty_arg_data.ty { - script_err_type_mismatch!( - trap, - "pod {} constructor expects {:?} component, got {:?}", - v1.name(), - v1.elem_ty(), - pod_ty_arg_data.ty - ); - } - // check field counter - if offset.field_index + 1 > v1.dims() { - script_err_pod!( - trap, - "pod {} constructor: component {} exceeds {} dimensions", - v1.name(), - offset.field_index + 1, - v1.dims() - ); - } - offset.field_index += 1; - return; - } - // multi component - ScriptPodTy::Vec(v2) => { - if v1.elem_ty() != v2.elem_ty() { - script_err_type_mismatch!(trap, "pod {} constructor element type {:?} doesn't match {} element type {:?}", v1.name(), v1.elem_ty(), v2.name(), v2.elem_ty()); - } - // check field counter - if offset.field_index + v2.dims() > v1.dims() { - script_err_pod!( - trap, - "pod {} + {} would exceed {} components: {} + {} > {}", - v1.name(), - v2.name(), - v1.name(), - offset.field_index, - v2.dims(), - v1.dims() - ); - return; - } - offset.field_index += v2.dims(); - } - _ => { - script_err_type_mismatch!( - trap, - "pod {} constructor expects scalar or vector, got {:?}", - v1.name(), - pod_ty_arg_data.ty - ); - offset.field_index += 1; - return; - } - } - } - ScriptPodTy::Mat(m) => { - match pod_ty_arg_data.ty { - ScriptPodTy::F32 => { - if offset.field_index >= m.dim() { - // check field counter - script_err_pod!( - trap, - "pod {} constructor: element {} exceeds {} elements", - m.name(), - offset.field_index, - m.dim() - ); - return; - } - offset.field_index += 1; - } - _ => { - script_err_type_mismatch!( - trap, - "pod {} constructor expects f32 elements, got {:?}", - m.name(), - pod_ty_arg_data.ty - ); - return; - } - } - } - ScriptPodTy::Struct { fields, .. } => { - if offset.field_index >= fields.len() { - script_err_pod!( - trap, - "pod struct constructor: arg {} exceeds {} fields", - offset.field_index, - fields.len() - ); - return; - } - if fields[offset.field_index].ty.data.ty != pod_ty_arg_data.ty { - script_err_type_mismatch!( - trap, - "pod struct field {:?} expects {:?}, got {:?}", - fields[offset.field_index].name, - fields[offset.field_index].ty.data.ty, - pod_ty_arg_data.ty - ); - return; - } - offset.field_index += 1; - } - ScriptPodTy::FixedArray { ty, len, .. } => { - if offset.field_index >= *len { - script_err_pod!( - trap, - "pod fixed array constructor: arg {} exceeds length {}", - offset.field_index, - len - ); - return; - } - if ty.data.ty != pod_ty_arg_data.ty { - script_err_type_mismatch!( - trap, - "pod fixed array expects element type {:?}, got {:?}", - ty.data.ty, - pod_ty_arg_data.ty - ); - return; - } - offset.field_index += 1; - } - ScriptPodTy::VariableArray { ty, .. } => { - if ty.data.ty != pod_ty_arg_data.ty { - script_err_type_mismatch!( - trap, - "pod variable array expects element type {:?}, got {:?}", - ty.data.ty, - pod_ty_arg_data.ty - ); - return; - } - offset.field_index += 1; - } - ScriptPodTy::Enum { .. } => todo!(), - _ => { - script_err_type_mismatch!( - trap, - "pod type {:?} does not support typed constructor args", - pod_ty_data.ty - ); - } - } - } - - // Debug printing - - pub fn pod_debug( - &self, - out: &mut String, - pod_type: &ScriptPodTypeData, - offset_of: usize, - data: &[u32], - ) { - // alright we have a range of data, and a podtype we should be able to print it - match &pod_type.ty { - ScriptPodTy::Void => { - write!(out, "ScriptPodTy::Void").ok(); - } - ScriptPodTy::ArrayBuilder => { - write!(out, "ScriptPodTy::ArrayBuilder").ok(); - } - ScriptPodTy::UndefinedStruct => { - write!(out, "ScriptPodTy::UndefinedStruct").ok(); - } - ScriptPodTy::Bool => { - write!( - out, - "bool:{}", - if data[offset_of >> 2] != 0 { - true - } else { - false - } - ) - .ok(); - } - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => { - write!(out, "u32:{}", data[offset_of >> 2]).ok(); - } - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => { - write!(out, "i32:{}", data[offset_of >> 2] as i32).ok(); - } - ScriptPodTy::F32 => { - write!(out, "f32:{}", f32::from_bits(data[offset_of >> 2])).ok(); - } - ScriptPodTy::F16 => { - if offset_of & 3 >= 2 { - write!( - out, - "f16:{}", - f16_to_f32((data[offset_of >> 2] >> 16) as u16) - ) - .ok(); - } else { - write!(out, "f16:{}", f16_to_f32(data[offset_of >> 2] as u16)).ok(); - } - } - ScriptPodTy::Vec(vt) => { - write!(out, "{}(", vt.name()).ok(); - let mut offset_of = offset_of; - for i in 0..vt.dims() { - if i > 0 { - write!(out, ", ").ok(); - } - if vt.elem_size() == 2 { - if offset_of & 3 >= 2 { - write!(out, "{}", f16_to_f32((data[offset_of >> 2] >> 16) as u16)).ok(); - } else { - write!(out, "{}", f16_to_f32(data[offset_of >> 2] as u16)).ok(); - } - } else { - write!(out, "{}", f32::from_bits(data[offset_of >> 2])).ok(); - } - offset_of += vt.elem_size(); - } - write!(out, ")").ok(); - } - ScriptPodTy::Mat(mt) => { - write!(out, "{}(", mt.name()).ok(); - let (dim_x, dim_y) = mt.dims(); - let mut offset_of = offset_of; - for y in 0..dim_y { - if y > 0 { - write!(out, ", ").ok(); - } - write!(out, "[").ok(); - for x in 0..dim_x { - if x > 0 { - write!(out, ", ").ok(); - } - write!(out, "{}", f32::from_bits(data[offset_of >> 2])).ok(); - offset_of += mt.elem_size(); - } - write!(out, "]").ok(); - } - write!(out, ")").ok(); - } - ScriptPodTy::Struct { fields, .. } => { - write!(out, "struct{{").ok(); - // keep a counter - let mut offset_of = offset_of; - let mut first = true; - for field in fields { - if !first { - write!(out, ", ").ok(); - } - first = false; - // align the field offset - let align_of = field.ty.data.ty.align_of(); - let size_of = field.ty.data.ty.size_of(); - let rem = offset_of % align_of; - if rem != 0 { - // align offset - offset_of += align_of - rem - } - write!(out, "{}:", field.name).ok(); - self.pod_debug(out, &field.ty.data, offset_of, data); - offset_of += size_of; - } - write!(out, "}}").ok(); - } - ScriptPodTy::Enum { .. } => {} - ScriptPodTy::FixedArray { len, ty, .. } => { - write!(out, "array(").ok(); - - let mut offset_of = offset_of; - let mut first = true; - for i in 0..*len { - if !first { - write!(out, ", ").ok(); - } - first = false; - // align the field offset - let align_of = ty.data.ty.align_of(); - let size_of = ty.data.ty.size_of(); - let rem = offset_of % align_of; - if rem != 0 { - // align offset - offset_of += align_of - rem - } - write!(out, "{}:", i).ok(); - self.pod_debug(out, &ty.data, offset_of, data); - offset_of += size_of; - } - write!(out, ")").ok(); - } - ScriptPodTy::VariableArray { ty, .. } => { - write!(out, "var_array(").ok(); - - let mut offset_of = offset_of; - let mut first = true; - let start = offset_of; - for i in start..data.len() << 2 { - if !first { - write!(out, ", ").ok(); - } - first = false; - // align the field offset - let align_of = ty.data.ty.align_of(); - let size_of = ty.data.ty.size_of(); - let rem = offset_of % align_of; - if rem != 0 { - // align offset - offset_of += align_of - rem - } - write!(out, "{}:", (i - start) / ty.data.ty.align_of()).ok(); - self.pod_debug(out, &ty.data, i, data); - offset_of += size_of; - } - write!(out, ")").ok(); - } - } - } -} - -// AI generated f16/f32 conversions. They look correct at first glance/test - -pub fn f16_to_f32(h: u16) -> f32 { - // Extract sign, exponent, and mantissa - let sign = (h as u32) >> 15; - let exponent = (h >> 10) & 0x1F; - let mantissa = (h & 0x03FF) as u32; - - let bits = if exponent == 0x1F { - // Infinity or NaN - let new_mantissa = if mantissa != 0 { 0x400000 } else { 0 }; // Preserve NaN - (sign << 31) | 0x7F800000 | new_mantissa - } else if exponent == 0 { - // Zero or Subnormal - if mantissa == 0 { - // Zero - sign << 31 - } else { - // Subnormal number - // Count leading zeros in the 10-bit mantissa - // We use `(mantissa as u16).leading_zeros() - 6` because we're interested - // in the position within the 10 bits, not the full 16 bits of the u16. - let shift = (mantissa as u16).leading_zeros() as u32 - 6; - - // Re-bias exponent and shift mantissa - let new_exponent = 127 - 15 - shift; - let new_mantissa = (mantissa << (shift + 1)) & 0x7FFFFF; - - (sign << 31) | (new_exponent << 23) | (new_mantissa << 13) - } - } else { - // Normal number - // Re-bias exponent from 15 to 127 - let new_exponent = (exponent as u32 - 15) + 127; - // Scale the mantissa - let new_mantissa = mantissa << 13; - (sign << 31) | (new_exponent << 23) | new_mantissa - }; - - f32::from_bits(bits) -} - -pub fn f32_to_f16(f: f32) -> u16 { - let bits: u32 = f.to_bits(); - // Extract the sign, exponent, and mantissa from the f32 - let sign = (bits >> 31) & 0x1; - let exponent = (bits >> 23) & 0xff; - let mantissa = bits & 0x7fffff; - - // Handle special cases: NaN and Infinity - if exponent == 0xff { - // NaN or Infinity - let new_mantissa = if mantissa != 0 { 0x200 } else { 0 }; // Preserve NaN-ness - return ((sign as u16) << 15) | 0x7c00 | new_mantissa; - } - - // Re-bias the exponent from f32's bias (127) to f16's bias (15) - let new_exponent = exponent as i32 - 127 + 15; - - if new_exponent >= 31 { - // Overflow to infinity - return ((sign as u16) << 15) | 0x7c00; - } - - if new_exponent <= 0 { - if new_exponent < -10 { - // Underflow to zero - return (sign as u16) << 15; - } - // Handle subnormal numbers - let new_mantissa = (mantissa | 0x800000) >> (1 - new_exponent); - return ((sign as u16) << 15) | (new_mantissa >> 13) as u16; - } - - // Normal number - let new_mantissa = mantissa >> 13; - ((sign as u16) << 15) | ((new_exponent as u16) << 10) | (new_mantissa as u16) -} diff --git a/vendor/makepad/platform/script/src/prims.rs b/vendor/makepad/platform/script/src/prims.rs deleted file mode 100644 index e004578..0000000 --- a/vendor/makepad/platform/script/src/prims.rs +++ /dev/null @@ -1,1042 +0,0 @@ -use crate::apply::*; -use crate::function::*; -use crate::handle::*; -use crate::heap::*; -use crate::object::*; -use crate::pod::*; -use crate::traits::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use makepad_live_id::*; - -#[macro_export] -macro_rules!script_primitive { - ( $ ty: ty, $new:item, $ type_check: item, $ apply: item, $ to_value: item) => { - impl ScriptHook for $ty{} - impl ScriptNew for $ty{ - $ new - $ type_check - fn script_type_name()->Option{ LiveId::from_str_with_lut(stringify!($ty)).ok() } - fn script_default(vm:&mut ScriptVm)->ScriptValue{Self::script_new(vm).script_to_value(vm)} - fn script_proto_build(vm:&mut ScriptVm, _props:&mut ScriptTypeProps)->ScriptValue{ - Self::script_default(vm) - } - } - impl ScriptApply for $ty{ - fn script_type_id(&self)->ScriptTypeId{ScriptTypeId::of::()} - $apply - $to_value - } - } -} - -script_primitive!( - f32, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v as _; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1.0 } else { 0.0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self as _) - } -); - -script_primitive!( - f64, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1.0 } else { 0.0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self) - } -); - -script_primitive!( - u64, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v as u64; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1 } else { 0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self as f64) - } -); - -script_primitive!( - usize, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v as usize; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1 } else { 0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self as f64) - } -); - -script_primitive!( - ScriptObjectRef, - fn script_new(vm: &mut ScriptVm) -> Self { - vm.bx.heap.new_object_ref(ScriptObject::ZERO) - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_object() - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(obj) = value.as_object() { - *self = vm.bx.heap.new_object_ref(obj) - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - self.as_object().into() - } -); - -script_primitive!( - ScriptFnRef, - fn script_new(vm: &mut ScriptVm) -> Self { - vm.bx.heap.new_fn_ref(ScriptObject::ZERO) - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - heap.is_fn(obj) - } else { - false - } - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(obj) = value.as_object() { - if vm.bx.heap.is_fn(obj) { - *self = vm.bx.heap.new_fn_ref(obj) - } - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - self.as_object().into() - } -); - -script_primitive!( - ScriptHandleRef, - fn script_new(vm: &mut ScriptVm) -> Self { - vm.bx.heap.new_handle_ref(ScriptHandle::ZERO) - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.as_handle().is_some() - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(handle) = value.as_handle() { - *self = vm.bx.heap.new_handle_ref(handle) - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - self.as_handle().into() - } -); - -script_primitive!( - u32, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v as u32; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1 } else { 0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self as f64) - } -); - -script_primitive!( - u16, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_number() || value.is_bool() || heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - *self = v as u16; - return; - } - if let Some(v) = value.as_bool() { - *self = if v { 1 } else { 0 }; - return; - } - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_f64(*self as f64) - } -); - -script_primitive!( - bool, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_bool() - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - *self = vm.bx.heap.cast_to_bool(value); - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - ScriptValue::from_bool(*self) - } -); - -script_primitive!( - String, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_string_like() - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - // Same rationale as `ArcStringMut::script_apply`: text-bearing fields - // (`TextInput.text`, `TextInput.empty_text`, etc.) are canonically - // mutated through imperative setters at runtime. A ScriptReapply - // walk fired by `cx.request_script_reapply()` (preference broadcast, - // safe-area inset change) would otherwise clobber that runtime value - // with the stale DSL literal. Strings are not part of the shared- - // heap-object propagation pipeline (which uses `Size`/numerics), so - // bailing here is safe. - if apply.is_script_reapply() { - return; - } - self.clear(); - vm.bx.heap.cast_to_string(value, self); - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - vm.bx.heap.new_string_from_str(self).into() - } -); -impl ScriptDeriveMarker for String {} - -script_primitive!( - &'static str, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_string_like() - }, - fn script_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - vm.bx.heap.new_string_from_str(self).into() - } -); -impl ScriptDeriveMarker for &'static str {} - -script_primitive!( - LiveId, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_id() - }, - fn script_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(id) = value.as_id() { - *self = id - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - self.into() - } -); -impl ScriptDeriveMarker for LiveId {} - -script_primitive!( - ScriptObject, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_object() - }, - fn script_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(object) = value.as_object() { - *self = object - } - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - (*self).into() - } -); -//impl ScriptDeriveMarker for ScriptObject{} - -script_primitive!( - ScriptValue, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(_heap: &ScriptHeap, _value: ScriptValue) -> bool { - true - }, - fn script_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - value: ScriptValue, - ) { - *self = value - }, - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - *self - } -); -//impl ScriptDeriveMarker for ScriptValue{} - -// LiveIdMap implementation -impl ScriptHook for LiveIdMap -where - K: ScriptApply - + ScriptNew - + 'static - + std::cmp::Eq - + std::hash::Hash - + Copy - + From - + std::fmt::Debug, - V: ScriptApply + ScriptNew + 'static, -{ -} - -impl ScriptNew for LiveIdMap -where - K: ScriptApply - + ScriptNew - + 'static - + std::cmp::Eq - + std::hash::Hash - + Copy - + From - + std::fmt::Debug, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - let map = heap.map_ref(obj); - for (key, value) in map.iter() { - if !K::script_type_check(heap, *key) { - return false; - } - if !V::script_type_check(heap, value.value) { - return false; - } - } - return true; - } - value.is_nil() || heap.has_apply_transform(value) - } - fn script_default(_vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(_vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - NIL - } -} - -impl ScriptApply for LiveIdMap -where - K: ScriptApply - + ScriptNew - + 'static - + std::cmp::Eq - + std::hash::Hash - + Copy - + From - + std::fmt::Debug, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - self.clear(); - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in obj_map.iter_mut() { - let key = K::script_from_value(vm, *key); - let value = V::script_from_value(vm, value.value); - self.insert(key, value); - } - }) - } else if value.is_nil() { - self.clear() - } else { - script_err_type_mismatch!(vm.bx.threads.cur_ref().trap, "wrong type in apply"); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let obj = vm.bx.heap.new_object(); - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in self.iter() { - let key = key.script_to_value(vm); - let value = value.script_to_value(vm); - obj_map.insert( - key, - ScriptMapValue { - tag: Default::default(), - value, - }, - ); - } - }); - obj.into() - } -} - -script_primitive!( - makepad_math::Vec2d, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if value.is_number() { - return true; - } - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - return v.dims() == 2; - } - } - heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - self.x = v; - self.y = v; - return; - } - if let Some(pod) = value.as_pod() { - let pod_data = &vm.bx.heap.pods[pod]; - let pod_type = &vm.bx.heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - if v.dims() == 2 { - match v { - ScriptPodVec::Vec2f => { - self.x = f32::from_bits(pod_data.data[0]) as f64; - self.y = f32::from_bits(pod_data.data[1]) as f64; - } - ScriptPodVec::Vec2i => { - self.x = pod_data.data[0] as i32 as f64; - self.y = pod_data.data[1] as i32 as f64; - } - ScriptPodVec::Vec2u => { - self.x = pod_data.data[0] as f64; - self.y = pod_data.data[1] as f64; - } - ScriptPodVec::Vec2b => { - self.x = if pod_data.data[0] != 0 { 1.0 } else { 0.0 }; - self.y = if pod_data.data[1] != 0 { 1.0 } else { 0.0 }; - } - ScriptPodVec::Vec2h => { - self.x = crate::pod_heap::f16_to_f32(pod_data.data[0] as u16) as f64; - self.y = - crate::pod_heap::f16_to_f32((pod_data.data[0] >> 16) as u16) as f64; - } - _ => (), - } - return; - } - } - } - // Try apply transform at the bottom - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let pod_type = vm.bx.code.builtins.pod.pod_vec2f; - let pod = vm.bx.heap.new_pod(pod_type); - let pod_data = &mut vm.bx.heap.pods[pod]; - pod_data.data[0] = (self.x as f32).to_bits(); - pod_data.data[1] = (self.y as f32).to_bits(); - pod.into() - } -); - -script_primitive!( - makepad_math::Vec2f, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if value.is_number() { - return true; - } - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - return v.dims() == 2; - } - } - heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - self.x = v as f32; - self.y = v as f32; - return; - } - if let Some(pod) = value.as_pod() { - let pod_data = &vm.bx.heap.pods[pod]; - let pod_type = &vm.bx.heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - if v.dims() == 2 { - match v { - ScriptPodVec::Vec2f => { - self.x = f32::from_bits(pod_data.data[0]); - self.y = f32::from_bits(pod_data.data[1]); - } - ScriptPodVec::Vec2i => { - self.x = pod_data.data[0] as i32 as f32; - self.y = pod_data.data[1] as i32 as f32; - } - ScriptPodVec::Vec2u => { - self.x = pod_data.data[0] as f32; - self.y = pod_data.data[1] as f32; - } - ScriptPodVec::Vec2b => { - self.x = if pod_data.data[0] != 0 { 1.0 } else { 0.0 }; - self.y = if pod_data.data[1] != 0 { 1.0 } else { 0.0 }; - } - ScriptPodVec::Vec2h => { - self.x = crate::pod_heap::f16_to_f32(pod_data.data[0] as u16); - self.y = crate::pod_heap::f16_to_f32((pod_data.data[0] >> 16) as u16); - } - _ => (), - } - return; - } - } - } - // Try apply transform at the bottom - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let pod_type = vm.bx.code.builtins.pod.pod_vec2f; - let pod = vm.bx.heap.new_pod(pod_type); - let pod_data = &mut vm.bx.heap.pods[pod]; - pod_data.data[0] = (self.x).to_bits(); - pod_data.data[1] = (self.y).to_bits(); - pod.into() - } -); - -script_primitive!( - makepad_math::Vec3f, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if value.is_number() { - return true; - } - if value.is_color() { - return true; - } - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - return v.dims() == 3; - } - } - heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - self.x = v as f32; - self.y = v as f32; - self.z = v as f32; - return; - } - if let Some(c) = value.as_color() { - let v = makepad_math::Vec4f::from_u32(c); - self.x = v.x; - self.y = v.y; - self.z = v.z; - return; - } - if let Some(pod) = value.as_pod() { - let pod_data = &vm.bx.heap.pods[pod]; - let pod_type = &vm.bx.heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - if v.dims() == 3 { - match v { - ScriptPodVec::Vec3f => { - self.x = f32::from_bits(pod_data.data[0]); - self.y = f32::from_bits(pod_data.data[1]); - self.z = f32::from_bits(pod_data.data[2]); - } - ScriptPodVec::Vec3i => { - self.x = pod_data.data[0] as i32 as f32; - self.y = pod_data.data[1] as i32 as f32; - self.z = pod_data.data[2] as i32 as f32; - } - ScriptPodVec::Vec3u => { - self.x = pod_data.data[0] as f32; - self.y = pod_data.data[1] as f32; - self.z = pod_data.data[2] as f32; - } - ScriptPodVec::Vec3b => { - self.x = if pod_data.data[0] != 0 { 1.0 } else { 0.0 }; - self.y = if pod_data.data[1] != 0 { 1.0 } else { 0.0 }; - self.z = if pod_data.data[2] != 0 { 1.0 } else { 0.0 }; - } - ScriptPodVec::Vec3h => { - self.x = crate::pod_heap::f16_to_f32(pod_data.data[0] as u16); - self.y = crate::pod_heap::f16_to_f32((pod_data.data[0] >> 16) as u16); - self.z = crate::pod_heap::f16_to_f32(pod_data.data[1] as u16); - } - _ => (), - } - return; - } - } - } - // Try apply transform at the bottom - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let pod_type = vm.bx.code.builtins.pod.pod_vec3f; - let pod = vm.bx.heap.new_pod(pod_type); - let pod_data = &mut vm.bx.heap.pods[pod]; - pod_data.data[0] = (self.x).to_bits(); - pod_data.data[1] = (self.y).to_bits(); - pod_data.data[2] = (self.z).to_bits(); - pod.into() - } -); - -script_primitive!( - makepad_math::Vec4f, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if value.is_number() { - return true; - } - if value.is_color() { - return true; - } - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - return v.dims() == 4; - } - } - heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - self.x = v as f32; - self.y = v as f32; - self.z = v as f32; - self.w = v as f32; - return; - } - if let Some(c) = value.as_color() { - let v = makepad_math::Vec4f::from_u32(c); - *self = v; - return; - } - if let Some(pod) = value.as_pod() { - let pod_data = &vm.bx.heap.pods[pod]; - let pod_type = &vm.bx.heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Vec(v) = &pod_type.ty { - if v.dims() == 4 { - match v { - ScriptPodVec::Vec4f => { - self.x = f32::from_bits(pod_data.data[0]); - self.y = f32::from_bits(pod_data.data[1]); - self.z = f32::from_bits(pod_data.data[2]); - self.w = f32::from_bits(pod_data.data[3]); - } - ScriptPodVec::Vec4i => { - self.x = pod_data.data[0] as i32 as f32; - self.y = pod_data.data[1] as i32 as f32; - self.z = pod_data.data[2] as i32 as f32; - self.w = pod_data.data[3] as i32 as f32; - } - ScriptPodVec::Vec4u => { - self.x = pod_data.data[0] as f32; - self.y = pod_data.data[1] as f32; - self.z = pod_data.data[2] as f32; - self.w = pod_data.data[3] as f32; - } - ScriptPodVec::Vec4b => { - self.x = if pod_data.data[0] != 0 { 1.0 } else { 0.0 }; - self.y = if pod_data.data[1] != 0 { 1.0 } else { 0.0 }; - self.z = if pod_data.data[2] != 0 { 1.0 } else { 0.0 }; - self.w = if pod_data.data[3] != 0 { 1.0 } else { 0.0 }; - } - ScriptPodVec::Vec4h => { - self.x = crate::pod_heap::f16_to_f32(pod_data.data[0] as u16); - self.y = crate::pod_heap::f16_to_f32((pod_data.data[0] >> 16) as u16); - self.z = crate::pod_heap::f16_to_f32(pod_data.data[1] as u16); - self.w = crate::pod_heap::f16_to_f32((pod_data.data[1] >> 16) as u16); - } - _ => (), - } - return; - } - } - } - // Try apply transform at the bottom - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let pod_type = vm.bx.code.builtins.pod.pod_vec4f; - let pod = vm.bx.heap.new_pod(pod_type); - let pod_data = &mut vm.bx.heap.pods[pod]; - pod_data.data[0] = (self.x).to_bits(); - pod_data.data[1] = (self.y).to_bits(); - pod_data.data[2] = (self.z).to_bits(); - pod_data.data[3] = (self.w).to_bits(); - pod.into() - } -); - -script_primitive!( - makepad_math::Mat4f, - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - }, - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if value.is_number() { - return true; - } - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - let pod_type = &heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Mat(m) = &pod_type.ty { - return m.dims() == (4, 4); - } - } - heap.has_apply_transform(value) - }, - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = value.as_number() { - for i in 0..16 { - self.v[i] = v as f32; - } - return; - } - if let Some(pod) = value.as_pod() { - let pod_data = &vm.bx.heap.pods[pod]; - let pod_type = &vm.bx.heap.pod_types[pod_data.ty.index as usize]; - if let ScriptPodTy::Mat(m) = &pod_type.ty { - if m.dims() == (4, 4) { - match m { - ScriptPodMat::Mat4x4f => { - for i in 0..16 { - self.v[i] = f32::from_bits(pod_data.data[i]); - } - } - _ => (), - } - return; - } - } - } - // Try apply transform at the bottom - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - }, - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let pod_type = vm.bx.code.builtins.pod.pod_mat4x4f; - let pod = vm.bx.heap.new_pod(pod_type); - let pod_data = &mut vm.bx.heap.pods[pod]; - for i in 0..16 { - pod_data.data[i] = self.v[i].to_bits(); - } - pod.into() - } -); - -// Option - -impl ScriptHook for Option where T: ScriptApply + ScriptNew + 'static {} -impl ScriptNew for Option -where - T: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - value.is_nil() || T::script_type_check(heap, value) - } - fn script_default(_vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(_vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - NIL - } -} -impl ScriptApply for Option -where - T: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - if let Some(v) = self { - if value.is_nil() { - *self = None - } else { - v.script_apply(vm, apply, scope, value); - } - } else { - if !value.is_nil() { - let mut inner = T::script_new(vm); - inner.script_apply(vm, apply, scope, value); - *self = Some(inner); - } - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - if let Some(s) = self { - s.script_to_value(vm) - } else { - NIL - } - } -} diff --git a/vendor/makepad/platform/script/src/regex.rs b/vendor/makepad/platform/script/src/regex.rs deleted file mode 100644 index bfc27a6..0000000 --- a/vendor/makepad/platform/script/src/regex.rs +++ /dev/null @@ -1,150 +0,0 @@ -use crate::makepad_regex; -use makepad_regex::ParseOptions; -use makepad_regex::Regex as InnerRegex; - -/// Tag for GC marking of regex objects (same pattern as StringTag) -#[derive(Default)] -pub struct RegexTag(u64); - -impl RegexTag { - const MARK: u64 = 0x1; - const STATIC: u64 = 0x2; - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } -} - -/// Flags parsed from the flags string "gims" -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -pub struct RegexFlags { - pub global: bool, - pub ignore_case: bool, - pub multiline: bool, - pub dot_all: bool, -} - -impl RegexFlags { - pub fn parse(flags: &str) -> Result { - let mut f = RegexFlags::default(); - for ch in flags.chars() { - match ch { - 'g' => { - if f.global { - return Err("duplicate flag 'g'".into()); - } - f.global = true; - } - 'i' => { - if f.ignore_case { - return Err("duplicate flag 'i'".into()); - } - f.ignore_case = true; - } - 'm' => { - if f.multiline { - return Err("duplicate flag 'm'".into()); - } - f.multiline = true; - } - 's' => { - if f.dot_all { - return Err("duplicate flag 's'".into()); - } - f.dot_all = true; - } - _ => return Err(format!("unknown regex flag '{}'", ch)), - } - } - Ok(f) - } - - pub fn to_parse_options(&self) -> ParseOptions { - ParseOptions { - dot_all: self.dot_all, - ignore_case: self.ignore_case, - multiline: self.multiline, - } - } -} - -/// The key used for interning: (pattern, flags) -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RegexInternKey { - pub pattern: String, - pub flags: RegexFlags, -} - -/// Data stored per regex on the heap -pub struct ScriptRegexData { - pub tag: RegexTag, - pub inner: InnerRegex, - pub pattern: String, - pub flags: RegexFlags, - /// Number of capture groups (not counting group 0) - pub num_captures: usize, -} - -impl ScriptRegexData { - pub fn new(pattern: &str, flags: RegexFlags) -> Result { - let options = flags.to_parse_options(); - let inner = InnerRegex::new_with_options(pattern, options).map_err(|e| e.to_string())?; - let num_captures = count_captures(pattern); - Ok(ScriptRegexData { - tag: RegexTag::default(), - inner, - pattern: pattern.to_string(), - flags, - num_captures, - }) - } -} - -/// Count the number of capturing groups in a pattern. -/// Counts unescaped '(' that are NOT followed by '?' -fn count_captures(pattern: &str) -> usize { - let mut count = 0; - let bytes = pattern.as_bytes(); - let mut i = 0; - while i < bytes.len() { - if bytes[i] == b'\\' { - i += 2; // skip escaped char - continue; - } - if bytes[i] == b'[' { - // skip character class contents - i += 1; - while i < bytes.len() && bytes[i] != b']' { - if bytes[i] == b'\\' { - i += 1; - } - i += 1; - } - } - if bytes[i] == b'(' { - if i + 1 < bytes.len() && bytes[i + 1] == b'?' { - // non-capturing or lookahead - don't count - } else { - count += 1; - } - } - i += 1; - } - count -} diff --git a/vendor/makepad/platform/script/src/regex_heap.rs b/vendor/makepad/platform/script/src/regex_heap.rs deleted file mode 100644 index 972464d..0000000 --- a/vendor/makepad/platform/script/src/regex_heap.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::heap::*; -use crate::regex::*; -use crate::value::*; - -impl ScriptHeap { - /// Create or intern a regex. If the same (pattern, flags) was already compiled, - /// returns the existing ScriptRegex index. - pub fn new_regex(&mut self, pattern: &str, flags_str: &str) -> Result { - let flags = RegexFlags::parse(flags_str)?; - let key = RegexInternKey { - pattern: pattern.to_string(), - flags, - }; - - // Check intern table first - if let Some(idx) = self.regex_intern.get(&key) { - return Ok((*idx).into()); - } - - // Compile and store - let data = ScriptRegexData::new(pattern, flags)?; - - let idx = if let Some(re) = self.regexes_free.pop() { - // re already has the correct generation from gc sweep - self.regexes[re] = Some(data); - re - } else { - let index = self.regexes.len(); - self.regexes.push(Some(data)); - ScriptRegex::new(index as u32, crate::value::GENERATION_ZERO) - }; - - self.regex_intern.insert(key, idx); - self.reconcile_heap_bytes_if_limited(); - Ok(idx.into()) - } - - /// Get a reference to a regex's data - pub fn regex(&self, ptr: ScriptRegex) -> Option<&ScriptRegexData> { - self.regexes[ptr].as_ref() - } - - /// Get a mutable reference to a regex's data - pub fn regex_mut(&mut self, ptr: ScriptRegex) -> Option<&mut ScriptRegexData> { - self.regexes[ptr].as_mut() - } -} diff --git a/vendor/makepad/platform/script/src/scratch.rs b/vendor/makepad/platform/script/src/scratch.rs deleted file mode 100644 index f875c73..0000000 --- a/vendor/makepad/platform/script/src/scratch.rs +++ /dev/null @@ -1,26 +0,0 @@ - - - -let fib = |n| if n <= 1 n else fib(n - 1) + fib(n - 2) -~fib(34); - -let MyApp = App{ - $app_bar+:{ - title: "Talk to AI" - } - body := +{ - TextInput{ - on_enter: ||{ - let stream = ai(sself.text) - sself.clear() - $body += Label{ - text <=> stream.text - } - } - } - } -} - -http.server(8080,{ - on_request:|req,res| res.write(200,"Working") -}) diff --git a/vendor/makepad/platform/script/src/shader.rs b/vendor/makepad/platform/script/src/shader.rs deleted file mode 100644 index 79beab7..0000000 --- a/vendor/makepad/platform/script/src/shader.rs +++ /dev/null @@ -1,1693 +0,0 @@ -use crate::function::*; -use crate::makepad_error_log::*; -use crate::mod_pod::*; -use crate::mod_shader::*; -use crate::opcode::*; -use crate::pod::ScriptPodTy; -use crate::shader_backend::*; -use crate::suggest::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use makepad_live_id::*; -use makepad_math::*; -use std::fmt::Write; - -// Re-export types from shader_output -pub use crate::shader_output::*; - -/// Writes a float value for shader output, using scientific notation when needed. -/// This prevents very large numbers like 1e20 from being output as 100000000000000000000.0 -/// which would break shader parsers like Metal. -fn write_shader_float(out: &mut String, v: f64) { - let abs_v = v.abs(); - // Use scientific notation for very large or very small numbers - if abs_v != 0.0 && (abs_v >= 1e15 || abs_v < 1e-6) { - write!(out, "{:e}", v).ok(); - } else { - let start = out.len(); - write!(out, "{}", v).ok(); - // Ensure there's always a decimal point so that appending 'f' produces valid Metal/GLSL - // (e.g. "1" -> "1.0" so we get "1.0f" not "1f") - if !out[start..].contains('.') && !out[start..].contains('e') { - out.push_str(".0"); - } - } -} - -#[derive(Debug)] -pub struct ShaderPodArg { - pub name: Option, - pub ty: ShaderType, - pub s: String, -} - -#[derive(Debug)] -pub enum ShaderMe { - FnBody { - ret: Option, - escaped: bool, // true when all code paths have returned - stack_depth: usize, - }, - LoopBody { - stack_depth: usize, - }, - ForLoop { - var_id: LiveId, - stack_depth: usize, - }, - IfBody { - target_ip: u32, - start_pos: usize, - stack_depth: usize, - phi: Option, - phi_type: Option, - has_return: bool, // true if current branch has a return - if_branch_returned: bool, // remembers if the if-branch returned (used when in else) - phi_assigned_by_inner: bool, // true if an inner if assigned to this phi (for match/else-if chains) - created_unreachable: bool, // true if this IfBody was created while in unreachable code (no code emitted) - }, - /// Logic operation (&&, ||) - for short-circuit bytecode handling in shaders - /// Shaders evaluate both operands and combine with the operator - LogicOp { - target_ip: u32, - op: &'static str, // "&&" or "||" - first_operand: String, // The first operand expression - first_type: ShaderType, // The type of the first operand - }, - BuiltinCall { - name: LiveId, - fnptr: NativeId, - args: Vec<(ShaderType, String)>, - }, - /// Pod builtin method call: x.mix(y, a) -> mix(x, y, a) - PodBuiltinMethod { - name: LiveId, - self_ty: ScriptPodType, - args: Vec<(ShaderType, String)>, - }, - ScriptCall { - out: String, - name: LiveId, - fnobj: ScriptObject, - sself: ShaderType, - args: Vec, - }, - Pod { - pod_ty: ScriptPodType, - args: Vec, - }, - ArrayConstruct { - args: Vec, - elem_ty: Option, - }, - TextureBuiltin { - method_id: LiveId, - tex_type: TextureType, - texture_expr: String, - args: Vec, - }, -} - -#[derive(Debug, PartialEq, Clone)] -pub enum ShaderType { - None, - IoSelf(ScriptObject), - PodType(ScriptPodType), - Pod(ScriptPodType), - PodPtr(ScriptPodType), // Pointer to pod type (used for uniform buffers in Metal) - Texture(TextureType), // Texture type for method calls like .size() - Id(LiveId), - AbstractInt, - AbstractFloat, - Range { - start: String, - end: String, - ty: ScriptPodType, - }, - Error(ScriptValue), - /// A script scope object that we're accessing properties from. - /// Properties are flattened into ScopeUniforms. - ScopeObject(ScriptObject), - /// A uniform buffer defined in the script scope (e.g., `let buf = shader.uniform_buffer(...)`) - /// Contains the uniform buffer object and its pod type. - ScopeUniformBuffer { - obj: ScriptObject, - pod_ty: ScriptPodType, - }, - /// A texture defined in the script scope (e.g., `let tex = shader.texture_2d(float)`) - /// Contains the texture object and its type. - ScopeTexture { - obj: ScriptObject, - tex_type: TextureType, - shader_name: LiveId, - }, -} - -impl ShaderType { - pub fn make_concrete(&self, builtins: &ScriptPodBuiltins) -> Option { - match self { - Self::Pod(ty) => Some(*ty), - Self::PodPtr(ty) => Some(*ty), - Self::Texture(_) => None, // Textures don't have a concrete pod type - Self::ScopeTexture { .. } => None, // Scope textures don't have a concrete pod type - Self::Id(_id) => None, - Self::None => None, - Self::IoSelf(_) => None, - Self::ScopeObject(_) => None, // Scope objects don't have a concrete pod type - Self::ScopeUniformBuffer { pod_ty, .. } => Some(*pod_ty), - Self::PodType(_) => None, - Self::AbstractInt => Some(builtins.pod_i32), - Self::AbstractFloat => Some(builtins.pod_f32), - Self::Range { ty, .. } => Some(*ty), - Self::Error(_e) => None, - } - } -} - -#[derive(Debug)] -pub enum ShaderScopeItem { - IoSelf(ScriptObject), - ScopeObject(ScriptObject), - Param { ty: ScriptPodType, shadow: usize }, - Let { ty: ScriptPodType, shadow: usize }, - Var { ty: ScriptPodType, shadow: usize }, - PodType { ty: ScriptPodType, shadow: usize }, -} - -impl ShaderScopeItem { - pub fn ty(&self) -> ScriptPodType { - match self { - Self::IoSelf(_) => ScriptPodType::VOID, - Self::ScopeObject(_) => ScriptPodType::VOID, - Self::Param { ty, .. } => *ty, - Self::Let { ty, .. } => *ty, - Self::Var { ty, .. } => *ty, - Self::PodType { ty, .. } => *ty, - } - } - - pub fn shadow(&self) -> usize { - match self { - Self::IoSelf(_) => 0, - Self::ScopeObject(_) => 0, - Self::Param { shadow, .. } => *shadow, - Self::Let { shadow, .. } => *shadow, - Self::Var { shadow, .. } => *shadow, - Self::PodType { shadow, .. } => *shadow, - } - } -} - -#[derive(Default)] -pub struct ShaderScope { - pub shader_scope: Vec>, -} - -#[derive(Default)] -pub struct ShaderFnCompiler { - pub out: String, - pub stack: ShaderStack, - pub script_scope: ScriptObject, - pub shader_scope: ShaderScope, - pub mes: Vec, - pub trap: ScriptTrapInner, - pub debug: bool, - /// Skip the next POP_TO_ME opcode - used when closing an if that had a return - pub skip_next_pop_to_me: bool, -} - -#[derive(Default)] -pub struct ShaderStack { - pub(crate) stack_limit: usize, - pub(crate) types: Vec, - pub(crate) strings: Vec, - pub(crate) free: Vec, -} - -macro_rules! push_fmt { - ($self:ident, $ty:expr, $fmt_str:literal, $($args:expr),*) => {{ - let s = free_fmt!($self, $fmt_str, $($args),*); - $self.stack.push($self.trap.pass(), $ty, s); - }}; -} - -macro_rules! free_fmt { - ($self:ident, $fmt_str:literal, $($args:expr),*) => {{ - let mut s = $self.stack.new_string(); - write!(s, $fmt_str, $($args),*).ok(); - s - }}; -} - -impl ShaderScope { - pub fn enter_scope(&mut self) { - self.shader_scope.push(Default::default()); - } - - pub fn exit_scope(&mut self) { - self.shader_scope.pop(); - } - - pub fn find_var(&self, id: LiveId) -> Option<(&ShaderScopeItem, usize)> { - for scope in self.shader_scope.iter().rev() { - if let Some(item) = scope.get(&id) { - return Some((item, item.shadow())); - } - } - None - } - - /// Collect all variable names in scope for suggestions - pub fn all_var_names(&self) -> Vec { - let mut names = Vec::new(); - for scope in self.shader_scope.iter() { - for key in scope.keys() { - if !names.contains(key) { - names.push(*key); - } - } - } - names - } - - pub fn define_io_self(&mut self, sself: ScriptObject) { - let scope = self.shader_scope.last_mut().unwrap(); - scope.insert(id!(self), ShaderScopeItem::IoSelf(sself)); - } - - pub fn define_scope_object(&mut self, sself: ScriptObject) { - let scope = self.shader_scope.last_mut().unwrap(); - scope.insert(id!(self), ShaderScopeItem::ScopeObject(sself)); - } - - pub fn define_var(&mut self, id: LiveId, ty: ScriptPodType) -> usize { - let scope = self.shader_scope.last_mut().unwrap(); - if let Some(item) = scope.get_mut(&id) { - let shadow = item.shadow() + 1; - *item = ShaderScopeItem::Var { ty, shadow }; - shadow - } else { - scope.insert(id, ShaderScopeItem::Var { ty, shadow: 0 }); - 0 - } - } - - pub fn define_let(&mut self, id: LiveId, ty: ScriptPodType) -> usize { - let scope = self.shader_scope.last_mut().unwrap(); - if let Some(item) = scope.get_mut(&id) { - let shadow = item.shadow() + 1; - *item = ShaderScopeItem::Let { ty, shadow }; - shadow - } else { - scope.insert(id, ShaderScopeItem::Let { ty, shadow: 0 }); - 0 - } - } - - pub fn define_param(&mut self, id: LiveId, ty: ScriptPodType) -> usize { - let scope = self.shader_scope.last_mut().unwrap(); - if let Some(item) = scope.get_mut(&id) { - let shadow = item.shadow() + 1; - *item = ShaderScopeItem::Param { ty, shadow }; - shadow - } else { - scope.insert(id, ShaderScopeItem::Param { ty, shadow: 0 }); - 0 - } - } - - pub fn define_pod_type(&mut self, id: LiveId, ty: ScriptPodType) { - let scope = self.shader_scope.last_mut().unwrap(); - if let Some(item) = scope.get_mut(&id) { - let shadow = item.shadow() + 1; - *item = ShaderScopeItem::PodType { ty, shadow }; - } else { - scope.insert(id, ShaderScopeItem::PodType { ty, shadow: 0 }); - } - } -} - -impl ShaderStack { - pub fn pop(&mut self, trap: ScriptTrap) -> (ShaderType, String) { - if let Some(s) = self.types.pop() { - return (s, self.strings.pop().unwrap()); - } else { - script_err_stack!(trap, "shader stack underflow"); - (ShaderType::Error(NIL), String::new()) - } - } - - pub fn peek(&self, trap: ScriptTrap) -> (&ShaderType, &String) { - if let Some(ty) = self.types.last() { - return (ty, self.strings.last().unwrap()); - } else { - script_err_stack!(trap, "shader stack underflow"); - static EMPTY: (ShaderType, String) = (ShaderType::None, String::new()); - (&EMPTY.0, &EMPTY.1) - } - } - - pub fn push(&mut self, trap: ScriptTrap, ty: ShaderType, s: String) { - if self.types.len() > self.stack_limit { - script_err_stack!(trap, "shader stack overflow"); - } else { - self.types.push(ty); - self.strings.push(s); - } - } - - pub fn new_string(&mut self) -> String { - if let Some(s) = self.free.pop() { - s - } else { - String::new() - } - } - - pub fn free_string(&mut self, s: String) { - let mut s = s; - s.clear(); - self.free.push(s); - } -} - -impl ShaderFnCompiler { - fn shader_math_const_value(id: LiveId) -> Option { - match id { - id!(PI) => Some(3.141592653589793), - id!(E) => Some(2.718281828459045), - id!(LN2) => Some(0.6931471805599453), - id!(LN10) => Some(2.302585092994046), - id!(LOG2E) => Some(1.4426950408889634), - id!(LOG10E) => Some(0.4342944819032518), - id!(SQRT1_2) => Some(0.70710678118654757), - id!(TORAD) => Some(0.017453292519943295), - id!(GOLDEN) => Some(1.618033988749895), - _ => None, - } - } - - pub fn new(script_scope: ScriptObject) -> Self { - ShaderFnCompiler { - script_scope, - stack: ShaderStack { - stack_limit: 1000000, - ..Default::default() - }, - mes: vec![], - shader_scope: ShaderScope { - shader_scope: vec![Default::default()], - }, - ..Default::default() - } - } - - pub fn compile_fn( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - fnip: ScriptIp, - ) -> ScriptPodType { - //output.backend = ShaderBackend::Wgsl; - output.backend.register_ids(); - - self.mes.push(ShaderMe::FnBody { - ret: None, - escaped: false, - stack_depth: self.stack.types.len(), - }); - // alright lets go trace the opcodes - self.trap.ip = fnip; - - // Calculate function end position from the FN_BODY_DYN opcode that precedes the function body - // fnip.index points to the first opcode AFTER FN_BODY_DYN - // FN_BODY_DYN's opargs contains the jump offset from its position to the end of the function - let fn_end_index = { - let bodies = vm.bx.code.bodies.borrow(); - let body = &bodies[self.trap.ip.body as usize]; - let fn_body_opcode = body.parser.opcodes[(fnip.index - 1) as usize]; - if let Some((_opcode, args)) = fn_body_opcode.as_opcode() { - (fnip.index - 1) + args.to_u32() - } else { - // Fallback to opcodes.len() if we can't find FN_BODY_DYN - body.parser.opcodes.len() as u32 - } - }; - - while self.trap.ip.index < fn_end_index { - // Re-borrow bodies at each iteration to allow mutable vm access in method calls - let opcode = { - let bodies = vm.bx.code.bodies.borrow(); - let body = &bodies[self.trap.ip.body as usize]; - body.parser.opcodes[self.trap.ip.index as usize] - }; - - if self.skip_next_pop_to_me { - let next_is_pop_to_me = matches!(opcode.as_opcode(), Some((Opcode::POP_TO_ME, _))); - if !next_is_pop_to_me { - self.skip_next_pop_to_me = false; - } - } - - // Skip processing when in unreachable code (after a return in current branch) - // But still need to process control flow opcodes to maintain structure - if self.is_unreachable() { - if let Some((op, args)) = opcode.as_opcode() { - // Only process control flow opcodes when unreachable - match op { - Opcode::IF_TEST => self.handle_if_test_unreachable(args), - // IF_ELSE is special: it transitions to the else branch which IS reachable - // (if the parent scope is reachable). Check if parent scope is unreachable. - Opcode::IF_ELSE => { - if self.is_parent_scope_unreachable() { - self.handle_if_else_unreachable(args); - } else { - self.handle_if_else(vm, output, args); - } - } - _ => {} - } - } - self.trap.goto_next(); - self.handle_if_else_phi_unreachable(); - } else { - // A short-circuit RHS ends at the current IP, so resolve it before - // the next opcode/immediate consumes the stack value. - self.handle_logic_phi(vm, output); - if let Some((opcode, args)) = opcode.as_opcode() { - self.opcode(vm, output, opcode, args); - self.trap.goto_next(); - self.handle_logic_phi(vm, output); - self.handle_if_else_phi(vm, output); - } else { - // id or immediate value - self.push_immediate(opcode, &vm.bx.code.builtins.pod, &output.backend); - self.trap.goto_next(); - self.handle_logic_phi(vm, output); - self.handle_if_else_phi(vm, output); - } - } - // alright lets see if we have a trap, ifso we can log it - if let Some(err) = self.trap.err.borrow_mut().pop_front() { - output.has_errors = true; - if let Some(ptr) = err.value.as_err() { - if let Some(loc2) = vm.bx.code.ip_to_loc(ptr.ip) { - log_with_level( - &loc2.file, - loc2.line, - loc2.col, - loc2.line, - loc2.col, - format!("{} ({}:{})", err.message, err.origin_file, err.origin_line), - LogLevel::Error, - ); - } - } - } - // The trap handling for Return is no longer needed since we use fn_end_index - // to determine when to stop. The trap may still be set by handle_return but - // we ignore it and continue processing to properly close all control structures. - self.trap.on.take(); - } - let value = self.mes.pop(); - if let Some(ShaderMe::FnBody { ret, .. }) = value { - return ret.unwrap_or(vm.bx.code.builtins.pod.pod_void); - } - panic!("Unexpected ME at end {:?}", value) - } - - pub(crate) fn pop_resolved( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - ) -> (ShaderType, String) { - let (ty, s) = self.stack.pop(self.trap.pass()); - // if ty is an id, look it up - match ty { - ShaderType::Id(id) => { - // First, look it up on our shader scope (local variables) - if let Some((sc, shadow)) = self.shader_scope.find_var(id) { - let mut s2 = self.stack.new_string(); - if let ShaderScopeItem::IoSelf(obj) = sc { - return (ShaderType::IoSelf(*obj), s2); - } - if let ShaderScopeItem::ScopeObject(obj) = sc { - // `self` is a ScopeObject - return it for field access handling - return (ShaderType::ScopeObject(*obj), s2); - } - let scoped_name = match sc { - ShaderScopeItem::Param { .. } => output.backend.map_param_name(id, shadow), - ShaderScopeItem::Let { .. } | ShaderScopeItem::Var { .. } => { - output.backend.map_local_name(id, shadow) - } - ShaderScopeItem::PodType { .. } => { - output.backend.map_local_name(id, shadow) - } - ShaderScopeItem::IoSelf(_) | ShaderScopeItem::ScopeObject(_) => { - String::new() - } - }; - write!(s2, "{}", scoped_name).ok(); - self.stack.free_string(s); - return (ShaderType::Pod(sc.ty()), s2); - } - - // Not found in shader scope - try script scope for scope uniforms - let value = vm - .bx - .heap - .scope_value(self.script_scope, id.into(), self.trap.pass()); - if !value.is_nil() && self.trap.err.borrow().is_empty() { - // Check if this is a shader_io type - if let Some(value_obj) = value.as_object() { - if let Some(io_type) = vm.bx.heap.as_shader_io(value_obj) { - // Uniform buffers from scope are supported - if io_type == SHADER_IO_UNIFORM_BUFFER { - // Get the pod type from the prototype - let proto_value = vm.bx.heap.proto(value_obj); - if let Some(pod_ty) = vm.bx.heap.pod_type(proto_value) { - self.stack.free_string(s); - return ( - ShaderType::ScopeUniformBuffer { - obj: value_obj, - pod_ty, - }, - self.stack.new_string(), - ); - } else if let Some(pod_ty) = proto_value.as_pod_type() { - self.stack.free_string(s); - return ( - ShaderType::ScopeUniformBuffer { - obj: value_obj, - pod_ty, - }, - self.stack.new_string(), - ); - } - } - // Textures from scope are supported - let tex_type = match io_type { - SHADER_IO_TEXTURE_1D => Some(TextureType::Texture1d), - SHADER_IO_TEXTURE_1D_ARRAY => Some(TextureType::Texture1dArray), - SHADER_IO_TEXTURE_2D => Some(TextureType::Texture2d), - SHADER_IO_TEXTURE_2D_ARRAY => Some(TextureType::Texture2dArray), - SHADER_IO_TEXTURE_3D => Some(TextureType::Texture3d), - SHADER_IO_TEXTURE_3D_ARRAY => Some(TextureType::Texture3dArray), - SHADER_IO_TEXTURE_CUBE => Some(TextureType::TextureCube), - SHADER_IO_TEXTURE_CUBE_ARRAY => Some(TextureType::TextureCubeArray), - SHADER_IO_TEXTURE_DEPTH => Some(TextureType::TextureDepth), - SHADER_IO_TEXTURE_DEPTH_ARRAY => { - Some(TextureType::TextureDepthArray) - } - SHADER_IO_TEXTURE_VIDEO => Some(TextureType::TextureVideo), - _ => None, - }; - if let Some(tex_type) = tex_type { - // Check if we already have this scope texture registered - let existing = - output.scope_textures.iter().find(|st| st.obj == value_obj); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - // Generate unique name for this scope texture - let shader_name = - self.generate_scope_texture_name(output, id, value_obj); - - // Add to scope_textures for runtime tracking - output.scope_textures.push(ScopeTextureSource { - obj: value_obj, - tex_type, - shader_name, - }); - - // Add to IO list as Texture - if !output.io.iter().any(|io| { - io.name == shader_name - && matches!(io.kind, ShaderIoKind::Texture(_)) - }) { - output.io.push(ShaderIo { - kind: ShaderIoKind::Texture(tex_type), - name: shader_name, - ty: ScriptPodType::VOID, // Textures don't have a pod type - buffer_index: None, - }); - } - - shader_name - }; - - // Generate the texture expression with proper prefix - let mut s2 = self.stack.new_string(); - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, io_type); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let mapped_name = output.backend.map_io_name(shader_name); - write!(s2, "{}{}", prefix, mapped_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s2, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s2, "{}", full).ok(), - }; - - self.stack.free_string(s); - return ( - ShaderType::ScopeTexture { - obj: value_obj, - tex_type, - shader_name, - }, - s2, - ); - } - // Other shader_io types are not supported in scope - script_err_shader!(self.trap, "opcode not supported"); - self.stack.free_string(s); - return (ShaderType::Error(NIL), self.stack.new_string()); - } - // Check if this is an object we can walk for properties - // Return ScopeObject so handle_field can process property access - self.stack.free_string(s); - return (ShaderType::ScopeObject(value_obj), self.stack.new_string()); - } - - // Inline built-in math constants directly as literals. - // This avoids routing constants (e.g. PI) through scope uniform buffers. - if let Some(c) = Self::shader_math_const_value(id) { - let mut s2 = self.stack.new_string(); - write_shader_float(&mut s2, c); - self.stack.free_string(s); - return (ShaderType::Pod(vm.bx.code.builtins.pod.pod_f32), s2); - } - - // It's a direct value - add as scope uniform - if let Some(pod_ty) = self.get_scope_value_pod_type(vm, value) { - // Check if we already have this scope uniform - let existing = output - .scope_uniforms - .iter() - .find(|su| su.source_obj == self.script_scope && su.key == id); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - // Generate unique name if there's a collision (use script_scope as source obj) - let shader_name = - self.generate_scope_uniform_name(output, id, self.script_scope); - output.scope_uniforms.push(ScopeUniformSource { - source_obj: self.script_scope, - key: id, - shader_name, - ty: pod_ty, - }); - // Also add to IO list - if !output.io.iter().any(|io| { - io.name == shader_name - && matches!(io.kind, ShaderIoKind::ScopeUniform) - }) { - vm.bx.heap.pod_type_name_if_not_set(pod_ty, shader_name); - output.io.push(ShaderIo { - kind: ShaderIoKind::ScopeUniform, - name: shader_name, - ty: pod_ty, - buffer_index: None, - }); - } - shader_name - }; - - let mut s2 = self.stack.new_string(); - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, SHADER_IO_SCOPE_UNIFORM); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let mapped_name = output.backend.map_io_name(shader_name); - write!(s2, "{}{}", prefix, mapped_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s2, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s2, "{}", full).ok(), - }; - self.stack.free_string(s); - return (ShaderType::Pod(pod_ty), s2); - } - } - - // Clear any error from scope_value lookup failure - self.trap.err.take(); - script_err_not_found!( - self.trap, - "shader variable {:?} not found{}", - id, - suggest_from_live_ids(id, &self.shader_scope.all_var_names()) - ); - self.stack.free_string(s); - return (ShaderType::Error(NIL), self.stack.new_string()); - } - _ => (ty, s), - } - } - - /// Get the pod type from a scope value, if it's a supported type - pub(crate) fn get_scope_value_pod_type( - &self, - vm: &ScriptVm, - value: ScriptValue, - ) -> Option { - // Check if it's a primitive type (f32, f64, bool, etc.) - if let Some(pod_ty) = vm.bx.code.builtins.pod.value_to_exact_type(value) { - return Some(pod_ty); - } - // Check if it's a color - colors map to vec4f - if value.is_color() { - return Some(vm.bx.code.builtins.pod.pod_vec4f); - } - // Check if it's a pod instance - if let Some(pod) = value.as_pod() { - let pod = &vm.bx.heap.pods[pod]; - return Some(pod.ty); - } - None - } - - /// Generate a unique name for a scope uniform, handling collisions. - /// Uses the source object's index to create unique names when there are collisions. - pub(crate) fn generate_scope_uniform_name( - &self, - output: &ShaderOutput, - base_name: LiveId, - source_obj: ScriptObject, - ) -> LiveId { - // First, ensure base_name is actually in the LUT. If not, use a default. - let base_name_str = base_name.as_string(|s| s.map(|s| s.to_string())); - let base_name_str = base_name_str.unwrap_or_else(|| "scope_uni".to_string()); - - // Re-register the base name to ensure it's in the LUT - let base_name = - LiveId::from_str_with_lut(&base_name_str).unwrap_or_else(|_| id!(scope_uni)); - - // Check if name is already used - let name_used = output.io.iter().any(|io| io.name == base_name) - || output - .scope_uniforms - .iter() - .any(|su| su.shader_name == base_name); - - if !name_used { - return base_name; - } - - // Name collision - use the object index to create a unique name - // Format: base_name_objN where N is the object index - // Use from_str_with_lut to register the name in the LiveId lookup table - let unique_name_str = format!("{}_obj{}", base_name_str, source_obj.index); - let unique_name = LiveId::from_str_with_lut(&unique_name_str) - .unwrap_or_else(|_| LiveId::from_str(&unique_name_str)); - - // Check if this unique name is also used (very unlikely but possible) - let unique_name_used = output.io.iter().any(|io| io.name == unique_name) - || output - .scope_uniforms - .iter() - .any(|su| su.shader_name == unique_name); - - if !unique_name_used { - return unique_name; - } - - // Fallback: add counter suffix - for i in 1..100 { - let new_name_str = format!("{}_obj{}_{}", base_name_str, source_obj.index, i); - let new_name = LiveId::from_str_with_lut(&new_name_str) - .unwrap_or_else(|_| LiveId::from_str(&new_name_str)); - let new_name_used = output.io.iter().any(|io| io.name == new_name) - || output - .scope_uniforms - .iter() - .any(|su| su.shader_name == new_name); - if !new_name_used { - return new_name; - } - } - - // Final fallback - should never reach here - unique_name - } - - /// Generate names for a scope uniform buffer. - /// These are uniform buffers defined in the script scope, e.g., `let buf = shader.uniform_buffer(...)` - /// Returns (shader_name, struct_type_name): - /// - shader_name: identifier used in shader code, e.g., `scopebuf_{obj_index}` - /// - struct_type_name: the struct type name, e.g., `IoScopeUniformBuf{obj_index}` - pub(crate) fn generate_scope_uniform_buffer_names( - &self, - output: &ShaderOutput, - obj: ScriptObject, - ) -> (LiveId, LiveId) { - // Generate the shader identifier name: scopebuf_{index} - let shader_name_str = format!("scopebuf_{}", obj.index); - let shader_name = LiveId::from_str_with_lut(&shader_name_str) - .unwrap_or_else(|_| LiveId::from_str(&shader_name_str)); - - // Generate the struct type name: IoScopeUniformBuf{index} - let struct_name_str = format!("IoScopeUniformBuf{}", obj.index); - let struct_name = LiveId::from_str_with_lut(&struct_name_str) - .unwrap_or_else(|_| LiveId::from_str(&struct_name_str)); - - // Check if shader name is already used (shouldn't happen since obj.index is unique, but just in case) - let name_used = output.io.iter().any(|io| io.name == shader_name) - || output - .scope_uniform_buffers - .iter() - .any(|sub| sub.shader_name == shader_name); - - if !name_used { - return (shader_name, struct_name); - } - - // Name collision - add counter suffix - for i in 0..100 { - let new_shader_name_str = format!("scopebuf_{}_{}", obj.index, i); - let new_shader_name = LiveId::from_str_with_lut(&new_shader_name_str) - .unwrap_or_else(|_| LiveId::from_str(&new_shader_name_str)); - let new_struct_name_str = format!("IoScopeUniformBuf{}_{}", obj.index, i); - let new_struct_name = LiveId::from_str_with_lut(&new_struct_name_str) - .unwrap_or_else(|_| LiveId::from_str(&new_struct_name_str)); - - let new_name_used = output.io.iter().any(|io| io.name == new_shader_name) - || output - .scope_uniform_buffers - .iter() - .any(|sub| sub.shader_name == new_shader_name); - if !new_name_used { - return (new_shader_name, new_struct_name); - } - } - - // Final fallback - should never reach here - (shader_name, struct_name) - } - - /// Generate a unique name for a scope texture. - /// These are textures defined in the script scope, e.g., `let tex = shader.texture_2d(float)` - pub(crate) fn generate_scope_texture_name( - &self, - output: &ShaderOutput, - base_name: LiveId, - obj: ScriptObject, - ) -> LiveId { - // First, ensure base_name is actually in the LUT. If not, use a default. - let base_name_str = base_name.as_string(|s| s.map(|s| s.to_string())); - let base_name_str = base_name_str.unwrap_or_else(|| format!("scope_tex_{}", obj.index)); - - // Re-register the base name to ensure it's in the LUT - let base_name = - LiveId::from_str_with_lut(&base_name_str).unwrap_or_else(|_| id!(scope_tex)); - - // Check if name is already used - let name_used = output - .io - .iter() - .any(|io| io.name == base_name && matches!(io.kind, ShaderIoKind::Texture(_))) - || output - .scope_textures - .iter() - .any(|st| st.shader_name == base_name); - - if !name_used { - return base_name; - } - - // Name collision - use the object index to create a unique name - let unique_name_str = format!("{}_obj{}", base_name_str, obj.index); - let unique_name = LiveId::from_str_with_lut(&unique_name_str) - .unwrap_or_else(|_| LiveId::from_str(&unique_name_str)); - - // Check if this unique name is also used - let unique_name_used = output - .io - .iter() - .any(|io| io.name == unique_name && matches!(io.kind, ShaderIoKind::Texture(_))) - || output - .scope_textures - .iter() - .any(|st| st.shader_name == unique_name); - - if !unique_name_used { - return unique_name; - } - - // Fallback: add counter suffix - for i in 1..100 { - let new_name_str = format!("{}_obj{}_{}", base_name_str, obj.index, i); - let new_name = LiveId::from_str_with_lut(&new_name_str) - .unwrap_or_else(|_| LiveId::from_str(&new_name_str)); - let new_name_used = output - .io - .iter() - .any(|io| io.name == new_name && matches!(io.kind, ShaderIoKind::Texture(_))) - || output - .scope_textures - .iter() - .any(|st| st.shader_name == new_name); - if !new_name_used { - return new_name; - } - } - - // Final fallback - unique_name - } - - fn push_immediate( - &mut self, - value: ScriptValue, - builtins: &ScriptPodBuiltins, - backend: &ShaderBackend, - ) { - if let Some(v) = value.as_f64() { - // abstract int or float - let mut s = self.stack.new_string(); - write_shader_float(&mut s, v); - return self - .stack - .push(self.trap.pass(), ShaderType::AbstractFloat, s); - } - if let Some(v) = value.as_u40() { - return push_fmt!(self, ShaderType::AbstractInt, "{}", v); - } - if let Some(id) = value.as_id() { - let mut s = self.stack.new_string(); - if let Some((sc, shadow)) = self.shader_scope.find_var(id) { - let mapped = match sc { - ShaderScopeItem::Param { .. } => backend.map_param_name(id, shadow), - ShaderScopeItem::Let { .. } - | ShaderScopeItem::Var { .. } - | ShaderScopeItem::PodType { .. } => backend.map_local_name(id, shadow), - ShaderScopeItem::IoSelf(_) | ShaderScopeItem::ScopeObject(_) => { - format!("{}", id) - } - }; - write!(s, "{}", mapped).ok(); - } else { - write!(s, "{}", id).ok(); - } - return self.stack.push(self.trap.pass(), ShaderType::Id(id), s); - } - if let Some(v) = value.as_f32() { - let mut s = self.stack.new_string(); - write_shader_float(&mut s, v as f64); - match backend { - ShaderBackend::Rust => s.push_str("f32"), - _ => s.push('f'), - } - return self - .stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_f32), s); - } - if let Some(v) = value.as_f16() { - let mut s = self.stack.new_string(); - write_shader_float(&mut s, v as f64); - match backend { - ShaderBackend::Rust => s.push_str("f32"), // f16 maps to f32 in Rust - _ => s.push('h'), - } - return self - .stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_f16), s); - } - if let Some(v) = value.as_u32() { - match backend { - ShaderBackend::Rust => { - return push_fmt!(self, ShaderType::Pod(builtins.pod_u32), "{}u32", v) - } - _ => return push_fmt!(self, ShaderType::Pod(builtins.pod_u32), "{}u", v), - } - } - if let Some(v) = value.as_i32() { - match backend { - ShaderBackend::Rust => { - return push_fmt!(self, ShaderType::Pod(builtins.pod_i32), "{}i32", v) - } - _ => return push_fmt!(self, ShaderType::Pod(builtins.pod_i32), "{}i", v), - } - } - if let Some(v) = value.as_bool() { - return push_fmt!(self, ShaderType::Pod(builtins.pod_bool), "{}", v); - } - if let Some(v) = value.as_color() { - let v = Vec4f::from_u32(v); - let name = backend.map_pod_name(id!(vec4f)); - let mut s = self.stack.new_string(); - write!(s, "{}(", name).ok(); - write_shader_float(&mut s, v.x as f64); - s.push(','); - write_shader_float(&mut s, v.y as f64); - s.push(','); - write_shader_float(&mut s, v.z as f64); - s.push(','); - write_shader_float(&mut s, v.w as f64); - s.push(')'); - return self - .stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_vec4f), s); - } - script_err_shader!(self.trap, "no matching shader type"); - } - - pub(crate) fn ensure_struct_name( - &self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - pod_ty: ScriptPodType, - used_name: LiveId, - ) -> LiveId { - // Always insert struct types into output.structs so they get defined in shader output - if let ScriptPodTy::Struct { .. } = vm.bx.heap.pod_type_ref(pod_ty).ty { - output.structs.insert(pod_ty); - } - - if let Some(name) = vm.bx.heap.pod_type_name(pod_ty) { - let alias_ok = (name == id!(f32) && used_name == id!(float)) - || (name == id!(u32) && used_name == id!(uint)) - || (name == id!(i32) && used_name == id!(int)); - if name != used_name - && !alias_ok - && used_name != id!(self) - && used_name != id!(vec2) - && used_name != id!(vec3) - && used_name != id!(vec4) - { - script_err_inconsistent!(self.trap, "struct name not consistent"); - } - return name; - } - vm.bx.heap.pod_type_name_set(pod_ty, used_name); - used_name - } - - fn opcode( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opcode: Opcode, - opargs: OpcodeArgs, - ) { - match opcode { - // Arithmetic - Opcode::NOT => self.handle_not(vm, output, opargs), - Opcode::NEG => self.handle_neg(vm, output, opargs, "-"), - Opcode::MUL => self.handle_arithmetic(vm, output, opargs, "*", false), - Opcode::DIV => self.handle_arithmetic(vm, output, opargs, "/", false), - Opcode::MOD => self.handle_arithmetic(vm, output, opargs, "%", false), - Opcode::ADD => self.handle_arithmetic(vm, output, opargs, "+", false), - Opcode::SUB => self.handle_arithmetic(vm, output, opargs, "-", false), - Opcode::SHL => self.handle_arithmetic(vm, output, opargs, "<<", true), - Opcode::SHR => self.handle_arithmetic(vm, output, opargs, ">>", true), - Opcode::AND => self.handle_arithmetic(vm, output, opargs, "&", true), - Opcode::OR => self.handle_arithmetic(vm, output, opargs, "|", true), - Opcode::XOR => self.handle_arithmetic(vm, output, opargs, "^", true), - - // ASSIGN - Opcode::ASSIGN => self.handle_assign(vm, output), - Opcode::ASSIGN_ADD => { - self.handle_arithmetic_assign(vm, output, opargs, "+=", false); - } - Opcode::ASSIGN_SUB => { - self.handle_arithmetic_assign(vm, output, opargs, "-=", false); - } - Opcode::ASSIGN_MUL => { - self.handle_arithmetic_assign(vm, output, opargs, "*=", false); - } - Opcode::ASSIGN_DIV => { - self.handle_arithmetic_assign(vm, output, opargs, "/=", false); - } - Opcode::ASSIGN_MOD => { - self.handle_arithmetic_assign(vm, output, opargs, "%=", false); - } - Opcode::ASSIGN_AND => { - self.handle_arithmetic_assign(vm, output, opargs, "&=", true); - } - Opcode::ASSIGN_OR => { - self.handle_arithmetic_assign(vm, output, opargs, "|=", true); - } - Opcode::ASSIGN_XOR => { - self.handle_arithmetic_assign(vm, output, opargs, "^=", true); - } - Opcode::ASSIGN_SHL => { - self.handle_arithmetic_assign(vm, output, opargs, "<<=", true); - } - Opcode::ASSIGN_SHR => { - self.handle_arithmetic_assign(vm, output, opargs, ">>=", true); - } - Opcode::ASSIGN_IFNIL => { - script_err_not_impl!(self.trap, "ASSIGN_IFNIL: null-coalescing assignment `x ??= default` not supported in shaders"); - } - // ASSIGN FIELD - Opcode::ASSIGN_FIELD => self.handle_assign_field(vm, output), - Opcode::ASSIGN_FIELD_ADD => { - self.handle_arithmetic_field_assign(vm, output, opargs, "+=", false); - } - Opcode::ASSIGN_FIELD_SUB => { - self.handle_arithmetic_field_assign(vm, output, opargs, "-=", false); - } - Opcode::ASSIGN_FIELD_MUL => { - self.handle_arithmetic_field_assign(vm, output, opargs, "*=", false); - } - Opcode::ASSIGN_FIELD_DIV => { - self.handle_arithmetic_field_assign(vm, output, opargs, "/=", false); - } - Opcode::ASSIGN_FIELD_MOD => { - self.handle_arithmetic_field_assign(vm, output, opargs, "%=", false); - } - Opcode::ASSIGN_FIELD_AND => { - self.handle_arithmetic_field_assign(vm, output, opargs, "&=", true); - } - Opcode::ASSIGN_FIELD_OR => { - self.handle_arithmetic_field_assign(vm, output, opargs, "|=", true); - } - Opcode::ASSIGN_FIELD_XOR => { - self.handle_arithmetic_field_assign(vm, output, opargs, "^=", true); - } - Opcode::ASSIGN_FIELD_SHL => { - self.handle_arithmetic_field_assign(vm, output, opargs, "<<=", true); - } - Opcode::ASSIGN_FIELD_SHR => { - self.handle_arithmetic_field_assign(vm, output, opargs, ">>=", true); - } - Opcode::ASSIGN_FIELD_IFNIL => { - script_err_not_impl!(self.trap, "ASSIGN_FIELD_IFNIL: null-coalescing field assignment `obj.x ??= default` not supported in shaders"); - } - - Opcode::ASSIGN_INDEX => self.handle_assign_index(vm, output), - Opcode::ASSIGN_INDEX_ADD => { - self.handle_arithmetic_index_assign(vm, output, opargs, "+=", false); - } - Opcode::ASSIGN_INDEX_SUB => { - self.handle_arithmetic_index_assign(vm, output, opargs, "-=", false); - } - Opcode::ASSIGN_INDEX_MUL => { - self.handle_arithmetic_index_assign(vm, output, opargs, "*=", false); - } - Opcode::ASSIGN_INDEX_DIV => { - self.handle_arithmetic_index_assign(vm, output, opargs, "/=", false); - } - Opcode::ASSIGN_INDEX_MOD => { - self.handle_arithmetic_index_assign(vm, output, opargs, "%=", false); - } - Opcode::ASSIGN_INDEX_AND => { - self.handle_arithmetic_index_assign(vm, output, opargs, "&=", true); - } - Opcode::ASSIGN_INDEX_OR => { - self.handle_arithmetic_index_assign(vm, output, opargs, "|=", true); - } - Opcode::ASSIGN_INDEX_XOR => { - self.handle_arithmetic_index_assign(vm, output, opargs, "^=", true); - } - Opcode::ASSIGN_INDEX_SHL => { - self.handle_arithmetic_index_assign(vm, output, opargs, "<<=", true); - } - Opcode::ASSIGN_INDEX_SHR => { - self.handle_arithmetic_index_assign(vm, output, opargs, ">>=", true); - } - Opcode::ASSIGN_INDEX_IFNIL => { - script_err_not_impl!(self.trap, "ASSIGN_INDEX_IFNIL: null-coalescing index assignment `arr[i] ??= default` not supported in shaders"); - } - // ASSIGN ME - Opcode::ASSIGN_ME => self.handle_assign_me(vm), - Opcode::ASSIGN_ME_VEC => { - script_err_shader!( - self.trap, - "ASSIGN_ME_VEC: vec assignment `:=` not supported in shaders" - ); - } - - Opcode::ASSIGN_ME_BEFORE | Opcode::ASSIGN_ME_AFTER => { - script_err_shader!( - self.trap, - "ASSIGN_ME_BEFORE/AFTER: `++x` / `x++` not supported in shaders, use `x += 1`" - ); - } - - Opcode::ASSIGN_ME_BEGIN => { - script_err_shader!( - self.trap, - "ASSIGN_ME_BEGIN: compound assignment not supported in shaders" - ); - } - - // CONCAT - Opcode::CONCAT => { - script_err_shader!( - self.trap, - "CONCAT: string concatenation `a + b` not supported in shaders" - ); - } - // EQUALITY - Opcode::EQ => { - self.handle_eq(vm, output, opargs, "=="); - } - Opcode::NEQ => { - self.handle_eq(vm, output, opargs, "!="); - } - - Opcode::LT => { - self.handle_eq(vm, output, opargs, "<"); - } - Opcode::GT => { - self.handle_eq(vm, output, opargs, ">"); - } - Opcode::LEQ => { - self.handle_eq(vm, output, opargs, "<="); - } - Opcode::GEQ => { - self.handle_eq(vm, output, opargs, ">="); - } - - Opcode::LOGIC_AND_TEST => { - self.handle_logic_test(vm, output, opargs, "&&"); - } - Opcode::LOGIC_OR_TEST => { - self.handle_logic_test(vm, output, opargs, "||"); - } - Opcode::NIL_OR_TEST => { - script_err_shader!( - self.trap, - "NIL_OR_TEST: null-coalescing `a |? b` not supported in shaders" - ); - } - Opcode::SHALLOW_EQ => { - script_err_shader!( - self.trap, - "SHALLOW_EQ: shallow equality `===` not supported in shaders" - ); - } - Opcode::SHALLOW_NEQ => { - script_err_shader!( - self.trap, - "SHALLOW_NEQ: shallow inequality `!==` not supported in shaders" - ); - } - // Object/Array begin - Opcode::BEGIN_PROTO => { - script_err_shader!( - self.trap, - "BEGIN_PROTO: object literal `{{...}}` not supported in shaders" - ); - } - Opcode::PROTO_INHERIT_READ => { - script_err_shader!( - self.trap, - "PROTO_INHERIT: prototype inheritance not supported in shaders" - ); - } - Opcode::PROTO_INHERIT_WRITE => { - script_err_shader!( - self.trap, - "PROTO_INHERIT: prototype inheritance not supported in shaders" - ); - } - Opcode::SCOPE_INHERIT_READ => { - script_err_shader!( - self.trap, - "SCOPE_INHERIT: scope inheritance not supported in shaders" - ); - } - Opcode::SCOPE_INHERIT_WRITE => { - script_err_shader!( - self.trap, - "SCOPE_INHERIT: scope inheritance not supported in shaders" - ); - } - Opcode::FIELD_INHERIT_READ => { - script_err_shader!( - self.trap, - "FIELD_INHERIT: field inheritance not supported in shaders" - ); - } - Opcode::FIELD_INHERIT_WRITE => { - script_err_shader!( - self.trap, - "FIELD_INHERIT: field inheritance not supported in shaders" - ); - } - Opcode::INDEX_INHERIT_READ => { - script_err_shader!( - self.trap, - "INDEX_INHERIT: index inheritance not supported in shaders" - ); - } - Opcode::INDEX_INHERIT_WRITE => { - script_err_shader!( - self.trap, - "INDEX_INHERIT: index inheritance not supported in shaders" - ); - } - Opcode::END_PROTO => { - script_err_shader!( - self.trap, - "END_PROTO: object literal `{{...}}` not supported in shaders" - ); - } - Opcode::BEGIN_BARE => { - script_err_shader!( - self.trap, - "BEGIN_BARE: bare object `{{..}}` not supported in shaders" - ); - } - Opcode::END_BARE => { - script_err_shader!(self.trap, "END_BARE: bare object not supported in shaders"); - } - Opcode::BEGIN_ARRAY => { - script_err_shader!(self.trap, "BEGIN_ARRAY: dynamic array `[...]` not supported in shaders, use fixed-size arrays"); - } - Opcode::END_ARRAY => { - script_err_shader!( - self.trap, - "END_ARRAY: dynamic array not supported in shaders" - ); - } - // Calling - Opcode::CALL_ARGS => { - self.handle_call_args(vm, output, opargs); - } - Opcode::CALL_EXEC | Opcode::METHOD_CALL_EXEC => { - self.handle_call_exec(vm, output); - } - Opcode::METHOD_CALL_ARGS => { - self.handle_method_call_args(vm, output, opargs); - } - // Fn def - Opcode::FN_ARGS => { - script_err_not_impl!( - self.trap, - "FN_ARGS: nested function definitions `fn foo() {{}}` not supported in shaders" - ); - } - Opcode::FN_LET_ARGS => { - script_err_not_impl!(self.trap, "FN_LET_ARGS: nested function definitions `let foo = fn() {{}}` not supported in shaders"); - } - Opcode::FN_ARG_DYN => { - script_err_not_impl!( - self.trap, - "FN_ARG_DYN: dynamic function arguments not supported in shaders" - ); - } - Opcode::FN_ARG_TYPED => { - script_err_not_impl!( - self.trap, - "FN_ARG_TYPED: typed function arguments not supported in shaders" - ); - } - Opcode::FN_BODY_DYN => { - script_err_not_impl!( - self.trap, - "FN_BODY_DYN: function body definition not supported in shaders" - ); - } - Opcode::FN_BODY_TYPED => { - script_err_not_impl!( - self.trap, - "FN_BODY_TYPED: typed function body not supported in shaders" - ); - } - Opcode::RETURN => self.handle_return(vm, output, opargs), - Opcode::RETURN_IF_ERR => { - script_err_shader!( - self.trap, - "RETURN_IF_ERR: error propagation `?` not supported in shaders" - ); - } - // IF - Opcode::IF_TEST => self.handle_if_test(opargs), - - Opcode::IF_ELSE => self.handle_if_else(vm, output, opargs), - // Use - Opcode::USE => { - script_err_shader!(self.trap, "USE: `use` imports not supported in shaders"); - } - // Field - Opcode::FIELD => self.handle_field(vm, output), - Opcode::FIELD_NIL => { - script_err_shader!( - self.trap, - "FIELD_NIL: optional chaining `obj?.field` not supported in shaders" - ); - } - Opcode::ME_FIELD => { - script_err_not_impl!( - self.trap, - "ME_FIELD: `me.field` access not supported in shaders" - ); - } - Opcode::PROTO_FIELD => self.handle_field(vm, output), - - Opcode::POP_TO_ME => { - self.pop_to_me(vm, output); - } - // Array index - Opcode::ARRAY_INDEX => self.handle_array_index(vm, output), - // Let - Opcode::LET_DYN => self.handle_let_dyn(vm, output, opargs), - Opcode::LET_TYPED => { - script_err_not_impl!(self.trap, "LET_TYPED: typed let `let x: Type = ...` not yet supported in shaders, use `let x = Type(...)`"); - } - Opcode::VAR_DYN => self.handle_var_dyn(vm, output, opargs), - Opcode::VAR_TYPED => { - script_err_not_impl!(self.trap, "VAR_TYPED: typed var `var x: Type = ...` not yet supported in shaders, use `var x = Type(...)`"); - } - // Tree search - Opcode::SEARCH_TREE => { - script_err_shader!( - self.trap, - "SEARCH_TREE: tree search `#identifier` not supported in shaders" - ); - } - // Log - Opcode::LOG => { - self.handle_log(vm); - } - // Me/Scope - Opcode::ME => { - script_err_shader!(self.trap, "ME: `me` keyword not supported in shaders"); - } - - Opcode::SCOPE => { - script_err_shader!(self.trap, "SCOPE: `scope` keyword not supported in shaders"); - } - // For - Opcode::FOR_1 => self.handle_for_1(vm, &output.backend), - Opcode::FOR_2 => { - script_err_shader!(self.trap, "FOR_2: `for k, v in obj` iteration not supported in shaders, use `for i in 0..n`"); - } - Opcode::FOR_3 => { - script_err_shader!(self.trap, "FOR_3: `for i, k, v in obj` iteration not supported in shaders, use `for i in 0..n`"); - } - Opcode::LOOP => self.handle_loop(), - Opcode::FOR_END => self.handle_for_end(), - Opcode::BREAK => self.handle_break(), - Opcode::BREAKIFNOT => self.handle_breakifnot(), - Opcode::CONTINUE => self.handle_continue(), - // Range - Opcode::RANGE => self.handle_range(vm), - // Is - Opcode::IS => { - script_err_shader!( - self.trap, - "IS: type check `x is Type` not supported in shaders" - ); - } - // Try / OK - Opcode::OK_TEST => { - script_err_shader!( - self.trap, - "OK_TEST: `ok {{}}` block not supported in shaders" - ); - } - Opcode::OK_END => { - script_err_shader!( - self.trap, - "OK_END: `ok {{}}` block not supported in shaders" - ); - } - Opcode::TRY_TEST => { - script_err_shader!( - self.trap, - "TRY_TEST: `try {{}}` block not supported in shaders" - ); - } - Opcode::TRY_ERR => { - script_err_shader!( - self.trap, - "TRY_ERR: `try {{}} catch {{}}` not supported in shaders" - ); - } - Opcode::TRY_OK => { - script_err_shader!( - self.trap, - "TRY_OK: `try {{}}` block not supported in shaders" - ); - } - opcode => { - script_err_shader!( - self.trap, - "unknown opcode {:?} not supported in shaders", - opcode - ); - self.trap.goto_next(); - // unknown instruction - } - } - self.maybe_pop_to_me(vm, output, opargs); - } - - pub(crate) fn pop_to_me(&mut self, vm: &ScriptVm, output: &mut ShaderOutput) { - // Skip if we just closed an if block that had a return without a value - if self.skip_next_pop_to_me { - self.skip_next_pop_to_me = false; - return; - } - if let Some(me) = self.mes.last_mut() { - match me { - ShaderMe::FnBody { stack_depth, .. } - | ShaderMe::ForLoop { stack_depth, .. } - | ShaderMe::LoopBody { stack_depth } - | ShaderMe::IfBody { stack_depth, .. } => { - if self.stack.types.len() <= *stack_depth { - return; - } - let (_ty, s) = self.stack.pop(self.trap.pass()); - self.out.push_str(&s); - self.out.push_str(";\n"); - self.stack.free_string(s); - } - ShaderMe::Pod { pod_ty: _, args } => { - let (ty, s) = self.stack.pop(self.trap.pass()); - - if let Some(last) = args.last() { - let last_was_named = last.name.is_some(); - if last_was_named { - script_err_pod!(self.trap, "mixing named and ordered fields"); - } - } - - args.push(ShaderPodArg { name: None, ty, s }); - } - ShaderMe::ArrayConstruct { args, elem_ty } => { - let (ty, s) = self.stack.pop(self.trap.pass()); - let arg_ty = if let ShaderType::Id(id) = ty { - if let Some((v, _name)) = self.shader_scope.find_var(id) { - v.ty() - } else { - script_err_not_found!( - self.trap, - "shader variable {:?} not found{}", - id, - suggest_from_live_ids(id, &self.shader_scope.all_var_names()) - ); - vm.bx.code.builtins.pod.pod_void - } - } else if let Some(ty) = ty.make_concrete(&vm.bx.code.builtins.pod) { - ty - } else { - script_err_shader!(self.trap, "no matching shader type"); - vm.bx.code.builtins.pod.pod_void - }; - - if let Some(elem_ty) = elem_ty { - if *elem_ty != arg_ty { - script_err_pod!( - self.trap, - "array element type mismatch: expected {}, got {}", - format_pod_type_name(&vm.bx.heap, *elem_ty), - format_pod_type_name(&vm.bx.heap, arg_ty) - ); - } - } else { - *elem_ty = Some(arg_ty); - } - args.push(s); - } - ShaderMe::TextureBuiltin { args, .. } => { - let (_ty, s) = self.stack.pop(self.trap.pass()); - args.push(s); - } - ShaderMe::ScriptCall { out, args, .. } => { - let (ty, s) = self.stack.pop(self.trap.pass()); - //let has_self = if let ShaderType::Pod(_) = sself{true} else {false}; - if out.len() > 0 { - out.push_str(", "); - } - // Store the ShaderType directly - we'll resolve AbstractInt/AbstractFloat - // against the function's declared parameter types later - if let ShaderType::Id(id) = &ty { - if let Some((v, _name)) = self.shader_scope.find_var(*id) { - args.push(ShaderType::Pod(v.ty())); - } else { - script_err_not_found!( - self.trap, - "shader variable {:?} not found{}", - id, - suggest_from_live_ids(*id, &self.shader_scope.all_var_names()) - ); - args.push(ty); - } - } else { - args.push(ty); - } - // Rust backend: if the argument is a nested function call that - // borrows rcx, and the call already has rcx as an argument, - // hoist the nested call into a let-binding to avoid double - // mutable borrow in the same expression. - if matches!(output.backend, ShaderBackend::Rust) - && out.contains("rcx") - && s.contains("(rcx") - { - let id = output.next_rust_tmp_id(); - let tmp = format!("_rcx_tmp{}", id); - writeln!(self.out, "let {} = {};", tmp, s).ok(); - out.push_str(&tmp); - } else { - out.push_str(&s); - } - self.stack.free_string(s); - } - ShaderMe::BuiltinCall { args, .. } | ShaderMe::PodBuiltinMethod { args, .. } => { - let (ty, s) = self.stack.pop(self.trap.pass()); - // Resolve Id to Pod type, but keep AbstractInt/AbstractFloat as-is - let resolved_ty = if let ShaderType::Id(id) = &ty { - if let Some((v, _name)) = self.shader_scope.find_var(*id) { - ShaderType::Pod(v.ty()) - } else { - script_err_not_found!( - self.trap, - "shader variable {:?} not found{}", - id, - suggest_from_live_ids(*id, &self.shader_scope.all_var_names()) - ); - ty - } - } else { - ty - }; - args.push((resolved_ty, s)); - } - _ => todo!(), - } - } - } - - pub(crate) fn maybe_pop_to_me( - &mut self, - vm: &ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - if opargs.is_pop_to_me() { - self.pop_to_me(vm, output); - } - } -} diff --git a/vendor/makepad/platform/script/src/shader_backend.rs b/vendor/makepad/platform/script/src/shader_backend.rs deleted file mode 100644 index ba35fc8..0000000 --- a/vendor/makepad/platform/script/src/shader_backend.rs +++ /dev/null @@ -1,1668 +0,0 @@ -use crate::heap::*; -use crate::mod_shader::*; -use crate::pod::*; -use crate::shader::ShaderIoKind; -use crate::shader::ShaderMode; -use crate::shader::ShaderSamplerOptions; -use crate::shader::TextureType; -use crate::value::*; -use makepad_live_id::*; -use std::collections::BTreeSet; -use std::fmt::Write; - -#[derive(Default, Debug)] -pub enum ShaderBackend { - #[default] - Metal, - Wgsl, - Hlsl, - Glsl, - Rust, -} - -#[derive(Debug, Clone)] -pub enum ShaderIoPrefix { - Prefix(&'static str), - Full(&'static str), - FullOwned(String), -} - -impl ShaderBackend { - pub fn get_shader_io_kind_and_prefix( - &self, - mode: ShaderMode, - io_type: ShaderIoType, - ) -> (ShaderIoKind, ShaderIoPrefix) { - match self { - Self::Metal => { - match mode { - ShaderMode::Vertex => match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("_io.i->"), - ), - SHADER_IO_DYN_INSTANCE => { - (ShaderIoKind::DynInstance, ShaderIoPrefix::Prefix("_io.i->")) - } - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("_io.u->")) - } - SHADER_IO_UNIFORM_BUFFER => ( - ShaderIoKind::UniformBuffer, - ShaderIoPrefix::Prefix("_io.u_"), - ), - SHADER_IO_VARYING => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("_iov.v->")) - } - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("_iov.v->_position"), - ), - SHADER_IO_VERTEX_BUFFER => ( - ShaderIoKind::VertexBuffer, - ShaderIoPrefix::Prefix("_io.vb[_iov.vid]."), - ), - SHADER_IO_FRAGMENT_OUTPUT_0 => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("")) - } - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_SCOPE_UNIFORM => ( - ShaderIoKind::ScopeUniform, - ShaderIoPrefix::Prefix("_io.su->"), - ), - - _ => panic!(), - }, - ShaderMode::Fragment => { - // Check for fragment output range first - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 - { - let index = io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0; - return ( - ShaderIoKind::FragmentOutput(index as u8), - ShaderIoPrefix::FullOwned(format!("_iof.fb->fb{}", index)), - ); - } - match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("_io.i->"), - ), - SHADER_IO_DYN_INSTANCE => { - (ShaderIoKind::DynInstance, ShaderIoPrefix::Prefix("_io.i->")) - } - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("_io.u->")) - } - SHADER_IO_UNIFORM_BUFFER => ( - ShaderIoKind::UniformBuffer, - ShaderIoPrefix::Prefix("_io.u_"), - ), - SHADER_IO_VARYING => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("_iof.v->")) - } - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("_iof.v->_position"), - ), - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix("_io."), - ), - SHADER_IO_SCOPE_UNIFORM => ( - ShaderIoKind::ScopeUniform, - ShaderIoPrefix::Prefix("_io.su->"), - ), - _ => panic!(), - } - } - _ => panic!(), - } - } - Self::Hlsl => { - match mode { - ShaderMode::Vertex => { - // Check for fragment output range first - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 - { - let index = io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0; - return ( - ShaderIoKind::FragmentOutput(index as u8), - ShaderIoPrefix::FullOwned(format!("_iofb.fb{}", index)), - ); - } - match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("_mp_iov.i."), - ), - SHADER_IO_DYN_INSTANCE => ( - ShaderIoKind::DynInstance, - ShaderIoPrefix::Prefix("_mp_iov.i."), - ), - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("u_")) - } - SHADER_IO_UNIFORM_BUFFER => { - (ShaderIoKind::UniformBuffer, ShaderIoPrefix::Prefix("u_")) - } - SHADER_IO_VARYING => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("_mp_iov.v.")) - } - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("_mp_iov.v._position"), - ), - SHADER_IO_VERTEX_BUFFER => ( - ShaderIoKind::VertexBuffer, - ShaderIoPrefix::Prefix("_mp_iov.vb."), - ), - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_SCOPE_UNIFORM => { - (ShaderIoKind::ScopeUniform, ShaderIoPrefix::Prefix("su_")) - } - _ => panic!(), - } - } - ShaderMode::Fragment => { - // Check for fragment output range first - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 - { - let index = io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0; - return ( - ShaderIoKind::FragmentOutput(index as u8), - ShaderIoPrefix::FullOwned(format!("_mp_iof.fb{}", index)), - ); - } - match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("_mp_iof.v."), - ), - SHADER_IO_DYN_INSTANCE => ( - ShaderIoKind::DynInstance, - ShaderIoPrefix::Prefix("_mp_iof.v."), - ), - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("u_")) - } - SHADER_IO_UNIFORM_BUFFER => { - (ShaderIoKind::UniformBuffer, ShaderIoPrefix::Prefix("u_")) - } - SHADER_IO_VARYING => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("_mp_iof.v.")) - } - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("_mp_iof.v._position"), - ), - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix(""), - ), - SHADER_IO_SCOPE_UNIFORM => { - (ShaderIoKind::ScopeUniform, ShaderIoPrefix::Prefix("su_")) - } - _ => panic!(), - } - } - _ => panic!(), - } - } - Self::Rust => { - // Check for fragment output range first - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 - { - let index = io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0; - return ( - ShaderIoKind::FragmentOutput(index as u8), - ShaderIoPrefix::FullOwned(format!("rcx.frag_fb{}", index)), - ); - } - match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("rcx.rustinst_"), - ), - SHADER_IO_DYN_INSTANCE => ( - ShaderIoKind::DynInstance, - ShaderIoPrefix::Prefix("rcx.dyninst_"), - ), - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("rcx.uni_")) - } - SHADER_IO_UNIFORM_BUFFER => ( - ShaderIoKind::UniformBuffer, - ShaderIoPrefix::Prefix("rcx.unibuf_"), - ), - SHADER_IO_VARYING => { - (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("rcx.var_")) - } - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("rcx.vtx_pos"), - ), - SHADER_IO_VERTEX_BUFFER => ( - ShaderIoKind::VertexBuffer, - ShaderIoPrefix::Prefix("rcx.vb_"), - ), - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix("rcx.tex_"), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix("rcx.sampler_"), - ), - SHADER_IO_SCOPE_UNIFORM => ( - ShaderIoKind::ScopeUniform, - ShaderIoPrefix::Prefix("rcx.su_"), - ), - _ => panic!(), - } - } - Self::Glsl | Self::Wgsl => { - // Check for fragment output range first - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 - { - let index = io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0; - return ( - ShaderIoKind::FragmentOutput(index as u8), - ShaderIoPrefix::FullOwned(format!("frag_fb{}", index)), - ); - } - match io_type { - SHADER_IO_RUST_INSTANCE => ( - ShaderIoKind::RustInstance, - ShaderIoPrefix::Prefix("rustinst_"), - ), - SHADER_IO_DYN_INSTANCE => ( - ShaderIoKind::DynInstance, - ShaderIoPrefix::Prefix("dyninst_"), - ), - SHADER_IO_DYN_UNIFORM => { - (ShaderIoKind::Uniform, ShaderIoPrefix::Prefix("uni_")) - } - SHADER_IO_UNIFORM_BUFFER => ( - ShaderIoKind::UniformBuffer, - ShaderIoPrefix::Prefix("unibuf_"), - ), - SHADER_IO_VARYING => (ShaderIoKind::Varying, ShaderIoPrefix::Prefix("var_")), - SHADER_IO_VERTEX_POSITION => ( - ShaderIoKind::VertexPosition, - ShaderIoPrefix::Full("vtx_pos"), - ), - SHADER_IO_VERTEX_BUFFER => { - (ShaderIoKind::VertexBuffer, ShaderIoPrefix::Prefix("vb_")) - } - SHADER_IO_TEXTURE_1D => ( - ShaderIoKind::Texture(TextureType::Texture1d), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_1D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture1dArray), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_2D => ( - ShaderIoKind::Texture(TextureType::Texture2d), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_2D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture2dArray), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_3D => ( - ShaderIoKind::Texture(TextureType::Texture3d), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_3D_ARRAY => ( - ShaderIoKind::Texture(TextureType::Texture3dArray), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_CUBE => ( - ShaderIoKind::Texture(TextureType::TextureCube), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_CUBE_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureCubeArray), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_DEPTH => ( - ShaderIoKind::Texture(TextureType::TextureDepth), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_DEPTH_ARRAY => ( - ShaderIoKind::Texture(TextureType::TextureDepthArray), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_TEXTURE_VIDEO => ( - ShaderIoKind::Texture(TextureType::TextureVideo), - ShaderIoPrefix::Prefix("tex_"), - ), - SHADER_IO_SAMPLER => ( - ShaderIoKind::Sampler(ShaderSamplerOptions::default()), - ShaderIoPrefix::Prefix("sampler_"), - ), - SHADER_IO_SCOPE_UNIFORM => { - (ShaderIoKind::ScopeUniform, ShaderIoPrefix::Prefix("su_")) - } - _ => panic!(), - } - } - } - } - - pub fn get_io_all(&self, _mode: ShaderMode) -> &'static str { - match self { - Self::Metal => "_io", - Self::Hlsl => "", - Self::Rust => "rcx", - _ => "", - } - } - - pub fn get_io_all_decl(&self, _mode: ShaderMode) -> &'static str { - match self { - Self::Metal => "thread Io &_io", - Self::Hlsl => "", - Self::Rust => "rcx: &mut RenderCx", - _ => "", - } - } - - pub fn get_io_self(&self, mode: ShaderMode) -> &'static str { - match self { - Self::Metal => match mode { - ShaderMode::Vertex => "_iov", - ShaderMode::Fragment => "_iof", - _ => "", - }, - Self::Hlsl => match mode { - ShaderMode::Vertex => "", - ShaderMode::Fragment => "", - _ => "", - }, - Self::Rust => "", - _ => "", - } - } - - pub fn get_io_self_decl(&self, mode: ShaderMode) -> &'static str { - match self { - Self::Metal => match mode { - ShaderMode::Vertex => "thread IoV &_iov", - ShaderMode::Fragment => "thread IoF &_iof", - _ => "", - }, - Self::Hlsl => match mode { - ShaderMode::Vertex => "", - ShaderMode::Fragment => "", - _ => "", - }, - Self::Rust => "", - _ => "", - } - } - - pub fn map_local_name(&self, id: LiveId, shadow: usize) -> String { - match self { - Self::Hlsl => { - if shadow > 0 { - format!("l_{}_{}", id, shadow) - } else { - format!("l_{}", id) - } - } - Self::Glsl => { - let base = if id == id!(self) { - "_self".to_string() - } else { - format!("{}", id) - }; - if shadow > 0 { - format!("l_{}_{}", base, shadow) - } else { - format!("l_{}", base) - } - } - Self::Rust => { - let base = if id == id!(self) { - "_self".to_string() - } else if id == id!(type) - || id == id!(match) - || id == id!(fn) - || id == id!(let) - || id == id!(mut) - || id == id!(ref) - || id == id!(loop) - || id == id!(move) - || id == id!(pub) - || id == id!(use) - || id == id!(mod) - || id == id!(impl) - || id == id!(where) - || id == id!(as) - || id == id!(in) - || id == id!(for) - || id == id!(if) - || id == id!(else) - || id == id!(while) - || id == id!(return) - || id == id!(break) - || id == id!(continue) - || id == id!(struct) - || id == id!(enum) - || id == id!(trait) - || id == id!(super) - || id == id!(crate) - { - format!("r#{}", id) - } else { - format!("{}", id) - }; - if shadow > 0 { - format!("{}_{}", base, shadow) - } else { - base - } - } - _ => { - if shadow > 0 { - format!("_s{}{}", shadow, id) - } else if id == id!(self) { - "_self".to_string() - } else { - format!("{}", id) - } - } - } - } - - pub fn map_param_name(&self, id: LiveId, shadow: usize) -> String { - if id == id!(self) { - // Rust and WGSL self params are pointers, so dereference for field access. - if matches!(self, Self::Rust | Self::Wgsl) { - return "(*_self)".to_string(); - } - return "_self".to_string(); - } - match self { - Self::Hlsl | Self::Glsl => { - if shadow > 0 { - format!("p_{}_{}", id, shadow) - } else { - format!("p_{}", id) - } - } - Self::Rust => self.map_local_name(id, shadow), - _ => self.map_local_name(id, shadow), - } - } - - pub fn map_function_name(&self, name: &str) -> String { - match self { - Self::Hlsl => format!("f_{}", name), - Self::Rust => name.to_string(), - _ => name.to_string(), - } - } - - pub fn map_io_name(&self, id: LiveId) -> String { - match self { - Self::Hlsl => format!("io_{}", id), - Self::Rust => format!("{}", id), - _ => format!("{}", id), - } - } - - pub fn map_field_name(&self, id: LiveId) -> String { - self.map_field_name_typed(id, true) - } - - /// Map a field name, with `is_vec_type` indicating whether the parent type is a vec - /// (where swizzle transformations apply). - pub fn map_field_name_typed(&self, id: LiveId, is_vec_type: bool) -> String { - match self { - Self::Hlsl => { - let id_str = format!("{}", id); - let len = id_str.len(); - let is_swizzle = (1..=4).contains(&len) - && id_str.bytes().all(|c| { - matches!(c, b'x' | b'y' | b'z' | b'w' | b'r' | b'g' | b'b' | b'a') - }); - if is_swizzle { - id_str - } else { - format!("f_{}", id_str) - } - } - Self::Rust => { - let id_str = format!("{}", id); - if !is_vec_type { - return id_str; - } - let len = id_str.len(); - let is_swizzle_char = - |c: u8| matches!(c, b'x' | b'y' | b'z' | b'w' | b'r' | b'g' | b'b' | b'a'); - let all_swizzle = !id_str.is_empty() && id_str.bytes().all(is_swizzle_char); - if all_swizzle && len >= 2 { - // Multi-component swizzles become method calls: .xy() not .xy - // Map rgba to xyzw - let mapped: String = id_str - .chars() - .map(|c| match c { - 'r' => 'x', - 'g' => 'y', - 'b' => 'z', - 'a' => 'w', - other => other, - }) - .collect(); - format!("{}()", mapped) - } else if all_swizzle && len == 1 { - // Single-char field access: map rgba to xyzw - match id_str.as_str() { - "r" => "x".to_string(), - "g" => "y".to_string(), - "b" => "z".to_string(), - "a" => "w".to_string(), - other => other.to_string(), - } - } else { - id_str - } - } - _ => format!("{}", id), - } - } - - /// Generate a variable declaration statement for the backend. - /// For C-style backends (Metal, HLSL, GLSL): `type_name var_name;\n` - /// For WGSL: `var var_name:type_name;\n` - pub fn write_var_decl(&self, out: &mut String, ty_name: LiveId, var_name: &str) { - match self { - Self::Metal | Self::Hlsl | Self::Glsl => { - write!(out, "{} {};\n", ty_name, var_name).ok(); - } - Self::Wgsl => { - write!(out, "var {}:{};\n", var_name, ty_name).ok(); - } - Self::Rust => { - let zero = self.zero_literal(ty_name); - write!(out, "let mut {}: {} = {};\n", var_name, ty_name, zero).ok(); - } - } - } - - /// Generate a variable declaration with zero initialization for the backend. - /// For C-style backends (Metal, HLSL, GLSL): `type_name var_name = type_name(0);\n` - /// For WGSL: `var var_name:type_name = type_name();\n` (zero-initialized) - pub fn write_var_decl_zero_init(&self, out: &mut String, ty_name: LiveId, var_name: &str) { - match self { - Self::Metal | Self::Hlsl => { - // Use constructor with zero for compound types, literal for scalars - let zero = self.zero_literal(ty_name); - write!(out, "{} {} = {};\n", ty_name, var_name, zero).ok(); - } - Self::Glsl => { - let zero = self.zero_literal(ty_name); - write!(out, "{} {} = {};\n", ty_name, var_name, zero).ok(); - } - Self::Wgsl => { - let zero = self.zero_literal(ty_name); - write!(out, "var {}:{} = {};\n", var_name, ty_name, zero).ok(); - } - Self::Rust => { - let zero = self.zero_literal(ty_name); - write!(out, "let mut {}: {} = {};\n", var_name, ty_name, zero).ok(); - } - } - } - - /// Returns the zero literal for a given backend type name. - fn zero_literal(&self, ty_name: LiveId) -> String { - match self { - Self::Metal => { - match ty_name { - // Scalars - id!(float) => "0.0".to_string(), - id!(half) => "0.0h".to_string(), - id!(uint) => "0".to_string(), - id!(int) => "0".to_string(), - id!(bool) => "false".to_string(), - // Vectors - use constructor syntax - id!(float2) - | id!(float3) - | id!(float4) - | id!(half2) - | id!(half3) - | id!(half4) - | id!(uint2) - | id!(uint3) - | id!(uint4) - | id!(int2) - | id!(int3) - | id!(int4) - | id!(bool2) - | id!(bool3) - | id!(bool4) => format!("{}(0)", ty_name), - // Matrices - use constructor syntax - id!(float2x2) - | id!(float2x3) - | id!(float2x4) - | id!(float3x2) - | id!(float3x3) - | id!(float3x4) - | id!(float4x2) - | id!(float4x3) - | id!(float4x4) => format!("{}(0.0)", ty_name), - // Default: use constructor with zero - _ => format!("{}()", ty_name), - } - } - Self::Hlsl => { - fn join_n(lit: &str, n: usize) -> String { - std::iter::repeat(lit) - .take(n) - .collect::>() - .join(", ") - } - match ty_name { - // Scalars - id!(float) => "0.0".to_string(), - id!(half) => "0.0h".to_string(), - id!(uint) => "0".to_string(), - id!(int) => "0".to_string(), - id!(bool) => "false".to_string(), - // Float/half vectors - id!(float2) => "float2(0.0, 0.0)".to_string(), - id!(float3) => "float3(0.0, 0.0, 0.0)".to_string(), - id!(float4) => "float4(0.0, 0.0, 0.0, 0.0)".to_string(), - id!(half2) => "half2(0.0h, 0.0h)".to_string(), - id!(half3) => "half3(0.0h, 0.0h, 0.0h)".to_string(), - id!(half4) => "half4(0.0h, 0.0h, 0.0h, 0.0h)".to_string(), - // Int/uint vectors - id!(uint2) => "uint2(0, 0)".to_string(), - id!(uint3) => "uint3(0, 0, 0)".to_string(), - id!(uint4) => "uint4(0, 0, 0, 0)".to_string(), - id!(int2) => "int2(0, 0)".to_string(), - id!(int3) => "int3(0, 0, 0)".to_string(), - id!(int4) => "int4(0, 0, 0, 0)".to_string(), - // Bool vectors - id!(bool2) => "bool2(false, false)".to_string(), - id!(bool3) => "bool3(false, false, false)".to_string(), - id!(bool4) => "bool4(false, false, false, false)".to_string(), - // Matrices - id!(float2x2) => format!("float2x2({})", join_n("0.0", 4)), - id!(float2x3) => format!("float2x3({})", join_n("0.0", 6)), - id!(float2x4) => format!("float2x4({})", join_n("0.0", 8)), - id!(float3x2) => format!("float3x2({})", join_n("0.0", 6)), - id!(float3x3) => format!("float3x3({})", join_n("0.0", 9)), - id!(float3x4) => format!("float3x4({})", join_n("0.0", 12)), - id!(float4x2) => format!("float4x2({})", join_n("0.0", 8)), - id!(float4x3) => format!("float4x3({})", join_n("0.0", 12)), - id!(float4x4) => format!("float4x4({})", join_n("0.0", 16)), - // Default: use constructor with no args - _ => format!("{}()", ty_name), - } - } - Self::Glsl => { - match ty_name { - // Scalars - id!(float) => "0.0".to_string(), - id!(uint) => "0u".to_string(), - id!(int) => "0".to_string(), - id!(bool) => "false".to_string(), - // Vectors - use constructor syntax - id!(vec2) | id!(vec3) | id!(vec4) => format!("{}(0.0)", ty_name), - id!(uvec2) | id!(uvec3) | id!(uvec4) => format!("{}(0u)", ty_name), - id!(ivec2) | id!(ivec3) | id!(ivec4) => format!("{}(0)", ty_name), - id!(bvec2) | id!(bvec3) | id!(bvec4) => format!("{}(false)", ty_name), - // Matrices - use constructor syntax - id!(mat2) | id!(mat3) | id!(mat4) => format!("{}(0.0)", ty_name), - // Default: use constructor with zero - _ => format!("{}(0)", ty_name), - } - } - Self::Wgsl => { - match ty_name { - // Scalars - id!(f32) => "0.0".to_string(), - id!(f16) => "0.0h".to_string(), - id!(u32) => "0u".to_string(), - id!(i32) => "0i".to_string(), - id!(bool) => "false".to_string(), - // Vectors - use constructor syntax (WGSL allows empty constructor for zero) - id!(vec2f) - | id!(vec3f) - | id!(vec4f) - | id!(vec2h) - | id!(vec3h) - | id!(vec4h) - | id!(vec2u) - | id!(vec3u) - | id!(vec4u) - | id!(vec2i) - | id!(vec3i) - | id!(vec4i) - | id!(vec2b) - | id!(vec3b) - | id!(vec4b) => format!("{}()", ty_name), - // Matrices - empty constructor for zero - id!(mat2x2f) - | id!(mat2x3f) - | id!(mat2x4f) - | id!(mat3x2f) - | id!(mat3x3f) - | id!(mat3x4f) - | id!(mat4x2f) - | id!(mat4x3f) - | id!(mat4x4f) => format!("{}()", ty_name), - // Default: use empty constructor - _ => format!("{}()", ty_name), - } - } - Self::Rust => { - match ty_name { - // Scalars - id!(f32) => "0.0f32".to_string(), - id!(f16) => "0.0f32".to_string(), // f16 maps to f32 in Rust runtime - id!(u32) => "0u32".to_string(), - id!(i32) => "0i32".to_string(), - id!(bool) => "false".to_string(), - // Vectors - use constructor functions - id!(vec2f) => "vec2(0.0, 0.0)".to_string(), - id!(vec3f) => "vec3(0.0, 0.0, 0.0)".to_string(), - id!(vec4f) => "vec4(0.0, 0.0, 0.0, 0.0)".to_string(), - // Matrices - id!(mat4x4f) => "Mat4f::default()".to_string(), - // Default: use Default trait - _ => format!("{}::default()", ty_name), - } - } - } - } - - pub fn register_ids(&self) { - match self { - Self::Metal | Self::Hlsl => { - id_lut!(float); - id_lut!(half); - id_lut!(uint); - id_lut!(int); - id_lut!(float2); - id_lut!(float3); - id_lut!(float4); - id_lut!(half2); - id_lut!(half3); - id_lut!(half4); - id_lut!(uint2); - id_lut!(uint3); - id_lut!(uint4); - id_lut!(int2); - id_lut!(int3); - id_lut!(int4); - id_lut!(bool2); - id_lut!(bool3); - id_lut!(bool4); - id_lut!(float2x2); - id_lut!(float2x3); - id_lut!(float2x4); - id_lut!(float3x2); - id_lut!(float3x3); - id_lut!(float3x4); - id_lut!(float4x2); - id_lut!(float4x3); - id_lut!(float4x4); - id_lut!(atomic_uint); - id_lut!(atomic_int); - // Packed types for Metal instance/vertex buffers - id_lut!(packed_float2); - id_lut!(packed_float3); - id_lut!(packed_float4); - id_lut!(packed_half2); - id_lut!(packed_half3); - id_lut!(packed_half4); - id_lut!(packed_uint2); - id_lut!(packed_uint3); - id_lut!(packed_uint4); - id_lut!(packed_int2); - id_lut!(packed_int3); - id_lut!(packed_int4); - id_lut!(packed_bool2); - id_lut!(packed_bool3); - id_lut!(packed_bool4); - id_lut!(packed_float2x2); - id_lut!(packed_float2x3); - id_lut!(packed_float2x4); - id_lut!(packed_float3x2); - id_lut!(packed_float3x3); - id_lut!(packed_float3x4); - id_lut!(packed_float4x2); - id_lut!(packed_float4x3); - id_lut!(packed_float4x4); - // Builtin function names - id_lut!(dfdx); - id_lut!(dfdy); - id_lut!(ddx); - id_lut!(ddy); - id_lut!(_mp_inverse); - id_lut!(rsqrt); - id_lut!(fmod); - id_lut!(frac); - id_lut!(lerp); - id_lut!(discard_fragment); - } - Self::Glsl => { - id_lut!(float); - id_lut!(uint); - id_lut!(int); - id_lut!(vec2); - id_lut!(vec3); - id_lut!(vec4); - id_lut!(uvec2); - id_lut!(uvec3); - id_lut!(uvec4); - id_lut!(ivec2); - id_lut!(ivec3); - id_lut!(ivec4); - id_lut!(bvec2); - id_lut!(bvec3); - id_lut!(bvec4); - id_lut!(mat2); - id_lut!(mat3); - id_lut!(mat4); - // Builtin function names - id_lut!(dFdx); - id_lut!(dFdy); - id_lut!(inverse); - id_lut!(inversesqrt); - id_lut!(mod); - } - Self::Wgsl => { - // Builtin function names - id_lut!(dpdx); - id_lut!(dpdy); - id_lut!(inverse); - } - Self::Rust => { - // Rust uses canonical names from makepad_math - no remapping needed - // Register builtin function names used in Rust backend - id_lut!(inverse); - id_lut!(inverseSqrt); - id_lut!(modf); - } - } - } - - pub fn map_builtin_name(&self, name_in: LiveId) -> LiveId { - match self { - Self::Metal => match name_in { - id!(dFdx) => id!(dfdx), - id!(dFdy) => id!(dfdy), - id!(inverse) => id!(_mp_inverse), - id!(inverseSqrt) => id!(rsqrt), - id!(modf) => id!(fmod), - id!(discard) => id!(discard_fragment), - x => x, - }, - Self::Hlsl => match name_in { - id!(dFdx) => id!(ddx), - id!(dFdy) => id!(ddy), - id!(inverseSqrt) => id!(rsqrt), - id!(modf) => id!(fmod), - id!(fract) => id!(frac), - id!(mix) => id!(lerp), - x => x, - }, - Self::Glsl => { - match name_in { - // GLSL uses dFdx/dFdy natively, mod is native - id!(inverseSqrt) => id!(inversesqrt), - id!(modf) => id!(mod), - id!(atan2) => id!(atan), - x => x, - } - } - Self::Wgsl => { - match name_in { - // WGSL uses dpdx/dpdy, mod is native (%) - id!(dFdx) => id!(dpdx), - id!(dFdy) => id!(dpdy), - id!(inverseSqrt) => id!(inverseSqrt), - x => x, - } - } - Self::Rust => { - match name_in { - // Rust backend maps to makepad_math::shader_runtime functions - id!(inverseSqrt) => id!(inverseSqrt), // maps to inverse_sqrt in codegen - id!(modf) => id!(modf), // maps to modf in shader_runtime - id!(dFdx) => id!(dFdx), // no-op in CPU (returns 0) - id!(dFdy) => id!(dFdy), // no-op in CPU (returns 0) - id!(discard) => id!(discard), // no-op in CPU - x => x, - } - } - } - } - - /// Map pod type names to packed versions for Metal instance buffers. - /// Packed types match CPU-side repr(C) struct alignment. - pub fn map_packed_pod_name(&self, name_in: LiveId) -> LiveId { - match self { - Self::Metal => { - match name_in { - id!(f32) => id!(float), - id!(f16) => id!(half), - id!(u32) => id!(uint), - id!(i32) => id!(int), - id!(vec2f) => id!(packed_float2), - id!(vec3f) => id!(packed_float3), - id!(vec4f) => id!(packed_float4), - id!(vec2h) => id!(packed_half2), - id!(vec3h) => id!(packed_half3), - id!(vec4h) => id!(packed_half4), - id!(vec2u) => id!(packed_uint2), - id!(vec3u) => id!(packed_uint3), - id!(vec4u) => id!(packed_uint4), - id!(vec2i) => id!(packed_int2), - id!(vec3i) => id!(packed_int3), - id!(vec4i) => id!(packed_int4), - id!(vec2b) => id!(packed_bool2), - id!(vec3b) => id!(packed_bool3), - id!(vec4b) => id!(packed_bool4), - // Metal exposes packed vector types, but not packed matrix aliases. - // Keep matrix names plain and rely on their native column layout. - id!(mat2x2f) => id!(float2x2), - id!(mat2x3f) => id!(float2x3), - id!(mat2x4f) => id!(float2x4), - id!(mat3x2f) => id!(float3x2), - id!(mat3x3f) => id!(float3x3), - id!(mat3x4f) => id!(float3x4), - id!(mat4x2f) => id!(float4x2), - id!(mat4x3f) => id!(float4x3), - id!(mat4x4f) => id!(float4x4), - x => x, - } - } - _ => self.map_pod_name(name_in), - } - } - - pub fn map_pod_name(&self, name_in: LiveId) -> LiveId { - match self { - Self::Metal | Self::Hlsl => match name_in { - id!(f32) => id!(float), - id!(f16) => id!(half), - id!(u32) => id!(uint), - id!(i32) => id!(int), - id!(vec2f) => id!(float2), - id!(vec3f) => id!(float3), - id!(vec4f) => id!(float4), - id!(vec2h) => id!(half2), - id!(vec3h) => id!(half3), - id!(vec4h) => id!(half4), - id!(vec2u) => id!(uint2), - id!(vec3u) => id!(uint3), - id!(vec4u) => id!(uint4), - id!(vec2i) => id!(int2), - id!(vec3i) => id!(int3), - id!(vec4i) => id!(int4), - id!(vec2b) => id!(bool2), - id!(vec3b) => id!(bool3), - id!(vec4b) => id!(bool4), - id!(mat2x2f) => id!(float2x2), - id!(mat2x3f) => id!(float2x3), - id!(mat2x4f) => id!(float2x4), - id!(mat3x2f) => id!(float3x2), - id!(mat3x3f) => id!(float3x3), - id!(mat3x4f) => id!(float3x4), - id!(mat4x2f) => id!(float4x2), - id!(mat4x3f) => id!(float4x3), - id!(mat4x4f) => id!(float4x4), - id!(atomic_u32) => id!(atomic_uint), - id!(atomic_i32) => id!(atomic_int), - x => x, - }, - Self::Glsl => { - match name_in { - id!(f32) => id!(float), - id!(f16) => id!(float), // no half in standard GLSL 300 es, could use mediump float - id!(u32) => id!(uint), - id!(i32) => id!(int), - id!(vec2f) => id!(vec2), - id!(vec3f) => id!(vec3), - id!(vec4f) => id!(vec4), - id!(vec2h) => id!(vec2), - id!(vec3h) => id!(vec3), - id!(vec4h) => id!(vec4), - id!(vec2u) => id!(uvec2), - id!(vec3u) => id!(uvec3), - id!(vec4u) => id!(uvec4), - id!(vec2i) => id!(ivec2), - id!(vec3i) => id!(ivec3), - id!(vec4i) => id!(ivec4), - id!(vec2b) => id!(bvec2), - id!(vec3b) => id!(bvec3), - id!(vec4b) => id!(bvec4), - id!(mat2x2f) => id!(mat2), - id!(mat3x3f) => id!(mat3), - id!(mat4x4f) => id!(mat4), - // TODO more matrices - x => x, - } - } - Self::Wgsl | Self::Rust => name_in, - } - } - - pub fn pod_struct_defs( - &self, - heap: &ScriptHeap, - root_structs: &BTreeSet, - out: &mut String, - ) { - let mut visited = BTreeSet::new(); - let mut order = Vec::new(); - - for root in root_structs { - self.pod_struct_visit(heap, *root, &mut visited, &mut order); - } - - for ty in order { - let pod_type = heap.pod_type_ref(ty); - if let ScriptPodTy::Struct { .. } = &pod_type.ty { - let mut referenced = BTreeSet::new(); - self.pod_type_def_impl(heap, ty, &mut referenced, out, false); - } - } - } - - pub fn pod_struct_defs_mixed( - &self, - heap: &ScriptHeap, - plain_root_structs: &BTreeSet, - packed_root_structs: &BTreeSet, - out: &mut String, - ) { - let mut packed_visited = BTreeSet::new(); - let mut packed_order = Vec::new(); - for root in packed_root_structs { - self.pod_struct_visit(heap, *root, &mut packed_visited, &mut packed_order); - } - - let mut plain_visited = packed_visited.clone(); - let mut plain_order = Vec::new(); - for root in plain_root_structs { - self.pod_struct_visit(heap, *root, &mut plain_visited, &mut plain_order); - } - - for ty in packed_order { - let pod_type = heap.pod_type_ref(ty); - if let ScriptPodTy::Struct { .. } = &pod_type.ty { - let mut referenced = BTreeSet::new(); - self.pod_type_def_impl(heap, ty, &mut referenced, out, true); - } - } - - for ty in plain_order { - let pod_type = heap.pod_type_ref(ty); - if let ScriptPodTy::Struct { .. } = &pod_type.ty { - let mut referenced = BTreeSet::new(); - self.pod_type_def_impl(heap, ty, &mut referenced, out, false); - } - } - } - - fn pod_struct_visit( - &self, - heap: &ScriptHeap, - ty: ScriptPodType, - visited: &mut BTreeSet, - order: &mut Vec, - ) { - if visited.contains(&ty) { - return; - } - visited.insert(ty); - - let pod_type = heap.pod_type_ref(ty); - let mut referenced = BTreeSet::new(); - let mut dummy = String::new(); - - match &pod_type.ty { - ScriptPodTy::Struct { fields, .. } => { - for field in fields { - self.pod_type_name_referenced(&field.ty, &mut referenced, &mut dummy); - } - } - ScriptPodTy::FixedArray { ty: inner, .. } - | ScriptPodTy::VariableArray { ty: inner, .. } => { - self.pod_type_name_referenced(inner, &mut referenced, &mut dummy); - } - _ => {} - } - - for ref_ty in referenced { - self.pod_struct_visit(heap, ref_ty, visited, order); - } - - order.push(ty); - } - - pub fn pod_type_def( - &self, - heap: &ScriptHeap, - pod_ty: ScriptPodType, - referenced: &mut BTreeSet, - out: &mut String, - ) { - self.pod_type_def_impl(heap, pod_ty, referenced, out, false) - } - - fn pod_type_def_impl( - &self, - heap: &ScriptHeap, - pod_ty: ScriptPodType, - referenced: &mut BTreeSet, - out: &mut String, - packed_fields: bool, - ) { - let pod_type = heap.pod_type_ref(pod_ty); - if let ScriptPodTy::Struct { fields, .. } = &pod_type.ty { - if matches!(self, Self::Rust) { - writeln!(out, "#[derive(Default, Clone, Copy)]").ok(); - writeln!(out, "#[repr(C)]").ok(); - } - if let Some(name) = pod_type.name { - writeln!(out, "struct {} {{", self.map_pod_name(name)).ok(); - } else { - writeln!(out, "struct S{} {{", pod_ty.index).ok(); - }; - for field in fields { - match self { - Self::Metal | Self::Hlsl | Self::Glsl => { - write!(out, " ").ok(); - if let ScriptPodTy::FixedArray { .. } = &field.ty.data.ty { - self.pod_type_def_metal_array( - &field.ty, - &field.name, - referenced, - out, - packed_fields, - ); - } else { - if packed_fields { - self.pod_type_name_packed_referenced(&field.ty, referenced, out); - } else { - self.pod_type_name_referenced(&field.ty, referenced, out); - } - let field_name = self.map_field_name(field.name); - writeln!(out, " {};", field_name).ok(); - } - } - Self::Wgsl => { - write!(out, " {}: ", field.name).ok(); - self.pod_type_name_referenced(&field.ty, referenced, out); - writeln!(out, ",").ok(); - } - Self::Rust => { - write!(out, " pub {}: ", field.name).ok(); - self.pod_type_name_referenced(&field.ty, referenced, out); - writeln!(out, ",").ok(); - } - } - } - match self { - Self::Metal | Self::Hlsl | Self::Glsl => { - writeln!(out, "}};").ok(); - } - Self::Wgsl => { - writeln!(out, "}}").ok(); - } - Self::Rust => { - writeln!(out, "}}").ok(); - } - } - - if matches!(self, Self::Hlsl) { - let struct_name = if let Some(name) = pod_type.name { - format!("{}", self.map_pod_name(name)) - } else { - format!("S{}", pod_ty.index) - }; - - write!(out, "{} consfn_{}(", struct_name, struct_name).ok(); - for (index, field) in fields.iter().enumerate() { - if index > 0 { - write!(out, ", ").ok(); - } - self.pod_type_name_referenced(&field.ty, referenced, out); - let field_param = self.map_param_name(field.name, 0); - write!(out, " {}", field_param).ok(); - } - writeln!(out, "){{").ok(); - writeln!(out, " {} r;", struct_name).ok(); - for field in fields { - let field_name = self.map_field_name(field.name); - let field_param = self.map_param_name(field.name, 0); - writeln!(out, " r.{0} = {1};", field_name, field_param).ok(); - } - writeln!(out, " return r;").ok(); - writeln!(out, "}}").ok(); - } - } - } - - fn pod_type_def_metal_array( - &self, - ty: &ScriptPodTypeInline, - name: &LiveId, - referenced: &mut BTreeSet, - out: &mut String, - packed: bool, - ) { - let mut dims = String::new(); - let mut curr = ty; - loop { - match &curr.data.ty { - ScriptPodTy::FixedArray { ty: inner, len, .. } => { - write!(dims, "[{}]", len).ok(); - curr = inner; - } - _ => break, - } - } - if packed { - self.pod_type_name_packed_referenced(curr, referenced, out); - } else { - self.pod_type_name_referenced(curr, referenced, out); - } - let mapped = self.map_field_name(*name); - writeln!(out, " {}{};", mapped, dims).ok(); - } - - fn pod_type_name_referenced( - &self, - ty: &ScriptPodTypeInline, - referenced: &mut BTreeSet, - out: &mut String, - ) { - match &ty.data.ty { - ScriptPodTy::Struct { .. } => { - referenced.insert(ty.self_ref); - let name = ty.data.name.unwrap(); - let name = self.map_pod_name(name); - write!(out, "{}", name).ok(); - } - ScriptPodTy::FixedArray { ty: inner, len, .. } => { - out.push_str("array<"); - self.pod_type_name_referenced(inner, referenced, out); - write!(out, ", {}>", len).ok(); - } - ScriptPodTy::VariableArray { ty: inner, .. } => { - out.push_str("array<"); - self.pod_type_name_referenced(inner, referenced, out); - out.push_str(">"); - } - _ => self.pod_type_name(ty, out), - } - } - - fn pod_type_name_packed_referenced( - &self, - ty: &ScriptPodTypeInline, - referenced: &mut BTreeSet, - out: &mut String, - ) { - match &ty.data.ty { - ScriptPodTy::Struct { .. } => { - referenced.insert(ty.self_ref); - let name = ty.data.name.unwrap(); - let name = self.map_pod_name(name); - write!(out, "{}", name).ok(); - } - ScriptPodTy::FixedArray { ty: inner, len, .. } => { - out.push_str("array<"); - self.pod_type_name_packed_referenced(inner, referenced, out); - write!(out, ", {}>", len).ok(); - } - ScriptPodTy::VariableArray { ty: inner, .. } => { - out.push_str("array<"); - self.pod_type_name_packed_referenced(inner, referenced, out); - out.push_str(">"); - } - _ => self.pod_type_name_packed(ty, out), - } - } - - pub fn pod_type_name_from_ty(&self, heap: &ScriptHeap, ty: ScriptPodType, out: &mut String) { - let pod_ty = heap.pod_type_ref(ty); - let inline = ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - self.pod_type_name(&inline, out); - } - - /// Output packed type name for instance buffer structs (Metal only). - /// Uses packed_float2, packed_float3, etc. to match CPU struct alignment. - pub fn pod_type_name_packed_from_ty( - &self, - heap: &ScriptHeap, - ty: ScriptPodType, - out: &mut String, - ) { - let pod_ty = heap.pod_type_ref(ty); - let inline = ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - self.pod_type_name_packed(&inline, out); - } - - /// Output packed type name (for instance buffer structs in Metal). - pub fn pod_type_name_packed(&self, ty: &ScriptPodTypeInline, out: &mut String) { - match &ty.data.ty { - ScriptPodTy::F32 => write!(out, "{}", self.map_packed_pod_name(id!(f32))) - .ok() - .unwrap_or(()), - ScriptPodTy::F16 => write!(out, "{}", self.map_packed_pod_name(id!(f16))) - .ok() - .unwrap_or(()), - ScriptPodTy::U32 => write!(out, "{}", self.map_packed_pod_name(id!(u32))) - .ok() - .unwrap_or(()), - ScriptPodTy::I32 => write!(out, "{}", self.map_packed_pod_name(id!(i32))) - .ok() - .unwrap_or(()), - ScriptPodTy::Bool => write!(out, "{}", self.map_packed_pod_name(id!(bool))) - .ok() - .unwrap_or(()), - ScriptPodTy::Vec(v) => write!(out, "{}", self.map_packed_pod_name(v.name())) - .ok() - .unwrap_or(()), - ScriptPodTy::Mat(m) => write!(out, "{}", self.map_packed_pod_name(m.name())) - .ok() - .unwrap_or(()), - // For other types, fall back to regular type names - _ => self.pod_type_name(ty, out), - } - } - - pub fn pod_type_name(&self, ty: &ScriptPodTypeInline, out: &mut String) { - match &ty.data.ty { - ScriptPodTy::F32 => write!(out, "{}", self.map_pod_name(id!(f32))) - .ok() - .unwrap_or(()), - ScriptPodTy::F16 => write!(out, "{}", self.map_pod_name(id!(f16))) - .ok() - .unwrap_or(()), - ScriptPodTy::U32 => write!(out, "{}", self.map_pod_name(id!(u32))) - .ok() - .unwrap_or(()), - ScriptPodTy::I32 => write!(out, "{}", self.map_pod_name(id!(i32))) - .ok() - .unwrap_or(()), - ScriptPodTy::Bool => write!(out, "{}", self.map_pod_name(id!(bool))) - .ok() - .unwrap_or(()), - ScriptPodTy::AtomicU32 => write!(out, "atomic<{}>", self.map_pod_name(id!(u32))) - .ok() - .unwrap_or(()), - ScriptPodTy::AtomicI32 => write!(out, "atomic<{}>", self.map_pod_name(id!(i32))) - .ok() - .unwrap_or(()), - ScriptPodTy::Vec(v) => write!(out, "{}", self.map_pod_name(v.name())) - .ok() - .unwrap_or(()), - ScriptPodTy::Mat(m) => write!(out, "{}", self.map_pod_name(m.name())) - .ok() - .unwrap_or(()), - ScriptPodTy::Struct { .. } => { - let name = ty.data.name.unwrap(); - let name = self.map_pod_name(name); - write!(out, "{}", name).ok().unwrap_or(()); - } - ScriptPodTy::FixedArray { ty: inner, len, .. } => { - out.push_str("array<"); - self.pod_type_name(inner, out); - write!(out, ", {}>", len).ok(); - } - ScriptPodTy::VariableArray { ty: inner, .. } => { - out.push_str("array<"); - self.pod_type_name(inner, out); - out.push_str(">"); - } - _ => out.push_str("unknown"), - } - } -} diff --git a/vendor/makepad/platform/script/src/shader_builtins.rs b/vendor/makepad/platform/script/src/shader_builtins.rs deleted file mode 100644 index b9ced31..0000000 --- a/vendor/makepad/platform/script/src/shader_builtins.rs +++ /dev/null @@ -1,1574 +0,0 @@ -use crate::heap::*; -use crate::makepad_live_id::live_id::*; -use crate::makepad_live_id_macros::*; -use crate::mod_pod::ScriptPodBuiltins; -use crate::native::*; -use crate::numeric::NumericValue; -use crate::suggest::format_pod_type_from_builtins; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use makepad_math::{Mat4f, Vec2f, Vec3f, Vec4f}; - -// Helper trait to add vm-based conversion methods for NumericValue -trait NumericValueVmExt { - fn from_script_value_vm(vm: &mut ScriptVm, value: ScriptValue) -> NumericValue; - fn to_script_value_vm(self, vm: &mut ScriptVm) -> ScriptValue; -} - -impl NumericValueVmExt for NumericValue { - fn from_script_value_vm(vm: &mut ScriptVm, value: ScriptValue) -> NumericValue { - NumericValue::from_script_value_heap(&vm.bx.heap, value, vm.bx.threads.cur_ref().trap.ip) - } - - fn to_script_value_vm(self, vm: &mut ScriptVm) -> ScriptValue { - self.to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - } -} - -pub fn define_shader_builtins( - heap: &mut ScriptHeap, - math: ScriptObject, - native: &mut ScriptNative, -) { - // constants - let consts = [ - (id_lut!(PI), 3.141592653589793), - (id_lut!(TAU), 6.283185307179586), - (id_lut!(E), 2.718281828459045), - (id_lut!(LN2), 0.6931471805599453), - (id_lut!(LN10), 2.302585092994046), - (id_lut!(LOG2E), 1.4426950408889634), - (id_lut!(LOG10E), 0.4342944819032518), - (id_lut!(SQRT1_2), 0.70710678118654757), - (id_lut!(TORAD), 0.017453292519943295), - (id_lut!(GOLDEN), 1.618033988749895), - ]; - for (id, val) in consts { - heap.set_value_def(math, id.into(), (val).into()); - } - // 1 argument functions - support f64, Vec2f, Vec3f, Vec4f, Color - native.add_method( - heap, - math, - id_lut!(abs), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.abs()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(acos), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.acos()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(acosh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.acosh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(asin), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.asin()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(asinh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.asinh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(atan), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.atan()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(atan2), - script_args!(y = 0.0, x = 0.0), - |vm, args| { - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - // atan2 computes atan(y/x) with correct quadrant - y_nv.zip_f32(x_nv, |y, x| y.atan2(x)).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(atanh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.atanh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(ceil), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.ceil()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(cos), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.cos()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(cosh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.cosh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(degrees), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.to_degrees()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(exp), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.exp()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(exp2), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.exp2()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(floor), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.floor()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(fract), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.fract()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(inverseSqrt), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.sqrt().recip()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(inverse), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - match NumericValue::from_script_value_vm(vm, x_val) { - NumericValue::Mat4(m) => { - NumericValue::Mat4(Mat4f { v: m }.invert().v).to_script_value_vm(vm) - } - other => other.to_script_value_vm(vm), - } - }, - ); - native.add_method( - heap, - math, - id_lut!(length), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let nv = NumericValue::from_script_value_vm(vm, x_val); - // length returns a scalar for vectors - ScriptValue::from_f64(nv.length()) - }, - ); - // lerp(a, b, t) — the GDScript spelling; identical to mix. Works for - // scalars and vectors (component-wise with scalar t). - native.add_method( - heap, - math, - id_lut!(lerp), - script_args!(a = 0.0, b = 0.0, t = 0.0), - |vm, args| { - let trap = vm.bx.threads.cur_ref().trap.pass(); - let a_val = vm.bx.heap.value(args, id!(a).into(), trap); - let b_val = vm.bx.heap.value(args, id!(b).into(), trap); - let t_val = vm.bx.heap.value(args, id!(t).into(), trap); - let ip = vm.bx.threads.cur_ref().trap.ip; - let a_nv = NumericValue::from_script_value_heap(&vm.bx.heap, a_val, ip); - let b_nv = NumericValue::from_script_value_heap(&vm.bx.heap, b_val, ip); - let t = vm.bx.heap.cast_to_f64(t_val, ip); - a_nv.mix_scalar(b_nv, t) - .to_script_value_heap(&mut vm.bx.heap, &vm.bx.code) - }, - ); - native.add_method( - heap, - math, - id_lut!(log), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.ln()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(log2), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.log2()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(radians), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.to_radians()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(round), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.round()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(sign), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| { - if v > 0.0 { - 1.0 - } else if v < 0.0 { - -1.0 - } else { - 0.0 - } - }) - .to_script_value_vm(vm) - }, - ); - // sin is already in mod_math but we can overwrite or duplicate here, the user asked to add to math_module - native.add_method( - heap, - math, - id_lut!(sin), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.sin()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(sinh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.sinh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(sqrt), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.sqrt()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(tan), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.tan()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(tanh), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.tanh()) - .to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(trunc), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - NumericValue::from_script_value_vm(vm, x_val) - .map_f32(|v| v.trunc()) - .to_script_value_vm(vm) - }, - ); - - // Derivative functions (shader-only, return 0.0 in script runtime) - native.add_method( - heap, - math, - id_lut!(dFdx), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - // Return zero with same type as input - let nv = NumericValue::from_script_value_vm(vm, x_val); - nv.zero_like().to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(dFdy), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - // Return zero with same type as input - let nv = NumericValue::from_script_value_vm(vm, x_val); - nv.zero_like().to_script_value_vm(vm) - }, - ); - - // discard() - fragment shader only, discards the current fragment (shader-only, no-op in script runtime) - native.add_method( - heap, - math, - id_lut!(discard), - script_args!(), - |_vm, _args| ScriptValue::NIL, - ); - - // Bitcast helpers for shader code. These are primarily intended for shader use, - // but we provide scalar runtime behavior so expressions can still evaluate. - native.add_method( - heap, - math, - id_lut!(asuint), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - if let Some(v) = x_val.as_u32() { - return ScriptValue::from_u32(v); - } - if let Some(v) = x_val.as_i32() { - return ScriptValue::from_u32(v as u32); - } - if let Some(v) = x_val.as_f32() { - return ScriptValue::from_u32(v.to_bits()); - } - if let Some(v) = x_val.as_f16() { - return ScriptValue::from_u32(v.to_bits()); - } - let f = vm - .bx - .heap - .cast_to_f64(x_val, vm.bx.threads.cur_ref().trap.ip) as f32; - ScriptValue::from_u32(f.to_bits()) - }, - ); - native.add_method( - heap, - math, - id_lut!(asint), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - if let Some(v) = x_val.as_i32() { - return ScriptValue::from_i32(v); - } - if let Some(v) = x_val.as_u32() { - return ScriptValue::from_i32(v as i32); - } - if let Some(v) = x_val.as_f32() { - return ScriptValue::from_i32(v.to_bits() as i32); - } - if let Some(v) = x_val.as_f16() { - return ScriptValue::from_i32(v.to_bits() as i32); - } - let f = vm - .bx - .heap - .cast_to_f64(x_val, vm.bx.threads.cur_ref().trap.ip) as f32; - ScriptValue::from_i32(f.to_bits() as i32) - }, - ); - native.add_method( - heap, - math, - id_lut!(asfloat), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - if let Some(v) = x_val.as_f32() { - return ScriptValue::from_f32(v); - } - if let Some(v) = x_val.as_u32() { - return ScriptValue::from_f32(f32::from_bits(v)); - } - if let Some(v) = x_val.as_i32() { - return ScriptValue::from_f32(f32::from_bits(v as u32)); - } - let f = vm - .bx - .heap - .cast_to_f64(x_val, vm.bx.threads.cur_ref().trap.ip) as f32; - ScriptValue::from_f32(f) - }, - ); - - // 2 argument functions - support f64, Vec2f, Vec3f, Vec4f, Color - native.add_method( - heap, - math, - id_lut!(atan2), - script_args!(y = 0.0, x = 0.0), - |vm, args| { - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - y_nv.zip_f32(x_nv, |y, x| y.atan2(x)).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(distance), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - // distance returns a scalar (length of difference) - let diff = x_nv.zip_f32(y_nv, |a, b| a - b); - ScriptValue::from_f64(diff.length()) - }, - ); - native.add_method( - heap, - math, - id_lut!(dot), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - // dot returns a scalar (sum of component-wise products) - ScriptValue::from_f64(x_nv.dot(y_nv)) - }, - ); - native.add_method( - heap, - math, - id_lut!(normalize), - script_args!(x = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let nv = NumericValue::from_script_value_vm(vm, x_val); - // normalize returns a unit vector in the same direction - nv.normalize().to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(cross), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - // cross product (only defined for vec3) - x_nv.cross(y_nv).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(max), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - x_nv.zip_f32(y_nv, |a, b| a.max(b)).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(min), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - x_nv.zip_f32(y_nv, |a, b| a.min(b)).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(pow), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - x_nv.zip_f32(y_nv, |a, b| a.powf(b)).to_script_value_vm(vm) - }, - ); - // modf (fmod) - float modulo - native.add_method( - heap, - math, - id_lut!(modf), - script_args!(x = 0.0, y = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - x_nv.zip_f32(y_nv, |a, b| a % b).to_script_value_vm(vm) - }, - ); - native.add_method( - heap, - math, - id_lut!(step), - script_args!(edge = 0.0, x = 0.0), - |vm, args| { - let edge_val = - vm.bx - .heap - .value(args, id!(edge).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - // step can have scalar edge or matching type edge - if let Some(edge_f) = edge_val.as_f64() { - NumericValue::step_scalar(edge_f, x_nv).to_script_value_vm(vm) - } else { - let edge_nv = NumericValue::from_script_value_vm(vm, edge_val); - edge_nv - .zip_f32(x_nv, |e, x| if x < e { 0.0 } else { 1.0 }) - .to_script_value_vm(vm) - } - }, - ); - - // 3 argument functions - support f64, Vec2f, Vec3f, Vec4f, Color - native.add_method( - heap, - math, - id_lut!(clamp), - script_args!(x = 0.0, min = 0.0, max = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let min_val = - vm.bx - .heap - .value(args, id!(min).into(), vm.bx.threads.cur_ref().trap.pass()); - let max_val = - vm.bx - .heap - .value(args, id!(max).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - // clamp can have scalar min/max or matching type - if let (Some(min_f), Some(max_f)) = (min_val.as_f64(), max_val.as_f64()) { - x_nv.clamp_scalar(min_f, max_f).to_script_value_vm(vm) - } else { - let min_nv = NumericValue::from_script_value_vm(vm, min_val); - let max_nv = NumericValue::from_script_value_vm(vm, max_val); - x_nv.zip_f32(min_nv, |x, m| x.max(m)) - .zip_f32(max_nv, |x, m| x.min(m)) - .to_script_value_vm(vm) - } - }, - ); - native.add_method( - heap, - math, - id_lut!(mix), - script_args!(x = 0.0, y = 0.0, a = 0.0), - |vm, args| { - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let y_val = vm - .bx - .heap - .value(args, id!(y).into(), vm.bx.threads.cur_ref().trap.pass()); - let a_val = vm - .bx - .heap - .value(args, id!(a).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - let y_nv = NumericValue::from_script_value_vm(vm, y_val); - // mix typically has scalar alpha, but can also have matching type alpha - if let Some(a_f) = a_val.as_f64() { - x_nv.mix_scalar(y_nv, a_f).to_script_value_vm(vm) - } else { - let a_nv = NumericValue::from_script_value_vm(vm, a_val); - // Component-wise mix - match (x_nv, y_nv, a_nv) { - (NumericValue::Vec2(x), NumericValue::Vec2(y), NumericValue::Vec2(a)) => { - NumericValue::Vec2(Vec2f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - }) - .to_script_value_vm(vm) - } - (NumericValue::Vec3(x), NumericValue::Vec3(y), NumericValue::Vec3(a)) => { - NumericValue::Vec3(Vec3f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - }) - .to_script_value_vm(vm) - } - (NumericValue::Vec4(x), NumericValue::Vec4(y), NumericValue::Vec4(a)) => { - NumericValue::Vec4(Vec4f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - w: x.w * (1.0 - a.w) + y.w * a.w, - }) - .to_script_value_vm(vm) - } - (NumericValue::Color(x), NumericValue::Color(y), NumericValue::Color(a)) => { - NumericValue::Color(Vec4f { - x: x.x * (1.0 - a.x) + y.x * a.x, - y: x.y * (1.0 - a.y) + y.y * a.y, - z: x.z * (1.0 - a.z) + y.z * a.z, - w: x.w * (1.0 - a.w) + y.w * a.w, - }) - .to_script_value_vm(vm) - } - _ => { - // Fallback: treat alpha as scalar - let a_f = match a_nv { - NumericValue::F64(v) => v, - _ => 0.5, // Default alpha - }; - x_nv.mix_scalar(y_nv, a_f).to_script_value_vm(vm) - } - } - } - }, - ); - native.add_method( - heap, - math, - id_lut!(smoothstep), - script_args!(e0 = 0.0, e1 = 0.0, x = 0.0), - |vm, args| { - let e0_val = - vm.bx - .heap - .value(args, id!(e0).into(), vm.bx.threads.cur_ref().trap.pass()); - let e1_val = - vm.bx - .heap - .value(args, id!(e1).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_val = vm - .bx - .heap - .value(args, id!(x).into(), vm.bx.threads.cur_ref().trap.pass()); - let x_nv = NumericValue::from_script_value_vm(vm, x_val); - // smoothstep can have scalar edges or matching type edges - if let (Some(e0_f), Some(e1_f)) = (e0_val.as_f64(), e1_val.as_f64()) { - NumericValue::smoothstep_scalar(e0_f, e1_f, x_nv).to_script_value_vm(vm) - } else { - let e0_nv = NumericValue::from_script_value_vm(vm, e0_val); - let e1_nv = NumericValue::from_script_value_vm(vm, e1_val); - // Component-wise smoothstep - match (e0_nv, e1_nv, x_nv) { - (NumericValue::Vec2(e0), NumericValue::Vec2(e1), NumericValue::Vec2(x)) => { - let smoothstep_f = |e0: f32, e1: f32, x: f32| { - let t = ((x - e0) / (e1 - e0)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) - }; - NumericValue::Vec2(Vec2f { - x: smoothstep_f(e0.x, e1.x, x.x), - y: smoothstep_f(e0.y, e1.y, x.y), - }) - .to_script_value_vm(vm) - } - (NumericValue::Vec3(e0), NumericValue::Vec3(e1), NumericValue::Vec3(x)) => { - let smoothstep_f = |e0: f32, e1: f32, x: f32| { - let t = ((x - e0) / (e1 - e0)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) - }; - NumericValue::Vec3(Vec3f { - x: smoothstep_f(e0.x, e1.x, x.x), - y: smoothstep_f(e0.y, e1.y, x.y), - z: smoothstep_f(e0.z, e1.z, x.z), - }) - .to_script_value_vm(vm) - } - (NumericValue::Vec4(e0), NumericValue::Vec4(e1), NumericValue::Vec4(x)) => { - let smoothstep_f = |e0: f32, e1: f32, x: f32| { - let t = ((x - e0) / (e1 - e0)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) - }; - NumericValue::Vec4(Vec4f { - x: smoothstep_f(e0.x, e1.x, x.x), - y: smoothstep_f(e0.y, e1.y, x.y), - z: smoothstep_f(e0.z, e1.z, x.z), - w: smoothstep_f(e0.w, e1.w, x.w), - }) - .to_script_value_vm(vm) - } - (NumericValue::Color(e0), NumericValue::Color(e1), NumericValue::Color(x)) => { - let smoothstep_f = |e0: f32, e1: f32, x: f32| { - let t = ((x - e0) / (e1 - e0)).max(0.0).min(1.0); - t * t * (3.0 - 2.0 * t) - }; - NumericValue::Color(Vec4f { - x: smoothstep_f(e0.x, e1.x, x.x), - y: smoothstep_f(e0.y, e1.y, x.y), - z: smoothstep_f(e0.z, e1.z, x.z), - w: smoothstep_f(e0.w, e1.w, x.w), - }) - .to_script_value_vm(vm) - } - _ => { - // Fallback: use scalar edges - let e0_f = match e0_nv { - NumericValue::F64(v) => v, - _ => 0.0, - }; - let e1_f = match e1_nv { - NumericValue::F64(v) => v, - _ => 1.0, - }; - NumericValue::smoothstep_scalar(e0_f, e1_f, x_nv).to_script_value_vm(vm) - } - } - } - }, - ); - native.add_method( - heap, - math, - id_lut!(fma), - script_args!(a = 0.0, b = 0.0, c = 0.0), - |vm, args| { - let a_val = vm - .bx - .heap - .value(args, id!(a).into(), vm.bx.threads.cur_ref().trap.pass()); - let b_val = vm - .bx - .heap - .value(args, id!(b).into(), vm.bx.threads.cur_ref().trap.pass()); - let c_val = vm - .bx - .heap - .value(args, id!(c).into(), vm.bx.threads.cur_ref().trap.pass()); - let a_nv = NumericValue::from_script_value_vm(vm, a_val); - let b_nv = NumericValue::from_script_value_vm(vm, b_val); - let c_nv = NumericValue::from_script_value_vm(vm, c_val); - // fma: a * b + c, component-wise - a_nv.zip_f32(b_nv, |a, b| a * b) - .zip_f32(c_nv, |ab, c| ab + c) - .to_script_value_vm(vm) - }, - ); -} - -pub fn type_table_builtin( - name: LiveId, - args: &[ScriptPodType], - builtins: &ScriptPodBuiltins, - trap: ScriptTrap, -) -> ScriptPodType { - // Helper to format type names for error messages - let fmt_ty = |t: ScriptPodType| format_pod_type_from_builtins(t, builtins); - - let f32_t = builtins.pod_f32; - let f16_t = builtins.pod_f16; - let u32_t = builtins.pod_u32; - let i32_t = builtins.pod_i32; - - let vec2f_t = builtins.pod_vec2f; - let vec3f_t = builtins.pod_vec3f; - let vec4f_t = builtins.pod_vec4f; - - let vec2h_t = builtins.pod_vec2h; - let vec3h_t = builtins.pod_vec3h; - let vec4h_t = builtins.pod_vec4h; - - let vec2u_t = builtins.pod_vec2u; - let vec3u_t = builtins.pod_vec3u; - let vec4u_t = builtins.pod_vec4u; - - let vec2i_t = builtins.pod_vec2i; - let vec3i_t = builtins.pod_vec3i; - let vec4i_t = builtins.pod_vec4i; - - // Helpers to check types - let is_float = |t| t == f32_t || t == f16_t; - let is_int = |t| t == u32_t || t == i32_t; - let is_vec_float = |t| { - t == vec2f_t || t == vec3f_t || t == vec4f_t || t == vec2h_t || t == vec3h_t || t == vec4h_t - }; - let is_vec_int = |t| { - t == vec2u_t || t == vec3u_t || t == vec4u_t || t == vec2i_t || t == vec3i_t || t == vec4i_t - }; - - let is_any_float = |t| is_float(t) || is_vec_float(t); - let is_any_int = |t| is_int(t) || is_vec_int(t); - - match name { - id!(asuint) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin 'asuint' requires 1 arg, got {}", - args.len() - ); - return builtins.pod_void; - } - return match args[0] { - t if t == f32_t || t == f16_t || t == u32_t => u32_t, - t => { - script_err_type_mismatch!( - trap, - "shader builtin 'asuint' requires scalar float arg, got {}", - fmt_ty(t) - ); - builtins.pod_void - } - }; - } - id!(asint) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin 'asint' requires 1 arg, got {}", - args.len() - ); - return builtins.pod_void; - } - return match args[0] { - t if t == f32_t || t == f16_t || t == i32_t => i32_t, - t => { - script_err_type_mismatch!( - trap, - "shader builtin 'asint' requires scalar float arg, got {}", - fmt_ty(t) - ); - builtins.pod_void - } - }; - } - id!(asfloat) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin 'asfloat' requires 1 arg, got {}", - args.len() - ); - return builtins.pod_void; - } - return match args[0] { - t if t == u32_t || t == i32_t || t == f32_t => f32_t, - t => { - script_err_type_mismatch!( - trap, - "shader builtin 'asfloat' requires scalar int arg, got {}", - fmt_ty(t) - ); - builtins.pod_void - } - }; - } - // Float only 1 argument - id!(acos) - | id!(acosh) - | id!(asin) - | id!(asinh) - | id!(atan) - | id!(atanh) - | id!(ceil) - | id!(cos) - | id!(cosh) - | id!(degrees) - | id!(exp) - | id!(exp2) - | id!(floor) - | id!(fract) - | id!(inverse) - | id!(inverseSqrt) - | id!(log) - | id!(log2) - | id!(radians) - | id!(round) - | id!(sin) - | id!(sinh) - | id!(sqrt) - | id!(tan) - | id!(tanh) - | id!(trunc) - | id!(dFdx) - | id!(dFdy) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 1 arg, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let t = args[0]; - if name == id!(inverse) { - if t == builtins.pod_mat4x4f { - return t; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires mat4 arg, got {}", - name, - fmt_ty(t) - ); - return builtins.pod_void; - } - if is_any_float(t) { - return t; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires float/vec-float arg, got {}", - name, - fmt_ty(t) - ); - return builtins.pod_void; - } - // discard() - takes 0 arguments, returns void - id!(discard) => { - if args.len() != 0 { - script_err_invalid_args!( - trap, - "shader builtin 'discard' requires 0 args, got {}", - args.len() - ); - return builtins.pod_void; - } - return builtins.pod_void; - } - id!(length) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin 'length' requires 1 arg, got {}", - args.len() - ); - return builtins.pod_void; - } - let t = args[0]; - if is_any_float(t) { - if t == vec2f_t || t == vec3f_t || t == vec4f_t { - return f32_t; - } - if t == vec2h_t || t == vec3h_t || t == vec4h_t { - return f16_t; - } - return t; - } - script_err_type_mismatch!( - trap, - "shader builtin 'length' requires float/vec-float arg, got {}", - fmt_ty(t) - ); - return builtins.pod_void; - } - // normalize: returns unit vector in same direction - id!(normalize) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin 'normalize' requires 1 arg, got {}", - args.len() - ); - return builtins.pod_void; - } - let t = args[0]; - if is_vec_float(t) { - return t; - } - script_err_type_mismatch!( - trap, - "shader builtin 'normalize' requires vec-float arg, got {}", - fmt_ty(t) - ); - return builtins.pod_void; - } - // Float or Int 1 argument - id!(abs) | id!(sign) => { - if args.len() != 1 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 1 arg, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let t = args[0]; - if is_any_float(t) || is_any_int(t) { - return t; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires float/int arg, got {}", - name, - fmt_ty(t) - ); - return builtins.pod_void; - } - // Float 2 arguments - id!(atan2) | id!(pow) | id!(modf) => { - if args.len() != 2 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 2 args, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let (t1, t2) = (args[0], args[1]); - if t1 == t2 && is_any_float(t1) { - return t1; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires matching float types, got {} and {}", - name, - fmt_ty(t1), - fmt_ty(t2) - ); - return builtins.pod_void; - } - id!(step) => { - if args.len() != 2 { - script_err_invalid_args!( - trap, - "shader builtin 'step' requires 2 args, got {}", - args.len() - ); - return builtins.pod_void; - } - let (t1, t2) = (args[0], args[1]); - if t1 == t2 && is_any_float(t1) { - return t1; - } - if is_vec_float(t2) - && (t1 == f32_t && (t2 == vec2f_t || t2 == vec3f_t || t2 == vec4f_t) - || t1 == f16_t && (t2 == vec2h_t || t2 == vec3h_t || t2 == vec4h_t)) - { - return t2; - } - script_err_type_mismatch!( - trap, - "shader builtin 'step' requires (float,float) or (scalar,vec-float), got {} and {}", - fmt_ty(t1), - fmt_ty(t2) - ); - return builtins.pod_void; - } - id!(distance) | id!(dot) => { - if args.len() != 2 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 2 args, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let (t1, t2) = (args[0], args[1]); - if t1 == t2 && is_any_float(t1) { - if t1 == vec2f_t || t1 == vec3f_t || t1 == vec4f_t { - return f32_t; - } - if t1 == vec2h_t || t1 == vec3h_t || t1 == vec4h_t { - return f16_t; - } - return t1; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires matching float types, got {} and {}", - name, - fmt_ty(t1), - fmt_ty(t2) - ); - return builtins.pod_void; - } - // cross product: only works on vec3 - id!(cross) => { - if args.len() != 2 { - script_err_invalid_args!( - trap, - "shader builtin 'cross' requires 2 args, got {}", - args.len() - ); - return builtins.pod_void; - } - let (t1, t2) = (args[0], args[1]); - if t1 == t2 { - if t1 == vec3f_t { - return vec3f_t; - } - if t1 == vec3h_t { - return vec3h_t; - } - } - script_err_type_mismatch!( - trap, - "shader builtin 'cross' requires two vec3 args, got {} and {}", - fmt_ty(t1), - fmt_ty(t2) - ); - return builtins.pod_void; - } - // Float or Int 2 arguments - id!(max) | id!(min) => { - if args.len() != 2 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 2 args, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let (t1, t2) = (args[0], args[1]); - if t1 == t2 && (is_any_float(t1) || is_any_int(t1)) { - return t1; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires matching float/int types, got {} and {}", - name, - fmt_ty(t1), - fmt_ty(t2) - ); - return builtins.pod_void; - } - // Float 3 arguments - id!(mix) => { - if args.len() != 3 { - script_err_invalid_args!( - trap, - "shader builtin 'mix' requires 3 args (x, y, alpha), got {}", - args.len() - ); - return builtins.pod_void; - } - let (t1, t2, t3) = (args[0], args[1], args[2]); - // mix(x, y, a) - if t1 == t2 && is_any_float(t1) { - if t3 == t1 { - return t1; - } - // vector with scalar alpha - if (t1 == vec2f_t || t1 == vec3f_t || t1 == vec4f_t) && (is_float(t3) || is_int(t3)) - { - return t1; - } - } - script_err_type_mismatch!(trap, "shader builtin 'mix' requires matching float types for x,y and compatible alpha, got {}, {}, {}", fmt_ty(t1), fmt_ty(t2), fmt_ty(t3)); - return builtins.pod_void; - } - id!(smoothstep) | id!(fma) => { - if args.len() != 3 { - script_err_invalid_args!( - trap, - "shader builtin {:?} requires 3 args, got {}", - name, - args.len() - ); - return builtins.pod_void; - } - let (t1, t2, t3) = (args[0], args[1], args[2]); - if t1 == t2 && t2 == t3 && is_any_float(t1) { - return t1; - } - script_err_type_mismatch!( - trap, - "shader builtin {:?} requires 3 matching float args, got {}, {}, {}", - name, - fmt_ty(t1), - fmt_ty(t2), - fmt_ty(t3) - ); - return builtins.pod_void; - } - // Clamp: Float or Int 3 arguments - id!(clamp) => { - if args.len() != 3 { - script_err_invalid_args!( - trap, - "shader builtin 'clamp' requires 3 args (value, min, max), got {}", - args.len() - ); - return builtins.pod_void; - } - let (t1, t2, t3) = (args[0], args[1], args[2]); - if t1 == t2 && t2 == t3 && (is_any_float(t1) || is_any_int(t1)) { - return t1; - } - script_err_type_mismatch!( - trap, - "shader builtin 'clamp' requires 3 matching float/int args, got {}, {}, {}", - fmt_ty(t1), - fmt_ty(t2), - fmt_ty(t3) - ); - return builtins.pod_void; - } - id!(depth_clip) => { - if args.len() != 3 { - script_err_invalid_args!( - trap, - "shader builtin 'depth_clip' requires 3 args (world, color, clip), got {}", - args.len() - ); - return builtins.pod_void; - } - let (t1, t2, t3) = (args[0], args[1], args[2]); - if t1 == vec4f_t && t2 == vec4f_t && is_float(t3) { - return vec4f_t; - } - script_err_type_mismatch!( - trap, - "shader builtin 'depth_clip' requires (vec4f, vec4f, float), got {}, {}, {}", - fmt_ty(t1), - fmt_ty(t2), - fmt_ty(t3) - ); - return builtins.pod_void; - } - _ => { - script_err_wrong_value!(trap, "unknown shader builtin function {:?}", name); - builtins.pod_void - } - } -} diff --git a/vendor/makepad/platform/script/src/shader_calls.rs b/vendor/makepad/platform/script/src/shader_calls.rs deleted file mode 100644 index 223222d..0000000 --- a/vendor/makepad/platform/script/src/shader_calls.rs +++ /dev/null @@ -1,2420 +0,0 @@ -//! Shader function and method call operations -//! -//! This module contains handle functions for function calls, method calls, -//! type construction (Pod, Array), and builtin calls. - -use crate::function::*; -use crate::opcode::*; -use crate::pod::*; -use crate::shader::*; -use crate::shader_backend::*; -use crate::shader_builtins::*; -use crate::suggest::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use makepad_live_id::*; -use std::fmt::Write; - -impl ShaderFnCompiler { - pub(crate) fn handle_pod_type_call( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - pod_ty: ScriptPodType, - name: LiveId, - ) { - if let ScriptPodTy::ArrayBuilder = &vm.bx.heap.pod_types[pod_ty.index as usize].ty { - self.mes.push(ShaderMe::ArrayConstruct { - args: Vec::new(), - elem_ty: None, - }); - self.maybe_pop_to_me(vm, output, opargs); - return; - } - - // alright lets see what Id we got - let _name = self.ensure_struct_name(vm, output, pod_ty, name); - - self.mes.push(ShaderMe::Pod { - pod_ty, - args: Vec::new(), - }); - - self.maybe_pop_to_me(vm, output, opargs); - } - - pub(crate) fn handle_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - let (ty, _s) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(name) = ty { - // Check shader scope for PodType - if let Some((ShaderScopeItem::PodType { ty, .. }, _)) = self.shader_scope.find_var(name) - { - self.handle_pod_type_call(vm, output, opargs, *ty, name); - return; - } - - // alright lets look it up on our script scope - let value = vm - .bx - .heap - .scope_value(self.script_scope, name.into(), self.trap.pass()); - // lets check if our obj is a PodType - if let Some(pod_ty) = vm.bx.heap.pod_type(value) { - self.handle_pod_type_call(vm, output, opargs, pod_ty, name); - return; - } - - if let Some(fnobj) = value.as_object() { - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - match fnptr { - // another script fn - ScriptFnPtr::Script(_fnptr) => { - let mut out = self.stack.new_string(); - write!(out, "{}", output.backend.get_io_all(output.mode)).ok(); - self.mes.push(ShaderMe::ScriptCall { - name, - out, - fnobj, - sself: ShaderType::None, - args: Default::default(), - }); - } - // builtin shader fns - ScriptFnPtr::Native(fnptr) => { - self.mes.push(ShaderMe::BuiltinCall { - name, - fnptr, - args: Default::default(), - }); - self.maybe_pop_to_me(vm, output, opargs); - return; - } - } - - self.maybe_pop_to_me(vm, output, opargs); - return; - } - } - } - script_err_wrong_value!(self.trap, "shader call target is not a function"); - } - - pub(crate) fn handle_array_construct( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - args: Vec, - elem_ty: Option, - ) { - let elem_ty = elem_ty.unwrap_or(vm.bx.code.builtins.pod.pod_f32); - let count = args.len(); - - let elem_data = vm.bx.heap.pod_types[elem_ty.index as usize].clone(); - let elem_inline = ScriptPodTypeInline { - self_ref: elem_ty, - data: elem_data, - }; - - let align_of = elem_inline.data.ty.align_of(); - let raw_size = elem_inline.data.ty.size_of(); - let stride = if raw_size % align_of != 0 { - raw_size + (align_of - (raw_size % align_of)) - } else { - raw_size - }; - let total_size = stride * count; - - let array_ty = vm.bx.heap.new_pod_array_type( - ScriptPodTy::FixedArray { - align_of, - size_of: total_size, - len: count, - ty: Box::new(elem_inline), - }, - NIL, - ); - - let mut out = self.stack.new_string(); - - if let Some(name) = vm.bx.heap.pod_type_name(elem_ty) { - if matches!( - vm.bx.heap.pod_types[elem_ty.index as usize].ty, - ScriptPodTy::Struct { .. } - ) { - output.structs.insert(elem_ty); - } - match output.backend { - ShaderBackend::Wgsl => { - let name = output.backend.map_pod_name(name); - write!(out, "array<{}, {}>", name, count).ok(); - write!(out, "(").ok(); - } - ShaderBackend::Metal | ShaderBackend::Hlsl => { - write!(out, "{{").ok(); - } - ShaderBackend::Glsl | ShaderBackend::Rust => { - let name = output.backend.map_pod_name(name); - write!(out, "{}[{}]", name, count).ok(); // array constructor - write!(out, "(").ok(); - } - } - } else { - script_err_shader!(self.trap, "no shader type for array element"); - match output.backend { - ShaderBackend::Wgsl => { - write!(out, "(").ok(); - } - ShaderBackend::Metal | ShaderBackend::Hlsl => { - write!(out, "{{").ok(); - } - ShaderBackend::Glsl | ShaderBackend::Rust => { - write!(out, "(").ok(); // Should not happen if type not found - } - } - } - - for (i, s) in args.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(s); - } - - match output.backend { - ShaderBackend::Wgsl | ShaderBackend::Glsl | ShaderBackend::Rust => { - out.push_str(")"); - } - ShaderBackend::Metal | ShaderBackend::Hlsl => { - out.push_str("}"); - } - } - - for s in args { - self.stack.free_string(s); - } - - self.stack - .push(self.trap.pass(), ShaderType::Pod(array_ty), out); - } - - pub(crate) fn handle_pod_construct( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - pod_ty: ScriptPodType, - args: Vec, - ) { - let mut offset = ScriptPodOffset::default(); - let pod_ty_data = &vm.bx.heap.pod_types[pod_ty.index as usize]; - - let mut out = self.stack.new_string(); - if let Some(name) = vm.bx.heap.pod_type_name(pod_ty) { - let name = output.backend.map_pod_name(name); - match output.backend { - ShaderBackend::Wgsl => { - write!(out, "{}(", name).ok(); - } - ShaderBackend::Metal => { - if let ScriptPodTy::Struct { .. } = &pod_ty_data.ty { - write!(out, "{{").ok(); - } else { - write!(out, "{}(", name).ok(); - } - } - ShaderBackend::Hlsl => { - if let ScriptPodTy::Struct { .. } = &pod_ty_data.ty { - write!(out, "consfn_{}(", name).ok(); - } else { - write!(out, "{}(", name).ok(); - } - } - ShaderBackend::Glsl => { - write!(out, "{}(", name).ok(); - } - ShaderBackend::Rust => { - if let ScriptPodTy::Struct { .. } = &pod_ty_data.ty { - write!(out, "{} {{ ", name).ok(); - } else { - // Scalar constructors are casts, and Rust has no u32(x) call - // form — emit `as` casts (with != for bool, which `as` can't - // target, and via u32 for bool→float, which `as` can't source). - let is_scalar = matches!( - pod_ty_data.ty, - ScriptPodTy::F32 - | ScriptPodTy::F16 - | ScriptPodTy::U32 - | ScriptPodTy::I32 - | ScriptPodTy::Bool - ); - if is_scalar && args.len() == 1 { - let builtins = &vm.bx.code.builtins.pod; - let arg = &args[0]; - let arg_ty = - arg.ty.make_concrete(builtins).unwrap_or(builtins.pod_void); - let arg_is_float = - arg_ty == builtins.pod_f32 || arg_ty == builtins.pod_f16; - let arg_is_bool = arg_ty == builtins.pod_bool; - match &pod_ty_data.ty { - ScriptPodTy::Bool if arg_is_bool => { - write!(out, "({})", arg.s).ok(); - } - ScriptPodTy::Bool if arg_is_float => { - write!(out, "(({}) != 0.0)", arg.s).ok(); - } - ScriptPodTy::Bool => { - write!(out, "(({}) != 0)", arg.s).ok(); - } - ScriptPodTy::F32 | ScriptPodTy::F16 if arg_is_bool => { - write!(out, "(({}) as u32 as f32)", arg.s).ok(); - } - ScriptPodTy::F32 | ScriptPodTy::F16 => { - write!(out, "(({}) as f32)", arg.s).ok(); - } - ScriptPodTy::U32 => { - write!(out, "(({}) as u32)", arg.s).ok(); - } - ScriptPodTy::I32 => { - write!(out, "(({}) as i32)", arg.s).ok(); - } - _ => unreachable!(), - } - for arg in args { - self.stack.free_string(arg.s); - } - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), out); - return; - } - // For vec types, we need to expand heterogeneous constructors - // like vec4f(vec3, f32) → vec4(v.x, v.y, v.z, s) - // This is handled by rust_expand_pod_construct below - let total_slots = pod_ty_data.ty.slots(); - if args.len() != total_slots && total_slots > 1 { - // Expand heterogeneous constructor - let base_name = match total_slots { - 2 => "vec2", - 3 => "vec3", - 4 => "vec4", - _ => "vec4", - }; - let expanded = self.rust_expand_pod_construct(vm, &args, total_slots); - write!(out, "{}({})", base_name, expanded).ok(); - - for arg in args { - self.stack.free_string(arg.s); - } - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), out); - return; - } - write!(out, "{}(", name).ok(); - } - } - } - } else { - script_err_shader!(self.trap, "no shader type for pod construct"); - } - - if let Some(first) = args.first() { - if first.name.is_some() { - // Named args - if let ScriptPodTy::Struct { fields, .. } = &pod_ty_data.ty { - for (i, field) in fields.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - - // Find the arg with self name - if let Some(arg) = args.iter().find(|a| a.name.unwrap() == field.name) { - // Check type - match &arg.ty { - ShaderType::Pod(arg_pod_ty) => { - if *arg_pod_ty != field.ty.self_ref { - script_err_pod!( - self.trap, - "named arg {:?} type mismatch: expected {}, got {}", - field.name, - format_pod_type_name(&vm.bx.heap, field.ty.self_ref), - format_pod_type_name(&vm.bx.heap, *arg_pod_ty) - ); - } - } - ShaderType::Id(id) => { - if let Some((v, _name)) = self.shader_scope.find_var(*id) { - if v.ty() != field.ty.self_ref { - script_err_pod!(self.trap, "var {:?} type mismatch for field {:?}: expected {}, got {}", id, field.name, format_pod_type_name(&vm.bx.heap, field.ty.self_ref), format_pod_type_name(&vm.bx.heap, v.ty())); - } - } else { - script_err_not_found!( - self.trap, - "var {:?} not found{}", - id, - suggest_from_live_ids( - *id, - &self.shader_scope.all_var_names() - ) - ); - } - } - ShaderType::AbstractInt => { - let builtins = &vm.bx.code.builtins.pod; - if field.ty.self_ref != builtins.pod_i32 - && field.ty.self_ref != builtins.pod_u32 - && field.ty.self_ref != builtins.pod_f32 - { - script_err_pod!(self.trap, "abstract int not compatible with field {:?} (expects {})", field.name, format_pod_type_name(&vm.bx.heap, field.ty.self_ref)); - } - } - ShaderType::AbstractFloat => { - let builtins = &vm.bx.code.builtins.pod; - if field.ty.self_ref != builtins.pod_f32 { - script_err_pod!(self.trap, "abstract float not compatible with field {:?} (expects {})", field.name, format_pod_type_name(&vm.bx.heap, field.ty.self_ref)); - } - } - _ => {} - } - if matches!(output.backend, ShaderBackend::Rust) { - write!(out, "{}: ", field.name).ok(); - } - out.push_str(&arg.s); - } else { - script_err_type_mismatch!( - self.trap, - "missing arg for field {:?}", - field.name - ); - } - } - - if args.len() != fields.len() { - script_err_invalid_args!( - self.trap, - "expected {} args, got {}", - fields.len(), - args.len() - ); - } - } else { - script_err_unexpected!(self.trap, "named args require struct type"); - } - } else { - // Positional args - let pod_name = vm - .bx - .heap - .pod_type_name(pod_ty) - .map(|name| output.backend.map_pod_name(name)); - let hlsl_splat_len = - if matches!(output.backend, ShaderBackend::Hlsl) && args.len() == 1 { - match pod_name { - Some(id!(float2)) | Some(id!(half2)) | Some(id!(uint2)) - | Some(id!(int2)) | Some(id!(bool2)) => Some(2usize), - Some(id!(float3)) | Some(id!(half3)) | Some(id!(uint3)) - | Some(id!(int3)) | Some(id!(bool3)) => Some(3usize), - Some(id!(float4)) | Some(id!(half4)) | Some(id!(uint4)) - | Some(id!(int4)) | Some(id!(bool4)) => Some(4usize), - _ => None, - } - } else { - None - }; - - // For Rust struct types, get field names for positional args - let rust_struct_fields: Option> = - if matches!(output.backend, ShaderBackend::Rust) { - if let ScriptPodTy::Struct { fields, .. } = &pod_ty_data.ty { - Some(fields.iter().map(|f| f.name).collect()) - } else { - None - } - } else { - None - }; - - for (i, arg) in args.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - match &arg.ty { - ShaderType::Pod(pod_ty_field) | ShaderType::PodPtr(pod_ty_field) => { - vm.bx.heap.pod_check_constructor_arg( - pod_ty, - *pod_ty_field, - &mut offset, - self.trap.pass(), - ); - } - ShaderType::Id(id) => { - if let Some((v, _name)) = self.shader_scope.find_var(*id) { - vm.bx.heap.pod_check_constructor_arg( - pod_ty, - v.ty(), - &mut offset, - self.trap.pass(), - ); - } else { - script_err_not_found!( - self.trap, - "var {:?} not found in constructor{}", - id, - suggest_from_live_ids(*id, &self.shader_scope.all_var_names()) - ); - } - } - ShaderType::AbstractInt | ShaderType::AbstractFloat => { - vm.bx.heap.pod_check_abstract_constructor_arg( - pod_ty, - &mut offset, - self.trap.pass(), - ); - } - ShaderType::None - | ShaderType::Range { .. } - | ShaderType::Error(_) - | ShaderType::IoSelf(_) - | ShaderType::ScopeObject(_) - | ShaderType::ScopeUniformBuffer { .. } - | ShaderType::ScopeTexture { .. } - | ShaderType::PodType(_) - | ShaderType::Texture(_) => {} - } - - if i == 0 { - if let Some(n) = hlsl_splat_len { - for j in 0..n { - if j > 0 { - out.push_str(", "); - } - out.push_str(&arg.s); - } - break; - } - } - // For Rust struct types, prefix with field name - if let Some(ref fields) = rust_struct_fields { - if i < fields.len() { - write!(out, "{}: ", fields[i]).ok(); - } - } - out.push_str(&arg.s); - } - vm.bx - .heap - .pod_check_constructor_arg_count(pod_ty, &offset, self.trap.pass()); - } - } else { - vm.bx - .heap - .pod_check_constructor_arg_count(pod_ty, &offset, self.trap.pass()); - } - - match output.backend { - ShaderBackend::Wgsl => { - out.push_str(")"); - } - ShaderBackend::Metal => { - if let ScriptPodTy::Struct { .. } = &pod_ty_data.ty { - out.push_str("}"); - } else { - out.push_str(")"); - } - } - ShaderBackend::Hlsl => { - out.push_str(")"); - } - ShaderBackend::Glsl => { - out.push_str(")"); - } - ShaderBackend::Rust => { - if let ScriptPodTy::Struct { .. } = &pod_ty_data.ty { - out.push_str(" }"); - } else { - out.push_str(")"); - } - } - } - - for arg in args { - self.stack.free_string(arg.s); - } - - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), out); - } - - pub fn compile_shader_def( - vm: &mut ScriptVm, - output: &mut ShaderOutput, - trap: ScriptTrap, - name: LiveId, - fnobj: ScriptObject, - sself: ShaderType, - args: Vec, - ) -> (ScriptPodType, String) { - let mut method_name_prefix = String::new(); - if let ShaderType::PodType(ty) = sself { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - write!(method_name_prefix, "{}_", name).ok(); - } - } else if let ShaderType::Pod(ty) = sself { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - write!(method_name_prefix, "{}_", name).ok(); - } - } else if let ShaderType::IoSelf(_) = sself { - write!(method_name_prefix, "io_").ok(); - } else if let ShaderType::ScopeObject(obj) = sself { - // Use the object index to create a unique prefix for scope object methods - write!(method_name_prefix, "scope{}_", obj.index).ok(); - } - - // First pass: resolve AbstractInt/AbstractFloat against declared parameter types - // Also count expected parameters to validate argument count - let builtins = &vm.bx.code.builtins.pod; - let argc = vm.bx.heap.vec_len(fnobj); - let mut resolved_args: Vec = Vec::new(); - let mut argi = 0; - let mut expected_param_count = 0; - for i in 0..argc { - let kv = vm.bx.heap.vec_key_value(fnobj, i, trap); - if kv.key == id!(self).into() { - continue; - } - expected_param_count += 1; - if argi >= args.len() { - continue; // Keep counting expected params but skip arg processing - } - let arg = &args[argi]; - // Get declared parameter type from kv.value - // Try both direct pod_type value and object-based pod_type - let declared_ty = kv - .value - .as_pod_type() - .or_else(|| vm.bx.heap.pod_type(kv.value)); - - let resolved = match arg { - ShaderType::AbstractInt | ShaderType::AbstractFloat => { - // Use declared type if available, otherwise fall back to default - if let Some(declared) = declared_ty { - declared - } else { - arg.make_concrete(builtins).unwrap_or(builtins.pod_void) - } - } - _ => arg.make_concrete(builtins).unwrap_or(builtins.pod_void), - }; - resolved_args.push(resolved); - argi += 1; - } - - // Validate argument count - if args.len() != expected_param_count { - output.has_errors = true; - script_err_invalid_args!( - trap, - "function {:?} expects {} argument{}, but {} {} provided", - name, - expected_param_count, - if expected_param_count == 1 { "" } else { "s" }, - args.len(), - if args.len() == 1 { "was" } else { "were" } - ); - } - - // lets see if we already have fnobj with our argstypes - if let Some(fun) = output - .functions - .iter() - .find(|v| v.fnobj == fnobj && v.args == resolved_args) - { - let mut fn_name_base = String::new(); - if fun.overload != 0 { - write!( - fn_name_base, - "_f{}{}{}", - fun.overload, method_name_prefix, name - ) - .ok(); - } else { - write!(fn_name_base, "{}{}", method_name_prefix, name).ok(); - } - let mut fn_name = output.backend.map_function_name(&fn_name_base); - write!(fn_name, "(").ok(); // Add opening paren to match new function path - return (fun.ret, fn_name); - } - - let overload = output.functions.iter().filter(|v| v.name == name).count(); - - let mut compiler = ShaderFnCompiler::new(fnobj); - let mut call_sig = String::new(); - - let mut fn_name_base = String::new(); - let mut fn_args = String::new(); - - if overload != 0 { - write!(fn_name_base, "_f{}{}{}", overload, method_name_prefix, name).ok(); - } else { - write!(fn_name_base, "{}{}", method_name_prefix, name).ok(); - } - let mut fn_name = output.backend.map_function_name(&fn_name_base); - - let mut has_self = false; - write!(fn_args, "{}", output.backend.get_io_all_decl(output.mode)).ok(); - if let ShaderType::Pod(ty) = sself { - has_self = true; - match output.backend { - ShaderBackend::Wgsl => { - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "_self:").ok(); - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - let name = output.backend.map_pod_name(name); - write!(fn_args, "ptr", name).ok(); - } - } - ShaderBackend::Metal => { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - let name = output.backend.map_pod_name(name); - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "thread {}& _self", name).ok(); - } - } - ShaderBackend::Hlsl => { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - let name = output.backend.map_pod_name(name); - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "inout {} _self", name).ok(); - } - } - ShaderBackend::Glsl => { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - let name = output.backend.map_pod_name(name); - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "inout {} _self", name).ok(); - } - } - ShaderBackend::Rust => { - if let Some(name) = vm.bx.heap.pod_type_name(ty) { - let name = output.backend.map_pod_name(name); - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "_self: *mut {}", name).ok(); - } - } - } - compiler.shader_scope.define_param(id!(self), ty); - } else if let ShaderType::PodType(ty) = sself { - compiler.shader_scope.define_pod_type(id!(self), ty); - } else if let ShaderType::IoSelf(obj) = sself { - let io_self_decl = output.backend.get_io_self_decl(output.mode); - if !io_self_decl.is_empty() { - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - write!(fn_args, "{}", io_self_decl).ok(); - } - compiler.shader_scope.define_io_self(obj); - } else if let ShaderType::ScopeObject(obj) = sself { - // ScopeObject methods don't have a _self parameter - `self` references - // are resolved to IoScopeUniform accesses at compile time - compiler.shader_scope.define_scope_object(obj); - } - - let argc = vm.bx.heap.vec_len(fnobj); - let mut argi = 0; - for i in 0..argc { - let kv = vm.bx.heap.vec_key_value(fnobj, i, trap); - - if kv.key == id!(self).into() { - if !has_self || argi != 0 { - output.has_errors = true; - script_err_not_found!(trap, "self arg must be first with has_self"); - } - continue; - } - - if let Some(id) = kv.key.as_id() { - if fn_args.len() > 0 { - write!(fn_args, ", ").ok(); - } - if argi >= resolved_args.len() { - output.has_errors = true; - script_err_invalid_args!(trap, "more formal params than resolved args"); - break; - } - let arg_ty = resolved_args[argi]; - let param_shadow = compiler.shader_scope.define_param(id, arg_ty); - let param_name = output.backend.map_param_name(id, param_shadow); - - match output.backend { - ShaderBackend::Wgsl => { - write!(fn_args, "{}:", param_name).ok(); - if let Some(name) = vm.bx.heap.pod_type_name(arg_ty) { - let name = output.backend.map_pod_name(name); - write!(fn_args, "{}", name).ok(); - } else { - // todo!() - } - } - ShaderBackend::Metal | ShaderBackend::Hlsl | ShaderBackend::Glsl => { - if let Some(name) = vm.bx.heap.pod_type_name(arg_ty) { - let name = output.backend.map_pod_name(name); - write!(fn_args, "{} {}", name, param_name).ok(); - } else { - // todo!() - } - } - ShaderBackend::Rust => { - if let Some(name) = vm.bx.heap.pod_type_name(arg_ty) { - let name = output.backend.map_pod_name(name); - write!(fn_args, "{}: {}", param_name, name).ok(); - } else { - // todo!() - } - } - } - } - argi += 1; - } - if argi < resolved_args.len() { - output.has_errors = true; - script_err_invalid_args!(trap, "fewer formal params than resolved args"); - } - - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - if let ScriptFnPtr::Script(fnip) = fnptr { - if output.recur_block.iter().any(|v| *v == fnobj) { - output.has_errors = true; - script_err_not_allowed!(trap, "shader functions cannot recurse"); - (vm.bx.code.builtins.pod.pod_void, fn_name) - } else { - output.recur_block.push(fnobj); - let ret = compiler.compile_fn(vm, output, fnip); - output.recur_block.pop(); - - // Ensure struct return types are registered in output.structs - if let ScriptPodTy::Struct { .. } = vm.bx.heap.pod_type_ref(ret).ty { - output.structs.insert(ret); - } - - match output.backend { - ShaderBackend::Wgsl => { - write!(call_sig, "fn {}({})", fn_name, fn_args).ok(); - if let Some(name) = vm.bx.heap.pod_type_name(ret) { - if name != id!(void) { - let name = output.backend.map_pod_name(name); - write!(call_sig, "->{}", name).ok(); - } - } - } - ShaderBackend::Metal | ShaderBackend::Hlsl | ShaderBackend::Glsl => { - let ret_name = if let Some(name) = vm.bx.heap.pod_type_name(ret) { - output.backend.map_pod_name(name) - } else { - id!(void) - }; - write!(call_sig, "{} {}({})", ret_name, fn_name, fn_args).ok(); - } - ShaderBackend::Rust => { - let ret_name = if let Some(name) = vm.bx.heap.pod_type_name(ret) { - output.backend.map_pod_name(name) - } else { - id!(void) - }; - if ret_name == id!(void) { - write!(call_sig, "fn {}({})", fn_name, fn_args).ok(); - } else { - write!(call_sig, "fn {}({}) -> {}", fn_name, fn_args, ret_name) - .ok(); - } - } - } - - output.functions.push(ShaderFn { - overload, - call_sig, - name, - args: resolved_args, - fnobj, - out: compiler.out, - ret, - }); - write!(fn_name, "(").ok(); - (ret, fn_name) - } - } else { - panic!() - } - } else { - panic!() - } - } - - pub(crate) fn handle_script_call( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - mut out: String, - name: LiveId, - fnobj: ScriptObject, - sself: ShaderType, - args: Vec, - ) { - // we should compare number of arguments (needs to be exact) - // Note: fn_name already includes "(" at the end from compile_shader_def - let arg_types = args.clone(); - let resolved_arg_types = - Self::resolve_script_call_arg_types(vm, fnobj, &arg_types, self.trap.pass()); - let (ret, fn_name) = - Self::compile_shader_def(vm, output, self.trap.pass(), name, fnobj, sself, args); - if matches!(output.backend, ShaderBackend::Glsl | ShaderBackend::Rust) { - out = Self::glsl_rewrite_call_args(vm, &out, &arg_types, &resolved_arg_types); - } - out.insert_str(0, &fn_name); - out.push_str(")"); - self.stack.push(self.trap.pass(), ShaderType::Pod(ret), out); - } - - fn resolve_script_call_arg_types( - vm: &ScriptVm, - fnobj: ScriptObject, - args: &[ShaderType], - trap: ScriptTrap, - ) -> Vec { - let builtins = &vm.bx.code.builtins.pod; - let argc = vm.bx.heap.vec_len(fnobj); - let mut resolved_args: Vec = Vec::new(); - let mut argi = 0; - - for i in 0..argc { - let kv = vm.bx.heap.vec_key_value(fnobj, i, trap); - if kv.key == id!(self).into() { - continue; - } - if argi >= args.len() { - break; - } - let arg = &args[argi]; - let declared_ty = kv - .value - .as_pod_type() - .or_else(|| vm.bx.heap.pod_type(kv.value)); - - let resolved = match arg { - ShaderType::AbstractInt | ShaderType::AbstractFloat => declared_ty - .unwrap_or_else(|| arg.make_concrete(builtins).unwrap_or(builtins.pod_void)), - _ => arg.make_concrete(builtins).unwrap_or(builtins.pod_void), - }; - resolved_args.push(resolved); - argi += 1; - } - - resolved_args - } - - fn glsl_rewrite_call_args( - vm: &ScriptVm, - raw_args: &str, - arg_types: &[ShaderType], - resolved_arg_types: &[ScriptPodType], - ) -> String { - let mut parts = Self::split_call_args_top_level(raw_args); - if parts.is_empty() || arg_types.is_empty() || parts.len() < arg_types.len() { - return raw_args.to_string(); - } - - let explicit_start = parts.len() - arg_types.len(); - let explicit_len = arg_types.len().min(resolved_arg_types.len()); - for i in 0..explicit_len { - if !matches!(arg_types[i], ShaderType::AbstractInt) { - continue; - } - let resolved_ty = resolved_arg_types[i]; - if !vm.bx.heap.pod_types[resolved_ty.index as usize] - .ty - .is_float_type() - { - continue; - } - let arg_index = explicit_start + i; - let value = parts[arg_index].trim(); - if Self::is_simple_int_literal(value) { - parts[arg_index] = format!("{}.0", value); - } - } - - parts.join(", ") - } - - fn split_call_args_top_level(raw_args: &str) -> Vec { - if raw_args.trim().is_empty() { - return Vec::new(); - } - let mut out = Vec::new(); - let mut start = 0usize; - let mut paren_depth = 0usize; - let mut bracket_depth = 0usize; - let mut brace_depth = 0usize; - - for (idx, ch) in raw_args.char_indices() { - match ch { - '(' => paren_depth += 1, - ')' => paren_depth = paren_depth.saturating_sub(1), - '[' => bracket_depth += 1, - ']' => bracket_depth = bracket_depth.saturating_sub(1), - '{' => brace_depth += 1, - '}' => brace_depth = brace_depth.saturating_sub(1), - ',' if paren_depth == 0 && bracket_depth == 0 && brace_depth == 0 => { - out.push(raw_args[start..idx].trim().to_string()); - start = idx + ch.len_utf8(); - } - _ => {} - } - } - - if start < raw_args.len() { - out.push(raw_args[start..].trim().to_string()); - } - out - } - - fn is_simple_int_literal(value: &str) -> bool { - !value.is_empty() - && value - .chars() - .all(|c| c.is_ascii_digit() || c == '-' || c == '+') - } - - pub(crate) fn handle_call_exec(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - // Only pop if the top of the stack is a call-related ME, not a control flow ME - // This prevents corrupting the ME stack when a call setup (CALL_ARGS/CALL_METHOD_ARGS) fails - let is_call_me = matches!( - self.mes.last(), - Some(ShaderMe::ArrayConstruct { .. }) - | Some(ShaderMe::Pod { .. }) - | Some(ShaderMe::ScriptCall { .. }) - | Some(ShaderMe::TextureBuiltin { .. }) - | Some(ShaderMe::BuiltinCall { .. }) - | Some(ShaderMe::PodBuiltinMethod { .. }) - ); - if !is_call_me { - // No call ME was pushed - the call setup must have failed - // Push a dummy value onto the stack so subsequent code doesn't break - let s = self.stack.new_string(); - self.stack.push(self.trap.pass(), ShaderType::Error(NIL), s); - return; - } - if let Some(me) = self.mes.pop() { - match me { - ShaderMe::ArrayConstruct { args, elem_ty } => { - self.handle_array_construct(vm, output, args, elem_ty); - } - ShaderMe::Pod { pod_ty, args } => { - self.handle_pod_construct(vm, output, pod_ty, args); - } - ShaderMe::ScriptCall { - out, - name, - fnobj, - sself, - args, - } => { - self.handle_script_call(vm, output, out, name, fnobj, sself, args); - } - ShaderMe::TextureBuiltin { - method_id, - tex_type, - texture_expr, - args, - } => { - self.handle_texture_builtin_exec( - vm, - output, - method_id, - tex_type, - texture_expr, - args, - ); - } - ShaderMe::BuiltinCall { - name, - fnptr: _, - args, - } => { - self.handle_builtin_call(vm, output, name, args); - } - ShaderMe::PodBuiltinMethod { - name, - self_ty: _, - args, - } => { - // Pod builtin method: x.mix(y, a) -> mix(x, y, a) - // Reuse the same logic as BuiltinCall - self.handle_builtin_call(vm, output, name, args); - } - _ => { - // This case should not be reached due to the guard at the top of handle_call_exec - script_err_not_impl!( - self.trap, - "CALL_EXEC: unexpected call type in shader (internal error)" - ); - } - } - } - } - - /// Handle a builtin function call (either from BuiltinCall or PodBuiltinMethod) - fn handle_builtin_call( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - name: LiveId, - args: Vec<(ShaderType, String)>, - ) { - let builtins = &vm.bx.code.builtins.pod; - - // Special case: discard() - emits backend-specific discard statement - if name == id!(discard) { - for (_, s) in args { - self.stack.free_string(s); - } - let mut out = self.stack.new_string(); - match output.backend { - // Metal: discard_fragment() is a function call - ShaderBackend::Metal => write!(out, "discard_fragment()").ok(), - // GLSL, WGSL, HLSL: discard is a keyword/statement (no parens) - ShaderBackend::Glsl | ShaderBackend::Wgsl | ShaderBackend::Hlsl => { - write!(out, "discard").ok() - } - ShaderBackend::Rust => write!(out, "{{ rcx.discard = 1.0; return }}").ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_void), out); - return; - } - - if name == id!(depth_clip) { - let mut concrete_args = Vec::new(); - let mut formatted_args = Vec::new(); - for (ty, s) in args { - concrete_args.push(ty.make_concrete(builtins).unwrap_or(builtins.pod_void)); - formatted_args.push(s); - } - - let mut out = self.stack.new_string(); - match output.backend { - ShaderBackend::Glsl => { - write!( - out, - "depth_clip({}, {}, {})", - formatted_args[0], formatted_args[1], formatted_args[2] - ) - .ok(); - } - ShaderBackend::Wgsl => { - write!( - out, - "depth_clip({}, {}, {})", - formatted_args[0], formatted_args[1], formatted_args[2] - ) - .ok(); - } - ShaderBackend::Metal | ShaderBackend::Hlsl | ShaderBackend::Rust => { - write!(out, "{}", formatted_args[1]).ok(); - } - } - - for s in formatted_args { - self.stack.free_string(s); - } - - let ret = type_table_builtin(name, &concrete_args, builtins, self.trap.pass()); - self.stack.push(self.trap.pass(), ShaderType::Pod(ret), out); - return; - } - - if name == id!(asuint) || name == id!(asint) || name == id!(asfloat) { - let mut concrete_args = Vec::new(); - let mut formatted_args = Vec::new(); - for (ty, s) in args { - concrete_args.push(ty.make_concrete(builtins).unwrap_or(builtins.pod_void)); - formatted_args.push(s); - } - - let arg = formatted_args.first().cloned().unwrap_or_default(); - let arg_ty = concrete_args.first().copied().unwrap_or(builtins.pod_void); - let mut out = self.stack.new_string(); - match name { - id!(asuint) => match output.backend { - ShaderBackend::Glsl => { - if arg_ty == builtins.pod_u32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "floatBitsToUint({arg})").ok(); - } - } - ShaderBackend::Wgsl => { - if arg_ty == builtins.pod_u32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "bitcast({arg})").ok(); - } - } - ShaderBackend::Hlsl => { - write!(out, "asuint({arg})").ok(); - } - ShaderBackend::Metal => { - write!(out, "as_type({arg})").ok(); - } - ShaderBackend::Rust => { - if arg_ty == builtins.pod_u32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "({arg}).to_bits()").ok(); - } - } - }, - id!(asint) => match output.backend { - ShaderBackend::Glsl => { - if arg_ty == builtins.pod_i32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "floatBitsToInt({arg})").ok(); - } - } - ShaderBackend::Wgsl => { - if arg_ty == builtins.pod_i32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "bitcast({arg})").ok(); - } - } - ShaderBackend::Hlsl => { - write!(out, "asint({arg})").ok(); - } - ShaderBackend::Metal => { - write!(out, "as_type({arg})").ok(); - } - ShaderBackend::Rust => { - if arg_ty == builtins.pod_i32 { - write!(out, "{arg}").ok(); - } else { - write!(out, "(({arg}).to_bits() as i32)").ok(); - } - } - }, - id!(asfloat) => match output.backend { - ShaderBackend::Glsl => { - if arg_ty == builtins.pod_f32 || arg_ty == builtins.pod_f16 { - write!(out, "{arg}").ok(); - } else if arg_ty == builtins.pod_i32 { - write!(out, "intBitsToFloat({arg})").ok(); - } else { - write!(out, "uintBitsToFloat({arg})").ok(); - } - } - ShaderBackend::Wgsl => { - if arg_ty == builtins.pod_f32 || arg_ty == builtins.pod_f16 { - write!(out, "{arg}").ok(); - } else { - write!(out, "bitcast({arg})").ok(); - } - } - ShaderBackend::Hlsl => { - write!(out, "asfloat({arg})").ok(); - } - ShaderBackend::Metal => { - write!(out, "as_type({arg})").ok(); - } - ShaderBackend::Rust => { - if arg_ty == builtins.pod_f32 || arg_ty == builtins.pod_f16 { - write!(out, "{arg}").ok(); - } else { - write!(out, "f32::from_bits(({arg}) as u32)").ok(); - } - } - }, - _ => {} - } - - for s in formatted_args { - self.stack.free_string(s); - } - - let ret = type_table_builtin(name, &concrete_args, builtins, self.trap.pass()); - self.stack.push(self.trap.pass(), ShaderType::Pod(ret), out); - return; - } - - // Check if any arg is a float type - if so, abstract ints should be floats - let has_float = args.iter().any(|(ty, _)| match ty { - ShaderType::Pod(pt) => vm.bx.heap.pod_types[pt.index as usize].ty.is_float_type(), - ShaderType::AbstractFloat => true, - _ => false, - }); - - // Build concrete args for type_table_builtin and format output - let mut concrete_args = Vec::new(); - let mut out = self.stack.new_string(); - let mapped_name = output.backend.map_builtin_name(name); - let hlsl_ctor_splat_len = - if matches!(output.backend, ShaderBackend::Hlsl) && args.len() == 1 { - match mapped_name { - id!(float2) | id!(half2) | id!(uint2) | id!(int2) | id!(bool2) => Some(2usize), - id!(float3) | id!(half3) | id!(uint3) | id!(int3) | id!(bool3) => Some(3usize), - id!(float4) | id!(half4) | id!(uint4) | id!(int4) | id!(bool4) => Some(4usize), - _ => None, - } - } else { - None - }; - - // For Rust backend, collect formatted args first so we can suffix the - // function name with the first-argument type (e.g. clamp_2f, max_2f) - let mut formatted_args = Vec::new(); - - for (i, (ty, s)) in args.into_iter().enumerate() { - let mut formatted = s.clone(); - match &ty { - ShaderType::AbstractInt | ShaderType::AbstractFloat => { - if has_float { - // Format as float literal - concrete_args.push(builtins.pod_f32); - // Check if s is a simple integer that needs .0 suffix - if s.chars().all(|c| c.is_ascii_digit() || c == '-') { - formatted.push_str(".0"); - } - } else { - concrete_args.push(ty.make_concrete(builtins).unwrap_or(builtins.pod_void)); - } - } - ShaderType::Pod(pt) => { - concrete_args.push(*pt); - } - _ => { - concrete_args.push(ty.make_concrete(builtins).unwrap_or(builtins.pod_void)); - } - } - - if i == 0 { - if let Some(n) = hlsl_ctor_splat_len { - for _j in 0..n { - formatted_args.push(formatted.clone()); - } - self.stack.free_string(s); - break; - } - } - formatted_args.push(formatted); - self.stack.free_string(s); - } - - let is_derivative_builtin = name == id!(dFdx) || name == id!(dFdy); - if is_derivative_builtin { - output.uses_derivatives = true; - } - - if matches!(output.backend, ShaderBackend::Wgsl) - && name == id!(modf) - && formatted_args.len() == 2 - { - // Script `modf(x, y)` means float modulo (fmod), while WGSL's `modf` - // builtin is fractional decomposition. Emit remainder expression directly. - write!(out, "(({}) % ({}))", formatted_args[0], formatted_args[1]).ok(); - let ret = type_table_builtin(name, &concrete_args, builtins, self.trap.pass()); - self.stack.push(self.trap.pass(), ShaderType::Pod(ret), out); - return; - } - - // For Rust backend, dFdx/dFdy are emitted as inline record/compute blocks - // using the 3-pass quad approach. In recording passes (quad_mode 0=dx, 1=dy), - // the value is stored into quad_dx_buf/quad_dy_buf. In compute pass (mode 2), - // the stored neighbor value is diffed against the current value. - if matches!(output.backend, ShaderBackend::Rust) - && is_derivative_builtin - && !formatted_args.is_empty() - { - let expr = &formatted_args[0]; - let is_dfdx = name == id!(dFdx); - // Determine number of f32 slots from the argument type - let first_ty = if !concrete_args.is_empty() { - concrete_args[0] - } else { - builtins.pod_f32 - }; - let slots = if first_ty == builtins.pod_vec4f { - 4 - } else if first_ty == builtins.pod_vec3f { - 3 - } else if first_ty == builtins.pod_vec2f { - 2 - } else { - 1 - }; - // The compute buffer: dFdx reads from quad_dx_buf, dFdy from quad_dy_buf - let compute_buf = if is_dfdx { - "quad_dx_buf" - } else { - "quad_dy_buf" - }; - let lane_field = if is_dfdx { - "quad_lane_x" - } else { - "quad_lane_y" - }; - - if slots == 1 { - write!( - out, - "{{ let __s = rcx.quad_slot as usize; rcx.quad_slot = rcx.quad_slot.saturating_add(1); \ - let __v: f32 = ({expr}); \ - if __s < rcx.quad_dx_buf.len() {{ \ - if rcx.quad_mode == 2 {{ let __d = rcx.{compute_buf}[__s] - __v; if rcx.{lane_field} == 0 {{ __d }} else {{ -__d }} }} \ - else {{ if rcx.quad_mode == 0 {{ rcx.quad_dx_buf[__s] = __v; }} \ - else {{ rcx.quad_dy_buf[__s] = __v; }}; 0.0f32 }} \ - }} else {{ 0.0f32 }} }}" - ) - .ok(); - } else if slots == 2 { - write!(out, - "{{ let __s = rcx.quad_slot as usize; rcx.quad_slot = rcx.quad_slot.saturating_add(2); \ - let __v: Vec2f = ({expr}); \ - if __s <= rcx.quad_dx_buf.len().saturating_sub(2) {{ \ - if rcx.quad_mode == 2 {{ let __d = vec2f(rcx.{compute_buf}[__s] - __v.x, rcx.{compute_buf}[__s+1] - __v.y); if rcx.{lane_field} == 0 {{ __d }} else {{ vec2f(-__d.x, -__d.y) }} }} \ - else {{ if rcx.quad_mode == 0 {{ rcx.quad_dx_buf[__s] = __v.x; rcx.quad_dx_buf[__s+1] = __v.y; }} \ - else {{ rcx.quad_dy_buf[__s] = __v.x; rcx.quad_dy_buf[__s+1] = __v.y; }}; vec2f(0.0, 0.0) }} \ - }} else {{ vec2f(0.0, 0.0) }} }}" - ).ok(); - } else if slots == 3 { - write!(out, - "{{ let __s = rcx.quad_slot as usize; rcx.quad_slot = rcx.quad_slot.saturating_add(3); \ - let __v: Vec3f = ({expr}); \ - if __s <= rcx.quad_dx_buf.len().saturating_sub(3) {{ \ - if rcx.quad_mode == 2 {{ let __d = vec3f(rcx.{compute_buf}[__s] - __v.x, rcx.{compute_buf}[__s+1] - __v.y, rcx.{compute_buf}[__s+2] - __v.z); if rcx.{lane_field} == 0 {{ __d }} else {{ vec3f(-__d.x, -__d.y, -__d.z) }} }} \ - else {{ if rcx.quad_mode == 0 {{ rcx.quad_dx_buf[__s] = __v.x; rcx.quad_dx_buf[__s+1] = __v.y; rcx.quad_dx_buf[__s+2] = __v.z; }} \ - else {{ rcx.quad_dy_buf[__s] = __v.x; rcx.quad_dy_buf[__s+1] = __v.y; rcx.quad_dy_buf[__s+2] = __v.z; }}; vec3f(0.0, 0.0, 0.0) }} \ - }} else {{ vec3f(0.0, 0.0, 0.0) }} }}" - ).ok(); - } else { - write!(out, - "{{ let __s = rcx.quad_slot as usize; rcx.quad_slot = rcx.quad_slot.saturating_add(4); \ - let __v: Vec4f = ({expr}); \ - if __s <= rcx.quad_dx_buf.len().saturating_sub(4) {{ \ - if rcx.quad_mode == 2 {{ let __d = vec4f(rcx.{compute_buf}[__s] - __v.x, rcx.{compute_buf}[__s+1] - __v.y, rcx.{compute_buf}[__s+2] - __v.z, rcx.{compute_buf}[__s+3] - __v.w); if rcx.{lane_field} == 0 {{ __d }} else {{ vec4f(-__d.x, -__d.y, -__d.z, -__d.w) }} }} \ - else {{ if rcx.quad_mode == 0 {{ rcx.quad_dx_buf[__s] = __v.x; rcx.quad_dx_buf[__s+1] = __v.y; rcx.quad_dx_buf[__s+2] = __v.z; rcx.quad_dx_buf[__s+3] = __v.w; }} \ - else {{ rcx.quad_dy_buf[__s] = __v.x; rcx.quad_dy_buf[__s+1] = __v.y; rcx.quad_dy_buf[__s+2] = __v.z; rcx.quad_dy_buf[__s+3] = __v.w; }}; vec4f(0.0, 0.0, 0.0, 0.0) }} \ - }} else {{ vec4f(0.0, 0.0, 0.0, 0.0) }} }}" - ).ok(); - } - } else { - // For Rust backend, append a type suffix for overloaded builtins - if matches!(output.backend, ShaderBackend::Rust) { - let needs_suffix = matches!( - name, - id if id == id!(clamp) - || id == id!(max) - || id == id!(min) - || id == id!(abs) - || id == id!(length) - || id == id!(dot) - || id == id!(normalize) - || id == id!(distance) - || id == id!(floor) - || id == id!(ceil) - || id == id!(fract) - || id == id!(round) - || id == id!(sign) - || id == id!(sqrt) - || id == id!(sin) - || id == id!(cos) - || id == id!(step) - || id == id!(smoothstep) - ); - if needs_suffix && !concrete_args.is_empty() { - let first_ty = concrete_args[0]; - let suffix = if first_ty == builtins.pod_vec2f { - "_2f" - } else if first_ty == builtins.pod_vec3f { - "_3f" - } else if first_ty == builtins.pod_vec4f { - "_4f" - } else { - "" - }; - write!(out, "{}{}(", mapped_name, suffix).ok(); - } else { - write!(out, "{}(", mapped_name).ok(); - } - } else { - write!(out, "{}(", mapped_name).ok(); - } - - for (i, formatted) in formatted_args.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(formatted); - } - - out.push_str(")"); - } - let ret = type_table_builtin(name, &concrete_args, builtins, self.trap.pass()); - self.stack.push(self.trap.pass(), ShaderType::Pod(ret), out); - } - - pub(crate) fn handle_texture_builtin_exec( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - method_id: LiveId, - tex_type: TextureType, - texture_expr: String, - args: Vec, - ) { - // Handle texture methods - these are virtual methods that transpile to backend-specific code - match method_id { - id!(size) => { - // size() returns vec2f with the texture dimensions - let mut s = self.stack.new_string(); - match output.backend { - ShaderBackend::Metal => { - // Metal: float2(texture.get_width(), texture.get_height()) - write!( - s, - "float2({}.get_width(), {}.get_height())", - texture_expr, texture_expr - ) - .ok(); - } - ShaderBackend::Wgsl => { - // WGSL: textureDimensions(texture) returns vec2, cast to vec2 - write!(s, "vec2f(textureDimensions({}))", texture_expr).ok(); - } - ShaderBackend::Hlsl => { - // HLSL: GetDimensions requires output params, use helper function - output.hlsl_needs_tex_size = true; - write!(s, "_mpTexSize2D({})", texture_expr).ok(); - } - ShaderBackend::Glsl => { - // GLSL: textureSize(texture, 0) returns ivec2, cast to vec2 - write!(s, "vec2(textureSize({}, 0))", texture_expr).ok(); - } - ShaderBackend::Rust => { - // Rust: texture.size() returns Vec2f - write!( - s, - "vec2({}.width as f32, {}.height as f32)", - texture_expr, texture_expr - ) - .ok(); - } - } - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec2f), - s, - ); - } - id!(sample) | id!(sample_as_bgra) | id!(sample_lod) | id!(sample_nearest) => { - // sample(coord) samples the texture at normalized coordinates. - // sample_as_bgra(coord) is identical except on WebGL GLSL, where it - // applies a BGRA->RGBA swizzle in the sampler helper. - let method_name = if method_id == id!(sample_as_bgra) { - "sample_as_bgra" - } else if method_id == id!(sample_nearest) { - "sample_nearest" - } else if method_id == id!(sample_lod) { - "sample_lod" - } else { - "sample" - }; - let required_args = if method_id == id!(sample_lod) { 2 } else { 1 }; - if args.len() != required_args { - script_err_invalid_args!( - self.trap, - "texture.{} requires {} arg{}", - method_name, - required_args, - if required_args == 1 { "" } else { "s" } - ); - let empty = self.stack.new_string(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec4f), - empty, - ); - } else { - let coord = &args[0]; - let lod = args.get(1); - let mut s = self.stack.new_string(); - - let sampler = if method_id == id!(sample_nearest) { - ShaderSampler { - filter: SamplerFilter::Nearest, - ..ShaderSampler::default() - } - } else { - ShaderSampler::default() - }; - let sampler_idx = output.get_or_create_sampler(sampler); - - match output.backend { - ShaderBackend::Metal => { - if let Some(lod) = lod { - write!( - s, - "{}.sample(_s{}, {}, level({}))", - texture_expr, sampler_idx, coord, lod - ) - .ok(); - } else { - // Metal: texture.sample(sampler, coord) - write!(s, "{}.sample(_s{}, {})", texture_expr, sampler_idx, coord) - .ok(); - } - } - ShaderBackend::Wgsl => { - if let Some(lod) = lod { - write!( - s, - "textureSampleLevel({}, _s{}, {}, {})", - texture_expr, sampler_idx, coord, lod - ) - .ok(); - } else { - // WGSL: textureSample(texture, sampler, coord) - write!( - s, - "textureSample({}, _s{}, {})", - texture_expr, sampler_idx, coord - ) - .ok(); - } - } - ShaderBackend::Hlsl => { - // D3D11 uses DXGI_FORMAT_B8G8R8A8_UNORM, so the GPU already - // interprets BGRA data as RGBA when sampling. No swizzle needed - // for sample_as_bgra (same as Metal). - let lod_expr = lod.map_or("0.0", |lod| lod.as_str()); - write!( - s, - "{}.SampleLevel(_s{}, {}, {})", - texture_expr, sampler_idx, coord, lod_expr - ) - .ok(); - } - ShaderBackend::Glsl => { - // GLSL ES uses runtime-bound sampler state (glBindSampler), - // so we sample via helper functions and track texture->sampler - // bindings separately in ShaderOutput. - output.bind_texture_sampler(&texture_expr, sampler_idx); - match tex_type { - TextureType::TextureCube | TextureType::TextureCubeArray => { - if let Some(lod) = lod { - write!( - s, - "samplecube_lod({}, {}, {})", - texture_expr, coord, lod - ) - .ok(); - } else if method_id == id!(sample_as_bgra) { - write!(s, "samplecube_bgra({}, {})", texture_expr, coord) - .ok(); - } else { - write!(s, "samplecube({}, {})", texture_expr, coord).ok(); - } - } - _ => { - if let Some(lod) = lod { - write!( - s, - "sample2d_lod({}, {}, {})", - texture_expr, coord, lod - ) - .ok(); - } else if method_id == id!(sample_as_bgra) { - write!(s, "sample2d_bgra({}, {})", texture_expr, coord) - .ok(); - } else { - write!(s, "sample2d({}, {})", texture_expr, coord).ok(); - } - } - } - } - ShaderBackend::Rust => { - // Rust headless backend keeps texture data in logical RGBA, - // so sample_as_bgra is a no-op alias of sample. - if let Some(lod) = lod { - write!(s, "{}.sample_lod({}, {})", texture_expr, coord, lod).ok(); - } else { - write!(s, "{}.sample({})", texture_expr, coord).ok(); - } - } - } - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec4f), - s, - ); - } - } - id!(sample_video) => { - // sample_video(coord) samples a video texture (platform external texture). - // In GLSL this calls sample2dOES() which is provided by the runtime preamble. - // On other backends, falls back to regular sample. - if args.len() != 1 { - script_err_invalid_args!(self.trap, "texture.sample_video requires 1 arg"); - let empty = self.stack.new_string(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec4f), - empty, - ); - } else { - let coord = &args[0]; - let mut s = self.stack.new_string(); - - match output.backend { - ShaderBackend::Glsl => { - let sampler = ShaderSampler::default(); - let sampler_idx = output.get_or_create_sampler(sampler); - output.bind_texture_sampler(&texture_expr, sampler_idx); - if cfg!(target_os = "android") && !output.use_vulkan { - write!(s, "sample2dOES({}, {})", texture_expr, coord).ok(); - } else { - write!(s, "sample2d({}, {})", texture_expr, coord).ok(); - } - } - ShaderBackend::Metal => { - let sampler = ShaderSampler::video(); - let sampler_idx = output.get_or_create_sampler(sampler); - write!(s, "{}.sample(_s{}, {})", texture_expr, sampler_idx, coord).ok(); - } - ShaderBackend::Wgsl => { - let sampler = ShaderSampler::default(); - let sampler_idx = output.get_or_create_sampler(sampler); - output.bind_texture_sampler(&texture_expr, sampler_idx); - write!( - s, - "textureSampleLevel({}, _s{}, {}, 0.0)", - texture_expr, sampler_idx, coord - ) - .ok(); - } - ShaderBackend::Hlsl => { - let sampler = ShaderSampler::video(); - let sampler_idx = output.get_or_create_sampler(sampler); - write!( - s, - "{}.SampleLevel(_s{}, {}, 0.0)", - texture_expr, sampler_idx, coord - ) - .ok(); - } - ShaderBackend::Rust => { - write!(s, "{}.sample({})", texture_expr, coord).ok(); - } - } - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec4f), - s, - ); - } - } - _ => { - script_err_not_found!( - self.trap, - "unknown texture method {:?}{}", - method_id, - suggest_from_live_ids( - method_id, - &[ - id!(sample), - id!(sample_as_bgra), - id!(sample_lod), - id!(sample_video), - id!(size) - ] - ) - ); - } - } - self.stack.free_string(texture_expr); - for arg in args { - self.stack.free_string(arg); - } - } - - pub(crate) fn handle_method_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - let (method_ty, method_s) = self.stack.pop(self.trap.pass()); - let (self_ty, self_s) = self.stack.pop(self.trap.pass()); - self.stack.free_string(method_s); - - if let ShaderType::Id(method_id) = method_ty { - // Handle method calls on Texture types (e.g., texture.size()) - if let ShaderType::Texture(tex_type) = self_ty { - self.handle_texture_method_call_args( - vm, output, opargs, method_id, tex_type, self_s, - ); - return; - } - - // Handle method calls on ScopeTexture types (e.g., scope_texture.sample()) - if let ShaderType::ScopeTexture { tex_type, .. } = self_ty { - self.handle_texture_method_call_args( - vm, output, opargs, method_id, tex_type, self_s, - ); - return; - } - - if let ShaderType::Id(self_id) = self_ty { - // Try to resolve as variable on shader scope - extract info before mutable borrows - let scope_info = self - .shader_scope - .find_var(self_id) - .map(|(var, _)| match var { - ShaderScopeItem::IoSelf(obj) => (Some(*obj), None), - _ => (None, Some(var.ty())), - }); - - if let Some((io_self_obj, pod_ty_opt)) = scope_info { - // Method call on IoSelf - if let Some(obj) = io_self_obj { - if self.handle_io_self_method_call_args( - vm, output, opargs, method_id, obj, &self_s, - ) { - self.stack.free_string(self_s); - return; - } - } - - // Method call on a Pod instance - if let Some(pod_ty) = pod_ty_opt { - let self_s_slice = if self_id == id!(self) { - // Rust and WGSL pass self as a pointer. - if matches!(output.backend, ShaderBackend::Rust | ShaderBackend::Wgsl) { - "(*_self)" - } else { - "_self" - } - } else { - &self_s - }; - if self.handle_pod_method_call_args( - vm, - output, - opargs, - method_id, - pod_ty, - self_s_slice, - &self_s, - ) { - return; - } - } - - // Method not found on the type - self.stack.free_string(self_s); - let type_name = if let Some(pod_ty) = pod_ty_opt { - vm.bx - .heap - .pod_type_name(pod_ty) - .map(|id| id.as_string(|s| s.unwrap_or("unknown").to_string())) - .unwrap_or_else(|| "unknown".to_string()) - } else { - format!("{:?}", self_id) - }; - script_err_not_found!( - self.trap, - "method {:?} not found on {}", - method_id, - type_name - ); - return; - } else { - // Try to resolve as PodType static method in script scope - if self.handle_pod_type_method_call_args( - vm, output, opargs, method_id, self_id, &self_s, - ) { - return; - } - - // Not a PodType - try as ScopeObject method call - if self.handle_scope_object_method_call_by_id( - vm, output, opargs, method_id, self_id, - ) { - self.stack.free_string(self_s); - return; - } - - // Try as scope texture method call (e.g., test_tex.sample(...)) - if self.handle_scope_texture_method_call_by_id( - vm, output, opargs, method_id, self_id, - ) { - self.stack.free_string(self_s); - return; - } - - // Nothing matched - variable or type not found - self.stack.free_string(self_s); - script_err_not_found!( - self.trap, - "method {:?} not found on {:?}", - method_id, - self_id - ); - return; - } - } - - // self_ty is directly a Pod type (not an Id that resolves to a Pod) - if let ShaderType::Pod(pod_ty) = self_ty { - if self.handle_pod_method_call_args( - vm, - output, - opargs, - method_id, - pod_ty, - &self_s.clone(), - &self_s, - ) { - return; - } - // Method not found on pod type - let type_name = vm - .bx - .heap - .pod_type_name(pod_ty) - .map(|id| id.as_string(|s| s.unwrap_or("unknown").to_string())) - .unwrap_or_else(|| "unknown".to_string()); - self.stack.free_string(self_s); - script_err_not_found!( - self.trap, - "method {:?} not found on {}", - method_id, - type_name - ); - return; - } - - // self_ty wasn't an Id or Pod - some other type - let type_name = self.shader_type_to_string(vm, &self_ty); - self.stack.free_string(self_s); - script_err_not_found!( - self.trap, - "method {:?} not found on {}", - method_id, - type_name - ); - return; - } - - self.stack.free_string(self_s); - script_err_not_impl!( - self.trap, - "METHOD_CALL_ARGS: method call syntax not valid here" - ); - } - - pub(crate) fn handle_io_self_method_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - method_id: LiveId, - obj: ScriptObject, - _self_s: &str, - ) -> bool { - let fnobj = vm.bx.heap.value(obj, method_id.into(), self.trap.pass()); - if let Some(fnobj) = fnobj.as_object() { - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - match fnptr { - ScriptFnPtr::Script(_fnptr) => { - let mut out = self.stack.new_string(); - write!(out, "{}", output.backend.get_io_all(output.mode)).ok(); - let io_self = output.backend.get_io_self(output.mode); - if !io_self.is_empty() { - if out.len() > 0 { - write!(out, ", ").ok(); - } - write!(out, "{}", io_self).ok(); - } - self.mes.push(ShaderMe::ScriptCall { - name: method_id, - out, - fnobj, - sself: ShaderType::IoSelf(obj), - args: vec![], - }); - } - ScriptFnPtr::Native(_) => { - todo!() - } - } - self.maybe_pop_to_me(vm, output, opargs); - return true; - } - } - false - } - - pub(crate) fn handle_scope_object_method_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - method_id: LiveId, - obj: ScriptObject, - ) -> bool { - // Look up the method on the scope object - let fnobj = vm.bx.heap.value(obj, method_id.into(), self.trap.pass()); - if let Some(fnobj) = fnobj.as_object() { - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - match fnptr { - ScriptFnPtr::Script(_fnptr) => { - // For ScopeObject methods, we only pass the io_all parameter - // since `self` references are resolved to IoScopeUniform accesses - // at compile time (no runtime _self parameter) - let mut out = self.stack.new_string(); - write!(out, "{}", output.backend.get_io_all(output.mode)).ok(); - self.mes.push(ShaderMe::ScriptCall { - name: method_id, - out, - fnobj, - sself: ShaderType::ScopeObject(obj), - args: vec![], - }); - } - ScriptFnPtr::Native(_) => { - // Native methods on scope objects not supported - script_err_shader!( - self.trap, - "native methods not supported on scope objects" - ); - return false; - } - } - self.maybe_pop_to_me(vm, output, opargs); - return true; - } - } - false - } - - /// Handle method call on a scope object identified by name (self_id). - /// This is called when PodType handling didn't match - we try to resolve - /// the identifier as a scope object and call the method on it. - pub(crate) fn handle_scope_object_method_call_by_id( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - method_id: LiveId, - self_id: LiveId, - ) -> bool { - // Look up self_id in script scope - let script_value = vm - .bx - .heap - .scope_value(self.script_scope, self_id.into(), NoTrap); - if script_value.is_nil() || script_value.is_err() { - return false; - } - - // Must be an object - let value_obj = match script_value.as_object() { - Some(obj) => obj, - None => return false, - }; - - // Must not be a shader_io type or a function - if vm.bx.heap.as_shader_io(value_obj).is_some() || vm.bx.heap.as_fn(value_obj).is_some() { - return false; - } - - // It's a scope object - handle the method call - self.handle_scope_object_method_call_args(vm, output, opargs, method_id, value_obj) - } - - /// Handle method call on a scope texture identified by name (self_id). - /// This is called for expressions like `test_tex.sample(coord)` where `test_tex` - /// is a texture defined in the script scope. - pub(crate) fn handle_scope_texture_method_call_by_id( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - _opargs: OpcodeArgs, - method_id: LiveId, - self_id: LiveId, - ) -> bool { - use crate::mod_shader::*; - use std::fmt::Write; - - // Look up self_id in script scope - let script_value = vm - .bx - .heap - .scope_value(self.script_scope, self_id.into(), NoTrap); - if script_value.is_nil() || script_value.is_err() { - return false; - } - - // Must be an object - let value_obj = match script_value.as_object() { - Some(obj) => obj, - None => return false, - }; - - // Must be a texture shader_io type - let io_type = match vm.bx.heap.as_shader_io(value_obj) { - Some(io_type) => io_type, - None => return false, - }; - - // Check if it's a texture type - let tex_type = match io_type { - SHADER_IO_TEXTURE_1D => TextureType::Texture1d, - SHADER_IO_TEXTURE_1D_ARRAY => TextureType::Texture1dArray, - SHADER_IO_TEXTURE_2D => TextureType::Texture2d, - SHADER_IO_TEXTURE_2D_ARRAY => TextureType::Texture2dArray, - SHADER_IO_TEXTURE_3D => TextureType::Texture3d, - SHADER_IO_TEXTURE_3D_ARRAY => TextureType::Texture3dArray, - SHADER_IO_TEXTURE_CUBE => TextureType::TextureCube, - SHADER_IO_TEXTURE_CUBE_ARRAY => TextureType::TextureCubeArray, - SHADER_IO_TEXTURE_DEPTH => TextureType::TextureDepth, - SHADER_IO_TEXTURE_DEPTH_ARRAY => TextureType::TextureDepthArray, - SHADER_IO_TEXTURE_VIDEO => TextureType::TextureVideo, - _ => return false, - }; - - // Check if we already have this scope texture registered - let existing = output.scope_textures.iter().find(|st| st.obj == value_obj); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - // Generate unique name for this scope texture - let shader_name = self.generate_scope_texture_name(output, self_id, value_obj); - - // Add to scope_textures for runtime tracking - output.scope_textures.push(ScopeTextureSource { - obj: value_obj, - tex_type, - shader_name, - }); - - // Add to IO list as Texture - if !output - .io - .iter() - .any(|io| io.name == shader_name && matches!(io.kind, ShaderIoKind::Texture(_))) - { - output.io.push(ShaderIo { - kind: ShaderIoKind::Texture(tex_type), - name: shader_name, - ty: ScriptPodType::VOID, // Textures don't have a pod type - buffer_index: None, - }); - } - - shader_name - }; - - // Generate the texture expression with proper prefix - let mut texture_expr = self.stack.new_string(); - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, io_type); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - write!(texture_expr, "{}{}", prefix, shader_name).ok() - } - ShaderIoPrefix::Full(full) => write!(texture_expr, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(texture_expr, "{}", full).ok(), - }; - - // Push TextureBuiltin ME to handle the method call - self.mes.push(ShaderMe::TextureBuiltin { - method_id, - tex_type, - texture_expr, - args: vec![], - }); - - true - } - - pub(crate) fn handle_pod_method_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - method_id: LiveId, - pod_ty: ScriptPodType, - self_s_slice: &str, - self_s: &String, - ) -> bool { - // First check for known shader builtin methods (mix, clamp, etc.) - // These translate to builtin shader functions: x.mix(y, a) -> mix(x, y, a) - if Self::is_pod_builtin_method(method_id) { - let mut self_arg = self.stack.new_string(); - write!(self_arg, "{}", self_s_slice).ok(); - self.mes.push(ShaderMe::PodBuiltinMethod { - name: method_id, - self_ty: pod_ty, - args: vec![(ShaderType::Pod(pod_ty), self_arg)], - }); - self.stack.free_string(self_s.clone()); - self.maybe_pop_to_me(vm, output, opargs); - return true; - } - - // Look up method on the pod type's object (use NoTrap to avoid error messages) - let pod_ty_data = &vm.bx.heap.pod_types[pod_ty.index as usize]; - let fnobj = vm - .bx - .heap - .value(pod_ty_data.object, method_id.into(), NoTrap); - - if let Some(fnobj) = fnobj.as_object() { - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - match fnptr { - ScriptFnPtr::Script(_fnptr) => { - let mut out = self.stack.new_string(); - write!(out, "{}", output.backend.get_io_all(output.mode)).ok(); - match output.backend { - ShaderBackend::Wgsl => { - if out.len() > 0 { - write!(out, ", ").ok(); - } - write!(out, "&{}", self_s_slice).ok(); - } - ShaderBackend::Metal => { - // Metal uses references (thread T&), not pointers - // Pass the variable directly without & - if out.len() > 0 { - write!(out, ", ").ok(); - } - write!(out, "{}", self_s_slice).ok(); - } - ShaderBackend::Hlsl | ShaderBackend::Glsl => { - if out.len() > 0 { - write!(out, ", ").ok(); - } - write!(out, "{}", self_s_slice).ok(); - } - ShaderBackend::Rust => { - if out.len() > 0 { - write!(out, ", ").ok(); - } - // If self_s_slice is "(*_self)", _self is already *mut T - if self_s_slice == "(*_self)" { - write!(out, "_self").ok(); - } else { - write!(out, "&mut {} as *mut _", self_s_slice).ok(); - } - } - } - self.mes.push(ShaderMe::ScriptCall { - name: method_id, - out, - fnobj, - sself: ShaderType::Pod(pod_ty), - args: vec![], - }); - } - ScriptFnPtr::Native(fnptr) => { - // Store self as first argument - let mut self_arg = self.stack.new_string(); - write!(self_arg, "{}", self_s_slice).ok(); - self.mes.push(ShaderMe::BuiltinCall { - name: method_id, - fnptr, - args: vec![(ShaderType::Pod(pod_ty), self_arg)], - }); - } - } - self.stack.free_string(self_s.clone()); - self.maybe_pop_to_me(vm, output, opargs); - return true; - } - } - - false - } - - /// Check if a method name is a known shader builtin that can be called on pod types - fn is_pod_builtin_method(method_id: LiveId) -> bool { - method_id == id!(mix) - || method_id == id!(clamp) - || method_id == id!(smoothstep) - || method_id == id!(step) - || method_id == id!(min) - || method_id == id!(max) - } - - pub(crate) fn handle_pod_type_method_call_args( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - method_id: LiveId, - self_id: LiveId, - self_s: &String, - ) -> bool { - let value = vm - .bx - .heap - .scope_value(self.script_scope, self_id.into(), self.trap.pass()); - if let Some(pod_ty) = vm.bx.heap.pod_type(value) { - self.ensure_struct_name(vm, output, pod_ty, self_id); - // It is a PodType. Look up static method. - let pod_ty_data = &vm.bx.heap.pod_types[pod_ty.index as usize]; - let fnobj = vm - .bx - .heap - .value(pod_ty_data.object, method_id.into(), self.trap.pass()); - - if let Some(fnobj) = fnobj.as_object() { - if let Some(fnptr) = vm.bx.heap.as_fn(fnobj) { - match fnptr { - ScriptFnPtr::Script(_fnptr) => { - let mut out = self.stack.new_string(); - write!(out, "{}", output.backend.get_io_all(output.mode)).ok(); - self.mes.push(ShaderMe::ScriptCall { - name: method_id, - out, - fnobj, - sself: ShaderType::PodType(pod_ty), - args: Default::default(), - }); - } - ScriptFnPtr::Native(fnptr) => { - self.mes.push(ShaderMe::BuiltinCall { - name: method_id, - fnptr, - args: Default::default(), - }); - } - } - self.stack.free_string(self_s.clone()); - self.maybe_pop_to_me(vm, output, opargs); - return true; - } - } - } - false - } - - pub(crate) fn handle_texture_method_call_args( - &mut self, - _vm: &mut ScriptVm, - _output: &mut ShaderOutput, - _opargs: OpcodeArgs, - method_id: LiveId, - tex_type: TextureType, - texture_expr: String, - ) { - // Push TextureBuiltin to collect arguments - actual code gen happens in handle_call_exec - self.mes.push(ShaderMe::TextureBuiltin { - method_id, - tex_type, - texture_expr, - args: vec![], - }); - } - - /// Expand a heterogeneous pod constructor to individual float components for Rust backend. - /// E.g., `vec4(vec3_expr, f32_expr)` → `vec3_expr.x, vec3_expr.y, vec3_expr.z, f32_expr` - /// and `vec2(f32_expr)` → `f32_expr, f32_expr` (splat) - fn rust_expand_pod_construct( - &self, - vm: &ScriptVm, - args: &[ShaderPodArg], - total_slots: usize, - ) -> String { - //let builtins = &vm.bx.code.builtins.pod; - let mut components = Vec::new(); - - for arg in args { - let arg_slots = match &arg.ty { - ShaderType::Pod(pt) | ShaderType::PodPtr(pt) => { - vm.bx.heap.pod_types[pt.index as usize].ty.slots() - } - // A bare variable reference reaches here unresolved — look it - // up in the scope, or `vec4(some_vec3, s)` counts it as one - // slot and the splat-fill below pads with repeated scalars. - ShaderType::Id(id) => self - .shader_scope - .find_var(*id) - .map(|(sc, _)| vm.bx.heap.pod_types[sc.ty().index as usize].ty.slots()) - .unwrap_or(1), - ShaderType::AbstractInt | ShaderType::AbstractFloat => 1, - _ => 1, - }; - - match arg_slots { - 1 => { - // Scalar: might need .0 suffix for abstract ints - let mut s = arg.s.clone(); - if matches!(arg.ty, ShaderType::AbstractInt) { - if s.chars().all(|c| c.is_ascii_digit() || c == '-') { - s.push_str(".0"); - } - } - components.push(s); - } - 2 => { - components.push(format!("{}.x", arg.s)); - components.push(format!("{}.y", arg.s)); - } - 3 => { - components.push(format!("{}.x", arg.s)); - components.push(format!("{}.y", arg.s)); - components.push(format!("{}.z", arg.s)); - } - 4 => { - components.push(format!("{}.x", arg.s)); - components.push(format!("{}.y", arg.s)); - components.push(format!("{}.z", arg.s)); - components.push(format!("{}.w", arg.s)); - } - _ => { - components.push(arg.s.clone()); - } - } - } - - // Handle splat: if we have fewer components than needed, repeat the last one - while components.len() < total_slots { - if let Some(last) = components.last().cloned() { - components.push(last); - } else { - components.push("0.0".to_string()); - } - } - - components.join(", ") - } -} diff --git a/vendor/makepad/platform/script/src/shader_control.rs b/vendor/makepad/platform/script/src/shader_control.rs deleted file mode 100644 index a88fb5a..0000000 --- a/vendor/makepad/platform/script/src/shader_control.rs +++ /dev/null @@ -1,655 +0,0 @@ -//! Shader control flow operations -//! -//! This module contains handle functions for control flow: if/else statements, -//! for loops, ranges, and return statements. - -use crate::opcode::*; -use crate::shader::*; -use crate::shader_backend::ShaderBackend; -use crate::shader_tables::*; -use crate::suggest::format_pod_type_name; -use crate::vm::*; -use crate::*; -use makepad_live_id::*; -use std::fmt::Write; - -impl ShaderFnCompiler { - /// Check if we're currently in unreachable code (after a return in the current branch) - pub(crate) fn is_unreachable(&self) -> bool { - // Check if ANY IfBody in the scope chain has returned (making subsequent code unreachable) - // or if the FnBody is fully escaped - for me in self.mes.iter().rev() { - match me { - ShaderMe::IfBody { has_return, .. } => { - if *has_return { - return true; - } - // Continue checking parent scopes - } - ShaderMe::FnBody { escaped, .. } => { - return *escaped; - } - _ => {} - } - } - false - } - - /// Check if the PARENT scope is unreachable (skipping the innermost IfBody) - /// Used for IF_ELSE to determine if the else branch should generate code - pub(crate) fn is_parent_scope_unreachable(&self) -> bool { - let mut skipped_first_if = false; - for me in self.mes.iter().rev() { - match me { - ShaderMe::IfBody { has_return, .. } => { - if !skipped_first_if { - // Skip the innermost IfBody (the one we're transitioning out of) - skipped_first_if = true; - continue; - } - if *has_return { - return true; - } - } - ShaderMe::FnBody { escaped, .. } => { - return *escaped; - } - _ => {} - } - } - false - } - - /// Find an outer IfBody's phi variable (skipping the innermost IfBody) and mark it as assigned. - /// Used when an inner if-block (like in match/else-if chains) has a value but no phi, - /// and we need to assign to an outer phi instead. - /// Returns the phi name if found, and sets `phi_assigned_by_inner` on the outer IfBody. - pub(crate) fn find_and_mark_outer_phi(&mut self) -> Option { - let mut skipped_first_if = false; - for me in self.mes.iter_mut().rev() { - if let ShaderMe::IfBody { - phi, - phi_assigned_by_inner, - .. - } = me - { - if !skipped_first_if { - // Skip the innermost IfBody (the one we're closing) - skipped_first_if = true; - continue; - } - // Found an outer IfBody - return its phi if present and mark it - if let Some(phi) = phi { - *phi_assigned_by_inner = true; - return Some(phi.clone()); - } - } - } - None - } - - pub(crate) fn handle_if_else_phi(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - // Loop to handle ALL IfBodies whose target_ip has been reached. - // This is important for match/else-if chains where multiple ifs end at the same position. - loop { - // Check if the last me is an IfBody that needs closing - let should_handle = if let Some(ShaderMe::IfBody { target_ip, .. }) = self.mes.last() { - self.trap.ip.index >= *target_ip - } else { - false - }; - - if !should_handle { - break; - } - - // Now extract the fields we need (we know it's an IfBody that needs handling) - if let Some(ShaderMe::IfBody { - target_ip: _, - phi, - start_pos, - stack_depth, - phi_type, - has_return, - if_branch_returned, - phi_assigned_by_inner, - created_unreachable: _, - }) = self.mes.last() - { - // Check if both branches returned (escape analysis) - let both_returned = *if_branch_returned && *has_return; - - // Clone/copy what we need before any mutable operations - let phi = phi.clone(); - let start_pos = *start_pos; - let stack_depth = *stack_depth; - let phi_type = phi_type.clone(); - let has_return = *has_return; - let phi_assigned_by_inner = *phi_assigned_by_inner; - - if self.stack.types.len() > stack_depth { - // Else branch has a value on the stack - let (ty, val) = self.pop_resolved(vm, output); - - // Check if the else value is void - let else_concrete = ty.make_concrete(&vm.bx.code.builtins.pod); - let else_is_void = else_concrete - .map(|t| t == vm.bx.code.builtins.pod.pod_void) - .unwrap_or(false); - - if else_is_void { - // Emit void value as statement - if !val.is_empty() { - self.out.push_str(&val); - self.out.push_str(";\n"); - } - } else if let Some(ref phi) = phi { - if let Some(ref phi_type) = phi_type { - // declare the phi at start - let ty = type_table_if_else( - phi_type, - &ty, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ); - let ty = ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - - // Skip phi handling if type is void - if ty != vm.bx.code.builtins.pod.pod_void { - self.out.push_str(&format!("{} = {};\n", phi, val)); - let ty_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - // Generate backend-appropriate variable declaration with zero init - let mut s = self.stack.new_string(); - output - .backend - .write_var_decl_zero_init(&mut s, ty_name, phi); - self.out.insert_str(start_pos, &s); - self.stack.free_string(s); - let mut s = self.stack.new_string(); - write!(s, "{}", phi).ok(); - self.stack.push(self.trap.pass(), ShaderType::Pod(ty), s); - } - } - } else { - // No phi for this IfBody, but we have a non-void value. - // This happens in match/else-if chains where inner if has no else. - // Look for an outer IfBody's phi to assign to. - let outer_phi = self.find_and_mark_outer_phi(); - if let Some(outer_phi) = outer_phi { - // Assign to the outer phi (flag is already set by find_and_mark_outer_phi) - self.out.push_str(&format!("{} = {};\n", outer_phi, val)); - } - // If no outer phi, the value is discarded (this shouldn't happen in well-formed code) - } - self.stack.free_string(val); - } else if let Some(ref phi) = phi { - // If branch had a value (created phi) but else branch has no value on stack. - // This can happen in two cases: - // 1. Only if-branch has value (else is statement-only) - don't push result - // 2. Inner if assigned to our phi (match/else-if) - push result - if let Some(ref phi_type) = phi_type { - let ty = phi_type - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - - // Skip phi handling if type is void - if ty != vm.bx.code.builtins.pod.pod_void { - let ty_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - // Generate backend-appropriate variable declaration with zero init - let mut s = self.stack.new_string(); - output - .backend - .write_var_decl_zero_init(&mut s, ty_name, phi); - self.out.insert_str(start_pos, &s); - self.stack.free_string(s); - - // If inner code assigned to our phi, push the result onto the stack - if phi_assigned_by_inner { - let mut s = self.stack.new_string(); - write!(s, "{}", phi).ok(); - self.stack.push(self.trap.pass(), ShaderType::Pod(ty), s); - } - } - } - } else if has_return { - // If branch had a return with no else branch and no phi value. - // The following POP_TO_ME opcode expects a value but there isn't one. - // Skip it to avoid stack underflow. - self.skip_next_pop_to_me = true; - } - self.out.push_str("}\n"); - self.shader_scope.exit_scope(); - self.mes.pop(); - - // If both branches returned, propagate escape status up - if both_returned { - // Find the parent and mark it as having returned/escaped - if let Some(parent) = self.mes.last_mut() { - match parent { - ShaderMe::IfBody { has_return, .. } => { - *has_return = true; - } - ShaderMe::FnBody { escaped, .. } => { - *escaped = true; - } - _ => {} - } - } - } - } else { - // Shouldn't happen since we checked above - break; - } - } - } - - pub(crate) fn handle_if_test(&mut self, opargs: OpcodeArgs) { - let (_ty, val) = self.stack.pop(self.trap.pass()); - let start_pos = self.out.len(); - self.out.push_str("if("); - self.out.push_str(&val); - self.out.push_str("){\n"); - self.shader_scope.enter_scope(); - self.stack.free_string(val); - - self.mes.push(ShaderMe::IfBody { - target_ip: self.trap.ip.index + opargs.to_u32(), - start_pos, - stack_depth: self.stack.types.len(), - phi: None, - phi_type: None, - has_return: false, - if_branch_returned: false, - phi_assigned_by_inner: false, - created_unreachable: false, - }); - } - - /// Handle IF_TEST when in unreachable code - don't generate code or pop stack, - /// but track the control structure so we can properly close it - pub(crate) fn handle_if_test_unreachable(&mut self, opargs: OpcodeArgs) { - // Don't pop from stack or generate code - just track the structure - // Mark has_return: true since we're already in unreachable code - // Mark created_unreachable: true so we don't emit closing } later - self.mes.push(ShaderMe::IfBody { - target_ip: self.trap.ip.index + opargs.to_u32(), - start_pos: self.out.len(), - stack_depth: self.stack.types.len(), - phi: None, - phi_type: None, - has_return: true, // Already unreachable, so this branch is "returned" - if_branch_returned: false, - phi_assigned_by_inner: false, - created_unreachable: true, // No code emitted for this if block - }); - } - - pub(crate) fn handle_if_else( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - let popped = if let Some(ShaderMe::IfBody { stack_depth, .. }) = self.mes.last() { - if self.stack.types.len() > *stack_depth { - Some(self.pop_resolved(vm, output)) - } else { - None - } - } else { - None - }; - - if let Some(ShaderMe::IfBody { - target_ip, - start_pos, - stack_depth: _, - phi, - phi_type, - has_return, - if_branch_returned, - phi_assigned_by_inner: _, - created_unreachable: _, - }) = self.mes.last_mut() - { - if let Some((ty, val)) = popped { - // Check if the type is void - if so, don't create a phi, just emit as statement - let concrete_ty = ty.make_concrete(&vm.bx.code.builtins.pod); - let is_void = concrete_ty - .map(|t| t == vm.bx.code.builtins.pod.pod_void) - .unwrap_or(false); - - if is_void { - // Emit as statement without phi assignment - if !val.is_empty() { - self.out.push_str(&val); - self.out.push_str(";\n"); - } - } else { - *phi_type = Some(ty); - let phi_name = if let Some(p) = phi { - p.clone() - } else { - let s = format!("_phi_{}", start_pos); - *phi = Some(s.clone()); - s - }; - self.out.push_str(&format!("{} = {};\n", phi_name, val)); - } - self.stack.free_string(val); - } - self.out.push_str("}\nelse{\n"); - self.shader_scope.exit_scope(); - self.shader_scope.enter_scope(); - *target_ip = self.trap.ip.index + opargs.to_u32(); - // Save whether the if-branch returned, reset has_return for else branch - *if_branch_returned = *has_return; - *has_return = false; - } else { - script_err_unexpected!(self.trap, "unexpected in shader control"); - } - } - - /// Handle IF_ELSE when in unreachable code - just update structure, no code generation - pub(crate) fn handle_if_else_unreachable(&mut self, opargs: OpcodeArgs) { - if let Some(ShaderMe::IfBody { - target_ip, - has_return, - if_branch_returned, - .. - }) = self.mes.last_mut() - { - *target_ip = self.trap.ip.index + opargs.to_u32(); - // Save whether the if-branch "returned", keep has_return true since we're unreachable - *if_branch_returned = *has_return; - // Keep has_return true since we're in unreachable code - else branch is also unreachable - *has_return = true; - } - } - - /// Handle if/else phi when in unreachable code - close the structure properly - pub(crate) fn handle_if_else_phi_unreachable(&mut self) { - if let Some(ShaderMe::IfBody { - target_ip, - has_return, - if_branch_returned, - created_unreachable, - .. - }) = self.mes.last() - { - if self.trap.ip.index >= *target_ip { - let both_returned = *if_branch_returned && *has_return; - let was_created_unreachable = *created_unreachable; - - // Only emit closing brace if code was actually generated for this if block - // If created_unreachable is true, no `if(...){` was emitted, so no `}` needed - if !was_created_unreachable { - self.out.push_str("}\n"); - self.shader_scope.exit_scope(); - } - self.mes.pop(); - - // If both branches returned, propagate up - if both_returned { - if let Some(parent) = self.mes.last_mut() { - match parent { - ShaderMe::IfBody { has_return, .. } => { - *has_return = true; - } - ShaderMe::FnBody { escaped, .. } => { - *escaped = true; - } - _ => {} - } - } - } - } - } - } - - pub(crate) fn handle_return( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - // Check if we're already escaped (all code paths have returned) - let already_escaped = self - .mes - .iter() - .rev() - .find_map(|me| match me { - ShaderMe::FnBody { escaped, .. } => Some(*escaped), - _ => None, - }) - .unwrap_or(false); - - if already_escaped { - // Still need to consume the stack value if present - if !opargs.is_nil() { - let (_ty, s) = self.stack.pop(self.trap.pass()); - self.stack.free_string(s); - } - return; - } - - // Check if we're inside an IfBody before taking mutable borrow - let inside_if = self - .mes - .iter() - .any(|me| matches!(me, ShaderMe::IfBody { .. })); - - // Pop and resolve the return value BEFORE borrowing self.mes mutably - // Use pop_resolved to resolve Id types (like variable names) to their actual Pod types - let (ty, s) = if opargs.is_nil() { - (vm.bx.code.builtins.pod.pod_void, self.stack.new_string()) - } else { - let (ty, s) = self.pop_resolved(vm, output); - let ty = ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - (ty, s) - }; - - // Find our FnBody to record return type - if let Some(me) = self - .mes - .iter_mut() - .rev() - .find(|v| matches!(v, ShaderMe::FnBody { .. })) - { - if let ShaderMe::FnBody { ret, escaped, .. } = me { - if let Some(ret) = ret { - if ty != *ret { - script_err_inconsistent!(self.trap, "return type changed"); - } - } - *ret = Some(ty); - - if ty == vm.bx.code.builtins.pod.pod_void { - self.out.push_str(&s); - self.out.push_str(";\nreturn;\n"); - } else { - self.out.push_str("return "); - self.out.push_str(&s); - self.out.push_str(";\n"); - } - - // If not inside an IfBody (return at function level), mark function as escaped - if !inside_if { - *escaped = true; - } - } - } - - self.stack.free_string(s); - - // Mark the innermost IfBody as having a return - if let Some(me) = self - .mes - .iter_mut() - .rev() - .find(|v| matches!(v, ShaderMe::IfBody { .. })) - { - if let ShaderMe::IfBody { has_return, .. } = me { - *has_return = true; - } - } - - // NOTE: For a transpiler (unlike an interpreter), we do NOT set the trap here. - // The interpreter sets ScriptTrapOn::Return to actually return control flow, - // but the transpiler just generates code and must continue processing all opcodes - // to properly close if/else blocks and other control structures. - // The compile_fn loop uses fn_end_index (derived from FN_BODY_DYN's opargs) to know - // when to stop, rather than relying on the Return trap. - } - - pub(crate) fn handle_for_1(&mut self, vm: &mut ScriptVm, backend: &ShaderBackend) { - let (source, _) = self.stack.pop(self.trap.pass()); - let (val_id, _) = self.stack.pop(self.trap.pass()); - if let ShaderType::Range { start, end, mut ty } = source { - if let ShaderType::Id(id) = val_id { - // Shader for loops only support u32 for now. - // If the range is abstract int or i32, we cast it to u32. - if ty == vm.bx.code.builtins.pod.pod_i32 { - ty = vm.bx.code.builtins.pod.pod_u32; - } - - if ty != vm.bx.code.builtins.pod.pod_u32 { - script_err_type_mismatch!( - self.trap, - "shader for loop only supports u32 range, got {}", - format_pod_type_name(&vm.bx.heap, ty) - ); - } - self.shader_scope.enter_scope(); - let shadow = self.shader_scope.define_var(id, ty); - let loop_var_name = backend.map_local_name(id, shadow); - let ty_name = backend.map_pod_name(id!(u32)); - match backend { - ShaderBackend::Wgsl => { - write!( - self.out, - "for(var {0}: {3} = {1}; {0} < {2}; {0}++){{\n", - loop_var_name, start, end, ty_name - ) - .ok(); - } - ShaderBackend::Rust => { - write!( - self.out, - "for {0} in {1}..{2} {{\n", - loop_var_name, start, end - ) - .ok(); - } - ShaderBackend::Glsl => { - // GLSL ES 3.0 disallows implicit casts from int to uint, - // so we must explicitly cast the bounds to the loop variable type. - write!( - self.out, - "for({3} {0} = {3}({1}); {0} < {3}({2}); {0}++){{\n", - loop_var_name, start, end, ty_name - ) - .ok(); - } - _ => { - write!( - self.out, - "for({3} {0} = {1}; {0} < {2}; {0}++){{\n", - loop_var_name, start, end, ty_name - ) - .ok(); - } - } - self.mes.push(ShaderMe::ForLoop { - var_id: id, - stack_depth: self.stack.types.len(), - }); - } else { - script_err_unexpected!(self.trap, "unexpected in shader control"); - } - } else { - script_err_unexpected!(self.trap, "unexpected in shader control"); - } - } - - pub(crate) fn handle_for_end(&mut self) { - if let Some(me) = self.mes.pop() { - match me { - ShaderMe::ForLoop { .. } | ShaderMe::LoopBody { .. } => { - self.out.push_str("}\n"); - self.shader_scope.exit_scope(); - } - _ => { - script_err_unexpected!(self.trap, "unexpected in shader control"); - } - } - } else { - script_err_unexpected!(self.trap, "unexpected in shader control"); - } - } - - pub(crate) fn handle_loop(&mut self) { - self.shader_scope.enter_scope(); - self.out.push_str("while(true){\n"); - self.mes.push(ShaderMe::LoopBody { - stack_depth: self.stack.types.len(), - }); - } - - pub(crate) fn handle_break(&mut self) { - self.out.push_str("break;\n"); - } - - pub(crate) fn handle_breakifnot(&mut self) { - let (_ty, cond_s) = self.stack.pop(self.trap.pass()); - write!(self.out, "if(!({cond_s})){{break;}}\n").ok(); - } - - pub(crate) fn handle_continue(&mut self) { - self.out.push_str("continue;\n"); - } - - pub(crate) fn handle_range(&mut self, vm: &mut ScriptVm) { - let (end_ty, end_s) = self.stack.pop(self.trap.pass()); - let (start_ty, start_s) = self.stack.pop(self.trap.pass()); - // Validate that both operands can be made into concrete numeric types - let start_concrete = start_ty.make_concrete(&vm.bx.code.builtins.pod); - let end_concrete = end_ty.make_concrete(&vm.bx.code.builtins.pod); - if let (Some(start_pod), Some(end_pod)) = (start_concrete, end_concrete) { - // Check that both are numeric types - let start_is_number = vm.bx.heap.pod_type_ref(start_pod).ty.is_number(); - let end_is_number = vm.bx.heap.pod_type_ref(end_pod).ty.is_number(); - if !start_is_number || !end_is_number { - self.stack.free_string(start_s); - self.stack.free_string(end_s); - script_err_type_mismatch!(self.trap, "range requires numbers"); - return; - } - self.stack.push( - self.trap.pass(), - ShaderType::Range { - start: start_s, - end: end_s, - ty: start_pod, - }, - String::new(), - ); - } else { - self.stack.free_string(start_s); - self.stack.free_string(end_s); - script_err_type_mismatch!(self.trap, "range requires numbers"); - } - } -} diff --git a/vendor/makepad/platform/script/src/shader_glsl.rs b/vendor/makepad/platform/script/src/shader_glsl.rs deleted file mode 100644 index 2ffe5e8..0000000 --- a/vendor/makepad/platform/script/src/shader_glsl.rs +++ /dev/null @@ -1,835 +0,0 @@ -use crate::pod::{ScriptPodTy, ScriptPodTypeInline}; -use crate::shader::{ShaderIoKind, ShaderOutput, TextureType}; -use crate::value::ScriptPodType; -use crate::vm::ScriptVm; -use makepad_live_id::{id, LiveId}; -use std::collections::BTreeSet; -use std::fmt::Write; - -#[derive(Clone, Copy, PartialEq, Eq)] -enum GlslPackedFormat { - Float, - UInt, - SInt, -} - -#[derive(Clone, Copy, PartialEq, Eq)] -enum GlslPackedSource { - NumericFloat, - BitPackedFloat, -} - -#[derive(Clone)] -struct GlslPackedField { - name: String, - ty: ScriptPodType, - slots: usize, - offset: usize, -} - -impl ShaderOutput { - pub fn glsl_create_vertex_shader(&self, vm: &ScriptVm, shared_defs: &str, out: &mut String) { - let geometry_fields = self.glsl_collect_geometry_fields(vm); - let instance_fields = self.glsl_collect_instance_fields(vm); - let varying_fields = self.glsl_collect_varying_pack_fields(vm); - - let varying_slots = varying_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - - out.push_str(shared_defs); - self.glsl_write_uniform_blocks(vm, out); - self.glsl_write_texture_uniforms(out); - self.glsl_write_vertex_globals(vm, out); - self.glsl_write_vertex_input_attrs(&geometry_fields, &instance_fields, out); - self.glsl_write_varying_interface(varying_slots, true, out); - let vertex_entry = self.backend.map_function_name("io_vertex"); - self.glsl_write_functions_for_entries(out, &[vertex_entry.as_str()]); - self.glsl_write_vertex_main(vm, &geometry_fields, &instance_fields, &varying_fields, out); - } - - pub fn glsl_create_fragment_shader(&self, vm: &ScriptVm, shared_defs: &str, out: &mut String) { - let varying_fields = self.glsl_collect_varying_pack_fields(vm); - let varying_slots = varying_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - - out.push_str(shared_defs); - self.glsl_write_uniform_blocks(vm, out); - self.glsl_write_texture_uniforms(out); - self.glsl_write_fragment_globals(vm, out); - self.glsl_write_varying_interface(varying_slots, false, out); - self.glsl_write_fragment_outputs(vm, out); - let fragment_entry = self.backend.map_function_name("io_fragment"); - self.glsl_write_functions_for_entries(out, &[fragment_entry.as_str()]); - self.glsl_write_fragment_main(vm, &varying_fields, out); - } - - fn glsl_write_uniform_blocks(&self, vm: &ScriptVm, out: &mut String) { - for io in &self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - let block_name = self.glsl_uniform_block_name(io.name); - let io_name = self.backend.map_io_name(io.name); - if io_name == "draw_pass" - && self.glsl_write_draw_pass_uniform_block( - vm, - io.ty, - &block_name, - &io_name, - out, - ) - { - continue; - } - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - writeln!(out, "layout(std140) uniform {} {{", block_name).ok(); - writeln!(out, " {} unibuf_{};", type_name, io_name).ok(); - writeln!(out, "}};").ok(); - } - } - - let mut has_uniforms = false; - for io in &self.io { - if matches!(io.kind, ShaderIoKind::Uniform) { - if !has_uniforms { - writeln!(out, "layout(std140) uniform userUniforms {{").ok(); - has_uniforms = true; - } - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " {} uni_{};", type_name, io_name).ok(); - } - } - if has_uniforms { - writeln!(out, "}};").ok(); - } - - let mut has_scope_uniforms = false; - for io in &self.io { - if matches!(io.kind, ShaderIoKind::ScopeUniform) { - if !has_scope_uniforms { - writeln!(out, "layout(std140) uniform liveUniforms {{").ok(); - has_scope_uniforms = true; - } - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " {} su_{};", type_name, io_name).ok(); - } - } - if has_scope_uniforms { - writeln!(out, "}};").ok(); - } - } - - fn glsl_write_draw_pass_uniform_block( - &self, - vm: &ScriptVm, - ty: ScriptPodType, - block_name: &str, - io_name: &str, - out: &mut String, - ) -> bool { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let ScriptPodTy::Struct { fields, .. } = &pod_ty.ty else { - return false; - }; - - writeln!(out, "layout(std140) uniform {} {{", block_name).ok(); - for field in fields { - let field_name = self.backend.map_field_name(field.name); - let type_name = self.glsl_type_name_inline(&field.ty); - match field_name.as_str() { - "camera_projection" | "camera_view" | "depth_projection" | "depth_view" - | "camera_inv" => { - writeln!(out, " {} {}[2];", type_name, field_name).ok(); - } - "camera_projection_r" - | "camera_view_r" - | "depth_projection_r" - | "depth_view_r" - | "camera_inv_r" => {} - _ => { - writeln!(out, " {} {};", type_name, field_name).ok(); - } - } - } - writeln!(out, "}} unibuf_{};", io_name).ok(); - true - } - - fn glsl_write_texture_uniforms(&self, out: &mut String) { - for io in &self.io { - if let ShaderIoKind::Texture(tex_type) = io.kind { - let tex_name = self.backend.map_io_name(io.name); - writeln!( - out, - "uniform {} tex_{};", - self.glsl_sampler_type(tex_type), - tex_name - ) - .ok(); - } - } - } - - fn glsl_write_vertex_globals(&self, vm: &ScriptVm, out: &mut String) { - // Keep the vertex position register available as a global for shaders - // that write `self.pos` directly instead of returning a vec4 from io_vertex(). - writeln!(out, "vec4 vtx_pos;").ok(); - for io in &self.io { - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - let io_name = self.backend.map_io_name(io.name); - match io.kind { - ShaderIoKind::VertexBuffer => { - writeln!(out, "{} vb_{};", type_name, io_name).ok(); - } - ShaderIoKind::DynInstance => { - writeln!(out, "{} dyninst_{};", type_name, io_name).ok(); - } - ShaderIoKind::RustInstance => { - writeln!(out, "{} rustinst_{};", type_name, io_name).ok(); - } - ShaderIoKind::Varying => { - writeln!(out, "{} var_{};", type_name, io_name).ok(); - } - _ => {} - } - } - } - - fn glsl_write_fragment_globals(&self, vm: &ScriptVm, out: &mut String) { - for io in &self.io { - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - let io_name = self.backend.map_io_name(io.name); - match io.kind { - ShaderIoKind::DynInstance => { - writeln!(out, "{} dyninst_{};", type_name, io_name).ok(); - } - ShaderIoKind::RustInstance => { - writeln!(out, "{} rustinst_{};", type_name, io_name).ok(); - } - ShaderIoKind::Varying => { - writeln!(out, "{} var_{};", type_name, io_name).ok(); - } - ShaderIoKind::FragmentOutput(index) => { - writeln!(out, "{} frag_fb{};", type_name, index).ok(); - } - _ => {} - } - } - } - - fn glsl_write_vertex_input_attrs( - &self, - geometry_fields: &[GlslPackedField], - instance_fields: &[GlslPackedField], - out: &mut String, - ) { - let geometry_slots = geometry_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - let instance_slots = instance_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - for idx in 0..Self::glsl_num_packed_vec4s(geometry_slots) { - writeln!(out, "in vec4 packed_geometry_{};", idx).ok(); - } - for idx in 0..Self::glsl_num_packed_vec4s(instance_slots) { - writeln!(out, "in vec4 packed_instance_{};", idx).ok(); - } - } - - fn glsl_write_varying_interface( - &self, - varying_slots: usize, - is_vertex: bool, - out: &mut String, - ) { - let qualifier = if is_vertex { "out" } else { "in" }; - for idx in 0..Self::glsl_num_packed_vec4s(varying_slots) { - writeln!(out, "{} vec4 packed_varying_{};", qualifier, idx).ok(); - } - } - - fn glsl_write_fragment_outputs(&self, vm: &ScriptVm, out: &mut String) { - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - let type_name = self.glsl_type_name_from_ty(vm, io.ty); - writeln!( - out, - "layout(location = {}) out {} _mp_frag_{};", - index, type_name, index - ) - .ok(); - } - } - } - - fn glsl_write_vertex_main( - &self, - vm: &ScriptVm, - geometry_fields: &[GlslPackedField], - instance_fields: &[GlslPackedField], - varying_fields: &[GlslPackedField], - out: &mut String, - ) { - writeln!(out, "void main() {{").ok(); - for field in geometry_fields { - self.glsl_unpack_field_to_statements( - vm, - field, - "packed_geometry_", - GlslPackedSource::BitPackedFloat, - out, - ); - } - for field in instance_fields { - self.glsl_unpack_field_to_statements( - vm, - field, - "packed_instance_", - GlslPackedSource::BitPackedFloat, - out, - ); - } - writeln!(out, " vtx_pos = vec4(0.0, 0.0, 0.0, 1.0);").ok(); - - let vertex_returns_vec4f = self - .functions - .iter() - .find(|f| f.name == id!(vertex)) - .map(|f| f.ret == vm.bx.code.builtins.pod.pod_vec4f) - .unwrap_or(false); - let vertex_fn_name = self.backend.map_function_name("io_vertex"); - - if vertex_returns_vec4f { - writeln!(out, " vtx_pos = {}();", vertex_fn_name).ok(); - } else { - writeln!(out, " {}();", vertex_fn_name).ok(); - } - - for field in varying_fields { - let mut scalars = Vec::new(); - self.glsl_flatten_exprs(vm, field.ty, &field.name, &mut scalars); - for slot in 0..field.slots { - let src = scalars - .get(slot) - .cloned() - .unwrap_or_else(|| "0.0".to_string()); - let dst = Self::glsl_packed_component("packed_varying_", field.offset + slot); - writeln!(out, " {} = {};", dst, src).ok(); - } - } - writeln!(out, " gl_Position = vtx_pos;").ok(); - writeln!(out, "}}").ok(); - } - - fn glsl_write_fragment_main( - &self, - vm: &ScriptVm, - varying_fields: &[GlslPackedField], - out: &mut String, - ) { - writeln!(out, "void main() {{").ok(); - for field in varying_fields { - self.glsl_unpack_field_to_statements( - vm, - field, - "packed_varying_", - GlslPackedSource::NumericFloat, - out, - ); - } - let fragment_fn_name = self.backend.map_function_name("io_fragment"); - writeln!(out, " {}();", fragment_fn_name).ok(); - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - writeln!(out, " _mp_frag_{} = frag_fb{};", index, index).ok(); - } - } - writeln!(out, "}}").ok(); - } - - fn glsl_write_functions_for_entries(&self, out: &mut String, entries: &[&str]) { - let reachable = self.glsl_collect_reachable_functions(entries); - for (index, fns) in self.functions.iter().enumerate() { - if !reachable.contains(&index) { - continue; - } - writeln!(out, "{}{{", fns.call_sig).ok(); - writeln!(out, "{}", fns.out).ok(); - writeln!(out, "}}\n").ok(); - } - } - - fn glsl_collect_reachable_functions(&self, entries: &[&str]) -> BTreeSet { - let mut reachable = BTreeSet::new(); - let mut work = Vec::new(); - let function_names: Vec = self - .functions - .iter() - .filter_map(|func| Self::glsl_function_name_from_sig(&func.call_sig)) - .collect(); - - if function_names.len() != self.functions.len() { - // If we failed to parse any signature, fall back to including everything. - return (0..self.functions.len()).collect(); - } - - for entry in entries { - for (index, name) in function_names.iter().enumerate() { - if name == entry && reachable.insert(index) { - work.push(index); - } - } - } - - while let Some(current) = work.pop() { - let body = &self.functions[current].out; - for (index, name) in function_names.iter().enumerate() { - if reachable.contains(&index) { - continue; - } - if Self::glsl_body_calls_function(body, name) { - reachable.insert(index); - work.push(index); - } - } - } - - reachable - } - - fn glsl_function_name_from_sig(call_sig: &str) -> Option { - let open_paren = call_sig.find('(')?; - let head = call_sig[..open_paren].trim_end(); - let name = head.split_whitespace().next_back()?; - Some(name.to_string()) - } - - fn glsl_body_calls_function(body: &str, function_name: &str) -> bool { - let pattern = format!("{}(", function_name); - let mut search_start = 0; - while let Some(pos) = body[search_start..].find(&pattern) { - let abs = search_start + pos; - let prev = body[..abs].chars().next_back(); - let prev_is_ident = prev - .map(|c| c.is_ascii_alphanumeric() || c == '_') - .unwrap_or(false); - if !prev_is_ident { - return true; - } - search_start = abs + pattern.len(); - } - false - } - - fn glsl_collect_geometry_fields(&self, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0; - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - self.glsl_push_field(vm, io, "vb_", true, &mut offset, &mut out); - } - } - out - } - - fn glsl_collect_instance_fields(&self, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0; - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - self.glsl_push_field(vm, io, "dyninst_", true, &mut offset, &mut out); - } - } - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - self.glsl_push_field(vm, io, "rustinst_", true, &mut offset, &mut out); - } - } - out - } - - fn glsl_collect_varying_pack_fields(&self, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0; - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - self.glsl_push_field(vm, io, "dyninst_", false, &mut offset, &mut out); - } - } - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - self.glsl_push_field(vm, io, "rustinst_", false, &mut offset, &mut out); - } - } - for io in &self.io { - if let ShaderIoKind::Varying = io.kind { - self.glsl_push_field(vm, io, "var_", false, &mut offset, &mut out); - } - } - out - } - - fn glsl_push_field( - &self, - vm: &ScriptVm, - io: &crate::shader::ShaderIo, - prefix: &str, - attribute_packing: bool, - offset: &mut usize, - out: &mut Vec, - ) { - let io_name = self.backend.map_io_name(io.name); - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - let slots = pod_ty.ty.slots(); - let attr_format = if attribute_packing { - Self::glsl_attr_format_from_pod_ty(&pod_ty.ty) - } else { - GlslPackedFormat::Float - }; - - if attribute_packing - && attr_format != GlslPackedFormat::Float - && slots > 1 - && (*offset & 3) != 0 - { - *offset += 4 - (*offset & 3); - } - out.push(GlslPackedField { - name: format!("{}{}", prefix, io_name), - ty: io.ty, - slots, - offset: *offset, - }); - *offset += slots; - if attribute_packing - && attr_format != GlslPackedFormat::Float - && slots > 1 - && (*offset & 3) != 0 - { - *offset += 4 - (*offset & 3); - } - } - - fn glsl_unpack_expr_for_field( - &self, - vm: &ScriptVm, - field: &GlslPackedField, - prefix: &str, - source: GlslPackedSource, - ) -> String { - let scalars = (0..field.slots) - .map(|slot| Self::glsl_packed_component(prefix, field.offset + slot)) - .collect::>(); - let mut scalar_index = 0usize; - self.glsl_reconstruct_from_scalars(vm, field.ty, source, &scalars, &mut scalar_index) - } - - /// Emit assignment statements to unpack a packed field into a variable. - /// - /// For struct-typed fields, this generates per-sub-field assignments instead - /// of using GLSL struct constructor syntax, which some GLES drivers (notably - /// the Android emulator's ANGLE/SwiftShader) reject. - /// - /// For example, instead of `vb_geom = QuadVertex(vec2(x, y));` this emits: - /// `vb_geom.pos = vec2(x, y);` - fn glsl_unpack_field_to_statements( - &self, - vm: &ScriptVm, - field: &GlslPackedField, - prefix: &str, - source: GlslPackedSource, - out: &mut String, - ) { - let pod_ty = vm.bx.heap.pod_type_ref(field.ty); - if let ScriptPodTy::Struct { - fields: sub_fields, .. - } = &pod_ty.ty - { - let scalars = (0..field.slots) - .map(|slot| Self::glsl_packed_component(prefix, field.offset + slot)) - .collect::>(); - let mut scalar_index = 0usize; - for sub_field in sub_fields { - let sub_field_name = self.backend.map_field_name(sub_field.name); - let value_expr = self.glsl_reconstruct_inline( - vm, - &sub_field.ty, - source, - &scalars, - &mut scalar_index, - ); - writeln!( - out, - " {}.{} = {};", - field.name, sub_field_name, value_expr - ) - .ok(); - } - } else { - let value_expr = self.glsl_unpack_expr_for_field(vm, field, prefix, source); - writeln!(out, " {} = {};", field.name, value_expr).ok(); - } - } - - fn glsl_reconstruct_from_scalars( - &self, - vm: &ScriptVm, - ty: ScriptPodType, - source: GlslPackedSource, - scalars: &[String], - scalar_index: &mut usize, - ) -> String { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let inline = ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - self.glsl_reconstruct_inline(vm, &inline, source, scalars, scalar_index) - } - - fn glsl_reconstruct_inline( - &self, - vm: &ScriptVm, - ty: &ScriptPodTypeInline, - source: GlslPackedSource, - scalars: &[String], - scalar_index: &mut usize, - ) -> String { - match &ty.data.ty { - ScriptPodTy::Struct { fields, .. } => { - let mut field_exprs = Vec::new(); - for field in fields { - field_exprs.push(self.glsl_reconstruct_inline( - vm, - &field.ty, - source, - scalars, - scalar_index, - )); - } - format!( - "{}({})", - self.glsl_type_name_inline(ty), - field_exprs.join(", ") - ) - } - ScriptPodTy::Vec(vec_ty) => { - let dims = vec_ty.dims(); - let mut comps = Vec::with_capacity(dims); - let elem_ty = vec_ty.elem_ty(); - for _ in 0..dims { - let scalar = Self::glsl_take_scalar_or_zero(scalars, scalar_index); - comps.push(Self::glsl_convert_scalar_expr(source, &elem_ty, &scalar)); - } - format!("{}({})", self.glsl_type_name_inline(ty), comps.join(", ")) - } - ScriptPodTy::Mat(mat_ty) => { - let mut comps = Vec::new(); - for _ in 0..mat_ty.dim() { - let scalar = Self::glsl_take_scalar_or_zero(scalars, scalar_index); - comps.push(Self::glsl_convert_scalar_expr( - source, - &ScriptPodTy::F32, - &scalar, - )); - } - format!("{}({})", self.glsl_type_name_inline(ty), comps.join(", ")) - } - scalar_ty => { - let scalar = Self::glsl_take_scalar_or_zero(scalars, scalar_index); - Self::glsl_convert_scalar_expr(source, scalar_ty, &scalar) - } - } - } - - fn glsl_take_scalar_or_zero(scalars: &[String], scalar_index: &mut usize) -> String { - let value = scalars - .get(*scalar_index) - .cloned() - .unwrap_or_else(|| "0.0".to_string()); - *scalar_index += 1; - value - } - - fn glsl_flatten_exprs( - &self, - vm: &ScriptVm, - ty: ScriptPodType, - expr: &str, - out: &mut Vec, - ) { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let inline = ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - self.glsl_flatten_inline(&inline, expr, out); - } - - fn glsl_flatten_inline(&self, ty: &ScriptPodTypeInline, expr: &str, out: &mut Vec) { - match &ty.data.ty { - ScriptPodTy::Struct { fields, .. } => { - for field in fields { - let field_name = self.backend.map_field_name(field.name); - let field_expr = format!("({}).{}", expr, field_name); - self.glsl_flatten_inline(&field.ty, &field_expr, out); - } - } - ScriptPodTy::Vec(vec_ty) => { - let elem_ty = vec_ty.elem_ty(); - for comp in 0..vec_ty.dims() { - let swizzle = Self::glsl_swizzle_component(comp); - let comp_expr = format!("({}).{}", expr, swizzle); - out.push(Self::glsl_to_float_scalar_expr(&elem_ty, &comp_expr)); - } - } - ScriptPodTy::Mat(mat_ty) => { - let (cols, rows) = mat_ty.dims(); - for col in 0..cols { - for row in 0..rows { - out.push(format!("({})[{}][{}]", expr, col, row)); - } - } - } - scalar_ty => { - out.push(Self::glsl_to_float_scalar_expr(scalar_ty, expr)); - } - } - } - - fn glsl_to_float_scalar_expr(ty: &ScriptPodTy, expr: &str) -> String { - match ty { - ScriptPodTy::F32 | ScriptPodTy::F16 => expr.to_string(), - ScriptPodTy::U32 - | ScriptPodTy::I32 - | ScriptPodTy::AtomicU32 - | ScriptPodTy::AtomicI32 => format!("float({})", expr), - ScriptPodTy::Bool => format!("(({}) ? 1.0 : 0.0)", expr), - _ => format!("float({})", expr), - } - } - - fn glsl_convert_scalar_expr( - source: GlslPackedSource, - target: &ScriptPodTy, - expr: &str, - ) -> String { - match source { - GlslPackedSource::NumericFloat => match target { - ScriptPodTy::F32 | ScriptPodTy::F16 => expr.to_string(), - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => format!("uint({})", expr), - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => format!("int({})", expr), - ScriptPodTy::Bool => format!("({} != 0.0)", expr), - _ => format!("float({})", expr), - }, - GlslPackedSource::BitPackedFloat => match target { - ScriptPodTy::F32 | ScriptPodTy::F16 => expr.to_string(), - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => format!("floatBitsToUint({})", expr), - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => format!("floatBitsToInt({})", expr), - ScriptPodTy::Bool => format!("(floatBitsToUint({}) != 0u)", expr), - _ => expr.to_string(), - }, - } - } - - fn glsl_attr_format_from_pod_ty(ty: &ScriptPodTy) -> GlslPackedFormat { - match ty { - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 | ScriptPodTy::Bool => GlslPackedFormat::UInt, - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => GlslPackedFormat::SInt, - ScriptPodTy::Vec(v) => match v { - crate::pod::ScriptPodVec::Vec2u - | crate::pod::ScriptPodVec::Vec3u - | crate::pod::ScriptPodVec::Vec4u - | crate::pod::ScriptPodVec::Vec2b - | crate::pod::ScriptPodVec::Vec3b - | crate::pod::ScriptPodVec::Vec4b => GlslPackedFormat::UInt, - crate::pod::ScriptPodVec::Vec2i - | crate::pod::ScriptPodVec::Vec3i - | crate::pod::ScriptPodVec::Vec4i => GlslPackedFormat::SInt, - _ => GlslPackedFormat::Float, - }, - _ => GlslPackedFormat::Float, - } - } - - fn glsl_uniform_block_name(&self, name: LiveId) -> String { - let io_name = self.backend.map_io_name(name); - match io_name.as_str() { - "draw_pass" => "passUniforms".to_string(), - "draw_list" => "draw_listUniforms".to_string(), - "draw_call" => "draw_callUniforms".to_string(), - _ => format!("{}_Uniforms", io_name), - } - } - - fn glsl_sampler_type(&self, tex_type: TextureType) -> &'static str { - match tex_type { - TextureType::Texture1d => "sampler2D", - TextureType::Texture1dArray => "sampler2DArray", - TextureType::Texture2d => "sampler2D", - TextureType::Texture2dArray => "sampler2DArray", - TextureType::Texture3d => "sampler3D", - TextureType::Texture3dArray => "sampler3D", - TextureType::TextureCube => "samplerCube", - TextureType::TextureCubeArray => "samplerCubeArray", - TextureType::TextureDepth => "sampler2D", - TextureType::TextureDepthArray => "sampler2DArray", - TextureType::TextureVideo => { - if cfg!(target_os = "android") && !self.use_vulkan { - "samplerExternalOES" - } else { - "sampler2D" - } - } - } - } - - fn glsl_num_packed_vec4s(slots: usize) -> usize { - if slots == 0 { - 0 - } else { - (slots + 3) / 4 - } - } - - fn glsl_packed_component(prefix: &str, slot: usize) -> String { - let vec_idx = slot / 4; - let comp = Self::glsl_swizzle_component(slot & 3); - format!("{}{}.{}", prefix, vec_idx, comp) - } - - fn glsl_swizzle_component(index: usize) -> &'static str { - match index { - 0 => "x", - 1 => "y", - 2 => "z", - _ => "w", - } - } - - fn glsl_type_name_from_ty(&self, vm: &ScriptVm, ty: ScriptPodType) -> String { - let mut out = String::new(); - self.backend - .pod_type_name_from_ty(&vm.bx.heap, ty, &mut out); - out - } - - fn glsl_type_name_inline(&self, ty: &ScriptPodTypeInline) -> String { - if matches!(ty.data.ty, ScriptPodTy::Struct { .. }) { - if let Some(name) = ty.data.name { - return format!("{}", self.backend.map_pod_name(name)); - } - return format!("S{}", ty.self_ref.index); - } - let mut out = String::new(); - self.backend.pod_type_name(ty, &mut out); - out - } -} diff --git a/vendor/makepad/platform/script/src/shader_hlsl.rs b/vendor/makepad/platform/script/src/shader_hlsl.rs deleted file mode 100644 index d79b713..0000000 --- a/vendor/makepad/platform/script/src/shader_hlsl.rs +++ /dev/null @@ -1,591 +0,0 @@ -use crate::pod::ScriptPodTy; -use crate::shader::{SamplerAddress, SamplerFilter, ShaderIoKind, ShaderOutput, TextureType}; -use crate::vm::ScriptVm; -use makepad_live_id::{id, LiveId}; -use std::fmt::Write; - -impl ShaderOutput { - fn hlsl_is_integer_like_input(vm: &ScriptVm, ty: crate::ScriptPodType) -> bool { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - match pod_ty.ty { - ScriptPodTy::U32 - | ScriptPodTy::I32 - | ScriptPodTy::Bool - | ScriptPodTy::AtomicU32 - | ScriptPodTy::AtomicI32 => true, - ScriptPodTy::Vec(vec_ty) => matches!( - vec_ty, - crate::pod::ScriptPodVec::Vec2u - | crate::pod::ScriptPodVec::Vec3u - | crate::pod::ScriptPodVec::Vec4u - | crate::pod::ScriptPodVec::Vec2i - | crate::pod::ScriptPodVec::Vec3i - | crate::pod::ScriptPodVec::Vec4i - | crate::pod::ScriptPodVec::Vec2b - | crate::pod::ScriptPodVec::Vec3b - | crate::pod::ScriptPodVec::Vec4b - ), - _ => false, - } - } - - fn hlsl_slot_chunks(slots: usize) -> Vec { - match slots { - 0 => Vec::new(), - // Keep matrix layouts aligned with D3D input layout chunking. - 9 => vec![3, 3, 3], - 16 => vec![4, 4, 4, 4], - _ => { - let mut rem = slots; - let mut chunks = Vec::new(); - while rem > 0 { - let chunk = rem.min(4); - chunks.push(chunk); - rem -= chunk; - } - chunks - } - } - } - - fn hlsl_chunk_ty(slots: usize) -> &'static str { - match slots { - 1 => "float", - 2 => "float2", - 3 => "float3", - 4 => "float4", - _ => "float4", - } - } - - fn hlsl_input_needs_chunks(vm: &ScriptVm, ty: crate::ScriptPodType) -> bool { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let slots = pod_ty.ty.slots(); - slots > 4 || matches!(pod_ty.ty, ScriptPodTy::Struct { .. }) - } - - fn hlsl_reconstruct_from_scalars( - &self, - vm: &ScriptVm, - ty: &crate::pod::ScriptPodTypeInline, - scalars: &[String], - scalar_idx: &mut usize, - ) -> String { - match &ty.data.ty { - ScriptPodTy::Struct { fields, .. } => { - let struct_name = if let Some(name) = vm.bx.heap.pod_type_name(ty.self_ref) { - format!("{}", self.backend.map_pod_name(name)) - } else { - format!("S{}", ty.self_ref.index) - }; - let mut field_exprs = Vec::new(); - for field in fields { - field_exprs.push( - self.hlsl_reconstruct_from_scalars(vm, &field.ty, scalars, scalar_idx), - ); - } - format!("consfn_{}({})", struct_name, field_exprs.join(", ")) - } - _ => { - let slot_count = ty.data.ty.slots(); - if slot_count <= 1 { - let v = scalars - .get(*scalar_idx) - .cloned() - .unwrap_or_else(|| "0.0".to_string()); - *scalar_idx += 1; - return v; - } - let start = *scalar_idx; - let end = (start + slot_count).min(scalars.len()); - *scalar_idx = end; - let args = scalars[start..end].join(", "); - let mut ty_name = String::new(); - self.backend.pod_type_name(ty, &mut ty_name); - if matches!(ty.data.ty, ScriptPodTy::Mat(_)) { - // Mat4f/MatNxM are stored column-major in CPU slot streams. - // HLSL scalar constructors consume row-major order, so transpose. - format!("transpose({}({}))", ty_name, args) - } else { - format!("{}({})", ty_name, args) - } - } - } - } - - fn hlsl_reconstruct_input_value( - &self, - vm: &ScriptVm, - ty: crate::ScriptPodType, - input_prefix: &str, - io_name: LiveId, - ) -> String { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let slots = pod_ty.ty.slots(); - let io_name = self.backend.map_io_name(io_name); - - if !Self::hlsl_input_needs_chunks(vm, ty) { - return format!("input.{}_{}", input_prefix, io_name); - } - - let mut args: Vec = Vec::new(); - for (chunk_idx, chunk_slots) in Self::hlsl_slot_chunks(slots).into_iter().enumerate() { - let base = format!("input.{}_{}_{}", input_prefix, io_name, chunk_idx); - if chunk_slots == 1 { - args.push(base); - } else { - for comp in 0..chunk_slots { - let swiz = match comp { - 0 => "x", - 1 => "y", - 2 => "z", - 3 => "w", - _ => "x", - }; - args.push(format!("{}.{}", base, swiz)); - } - } - } - let inline = crate::pod::ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - let mut scalar_idx = 0usize; - self.hlsl_reconstruct_from_scalars(vm, &inline, &args, &mut scalar_idx) - } - - /// Emit HLSL helper functions that are needed by the shader - pub fn hlsl_create_helpers(&self, _vm: &ScriptVm, out: &mut String) { - if self.hlsl_needs_tex_size { - writeln!(out, "float2 _mpTexSize2D(Texture2D tex) {{ uint w, h; tex.GetDimensions(w, h); return float2(w, h); }}").ok(); - } - } - - pub fn hlsl_create_instance_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoInstance {{").ok(); - - // 1. Output Dyn instance fields first (order doesn't matter, just output as encountered) - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " {};", io_name).ok(); - } - } - - // 2. Output Rust instance fields last (already in correct order from pre_collect_rust_instance_io) - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " {};", io_name).ok(); - } - } - - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_uniform_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "cbuffer IoUniform : register(b2) {{").ok(); - for io in &self.io { - match &io.kind { - ShaderIoKind::Uniform => { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " u_{};", io_name).ok(); - } - _ => (), - } - } - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_scope_uniform_cbuffer(&self, vm: &ScriptVm, out: &mut String) { - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - if !has_scope_uniforms { - return; - } - - let scope_uniform_buffer_idx = self - .io - .iter() - .filter_map(|io| io.buffer_index) - .max() - .map(|m| m + 1) - .unwrap_or(3); - - writeln!( - out, - "cbuffer IoScopeUniform : register(b{}) {{", - scope_uniform_buffer_idx - ) - .ok(); - for io in &self.io { - if let ShaderIoKind::ScopeUniform = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " su_{};", io_name).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_uniform_buffer_cbuffers(&self, vm: &ScriptVm, out: &mut String) { - // Create cbuffer declarations for each uniform buffer using pre-assigned buffer indices - for io in &self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - let buf_idx = io - .buffer_index - .expect("UniformBuffer must have buffer_index assigned"); - let io_name = self.backend.map_io_name(io.name); - write!(out, "cbuffer cb_{} : register(b{}) {{ ", io_name, buf_idx).ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " u_{}; }};", io_name).ok(); - } - } - } - - pub fn hlsl_create_varying_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoVarying {{").ok(); - let mut semantic_idx = 0usize; - for io in &self.io { - match io.kind { - ShaderIoKind::DynInstance | ShaderIoKind::RustInstance | ShaderIoKind::Varying => { - write!(out, " ").ok(); - if Self::hlsl_is_integer_like_input(vm, io.ty) { - write!(out, "nointerpolation ").ok(); - } - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!( - out, - " {} : VARY{};", - self.backend.map_io_name(io.name), - index_to_semantic(semantic_idx) - ) - .ok(); - semantic_idx += 1; - } - _ => (), - } - } - writeln!(out, " nointerpolation uint _iid : TEXCOORD0;").ok(); - writeln!(out, " float4 _position : SV_POSITION;").ok(); - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_vertex_buffer_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoVertexBuffer {{").ok(); - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " {};", io_name).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_vertex_input_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct VertexInput {{").ok(); - - // Vertex buffer fields - let mut semantic_idx = 0; - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - let slots = pod_ty.ty.slots(); - let io_name = self.backend.map_io_name(io.name); - if Self::hlsl_input_needs_chunks(vm, io.ty) { - for (chunk_idx, chunk_slots) in - Self::hlsl_slot_chunks(slots).into_iter().enumerate() - { - writeln!( - out, - " {} vb_{}_{} : GEOM{}{};", - Self::hlsl_chunk_ty(chunk_slots), - io_name, - chunk_idx, - index_to_semantic(semantic_idx), - chunk_idx - ) - .ok(); - } - } else { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!( - out, - " vb_{} : GEOM{};", - io_name, - index_to_semantic(semantic_idx) - ) - .ok(); - } - semantic_idx += 1; - } - } - - // Instance fields - semantic_idx = 0; - // Dyn instance fields first - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - let slots = pod_ty.ty.slots(); - let io_name = self.backend.map_io_name(io.name); - if Self::hlsl_input_needs_chunks(vm, io.ty) { - for (chunk_idx, chunk_slots) in - Self::hlsl_slot_chunks(slots).into_iter().enumerate() - { - writeln!( - out, - " {} i_{}_{} : INST{}{};", - Self::hlsl_chunk_ty(chunk_slots), - io_name, - chunk_idx, - index_to_semantic(semantic_idx), - chunk_idx - ) - .ok(); - } - } else { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!( - out, - " i_{} : INST{};", - io_name, - index_to_semantic(semantic_idx) - ) - .ok(); - } - semantic_idx += 1; - } - } - // Rust instance fields - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - let slots = pod_ty.ty.slots(); - let io_name = self.backend.map_io_name(io.name); - if Self::hlsl_input_needs_chunks(vm, io.ty) { - for (chunk_idx, chunk_slots) in - Self::hlsl_slot_chunks(slots).into_iter().enumerate() - { - writeln!( - out, - " {} i_{}_{} : INST{}{};", - Self::hlsl_chunk_ty(chunk_slots), - io_name, - chunk_idx, - index_to_semantic(semantic_idx), - chunk_idx - ) - .ok(); - } - } else { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!( - out, - " i_{} : INST{};", - io_name, - index_to_semantic(semantic_idx) - ) - .ok(); - } - semantic_idx += 1; - } - } - - writeln!(out, " uint vid : SV_VertexID;").ok(); - writeln!(out, " uint iid : SV_InstanceID;").ok(); - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_io_structs(&self, vm: &ScriptVm, out: &mut String) { - // IoV for vertex shader - writeln!(out, "struct IoV {{").ok(); - writeln!(out, " IoVarying v;").ok(); - writeln!(out, " IoVertexBuffer vb;").ok(); - writeln!(out, " IoInstance i;").ok(); - writeln!(out, " uint vid;").ok(); - writeln!(out, " uint iid;").ok(); - writeln!(out, "}};").ok(); - writeln!(out).ok(); - - // IoF for fragment shader - writeln!(out, "struct IoF {{").ok(); - writeln!(out, " IoVarying v;").ok(); - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " fb{};", index).ok(); - } - } - writeln!(out, "}};").ok(); - writeln!(out).ok(); - - // Io for passing to shader functions - writeln!(out, "struct Io {{").ok(); - writeln!(out, "}};").ok(); - writeln!(out, "static Io _mp_io;").ok(); - writeln!(out, "static IoV _mp_iov;").ok(); - writeln!(out, "static IoF _mp_iof;").ok(); - } - - pub fn hlsl_create_fragment_output_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoFb {{").ok(); - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " fb{} : SV_TARGET{};", index, index).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn hlsl_create_texture_samplers(&self, _vm: &ScriptVm, out: &mut String) { - let mut tex_idx = 0; - let mut samp_idx = 0; - for io in &self.io { - match &io.kind { - ShaderIoKind::Texture(tex_type) => { - let hlsl_type = match tex_type { - TextureType::Texture1d => "Texture1D", - TextureType::Texture1dArray => "Texture1DArray", - TextureType::Texture2d => "Texture2D", - TextureType::Texture2dArray => "Texture2DArray", - TextureType::Texture3d => "Texture3D", - TextureType::Texture3dArray => "Texture3D", // HLSL doesn't support 3D array textures - TextureType::TextureCube => "TextureCube", - TextureType::TextureCubeArray => "TextureCubeArray", - TextureType::TextureDepth => "Texture2D", - TextureType::TextureDepthArray => "Texture2DArray", - TextureType::TextureVideo => "Texture2D", // Video textures are standard Texture2D on HLSL - }; - let io_name = self.backend.map_io_name(io.name); - writeln!(out, "{} {} : register(t{});", hlsl_type, io_name, tex_idx).ok(); - tex_idx += 1; - } - ShaderIoKind::Sampler(_) => { - let io_name = self.backend.map_io_name(io.name); - writeln!(out, "SamplerState {} : register(s{});", io_name, samp_idx).ok(); - samp_idx += 1; - } - _ => (), - } - } - - for (idx, sampler) in self.samplers.iter().enumerate() { - let filter = match sampler.filter { - SamplerFilter::Nearest => "MIN_MAG_MIP_POINT", - SamplerFilter::Linear => "MIN_MAG_MIP_LINEAR", - }; - let address = match sampler.address { - SamplerAddress::Repeat => "Wrap", - SamplerAddress::ClampToEdge => "Clamp", - SamplerAddress::ClampToZero => "Border", - SamplerAddress::MirroredRepeat => "Mirror", - }; - writeln!( - out, - "SamplerState _s{} {{ Filter = {}; AddressU = {}; AddressV = {}; AddressW = {}; }};", - idx, filter, address, address, address - ) - .ok(); - } - } - - pub fn hlsl_create_vertex_fn(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "IoVarying vertex_main(VertexInput input) {{").ok(); - writeln!(out, " _mp_iov.vid = input.vid;").ok(); - writeln!(out, " _mp_iov.iid = input.iid;").ok(); - writeln!(out, " _mp_iov.v._iid = input.iid;").ok(); - writeln!(out).ok(); - - // Copy vertex/instance input into IoV so helper functions can access it. - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - let expr = self.hlsl_reconstruct_input_value(vm, io.ty, "vb", io.name); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " _mp_iov.vb.{0} = {1};", io_name, expr).ok(); - } - } - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - let expr = self.hlsl_reconstruct_input_value(vm, io.ty, "i", io.name); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " _mp_iov.i.{0} = {1};", io_name, expr).ok(); - writeln!(out, " _mp_iov.v.{0} = _mp_iov.i.{0};", io_name).ok(); - } - } - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - let expr = self.hlsl_reconstruct_input_value(vm, io.ty, "i", io.name); - let io_name = self.backend.map_io_name(io.name); - writeln!(out, " _mp_iov.i.{0} = {1};", io_name, expr).ok(); - writeln!(out, " _mp_iov.v.{0} = _mp_iov.i.{0};", io_name).ok(); - } - } - - // Check if vertex shader returns Vec4f - if so, assign to _position automatically - let vertex_returns_vec4f = self - .functions - .iter() - .find(|f| f.name == id!(vertex)) - .map(|f| f.ret == vm.bx.code.builtins.pod.pod_vec4f) - .unwrap_or(false); - - let vertex_fn_name = self.backend.map_function_name("io_vertex"); - if vertex_returns_vec4f { - writeln!(out, " _mp_iov.v._position = {}();", vertex_fn_name).ok(); - } else { - writeln!(out, " {}();", vertex_fn_name).ok(); - } - writeln!(out, " _mp_iov.v._iid = input.iid;").ok(); - writeln!(out, " return _mp_iov.v;").ok(); - writeln!(out, "}}").ok(); - } - - pub fn hlsl_create_fragment_fn(&self, _vm: &ScriptVm, out: &mut String) { - writeln!(out, "IoFb pixel_main(IoVarying v) {{").ok(); - writeln!(out, " _mp_iof.v = v;").ok(); - let fragment_fn_name = self.backend.map_function_name("io_fragment"); - writeln!(out, " {}();", fragment_fn_name).ok(); - writeln!(out, " IoFb _iofb;").ok(); - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - writeln!(out, " _iofb.fb{0} = _mp_iof.fb{0};", index).ok(); - } - } - writeln!(out, " return _iofb;").ok(); - writeln!(out, "}}").ok(); - } -} - -/// Convert index to HLSL semantic suffix (A..Z, AA..AZ, BA..). -pub fn index_to_semantic(index: usize) -> String { - const LETTERS: &[u8; 26] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - let mut value = index; - let mut out = Vec::new(); - loop { - let rem = value % 26; - out.push(LETTERS[rem] as char); - if value < 26 { - break; - } - value = value / 26 - 1; - } - out.iter().rev().collect() -} diff --git a/vendor/makepad/platform/script/src/shader_metal.rs b/vendor/makepad/platform/script/src/shader_metal.rs deleted file mode 100644 index 7e4517e..0000000 --- a/vendor/makepad/platform/script/src/shader_metal.rs +++ /dev/null @@ -1,600 +0,0 @@ -use crate::pod::{ScriptPodMat, ScriptPodTy}; -use crate::shader::{ShaderIoKind, ShaderOutput, TextureType}; -use crate::vm::ScriptVm; -use makepad_live_id::{id, LiveId}; -use std::fmt::Write; - -impl ShaderOutput { - pub fn metal_create_helpers(&self, out: &mut String) { - writeln!(out, "inline float4x4 _mp_inverse(float4x4 m) {{").ok(); - writeln!(out, " float a00 = m[0][0];").ok(); - writeln!(out, " float a01 = m[0][1];").ok(); - writeln!(out, " float a02 = m[0][2];").ok(); - writeln!(out, " float a03 = m[0][3];").ok(); - writeln!(out, " float a10 = m[1][0];").ok(); - writeln!(out, " float a11 = m[1][1];").ok(); - writeln!(out, " float a12 = m[1][2];").ok(); - writeln!(out, " float a13 = m[1][3];").ok(); - writeln!(out, " float a20 = m[2][0];").ok(); - writeln!(out, " float a21 = m[2][1];").ok(); - writeln!(out, " float a22 = m[2][2];").ok(); - writeln!(out, " float a23 = m[2][3];").ok(); - writeln!(out, " float a30 = m[3][0];").ok(); - writeln!(out, " float a31 = m[3][1];").ok(); - writeln!(out, " float a32 = m[3][2];").ok(); - writeln!(out, " float a33 = m[3][3];").ok(); - writeln!(out, " float b00 = a00 * a11 - a01 * a10;").ok(); - writeln!(out, " float b01 = a00 * a12 - a02 * a10;").ok(); - writeln!(out, " float b02 = a00 * a13 - a03 * a10;").ok(); - writeln!(out, " float b03 = a01 * a12 - a02 * a11;").ok(); - writeln!(out, " float b04 = a01 * a13 - a03 * a11;").ok(); - writeln!(out, " float b05 = a02 * a13 - a03 * a12;").ok(); - writeln!(out, " float b06 = a20 * a31 - a21 * a30;").ok(); - writeln!(out, " float b07 = a20 * a32 - a22 * a30;").ok(); - writeln!(out, " float b08 = a20 * a33 - a23 * a30;").ok(); - writeln!(out, " float b09 = a21 * a32 - a22 * a31;").ok(); - writeln!(out, " float b10 = a21 * a33 - a23 * a31;").ok(); - writeln!(out, " float b11 = a22 * a33 - a23 * a32;").ok(); - writeln!( - out, - " float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;" - ) - .ok(); - writeln!(out, " if (det == 0.0) {{").ok(); - writeln!( - out, - " return float4x4(float4(1.0, 0.0, 0.0, 0.0), float4(0.0, 1.0, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0));" - ) - .ok(); - writeln!(out, " }}").ok(); - writeln!(out, " float idet = 1.0 / det;").ok(); - writeln!(out, " return float4x4(").ok(); - writeln!( - out, - " float4((a11 * b11 - a12 * b10 + a13 * b09) * idet, (a02 * b10 - a01 * b11 - a03 * b09) * idet, (a31 * b05 - a32 * b04 + a33 * b03) * idet, (a22 * b04 - a21 * b05 - a23 * b03) * idet)," - ) - .ok(); - writeln!( - out, - " float4((a12 * b08 - a10 * b11 - a13 * b07) * idet, (a00 * b11 - a02 * b08 + a03 * b07) * idet, (a32 * b02 - a30 * b05 - a33 * b01) * idet, (a20 * b05 - a22 * b02 + a23 * b01) * idet)," - ) - .ok(); - writeln!( - out, - " float4((a10 * b10 - a11 * b08 + a13 * b06) * idet, (a01 * b08 - a00 * b10 - a03 * b06) * idet, (a30 * b04 - a31 * b02 + a33 * b00) * idet, (a21 * b02 - a20 * b04 - a23 * b00) * idet)," - ) - .ok(); - writeln!( - out, - " float4((a11 * b07 - a10 * b09 - a12 * b06) * idet, (a00 * b09 - a01 * b07 + a02 * b06) * idet, (a31 * b01 - a30 * b03 - a32 * b00) * idet, (a20 * b03 - a21 * b01 + a22 * b00) * idet)" - ) - .ok(); - writeln!(out, " );").ok(); - writeln!(out, "}}").ok(); - } - - pub fn metal_create_io_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct Io {{").ok(); - writeln!(out, " constant IoUniform *u;").ok(); - writeln!(out, " thread IoInstance *i;").ok(); - - // Add scope uniforms buffer pointer if we have any scope uniforms - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - if has_scope_uniforms { - writeln!(out, " constant IoScopeUniform *su;").ok(); - } - - for io in &self.io { - match &io.kind { - ShaderIoKind::Texture(tex_type) => { - let metal_type = match tex_type { - TextureType::Texture1d => "texture1d", - TextureType::Texture1dArray => "texture1d_array", - TextureType::Texture2d => "texture2d", - TextureType::Texture2dArray => "texture2d_array", - TextureType::Texture3d => "texture3d", - TextureType::Texture3dArray => "texture3d", // Metal doesn't support 3D array textures - TextureType::TextureCube => "texturecube", - TextureType::TextureCubeArray => "texturecube_array", - TextureType::TextureDepth => "depth2d", - TextureType::TextureDepthArray => "depth2d_array", - TextureType::TextureVideo => "texture2d", // Video textures are standard texture2d on Metal - }; - writeln!(out, " {} {};", metal_type, io.name).ok(); - } - ShaderIoKind::Sampler(_) => { - writeln!(out, " sampler {};", io.name).ok(); - } - ShaderIoKind::UniformBuffer => { - write!(out, " constant ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " *u_{};", io.name).ok(); - } - _ => (), - } - } - - let mut have_vb = false; - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - if !have_vb { - writeln!(out, " constant IoVertexBuffer *vb;").ok(); - have_vb = true; - } - } - } - writeln!(out, "}};").ok(); - } - - /// Creates the IoScopeUniform struct that holds values read from the script scope. - /// This struct is populated by reading values from scope_uniforms sources before drawing. - pub fn metal_create_scope_uniform_struct(&self, vm: &ScriptVm, out: &mut String) { - // Only create the struct if there are scope uniforms - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - if !has_scope_uniforms { - return; - } - - writeln!(out, "struct IoScopeUniform {{").ok(); - for io in &self.io { - if let ShaderIoKind::ScopeUniform = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn metal_create_instance_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoInstanceRaw {{").ok(); - - // 1. Output Dyn instance fields first (order doesn't matter, just output as encountered) - // Use packed types to match CPU-side repr(C) struct alignment - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - if matches!(pod_ty.ty, ScriptPodTy::Mat(ScriptPodMat::Mat4x4f)) { - for col in 0..4 { - writeln!(out, " packed_float4 {}_{};", io.name, col).ok(); - } - } else { - write!(out, " ").ok(); - self.backend - .pod_type_name_packed_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - } - - // 2. Output Rust instance fields last (already in correct order from pre_collect_rust_instance_io) - // Use packed types to match CPU-side repr(C) struct alignment - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - if matches!(pod_ty.ty, ScriptPodTy::Mat(ScriptPodMat::Mat4x4f)) { - for col in 0..4 { - writeln!(out, " packed_float4 {}_{};", io.name, col).ok(); - } - } else { - write!(out, " ").ok(); - self.backend - .pod_type_name_packed_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - } - - writeln!(out, "}};").ok(); - - writeln!(out, "struct IoInstance {{").ok(); - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - writeln!(out, "}};").ok(); - - writeln!( - out, - "inline IoInstance _mp_decode_instance(constant IoInstanceRaw &raw) {{" - ) - .ok(); - writeln!(out, " IoInstance out_instance;").ok(); - for io in &self.io { - if let ShaderIoKind::DynInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - if matches!(pod_ty.ty, ScriptPodTy::Mat(ScriptPodMat::Mat4x4f)) { - writeln!( - out, - " out_instance.{0} = float4x4(float4(raw.{0}_0), float4(raw.{0}_1), float4(raw.{0}_2), float4(raw.{0}_3));", - io.name - ) - .ok(); - } else { - writeln!(out, " out_instance.{0} = raw.{0};", io.name).ok(); - } - } - } - for io in &self.io { - if let ShaderIoKind::RustInstance = io.kind { - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - if matches!(pod_ty.ty, ScriptPodTy::Mat(ScriptPodMat::Mat4x4f)) { - writeln!( - out, - " out_instance.{0} = float4x4(float4(raw.{0}_0), float4(raw.{0}_1), float4(raw.{0}_2), float4(raw.{0}_3));", - io.name - ) - .ok(); - } else { - writeln!(out, " out_instance.{0} = raw.{0};", io.name).ok(); - } - } - } - writeln!(out, " return out_instance;").ok(); - writeln!(out, "}}").ok(); - } - - pub fn metal_create_uniform_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoUniform {{").ok(); - for io in &self.io { - match &io.kind { - ShaderIoKind::Uniform => { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - _ => (), - } - } - writeln!(out, "}};").ok(); - } - - pub fn metal_create_varying_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoVarying {{").ok(); - // Put _iid first to ensure consistent offset regardless of other varyings - writeln!(out, " uint _iid [[flat]];").ok(); - for io in &self.io { - match io.kind { - ShaderIoKind::Varying => { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - _ => (), - } - } - writeln!(out, " float4 _position [[position]];").ok(); - writeln!(out, "}};").ok(); - } - - pub fn metal_create_vertex_buffer_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoVertexBuffer {{").ok(); - // Use packed types to match CPU-side repr(C) struct alignment - for io in &self.io { - if let ShaderIoKind::VertexBuffer = io.kind { - write!(out, " ").ok(); - self.backend - .pod_type_name_packed_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " {};", io.name).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn metal_create_io_vertex_struct(&self, _vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoV {{").ok(); - writeln!(out, " thread IoVarying *v;").ok(); - writeln!(out, " uint vid;").ok(); - writeln!(out, " uint iid;").ok(); - writeln!(out, "}};").ok(); - } - - pub fn metal_create_vertex_fn(&self, vm: &ScriptVm, out: &mut String) { - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - - writeln!(out, "vertex IoVarying vertex_main(").ok(); - writeln!(out, " constant IoVertexBuffer *vb [[buffer(0)]],").ok(); - writeln!(out, " constant IoInstanceRaw *i_raw [[buffer(1)]],").ok(); - writeln!(out, " constant IoUniform *u [[buffer(2)]],").ok(); - - // Use pre-assigned buffer indices from assign_uniform_buffer_indices() - for io in &self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - let buf_idx = io - .buffer_index - .expect("UniformBuffer must have buffer_index assigned"); - write!(out, " constant ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " *u_{} [[buffer({})]],", io.name, buf_idx).ok(); - } - } - - // Add scope uniforms buffer parameter if we have any - if has_scope_uniforms { - // Use a fixed buffer index for scope uniforms (after uniform buffers) - let scope_uniform_buffer_idx = self - .io - .iter() - .filter_map(|io| io.buffer_index) - .max() - .map(|m| m + 1) - .unwrap_or(3); - writeln!( - out, - " constant IoScopeUniform *su [[buffer({})]],", - scope_uniform_buffer_idx - ) - .ok(); - } - - let mut tex_idx = 0; - let mut samp_idx = 0; - for io in &self.io { - match &io.kind { - ShaderIoKind::Texture(tex_type) => { - let metal_type = match tex_type { - TextureType::Texture1d => "texture1d", - TextureType::Texture1dArray => "texture1d_array", - TextureType::Texture2d => "texture2d", - TextureType::Texture2dArray => "texture2d_array", - TextureType::Texture3d => "texture3d", - TextureType::Texture3dArray => "texture3d", - TextureType::TextureCube => "texturecube", - TextureType::TextureCubeArray => "texturecube_array", - TextureType::TextureDepth => "depth2d", - TextureType::TextureDepthArray => "depth2d_array", - TextureType::TextureVideo => "texture2d", // Video textures are standard texture2d on Metal - }; - writeln!( - out, - " {} {} [[texture({})]],", - metal_type, io.name, tex_idx - ) - .ok(); - tex_idx += 1; - } - ShaderIoKind::Sampler(_) => { - writeln!(out, " sampler {} [[sampler({})]],", io.name, samp_idx).ok(); - samp_idx += 1; - } - _ => (), - } - } - - writeln!(out, " uint vid [[vertex_id]],").ok(); - writeln!(out, " uint iid [[instance_id]]").ok(); - writeln!(out, ") {{").ok(); - - writeln!(out, " Io _io;").ok(); - writeln!( - out, - " IoInstance _inst = _mp_decode_instance(i_raw[iid]);" - ) - .ok(); - writeln!(out, " _io.vb = vb;").ok(); - writeln!(out, " _io.i = &_inst;").ok(); - writeln!(out, " _io.u = u;").ok(); - - if has_scope_uniforms { - writeln!(out, " _io.su = su;").ok(); - } - - for io in &self.io { - match &io.kind { - ShaderIoKind::UniformBuffer => { - writeln!(out, " _io.u_{} = u_{};", io.name, io.name).ok(); - } - ShaderIoKind::Texture(_) | ShaderIoKind::Sampler(_) => { - writeln!(out, " _io.{} = {};", io.name, io.name).ok(); - } - _ => (), - } - } - - writeln!(out, " IoVarying _v = {{}};").ok(); // Local varying struct, zero-initialized - writeln!(out, " IoV _iov;").ok(); - writeln!(out, " _iov.v = &_v;").ok(); // Point to local varying (like fragment shader) - writeln!(out, " _iov.vid = vid;").ok(); - writeln!(out, " _iov.iid = iid;").ok(); - writeln!(out, " _iov.v->_iid = iid;").ok(); // Set before io_vertex so user can read it - - // Check if vertex shader returns Vec4f - if so, assign to _position automatically - let vertex_returns_vec4f = self - .functions - .iter() - .find(|f| f.name == id!(vertex)) - .map(|f| f.ret == vm.bx.code.builtins.pod.pod_vec4f) - .unwrap_or(false); - - if vertex_returns_vec4f { - writeln!(out, " _v._position = io_vertex(_io, _iov);").ok(); - } else { - writeln!(out, " io_vertex(_io, _iov);").ok(); - } - // Ensure instance id is set after user code in case they modified it - writeln!(out, " _iov.v->_iid = iid;").ok(); - writeln!(out, " return _v;").ok(); - writeln!(out, "}}").ok(); - } - - pub fn metal_create_fragment_main_fn(&self, vm: &ScriptVm, out: &mut String) { - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - - writeln!(out, "fragment IoFb fragment_main(").ok(); - writeln!(out, " IoVarying v [[stage_in]],").ok(); - writeln!(out, " constant IoVertexBuffer *vb [[buffer(0)]],").ok(); - writeln!(out, " constant IoInstanceRaw *i_raw [[buffer(1)]],").ok(); - write!(out, " constant IoUniform *u [[buffer(2)]]").ok(); - - // Use pre-assigned buffer indices from assign_uniform_buffer_indices() - for io in &self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - let buf_idx = io - .buffer_index - .expect("UniformBuffer must have buffer_index assigned"); - writeln!(out, ",").ok(); - write!(out, " constant ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - write!(out, " *u_{} [[buffer({})]]", io.name, buf_idx).ok(); - } - } - - // Add scope uniforms buffer parameter if we have any - if has_scope_uniforms { - let scope_uniform_buffer_idx = self - .io - .iter() - .filter_map(|io| io.buffer_index) - .max() - .map(|m| m + 1) - .unwrap_or(3); - writeln!(out, ",").ok(); - write!( - out, - " constant IoScopeUniform *su [[buffer({})]]", - scope_uniform_buffer_idx - ) - .ok(); - } - - let mut tex_idx = 0; - let mut samp_idx = 0; - for io in &self.io { - match &io.kind { - ShaderIoKind::Texture(tex_type) => { - let metal_type = match tex_type { - TextureType::Texture1d => "texture1d", - TextureType::Texture1dArray => "texture1d_array", - TextureType::Texture2d => "texture2d", - TextureType::Texture2dArray => "texture2d_array", - TextureType::Texture3d => "texture3d", - TextureType::Texture3dArray => "texture3d", - TextureType::TextureCube => "texturecube", - TextureType::TextureCubeArray => "texturecube_array", - TextureType::TextureDepth => "depth2d", - TextureType::TextureDepthArray => "depth2d_array", - TextureType::TextureVideo => "texture2d", // Video textures are standard texture2d on Metal - }; - writeln!(out, ",").ok(); - write!( - out, - " {} {} [[texture({})]]", - metal_type, io.name, tex_idx - ) - .ok(); - tex_idx += 1; - } - ShaderIoKind::Sampler(_) => { - writeln!(out, ",").ok(); - write!(out, " sampler {} [[sampler({})]]", io.name, samp_idx).ok(); - samp_idx += 1; - } - _ => (), - } - } - - writeln!(out, ") {{").ok(); - - writeln!(out, " Io _io;").ok(); - writeln!( - out, - " IoInstance _inst = _mp_decode_instance(i_raw[v._iid]);" - ) - .ok(); - writeln!(out, " _io.vb = vb;").ok(); - writeln!(out, " _io.i = &_inst;").ok(); - writeln!(out, " _io.u = u;").ok(); - - if has_scope_uniforms { - writeln!(out, " _io.su = su;").ok(); - } - - for io in &self.io { - match &io.kind { - ShaderIoKind::UniformBuffer => { - writeln!(out, " _io.u_{} = u_{};", io.name, io.name).ok(); - } - ShaderIoKind::Texture(_) | ShaderIoKind::Sampler(_) => { - writeln!(out, " _io.{} = {};", io.name, io.name).ok(); - } - _ => (), - } - } - - writeln!(out, " IoFb _iofb;").ok(); - writeln!(out, " IoF _iof;").ok(); - writeln!(out, " _iof.v = &v;").ok(); - writeln!(out, " _iof.fb = &_iofb;").ok(); - writeln!(out, " io_fragment(_io, _iof);").ok(); - writeln!(out, " return _iofb;").ok(); - writeln!(out, "}}").ok(); - } - - pub fn metal_create_io_fragment_struct(&self, _vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoF {{").ok(); - writeln!(out, " thread IoVarying *v;").ok(); - writeln!(out, " thread IoFb *fb;").ok(); - writeln!(out, "}};").ok(); - } - - pub fn metal_create_io_framebuffer_struct(&self, vm: &ScriptVm, out: &mut String) { - writeln!(out, "struct IoFb {{").ok(); - for io in &self.io { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - write!(out, " ").ok(); - self.backend.pod_type_name_from_ty(&vm.bx.heap, io.ty, out); - writeln!(out, " fb{} [[color({})]];", index, index).ok(); - } - } - writeln!(out, "}};").ok(); - } - - pub fn metal_create_sampler_decls(&self, out: &mut String) { - use crate::shader::{SamplerAddress, SamplerCoord, SamplerFilter}; - - for (idx, sampler) in self.samplers.iter().enumerate() { - let filter = match sampler.filter { - SamplerFilter::Nearest => "nearest", - SamplerFilter::Linear => "linear", - }; - let address = match sampler.address { - SamplerAddress::Repeat => "repeat", - SamplerAddress::ClampToEdge => "clamp_to_edge", - SamplerAddress::ClampToZero => "clamp_to_zero", - SamplerAddress::MirroredRepeat => "mirrored_repeat", - }; - let coord = match sampler.coord { - SamplerCoord::Normalized => "normalized", - SamplerCoord::Pixel => "pixel", - }; - writeln!( - out, - "constexpr sampler _s{}(filter::{}, mip_filter::linear, address::{}, coord::{});", - idx, filter, address, coord - ) - .ok(); - } - } -} diff --git a/vendor/makepad/platform/script/src/shader_ops.rs b/vendor/makepad/platform/script/src/shader_ops.rs deleted file mode 100644 index c92fa59..0000000 --- a/vendor/makepad/platform/script/src/shader_ops.rs +++ /dev/null @@ -1,640 +0,0 @@ -//! Shader arithmetic and comparison operations -//! -//! This module contains handle functions for arithmetic operations (+, -, *, /, etc.), -//! comparison operations (==, !=, <, >, etc.), and logical operations (&&, ||). - -use crate::opcode::*; -use crate::shader::*; -use crate::shader_backend::ShaderBackend; -use crate::shader_tables::*; -use crate::suggest::*; -use crate::vm::*; -use crate::*; -use std::fmt::Write; - -impl ShaderFnCompiler { - pub(crate) fn handle_not( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - _opargs: OpcodeArgs, - ) { - let (t1, s1) = self.pop_resolved(vm, output); - let concrete = t1.make_concrete(&vm.bx.code.builtins.pod); - let mut s = self.stack.new_string(); - let ty = match concrete { - Some(pod_ty) if pod_ty == vm.bx.code.builtins.pod.pod_bool => { - write!(s, "(!{})", s1).ok(); - ShaderType::Pod(pod_ty) - } - Some(pod_ty) - if pod_ty == vm.bx.code.builtins.pod.pod_i32 - || pod_ty == vm.bx.code.builtins.pod.pod_u32 => - { - write!(s, "(~{})", s1).ok(); - ShaderType::Pod(pod_ty) - } - Some(pod_ty) => { - script_err_shader!( - self.trap, - "`!` in shaders only supports bool, i32, or u32; got {}", - format_pod_type_name(&vm.bx.heap, pod_ty) - ); - ShaderType::Error(NIL) - } - None => { - script_err_shader!(self.trap, "`!` in shaders requires a concrete type"); - ShaderType::Error(NIL) - } - }; - self.stack.push(self.trap.pass(), ty, s); - } - - pub(crate) fn handle_neg( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - _opargs: OpcodeArgs, - op: &str, - ) { - let (t1, s1) = self.pop_resolved(vm, output); - let mut s = self.stack.new_string(); - write!(s, "({}{})", op, s1).ok(); - let ty = type_table_neg(&t1, self.trap.pass(), &vm.bx.code.builtins.pod); - self.stack.push(self.trap.pass(), ty, s); - } - - pub(crate) fn handle_eq( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &str, - ) { - let (t2, s2) = if opargs.is_u32() { - let mut s = self.stack.new_string(); - write!(s, "{}", opargs.to_u32()).ok(); - (ShaderType::AbstractInt, s) - } else { - self.pop_resolved(vm, output) - }; - let (t1, s1) = self.pop_resolved(vm, output); - let mut s = self.stack.new_string(); - - let is_simple_int_literal = |value: &str| { - !value.is_empty() - && value - .chars() - .all(|c| c.is_ascii_digit() || c == '-' || c == '+') - }; - let is_simple_uint_literal = - |value: &str| value.ends_with('u') && is_simple_int_literal(&value[..value.len() - 1]); - let to_float_literal = |value: &str| { - if is_simple_int_literal(value) { - Some(format!("{}.0", value)) - } else if is_simple_uint_literal(value) { - Some(format!("{}.0", &value[..value.len() - 1])) - } else { - None - } - }; - let is_float_like = |ty: &ShaderType| match ty { - ShaderType::Pod(pt) => vm.bx.heap.pod_types[pt.index as usize].ty.is_float_type(), - ShaderType::AbstractFloat => true, - _ => false, - }; - let is_int_like = |ty: &ShaderType| match ty { - ShaderType::AbstractInt => true, - ShaderType::Pod(pt) - if *pt == vm.bx.code.builtins.pod.pod_i32 - || *pt == vm.bx.code.builtins.pod.pod_u32 => - { - true - } - _ => false, - }; - - let lhs = if matches!(output.backend, ShaderBackend::Glsl | ShaderBackend::Rust) - && is_int_like(&t1) - && is_float_like(&t2) - { - if let Some(v) = to_float_literal(&s1) { - v - } else { - format!("({} as f32)", s1) - } - } else { - s1.to_string() - }; - let rhs = if matches!(output.backend, ShaderBackend::Glsl | ShaderBackend::Rust) - && is_int_like(&t2) - && is_float_like(&t1) - { - if let Some(v) = to_float_literal(&s2) { - v - } else { - format!("({} as f32)", s2) - } - } else { - s2.to_string() - }; - - write!(s, "({} {} {})", lhs, op, rhs).ok(); - let ty = type_table_eq(&t1, &t2, self.trap.pass(), &vm.bx.code.builtins.pod); - self.stack.push(self.trap.pass(), ty, s); - } - - /// Handle LOGIC_AND_TEST / LOGIC_OR_TEST for shaders - /// These opcodes have short-circuit semantics in the interpreter, but in shaders - /// we evaluate both operands and combine them with the operator. - pub(crate) fn handle_logic_test( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &'static str, - ) { - // Pop the first operand (already evaluated and on the stack) - let (first_type, first_operand) = self.pop_resolved(vm, output); - - // Calculate the target IP (where the jump would land in the interpreter) - let target_ip = self.trap.ip.index + opargs.to_u32(); - - // Push a LogicOp marker - we'll combine when we reach target_ip - self.mes.push(ShaderMe::LogicOp { - target_ip, - op, - first_operand, - first_type, - }); - } - - /// Check if we've reached a logic operation's target IP and combine the operands - pub(crate) fn handle_logic_phi(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - // Loop to handle nested logic ops that may complete at the same IP - loop { - let ready_logic_index = - self.mes - .iter() - .enumerate() - .rev() - .find_map(|(index, me)| match me { - ShaderMe::FnBody { .. } - | ShaderMe::ForLoop { .. } - | ShaderMe::LoopBody { .. } - | ShaderMe::IfBody { .. } => None, - ShaderMe::LogicOp { target_ip, .. } if self.trap.ip.index >= *target_ip => { - Some(index) - } - ShaderMe::LogicOp { .. } - | ShaderMe::BuiltinCall { .. } - | ShaderMe::PodBuiltinMethod { .. } - | ShaderMe::ScriptCall { .. } - | ShaderMe::Pod { .. } - | ShaderMe::ArrayConstruct { .. } - | ShaderMe::TextureBuiltin { .. } => Some(usize::MAX), - }); - - let Some(index) = ready_logic_index else { - break; - }; - if index == usize::MAX { - break; - } - - // Pop the LogicOp and combine with the second operand on the stack - if let ShaderMe::LogicOp { - op, - first_operand, - first_type, - .. - } = self.mes.remove(index) - { - // Pop the second operand (result of evaluating the RHS) - must resolve Id types - let (second_type, second_operand) = self.pop_resolved(vm, output); - - // Combine them - let mut s = self.stack.new_string(); - write!(s, "({} {} {})", first_operand, op, second_operand).ok(); - - // Determine result type - let ty = type_table_logic( - &first_type, - &second_type, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ); - - // Push the combined result - self.stack.push(self.trap.pass(), ty, s); - - // Free the operand strings - self.stack.free_string(first_operand); - self.stack.free_string(second_operand); - } - } - } - - pub(crate) fn handle_arithmetic( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &str, - is_int: bool, - ) { - let (t2, s2) = if opargs.is_u32() { - let mut s = self.stack.new_string(); - write!(s, "{}", opargs.to_u32()).ok(); - (ShaderType::AbstractInt, s) - } else { - self.pop_resolved(vm, output) - }; - let (t1, s1) = self.pop_resolved(vm, output); - let mut s = self.stack.new_string(); - - let is_simple_int_literal = |value: &str| { - value - .chars() - .all(|c| c.is_ascii_digit() || c == '-' || c == '+') - }; - let is_float_like = |ty: &ShaderType| match ty { - ShaderType::Pod(pt) => vm.bx.heap.pod_types[pt.index as usize].ty.is_float_type(), - ShaderType::AbstractFloat => true, - _ => false, - }; - - let lhs = if matches!(output.backend, ShaderBackend::Glsl | ShaderBackend::Rust) - && !is_int - && matches!(t1, ShaderType::AbstractInt) - && is_float_like(&t2) - && is_simple_int_literal(&s1) - { - format!("{}.0", s1) - } else { - s1.to_string() - }; - let rhs = if matches!(output.backend, ShaderBackend::Glsl | ShaderBackend::Rust) - && !is_int - && matches!(t2, ShaderType::AbstractInt) - && is_float_like(&t1) - && is_simple_int_literal(&s2) - { - format!("{}.0", s2) - } else { - s2.to_string() - }; - - let is_hlsl_matrix_mul = if op == "*" && matches!(output.backend, ShaderBackend::Hlsl) { - let is_matrix = |ty: &ShaderType| match ty { - ShaderType::Pod(pod_ty) => matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Mat(_) - ), - _ => false, - }; - is_matrix(&t1) || is_matrix(&t2) - } else { - false - }; - - if is_hlsl_matrix_mul { - write!(s, "mul({}, {})", lhs, rhs).ok(); - } else { - write!(s, "({} {} {})", lhs, op, rhs).ok(); - } - let ty = if is_int { - type_table_int_arithmetic(&t1, &t2, self.trap.pass(), &vm.bx.code.builtins.pod) - } else { - type_table_float_arithmetic(&t1, &t2, self.trap.pass(), &vm.bx.code.builtins.pod) - }; - self.stack.push(self.trap.pass(), ty, s); - } - - pub(crate) fn handle_arithmetic_assign( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &str, - is_int: bool, - ) { - let (t2, s2) = if opargs.is_u32() { - let mut s = self.stack.new_string(); - write!(s, "{}", opargs.to_u32()).ok(); - (ShaderType::AbstractInt, s) - } else { - self.pop_resolved(vm, output) - }; - let (id_ty, id_s) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(id) = id_ty { - if let Some((var, shadow)) = self.shader_scope.find_var(id) { - if !matches!(var, ShaderScopeItem::Var { .. }) { - script_err_immutable!( - self.trap, - "shader: cannot assign to let-bound variable {:?}", - id - ); - } - let t1 = ShaderType::Pod(var.ty()); - let _ty = if is_int { - type_table_int_arithmetic(&t1, &t2, self.trap.pass(), &vm.bx.code.builtins.pod) - } else { - type_table_float_arithmetic( - &t1, - &t2, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ) - }; - - let mut s = self.stack.new_string(); - let var_name = if matches!(var, ShaderScopeItem::Param { .. }) { - output.backend.map_param_name(id, shadow) - } else { - output.backend.map_local_name(id, shadow) - }; - write!(s, "{}", var_name).ok(); - write!(s, " {} {}", op, s2).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!(self.trap, "shader: variable {} not found in scope", id); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else { - script_err_immutable!( - self.trap, - "shader: compound assign target must be identifier, got {:?}", - id_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(s2); - self.stack.free_string(id_s); - } - - pub(crate) fn handle_arithmetic_field_assign( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &str, - is_int: bool, - ) { - let (t2, s2) = if opargs.is_u32() { - let mut s = self.stack.new_string(); - write!(s, "{}", opargs.to_u32()).ok(); - (ShaderType::AbstractInt, s) - } else { - self.pop_resolved(vm, output) - }; - - let (field_ty, field_s) = self.stack.pop(self.trap.pass()); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Id(field_id) = field_ty { - if let ShaderType::Pod(pod_ty) = instance_ty { - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - let t1 = ShaderType::Pod(ret_ty); - let op_res_ty = if is_int { - type_table_int_arithmetic( - &t1, - &t2, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ) - } else { - type_table_float_arithmetic( - &t1, - &t2, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ) - }; - - let val_ty = op_res_ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - if val_ty != ret_ty { - script_err_pod!( - self.trap, - "shader: field {:?} compound assign type mismatch: expected {}, got {}", - field_id, - format_pod_type_name(&vm.bx.heap, ret_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let mut s = self.stack.new_string(); - let field_name = output.backend.map_field_name(field_id); - write!(s, "{0}.{1} {2} {3}", instance_s, field_name, op, s2).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!( - self.trap, - "shader: field {:?} not found in pod type{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else if let ShaderType::PodPtr(pod_ty) = instance_ty { - // Pointer type (e.g., uniform buffer in Metal) - use -> for field access - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - let t1 = ShaderType::Pod(ret_ty); - let op_res_ty = if is_int { - type_table_int_arithmetic( - &t1, - &t2, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ) - } else { - type_table_float_arithmetic( - &t1, - &t2, - self.trap.pass(), - &vm.bx.code.builtins.pod, - ) - }; - - let val_ty = op_res_ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - if val_ty != ret_ty { - script_err_pod!(self.trap, "shader: ptr field {:?} compound assign type mismatch: expected {}, got {}", field_id, format_pod_type_name(&vm.bx.heap, ret_ty), format_pod_type_name(&vm.bx.heap, val_ty)); - } - - let mut s = self.stack.new_string(); - let field_name = output.backend.map_field_name(field_id); - write!(s, "{0}->{1} {2} {3}", instance_s, field_name, op, s2).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!( - self.trap, - "shader: ptr field {:?} not found in pod type{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else { - script_err_shader!( - self.trap, - "shader: cannot do field compound assign on type {:?}", - instance_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else { - script_err_unexpected!( - self.trap, - "shader: field compound assign requires identifier, got {:?}", - field_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(s2); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - } - - pub(crate) fn handle_arithmetic_index_assign( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - op: &str, - is_int: bool, - ) { - let (t2, s2) = if opargs.is_u32() { - let mut s = self.stack.new_string(); - write!(s, "{}", opargs.to_u32()).ok(); - (ShaderType::AbstractInt, s) - } else { - self.pop_resolved(vm, output) - }; - - let (index_ty, index_s) = self.pop_resolved(vm, output); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Pod(pod_ty) = instance_ty { - let builtins = &vm.bx.code.builtins.pod; - let elem_ty = type_table_elem_type( - &vm.bx.heap.pod_types[pod_ty.index as usize].ty, - self.trap.pass(), - builtins, - ); - - if let Some(ret_ty) = elem_ty { - match index_ty { - ShaderType::AbstractInt => {} - ShaderType::Pod(t) if t == builtins.pod_i32 || t == builtins.pod_u32 => {} - _ => { - let got_type = match index_ty { - ShaderType::Pod(t) => format_pod_type_name(&vm.bx.heap, t), - _ => format!("{:?}", index_ty), - }; - script_err_pod!( - self.trap, - "shader: index must be integer, got {}", - got_type - ); - } - } - - let t1 = ShaderType::Pod(ret_ty); - let op_res_ty = if is_int { - type_table_int_arithmetic(&t1, &t2, self.trap.pass(), builtins) - } else { - type_table_float_arithmetic(&t1, &t2, self.trap.pass(), builtins) - }; - - let val_ty = op_res_ty - .make_concrete(builtins) - .unwrap_or(builtins.pod_void); - if val_ty != ret_ty { - script_err_pod!( - self.trap, - "shader: index compound assign type mismatch: expected {}, got {}", - format_pod_type_name(&vm.bx.heap, ret_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let mut s = self.stack.new_string(); - write!(s, "{}[{}] {} {}", instance_s, index_s, op, s2).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_void), s); - } else { - script_err_immutable!( - self.trap, - "shader: type is not indexable for compound assign" - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(builtins.pod_void), - String::new(), - ); - } - } else { - script_err_shader!( - self.trap, - "shader: cannot do index compound assign on type {:?}", - instance_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(s2); - self.stack.free_string(index_s); - self.stack.free_string(instance_s); - } -} diff --git a/vendor/makepad/platform/script/src/shader_output.rs b/vendor/makepad/platform/script/src/shader_output.rs deleted file mode 100644 index 42a19b2..0000000 --- a/vendor/makepad/platform/script/src/shader_output.rs +++ /dev/null @@ -1,627 +0,0 @@ -use crate::heap::*; -use crate::pod::*; -use crate::shader_backend::*; -use crate::value::*; -use crate::vm::*; -use makepad_live_id::*; -use std::collections::BTreeSet; -use std::fmt::Write; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum SamplerFilter { - Nearest, - Linear, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum SamplerAddress { - Repeat, - ClampToEdge, - ClampToZero, - MirroredRepeat, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum SamplerCoord { - Normalized, - Pixel, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ShaderSampler { - pub filter: SamplerFilter, - pub address: SamplerAddress, - pub coord: SamplerCoord, - pub is_video: bool, -} - -impl Default for ShaderSampler { - fn default() -> Self { - Self { - filter: SamplerFilter::Linear, - address: SamplerAddress::ClampToEdge, - coord: SamplerCoord::Normalized, - is_video: false, - } - } -} - -impl ShaderSampler { - pub fn video() -> Self { - Self { - is_video: true, - ..Self::default() - } - } -} - -#[derive(Default, Debug, Clone)] -pub struct ShaderSamplerOptions {} - -#[derive(Debug, Default, Clone)] -pub struct ShaderStorageFlags(u32); -impl ShaderStorageFlags { - pub fn set_read(&mut self) { - self.0 |= 1 - } - pub fn set_write(&mut self) { - self.0 |= 1 - } - pub fn is_read(&self) -> bool { - self.0 & 1 != 0 - } - pub fn is_write(&self) -> bool { - self.0 & 2 != 0 - } - pub fn is_readwrite(&self) -> bool { - self.0 & 3 == 3 - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum TextureType { - Texture1d, - Texture1dArray, - Texture2d, - Texture2dArray, - Texture3d, - Texture3dArray, - TextureCube, - TextureCubeArray, - TextureDepth, - TextureDepthArray, - TextureVideo, -} - -#[derive(Debug, Clone)] -pub enum ShaderIoKind { - StorageBuffer(ShaderStorageFlags), - UniformBuffer, - Sampler(ShaderSamplerOptions), - Texture(TextureType), - Varying, - VertexBuffer, - VertexPosition, - FragmentOutput(u8), - RustInstance, - Uniform, - DynInstance, - ScopeUniform, -} - -/// Tracks the source of a scope uniform for buffer refresh after compilation. -/// Each scope uniform comes from either: -/// - A direct scope value: `test_p1` -> source_obj is the scope, key is `test_p1` -/// - An object property: `test_obj.p2` -> source_obj is `test_obj`, key is `p2` -#[derive(Debug, Clone)] -pub struct ScopeUniformSource { - /// The source object to read the value from - pub source_obj: ScriptObject, - /// The key to read from the source object - pub key: LiveId, - /// The name used in the shader (may be prefixed for collision avoidance) - pub shader_name: LiveId, - /// The pod type of this uniform - pub ty: ScriptPodType, -} - -/// Tracks a uniform buffer defined in the script scope (e.g., `let buf = shader.uniform_buffer(...)`) -/// This is distinct from uniform buffers on io_self - these come from the surrounding scope. -#[derive(Debug, Clone)] -pub struct ScopeUniformBufferSource { - /// The uniform buffer ScriptObject itself (needed for runtime buffer binding) - pub obj: ScriptObject, - /// The pod type of the uniform buffer's prototype - pub pod_ty: ScriptPodType, - /// The name used in the shader code - pub shader_name: LiveId, -} - -/// Tracks a texture defined in the script scope (e.g., `let tex = shader.texture_2d(float)`) -/// This is distinct from textures on io_self - these come from the surrounding scope. -#[derive(Debug, Clone)] -pub struct ScopeTextureSource { - /// The texture ScriptObject itself (needed for runtime texture binding) - pub obj: ScriptObject, - /// The texture type (2d, cube, etc.) - pub tex_type: TextureType, - /// The name used in the shader code - pub shader_name: LiveId, -} - -#[allow(unused)] -#[derive(Debug)] -pub struct ShaderIo { - pub kind: ShaderIoKind, - pub name: LiveId, - pub ty: ScriptPodType, - /// Buffer index assigned during Metal/backend code generation (for uniform buffers, etc.) - pub buffer_index: Option, -} - -impl ShaderIo { - pub fn kind(&self) -> &ShaderIoKind { - &self.kind - } - - pub fn name(&self) -> LiveId { - self.name - } - - pub fn ty(&self) -> ScriptPodType { - self.ty - } - - pub fn buffer_index(&self) -> Option { - self.buffer_index - } -} - -#[derive(Default, Debug, Clone, Copy, PartialEq)] -pub enum ShaderMode { - Vertex, - #[default] - Fragment, - Compute, -} - -#[derive(Default, Debug)] -pub struct ShaderOutput { - pub mode: ShaderMode, - pub backend: ShaderBackend, - pub use_vulkan: bool, - pub io: Vec, - pub recur_block: Vec, - pub structs: BTreeSet, - pub functions: Vec, - pub samplers: Vec, - pub scope_uniforms: Vec, - pub scope_uniform_buffers: Vec, - pub scope_textures: Vec, - /// Per-texture sampler bindings inferred during shader lowering. - /// Entries are `(texture_expr, sampler_index)`. - pub texture_sampler_bindings: Vec<(String, usize)>, - /// HLSL helper: needs _mpTexSize helper function for texture.size() - pub hlsl_needs_tex_size: bool, - /// Set to true if any errors occurred during shader compilation - pub has_errors: bool, - /// True if this shader uses screen-space derivatives (dFdx/dFdy). - pub uses_derivatives: bool, - /// Monotonic temporary id source for Rust backend expression hoisting. - pub rust_tmp_counter: usize, -} - -/// Mapping of uniform buffer type names to their assigned buffer indices -#[derive(Default, Debug, Clone)] -pub struct UniformBufferBindings { - /// Maps Pod type name (e.g. DrawCallUniforms) to buffer index - pub bindings: Vec<(LiveId, usize)>, - /// Buffer index for the IoScopeUniform struct (if any scope uniforms exist) - pub scope_uniform_buffer_index: Option, -} - -impl UniformBufferBindings { - /// Look up buffer index by Pod type name - pub fn get_by_type_name(&self, type_name: LiveId) -> Option { - self.bindings - .iter() - .find(|(name, _)| *name == type_name) - .map(|(_, idx)| *idx) - } -} - -#[derive(Debug)] -pub struct ShaderFn { - pub call_sig: String, - pub overload: usize, - pub name: LiveId, - pub args: Vec, - pub fnobj: ScriptObject, - pub out: String, - pub ret: ScriptPodType, -} - -impl ShaderOutput { - pub fn next_rust_tmp_id(&mut self) -> usize { - let id = self.rust_tmp_counter; - self.rust_tmp_counter = self.rust_tmp_counter.wrapping_add(1); - id - } - - /// Pre-collect ALL Rust instance fields in the correct order for struct layout. - /// Uses recursion to process from deepest prototype to io_self, collecting all rust type properties. - /// Dyn instance fields are NOT pre-collected - they are added during compilation - /// as encountered, and their order doesn't matter. - /// - /// IoInstance struct layout: Dyn fields first (any order), Rust fields last (must match Repr(C)) - /// RustInstance fields are pushed in the correct order: deref parent fields first, then child fields. - pub fn pre_collect_rust_instance_io(&mut self, vm: &mut ScriptVm, io_self: ScriptObject) { - self.pre_collect_rust_instance_io_recursive(vm, io_self); - } - - fn pre_collect_rust_instance_io_recursive(&mut self, vm: &mut ScriptVm, obj: ScriptObject) { - // First, recurse to prototype (to process deepest ancestor first) - // This ensures parent's RustInstance fields come before child's fields - if let Some(proto_obj) = vm.bx.heap.proto(obj).as_object() { - self.pre_collect_rust_instance_io_recursive(vm, proto_obj); - } - - // Then process this object's type properties - let obj_data = vm.bx.heap.object_data(obj); - let ty_index = obj_data.tag.as_type_index(); - - if let Some(ty_index) = ty_index { - // Collect the ordered props - iter_rust_instance_ordered returns all instance fields - // (parent fields + this type's fields after deref) because rust_instance_start is now - // correctly left at 0 (config fields before deref are skipped during script_proto_props) - let type_check = vm.bx.heap.type_check(ty_index); - // Collect into a Vec first to avoid borrow issues with heap mutation below - let ordered_props: Vec<_> = type_check.props.iter_rust_instance_ordered().collect(); - - for (field_id, type_id) in ordered_props { - // Get the pod type from the type_id - if let Some(pod_ty) = vm - .bx - .heap - .type_id_to_pod_type(type_id, &vm.bx.code.builtins.pod) - { - // Skip if already added (handles duplicate prototypes in chain) - if !self.io.iter().any(|io| io.name == field_id) { - vm.bx.heap.pod_type_name_if_not_set(pod_ty, field_id); - self.io.push(ShaderIo { - kind: ShaderIoKind::RustInstance, - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - } - } - } - } - - /// Pre-collect ALL shader IO (uniforms, textures, fragment outputs) in definition order. - /// Walks from deepest prototype to io_self, collecting all shader IO properties in a single pass. - /// This ensures IO appears in definition order, not access order during compilation. - /// - /// Note: RustInstance and DynInstance are handled separately - RustInstance via - /// pre_collect_rust_instance_io (from Rust type properties), DynInstance during compilation. - pub fn pre_collect_shader_io(&mut self, vm: &mut ScriptVm, io_self: ScriptObject) { - // Use recursion to process from deepest prototype first (no temporary Vec needed) - self.pre_collect_shader_io_recursive(vm, io_self); - - // Set pod type names for uniforms (requires mutable heap, done after iteration) - for io in &self.io { - if matches!(io.kind, ShaderIoKind::Uniform) { - vm.bx.heap.pod_type_name_if_not_set(io.ty, io.name); - } - } - } - - fn pre_collect_shader_io_recursive(&mut self, vm: &ScriptVm, obj: ScriptObject) { - use crate::mod_shader::*; - - // First recurse to prototype (to process deepest first) - if let Some(proto_obj) = vm.bx.heap.proto(obj).as_object() { - self.pre_collect_shader_io_recursive(vm, proto_obj); - } - - // Then process this object's map entries in insertion order - let obj_data = vm.bx.heap.object_data(obj); - obj_data.map_iter_ordered(|key, value| { - if let Some(value_obj) = value.as_object() { - if let Some(io_type) = vm.bx.heap.as_shader_io(value_obj) { - if let Some(field_id) = key.as_id() { - // Skip if already exists (derived class overrides) - if self.io.iter().any(|io| io.name == field_id) { - return; - } - - // Get the pod type from the prototype - let proto_value = vm.bx.heap.proto(value_obj); - let pod_ty = Self::get_pod_type_from_value(vm, proto_value); - - // Handle different shader IO types - match io_type { - // Uniforms - SHADER_IO_DYN_UNIFORM => { - if let Some(pod_ty) = pod_ty { - self.io.push(ShaderIo { - kind: ShaderIoKind::Uniform, - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - } - - SHADER_IO_UNIFORM_BUFFER => { - if let Some(pod_ty) = pod_ty { - self.io.push(ShaderIo { - kind: ShaderIoKind::UniformBuffer, - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - } - - // Fragment outputs - io_type if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 => { - let index = (io_type.0 - SHADER_IO_FRAGMENT_OUTPUT_0.0) as u8; - // Check by index, not name - let already_exists = self.io.iter().any(|io| { - matches!(io.kind, ShaderIoKind::FragmentOutput(idx) if idx == index) - }); - if !already_exists { - if let Some(pod_ty) = pod_ty { - self.io.push(ShaderIo { - kind: ShaderIoKind::FragmentOutput(index), - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - } - } - - // Textures - SHADER_IO_TEXTURE_1D => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture1d), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_1D_ARRAY => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture1dArray), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_2D => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture2d), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_2D_ARRAY => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture2dArray), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_3D => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture3d), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_3D_ARRAY => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::Texture3dArray), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_CUBE => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::TextureCube), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_CUBE_ARRAY => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::TextureCubeArray), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_DEPTH => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::TextureDepth), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_DEPTH_ARRAY => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::TextureDepthArray), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - SHADER_IO_TEXTURE_VIDEO => self.io.push(ShaderIo { kind: ShaderIoKind::Texture(TextureType::TextureVideo), name: field_id, ty: ScriptPodType::VOID, buffer_index: None }), - - // Other IO types are handled during compilation or elsewhere - _ => {} - } - } - } - } - }); - } - - pub(crate) fn get_pod_type_from_value( - vm: &ScriptVm, - value: ScriptValue, - ) -> Option { - // Check if it's a primitive type (f32, f64, bool, etc.) - if let Some(pod_ty) = vm.bx.code.builtins.pod.value_to_exact_type(value) { - return Some(pod_ty); - } - // Check if it's a color - colors map to vec4f - if value.is_color() { - return Some(vm.bx.code.builtins.pod.pod_vec4f); - } - // Check if it's a pod type object - if let Some(pod_ty) = vm.bx.heap.pod_type(value) { - return Some(pod_ty); - } - // Check if it's a pod instance - if let Some(pod) = value.as_pod() { - let pod = &vm.bx.heap.pods[pod]; - return Some(pod.ty); - } - // Check if it's a pod type reference - if let Some(pod_ty) = value.as_pod_type() { - return Some(pod_ty); - } - None - } - - pub fn create_struct_defs(&mut self, vm: &ScriptVm, out: &mut String) { - let mut plain_structs = self.structs.clone(); - let mut packed_structs = BTreeSet::new(); - - for io in &self.io { - let ty = io.ty; - if !matches!(vm.bx.heap.pod_type_ref(ty).ty, ScriptPodTy::Struct { .. }) { - continue; - } - - if matches!(self.backend, ShaderBackend::Metal) - && matches!( - io.kind, - ShaderIoKind::UniformBuffer - | ShaderIoKind::VertexBuffer - | ShaderIoKind::RustInstance - | ShaderIoKind::DynInstance - ) - { - packed_structs.insert(ty); - } else { - plain_structs.insert(ty); - } - } - - for ty in &packed_structs { - plain_structs.remove(ty); - } - - self.structs.extend(plain_structs.iter().copied()); - self.structs.extend(packed_structs.iter().copied()); - - if matches!(self.backend, ShaderBackend::Metal) { - self.backend - .pod_struct_defs_mixed(&vm.bx.heap, &plain_structs, &packed_structs, out); - } else { - self.backend - .pod_struct_defs(&vm.bx.heap, &self.structs, out); - } - } - - pub fn create_functions(&self, out: &mut String) { - for fns in &self.functions { - writeln!(out, "{}{{", fns.call_sig).ok(); - if matches!(self.backend, ShaderBackend::Hlsl) { - if fns.call_sig.contains("inout IoV _iov") { - // DXC requires explicit definite assignment for inout params. - writeln!(out, " _iov = _iov;").ok(); - } - if fns.call_sig.contains("inout IoF _iof") { - // DXC requires explicit definite assignment for inout params. - writeln!(out, " _iof = _iof;").ok(); - } - } - writeln!(out, "{}", fns.out).ok(); - writeln!(out, "}}\n").ok(); - } - } - - /// Find the vertex buffer object from io_self by looking for SHADER_IO_VERTEX_BUFFER type - pub fn find_vertex_buffer_object( - &self, - vm: &ScriptVm, - io_self: ScriptObject, - ) -> Option { - use crate::mod_shader::SHADER_IO_VERTEX_BUFFER; - - // Walk the prototype chain looking for vertex buffer properties - let mut current = Some(io_self); - while let Some(obj) = current { - let obj_data = vm.bx.heap.object_data(obj); - - // Check map properties - if let Some(ret) = obj_data.map_iter_ret(|_key, value| { - if let Some(value_obj) = value.as_object() { - if let Some(io_type) = vm.bx.heap.as_shader_io(value_obj) { - if io_type == SHADER_IO_VERTEX_BUFFER { - return Some(value_obj); - } - } - } - None - }) { - return Some(ret); - } - - // Move to next prototype - current = vm.bx.heap.proto(obj).as_object(); - } - None - } - - /// Assign buffer indices to uniform buffers starting from `start_index`. - /// Returns the UniformBufferBindings and the next available buffer index. - /// Also sets the buffer_index field on each ShaderIo. - pub fn assign_uniform_buffer_indices( - &mut self, - heap: &ScriptHeap, - start_index: usize, - ) -> (UniformBufferBindings, usize) { - let mut bindings = UniformBufferBindings::default(); - let mut buf_idx = start_index; - - for io in &mut self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - // Get the Pod type name for this uniform buffer - let pod_type = heap.pod_type_ref(io.ty); - if let Some(type_name) = pod_type.name { - bindings.bindings.push((type_name, buf_idx)); - } - io.buffer_index = Some(buf_idx); - buf_idx += 1; - } - } - - // Assign scope uniform buffer index if we have any scope uniforms - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - if has_scope_uniforms { - bindings.scope_uniform_buffer_index = Some(buf_idx); - buf_idx += 1; - } - - (bindings, buf_idx) - } - - /// Get the UniformBufferBindings from the current IO state. - /// This should be called after `assign_uniform_buffer_indices` has been called. - pub fn get_uniform_buffer_bindings(&self, heap: &ScriptHeap) -> UniformBufferBindings { - let mut bindings = UniformBufferBindings::default(); - - for io in &self.io { - if let ShaderIoKind::UniformBuffer = io.kind { - if let Some(buf_idx) = io.buffer_index { - let pod_type = heap.pod_type_ref(io.ty); - if let Some(type_name) = pod_type.name { - bindings.bindings.push((type_name, buf_idx)); - } - } - } - } - - // Compute scope uniform buffer index (one past the max uniform buffer index, or start at 3) - let has_scope_uniforms = self - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - if has_scope_uniforms { - let max_idx = self - .io - .iter() - .filter_map(|io| io.buffer_index) - .max() - .map(|m| m + 1) - .unwrap_or(3); - bindings.scope_uniform_buffer_index = Some(max_idx); - } - - bindings - } - - /// Get or create a sampler with the given properties, returns the sampler index - pub fn get_or_create_sampler(&mut self, sampler: ShaderSampler) -> usize { - // Check if we already have this sampler - if let Some(idx) = self.samplers.iter().position(|s| *s == sampler) { - return idx; - } - // Create new sampler - let idx = self.samplers.len(); - self.samplers.push(sampler); - idx - } - - /// Record sampler usage for a texture expression. - /// If the same texture is sampled multiple times, the first sampler wins. - pub fn bind_texture_sampler(&mut self, texture_expr: &str, sampler_idx: usize) { - if self - .texture_sampler_bindings - .iter() - .any(|(expr, _)| expr == texture_expr) - { - return; - } - self.texture_sampler_bindings - .push((texture_expr.to_string(), sampler_idx)); - } -} diff --git a/vendor/makepad/platform/script/src/shader_tables.rs b/vendor/makepad/platform/script/src/shader_tables.rs deleted file mode 100644 index 3f460a4..0000000 --- a/vendor/makepad/platform/script/src/shader_tables.rs +++ /dev/null @@ -1,651 +0,0 @@ -use crate::mod_pod::ScriptPodBuiltins; -use crate::pod::*; -use crate::shader::ShaderType; -use crate::trap::ScriptTrap; -use crate::value::*; -use crate::*; - -pub fn type_table_neg( - val: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let r = match val { - ShaderType::AbstractInt => ShaderType::AbstractInt, - ShaderType::AbstractFloat => ShaderType::AbstractFloat, - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_f32), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_f16), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_i32), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_vec2h => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_vec3h => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_vec4h => ShaderType::Pod(builtins.pod_vec4h), - ShaderType::Pod(x) if *x == builtins.pod_vec2i => ShaderType::Pod(builtins.pod_vec2i), - ShaderType::Pod(x) if *x == builtins.pod_vec3i => ShaderType::Pod(builtins.pod_vec3i), - ShaderType::Pod(x) if *x == builtins.pod_vec4i => ShaderType::Pod(builtins.pod_vec4i), - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_shader!(trap, "opcode not defined for type"); - } - r -} - -pub fn type_table_float_arithmetic( - lhs: &ShaderType, - rhs: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let r = match lhs { - ShaderType::AbstractFloat => match rhs { - ShaderType::AbstractFloat => ShaderType::AbstractFloat, - ShaderType::AbstractInt => ShaderType::AbstractFloat, - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_f32), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_f16), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_vec2h => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_vec3h => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_vec4h => ShaderType::Pod(builtins.pod_vec4h), - // abstract float * matrix -> matrix - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => { - ShaderType::Pod(builtins.pod_mat2x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x3f => { - ShaderType::Pod(builtins.pod_mat2x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x4f => { - ShaderType::Pod(builtins.pod_mat2x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x2f => { - ShaderType::Pod(builtins.pod_mat3x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => { - ShaderType::Pod(builtins.pod_mat3x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x4f => { - ShaderType::Pod(builtins.pod_mat3x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x2f => { - ShaderType::Pod(builtins.pod_mat4x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x3f => { - ShaderType::Pod(builtins.pod_mat4x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => { - ShaderType::Pod(builtins.pod_mat4x4f) - } - _ => ShaderType::Error(NIL), - }, - ShaderType::AbstractInt => match rhs { - ShaderType::AbstractFloat => ShaderType::AbstractFloat, - ShaderType::AbstractInt => ShaderType::AbstractInt, - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_u32), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_i32), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_vec2h => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_vec3h => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_vec4h => ShaderType::Pod(builtins.pod_vec4h), - ShaderType::Pod(x) if *x == builtins.pod_vec2u => ShaderType::Pod(builtins.pod_vec2u), - ShaderType::Pod(x) if *x == builtins.pod_vec3u => ShaderType::Pod(builtins.pod_vec3u), - ShaderType::Pod(x) if *x == builtins.pod_vec4u => ShaderType::Pod(builtins.pod_vec4u), - ShaderType::Pod(x) if *x == builtins.pod_vec2i => ShaderType::Pod(builtins.pod_vec2i), - ShaderType::Pod(x) if *x == builtins.pod_vec3i => ShaderType::Pod(builtins.pod_vec3i), - ShaderType::Pod(x) if *x == builtins.pod_vec4i => ShaderType::Pod(builtins.pod_vec4i), - // abstract int * matrix -> matrix - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => { - ShaderType::Pod(builtins.pod_mat2x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x3f => { - ShaderType::Pod(builtins.pod_mat2x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x4f => { - ShaderType::Pod(builtins.pod_mat2x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x2f => { - ShaderType::Pod(builtins.pod_mat3x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => { - ShaderType::Pod(builtins.pod_mat3x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x4f => { - ShaderType::Pod(builtins.pod_mat3x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x2f => { - ShaderType::Pod(builtins.pod_mat4x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x3f => { - ShaderType::Pod(builtins.pod_mat4x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => { - ShaderType::Pod(builtins.pod_mat4x4f) - } - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_f32 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_f32), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_f32), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_f32), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - // scalar * matrix -> matrix - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => { - ShaderType::Pod(builtins.pod_mat2x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x3f => { - ShaderType::Pod(builtins.pod_mat2x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat2x4f => { - ShaderType::Pod(builtins.pod_mat2x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x2f => { - ShaderType::Pod(builtins.pod_mat3x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => { - ShaderType::Pod(builtins.pod_mat3x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat3x4f => { - ShaderType::Pod(builtins.pod_mat3x4f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x2f => { - ShaderType::Pod(builtins.pod_mat4x2f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x3f => { - ShaderType::Pod(builtins.pod_mat4x3f) - } - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => { - ShaderType::Pod(builtins.pod_mat4x4f) - } - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_f16 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_f16), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_f16), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_f16), - ShaderType::Pod(x) if *x == builtins.pod_vec2h => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_vec3h => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_vec4h => ShaderType::Pod(builtins.pod_vec4h), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_u32 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_u32), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_u32), - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_u32), - ShaderType::Pod(x) if *x == builtins.pod_vec2u => ShaderType::Pod(builtins.pod_vec2u), - ShaderType::Pod(x) if *x == builtins.pod_vec3u => ShaderType::Pod(builtins.pod_vec3u), - ShaderType::Pod(x) if *x == builtins.pod_vec4u => ShaderType::Pod(builtins.pod_vec4u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_i32 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_i32), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_i32), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_i32), - ShaderType::Pod(x) if *x == builtins.pod_vec2i => ShaderType::Pod(builtins.pod_vec2i), - ShaderType::Pod(x) if *x == builtins.pod_vec3i => ShaderType::Pod(builtins.pod_vec3i), - ShaderType::Pod(x) if *x == builtins.pod_vec4i => ShaderType::Pod(builtins.pod_vec4i), - _ => ShaderType::Error(NIL), - }, - // vec2f * matCx2 -> vecC (vector * matrix multiplication) - ShaderType::Pod(x) if *x == builtins.pod_vec2f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_mat3x2f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_mat4x2f => ShaderType::Pod(builtins.pod_vec4f), - _ => ShaderType::Error(NIL), - }, - // vec3f * matCx3 -> vecC - ShaderType::Pod(x) if *x == builtins.pod_vec3f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_mat2x3f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_mat4x3f => ShaderType::Pod(builtins.pod_vec4f), - _ => ShaderType::Error(NIL), - }, - // vec4f * matCx4 -> vecC - ShaderType::Pod(x) if *x == builtins.pod_vec4f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_mat2x4f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_mat3x4f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => ShaderType::Pod(builtins.pod_vec4f), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2h => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_vec2h), - ShaderType::Pod(x) if *x == builtins.pod_vec2h => ShaderType::Pod(builtins.pod_vec2h), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3h => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_vec3h), - ShaderType::Pod(x) if *x == builtins.pod_vec3h => ShaderType::Pod(builtins.pod_vec3h), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4h => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_vec4h), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec4h), - ShaderType::Pod(x) if *x == builtins.pod_f16 => ShaderType::Pod(builtins.pod_vec4h), - ShaderType::Pod(x) if *x == builtins.pod_vec4h => ShaderType::Pod(builtins.pod_vec4h), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2u => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec2u), - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_vec2u), - ShaderType::Pod(x) if *x == builtins.pod_vec2u => ShaderType::Pod(builtins.pod_vec2u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3u => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec3u), - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_vec3u), - ShaderType::Pod(x) if *x == builtins.pod_vec3u => ShaderType::Pod(builtins.pod_vec3u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4u => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec4u), - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_vec4u), - ShaderType::Pod(x) if *x == builtins.pod_vec4u => ShaderType::Pod(builtins.pod_vec4u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2i => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec2i), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_vec2i), - ShaderType::Pod(x) if *x == builtins.pod_vec2i => ShaderType::Pod(builtins.pod_vec2i), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3i => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec3i), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_vec3i), - ShaderType::Pod(x) if *x == builtins.pod_vec3i => ShaderType::Pod(builtins.pod_vec3i), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4i => match rhs { - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_vec4i), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_vec4i), - ShaderType::Pod(x) if *x == builtins.pod_vec4i => ShaderType::Pod(builtins.pod_vec4i), - _ => ShaderType::Error(NIL), - }, - // Matrix multiplication: matCxR * vecR -> vecC - // mat2x2f * vec2f -> vec2f, mat2x2f * scalar -> mat2x2f - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat2x2f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat2x2f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat2x2f), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec2f), - ShaderType::Pod(x) if *x == builtins.pod_mat2x2f => { - ShaderType::Pod(builtins.pod_mat2x2f) - } - _ => ShaderType::Error(NIL), - }, - // mat2x3f * vec3f -> vec2f - ShaderType::Pod(x) if *x == builtins.pod_mat2x3f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat2x3f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat2x3f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat2x3f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec2f), - _ => ShaderType::Error(NIL), - }, - // mat2x4f * vec4f -> vec2f - ShaderType::Pod(x) if *x == builtins.pod_mat2x4f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat2x4f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat2x4f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat2x4f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec2f), - _ => ShaderType::Error(NIL), - }, - // mat3x2f * vec2f -> vec3f - ShaderType::Pod(x) if *x == builtins.pod_mat3x2f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat3x2f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat3x2f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat3x2f), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec3f), - _ => ShaderType::Error(NIL), - }, - // mat3x3f * vec3f -> vec3f - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat3x3f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat3x3f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat3x3f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec3f), - ShaderType::Pod(x) if *x == builtins.pod_mat3x3f => { - ShaderType::Pod(builtins.pod_mat3x3f) - } - _ => ShaderType::Error(NIL), - }, - // mat3x4f * vec4f -> vec3f - ShaderType::Pod(x) if *x == builtins.pod_mat3x4f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat3x4f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat3x4f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat3x4f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec3f), - _ => ShaderType::Error(NIL), - }, - // mat4x2f * vec2f -> vec4f - ShaderType::Pod(x) if *x == builtins.pod_mat4x2f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat4x2f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat4x2f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat4x2f), - ShaderType::Pod(x) if *x == builtins.pod_vec2f => ShaderType::Pod(builtins.pod_vec4f), - _ => ShaderType::Error(NIL), - }, - // mat4x3f * vec3f -> vec4f - ShaderType::Pod(x) if *x == builtins.pod_mat4x3f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat4x3f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat4x3f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat4x3f), - ShaderType::Pod(x) if *x == builtins.pod_vec3f => ShaderType::Pod(builtins.pod_vec4f), - _ => ShaderType::Error(NIL), - }, - // mat4x4f * vec4f -> vec4f - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_mat4x4f), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_mat4x4f), - ShaderType::Pod(x) if *x == builtins.pod_f32 => ShaderType::Pod(builtins.pod_mat4x4f), - ShaderType::Pod(x) if *x == builtins.pod_vec4f => ShaderType::Pod(builtins.pod_vec4f), - ShaderType::Pod(x) if *x == builtins.pod_mat4x4f => { - ShaderType::Pod(builtins.pod_mat4x4f) - } - _ => ShaderType::Error(NIL), - }, - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_shader!(trap, "no wgsl conversion"); - } - r -} - -pub fn type_table_int_arithmetic( - lhs: &ShaderType, - rhs: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let r = match lhs { - ShaderType::AbstractFloat => match rhs { - _ => ShaderType::Error(NIL), - }, - ShaderType::AbstractInt => match rhs { - ShaderType::AbstractInt => ShaderType::AbstractInt, - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_u32), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_i32), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_u32 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_u32), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_u32), - ShaderType::Pod(x) if *x == builtins.pod_u32 => ShaderType::Pod(builtins.pod_u32), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_i32 => match rhs { - ShaderType::AbstractFloat => ShaderType::Pod(builtins.pod_i32), - ShaderType::AbstractInt => ShaderType::Pod(builtins.pod_i32), - ShaderType::Pod(x) if *x == builtins.pod_i32 => ShaderType::Pod(builtins.pod_i32), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2u => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec2u => ShaderType::Pod(builtins.pod_vec2u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3u => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec3u => ShaderType::Pod(builtins.pod_vec3u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4u => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec4u => ShaderType::Pod(builtins.pod_vec4u), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2i => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec2i => ShaderType::Pod(builtins.pod_vec2i), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3i => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec3i => ShaderType::Pod(builtins.pod_vec3i), - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4i => match rhs { - ShaderType::Pod(x) if *x == builtins.pod_vec4i => ShaderType::Pod(builtins.pod_vec4i), - _ => ShaderType::Error(NIL), - }, - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_shader!(trap, "no wgsl conversion"); - } - r -} - -pub fn type_table_logic( - lhs: &ShaderType, - rhs: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let bool_ty = ShaderType::Pod(builtins.pod_bool); - let r = match lhs { - ShaderType::Pod(x) if *x == builtins.pod_bool => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_bool => bool_ty, - _ => ShaderType::Error(NIL), - }, - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_shader!(trap, "no wgsl conversion"); - } - r -} - -pub fn type_table_eq( - lhs: &ShaderType, - rhs: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let bool_ty = ShaderType::Pod(builtins.pod_bool); - let vec2b_ty = ShaderType::Pod(builtins.pod_vec2b); - let vec3b_ty = ShaderType::Pod(builtins.pod_vec3b); - let vec4b_ty = ShaderType::Pod(builtins.pod_vec4b); - - let r = match lhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => match rhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => bool_ty, - ShaderType::Pod(x) - if *x == builtins.pod_f32 - || *x == builtins.pod_f16 - || *x == builtins.pod_u32 - || *x == builtins.pod_i32 => - { - bool_ty - } - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_f32 => match rhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => bool_ty, - ShaderType::Pod(y) if *y == builtins.pod_f32 => bool_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_f16 => match rhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => bool_ty, - ShaderType::Pod(y) if *y == builtins.pod_f16 => bool_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_u32 => match rhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => bool_ty, - ShaderType::Pod(y) if *y == builtins.pod_u32 => bool_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_i32 => match rhs { - ShaderType::AbstractFloat | ShaderType::AbstractInt => bool_ty, - ShaderType::Pod(y) if *y == builtins.pod_i32 => bool_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_bool => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_bool => bool_ty, - _ => ShaderType::Error(NIL), - }, - // Vec2f - ShaderType::Pod(x) if *x == builtins.pod_vec2f => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec2f => vec2b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2h => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec2h => vec2b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2u => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec2u => vec2b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec2i => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec2i => vec2b_ty, - _ => ShaderType::Error(NIL), - }, - // Vec3f - ShaderType::Pod(x) if *x == builtins.pod_vec3f => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec3f => vec3b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3h => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec3h => vec3b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3u => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec3u => vec3b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec3i => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec3i => vec3b_ty, - _ => ShaderType::Error(NIL), - }, - // Vec4f - ShaderType::Pod(x) if *x == builtins.pod_vec4f => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec4f => vec4b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4h => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec4h => vec4b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4u => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec4u => vec4b_ty, - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) if *x == builtins.pod_vec4i => match rhs { - ShaderType::Pod(y) if *y == builtins.pod_vec4i => vec4b_ty, - _ => ShaderType::Error(NIL), - }, - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_shader!(trap, "no wgsl conversion"); - } - r -} - -pub fn type_table_if_else( - lhs: &ShaderType, - rhs: &ShaderType, - trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> ShaderType { - let r = match lhs { - ShaderType::AbstractFloat => match rhs { - ShaderType::AbstractFloat => ShaderType::AbstractFloat, - ShaderType::AbstractInt => ShaderType::AbstractFloat, - ShaderType::Pod(x) if *x == builtins.pod_f32 || *x == builtins.pod_f16 => { - ShaderType::Pod(*x) - } - _ => ShaderType::Error(NIL), - }, - ShaderType::AbstractInt => match rhs { - ShaderType::AbstractFloat => ShaderType::AbstractFloat, - ShaderType::AbstractInt => ShaderType::AbstractInt, - ShaderType::Pod(x) - if *x == builtins.pod_f32 - || *x == builtins.pod_f16 - || *x == builtins.pod_i32 - || *x == builtins.pod_u32 => - { - ShaderType::Pod(*x) - } - _ => ShaderType::Error(NIL), - }, - ShaderType::Pod(x) => match rhs { - ShaderType::AbstractFloat if *x == builtins.pod_f32 || *x == builtins.pod_f16 => { - ShaderType::Pod(*x) - } - ShaderType::AbstractInt - if *x == builtins.pod_f32 - || *x == builtins.pod_f16 - || *x == builtins.pod_i32 - || *x == builtins.pod_u32 => - { - ShaderType::Pod(*x) - } - ShaderType::Pod(y) if x == y => ShaderType::Pod(*x), - _ => ShaderType::Error(NIL), - }, - _ => ShaderType::Error(NIL), - }; - if let ShaderType::Error(_) = r { - script_err_inconsistent!(trap, "if-else type mismatch"); - } - r -} - -pub fn type_table_elem_type( - ty: &ScriptPodTy, - _trap: ScriptTrap, - builtins: &ScriptPodBuiltins, -) -> Option { - match ty { - ScriptPodTy::FixedArray { ty, .. } => Some(ty.self_ref), - ScriptPodTy::VariableArray { ty, .. } => Some(ty.self_ref), - ScriptPodTy::Vec(v) => match v { - ScriptPodVec::Vec2f | ScriptPodVec::Vec3f | ScriptPodVec::Vec4f => { - Some(builtins.pod_f32) - } - ScriptPodVec::Vec2h | ScriptPodVec::Vec3h | ScriptPodVec::Vec4h => { - Some(builtins.pod_f16) - } - ScriptPodVec::Vec2u | ScriptPodVec::Vec3u | ScriptPodVec::Vec4u => { - Some(builtins.pod_u32) - } - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - Some(builtins.pod_i32) - } - ScriptPodVec::Vec2b | ScriptPodVec::Vec3b | ScriptPodVec::Vec4b => { - Some(builtins.pod_bool) - } - }, - ScriptPodTy::Mat(m) => match m { - ScriptPodMat::Mat2x2f | ScriptPodMat::Mat3x2f | ScriptPodMat::Mat4x2f => { - Some(builtins.pod_vec2f) - } - ScriptPodMat::Mat2x3f | ScriptPodMat::Mat3x3f | ScriptPodMat::Mat4x3f => { - Some(builtins.pod_vec3f) - } - ScriptPodMat::Mat2x4f | ScriptPodMat::Mat3x4f | ScriptPodMat::Mat4x4f => { - Some(builtins.pod_vec4f) - } - }, - _ => None, - } -} diff --git a/vendor/makepad/platform/script/src/shader_vars.rs b/vendor/makepad/platform/script/src/shader_vars.rs deleted file mode 100644 index 6c0cbf0..0000000 --- a/vendor/makepad/platform/script/src/shader_vars.rs +++ /dev/null @@ -1,1542 +0,0 @@ -//! Shader variable and field operations -//! -//! This module contains handle functions for variable declarations (let, var), -//! assignments, field access, and logging. - -use crate::mod_shader::*; -use crate::opcode::*; -use crate::shader::*; -use crate::shader_backend::*; -use crate::shader_tables::*; -use crate::suggest::*; -use crate::trap::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use makepad_live_id::*; -use std::fmt::Write; - -impl ShaderFnCompiler { - pub(crate) fn handle_log(&mut self, vm: &ScriptVm) { - let (ty, value_str) = self.stack.peek(self.trap.pass()); - let type_name = self.shader_type_to_string(vm, ty); - if let Some(loc) = vm.bx.code.ip_to_loc(self.trap.ip) { - crate::makepad_error_log::log_with_level( - &loc.file, - loc.line, - loc.col, - loc.line, - loc.col, - format!("{}:{}", value_str, type_name), - crate::makepad_error_log::LogLevel::Log, - ); - } - } - - pub(crate) fn shader_type_to_string(&self, vm: &ScriptVm, ty: &ShaderType) -> String { - match ty { - ShaderType::None => "none".to_string(), - ShaderType::IoSelf(_) => "io".to_string(), - ShaderType::PodType(pod_ty) | ShaderType::Pod(pod_ty) | ShaderType::PodPtr(pod_ty) => { - if let Some(name) = vm.bx.heap.pod_type_name(*pod_ty) { - name.to_string() - } else { - format!("{:?}", pod_ty) - } - } - ShaderType::Id(id) => { - // Try to resolve the id to get its actual type - if let Some((sc, _shadow)) = self.shader_scope.find_var(*id) { - let pod_ty = sc.ty(); - if let Some(name) = vm.bx.heap.pod_type_name(pod_ty) { - return name.to_string(); - } - } - format!("id({})", id) - } - ShaderType::AbstractInt => "abstract_int".to_string(), - ShaderType::AbstractFloat => "abstract_float".to_string(), - ShaderType::Range { ty, .. } => { - if let Some(name) = vm.bx.heap.pod_type_name(*ty) { - format!("range<{}>", name) - } else { - "range".to_string() - } - } - ShaderType::Error(_) => "error".to_string(), - ShaderType::Texture(tex_type) => format!("texture({:?})", tex_type), - ShaderType::ScopeTexture { tex_type, .. } => format!("scope_texture({:?})", tex_type), - ShaderType::ScopeObject(_) => "scope_object".to_string(), - ShaderType::ScopeUniformBuffer { pod_ty, .. } => { - if let Some(name) = vm.bx.heap.pod_type_name(*pod_ty) { - format!("scope_uniform_buffer<{}>", name) - } else { - "scope_uniform_buffer".to_string() - } - } - } - } - - pub(crate) fn handle_assign(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - let (_value_ty, value) = self.stack.pop(self.trap.pass()); - let (id_ty, _id) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(id) = id_ty { - if let Some((var, shadow)) = self.shader_scope.find_var(id) { - if !matches!(var, ShaderScopeItem::Var { .. }) { - script_err_immutable!(self.trap, "cannot assign to let binding {:?}", id); - } - let mut s = self.stack.new_string(); - let var_name = if matches!(var, ShaderScopeItem::Param { .. }) { - // Params are immutable and should not reach assignment, but keep this path stable. - output.backend.map_param_name(id, shadow) - } else { - output.backend.map_local_name(id, shadow) - }; - write!(s, "{}", var_name).ok(); - write!(s, " = {}", value).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!( - self.trap, - "variable {:?} not found in shader scope{}", - id, - suggest_from_live_ids(id, &self.shader_scope.all_var_names()) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else { - script_err_immutable!(self.trap, "shader assign target is not an id"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(value); - } - - pub(crate) fn handle_assign_field(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - let (value_ty, value_s) = self.pop_resolved(vm, output); - let (field_ty, field_s) = self.stack.pop(self.trap.pass()); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Id(field_id) = field_ty { - if let ShaderType::Pod(pod_ty) = instance_ty { - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - let val_ty = value_ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - if val_ty != ret_ty { - script_err_pod!( - self.trap, - "field {:?} type mismatch: expected {}, got {}", - field_id, - format_pod_type_name(&vm.bx.heap, ret_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}.{} = {}", instance_s, field_name, value_s).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!( - self.trap, - "field {:?} not found on pod{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else if let ShaderType::PodPtr(pod_ty) = instance_ty { - // Pointer type (e.g., uniform buffer in Metal) - use -> for field access - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - let val_ty = value_ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - if val_ty != ret_ty { - script_err_pod!( - self.trap, - "field {:?} type mismatch on pod ptr: expected {}, got {}", - field_id, - format_pod_type_name(&vm.bx.heap, ret_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}->{} = {}", instance_s, field_name, value_s).ok(); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - } else { - script_err_not_found!( - self.trap, - "field {:?} not found on pod ptr{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else if let ShaderType::IoSelf(obj) = instance_ty { - let value = vm.bx.heap.value(obj, field_id.into(), self.trap.pass()); - if let Some(value_obj) = value.as_object() { - if let Some(io_type) = vm.bx.heap.as_shader_io(value_obj) { - let allowed = match io_type { - SHADER_IO_VARYING => output.mode == ShaderMode::Vertex, - SHADER_IO_VERTEX_POSITION => output.mode == ShaderMode::Vertex, - io_type - if io_type.0 >= SHADER_IO_FRAGMENT_OUTPUT_0.0 - && io_type.0 <= SHADER_IO_FRAGMENT_OUTPUT_MAX.0 => - { - output.mode == ShaderMode::Fragment - } - _ => false, - }; - - if !allowed { - script_err_immutable!( - self.trap, - "cannot assign to shader io in this mode" - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - self.stack.free_string(value_s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - // we need to find the type of the field - let proto = vm.bx.heap.proto(value.as_object().unwrap()); - let ty = Self::type_from_value(vm, proto); - let concrete_ty = match ty { - ShaderType::Pod(pt) => Some(pt), - ShaderType::PodType(pt) => Some(pt), - _ => None, - }; - - if let Some(pod_ty) = concrete_ty { - let val_ty = value_ty - .make_concrete(&vm.bx.code.builtins.pod) - .unwrap_or(vm.bx.code.builtins.pod.pod_void); - if val_ty != pod_ty { - script_err_pod!( - self.trap, - "shader io field {:?} type mismatch: expected {}, got {}", - field_id, - format_pod_type_name(&vm.bx.heap, pod_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let (kind, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, io_type); - - if !output.io.iter().any(|io| io.name == field_id) { - output.io.push(ShaderIo { - kind, - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - let mut s = self.stack.new_string(); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(field_id); - write!(s, "{}{} = {}", prefix, io_name, value_s).ok() - } - ShaderIoPrefix::Full(full) => { - write!(s, "{} = {}", full, value_s).ok() - } - ShaderIoPrefix::FullOwned(full) => { - write!(s, "{} = {}", full, value_s).ok() - } - }; - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - s, - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - self.stack.free_string(value_s); - return; - } - } - } - script_err_shader!(self.trap, "no matching shader type for self field"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } else { - script_err_shader!(self.trap, "no matching shader type for instance"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } else { - script_err_unexpected!(self.trap, "field assign requires Id field type"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(value_s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - } - - pub(crate) fn handle_array_index(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - let (index_ty, index_s) = self.pop_resolved(vm, output); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Pod(pod_ty) = instance_ty { - let builtins = &vm.bx.code.builtins.pod; - let elem_ty = type_table_elem_type( - &vm.bx.heap.pod_types[pod_ty.index as usize].ty, - self.trap.pass(), - builtins, - ); - - if let Some(ret_ty) = elem_ty { - // Validate index type - must be integer - match index_ty { - ShaderType::AbstractInt => {} - ShaderType::Pod(t) if t == builtins.pod_i32 || t == builtins.pod_u32 => {} - _ => { - let got_type = match index_ty { - ShaderType::Pod(t) => format_pod_type_name(&vm.bx.heap, t), - _ => format!("{:?}", index_ty), - }; - script_err_pod!(self.trap, "array index must be integer, got {}", got_type); - } - } - - let mut s = self.stack.new_string(); - write!(s, "{}[{}]", instance_s, index_s).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - } else { - script_err_shader!(self.trap, "type is not indexable"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(builtins.pod_void), - String::new(), - ); - } - } else { - script_err_shader!( - self.trap, - "array index requires Pod type, got {:?}", - instance_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(index_s); - self.stack.free_string(instance_s); - } - - pub(crate) fn handle_assign_index(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - let (value_ty, value_s) = self.pop_resolved(vm, output); - let (index_ty, index_s) = self.pop_resolved(vm, output); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Pod(pod_ty) = instance_ty { - let builtins = &vm.bx.code.builtins.pod; - let elem_ty = type_table_elem_type( - &vm.bx.heap.pod_types[pod_ty.index as usize].ty, - self.trap.pass(), - builtins, - ); - - if let Some(ret_ty) = elem_ty { - match index_ty { - ShaderType::AbstractInt => {} - ShaderType::Pod(t) if t == builtins.pod_i32 || t == builtins.pod_u32 => {} - _ => { - let got_type = match index_ty { - ShaderType::Pod(t) => format_pod_type_name(&vm.bx.heap, t), - _ => format!("{:?}", index_ty), - }; - script_err_pod!( - self.trap, - "index type must be int or uint, got {}", - got_type - ); - } - } - - let val_ty = value_ty - .make_concrete(builtins) - .unwrap_or(builtins.pod_void); - if val_ty != ret_ty { - script_err_pod!( - self.trap, - "index assign type mismatch: expected {}, got {}", - format_pod_type_name(&vm.bx.heap, ret_ty), - format_pod_type_name(&vm.bx.heap, val_ty) - ); - } - - let mut s = self.stack.new_string(); - write!(s, "{}[{}] = {}", instance_s, index_s, value_s).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(builtins.pod_void), s); - } else { - script_err_immutable!(self.trap, "index assign not supported for this type"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(builtins.pod_void), - String::new(), - ); - } - } else { - script_err_shader!(self.trap, "index assign requires Pod type"); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(value_s); - self.stack.free_string(index_s); - self.stack.free_string(instance_s); - } - - pub(crate) fn handle_assign_me(&mut self, vm: &mut ScriptVm) { - let (val_ty, val_s) = self.stack.pop(self.trap.pass()); - let (id_ty, id_s) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(id) = id_ty { - if let Some(ShaderMe::Pod { args, .. }) = self.mes.last_mut() { - if let Some(last) = args.last() { - if last.name.is_none() { - script_err_pod!(self.trap, "mixing named and ordered args"); - } - } - args.push(ShaderPodArg { - name: Some(id), - ty: val_ty, - s: val_s, - }); - } else { - script_err_unexpected!(self.trap, "assign_me requires Pod on me stack"); - self.stack.free_string(val_s); - } - self.stack.free_string(id_s); - } else { - script_err_unexpected!(self.trap, "assign_me requires Id type"); - self.stack.free_string(val_s); - self.stack.free_string(id_s); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - } - - pub(crate) fn type_from_value(vm: &ScriptVm, value: ScriptValue) -> ShaderType { - if let Some(pod_ty) = vm.bx.code.builtins.pod.value_to_exact_type(value) { - return ShaderType::Pod(pod_ty); - } - // Check if it's a color - colors map to vec4f - if value.is_color() { - return ShaderType::Pod(vm.bx.code.builtins.pod.pod_vec4f); - } - // Check if it's a repr(u32) enum variant - these have _repr_u32_enum_value set - if let Some(obj) = value.as_object() { - let enum_val = vm - .bx - .heap - .value(obj, id!(_repr_u32_enum_value).into(), NoTrap); - if enum_val.is_f64() { - // repr(u32) enum variants map to u32 in shaders (matches enum constant emission) - return ShaderType::Pod(vm.bx.code.builtins.pod.pod_u32); - } - } - if let Some(pod_ty) = vm.bx.heap.pod_type(value) { - return ShaderType::PodType(pod_ty); - } - if let Some(pod) = value.as_pod() { - let pod = &vm.bx.heap.pods[pod]; - return ShaderType::Pod(pod.ty); - } - if let Some(pod_ty) = value.as_pod_type() { - return ShaderType::Pod(pod_ty); - } - ShaderType::None - } - - /// Find the highest (most ancestral) shader IO definition for a field in the prototype chain. - /// This ensures that if a parent defines `x: shader.uniform(vec4f)` and a child overrides - /// with `x: #ffff`, we still use the uniform type from the parent. - /// Returns (value_object, shader_io_type) if found, or None if no shader IO marker exists. - pub(crate) fn find_highest_shader_io( - vm: &ScriptVm, - io_self: ScriptObject, - field_id: LiveId, - _trap: ScriptTrap, - ) -> Option<(ScriptObject, ShaderIoType)> { - let mut result: Option<(ScriptObject, ShaderIoType)> = None; - let mut current: Option = Some(io_self); - - // Walk up the prototype chain - while let Some(obj) = current { - // Check if this object has the field directly (not inherited) - let obj_data = vm.bx.heap.object_data(obj); - if let Some(map_value) = obj_data.map.get(&field_id.into()) { - if let Some(value_obj) = map_value.value.as_object() { - if let Some(io_type) = vm.bx.heap.as_shader_io(value_obj) { - // Found a shader IO marker - keep track of it (will be overwritten by higher ones) - result = Some((value_obj, io_type)); - } - } - } - - // Move to parent prototype - current = vm.bx.heap.proto(obj).as_object(); - } - - result - } - - /// Get the value for a field, preferring inherited shader IO markers over local values. - /// If a shader IO marker exists higher in the prototype chain, returns that. - /// Otherwise returns the normal (lowest/most derived) value. - pub(crate) fn get_io_self_field_value( - vm: &ScriptVm, - io_self: ScriptObject, - field_id: LiveId, - trap: ScriptTrap, - ) -> (ScriptValue, Option) { - // First, try to find the highest shader IO definition - if let Some((io_obj, io_type)) = Self::find_highest_shader_io(vm, io_self, field_id, trap) { - return (io_obj.into(), Some(io_type)); - } - - // No shader IO marker found - get the normal value (for RustInstance fields) - let value = vm.bx.heap.value(io_self, field_id.into(), trap); - (value, None) - } - - fn shader_io_kind_matches(a: &ShaderIoKind, b: &ShaderIoKind) -> bool { - use ShaderIoKind::*; - match (a, b) { - (StorageBuffer(_), StorageBuffer(_)) => true, - (UniformBuffer, UniformBuffer) => true, - (Sampler(_), Sampler(_)) => true, - (Texture(at), Texture(bt)) => at == bt, - (Varying, Varying) => true, - (VertexBuffer, VertexBuffer) => true, - (VertexPosition, VertexPosition) => true, - (FragmentOutput(ai), FragmentOutput(bi)) => ai == bi, - (RustInstance, RustInstance) => true, - (Uniform, Uniform) => true, - (DynInstance, DynInstance) => true, - (ScopeUniform, ScopeUniform) => true, - // Rust/Dyn instance intentionally share backing storage and prefixes. - (RustInstance, DynInstance) | (DynInstance, RustInstance) => true, - _ => false, - } - } - - fn shader_io_type_from_kind(kind: &ShaderIoKind) -> Option { - use ShaderIoKind::*; - match kind { - UniformBuffer => Some(SHADER_IO_UNIFORM_BUFFER), - Sampler(_) => Some(SHADER_IO_SAMPLER), - Texture(TextureType::Texture1d) => Some(SHADER_IO_TEXTURE_1D), - Texture(TextureType::Texture1dArray) => Some(SHADER_IO_TEXTURE_1D_ARRAY), - Texture(TextureType::Texture2d) => Some(SHADER_IO_TEXTURE_2D), - Texture(TextureType::Texture2dArray) => Some(SHADER_IO_TEXTURE_2D_ARRAY), - Texture(TextureType::Texture3d) => Some(SHADER_IO_TEXTURE_3D), - Texture(TextureType::Texture3dArray) => Some(SHADER_IO_TEXTURE_3D_ARRAY), - Texture(TextureType::TextureCube) => Some(SHADER_IO_TEXTURE_CUBE), - Texture(TextureType::TextureCubeArray) => Some(SHADER_IO_TEXTURE_CUBE_ARRAY), - Texture(TextureType::TextureDepth) => Some(SHADER_IO_TEXTURE_DEPTH), - Texture(TextureType::TextureDepthArray) => Some(SHADER_IO_TEXTURE_DEPTH_ARRAY), - Texture(TextureType::TextureVideo) => Some(SHADER_IO_TEXTURE_VIDEO), - Varying => Some(SHADER_IO_VARYING), - VertexBuffer => Some(SHADER_IO_VERTEX_BUFFER), - VertexPosition => Some(SHADER_IO_VERTEX_POSITION), - FragmentOutput(index) => { - Some(ShaderIoType(SHADER_IO_FRAGMENT_OUTPUT_0.0 + *index as u32)) - } - RustInstance => Some(SHADER_IO_RUST_INSTANCE), - Uniform => Some(SHADER_IO_DYN_UNIFORM), - DynInstance => Some(SHADER_IO_DYN_INSTANCE), - ScopeUniform => Some(SHADER_IO_SCOPE_UNIFORM), - StorageBuffer(_) => None, - } - } - - fn infer_shader_io_type_from_pod_ty(pod_ty: &crate::pod::ScriptPodTy) -> Option { - use crate::pod::ScriptPodTy::*; - match pod_ty { - // Implicit scalar rule: float/int become dynamic instance fields. - F32 | F16 | U32 | I32 => Some(SHADER_IO_DYN_INSTANCE), - // Implicit vector/matrix rule: vec* and mat* become dynamic uniforms. - Vec(_) | Mat(_) => Some(SHADER_IO_DYN_UNIFORM), - _ => None, - } - } - - fn infer_unmarked_shader_io_type( - vm: &ScriptVm, - value: ScriptValue, - ) -> Option<(ShaderIoType, ScriptPodType)> { - let pod_ty = match Self::type_from_value(vm, value) { - ShaderType::Pod(pod_ty) | ShaderType::PodType(pod_ty) => pod_ty, - _ => return None, - }; - let pod_data = &vm.bx.heap.pod_types[pod_ty.index as usize]; - Self::infer_shader_io_type_from_pod_ty(&pod_data.ty).map(|io_type| (io_type, pod_ty)) - } - - pub(crate) fn handle_field(&mut self, vm: &mut ScriptVm, output: &mut ShaderOutput) { - let (field_ty, field_s) = self.stack.pop(self.trap.pass()); - let (instance_ty, instance_s) = self.pop_resolved(vm, output); - - if let ShaderType::Id(field_id) = field_ty { - if let ShaderType::Pod(pod_ty) = instance_ty { - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - if matches!(output.backend, ShaderBackend::Glsl) - && instance_s == "unibuf_draw_pass" - { - let mut s = self.stack.new_string(); - match field_id { - id!(camera_projection) => { - write!(s, "unibuf_draw_pass.camera_projection[int(VIEW_ID)]").ok(); - } - id!(camera_view) => { - write!(s, "unibuf_draw_pass.camera_view[int(VIEW_ID)]").ok(); - } - id!(depth_projection) => { - write!(s, "unibuf_draw_pass.depth_projection[int(VIEW_ID)]").ok(); - } - id!(depth_view) => { - write!(s, "unibuf_draw_pass.depth_view[int(VIEW_ID)]").ok(); - } - id!(camera_inv) => { - write!(s, "unibuf_draw_pass.camera_inv[int(VIEW_ID)]").ok(); - } - _ => { - self.stack.free_string(s); - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = - output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}.{}", instance_s, field_name).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - if matches!(output.backend, ShaderBackend::Wgsl) - && instance_s == "unibuf_draw_pass" - { - let mut s = self.stack.new_string(); - match field_id { - id!(camera_projection) => { - write!(s, "mp_draw_pass_camera_projection()").ok(); - } - id!(camera_view) => { - write!(s, "mp_draw_pass_camera_view()").ok(); - } - id!(depth_projection) => { - write!(s, "mp_draw_pass_depth_projection()").ok(); - } - id!(depth_view) => { - write!(s, "mp_draw_pass_depth_view()").ok(); - } - id!(camera_inv) => { - write!(s, "mp_draw_pass_camera_inv()").ok(); - } - _ => { - self.stack.free_string(s); - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = - output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}.{}", instance_s, field_name).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}.{}", instance_s, field_name).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - } else { - script_err_not_found!( - self.trap, - "field {:?} not found on Pod{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } else if let ShaderType::PodPtr(pod_ty) = instance_ty { - // Pointer type (e.g., uniform buffer in Metal) - use -> for field access - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - let mut s = self.stack.new_string(); - let is_vec = vm.bx.heap.pod_types[pod_ty.index as usize] - .ty - .is_float_type() - && !matches!( - vm.bx.heap.pod_types[pod_ty.index as usize].ty, - crate::pod::ScriptPodTy::Struct { .. } - ); - let field_name = output.backend.map_field_name_typed(field_id, is_vec); - write!(s, "{}->{}", instance_s, field_name).ok(); - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - } else { - script_err_not_found!( - self.trap, - "field {:?} not found on PodPtr{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } else if let ShaderType::Texture(tex_type) = instance_ty { - // Field/method access on a texture - push texture and field name for method call handling - // The field name (like "size") will be used as the method name - self.stack - .push(self.trap.pass(), ShaderType::Texture(tex_type), instance_s); - self.stack - .push(self.trap.pass(), ShaderType::Id(field_id), field_s); - return; - } else if let ShaderType::ScopeObject(obj) = instance_ty { - // Field access on a scope object (e.g., test_obj.p2 or test_obj.objfn or test_obj.sub_obj) - // Look up the field value - let value = vm.bx.heap.value(obj, field_id.into(), self.trap.pass()); - - if !value.is_nil() && self.trap.err.borrow().is_empty() { - // Check if this is an object - if let Some(value_obj) = value.as_object() { - // Check if this is a shader_io type - not supported for scope objects - if vm.bx.heap.as_shader_io(value_obj).is_some() { - script_err_shader!( - self.trap, - "shader_io not supported on scope objects" - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - // Check if it's a function - if so, push it for calling - if vm.bx.heap.as_fn(value_obj).is_some() { - // Push the ScopeObject as the receiver and the function for calling - // Similar to how IoSelf handles method calls - self.stack.push( - self.trap.pass(), - ShaderType::ScopeObject(obj), - instance_s, - ); - self.stack - .push(self.trap.pass(), ShaderType::Id(field_id), field_s); - return; - } - - // Check if this is a repr(u32) enum variant (has a 'repr_u32_enum_value' field) - // If so, emit the value directly as a u32 constant - let enum_value = vm.bx.heap.value( - value_obj, - id!(_repr_u32_enum_value).into(), - self.trap.pass(), - ); - if !enum_value.is_nil() { - self.trap.err.take(); // Clear any error - if let Some(f) = enum_value.as_f64() { - let mut s = self.stack.new_string(); - match output.backend { - ShaderBackend::Rust => write!(s, "{}u32", f as u32).ok(), - _ => write!(s, "{}u", f as u32).ok(), - }; - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_u32), - s, - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - self.trap.err.take(); // Clear any error from value lookup - - // It's a regular sub-object (like test_obj.sub_obj) - return it as ScopeObject - // so that further field access can continue (e.g., test_obj.sub_obj.test_p1) - let empty_s = self.stack.new_string(); - self.stack.push( - self.trap.pass(), - ShaderType::ScopeObject(value_obj), - empty_s, - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - // Get the pod type from the value - it's a regular property (primitive or pod) - if let Some(pod_ty) = self.get_scope_value_pod_type(vm, value) { - // Check if we already have this scope uniform - let existing = output - .scope_uniforms - .iter() - .find(|su| su.source_obj == obj && su.key == field_id); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - // Generate unique name if there's a collision (use obj as source) - let shader_name = - self.generate_scope_uniform_name(output, field_id, obj); - output.scope_uniforms.push(ScopeUniformSource { - source_obj: obj, - key: field_id, - shader_name, - ty: pod_ty, - }); - // Also add to IO list - if !output.io.iter().any(|io| { - io.name == shader_name - && matches!(io.kind, ShaderIoKind::ScopeUniform) - }) { - vm.bx.heap.pod_type_name_if_not_set(pod_ty, shader_name); - output.io.push(ShaderIo { - kind: ShaderIoKind::ScopeUniform, - name: shader_name, - ty: pod_ty, - buffer_index: None, - }); - } - shader_name - }; - - let mut s = self.stack.new_string(); - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, SHADER_IO_SCOPE_UNIFORM); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(shader_name); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - - // Value not found on prototype - try to get the type from type-check structure - self.trap.err.take(); // Clear any error from value lookup - if let Some(field_type_id) = vm.bx.heap.field_type_from_type_check(obj, field_id) { - // Found field type in type-check structure - convert to pod type - if let Some(pod_ty) = vm - .bx - .heap - .type_id_to_pod_type(field_type_id, &vm.bx.code.builtins.pod) - { - // Check if we already have this scope uniform - let existing = output - .scope_uniforms - .iter() - .find(|su| su.source_obj == obj && su.key == field_id); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - let shader_name = - self.generate_scope_uniform_name(output, field_id, obj); - output.scope_uniforms.push(ScopeUniformSource { - source_obj: obj, - key: field_id, - shader_name, - ty: pod_ty, - }); - if !output.io.iter().any(|io| { - io.name == shader_name - && matches!(io.kind, ShaderIoKind::ScopeUniform) - }) { - vm.bx.heap.pod_type_name_if_not_set(pod_ty, shader_name); - output.io.push(ShaderIo { - kind: ShaderIoKind::ScopeUniform, - name: shader_name, - ty: pod_ty, - buffer_index: None, - }); - } - shader_name - }; - - let mut s = self.stack.new_string(); - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, SHADER_IO_SCOPE_UNIFORM); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(shader_name); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - - // Field not found in type-check structure either - script_err_not_found!( - self.trap, - "field {:?} not found on ScopeObject{}", - field_id, - suggest_property(&vm.bx.heap, obj, field_id.into()) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } else if let ShaderType::ScopeUniformBuffer { obj, pod_ty } = instance_ty { - // Field access on a scope-level uniform buffer (e.g., test_buf.p3) - // Look up the field on the pod type - if let Some(ret_ty) = - vm.bx - .heap - .pod_field_type(pod_ty, field_id, &vm.bx.code.builtins.pod) - { - // Check if we already have this scope uniform buffer registered - let existing = output - .scope_uniform_buffers - .iter() - .find(|sub| sub.obj == obj); - - let shader_name = if let Some(existing) = existing { - existing.shader_name - } else { - // Generate unique names for this scope uniform buffer: - // - shader_name: identifier used in shader code (us_{id}) - // - struct_type_name: the struct type name (IoScopeUniformBuf{id}) - let (shader_name, struct_type_name) = - self.generate_scope_uniform_buffer_names(output, obj); - - // Add to scope_uniform_buffers for runtime tracking - output.scope_uniform_buffers.push(ScopeUniformBufferSource { - obj, - pod_ty, - shader_name, - }); - - // Add to IO list as UniformBuffer - // Set the struct type name (not the shader identifier name) - vm.bx - .heap - .pod_type_name_if_not_set(pod_ty, struct_type_name); - output.io.push(ShaderIo { - kind: ShaderIoKind::UniformBuffer, - name: shader_name, - ty: pod_ty, - buffer_index: None, - }); - - shader_name - }; - - // Generate field access code - // Note: Don't use the backend prefix since our name already has `us_` prefix - let mut s = self.stack.new_string(); - let io_name = output.backend.map_io_name(shader_name); - let field_name = output.backend.map_field_name(field_id); - // For Metal, uniform buffers are pointers, use -> - if matches!(output.backend, ShaderBackend::Metal) { - write!(s, "{}->{}", io_name, field_name).ok(); - } else { - write!(s, "{}.{}", io_name, field_name).ok(); - } - self.stack - .push(self.trap.pass(), ShaderType::Pod(ret_ty), s); - } else { - script_err_not_found!( - self.trap, - "field {:?} not found on ScopeUniformBuffer{}", - field_id, - suggest_pod_field(&vm.bx.heap, pod_ty, field_id) - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - } - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } else if let ShaderType::IoSelf(obj) = instance_ty { - // Look up field value, preferring the highest shader IO marker in the prototype chain - let (value, maybe_io_type) = - Self::get_io_self_field_value(vm, obj, field_id, self.trap.pass()); - - if let Some(io_type) = maybe_io_type { - // Found a shader IO marker (uniform, varying, texture, etc.) - let value_obj = value.as_object().unwrap(); - let proto = vm.bx.heap.proto(value_obj); - let ty = Self::type_from_value(vm, proto); - let concrete_ty = match ty { - ShaderType::Pod(pt) => Some(pt), - ShaderType::PodType(pt) => Some(pt), - _ => None, - }; - - let (mut kind, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, io_type); - let mut resolved_prefix = prefix; - if let Some(existing) = output.io.iter().find(|io| io.name == field_id) { - if !Self::shader_io_kind_matches(&existing.kind, &kind) { - if let Some(existing_io_type) = - Self::shader_io_type_from_kind(&existing.kind) - { - // Keep expression generation in lockstep with the already-registered IO entry. - // This prevents backend code from referencing undeclared members. - let (existing_kind, existing_prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, existing_io_type); - kind = existing_kind; - resolved_prefix = existing_prefix; - } - } else { - resolved_prefix = match (&existing.kind, &kind) { - (ShaderIoKind::RustInstance, ShaderIoKind::DynInstance) => { - output - .backend - .get_shader_io_kind_and_prefix( - output.mode, - SHADER_IO_RUST_INSTANCE, - ) - .1 - } - (ShaderIoKind::DynInstance, ShaderIoKind::RustInstance) => { - output - .backend - .get_shader_io_kind_and_prefix( - output.mode, - SHADER_IO_DYN_INSTANCE, - ) - .1 - } - _ => resolved_prefix, - }; - } - } - - // Handle texture types specially - they don't have a concrete pod type - if let ShaderIoKind::Texture(tex_type) = &kind { - if !output.io.iter().any(|io| io.name == field_id) { - output.io.push(ShaderIo { - kind: kind.clone(), - name: field_id, - ty: ScriptPodType::VOID, // Textures don't have a pod type - buffer_index: None, - }); - } - let mut s = self.stack.new_string(); - match &resolved_prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(field_id); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Texture(*tex_type), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - if let Some(pod_ty) = concrete_ty { - // lets see if our podtype has a name. ifnot use pod_ty - vm.bx.heap.pod_type_name_if_not_set(pod_ty, field_id); - if !output.io.iter().any(|io| io.name == field_id) { - output.io.push(ShaderIo { - kind: kind.clone(), - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - let mut s = self.stack.new_string(); - match &resolved_prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(field_id); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - // UniformBuffer in Metal is a pointer, use PodPtr for correct -> access - let shader_ty = if matches!(kind, ShaderIoKind::UniformBuffer) - && matches!(output.backend, ShaderBackend::Metal) - { - ShaderType::PodPtr(pod_ty) - } else { - ShaderType::Pod(pod_ty) - }; - self.stack.push(self.trap.pass(), shader_ty, s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - - // No explicit marker, try implicit inference based on value type: - // - float/int scalar => instance - // - vec*/mat* => uniform - if let Some((io_type, pod_ty)) = Self::infer_unmarked_shader_io_type(vm, value) { - let (mut kind, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, io_type); - let mut resolved_prefix = prefix; - - if let Some(existing) = output.io.iter().find(|io| io.name == field_id) { - if !Self::shader_io_kind_matches(&existing.kind, &kind) { - if let Some(existing_io_type) = - Self::shader_io_type_from_kind(&existing.kind) - { - let (existing_kind, existing_prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, existing_io_type); - kind = existing_kind; - resolved_prefix = existing_prefix; - } - } else { - resolved_prefix = match (&existing.kind, &kind) { - (ShaderIoKind::RustInstance, ShaderIoKind::DynInstance) => { - output - .backend - .get_shader_io_kind_and_prefix( - output.mode, - SHADER_IO_RUST_INSTANCE, - ) - .1 - } - (ShaderIoKind::DynInstance, ShaderIoKind::RustInstance) => { - output - .backend - .get_shader_io_kind_and_prefix( - output.mode, - SHADER_IO_DYN_INSTANCE, - ) - .1 - } - _ => resolved_prefix, - }; - } - } - - vm.bx.heap.pod_type_name_if_not_set(pod_ty, field_id); - if !output.io.iter().any(|io| io.name == field_id) { - output.io.push(ShaderIo { - kind: kind.clone(), - name: field_id, - ty: pod_ty, - buffer_index: None, - }); - } - - let mut s = self.stack.new_string(); - match &resolved_prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(field_id); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - // No shader IO marker found - clear any trap error from value lookup - // before checking RustInstance fields (which don't depend on prototype values) - self.trap.err.take(); - - // Check if this is a RustInstance field - // RustInstance fields are pre-collected into output.io, so just look it up there - if let Some(io) = output - .io - .iter() - .find(|io| io.name == field_id && matches!(io.kind, ShaderIoKind::RustInstance)) - { - let pod_ty = io.ty; - let (_, prefix) = output - .backend - .get_shader_io_kind_and_prefix(output.mode, SHADER_IO_RUST_INSTANCE); - let mut s = self.stack.new_string(); - match prefix { - ShaderIoPrefix::Prefix(prefix) => { - let io_name = output.backend.map_io_name(field_id); - write!(s, "{}{}", prefix, io_name).ok() - } - ShaderIoPrefix::Full(full) => write!(s, "{}", full).ok(), - ShaderIoPrefix::FullOwned(full) => write!(s, "{}", full).ok(), - }; - self.stack - .push(self.trap.pass(), ShaderType::Pod(pod_ty), s); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - - // Not a RustInstance field and no shader IO marker found. - // Script-defined shader fields either need an explicit marker or an inferable type. - script_err_shader!( - self.trap, - "shader field `{}` needs explicit IO marker (uniform/instance/varying) or implicit scalar/vec/mat type", - field_id - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - return; - } - } - script_err_not_found!( - self.trap, - "field {:?} not found on shader type {:?}", - field_ty, - instance_ty - ); - self.stack.push( - self.trap.pass(), - ShaderType::Pod(vm.bx.code.builtins.pod.pod_void), - String::new(), - ); - self.stack.free_string(field_s); - self.stack.free_string(instance_s); - } - - pub(crate) fn handle_let_dyn( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - if opargs.is_nil() { - script_err_not_allowed!(self.trap, "shader let requires initializer"); - self.stack.pop(self.trap.pass()); - } else { - let (ty_value, value) = self.pop_resolved(vm, output); - let (ty_id, _id) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(id) = ty_id { - // lets define our let type - if let Some(ty) = ty_value.make_concrete(&vm.bx.code.builtins.pod) { - let shadow = self.shader_scope.define_let(id, ty); - let local_name = output.backend.map_local_name(id, shadow); - match output.backend { - ShaderBackend::Wgsl => { - // Composite values are frequently mutated through method calls or - // component writes. Keep scalar lets immutable, but lower composite - // lets to `var` so WGSL can take references and assign fields. - let is_composite_let = matches!( - vm.bx.heap.pod_types[ty.index as usize].ty, - crate::pod::ScriptPodTy::Vec(_) - | crate::pod::ScriptPodTy::Mat(_) - | crate::pod::ScriptPodTy::Struct { .. } - | crate::pod::ScriptPodTy::Enum { .. } - | crate::pod::ScriptPodTy::FixedArray { .. } - | crate::pod::ScriptPodTy::VariableArray { .. } - ); - if is_composite_let { - write!(self.out, "var {} = {};\n", local_name, value).ok(); - } else { - write!(self.out, "let {} = {};\n", local_name, value).ok(); - } - } - ShaderBackend::Metal | ShaderBackend::Hlsl | ShaderBackend::Glsl => { - let type_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - write!(self.out, "{} {} = {};\n", type_name, local_name, value).ok(); - } - ShaderBackend::Rust => { - let type_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - // All shader locals are potentially mutable in Rust backend - write!( - self.out, - "let mut {}: {} = {};\n", - local_name, type_name, value - ) - .ok(); - } - } - } else { - script_err_shader!(self.trap, "cannot determine shader type for let"); - } - } else { - script_err_unexpected!(self.trap, "let requires Id"); - } - } - } - - pub(crate) fn handle_var_dyn( - &mut self, - vm: &mut ScriptVm, - output: &mut ShaderOutput, - opargs: OpcodeArgs, - ) { - if opargs.is_nil() { - script_err_not_allowed!(self.trap, "shader var requires initializer"); - self.stack.pop(self.trap.pass()); - } else { - let (ty_value, value) = self.pop_resolved(vm, output); - let (ty_id, _id) = self.stack.pop(self.trap.pass()); - if let ShaderType::Id(id) = ty_id { - // lets define our let type - if let Some(ty) = ty_value.make_concrete(&vm.bx.code.builtins.pod) { - let shadow = self.shader_scope.define_var(id, ty); - let local_name = output.backend.map_local_name(id, shadow); - match output.backend { - ShaderBackend::Wgsl => { - write!(self.out, "var {} = {};\n", local_name, value).ok(); - } - ShaderBackend::Metal | ShaderBackend::Hlsl | ShaderBackend::Glsl => { - let type_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - write!(self.out, "{} {} = {};\n", type_name, local_name, value).ok(); - } - ShaderBackend::Rust => { - let type_name = if let Some(name) = vm.bx.heap.pod_type_name(ty) { - output.backend.map_pod_name(name) - } else { - id!(unknown) - }; - write!( - self.out, - "let mut {}: {} = {};\n", - local_name, type_name, value - ) - .ok(); - } - } - } else { - script_err_shader!(self.trap, "cannot determine shader type for var"); - } - } else { - script_err_unexpected!(self.trap, "var requires Id"); - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::pod::{ScriptPodMat, ScriptPodTy, ScriptPodVec}; - - #[test] - fn infer_unmarked_shader_io_rules_match_requested_defaults() { - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::F32), - Some(SHADER_IO_DYN_INSTANCE) - ); - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::I32), - Some(SHADER_IO_DYN_INSTANCE) - ); - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::U32), - Some(SHADER_IO_DYN_INSTANCE) - ); - - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::Vec( - ScriptPodVec::Vec2f - )), - Some(SHADER_IO_DYN_UNIFORM) - ); - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::Vec( - ScriptPodVec::Vec4i - )), - Some(SHADER_IO_DYN_UNIFORM) - ); - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::Mat( - ScriptPodMat::Mat4x4f - )), - Some(SHADER_IO_DYN_UNIFORM) - ); - - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::Bool), - None - ); - assert_eq!( - ShaderFnCompiler::infer_shader_io_type_from_pod_ty(&ScriptPodTy::Struct { - align_of: 4, - size_of: 4, - fields: Vec::new(), - }), - None - ); - } -} diff --git a/vendor/makepad/platform/script/src/shader_wgsl.rs b/vendor/makepad/platform/script/src/shader_wgsl.rs deleted file mode 100644 index 298c103..0000000 --- a/vendor/makepad/platform/script/src/shader_wgsl.rs +++ /dev/null @@ -1,1118 +0,0 @@ -use { - crate::{ - pod::{ScriptPodTy, ScriptPodTypeInline, ScriptPodVec}, - shader::{ - ShaderFnCompiler, ShaderIoKind, ShaderMode, ShaderOutput, ShaderType, TextureType, - }, - shader_backend::ShaderBackend, - shader_output::ShaderIo, - trap::NoTrap, - value::{ScriptObject, ScriptPodType}, - vm::ScriptVm, - }, - makepad_live_id::{id, LiveId}, - std::fmt::Write, -}; - -#[derive(Clone)] -pub struct WgslDrawShaderSource { - pub wgsl: String, - pub dyn_uniform_binding: u32, - pub texture_binding_base: u32, - pub sampler_binding_base: u32, - pub xr_depth_binding: u32, - pub geometry_slots: usize, - pub instance_slots: usize, -} - -#[derive(Clone, Copy, PartialEq, Eq)] -enum WgslPackedFormat { - Float, - UInt, - SInt, -} - -#[derive(Clone, Copy, PartialEq, Eq)] -enum WgslPackedSource { - NumericFloat, - BitPackedFloat, -} - -#[derive(Clone)] -struct WgslPackedField { - name: String, - ty: ScriptPodType, - slots: usize, - offset: usize, -} - -fn wgsl_texture_type(tex_type: TextureType) -> &'static str { - match tex_type { - TextureType::Texture1d => "texture_2d", - TextureType::Texture1dArray => "texture_2d_array", - TextureType::Texture2d => "texture_2d", - TextureType::Texture2dArray => "texture_2d_array", - TextureType::Texture3d => "texture_3d", - TextureType::Texture3dArray => "texture_3d", - TextureType::TextureCube => "texture_cube", - TextureType::TextureCubeArray => "texture_cube_array", - TextureType::TextureDepth => "texture_depth_2d", - TextureType::TextureDepthArray => "texture_depth_2d_array", - TextureType::TextureVideo => "texture_2d", - } -} - -fn wgsl_type_name(output: &ShaderOutput, vm: &ScriptVm, ty: ScriptPodType) -> String { - let mut out = String::new(); - output - .backend - .pod_type_name_from_ty(&vm.bx.heap, ty, &mut out); - out -} - -fn wgsl_type_name_inline(output: &ShaderOutput, vm: &ScriptVm, ty: &ScriptPodTypeInline) -> String { - if matches!(ty.data.ty, ScriptPodTy::Struct { .. }) { - if let Some(name) = ty.data.name { - return format!("{}", output.backend.map_pod_name(name)); - } - return wgsl_type_name(output, vm, ty.self_ref); - } - let mut out = String::new(); - output.backend.pod_type_name(ty, &mut out); - out -} - -fn wgsl_attr_format_from_pod_ty(ty: &ScriptPodTy) -> WgslPackedFormat { - match ty { - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 | ScriptPodTy::Bool => WgslPackedFormat::UInt, - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => WgslPackedFormat::SInt, - ScriptPodTy::Vec(v) => match v { - ScriptPodVec::Vec2u - | ScriptPodVec::Vec3u - | ScriptPodVec::Vec4u - | ScriptPodVec::Vec2b - | ScriptPodVec::Vec3b - | ScriptPodVec::Vec4b => WgslPackedFormat::UInt, - ScriptPodVec::Vec2i | ScriptPodVec::Vec3i | ScriptPodVec::Vec4i => { - WgslPackedFormat::SInt - } - _ => WgslPackedFormat::Float, - }, - _ => WgslPackedFormat::Float, - } -} - -fn wgsl_num_packed_vec4s(slots: usize) -> usize { - if slots == 0 { - 0 - } else { - (slots + 3) / 4 - } -} - -fn wgsl_swizzle_component(index: usize) -> &'static str { - match index { - 0 => "x", - 1 => "y", - 2 => "z", - _ => "w", - } -} - -fn wgsl_packed_component(prefix: &str, slot: usize) -> String { - let vec_idx = slot / 4; - let comp = wgsl_swizzle_component(slot & 3); - format!("{prefix}{vec_idx}.{comp}") -} - -fn wgsl_push_field( - output: &ShaderOutput, - vm: &ScriptVm, - io: &ShaderIo, - prefix: &str, - attribute_packing: bool, - offset: &mut usize, - out: &mut Vec, -) { - let io_name = output.backend.map_io_name(io.name); - let pod_ty = vm.bx.heap.pod_type_ref(io.ty); - let slots = pod_ty.ty.slots(); - let attr_format = if attribute_packing { - wgsl_attr_format_from_pod_ty(&pod_ty.ty) - } else { - WgslPackedFormat::Float - }; - - if attribute_packing - && attr_format != WgslPackedFormat::Float - && slots > 1 - && (*offset & 3) != 0 - { - *offset += 4 - (*offset & 3); - } - - out.push(WgslPackedField { - name: format!("{prefix}{io_name}"), - ty: io.ty, - slots, - offset: *offset, - }); - *offset += slots; - - if attribute_packing - && attr_format != WgslPackedFormat::Float - && slots > 1 - && (*offset & 3) != 0 - { - *offset += 4 - (*offset & 3); - } -} - -fn wgsl_collect_geometry_fields(output: &ShaderOutput, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0usize; - for io in &output.io { - if let ShaderIoKind::VertexBuffer = io.kind { - wgsl_push_field(output, vm, io, "vb_", true, &mut offset, &mut out); - } - } - out -} - -fn wgsl_collect_instance_fields(output: &ShaderOutput, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0usize; - for io in &output.io { - if let ShaderIoKind::DynInstance = io.kind { - wgsl_push_field(output, vm, io, "dyninst_", true, &mut offset, &mut out); - } - } - for io in &output.io { - if let ShaderIoKind::RustInstance = io.kind { - wgsl_push_field(output, vm, io, "rustinst_", true, &mut offset, &mut out); - } - } - out -} - -fn wgsl_collect_varying_fields(output: &ShaderOutput, vm: &ScriptVm) -> Vec { - let mut out = Vec::new(); - let mut offset = 0usize; - for io in &output.io { - if let ShaderIoKind::DynInstance = io.kind { - wgsl_push_field(output, vm, io, "dyninst_", false, &mut offset, &mut out); - } - } - for io in &output.io { - if let ShaderIoKind::RustInstance = io.kind { - wgsl_push_field(output, vm, io, "rustinst_", false, &mut offset, &mut out); - } - } - for io in &output.io { - if let ShaderIoKind::Varying = io.kind { - wgsl_push_field(output, vm, io, "var_", false, &mut offset, &mut out); - } - } - out -} - -fn wgsl_to_float_scalar_expr(ty: &ScriptPodTy, expr: &str) -> String { - match ty { - ScriptPodTy::F32 | ScriptPodTy::F16 => expr.to_string(), - ScriptPodTy::U32 | ScriptPodTy::I32 | ScriptPodTy::AtomicU32 | ScriptPodTy::AtomicI32 => { - format!("f32({expr})") - } - ScriptPodTy::Bool => format!("select(0.0, 1.0, {expr})"), - _ => format!("f32({expr})"), - } -} - -fn wgsl_convert_scalar_expr(source: WgslPackedSource, target: &ScriptPodTy, expr: &str) -> String { - match source { - WgslPackedSource::NumericFloat => match target { - ScriptPodTy::F32 => expr.to_string(), - ScriptPodTy::F16 => format!("f16({expr})"), - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => format!("u32({expr})"), - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => format!("i32({expr})"), - ScriptPodTy::Bool => format!("({expr} != 0.0)"), - _ => format!("f32({expr})"), - }, - WgslPackedSource::BitPackedFloat => match target { - ScriptPodTy::F32 => expr.to_string(), - ScriptPodTy::F16 => format!("f16({expr})"), - ScriptPodTy::U32 | ScriptPodTy::AtomicU32 => format!("bitcast({expr})"), - ScriptPodTy::I32 | ScriptPodTy::AtomicI32 => format!("bitcast({expr})"), - ScriptPodTy::Bool => format!("(bitcast({expr}) != 0u)"), - _ => expr.to_string(), - }, - } -} - -fn wgsl_take_scalar_or_zero(scalars: &[String], scalar_index: &mut usize) -> String { - let value = scalars - .get(*scalar_index) - .cloned() - .unwrap_or_else(|| "0.0".to_string()); - *scalar_index += 1; - value -} - -fn wgsl_flatten_inline( - output: &ShaderOutput, - ty: &ScriptPodTypeInline, - expr: &str, - out: &mut Vec, -) { - match &ty.data.ty { - ScriptPodTy::Struct { fields, .. } => { - for field in fields { - let field_name = output.backend.map_field_name(field.name); - let field_expr = format!("({expr}).{field_name}"); - wgsl_flatten_inline(output, &field.ty, &field_expr, out); - } - } - ScriptPodTy::Vec(vec_ty) => { - let elem_ty = vec_ty.elem_ty(); - for comp in 0..vec_ty.dims() { - let swizzle = wgsl_swizzle_component(comp); - let comp_expr = format!("({expr}).{swizzle}"); - out.push(wgsl_to_float_scalar_expr(&elem_ty, &comp_expr)); - } - } - ScriptPodTy::Mat(mat_ty) => { - let (cols, rows) = mat_ty.dims(); - for col in 0..cols { - for row in 0..rows { - out.push(format!("({expr})[{col}][{row}]")); - } - } - } - scalar_ty => { - out.push(wgsl_to_float_scalar_expr(scalar_ty, expr)); - } - } -} - -fn wgsl_flatten_exprs( - output: &ShaderOutput, - vm: &ScriptVm, - ty: ScriptPodType, - expr: &str, - out: &mut Vec, -) { - let pod_ty = vm.bx.heap.pod_type_ref(ty); - let inline = ScriptPodTypeInline { - self_ref: ty, - data: pod_ty.clone(), - }; - wgsl_flatten_inline(output, &inline, expr, out); -} - -fn wgsl_reconstruct_inline( - output: &ShaderOutput, - vm: &ScriptVm, - ty: &ScriptPodTypeInline, - source: WgslPackedSource, - scalars: &[String], - scalar_index: &mut usize, -) -> String { - match &ty.data.ty { - ScriptPodTy::Struct { fields, .. } => { - let mut field_exprs = Vec::new(); - for field in fields { - field_exprs.push(wgsl_reconstruct_inline( - output, - vm, - &field.ty, - source, - scalars, - scalar_index, - )); - } - format!( - "{}({})", - wgsl_type_name_inline(output, vm, ty), - field_exprs.join(", ") - ) - } - ScriptPodTy::Vec(vec_ty) => { - let dims = vec_ty.dims(); - let mut comps = Vec::with_capacity(dims); - let elem_ty = vec_ty.elem_ty(); - for _ in 0..dims { - let scalar = wgsl_take_scalar_or_zero(scalars, scalar_index); - comps.push(wgsl_convert_scalar_expr(source, &elem_ty, &scalar)); - } - format!( - "{}({})", - wgsl_type_name_inline(output, vm, ty), - comps.join(", ") - ) - } - ScriptPodTy::Mat(mat_ty) => { - let mut comps = Vec::new(); - for _ in 0..mat_ty.dim() { - let scalar = wgsl_take_scalar_or_zero(scalars, scalar_index); - comps.push(wgsl_convert_scalar_expr(source, &ScriptPodTy::F32, &scalar)); - } - format!( - "{}({})", - wgsl_type_name_inline(output, vm, ty), - comps.join(", ") - ) - } - scalar_ty => { - let scalar = wgsl_take_scalar_or_zero(scalars, scalar_index); - wgsl_convert_scalar_expr(source, scalar_ty, &scalar) - } - } -} - -fn wgsl_unpack_expr_for_field( - output: &ShaderOutput, - vm: &ScriptVm, - field: &WgslPackedField, - prefix: &str, - source: WgslPackedSource, -) -> String { - let scalars = (0..field.slots) - .map(|slot| wgsl_packed_component(prefix, field.offset + slot)) - .collect::>(); - let pod_ty = vm.bx.heap.pod_type_ref(field.ty); - let inline = ScriptPodTypeInline { - self_ref: field.ty, - data: pod_ty.clone(), - }; - let mut scalar_index = 0usize; - wgsl_reconstruct_inline(output, vm, &inline, source, &scalars, &mut scalar_index) -} - -fn build_draw_shader_wgsl( - vm: &ScriptVm, - output: &mut ShaderOutput, - xr_multiview: bool, -) -> (String, u32, u32, u32, u32) { - let mut out = String::new(); - - let geometry_fields = wgsl_collect_geometry_fields(output, vm); - let instance_fields = wgsl_collect_instance_fields(output, vm); - let varying_fields = wgsl_collect_varying_fields(output, vm); - let varying_slots = varying_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - - let has_dyn_uniforms = output - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::Uniform)); - let has_scope_uniforms = output - .io - .iter() - .any(|io| matches!(io.kind, ShaderIoKind::ScopeUniform)); - - let dyn_uniform_binding = 2u32; - let uniform_bindings = output.get_uniform_buffer_bindings(&vm.bx.heap); - let scope_uniform_binding = uniform_bindings - .scope_uniform_buffer_index - .map(|v| v as u32); - - let mut max_reserved_binding = dyn_uniform_binding; - for io in &output.io { - if let ShaderIoKind::UniformBuffer = io.kind { - if let Some(idx) = io.buffer_index { - max_reserved_binding = max_reserved_binding.max(idx as u32); - } - } - } - if let Some(scope_idx) = scope_uniform_binding { - max_reserved_binding = max_reserved_binding.max(scope_idx); - } - let mut next_binding = max_reserved_binding + 1; - let mut texture_binding_base: Option = None; - let mut sampler_binding_base: Option = None; - - output.create_struct_defs(vm, &mut out); - - if has_dyn_uniforms { - writeln!(out, "struct MpDynUniforms {{").ok(); - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::Uniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " uni_{}: {},", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - writeln!(out, "}}").ok(); - writeln!( - out, - "@group(0) @binding({}) var _mp_dyn_uniforms: MpDynUniforms;", - dyn_uniform_binding - ) - .ok(); - } - - if has_scope_uniforms { - let scope_binding = scope_uniform_binding.unwrap_or(max_reserved_binding + 1); - writeln!(out, "struct MpScopeUniforms {{").ok(); - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::ScopeUniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " su_{}: {},", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - writeln!(out, "}}").ok(); - writeln!( - out, - "@group(0) @binding({}) var _mp_scope_uniforms: MpScopeUniforms;", - scope_binding - ) - .ok(); - } - - writeln!(out, "var VIEW_ID: i32;").ok(); - writeln!(out, "var vtx_pos: vec4f;").ok(); - - for io in &output.io { - let io_name = output.backend.map_io_name(io.name); - match io.kind { - ShaderIoKind::VertexBuffer => { - writeln!( - out, - "var vb_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::DynInstance => { - writeln!( - out, - "var dyninst_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::RustInstance => { - writeln!( - out, - "var rustinst_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::Varying => { - writeln!( - out, - "var var_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::Uniform => { - writeln!( - out, - "var uni_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::UniformBuffer => { - let binding = io.buffer_index.unwrap_or(3) as u32; - writeln!( - out, - "@group(0) @binding({}) var unibuf_{}: {};", - binding, - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::ScopeUniform => { - writeln!( - out, - "var su_{}: {};", - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::FragmentOutput(index) => { - writeln!( - out, - "var frag_fb{}: {};", - index, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - } - ShaderIoKind::StorageBuffer(_) => { - writeln!( - out, - "@group(0) @binding({}) var sb_{}: {};", - next_binding, - io_name, - wgsl_type_name(output, vm, io.ty) - ) - .ok(); - next_binding += 1; - } - ShaderIoKind::Texture(tex_type) => { - if texture_binding_base.is_none() { - texture_binding_base = Some(next_binding); - } - writeln!( - out, - "@group(0) @binding({}) var tex_{}: {};", - next_binding, - io_name, - wgsl_texture_type(tex_type) - ) - .ok(); - next_binding += 1; - } - ShaderIoKind::Sampler(_) => { - if sampler_binding_base.is_none() { - sampler_binding_base = Some(next_binding); - } - writeln!( - out, - "@group(0) @binding({}) var sampler_{}: sampler;", - next_binding, io_name - ) - .ok(); - next_binding += 1; - } - ShaderIoKind::VertexPosition => {} - } - } - - for sampler_index in 0..output.samplers.len() { - let sampler_name = format!("_s{}", sampler_index); - if sampler_binding_base.is_none() { - sampler_binding_base = Some(next_binding); - } - writeln!( - out, - "@group(0) @binding({}) var {}: sampler;", - next_binding, sampler_name - ) - .ok(); - next_binding += 1; - } - - let xr_depth_binding = next_binding; - writeln!( - out, - "@group(0) @binding({}) var tex_xr_depth: {};", - xr_depth_binding, - if xr_multiview { - "texture_depth_2d_array" - } else { - "texture_depth_2d" - } - ) - .ok(); - - writeln!(out, "struct VertexMainIn {{").ok(); - if xr_multiview { - writeln!(out, " @builtin(view_index) view_index: i32,").ok(); - } - let mut location = 0u32; - let geometry_slots = geometry_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - let instance_slots = instance_fields - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - for idx in 0..wgsl_num_packed_vec4s(geometry_slots) { - writeln!( - out, - " @location({}) packed_geometry_{}: vec4f,", - location, idx - ) - .ok(); - location += 1; - } - for idx in 0..wgsl_num_packed_vec4s(instance_slots) { - writeln!( - out, - " @location({}) packed_instance_{}: vec4f,", - location, idx - ) - .ok(); - location += 1; - } - writeln!(out, "}}").ok(); - - writeln!(out, "struct VertexMainOut {{").ok(); - writeln!(out, " @builtin(position) position: vec4f,").ok(); - for idx in 0..wgsl_num_packed_vec4s(varying_slots) { - writeln!(out, " @location({}) packed_varying_{}: vec4f,", idx, idx).ok(); - } - writeln!(out, "}}").ok(); - writeln!(out, "struct FragmentMainIn {{").ok(); - if xr_multiview { - writeln!(out, " @builtin(view_index) view_index: i32,").ok(); - } - writeln!(out, " @builtin(position) position: vec4f,").ok(); - for idx in 0..wgsl_num_packed_vec4s(varying_slots) { - writeln!(out, " @location({}) packed_varying_{}: vec4f,", idx, idx).ok(); - } - writeln!(out, "}}").ok(); - - let mut fragment_outputs = output - .io - .iter() - .filter_map(|io| { - if let ShaderIoKind::FragmentOutput(index) = io.kind { - Some((index, wgsl_type_name(output, vm, io.ty))) - } else { - None - } - }) - .collect::>(); - fragment_outputs.sort_by_key(|(index, _)| *index); - if !fragment_outputs.is_empty() { - writeln!(out, "struct FragmentMainOut {{").ok(); - for (index, ty_name) in &fragment_outputs { - writeln!(out, " @location({}) fb{}: {},", index, index, ty_name).ok(); - } - writeln!(out, "}}").ok(); - } - - writeln!(out).ok(); - writeln!(out, "fn mp_draw_pass_camera_projection() -> mat4x4f {{").ok(); - if xr_multiview { - writeln!(out, " if (VIEW_ID != 0) {{").ok(); - writeln!(out, " return unibuf_draw_pass.camera_projection_r;").ok(); - writeln!(out, " }}").ok(); - } - writeln!(out, " return unibuf_draw_pass.camera_projection;").ok(); - writeln!(out, "}}").ok(); - writeln!(out, "fn mp_draw_pass_camera_view() -> mat4x4f {{").ok(); - if xr_multiview { - writeln!(out, " if (VIEW_ID != 0) {{").ok(); - writeln!(out, " return unibuf_draw_pass.camera_view_r;").ok(); - writeln!(out, " }}").ok(); - } - writeln!(out, " return unibuf_draw_pass.camera_view;").ok(); - writeln!(out, "}}").ok(); - writeln!(out, "fn mp_draw_pass_depth_projection() -> mat4x4f {{").ok(); - if xr_multiview { - writeln!(out, " if (VIEW_ID != 0) {{").ok(); - writeln!(out, " return unibuf_draw_pass.depth_projection_r;").ok(); - writeln!(out, " }}").ok(); - } - writeln!(out, " return unibuf_draw_pass.depth_projection;").ok(); - writeln!(out, "}}").ok(); - writeln!(out, "fn mp_draw_pass_depth_view() -> mat4x4f {{").ok(); - if xr_multiview { - writeln!(out, " if (VIEW_ID != 0) {{").ok(); - writeln!(out, " return unibuf_draw_pass.depth_view_r;").ok(); - writeln!(out, " }}").ok(); - } - writeln!(out, " return unibuf_draw_pass.depth_view;").ok(); - writeln!(out, "}}").ok(); - writeln!(out, "fn mp_draw_pass_camera_inv() -> mat4x4f {{").ok(); - if xr_multiview { - writeln!(out, " if (VIEW_ID != 0) {{").ok(); - writeln!(out, " return unibuf_draw_pass.camera_inv_r;").ok(); - writeln!(out, " }}").ok(); - } - writeln!(out, " return unibuf_draw_pass.camera_inv;").ok(); - writeln!(out, "}}").ok(); - writeln!(out).ok(); - output.create_functions(&mut out); - writeln!(out).ok(); - writeln!( - out, - "fn depth_clip(world: vec4f, color: vec4f, clip: f32) -> vec4f {{" - ) - .ok(); - writeln!(out, " if (clip < 0.5) {{").ok(); - writeln!(out, " return color;").ok(); - writeln!(out, " }}").ok(); - writeln!( - out, - " let depth_projection = mp_draw_pass_depth_projection();" - ) - .ok(); - writeln!(out, " let depth_view = mp_draw_pass_depth_view();").ok(); - writeln!(out, " if (abs(depth_view[3].w - 1.0) > 0.5) {{").ok(); - writeln!(out, " return color;").ok(); - writeln!(out, " }}").ok(); - writeln!( - out, - " let depth_pos = depth_projection * depth_view * world;" - ) - .ok(); - writeln!(out, " if (abs(depth_pos.w) < 0.000001) {{").ok(); - writeln!(out, " return color;").ok(); - writeln!(out, " }}").ok(); - writeln!( - out, - " let depth_hc = (depth_pos.xyz / vec3f(depth_pos.w)) * vec3f(0.5, 0.5, 0.5) + vec3f(0.5, 0.5, 0.5);" - ) - .ok(); - writeln!(out, " let dims = textureDimensions(tex_xr_depth);").ok(); - writeln!(out, " if (dims.x == 0u || dims.y == 0u) {{").ok(); - writeln!(out, " return color;").ok(); - writeln!(out, " }}").ok(); - writeln!( - out, - " let depth_x = clamp(i32(depth_hc.x * f32(dims.x)), 0, max(i32(dims.x) - 1, 0));" - ) - .ok(); - writeln!( - out, - " let depth_y = clamp(i32(depth_hc.y * f32(dims.y)), 0, max(i32(dims.y) - 1, 0));" - ) - .ok(); - if xr_multiview { - writeln!( - out, - " let depth_view_eye_z = textureLoad(tex_xr_depth, vec2i(depth_x, depth_y), VIEW_ID, 0);" - ) - .ok(); - } else { - writeln!( - out, - " let depth_view_eye_z = textureLoad(tex_xr_depth, vec2i(depth_x, depth_y), 0);" - ) - .ok(); - } - writeln!(out, " if (depth_view_eye_z >= depth_hc.z) {{").ok(); - writeln!(out, " return color;").ok(); - writeln!(out, " }}").ok(); - writeln!(out, " discard;").ok(); - writeln!(out, " return vec4f(0.0, 0.0, 0.0, 0.0);").ok(); - writeln!(out, "}}").ok(); - - let vertex_fn_name = output.backend.map_function_name("io_vertex"); - let fragment_fn_name = output.backend.map_function_name("io_fragment"); - let vertex_returns_vec4f = output - .functions - .iter() - .find(|f| f.name == id!(vertex)) - .map(|f| f.ret == vm.bx.code.builtins.pod.pod_vec4f) - .unwrap_or(false); - - writeln!(out, "@vertex").ok(); - writeln!(out, "fn vertex_main(in: VertexMainIn) -> VertexMainOut {{").ok(); - if xr_multiview { - writeln!(out, " VIEW_ID = in.view_index;").ok(); - } else { - writeln!(out, " VIEW_ID = 0;").ok(); - } - for field in &geometry_fields { - let value_expr = wgsl_unpack_expr_for_field( - output, - vm, - field, - "in.packed_geometry_", - WgslPackedSource::BitPackedFloat, - ); - writeln!(out, " {} = {};", field.name, value_expr).ok(); - } - for field in &instance_fields { - let value_expr = wgsl_unpack_expr_for_field( - output, - vm, - field, - "in.packed_instance_", - WgslPackedSource::BitPackedFloat, - ); - writeln!(out, " {} = {};", field.name, value_expr).ok(); - } - if has_dyn_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::Uniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " uni_{} = _mp_dyn_uniforms.uni_{};", - io_name, io_name - ) - .ok(); - } - } - if has_scope_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::ScopeUniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " su_{} = _mp_scope_uniforms.su_{};", - io_name, io_name - ) - .ok(); - } - } - writeln!(out, " vtx_pos = vec4f(0.0, 0.0, 0.0, 1.0);").ok(); - if vertex_returns_vec4f { - writeln!(out, " vtx_pos = {}();", vertex_fn_name).ok(); - } else { - writeln!(out, " {}();", vertex_fn_name).ok(); - } - writeln!(out, " var out_data: VertexMainOut;").ok(); - writeln!(out, " out_data.position = vtx_pos;").ok(); - for field in &varying_fields { - let mut scalars = Vec::new(); - wgsl_flatten_exprs(output, vm, field.ty, &field.name, &mut scalars); - for slot in 0..field.slots { - let src = scalars - .get(slot) - .cloned() - .unwrap_or_else(|| "0.0".to_string()); - let dst = wgsl_packed_component("out_data.packed_varying_", field.offset + slot); - writeln!(out, " {} = {};", dst, src).ok(); - } - } - writeln!(out, " return out_data;").ok(); - writeln!(out, "}}").ok(); - - if fragment_outputs.is_empty() { - writeln!(out, "@fragment").ok(); - writeln!(out, "fn fragment_main(in: FragmentMainIn) {{").ok(); - if xr_multiview { - writeln!(out, " VIEW_ID = in.view_index;").ok(); - } else { - writeln!(out, " VIEW_ID = 0;").ok(); - } - for field in &varying_fields { - let value_expr = wgsl_unpack_expr_for_field( - output, - vm, - field, - "in.packed_varying_", - WgslPackedSource::NumericFloat, - ); - writeln!(out, " {} = {};", field.name, value_expr).ok(); - } - if has_dyn_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::Uniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " uni_{} = _mp_dyn_uniforms.uni_{};", - io_name, io_name - ) - .ok(); - } - } - if has_scope_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::ScopeUniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " su_{} = _mp_scope_uniforms.su_{};", - io_name, io_name - ) - .ok(); - } - } - writeln!(out, " {}();", fragment_fn_name).ok(); - writeln!(out, "}}").ok(); - } else { - writeln!(out, "@fragment").ok(); - writeln!( - out, - "fn fragment_main(in: FragmentMainIn) -> FragmentMainOut {{" - ) - .ok(); - if xr_multiview { - writeln!(out, " VIEW_ID = in.view_index;").ok(); - } else { - writeln!(out, " VIEW_ID = 0;").ok(); - } - for field in &varying_fields { - let value_expr = wgsl_unpack_expr_for_field( - output, - vm, - field, - "in.packed_varying_", - WgslPackedSource::NumericFloat, - ); - writeln!(out, " {} = {};", field.name, value_expr).ok(); - } - if has_dyn_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::Uniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " uni_{} = _mp_dyn_uniforms.uni_{};", - io_name, io_name - ) - .ok(); - } - } - if has_scope_uniforms { - for io in &output.io { - if !matches!(io.kind, ShaderIoKind::ScopeUniform) { - continue; - } - let io_name = output.backend.map_io_name(io.name); - writeln!( - out, - " su_{} = _mp_scope_uniforms.su_{};", - io_name, io_name - ) - .ok(); - } - } - writeln!(out, " {}();", fragment_fn_name).ok(); - writeln!(out, " var out_data: FragmentMainOut;").ok(); - for (index, ty_name) in &fragment_outputs { - let expr = match ty_name.as_str() { - "f32" => "f32(0.0)".to_string(), - "i32" => "i32(0)".to_string(), - "u32" => "u32(0)".to_string(), - "vec2f" => "vec2f(0.0)".to_string(), - "vec3f" => "vec3f(0.0)".to_string(), - "vec4f" => "frag_fb0".to_string(), - "vec2i" => "vec2i(0)".to_string(), - "vec3i" => "vec3i(0)".to_string(), - "vec4i" => "vec4i(0)".to_string(), - "vec2u" => "vec2u(0u)".to_string(), - "vec3u" => "vec3u(0u)".to_string(), - "vec4u" => "vec4u(0u)".to_string(), - _ => format!("{}(0.0)", ty_name), - }; - writeln!(out, " out_data.fb{} = {};", index, expr).ok(); - } - writeln!(out, " return out_data;").ok(); - writeln!(out, "}}").ok(); - } - - ( - out, - dyn_uniform_binding, - texture_binding_base.unwrap_or(0), - sampler_binding_base.unwrap_or(0), - xr_depth_binding, - ) -} - -pub fn compile_draw_shader_wgsl_source( - vm: &mut ScriptVm, - io_self: ScriptObject, - layout_source: &ShaderOutput, - xr_multiview: bool, -) -> Result { - let mut output = ShaderOutput::default(); - output.backend = ShaderBackend::Wgsl; - output.use_vulkan = false; - output.pre_collect_rust_instance_io(vm, io_self); - output.pre_collect_shader_io(vm, io_self); - - if let Some(fnobj) = vm - .bx - .heap - .object_method(io_self, id!(vertex).into(), vm.thread().trap.pass()) - .as_object() - { - output.mode = ShaderMode::Vertex; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(vertex), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - - if let Some(fnobj) = vm - .bx - .heap - .object_method(io_self, id!(fragment).into(), vm.thread().trap.pass()) - .as_object() - { - output.mode = ShaderMode::Fragment; - ShaderFnCompiler::compile_shader_def( - vm, - &mut output, - NoTrap, - id!(fragment), - fnobj, - ShaderType::IoSelf(io_self), - vec![], - ); - } - - if output.has_errors { - return Err("WGSL lowering reported shader errors".to_string()); - } - - // Keep Vulkan shader IO layout in lockstep with the draw mapping produced by the - // primary compiler path (dyn/rust instance packing, uniform buffer bindings, etc.). - output.io = layout_source - .io - .iter() - .map(|io| ShaderIo { - kind: io.kind.clone(), - name: io.name, - ty: io.ty, - buffer_index: io.buffer_index, - }) - .collect(); - output.samplers = layout_source.samplers.clone(); - - output.assign_uniform_buffer_indices(&vm.bx.heap, 3); - - let geometry_slots = wgsl_collect_geometry_fields(&output, vm) - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - let instance_slots = wgsl_collect_instance_fields(&output, vm) - .last() - .map(|field| field.offset + field.slots) - .unwrap_or(0); - - let (wgsl, dyn_uniform_binding, texture_binding_base, sampler_binding_base, xr_depth_binding) = - build_draw_shader_wgsl(vm, &mut output, xr_multiview); - - Ok(WgslDrawShaderSource { - wgsl, - dyn_uniform_binding, - texture_binding_base, - sampler_binding_base, - xr_depth_binding, - geometry_slots, - instance_slots, - }) -} diff --git a/vendor/makepad/platform/script/src/string.rs b/vendor/makepad/platform/script/src/string.rs deleted file mode 100644 index 8cf1a75..0000000 --- a/vendor/makepad/platform/script/src/string.rs +++ /dev/null @@ -1,869 +0,0 @@ -use crate::array::*; -use crate::heap::*; -use crate::makepad_live_id::*; -use crate::native::*; -use crate::value::*; -use crate::*; -use ::std::borrow::Borrow; -use ::std::sync::Arc; - -#[derive(Clone, Default, PartialEq, Eq, Hash)] -pub struct ScriptRcString(pub Arc); - -impl ScriptRcString { - pub fn new(str: String) -> Self { - Self(Arc::new(str)) - } -} - -impl Borrow for ScriptRcString { - fn borrow(&self) -> &str { - (*self.0).as_str() - } -} - -impl Borrow for ScriptRcString { - fn borrow(&self) -> &String { - &(*self.0) - } -} - -#[derive(Default)] -pub struct StringTag(u64); - -impl StringTag { - const MARK: u64 = 0x1; - const STATIC: u64 = 0x2; - - pub fn is_marked(&self) -> bool { - self.0 & Self::MARK != 0 - } - - pub fn set_mark(&mut self) { - self.0 |= Self::MARK - } - - pub fn clear_mark(&mut self) { - self.0 &= !Self::MARK - } - - pub fn set_static(&mut self) { - self.0 |= Self::STATIC - } - - pub fn is_static(&self) -> bool { - self.0 & Self::STATIC != 0 - } -} - -#[derive(Default)] -pub struct ScriptStringData { - pub tag: StringTag, - pub string: ScriptRcString, -} - -impl ScriptStringData { - pub fn add_type_methods(native: &mut ScriptNative, heap: &mut ScriptHeap) { - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(to_bytes), - &[], - |vm, args| { - let sself = script_value!(vm, args.self); - vm.bx.heap.string_to_bytes_array(sself).into() - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(to_chars), - &[], - |vm, args| { - let sself = script_value!(vm, args.self); - vm.bx.heap.string_to_chars_array(sself).into() - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(len), - &[], - |vm, args| { - let sself = script_value!(vm, args.self); - if let Some(len) = vm.bx.heap.string_with(sself, |_heap, s| s.len()) { - return (len as f64).into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "len called on non-string value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(to_f64), - &[], - |vm, args| { - let sself = script_value!(vm, args.self); - if let Some(r) = vm.bx.heap.string_mut_self_with(sself, |_heap, s| { - ScriptValue::from_f64(s.parse().unwrap_or(f64::NAN)) - }) { - r - } else { - ScriptValue::from_f64_traced_nan(f64::NAN, vm.bx.threads.cur_ref().trap.ip) - } - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(parse_json), - &[], - |vm, args| { - let sself = script_value!(vm, args.self); - - // Extract json_parser temporarily to avoid borrow conflict - let mut json_parser = std::mem::take(&mut vm.bx.threads.cur().json_parser); - let result = if let Some(r) = vm - .bx - .heap - .string_mut_self_with(sself, |heap, s| json_parser.read_json(s, heap)) - { - r - } else { - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "parse_json called on non-string value" - ) - }; - vm.bx.threads.cur().json_parser = json_parser; - result - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(trim), - script_args_def!(), - |vm, args| { - let sself = script_value!(vm, args.self); - if let Some(s) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.new_string_from_str(sself.trim()) - }) { - return s.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "trim called on non-string value" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(strip_prefix), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - if let Some(Some(s)) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.string_mut_self_with(pat, |heap, pat| { - heap.new_string_from_str(if let Some(s) = sself.strip_prefix(pat) { - s - } else { - sself - }) - }) - }) { - return s.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "strip_prefix requires string arguments" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(strip_suffix), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - if let Some(Some(s)) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.string_mut_self_with(pat, |heap, pat| { - heap.new_string_from_str(if let Some(s) = sself.strip_suffix(pat) { - s - } else { - sself - }) - }) - }) { - return s.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "strip_suffix requires string arguments" - ) - }, - ); - - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(split), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - - // Regex path - if let Some(re_ptr) = pat.as_regex() { - let result = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - regex_split(heap, sself, re_ptr) - }); - if let Some(arr) = result { - return arr.into(); - } - return script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "split: self must be a string" - ); - } - - // String path - if let Some(Some(s)) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.string_mut_self_with(pat, |heap, pat| { - let array = heap.new_array(); - heap.array_mut_mut_self_with(array, |heap, storage| { - if let ScriptArrayStorage::ScriptValue(_) = storage { - } else { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - } - if let ScriptArrayStorage::ScriptValue(vec) = storage { - vec.clear(); - for s in sself.split(pat) { - vec.push_back(heap.new_string_from_str(s)); - } - } - }); - array - }) - }) { - return s.into(); - } - - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "split requires string arguments for both self and pattern" - ) - }, - ); - - // str.search(pat) -> number (byte index of first match, or -1) - // pat can be a string or regex - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(search), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - - // Regex path - if let Some(re_ptr) = pat.as_regex() { - let result = vm.bx.heap.string_with(sself, |heap, s| { - if let Some(re) = heap.regex(re_ptr) { - let mut slots = [None; 2]; - if re.inner.run(s, &mut slots) { - slots[0].unwrap_or(0) as f64 - } else { - -1.0 - } - } else { - -1.0 - } - }); - return ScriptValue::from_f64(result.unwrap_or(-1.0)); - } - - // String path - if let Some(Some(result)) = vm.bx.heap.string_with(sself, |heap, sself| { - heap.string_with(pat, |_, pat| { - if let Some(idx) = sself.find(pat) { - idx as f64 - } else { - -1.0 - } - }) - }) { - return ScriptValue::from_f64(result); - } - ScriptValue::from_f64(-1.0) - }, - ); - - // str.match(pat) -> object or array or nil - // If pat is a non-global regex: returns {value, index, captures} or nil - // If pat is a global regex: returns array of matched strings - // If pat is a string: returns {value, index} or nil - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(match_str), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - - // Regex path - if let Some(re_ptr) = pat.as_regex() { - let (is_global, num_captures) = if let Some(re) = vm.bx.heap.regex(re_ptr) { - (re.flags.global, re.num_captures) - } else { - return NIL; - }; - - if is_global { - // Global: return array of all matched strings - let result = vm.bx.heap.string_mut_self_with(sself, |heap, s| { - regex_match_all_strings(heap, s, re_ptr) - }); - if let Some(arr) = result { - return arr.into(); - } - return NIL; - } else { - // Non-global: return first match detail - let result = vm.bx.heap.string_mut_self_with(sself, |heap, s| { - regex_exec_first(heap, s, re_ptr, num_captures) - }); - if let Some(val) = result { - return val; - } - return NIL; - } - } - - // String path: simple indexOf-style match - if let Some(Some(result)) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.string_mut_self_with(pat, |heap, pat| { - if let Some(idx) = sself.find(pat) { - let obj = heap.new_with_proto(NIL); - let value_sv = heap.new_string_from_str(pat); - heap.set_value_def(obj, id!(value).into(), value_sv); - heap.set_value_def( - obj, - id!(index).into(), - ScriptValue::from_f64(idx as f64), - ); - obj.into() - } else { - NIL - } - }) - }) { - return result; - } - NIL - }, - ); - - // str.match_all(pat) -> array of {value, index, captures} - // pat must be a regex - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(match_all), - script_args_def!(pat = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - - if let Some(re_ptr) = pat.as_regex() { - let num_captures = if let Some(re) = vm.bx.heap.regex(re_ptr) { - re.num_captures - } else { - return NIL; - }; - let result = vm.bx.heap.string_mut_self_with(sself, |heap, s| { - regex_match_all_detail(heap, s, re_ptr, num_captures) - }); - if let Some(arr) = result { - return arr.into(); - } - } - script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "match_all requires a regex argument" - ) - }, - ); - - // str.replace(pat, replacement) -> string - // pat can be a string or regex - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(replace), - script_args_def!(pat = NIL, rep = NIL), - |vm, args| { - let sself = script_value!(vm, args.self); - let pat = script_value!(vm, args.pat); - let rep = script_value!(vm, args.rep); - - // Regex path - if let Some(re_ptr) = pat.as_regex() { - let result = vm.bx.heap.string_mut_self_with(rep, |heap, replacement| { - heap.string_mut_self_with(sself, |heap, input| { - regex_replace(heap, input, re_ptr, replacement) - }) - }); - match result { - Some(Some(value)) => return value, - Some(None) => { - return script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "replace: self must be a string" - ); - } - None => { - return script_err_type_mismatch!( - vm.bx.threads.cur_ref().trap, - "replace: replacement must be a string" - ); - } - } - } - - // String path: replace first occurrence - if let Some(Some(result)) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.string_mut_self_with(pat, |heap, pat| { - heap.string_mut_self_with(rep, |heap, rep| { - heap.new_bounded_string_with(|_, out| { - if let Some(index) = sself.find(pat) { - out.append_str(&sself[..index]); - if !out.is_full() { - out.append_str(rep); - } - if !out.is_full() { - out.append_str(&sself[index + pat.len()..]); - } - } else { - out.append_str(sself); - } - }) - }) - }) - }) { - if let Some(result) = result { - return result; - } - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "replace requires string arguments" - ) - }, - ); - - // str.url_decode() -> string (percent-decode a URL-encoded string) - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(url_decode), - script_args_def!(), - |vm, args| { - let sself = script_value!(vm, args.self); - if let Some(s) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.new_bounded_string_with(|_, out| percent_decode(sself, out)) - }) { - return s.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "url_decode called on non-string value" - ) - }, - ); - - // str.url_encode() -> string (percent-encode a string for use in URLs) - native.add_type_method( - heap, - ScriptValueType::REDUX_STRING, - id!(url_encode), - script_args_def!(), - |vm, args| { - let sself = script_value!(vm, args.self); - if let Some(s) = vm.bx.heap.string_mut_self_with(sself, |heap, sself| { - heap.new_bounded_string_with(|_, out| percent_encode(sself, out)) - }) { - return s.into(); - } - script_err_unexpected!( - vm.bx.threads.cur_ref().trap, - "url_encode called on non-string value" - ) - }, - ); - } -} - -fn percent_decode(input: &str, out: &mut S) { - let bytes = input.as_bytes(); - let mut i = 0; - while i < bytes.len() && !out.is_full() { - if bytes[i] == b'%' && i + 2 < bytes.len() { - if let (Some(hi), Some(lo)) = (hex_val(bytes[i + 1]), hex_val(bytes[i + 2])) { - out.append_char((hi << 4 | lo) as char); - i += 3; - continue; - } - } else if bytes[i] == b'+' { - out.append_char(' '); - i += 1; - continue; - } - out.append_char(bytes[i] as char); - i += 1; - } -} - -fn hex_val(b: u8) -> Option { - match b { - b'0'..=b'9' => Some(b - b'0'), - b'a'..=b'f' => Some(b - b'a' + 10), - b'A'..=b'F' => Some(b - b'A' + 10), - _ => None, - } -} - -fn percent_encode(input: &str, out: &mut S) { - for b in input.bytes() { - if out.is_full() { - break; - } - match b { - b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => { - out.append_char(b as char); - } - _ => { - out.append_char('%'); - if !out.is_full() { - out.append_char(char::from(b"0123456789ABCDEF"[(b >> 4) as usize])); - } - if !out.is_full() { - out.append_char(char::from(b"0123456789ABCDEF"[(b & 0xf) as usize])); - } - } - } - } -} - -// ---- Regex helper functions ---- - -/// Find all non-overlapping matches and return their byte ranges -fn regex_find_all( - heap: &ScriptHeap, - input: &str, - re_ptr: ScriptRegex, - num_captures: usize, -) -> Vec<(usize, usize, Vec>)> { - let mut results = Vec::new(); - let num_slots = (num_captures + 1) * 2; - let mut slots = vec![None; num_slots]; - let mut search_from = 0; - - while search_from <= input.len() { - let haystack = &input[search_from..]; - for s in slots.iter_mut() { - *s = None; - } - - let re = match heap.regex(re_ptr) { - Some(re) => re, - None => break, - }; - - if !re.inner.run(haystack, &mut slots) { - break; - } - - let match_start = search_from + slots[0].unwrap_or(0); - let match_end = search_from + slots[1].unwrap_or(0); - - let mut caps = Vec::new(); - for i in 1..=num_captures { - let s = slots.get(i * 2).copied().flatten(); - let e = slots.get(i * 2 + 1).copied().flatten(); - match (s, e) { - (Some(s), Some(e)) => caps.push(Some((search_from + s, search_from + e))), - _ => caps.push(None), - } - } - - results.push((match_start, match_end, caps)); - - // Advance past this match (avoid infinite loop on zero-length match) - if match_end == search_from { - search_from = next_char_boundary(input, match_end); - } else { - search_from = match_end; - } - } - results -} - -fn next_char_boundary(s: &str, pos: usize) -> usize { - let mut p = pos + 1; - while p < s.len() && !s.is_char_boundary(p) { - p += 1; - } - p -} - -/// Split a string by regex matches -fn regex_split(heap: &mut ScriptHeap, input: &str, re_ptr: ScriptRegex) -> ScriptArray { - let num_captures = heap.regex(re_ptr).map(|r| r.num_captures).unwrap_or(0); - let matches = regex_find_all(heap, input, re_ptr, num_captures); - - let array = heap.new_array(); - heap.array_mut_mut_self_with(array, |heap, storage| { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(vec) = storage { - let mut last_end = 0; - for (start, end, caps) in &matches { - vec.push_back(heap.new_string_from_str(&input[last_end..*start])); - // JS behavior: include capture groups in split result - for cap in caps { - match cap { - Some((s, e)) => vec.push_back(heap.new_string_from_str(&input[*s..*e])), - None => vec.push_back(NIL), - } - } - last_end = *end; - } - vec.push_back(heap.new_string_from_str(&input[last_end..])); - } - }); - array -} - -/// Return array of all matched strings (for global match) -fn regex_match_all_strings(heap: &mut ScriptHeap, input: &str, re_ptr: ScriptRegex) -> ScriptArray { - let num_captures = heap.regex(re_ptr).map(|r| r.num_captures).unwrap_or(0); - let matches = regex_find_all(heap, input, re_ptr, num_captures); - - let array = heap.new_array(); - heap.array_mut_mut_self_with(array, |heap, storage| { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(vec) = storage { - for (start, end, _) in &matches { - vec.push_back(heap.new_string_from_str(&input[*start..*end])); - } - } - }); - array -} - -/// Execute regex and return first match as a script object -fn regex_exec_first( - heap: &mut ScriptHeap, - input: &str, - re_ptr: ScriptRegex, - num_captures: usize, -) -> ScriptValue { - let num_slots = (num_captures + 1) * 2; - let mut slots = vec![None; num_slots]; - - let matched = if let Some(re) = heap.regex(re_ptr) { - re.inner.run(input, &mut slots) - } else { - return NIL; - }; - - if !matched { - return NIL; - } - - let match_start = slots[0].unwrap_or(0); - let match_end = slots[1].unwrap_or(0); - let value = &input[match_start..match_end]; - - let obj = heap.new_with_proto(NIL); - let value_sv = heap.new_string_from_str(value); - heap.set_value_def(obj, id!(value).into(), value_sv); - heap.set_value_def( - obj, - id!(index).into(), - ScriptValue::from_f64(match_start as f64), - ); - - // Build captures array - let captures = heap.new_array(); - heap.array_mut_mut_self_with(captures, |heap, storage| { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(vec) = storage { - vec.push_back(heap.new_string_from_str(value)); - for i in 1..=num_captures { - let s = slots.get(i * 2).copied().flatten(); - let e = slots.get(i * 2 + 1).copied().flatten(); - match (s, e) { - (Some(s), Some(e)) => vec.push_back(heap.new_string_from_str(&input[s..e])), - _ => vec.push_back(NIL), - } - } - } - }); - heap.set_value_def(obj, id!(captures).into(), captures.into()); - obj.into() -} - -/// Return array of all match detail objects -fn regex_match_all_detail( - heap: &mut ScriptHeap, - input: &str, - re_ptr: ScriptRegex, - num_captures: usize, -) -> ScriptArray { - let matches = regex_find_all(heap, input, re_ptr, num_captures); - - let array = heap.new_array(); - heap.array_mut_mut_self_with(array, |heap, storage| { - *storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(vec) = storage { - for (start, end, caps) in &matches { - let value = &input[*start..*end]; - let obj = heap.new_with_proto(NIL); - let value_sv = heap.new_string_from_str(value); - heap.set_value_def(obj, id!(value).into(), value_sv); - heap.set_value_def(obj, id!(index).into(), ScriptValue::from_f64(*start as f64)); - - let cap_arr = heap.new_array(); - heap.array_mut_mut_self_with(cap_arr, |heap, cap_storage| { - *cap_storage = ScriptArrayStorage::ScriptValue(Default::default()); - if let ScriptArrayStorage::ScriptValue(cap_vec) = cap_storage { - cap_vec.push_back(heap.new_string_from_str(value)); - for cap in caps { - match cap { - Some((s, e)) => { - cap_vec.push_back(heap.new_string_from_str(&input[*s..*e])) - } - None => cap_vec.push_back(NIL), - } - } - } - }); - heap.set_value_def(obj, id!(captures).into(), cap_arr.into()); - vec.push_back(obj.into()); - } - } - }); - array -} - -/// Replace regex matches with a replacement string -/// Supports $& (whole match), $1-$9 (capture groups), $$ (literal $) -fn regex_replace( - heap: &mut ScriptHeap, - input: &str, - re_ptr: ScriptRegex, - replacement: &str, -) -> ScriptValue { - let is_global = heap.regex(re_ptr).map(|r| r.flags.global).unwrap_or(false); - let num_captures = heap.regex(re_ptr).map(|r| r.num_captures).unwrap_or(0); - - let matches = if is_global { - regex_find_all(heap, input, re_ptr, num_captures) - } else { - // Just get the first match - let all = regex_find_all(heap, input, re_ptr, num_captures); - if all.is_empty() { - vec![] - } else { - vec![all.into_iter().next().unwrap()] - } - }; - - if matches.is_empty() { - return heap.new_string_from_str(input); - } - - heap.new_bounded_string_with(|_heap, out| { - let mut last_end = 0; - for (start, end, caps) in &matches { - out.append_str(&input[last_end..*start]); - expand_replacement(out, replacement, &input[*start..*end], input, caps); - if out.is_full() { - break; - } - last_end = *end; - } - if !out.is_full() { - out.append_str(&input[last_end..]); - } - }) -} - -/// Expand replacement string patterns ($&, $1, $$, etc.) -fn expand_replacement( - out: &mut S, - replacement: &str, - matched: &str, - input: &str, - caps: &[Option<(usize, usize)>], -) { - let bytes = replacement.as_bytes(); - let mut i = 0; - while i < bytes.len() { - if bytes[i] == b'$' && i + 1 < bytes.len() { - match bytes[i + 1] { - b'$' => { - out.append_char('$'); - i += 2; - } - b'&' => { - out.append_str(matched); - i += 2; - } - b'0'..=b'9' => { - // Parse group number - let start = i + 1; - let mut end = start + 1; - while end < bytes.len() && bytes[end].is_ascii_digit() { - end += 1; - } - let num: usize = replacement[start..end].parse().unwrap_or(0); - if num >= 1 && num <= caps.len() { - if let Some((s, e)) = caps[num - 1] { - out.append_str(&input[s..e]); - } - } - i = end; - } - _ => { - out.append_char('$'); - i += 1; - } - } - } else { - let ch = replacement[i..].chars().next().unwrap(); - out.append_char(ch); - i += ch.len_utf8(); - } - if out.is_full() { - break; - } - } -} diff --git a/vendor/makepad/platform/script/src/string_heap.rs b/vendor/makepad/platform/script/src/string_heap.rs deleted file mode 100644 index fe235bf..0000000 --- a/vendor/makepad/platform/script/src/string_heap.rs +++ /dev/null @@ -1,492 +0,0 @@ -use crate::array::*; -use crate::gen_index::GenSlot; -use crate::heap::*; -use crate::string::*; -use crate::value::*; -use std::fmt::{self, Write}; -use std::mem::size_of; - -/// A sink used while the VM converts values into strings. -/// -/// Ordinary [`String`] sinks preserve the upstream unbounded behavior. The -/// runtime can instead use [`ScriptStringBuffer`] to stop a script-created -/// string before it grows past the host-selected limit. -pub trait ScriptStringSink: Write { - fn is_full(&self) -> bool; - - fn append_str(&mut self, value: &str) { - let _ = self.write_str(value); - } - - fn append_char(&mut self, value: char) { - let _ = self.write_char(value); - } -} - -impl ScriptStringSink for String { - fn is_full(&self) -> bool { - false - } -} - -/// A string builder that records a limit hit without allocating beyond its -/// configured logical byte length. -pub struct ScriptStringBuffer { - value: String, - maximum_bytes: Option, - full: bool, -} - -impl ScriptStringBuffer { - fn new(value: String, maximum_bytes: Option) -> Self { - Self { - value, - maximum_bytes, - full: false, - } - } - - pub fn as_str(&self) -> &str { - &self.value - } - - pub fn is_empty(&self) -> bool { - self.value.is_empty() - } - - fn into_parts(self) -> (String, bool) { - (self.value, self.full) - } - - fn reserve_append(&mut self, additional_bytes: usize) -> Result<(), fmt::Error> { - if self.full { - return Err(fmt::Error); - } - let Some(next_len) = self.value.len().checked_add(additional_bytes) else { - self.full = true; - return Err(fmt::Error); - }; - if self - .maximum_bytes - .is_some_and(|maximum| next_len > maximum) - { - self.full = true; - return Err(fmt::Error); - } - if self.value.try_reserve(additional_bytes).is_err() { - self.full = true; - return Err(fmt::Error); - } - Ok(()) - } -} - -impl Write for ScriptStringBuffer { - fn write_str(&mut self, value: &str) -> fmt::Result { - self.reserve_append(value.len())?; - self.value.push_str(value); - Ok(()) - } - - fn write_char(&mut self, value: char) -> fmt::Result { - let mut encoded = [0; 4]; - self.write_str(value.encode_utf8(&mut encoded)) - } -} - -impl ScriptStringSink for ScriptStringBuffer { - fn is_full(&self) -> bool { - self.full - } -} - -impl ScriptHeap { - // Strings - - /// Sets a maximum length for newly constructed script strings. - /// - /// `None` preserves the inherited VM behavior. A limit applies only to - /// string construction after this call; existing heap strings remain - /// valid so a host can safely lower a limit between completed runs. - pub fn set_max_string_bytes(&mut self, maximum_bytes: Option) { - self.max_string_bytes = maximum_bytes; - self.string_limit_exceeded = false; - } - - /// Returns and clears a pending bounded-string construction failure. - pub fn take_string_limit_exceeded(&mut self) -> bool { - std::mem::take(&mut self.string_limit_exceeded) - } - - pub fn string_mut_self_with R>( - &mut self, - value: ScriptValue, - cb: F, - ) -> Option { - if let Some(s) = value.as_string() { - if let Some(s) = &self.strings[s] { - let s = s.string.clone(); - let r = cb(self, &s.0); - return Some(r); - } else { - return None; - } - } - if let Some(r) = value.as_inline_string(|s| cb(self, s)) { - return Some(r); - } - None - } - - pub fn string_with R>( - &self, - value: ScriptValue, - cb: F, - ) -> Option { - if let Some(s) = value.as_string() { - if let Some(s) = &self.strings[s] { - let r = cb(self, &s.string.0); - return Some(r); - } else { - return None; - } - } - if let Some(r) = value.as_inline_string(|s| cb(self, s)) { - return Some(r); - } - None - } - - pub fn new_string_from_str(&mut self, value: &str) -> ScriptValue { - if self.max_string_bytes.is_none() { - if let Some(value) = ScriptValue::from_inline_string(value) { - return value; - } - } - self.new_bounded_string_with(|_, out| { - out.append_str(value); - }) - } - - /// Builds a temporary host string with the inherited unbounded callback - /// contract. Runtime-owned native operations must use - /// [`Self::temp_bounded_string_with`] instead. - pub fn temp_string_with R>( - &mut self, - cb: F, - ) -> R { - let mut out = self.take_string_buffer(); - let r = cb(self, &mut out); - self.recycle_string(out); - r - } - - /// Builds a temporary string through the configured per-string limit. - pub fn temp_bounded_string_with R>( - &mut self, - cb: F, - ) -> R { - let mut out = self.new_string_buffer(); - let r = cb(self, &mut out); - self.recycle_string_buffer(out); - r - } - - /// Builds a host string with the inherited unbounded callback contract. - /// Runtime-owned native operations must use - /// [`Self::new_bounded_string_with`] instead. - pub fn new_string_with(&mut self, cb: F) -> ScriptValue { - let mut out = self.take_string_buffer(); - cb(self, &mut out); - self.intern_or_store_string(out) - } - - /// Builds a script string through the configured per-string limit. - pub fn new_bounded_string_with( - &mut self, - cb: F, - ) -> ScriptValue { - let mut out = self.new_string_buffer(); - cb(self, &mut out); - let (out, exceeded) = out.into_parts(); - if exceeded { - self.string_limit_exceeded = true; - self.recycle_string(out); - return NIL; - } - self.intern_or_store_string(out) - } - - /// Takes an owned String and either interns it, reuses an existing interned value, or stores it as a new string. - /// The String is consumed and may be returned to the reuse pool. - pub fn intern_or_store_string(&mut self, out: String) -> ScriptValue { - if self - .max_string_bytes - .is_some_and(|maximum| out.len() > maximum) - { - self.string_limit_exceeded = true; - self.recycle_string(out); - return NIL; - } - if let Some(v) = ScriptValue::from_inline_string(&out) { - self.recycle_string(out); - return v; - } - - // check intern table - if let Some(index) = self.string_intern.get(&out).copied() { - self.recycle_string(out); - return index.into(); - } - - let string_capacity = out.capacity(); - let strings_capacity = self.strings.capacity(); - let intern_capacity = self.string_intern.capacity(); - - // fetch a free string - let stored = if let Some(str) = self.strings_free.pop() { - // str already has the correct generation from gc.rs sweep - let out = ScriptRcString::new(out); - self.strings[str] = Some(ScriptStringData { - tag: Default::default(), - string: out.clone(), - }); - self.string_intern.insert(out, str); - str - } else { - let out = ScriptRcString::new(out); - let index = self.strings.len(); - self.strings.push(Some(ScriptStringData { - tag: Default::default(), - string: out.clone(), - })); - // New slot starts at generation 0 - let ret = ScriptString::new(index as _, crate::value::GENERATION_ZERO); - self.string_intern.insert(out, ret); - ret - }; - - let slot_growth = self - .strings - .capacity() - .saturating_sub(strings_capacity) - .saturating_mul(size_of::>>()); - let intern_entry_bytes = size_of::<(ScriptRcString, ScriptString)>() - .saturating_add(size_of::().saturating_mul(2)) - .saturating_add(1); - let intern_growth = self - .string_intern - .capacity() - .saturating_sub(intern_capacity) - .saturating_mul(intern_entry_bytes); - self.note_heap_growth( - string_capacity - .saturating_add(slot_growth) - .saturating_add(intern_growth), - ); - - stored.into() - } - - pub fn check_intern_string(&self, value: &str) -> Option { - if self - .max_string_bytes - .is_some_and(|maximum| value.len() > maximum) - { - return None; - } - if let Some(v) = ScriptValue::from_inline_string(&value) { - Some(v) - } else if let Some(idx) = self.string_intern.get(value) { - Some((*idx).into()) - } else { - None - } - } - - pub fn string(&self, ptr: ScriptString) -> &str { - if let Some(s) = &self.strings[ptr] { - &s.string.0 - } else { - "" - } - } - - pub fn string_to_bytes_array(&mut self, v: ScriptValue) -> ScriptArray { - let arr = self.new_array(); - let before = self.arrays[arr].storage.retained_bytes(); - if v.as_inline_string(|str| { - let array = &mut self.arrays[arr]; - if let ScriptArrayStorage::U8(v) = &mut array.storage { - v.clear(); - v.extend(str.as_bytes()) - } else { - array.storage = ScriptArrayStorage::U8(str.as_bytes().into()); - } - }) - .is_some() - { - } else if let Some(str) = v.as_string() { - let array = &mut self.arrays[arr]; - let str = if let Some(s) = &self.strings[str] { - &s.string.0 - } else { - "" - }; - if let ScriptArrayStorage::U8(v) = &mut array.storage { - v.clear(); - v.extend(str.as_bytes()) - } else { - array.storage = ScriptArrayStorage::U8(str.as_bytes().into()); - } - } - self.note_array_storage_growth(arr, before); - arr - } - - pub fn string_to_chars_array(&mut self, v: ScriptValue) -> ScriptArray { - let arr = self.new_array(); - let before = self.arrays[arr].storage.retained_bytes(); - if v.as_inline_string(|str| { - let array = &mut self.arrays[arr]; - if let ScriptArrayStorage::U32(v) = &mut array.storage { - v.clear(); - for c in str.chars() { - v.push(c as u32) - } - } else { - array.storage = ScriptArrayStorage::U32(str.chars().map(|c| c as u32).collect()); - } - }) - .is_some() - { - } else if let Some(str) = v.as_string() { - let array = &mut self.arrays[arr]; - let str = if let Some(s) = &self.strings[str] { - &s.string.0 - } else { - "" - }; - if let ScriptArrayStorage::U32(v) = &mut array.storage { - v.clear(); - for c in str.chars() { - v.push(c as u32) - } - } else { - array.storage = ScriptArrayStorage::U32(str.chars().map(|c| c as u32).collect()); - } - } - self.note_array_storage_growth(arr, before); - arr - } - - pub fn cast_to_string(&self, v: ScriptValue, out: &mut S) { - if v.as_inline_string(|s| out.append_str(s)).is_some() { - return; - } - if let Some(v) = v.as_string() { - let str = self.string(v); - out.append_str(str); - return; - } - if let Some(v) = v.as_f64() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_u40() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_bool() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_id() { - write!(out, "{v}").ok(); - return; - } - if v.is_nil() { - return; - } - if let Some(v) = v.as_f32() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_f16() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_u32() { - write!(out, "{v}").ok(); - return; - } - if let Some(v) = v.as_i32() { - write!(out, "{v}").ok(); - return; - } - if let Some(_v) = v.as_object() { - write!(out, "[ScriptObject]").ok(); - return; - } - if let Some(v) = v.as_color() { - write!(out, "#{:08x}", v).ok(); - return; - } - if v.is_opcode() { - write!(out, "[Opcode]").ok(); - return; - } - if v.is_err() { - write!(out, "[Error:{}]", v).ok(); - return; - } - write!(out, "[Unknown]").ok(); - } - - fn new_string_buffer(&mut self) -> ScriptStringBuffer { - let out = if self.max_heap_bytes.is_some() { - String::new() - } else if let Some(out) = self.strings_reuse.pop() { - if self - .max_string_bytes - .is_some_and(|maximum| out.capacity() > maximum) - { - String::new() - } else { - out - } - } else { - String::new() - }; - ScriptStringBuffer::new(out, self.max_string_bytes) - } - - fn take_string_buffer(&mut self) -> String { - if self.max_heap_bytes.is_some() { - String::new() - } else { - self.strings_reuse.pop().unwrap_or_default() - } - } - - fn recycle_string_buffer(&mut self, out: ScriptStringBuffer) { - let (out, exceeded) = out.into_parts(); - if exceeded { - self.string_limit_exceeded = true; - } - self.recycle_string(out); - } - - fn recycle_string(&mut self, mut out: String) { - out.clear(); - if self.max_heap_bytes.is_some() { - return; - } - if self - .max_string_bytes - .is_none_or(|maximum| out.capacity() <= maximum) - { - self.strings_reuse.push(out); - } - } -} diff --git a/vendor/makepad/platform/script/src/suggest.rs b/vendor/makepad/platform/script/src/suggest.rs deleted file mode 100644 index 7648260..0000000 --- a/vendor/makepad/platform/script/src/suggest.rs +++ /dev/null @@ -1,694 +0,0 @@ -//! "Did you mean?" suggestions for property lookup errors -//! -//! This module provides fuzzy matching for property names to help users -//! identify typos when a property lookup fails. - -use crate::heap::*; -use crate::makepad_live_id::*; -use crate::pod::*; -use crate::traits::ScriptTypeObject; -use crate::value::*; -use std::fmt::Write; - -/// Compute Levenshtein distance between two strings -pub fn levenshtein(a: &str, b: &str) -> usize { - let a_len = a.len(); - let b_len = b.len(); - - if a_len == 0 { - return b_len; - } - if b_len == 0 { - return a_len; - } - - // Use two rows instead of full matrix for efficiency - let mut prev_row: Vec = (0..=b_len).collect(); - let mut curr_row: Vec = vec![0; b_len + 1]; - - for (i, ca) in a.chars().enumerate() { - curr_row[0] = i + 1; - for (j, cb) in b.chars().enumerate() { - let cost = if ca == cb { 0 } else { 1 }; - curr_row[j + 1] = (prev_row[j + 1] + 1) // deletion - .min(curr_row[j] + 1) // insertion - .min(prev_row[j] + cost); // substitution - } - std::mem::swap(&mut prev_row, &mut curr_row); - } - prev_row[b_len] -} - -/// Format a ScriptValue briefly for display in suggestions. -/// Shows type and a short preview of the value, e.g.: -/// - `#ff0000` for colors -/// - `fn123` for functions -/// - `obj` for objects -/// - `3.14` for numbers -/// - `"hello"` for strings (truncated) -pub fn format_value_brief(heap: &ScriptHeap, value: ScriptValue) -> String { - // Handle nil - if value.is_nil() { - return "nil".to_string(); - } - - // Handle bool - if value.is_bool() { - return if value == TRUE { "true" } else { "false" }.to_string(); - } - - // Handle numbers (f64, f32, u32, i32, u40) - if let Some(n) = value.as_f64() { - if n.fract() == 0.0 && n.abs() < 1e10 { - return format!("{}", n as i64); - } - return format!("{:.3}", n); - } - if let Some(n) = value.as_u40() { - return format!("{}", n); - } - - // Handle color - if let Some(color) = value.as_color() { - return format!( - "#{:02x}{:02x}{:02x}{:02x}", - (color >> 24) as u8, - (color >> 16) as u8, - (color >> 8) as u8, - color as u8 - ); - } - - // Handle LiveId - if let Some(id) = value.as_id() { - return id.as_string(|s| s.unwrap_or("id").to_string()); - } - - // Handle inline strings - if let Some(s) = value.as_inline_string(|s| s.to_string()) { - return format!("\"{}\"", truncate_preview(&s, 12)); - } - - // Handle heap strings - if let Some(s) = value.as_string() { - if let Some(str_data) = &heap.strings[s] { - let s = &str_data.string.0; - return format!("\"{}\"", truncate_preview(s, 12)); - } - return "\"\"".to_string(); - } - - // Handle objects - check if it's a function - if let Some(obj) = value.as_object() { - if heap.is_fn(obj) { - return format!("fn{}", obj.index); - } - // Regular object - show object id - return format!("obj{}", obj.index); - } - - // Handle arrays - if let Some(arr) = value.as_array() { - let len = heap.arrays[arr].storage.len(); - return format!("[{}]", len); - } - - // Handle pod values - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - if let Some(name) = heap.pod_type_name(pod_data.ty) { - return name.as_string(|s| s.unwrap_or("pod").to_string()); - } - return "pod".to_string(); - } - - // Handle pod types - if let Some(pod_ty) = value.as_pod_type() { - if let Some(name) = heap.pod_type_name(pod_ty) { - return format!("type:{}", name.as_string(|s| s.unwrap_or("?").to_string())); - } - return "type".to_string(); - } - - // Handle errors - if value.is_err() { - return "err".to_string(); - } - - // Fallback - format!("{:?}", value.value_type()) -} - -fn truncate_preview(value: &str, maximum_characters: usize) -> String { - let Some((end, _)) = value.char_indices().nth(maximum_characters) else { - return value.to_owned(); - }; - format!("{}...", &value[..end]) -} - -/// Format the type of a ScriptValue as a human-readable string for error messages. -/// Unlike format_value_brief which shows the value, this shows the type. -/// Examples: "number", "string", "bool", "vec4f", "MyStruct", "object", "function", "array" -pub fn format_value_type(heap: &ScriptHeap, value: ScriptValue) -> String { - // Handle nil - if value.is_nil() { - return "nil".to_string(); - } - - // Handle bool - if value.is_bool() { - return "bool".to_string(); - } - - // Handle numbers (f64, f32, u32, i32, u40) - if value.as_f64().is_some() || value.as_u40().is_some() { - return "number".to_string(); - } - - // Handle color - if value.as_color().is_some() { - return "color".to_string(); - } - - // Handle LiveId - if value.as_id().is_some() { - return "id".to_string(); - } - - // Handle strings - if value.as_inline_string(|_| ()).is_some() || value.as_string().is_some() { - return "string".to_string(); - } - - // Handle objects - check if it's a function - if let Some(obj) = value.as_object() { - if heap.is_fn(obj) { - return "function".to_string(); - } - // Check if it has a proto that indicates its type - let proto = heap.proto(obj); - if let Some(id) = proto.as_id() { - return id.as_string(|s| s.unwrap_or("object").to_string()); - } - return "object".to_string(); - } - - // Handle arrays - if value.as_array().is_some() { - return "array".to_string(); - } - - // Handle pod values - show the pod type name - if let Some(pod) = value.as_pod() { - let pod_data = &heap.pods[pod]; - return format_pod_type_name(heap, pod_data.ty); - } - - // Handle pod types - if let Some(pod_ty) = value.as_pod_type() { - return format!("type:{}", format_pod_type_name(heap, pod_ty)); - } - - // Handle errors - if value.is_err() { - return "error".to_string(); - } - - // Fallback - format!("{:?}", value.value_type()) -} - -/// Format the expected type name from a ScriptTypeObject for error messages. -/// This is used when type checking fails and we need to show what type was expected. -pub fn format_expected_type(heap: &ScriptHeap, type_object: &ScriptTypeObject) -> String { - // First check if we have an explicit type name set (from derive macro) - if let Some(name) = type_object.name { - return name.as_string(|s| s.unwrap_or("object").to_string()); - } - // Check if proto is a pod value (e.g., Vec4f, Mat4f primitives) - if let Some(pod) = type_object.proto.as_pod() { - let pod_data = &heap.pods[pod]; - return format_pod_type_name(heap, pod_data.ty); - } - // Check if proto is an object - if let Some(proto_obj) = type_object.proto.as_object() { - let obj_data = &heap.objects[proto_obj]; - // Check if it's a pod type first - this handles Vec4f, etc. - if let Some(pod_type) = obj_data.tag.as_pod_type() { - return format_pod_type_name(heap, pod_type); - } - // Check if the object itself has a name via its proto - let proto_val = heap.proto(proto_obj); - if let Some(id) = proto_val.as_id() { - return id.as_string(|s| s.unwrap_or("object").to_string()); - } - // Check if the object has entries that indicate it's a known type - if let Some(name_val) = obj_data.map_get(&id!(name).into()) { - if let Some(id) = name_val.as_id() { - return id.as_string(|s| s.unwrap_or("object").to_string()); - } - } - } - // Proto is directly an id - if let Some(id) = type_object.proto.as_id() { - return id.as_string(|s| s.unwrap_or("object").to_string()); - } - // Fallback - "object".to_string() -} - -/// Format a ScriptPodType as a human-readable type name for error messages. -/// Returns names like "f32", "vec2f", "vec4f", "MyStruct", etc. -pub fn format_pod_type_name(heap: &ScriptHeap, pod_ty: ScriptPodType) -> String { - // First try to get the registered name - if let Some(name) = heap.pod_type_name(pod_ty) { - return name.as_string(|s| s.unwrap_or("?").to_string()); - } - - // Fallback: try to describe based on the type structure - format_pod_type_from_ty(heap, pod_ty) -} - -/// Format a ScriptPodType based on its type structure (without using registered name). -pub fn format_pod_type_from_ty(heap: &ScriptHeap, pod_ty: ScriptPodType) -> String { - let pod_type = &heap.pod_types[pod_ty.index as usize]; - match &pod_type.ty { - ScriptPodTy::F32 => "f32".to_string(), - ScriptPodTy::F16 => "f16".to_string(), - ScriptPodTy::U32 => "u32".to_string(), - ScriptPodTy::I32 => "i32".to_string(), - ScriptPodTy::Bool => "bool".to_string(), - ScriptPodTy::Vec(vt) => { - // Use the name() method which returns the correct LiveId - vt.name().as_string(|s| s.unwrap_or("vec").to_string()) - } - ScriptPodTy::Mat(mt) => { - // Use the name() method which returns the correct LiveId - mt.name().as_string(|s| s.unwrap_or("mat").to_string()) - } - ScriptPodTy::Struct { .. } => { - // Try to get name if available - if let Some(name) = heap.pod_type_name(pod_ty) { - return name.as_string(|s| s.unwrap_or("struct").to_string()); - } - format!("struct#{}", pod_ty.index) - } - ScriptPodTy::Enum { .. } => { - if let Some(name) = heap.pod_type_name(pod_ty) { - return name.as_string(|s| s.unwrap_or("enum").to_string()); - } - format!("enum#{}", pod_ty.index) - } - ScriptPodTy::FixedArray { .. } => format!("array#{}", pod_ty.index), - ScriptPodTy::VariableArray { .. } => format!("vararray#{}", pod_ty.index), - ScriptPodTy::Void => "void".to_string(), - ScriptPodTy::AtomicU32 => "atomic_u32".to_string(), - ScriptPodTy::AtomicI32 => "atomic_i32".to_string(), - _ => format!("type#{}", pod_ty.index), - } -} - -/// Format a ScriptPodType using builtin constants (for use in shader builtins where we don't have heap access). -/// This compares against known builtin type indices to get the name. -pub fn format_pod_type_from_builtins( - pod_ty: ScriptPodType, - builtins: &crate::mod_pod::ScriptPodBuiltins, -) -> String { - // Check against known builtin types - if pod_ty == builtins.pod_void { - return "void".to_string(); - } - if pod_ty == builtins.pod_f32 { - return "f32".to_string(); - } - if pod_ty == builtins.pod_f16 { - return "f16".to_string(); - } - if pod_ty == builtins.pod_u32 { - return "u32".to_string(); - } - if pod_ty == builtins.pod_i32 { - return "i32".to_string(); - } - if pod_ty == builtins.pod_vec2f { - return "vec2f".to_string(); - } - if pod_ty == builtins.pod_vec3f { - return "vec3f".to_string(); - } - if pod_ty == builtins.pod_vec4f { - return "vec4f".to_string(); - } - if pod_ty == builtins.pod_vec2h { - return "vec2h".to_string(); - } - if pod_ty == builtins.pod_vec3h { - return "vec3h".to_string(); - } - if pod_ty == builtins.pod_vec4h { - return "vec4h".to_string(); - } - if pod_ty == builtins.pod_vec2u { - return "vec2u".to_string(); - } - if pod_ty == builtins.pod_vec3u { - return "vec3u".to_string(); - } - if pod_ty == builtins.pod_vec4u { - return "vec4u".to_string(); - } - if pod_ty == builtins.pod_vec2i { - return "vec2i".to_string(); - } - if pod_ty == builtins.pod_vec3i { - return "vec3i".to_string(); - } - if pod_ty == builtins.pod_vec4i { - return "vec4i".to_string(); - } - if pod_ty == builtins.pod_mat2x2f { - return "mat2x2f".to_string(); - } - if pod_ty == builtins.pod_mat3x3f { - return "mat3x3f".to_string(); - } - if pod_ty == builtins.pod_mat4x4f { - return "mat4x4f".to_string(); - } - if pod_ty == builtins.pod_mat2x3f { - return "mat2x3f".to_string(); - } - if pod_ty == builtins.pod_mat2x4f { - return "mat2x4f".to_string(); - } - if pod_ty == builtins.pod_mat3x2f { - return "mat3x2f".to_string(); - } - if pod_ty == builtins.pod_mat3x4f { - return "mat3x4f".to_string(); - } - if pod_ty == builtins.pod_mat4x2f { - return "mat4x2f".to_string(); - } - if pod_ty == builtins.pod_mat4x3f { - return "mat4x3f".to_string(); - } - - // Unknown type - just show index - format!("type#{}", pod_ty.index) -} - -/// Maximum number of items to show in "Available:" list -const MAX_AVAILABLE_ITEMS: usize = 4; - -/// Format suggestions from a list of candidate names -/// Returns a string like: `. Did you mean: foo or bar, baz (+2 more)` -pub fn suggest_from_iter<'a>(key_str: &str, candidates: impl Iterator) -> String { - let mut result = String::new(); - let mut scored: Vec<(&str, usize)> = candidates - .map(|name| (name, levenshtein(key_str, name))) - .collect(); - - if scored.is_empty() { - return result; - } - - // Sort by distance to find best matches - scored.sort_by_key(|(_, dist)| *dist); - - let total_count = scored.len(); - - // Format: "Did you mean: first or second, third, fourth (+x more)" - write!(result, ". Did you mean: {}", scored[0].0).ok(); - - if total_count > 1 { - write!(result, " or ").ok(); - for (i, (name, _)) in scored.iter().skip(1).take(MAX_AVAILABLE_ITEMS).enumerate() { - if i > 0 { - result.push_str(", "); - } - write!(result, "{}", name).ok(); - } - if total_count > MAX_AVAILABLE_ITEMS + 1 { - write!(result, " (+{} more)", total_count - MAX_AVAILABLE_ITEMS - 1).ok(); - } - } - - result -} - -/// A candidate field with its name, value preview, and distance score -struct FieldCandidate { - name: String, - value_preview: String, - distance: usize, -} - -/// Format suggestions from a list of candidate names with values -fn suggest_from_candidates(candidates: Vec) -> String { - let mut result = String::new(); - - if candidates.is_empty() { - return result; - } - - // Sort by distance to find best matches - let mut sorted = candidates; - sorted.sort_by_key(|c| c.distance); - - let total_count = sorted.len(); - - // Format first item - let first = &sorted[0]; - if first.value_preview.is_empty() { - write!(result, ". Did you mean: {}", first.name).ok(); - } else { - write!( - result, - ". Did you mean: {}({})", - first.name, first.value_preview - ) - .ok(); - } - - // Format remaining items - if total_count > 1 { - write!(result, " or ").ok(); - for (i, candidate) in sorted.iter().skip(1).take(MAX_AVAILABLE_ITEMS).enumerate() { - if i > 0 { - result.push_str(", "); - } - if candidate.value_preview.is_empty() { - write!(result, "{}", candidate.name).ok(); - } else { - write!(result, "{}({})", candidate.name, candidate.value_preview).ok(); - } - } - if total_count > MAX_AVAILABLE_ITEMS + 1 { - write!(result, " (+{} more)", total_count - MAX_AVAILABLE_ITEMS - 1).ok(); - } - } - - result -} - -/// Format suggestions from a list of LiveId names -pub fn suggest_from_live_ids(key: LiveId, candidates: &[LiveId]) -> String { - let key_str = key.as_string(|s| s.unwrap_or("").to_string()); - let names: Vec = candidates - .iter() - .filter_map(|id| id.as_string(|s| s.map(|s| s.to_string()))) - .collect(); - suggest_from_iter(&key_str, names.iter().map(|s| s.as_str())) -} - -/// Try to get a value from an object without erroring, returns NIL if not found -fn value_or_nil(heap: &ScriptHeap, obj_ptr: ScriptObject, key: ScriptValue) -> ScriptValue { - let mut ptr = obj_ptr; - let mut visited = 0; - loop { - if visited > 100 { - break; - } - visited += 1; - - let object = &heap.objects[ptr]; - if let Some(value) = object.map.get(&key) { - return value.value; - } - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr; - } else { - break; - } - } - NIL -} - -/// Format suggestions for a missing property on an object -/// Returns a string like: `. Did you mean 'foo'? Available: bar(obj), baz(fn12:0), foo(#ff0000)` -pub fn suggest_property(heap: &ScriptHeap, obj_ptr: ScriptObject, key: ScriptValue) -> String { - let mut candidates: Vec = Vec::new(); - - // Get the key as a string for comparison - let key_str = key_to_string(heap, key); - - // Helper to add a candidate if not already present - let mut add_candidate = |name: String, value: ScriptValue| { - if !candidates.iter().any(|c| c.name == name) { - let distance = levenshtein(&key_str, &name); - let value_preview = format_value_brief(heap, value); - candidates.push(FieldCandidate { - name, - value_preview, - distance, - }); - } - }; - - // First, check the type_check for registered type properties - let object = &heap.objects[obj_ptr]; - if let Some(ty_index) = object.tag.as_type_index() { - let type_check = &heap.type_check[ty_index.0 as usize]; - for (prop_id, _prop_ty) in type_check.props.iter_ordered() { - if let Some(name) = prop_id.as_string(|s| s.map(|s| s.to_string())) { - // Try to get the actual value from the prototype chain - let value = value_or_nil(heap, obj_ptr, prop_id.into()); - add_candidate(name, value); - } - } - } - - // Collect all property names from the object and its prototype chain - let mut ptr = obj_ptr; - let mut visited = 0; - loop { - if visited > 100 { - break; - } // Safety limit - visited += 1; - - let object = &heap.objects[ptr]; - - // Also check type_check on prototype objects - if let Some(ty_index) = object.tag.as_type_index() { - let type_check = &heap.type_check[ty_index.0 as usize]; - for (prop_id, _prop_ty) in type_check.props.iter_ordered() { - if let Some(name) = prop_id.as_string(|s| s.map(|s| s.to_string())) { - let value = value_or_nil(heap, ptr, prop_id.into()); - add_candidate(name, value); - } - } - } - - // Collect from map - for (map_key, map_value) in object.map.iter() { - if let Some(name) = key_to_string_opt(heap, *map_key) { - add_candidate(name, map_value.value); - } - } - - // Collect from vec - for kv in object.vec.iter() { - if let Some(name) = key_to_string_opt(heap, kv.key) { - add_candidate(name, kv.value); - } - } - - // Follow prototype chain - if let Some(next_ptr) = object.proto.as_object() { - ptr = next_ptr; - } else { - break; - } - } - - suggest_from_candidates(candidates) -} - -/// Convert a ScriptValue key to a string for display -fn key_to_string(heap: &ScriptHeap, key: ScriptValue) -> String { - key_to_string_opt(heap, key).unwrap_or_else(|| format!("{:?}", key)) -} - -/// Try to convert a ScriptValue key to a string, returns None if not possible -fn key_to_string_opt(heap: &ScriptHeap, key: ScriptValue) -> Option { - if let Some(id) = key.as_id() { - return id.as_string(|s| s.map(|s| s.to_string())); - } - if let Some(s) = key.as_string() { - if let Some(s) = &heap.strings[s] { - return Some(s.string.0.to_string()); - } - } - if let Some(s) = key.as_inline_string(|s| s.to_string()) { - return Some(s); - } - None -} - -/// Format suggestions for scope variable lookup -pub fn suggest_scope_var(heap: &ScriptHeap, obj_ptr: ScriptObject, key: LiveId) -> String { - suggest_property(heap, obj_ptr, key.into()) -} - -/// Format an enum variant error with a descriptive message about the received value. -/// Returns a string like: "expected MyEnum variant, got object with proto 'SomeOther'" -pub fn format_enum_variant_error(heap: &ScriptHeap, value: ScriptValue) -> String { - if value.is_nil() { - return "nil".to_string(); - } - - if let Some(obj) = value.as_object() { - // Get the root proto to identify what type this is - let root_proto = heap.root_proto(obj); - if let Some(id) = root_proto.as_id() { - return id.as_string(|s| format!("object with proto '{}'", s.unwrap_or("?"))); - } - if let Some(proto_obj) = root_proto.as_object() { - return format!("object(proto=obj{})", proto_obj.index); - } - return format!("object(obj{})", obj.index); - } - - // Use the format_value_type for other cases - format_value_type(heap, value) -} - -/// Format suggestions for pod struct field lookup -pub fn suggest_pod_field(heap: &ScriptHeap, pod_ty: ScriptPodType, field: LiveId) -> String { - let pod_type = &heap.pod_types[pod_ty.index as usize]; - match &pod_type.ty { - ScriptPodTy::Struct { fields, .. } => { - let field_names: Vec = fields.iter().map(|f| f.name).collect(); - suggest_from_live_ids(field, &field_names) - } - ScriptPodTy::Vec(vt) => { - // For vectors, suggest swizzle components based on dimension - let key_str = field.as_string(|s| s.unwrap_or("").to_string()); - let components = match vt.dims() { - 2 => vec!["x", "y"], - 3 => vec!["x", "y", "z"], - 4 => vec!["x", "y", "z", "w"], - _ => vec![], - }; - suggest_from_iter(&key_str, components.into_iter()) - } - _ => String::new(), - } -} - -#[cfg(test)] -mod tests { - use super::truncate_preview; - - #[test] - fn preview_truncation_preserves_utf8_boundaries() { - let value = "abcdefghijk\u{057e}"; - assert_eq!(truncate_preview(value, 12), value); - assert_eq!( - truncate_preview(&format!("{value}z"), 12), - format!("{value}...") - ); - } -} diff --git a/vendor/makepad/platform/script/src/test.rs b/vendor/makepad/platform/script/src/test.rs deleted file mode 100644 index 8b13789..0000000 --- a/vendor/makepad/platform/script/src/test.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/makepad/platform/script/src/thread.rs b/vendor/makepad/platform/script/src/thread.rs deleted file mode 100644 index 1626717..0000000 --- a/vendor/makepad/platform/script/src/thread.rs +++ /dev/null @@ -1,475 +0,0 @@ -use crate::heap::*; -use crate::json::*; -use crate::makepad_live_id::*; -use crate::opcode::*; -use crate::pod::*; -use crate::trap::*; -use crate::value::*; -use crate::*; - -#[derive(Clone, Copy, Debug, Default)] -pub struct StackBases { - pub loops: usize, - pub tries: usize, - pub stack: usize, - pub scope: usize, - pub mes: usize, -} - -#[derive(Debug)] -pub struct LoopValues { - pub value_id: LiveId, - pub key_id: Option, - pub index_id: Option, - pub source: ScriptValue, - pub index: f64, -} - -#[derive(Debug)] -pub struct TryFrame { - pub push_nil: bool, - pub start_ip: u32, - pub jump: u32, - pub bases: StackBases, -} - -#[derive(Debug)] -pub struct LoopFrame { - pub values: Option, - pub start_ip: u32, - pub jump: u32, - pub bases: StackBases, -} - -pub struct CallFrame { - pub bases: StackBases, - pub args: OpcodeArgs, - pub return_ip: Option, -} - -#[derive(Debug)] -pub enum ScriptMe { - Object(ScriptObject), - Call { - sself: Option, - args: ScriptObject, - /// When set, this is a dynamic dispatch via the type's call function. - /// The method name is passed to the call handler at exec time. - method: Option, - }, - Pod { - pod: ScriptPod, - offset: ScriptPodOffset, - }, - Array(ScriptArray), -} - -impl Into for ScriptMe { - fn into(self) -> ScriptValue { - match self { - Self::Object(v) => v.into(), - Self::Call { args, .. } => args.into(), - Self::Pod { pod, .. } => pod.into(), - Self::Array(v) => v.into(), - } - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub struct ScriptThreadId(pub(crate) u32); - -impl ScriptThreadId { - pub fn to_index(&self) -> usize { - self.0 as usize - } -} - -#[allow(unused)] -pub struct ScriptThread { - pub(crate) is_paused: bool, - /// Maximum live operand values for this thread. The raw Makepad VM keeps - /// its historical one-million-value ceiling; constrained hosts can lower - /// it for one evaluation through `ScriptVm::with_stack_value_limit`. - pub(crate) stack_limit: usize, - /// Optional maximum number of active VM call frames, including a root - /// evaluation frame. The raw VM leaves this unbounded; constrained hosts - /// install a limit for their evaluation. - pub(crate) call_frame_limit: Option, - pub(crate) tries: Vec, - pub(crate) loops: Vec, - pub(crate) scopes: Vec, - pub(crate) stack: Vec, - pub(crate) calls: Vec, - pub(crate) mes: Vec, - /// Resource-limit signals are consumed by the VM loop so these failures - /// cannot enter script-level `try` recovery. - pub(crate) stack_limit_exceeded: bool, - pub(crate) call_frame_limit_exceeded: bool, - pub(crate) instruction_limit_remaining: Option, - pub trap: ScriptTrapInner, - //pub(crate) last_err: ScriptValue, - pub(crate) json_parser: JsonParserThread, - pub(crate) thread_id: ScriptThreadId, -} - -impl ScriptThread { - pub fn new(thread_id: ScriptThreadId) -> Self { - Self { - thread_id, - is_paused: false, - //last_err: NIL, - scopes: vec![], - tries: vec![], - stack_limit: 1_000_000, - call_frame_limit: None, - loops: vec![], - stack: vec![], - calls: vec![], - mes: vec![], - stack_limit_exceeded: false, - call_frame_limit_exceeded: false, - instruction_limit_remaining: None, - trap: ScriptTrapInner::default(), - json_parser: Default::default(), - } - } - - pub fn new_bases(&self) -> StackBases { - StackBases { - tries: self.tries.len(), - loops: self.loops.len(), - stack: self.stack.len(), - scope: self.scopes.len(), - mes: self.mes.len(), - } - } - - pub fn pause(&mut self) -> ScriptThreadId { - self.trap.on.set(Some(ScriptTrapOn::Pause)); - self.is_paused = true; - self.thread_id - } - - pub fn is_paused(&self) -> bool { - self.is_paused - } - - pub fn thread_id(&self) -> ScriptThreadId { - self.thread_id - } - - pub fn truncate_bases(&mut self, bases: StackBases, heap: &mut ScriptHeap) { - self.tries.truncate(bases.tries); - self.loops.truncate(bases.loops); - self.stack.truncate(bases.stack); - self.free_unreffed_scopes(&bases, heap); - self.mes.truncate(bases.mes); - } - - pub fn truncate_loop_iteration_bases(&mut self, bases: StackBases, heap: &mut ScriptHeap) { - self.tries.truncate(bases.tries); - self.stack.truncate(bases.stack); - self.free_unreffed_scopes(&bases, heap); - self.mes.truncate(bases.mes); - } - - pub fn free_unreffed_scopes(&mut self, bases: &StackBases, heap: &mut ScriptHeap) { - while self.scopes.len() > bases.scope { - let scope = self.scopes.pop().unwrap(); - heap.free_object_if_unreffed(scope); // DISABLED: investigating RootObject already freed - } - } - - #[inline] - pub fn pop_stack_resolved(&mut self, heap: &ScriptHeap) -> ScriptValue { - if let Some(val) = self.stack.pop() { - if let Some(id) = val.as_id() { - if val.is_escaped_id() { - return val; - } - return self.scope_value(heap, id); - } - return val; - } else { - script_err_stack!(self.trap, "pop_stack_resolved on empty stack") - } - } - - pub fn peek_stack_resolved(&mut self, heap: &ScriptHeap) -> ScriptValue { - if let Some(val) = self.stack.last() { - if let Some(id) = val.as_id() { - if val.is_escaped_id() { - return *val; - } - return self.scope_value(heap, id); - } - return *val; - } else { - script_err_stack!(self.trap, "peek_stack_resolved on empty stack") - } - } - - pub fn peek_stack_value(&mut self) -> ScriptValue { - if let Some(value) = self.stack.last() { - return *value; - } else { - script_err_stack!(self.trap, "peek_stack_value on empty stack") - } - } - - pub fn peek_stack_value_at(&mut self, offset: usize) -> ScriptValue { - let len = self.stack.len(); - if offset < len { - return self.stack[len - 1 - offset]; - } else { - script_err_stack!( - self.trap, - "peek at offset {} exceeds stack len {}", - offset, - len - ) - } - } - - pub fn pop_stack_value(&mut self) -> ScriptValue { - if let Some(value) = self.stack.pop() { - return value; - } else { - script_err_stack!(self.trap, "pop_stack_value on empty stack") - } - } - - pub fn push_stack_value(&mut self, value: ScriptValue) { - self.push_stack_unchecked(value); - } - - #[inline] - pub fn push_stack_unchecked(&mut self, value: ScriptValue) { - // This is the common operand-push path used by opcode handlers. Its - // historical name distinguishes it from identifier resolution, not - // from resource accounting. - if self.stack.len() >= self.stack_limit { - self.stack_limit_exceeded = true; - return; - } - self.stack.push(value); - } - - pub(crate) fn push_call_frame(&mut self, call: CallFrame) -> bool { - if self - .call_frame_limit - .is_some_and(|limit| self.calls.len() >= limit) - { - self.call_frame_limit_exceeded = true; - return false; - } - self.calls.push(call); - true - } - - pub(crate) fn take_stack_limit_exceeded(&mut self) -> bool { - std::mem::take(&mut self.stack_limit_exceeded) - } - - pub(crate) fn take_call_frame_limit_exceeded(&mut self) -> bool { - std::mem::take(&mut self.call_frame_limit_exceeded) - } - - pub(crate) fn has_execution_limit_exceeded(&self) -> bool { - self.stack_limit_exceeded || self.call_frame_limit_exceeded - } - - pub fn call_has_me(&self) -> bool { - self.calls - .last() - .map(|call| self.mes.len() > call.bases.mes) - .unwrap_or(false) - } - - pub fn call_has_try(&self) -> bool { - self.calls - .last() - .map(|call| self.tries.len() > call.bases.tries) - .unwrap_or(false) - } - - pub(crate) fn call_stack_has_try(&self) -> bool { - self.calls - .iter() - .rev() - .any(|call| self.tries.len() > call.bases.tries) - } - - // lets resolve an id to a ScriptValue - pub fn scope_value(&mut self, heap: &ScriptHeap, id: LiveId) -> ScriptValue { - heap.scope_value(*self.scopes.last().unwrap(), id.into(), self.trap.pass()) - } - - pub fn set_scope_value( - &mut self, - heap: &mut ScriptHeap, - id: LiveId, - value: ScriptValue, - ) -> ScriptValue { - heap.set_scope_value( - *self.scopes.last().unwrap(), - id.into(), - value, - self.trap.pass(), - ) - } - - pub fn def_scope_value(&mut self, heap: &mut ScriptHeap, id: LiveId, value: ScriptValue) { - // alright if we are shadowing a value, we need to make a new scope - if let Some(new_scope) = heap.def_scope_value(*self.scopes.last().unwrap(), id, value) { - self.scopes.push(new_scope); - } - } -} - -/// Wrapper around Vec with a current thread index. -/// This allows accessing the current thread without borrowing the entire container, -/// enabling split borrows between threads and other fields like heap/code. -pub struct ScriptThreads { - threads: Vec, - current: usize, - /// Cached raw pointer to current thread for fast access in hot paths. - /// SAFETY: This must be updated whenever `current` changes or threads are reallocated. - cur_ptr: *mut ScriptThread, -} - -impl ScriptThreads { - pub fn new() -> Self { - let mut threads = vec![ScriptThread::new(ScriptThreadId(0))]; - let cur_ptr = threads.as_mut_ptr(); - Self { - threads, - current: 0, - cur_ptr, - } - } - - pub fn empty() -> Self { - Self { - threads: vec![], - current: 0, - cur_ptr: std::ptr::null_mut(), - } - } - - /// Update the cached pointer after any operation that might invalidate it - #[inline(always)] - fn update_ptr(&mut self) { - self.cur_ptr = self - .threads - .get_mut(self.current) - .map_or(std::ptr::null_mut(), |thread| thread as *mut ScriptThread); - } - - /// Get a mutable reference to the current thread using cached pointer - /// SAFETY: The pointer is kept in sync with the current index and thread vector - #[inline(always)] - pub fn cur(&mut self) -> &mut ScriptThread { - assert!( - !self.cur_ptr.is_null(), - "current ScriptThread index is invalid" - ); - unsafe { &mut *self.cur_ptr } - } - - pub fn trap<'a>(&'a self) -> ScriptTrap<'a> { - assert!( - !self.cur_ptr.is_null(), - "current ScriptThread index is invalid" - ); - unsafe { (*self.cur_ptr).trap.pass() } - } - - /// Get an immutable reference to the current thread using cached pointer - /// SAFETY: The pointer is kept in sync with the current index and thread vector - #[inline(always)] - pub fn cur_ref(&self) -> &ScriptThread { - assert!( - !self.cur_ptr.is_null(), - "current ScriptThread index is invalid" - ); - unsafe { &*self.cur_ptr } - } - - /// Set which thread is current - pub fn set_current(&mut self, id: usize) { - assert!( - id < self.threads.len(), - "current ScriptThread index {id} is out of bounds for {} threads", - self.threads.len() - ); - self.current = id; - self.update_ptr(); - } - - /// Get the current thread index - pub fn current(&self) -> usize { - self.current - } - - /// Find the first unpaused thread (creating one if needed) and set it as current - pub fn set_current_to_first_unpaused_thread(&mut self) { - for (id, thread) in self.threads.iter().enumerate() { - if !thread.is_paused { - self.current = id; - self.update_ptr(); - return; - } - } - // No unpaused thread found, create a new one - let id = self.threads.len(); - self.threads - .push(ScriptThread::new(ScriptThreadId(id as u32))); - self.current = id; - self.update_ptr(); - } - - /// Set the current thread by ScriptThreadId - pub fn set_current_thread_id(&mut self, thread_id: ScriptThreadId) { - self.set_current(thread_id.to_index()); - } - - /// Get the number of threads - pub fn len(&self) -> usize { - self.threads.len() - } - - /// Check if empty - pub fn is_empty(&self) -> bool { - self.threads.is_empty() - } - - /// Push a new thread - pub fn push(&mut self, thread: ScriptThread) { - self.threads.push(thread); - // push may reallocate, so update pointer - self.update_ptr(); - } - - /// Get thread by index - pub fn get(&self, index: usize) -> Option<&ScriptThread> { - self.threads.get(index) - } - - /// Get thread by index mutably - pub fn get_mut(&mut self, index: usize) -> Option<&mut ScriptThread> { - self.threads.get_mut(index) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic(expected = "out of bounds")] - fn selecting_an_unknown_current_thread_panics_before_pointer_update() { - let mut threads = ScriptThreads::new(); - threads.set_current(1); - } -} diff --git a/vendor/makepad/platform/script/src/tokenizer.rs b/vendor/makepad/platform/script/src/tokenizer.rs deleted file mode 100644 index 8121b84..0000000 --- a/vendor/makepad/platform/script/src/tokenizer.rs +++ /dev/null @@ -1,1097 +0,0 @@ -// Makepad script streaming tokenizer - -use crate::colorhex::hex_bytes_to_u32; -use crate::heap::*; -use crate::makepad_live_id::LiveId; -use crate::makepad_live_id_macros::*; -use crate::value::*; - -#[derive(Copy, Clone, Debug)] -pub enum ScriptToken { - End, - StreamEnd, - Identifier(LiveId), - Operator(LiveId), - Separator(LiveId), - OpenCurly, - CloseCurly, - OpenRound, - CloseRound, - OpenSquare, - CloseSquare, - StringUnfinished, - String(ScriptValue), - F32(f32), - U32(u32), - I32(i32), - F16(f32), - F64(f64), - U40(u64), - Color(u32), - RustValue(u32), -} - -impl ScriptToken { - pub fn identifier(&self) -> LiveId { - match self { - ScriptToken::Identifier(id) => *id, - _ => id!(), - } - } - pub fn operator(&self) -> LiveId { - match self { - ScriptToken::Operator(id) => *id, - _ => id!(), - } - } - pub fn separator(&self) -> LiveId { - match self { - ScriptToken::Separator(id) => *id, - _ => id!(), - } - } - pub fn f64(&self) -> f64 { - match self { - ScriptToken::F64(v) => *v, - _ => 0.0, - } - } - pub fn as_f64(&self) -> Option { - match self { - ScriptToken::F64(v) => Some(*v), - _ => None, - } - } - pub fn as_u40(&self) -> Option { - match self { - ScriptToken::U40(v) => Some(*v), - _ => None, - } - } - pub fn as_f32(&self) -> Option { - match self { - ScriptToken::F32(v) => Some(*v), - _ => None, - } - } - pub fn as_u32(&self) -> Option { - match self { - ScriptToken::U32(v) => Some(*v), - _ => None, - } - } - pub fn as_i32(&self) -> Option { - match self { - ScriptToken::I32(v) => Some(*v), - _ => None, - } - } - pub fn as_f16(&self) -> Option { - match self { - ScriptToken::F16(v) => Some(*v), - _ => None, - } - } - pub fn as_color(&self) -> Option { - match self { - ScriptToken::Color(v) => Some(*v), - _ => None, - } - } - pub fn as_string(&self) -> Option { - match self { - ScriptToken::String(v) => Some(*v), - ScriptToken::StringUnfinished => Some(ScriptValue::EMPTY_STRING), - _ => None, - } - } - pub fn as_rust_value(&self) -> Option { - match self { - ScriptToken::RustValue(v) => Some(*v), - _ => None, - } - } - - pub fn is_identifier(&self) -> bool { - match self { - ScriptToken::Identifier { .. } => true, - _ => false, - } - } - pub fn is_operator(&self) -> bool { - match self { - ScriptToken::Operator(_) => true, - _ => false, - } - } - pub fn is_open_curly(&self) -> bool { - match self { - ScriptToken::OpenCurly => true, - _ => false, - } - } - pub fn is_close_curly(&self) -> bool { - match self { - ScriptToken::CloseCurly => true, - _ => false, - } - } - pub fn is_open_round(&self) -> bool { - match self { - ScriptToken::OpenRound => true, - _ => false, - } - } - pub fn is_close_round(&self) -> bool { - match self { - ScriptToken::CloseRound => true, - _ => false, - } - } - pub fn is_open_square(&self) -> bool { - match self { - ScriptToken::OpenSquare => true, - _ => false, - } - } - pub fn is_close_square(&self) -> bool { - match self { - ScriptToken::CloseSquare => true, - _ => false, - } - } - pub fn is_string(&self) -> bool { - match self { - ScriptToken::StringUnfinished | ScriptToken::String(_) => true, - _ => false, - } - } - pub fn is_f64(&self) -> bool { - match self { - ScriptToken::F64(_) => true, - _ => false, - } - } - pub fn is_u40(&self) -> bool { - match self { - ScriptToken::U40(_) => true, - _ => false, - } - } - pub fn is_f32(&self) -> bool { - match self { - ScriptToken::F32(_) => true, - _ => false, - } - } - pub fn is_u32(&self) -> bool { - match self { - ScriptToken::U32(_) => true, - _ => false, - } - } - pub fn is_i32(&self) -> bool { - match self { - ScriptToken::I32(_) => true, - _ => false, - } - } - pub fn is_f16(&self) -> bool { - match self { - ScriptToken::F16(_) => true, - _ => false, - } - } - pub fn is_color(&self) -> bool { - match self { - ScriptToken::Color(_) => true, - _ => false, - } - } - pub fn is_rust_value(&self) -> bool { - match self { - ScriptToken::RustValue(_) => true, - _ => false, - } - } -} - -#[derive(Copy, Clone, Debug)] -pub struct ScriptTokenPos { - pub token: ScriptToken, - pos: usize, -} - -#[derive(Default, Eq, PartialEq)] -enum State { - #[default] - Whitespace, - Identifier, - Operator, - RustValue, - String(bool), - EscapeInString(bool), - UnicodeHexInString(bool), - UnicodeCurlyInString(bool), - AsciiHexInString(bool), - BlockComment(usize), - MaybeEndBlock(usize), - LineComment, - Number, - Color, -} - -#[derive(Default)] -pub struct ScriptTokenizer { - // This is a Unicode scalar offset because token_index_to_row_col iterates chars. - pos: usize, - pub tokens: Vec, - pub original: String, - unfinished: String, - temp: String, - state: State, -} - -pub struct ScriptLoc { - pub row: usize, - pub col: usize, -} - -impl ScriptTokenizer { - pub fn clear(&mut self) { - self.pos = 0; - self.tokens.clear(); - self.original.clear(); - self.unfinished.clear(); - self.temp.clear(); - self.state = State::Whitespace - } - - /// Iterate over all string values in the token stream. - /// Used by GC to mark tokenizer strings as roots. - pub fn iter_strings(&self) -> impl Iterator + '_ { - self.tokens.iter().filter_map(|tp| { - if let ScriptToken::String(v) = tp.token { - Some(v) - } else { - None - } - }) - } - - pub fn token_index_to_row_col(&self, tok_index: u32) -> Option<(u32, u32)> { - // first find the real pos - - let char_index = self.tokens[tok_index as usize].pos; - - let mut line = 0; - let mut line_start = 0; - for (i, c) in self.original.chars().enumerate() { - if i >= char_index as usize { - return Some((line as u32, (i - line_start) as u32)); - } - if c == '\n' { - line_start = i + 1; - line += 1; - } - } - None - } - - pub fn dump_tokens(&self, heap: &ScriptHeap) { - for i in 0..self.tokens.len() { - match self.tokens[i].token { - ScriptToken::End => print!("End"), - ScriptToken::StreamEnd => print!("StreamEnd"), - ScriptToken::Identifier(id) => print!("{id}"), - ScriptToken::Operator(id) => print!("{id}"), - ScriptToken::Separator(id) => print!("{id}"), - ScriptToken::OpenCurly => print!("{{"), - ScriptToken::CloseCurly => print!("}}"), - ScriptToken::OpenRound => print!("("), - ScriptToken::CloseRound => print!(")"), - ScriptToken::OpenSquare => print!("["), - ScriptToken::CloseSquare => print!("]"), - ScriptToken::StringUnfinished => print!("\"\".."), - ScriptToken::String(v) => { - let mut s = String::new(); - heap.cast_to_string(v, &mut s); - print!("\"{}\"", s) - } - ScriptToken::U40(v) => print!("{v}"), - ScriptToken::F64(v) => print!("{v}"), - ScriptToken::F32(v) => print!("{v}"), - ScriptToken::I32(v) => print!("{v}"), - ScriptToken::U32(v) => print!("{v}"), - ScriptToken::F16(v) => print!("{v}"), - ScriptToken::Color(v) => print!("{:08x}", v), - ScriptToken::RustValue(v) => print!("#({v})"), - } - print!(" "); - } - print!("\n"); - } - - pub fn pos_to_loc(&self, pos: usize) -> Option { - let mut row = 0; - let mut col = 0; - for (i, c) in self.original.chars().enumerate() { - if c == '\n' { - row += 1; - col = 0; - } else { - col += 1; - } - if i >= pos { - return Some(ScriptLoc { row, col }); - } - } - None - } - - fn emit_rust_value(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - self.temp.clear(); - v - } else { - 0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::RustValue(number), - }); - } - - fn emit_f64(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - // allow the shader compiler to recognise the difference btween 1 and 1. - if !(self.temp.contains('.') || self.temp.contains('e') || self.temp.contains('E')) - && v <= 0xFF_FFFF_FFFFu64 as f64 - { - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::U40(v as u64), - }); - return; - } - self.temp.clear(); - v - } else { - 0.0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::F64(number), - }); - } - - fn emit_f32(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - self.temp.clear(); - v - } else { - 0.0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::F32(number), - }); - } - - fn emit_u32(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - self.temp.clear(); - v - } else { - 0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::U32(number), - }); - } - - fn emit_i32(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - self.temp.clear(); - v - } else { - 0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::I32(number), - }); - } - - fn emit_f16(&mut self) { - let len = self.temp.chars().count(); - let number = if let Ok(v) = self.temp.parse::() { - self.temp.clear(); - v - } else { - 0.0 - }; - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::F16(number), - }); - } - - fn emit_identifier(&mut self) { - let id = match LiveId::from_str_with_lut(&self.temp) { - Err(str) => { - println!( - "--WARNING-- LiveId LUT collision between {} and {}", - self.temp, str - ); - LiveId::from_str(&self.temp) - } - Ok(id) => id, - }; - let len = self.temp.chars().count(); - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::Identifier(id), - }); - } - - fn emit_operator(&mut self) { - if self.temp.len() == 0 { - return; - } - let id = match LiveId::from_str_with_lut(&self.temp) { - Err(str) => { - println!( - "--WARNING-- LiveId LUT collision between {} and {}", - self.temp, str - ); - LiveId::from_str(&self.temp) - } - Ok(id) => id, - }; - let len = self.temp.chars().count(); - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::Operator(id), - }); - } - - fn emit_separator(&mut self, c: char) { - if self.temp.len() != 0 { - panic!() - } - self.temp.push(c); - let id = match LiveId::from_str_with_lut(&self.temp) { - Err(str) => { - println!( - "--WARNING-- LiveId LUT collision between {} and {}", - self.temp, str - ); - LiveId::from_str(&self.temp) - } - Ok(id) => id, - }; - let len = self.temp.chars().count(); - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::Separator(id), - }); - } - - fn emit_color(&mut self) { - let color = match hex_bytes_to_u32(&self.temp.as_bytes()) { - Err(()) => 0xff00ffff, - Ok(color) => color, - }; - let len = self.temp.chars().count(); - self.temp.clear(); - self.tokens.push(ScriptTokenPos { - pos: self.pos - len, - token: ScriptToken::Color(color), - }); - } - - fn emit_token_here(&mut self, token: ScriptToken) { - self.tokens.push(ScriptTokenPos { - pos: self.pos, - token, - }) - } - - fn append_unfinished_string(&mut self, c: char) { - if let Some(ScriptTokenPos { - token: ScriptToken::StringUnfinished, - .. - }) = self.tokens.last_mut() - { - self.unfinished.push(c); - } else { - self.unfinished.clear(); - self.unfinished.push(c); - self.tokens.push(ScriptTokenPos { - pos: self.pos, - token: ScriptToken::StringUnfinished, - }); - } - } - - /// If the last token is `StringUnfinished`, intern the unfinished buffer content - /// via the heap and return it as a ScriptValue. Does NOT modify the token — the - /// tokenizer state remains unchanged for the next `tokenize()` call. - /// Used at incremental parsing boundaries so the parser gets the real partial string. - pub fn intern_unfinished_string(&mut self, heap: &mut ScriptHeap) -> Option { - if let Some(ScriptTokenPos { - token: ScriptToken::StringUnfinished, - .. - }) = self.tokens.last() - { - Some(heap.new_string_from_str(&self.unfinished)) - } else { - None - } - } - - fn finish_string(&mut self, heap: &mut ScriptHeap) { - if let Some(ScriptTokenPos { - token: ScriptToken::StringUnfinished, - .. - }) = self.tokens.last() - { - if let Some(ScriptTokenPos { - token: ScriptToken::StringUnfinished, - pos, - }) = self.tokens.pop() - { - let v = heap.new_string_from_str(&self.unfinished); - self.unfinished.clear(); - self.tokens.push(ScriptTokenPos { - token: ScriptToken::String(v), - pos, - }) - } - } else { - self.tokens.push(ScriptTokenPos { - token: ScriptToken::String(ScriptValue::EMPTY_STRING), - pos: self.pos, - }) - } - } - - pub fn tokenize(&mut self, new_chars: &str, heap: &mut ScriptHeap) -> &[ScriptTokenPos] { - let mut iter = new_chars.chars(); - - fn is_operator(c: char) -> bool { - c == '!' - || c == '^' - || c == '&' - || c == '*' - || c == '+' - || c == '-' - || c == '|' - || c == '?' - || c == ':' - || c == '=' - || c == '@' - || c == '>' - || c == '<' - || c == '.' - || c == '/' - || c == '~' - || c == '%' - } - fn is_separator(c: char) -> bool { - c == ',' || c == ';' - } - fn is_block(c: char) -> Option { - match c { - '{' => Some(ScriptToken::OpenCurly), - '}' => Some(ScriptToken::CloseCurly), - '[' => Some(ScriptToken::OpenSquare), - ']' => Some(ScriptToken::CloseSquare), - '(' => Some(ScriptToken::OpenRound), - ')' => Some(ScriptToken::CloseRound), - _ => None, - } - } - // unfinished string at the end - let start = if let Some(ScriptTokenPos { - token: ScriptToken::StringUnfinished, - .. - }) = self.tokens.last_mut() - { - self.tokens.len() - 1 - } else { - self.tokens.len() - }; - - while let Some(c) = iter.next() { - self.original.push(c); - self.pos += 1; - match self.state { - State::Whitespace => { - if c.is_numeric() { - self.state = State::Number; - self.temp.push(c); - } else if c == '_' || c == '$' || c.is_alphabetic() { - self.state = State::Identifier; - self.temp.push(c); - } else if c == '#' { - self.state = State::Color; - } else if is_separator(c) { - self.emit_separator(c); - } else if is_operator(c) { - self.state = State::Operator; - self.temp.push(c); - } else if c == '"' { - self.state = State::String(true); - } else if c == '\'' { - self.state = State::String(false); - } else if let Some(tok) = is_block(c) { - self.emit_token_here(tok); - } - } - State::Identifier => { - if c == '_' || c == '$' || c.is_alphanumeric() { - self.temp.push(c); - } else if c.is_whitespace() { - self.emit_identifier(); - self.state = State::Whitespace; - } else if is_operator(c) { - self.emit_identifier(); - self.state = State::Operator; - self.temp.push(c); - } else if is_separator(c) { - self.emit_identifier(); - self.emit_separator(c); - self.state = State::Whitespace; - } else if c == '#' { - self.emit_identifier(); - self.state = State::Color; - } else if let Some(tok) = is_block(c) { - self.emit_identifier(); - self.emit_token_here(tok); - self.state = State::Whitespace; - } else if c == '"' { - self.emit_identifier(); - self.state = State::String(true); - } else if c == '\'' { - self.emit_identifier(); - self.state = State::String(false); - } else { - self.emit_identifier(); - self.state = State::Whitespace; - } - } - State::Operator => { - // Helper to check if a string is a valid operator or valid prefix of an operator - fn is_valid_operator(s: &str) -> bool { - matches!( - s, - // Single character operators - "!" | "~" | "+" | "-" | "*" | "/" | "%" | "&" | "|" | "^" | - "<" | ">" | "=" | "." | "?" | ":" | "@" | - // Double character operators - "==" | "!=" | "<=" | ">=" | "&&" | "||" | "|?" | - "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | ":=" | - "<<" | ">>" | ".." | "->" | ".?" | ">:" | "<:" | "^:" | "+:" | "?=" | - "++" | "-:" | "=>" | - "/*" | "//" | - // Triple character operators - "===" | "!==" | "<<=" | ">>=" | "..." - ) - } - - fn could_be_operator_prefix(s: &str) -> bool { - // Check if s could be the start of a valid multi-char operator - matches!( - s, - // Single chars that could become 2-char operators - "!" | // !=, !== - "=" | // ==, === - "<" | // <=, <<, <:, <<= - ">" | // >=, >>, >:, >>= - "&" | // && - "|" | // ||, |?, |= - "+" | // +=, +:, ++ - "-" | // -=, ->, -: - "*" | // *= - "/" | // /=, /*, // - "%" | // %= - "^" | // ^=, ^: - ":" | // := - "." | // .., .?, ... - "?" | // ?= - // Double chars that could become 3-char operators - "==" | // === - "!=" | // !== - "<<" | // <<= - ">>" | // >>= - ".." // ... - ) - } - - // Special case: @( starts a RustValue - if self.temp == "@" && c == '(' { - self.temp.clear(); - self.state = State::RustValue; - continue; - } - - // Handle non-operator characters - emit current operator and transition - if c.is_whitespace() { - self.emit_operator(); - self.state = State::Whitespace; - } else if c.is_numeric() { - // Handle .5 as 0.5 (float literal starting with dot) - if self.temp == "." { - self.temp.push(c); - self.state = State::Number; - } else { - self.emit_operator(); - self.state = State::Number; - self.temp.push(c); - } - } else if is_separator(c) { - self.emit_operator(); - self.emit_separator(c); - self.state = State::Whitespace; - } else if c == '_' || c == '$' || c.is_alphabetic() { - self.emit_operator(); - self.state = State::Identifier; - self.temp.push(c); - } else if c == '#' { - self.emit_operator(); - self.state = State::Color; - } else if c == '"' { - self.emit_operator(); - self.state = State::String(true); - } else if c == '\'' { - self.emit_operator(); - self.state = State::String(false); - } else if let Some(tok) = is_block(c) { - self.emit_operator(); - self.emit_token_here(tok); - self.state = State::Whitespace; - } else if is_operator(c) { - // Try to extend the current operator - let mut extended = self.temp.clone(); - extended.push(c); - - if is_valid_operator(&extended) || could_be_operator_prefix(&extended) { - // Valid extension, keep building - self.temp.push(c); - } else { - // Can't extend - emit current operator and start new one - self.emit_operator(); - self.temp.push(c); - } - } else { - self.emit_operator(); - self.state = State::Whitespace; - } - - // Check for comment start - if self.temp == "/*" { - self.state = State::BlockComment(0); - self.temp.clear(); - } else if self.temp == "//" { - self.state = State::LineComment; - self.temp.clear(); - } - // Emit complete operators that can't be extended - else if is_valid_operator(&self.temp) && !could_be_operator_prefix(&self.temp) - { - self.emit_operator(); - } - } - State::EscapeInString(double) => { - // ok lets see what we have for an escape character sequence - if c == '\\' { - self.append_unfinished_string('\\'); - self.state = State::String(double); - } else if c == '"' { - self.append_unfinished_string('"'); - self.state = State::String(double); - } else if c == '\'' { - self.append_unfinished_string('\''); - self.state = State::String(double); - } else if c == 'r' { - self.append_unfinished_string('\r'); - self.state = State::String(double); - } else if c == 'n' { - self.append_unfinished_string('\n'); - self.state = State::String(double); - } else if c == 't' { - self.append_unfinished_string('\t'); - self.state = State::String(double); - } else if c == '0' { - self.append_unfinished_string('\0'); - self.state = State::String(double); - } else if c == 'x' { - self.state = State::AsciiHexInString(double); - } else if c == 'u' { - self.state = State::UnicodeHexInString(double); - } - } - State::AsciiHexInString(double) => { - self.temp.push(c); - if self.temp.len() == 2 { - if let Ok(v) = i64::from_str_radix(&self.temp, 16) { - self.append_unfinished_string(v as u8 as char); - } - self.temp.clear(); - self.state = State::String(double); - } - } - State::UnicodeHexInString(double) => { - if c == '{' { - self.state = State::UnicodeCurlyInString(double); - } else { - // its kinda unknown how long we need to keep pushing sself - self.temp.push(c); - if self.temp.len() == 4 { - if let Ok(v) = i64::from_str_radix(&self.temp, 16) { - if let Some(v) = char::from_u32(v as u32) { - self.append_unfinished_string(v); - } - } - self.temp.clear(); - self.state = State::String(double); - } - } - } - State::UnicodeCurlyInString(double) => { - if c == '}' { - if let Ok(v) = i64::from_str_radix(&self.temp, 16) { - if let Some(v) = char::from_u32(v as u32) { - self.append_unfinished_string(v); - } - } - self.temp.clear(); - self.state = State::String(double); - } else { - self.temp.push(c); - } - } - State::String(double) => { - // check last token is - if c == '\\' { - // escape char - self.temp.clear(); - self.state = State::EscapeInString(double); - } else if (double && c == '"') || (!double && c == '\'') { - self.finish_string(heap); - self.state = State::Whitespace; - } else { - self.append_unfinished_string(c); - } - } - State::BlockComment(depth) => { - if c == '*' { - // end block comment - self.state = State::MaybeEndBlock(depth); - } - } - State::MaybeEndBlock(depth) => { - if c == '/' { - // end block comment - if depth > 0 { - self.state = State::BlockComment(depth - 1) - } else { - self.state = State::Whitespace; - } - } else { - self.state = State::BlockComment(depth) - } - } - State::LineComment => { - if c == '\n' { - // end line comment - self.state = State::Whitespace; - } - } - State::Number => { - if c.is_numeric() { - self.temp.push(c); - } else if c == '.' && self.temp.chars().last() == Some('.') { - self.temp.pop(); - self.emit_f64(); - self.temp.push('.'); - self.temp.push('.'); - self.emit_operator(); - self.state = State::Whitespace - } else if c == '.' && self.temp.chars().position(|v| v == '.').is_none() { - self.temp.push(c); - } else if (c == 'e' || c == 'E') - && self - .temp - .chars() - .position(|v| v == 'e' || v == 'E') - .is_none() - { - self.temp.push(c); - } else if (c == '+' || c == '-') - && matches!(self.temp.chars().last(), Some('e') | Some('E')) - { - // Handle exponent sign in scientific notation like 1e+20 or 1e-5 - self.temp.push(c); - } else if (c == 'x' || c == 'X') - && self - .temp - .chars() - .position(|v| v == 'x' || v == 'X') - .is_none() - { - self.temp.push(c); - } else if c == 'f' { - self.emit_f32(); - self.state = State::Whitespace - } else if c == 'u' { - self.emit_u32(); - self.state = State::Whitespace - } else if c == 'i' { - self.emit_i32(); - self.state = State::Whitespace - } else if c == 'h' { - self.emit_f16(); - self.state = State::Whitespace - } else if c == '_' { - // Numeric separators stay in the literal. Moving to whitespace here - // left `temp` stale and let a later separator panic. - continue; - } else if c == '$' || c.is_alphabetic() { - self.emit_f64(); - self.state = State::Identifier; - self.temp.push(c); - } else if c == '#' { - self.emit_f64(); - self.state = State::Color; - self.temp.push(c); - } else if is_operator(c) { - self.emit_f64(); - self.state = State::Operator; - self.temp.push(c); - } else if is_separator(c) { - self.emit_f64(); - self.emit_separator(c); - self.state = State::Whitespace; - } else if c == '"' { - self.emit_f64(); - self.state = State::String(true); - } else if c == '\'' { - self.emit_f64(); - self.state = State::String(false); - } else if let Some(tok) = is_block(c) { - self.emit_f64(); - self.emit_token_here(tok); - self.state = State::Whitespace; - } else { - self.emit_f64(); - self.state = State::Whitespace; - } - } - State::RustValue => { - if c >= '0' && c <= '9' { - self.temp.push(c); - } else { - self.emit_rust_value(); - self.state = State::Whitespace - } - } - State::Color => { - if self.temp.len() == 0 && c == '(' { - self.state = State::RustValue - } else if c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' { - self.temp.push(c); - if self.temp.len() == 8 { - self.emit_color(); - self.state = State::Whitespace - } - } else if c == 'x' && self.temp.len() == 0 { // eat first x - } else if c == '_' || c == '$' || c.is_alphabetic() { - self.emit_color(); - self.state = State::Identifier; - self.temp.push(c); - } else if c == '#' { - self.emit_color(); - self.state = State::Color; - self.temp.push(c); - } else if is_operator(c) { - self.emit_color(); - self.state = State::Operator; - self.temp.push(c); - } else if is_separator(c) { - self.emit_color(); - self.emit_separator(c); - self.state = State::Whitespace; - } else if c == '"' { - self.emit_color(); - self.state = State::String(true); - } else if c == '\'' { - self.emit_color(); - self.state = State::String(false); - } else if let Some(tok) = is_block(c) { - self.emit_color(); - self.emit_token_here(tok); - self.state = State::Whitespace; - } else { - self.emit_color(); - self.state = State::Whitespace; - } - } - } - } - &self.tokens[start..self.tokens.len()] - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn unicode_identifier_does_not_underflow_its_token_position() { - let mut heap = ScriptHeap::default(); - let mut tokenizer = ScriptTokenizer::default(); - - tokenizer.tokenize("\u{540d} ", &mut heap); - - assert_eq!(tokenizer.tokens.len(), 1); - } - - #[test] - fn numeric_underscores_stay_in_the_pending_number_until_a_separator() { - let mut heap = ScriptHeap::default(); - let mut tokenizer = ScriptTokenizer::default(); - - tokenizer.tokenize("0_;1_000;1.5_;1e2_;", &mut heap); - - assert_eq!(tokenizer.tokens.len(), 8); - assert_eq!(tokenizer.tokens[0].token.as_u40(), Some(0)); - assert_eq!(tokenizer.tokens[2].token.as_u40(), Some(1_000)); - assert_eq!(tokenizer.tokens[4].token.as_f64(), Some(1.5)); - assert_eq!(tokenizer.tokens[6].token.as_f64(), Some(100.0)); - for separator in [1, 3, 5, 7] { - assert!(matches!( - tokenizer.tokens[separator].token, - ScriptToken::Separator(_) - )); - } - } -} diff --git a/vendor/makepad/platform/script/src/traits.rs b/vendor/makepad/platform/script/src/traits.rs deleted file mode 100644 index cce1f9b..0000000 --- a/vendor/makepad/platform/script/src/traits.rs +++ /dev/null @@ -1,593 +0,0 @@ -use crate::apply::*; -use crate::heap::*; -use crate::value::*; -use crate::vm::*; -use makepad_live_id::*; - -// ============================================================================ -// Script traits -// ============================================================================ - -pub trait ScriptDeriveMarker {} - -pub type ScriptTypeId = std::any::TypeId; - -// sself we implement -pub trait ScriptHook { - // these are the root entrypoints, and they by default dispatch to simpler lifecycle points - fn on_before_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - } - - fn on_before_dispatch( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - _value: ScriptValue, - ) { - match apply { - Apply::New => self.on_before_new_scoped(vm, scope), - // Both LiveEdit (Reload) and request_script_reapply (ScriptReapply) - // fire the reload hooks — `apply.is_reload()` returns true for - // both, and widgets that branch on it expect the broader semantic. - // Widgets that need to differentiate can branch on - // `apply.is_live_edit_reload()` or `apply.is_script_reapply()` - // inside the hook. - Apply::Reload | Apply::ScriptReapply => self.on_before_reload_scoped(vm, scope), - _ => (), - } - } - - fn on_after_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - } - - fn on_after_dispatch( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - _value: ScriptValue, - ) { - match apply { - Apply::New => self.on_after_new_scoped(vm, scope), - Apply::Reload | Apply::ScriptReapply => self.on_after_reload_scoped(vm, scope), - _ => (), - } - self.on_alive() - } - // allows you to provide a custom apply impl, return true to skip generated apply code - fn on_custom_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) -> bool { - false - } - - // implemented by procmacro for reflection into script objects/type cchecking - fn on_type_check(_heap: &ScriptHeap, _value: ScriptValue) -> bool { - false - } - fn on_proto_build(_vm: &mut ScriptVm, _obj: ScriptObject, _props: &mut ScriptTypeProps) {} - fn on_proto_methods(_vm: &mut ScriptVm, _obj: ScriptObject) {} - - // Simple signatured lifecyclehooks - fn on_alive(&self) {} // use this hook to quickly check if your object is alive, useful for debugging - fn on_before_new(&mut self, _vm: &mut ScriptVm) {} - fn on_before_reload(&mut self, _vm: &mut ScriptVm) {} - fn on_after_new(&mut self, _vm: &mut ScriptVm) {} - fn on_after_reload(&mut self, _vm: &mut ScriptVm) {} - - // simple with scope - fn on_before_new_scoped(&mut self, vm: &mut ScriptVm, _scope: &mut Scope) { - self.on_before_new(vm) - } - fn on_before_reload_scoped(&mut self, vm: &mut ScriptVm, _scope: &mut Scope) { - self.on_before_reload(vm) - } - fn on_after_new_scoped(&mut self, vm: &mut ScriptVm, _scope: &mut Scope) { - self.on_after_new(vm) - } - fn on_after_reload_scoped(&mut self, vm: &mut ScriptVm, _scope: &mut Scope) { - self.on_after_reload(vm) - } -} - -pub trait ScriptHookDeref { - fn on_deref_before_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - } - fn on_deref_after_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - } -} - -#[derive(Clone, Copy, Debug)] -pub struct ScriptTypeProp { - pub order: u32, - pub ty: ScriptTypeId, -} - -#[derive(Default, Debug)] -pub struct ScriptTypeProps { - pub props: LiveIdMap, - /// Index marking where Rust instance fields begin in the props list. - /// Fields with order < rust_instance_start are config fields (live fields before #[deref]). - /// Fields with order >= rust_instance_start are instance fields (deref parent fields + child's fields after deref). - /// The shader compiler uses iter_rust_instance_ordered() to process only instance fields. - pub rust_instance_start: u32, -} - -impl ScriptTypeProps { - pub fn insert(&mut self, id: LiveId, ty: ScriptTypeId) { - let order = self.props.len() as u32; - self.props.insert(id, ScriptTypeProp { order, ty }); - } - - /// Mark the current position as where Rust instance fields begin. - /// Called by the derive macro just before processing the #[deref] field. - /// Config fields (live fields before #[deref]) are added to props before this call, - /// then parent fields and child's own fields are added after. - pub fn mark_rust_instance_start(&mut self) { - self.rust_instance_start = self.props.len() as u32; - } - - pub fn iter_ordered(&self) -> impl Iterator + '_ { - let mut ordered: Vec<_> = self.props.iter().map(|(k, v)| (*k, *v)).collect(); - ordered.sort_by_key(|(_, prop)| prop.order); - ordered.into_iter().map(|(id, prop)| (id, prop.ty)) - } - - /// Iterate over props that are part of the Rust instance data. - /// Skips config fields (live fields before #[deref]) and returns instance fields in order: - /// deref parent fields first, then child's own fields after deref. - /// Used by the shader compiler to build the RustInstance struct layout. - pub fn iter_rust_instance_ordered(&self) -> impl Iterator + '_ { - let rust_instance_start = self.rust_instance_start; - let mut ordered: Vec<_> = self - .props - .iter() - .filter(|(_, prop)| prop.order >= rust_instance_start) - .map(|(k, v)| (*k, *v)) - .collect(); - ordered.sort_by_key(|(_, prop)| prop.order); - ordered.into_iter().map(|(id, prop)| (id, prop.ty)) - } -} - -pub struct ScriptTypeObject { - pub(crate) type_id: ScriptTypeId, - pub(crate) check: fn(&ScriptHeap, ScriptValue) -> bool, // Function pointer instead of boxed closure - pub(crate) proto: ScriptValue, - pub(crate) name: Option, -} - -pub struct ScriptTypeCheck { - pub props: ScriptTypeProps, - pub object: Option, - /// If true, this type is a `repr(u32)` enum and should be treated as `u32` in shaders. - pub is_repr_u32_enum: bool, -} - -#[derive(Copy, Clone, Hash, Eq, PartialEq)] -pub struct ScriptTypeIndex(pub(crate) u32); - -// Non-generic helper to reduce monomorphization in script_proto -#[inline(never)] -fn register_type_inner( - vm: &mut ScriptVm, - type_id: ScriptTypeId, - proto: ScriptValue, - props: ScriptTypeProps, - check: fn(&ScriptHeap, ScriptValue) -> bool, - name: Option, - is_repr_u32_enum: bool, -) -> ScriptValue { - let ty_check = ScriptTypeCheck { - object: Some(ScriptTypeObject { - type_id, - proto, - check, - name, - }), - props, - is_repr_u32_enum, - }; - let ty_index = vm.bx.heap.register_type(Some(type_id), ty_check); - if let Some(obj) = proto.as_object() { - vm.bx.heap.set_type(obj, ty_index); - } - proto -} - -// implementation is procmacro generated -pub trait ScriptNew: ScriptApply + ScriptHook -where - Self: 'static, -{ - /// Returns the LiveId name of this type for error messages. - /// Override this in derive macro to provide meaningful type names. - fn script_type_name() -> Option { - None - } - - /// Returns true if this type is a `repr(u32)` enum. - /// Override in derive macro for enums with discriminants. - /// Used by shader compiler to treat the enum as `u32`. - fn is_repr_u32_enum() -> bool { - false - } - - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if ::on_type_check(heap, value) { - return true; - } - if let Some(o) = value.as_object() { - heap.type_matches_id(o, Self::script_type_id_static()) - } else { - false - } - } - - /// Builds a pod struct type from the macro-generated type reflection. - /// This iterates through the ScriptTypeProps in order and generates - /// a ScriptPodTy::Struct with fields matching the struct's layout. - /// Uses iter_rust_instance_ordered() to skip config fields before #[deref]. - fn script_pod(vm: &mut ScriptVm) -> Option - where - Self: Sized, - { - use crate::pod::*; - use makepad_math::{Mat4f, Quat, Vec2f, Vec3f, Vec4f}; - use std::any::TypeId; - - fn align_up(offset: usize, align: usize) -> usize { - if align == 0 { - return offset; - } - let rem = offset % align; - if rem == 0 { - offset - } else { - offset + (align - rem) - } - } - - fn rust_repr_layout_for_type_id( - heap: &ScriptHeap, - type_id: ScriptTypeId, - ) -> Option<(usize, usize)> { - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - if type_id == TypeId::of::() { - return Some((std::mem::size_of::(), std::mem::align_of::())); - } - - let type_check = heap.registered_type(type_id)?; - let mut offset = 0usize; - let mut align = 1usize; - for (_, field_type_id) in type_check.props.iter_rust_instance_ordered() { - let (field_size, field_align) = rust_repr_layout_for_type_id(heap, field_type_id)?; - offset = align_up(offset, field_align); - offset += field_size; - align = align.max(field_align); - } - Some((align_up(offset, align), align)) - } - - // First ensure the proto is built so type reflection is available - Self::script_proto(vm); - - let type_id = Self::script_type_id_static(); - let type_check = vm.bx.heap.registered_type(type_id)?; - - // Build pod fields from the type props - // Use iter_rust_instance_ordered to skip config fields (live fields before #[deref]) - let mut fields = Vec::new(); - let mut ordered_layout = Vec::new(); - - for (field_name, field_type_id) in type_check.props.iter_rust_instance_ordered() { - // Try to get the pod type for this field's type - if let Some(pod_type) = vm - .bx - .heap - .type_id_to_pod_type(field_type_id, &vm.bx.code.builtins.pod) - { - let pod_type_data = vm.bx.heap.pod_type_ref(pod_type); - - fields.push(ScriptPodField { - name: field_name, - ty: ScriptPodTypeInline { - self_ref: pod_type, - data: pod_type_data.clone(), - }, - default: pod_type_data.default, - }); - ordered_layout.push((field_name, field_type_id, pod_type_data.ty.clone())); - } else { - // Field type doesn't have a corresponding pod type - return None; - } - } - - // Create the pod type using the centralized layout calculation - let pod_obj = vm.bx.heap.new_with_proto(id!(pod_struct).into()); - vm.bx.heap.set_object_storage_vec2(pod_obj); - vm.bx.heap.set_notproto(pod_obj); - - let mut rust_offset = 0usize; - let mut shader_offset = 0usize; - for (field_name, field_type_id, shader_ty) in &ordered_layout { - let (rust_size, rust_align) = - rust_repr_layout_for_type_id(&vm.bx.heap, *field_type_id)?; - rust_offset = align_up(rust_offset, rust_align); - shader_offset = align_up(shader_offset, shader_ty.align_of()); - assert!( - rust_offset == shader_offset, - "Rust POD field offset mismatch for {}.{}: Rust repr(C) offset is {}, shader POD offset is {}. Add explicit padding fields for std140 compatibility.", - std::any::type_name::(), - field_name, - rust_offset, - shader_offset - ); - rust_offset += rust_size; - shader_offset += shader_ty.size_of(); - } - - let pod_ty = ScriptPodTy::new_struct(fields); - let rust_size = rust_repr_layout_for_type_id(&vm.bx.heap, type_id)?.0; - let pod_size = pod_ty.size_of(); - assert!( - rust_size == pod_size, - "Rust POD size mismatch for {}: Rust repr(C) size is {}, shader POD size is {}. Add explicit padding fields for std140 compatibility.", - std::any::type_name::(), - rust_size, - pod_size - ); - - let pt = vm.bx.heap.new_pod_type(pod_obj, None, pod_ty, NIL); - vm.bx.heap.set_object_pod_type(pod_obj, pt); - vm.bx.heap.freeze(pod_obj); - - Some(pt) - } - - fn script_default(vm: &mut ScriptVm) -> ScriptValue - where - Self: Sized, - { - Self::script_proto(vm); - Self::script_new(vm).script_to_value(vm) - } - - fn script_reload_default(vm: &mut ScriptVm) -> ScriptValue - where - Self: Sized, - { - let type_id = Self::script_type_id_static(); - if let Some(default_obj) = vm.bx.heap.type_default_for_id(type_id) { - default_obj.into() - } else { - NIL - } - } - - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_new(vm: &mut ScriptVm) -> Self; - - fn script_new_with_default(vm: &mut ScriptVm) -> Self - where - Self: Sized, - { - let type_id = Self::script_type_id_static(); - if let Some(default_obj) = vm.bx.heap.type_default_for_id(type_id) { - Self::script_from_value(vm, default_obj.into()) - } else { - Self::script_new(vm) - } - } - - fn from_script_mod(vm: &mut ScriptVm, f: fn(&mut ScriptVm) -> ScriptValue) -> Self - where - Self: Sized, - { - let value = f(vm); - if value.is_nil() { - panic!( - "script_mod! returned nil — the script block must end with an expression \ - that evaluates to the app value (e.g. add `app` as the last line after \ - `let app = startup() do ...{{ }}`)." - ); - } - Self::script_from_value(vm, value) - } - - // default impls - - fn script_from_value(vm: &mut ScriptVm, value: ScriptValue) -> Self - where - Self: Sized, - { - let mut s = Self::script_new(vm); - s.script_apply(vm, &Apply::New, &mut Scope::empty(), value); - s - } - - fn script_from_value_scoped(vm: &mut ScriptVm, scope: &mut Scope, value: ScriptValue) -> Self - where - Self: Sized, - { - let mut s = Self::script_new(vm); - s.script_apply(vm, &Apply::New, scope, value); - s - } - - fn script_proto(vm: &mut ScriptVm) -> ScriptValue { - let type_id = Self::script_type_id_static(); - if let Some(check) = vm.bx.heap.registered_type(type_id) { - return check.object.as_ref().unwrap().proto; - } - let mut props = ScriptTypeProps::default(); - let proto = Self::script_proto_build(vm, &mut props); - // Use non-generic helper for registration to reduce monomorphization - register_type_inner( - vm, - type_id, - proto, - props, - Self::script_type_check, - Self::script_type_name(), - Self::is_repr_u32_enum(), - ) - } - - fn script_proto_build(vm: &mut ScriptVm, props: &mut ScriptTypeProps) -> ScriptValue { - let proto = vm.bx.heap.new_object(); - // build prototype here - Self::script_proto_props(vm, proto, props); - Self::on_proto_build(vm, proto, props); - Self::on_proto_methods(vm, proto); - proto.into() - } - - fn script_proto_props(_vm: &mut ScriptVm, _object: ScriptObject, _props: &mut ScriptTypeProps) { - } - - fn script_api(vm: &mut ScriptVm) -> ScriptValue { - let val = Self::script_proto(vm); - vm.bx.heap.freeze_api(val.into()); - val - } - - fn script_component(vm: &mut ScriptVm) -> ScriptValue { - let val = Self::script_proto(vm); - vm.bx.heap.freeze_component(val.into()); - val - } - - fn script_shader(vm: &mut ScriptVm) -> ScriptValue { - let val = Self::script_proto(vm); - vm.bx.heap.freeze_shader(val.into()); - val - } - - fn script_ext(vm: &mut ScriptVm) -> ScriptValue { - let val = Self::script_proto(vm); - vm.bx.heap.freeze_ext(val.into()); - val - } - - fn script_enum_lookup_variant(vm: &mut ScriptVm, variant: LiveId) -> ScriptValue { - let rt = vm - .bx - .heap - .registered_type(Self::script_type_id_static()) - .unwrap(); - let obj = rt.object.as_ref().unwrap().proto.into(); - vm.bx - .heap - .value(obj, variant.into(), vm.bx.threads.cur_ref().trap.pass()) - } -} - -pub trait ScriptApply { - fn script_type_id(&self) -> ScriptTypeId - where - Self: 'static, - { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) { - } - fn script_to_value(&self, _vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_to_value_props(&self, _vm: &mut ScriptVm, _obj: ScriptObject) {} - fn script_source(&self) -> ScriptObject { - ScriptObject::ZERO - } - - /// Evaluates a ScriptMod and applies the result to self. - /// The ScriptMod is deduplicated by file/line/column so calling this repeatedly - /// with the same source location won't create multiple code blocks. - /// The script code should be wrapped as `__script_source__{...}` and this method - /// sets `__script_source__` on the scope to `self.script_source()` before evaluation. - fn script_apply_eval(&mut self, vm: &mut ScriptVm, script_mod: ScriptMod) { - let source = self.script_source(); - let value = vm.eval_with_source(script_mod, source); - self.script_apply(vm, &Apply::Eval, &mut Scope::default(), value); - } -} - -pub trait ScriptApplyDefault { - fn script_apply_default( - &mut self, - _vm: &mut ScriptVm, - _apply: &Apply, - _scope: &mut Scope, - _value: ScriptValue, - ) -> Option { - None - } -} - -pub trait ScriptReset { - fn script_reset(&mut self, vm: &mut ScriptVm, apply: &Apply, value: ScriptValue); -} diff --git a/vendor/makepad/platform/script/src/trap.rs b/vendor/makepad/platform/script/src/trap.rs deleted file mode 100644 index e7b91cb..0000000 --- a/vendor/makepad/platform/script/src/trap.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::makepad_script_derive::*; -use crate::value::*; -use std::cell::RefCell; -use std::collections::VecDeque; - -#[derive(Debug, Clone)] -pub struct ScriptError { - pub message: String, - pub origin_file: String, - pub origin_line: u32, - pub value: ScriptValue, -} - -#[derive(Debug, Clone, Copy)] -pub enum ScriptTrapOn { - Pause, - TimeBudgetYield, - Return(ScriptValue), - Bail(ScriptValue), -} -use std::cell::Cell; -#[derive(Default, Debug)] -pub struct ScriptTrapInner { - pub(crate) err: RefCell>, - pub(crate) on: Cell>, - pub ip: ScriptIp, -} - -#[derive(Clone, Copy)] -pub enum ScriptTrap<'a> { - NoTrap, - Inner(&'a ScriptTrapInner), -} - -pub use ScriptTrap::NoTrap; - -impl<'a> ScriptTrap<'a> { - pub fn pass(self) -> Self { - self - } -} - -impl ScriptTrapInner { - pub fn pass<'a>(&'a self) -> ScriptTrap<'a> { - ScriptTrap::Inner(self) - } -} - -impl ScriptTrapInner { - pub fn push_err( - &self, - value: ScriptValue, - message: String, - origin_file: String, - origin_line: u32, - ) -> ScriptValue { - self.err.borrow_mut().push_back(ScriptError { - value, - message, - origin_file, - origin_line, - }); - value - } - pub fn ip(&self) -> u32 { - self.ip.index - } - pub fn goto(&mut self, wh: u32) { - self.ip.index = wh; - } - pub fn goto_rel(&mut self, wh: u32) { - self.ip.index += wh; - } - #[inline] - pub fn goto_next(&mut self) { - self.ip.index += 1; - } -} - -// Consolidated error macros (19 total, down from 56) -script_err_gen!(script_err_not_found); // lookup failures -script_err_gen!(script_err_type_mismatch); // wrong type for operation -script_err_gen!(script_err_wrong_value); // expected different kind -script_err_gen!(script_err_out_of_bounds); // index/bounds errors -script_err_gen!(script_err_immutable); // cannot modify -script_err_gen!(script_err_stack); // stack errors -script_err_gen!(script_err_invalid_args); // argument errors -script_err_gen!(script_err_not_allowed); // operation not allowed -script_err_gen!(script_err_inconsistent); // types don't match across branches -script_err_gen!(script_err_not_impl); // not implemented -script_err_gen!(script_err_unexpected); // catch-all -script_err_gen!(script_err_assert_fail); // assertions -script_err_gen!(script_err_user); // user-generated -script_err_gen!(script_err_pod); // all pod errors -script_err_gen!(script_err_shader); // all shader errors -script_err_gen!(script_err_unknown_type); // type not registered -script_err_gen!(script_err_duplicate); // key already exists -script_err_gen!(script_err_io); // file system, child process -script_err_gen!(script_err_limit); // resource limits diff --git a/vendor/makepad/platform/script/src/value.rs b/vendor/makepad/platform/script/src/value.rs deleted file mode 100644 index f302107..0000000 --- a/vendor/makepad/platform/script/src/value.rs +++ /dev/null @@ -1,1635 +0,0 @@ -use crate::gen_index::GenRef; -use crate::makepad_live_id::*; -use crate::opcode::*; -use std::fmt; - -#[derive(PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] -pub struct ScriptValue(u64); - -pub const NIL: ScriptValue = ScriptValue::NIL; -pub const TRUE: ScriptValue = ScriptValue::TRUE; -pub const FALSE: ScriptValue = ScriptValue::FALSE; - -impl Default for ScriptValue { - fn default() -> Self { - Self::NIL - } -} - -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct ScriptIp { - pub body: u16, - pub index: u32, -} - -impl ScriptIp { - pub const fn from_u40(value: u64) -> Self { - Self { - body: ((value >> 28) & 0xFFF) as u16, - index: ((value) & 0xFFF_FFFF) as u32, - } - } - pub const fn to_u40(&self) -> u64 { - ((self.body as u64) << 28) | self.index as u64 - } -} - -/// Generation type for use-after-free detection. -/// When check_gen feature is enabled: 8 bits gives us 256 generations per slot before wraparound. -/// When disabled: zero-sized type that compiles away. -#[cfg(feature = "check_gen")] -pub type Generation = u8; -#[cfg(not(feature = "check_gen"))] -pub type Generation = (); - -/// Default generation value for new allocations -#[cfg(feature = "check_gen")] -pub const GENERATION_ZERO: Generation = 0; -#[cfg(not(feature = "check_gen"))] -pub const GENERATION_ZERO: Generation = (); - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptPod { - pub(crate) index: u32, - #[cfg(feature = "check_gen")] - pub(crate) generation: Generation, -} - -impl ScriptPod { - #[cfg(feature = "check_gen")] - pub const fn new(index: u32, generation: Generation) -> Self { - Self { index, generation } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(index: u32, _generation: Generation) -> Self { - Self { index } - } - pub fn index(&self) -> u32 { - self.index - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -impl From for ScriptValue { - fn from(v: ScriptPod) -> Self { - ScriptValue::from_pod(v) - } -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptPodType { - pub(crate) index: u32, -} - -impl ScriptPodType { - pub const VOID: ScriptPodType = ScriptPodType { index: 0 }; -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptObject { - pub(crate) index: u32, - #[cfg(feature = "check_gen")] - pub(crate) generation: Generation, -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptArray { - pub(crate) index: u32, - #[cfg(feature = "check_gen")] - pub(crate) generation: Generation, -} - -impl ScriptObject { - #[cfg(feature = "check_gen")] - pub const ZERO: ScriptObject = ScriptObject { - index: 0, - generation: 0, - }; - #[cfg(not(feature = "check_gen"))] - pub const ZERO: ScriptObject = ScriptObject { index: 0 }; - #[cfg(feature = "check_gen")] - pub const fn new(index: u32, generation: Generation) -> Self { - Self { index, generation } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(index: u32, _generation: Generation) -> Self { - Self { index } - } - pub fn index(&self) -> u32 { - self.index - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -impl ScriptArray { - #[cfg(feature = "check_gen")] - pub const fn new(index: u32, generation: Generation) -> Self { - Self { index, generation } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(index: u32, _generation: Generation) -> Self { - Self { index } - } - pub fn index(&self) -> u32 { - self.index - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -// GenRef implementations for use with GenVec -impl GenRef for ScriptObject { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self::new(index, generation) - } -} - -impl GenRef for ScriptArray { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self::new(index, generation) - } -} - -impl GenRef for ScriptPod { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self::new(index, generation) - } -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptHandleType(pub(crate) u8); - -impl ScriptHandleType { - pub fn to_redux(&self) -> ScriptTypeRedux { - ScriptTypeRedux(ScriptValueType::REDUX_HANDLE_FIRST.0 + self.0) - } -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptTypeRedux(u8); - -impl ScriptTypeRedux { - pub(crate) fn to_index(&self) -> usize { - self.0 as usize - } - - pub const fn name(&self) -> &'static str { - match self.0 { - 0 => "number", - 1 => "nan", - 7 => "bool", - 8 => "nil", - 9 => "color", - 10 => "object", - 11 => "array", - 12 => "pod", - 13 => "pod_type", - 14 => "regex", - 15 => "opcode", - 16 => "string", - 17 => "error", - 18 => "id", - v if v >= ScriptValueType::REDUX_HANDLE_FIRST.0 => "handle", - _ => "unknown", - } - } -} - -impl fmt::Display for ScriptTypeRedux { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0 >= ScriptValueType::REDUX_HANDLE_FIRST.0 { - write!( - f, - "{}({})", - self.name(), - self.0 - ScriptValueType::REDUX_HANDLE_FIRST.0 - ) - } else if self.name() == "unknown" { - write!(f, "unknown({})", self.0) - } else { - write!(f, "{}", self.name()) - } - } -} - -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptHandle { - pub(crate) ty: ScriptHandleType, - pub(crate) index: u32, - #[cfg(feature = "check_gen")] - pub(crate) generation: Generation, -} - -impl ScriptHandle { - #[cfg(feature = "check_gen")] - pub const ZERO: ScriptHandle = ScriptHandle { - ty: ScriptHandleType(0), - index: 0, - generation: 0, - }; - #[cfg(not(feature = "check_gen"))] - pub const ZERO: ScriptHandle = ScriptHandle { - ty: ScriptHandleType(0), - index: 0, - }; - #[cfg(feature = "check_gen")] - pub const fn new(ty: ScriptHandleType, index: u32, generation: Generation) -> Self { - Self { - ty, - index, - generation, - } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(ty: ScriptHandleType, index: u32, _generation: Generation) -> Self { - Self { ty, index } - } - pub fn index(&self) -> u32 { - self.index - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -// Note: ScriptHandle has a `ty` field so GenRef needs special handling -// We implement it but the `new` won't set ty - callers need to handle that -impl GenRef for ScriptHandle { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[cfg(feature = "check_gen")] - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self { - ty: ScriptHandleType(0), - index, - generation, - } - } - #[cfg(not(feature = "check_gen"))] - #[inline] - fn new(index: u32, _generation: Generation) -> Self { - Self { - ty: ScriptHandleType(0), - index, - } - } -} - -impl From for ScriptValue { - fn from(v: ScriptObject) -> Self { - ScriptValue::from_object(v) - } -} - -impl From for ScriptValue { - fn from(v: ScriptArray) -> Self { - ScriptValue::from_array(v) - } -} - -impl From for ScriptObject { - fn from(v: ScriptValue) -> Self { - if let Some(obj) = v.as_object() { - obj - } else { - ScriptObject::ZERO - } - } -} - -impl From for ScriptValue { - fn from(v: ScriptHandle) -> Self { - ScriptValue::from_handle(v) - } -} - -impl From for ScriptValue { - fn from(v: ScriptPodType) -> Self { - ScriptValue::from_pod_type(v) - } -} - -impl From for ScriptHandle { - fn from(v: ScriptValue) -> Self { - if let Some(obj) = v.as_handle() { - obj - } else { - ScriptHandle::ZERO - } - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ScriptRegex { - pub(crate) index: u32, - #[cfg(feature = "check_gen")] - pub(crate) generation: Generation, -} - -impl ScriptRegex { - #[cfg(feature = "check_gen")] - pub const fn new(index: u32, generation: Generation) -> Self { - Self { index, generation } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(index: u32, _generation: Generation) -> Self { - Self { index } - } - pub fn index(&self) -> u32 { - self.index - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -impl GenRef for ScriptRegex { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self::new(index, generation) - } -} - -impl From for ScriptValue { - fn from(v: ScriptRegex) -> Self { - ScriptValue::from_regex(v) - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct ScriptString { - pub index: u32, - #[cfg(feature = "check_gen")] - pub generation: Generation, -} - -impl ScriptString { - #[cfg(feature = "check_gen")] - pub const fn new(index: u32, generation: Generation) -> Self { - Self { index, generation } - } - #[cfg(not(feature = "check_gen"))] - pub const fn new(index: u32, _generation: Generation) -> Self { - Self { index } - } - #[cfg(feature = "check_gen")] - pub fn generation(&self) -> Generation { - self.generation - } - #[cfg(not(feature = "check_gen"))] - pub fn generation(&self) -> Generation { - () - } -} - -impl GenRef for ScriptString { - #[inline] - fn index(&self) -> u32 { - self.index - } - #[inline] - fn generation(&self) -> Generation { - self.generation() - } - #[inline] - fn new(index: u32, generation: Generation) -> Self { - Self::new(index, generation) - } -} - -impl From for ScriptValue { - fn from(v: ScriptString) -> Self { - ScriptValue::from_string(v) - } -} - -impl From for ScriptValue { - fn from(v: f64) -> Self { - ScriptValue::from_f64(v) - } -} - -impl From for f64 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: u32) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for u32 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: i32) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for i32 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: u16) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for u16 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: u8) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for u8 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: f32) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for f32 { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: usize) -> Self { - ScriptValue::from_f64(v as f64) - } -} - -impl From for usize { - fn from(v: ScriptValue) -> Self { - v.as_f64().unwrap_or(0.0) as _ - } -} - -impl From for ScriptValue { - fn from(v: bool) -> Self { - ScriptValue::from_bool(v) - } -} - -impl From for ScriptValue { - fn from(v: LiveId) -> Self { - ScriptValue::from_id(v) - } -} - -impl From<&LiveId> for ScriptValue { - fn from(v: &LiveId) -> Self { - ScriptValue::from_id(*v) - } -} - -impl From for ScriptValue { - fn from(v: Opcode) -> Self { - ScriptValue::from_opcode(v) - } -} -// NaN box value - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct ValueError { - pub ty: ScriptValueType, - pub ip: ScriptIp, -} - -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct ScriptValueType(u8); - -impl ScriptValueType { - pub const F64: Self = Self(0); - pub const NAN: Self = Self(1); - pub const F32: Self = Self(2); - pub const F16: Self = Self(3); - pub const U32: Self = Self(4); - pub const I32: Self = Self(5); - pub const U40: Self = Self(6); - pub const BOOL: Self = Self(7); - pub const NIL: Self = Self(8); - pub const COLOR: Self = Self(9); - pub const OBJECT: Self = Self(10); - pub const ARRAY: Self = Self(11); - pub const POD_TYPE: Self = Self(12); - pub const POD: Self = Self(13); - pub const REGEX: Self = Self(14); - pub const OPCODE: Self = Self(15); - pub const STRING: Self = Self(16); - pub const ERROR: Self = Self(17); - - pub const REDUX_MARKER: Self = Self(18); - - pub const INLINE_STRING_0: Self = Self(18); - pub const INLINE_STRING_1: Self = Self(19); - pub const INLINE_STRING_2: Self = Self(20); - pub const INLINE_STRING_3: Self = Self(21); - pub const INLINE_STRING_4: Self = Self(22); - pub const INLINE_STRING_5: Self = Self(23); - pub const INLINE_STRING_END: Self = Self(24); - - pub const ERR_FIRST: Self = Self(24); - // Consolidated error types (19 total, down from 56) - pub const ERR_NOT_FOUND: Self = Self(Self::ERR_FIRST.0 + 0); // lookup failures (property, field, variable, name, index) - pub const ERR_TYPE_MISMATCH: Self = Self(Self::ERR_FIRST.0 + 1); // wrong type for operation - pub const ERR_WRONG_VALUE: Self = Self(Self::ERR_FIRST.0 + 2); // expected different kind (not object/fn/array/proto) - pub const ERR_OUT_OF_BOUNDS: Self = Self(Self::ERR_FIRST.0 + 3); // index/bounds errors - pub const ERR_IMMUTABLE: Self = Self(Self::ERR_FIRST.0 + 4); // cannot modify (frozen, not assignable, let) - pub const ERR_STACK: Self = Self(Self::ERR_FIRST.0 + 5); // stack underflow/overflow - pub const ERR_INVALID_ARGS: Self = Self(Self::ERR_FIRST.0 + 6); // argument count/format errors - pub const ERR_NOT_ALLOWED: Self = Self(Self::ERR_FIRST.0 + 7); // operation not allowed in context - pub const ERR_INCONSISTENT: Self = Self(Self::ERR_FIRST.0 + 8); // types/names don't match across branches - pub const ERR_NOT_IMPL: Self = Self(Self::ERR_FIRST.0 + 9); // not implemented - pub const ERR_UNEXPECTED: Self = Self(Self::ERR_FIRST.0 + 10); // catch-all - pub const ERR_ASSERT_FAIL: Self = Self(Self::ERR_FIRST.0 + 11); // assertions - pub const ERR_USER: Self = Self(Self::ERR_FIRST.0 + 12); // user-generated - pub const ERR_POD: Self = Self(Self::ERR_FIRST.0 + 13); // all pod errors - pub const ERR_SHADER: Self = Self(Self::ERR_FIRST.0 + 14); // all shader errors - pub const ERR_UNKNOWN_TYPE: Self = Self(Self::ERR_FIRST.0 + 15); // type not registered, unknown variant - pub const ERR_DUPLICATE: Self = Self(Self::ERR_FIRST.0 + 16); // key already exists - pub const ERR_IO: Self = Self(Self::ERR_FIRST.0 + 17); // file system, child process - pub const ERR_LIMIT: Self = Self(Self::ERR_FIRST.0 + 18); // resource limits - pub const ERR_LAST: Self = Self(Self::ERR_FIRST.0 + 19); - - pub const HANDLE_FIRST: Self = Self(0x50); - pub const HANDLE_LAST: Self = Self(0x7F); - pub const REDUX_HANDLE_MAX: u8 = Self::HANDLE_LAST.0 - Self::HANDLE_FIRST.0; - pub const ID: Self = Self(0x80); - - pub const REDUX_NUMBER: ScriptTypeRedux = ScriptTypeRedux(0); - pub const REDUX_NAN: ScriptTypeRedux = ScriptTypeRedux(1); - pub const REDUX_BOOL: ScriptTypeRedux = ScriptTypeRedux(7); - pub const REDUX_NIL: ScriptTypeRedux = ScriptTypeRedux(8); - pub const REDUX_COLOR: ScriptTypeRedux = ScriptTypeRedux(9); - pub const REDUX_OBJECT: ScriptTypeRedux = ScriptTypeRedux(10); - pub const REDUX_ARRAY: ScriptTypeRedux = ScriptTypeRedux(11); - pub const REDUX_POD: ScriptTypeRedux = ScriptTypeRedux(12); - pub const REDUX_POD_TYPE: ScriptTypeRedux = ScriptTypeRedux(13); - pub const REDUX_REGEX: ScriptTypeRedux = ScriptTypeRedux(14); - pub const REDUX_OPCODE: ScriptTypeRedux = ScriptTypeRedux(15); - pub const REDUX_STRING: ScriptTypeRedux = ScriptTypeRedux(16); - pub const REDUX_ERR: ScriptTypeRedux = ScriptTypeRedux(17); - pub const REDUX_ID: ScriptTypeRedux = ScriptTypeRedux(18); - pub const REDUX_HANDLE_FIRST: ScriptTypeRedux = ScriptTypeRedux(19); - - pub const fn to_u64(&self) -> u64 { - ((self.0 as u64) << 40) | 0xFFFF_0000_0000_0000 - } - pub const fn from_u64(val: u64) -> Self { - let val = ((val >> 40) & 0xff) as u8; - if val > Self::ID.0 { - return Self::ID; - } - Self(val) - } - - pub const fn to_redux(&self) -> ScriptTypeRedux { - if self.0 >= Self::REDUX_MARKER.0 { - if self.0 >= Self::ID.0 { - return Self::REDUX_ID; - } else if self.0 >= Self::HANDLE_FIRST.0 { - ScriptTypeRedux(Self::REDUX_HANDLE_FIRST.0 + (self.0 - Self::HANDLE_FIRST.0)) - } else if self.0 >= Self::ERR_FIRST.0 { - Self::REDUX_ERR - } else { - Self::REDUX_STRING - } - } else { - ScriptTypeRedux(self.0) - } - } -} - -impl fmt::Debug for ScriptValueType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for ScriptValueType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - // Numeric types - Self::F64 => write!(f, "f64"), - Self::F32 => write!(f, "f32"), - Self::U40 => write!(f, "u40"), - Self::U32 => write!(f, "u32"), - Self::I32 => write!(f, "i32"), - Self::F16 => write!(f, "f16"), - Self::NAN => write!(f, "nan"), - // Basic types - Self::BOOL => write!(f, "bool"), - Self::NIL => write!(f, "nil"), - Self::COLOR => write!(f, "color"), - Self::STRING => write!(f, "string"), - Self::OBJECT => write!(f, "object"), - Self::ARRAY => write!(f, "array"), - Self::POD => write!(f, "pod"), - Self::POD_TYPE => write!(f, "type"), - Self::REGEX => write!(f, "regex"), - Self::OPCODE => write!(f, "opcode"), - // Inline strings all display as "string" - Self::INLINE_STRING_0 - | Self::INLINE_STRING_1 - | Self::INLINE_STRING_2 - | Self::INLINE_STRING_3 - | Self::INLINE_STRING_4 - | Self::INLINE_STRING_5 => write!(f, "string"), - // Consolidated error types (19 total) - Self::ERR_NOT_FOUND => write!(f, "NotFound"), - Self::ERR_TYPE_MISMATCH => write!(f, "TypeMismatch"), - Self::ERR_WRONG_VALUE => write!(f, "WrongValue"), - Self::ERR_OUT_OF_BOUNDS => write!(f, "OutOfBounds"), - Self::ERR_IMMUTABLE => write!(f, "Immutable"), - Self::ERR_STACK => write!(f, "StackError"), - Self::ERR_INVALID_ARGS => write!(f, "InvalidArgs"), - Self::ERR_NOT_ALLOWED => write!(f, "NotAllowed"), - Self::ERR_INCONSISTENT => write!(f, "Inconsistent"), - Self::ERR_NOT_IMPL => write!(f, "NotImplemented"), - Self::ERR_UNEXPECTED => write!(f, "Unexpected"), - Self::ERR_ASSERT_FAIL => write!(f, "AssertFailure"), - Self::ERR_USER => write!(f, "UserGenerated"), - Self::ERR_POD => write!(f, "PodError"), - Self::ERR_SHADER => write!(f, "ShaderError"), - Self::ERR_UNKNOWN_TYPE => write!(f, "UnknownType"), - Self::ERR_DUPLICATE => write!(f, "Duplicate"), - Self::ERR_IO => write!(f, "IoError"), - Self::ERR_LIMIT => write!(f, "LimitExceeded"), - x if x.0 >= Self::ID.0 => write!(f, "id"), - x if x.0 >= Self::HANDLE_FIRST.0 => write!(f, "handle({})", x.0 - Self::HANDLE_FIRST.0), - _ => write!(f, "ScriptValueType?"), - } - } -} - -pub trait IdExt { - fn escape(&self) -> ScriptValue; -} - -impl IdExt for LiveId { - fn escape(&self) -> ScriptValue { - ScriptValue::from_escaped_id(*self) - } -} - -macro_rules! err_fn { - ($name:ident, $cnst:ident) => { - pub const fn $name(ip: ScriptIp) -> Self { - Self(ScriptValueType::$cnst.to_u64() | ip.to_u40()) - } - }; -} -impl ScriptValue { - pub const TYPE_MASK: u64 = 0xFFFF_FF00_0000_0000; - - pub const TYPE_TRACED_NAN_MAX: u64 = ScriptValueType::NAN.to_u64() | 0xFF_FFFF_FFFF; - pub const NAN: ScriptValue = ScriptValue(Self::TYPE_NAN); - - pub const TYPE_NAN: u64 = ScriptValueType::NAN.to_u64(); - pub const TYPE_F32: u64 = ScriptValueType::F32.to_u64(); - pub const TYPE_F16: u64 = ScriptValueType::F16.to_u64(); - pub const TYPE_U32: u64 = ScriptValueType::U32.to_u64(); - pub const TYPE_I32: u64 = ScriptValueType::I32.to_u64(); - pub const TYPE_U40: u64 = ScriptValueType::U40.to_u64(); - - pub const TYPE_NUMBER_MAX: u64 = ScriptValueType::U40.to_u64() | 0xFF_FFFF_FFFF; - - pub const TYPE_BOOL: u64 = ScriptValueType::BOOL.to_u64(); - pub const FALSE: ScriptValue = ScriptValue(Self::TYPE_BOOL | 0x0000_0000); - pub const TRUE: ScriptValue = ScriptValue(Self::TYPE_BOOL | 0x0000_0001); - pub const EMPTY_STRING: ScriptValue = ScriptValue(Self::TYPE_INLINE_STRING_0); - pub const TYPE_NIL: u64 = ScriptValueType::NIL.to_u64(); - pub const NIL: ScriptValue = ScriptValue(Self::TYPE_NIL); - pub const OBJECT_ZERO: ScriptValue = ScriptValue::from_object(ScriptObject::ZERO); - pub const TYPE_COLOR: u64 = ScriptValueType::COLOR.to_u64(); - pub const TYPE_STRING: u64 = ScriptValueType::STRING.to_u64(); - pub const TYPE_OBJECT: u64 = ScriptValueType::OBJECT.to_u64(); - pub const TYPE_ARRAY: u64 = ScriptValueType::ARRAY.to_u64(); - pub const TYPE_POD: u64 = ScriptValueType::POD.to_u64(); - pub const TYPE_POD_TYPE: u64 = ScriptValueType::POD_TYPE.to_u64(); - pub const TYPE_REGEX: u64 = ScriptValueType::REGEX.to_u64(); - - pub const TYPE_INLINE_STRING_0: u64 = ScriptValueType::INLINE_STRING_0.to_u64(); - pub const TYPE_INLINE_STRING_1: u64 = ScriptValueType::INLINE_STRING_1.to_u64(); - pub const TYPE_INLINE_STRING_2: u64 = ScriptValueType::INLINE_STRING_2.to_u64(); - pub const TYPE_INLINE_STRING_3: u64 = ScriptValueType::INLINE_STRING_3.to_u64(); - pub const TYPE_INLINE_STRING_4: u64 = ScriptValueType::INLINE_STRING_4.to_u64(); - pub const TYPE_INLINE_STRING_5: u64 = ScriptValueType::INLINE_STRING_5.to_u64(); - pub const TYPE_INLINE_STRING_END: u64 = ScriptValueType::INLINE_STRING_END.to_u64(); - - pub const TYPE_HANDLE_FIRST: u64 = ScriptValueType::HANDLE_FIRST.to_u64(); - pub const TYPE_HANDLE_LAST: u64 = ScriptValueType::HANDLE_LAST.to_u64(); - - pub const TYPE_ID: u64 = ScriptValueType::ID.to_u64(); - - pub const ESCAPED_ID: u64 = 0x0000_4000_0000_0000; - - pub const fn value_type(&self) -> ScriptValueType { - if self.is_non_nan_number() { - return ScriptValueType::F64; - } - ScriptValueType::from_u64(self.0 & Self::TYPE_MASK) - } - - // Errors - - // Consolidated error functions (19 total, down from 56) - err_fn!(script_err_not_found, ERR_NOT_FOUND); // lookup failures - err_fn!(script_err_type_mismatch, ERR_TYPE_MISMATCH); // wrong type for operation - err_fn!(script_err_wrong_value, ERR_WRONG_VALUE); // expected different kind - err_fn!(script_err_out_of_bounds, ERR_OUT_OF_BOUNDS); // index/bounds errors - err_fn!(script_err_immutable, ERR_IMMUTABLE); // cannot modify - err_fn!(script_err_stack, ERR_STACK); // stack errors - err_fn!(script_err_invalid_args, ERR_INVALID_ARGS); // argument errors - err_fn!(script_err_not_allowed, ERR_NOT_ALLOWED); // operation not allowed - err_fn!(script_err_inconsistent, ERR_INCONSISTENT); // types don't match across branches - err_fn!(script_err_not_impl, ERR_NOT_IMPL); // not implemented - err_fn!(script_err_unexpected, ERR_UNEXPECTED); // catch-all - err_fn!(script_err_assert_fail, ERR_ASSERT_FAIL); // assertions - err_fn!(script_err_user, ERR_USER); // user-generated - err_fn!(script_err_pod, ERR_POD); // all pod errors - err_fn!(script_err_shader, ERR_SHADER); // all shader errors - err_fn!(script_err_unknown_type, ERR_UNKNOWN_TYPE); // type not registered - err_fn!(script_err_duplicate, ERR_DUPLICATE); // key already exists - err_fn!(script_err_io, ERR_IO); // file system, child process - err_fn!(script_err_limit, ERR_LIMIT); // resource limits - - pub const fn raw(&self) -> u64 { - self.0 - } - - pub const fn is_err(&self) -> bool { - (self.0 & Self::TYPE_MASK) >= ScriptValueType::ERR_FIRST.to_u64() - && (self.0 & Self::TYPE_MASK) <= ScriptValueType::ERR_LAST.to_u64() - } - - pub const fn as_err(&self) -> Option { - if self.is_err() { - Some(ValueError { - ty: self.value_type(), - ip: ScriptIp::from_u40(self.0), - }) - } else { - None - } - } - - // opcodes - - pub const TYPE_OPCODE: u64 = ScriptValueType::OPCODE.to_u64(); - - pub const fn from_opcode(op: Opcode) -> Self { - Self(Self::TYPE_OPCODE | (op.0 as u64) << 32) - } - - #[inline] - pub const fn is_opcode(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_OPCODE - } - - pub const fn from_opcode_args(op: Opcode, args: OpcodeArgs) -> Self { - Self(Self::TYPE_OPCODE | (op.0 as u64) << 32 | (args.0 as u64)) - } - #[inline] - pub const fn as_opcode(&self) -> Option<(Opcode, OpcodeArgs)> { - if self.is_opcode() { - return Some(( - Opcode(((self.0 >> 32) & 0xff) as u8), - OpcodeArgs((self.0 & 0xffff_ffff) as u32), - )); - } - None - } - - pub const fn set_opcode_args(&mut self, args: OpcodeArgs) { - if self.is_opcode() { - self.0 = (self.0 & 0xffff_ffff_0000_0000) | (args.0 as u64); - } - } - - pub const fn set_opcode_args_pop_to_me(&mut self) { - if self.is_opcode() { - self.0 |= OpcodeArgs::POP_TO_ME_FLAG as u64; - } - } - - pub const fn clear_opcode_args_pop_to_me(&mut self) { - if self.is_opcode() { - self.0 &= !(OpcodeArgs::POP_TO_ME_FLAG as u64); - } - } - - pub const fn has_opcode_args_pop_to_me(&self) -> bool { - if self.is_opcode() { - self.0 & (OpcodeArgs::POP_TO_ME_FLAG as u64) != 0 - } else { - false - } - } - - pub const fn is_assign_opcode(&self) -> bool { - if self.is_opcode() { - let code = Opcode(((self.0 >> 32) & 0xff) as u8); - return code.is_assign(); - } - false - } - - pub const fn is_let_opcode(&self) -> bool { - if self.is_opcode() { - let code = Opcode(((self.0 >> 32) & 0xff) as u8); - return code.0 == Opcode::LET_TYPED.0 - || code.0 == Opcode::LET_DYN.0 - || code.0 == Opcode::VAR_TYPED.0 - || code.0 == Opcode::VAR_DYN.0; - } - false - } - - // NIL - - pub const fn is_nil(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_NIL - } - - // number - - pub const fn is_number(&self) -> bool { - self.0 <= Self::TYPE_NUMBER_MAX - } - - pub const fn as_number(&self) -> Option { - if let Some(v) = self.as_f64() { - return Some(v); - } - if let Some(v) = self.as_u40() { - return Some(v as _); - } - if let Some(v) = self.as_f32() { - return Some(v as _); - } - if let Some(v) = self.as_u32() { - return Some(v as _); - } - if let Some(v) = self.as_i32() { - return Some(v as _); - } - if let Some(v) = self.as_f16() { - return Some(v as _); - } - None - } - - // f32 - - pub const fn from_f32(v: f32) -> Self { - Self(v.to_bits() as u64 | Self::TYPE_F32) - } - - pub const fn is_f32(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_F32 - } - - pub const fn as_f32(&self) -> Option { - if self.is_f32() { - return Some(f32::from_bits(self.0 as u32)); - } - None - } - - // f16 - - pub const fn from_f16(v: f32) -> Self { - Self(v.to_bits() as u64 | Self::TYPE_F16) - } - - pub const fn is_f16(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_F16 - } - - pub const fn as_f16(&self) -> Option { - if self.is_f16() { - return Some(f32::from_bits(self.0 as u32)); - } - None - } - - // ints - - // f32 - - pub const fn from_u40(v: u64) -> Self { - Self((v & 0xFF_FFFF_FFFF) as u64 | Self::TYPE_U40) - } - - pub const fn is_u40(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_U40 - } - - pub const fn as_u40(&self) -> Option { - if self.is_u40() { - return Some(self.0 & 0xFF_FFFF_FFFF); - } - None - } - - pub const fn from_u32(v: u32) -> Self { - Self(v as u64 | Self::TYPE_U32) - } - - pub const fn is_u32(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_U32 - } - - pub const fn as_u32(&self) -> Option { - if self.is_u32() { - return Some(self.0 as u32); - } - None - } - - pub const fn from_i32(v: i32) -> Self { - Self(v as u64 | Self::TYPE_I32) - } - - pub const fn is_i32(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_I32 - } - - pub const fn as_i32(&self) -> Option { - if self.is_i32() { - return Some(self.0 as i32); - } - None - } - - // f64 - - #[inline] - pub const fn from_f64(val: f64) -> Self { - if val.is_nan() { - Self::NAN - } else { - Self(val.to_bits()) - } - } - - #[inline] - pub const fn as_f64(&self) -> Option { - if self.is_f64() { - return Some(f64::from_bits(self.0)); - } - None - } - - pub const fn as_f64_traced_nan(&self) -> Option { - if self.is_nan() { - Some(ScriptIp::from_u40(self.0)) - } else { - None - } - } - - #[inline] - pub fn from_f64_traced_nan(val: f64, ip: ScriptIp) -> Self { - let bits = val.to_bits(); - if val.is_nan() { - if bits >= Self::TYPE_NAN && bits <= Self::TYPE_TRACED_NAN_MAX { - Self(bits) - } else { - Self(Self::TYPE_NAN | ip.to_u40()) - } - } else { - Self(bits) - } - } - - #[inline] - pub const fn is_f64(&self) -> bool { - self.0 <= Self::TYPE_TRACED_NAN_MAX - } - - pub const fn is_non_nan_number(&self) -> bool { - self.0 < Self::TYPE_NAN - } - - /// Checked index for language reads and writes; unlike `as_index`, this - /// cannot truncate, saturate, or turn a non-number into item zero. - pub fn checked_index(&self) -> Option { - let value = self.as_number()?; - (value.is_finite() && value >= 0.0 && value.fract() == 0.0 && value < usize::MAX as f64) - .then_some(value as usize) - } - - pub const fn as_index(&self) -> usize { - if let Some(f) = self.as_f64() { - return f as usize; - } - if let Some(f) = self.as_u40() { - return f as usize; - } - if let Some(f) = self.as_u32() { - return f as usize; - } - if let Some(f) = self.as_i32() { - return f as usize; - } - if let Some(f) = self.as_f32() { - return f as usize; - } - if let Some(f) = self.as_f16() { - return f as usize; - } - if let Some(b) = self.as_bool() { - return if b { 1 } else { 0 }; - } - 0 - } - - pub const fn is_index(&self) -> bool { - self.0 <= Self::TYPE_NIL - } - - pub const fn is_nan(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_NAN - } - - // Object - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - - #[cfg(feature = "check_gen")] - pub const fn from_object(ptr: ScriptObject) -> Self { - Self(ptr.index as u64 | ((ptr.generation as u64) << 32) | Self::TYPE_OBJECT) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_object(ptr: ScriptObject) -> Self { - Self(ptr.index as u64 | Self::TYPE_OBJECT) - } - - pub const fn is_object(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_OBJECT - } - - #[cfg(feature = "check_gen")] - pub const fn as_object(&self) -> Option { - if self.is_object() { - return Some(ScriptObject { - index: (self.0 & 0xffff_ffff) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }); - } - None - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_object(&self) -> Option { - if self.is_object() { - return Some(ScriptObject { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - // PodType - - pub const fn from_pod_type(ptr: ScriptPodType) -> Self { - Self(ptr.index as u64 | Self::TYPE_POD_TYPE) - } - - pub const fn is_pod_type(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_POD_TYPE - } - - pub const fn as_pod_type(&self) -> Option { - if self.is_pod_type() { - return Some(ScriptPodType { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - // Pod - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - - #[cfg(feature = "check_gen")] - pub const fn from_pod(ptr: ScriptPod) -> Self { - Self(ptr.index as u64 | ((ptr.generation as u64) << 32) | Self::TYPE_POD) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_pod(ptr: ScriptPod) -> Self { - Self(ptr.index as u64 | Self::TYPE_POD) - } - - pub const fn is_pod(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_POD - } - - #[cfg(feature = "check_gen")] - pub const fn as_pod(&self) -> Option { - if self.is_pod() { - return Some(ScriptPod { - index: (self.0 & 0xffff_ffff) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }); - } - None - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_pod(&self) -> Option { - if self.is_pod() { - return Some(ScriptPod { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - // Handle - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - // Handle type is encoded in the TYPE_MASK (different type tags per handle type) - - #[cfg(feature = "check_gen")] - pub const fn from_handle(ptr: ScriptHandle) -> Self { - Self( - ptr.index as u64 - | ((ptr.generation as u64) << 32) - | (Self::TYPE_HANDLE_FIRST + ((ptr.ty.0 as u64) << 40)), - ) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_handle(ptr: ScriptHandle) -> Self { - Self(ptr.index as u64 | (Self::TYPE_HANDLE_FIRST + ((ptr.ty.0 as u64) << 40))) - } - - pub const fn is_handle(&self) -> bool { - let ty = self.0 & Self::TYPE_MASK; - ty >= Self::TYPE_HANDLE_FIRST && ty <= Self::TYPE_HANDLE_LAST - } - - #[cfg(feature = "check_gen")] - pub const fn as_handle(&self) -> Option { - if self.is_handle() { - return Some(ScriptHandle { - ty: ScriptHandleType( - (((self.0 & Self::TYPE_MASK) - Self::TYPE_HANDLE_FIRST) >> 40) as u8, - ), - index: (self.0 & 0xffff_ffff) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }); - } - None - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_handle(&self) -> Option { - if self.is_handle() { - return Some(ScriptHandle { - ty: ScriptHandleType( - (((self.0 & Self::TYPE_MASK) - Self::TYPE_HANDLE_FIRST) >> 40) as u8, - ), - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - // bool - - pub const fn from_bool(val: bool) -> Self { - if val { - Self::TRUE - } else { - Self::FALSE - } - } - - pub const fn as_bool(&self) -> Option { - if self.is_bool() { - return Some(self.0 == Self::TRUE.0); - } - None - } - - pub const fn is_bool(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_BOOL - } - - // color - - pub const fn from_color(val: u32) -> Self { - Self(val as u64 | Self::TYPE_COLOR) - } - - pub const fn as_color(&self) -> Option { - if self.is_color() { - return Some((self.0 & 0xffff_ffff) as u32); - } - None - } - - pub const fn is_color(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_COLOR - } - - // array - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - - #[cfg(feature = "check_gen")] - pub const fn from_array(val: ScriptArray) -> Self { - Self((val.index as u64) | ((val.generation as u64) << 32) | Self::TYPE_ARRAY) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_array(val: ScriptArray) -> Self { - Self((val.index as u64) | Self::TYPE_ARRAY) - } - - pub const fn is_array(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_ARRAY - } - - #[cfg(feature = "check_gen")] - pub const fn as_array(&self) -> Option { - if self.is_array() { - Some(ScriptArray { - index: (self.0 & 0xFFFF_FFFF) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }) - } else { - None - } - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_array(&self) -> Option { - if self.is_array() { - Some(ScriptArray { - index: (self.0 & 0xFFFF_FFFF) as u32, - }) - } else { - None - } - } - - // id - - pub const fn from_id(val: LiveId) -> Self { - Self(val.0 | Self::TYPE_ID) - } - - pub const fn is_id(&self) -> bool { - self.0 >= Self::TYPE_ID - } - - pub const fn from_escaped_id(val: LiveId) -> Self { - Self(val.0 | Self::TYPE_ID | Self::ESCAPED_ID) - } - - pub const fn as_id(&self) -> Option { - if self.is_id() { - return Some(LiveId(self.0 & 0x0000_3fff_ffff_ffff)); - } - None - } - - pub const fn is_escaped_id(&self) -> bool { - self.0 >= Self::TYPE_ID | Self::ESCAPED_ID - } - - // regex - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - - #[cfg(feature = "check_gen")] - pub const fn from_regex(ptr: ScriptRegex) -> Self { - Self(ptr.index as u64 | ((ptr.generation as u64) << 32) | Self::TYPE_REGEX) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_regex(ptr: ScriptRegex) -> Self { - Self(ptr.index as u64 | Self::TYPE_REGEX) - } - - #[cfg(feature = "check_gen")] - pub const fn as_regex(&self) -> Option { - if self.is_regex() { - return Some(ScriptRegex { - index: (self.0 & 0xffff_ffff) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }); - } - None - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_regex(&self) -> Option { - if self.is_regex() { - return Some(ScriptRegex { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - pub const fn is_regex(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_REGEX - } - - // string - // Layout: bits 0-31 = index, bits 32-39 = generation (when check_gen enabled) - - #[cfg(feature = "check_gen")] - pub const fn from_string(ptr: ScriptString) -> Self { - Self(ptr.index as u64 | ((ptr.generation as u64) << 32) | Self::TYPE_STRING) - } - #[cfg(not(feature = "check_gen"))] - pub const fn from_string(ptr: ScriptString) -> Self { - Self(ptr.index as u64 | Self::TYPE_STRING) - } - - #[cfg(feature = "check_gen")] - pub const fn as_string(&self) -> Option { - if self.is_string() { - return Some(ScriptString { - index: (self.0 & 0xffff_ffff) as u32, - generation: ((self.0 >> 32) & 0xff) as Generation, - }); - } - None - } - #[cfg(not(feature = "check_gen"))] - pub const fn as_string(&self) -> Option { - if self.is_string() { - return Some(ScriptString { - index: (self.0 & 0xffff_ffff) as u32, - }); - } - None - } - - pub const fn is_string(&self) -> bool { - (self.0 & Self::TYPE_MASK) == Self::TYPE_STRING - } - - pub const fn is_string_like(&self) -> bool { - let ty = self.0 & Self::TYPE_MASK; - ty >= Self::TYPE_STRING && ty < Self::TYPE_INLINE_STRING_END - } - - pub const fn from_inline_string(str: &str) -> Option { - let bytes = str.as_bytes(); - if bytes.len() > 5 { - return None; - } - if bytes.len() == 0 { - Some(Self(Self::TYPE_INLINE_STRING_0)) - } else if bytes.len() == 1 { - Some(Self(Self::TYPE_INLINE_STRING_1 | bytes[0] as u64)) - } else if bytes.len() == 2 { - Some(Self( - Self::TYPE_INLINE_STRING_2 | bytes[0] as u64 | ((bytes[1] as u64) << 8), - )) - } else if bytes.len() == 3 { - Some(Self( - Self::TYPE_INLINE_STRING_3 - | bytes[0] as u64 - | ((bytes[1] as u64) << 8) - | ((bytes[2] as u64) << 16), - )) - } else if bytes.len() == 4 { - Some(Self( - Self::TYPE_INLINE_STRING_4 - | bytes[0] as u64 - | ((bytes[1] as u64) << 8) - | ((bytes[2] as u64) << 16) - | ((bytes[3] as u64) << 24), - )) - } else { - Some(Self( - Self::TYPE_INLINE_STRING_5 - | bytes[0] as u64 - | ((bytes[1] as u64) << 8) - | ((bytes[2] as u64) << 16) - | ((bytes[3] as u64) << 24) - | ((bytes[4] as u64) << 32), - )) - } - } - - pub fn as_inline_string R>(&self, f: F) -> Option { - if !self.is_inline_string() { - return None; - } - if self.0 < Self::TYPE_INLINE_STRING_1 { - return Some(f("")); - } else if self.0 < Self::TYPE_INLINE_STRING_2 { - return Some(f(unsafe { - std::str::from_utf8_unchecked(&[(self.0 & 0xff) as u8]) - })); - } else if self.0 < Self::TYPE_INLINE_STRING_3 { - return Some(f(unsafe { - std::str::from_utf8_unchecked(&[ - (self.0 & 0xff) as u8, - ((self.0 >> 8) & 0xff) as u8, - ]) - })); - } else if self.0 < Self::TYPE_INLINE_STRING_4 { - return Some(f(unsafe { - std::str::from_utf8_unchecked(&[ - (self.0 & 0xff) as u8, - ((self.0 >> 8) & 0xff) as u8, - ((self.0 >> 16) & 0xff) as u8, - ]) - })); - } else if self.0 < Self::TYPE_INLINE_STRING_5 { - return Some(f(unsafe { - std::str::from_utf8_unchecked(&[ - (self.0 & 0xff) as u8, - ((self.0 >> 8) & 0xff) as u8, - ((self.0 >> 16) & 0xff) as u8, - ((self.0 >> 24) & 0xff) as u8, - ]) - })); - } else { - return Some(f(unsafe { - std::str::from_utf8_unchecked(&[ - (self.0 & 0xff) as u8, - ((self.0 >> 8) & 0xff) as u8, - ((self.0 >> 16) & 0xff) as u8, - ((self.0 >> 24) & 0xff) as u8, - ((self.0 >> 32) & 0xff) as u8, - ]) - })); - } - } - - pub const fn inline_string_not_empty(&self) -> bool { - self.0 >= Self::TYPE_INLINE_STRING_1 && self.0 <= Self::TYPE_INLINE_STRING_END - } - - pub const fn is_inline_string(&self) -> bool { - self.0 >= Self::TYPE_INLINE_STRING_0 && self.0 < Self::TYPE_INLINE_STRING_END - } -} - -impl fmt::Debug for ScriptValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for ScriptValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(v) = self.as_f64() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_u40() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_id() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_bool() { - return write!(f, "{}", v); - } - if let Some(_) = self.as_string() { - return write!(f, "[String]"); - } - if let Some(x) = self.as_color() { - return write!(f, "[Color:{:8x}]", x); - } - if let Some(r) = self.as_inline_string(|s| write!(f, "{s}")) { - return r; - } - if let Some(v) = self.as_f32() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_i32() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_u32() { - return write!(f, "{}", v); - } - if let Some(v) = self.as_f16() { - return write!(f, "{}", v); - } - if let Some(ptr) = self.as_object() { - return write!(f, "[ScriptObject:{}]", ptr.index); - } - if let Some(ptr) = self.as_array() { - return write!(f, "[ScriptArray:{}]", ptr.index); - } - if let Some(ptr) = self.as_regex() { - return write!(f, "[ScriptRegex:{}]", ptr.index); - } - if let Some(ptr) = self.as_handle() { - return write!(f, "[ScriptHandle:{}]", ptr.index); - } - if let Some(ptr) = self.as_pod_type() { - return write!(f, "[ScriptPodType:{}]", ptr.index); - } - if let Some(ptr) = self.as_pod() { - return write!(f, "[ScriptPod:{}]", ptr.index); - } - if let Some(error) = self.as_err() { - return write!(f, "{}", error.ty); - } - if self.is_nil() { - return write!(f, "nil"); - } - if let Some((opcode, args)) = self.as_opcode() { - return write!(f, "{opcode}{args}"); - } - write!(f, "?{:08x}", self.0) - } -} diff --git a/vendor/makepad/platform/script/src/value_map.rs b/vendor/makepad/platform/script/src/value_map.rs deleted file mode 100644 index 60a8d27..0000000 --- a/vendor/makepad/platform/script/src/value_map.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::makepad_live_id::LiveId; - -use std::{ - collections::HashMap, - ops::{Deref, DerefMut, Index, IndexMut}, -}; - -// Idea taken from the `nohash_hasher` crate. -#[derive(Default)] -pub struct ValueHasher(u64); - -impl std::hash::Hasher for ValueHasher { - fn write(&mut self, _: &[u8]) { - unreachable!(); - } - fn write_u8(&mut self, _n: u8) { - unreachable!(); - } - fn write_u16(&mut self, _n: u16) { - unreachable!(); - } - fn write_u32(&mut self, _n: u32) { - unreachable!(); - } - #[inline(always)] - fn write_u64(&mut self, n: u64) { - self.0 = n; - } - fn write_usize(&mut self, _n: usize) { - unreachable!(); - } - fn write_i8(&mut self, _n: i8) { - unreachable!(); - } - fn write_i16(&mut self, _n: i16) { - unreachable!(); - } - fn write_i32(&mut self, _n: i32) { - unreachable!(); - } - fn write_i64(&mut self, _n: i64) { - unreachable!(); - } - fn write_isize(&mut self, _n: isize) { - unreachable!(); - } - #[inline(always)] - fn finish(&self) -> u64 { - self.0 - } -} - -#[derive(Copy, Clone, Default)] -pub struct ValueHasherBuilder {} - -impl std::hash::BuildHasher for ValueHasherBuilder { - type Hasher = ValueHasher; - - #[inline(always)] - fn build_hasher(&self) -> ValueHasher { - ValueHasher::default() - } -} - -#[derive(Clone, Debug)] -pub struct ValueMap { - map: HashMap, - //alloc_set: HashSet -} - -impl Default for ValueMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From + std::fmt::Debug, -{ - fn default() -> Self { - Self { - map: HashMap::with_hasher(ValueHasherBuilder {}), - //alloc_set: HashSet::with_hasher(LiveIdHasherBuilder {}) - } - } -} - -impl Deref for ValueMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - type Target = HashMap; - fn deref(&self) -> &Self::Target { - &self.map - } -} - -impl DerefMut for ValueMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.map - } -} - -impl Index for ValueMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - type Output = V; - fn index(&self, index: K) -> &Self::Output { - self.map.get(&index).unwrap() - } -} - -impl IndexMut for ValueMap -where - K: std::cmp::Eq + std::hash::Hash + Copy + From, -{ - fn index_mut(&mut self, index: K) -> &mut Self::Output { - self.map.get_mut(&index).unwrap() - } -} diff --git a/vendor/makepad/platform/script/src/vec_prims.rs b/vendor/makepad/platform/script/src/vec_prims.rs deleted file mode 100644 index 66f5538..0000000 --- a/vendor/makepad/platform/script/src/vec_prims.rs +++ /dev/null @@ -1,549 +0,0 @@ -use crate::apply::*; -use crate::array::*; -use crate::heap::*; -use crate::object::*; -use crate::traits::*; -use crate::value::*; -use crate::vm::*; -use crate::*; -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::hash::Hash; - -impl ScriptHook for Vec where T: ScriptApply + ScriptNew + 'static + ScriptDeriveMarker {} -impl ScriptNew for Vec -where - T: ScriptApply + ScriptNew + 'static + ScriptDeriveMarker, -{ - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - let len = heap.vec_len(obj); - for i in 0..len { - if let Some(value) = heap.vec_value_if_exist(obj, i) { - if !T::script_type_check(heap, value) { - return false; - } - } - } - return true; - } else if let Some(arr) = value.as_array() { - match heap.array_storage(arr) { - ScriptArrayStorage::ScriptValue(vec) => { - for v in vec { - if !T::script_type_check(heap, *v) { - return false; - } - } - return true; - } - ScriptArrayStorage::F32(_) => return true, - ScriptArrayStorage::U32(_) => return true, - ScriptArrayStorage::U16(_) => return true, - ScriptArrayStorage::U8(_) => return true, - } - } - value.is_nil() || T::script_type_check(heap, value) || heap.has_apply_transform(value) - } - fn script_default(_vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(_vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - NIL - } -} -impl ScriptApply for Vec -where - T: ScriptApply + ScriptNew + 'static + ScriptDeriveMarker, -{ - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - let len = vm.bx.heap.vec_len(obj); - self.resize_with(len, || ScriptNew::script_new(vm)); - for i in 0..len { - if let Some(value) = vm.bx.heap.vec_value_if_exist(obj, i) { - self[i].script_apply(vm, apply, scope, value); - } - } - } else if let Some(arr) = value.as_array() { - let len = vm.bx.heap.array_len(arr); - self.resize_with(len, || ScriptNew::script_new(vm)); - for i in 0..len { - let value = vm.bx.heap.array_index_unchecked(arr, i); - self[i].script_apply(vm, apply, scope, value); - } - } else if value.is_nil() { - self.clear() - } else { - self.clear(); - self.push(ScriptNew::script_from_value(vm, value)); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur().trap.pass(); - // we swap the vec off of the heap to be able to script_to_value the rest - let mut vec_store = vm - .bx - .heap - .array_mut_with(arr, trap, |astore| { - let mut store = ScriptArrayStorage::ScriptValue(Default::default()); - std::mem::swap(&mut store, astore); - store - }) - .unwrap(); - if !matches!(vec_store, ScriptArrayStorage::ScriptValue(_)) { - vec_store = ScriptArrayStorage::ScriptValue(Default::default()); - } - let ScriptArrayStorage::ScriptValue(vec) = &mut vec_store else { - unreachable!("array storage was normalized to ScriptValue"); - }; - vec.clear(); - for v in self { - vec.push_back(v.script_to_value(vm)); - } - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx - .heap - .array_mut_with(arr, trap, |astore| std::mem::swap(&mut vec_store, astore)) - .unwrap(); - arr.into() - } -} - -impl ScriptHook for Vec {} -impl ScriptNew for Vec { - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - for kv in heap.vec_ref(obj) { - if !kv.value.is_number() { - return false; - } - } - return true; - } else if let Some(arr) = value.as_array() { - match heap.array_storage(arr) { - ScriptArrayStorage::ScriptValue(vec) => { - for v in vec { - if !v.is_number() { - return false; - } - } - return true; - } - ScriptArrayStorage::F32(_) => return true, - ScriptArrayStorage::U32(_) => return true, - ScriptArrayStorage::U16(_) => return true, - ScriptArrayStorage::U8(_) => return true, - } - } - value.is_string_like() || value.is_nil() || heap.has_apply_transform(value) - } - fn script_default(vm: &mut ScriptVm) -> ScriptValue { - vm.bx.heap.new_object().into() - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - vm.bx.heap.new_object().into() - } -} - -impl ScriptApply for Vec { - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - self.clear(); - for kv in vm.bx.heap.vec_ref(obj) { - self.push(kv.value.as_f64().unwrap_or(0.0) as _); - } - } else if let Some(arr) = value.as_array() { - self.clear(); - match vm.bx.heap.array_storage(arr) { - ScriptArrayStorage::ScriptValue(vec) => { - for v in vec { - self.push((*v).into()) - } - } - ScriptArrayStorage::F32(vec) => { - for v in vec { - self.push(*v as _) - } - } - ScriptArrayStorage::U32(vec) => { - for v in vec { - self.push(*v as _) - } - } - ScriptArrayStorage::U16(vec) => { - for v in vec { - self.push(*v as _) - } - } - ScriptArrayStorage::U8(vec) => { - for v in vec { - self.push(*v as _) - } - } - } - } else if let Some(str) = value.as_string() { - let str = vm.bx.heap.string(str); - self.clear(); - self.extend(str.as_bytes()); - } else if value - .as_inline_string(|s| { - self.clear(); - self.extend(s.as_bytes()); - }) - .is_some() - { - } else if value.is_nil() { - self.clear(); - } else { - script_err_type_mismatch!(vm.bx.threads.cur_ref().trap, "wrong vec type in apply"); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx - .heap - .array_mut_with(arr, trap, |astore| { - if let ScriptArrayStorage::U8(v) = astore { - v.clear(); - v.extend(self) - } else { - *astore = ScriptArrayStorage::U8(self.clone()); - } - }) - .unwrap(); - arr.into() - } -} - -impl ScriptHook for Vec {} -impl ScriptNew for Vec { - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(_heap: &ScriptHeap, _value: ScriptValue) -> bool { - true - } - fn script_default(vm: &mut ScriptVm) -> ScriptValue { - vm.bx.heap.new_object().into() - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - vm.bx.heap.new_object().into() - } -} - -impl ScriptApply for Vec { - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - self.clear(); - for kv in vm.bx.heap.vec_ref(obj) { - self.push(kv.value); - } - } else if let Some(arr) = value.as_array() { - self.clear(); - match vm.bx.heap.array_storage(arr) { - ScriptArrayStorage::ScriptValue(vec) => { - for v in vec { - self.push((*v).into()) - } - } - ScriptArrayStorage::F32(vec) => { - for v in vec { - self.push((*v).into()) - } - } - ScriptArrayStorage::U32(vec) => { - for v in vec { - self.push((*v).into()) - } - } - ScriptArrayStorage::U16(vec) => { - for v in vec { - self.push((*v).into()) - } - } - ScriptArrayStorage::U8(vec) => { - for v in vec { - self.push((*v).into()) - } - } - } - } else if value.is_nil() { - self.clear(); - } else { - self.clear(); - self.push(value); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let arr = vm.bx.heap.new_array(); - let trap = vm.bx.threads.cur().trap.pass(); - vm.bx - .heap - .array_mut_with(arr, trap, |astore| { - if let ScriptArrayStorage::ScriptValue(v) = astore { - v.clear(); - v.extend(self) - } else { - *astore = ScriptArrayStorage::ScriptValue(self.iter().cloned().collect()); - } - }) - .unwrap(); - arr.into() - } -} - -impl ScriptHook for HashMap -where - K: ScriptApply + ScriptNew + 'static + Eq + Hash, - V: ScriptApply + ScriptNew + 'static, -{ -} -impl ScriptNew for HashMap -where - K: ScriptApply + ScriptNew + 'static + Eq + Hash, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - let map = heap.map_ref(obj); - for (key, value) in map.iter() { - if !K::script_type_check(heap, *key) { - return false; - } - if !V::script_type_check(heap, value.value) { - return false; - } - } - return true; - } - value.is_nil() || heap.has_apply_transform(value) - } - fn script_default(_vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(_vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - NIL - } -} -impl ScriptApply for HashMap -where - K: ScriptApply + ScriptNew + 'static + Eq + Hash, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - // hashmaps and btreemaps are cleared and copied fresh we can optimise later - self.clear(); - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in obj_map.iter_mut() { - let key = K::script_from_value(vm, *key); - let value = V::script_from_value(vm, value.value); - self.insert(key, value); - } - }) - } else if value.is_nil() { - self.clear() - } else { - script_err_type_mismatch!(vm.bx.threads.cur_ref().trap, "wrong vec type in apply"); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let obj = vm.bx.heap.new_object(); - let mut has_string_keys = false; - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in self.iter() { - let key = key.script_to_value(vm); - if key.is_string_like() { - has_string_keys = true; - } - let value = value.script_to_value(vm); - obj_map.insert( - key, - ScriptMapValue { - tag: Default::default(), - value, - }, - ); - } - }); - if has_string_keys { - vm.bx.heap.set_string_keys(obj); - } - obj.into() - } -} - -impl ScriptHook for BTreeMap -where - K: ScriptApply + ScriptNew + 'static + Ord, - V: ScriptApply + ScriptNew + 'static, -{ -} -impl ScriptNew for BTreeMap -where - K: ScriptApply + ScriptNew + 'static + Ord, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id_static() -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_type_check(heap: &ScriptHeap, value: ScriptValue) -> bool { - if let Some(obj) = value.as_object() { - let map = heap.map_ref(obj); - for (key, value) in map.iter() { - if !K::script_type_check(heap, *key) { - return false; - } - if !V::script_type_check(heap, value.value) { - return false; - } - } - return true; - } - value.is_nil() || heap.has_apply_transform(value) - } - fn script_default(_vm: &mut ScriptVm) -> ScriptValue { - NIL - } - fn script_new(_vm: &mut ScriptVm) -> Self { - Default::default() - } - fn script_proto_build(_vm: &mut ScriptVm, _props: &mut ScriptTypeProps) -> ScriptValue { - NIL - } -} -impl ScriptApply for BTreeMap -where - K: ScriptApply + ScriptNew + 'static + Ord, - V: ScriptApply + ScriptNew + 'static, -{ - fn script_type_id(&self) -> ScriptTypeId { - ScriptTypeId::of::() - } - fn script_apply( - &mut self, - vm: &mut ScriptVm, - apply: &Apply, - scope: &mut Scope, - value: ScriptValue, - ) { - // Check for apply transform - if let Some(transformed) = vm.call_apply_transform(value) { - return self.script_apply(vm, apply, scope, transformed); - } - if let Some(obj) = value.as_object() { - // hashmaps and btreemaps are cleared and copied fresh we can optimise later - self.clear(); - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in obj_map.iter_mut() { - let key = K::script_from_value(vm, *key); - let value = V::script_from_value(vm, value.value); - self.insert(key, value); - } - }) - } else if value.is_nil() { - self.clear() - } else { - script_err_type_mismatch!(vm.bx.threads.cur_ref().trap, "wrong vec type in apply"); - } - } - fn script_to_value(&self, vm: &mut ScriptVm) -> ScriptValue { - let obj = vm.bx.heap.new_object(); - let mut has_string_keys = false; - vm.map_mut_with(obj, |vm, obj_map| { - for (key, value) in self.iter() { - let key = key.script_to_value(vm); - if key.is_string_like() { - has_string_keys = true; - } - let value = value.script_to_value(vm); - obj_map.insert( - key, - ScriptMapValue { - tag: Default::default(), - value, - }, - ); - } - }); - if has_string_keys { - vm.bx.heap.set_string_keys(obj); - } - obj.into() - } -} diff --git a/vendor/makepad/platform/script/src/vm.rs b/vendor/makepad/platform/script/src/vm.rs deleted file mode 100644 index 1769be8..0000000 --- a/vendor/makepad/platform/script/src/vm.rs +++ /dev/null @@ -1,2016 +0,0 @@ -use crate::function::*; -use crate::heap::*; -use crate::makepad_error_log::*; -use crate::makepad_live_id::*; -use crate::mod_gc::*; -use crate::mod_html::*; -use crate::mod_math::*; -use crate::mod_pod::*; -use crate::mod_regex::*; -use crate::mod_shader::*; -use crate::mod_std::*; -use crate::native::*; -use crate::object::*; -use crate::opcode::*; -use crate::parser::*; -use crate::thread::*; -use crate::tokenizer::*; -use crate::trap::*; -use crate::value::*; -use crate::*; -use std::any::Any; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; -use std::time::{Duration, Instant}; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] -pub struct ScriptModKey { - pub file: String, - pub line: usize, - pub column: usize, -} - -impl ScriptModKey { - pub fn from_script_mod(script_mod: &ScriptMod) -> Self { - Self { - file: script_mod.file.clone(), - line: script_mod.line, - column: script_mod.column, - } - } -} - -#[derive(Default, Debug)] -pub struct ScriptMod { - pub cargo_manifest_path: String, - pub module_path: String, - pub file: String, - pub line: usize, - pub column: usize, - pub code: String, - pub values: Vec, -} - -pub enum ScriptSource { - Mod(ScriptMod), - Streaming { code: String }, -} - -pub struct ScriptBody { - pub source: ScriptSource, - pub effective_code: String, - pub tokenizer: ScriptTokenizer, - pub parser: ScriptParser, - pub scope: ScriptObjectRef, - pub me: ScriptObjectRef, - pub checkpoint: Option, - pub source_len: usize, -} - -#[derive(Default)] -pub struct ScriptBuiltins { - pub range: ScriptObject, - pub pod: ScriptPodBuiltins, -} - -impl ScriptBuiltins { - pub fn new(heap: &mut ScriptHeap, pod: ScriptPodBuiltins) -> Self { - Self { - range: heap - .value_path(heap.modules, ids!(std.Range), NoTrap) - .as_object() - .unwrap(), - pod, - } - } -} - -#[derive(Default)] -pub struct ScriptCode { - pub builtins: ScriptBuiltins, - pub native: RefCell, - pub bodies: RefCell>, - pub crate_manifests: Rc>>, - pub script_mod_overrides: Rc>>, -} - -pub struct ScriptLoc { - pub file: String, - pub col: u32, - pub line: u32, -} - -impl std::fmt::Debug for ScriptLoc { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(self, f) - } -} - -impl std::fmt::Display for ScriptLoc { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}:{}:{}", self.file, self.line, self.col) - } -} - -impl ScriptCode { - pub fn ip_to_loc(&self, ip: ScriptIp) -> Option { - if let Some(body) = self.bodies.borrow().get(ip.body as usize) { - let source_map = &body.parser.source_map; - let ip_index = ip.index as usize; - - let direct_token = source_map.get(ip_index).and_then(|slot| *slot); - // Some opcodes are synthetic and have `None` in source_map. - // For error reporting, fall back to the nearest mapped token so we still - // surface a real file/line instead of "unknown". - let nearest_token = if direct_token.is_some() { - direct_token - } else { - let left = ip_index.min(source_map.len().saturating_sub(1)); - let left_token = (0..=left) - .rev() - .find_map(|idx| source_map.get(idx).and_then(|slot| *slot)); - if left_token.is_some() { - left_token - } else { - ((ip_index + 1)..source_map.len()) - .find_map(|idx| source_map.get(idx).and_then(|slot| *slot)) - } - }; - - if let Some(token_index) = nearest_token { - if let Some(rc) = body.tokenizer.token_index_to_row_col(token_index) { - if let ScriptSource::Mod(script_mod) = &body.source { - return Some(ScriptLoc { - file: script_mod.file.clone(), - line: rc.0 + script_mod.line as u32, - col: rc.1, - }); - } - return Some(ScriptLoc { - file: "generated".into(), - line: rc.0, - col: rc.1, - }); - } - } - } - return Some(ScriptLoc { - file: "unknown".into(), - line: ip.body as _, - col: ip.index as _, - }); - } -} - -pub struct ScriptVm<'a> { - pub host: &'a mut dyn Any, - pub std: &'a mut dyn Any, - pub bx: Box, -} - -#[derive(Clone, Copy, Debug)] -pub struct ScriptRunBudget { - pub soft_deadline: Instant, - pub hard_deadline: Instant, - pub sample_interval_instructions: u32, - pub instructions_until_sample: u32, -} - -impl ScriptRunBudget { - pub fn from_durations( - soft: Duration, - hard: Duration, - sample_interval_instructions: u32, - ) -> Self { - let now = Instant::now(); - let sample_interval_instructions = sample_interval_instructions.max(1); - Self { - soft_deadline: now + soft, - hard_deadline: now + hard, - sample_interval_instructions, - instructions_until_sample: sample_interval_instructions, - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum ScriptRunBudgetHit { - Soft, - Hard, -} - -impl<'a> ScriptVm<'a> { - /// Bail out of the interpreter with a script error. - /// Use this when a stack (mes, scopes, loops, calls) is unexpectedly empty, - /// indicating corrupted bytecode (e.g. from incomplete streaming input). - /// Sets trap.on to Return(err) so run_core exits cleanly. - pub(crate) fn bail(&mut self, msg: &str) { - let err = script_err_unexpected!(self.bx.threads.cur_ref().trap, "{}", msg); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - } - - pub fn with_instruction_limit( - &mut self, - instruction_limit: usize, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let previous_remaining = self.bx.threads.cur_ref().instruction_limit_remaining; - self.bx.threads.cur().instruction_limit_remaining = Some( - previous_remaining - .map(|remaining| remaining.min(instruction_limit)) - .unwrap_or(instruction_limit), - ); - let result = f(self); - if !self.bx.threads.cur_ref().is_paused() { - self.bx.threads.cur().instruction_limit_remaining = previous_remaining; - } - result - } - - /// Runs an operation with a cap on live VM operand values. - /// - /// Nested caps can only narrow the current limit. A paused continuation - /// retains the cap that began its evaluation, matching instruction-limit - /// behavior. - pub fn with_stack_value_limit( - &mut self, - stack_value_limit: usize, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let previous_limit = self.bx.threads.cur_ref().stack_limit; - self.bx.threads.cur().stack_limit = previous_limit.min(stack_value_limit); - let result = f(self); - if !self.bx.threads.cur_ref().is_paused() { - self.bx.threads.cur().stack_limit = previous_limit; - } - result - } - - /// Runs an operation with a cap on active VM call frames. - /// - /// The count includes a root evaluation frame. The raw Makepad VM has no - /// call-frame cap, while nested bounded executions retain the narrower - /// cap. A paused continuation retains its starting cap. - pub fn with_call_frame_limit( - &mut self, - call_frame_limit: usize, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let previous_limit = self.bx.threads.cur_ref().call_frame_limit; - self.bx.threads.cur().call_frame_limit = Some( - previous_limit - .map(|previous| previous.min(call_frame_limit)) - .unwrap_or(call_frame_limit), - ); - let result = f(self); - if !self.bx.threads.cur_ref().is_paused() { - self.bx.threads.cur().call_frame_limit = previous_limit; - } - result - } - - /// Clears resource-limit signals that did not belong to an active VM - /// instruction. Hosts normally do not need this: `run_core` consumes its - /// own failures, and Octoscript clears stale signals before a fresh eval. - pub fn clear_execution_limit_failures(&mut self) { - self.bx.threads.cur().take_stack_limit_exceeded(); - self.bx.threads.cur().take_call_frame_limit_exceeded(); - } - - pub fn heap(&self) -> &ScriptHeap { - &self.bx.heap - } - - pub fn heap_mut(&mut self) -> &mut ScriptHeap { - &mut self.bx.heap - } - - /// Print a script value to stdout with debug formatting. - pub fn println(&self, value: impl Into) { - self.bx.heap.println(value.into()); - } - - /// Run garbage collection (mark and sweep), only logs if it takes >1ms. - pub fn gc(&mut self) { - self.bx.heap.mark(&self.bx.threads, &self.bx.code); - self.bx.heap.sweep(false); - // Return memory held purely for reuse/over-allocation after the sweep (safe: no live - // slot is moved or removed). gc() is itself gated by `needs_gc()`, so this is rare. - self.bx.heap.shrink_to_fit(); - } - - /// Run garbage collection with status logging. - pub fn gc_with_status(&mut self) { - self.bx.heap.mark(&self.bx.threads, &self.bx.code); - self.bx.heap.sweep(true); - } - - pub fn thread(&self) -> &ScriptThread { - self.bx.threads.cur_ref() - } - - pub fn thread_mut(&mut self) -> &mut ScriptThread { - self.bx.threads.cur() - } - - pub fn trap(&'a self) -> ScriptTrap<'a> { - self.bx.threads.cur_ref().trap.pass() - } - - /// Format an enum variant error with descriptive information about the value. - /// Used by generated code from derive macros for better error messages. - pub fn format_enum_variant_error(&self, value: ScriptValue) -> String { - crate::suggest::format_enum_variant_error(&self.bx.heap, value) - } - - /// Format a ScriptObject for error messages with a brief debug representation. - /// Shows the object's proto chain and key properties. - pub fn format_object_for_error(&self, obj: ScriptObject) -> String { - let mut out = String::new(); - let mut recur = Vec::new(); - // Use the heap's debug string but limit depth to keep it concise - self.bx - .heap - .to_debug_string(obj.into(), &mut recur, &mut out, false, 0); - // Truncate if too long - if out.len() > 200 { - out.truncate(197); - out.push_str("..."); - } - out - } - - pub fn set_thread(&mut self, id: usize) { - self.bx.threads.set_current(id); - } - - pub fn with_vm R>(&mut self, f: F) -> R { - f(self) - } - - pub fn is_reload(&self) -> bool { - self.bx.is_reload - } - - pub fn with_reload R>(&mut self, f: F) -> R { - let was_reload = std::mem::replace(&mut self.bx.is_reload, true); - let out = f(self); - self.bx.is_reload = was_reload; - out - } - - fn script_me_from_value(&mut self, me: ScriptValue) -> Option { - if me.is_nil() { - return None; - } - if let Some(obj) = me.as_object() { - return Some(ScriptMe::Object(obj)); - } - if let Some(arr) = me.as_array() { - return Some(ScriptMe::Array(arr)); - } - if let Some(pod) = me.as_pod() { - return Some(ScriptMe::Pod { - pod, - offset: Default::default(), - }); - } - None - } - - fn call_with_scope(&mut self, scope: ScriptObject, me: ScriptValue) -> ScriptValue { - if let Some(fnptr) = self.bx.heap.parent_as_fn(scope) { - match fnptr { - ScriptFnPtr::Native(ni) => { - // Get the function pointer and drop the borrow before calling - let func_ptr: *const dyn Fn(&mut ScriptVm, ScriptObject) -> ScriptValue = { - let native = self.bx.code.native.borrow(); - &*native.functions[ni.index as usize] as *const _ - }; - // Pause thread before native call so re-entrant calls get a different thread - self.bx.threads.cur().is_paused = true; - // SAFETY: The function pointer is valid as long as native functions aren't removed during execution - let result = unsafe { (*func_ptr)(self, scope) }; - // Only unpause if native didn't explicitly pause (via pause() which sets trap.on to Pause) - if !matches!( - self.bx.threads.cur().trap.on.get(), - Some(ScriptTrapOn::Pause) - ) { - self.bx.threads.cur().is_paused = false; - } - return result; - } - ScriptFnPtr::Script(sip) => { - let call = CallFrame { - bases: self.bx.threads.cur_ref().new_bases(), - args: OpcodeArgs::default(), - return_ip: None, - }; - if !self.bx.threads.cur().push_call_frame(call) { - return self - .handle_execution_limit_failure() - .expect("a rejected call frame raises a limit failure"); - } - self.bx.threads.cur().scopes.push(scope); - if let Some(me) = self.script_me_from_value(me) { - self.bx.threads.cur().mes.push(me); - } - self.bx.threads.cur().trap.ip = sip; - return self.run_core(); - } - } - } else { - return script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "call target is not a function (got {:?})", - self.bx.heap.proto(scope).value_type() - ); - } - } - - pub fn call(&mut self, fnobj: ScriptValue, args: &[ScriptValue]) -> ScriptValue { - self.call_with_me(fnobj, args, NIL) - } - - pub fn call_with_self( - &mut self, - fnobj: ScriptValue, - args: &[ScriptValue], - sself: ScriptValue, - ) -> ScriptValue { - let scope = self.bx.heap.new_with_proto(fnobj); - - self.bx.heap.clear_object_deep(scope); - if fnobj.is_err() { - return fnobj; - } - - let trap = self.bx.threads.cur().trap.pass(); - let err = self.bx.heap.push_all_fn_args(scope, args, trap); - if err.is_err() { - return err; - } - if !sself.is_nil() { - self.bx - .heap - .force_value_in_map(scope, id!(self).into(), sself); - } - - self.bx.heap.set_object_deep(scope); - self.bx.heap.set_object_storage_auto(scope); - self.call_with_scope(scope, NIL) - } - - pub fn call_with_me( - &mut self, - fnobj: ScriptValue, - args: &[ScriptValue], - me: ScriptValue, - ) -> ScriptValue { - let scope = self.bx.heap.new_with_proto(fnobj); - - self.bx.heap.clear_object_deep(scope); - if fnobj.is_err() { - return fnobj; - } - - let trap = self.bx.threads.cur().trap.pass(); - let err = self.bx.heap.push_all_fn_args(scope, args, trap); - if err.is_err() { - return err; - } - - self.bx.heap.set_object_deep(scope); - self.bx.heap.set_object_storage_auto(scope); - self.call_with_scope(scope, me) - } - - pub fn call_with_args_object( - &mut self, - fnobj: ScriptValue, - args_obj: ScriptObject, - ) -> ScriptValue { - self.call_with_args_object_with_me(fnobj, args_obj, NIL) - } - - pub fn call_with_args_object_with_me( - &mut self, - fnobj: ScriptValue, - args_obj: ScriptObject, - me: ScriptValue, - ) -> ScriptValue { - if fnobj.is_err() { - return fnobj; - } - if fnobj.as_object().is_none() { - return script_err_wrong_value!( - self.bx.threads.cur_ref().trap, - "call target is not a function (got {:?})", - fnobj.value_type() - ); - } - - let scope = self.bx.heap.new_with_proto(fnobj); - self.bx.heap.set_object_storage_vec2(scope); - self.bx.heap.clear_object_deep(scope); - - let trap = self.bx.threads.cur().trap.pass(); - // Map positional (unnamed) vec args to named function parameters, - // and merge named map args directly. - let vec_len = self.bx.heap.vec_len(args_obj); - for i in 0..vec_len { - let kv = self.bx.heap.vec_key_value(args_obj, i, trap); - if kv.key.is_nil() { - // Unnamed positional arg — map to named parameter via unnamed_fn_arg - self.bx.heap.unnamed_fn_arg(scope, kv.value, trap); - } else { - // Named arg — insert directly - self.bx.heap.vec_push(scope, kv.key, kv.value, trap); - } - } - // Copy map entries (like `self`, `ui`) from args_obj to scope - let map_entries: Vec<_> = self - .bx - .heap - .map_ref(args_obj) - .iter() - .map(|(k, v)| (*k, v.value)) - .collect(); - for (k, v) in map_entries { - self.bx.heap.force_value_in_map(scope, k, v); - } - - self.bx.heap.set_object_deep(scope); - self.bx.heap.set_object_storage_auto(scope); - self.call_with_scope(scope, me) - } - - fn format_error(&self, err: &crate::trap::ScriptError) -> String { - let loc = err - .value - .as_err() - .and_then(|ptr| self.bx.code.ip_to_loc(ptr.ip)); - if let Some(loc) = loc { - format!( - "{}:{}:{}: {} ({}:{})", - loc.file, loc.line, loc.col, err.message, err.origin_file, err.origin_line - ) - } else { - format!("{}: {}", err.origin_file, err.message) - } - } - - /// Drain pending errors into formatted strings instead of logging them. - /// Note that errors raised DURING execution are drained by `run_core` - /// itself (into the log, or into the captured-error sink when one is - /// installed) — this only sees errors still queued afterwards. Hosts that - /// need reliable capture install a sink: `vm.bx.captured_errors = - /// Some(Vec::new())` before running, then take it after. - pub fn take_errors(&mut self) -> Vec { - let mut out = std::mem::take(&mut self.bx.captured_errors).unwrap_or_default(); - loop { - let err = self.bx.threads.cur().trap.err.borrow_mut().pop_front(); - let Some(err) = err else { - break; - }; - out.push(self.format_error(&err)); - } - out - } - - /// Drain and log any pending errors in the error queue. - /// Call this after operations that may produce errors outside of run_core - /// (e.g., script_apply calls from Rust code). - /// - /// When a captured-error sink is installed (`bx.captured_errors`), errors - /// go there instead of the log — even while `silence_errors` is set, so a - /// host can collect diagnostics from streaming/incremental evals that - /// would otherwise be dropped as meaningless-mid-stream. - pub fn drain_errors(&mut self) { - loop { - let err = self.bx.threads.cur().trap.err.borrow_mut().pop_front(); - if let Some(err) = err { - if self.bx.captured_errors.is_some() { - let formatted = self.format_error(&err); - if let Some(sink) = self.bx.captured_errors.as_mut() { - sink.push(formatted); - } - continue; - } - if self.bx.silence_errors { - continue; - } - if let Some(ptr) = err.value.as_err() { - if let Some(loc2) = self.bx.code.ip_to_loc(ptr.ip) { - log_with_level( - &loc2.file, - loc2.line, - loc2.col, - loc2.line, - loc2.col, - format!("{} ({}:{})", err.message, err.origin_file, err.origin_line), - LogLevel::Error, - ); - } else { - // No location info, still log the error - log_with_level( - &err.origin_file, - err.origin_line, - 0, - err.origin_line, - 0, - err.message.clone(), - LogLevel::Error, - ); - } - } else { - // Error without IP, still log - log_with_level( - &err.origin_file, - err.origin_line, - 0, - err.origin_line, - 0, - err.message.clone(), - LogLevel::Error, - ); - } - } else { - break; - } - } - } - - #[inline(never)] - #[cold] - fn handle_errors(&mut self) { - if self.bx.threads.cur_ref().call_stack_has_try() { - // Discard younger calls until the active frame owns a try frame. - while !self.bx.threads.cur_ref().call_has_try() { - let Some(call) = self.bx.threads.cur().calls.pop() else { - self.bail("calls empty while unwinding to a try frame"); - return; - }; - let return_ip = call.return_ip; - self.bx - .threads - .cur() - .truncate_bases(call.bases, &mut self.bx.heap); - let Some(return_ip) = return_ip else { - self.bail("root call reached while unwinding to a try frame"); - return; - }; - self.bx.threads.cur().trap.ip = return_ip; - } - // pop all errors - self.bx.threads.cur().trap.err.borrow_mut().clear(); - let try_frame = self.bx.threads.cur().tries.pop().unwrap(); - self.bx - .threads - .cur() - .truncate_bases(try_frame.bases, &mut self.bx.heap); - if try_frame.push_nil { - self.bx.threads.cur().push_stack_unchecked(NIL) - } - self.bx - .threads - .cur() - .trap - .goto(try_frame.start_ip + try_frame.jump); - } else { - // An uncaught error terminates this evaluation before another - // instruction (and therefore another host effect) can execute. - let error = self - .bx - .threads - .cur_ref() - .trap - .err - .borrow() - .front() - .map(|e| e.value); - self.drain_errors(); - if let Some(error) = error { - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(error))); - } - } - } - - fn check_run_budget(&mut self) -> Option { - let budget = self.bx.run_budget.as_mut()?; - budget.instructions_until_sample = budget.instructions_until_sample.saturating_sub(1); - if budget.instructions_until_sample > 0 { - return None; - } - budget.instructions_until_sample = budget.sample_interval_instructions; - - let now = Instant::now(); - if now >= budget.hard_deadline { - return Some(ScriptRunBudgetHit::Hard); - } - if now >= budget.soft_deadline { - return Some(ScriptRunBudgetHit::Soft); - } - None - } - - #[inline(never)] - #[cold] - fn bail_resource_limit(&mut self, message: &'static str) -> ScriptValue { - let err = script_err_limit!(self.bx.threads.cur_ref().trap, "{message}"); - // Resource-limit failures are uncatchable. Drain pre-existing script - // errors before the Bail unwinds to a clean root state. - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - self.handle_trap_on() - .expect("resource-limit Bail must return a VM value") - } - - fn handle_execution_limit_failure(&mut self) -> Option { - let stack_limit_exceeded = self.bx.threads.cur().take_stack_limit_exceeded(); - let call_frame_limit_exceeded = self.bx.threads.cur().take_call_frame_limit_exceeded(); - if stack_limit_exceeded { - return Some(self.bail_resource_limit("script operand stack limit exceeded")); - } - if call_frame_limit_exceeded { - return Some(self.bail_resource_limit("script call frame limit exceeded")); - } - None - } - - fn handle_trap_on(&mut self) -> Option { - if self.bx.threads.cur().trap.on.get().is_none() { - return None; - } - Some(match self.bx.threads.cur().trap.on.take().unwrap() { - ScriptTrapOn::Pause | ScriptTrapOn::TimeBudgetYield => NIL, - ScriptTrapOn::Return(value) => { - self.bx.threads.cur().instruction_limit_remaining = None; - value - } - ScriptTrapOn::Bail(value) => { - // Stack corruption or hard failure: unwind calls to find our root frame - // and truncate all stacks back to clean state. - loop { - if let Some(call) = self.bx.threads.cur().calls.pop() { - self.bx - .threads - .cur() - .truncate_bases(call.bases, &mut self.bx.heap); - if call.return_ip.is_none() { - break; - } - } else { - break; - } - } - self.bx.threads.cur().instruction_limit_remaining = None; - value - } - }) - } - - pub fn run_core(&mut self) -> ScriptValue { - loop { - if let Some(value) = self.handle_execution_limit_failure() { - return value; - } - - if self.bx.heap.take_heap_limit_exceeded() { - let err = script_err_limit!( - self.bx.threads.cur_ref().trap, - "script heap allocation limit exceeded" - ); - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - if let Some(value) = self.handle_trap_on() { - return value; - } - } - - if self.bx.heap.take_string_limit_exceeded() { - let err = script_err_limit!( - self.bx.threads.cur_ref().trap, - "script string allocation limit exceeded" - ); - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - if let Some(value) = self.handle_trap_on() { - return value; - } - } - - let instruction_limit_exceeded = if let Some(remaining) = - self.bx.threads.cur().instruction_limit_remaining.as_mut() - { - if *remaining == 0 { - true - } else { - *remaining -= 1; - false - } - } else { - false - }; - if instruction_limit_exceeded { - let err = script_err_limit!( - self.bx.threads.cur_ref().trap, - "script instruction limit exceeded" - ); - // drain_errors routes to the captured-error sink, the log, or - // the void depending on host configuration. - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - if let Some(value) = self.handle_trap_on() { - return value; - } - } - - if let Some(hit) = self.check_run_budget() { - match hit { - ScriptRunBudgetHit::Soft => { - self.bx.threads.cur().is_paused = true; - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::TimeBudgetYield)); - } - ScriptRunBudgetHit::Hard => { - let err = script_err_limit!( - self.bx.threads.cur().trap.pass(), - "script time budget exceeded" - ); - // A hard budget hit is an uncatchable VM bail. Move its - // diagnostic out of the thread queue before unwinding so - // a later run cannot observe it as a script error. - self.drain_errors(); - self.bx - .threads - .cur() - .trap - .on - .set(Some(ScriptTrapOn::Bail(err))); - } - } - if let Some(value) = self.handle_trap_on() { - return value; - } - } - - let thread = self.bx.threads.cur(); - let body_index = thread.trap.ip.body as usize; - let ip_index = thread.trap.ip.index as usize; - - // Copy the opcode while the body borrow is live. Native calls may - // re-enter the VM and replace a body's parser, so a cached pointer - // into its opcode buffer cannot outlive this iteration. - let opcode = { - let bodies = self.bx.code.bodies.borrow(); - let body = &bodies[body_index]; - body.parser.opcodes.get(ip_index).copied() - }; - - let Some(opcode) = opcode else { - // If there's a value on the stack, return it (for expression-style scripts) - let stack_len = self.bx.threads.cur().stack.len(); - if stack_len > 0 { - return self.bx.threads.cur().pop_stack_value(); - } - return NIL; - }; - - if let Some((opcode, args)) = opcode.as_opcode() { - self.opcode(opcode, args); - if let Some(value) = self.handle_execution_limit_failure() { - return value; - } - // if exception tracing - is_empty() is faster than len()>0 - if !self.bx.threads.cur().trap.err.borrow().is_empty() { - self.handle_errors(); - } - if let Some(value) = self.handle_trap_on() { - return value; - } - } else { - // its a direct value-to-stack - self.bx.threads.cur().push_stack_value(opcode); - self.bx.threads.cur().trap.goto_next(); - } - } - } - - pub fn run_root(&mut self, body_id: u16) -> ScriptValue { - // Extract values from bodies before modifying thread state - let (scope, me) = { - let bodies = self.bx.code.bodies.borrow(); - ( - bodies[body_id as usize].scope.obj, - bodies[body_id as usize].me.obj, - ) - }; - - if !self.bx.threads.cur().push_call_frame(CallFrame { - bases: StackBases { - tries: 0, - loops: 0, - stack: 0, - scope: 0, - mes: 0, - }, - args: Default::default(), - return_ip: None, - }) { - return self - .handle_execution_limit_failure() - .expect("a rejected root frame raises a limit failure"); - } - - self.bx.threads.cur().scopes.push(scope); - self.bx.threads.cur().mes.push(ScriptMe::Object(me)); - - self.bx.threads.cur().trap.ip.body = body_id; - self.bx.threads.cur().trap.ip.index = 0; - - // the main interpreter loop - self.run_core() - } - - /// Checks if the value has an apply transform and calls it, returning the transformed value. - /// Returns None if no transform exists, Some(transformed) if a transform was applied. - pub fn call_apply_transform(&mut self, value: ScriptValue) -> Option { - if let Some(obj) = value.as_object() { - if let Some(ni) = self.bx.heap.objects[obj].tag.as_apply_transform() { - let func_ptr: *const dyn Fn(&mut ScriptVm, ScriptObject) -> ScriptValue = { - let native = self.bx.code.native.borrow(); - &*native.functions[ni.index as usize] as *const _ - }; - // Pause thread before native call so re-entrant calls get a different thread - self.bx.threads.cur().is_paused = true; - let result = unsafe { (*func_ptr)(self, obj) }; - // Only unpause if native didn't explicitly pause - if !matches!( - self.bx.threads.cur().trap.on.get(), - Some(ScriptTrapOn::Pause) - ) { - self.bx.threads.cur().is_paused = false; - } - return Some(result); - } - } else if let Some(arr) = value.as_array() { - if let Some(ni) = self.bx.heap.arrays[arr].tag.as_apply_transform() { - // For arrays, we need to create a temporary args object - let args_obj = self.bx.heap.new_object(); - self.bx - .heap - .set_value_def(args_obj, id!(self).into(), value); - let func_ptr: *const dyn Fn(&mut ScriptVm, ScriptObject) -> ScriptValue = { - let native = self.bx.code.native.borrow(); - &*native.functions[ni.index as usize] as *const _ - }; - // Pause thread before native call so re-entrant calls get a different thread - self.bx.threads.cur().is_paused = true; - let result = unsafe { (*func_ptr)(self, args_obj) }; - // Only unpause if native didn't explicitly pause - if !matches!( - self.bx.threads.cur().trap.on.get(), - Some(ScriptTrapOn::Pause) - ) { - self.bx.threads.cur().is_paused = false; - } - return Some(result); - } - } - None - } - - pub fn resume(&mut self) -> ScriptValue { - self.bx.threads.cur().is_paused = false; - self.run_core() - } - - pub fn cast_to_f64(&self, v: ScriptValue) -> f64 { - self.bx - .heap - .cast_to_f64(v, self.bx.threads.cur_ref().trap.ip) - } - - pub fn handle_type(&self, id: LiveId) -> ScriptHandleType { - *self.bx.code.native.borrow().handle_type.get(&id).unwrap() - } - - pub fn new_handle_type(&mut self, id: LiveId) -> ScriptHandleType { - self.bx - .code - .native - .borrow_mut() - .new_handle_type(&mut self.bx.heap, id) - } - - pub fn downcast_handle_gc( - &self, - handle: ScriptHandle, - ) -> Option<&T> { - self.bx.heap.handle_ref::(handle) - } - - pub fn add_handle_method( - &mut self, - ht: ScriptHandleType, - method: LiveId, - args: &[(LiveId, ScriptValue)], - f: F, - ) where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - self.bx.code.native.borrow_mut().add_type_method( - &mut self.bx.heap, - ht.to_redux(), - method, - args, - f, - ) - } - - pub fn set_handle_setter(&mut self, ht: ScriptHandleType, f: F) - where - F: Fn(&mut ScriptVm, ScriptValue, LiveId, ScriptValue) -> ScriptValue + 'static, - { - self.bx - .code - .native - .borrow_mut() - .set_type_setter(ht.to_redux(), f) - } - - pub fn set_handle_getter(&mut self, ht: ScriptHandleType, f: F) - where - F: Fn(&mut ScriptVm, ScriptValue, LiveId) -> ScriptValue + 'static, - { - self.bx - .code - .native - .borrow_mut() - .set_type_getter(ht.to_redux(), f) - } - - /// Register a catch-all method dispatcher for a handle type. - /// When a method call is made on a handle that has no specific method - /// registered for that name, this call function is invoked with - /// (vm, args_object, method). The args object has `self` set - /// and all call arguments collected, just like a normal native method. - pub fn set_handle_call(&mut self, ht: ScriptHandleType, f: F) - where - F: Fn(&mut ScriptVm, ScriptObject, LiveId) -> ScriptValue + 'static, - { - self.bx - .code - .native - .borrow_mut() - .set_type_call(ht.to_redux(), f) - } - - pub fn new_module(&mut self, id: LiveId) -> ScriptObject { - self.bx.heap.new_module(id) - } - - pub fn module(&mut self, id: LiveId) -> ScriptObject { - self.bx.heap.module(id) - } - - pub fn map_mut_with R>( - &mut self, - object: ScriptObject, - f: F, - ) -> R { - let before = self.bx.heap.objects[object].retained_bytes(); - let mut map = ScriptObjectMap::default(); - std::mem::swap(&mut map, &mut self.bx.heap.objects[object].map); - let r = f(self, &mut map); - std::mem::swap(&mut map, &mut self.bx.heap.objects[object].map); - self.bx.heap.note_object_storage_growth(object, before); - r - } - - /// Walk the prototype chain from root (oldest ancestor) to leaf (the object itself), - /// calling the closure for each object's map. This is useful for collecting inherited - /// properties where child properties should override parent properties. - pub fn proto_map_iter_mut_with( - &mut self, - object: ScriptObject, - f: &mut F, - ) { - // First recurse to the prototype (if any), so we process from root to leaf - if let Some(proto) = self.bx.heap.objects[object].proto.as_object() { - self.proto_map_iter_mut_with(proto, f); - } - // Then process this object's map - let before = self.bx.heap.objects[object].retained_bytes(); - let mut map = ScriptObjectMap::default(); - std::mem::swap(&mut map, &mut self.bx.heap.objects[object].map); - f(self, &mut map); - std::mem::swap(&mut map, &mut self.bx.heap.objects[object].map); - self.bx.heap.note_object_storage_growth(object, before); - } - - pub fn vec_with R>( - &mut self, - object: ScriptObject, - f: F, - ) -> R { - let mut vec = Vec::new(); - std::mem::swap(&mut vec, &mut self.bx.heap.objects[object].vec); - let r = f(self, &vec); - std::mem::swap(&mut vec, &mut self.bx.heap.objects[object].vec); - r - } - - pub fn vec_mut_with) -> R>( - &mut self, - object: ScriptObject, - f: F, - ) -> R { - let before = self.bx.heap.objects[object].retained_bytes(); - let mut vec = Vec::new(); - std::mem::swap(&mut vec, &mut self.bx.heap.objects[object].vec); - let r = f(self, &mut vec); - std::mem::swap(&mut vec, &mut self.bx.heap.objects[object].vec); - self.bx.heap.note_object_storage_growth(object, before); - r - } - - pub fn string_with R>( - &mut self, - value: ScriptValue, - f: F, - ) -> Option { - if let Some(s) = value.as_string() { - if let Some(s) = &self.bx.heap.strings[s] { - let s = s.string.clone(); - return Some(f(self, &s.0)); - } - return None; - } - if let Some(r) = value.as_inline_string(|s| f(self, s)) { - return Some(r); - } - None - } - - pub fn new_string_with(&mut self, f: F) -> ScriptValue { - let mut out = if let Some(s) = self.bx.heap.strings_reuse.pop() { - s - } else { - String::new() - }; - f(self, &mut out); - self.bx.heap.intern_or_store_string(out) - } - - pub fn add_method( - &mut self, - module: ScriptObject, - method: LiveId, - args: &[(LiveId, ScriptValue)], - f: F, - ) where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - self.bx - .code - .native - .borrow_mut() - .add_method(&mut self.bx.heap, module, method, args, f) - } - - fn apply_injected_globals_to_scope(&mut self, scope_obj: ScriptObject) { - if self.bx.injected_globals.is_empty() { - return; - } - let globals: Vec<(LiveId, ScriptValue)> = self - .bx - .injected_globals - .iter() - .map(|(key, value)| (*key, *value)) - .collect(); - for (key, value) in globals { - self.bx - .heap - .force_value_in_map(scope_obj, key.into(), value); - } - } - - fn apply_injected_globals_to_all_scopes(&mut self) { - if self.bx.injected_globals.is_empty() { - return; - } - let scope_objects: Vec = { - let bodies = self.bx.code.bodies.borrow(); - bodies.iter().map(|body| body.scope.as_object()).collect() - }; - for scope_obj in scope_objects { - self.apply_injected_globals_to_scope(scope_obj); - } - } - - pub fn set_injected_global(&mut self, key: LiveId, value: ScriptValue) { - self.bx.injected_globals.insert(key, value); - self.apply_injected_globals_to_all_scopes(); - } - - /// Registers a native function to be used as an apply_transform and returns its NativeId. - /// This is used for creating objects that transform to a computed value when applied. - pub fn add_apply_transform_fn(&mut self, f: F) -> NativeId - where - F: Fn(&mut ScriptVm, ScriptObject) -> ScriptValue + 'static, - { - self.bx.code.native.borrow_mut().add_apply_transform_fn(f) - } - - pub fn add_script_mod(&mut self, new_mod: ScriptMod) -> u16 { - // Register this crate's manifest path for crate path resolution - let crate_name = new_mod.module_path.split("::").next().unwrap_or(""); - if !crate_name.is_empty() { - self.bx.code.crate_manifests.borrow_mut().insert( - crate_name.replace('-', "_"), - new_mod.cargo_manifest_path.clone(), - ); - } - - let scope_obj = self.bx.heap.new_with_proto(id!(scope).into()); - self.bx.heap.set_object_deep(scope_obj); - self.bx - .heap - .set_value_def(scope_obj, id!(mod).into(), self.bx.heap.modules.into()); - self.apply_injected_globals_to_scope(scope_obj); - let scope = self.bx.heap.new_object_ref(scope_obj); - let me_obj = self.bx.heap.new_with_proto(id!(root_me).into()); - let me = self.bx.heap.new_object_ref(me_obj); - let key = ScriptModKey::from_script_mod(&new_mod); - let override_code = self - .bx - .code - .script_mod_overrides - .borrow() - .get(&key) - .cloned(); - let effective_code = override_code - .clone() - .unwrap_or_else(|| new_mod.code.clone()); - - let new_body = ScriptBody { - source: ScriptSource::Mod(new_mod), - effective_code, - tokenizer: ScriptTokenizer::default(), - parser: ScriptParser::default(), - scope, - me, - checkpoint: None, - source_len: 0, - }; - let mut bodies = self.bx.code.bodies.borrow_mut(); - for (i, body) in bodies.iter_mut().enumerate() { - if let ScriptSource::Mod(script_mod) = &body.source { - if let ScriptSource::Mod(new_mod) = &new_body.source { - if script_mod.file == new_mod.file - && script_mod.line == new_mod.line - && script_mod.column == new_mod.column - { - let values_changed = script_mod.values != new_mod.values; - body.source = new_body.source; - body.scope = new_body.scope; - body.me = new_body.me; - if body.effective_code != new_body.effective_code || values_changed { - body.effective_code = new_body.effective_code; - body.tokenizer = ScriptTokenizer::default(); - body.parser = ScriptParser::default(); - body.checkpoint = None; - body.source_len = 0; - } - return i as u16; - } - } - } - } - let i = bodies.len(); - bodies.push(new_body); - i as u16 - } - - pub fn eval(&mut self, script_mod: ScriptMod) -> ScriptValue { - self.eval_with_source(script_mod, ScriptObject::ZERO) - } - - pub fn eval_with_source(&mut self, script_mod: ScriptMod, source: ScriptObject) -> ScriptValue { - let body_id = self.add_script_mod(script_mod); - - // Set __script_source__ on the scope if source is provided - // If source has FROM_EVAL flag, use its prototype instead - if source != ScriptObject::ZERO { - let actual_source = if self.bx.heap.is_from_eval(source) { - // Use the prototype of the FROM_EVAL object - if let Some(proto) = self.bx.heap.proto(source).as_object() { - proto - } else { - source - } - } else { - source - }; - let scope = self.bx.code.bodies.borrow()[body_id as usize].scope.obj; - self.bx - .heap - .set_value_def(scope, id!(__script_source__).into(), actual_source.into()); - } - - let mut bodies = self.bx.code.bodies.borrow_mut(); - let body = &mut bodies[body_id as usize]; - - if let ScriptSource::Mod(script_mod) = &body.source { - if body.source_len == 0 { - body.tokenizer.clear(); - body.parser = ScriptParser::default(); - body.tokenizer - .tokenize(&body.effective_code, &mut self.bx.heap); - body.parser.parse( - &body.tokenizer, - &script_mod.file, - (script_mod.line, script_mod.column), - &script_mod.values, - ); - body.source_len = body.effective_code.len(); - } - drop(bodies); - // lets point our thread to it - let result = self.run_root(body_id); - // Mark the result object with FROM_EVAL flag - if let Some(result_obj) = result.as_object() { - self.bx.heap.set_from_eval(result_obj); - } - - result - } else { - NIL - } - } - - /// Evaluate script incrementally by appending new source to an existing body. - /// - /// Pass the full growing source code string each time. On first call, creates - /// the body and tokenizes/parses everything. On subsequent calls, computes the - /// delta (new chars since last call), restores the parser checkpoint (removing - /// auto-close opcodes), tokenizes only the new chars, continues parsing, then - /// auto-closes again for execution. Always re-executes from opcode 0. - pub fn eval_with_append_source( - &mut self, - script_mod: ScriptMod, - code: &str, - source: ScriptObject, - ) -> ScriptValue { - // Look for an existing body with matching file/line/column - let existing_body_id = { - let bodies = self.bx.code.bodies.borrow(); - let mut found = None; - for (i, body) in bodies.iter().enumerate() { - if let ScriptSource::Mod(existing_mod) = &body.source { - if existing_mod.file == script_mod.file - && existing_mod.line == script_mod.line - && existing_mod.column == script_mod.column - { - found = Some(i as u16); - break; - } - } - } - found - }; - - let body_id = match existing_body_id { - Some(id) => id, - None => self.add_script_mod(script_mod), - }; - - // Set __script_source__ on the scope if source is provided - if source != ScriptObject::ZERO { - let actual_source = if self.bx.heap.is_from_eval(source) { - if let Some(proto) = self.bx.heap.proto(source).as_object() { - proto - } else { - source - } - } else { - source - }; - let scope = self.bx.code.bodies.borrow()[body_id as usize].scope.obj; - self.bx - .heap - .set_value_def(scope, id!(__script_source__).into(), actual_source.into()); - } - - let mut bodies = self.bx.code.bodies.borrow_mut(); - let body = &mut bodies[body_id as usize]; - - if let ScriptSource::Mod(existing_mod) = &body.source { - // Restore checkpoint (removes auto-close opcodes from previous run) - if let Some(cp) = body.checkpoint.take() { - body.parser.restore_checkpoint(cp); - } - - let prev_len = body.source_len; - // Check if the content has diverged (not just appended to). - // Compare the new code's prefix against what the tokenizer already has. - let content_changed = prev_len > 0 - && (code.len() < prev_len - || code[..prev_len] != body.tokenizer.original[..prev_len]); - - if content_changed { - // Content changed entirely — reset and re-tokenize from scratch - body.tokenizer.clear(); - body.parser = ScriptParser::default(); - body.checkpoint = None; - body.source_len = code.len(); - body.tokenizer.tokenize(code, &mut self.bx.heap); - } else if code.len() >= prev_len { - body.source_len = code.len(); - let new_chars = &code[prev_len..]; - if !new_chars.is_empty() { - body.tokenizer.tokenize(new_chars, &mut self.bx.heap); - } - } - - // If we stopped mid-string, intern the partial content so the parser - // can emit the real string value into opcodes for incremental rendering. - let unfinished = body.tokenizer.intern_unfinished_string(&mut self.bx.heap); - - // Incremental parse: continue from checkpoint, auto-close for execution - let cp = body.parser.parse_streaming( - &body.tokenizer, - &existing_mod.file, - (existing_mod.line, existing_mod.column), - &existing_mod.values, - unfinished, - ); - - body.checkpoint = Some(cp); - - drop(bodies); - // Silence runtime errors during incremental eval — incomplete code - // will inevitably produce errors that are meaningless until the - // source is fully received. - self.bx.silence_errors = true; - let result = self.run_root(body_id); - self.bx.silence_errors = false; - if let Some(result_obj) = result.as_object() { - self.bx.heap.set_from_eval(result_obj); - } - result - } else { - NIL - } - } -} - -pub struct ScriptVmBase { - pub void: usize, - pub code: ScriptCode, - pub heap: ScriptHeap, - pub threads: ScriptThreads, - pub injected_globals: std::collections::HashMap, - pub is_reload: bool, - pub debug_trace: bool, - pub silence_errors: bool, - /// Trusted raw Makepad hosts may log; standalone Octoscript disables this - /// before either canonical or compatibility source can execute. - pub allow_debug_output: bool, - /// When Some, drained errors are pushed here (formatted) instead of being - /// logged or dropped — even under `silence_errors`. Install before an - /// eval/call, take after, to feed diagnostics back to a host (e.g. an AI - /// agent editing the script live). - pub captured_errors: Option>, - pub run_budget: Option, -} - -impl ScriptVmBase { - pub fn empty() -> Self { - Self { - void: 0, - code: ScriptCode::default(), - threads: ScriptThreads::empty(), - heap: ScriptHeap::empty(), - injected_globals: Default::default(), - is_reload: false, - debug_trace: false, - silence_errors: false, - allow_debug_output: true, - captured_errors: None, - run_budget: None, - } - } - - pub fn new() -> Self { - let mut heap = ScriptHeap::empty(); - let mut native = ScriptNative::new(&mut heap); - define_math_module(&mut heap, &mut native); - define_std_module(&mut heap, &mut native); - define_regex_module(&mut heap, &mut native); - define_html_module(&mut heap, &mut native); - define_shader_module(&mut heap, &mut native); - define_gc_module(&mut heap, &mut native); - let pod_builtins = define_pod_module(&mut heap, &mut native); - - let builtins = ScriptBuiltins::new(&mut heap, pod_builtins); - - Self { - void: 0, - code: ScriptCode { - builtins, - native: RefCell::new(native), - bodies: Default::default(), - crate_manifests: Default::default(), - script_mod_overrides: Default::default(), - }, - threads: ScriptThreads::new(), - heap: heap, - injected_globals: Default::default(), - is_reload: false, - debug_trace: false, - silence_errors: false, - allow_debug_output: true, - captured_errors: None, - run_budget: None, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Script, ScriptHook, Default)] - struct ApplyEvalParityTest { - #[source] - source: ScriptObjectRef, - #[live] - is_even: f32, - } - - #[test] - fn script_apply_eval_refreshes_interpolated_values_on_reused_callsite() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - - let mut item = ApplyEvalParityTest::default(); - let obj = vm.heap_mut().new_object(); - item.source = vm.heap_mut().new_object_ref(obj); - - for idx in 0..6 { - let is_even_f = if idx % 2 == 0 { 1.0f32 } else { 0.0f32 }; - script_apply_eval!(vm, item, { - is_even: #(is_even_f) - }); - assert_eq!( - item.is_even, is_even_f, - "reused script_apply_eval callsite kept stale value at iteration {}", - idx - ); - } - } - - #[test] - fn streaming_try_catch_restores_the_contextual_separator_state() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - let script_mod = || ScriptMod { - file: "streaming-try-catch.octoscript".to_owned(), - ..Default::default() - }; - let prefix = "use mod.std.assert\n\ - let catch = 41\n\ - try {\n\ - assert(false)\n\ - } catch"; - - let _ = vm.eval_with_append_source(script_mod(), prefix, ScriptObject::ZERO); - let result = vm.eval_with_append_source( - script_mod(), - &format!("{prefix} catch + 1\n;"), - ScriptObject::ZERO, - ); - - assert_eq!(result.as_f64(), Some(42.0)); - } - - #[test] - fn streaming_logical_precedence_repatches_pending_short_circuits() { - for (prefix, suffix, expected) in [ - ("true || false ", "&& false", true), - ("false && true ", "|| true", true), - ("true == 2 ", "> 1", true), - ] { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - let module = || ScriptMod { - file: "streaming-precedence.octoscript".into(), - ..Default::default() - }; - let partial = vm.with_instruction_limit(1000, |vm| { - vm.eval_with_append_source(module(), prefix, ScriptObject::ZERO) - }); - assert!( - !partial.is_err(), - "unfinished logical expression must terminate: {prefix}" - ); - let result = vm.with_instruction_limit(1000, |vm| { - vm.eval_with_append_source( - module(), - &format!("{prefix}{suffix}\n;"), - ScriptObject::ZERO, - ) - }); - assert_eq!(result.as_bool(), Some(expected), "{prefix}{suffix}"); - } - } - - #[test] - fn streaming_legacy_try_ok_repatches_the_success_jump() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - let script_mod = || ScriptMod { - file: "streaming-try-ok.octoscript".to_owned(), - ..Default::default() - }; - let prefix = "let marker = 0\ntry { 7 } { marker = 1 }"; - - let _ = vm.eval_with_append_source(script_mod(), prefix, ScriptObject::ZERO); - let result = vm.eval_with_append_source( - script_mod(), - &format!("{prefix} ok {{ marker = 2 }}\nreturn marker\n;"), - ScriptObject::ZERO, - ); - - assert_eq!(result.as_u40(), Some(2)); - } - - #[test] - fn hard_time_budget_drains_its_uncatchable_error() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - vm.bx.captured_errors = Some(Vec::new()); - vm.bx.run_budget = Some(ScriptRunBudget::from_durations( - Duration::ZERO, - Duration::ZERO, - 1, - )); - - let result = vm.eval(ScriptMod { - file: "hard-time-budget.octoscript".to_owned(), - code: "loop {}\n;".to_owned(), - ..Default::default() - }); - - assert!(result.is_err()); - assert!(vm.bx.threads.cur_ref().trap.err.borrow().is_empty()); - assert!(vm - .take_errors() - .iter() - .any(|diagnostic| diagnostic.contains("script time budget exceeded"))); - } - - #[test] - fn string_limit_bails_instead_of_entering_a_try_fallback() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - vm.bx.heap.set_max_string_bytes(Some(8)); - vm.bx.captured_errors = Some(Vec::new()); - - let result = vm.eval(ScriptMod { - file: "string-limit.octoscript".to_owned(), - code: "let payload = \"x\"\n\ - let index = 0\n\ - while (index < 3) {\n\ - payload += payload\n\ - index += 1\n\ - }\n\ - try { payload + payload } { \"ok\" }\n\ - ;" - .to_owned(), - ..Default::default() - }); - - assert!(result.is_err()); - assert!(vm.bx.threads.cur_ref().trap.err.borrow().is_empty()); - assert!(vm - .take_errors() - .iter() - .any(|diagnostic| diagnostic.contains("script string allocation limit exceeded"))); - } - - #[test] - fn heap_limit_bails_instead_of_entering_a_try_fallback() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - vm.bx.heap.reconcile_heap_bytes(); - let baseline = vm.bx.heap.accounted_heap_bytes(); - vm.bx.heap.set_max_heap_bytes(Some(baseline + 256 * 1024)); - vm.bx.captured_errors = Some(Vec::new()); - - let result = vm.eval(ScriptMod { - file: "heap-limit.octoscript".to_owned(), - code: "let values = []\n\ - try { values[268435456] = 1 } { \"ok\" }\n\ - ;" - .to_owned(), - ..Default::default() - }); - - assert!(result.is_err()); - assert!(vm.bx.threads.cur_ref().trap.err.borrow().is_empty()); - assert!(vm - .take_errors() - .iter() - .any(|diagnostic| diagnostic.contains("script heap allocation limit exceeded"))); - } - - #[test] - fn return_does_not_pop_to_me_after_an_operand_stack_limit() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - let receiver = vm.heap_mut().new_object(); - let pop_to_me = OpcodeArgs(OpcodeArgs::POP_TO_ME_FLAG); - - { - let thread = vm.thread_mut(); - thread.stack.push(7.into()); - thread.mes.push(ScriptMe::Object(receiver)); - assert!(thread.push_call_frame(CallFrame { - bases: StackBases::default(), - args: OpcodeArgs::NONE, - return_ip: None, - })); - assert!(thread.push_call_frame(CallFrame { - bases: StackBases { - stack: 1, - mes: 1, - ..Default::default() - }, - args: pop_to_me, - return_ip: Some(ScriptIp::default()), - })); - } - - vm.with_stack_value_limit(1, |vm| { - vm.opcode( - Opcode::RETURN, - OpcodeArgs(OpcodeArgs::NIL.0 | OpcodeArgs::POP_TO_ME_FLAG), - ); - }); - - assert!(vm.thread().has_execution_limit_exceeded()); - assert_eq!(vm.thread().stack.len(), 1); - assert_eq!(vm.thread().stack[0].as_f64(), Some(7.0)); - assert_eq!(vm.bx.heap.vec_len(receiver), 0); - } - - #[test] - fn byte_array_string_conversion_stops_at_the_string_limit() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - vm.bx.heap.set_max_string_bytes(Some(8)); - vm.bx.captured_errors = Some(Vec::new()); - - let bytes = vm.bx.heap.new_array_from_vec_u8(vec![0xFF; 16]); - vm.set_injected_global(id!(bytes), bytes.into()); - - let result = vm.eval(ScriptMod { - file: "byte-array-string-limit.octoscript".to_owned(), - code: "try { bytes.to_string() } { \"ok\" }\n;".to_owned(), - ..Default::default() - }); - - assert!(result.is_err()); - assert!(vm - .take_errors() - .iter() - .any(|diagnostic| diagnostic.contains("script string allocation limit exceeded"))); - } - - #[test] - fn byte_array_string_conversion_preserves_lossy_utf8_without_a_limit() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - - let bytes = vm.bx.heap.new_array_from_vec_u8(vec![b'a', 0xFF, b'b']); - vm.set_injected_global(id!(bytes), bytes.into()); - - let result = vm.eval(ScriptMod { - file: "byte-array-lossy-utf8.octoscript".to_owned(), - code: "bytes.to_string()\n;".to_owned(), - ..Default::default() - }); - - assert_eq!( - vm.bx.heap.string_with(result, |_, value| value.to_owned()), - Some("a\u{FFFD}b".to_owned()) - ); - } - - #[test] - fn bounded_string_helpers_preserve_their_normal_results() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - - for (file, code, expected) in [ - ( - "string-replace.octoscript", - "\"abcd\".replace(\"b\", \"XX\")\n;", - "aXXcd", - ), - ( - "string-url-encode.octoscript", - "\"a b!\".url_encode()\n;", - "a%20b%21", - ), - ( - "string-url-decode.octoscript", - "\"a%20b%21\".url_decode()\n;", - "a b!", - ), - ] { - let result = vm.eval(ScriptMod { - file: file.to_owned(), - code: code.to_owned(), - ..Default::default() - }); - assert_eq!( - vm.bx.heap.string_with(result, |_, value| value.to_owned()), - Some(expected.to_owned()) - ); - } - } - - #[test] - fn byte_array_json_input_stops_at_the_string_limit() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - vm.bx.heap.set_max_string_bytes(Some(8)); - vm.bx.captured_errors = Some(Vec::new()); - - let bytes = vm - .bx - .heap - .new_array_from_vec_u8(br#"{"value": 12345}"#.to_vec()); - vm.set_injected_global(id!(bytes), bytes.into()); - - let result = vm.eval(ScriptMod { - file: "byte-array-json-limit.octoscript".to_owned(), - code: "try { bytes.parse_json() } { \"ok\" }\n;".to_owned(), - ..Default::default() - }); - - assert!(result.is_err()); - assert!(vm - .take_errors() - .iter() - .any(|diagnostic| diagnostic.contains("script string allocation limit exceeded"))); - } - - #[test] - fn malformed_ok_end_bails_instead_of_ignoring_the_missing_try_frame() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - - vm.handle_ok_end(); - - assert!(matches!( - vm.bx.threads.cur_ref().trap.on.get(), - Some(ScriptTrapOn::Bail(_)) - )); - } - - #[test] - fn reentrant_reload_of_the_active_body_does_not_keep_an_opcode_pointer() { - let mut host = (); - let mut std = (); - let mut vm = ScriptVm { - host: &mut host, - std: &mut std, - bx: Box::new(ScriptVmBase::new()), - }; - - let reentrant = vm.bx.heap.new_module(id!(reentrant)); - vm.add_method(reentrant, id!(reload), &[], |vm, _| { - vm.eval(ScriptMod { - file: "reentrant-reload.octoscript".to_owned(), - code: "41\n;".to_owned(), - ..Default::default() - }) - }); - - let _ = vm.eval(ScriptMod { - file: "reentrant-reload.octoscript".to_owned(), - code: "use mod.reentrant\nreentrant.reload()\n;".to_owned(), - ..Default::default() - }); - - // The replacement body intentionally makes the outer VM result - // unspecified. Under Miri or ASan this path used to dereference the - // old parser's freed opcode allocation before it could return. - } -} diff --git a/vendor/makepad/platform/script/tests/reload_defaults.rs b/vendor/makepad/platform/script/tests/reload_defaults.rs deleted file mode 100644 index b956ed8..0000000 --- a/vendor/makepad/platform/script/tests/reload_defaults.rs +++ /dev/null @@ -1,98 +0,0 @@ -use makepad_script::*; - -#[derive(Clone, Copy, Debug, PartialEq, Script, ScriptHook)] -enum ReloadEnumTest { - #[pick] - Fill, - Fixed, -} - -#[derive(Debug, Script, ScriptHook)] -struct ReloadEnumHolderTest { - #[live] - value: ReloadEnumTest, -} - -#[derive(Debug, Script, ScriptHook)] -struct ReloadObjectInnerTest { - #[live(1.0)] - value: f64, - #[rust(7u32)] - rust_value: u32, -} - -#[derive(Debug, Script, ScriptHook)] -struct ReloadObjectOuterTest { - #[live] - inner: ReloadObjectInnerTest, -} - -fn test_vm() -> ScriptVm<'static> { - let host = Box::leak(Box::new(0i32)); - let std = Box::leak(Box::new(0i32)); - ScriptVm { - host, - std, - bx: Box::new(ScriptVmBase::new()), - } -} - -#[test] -fn reload_missing_live_field_without_type_default_keeps_existing_value() { - let vm = &mut test_vm(); - - let holder_api = ReloadEnumHolderTest::script_api(vm); - let holder_value = vm.bx.heap.new_with_proto(holder_api); - let mut holder = ReloadEnumHolderTest { - value: ReloadEnumTest::Fixed, - }; - - holder.script_apply(vm, &Apply::Reload, &mut Scope::empty(), holder_value.into()); - assert_eq!(holder.value, ReloadEnumTest::Fixed); -} - -#[test] -fn reload_missing_enum_field_with_type_default_uses_pick_variant() { - let vm = &mut test_vm(); - - let enum_api = ReloadEnumTest::script_api(vm); - let enum_default = vm.bx.heap.new_with_proto(enum_api); - assert!(vm.bx.heap.set_type_default(enum_default)); - - let holder_api = ReloadEnumHolderTest::script_api(vm); - let holder_value = vm.bx.heap.new_with_proto(holder_api); - let mut holder = ReloadEnumHolderTest { - value: ReloadEnumTest::Fixed, - }; - - holder.script_apply(vm, &Apply::Reload, &mut Scope::empty(), holder_value.into()); - assert_eq!(holder.value, ReloadEnumTest::Fill); -} - -#[test] -fn reload_missing_object_field_with_type_default_refreshes_from_type_default() { - let vm = &mut test_vm(); - - let inner_api = ReloadObjectInnerTest::script_api(vm); - let inner_default = vm.bx.heap.new_with_proto(inner_api); - vm.bx.heap.set_value( - inner_default, - id!(value).into(), - 42.0.into(), - vm.bx.threads.cur().trap.pass(), - ); - assert!(vm.bx.heap.set_type_default(inner_default)); - - let outer_api = ReloadObjectOuterTest::script_api(vm); - let outer_value = vm.bx.heap.new_with_proto(outer_api); - let mut outer = ReloadObjectOuterTest { - inner: ReloadObjectInnerTest { - value: 1.0, - rust_value: 99, - }, - }; - - outer.script_apply(vm, &Apply::Reload, &mut Scope::empty(), outer_value.into()); - assert_eq!(outer.inner.value, 42.0); - assert_eq!(outer.inner.rust_value, 99); -}