/** * Optimize a given node * * @param xp.compiler.ast.Node in * @param xp.compiler.types.Scope scope * @param xp.compiler.optimize.Optimizations optimizations * @param xp.compiler.ast.Node optimized */ public function optimize(\xp\compiler\ast\Node $in, \xp\compiler\types\Scope $scope, Optimizations $optimizations) { $assign = cast($in, 'xp.compiler.ast.AssignmentNode'); $assign->expression = $optimizations->optimize($assign->expression, $scope); // Optimize "<var>= <var>+ <expr>" to "<var>+= <expr>" if ($assign->expression instanceof BinaryOpNode && isset(self::$optimizable[$assign->expression->op]) && $assign->variable->equals($assign->expression->lhs)) { $assign = new AssignmentNode(['variable' => $assign->variable, 'expression' => $assign->expression->rhs, 'op' => self::$optimizable[$assign->expression->op]]); } // Optimize "<var>-= -<expr>" to "<var>+= <expr>" // Optimize "<var>+= -<expr>" to "<var>-= <expr>" if ($assign->expression instanceof UnaryOpNode && '-' === $assign->expression->op && isset(self::$switch[$assign->op])) { $assign = new AssignmentNode(['variable' => $assign->variable, 'expression' => $assign->expression->expression, 'op' => self::$switch[$assign->op]]); } // Not optimizable return $assign; }
/** * Optimize a given node * * @param xp.compiler.ast.Node in * @param xp.compiler.types.Scope scope * @param xp.compiler.optimize.Optimizations optimizations * @param xp.compiler.ast.Node optimized */ public function optimize(\xp\compiler\ast\Node $in, \xp\compiler\types\Scope $scope, Optimizations $optimizations) { if (!isset(self::$optimizable[$in->op])) { return $in; } $in->lhs = $optimizations->optimize($this->unwrap($in->lhs), $scope); $in->rhs = $optimizations->optimize($this->unwrap($in->rhs), $scope); // Optimize "a + -b" to "a - b" and "a - -b" to "a + b" if ($in->rhs instanceof UnaryOpNode && '-' === $in->rhs->op && isset(self::$switch[$in->op])) { $in = new BinaryOpNode(['lhs' => $in->lhs, 'rhs' => $in->rhs->expression, 'op' => self::$switch[$in->op]]); } // Constant folding if ($in->lhs instanceof Resolveable && $in->rhs instanceof Resolveable) { $r = call_user_func_array([$this, 'eval' . self::$optimizable[$in->op]], [$in->lhs, $in->rhs]); if (null !== $r) { $in = $r; } } return $in; }