/**
* Operators object that maps operator names to their corresponding symbols.
* @type {Object}
*/
let Operators = {
add: '+',
mul: '*',
div: '/',
equals: '==',
pow: '**',
neg: '-',
lessThan: '<',
greaterThan: '>'
};
/**
* Object that handles boolean operations.
* @type {Object}
*/
let booleanHandler = Object.create(null);
/**
* Handles boolean operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {*} - The result of the operation.
*/
booleanHandler.boolean = function (op, other) {
if (op === 'equals') {
return this == other;
}
let className = other?.constructor?.name || typeof other;
throw new Error(`Boolean "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Handles object operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {*} - The result of the operation.
*/
booleanHandler.object = function (op, other) {
if (op === 'add') {
return other.add(Number(this));
}
throw new Error(`Boolean "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Object that handles function operations.
* @type {Object}
*/
let functionHandler = Object.create(null);
/**
* Handles boolean operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {Function} - A function that performs the operation.
*/
functionHandler.boolean = function (op, other) {
return (...x) => this(...x)[op](Number(other));
};
/**
* Handles function operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {Function} - A function that performs the operation.
*/
functionHandler.function = function (op, other) {
return (...x) => {
try {
return this(...x)[op](other(...x));
} catch (e) {
throw new Error(`Unsupported ${op} for ${other}`);
}
};
};
/**
* Handles object operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {Function} - A function that performs the operation.
*/
functionHandler.object = function (op, other) {
return (...x) => {
try {
return this(...x)[op](other);
} catch (e) {
throw new Error(`Unsupported ${op} for ${other}`);
}
};
};
/**
* Default handler for boolean and function operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @throws {Error} - Throws an error indicating the operation is not supported.
*/
booleanHandler.default = functionHandler.default = function (op, other) {
throw new Error(`Boolean "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Object that handles string operations.
* @type {Object}
*/
let stringHandler = Object.create(null);
/**
* Default handler for string operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @throws {Error} - Throws an error indicating the operation is not supported.
*/
stringHandler.default = function (op, other) {
if (op == 'equals') {
return this == other;
} else if (op == 'lessThan') {
return this < other;
} else if (op == 'greaterThan') {
return this > other;
}
throw new Error(`String "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Handles function operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {string} - The result of the operation.
*/
stringHandler.function = function (op, other) {
if (op == 'add') {
return this + String(other);
}
throw new Error(`String "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Handles boolean operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {string} - The result of the operation.
*/
stringHandler.boolean = function (op, other) {
if (op == 'add') {
return this + String(other);
} else if (op == 'equals') {
return this == other;
} else if (op == 'lessThan') {
return this < other;
} else if (op == 'greaterThan') {
return this > other;
}
throw new Error(`String "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Handles object operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {string} - The result of the operation.
*/
stringHandler.object = function (op, other) {
if (op == 'add') {
return this + String(other);
}
throw new Error(`String "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
/**
* Handles string operations.
* @param {string} op - The operator.
* @param {*} other - The other operand.
* @returns {string} - The result of the operation.
*/
stringHandler.string = function (op, other) {
if (op == 'add') {
return this + other;
} else if (op == 'equals') {
return this == other;
} else if (op == 'lessThan') {
return this < other;
} else if (op == 'greaterThan') {
return this > other;
}
throw new Error(`String "${this}" does not support "${Operators[op] || op}" for "${other}"`);
};
// Monkey patching the prototype objects
for (let op in Operators) {
Boolean.prototype[op] = function (other) {
return booleanHandler[typeof other]?.call(this, op, other) || booleanHandler.default.call(this, op, other);
};
Function.prototype[op] = function (other) {
return functionHandler[typeof other]?.call(this, op, other) || functionHandler.default.call(this, op, other);
};
String.prototype[op] = function (other) {
return stringHandler[typeof other]?.call(this, op, other) || stringHandler.default.call(this, op, other);
};
}