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
			| 
											3 years ago
										 | "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
 |