@bcts/envelope-pattern 1.0.0-alpha.16 → 1.0.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1992 -1714
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -31
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +147 -31
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +1984 -1707
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +1966 -1698
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/format.ts +32 -13
- package/src/parse/index.ts +138 -5
- package/src/parse/token.ts +59 -58
- package/src/pattern/index.ts +110 -2
- package/src/pattern/leaf/array-pattern.ts +26 -26
- package/src/pattern/leaf/bool-pattern.ts +12 -12
- package/src/pattern/leaf/byte-string-pattern.ts +15 -15
- package/src/pattern/leaf/cbor-pattern.ts +31 -31
- package/src/pattern/leaf/date-pattern.ts +9 -9
- package/src/pattern/leaf/index.ts +1 -2
- package/src/pattern/leaf/known-value-pattern.ts +21 -20
- package/src/pattern/leaf/map-pattern.ts +14 -14
- package/src/pattern/leaf/null-pattern.ts +8 -8
- package/src/pattern/leaf/number-pattern.ts +20 -20
- package/src/pattern/leaf/tagged-pattern.ts +20 -20
- package/src/pattern/leaf/text-pattern.ts +14 -14
- package/src/pattern/matcher.ts +88 -3
- package/src/pattern/meta/and-pattern.ts +19 -18
- package/src/pattern/meta/capture-pattern.ts +16 -17
- package/src/pattern/meta/group-pattern.ts +20 -17
- package/src/pattern/meta/not-pattern.ts +9 -8
- package/src/pattern/meta/or-pattern.ts +30 -25
- package/src/pattern/meta/search-pattern.ts +17 -17
- package/src/pattern/meta/traverse-pattern.ts +42 -18
- package/src/pattern/structure/assertions-pattern.ts +31 -32
- package/src/pattern/structure/digest-pattern.ts +23 -23
- package/src/pattern/structure/index.ts +1 -0
- package/src/pattern/structure/node-pattern.ts +17 -17
- package/src/pattern/structure/object-pattern.ts +14 -15
- package/src/pattern/structure/obscured-pattern.ts +7 -7
- package/src/pattern/structure/predicate-pattern.ts +14 -15
- package/src/pattern/structure/subject-pattern.ts +16 -17
- package/src/pattern/structure/wrapped-pattern.ts +40 -19
- package/src/pattern/vm.ts +12 -11
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Envelope } from "@bcts/envelope";
|
|
10
10
|
import type { Path } from "../../format";
|
|
11
|
-
import type
|
|
11
|
+
import { matchPattern, type Matcher } from "../matcher";
|
|
12
12
|
import type { Instr } from "../vm";
|
|
13
13
|
import type { Pattern } from "../index";
|
|
14
14
|
|
|
@@ -34,10 +34,10 @@ export type ObjectPatternType =
|
|
|
34
34
|
* Corresponds to the Rust `ObjectPattern` enum in object_pattern.rs
|
|
35
35
|
*/
|
|
36
36
|
export class ObjectPattern implements Matcher {
|
|
37
|
-
readonly
|
|
37
|
+
private readonly _pattern: ObjectPatternType;
|
|
38
38
|
|
|
39
39
|
private constructor(pattern: ObjectPatternType) {
|
|
40
|
-
this
|
|
40
|
+
this._pattern = pattern;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -58,14 +58,14 @@ export class ObjectPattern implements Matcher {
|
|
|
58
58
|
* Gets the pattern type.
|
|
59
59
|
*/
|
|
60
60
|
get patternType(): ObjectPatternType {
|
|
61
|
-
return this
|
|
61
|
+
return this._pattern;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Gets the inner pattern if this is a Pattern type, undefined otherwise.
|
|
66
66
|
*/
|
|
67
67
|
innerPattern(): Pattern | undefined {
|
|
68
|
-
return this
|
|
68
|
+
return this._pattern.type === "Pattern" ? this._pattern.pattern : undefined;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
@@ -77,13 +77,12 @@ export class ObjectPattern implements Matcher {
|
|
|
77
77
|
|
|
78
78
|
let paths: Path[];
|
|
79
79
|
|
|
80
|
-
switch (this
|
|
80
|
+
switch (this._pattern.type) {
|
|
81
81
|
case "Any":
|
|
82
82
|
paths = [[object]];
|
|
83
83
|
break;
|
|
84
84
|
case "Pattern": {
|
|
85
|
-
|
|
86
|
-
if (innerMatcher.matches(object)) {
|
|
85
|
+
if (matchPattern(this._pattern.pattern, object)) {
|
|
87
86
|
paths = [[object]];
|
|
88
87
|
} else {
|
|
89
88
|
paths = [];
|
|
@@ -117,11 +116,11 @@ export class ObjectPattern implements Matcher {
|
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
toString(): string {
|
|
120
|
-
switch (this
|
|
119
|
+
switch (this._pattern.type) {
|
|
121
120
|
case "Any":
|
|
122
121
|
return "obj";
|
|
123
122
|
case "Pattern":
|
|
124
|
-
return `obj(${(this
|
|
123
|
+
return `obj(${(this._pattern.pattern as unknown as { toString(): string }).toString()})`;
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
126
|
|
|
@@ -129,14 +128,14 @@ export class ObjectPattern implements Matcher {
|
|
|
129
128
|
* Equality comparison.
|
|
130
129
|
*/
|
|
131
130
|
equals(other: ObjectPattern): boolean {
|
|
132
|
-
if (this
|
|
131
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
133
132
|
return false;
|
|
134
133
|
}
|
|
135
|
-
if (this
|
|
134
|
+
if (this._pattern.type === "Any") {
|
|
136
135
|
return true;
|
|
137
136
|
}
|
|
138
|
-
const thisPattern = (this
|
|
139
|
-
const otherPattern = (other
|
|
137
|
+
const thisPattern = (this._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
138
|
+
const otherPattern = (other._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
140
139
|
return thisPattern === otherPattern;
|
|
141
140
|
}
|
|
142
141
|
|
|
@@ -144,6 +143,6 @@ export class ObjectPattern implements Matcher {
|
|
|
144
143
|
* Hash code for use in Maps/Sets.
|
|
145
144
|
*/
|
|
146
145
|
hashCode(): number {
|
|
147
|
-
return this
|
|
146
|
+
return this._pattern.type === "Any" ? 0 : 1;
|
|
148
147
|
}
|
|
149
148
|
}
|
|
@@ -39,10 +39,10 @@ export type ObscuredPatternType =
|
|
|
39
39
|
* Corresponds to the Rust `ObscuredPattern` enum in obscured_pattern.rs
|
|
40
40
|
*/
|
|
41
41
|
export class ObscuredPattern implements Matcher {
|
|
42
|
-
readonly
|
|
42
|
+
private readonly _pattern: ObscuredPatternType;
|
|
43
43
|
|
|
44
44
|
private constructor(pattern: ObscuredPatternType) {
|
|
45
|
-
this
|
|
45
|
+
this._pattern = pattern;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
@@ -77,13 +77,13 @@ export class ObscuredPattern implements Matcher {
|
|
|
77
77
|
* Gets the pattern type.
|
|
78
78
|
*/
|
|
79
79
|
get patternType(): ObscuredPatternType {
|
|
80
|
-
return this
|
|
80
|
+
return this._pattern;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
84
84
|
let isHit = false;
|
|
85
85
|
|
|
86
|
-
switch (this
|
|
86
|
+
switch (this._pattern.type) {
|
|
87
87
|
case "Any":
|
|
88
88
|
isHit = haystack.isObscured();
|
|
89
89
|
break;
|
|
@@ -122,7 +122,7 @@ export class ObscuredPattern implements Matcher {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
toString(): string {
|
|
125
|
-
switch (this
|
|
125
|
+
switch (this._pattern.type) {
|
|
126
126
|
case "Any":
|
|
127
127
|
return "obscured";
|
|
128
128
|
case "Elided":
|
|
@@ -138,14 +138,14 @@ export class ObscuredPattern implements Matcher {
|
|
|
138
138
|
* Equality comparison.
|
|
139
139
|
*/
|
|
140
140
|
equals(other: ObscuredPattern): boolean {
|
|
141
|
-
return this
|
|
141
|
+
return this._pattern.type === other._pattern.type;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
145
|
* Hash code for use in Maps/Sets.
|
|
146
146
|
*/
|
|
147
147
|
hashCode(): number {
|
|
148
|
-
switch (this
|
|
148
|
+
switch (this._pattern.type) {
|
|
149
149
|
case "Any":
|
|
150
150
|
return 0;
|
|
151
151
|
case "Elided":
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Envelope } from "@bcts/envelope";
|
|
10
10
|
import type { Path } from "../../format";
|
|
11
|
-
import type
|
|
11
|
+
import { matchPattern, type Matcher } from "../matcher";
|
|
12
12
|
import type { Instr } from "../vm";
|
|
13
13
|
import type { Pattern } from "../index";
|
|
14
14
|
|
|
@@ -36,10 +36,10 @@ export type PredicatePatternType =
|
|
|
36
36
|
* Corresponds to the Rust `PredicatePattern` enum in predicate_pattern.rs
|
|
37
37
|
*/
|
|
38
38
|
export class PredicatePattern implements Matcher {
|
|
39
|
-
readonly
|
|
39
|
+
private readonly _pattern: PredicatePatternType;
|
|
40
40
|
|
|
41
41
|
private constructor(pattern: PredicatePatternType) {
|
|
42
|
-
this
|
|
42
|
+
this._pattern = pattern;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -60,14 +60,14 @@ export class PredicatePattern implements Matcher {
|
|
|
60
60
|
* Gets the pattern type.
|
|
61
61
|
*/
|
|
62
62
|
get patternType(): PredicatePatternType {
|
|
63
|
-
return this
|
|
63
|
+
return this._pattern;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Gets the inner pattern if this is a Pattern type, undefined otherwise.
|
|
68
68
|
*/
|
|
69
69
|
innerPattern(): Pattern | undefined {
|
|
70
|
-
return this
|
|
70
|
+
return this._pattern.type === "Pattern" ? this._pattern.pattern : undefined;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
@@ -79,13 +79,12 @@ export class PredicatePattern implements Matcher {
|
|
|
79
79
|
|
|
80
80
|
let paths: Path[];
|
|
81
81
|
|
|
82
|
-
switch (this
|
|
82
|
+
switch (this._pattern.type) {
|
|
83
83
|
case "Any":
|
|
84
84
|
paths = [[predicate]];
|
|
85
85
|
break;
|
|
86
86
|
case "Pattern": {
|
|
87
|
-
|
|
88
|
-
if (innerMatcher.matches(predicate)) {
|
|
87
|
+
if (matchPattern(this._pattern.pattern, predicate)) {
|
|
89
88
|
paths = [[predicate]];
|
|
90
89
|
} else {
|
|
91
90
|
paths = [];
|
|
@@ -119,11 +118,11 @@ export class PredicatePattern implements Matcher {
|
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
toString(): string {
|
|
122
|
-
switch (this
|
|
121
|
+
switch (this._pattern.type) {
|
|
123
122
|
case "Any":
|
|
124
123
|
return "pred";
|
|
125
124
|
case "Pattern":
|
|
126
|
-
return `pred(${(this
|
|
125
|
+
return `pred(${(this._pattern.pattern as unknown as { toString(): string }).toString()})`;
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
128
|
|
|
@@ -131,14 +130,14 @@ export class PredicatePattern implements Matcher {
|
|
|
131
130
|
* Equality comparison.
|
|
132
131
|
*/
|
|
133
132
|
equals(other: PredicatePattern): boolean {
|
|
134
|
-
if (this
|
|
133
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
135
134
|
return false;
|
|
136
135
|
}
|
|
137
|
-
if (this
|
|
136
|
+
if (this._pattern.type === "Any") {
|
|
138
137
|
return true;
|
|
139
138
|
}
|
|
140
|
-
const thisPattern = (this
|
|
141
|
-
const otherPattern = (other
|
|
139
|
+
const thisPattern = (this._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
140
|
+
const otherPattern = (other._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
142
141
|
return thisPattern === otherPattern;
|
|
143
142
|
}
|
|
144
143
|
|
|
@@ -146,6 +145,6 @@ export class PredicatePattern implements Matcher {
|
|
|
146
145
|
* Hash code for use in Maps/Sets.
|
|
147
146
|
*/
|
|
148
147
|
hashCode(): number {
|
|
149
|
-
return this
|
|
148
|
+
return this._pattern.type === "Any" ? 0 : 1;
|
|
150
149
|
}
|
|
151
150
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Envelope } from "@bcts/envelope";
|
|
10
10
|
import type { Path } from "../../format";
|
|
11
|
-
import type
|
|
11
|
+
import { matchPattern, type Matcher } from "../matcher";
|
|
12
12
|
import type { Instr } from "../vm";
|
|
13
13
|
import type { Pattern } from "../index";
|
|
14
14
|
|
|
@@ -34,10 +34,10 @@ export type SubjectPatternType =
|
|
|
34
34
|
* Corresponds to the Rust `SubjectPattern` enum in subject_pattern.rs
|
|
35
35
|
*/
|
|
36
36
|
export class SubjectPattern implements Matcher {
|
|
37
|
-
readonly
|
|
37
|
+
private readonly _pattern: SubjectPatternType;
|
|
38
38
|
|
|
39
39
|
private constructor(pattern: SubjectPatternType) {
|
|
40
|
-
this
|
|
40
|
+
this._pattern = pattern;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -58,27 +58,26 @@ export class SubjectPattern implements Matcher {
|
|
|
58
58
|
* Gets the pattern type.
|
|
59
59
|
*/
|
|
60
60
|
get patternType(): SubjectPatternType {
|
|
61
|
-
return this
|
|
61
|
+
return this._pattern;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Gets the inner pattern if this is a Pattern type, undefined otherwise.
|
|
66
66
|
*/
|
|
67
67
|
innerPattern(): Pattern | undefined {
|
|
68
|
-
return this
|
|
68
|
+
return this._pattern.type === "Pattern" ? this._pattern.pattern : undefined;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
72
72
|
const subject = haystack.subject();
|
|
73
73
|
let paths: Path[];
|
|
74
74
|
|
|
75
|
-
switch (this
|
|
75
|
+
switch (this._pattern.type) {
|
|
76
76
|
case "Any":
|
|
77
77
|
paths = [[subject]];
|
|
78
78
|
break;
|
|
79
79
|
case "Pattern": {
|
|
80
|
-
|
|
81
|
-
if (innerMatcher.matches(subject)) {
|
|
80
|
+
if (matchPattern(this._pattern.pattern, subject)) {
|
|
82
81
|
paths = [[subject]];
|
|
83
82
|
} else {
|
|
84
83
|
paths = [];
|
|
@@ -99,7 +98,7 @@ export class SubjectPattern implements Matcher {
|
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
compile(code: Instr[], literals: Pattern[], captures: string[]): void {
|
|
102
|
-
switch (this
|
|
101
|
+
switch (this._pattern.type) {
|
|
103
102
|
case "Any":
|
|
104
103
|
code.push({ type: "NavigateSubject" });
|
|
105
104
|
break;
|
|
@@ -108,7 +107,7 @@ export class SubjectPattern implements Matcher {
|
|
|
108
107
|
code.push({ type: "NavigateSubject" });
|
|
109
108
|
// Save the path and run the inner pattern relative to the subject
|
|
110
109
|
code.push({ type: "ExtendTraversal" });
|
|
111
|
-
(this
|
|
110
|
+
(this._pattern.pattern as unknown as Matcher).compile(code, literals, captures);
|
|
112
111
|
code.push({ type: "CombineTraversal" });
|
|
113
112
|
break;
|
|
114
113
|
}
|
|
@@ -119,11 +118,11 @@ export class SubjectPattern implements Matcher {
|
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
toString(): string {
|
|
122
|
-
switch (this
|
|
121
|
+
switch (this._pattern.type) {
|
|
123
122
|
case "Any":
|
|
124
123
|
return "subj";
|
|
125
124
|
case "Pattern":
|
|
126
|
-
return `subj(${(this
|
|
125
|
+
return `subj(${(this._pattern.pattern as unknown as { toString(): string }).toString()})`;
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
128
|
|
|
@@ -131,15 +130,15 @@ export class SubjectPattern implements Matcher {
|
|
|
131
130
|
* Equality comparison.
|
|
132
131
|
*/
|
|
133
132
|
equals(other: SubjectPattern): boolean {
|
|
134
|
-
if (this
|
|
133
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
135
134
|
return false;
|
|
136
135
|
}
|
|
137
|
-
if (this
|
|
136
|
+
if (this._pattern.type === "Any") {
|
|
138
137
|
return true;
|
|
139
138
|
}
|
|
140
139
|
// For Pattern type, compare the inner patterns
|
|
141
|
-
const thisPattern = (this
|
|
142
|
-
const otherPattern = (other
|
|
140
|
+
const thisPattern = (this._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
141
|
+
const otherPattern = (other._pattern as { type: "Pattern"; pattern: Pattern }).pattern;
|
|
143
142
|
return thisPattern === otherPattern; // Reference equality for now
|
|
144
143
|
}
|
|
145
144
|
|
|
@@ -147,6 +146,6 @@ export class SubjectPattern implements Matcher {
|
|
|
147
146
|
* Hash code for use in Maps/Sets.
|
|
148
147
|
*/
|
|
149
148
|
hashCode(): number {
|
|
150
|
-
return this
|
|
149
|
+
return this._pattern.type === "Any" ? 0 : 1;
|
|
151
150
|
}
|
|
152
151
|
}
|
|
@@ -15,10 +15,29 @@ import type { Pattern } from "../index";
|
|
|
15
15
|
// Forward declaration for Pattern factory
|
|
16
16
|
let createStructureWrappedPattern: ((pattern: WrappedPattern) => Pattern) | undefined;
|
|
17
17
|
|
|
18
|
+
// Forward declaration for pattern dispatch (avoids circular imports)
|
|
19
|
+
let dispatchPatternPathsWithCaptures:
|
|
20
|
+
| ((pattern: Pattern, haystack: Envelope) => [Path[], Map<string, Path[]>])
|
|
21
|
+
| undefined;
|
|
22
|
+
let dispatchPatternCompile:
|
|
23
|
+
| ((pattern: Pattern, code: Instr[], literals: Pattern[], captures: string[]) => void)
|
|
24
|
+
| undefined;
|
|
25
|
+
let dispatchPatternToString: ((pattern: Pattern) => string) | undefined;
|
|
26
|
+
|
|
18
27
|
export function registerWrappedPatternFactory(factory: (pattern: WrappedPattern) => Pattern): void {
|
|
19
28
|
createStructureWrappedPattern = factory;
|
|
20
29
|
}
|
|
21
30
|
|
|
31
|
+
export function registerWrappedPatternDispatch(dispatch: {
|
|
32
|
+
pathsWithCaptures: (pattern: Pattern, haystack: Envelope) => [Path[], Map<string, Path[]>];
|
|
33
|
+
compile: (pattern: Pattern, code: Instr[], literals: Pattern[], captures: string[]) => void;
|
|
34
|
+
toString: (pattern: Pattern) => string;
|
|
35
|
+
}): void {
|
|
36
|
+
dispatchPatternPathsWithCaptures = dispatch.pathsWithCaptures;
|
|
37
|
+
dispatchPatternCompile = dispatch.compile;
|
|
38
|
+
dispatchPatternToString = dispatch.toString;
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
/**
|
|
23
42
|
* Pattern type for wrapped pattern matching.
|
|
24
43
|
*
|
|
@@ -34,10 +53,10 @@ export type WrappedPatternType =
|
|
|
34
53
|
* Corresponds to the Rust `WrappedPattern` enum in wrapped_pattern.rs
|
|
35
54
|
*/
|
|
36
55
|
export class WrappedPattern implements Matcher {
|
|
37
|
-
readonly
|
|
56
|
+
private readonly _pattern: WrappedPatternType;
|
|
38
57
|
|
|
39
58
|
private constructor(pattern: WrappedPatternType) {
|
|
40
|
-
this
|
|
59
|
+
this._pattern = pattern;
|
|
41
60
|
}
|
|
42
61
|
|
|
43
62
|
/**
|
|
@@ -69,14 +88,14 @@ export class WrappedPattern implements Matcher {
|
|
|
69
88
|
* Gets the pattern type.
|
|
70
89
|
*/
|
|
71
90
|
get patternType(): WrappedPatternType {
|
|
72
|
-
return this
|
|
91
|
+
return this._pattern;
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
/**
|
|
76
95
|
* Gets the inner pattern if this is an Unwrap type, undefined otherwise.
|
|
77
96
|
*/
|
|
78
97
|
innerPattern(): Pattern | undefined {
|
|
79
|
-
return this
|
|
98
|
+
return this._pattern.type === "Unwrap" ? this._pattern.pattern : undefined;
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
@@ -88,7 +107,7 @@ export class WrappedPattern implements Matcher {
|
|
|
88
107
|
|
|
89
108
|
let paths: Path[];
|
|
90
109
|
|
|
91
|
-
switch (this
|
|
110
|
+
switch (this._pattern.type) {
|
|
92
111
|
case "Any":
|
|
93
112
|
// Just match the wrapped envelope itself, don't descend
|
|
94
113
|
paths = [[haystack]];
|
|
@@ -96,9 +115,8 @@ export class WrappedPattern implements Matcher {
|
|
|
96
115
|
case "Unwrap": {
|
|
97
116
|
// Match the content of the wrapped envelope
|
|
98
117
|
const unwrapped = subject.tryUnwrap?.();
|
|
99
|
-
if (unwrapped !== undefined) {
|
|
100
|
-
const
|
|
101
|
-
const innerPaths = innerMatcher.paths(unwrapped);
|
|
118
|
+
if (unwrapped !== undefined && dispatchPatternPathsWithCaptures !== undefined) {
|
|
119
|
+
const [innerPaths] = dispatchPatternPathsWithCaptures(this._pattern.pattern, unwrapped);
|
|
102
120
|
paths = innerPaths.map((path) => {
|
|
103
121
|
// Add the current envelope to the path
|
|
104
122
|
return [haystack, ...path];
|
|
@@ -126,7 +144,7 @@ export class WrappedPattern implements Matcher {
|
|
|
126
144
|
throw new Error("WrappedPattern factory not registered");
|
|
127
145
|
}
|
|
128
146
|
|
|
129
|
-
switch (this
|
|
147
|
+
switch (this._pattern.type) {
|
|
130
148
|
case "Any": {
|
|
131
149
|
// Just match the wrapped envelope itself, don't descend
|
|
132
150
|
const idx = literals.length;
|
|
@@ -145,8 +163,9 @@ export class WrappedPattern implements Matcher {
|
|
|
145
163
|
code.push({ type: "PushAxis", axis });
|
|
146
164
|
|
|
147
165
|
// Then match the pattern
|
|
148
|
-
|
|
149
|
-
|
|
166
|
+
if (dispatchPatternCompile !== undefined) {
|
|
167
|
+
dispatchPatternCompile(this._pattern.pattern, code, literals, captures);
|
|
168
|
+
}
|
|
150
169
|
break;
|
|
151
170
|
}
|
|
152
171
|
}
|
|
@@ -157,12 +176,14 @@ export class WrappedPattern implements Matcher {
|
|
|
157
176
|
}
|
|
158
177
|
|
|
159
178
|
toString(): string {
|
|
160
|
-
switch (this
|
|
179
|
+
switch (this._pattern.type) {
|
|
161
180
|
case "Any":
|
|
162
181
|
return "wrapped";
|
|
163
182
|
case "Unwrap": {
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
const patternStr =
|
|
184
|
+
dispatchPatternToString !== undefined
|
|
185
|
+
? dispatchPatternToString(this._pattern.pattern)
|
|
186
|
+
: "*";
|
|
166
187
|
if (patternStr === "*") {
|
|
167
188
|
return "unwrap";
|
|
168
189
|
}
|
|
@@ -175,14 +196,14 @@ export class WrappedPattern implements Matcher {
|
|
|
175
196
|
* Equality comparison.
|
|
176
197
|
*/
|
|
177
198
|
equals(other: WrappedPattern): boolean {
|
|
178
|
-
if (this
|
|
199
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
179
200
|
return false;
|
|
180
201
|
}
|
|
181
|
-
if (this
|
|
202
|
+
if (this._pattern.type === "Any") {
|
|
182
203
|
return true;
|
|
183
204
|
}
|
|
184
|
-
const thisPattern = (this
|
|
185
|
-
const otherPattern = (other
|
|
205
|
+
const thisPattern = (this._pattern as { type: "Unwrap"; pattern: Pattern }).pattern;
|
|
206
|
+
const otherPattern = (other._pattern as { type: "Unwrap"; pattern: Pattern }).pattern;
|
|
186
207
|
return thisPattern === otherPattern;
|
|
187
208
|
}
|
|
188
209
|
|
|
@@ -190,6 +211,6 @@ export class WrappedPattern implements Matcher {
|
|
|
190
211
|
* Hash code for use in Maps/Sets.
|
|
191
212
|
*/
|
|
192
213
|
hashCode(): number {
|
|
193
|
-
return this
|
|
214
|
+
return this._pattern.type === "Any" ? 0 : 1;
|
|
194
215
|
}
|
|
195
216
|
}
|
package/src/pattern/vm.ts
CHANGED
|
@@ -987,24 +987,25 @@ function compileMetaPattern(
|
|
|
987
987
|
break;
|
|
988
988
|
}
|
|
989
989
|
case "Traverse": {
|
|
990
|
+
// Matches Rust's recursive compilation: each ExtendTraversal gets a
|
|
991
|
+
// matching CombineTraversal so saved paths are properly restored.
|
|
990
992
|
const patterns = pattern.pattern.patterns();
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
compilePattern(pat, code, literals, captureNames);
|
|
995
|
-
if (i < patterns.length - 1) {
|
|
993
|
+
if (patterns.length > 0) {
|
|
994
|
+
compilePattern(patterns[0], code, literals, captureNames);
|
|
995
|
+
for (let i = 1; i < patterns.length; i++) {
|
|
996
996
|
code.push({ type: "ExtendTraversal" });
|
|
997
|
+
compilePattern(patterns[i], code, literals, captureNames);
|
|
998
|
+
}
|
|
999
|
+
for (let i = 1; i < patterns.length; i++) {
|
|
1000
|
+
code.push({ type: "CombineTraversal" });
|
|
997
1001
|
}
|
|
998
|
-
}
|
|
999
|
-
if (patterns.length > 1) {
|
|
1000
|
-
code.push({ type: "CombineTraversal" });
|
|
1001
1002
|
}
|
|
1002
1003
|
break;
|
|
1003
1004
|
}
|
|
1004
1005
|
case "Group": {
|
|
1005
1006
|
const quantifier = pattern.pattern.quantifier();
|
|
1006
|
-
if (quantifier !== undefined) {
|
|
1007
|
-
// Repeat pattern
|
|
1007
|
+
if (quantifier !== undefined && !(quantifier.min() === 1 && quantifier.max() === 1)) {
|
|
1008
|
+
// Repeat pattern (skip for exactly-1 which is simple pass-through)
|
|
1008
1009
|
literals.push(pattern.pattern.pattern());
|
|
1009
1010
|
code.push({
|
|
1010
1011
|
type: "Repeat",
|
|
@@ -1012,7 +1013,7 @@ function compileMetaPattern(
|
|
|
1012
1013
|
quantifier,
|
|
1013
1014
|
});
|
|
1014
1015
|
} else {
|
|
1015
|
-
// Simple grouping
|
|
1016
|
+
// Simple grouping (including exactly-1 quantifier)
|
|
1016
1017
|
compilePattern(pattern.pattern.pattern(), code, literals, captureNames);
|
|
1017
1018
|
}
|
|
1018
1019
|
break;
|