method.js 2.3 KB

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