first commit
This commit is contained in:
122
javascript/functionalExpression.js
Normal file
122
javascript/functionalExpression.js
Normal file
@@ -0,0 +1,122 @@
|
||||
var cnst = (value) => (_x, _y, _z) => value;
|
||||
var variable = (name) => (x, y, z) => (name === "x" ? x : name === "y" ? y : z);
|
||||
|
||||
var one = cnst(1);
|
||||
var two = cnst(2);
|
||||
var three = cnst(3);
|
||||
|
||||
var binaryOp = (op) => (f, g) => (x, y, z) => op(f(x, y, z), g(x, y, z));
|
||||
var ternaryOp = (op) => (f, g, h) => (x, y, z) =>
|
||||
op(f(x, y, z), g(x, y, z), h(x, y, z));
|
||||
var quaternaryOp = (op) => (f, g, h, k) => (x, y, z) =>
|
||||
op(f(x, y, z), g(x, y, z), h(x, y, z), k(x, y, z));
|
||||
var quinaryOp = (op) => (f, g, h, i, j) => (x, y, z) =>
|
||||
op(f(x, y, z), g(x, y, z), h(x, y, z), i(x, y, z), j(x, y, z));
|
||||
|
||||
var add = binaryOp((a, b) => a + b);
|
||||
var subtract = binaryOp((a, b) => a - b);
|
||||
var multiply = binaryOp((a, b) => a * b);
|
||||
var divide = binaryOp((a, b) => a / b);
|
||||
var negate = (f) => (x, y, z) => -f(x, y, z);
|
||||
|
||||
var clamp = ternaryOp((v, mn, mx) => Math.min(Math.max(v, mn), mx));
|
||||
var wrap = ternaryOp(
|
||||
(v, mn, mx) => mn + ((((v - mn) % (mx - mn)) + (mx - mn)) % (mx - mn)),
|
||||
);
|
||||
|
||||
var softClamp = quaternaryOp(
|
||||
(v, mn, mx, lambda) =>
|
||||
mn + (mx - mn) / (1 + Math.exp(lambda * ((mx + mn) / 2 - v))),
|
||||
);
|
||||
|
||||
var argMin3 = ternaryOp((a, b, c) => [a, b, c].indexOf(Math.min(a, b, c)));
|
||||
var argMax3 = ternaryOp((a, b, c) => [a, b, c].indexOf(Math.max(a, b, c)));
|
||||
|
||||
var argMin5 = quinaryOp((a, b, c, d, e) =>
|
||||
[a, b, c, d, e].indexOf(Math.min(a, b, c, d, e)),
|
||||
);
|
||||
var argMax5 = quinaryOp((a, b, c, d, e) =>
|
||||
[a, b, c, d, e].indexOf(Math.max(a, b, c, d, e)),
|
||||
);
|
||||
|
||||
var tokenize = (expression) => {
|
||||
var tokens = [];
|
||||
var i = 0;
|
||||
while (i < expression.length) {
|
||||
while (i < expression.length && expression[i] === " ") i++;
|
||||
var start = i;
|
||||
while (i < expression.length && expression[i] !== " ") i++;
|
||||
if (i > start) tokens.push(expression.slice(start, i));
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
var unaryOp = (op) => (f) => (x, y, z) => op(f(x, y, z));
|
||||
|
||||
var arcTan = unaryOp(Math.atan);
|
||||
var arcTan2 = binaryOp(Math.atan2);
|
||||
var sin = unaryOp(Math.sin);
|
||||
var cos = unaryOp(Math.cos);
|
||||
|
||||
var ARITIES = {
|
||||
"+": 2,
|
||||
"-": 2,
|
||||
"*": 2,
|
||||
"/": 2,
|
||||
negate: 1,
|
||||
clamp: 3,
|
||||
wrap: 3,
|
||||
softClamp: 4,
|
||||
argMin3: 3,
|
||||
argMax3: 3,
|
||||
argMin5: 5,
|
||||
argMax5: 5,
|
||||
atan: 1,
|
||||
arcTan: 1,
|
||||
atan2: 2,
|
||||
arcTan2: 2,
|
||||
sin: 1,
|
||||
cos: 1,
|
||||
};
|
||||
|
||||
var OPERATIONS = {
|
||||
"+": add,
|
||||
"-": subtract,
|
||||
"*": multiply,
|
||||
"/": divide,
|
||||
negate: negate,
|
||||
clamp: clamp,
|
||||
wrap: wrap,
|
||||
softClamp: softClamp,
|
||||
argMin3: argMin3,
|
||||
argMax3: argMax3,
|
||||
argMin5: argMin5,
|
||||
argMax5: argMax5,
|
||||
atan: arcTan,
|
||||
arcTan: arcTan,
|
||||
atan2: arcTan2,
|
||||
arcTan2: arcTan2,
|
||||
sin: sin,
|
||||
cos: cos,
|
||||
};
|
||||
|
||||
var NAMED_CONSTS = { one: one, two: two, three: three };
|
||||
|
||||
var parse = (expression) => {
|
||||
var tokens = tokenize(expression);
|
||||
var stack = [];
|
||||
for (var token of tokens) {
|
||||
if (token in OPERATIONS) {
|
||||
var arity = ARITIES[token];
|
||||
var args = stack.splice(-arity);
|
||||
stack.push(OPERATIONS[token](...args));
|
||||
} else if (token in NAMED_CONSTS) {
|
||||
stack.push(NAMED_CONSTS[token]);
|
||||
} else if (token === "x" || token === "y" || token === "z") {
|
||||
stack.push(variable(token));
|
||||
} else {
|
||||
stack.push(cnst(parseFloat(token)));
|
||||
}
|
||||
}
|
||||
return stack[0];
|
||||
};
|
||||
Reference in New Issue
Block a user