Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
1619604
chore: prepare release 0.5.0
siy May 6, 2026
d00eaa1
feat: phase 0a — IdGenerator + LongLongMap foundation types
siy May 6, 2026
f0696a1
feat: phase 0b — sandbox IdCstNode with stable IDs
siy May 6, 2026
849b4ba
feat: phase 0c — sandbox IdNodeIndex with O(splicedSize+depth) increm…
siy May 6, 2026
9b55253
feat: phase 0d.1 — IdTreeSplicer + identity-invariant + trivia-edit g…
siy May 6, 2026
a2dd8ac
feat: phase 0d.2 — JMH bench (38-67x speedup confirms perf gate green)
siy May 6, 2026
a8c6efe
docs: phase 0e — GO verdict, CHANGELOG entry, HANDOVER updated to poi…
siy May 6, 2026
8f844eb
exp: phase 1.0/1.1 — path A SpanIndex prove-out (perf gate RED, 1.10-…
siy May 7, 2026
8b27dd6
feat: phase 1.1 path D — stable-id ancestor preservation (96-604x spe…
siy May 7, 2026
4043ddc
docs: phase 1 prove-out summary — path D is the architecture, HANDOVE…
siy May 7, 2026
2443779
feat: phase 1.2 — production CstNode gains long id (BREAKING record s…
siy May 7, 2026
39e11f9
feat: phase 1.5/1.6 — NodeIndex LongLongMap + Path D applyIncremental…
siy May 7, 2026
65a719f
fix: phase 1.7 — refresh nodesById after shiftAll + bench exception d…
siy May 7, 2026
43baaf8
docs: phase 1 results — production migration complete, point HANDOVER…
siy May 7, 2026
e038e4f
exp: phase 2 lever B — rolled back wiring, kept SafePivotAnalyzer + s…
siy May 7, 2026
0ea98af
fix: bench post-edit validation eliminates buffer-corruption exceptions
siy May 7, 2026
4ad5824
refactor: parseFull returns Result; Session.parseSuccessful() replace…
siy May 7, 2026
5275d86
chore: remove Phase 0/1 sandbox + sandbox JMH benches (production has…
siy May 7, 2026
4f06046
feat: Lever D — Cursor extracted from Session record (p99 -53%, frame…
siy May 7, 2026
1e524e2
docs: post-Lever-D status — bench+JBCT cleanup, Lever B blocked, Leve…
siy May 7, 2026
4ea7da4
docs: G0 — generator throughput profiling baseline (150 MB/op, 26.6% …
siy May 7, 2026
0ed2dcd
exp: A spike — opt-in mutableParseResult flag (Option -90.5%, bytes/o…
siy May 7, 2026
43ac902
docs: throughput engine Tier 1 spec — A proven, B/C/D sequence with m…
siy May 7, 2026
fedc389
feat: A coverage extension — Option at 0, wallclock -12.1% vs baseline
siy May 7, 2026
478b89b
refactor: D-pass sweep — replace .span().start().X() with primitive a…
siy May 7, 2026
5b2b6a1
feat: D emission-template sweep — inlineLocations on by default, Sour…
siy May 7, 2026
2ad2674
feat: E packrat — int-keyed cache replaces HashMap<Integer, X> (bytes…
siy May 7, 2026
2cd9cda
docs: throughput Tier 1 results — A+D+E shipped, B/C deferred
siy May 7, 2026
9e9414a
Revert "feat: E packrat — int-keyed cache replaces HashMap<Integer, X…
siy May 7, 2026
2a8cefc
feat: add self-host fixture to Java25ParseBenchmark + Tier 1 results …
siy May 7, 2026
7fdd5e8
feat: D2 — eliminate remaining location() callers in emission (-6% re…
siy May 7, 2026
dd1f150
feat: F — choice dispatch via transitive FIRST sets (62/64 choices, -…
siy May 8, 2026
eec8ba3
feat: Phase G — split Choice alternatives via Rule record (-10% both …
siy May 8, 2026
59be764
feat: G2+H — Sequence chunking + nested Choice extraction (-5% refere…
siy May 8, 2026
ca2dcfe
feat: selective packrat auto-detection (-38% reference, -14% self-hos…
siy May 8, 2026
3f7ca1d
docs: changelog — throughput engine Tier 1 arc (-67% reference wallcl…
siy May 8, 2026
0ea0765
feat: DFA fast-path for token-shaped rules (-10% reference, -8% self-…
siy May 8, 2026
fd278fe
docs: changelog — DFA fast-path token rules + javac comparison
siy May 8, 2026
e849b63
docs: HANDOVER updated to fd278fe state + detailed Move B spec for ne…
siy May 8, 2026
4763251
perf: trivia snapshot via int size — eliminates List.copyOf per snaps…
siy May 8, 2026
38b6a8e
perf: matchCharClassCst eliminates String.valueOf per match (-4.0%/-4…
siy May 8, 2026
25cdb57
docs: Move B post-mortem + post-rollback optimization arc lessons + s…
siy May 8, 2026
66460a4
docs: changelog — Move B post-mortem + post-rollback optimization arc…
siy May 8, 2026
6390ec3
docs: refresh test counts, perf numbers, and flag defaults for 0.5.0-…
siy May 8, 2026
4f54902
docs: remove obsolete RELEASE-PLAN-0.3.5-0.4.0 and update breadcrumbs
siy May 8, 2026
d6f8ac8
docs: archive shipped/abandoned specs to docs/archive/
siy May 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 151 additions & 7 deletions CHANGELOG.md

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ Sum <- Number '+' Number { return (Integer)$1 + (Integer)$2; }
- [x] Advanced error recovery with Rust-style diagnostics
- [x] Generated parser ErrorReporting (BASIC/ADVANCED) for optional Rust-style diagnostics
- [x] Cut operator (^/↑) - commits to current choice, prevents backtracking
- [x] 565 passing tests, 1 skipped (RoundTripTest — pre-existing trivia gap)
- [x] Performance rework (0.2.2): 4.23× speedup on 1,900-LOC Java 25 fixture via generator-time perf flags; see `docs/PERF-REWORK-SPEC.md` and `docs/bench-results/`.
- [x] 705 passing peglib-core tests + supporting modules (peglib-formatter 66, peglib-maven-plugin 5, peglib-playground 27); RoundTripTest enabled and 22/22 since 0.3.5
- [x] Performance rework (0.2.2): 4.23× speedup on 1,900-LOC Java 25 fixture via generator-time perf flags; see `docs/archive/PERF-REWORK-SPEC.md` (archived) and `docs/bench-results/`.
- [x] Throughput-engine Tier 1 arc + post-rollback wins (0.5.0-candidate): reference fixture **19.12 ms / 68.02 MB** (vs 76.2 ms / 150 MB pre-Tier-1); selfhost fixture 832 ms / 1.85 GB. See `docs/incremental/THROUGHPUT-ENGINE-TIER1.md` and `docs/incremental/THROUGHPUT-ENGINE-MOVE-B.md` (Move B post-mortem).

### Remaining Work
- [ ] Lambda action attachment (lowest priority) - attach actions programmatically using type-safe RuleId:
Expand Down Expand Up @@ -289,7 +290,7 @@ error: unexpected input
### Recovery Points
Parser recovers at: `,`, `;`, `}`, `)`, `]`, newline

## Test Coverage (565 tests)
## Test Coverage (705 peglib-core tests + supporting modules)

### Grammar Parser Tests (17 tests)
- Simple rules, actions, sequences, choices
Expand Down Expand Up @@ -419,7 +420,7 @@ The `Keyword` rule should only include hard keywords. Contextual keywords are ma

```bash
mvn compile # Compile
mvn test # Run tests (565 passing, 1 skipped)
mvn test # Run tests (705+ peglib-core tests; 0 skipped)
mvn verify # Full verification
```

Expand Down
44 changes: 33 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Quick links:
- [`peglib-incremental` README](peglib-incremental/README.md) — incremental reparsing
- [`peglib-formatter` README](peglib-formatter/README.md) — pretty-printer framework
- [`docs/PRETTY-PRINTING.md`](docs/PRETTY-PRINTING.md) — formatter design notes
- [`docs/incremental/SPEC.md`](docs/incremental/SPEC.md) — incremental parsing spec
- [`docs/incremental/ARCHITECTURE-0.5.0.md`](docs/incremental/ARCHITECTURE-0.5.0.md) — incremental parsing architecture (0.5.0)

## Quick Start

Expand All @@ -46,7 +46,7 @@ Quick links:
<dependency>
<groupId>org.pragmatica-lite</groupId>
<artifactId>peglib</artifactId>
<version>0.4.3</version>
<version>0.5.0</version>
</dependency>
```

Expand Down Expand Up @@ -394,7 +394,7 @@ The `peglib-maven-plugin` module (separate artifact, sibling to `peglib`) wraps
<plugin>
<groupId>org.pragmatica-lite</groupId>
<artifactId>peglib-maven-plugin</artifactId>
<version>0.4.3</version>
<version>0.5.0</version>
<executions>
<execution>
<goals>
Expand Down Expand Up @@ -453,13 +453,31 @@ public sealed interface CstNode {

## Performance

### Interpreter (PegEngine) — 0.4.1
### Throughput engine (generator) — 0.5.0-candidate

The parser generator output is now branded the **throughput engine** (full-reparse speed) and is distinct from the **incremental engine** (PegEngine + IncrementalSession, optimized for interactive editing). Different optimization targets, different code shapes, no shared code.

Cumulative arc on the 1,900-LOC reference fixture (`FactoryClassGenerator.java.txt`, JMH 1.37 avgT, JDK 25, Apple Silicon, variant `phase1_allStructural_mutableResult_autoSkipPackrat`):

| Stage | Wallclock | Allocation | vs original |
|---|---:|---:|---:|
| Pre-Tier-1 baseline | 76.2 ms | 150 MB | — |
| Post Tier 1 (A + D + F + G + G2/H + selective packrat + DFA Identifier) | 22.6 ms | 75.6 MB | -70% wallclock, -50% bytes |
| Post-rollback wins (trivia int snapshot, ASCII char interning) | **19.12 ms** | **68.02 MB** | **-75% wallclock, -55% bytes** |

A 37k-LOC self-host stress fixture (the Java25 generated parser parsing its own generated source) lands at **832 ms / 1.85 GB** — pre-Tier-1 it OOM'd. vs javac comparison: peglib parses the reference fixture in ~2× of javac wallclock with strictly more output (lossless CST + trivia for formatter and linter use cases).

On the same 1,900-LOC Java 25 fixture, the interpreter (`PegParser.fromGrammar(...).parseCst(...)`) is **3.88× faster in 0.4.1** than 0.4.0 (281 ms → 72.4 ms; JMH 1.37 avgT, JDK 25.0.2, Apple Silicon). Incremental cursor-far edits (`peglib-incremental`) drop from 322 ms to 107 ms (3.0×). Three flame-graph-driven changes: HashMap rule-lookup cache, singleton `ParseMode` constants, `LinkedHashSet` dedup for the furthest-failure expected-set. See [`docs/bench-results/post-0.4.0/`](docs/bench-results/post-0.4.0/) for raw JMH + JFR data.
See [`docs/incremental/THROUGHPUT-ENGINE-TIER1.md`](docs/incremental/THROUGHPUT-ENGINE-TIER1.md) and [`docs/incremental/THROUGHPUT-ENGINE-MOVE-B.md`](docs/incremental/THROUGHPUT-ENGINE-MOVE-B.md) for the full session post-mortem (including 5 reset attempts banked as lessons), and [`CHANGELOG.md`](CHANGELOG.md#050---2026-05-06) for the per-move detail.

### Incremental engine (interactive editing) — 0.5.0-candidate

`peglib-incremental`'s `IncrementalSession` provides cursor-anchored single-edit reparsing. Phase 1 of the 0.5.0 architectural rework (stable node IDs + `LongLongMap` NodeIndex + Path D ancestor-preservation algorithm) ships **1.9× faster median (10.8 ms → 5.6 ms)** and **96.5% of edits within the 16 ms frame budget** vs the 0.4.3 baseline. Lever D (Cursor/Session split) layers on a further -9% median / -53% p99. See [`docs/incremental/PHASE-1-RESULTS.md`](docs/incremental/PHASE-1-RESULTS.md).

### Interpreter (PegEngine) — 0.4.1

### Generated parsers — 0.2.2
On the same 1,900-LOC Java 25 fixture, the interpreter (`PegParser.fromGrammar(...).parseCst(...)`) is **3.88× faster in 0.4.1** than 0.4.0 (281 ms → 72.4 ms). Three flame-graph-driven changes: HashMap rule-lookup cache, singleton `ParseMode` constants, `LinkedHashSet` dedup for the furthest-failure expected-set. See [`docs/bench-results/post-0.4.0/`](docs/bench-results/post-0.4.0/) for raw JMH + JFR data.

The generated CST parser emits tuned helper variants driven by generator-time flags in `ParserConfig`. On the same fixture, the all-flags `phase1` variant runs at ~76 ms (4.7× over the pre-0.2.2 baseline; raw data in [`docs/bench-results/`](docs/bench-results/)).
### Generator-time perf flags (0.2.2 origin, evolved through 0.5.0)

Flags (all consumed at generation time — no runtime branching in the emitted parser):

Expand All @@ -471,12 +489,14 @@ Flags (all consumed at generation time — no runtime branching in the emitted p
| `bulkAdvanceLiteral` | 1 | on | Bulk `pos`/`column` update for no-newline literals |
| `skipWhitespaceFastPath` | 1 | on | First-char precheck derived from `%whitespace` rule |
| `reuseEndLocation` | 1 | on | Reuse end-position `SourceLocation` across span + result |
| `choiceDispatch` | 2 | on | `switch(input.charAt(pos))` dispatch for literal-prefixed Choice |
| `choiceDispatch` | 2 | on | First-set `switch(input.charAt(pos))` dispatch for Choice (extended in 0.5.0 to CharClass + Reference + mixed) |
| `inlineLocations` | 2 | on (since 0.5.0) | Inline int locals at rule entry instead of SourceLocation |
| `selectivePackrat` | 2 | on (since 0.5.0) | Skip packrat cache for rules in `packratSkipRules`; auto-derives skip-set when empty via `PackratAnalyzer.autoSkipPackratRules(grammar)` |
| `tokenFastPath` | 2 | on (since 0.5.0) | DFA fast-path scanner for token-shaped rules (`< CharClass + ZeroOrMore<CharClass> >`) |
| `markResetChildren` | 2 | off | Replace children clone+clear+addAll with mark-and-trim |
| `inlineLocations` | 2 | off | Inline int locals at rule entry instead of SourceLocation |
| `selectivePackrat` | 2 | off | Skip packrat cache for rules in `packratSkipRules` |
| `mutableParseResult` | 2 | off (opt-in) | Emit mutable `CstParseResult` with raw nullable fields — eliminates Option boxing |

The three default-off flags can be flipped on per-project via a custom `ParserConfig`. See [`docs/PERF-FLAGS.md`](docs/PERF-FLAGS.md) for the per-flag reference and guidance on when to flip, [`docs/PERF-REWORK-SPEC.md`](docs/PERF-REWORK-SPEC.md) for the underlying design, and [`docs/bench-results/java25-parse.json`](docs/bench-results/java25-parse.json) for raw JMH data.
Default-off flags can be flipped on per-project via a custom `ParserConfig`. See [`docs/PERF-FLAGS.md`](docs/PERF-FLAGS.md) for the per-flag reference and guidance on when to flip, [`docs/archive/PERF-REWORK-SPEC.md`](docs/archive/PERF-REWORK-SPEC.md) for the underlying design (archived; superseded by [`docs/incremental/THROUGHPUT-ENGINE-TIER1.md`](docs/incremental/THROUGHPUT-ENGINE-TIER1.md)), and [`docs/bench-results/java25-parse.json`](docs/bench-results/java25-parse.json) for raw JMH data.

To reproduce benchmarks:

Expand Down Expand Up @@ -505,6 +525,8 @@ Full history in [`CHANGELOG.md`](CHANGELOG.md). Highlights since the 0.2.x line:

| Version | Date | What |
|---|---|---|
| **0.5.0** | 2026-05-08 (candidate) | **Throughput engine** rebrand + Tier 1 perf arc — reference fixture **76.2 ms → 19.12 ms** (-75%) and self-host (37k LOC) **OOM → 832 ms**. Incremental engine Phase 1: stable node IDs + LongLongMap NodeIndex + Path D ancestor-preservation — **1.9× faster median** for cursor-aware edits. **BREAKING:** `CstNode` records gain `long id` as the first record component (equals/hashCode exclude id). New `Cursor` value type split out from `Session`. |
| **0.4.3** | 2026-05-06 | Interactive editing perf: -19% median, -26% p95. **BREAKING:** `SourceSpan` now stores int triples instead of `SourceLocation` refs. |
| **0.4.2** | 2026-05-05 | Generated parsers now truly standalone — emit zero peglib FQCN references in their source. Drop them into a project with no peglib runtime and they compile. |
| **0.4.1** | 2026-05-04 | **3.88× interpreter speedup** + 3.0× incremental cursor-far edit. Three flame-graph-driven fixes; no API change. |
| **0.4.0** | 2026-05-03 | **Breaking** — API consolidation. Multi-module split (`peglib`, `peglib-incremental`, `peglib-formatter`, `peglib-maven-plugin`, `peglib-playground`). Consistent factory naming. Result-typed pipelines at every boundary. Parse-don't-validate `Grammar`. Immutable `FormatterConfig` record. Migration notes in CHANGELOG. |
Expand Down
6 changes: 3 additions & 3 deletions docs/AUDIT-REPORTS/docs-backreference.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ No missing implementation, no stubs (`TODO`/`FIXME`/`UnsupportedOperationExcepti
| `InterpreterBaselineGenerator` util | ✓ | ✓ | ✓ | Same test dir. |
| `ParsingContext#bulkAdvanceNoNewline` | ✓ | ✓ | ✓ | Used in `parseLiteral`/`parseDictionary`. |
| JMH `interpreter` benchmark variant | ✓ | ✓ | ✓ | `docs/bench-results/java25-parse-interpreter.json` present. |
| PERF-REWORK-SPEC doc | ✓ | ✓ | n/a | `docs/PERF-REWORK-SPEC.md`. |
| PERF-REWORK-SPEC doc | ✓ | ✓ | n/a | `docs/archive/PERF-REWORK-SPEC.md` (archived 2026-05-08). |

## 0.2.4 — Trivia attribution + grammar DSL directives

Expand Down Expand Up @@ -178,15 +178,15 @@ All three mojos have `@Mojo(name = ..., defaultPhase = ..., threadSafe = true)`

All 10 docs under `docs/` referenced by CHANGELOG entries are present:

- `docs/PERF-REWORK-SPEC.md` (0.2.2/0.2.3)
- `docs/archive/PERF-REWORK-SPEC.md` (0.2.2/0.2.3) — archived 2026-05-08
- `docs/TRIVIA-ATTRIBUTION.md` (0.2.4)
- `docs/GRAMMAR-DSL.md` (0.2.4 + 0.2.8)
- `docs/PERF-FLAGS.md` (0.2.4)
- `docs/BENCHMARKING.md` (0.2.4)
- `docs/ERROR_RECOVERY.md` (expanded 0.2.4)
- `docs/PLAYGROUND.md` (0.2.7)
- `docs/PARTIAL-PARSE.md` (0.3.0)
- `docs/incremental/SPEC.md` (0.3.1)
- `docs/archive/SPEC-incremental-original.md` (0.3.1) — archived 2026-05-08
- `docs/PRETTY-PRINTING.md` (0.3.3)

Module READMEs:
Expand Down
19 changes: 15 additions & 4 deletions docs/BENCHMARKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,25 @@ Listed in the harness's `@Param` annotation:
| Variant | Configuration |
|---|---|
| `none` | All generator flags off — unflagged baseline |
| `phase1` | `ParserConfig.DEFAULT` (phase-1 on, `choiceDispatch` on, other phase-2 off) |
| `phase1` | Phase-1 flags on, all phase-2 flags off |
| `phase1_choiceDispatch` | phase-1 + `choiceDispatch` only |
| `phase1_markResetChildren` | phase-1 + `markResetChildren` only |
| `phase1_inlineLocations` | phase-1 + `inlineLocations` only |
| `phase1_allStructural` | phase-1 + all phase-2 (no `selectivePackrat`) |
| `phase1_allStructural_skipPackrat` | above + `selectivePackrat` with skip-set `{Identifier, QualifiedName, Type}` |
| `phase1_allStructural_skipPackrat` | above + `selectivePackrat` with explicit skip-set `{Identifier, QualifiedName, Type}` |
| `phase1_allStructural_mutableResult` | above + `mutableParseResult` (Move A: -8.5% wallclock vs `phase1_allStructural`) |
| `phase1_allStructural_mutableResult_autoSkipPackrat` | above with empty `packratSkipRules` → auto-derived skip-set via `PackratAnalyzer.autoSkipPackratRules`. **Currently the headline variant for cumulative throughput-engine numbers** (-67% wallclock vs pre-Tier-1 baseline). |
| `interpreter` | `PegEngine` path, `ParserConfig.DEFAULT` |

The harness is also parametrized on a `fixture` param:

| Fixture | Source | Purpose |
|---|---|---|
| `reference` | 1,900-LOC `FactoryClassGenerator.java.txt` | Stable, low-variance throughput bench |
| `selfhost` | The Java25 generated parser parsing its own ~37k-LOC generated source | Stress fixture; exposes scaling regressions the small fixture misses (e.g. Move E's IntCstParseResultMap regressed self-host by 22% while reference stayed in noise) |

The `selfhost` fixture is incompatible with `variant=interpreter` (no generated source to feed back) — that combination is rejected at `@Setup`.

## Adding a new variant

Edit `Java25ParseBenchmark.configFor(...)` and add an entry to the
Expand Down Expand Up @@ -169,6 +180,6 @@ raw files serve as machine-readable backup.
## Related

- [`PERF-FLAGS.md`](PERF-FLAGS.md) — what each `ParserConfig` flag does
- [`PERF-REWORK-SPEC.md`](PERF-REWORK-SPEC.md) — design rationale and
phase-by-phase specification
- [`archive/PERF-REWORK-SPEC.md`](archive/PERF-REWORK-SPEC.md) — design rationale and
phase-by-phase specification (archived; superseded by [`incremental/THROUGHPUT-ENGINE-TIER1.md`](incremental/THROUGHPUT-ENGINE-TIER1.md))
- [`CHANGELOG.md`](../CHANGELOG.md) — per-release measured numbers
6 changes: 3 additions & 3 deletions docs/GRAMMAR-DSL.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ Input `clss` produces a diagnostic with note `help: did you mean 'class'?`.

Multiple `%suggest` directives are permitted; their vocabularies combine.
Vocabularies are precomputed once per `ParsingContext` and do not change
between parse attempts (this matters for the planned incremental parser
in 0.3.1, which forwards the dictionary across reparses without
between parse attempts (this matters for the incremental parser introduced
in 0.3.0–0.3.2, which forwards the dictionary across reparses without
recomputation).

If no `%suggest` directive is declared, no suggestion logic runs and
Expand Down Expand Up @@ -251,7 +251,7 @@ Each finding has a stable tag for tooling integration. The full catalog:
| `grammar.nullable-rule` | INFO / WARNING | Rule can match the empty string. Promoted to WARNING when the rule is on a direct left-recursive path (infinite-loop risk) |
| `grammar.duplicate-literal` | ERROR | Literal repeated verbatim within the same `Choice` |
| `grammar.whitespace-cycle` | ERROR | `%whitespace` expression transitively references itself |
| `grammar.has-backreference` | INFO | Rule uses `$name` back-reference — forward-compat note: incremental parsing (planned for 0.3.1) falls back to full reparse on such rules |
| `grammar.has-backreference` | INFO | Rule uses `$name` back-reference — forward-compat note: incremental parsing (since 0.3.2) falls back to full reparse on such rules |

The ambiguous-choice check is conservative: it flags only choices where
*every* alternative has a fixed literal prefix. Rule-reference-prefixed or
Expand Down
Loading
Loading