# Expression trees

When parsing an expression via `math.parse(expr)`, math.js generates an
expression tree and returns the root node of the tree. An expression tree can
be used to analyze, manipulate, and evaluate expressions.

Example:

```js
var node = math.parse('sqrt(2 + x)');
```

In this case, the expression `sqrt(2 + x)` is parsed as:

```
  FunctionNode    sqrt
                   |
  OperatorNode     +
                  / \
  ConstantNode   2   x   SymbolNode
```

Alternatively, this expression tree can be build by manually creating nodes:

```js
var node1 = new math.expression.node.ConstantNode(2);
var node2 = new math.expression.node.SymbolNode('x');
var node3 = new math.expression.node.OperatorNode('+', 'add', [node1, node2]);
var node4 = new math.expression.node.FunctionNode('sqrt', [node3]);
```

The resulting expression tree with root node `node4` is equal to the expression
tree generated by `math.parse('sqrt(2 + x)')`.


## API

### Methods

All nodes have the following methods:

-   `clone() : Node`

    Create a shallow clone of the node.
    The node itself is cloned, its childs are not cloned.

-   `cloneDeep() : Node`

    Create a deep clone of the node.
    Both the node as well as all its childs are cloned recursively.

-   `compile() : Object`

    Compile an expression into optimized JavaScript code. `compile` returns an 
    object with a function `eval([scope])` to evaluate. Example:
    
    ```js
    var node = math.parse('2 + x'); // returns the root Node of an expression tree
    var code = node.compile();      // returns {eval: function (scope) {...}}
    var eval = code.eval({x: 3});   // returns 5
    ```

-   `eval([scope]) : Object`

    Compile and eval an expression, this is the equivalent of doing 
    `node.compile().eval(scope)`. Example:
    
    ```js
    var node = math.parse('2 + x'); // returns the root Node of an expression tree
    var eval = node.eval({x: 3});   // returns 5
    ```

-   `equals(other: Node) : boolean`

    Test whether this node equals an other node. Does a deep comparison of the
    values of both nodes.

-   `filter(callback: function) : Node[]`

    Recursively filter nodes in an expression tree. The `callback` function is
    called as `callback(node: Node, path: string, parent: Node) : boolean` for
    every node in the tree, and must return a boolean. The function `filter`
    returns an array with nodes for which the test returned true.
    Parameter `path` is a string containing a relative JSON Path.
    
    Example:

    ```js
    var node = math.parse('x^2 + x/4 + 3*y');
    var filtered = node.filter(function (node) {
      return node.isSymbolNode && node.name == 'x';
    });
    // returns an array with two entries: two SymbolNodes 'x'
    ```

-   `forEach(callback: function) : Node[]`

    Execute a callback for each of the child nodes of this node. The `callback`
    function is called as `callback(child: Node, path: string, parent: Node)`.
    Parameter `path` is a string containing a relative JSON Path.
    
    See also `traverse`, which is a recursive version of `forEach`.
    
    Example:
    
    ```js
    var node = math.parse('3 * x + 2');
    node.forEach(function (node, path, parent) {
      switch (node.type) {
        case 'OperatorNode': console.log(node.type, node.op);    break;
        case 'ConstantNode': console.log(node.type, node.value); break;
        case 'SymbolNode':   console.log(node.type, node.name);  break;
        default:             console.log(node.type);
      }
    });
    // outputs:
    //   OperatorNode *
    //   ConstantNode 2
    ```

-   `map(callback: function) : Node[]`

    Transform a node. Creates a new Node having it's childs be the results of
    calling the provided callback function for each of the childs of the original
    node. The `callback` function is called as `callback(child: Node, path: string,
    parent: Node)` and must return a Node. Parameter `path` is a string containing
    a relative JSON Path.
    
    See also `transform`, which is a recursive version of `map`.

