Skip to content

Commit debec10

Browse files
author
Willem Wyndham
authored
fix: make globals static so that they don't pollute downstream libraries (#42)
Also reorganized top level `let`s into static variables.
1 parent 4dc21b0 commit debec10

13 files changed

+306
-53
lines changed

.prettierignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# prettier doesn't support decorators on functions :-(
2-
assembly/char.ts
2+
assembly/char.ts
3+
assembly/nfa/types.ts

asconfig.empty.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"options": {
3+
"runtime": "stub",
4+
"textFile": "build/empty.wat",
5+
"debug": true
6+
},
7+
"entries": ["assembly/__tests__/empty.ts"]
8+
}

assembly/__tests__/empty.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import * as regex from "..";

assembly/__tests__/empty.wat

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(module
2+
(memory $0 0)
3+
(table $0 1 funcref)
4+
(export "memory" (memory $0))
5+
)

assembly/char.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// @ts-ignore
2+
@lazy
13
export const enum Char {
24
None = -1,
35
HorizontalTab = 0x09,

assembly/nfa/matcher.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ const enum MatcherType {
1616
CharacterSet,
1717
CharacterClass,
1818
}
19-
20-
let _flags: Flags;
21-
2219
export class Matcher {
20+
@lazy static _flags: Flags;
21+
2322
constructor(readonly type: MatcherType) {}
2423

2524
matches(code: u32): bool {
@@ -47,20 +46,23 @@ export class Matcher {
4746
node: CharacterClassNode,
4847
flags: Flags
4948
): CharacterClassMatcher {
50-
_flags = flags;
49+
Matcher._flags = flags;
5150
const matchers = node.expressions.map<Matcher>((exp) => {
5251
switch (exp.type) {
5352
case NodeType.CharacterRange:
5453
return Matcher.fromCharacterRangeNode(
5554
exp as CharacterRangeNode,
56-
_flags
55+
Matcher._flags
5756
);
5857
case NodeType.Character:
59-
return Matcher.fromCharacterNode(exp as CharacterNode, _flags);
58+
return Matcher.fromCharacterNode(
59+
exp as CharacterNode,
60+
Matcher._flags
61+
);
6062
case NodeType.CharacterSet:
6163
return Matcher.fromCharacterClassNode(
6264
exp as CharacterSetNode,
63-
_flags
65+
Matcher._flags
6466
);
6567
default:
6668
throw new Error("unsupported node type within character set");
@@ -93,9 +95,12 @@ export class CharacterMatcher extends Matcher {
9395
}
9496
}
9597

96-
const LOWERCASE_LETTERS = new Range(Char.a, Char.z);
97-
const UPPERCASE_LETTERS = new Range(Char.A, Char.Z);
98-
const UPPER_LOWER_OFFSET = Char.a - Char.A;
98+
// @ts-ignore
99+
@lazy const LOWERCASE_LETTERS = new Range(Char.a, Char.z);
100+
// @ts-ignore
101+
@lazy const UPPERCASE_LETTERS = new Range(Char.A, Char.Z);
102+
// @ts-ignore
103+
@lazy const UPPER_LOWER_OFFSET = Char.a - Char.A;
99104

100105
export class CharacterRangeMatcher extends Matcher {
101106
private ranges: Range[];

assembly/nfa/nfa.ts

+8-12
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,15 @@ import {
1414
import { Char } from "../char";
1515
import { Matcher } from "./matcher";
1616
import { Flags } from "../regexp";
17-
18-
export enum MatchResult {
19-
// a match has occurred - which is a signal to consume a character
20-
Match,
21-
// a match failed, abort this regex
22-
Fail,
23-
// this state doesn't preform a match
24-
Ignore,
25-
}
26-
27-
let _stateId: u32 = 0;
17+
import { MatchResult } from "./types";
2818

2919
/* eslint @typescript-eslint/no-empty-function: ["error", { "allow": ["constructors", "methods"] }] */
3020
export class State {
31-
constructor(public transitions: State[] = [], public id: u32 = _stateId++) {}
21+
@lazy static _stateId: u32 = 0;
22+
constructor(
23+
public transitions: State[] = [],
24+
public id: u32 = State._stateId++
25+
) {}
3226

3327
matches(input: string, position: u32): MatchResult {
3428
return MatchResult.Ignore;
@@ -253,3 +247,5 @@ class AutomataFactor {
253247
}
254248
}
255249
}
250+
251+
export { MatchResult } from "./types";

assembly/nfa/types.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @ts-ignore
2+
@lazy
3+
export enum MatchResult {
4+
// a match has occurred - which is a signal to consume a character
5+
Match,
6+
// a match failed, abort this regex
7+
Fail,
8+
// this state doesn't preform a match
9+
Ignore,
10+
}

assembly/parser/node.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ export const enum NodeType {
1515
Group,
1616
}
1717

18-
const emptyNodeArray = new Array<Node>();
19-
2018
export abstract class Node {
19+
@lazy static readonly emptyArray: Node[] = new Array<Node>();
2120
constructor(public type: NodeType) {}
2221

2322
children(): Node[] {
24-
return emptyNodeArray;
23+
return Node.emptyArray;
2524
}
2625

2726
abstract clone(): Node;
@@ -37,7 +36,7 @@ export class AST extends Node {
3736
}
3837

3938
children(): Node[] {
40-
return this.body != null ? [this.body as Node] : emptyNodeArray;
39+
return this.body != null ? [this.body as Node] : Node.emptyArray;
4140
}
4241

4342
clone(): Node {
@@ -210,17 +209,17 @@ export class AlternationNode extends Node {
210209
}
211210
}
212211

213-
let _id = 0;
214-
215212
export class GroupNode extends Node {
213+
@lazy static _id: i32 = 0;
214+
216215
constructor(
217216
public expression: Node,
218217
public capturing: bool,
219218
public id: i32 = -1
220219
) {
221220
super(NodeType.Group);
222221
if (id == -1) {
223-
this.id = _id++;
222+
this.id = GroupNode._id++;
224223
}
225224
}
226225

assembly/parser/walker.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ export function walker(ast: AST, visitor: (node: NodeVisitor) => void): void {
3434
}
3535
}
3636

37-
// range quantifiers are implemented via 'expansion', which significantly
38-
// increases the size of the AST. This imposes a hard limit to prevent
39-
// memory-related issues
40-
const QUANTIFIER_LIMIT = 1000;
37+
/**
38+
range quantifiers are implemented via 'expansion', which significantly
39+
increases the size of the AST. This imposes a hard limit to prevent
40+
memory-related issues
41+
*/
42+
// @ts-ignore
43+
@lazy const QUANTIFIER_LIMIT = 1000;
4144

4245
function parentAsConcatNode(visitor: NodeVisitor): ConcatenationNode {
4346
let concatNode: ConcatenationNode | null = null;

assembly/regexp.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ export class Match {
6969
}
7070
}
7171

72-
let gm = new Array<GroupStartMarkerState>();
73-
7472
export class Flags {
7573
global: bool = false;
7674
ignoreCase: bool = false;
@@ -112,6 +110,7 @@ function lastCapturesForGroup(groupMarkers: GroupStartMarkerState[]): string[] {
112110
}
113111

114112
export class RegExp {
113+
@lazy static gm: GroupStartMarkerState[] = new Array<GroupStartMarkerState>();
115114
lastIndex: i32 = 0;
116115
private flags: Flags;
117116
private nfa: Automata;
@@ -136,16 +135,16 @@ export class RegExp {
136135
this.nfa = Automata.toNFA(ast, flags);
137136

138137
// find all the group marker states
139-
gm = new Array<GroupStartMarkerState>();
138+
RegExp.gm = new Array<GroupStartMarkerState>();
140139
nfaWalker(this.nfa.start, (state) => {
141140
if (state instanceof GroupStartMarkerState) {
142141
const startMarker = state as GroupStartMarkerState;
143142
if (startMarker.capturing) {
144-
gm.push(state as GroupStartMarkerState);
143+
RegExp.gm.push(state as GroupStartMarkerState);
145144
}
146145
}
147146
});
148-
this.groupMarkers = gm;
147+
this.groupMarkers = RegExp.gm;
149148

150149
this.flags = flags;
151150
}

0 commit comments

Comments
 (0)