You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							143 lines
						
					
					
						
							5.1 KiB
						
					
					
				
			
		
		
	
	
							143 lines
						
					
					
						
							5.1 KiB
						
					
					
				| "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 || (exports.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;
 | |
| //# sourceMappingURL=scope.js.map
 |