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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
import * as assert from 'assert';
import { ICodeImplementation } from '../implementation/code';
import { IImplementation } from '../implementation/full';
import { INodeImplementation } from '../implementation/node';
import { ITransformImplementation } from '../implementation/transform';
import { IWrap } from '../wrap';
import { ContainerWrap } from './wrap';
export { ContainerWrap };
export class Container {
private readonly map: Map<string, IImplementation> = new Map();
public add(key: string, impl: IImplementation): void {
assert(!this.map.has(key), `Duplicate implementation key: "${key}"`);
this.map.set(key, impl);
}
public build(): IImplementation {
return {
code: this.buildCode(),
node: this.buildNode(),
transform: this.buildTransform(),
};
}
public buildCode(): ICodeImplementation {
return {
And: this.combine((impl) => impl.code.And),
IsEqual: this.combine((impl) => impl.code.IsEqual),
Load: this.combine((impl) => impl.code.Load),
Match: this.combine((impl) => impl.code.Match),
MulAdd: this.combine((impl) => impl.code.MulAdd),
Or: this.combine((impl) => impl.code.Or),
Span: this.combine((impl) => impl.code.Span),
Store: this.combine((impl) => impl.code.Store),
Test: this.combine((impl) => impl.code.Test),
Update: this.combine((impl) => impl.code.Update),
Value: this.combine((impl) => impl.code.Value),
};
}
public buildNode(): INodeImplementation {
return {
Consume: this.combine((impl) => impl.node.Consume),
Empty: this.combine((impl) => impl.node.Empty),
Error: this.combine((impl) => impl.node.Error),
Invoke: this.combine((impl) => impl.node.Invoke),
Pause: this.combine((impl) => impl.node.Pause),
Sequence: this.combine((impl) => impl.node.Sequence),
Single: this.combine((impl) => impl.node.Single),
SpanEnd: this.combine((impl) => impl.node.SpanEnd),
SpanStart: this.combine((impl) => impl.node.SpanStart),
TableLookup: this.combine((impl) => impl.node.TableLookup),
};
}
public buildTransform(): ITransformImplementation {
return {
ID: this.combine((impl) => impl.transform.ID),
ToLower: this.combine((impl) => impl.transform.ToLower),
ToLowerUnsafe: this.combine((impl) => impl.transform.ToLowerUnsafe),
};
}
private combine<T>(gather: (impl: IImplementation) => new(n: T) => IWrap<T>)
: new(n: T) => ContainerWrap<T> {
const wraps: Map<string, new(n: T) => IWrap<T>> = new Map();
for (const [ key, impl ] of this.map) {
wraps.set(key, gather(impl));
}
return class ContainerWrapSingle extends ContainerWrap<T> {
constructor(ref: T) {
super(ref);
for (const [ key, impl ] of wraps) {
this.map.set(key, new impl(ref));
}
}
};
}
}
|