-   `toString(options: object) : string`

    Get a string representation of the parsed expression. This is not exactly
    the same as the original input. Example:

    ```js
    var node = math.parse('3+4*2');
    node.toString();  // returns '3 + (4 * 2)'
    ```

    Information about the options in [Customization](customization.md#custom-latex-and-string-output).

-   `toTex(options: object): string`

    Get a [LaTeX](http://en.wikipedia.org/wiki/LaTeX) representation of the
    expression. Example:

    ```js
    var node = math.parse('sqrt(2/3)');
    node.toTex(); // returns '\sqrt{\frac{2}{3}}'
    ```

    Information about the options in [Customization](customization.md#custom-latex-and-string-output).

-   `transform(callback: function)`

    Recursively transform an expression tree via a transform function. Similar
    to `Array.map`, but recursively executed on all nodes in the expression tree.
    The callback function is a mapping function accepting a node, and returning
    a replacement for the node or the original node. Function `callback` is
    called as `callback(node: Node, path: string, parent: Node)` for every node
    in the tree, and must return a `Node`. Parameter `path` is a string containing
    a relative JSON Path.

    For example, to replace all nodes of type `SymbolNode` having name 'x' with a
    ConstantNode with value `3`:

    ```js
    var node = math.parse('x^2 + 5*x');
    var transformed = node.transform(function (node, path, parent) {
      if (node.SymbolNode && node.name == 'x') {
        return new math.expression.node.ConstantNode(3);
      }
      else {
        return node;
      }
    });
    transformed.toString(); // returns '(3 ^ 2) + (5 * 3)'
    ```

-   `traverse(callback)`

    Recursively traverse all nodes in a node tree. Executes given callback for
    this node and each of its child nodes. Similar to `Array.forEach`, except
    recursive.
    The callback function is a mapping function accepting a node, and returning
    a replacement for the node or the original node. Function `callback` is
    called as `callback(node: Node, path: string, parent: Node)` for every node
    in the tree. Parameter `path` is a string containing a relative JSON Path.
    Example:

    ```js
    var node = math.parse('3 * x + 2');
    node.traverse(function (node, path, parent) {
      switch (node.type) {
        case 'OperatorNode': console.log(node.type, node.op);    break;
        case 'ConstantNode': console.log(node.type, node.value); break;
        case 'SymbolNode':   console.log(node.type, node.name);  break;
        default:             console.log(node.type);
      }
    });
    // outputs:
    //   OperatorNode +
    //   OperatorNode *
    //   ConstantNode 3
    //   SymbolNode x
    //   ConstantNode 2
    ```


### Properties

Each `Node` has the following properties:

-   `comment: string`

    A string holding a comment if there was any in the expression, or else the
    string will be empty string. A comment can be attached to the root node of
    an expression or to each of the childs nodes of a `BlockNode`.

-   `isNode: true`

    Is defined with value `true` on Nodes. Additionally, each type of node 
    adds it's own flag, for example a `SymbolNode` as has a property 
    `isSymbolNode: true`. 

-   `type: string`

    The type of the node, for example `'SymbolNode'` in case of a `SymbolNode`.


## Nodes

math.js has the following types of nodes. All nodes are available at the
namespace `math.expression.node`.


### AccessorNode

Construction:

```
new AccessorNode(object: Node, index: IndexNode)
```

Properties:

- `object: Node`
- `index: IndexNode`
- `name: string` (read-only) The function or method name. Returns an empty string when undefined.

Examples:

```js
var node1 = math.parse('a[3]');

var object = new math.expression.node.SymbolNode('a');
var index = new math.expression.node.IndexNode([3]);
var node2 = new math.expression.node.AccessorNode(object, index);
```


### ArrayNode

Construction:

```
new ArrayNode(items: Node[])
```

Properties:

- `items: Node[]`

Examples:

```js
var node1 = math.parse('[1, 2, 3]');

var one    = new math.expression.node.ConstantNode(1);
var two    = new math.expression.node.ConstantNode(2);
var three  = new math.expression.node.ConstantNode(3);
var node2  = new math.expression.node.ArrayNode([one, two, three]);
```


### AssignmentNode

Construction:

```
new AssignmentNode(object: SymbolNode, value: Node)
new AssignmentNode(object: SymbolNode | AccessorNode, index: IndexNode, value: Node)
```

Properties:

- `object: SymbolNode | AccessorNode`
- `index: IndexNode | null`
- `value: Node`
- `name: string` (read-only) The function or method name. Returns an empty string when undefined.

Examples:

```js
var node1 = math.parse('a = 3');

var object = new math.expression.node.SymbolNode('a');
var value = new math.expression.node.ConstantNode(3);
var node2 = new math.expression.node.AssignmentNode(object, value);
```


### BlockNode

A `BlockNode` is created when parsing a multi line expression like `a=2;b=3` or
`a=2\nb=3`. Evaluating a `BlockNode` returns a `ResultSet`. The results can be
retrieved via `ResultSet.entries` or `ResultSet.valueOf()`, which contains
an `Array` with the results of the visible lines (i.e. lines not ending with
a semicolon).

Construction:

```
block = new BlockNode(Array.<{node: Node} | {node: Node, visible: boolean}>)
```

Properties:

- `blocks: Array.<{node: Node, visible: boolean}>`

Examples:

```js
var block1 = math.parse('a=1; b=2; c=3');

var a = new math.expression.node.SymbolNode('a');
var one = new math.expression.node.ConstantNode(1);
var ass1 = new math.expression.node.AssignmentNode(a, one);

var b = new math.expression.node.SymbolNode('b');
var two = new math.expression.node.ConstantNode(2);
var ass2 = new math.expression.node.AssignmentNode(b, two);

var c = new math.expression.node.SymbolNode('c');
var three = new math.expression.node.ConstantNode(3);
var ass3 = new math.expression.node.AssignmentNode(c, three);

var block2 = new BlockNode([
  {node: ass1, visible: false},
  {node: ass2, visible: false},
  {node: ass3, visible: true}
]);
```


### ConditionalNode

Construction:

```
new ConditionalNode(condition: Node, trueExpr: Node, falseExpr: Node)
```

Properties:

- `condition: Node`
- `trueExpr: Node`
- `falseExpr: Node`

Examples:

```js
var node1 = math.parse('a > 0 ? a : -a');

var a         = new math.expression.node.SymbolNode('a');
var zero      = new math.expression.node.ConstantNode(0);
var condition = new math.expression.node.OperatorNode('>', 'larger', [a, zero]);
var trueExpr  = a;
var falseExpr = new math.expression.node.OperatorNode('-', 'unaryMinus', [a]);
var node2     = new math.expression.node.ConditionalNode(condition, trueExpr, falseExpr);
```

### ConstantNode

Construction:

```
new ConstantNode(value: * [, valueType: string])
```

Properties:

- `value: *`
- `valueType: string`

Examples:

```js
var node1 = math.parse('2.4');

var node2 = new math.expression.node.ConstantNode(2.4);
var node3 = new math.expression.node.ConstantNode('2.4', 'number');
```


### FunctionAssignmentNode

Construction:

```
new FunctionAssignmentNode(name: string, params: string[], expr: Node)
```

Properties:

- `name: string`
- `params: string[]`
- `expr: Node`

Examples:

```js
var node1 = math.parse('f(x) = x^2');

var x      = new math.expression.node.SymbolNode('x');
var two    = new math.expression.node.ConstantNode(2);
var expr   = new math.expression.node.OperatorNode('^', 'pow', [x, 2]);
var node2  = new math.expression.node.FunctionAssignmentNode('f', ['x'], expr);
```


### FunctionNode

Construction:

```
new FunctionNode(fn: Node | string, args: Node[])
```

Properties:

- `fn: Node | string` (read-only) The object or function name which to invoke.
- `args: Node[]`

Examples:

```js
var node1 = math.parse('sqrt(4)');

var four  = new math.expression.node.ConstantNode(4);
var node3 = new math.expression.node.FunctionNode(new SymbolNode('sqrt'), [four]);
```


### IndexNode

Construction:

```
new IndexNode(dimensions: Node[])
new IndexNode(dimensions: Node[], dotNotation: boolean)
```

Each dimension can be a single value, a range, or a property. The values of
indices are one-based, including range end.

An optional property `dotNotation` can be provided describing whether this index
was written using dot notation like `a.b`, or using bracket notation
like `a["b"]`. Default value is `false`. This information is used when
stringifying the IndexNode.

Properties:

- `dimensions: Node[]`
- `dotNotation: boolean`

Examples:

```js
var node1 = math.parse('A[1:3, 2]');

var A     = new math.expression.node.SymbolNode('A');
var one   = new math.expression.node.ConstantNode(1);
var two   = new math.expression.node.ConstantNode(2);
var three = new math.expression.node.ConstantNode(3);

var range = new math.expression.node.RangeNode(one, three);
var index = new math.expression.node.IndexNode([range, two]);
var node2 = new math.expression.node.AccessNode(A, index);
```

### ObjectNode

Construction:

```
new ObjectNode(properties: Object.<string, Node>)
```

Properties:

- `properties: Object.<string, Node>`

Examples:

```js
var node1 = math.parse('{a: 1, b: 2, c: 3}');

var a = new math.expression.node.ConstantNode(1);
var b = new math.expression.node.ConstantNode(2);
var c = new math.expression.node.ConstantNode(3);
var node2  = new math.expression.node.ObjectNode({a: a, b: b, c: c});
```


### OperatorNode

Construction:

```
new OperatorNode(op: string, fn: string, args: Node[])
```

Properties:

- `op: string`
- `fn: string`
- `args: Node[]`

Examples:

```js
var node1 = math.parse('2.3 + 5');

var a     = new math.expression.node.ConstantNode(2.3);
var b     = new math.expression.node.ConstantNode(5);
var node2 = new math.expression.node.OperatorNode('+', 'add', [a, b]);
```

### ParenthesisNode

Construction:

```
new ParenthesisNode(content: Node)
```

Properties:

- `content: Node`

Examples:

```js
var node1 = math.parse('(1)');

var a     = new math.expression.node.ConstantNode(1);
var node2 = new math.expression.node.ParenthesisNode(a);
```

### RangeNode

Construction:

```
new RangeNode(start: Node, end: Node [, step: Node])
```

Properties:

- `start: Node`
- `end: Node`
- `step: Node | null`

Examples:

```js
var node1 = math.parse('1:10');
var node2 = math.parse('0:2:10');

var zero = new math.expression.node.ConstantNode(0);
var one = new math.expression.node.ConstantNode(1);
var two = new math.expression.node.ConstantNode(2);
var ten = new math.expression.node.ConstantNode(10);

var node3 = new math.expression.node.RangeNode(one, ten);
var node4 = new math.expression.node.RangeNode(zero, ten, two);
```


### SymbolNode

Construction:

```
new SymbolNode(name: string)
```

Properties:

- `name: string`

Examples:

```js
var node = math.parse('x');

var x = new math.expression.node.SymbolNode('x');
```
