-
Notifications
You must be signed in to change notification settings - Fork 1
/
expression.ts
55 lines (52 loc) · 1.84 KB
/
expression.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { Evaluable, Variable, isExpression, isVariable, Expression, Constant } from "./definitions";
import { isBinaryOperator } from "./operators/binary";
import { isUnaryOperator } from "./operators/unary";
import * as func from "./math/functions";
/**
* Contains helper functions needed by any class that is an [[Expression]].
*/
export namespace ExpressionBuilder {
/**
* Given any one or two [[Evaluable]] quantities, contructs a `Set` of
* unknowns it/they depend on.
* @param a First [[Evaluable]]
* @param b Second [[Evaluable]]
*/
export function createArgList(a: Evaluable, b?: Evaluable) {
const list = new Set<Variable>();
if(isExpression(a))
a.arg_list.forEach(v => list.add(v));
else if(isVariable(a))
list.add(a);
if(b !== undefined) {
if(isExpression(b))
b.arg_list.forEach(v => list.add(v));
else if(isVariable(b))
list.add(b);
}
return list;
}
function simplify(e: Evaluable, values: Map<Variable, Constant>): Evaluable {
if(isExpression(e)) {
let depends = false;
e.arg_list.forEach(v => depends = depends || values.has(v));
if(depends)
return evaluateAt(e, values);
}
return values.get(<Variable>e) || e;
}
/**
* Given an [[Expression]] and a `Map` of variables to constants, evaluates
* the value of the given expression at the given values of variables.
* It is like evaluating the expression by substituting the specified
* variables by respective constant values.
* @param exp The [[Expression]] to evaluate
* @param values The map of [[Variable]]s to [[Constant]]s.
*/
export function evaluateAt(exp: Expression, values: Map<Variable, Constant>) {
if(isBinaryOperator(exp.op))
return simplify(exp.lhs, values)[exp.op](simplify(exp.rhs, values), ...exp.rest);
if(isUnaryOperator(exp.op))
return (<any>func)[exp.op](simplify(exp.arg, values), ...exp.rest);
}
}