diff options
Diffstat (limited to 'deps/npm/node_modules/libcipm/node_modules/protoduck/node_modules/genfun/lib/genfun.js')
-rw-r--r-- | deps/npm/node_modules/libcipm/node_modules/protoduck/node_modules/genfun/lib/genfun.js | 296 |
1 files changed, 0 insertions, 296 deletions
diff --git a/deps/npm/node_modules/libcipm/node_modules/protoduck/node_modules/genfun/lib/genfun.js b/deps/npm/node_modules/libcipm/node_modules/protoduck/node_modules/genfun/lib/genfun.js deleted file mode 100644 index c6ba01ca54..0000000000 --- a/deps/npm/node_modules/libcipm/node_modules/protoduck/node_modules/genfun/lib/genfun.js +++ /dev/null @@ -1,296 +0,0 @@ -'use strict' - -const Method = require('./method') -const Role = require('./role') -const util = require('./util') - -const kCache = Symbol('cache') -const kDefaultMethod = Symbol('defaultMethod') -const kMethods = Symbol('methods') -const kNoNext = Symbol('noNext') - -module.exports = function genfun (opts) { - function gf () { - if (!gf[kMethods].length && gf[kDefaultMethod]) { - return gf[kDefaultMethod].func.apply(this, arguments) - } else { - return gf.applyGenfun(this, arguments) - } - } - Object.setPrototypeOf(gf, Genfun.prototype) - gf[kMethods] = [] - gf[kCache] = {key: [], methods: [], state: STATES.UNINITIALIZED} - if (opts && typeof opts === 'function') { - gf.add(opts) - } else if (opts && opts.default) { - gf.add(opts.default) - } - if (opts && opts.name) { - Object.defineProperty(gf, 'name', { - value: opts.name - }) - } - if (opts && opts.noNextMethod) { - gf[kNoNext] = true - } - return gf -} - -class Genfun extends Function {} -Genfun.prototype.isGenfun = true - -const STATES = { - UNINITIALIZED: 0, - MONOMORPHIC: 1, - POLYMORPHIC: 2, - MEGAMORPHIC: 3 -} - -const MAX_CACHE_SIZE = 32 - -/** - * Defines a method on a generic function. - * - * @function - * @param {Array-like} selector - Selector array for dispatching the method. - * @param {Function} methodFunction - Function to execute when the method - * successfully dispatches. - */ -Genfun.prototype.add = function addMethod (selector, func) { - if (!func && typeof selector === 'function') { - func = selector - selector = [] - } - selector = [].slice.call(selector) - for (var i = 0; i < selector.length; i++) { - if (!selector.hasOwnProperty(i)) { - selector[i] = Object.prototype - } - } - this[kCache] = {key: [], methods: [], state: STATES.UNINITIALIZED} - let method = new Method(this, selector, func) - if (selector.length) { - this[kMethods].push(method) - } else { - this[kDefaultMethod] = method - } - return this -} - -/** - * Removes a previously-defined method on `genfun` that matches - * `selector` exactly. - * - * @function - * @param {Genfun} genfun - Genfun to remove a method from. - * @param {Array-like} selector - Objects to match on when finding a - * method to remove. - */ -Genfun.prototype.rm = function removeMethod () { - throw new Error('not yet implemented') -} - -/** - * Returns true if there are methods that apply to the given arguments on - * `genfun`. Additionally, makes sure the cache is warmed up for the given - * arguments. - * - */ -Genfun.prototype.hasMethod = function hasMethod () { - const methods = this.getApplicableMethods(arguments) - return !!(methods && methods.length) -} - -/** - * This generic function is called when `genfun` has been called and no - * applicable method was found. The default method throws an `Error`. - * - * @function - * @param {Genfun} genfun - Generic function instance that was called. - * @param {*} newthis - value of `this` the genfun was called with. - * @param {Array} callArgs - Arguments the genfun was called with. - */ -module.exports.noApplicableMethod = module.exports() -module.exports.noApplicableMethod.add([], (gf, thisArg, args) => { - let msg = - 'No applicable method found when called with arguments of types: (' + - [].map.call(args, (arg) => { - return (/\[object ([a-zA-Z0-9]+)\]/) - .exec(({}).toString.call(arg))[1] - }).join(', ') + ')' - let err = new Error(msg) - err.genfun = gf - err.thisArg = thisArg - err.args = args - throw err -}) - -/* - * Internal - */ -Genfun.prototype.applyGenfun = function applyGenfun (newThis, args) { - let applicableMethods = this.getApplicableMethods(args) - if (applicableMethods.length === 1 || this[kNoNext]) { - return applicableMethods[0].func.apply(newThis, args) - } else if (applicableMethods.length > 1) { - let idx = 0 - const nextMethod = function nextMethod () { - if (arguments.length) { - // Replace args if passed in explicitly - args = arguments - Array.prototype.push.call(args, nextMethod) - } - const next = applicableMethods[idx++] - if (idx >= applicableMethods.length) { - Array.prototype.pop.call(args) - } - return next.func.apply(newThis, args) - } - Array.prototype.push.call(args, nextMethod) - return nextMethod() - } else { - return module.exports.noApplicableMethod(this, newThis, args) - } -} - -Genfun.prototype.getApplicableMethods = function getApplicableMethods (args) { - if (!args.length || !this[kMethods].length) { - return this[kDefaultMethod] ? [this[kDefaultMethod]] : [] - } - let applicableMethods - let maybeMethods = cachedMethods(this, args) - if (maybeMethods) { - applicableMethods = maybeMethods - } else { - applicableMethods = computeApplicableMethods(this, args) - cacheArgs(this, args, applicableMethods) - } - return applicableMethods -} - -function cacheArgs (genfun, args, methods) { - if (genfun[kCache].state === STATES.MEGAMORPHIC) { return } - var key = [] - var proto - for (var i = 0; i < args.length; i++) { - proto = cacheableProto(genfun, args[i]) - if (proto) { - key[i] = proto - } else { - return null - } - } - genfun[kCache].key.unshift(key) - genfun[kCache].methods.unshift(methods) - if (genfun[kCache].key.length === 1) { - genfun[kCache].state = STATES.MONOMORPHIC - } else if (genfun[kCache].key.length < MAX_CACHE_SIZE) { - genfun[kCache].state = STATES.POLYMORPHIC - } else { - genfun[kCache].state = STATES.MEGAMORPHIC - } -} - -function cacheableProto (genfun, arg) { - var dispatchable = util.dispatchableObject(arg) - if (Object.hasOwnProperty.call(dispatchable, Role.roleKeyName)) { - for (var j = 0; j < dispatchable[Role.roleKeyName].length; j++) { - var role = dispatchable[Role.roleKeyName][j] - if (role.method.genfun === genfun) { - return null - } - } - } - return Object.getPrototypeOf(dispatchable) -} - -function cachedMethods (genfun, args) { - if (genfun[kCache].state === STATES.UNINITIALIZED || - genfun[kCache].state === STATES.MEGAMORPHIC) { - return null - } - var protos = [] - var proto - for (var i = 0; i < args.length; i++) { - proto = cacheableProto(genfun, args[i]) - if (proto) { - protos[i] = proto - } else { - return - } - } - for (i = 0; i < genfun[kCache].key.length; i++) { - if (matchCachedMethods(genfun[kCache].key[i], protos)) { - return genfun[kCache].methods[i] - } - } -} - -function matchCachedMethods (key, protos) { - if (key.length !== protos.length) { return false } - for (var i = 0; i < key.length; i++) { - if (key[i] !== protos[i]) { - return false - } - } - return true -} - -function computeApplicableMethods (genfun, args) { - args = [].slice.call(args) - let discoveredMethods = [] - function findAndRankRoles (object, hierarchyPosition, index) { - var roles = Object.hasOwnProperty.call(object, Role.roleKeyName) - ? object[Role.roleKeyName] - : [] - roles.forEach(role => { - if (role.method.genfun === genfun && index === role.position) { - if (discoveredMethods.indexOf(role.method) < 0) { - Method.clearRank(role.method) - discoveredMethods.push(role.method) - } - Method.setRankHierarchyPosition(role.method, index, hierarchyPosition) - } - }) - // When a discovered method would receive more arguments than - // were specialized, we pretend all extra arguments have a role - // on Object.prototype. - if (util.isObjectProto(object)) { - discoveredMethods.forEach(method => { - if (method.minimalSelector <= index) { - Method.setRankHierarchyPosition(method, index, hierarchyPosition) - } - }) - } - } - args.forEach((arg, index) => { - getPrecedenceList(util.dispatchableObject(arg)) - .forEach((obj, hierarchyPosition) => { - findAndRankRoles(obj, hierarchyPosition, index) - }) - }) - let applicableMethods = discoveredMethods.filter(method => { - return (args.length === method._rank.length && - Method.isFullySpecified(method)) - }) - applicableMethods.sort((a, b) => Method.score(a) - Method.score(b)) - if (genfun[kDefaultMethod]) { - applicableMethods.push(genfun[kDefaultMethod]) - } - return applicableMethods -} - -/* - * Helper function for getting an array representing the entire - * inheritance/precedence chain for an object by navigating its - * prototype pointers. - */ -function getPrecedenceList (obj) { - var precedenceList = [] - var nextObj = obj - while (nextObj) { - precedenceList.push(nextObj) - nextObj = Object.getPrototypeOf(nextObj) - } - return precedenceList -} |