| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- 'use strict';
- // overloadDefs
- // self, overloadDefs
- var overload = module.exports = function () {
- var self, selfSet = false, overloadDefs;
- if (arguments.length === 1) {
- overloadDefs = arguments[0];
- } else {
- selfSet = true;
- self = arguments[0];
- overloadDefs = arguments[1];
- }
- return function () {
- if (!selfSet) {
- self = this;
- }
- var args = Array.prototype.slice.call(arguments);
- var overloadMatchData = findOverload(overloadDefs, args);
- if (!overloadMatchData) {
- throw new Error(createErrorMessage('No match found.', overloadDefs));
- }
- var overloadFn = overloadMatchData.def[overloadMatchData.def.length - 1];
- return overloadFn.apply(self, overloadMatchData.args);
- };
- };
- var findOverload = overload.findOverload = function (overloadDefs, args) {
- for (var i = 0; i < overloadDefs.length; i++) {
- if (i === overloadDefs.length - 1 && typeof(overloadDefs[i]) === 'function') {
- return { args: args, def: [overloadDefs[i]] };
- }
- var newArgs;
- if (newArgs = isMatch(overloadDefs[i], args)) {
- return { args: newArgs, def: overloadDefs[i] };
- }
- }
- return null;
- };
- function isMatch(overloadDef, args) {
- var overloadDefIdx;
- var argIdx;
- var newArgs = [];
- for (overloadDefIdx = 0, argIdx = 0; overloadDefIdx < overloadDef.length - 1; overloadDefIdx++) {
- if (typeof(overloadDef[overloadDefIdx]) !== 'function') {
- throw new Error("Invalid overload definition. Array should only contain functions.");
- }
- //console.log('overloadDef/arg:', overloadDef[overloadDefIdx], args[argIdx]);
- var result = overloadDef[overloadDefIdx](args[argIdx]);
- //console.log('result:', result);
- if (result) {
- if (result.hasOwnProperty('defaultValue')) {
- newArgs.push(result.defaultValue);
- } else {
- if (overloadDef[overloadDefIdx].optional && args[argIdx] === null) {
- argIdx++;
- newArgs.push(overloadDef[overloadDefIdx].defaultValue);
- continue;
- }
- newArgs.push(args[argIdx]);
- argIdx++;
- }
- } else {
- if (overloadDef[overloadDefIdx].optional) {
- newArgs.push(overloadDef[overloadDefIdx].defaultValue);
- continue;
- }
- return false;
- }
- }
- //console.log('compares', overloadDefIdx, overloadDef.length - 1, argIdx, args.length, newArgs.length);
- if (overloadDefIdx === overloadDef.length - 1 && argIdx >= args.length) {
- return newArgs;
- }
- return false;
- }
- function createErrorMessage(message, overloadDefs) {
- message += '\n';
- message += ' Possible matches:\n';
- for (var i = 0; i < overloadDefs.length; i++) {
- var overloadDef = overloadDefs[i];
- if (typeof(overloadDef) === 'function') {
- message += ' [default]\n';
- } else {
- var matchers = overloadDef.slice(0, overloadDef.length - 1);
- matchers = matchers.map(function (m) {
- if (!m) {
- return '[invalid argument definition]';
- }
- return m.name || m;
- });
- if (matchers.length === 0) {
- message += ' ()\n';
- } else {
- message += ' (' + matchers.join(', ') + ')\n';
- }
- }
- }
- return message;
- }
- // --- func
- overload.func = function func(arg) {
- return typeof(arg) === 'function';
- };
- overload.funcOptional = function funcOptional(arg) {
- if (!arg) {
- return true;
- }
- return overload.func(arg);
- };
- overload.funcOptional.optional = true;
- overload.funcOptionalWithDefault = function (def) {
- var fn = function funcOptionalWithDefault(arg) {
- if (arg === undefined) {
- return false;
- }
- return overload.func(arg);
- };
- fn.optional = true;
- fn.defaultValue = def;
- return fn;
- };
- // --- callback
- overload.callbackOptional = function callbackOptional(arg) {
- if (!arg) {
- return { defaultValue: function defaultCallback() {} };
- }
- return overload.func(arg);
- };
- overload.callbackOptional.optional = true;
- // --- string
- overload.string = function string(arg) {
- return typeof(arg) === 'string';
- };
- overload.stringOptional = function stringOptional(arg) {
- if (!arg) {
- return true;
- }
- return overload.string(arg);
- };
- overload.stringOptional.optional = true;
- overload.stringOptionalWithDefault = function (def) {
- var fn = function stringOptionalWithDefault(arg) {
- if (arg === undefined) {
- return false;
- }
- return overload.string(arg);
- };
- fn.optional = true;
- fn.defaultValue = def;
- return fn;
- };
- // --- number
- overload.number = function number(arg) {
- return typeof(arg) === 'number';
- };
- overload.numberOptional = function numberOptional(arg) {
- if (!arg) {
- return true;
- }
- return overload.number(arg);
- };
- overload.numberOptional.optional = true;
- overload.numberOptionalWithDefault = function (def) {
- var fn = function numberOptionalWithDefault(arg) {
- if (arg === undefined) {
- return false;
- }
- return overload.number(arg);
- };
- fn.optional = true;
- fn.defaultValue = def;
- return fn;
- };
- // --- array
- overload.array = function array(arg) {
- return arg instanceof Array;
- };
- overload.arrayOptional = function arrayOptional(arg) {
- if (!arg) {
- return true;
- }
- return overload.array(arg);
- };
- overload.arrayOptional.optional = true;
- overload.arrayOptionalWithDefault = function (def) {
- var fn = function arrayOptionalWithDefault(arg) {
- if (arg === undefined) {
- return false;
- }
- return overload.array(arg);
- };
- fn.optional = true;
- fn.defaultValue = def;
- return fn;
- };
- // --- object
- overload.object = function object(arg) {
- return typeof(arg) === 'object';
- };
- overload.objectOptional = function objectOptional(arg) {
- if (!arg) {
- return true;
- }
- return overload.object(arg);
- };
- overload.objectOptional.optional = true;
- overload.objectOptionalWithDefault = function (def) {
- var fn = function objectOptionalWithDefault(arg) {
- if (arg === undefined) {
- return false;
- }
- return overload.object(arg);
- };
- fn.optional = true;
- fn.defaultValue = def;
- return fn;
- };
|