* simplifyCore() performs single pass simplification suitable for * applications requiring ultimate performance. To roughly summarize, * it handles cases along the lines of simplifyConstant() but where * knowledge of a single argument is sufficient to determine the value. * In contrast,
(nodeToSimplify, options = {})
| 102 | * @return {Node} Returns expression with basic simplifications applied |
| 103 | */ |
| 104 | function _simplifyCore (nodeToSimplify, options = {}) { |
| 105 | const context = options ? options.context : undefined |
| 106 | if (hasProperty(nodeToSimplify, 'trivial', context)) { |
| 107 | // This node does nothing if it has only one argument, so if so, |
| 108 | // return that argument simplified |
| 109 | if (isFunctionNode(nodeToSimplify) && nodeToSimplify.args.length === 1) { |
| 110 | return _simplifyCore(nodeToSimplify.args[0], options) |
| 111 | } |
| 112 | // For other node types, we try the generic methods |
| 113 | let simpChild = false |
| 114 | let childCount = 0 |
| 115 | nodeToSimplify.forEach(c => { |
| 116 | ++childCount |
| 117 | if (childCount === 1) { |
| 118 | simpChild = _simplifyCore(c, options) |
| 119 | } |
| 120 | }) |
| 121 | if (childCount === 1) { |
| 122 | return simpChild |
| 123 | } |
| 124 | } |
| 125 | let node = nodeToSimplify |
| 126 | if (isFunctionNode(node)) { |
| 127 | const op = getOperator(node.name) |
| 128 | if (op) { |
| 129 | // Replace FunctionNode with a new OperatorNode |
| 130 | if (node.args.length > 2 && hasProperty(node, 'associative', context)) { |
| 131 | // unflatten into binary operations since that's what simplifyCore handles |
| 132 | while (node.args.length > 2) { |
| 133 | const last = node.args.pop() |
| 134 | const seclast = node.args.pop() |
| 135 | node.args.push(new OperatorNode(op, node.name, [last, seclast])) |
| 136 | } |
| 137 | } |
| 138 | node = new OperatorNode(op, node.name, node.args) |
| 139 | } else { |
| 140 | return new FunctionNode( |
| 141 | _simplifyCore(node.fn), node.args.map(n => _simplifyCore(n, options))) |
| 142 | } |
| 143 | } |
| 144 | if (isOperatorNode(node) && node.isUnary()) { |
| 145 | const a0 = _simplifyCore(node.args[0], options) |
| 146 | |
| 147 | if (node.op === '~') { // bitwise not |
| 148 | if (isOperatorNode(a0) && a0.isUnary() && a0.op === '~') { |
| 149 | return a0.args[0] |
| 150 | } |
| 151 | } |
| 152 | if (node.op === 'not') { // logical not |
| 153 | if (isOperatorNode(a0) && a0.isUnary() && a0.op === 'not') { |
| 154 | // Has the effect of turning the argument into a boolean |
| 155 | // So can only eliminate the double negation if |
| 156 | // the inside is already boolean |
| 157 | if (isAlwaysBoolean(a0.args[0])) { |
| 158 | return a0.args[0] |
| 159 | } |
| 160 | } |
| 161 | } |
nothing calls this directly
no test coverage detected
searching dependent graphs…