thedesk/app/node_modules/over/overload.js
2018-02-18 16:29:06 +09:00

237 lines
5.9 KiB
JavaScript

'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;
};