1'use strict' 2 3/* 4 * Method 5 * 6 * Methods are added, conceptually, to Genfuns, not to objects 7 * themselves, although the Genfun object does not have any pointers to 8 * method objects. 9 * 10 * The _rank vector is an internal datastructure used during dispatch 11 * to figure out whether a method is applicable, and if so, how to 12 * order multiple discovered methods. 13 * 14 * Right now, the score method on Method does not take into account any 15 * ordering, and all arguments to a method are ranked equally for the 16 * sake of ordering. 17 * 18 */ 19const Role = require('./role') 20const util = require('./util') 21 22module.exports = Method 23function Method (genfun, selector, func) { 24 var method = this 25 method.genfun = genfun 26 method.func = func 27 method._rank = [] 28 method.minimalSelector = 0 29 30 const tmpSelector = selector.length ? selector : [Object.prototype] 31 for (var object, i = tmpSelector.length - 1; i >= 0; i--) { 32 object = Object.hasOwnProperty.call(tmpSelector, i) 33 ? tmpSelector[i] 34 : Object.prototype 35 object = util.dispatchableObject(object) 36 if ( 37 typeof object === 'function' && 38 !object.isGenfun 39 ) { 40 object = object.prototype 41 } 42 if (i > 0 && 43 !method.minimalSelector && 44 util.isObjectProto(object)) { 45 continue 46 } else { 47 method.minimalSelector++ 48 if (!Object.hasOwnProperty.call(object, Role.roleKeyName)) { 49 // Object.defineProperty is JS 1.8.0+ 50 Object.defineProperty( 51 object, Role.roleKeyName, {value: [], enumerable: false}) 52 } 53 // XXX HACK - no method replacement now, so we just shove 54 // it in a place where it'll always show up first. This 55 // would probably seriously break method combination if we 56 // had it. 57 object[Role.roleKeyName].unshift(new Role(method, i)) 58 } 59 } 60} 61 62Method.setRankHierarchyPosition = (method, index, hierarchyPosition) => { 63 method._rank[index] = hierarchyPosition 64} 65 66Method.clearRank = method => { 67 method._rank = [] 68} 69 70Method.isFullySpecified = method => { 71 for (var i = 0; i < method.minimalSelector; i++) { 72 if (!method._rank.hasOwnProperty(i)) { 73 return false 74 } 75 } 76 return true 77} 78 79Method.score = method => { 80 // TODO - this makes all items in the list equal 81 return method._rank.reduce((a, b) => a + b, 0) 82} 83