|
| 1 | +# CHANGELOG |
| 2 | + |
| 3 | +## 2.0.0 |
| 4 | + |
| 5 | +- Nodes can now have arbitrary numbers of children, not just binary trees. This was designed in such a way to have identical performance to the previous version. Essentially, the `Node{T,D}` type is a wrapper around a tuple of `D` children. |
| 6 | + - Note that `Node{T}` automatically converts to `Node{T,2}` in many contexts, for backwards compatibility. |
| 7 | +- Node type signature changed from `Node{T}` to `Node{T,D}`. Usually `D` is 2. |
| 8 | +- Direct property access `.l` and `.r` is automatically forwarded to `get_child(tree, 1)` and `get_child(tree, 2)`, |
| 9 | + but it is recommended to use the generic accessors instead. |
| 10 | +- Similarly, `.l = child` should be replaced with `set_child!(tree, child, 1)` and similar for `.r`. |
| 11 | +- All internal code migrated to use generic accessors. |
| 12 | + |
| 13 | +### Backwards Compatibility |
| 14 | + |
| 15 | +- Existing `.l` and `.r` access continues to work without warnings |
| 16 | + |
| 17 | +### Breaking Changes |
| 18 | + |
| 19 | +The only breaking change is if: |
| 20 | + |
| 21 | +1. You have any types that are subtyped to `<:AbstractExpressionNode{T}` or `<:AbstractNode{T}`. These should now be subtyped to `<:AbstractExpressionNode{T,2}` or `<:AbstractNode{T,2}`. You may also allow a `D` parameter in case you want to support higher-arity trees. |
| 22 | +2. You assume a tree has type, e.g., `=== Node{T}`, rather than `<: Node{T}`. So any methods dispatched to `::Type{Node{T}}` will also break. (To be safe you should always use a form `<: Node{T}` in case of future type changes - in any library.) |
| 23 | +3. You assume `tree.degree <= 2` in conditional logic, and your code interacts with a tree that is _not_ a binary tree. For example, the following pattern was common before this change: |
| 24 | + |
| 25 | + ```julia |
| 26 | + if tree.degree == 0 |
| 27 | + #= operations on leaf node =# |
| 28 | + elseif tree.degree == 1 |
| 29 | + #= operations on unary node =# |
| 30 | + else |
| 31 | + # BAD: ASSUMED TO BE BINARY |
| 32 | + #= operations on binary node, using `.l` and `.r` only =# |
| 33 | + end |
| 34 | + ``` |
| 35 | + |
| 36 | + This will obviously break if you pass a tree that is not binary, such as `tree::Node{T,3}`. |
| 37 | + - To fix this, you can use the `get_children` function to get the children of the tree as a tuple of `D` children, and then index up to `tree.degree`. |
| 38 | + - Inside DynamicExpressions, we commonly use `Base.Cartesian.@nif` to generate code for different degrees, to avoid any unstable types. |
0 commit comments