/* * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ "use strict"; const Anything = Symbol(); function isWildcardKind(kind) { return kind == Anything; } class NameContext { constructor(delegate) { this._map = new Map(); this._set = new Set(); this._currentStatement = null; this._delegate = delegate; this._intrinsics = null; this._program = null; } add(thing) { if (!thing.name) return; if (!thing.origin) throw new Error("Thing does not have origin: " + thing); if (thing.isNative && !thing.implementation) { if (!this._intrinsics) throw new Error("Native function in a scope that does not recognize intrinsics"); this._intrinsics.add(thing); } if (thing.kind == Func) { this._set.add(thing); let array = this._map.get(thing.name); if (!array) { array = []; array.kind = Func; this._map.set(thing.name, array); } if (array.kind != Func) throw new WTypeError(thing.origin.originString, "Cannot reuse type name for function: " + thing.name); array.push(thing); return; } if (this._map.has(thing.name)) throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name); this._set.add(thing); this._map.set(thing.name, thing); } get(kind, name) { let result = this._map.get(name); if (!result && this._delegate) return this._delegate.get(kind, name); if (result && !isWildcardKind(kind) && result.kind != kind) return null; return result; } underlyingThings(kind, name) { let things = this.get(kind, name); return NameContext.underlyingThings(things); } static *underlyingThings(thing) { if (!thing) return; if (thing.kind === Func) { if (!(thing instanceof Array)) throw new Error("Func thing is not array: " + thing); for (let func of thing) yield func; return; } yield thing; } resolveFuncOverload(name, typeArguments, argumentTypes, returnType, allowEntryPoint = false) { let functions = this.get(Func, name); if (!functions) return {failures: []}; return resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType, allowEntryPoint); } get currentStatement() { if (this._currentStatement) return this._currentStatement; if (this._delegate) return this._delegate.currentStatement; return null; } doStatement(statement, callback) { this._currentStatement = statement; callback(); this._currentStatement = null; } recognizeIntrinsics() { this._intrinsics = new Intrinsics(this); } get intrinsics() { if (this._intrinsics) return this._intrinsics; if (this._delegate) return this._delegate.intrinsics; return null; } set program(value) { this._program = value; } get program() { if (this._program) return this._program; if (this._delegate) return this._delegate.program; return null; } *[Symbol.iterator]() { for (let value of this._map.values()) { if (value instanceof Array) { for (let func of value) yield func; continue; } yield value; } } }