| "use strict";
|
| Object.defineProperty(exports, "__esModule", { value: true });
|
| exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = void 0;
|
| const code_1 = require("./code");
|
| class ValueError extends Error {
|
| constructor(name) {
|
| super(`CodeGen: "code" for ${name} not defined`);
|
| this.value = name.value;
|
| }
|
| }
|
| var UsedValueState;
|
| (function (UsedValueState) {
|
| UsedValueState[UsedValueState["Started"] = 0] = "Started";
|
| UsedValueState[UsedValueState["Completed"] = 1] = "Completed";
|
| })(UsedValueState || (exports.UsedValueState = UsedValueState = {}));
|
| exports.varKinds = {
|
| const: new code_1.Name("const"),
|
| let: new code_1.Name("let"),
|
| var: new code_1.Name("var"),
|
| };
|
| class Scope {
|
| constructor({ prefixes, parent } = {}) {
|
| this._names = {};
|
| this._prefixes = prefixes;
|
| this._parent = parent;
|
| }
|
| toName(nameOrPrefix) {
|
| return nameOrPrefix instanceof code_1.Name ? nameOrPrefix : this.name(nameOrPrefix);
|
| }
|
| name(prefix) {
|
| return new code_1.Name(this._newName(prefix));
|
| }
|
| _newName(prefix) {
|
| const ng = this._names[prefix] || this._nameGroup(prefix);
|
| return `${prefix}${ng.index++}`;
|
| }
|
| _nameGroup(prefix) {
|
| var _a, _b;
|
| 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))) {
|
| throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`);
|
| }
|
| return (this._names[prefix] = { prefix, index: 0 });
|
| }
|
| }
|
| exports.Scope = Scope;
|
| class ValueScopeName extends code_1.Name {
|
| constructor(prefix, nameStr) {
|
| super(nameStr);
|
| this.prefix = prefix;
|
| }
|
| setValue(value, { property, itemIndex }) {
|
| this.value = value;
|
| this.scopePath = (0, code_1._) `.${new code_1.Name(property)}[${itemIndex}]`;
|
| }
|
| }
|
| exports.ValueScopeName = ValueScopeName;
|
| const line = (0, code_1._) `\n`;
|
| class ValueScope extends Scope {
|
| constructor(opts) {
|
| super(opts);
|
| this._values = {};
|
| this._scope = opts.scope;
|
| this.opts = { ...opts, _n: opts.lines ? line : code_1.nil };
|
| }
|
| get() {
|
| return this._scope;
|
| }
|
| name(prefix) {
|
| return new ValueScopeName(prefix, this._newName(prefix));
|
| }
|
| value(nameOrPrefix, value) {
|
| var _a;
|
| if (value.ref === undefined)
|
| throw new Error("CodeGen: ref must be passed in value");
|
| const name = this.toName(nameOrPrefix);
|
| const { prefix } = name;
|
| const valueKey = (_a = value.key) !== null && _a !== void 0 ? _a : value.ref;
|
| let vs = this._values[prefix];
|
| if (vs) {
|
| const _name = vs.get(valueKey);
|
| if (_name)
|
| return _name;
|
| }
|
| else {
|
| vs = this._values[prefix] = new Map();
|
| }
|
| vs.set(valueKey, name);
|
| const s = this._scope[prefix] || (this._scope[prefix] = []);
|
| const itemIndex = s.length;
|
| s[itemIndex] = value.ref;
|
| name.setValue(value, { property: prefix, itemIndex });
|
| return name;
|
| }
|
| getValue(prefix, keyOrRef) {
|
| const vs = this._values[prefix];
|
| if (!vs)
|
| return;
|
| return vs.get(keyOrRef);
|
| }
|
| scopeRefs(scopeName, values = this._values) {
|
| return this._reduceValues(values, (name) => {
|
| if (name.scopePath === undefined)
|
| throw new Error(`CodeGen: name "${name}" has no value`);
|
| return (0, code_1._) `${scopeName}${name.scopePath}`;
|
| });
|
| }
|
| scopeCode(values = this._values, usedValues, getCode) {
|
| return this._reduceValues(values, (name) => {
|
| if (name.value === undefined)
|
| throw new Error(`CodeGen: name "${name}" has no value`);
|
| return name.value.code;
|
| }, usedValues, getCode);
|
| }
|
| _reduceValues(values, valueCode, usedValues = {}, getCode) {
|
| let code = code_1.nil;
|
| for (const prefix in values) {
|
| const vs = values[prefix];
|
| if (!vs)
|
| continue;
|
| const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map());
|
| vs.forEach((name) => {
|
| if (nameSet.has(name))
|
| return;
|
| nameSet.set(name, UsedValueState.Started);
|
| let c = valueCode(name);
|
| if (c) {
|
| const def = this.opts.es5 ? exports.varKinds.var : exports.varKinds.const;
|
| code = (0, code_1._) `${code}${def} ${name} = ${c};${this.opts._n}`;
|
| }
|
| else if ((c = getCode === null || getCode === void 0 ? void 0 : getCode(name))) {
|
| code = (0, code_1._) `${code}${c}${this.opts._n}`;
|
| }
|
| else {
|
| throw new ValueError(name);
|
| }
|
| nameSet.set(name, UsedValueState.Completed);
|
| });
|
| }
|
| return code;
|
| }
|
| }
|
| exports.ValueScope = ValueScope;
|
| |