UNPKG

5.21 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = void 0;
4const code_1 = require("./code");
5class ValueError extends Error {
6 constructor(name) {
7 super(`CodeGen: "code" for ${name} not defined`);
8 this.value = name.value;
9 }
10}
11var UsedValueState;
12(function (UsedValueState) {
13 UsedValueState[UsedValueState["Started"] = 0] = "Started";
14 UsedValueState[UsedValueState["Completed"] = 1] = "Completed";
15})(UsedValueState = exports.UsedValueState || (exports.UsedValueState = {}));
16exports.varKinds = {
17 const: new code_1.Name("const"),
18 let: new code_1.Name("let"),
19 var: new code_1.Name("var"),
20};
21class Scope {
22 constructor({ prefixes, parent } = {}) {
23 this._names = {};
24 this._prefixes = prefixes;
25 this._parent = parent;
26 }
27 toName(nameOrPrefix) {
28 return nameOrPrefix instanceof code_1.Name ? nameOrPrefix : this.name(nameOrPrefix);
29 }
30 name(prefix) {
31 return new code_1.Name(this._newName(prefix));
32 }
33 _newName(prefix) {
34 const ng = this._names[prefix] || this._nameGroup(prefix);
35 return `${prefix}${ng.index++}`;
36 }
37 _nameGroup(prefix) {
38 var _a, _b;
39 if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a._prefixes) === null || _b === void 0 ? void 0 : _b.has(prefix)) || (this._prefixes && !this._prefixes.has(prefix))) {
40 throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`);
41 }
42 return (this._names[prefix] = { prefix, index: 0 });
43 }
44}
45exports.Scope = Scope;
46class ValueScopeName extends code_1.Name {
47 constructor(prefix, nameStr) {
48 super(nameStr);
49 this.prefix = prefix;
50 }
51 setValue(value, { property, itemIndex }) {
52 this.value = value;
53 this.scopePath = (0, code_1._) `.${new code_1.Name(property)}[${itemIndex}]`;
54 }
55}
56exports.ValueScopeName = ValueScopeName;
57const line = (0, code_1._) `\n`;
58class ValueScope extends Scope {
59 constructor(opts) {
60 super(opts);
61 this._values = {};
62 this._scope = opts.scope;
63 this.opts = { ...opts, _n: opts.lines ? line : code_1.nil };
64 }
65 get() {
66 return this._scope;
67 }
68 name(prefix) {
69 return new ValueScopeName(prefix, this._newName(prefix));
70 }
71 value(nameOrPrefix, value) {
72 var _a;
73 if (value.ref === undefined)
74 throw new Error("CodeGen: ref must be passed in value");
75 const name = this.toName(nameOrPrefix);
76 const { prefix } = name;
77 const valueKey = (_a = value.key) !== null && _a !== void 0 ? _a : value.ref;
78 let vs = this._values[prefix];
79 if (vs) {
80 const _name = vs.get(valueKey);
81 if (_name)
82 return _name;
83 }
84 else {
85 vs = this._values[prefix] = new Map();
86 }
87 vs.set(valueKey, name);
88 const s = this._scope[prefix] || (this._scope[prefix] = []);
89 const itemIndex = s.length;
90 s[itemIndex] = value.ref;
91 name.setValue(value, { property: prefix, itemIndex });
92 return name;
93 }
94 getValue(prefix, keyOrRef) {
95 const vs = this._values[prefix];
96 if (!vs)
97 return;
98 return vs.get(keyOrRef);
99 }
100 scopeRefs(scopeName, values = this._values) {
101 return this._reduceValues(values, (name) => {
102 if (name.scopePath === undefined)
103 throw new Error(`CodeGen: name "${name}" has no value`);
104 return (0, code_1._) `${scopeName}${name.scopePath}`;
105 });
106 }
107 scopeCode(values = this._values, usedValues, getCode) {
108 return this._reduceValues(values, (name) => {
109 if (name.value === undefined)
110 throw new Error(`CodeGen: name "${name}" has no value`);
111 return name.value.code;
112 }, usedValues, getCode);
113 }
114 _reduceValues(values, valueCode, usedValues = {}, getCode) {
115 let code = code_1.nil;
116 for (const prefix in values) {
117 const vs = values[prefix];
118 if (!vs)
119 continue;
120 const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map());
121 vs.forEach((name) => {
122 if (nameSet.has(name))
123 return;
124 nameSet.set(name, UsedValueState.Started);
125 let c = valueCode(name);
126 if (c) {
127 const def = this.opts.es5 ? exports.varKinds.var : exports.varKinds.const;
128 code = (0, code_1._) `${code}${def} ${name} = ${c};${this.opts._n}`;
129 }
130 else if ((c = getCode === null || getCode === void 0 ? void 0 : getCode(name))) {
131 code = (0, code_1._) `${code}${c}${this.opts._n}`;
132 }
133 else {
134 throw new ValueError(name);
135 }
136 nameSet.set(name, UsedValueState.Completed);
137 });
138 }
139 return code;
140 }
141}
142exports.ValueScope = ValueScope;
143//# sourceMappingURL=scope.js.map
\No newline at end of file