Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id A6BF8200BE3 for ; Thu, 8 Dec 2016 07:05:03 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id A5353160B0C; Thu, 8 Dec 2016 06:05:03 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 57A90160B2B for ; Thu, 8 Dec 2016 07:05:01 +0100 (CET) Received: (qmail 31736 invoked by uid 500); 8 Dec 2016 06:05:00 -0000 Mailing-List: contact commits-help@calcite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@calcite.apache.org Delivered-To: mailing list commits@calcite.apache.org Received: (qmail 31716 invoked by uid 99); 8 Dec 2016 06:05:00 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Dec 2016 06:05:00 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 59C40E7DE3; Thu, 8 Dec 2016 06:05:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jhyde@apache.org To: commits@calcite.apache.org Date: Thu, 08 Dec 2016 06:05:01 -0000 Message-Id: In-Reply-To: <12bb8e98bf324b8fafd2f78e6eb0af5d@git.apache.org> References: <12bb8e98bf324b8fafd2f78e6eb0af5d@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/3] calcite git commit: [CALCITE-1530] Create a visitor to traverse linq4j expressions without mutating them, and rename Visitor to Shuttle archived-at: Thu, 08 Dec 2016 06:05:03 -0000 [CALCITE-1530] Create a visitor to traverse linq4j expressions without mutating them, and rename Visitor to Shuttle Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/267e2f3e Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/267e2f3e Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/267e2f3e Branch: refs/heads/master Commit: 267e2f3e1db71e678f80bb69015164c0d45bcfe4 Parents: 02752fe Author: Julian Hyde Authored: Mon Dec 5 19:53:41 2016 -0800 Committer: Julian Hyde Committed: Wed Dec 7 11:17:40 2016 -0800 ---------------------------------------------------------------------- .../enumerable/EnumerableRelImplementor.java | 19 +- .../calcite/adapter/enumerable/RexImpTable.java | 4 +- .../calcite/linq4j/tree/AbstractNode.java | 2 +- .../calcite/linq4j/tree/BinaryExpression.java | 6 +- .../calcite/linq4j/tree/BlockBuilder.java | 67 +-- .../calcite/linq4j/tree/BlockStatement.java | 12 +- .../calcite/linq4j/tree/ClassDeclaration.java | 12 +- .../linq4j/tree/ClassDeclarationFinder.java | 8 +- .../linq4j/tree/ConditionalExpression.java | 6 +- .../linq4j/tree/ConditionalStatement.java | 12 +- .../calcite/linq4j/tree/ConstantExpression.java | 6 +- .../linq4j/tree/ConstructorDeclaration.java | 12 +- .../linq4j/tree/DeclarationStatement.java | 12 +- .../calcite/linq4j/tree/DefaultExpression.java | 7 +- .../calcite/linq4j/tree/DynamicExpression.java | 7 +- .../apache/calcite/linq4j/tree/Expression.java | 2 +- .../apache/calcite/linq4j/tree/Expressions.java | 44 +- .../calcite/linq4j/tree/FieldDeclaration.java | 12 +- .../calcite/linq4j/tree/ForStatement.java | 18 +- .../calcite/linq4j/tree/FunctionExpression.java | 12 +- .../calcite/linq4j/tree/GotoStatement.java | 12 +- .../calcite/linq4j/tree/IndexExpression.java | 13 +- .../linq4j/tree/InvocationExpression.java | 7 +- .../calcite/linq4j/tree/LabelStatement.java | 6 +- .../calcite/linq4j/tree/LambdaExpression.java | 7 +- .../calcite/linq4j/tree/ListInitExpression.java | 7 +- .../calcite/linq4j/tree/MemberDeclaration.java | 2 +- .../calcite/linq4j/tree/MemberExpression.java | 12 +- .../linq4j/tree/MemberInitExpression.java | 7 +- .../linq4j/tree/MethodCallExpression.java | 14 +- .../calcite/linq4j/tree/MethodDeclaration.java | 12 +- .../calcite/linq4j/tree/NewArrayExpression.java | 14 +- .../calcite/linq4j/tree/NewExpression.java | 14 +- .../org/apache/calcite/linq4j/tree/Node.java | 4 +- .../calcite/linq4j/tree/OptimizeShuttle.java | 422 ++++++++++++++++++ .../calcite/linq4j/tree/OptimizeVisitor.java | 423 ------------------- .../linq4j/tree/ParameterExpression.java | 6 +- .../org/apache/calcite/linq4j/tree/Shuttle.java | 335 +++++++++++++++ .../apache/calcite/linq4j/tree/Statement.java | 2 +- .../calcite/linq4j/tree/SwitchStatement.java | 7 +- .../calcite/linq4j/tree/TernaryExpression.java | 16 +- .../calcite/linq4j/tree/ThrowStatement.java | 12 +- .../calcite/linq4j/tree/TryStatement.java | 6 +- .../linq4j/tree/TypeBinaryExpression.java | 12 +- .../calcite/linq4j/tree/UnaryExpression.java | 12 +- .../org/apache/calcite/linq4j/tree/Visitor.java | 351 ++------------- .../apache/calcite/linq4j/tree/VisitorImpl.java | 206 +++++++++ .../calcite/linq4j/tree/WhileStatement.java | 14 +- .../calcite/linq4j/test/BlockBuilderTest.java | 8 +- .../calcite/linq4j/test/ExpressionTest.java | 12 +- site/_docs/adapter.md | 5 +- 51 files changed, 1336 insertions(+), 924 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java index bc88333..90105e0 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java @@ -36,7 +36,7 @@ import org.apache.calcite.linq4j.tree.ParameterExpression; import org.apache.calcite.linq4j.tree.Primitive; import org.apache.calcite.linq4j.tree.Statement; import org.apache.calcite.linq4j.tree.Types; -import org.apache.calcite.linq4j.tree.Visitor; +import org.apache.calcite.linq4j.tree.VisitorImpl; import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.runtime.Bindable; import org.apache.calcite.util.BuiltInMethod; @@ -458,26 +458,19 @@ public class EnumerableRelImplementor extends JavaRelImplementor { } /** Visitor that finds types in an {@link Expression} tree. */ - private static class TypeFinder extends Visitor { + private static class TypeFinder extends VisitorImpl { private final Collection types; TypeFinder(Collection types) { this.types = types; } - @Override public Expression visit( - NewExpression newExpression, - List arguments, - List memberDeclarations) { + @Override public Void visit(NewExpression newExpression) { types.add(newExpression.type); - return super.visit( - newExpression, - arguments, - memberDeclarations); + return super.visit(newExpression); } - @Override public Expression visit(NewArrayExpression newArrayExpression, - int dimension, Expression bound, List expressions) { + @Override public Void visit(NewArrayExpression newArrayExpression) { Type type = newArrayExpression.type; for (;;) { final Type componentType = Types.getComponentType(type); @@ -487,7 +480,7 @@ public class EnumerableRelImplementor extends JavaRelImplementor { type = componentType; } types.add(type); - return super.visit(newArrayExpression, dimension, bound, expressions); + return super.visit(newArrayExpression); } } http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java index 5984fca..ddcb8dc 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java @@ -27,7 +27,7 @@ import org.apache.calcite.linq4j.tree.Expression; import org.apache.calcite.linq4j.tree.ExpressionType; import org.apache.calcite.linq4j.tree.Expressions; import org.apache.calcite.linq4j.tree.MemberExpression; -import org.apache.calcite.linq4j.tree.OptimizeVisitor; +import org.apache.calcite.linq4j.tree.OptimizeShuttle; import org.apache.calcite.linq4j.tree.ParameterExpression; import org.apache.calcite.linq4j.tree.Primitive; import org.apache.calcite.linq4j.tree.Types; @@ -640,7 +640,7 @@ public class RexImpTable { } static Expression optimize(Expression expression) { - return expression.accept(new OptimizeVisitor()); + return expression.accept(new OptimizeShuttle()); } static Expression optimize2(Expression operand, Expression expression) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/AbstractNode.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/AbstractNode.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/AbstractNode.java index c74adc6..38aec48 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/AbstractNode.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/AbstractNode.java @@ -65,7 +65,7 @@ public abstract class AbstractNode implements Node { "un-parse not supported: " + getClass() + ":" + nodeType); } - public Node accept(Visitor visitor) { + public Node accept(Shuttle shuttle) { throw new RuntimeException( "visit not supported: " + getClass() + ":" + nodeType); } http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BinaryExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BinaryExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BinaryExpression.java index eb73da3..f8056c7 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BinaryExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BinaryExpression.java @@ -37,13 +37,17 @@ public class BinaryExpression extends Expression { this.primitive = Primitive.of(expression0.getType()); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle visitor) { visitor = visitor.preVisit(this); Expression expression0 = this.expression0.accept(visitor); Expression expression1 = this.expression1.accept(visitor); return visitor.visit(this, expression0, expression1); } + public R accept(Visitor visitor) { + return visitor.visit(this); + } + public Object evaluate(Evaluator evaluator) { switch (nodeType) { case AndAlso: http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java index c58a258..ff13d66 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java @@ -32,18 +32,18 @@ import java.util.Set; *

Has methods that help ensure that variable names are unique.

*/ public class BlockBuilder { - final List statements = new ArrayList(); - final Set variables = new HashSet(); + final List statements = new ArrayList<>(); + final Set variables = new HashSet<>(); /** Contains final-fine-to-reuse-declarations. * An entry to this map is added when adding final declaration of a * statement with optimize=true parameter. */ final Map expressionForReuse = - new HashMap(); + new HashMap<>(); private final boolean optimizing; private final BlockBuilder parent; - private static final Visitor OPTIMIZE_VISITOR = new OptimizeVisitor(); + private static final Shuttle OPTIMIZE_SHUTTLE = new OptimizeShuttle(); /** * Creates a non-optimizing BlockBuilder. @@ -111,13 +111,13 @@ public class BlockBuilder { } Expression result = null; final Map replacements = - new IdentityHashMap(); - final Visitor visitor = new SubstituteVariableVisitor(replacements); + new IdentityHashMap<>(); + final Shuttle shuttle = new SubstituteVariableVisitor(replacements); for (int i = 0; i < block.statements.size(); i++) { Statement statement = block.statements.get(i); if (!replacements.isEmpty()) { // Save effort, and only substitute variables if there are some. - statement = statement.accept(visitor); + statement = statement.accept(shuttle); } if (statement instanceof DeclarationStatement) { DeclarationStatement declaration = (DeclarationStatement) statement; @@ -303,11 +303,11 @@ public class BlockBuilder { // loop. Optimize should not loop forever, however it is hard to prove if // it always finishes in reasonable time. for (int i = 0; i < 10; i++) { - if (!optimize(createOptimizeVisitor(), true)) { + if (!optimize(createOptimizeShuttle(), true)) { break; } } - optimize(createFinishingOptimizeVisitor(), false); + optimize(createFinishingOptimizeShuttle(), false); } return Expressions.block(statements); } @@ -318,7 +318,7 @@ public class BlockBuilder { * * @return whether any optimizations were made */ - private boolean optimize(Visitor optimizer, boolean performInline) { + private boolean optimize(Shuttle optimizer, boolean performInline) { int optimizeCount = 0; final UseCounter useCounter = new UseCounter(); for (Statement statement : statements) { @@ -334,12 +334,10 @@ public class BlockBuilder { } } final Map subMap = - new IdentityHashMap( - useCounter.map.size()); + new IdentityHashMap<>(useCounter.map.size()); final SubstituteVariableVisitor visitor = new SubstituteVariableVisitor( subMap); - final ArrayList oldStatements = new ArrayList( - statements); + final ArrayList oldStatements = new ArrayList<>(statements); statements.clear(); for (Statement oldStatement : oldStatements) { @@ -400,10 +398,10 @@ public class BlockBuilder { DeclarationStatement newDecl = (DeclarationStatement) oldStatement; subMap.put(newDecl.parameter, normalizeDeclaration(newDecl)); - oldStatement = OptimizeVisitor.EMPTY_STATEMENT; + oldStatement = OptimizeShuttle.EMPTY_STATEMENT; } } - if (oldStatement != OptimizeVisitor.EMPTY_STATEMENT) { + if (oldStatement != OptimizeShuttle.EMPTY_STATEMENT) { if (oldStatement instanceof DeclarationStatement) { addExpressionForReuse((DeclarationStatement) oldStatement); } @@ -420,7 +418,7 @@ public class BlockBuilder { if (beforeOptimize != oldStatement) { ++optimizeCount; } - if (oldStatement != OptimizeVisitor.EMPTY_STATEMENT) { + if (oldStatement != OptimizeShuttle.EMPTY_STATEMENT) { statements.add(oldStatement); } } @@ -429,23 +427,23 @@ public class BlockBuilder { } /** - * Creates a visitor that will be used during block optimization. - * Subclasses might provide more specific optimizations (e.g. partial + * Creates a shuttle that will be used during block optimization. + * Sub-classes might provide more specific optimizations (e.g. partial * evaluation). * - * @return visitor used to optimize the statements when converting to block + * @return shuttle used to optimize the statements when converting to block */ - protected Visitor createOptimizeVisitor() { - return OPTIMIZE_VISITOR; + protected Shuttle createOptimizeShuttle() { + return OPTIMIZE_SHUTTLE; } /** - * Creates a final optimization visitor. + * Creates a final optimization shuttle. * Typically, the visitor will factor out constant expressions. * - * @return visitor that is used to finalize the optimization + * @return shuttle that is used to finalize the optimization */ - protected Visitor createFinishingOptimizeVisitor() { + protected Shuttle createFinishingOptimizeShuttle() { return ClassDeclarationFinder.create(); } @@ -484,10 +482,10 @@ public class BlockBuilder { } /** Substitute Variable Visitor. */ - private static class SubstituteVariableVisitor extends Visitor { + private static class SubstituteVariableVisitor extends Shuttle { private final Map map; private final Map actives = - new IdentityHashMap(); + new IdentityHashMap<>(); public SubstituteVariableVisitor(Map map) { this.map = map; @@ -544,11 +542,10 @@ public class BlockBuilder { } /** Use counter. */ - private static class UseCounter extends Visitor { - private final Map map = - new IdentityHashMap(); + private static class UseCounter extends VisitorImpl { + private final Map map = new IdentityHashMap<>(); - @Override public Expression visit(ParameterExpression parameter) { + @Override public Void visit(ParameterExpression parameter) { final Slot slot = map.get(parameter); if (slot != null) { // Count use of parameter, if it's registered. It's OK if @@ -558,6 +555,14 @@ public class BlockBuilder { } return super.visit(parameter); } + + @Override public Void visit(DeclarationStatement declarationStatement) { + // Unlike base class, do not visit declarationStatement.parameter. + if (declarationStatement.initializer != null) { + declarationStatement.initializer.accept(this); + } + return null; + } } /** http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockStatement.java index 26a8c09..54e62e4 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockStatement.java @@ -54,11 +54,15 @@ public class BlockStatement extends Statement { return true; } - @Override public BlockStatement accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public BlockStatement accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); List newStatements = Expressions.acceptStatements(statements, - visitor); - return visitor.visit(this, newStatements); + shuttle); + return shuttle.visit(this, newStatements); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept0(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclaration.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclaration.java index 172112f..424ce54 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclaration.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclaration.java @@ -59,11 +59,15 @@ public class ClassDeclaration extends MemberDeclaration { writer.newlineAndIndent(); } - public ClassDeclaration accept(Visitor visitor) { - visitor = visitor.preVisit(this); + public ClassDeclaration accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); final List members1 = - Expressions.acceptMemberDeclarations(memberDeclarations, visitor); - return visitor.visit(this, members1); + Expressions.acceptMemberDeclarations(memberDeclarations, shuttle); + return shuttle.visit(this, members1); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override public boolean equals(Object o) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclarationFinder.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclarationFinder.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclarationFinder.java index 2388538..3af0fe6 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclarationFinder.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ClassDeclarationFinder.java @@ -29,7 +29,7 @@ import java.util.List; * Instances of this class should not be reused, so new visitor should be * created for optimizing a new expression tree. */ -public class ClassDeclarationFinder extends Visitor { +public class ClassDeclarationFinder extends Shuttle { protected final ClassDeclarationFinder parent; /** @@ -144,7 +144,7 @@ public class ClassDeclarationFinder extends Visitor { * @param newExpression expression to optimize * @return nested visitor if anonymous class is given */ - @Override public Visitor preVisit(NewExpression newExpression) { + @Override public Shuttle preVisit(NewExpression newExpression) { if (newExpression.memberDeclarations == null) { return this; } @@ -159,7 +159,7 @@ public class ClassDeclarationFinder extends Visitor { * @param classDeclaration expression to optimize * @return nested visitor */ - @Override public Visitor preVisit(ClassDeclaration classDeclaration) { + @Override public Shuttle preVisit(ClassDeclaration classDeclaration) { ClassDeclarationFinder visitor = goDeeper(); visitor.learnFinalStaticDeclarations(classDeclaration.memberDeclarations); return visitor; @@ -228,7 +228,7 @@ public class ClassDeclarationFinder extends Visitor { return memberDeclarations; } List newDecls = - new ArrayList(memberDeclarations.size() + new ArrayList<>(memberDeclarations.size() + addedDeclarations.size()); newDecls.addAll(memberDeclarations); newDecls.addAll(addedDeclarations); http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalExpression.java index 6491aa0..1b49a81 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalExpression.java @@ -33,7 +33,7 @@ import java.util.Objects; *

*/ public class ConditionalExpression extends AbstractNode { - private final List expressionList; + final List expressionList; public ConditionalExpression(List expressionList, Type type) { super(ExpressionType.Conditional, type); @@ -41,6 +41,10 @@ public class ConditionalExpression extends AbstractNode { this.expressionList = expressionList; } + public R accept(Visitor visitor) { + return visitor.visit(this); + } + @Override void accept(ExpressionWriter writer, int lprec, int rprec) { for (int i = 0; i < expressionList.size(); i += 2) { writer.append(i > 0 ? " else if (" : "if (") http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalStatement.java index 2334557..64e54d4 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConditionalStatement.java @@ -40,10 +40,14 @@ public class ConditionalStatement extends Statement { this.expressionList = expressionList; } - @Override public Statement accept(Visitor visitor) { - visitor = visitor.preVisit(this); - List list = Expressions.acceptNodes(expressionList, visitor); - return visitor.visit(this, list); + @Override public Statement accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); + List list = Expressions.acceptNodes(expressionList, shuttle); + return shuttle.visit(this, list); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept0(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java index 52c6975..3fc112b 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java @@ -58,7 +58,11 @@ public class ConstantExpression extends Expression { return value; } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java index 471357d..1aa28b4 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstructorDeclaration.java @@ -48,11 +48,15 @@ public class ConstructorDeclaration extends MemberDeclaration { this.body = body; } - @Override public MemberDeclaration accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public MemberDeclaration accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); // do not visit parameters - final BlockStatement body = this.body.accept(visitor); - return visitor.visit(this, body); + final BlockStatement body = this.body.accept(shuttle); + return shuttle.visit(this, body); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } public void accept(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DeclarationStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DeclarationStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DeclarationStatement.java index f835d1e..c080c84 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DeclarationStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DeclarationStatement.java @@ -36,13 +36,17 @@ public class DeclarationStatement extends Statement { this.initializer = initializer; } - @Override public DeclarationStatement accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public DeclarationStatement accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); // do not visit parameter - visit may not return a ParameterExpression Expression initializer = this.initializer != null - ? this.initializer.accept(visitor) + ? this.initializer.accept(shuttle) : null; - return visitor.visit(this, initializer); + return shuttle.visit(this, initializer); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept0(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DefaultExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DefaultExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DefaultExpression.java index 8569528..c78847d 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DefaultExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DefaultExpression.java @@ -24,9 +24,14 @@ public class DefaultExpression extends Expression { super(ExpressionType.Default, type); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End DefaultExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DynamicExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DynamicExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DynamicExpression.java index ff03001..f9c7c4f 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DynamicExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/DynamicExpression.java @@ -24,9 +24,14 @@ public class DynamicExpression extends Expression { super(ExpressionType.Dynamic, type); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End DynamicExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expression.java index 4c3427b..ff5f38f 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expression.java @@ -41,7 +41,7 @@ public abstract class Expression extends AbstractNode { } @Override // More specific return type. - public abstract Expression accept(Visitor visitor); + public abstract Expression accept(Shuttle shuttle); /** * Indicates that the node can be reduced to a simpler node. If this http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java index fae932e..0651024 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java @@ -3090,28 +3090,28 @@ public abstract class Expressions { return toCollection(iterable).toArray(a); } - static Expression accept(T node, Visitor visitor) { + static Expression accept(T node, Shuttle shuttle) { if (node == null) { return null; } - return node.accept(visitor); + return node.accept(shuttle); } - static Statement accept(T node, Visitor visitor) { + static Statement accept(T node, Shuttle shuttle) { if (node == null) { return null; } - return node.accept(visitor); + return node.accept(shuttle); } static List acceptStatements(List statements, - Visitor visitor) { + Shuttle shuttle) { if (statements.isEmpty()) { return statements; // short cut } final List statements1 = new ArrayList(); for (Statement statement : statements) { - Statement newStatement = statement.accept(visitor); + Statement newStatement = statement.accept(shuttle); if (newStatement instanceof GotoStatement) { GotoStatement goto_ = (GotoStatement) newStatement; if (goto_.kind == GotoExpressionKind.Sequence @@ -3125,67 +3125,77 @@ public abstract class Expressions { return statements1; } - static List acceptNodes(List nodes, Visitor visitor) { + static List acceptNodes(List nodes, Shuttle shuttle) { if (nodes.isEmpty()) { return nodes; // short cut } final List statements1 = new ArrayList(); for (Node node : nodes) { - statements1.add(node.accept(visitor)); + statements1.add(node.accept(shuttle)); } return statements1; } static List acceptParameterExpressions( - List parameterExpressions, Visitor visitor) { + List parameterExpressions, Shuttle shuttle) { if (parameterExpressions.isEmpty()) { return Collections.emptyList(); // short cut } final List parameterExpressions1 = new ArrayList(); for (ParameterExpression parameterExpression : parameterExpressions) { - parameterExpressions1.add(parameterExpression.accept(visitor)); + parameterExpressions1.add(parameterExpression.accept(shuttle)); } return parameterExpressions1; } static List acceptDeclarations( - List declarations, Visitor visitor) { + List declarations, Shuttle shuttle) { if (declarations == null || declarations.isEmpty()) { return declarations; // short cut } final List declarations1 = new ArrayList(); for (DeclarationStatement declaration : declarations) { - declarations1.add(declaration.accept(visitor)); + declarations1.add(declaration.accept(shuttle)); } return declarations1; } static List acceptMemberDeclarations( - List memberDeclarations, Visitor visitor) { + List memberDeclarations, Shuttle shuttle) { if (memberDeclarations == null || memberDeclarations.isEmpty()) { return memberDeclarations; // short cut } final List memberDeclarations1 = new ArrayList(); for (MemberDeclaration memberDeclaration : memberDeclarations) { - memberDeclarations1.add(memberDeclaration.accept(visitor)); + memberDeclarations1.add(memberDeclaration.accept(shuttle)); } return memberDeclarations1; } static List acceptExpressions(List expressions, - Visitor visitor) { + Shuttle shuttle) { if (expressions.isEmpty()) { return expressions; // short cut } - final List expressions1 = new ArrayList(); + final List expressions1 = new ArrayList<>(); for (Expression expression : expressions) { - expressions1.add(expression.accept(visitor)); + expressions1.add(expression.accept(shuttle)); } return expressions1; } + static R acceptNodes(List nodes, Visitor visitor) { + R r = null; + if (nodes != null) { + for (Node node : nodes) { + r = node.accept(visitor); + } + } + return r; + } + // ~ Classes and interfaces ------------------------------------------------ // Some interfaces we'd rather not implement yet. They don't seem relevant http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FieldDeclaration.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FieldDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FieldDeclaration.java index 2a8db07..29ea7a7 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FieldDeclaration.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FieldDeclaration.java @@ -35,12 +35,16 @@ public class FieldDeclaration extends MemberDeclaration { this.initializer = initializer; } - @Override public MemberDeclaration accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public MemberDeclaration accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); // do not visit parameter - visit may not return a ParameterExpression final Expression initializer = - this.initializer == null ? null : this.initializer.accept(visitor); - return visitor.visit(this, initializer); + this.initializer == null ? null : this.initializer.accept(shuttle); + return shuttle.visit(this, initializer); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } public void accept(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ForStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ForStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ForStatement.java index e8a9fba..d39809b 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ForStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ForStatement.java @@ -45,15 +45,19 @@ public class ForStatement extends Statement { this.body = body; // may be empty block, not null } - @Override public ForStatement accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public ForStatement accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); List decls1 = - Expressions.acceptDeclarations(declarations, visitor); + Expressions.acceptDeclarations(declarations, shuttle); final Expression condition1 = - condition == null ? null : condition.accept(visitor); - final Expression post1 = post == null ? null : post.accept(visitor); - final Statement body1 = body.accept(visitor); - return visitor.visit(this, decls1, condition1, post1, body1); + condition == null ? null : condition.accept(shuttle); + final Expression post1 = post == null ? null : post.accept(shuttle); + final Statement body1 = body.accept(shuttle); + return shuttle.visit(this, decls1, condition1, post1, body1); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept0(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FunctionExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FunctionExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FunctionExpression.java index 4bbc99b..14c67ca 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FunctionExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/FunctionExpression.java @@ -68,10 +68,14 @@ public final class FunctionExpression> this(type, null, body, parameters); } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); - BlockStatement body = this.body.accept(visitor); - return visitor.visit(this, body); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); + BlockStatement body = this.body.accept(shuttle); + return shuttle.visit(this, body); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } public Invokable compile() { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/GotoStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/GotoStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/GotoStatement.java index 239f0e5..ff5582a 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/GotoStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/GotoStatement.java @@ -54,11 +54,15 @@ public class GotoStatement extends Statement { } } - @Override public Statement accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public Statement accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); Expression expression1 = - expression == null ? null : expression.accept(visitor); - return visitor.visit(this, expression1); + expression == null ? null : expression.accept(shuttle); + return shuttle.visit(this, expression1); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept0(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/IndexExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/IndexExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/IndexExpression.java index 9c7eb61..10e8463 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/IndexExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/IndexExpression.java @@ -35,14 +35,17 @@ public class IndexExpression extends Expression { this.indexExpressions = indexExpressions; } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); - Expression array = this.array.accept(visitor); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); + Expression array = this.array.accept(shuttle); List indexExpressions = Expressions.acceptExpressions( - this.indexExpressions, visitor); - return visitor.visit(this, array, indexExpressions); + this.indexExpressions, shuttle); + return shuttle.visit(this, array, indexExpressions); } + public R accept(Visitor visitor) { + return visitor.visit(this); + } @Override void accept(ExpressionWriter writer, int lprec, int rprec) { array.accept(writer, lprec, nodeType.lprec); http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/InvocationExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/InvocationExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/InvocationExpression.java index 666ab07..140c20d 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/InvocationExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/InvocationExpression.java @@ -25,9 +25,14 @@ public class InvocationExpression extends Expression { super(nodeType, type); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End InvocationExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LabelStatement.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LabelStatement.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LabelStatement.java index 15b6f44..4d23339 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LabelStatement.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LabelStatement.java @@ -33,7 +33,11 @@ public class LabelStatement extends Statement { this.defaultValue = defaultValue; } - @Override public LabelStatement accept(Visitor visitor) { + @Override public LabelStatement accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LambdaExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LambdaExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LambdaExpression.java index d406e8f..6fbf61c 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LambdaExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/LambdaExpression.java @@ -25,9 +25,14 @@ public class LambdaExpression extends Expression { super(nodeType, type); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End LambdaExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ListInitExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ListInitExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ListInitExpression.java index bf22c11..daf289a 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ListInitExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ListInitExpression.java @@ -24,9 +24,14 @@ public class ListInitExpression extends Expression { super(nodeType, type); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End ListInitExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberDeclaration.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberDeclaration.java index c3c10b4..b553f7a 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberDeclaration.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberDeclaration.java @@ -20,7 +20,7 @@ package org.apache.calcite.linq4j.tree; * Declaration of a member of a class. */ public abstract class MemberDeclaration implements Node { - public abstract MemberDeclaration accept(Visitor visitor); + public abstract MemberDeclaration accept(Shuttle shuttle); } // End MemberDeclaration.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberExpression.java index 9947c10..5e0c72d 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberExpression.java @@ -40,12 +40,16 @@ public class MemberExpression extends Expression { this.field = field; } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); Expression expression1 = expression == null ? null - : expression.accept(visitor); - return visitor.visit(this, expression1); + : expression.accept(shuttle); + return shuttle.visit(this, expression1); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } public Object evaluate(Evaluator evaluator) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberInitExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberInitExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberInitExpression.java index 79b4c46..5becd3c 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberInitExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MemberInitExpression.java @@ -25,9 +25,14 @@ public class MemberInitExpression extends Expression { super(ExpressionType.MemberInit, Void.TYPE); } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); } + } // End MemberInitExpression.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodCallExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodCallExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodCallExpression.java index 7b63a00..bd3cd91 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodCallExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodCallExpression.java @@ -53,13 +53,17 @@ public class MethodCallExpression extends Expression { this(method.getGenericReturnType(), method, targetExpression, expressions); } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); Expression targetExpression = Expressions.accept(this.targetExpression, - visitor); + shuttle); List expressions = Expressions.acceptExpressions( - this.expressions, visitor); - return visitor.visit(this, targetExpression, expressions); + this.expressions, shuttle); + return shuttle.visit(this, targetExpression, expressions); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override public Object evaluate(Evaluator evaluator) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java index b279434..800f387 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/MethodDeclaration.java @@ -47,11 +47,15 @@ public class MethodDeclaration extends MemberDeclaration { this.body = body; } - @Override public MemberDeclaration accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public MemberDeclaration accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); // do not visit parameters - final BlockStatement body = this.body.accept(visitor); - return visitor.visit(this, body); + final BlockStatement body = this.body.accept(shuttle); + return shuttle.visit(this, body); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } public void accept(ExpressionWriter writer) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewArrayExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewArrayExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewArrayExpression.java index 13670ae..36e64c0 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewArrayExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewArrayExpression.java @@ -41,14 +41,18 @@ public class NewArrayExpression extends Expression { this.expressions = expressions; } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); List expressions = this.expressions == null ? null - : Expressions.acceptExpressions(this.expressions, visitor); - Expression bound = Expressions.accept(this.bound, visitor); - return visitor.visit(this, dimension, bound, expressions); + : Expressions.acceptExpressions(this.expressions, shuttle); + Expression bound = Expressions.accept(this.bound, shuttle); + return shuttle.visit(this, dimension, bound, expressions); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept(ExpressionWriter writer, int lprec, int rprec) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewExpression.java index e4ca7ea..0c168a3 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/NewExpression.java @@ -43,13 +43,17 @@ public class NewExpression extends Expression { this.memberDeclarations = memberDeclarations; } - @Override public Expression accept(Visitor visitor) { - visitor = visitor.preVisit(this); + @Override public Expression accept(Shuttle shuttle) { + shuttle = shuttle.preVisit(this); final List arguments = Expressions.acceptExpressions( - this.arguments, visitor); + this.arguments, shuttle); final List memberDeclarations = - Expressions.acceptMemberDeclarations(this.memberDeclarations, visitor); - return visitor.visit(this, arguments, memberDeclarations); + Expressions.acceptMemberDeclarations(this.memberDeclarations, shuttle); + return shuttle.visit(this, arguments, memberDeclarations); + } + + public R accept(Visitor visitor) { + return visitor.visit(this); } @Override void accept(ExpressionWriter writer, int lprec, int rprec) { http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Node.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Node.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Node.java index 7c04f08..560f66a 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Node.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Node.java @@ -20,7 +20,9 @@ package org.apache.calcite.linq4j.tree; *

Parse tree node.

*/ public interface Node { - Node accept(Visitor visitor); + R accept(Visitor visitor); + + Node accept(Shuttle shuttle); void accept(ExpressionWriter expressionWriter); } http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeShuttle.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeShuttle.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeShuttle.java new file mode 100644 index 0000000..fa90a4c --- /dev/null +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeShuttle.java @@ -0,0 +1,422 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.calcite.linq4j.tree; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.calcite.linq4j.tree.ExpressionType.Equal; +import static org.apache.calcite.linq4j.tree.ExpressionType.NotEqual; + +/** + * Shuttle that optimizes expressions. + * + *

The optimizations are essential, not mere tweaks. Without + * optimization, expressions such as {@code false == null} will be left in, + * which are invalid to Janino (because it does not automatically box + * primitives). + */ +public class OptimizeShuttle extends Shuttle { + public static final ConstantExpression FALSE_EXPR = + Expressions.constant(false); + public static final ConstantExpression TRUE_EXPR = + Expressions.constant(true); + public static final MemberExpression BOXED_FALSE_EXPR = + Expressions.field(null, Boolean.class, "FALSE"); + public static final MemberExpression BOXED_TRUE_EXPR = + Expressions.field(null, Boolean.class, "TRUE"); + public static final Statement EMPTY_STATEMENT = Expressions.statement(null); + + private static final Set KNOWN_NON_NULL_METHODS = new HashSet<>(); + + static { + for (Class aClass : new Class[]{Boolean.class, Byte.class, Short.class, + Integer.class, Long.class, String.class}) { + for (Method method : aClass.getMethods()) { + if ("valueOf".equals(method.getName()) + && Modifier.isStatic(method.getModifiers())) { + KNOWN_NON_NULL_METHODS.add(method); + } + } + } + } + + private static final + Map NOT_BINARY_COMPLEMENT = + new EnumMap<>(ExpressionType.class); + + static { + addComplement(ExpressionType.Equal, ExpressionType.NotEqual); + addComplement(ExpressionType.GreaterThanOrEqual, ExpressionType.LessThan); + addComplement(ExpressionType.GreaterThan, ExpressionType.LessThanOrEqual); + } + + private static void addComplement(ExpressionType eq, ExpressionType ne) { + NOT_BINARY_COMPLEMENT.put(eq, ne); + NOT_BINARY_COMPLEMENT.put(ne, eq); + } + + private static final Method BOOLEAN_VALUEOF_BOOL = + Types.lookupMethod(Boolean.class, "valueOf", boolean.class); + + @Override public Expression visit( + TernaryExpression ternary, + Expression expression0, + Expression expression1, + Expression expression2) { + switch (ternary.getNodeType()) { + case Conditional: + Boolean always = always(expression0); + if (always != null) { + // true ? y : z === y + // false ? y : z === z + return always + ? expression1 + : expression2; + } + if (expression1.equals(expression2)) { + // a ? b : b === b + return expression1; + } + // !a ? b : c == a ? c : b + if (expression0 instanceof UnaryExpression) { + UnaryExpression una = (UnaryExpression) expression0; + if (una.getNodeType() == ExpressionType.Not) { + return Expressions.makeTernary(ternary.getNodeType(), + una.expression, expression2, expression1); + } + } + + // a ? true : b === a || b + // a ? false : b === !a && b + always = always(expression1); + if (always != null && isKnownNotNull(expression2)) { + return (always + ? Expressions.orElse(expression0, expression2) + : Expressions.andAlso(Expressions.not(expression0), + expression2)).accept(this); + } + + // a ? b : true === !a || b + // a ? b : false === a && b + always = always(expression2); + if (always != null && isKnownNotNull(expression1)) { + return (always + ? Expressions.orElse(Expressions.not(expression0), + expression1) + : Expressions.andAlso(expression0, expression1)).accept(this); + } + + if (expression0 instanceof BinaryExpression + && (expression0.getNodeType() == ExpressionType.Equal + || expression0.getNodeType() == ExpressionType.NotEqual)) { + BinaryExpression cmp = (BinaryExpression) expression0; + Expression expr = null; + if (eq(cmp.expression0, expression2) + && eq(cmp.expression1, expression1)) { + // a == b ? b : a === a (hint: if a==b, then a == b ? a : a) + // a != b ? b : a === b (hint: if a==b, then a != b ? b : b) + expr = expression0.getNodeType() == ExpressionType.Equal + ? expression2 : expression1; + } + if (eq(cmp.expression0, expression1) + && eq(cmp.expression1, expression2)) { + // a == b ? a : b === b (hint: if a==b, then a == b ? b : b) + // a != b ? a : b === a (hint: if a==b, then a == b ? a : a) + expr = expression0.getNodeType() == ExpressionType.Equal + ? expression2 : expression1; + } + if (expr != null) { + return expr; + } + } + } + return super.visit(ternary, expression0, expression1, expression2); + } + + @Override public Expression visit( + BinaryExpression binary, + Expression expression0, + Expression expression1) { + // + Expression result; + switch (binary.getNodeType()) { + case AndAlso: + case OrElse: + if (eq(expression0, expression1)) { + return expression0; + } + } + switch (binary.getNodeType()) { + case Equal: + case NotEqual: + if (eq(expression0, expression1)) { + return binary.getNodeType() == Equal ? TRUE_EXPR : FALSE_EXPR; + } else if (expression0 instanceof ConstantExpression && expression1 + instanceof ConstantExpression) { + ConstantExpression c0 = (ConstantExpression) expression0; + ConstantExpression c1 = (ConstantExpression) expression1; + if (c0.getType() == c1.getType() + || !(Primitive.is(c0.getType()) || Primitive.is(c1.getType()))) { + return binary.getNodeType() == NotEqual ? TRUE_EXPR : FALSE_EXPR; + } + } + if (expression0 instanceof TernaryExpression + && expression0.getNodeType() == ExpressionType.Conditional) { + TernaryExpression ternary = (TernaryExpression) expression0; + Expression expr = null; + if (eq(ternary.expression1, expression1)) { + // (a ? b : c) == b === a || c == b + expr = Expressions.orElse(ternary.expression0, + Expressions.equal(ternary.expression2, expression1)); + } else if (eq(ternary.expression2, expression1)) { + // (a ? b : c) == c === !a || b == c + expr = Expressions.orElse(Expressions.not(ternary.expression0), + Expressions.equal(ternary.expression1, expression1)); + } + if (expr != null) { + if (binary.getNodeType() == ExpressionType.NotEqual) { + expr = Expressions.not(expr); + } + return expr.accept(this); + } + } + // drop down + case AndAlso: + case OrElse: + result = visit0(binary, expression0, expression1); + if (result != null) { + return result; + } + result = visit0(binary, expression1, expression0); + if (result != null) { + return result; + } + } + return super.visit(binary, expression0, expression1); + } + + private Expression visit0( + BinaryExpression binary, + Expression expression0, + Expression expression1) { + Boolean always; + switch (binary.getNodeType()) { + case AndAlso: + always = always(expression0); + if (always != null) { + return always + ? expression1 + : FALSE_EXPR; + } + break; + case OrElse: + always = always(expression0); + if (always != null) { + // true or x --> true + // false or x --> x + return always + ? TRUE_EXPR + : expression1; + } + break; + case Equal: + if (isConstantNull(expression1) + && Primitive.is(expression0.getType())) { + return FALSE_EXPR; + } + // a == true -> a + // a == false -> !a + always = always(expression0); + if (always != null) { + return always ? expression1 : Expressions.not(expression1); + } + break; + case NotEqual: + if (isConstantNull(expression1) + && Primitive.is(expression0.getType())) { + return TRUE_EXPR; + } + // a != true -> !a + // a != false -> a + always = always(expression0); + if (always != null) { + return always ? Expressions.not(expression1) : expression1; + } + break; + } + return null; + } + + @Override public Expression visit(UnaryExpression unaryExpression, + Expression expression) { + switch (unaryExpression.getNodeType()) { + case Convert: + if (expression.getType() == unaryExpression.getType()) { + return expression; + } + if (expression instanceof ConstantExpression) { + return Expressions.constant(((ConstantExpression) expression).value, + unaryExpression.getType()); + } + break; + case Not: + Boolean always = always(expression); + if (always != null) { + return always ? FALSE_EXPR : TRUE_EXPR; + } + if (expression instanceof UnaryExpression) { + UnaryExpression arg = (UnaryExpression) expression; + if (arg.getNodeType() == ExpressionType.Not) { + return arg.expression; + } + } + if (expression instanceof BinaryExpression) { + BinaryExpression bin = (BinaryExpression) expression; + ExpressionType comp = NOT_BINARY_COMPLEMENT.get(bin.getNodeType()); + if (comp != null) { + return Expressions.makeBinary(comp, bin.expression0, bin.expression1); + } + } + } + return super.visit(unaryExpression, expression); + } + + @Override public Statement visit(ConditionalStatement conditionalStatement, + List list) { + // if (false) { <-- remove branch + // } if (true) { <-- stop here + // } else if (...) + // } else {...} + boolean optimal = true; + for (int i = 0; i < list.size() - 1 && optimal; i += 2) { + Boolean always = always((Expression) list.get(i)); + if (always == null) { + continue; + } + if (i == 0 && always) { + // when the very first test is always true, just return its statement + return (Statement) list.get(1); + } + optimal = false; + } + if (optimal) { + // Nothing to optimize + return super.visit(conditionalStatement, list); + } + List newList = new ArrayList<>(list.size()); + // Iterate over all the tests, except the latest "else" + for (int i = 0; i < list.size() - 1; i += 2) { + Expression test = (Expression) list.get(i); + Node stmt = list.get(i + 1); + Boolean always = always(test); + if (always == null) { + newList.add(test); + newList.add(stmt); + continue; + } + if (always) { + // No need to verify other tests + newList.add(stmt); + break; + } + } + // We might have dangling "else", however if we have just single item + // it means we have if (false) else if(false) else if (true) {...} code. + // Then we just return statement from true branch + if (list.size() == 1) { + return (Statement) list.get(0); + } + // Add "else" from original list + if (newList.size() % 2 == 0 && list.size() % 2 == 1) { + Node elseBlock = list.get(list.size() - 1); + if (newList.isEmpty()) { + return (Statement) elseBlock; + } + newList.add(elseBlock); + } + if (newList.isEmpty()) { + return EMPTY_STATEMENT; + } + return super.visit(conditionalStatement, newList); + } + + @Override public Expression visit(MethodCallExpression methodCallExpression, + Expression targetExpression, + List expressions) { + if (BOOLEAN_VALUEOF_BOOL.equals(methodCallExpression.method)) { + Boolean always = always(expressions.get(0)); + if (always != null) { + return always ? TRUE_EXPR : FALSE_EXPR; + } + } + return super.visit(methodCallExpression, targetExpression, expressions); + } + + private boolean isConstantNull(Expression expression) { + return expression instanceof ConstantExpression + && ((ConstantExpression) expression).value == null; + } + + /** + * Returns whether an expression always evaluates to true or false. + * Assumes that expression has already been optimized. + */ + private static Boolean always(Expression x) { + if (x.equals(FALSE_EXPR) || x.equals(BOXED_FALSE_EXPR)) { + return Boolean.FALSE; + } + if (x.equals(TRUE_EXPR) || x.equals(BOXED_TRUE_EXPR)) { + return Boolean.TRUE; + } + return null; + } + + /** + * Returns whether an expression always returns a non-null result. + * For instance, primitive types cannot contain null values. + * + * @param expression expression to test + * @return true when the expression is known to be not-null + */ + protected boolean isKnownNotNull(Expression expression) { + return Primitive.is(expression.getType()) + || always(expression) != null + || (expression instanceof MethodCallExpression + && KNOWN_NON_NULL_METHODS.contains( + ((MethodCallExpression) expression).method)); + } + + /** + * Treats two expressions equal even if they represent different null types + */ + private static boolean eq(Expression a, Expression b) { + return a.equals(b) + || (a instanceof ConstantExpression + && b instanceof ConstantExpression + && ((ConstantExpression) a).value + == ((ConstantExpression) b).value); + } +} + +// End OptimizeShuttle.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeVisitor.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeVisitor.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeVisitor.java deleted file mode 100644 index f0bed0f..0000000 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/OptimizeVisitor.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.calcite.linq4j.tree; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.apache.calcite.linq4j.tree.ExpressionType.Equal; -import static org.apache.calcite.linq4j.tree.ExpressionType.NotEqual; - -/** - * Visitor that optimizes expressions. - * - *

The optimizations are essential, not mere tweaks. Without - * optimization, expressions such as {@code false == null} will be left in, - * which are invalid to Janino (because it does not automatically box - * primitives).

- */ -public class OptimizeVisitor extends Visitor { - public static final ConstantExpression FALSE_EXPR = - Expressions.constant(false); - public static final ConstantExpression TRUE_EXPR = - Expressions.constant(true); - public static final MemberExpression BOXED_FALSE_EXPR = - Expressions.field(null, Boolean.class, "FALSE"); - public static final MemberExpression BOXED_TRUE_EXPR = - Expressions.field(null, Boolean.class, "TRUE"); - public static final Statement EMPTY_STATEMENT = Expressions.statement(null); - - private static final Set KNOWN_NON_NULL_METHODS = - new HashSet(); - - static { - for (Class aClass : new Class[]{Boolean.class, Byte.class, Short.class, - Integer.class, Long.class, String.class}) { - for (Method method : aClass.getMethods()) { - if ("valueOf".equals(method.getName()) - && Modifier.isStatic(method.getModifiers())) { - KNOWN_NON_NULL_METHODS.add(method); - } - } - } - } - - private static final Map - NOT_BINARY_COMPLEMENT = - new EnumMap(ExpressionType.class); - - static { - addComplement(ExpressionType.Equal, ExpressionType.NotEqual); - addComplement(ExpressionType.GreaterThanOrEqual, ExpressionType.LessThan); - addComplement(ExpressionType.GreaterThan, ExpressionType.LessThanOrEqual); - } - - private static void addComplement(ExpressionType eq, ExpressionType ne) { - NOT_BINARY_COMPLEMENT.put(eq, ne); - NOT_BINARY_COMPLEMENT.put(ne, eq); - } - - private static final Method BOOLEAN_VALUEOF_BOOL = - Types.lookupMethod(Boolean.class, "valueOf", boolean.class); - - @Override public Expression visit( - TernaryExpression ternary, - Expression expression0, - Expression expression1, - Expression expression2) { - switch (ternary.getNodeType()) { - case Conditional: - Boolean always = always(expression0); - if (always != null) { - // true ? y : z === y - // false ? y : z === z - return always - ? expression1 - : expression2; - } - if (expression1.equals(expression2)) { - // a ? b : b === b - return expression1; - } - // !a ? b : c == a ? c : b - if (expression0 instanceof UnaryExpression) { - UnaryExpression una = (UnaryExpression) expression0; - if (una.getNodeType() == ExpressionType.Not) { - return Expressions.makeTernary(ternary.getNodeType(), - una.expression, expression2, expression1); - } - } - - // a ? true : b === a || b - // a ? false : b === !a && b - always = always(expression1); - if (always != null && isKnownNotNull(expression2)) { - return (always - ? Expressions.orElse(expression0, expression2) - : Expressions.andAlso(Expressions.not(expression0), - expression2)).accept(this); - } - - // a ? b : true === !a || b - // a ? b : false === a && b - always = always(expression2); - if (always != null && isKnownNotNull(expression1)) { - return (always - ? Expressions.orElse(Expressions.not(expression0), - expression1) - : Expressions.andAlso(expression0, expression1)).accept(this); - } - - if (expression0 instanceof BinaryExpression - && (expression0.getNodeType() == ExpressionType.Equal - || expression0.getNodeType() == ExpressionType.NotEqual)) { - BinaryExpression cmp = (BinaryExpression) expression0; - Expression expr = null; - if (eq(cmp.expression0, expression2) - && eq(cmp.expression1, expression1)) { - // a == b ? b : a === a (hint: if a==b, then a == b ? a : a) - // a != b ? b : a === b (hint: if a==b, then a != b ? b : b) - expr = expression0.getNodeType() == ExpressionType.Equal - ? expression2 : expression1; - } - if (eq(cmp.expression0, expression1) - && eq(cmp.expression1, expression2)) { - // a == b ? a : b === b (hint: if a==b, then a == b ? b : b) - // a != b ? a : b === a (hint: if a==b, then a == b ? a : a) - expr = expression0.getNodeType() == ExpressionType.Equal - ? expression2 : expression1; - } - if (expr != null) { - return expr; - } - } - } - return super.visit(ternary, expression0, expression1, expression2); - } - - @Override public Expression visit( - BinaryExpression binary, - Expression expression0, - Expression expression1) { - // - Expression result; - switch (binary.getNodeType()) { - case AndAlso: - case OrElse: - if (eq(expression0, expression1)) { - return expression0; - } - } - switch (binary.getNodeType()) { - case Equal: - case NotEqual: - if (eq(expression0, expression1)) { - return binary.getNodeType() == Equal ? TRUE_EXPR : FALSE_EXPR; - } else if (expression0 instanceof ConstantExpression && expression1 - instanceof ConstantExpression) { - ConstantExpression c0 = (ConstantExpression) expression0; - ConstantExpression c1 = (ConstantExpression) expression1; - if (c0.getType() == c1.getType() - || !(Primitive.is(c0.getType()) || Primitive.is(c1.getType()))) { - return binary.getNodeType() == NotEqual ? TRUE_EXPR : FALSE_EXPR; - } - } - if (expression0 instanceof TernaryExpression - && expression0.getNodeType() == ExpressionType.Conditional) { - TernaryExpression ternary = (TernaryExpression) expression0; - Expression expr = null; - if (eq(ternary.expression1, expression1)) { - // (a ? b : c) == b === a || c == b - expr = Expressions.orElse(ternary.expression0, - Expressions.equal(ternary.expression2, expression1)); - } else if (eq(ternary.expression2, expression1)) { - // (a ? b : c) == c === !a || b == c - expr = Expressions.orElse(Expressions.not(ternary.expression0), - Expressions.equal(ternary.expression1, expression1)); - } - if (expr != null) { - if (binary.getNodeType() == ExpressionType.NotEqual) { - expr = Expressions.not(expr); - } - return expr.accept(this); - } - } - // drop down - case AndAlso: - case OrElse: - result = visit0(binary, expression0, expression1); - if (result != null) { - return result; - } - result = visit0(binary, expression1, expression0); - if (result != null) { - return result; - } - } - return super.visit(binary, expression0, expression1); - } - - private Expression visit0( - BinaryExpression binary, - Expression expression0, - Expression expression1) { - Boolean always; - switch (binary.getNodeType()) { - case AndAlso: - always = always(expression0); - if (always != null) { - return always - ? expression1 - : FALSE_EXPR; - } - break; - case OrElse: - always = always(expression0); - if (always != null) { - // true or x --> true - // false or x --> x - return always - ? TRUE_EXPR - : expression1; - } - break; - case Equal: - if (isConstantNull(expression1) - && Primitive.is(expression0.getType())) { - return FALSE_EXPR; - } - // a == true -> a - // a == false -> !a - always = always(expression0); - if (always != null) { - return always ? expression1 : Expressions.not(expression1); - } - break; - case NotEqual: - if (isConstantNull(expression1) - && Primitive.is(expression0.getType())) { - return TRUE_EXPR; - } - // a != true -> !a - // a != false -> a - always = always(expression0); - if (always != null) { - return always ? Expressions.not(expression1) : expression1; - } - break; - } - return null; - } - - @Override public Expression visit(UnaryExpression unaryExpression, - Expression expression) { - switch (unaryExpression.getNodeType()) { - case Convert: - if (expression.getType() == unaryExpression.getType()) { - return expression; - } - if (expression instanceof ConstantExpression) { - return Expressions.constant(((ConstantExpression) expression).value, - unaryExpression.getType()); - } - break; - case Not: - Boolean always = always(expression); - if (always != null) { - return always ? FALSE_EXPR : TRUE_EXPR; - } - if (expression instanceof UnaryExpression) { - UnaryExpression arg = (UnaryExpression) expression; - if (arg.getNodeType() == ExpressionType.Not) { - return arg.expression; - } - } - if (expression instanceof BinaryExpression) { - BinaryExpression bin = (BinaryExpression) expression; - ExpressionType comp = NOT_BINARY_COMPLEMENT.get(bin.getNodeType()); - if (comp != null) { - return Expressions.makeBinary(comp, bin.expression0, bin.expression1); - } - } - } - return super.visit(unaryExpression, expression); - } - - @Override public Statement visit(ConditionalStatement conditionalStatement, - List list) { - // if (false) { <-- remove branch - // } if (true) { <-- stop here - // } else if (...) - // } else {...} - boolean optimal = true; - for (int i = 0; i < list.size() - 1 && optimal; i += 2) { - Boolean always = always((Expression) list.get(i)); - if (always == null) { - continue; - } - if (i == 0 && always) { - // when the very first test is always true, just return its statement - return (Statement) list.get(1); - } - optimal = false; - } - if (optimal) { - // Nothing to optimize - return super.visit(conditionalStatement, list); - } - List newList = new ArrayList(list.size()); - // Iterate over all the tests, except the latest "else" - for (int i = 0; i < list.size() - 1; i += 2) { - Expression test = (Expression) list.get(i); - Node stmt = list.get(i + 1); - Boolean always = always(test); - if (always == null) { - newList.add(test); - newList.add(stmt); - continue; - } - if (always) { - // No need to verify other tests - newList.add(stmt); - break; - } - } - // We might have dangling "else", however if we have just single item - // it means we have if (false) else if(false) else if (true) {...} code. - // Then we just return statement from true branch - if (list.size() == 1) { - return (Statement) list.get(0); - } - // Add "else" from original list - if (newList.size() % 2 == 0 && list.size() % 2 == 1) { - Node elseBlock = list.get(list.size() - 1); - if (newList.isEmpty()) { - return (Statement) elseBlock; - } - newList.add(elseBlock); - } - if (newList.isEmpty()) { - return EMPTY_STATEMENT; - } - return super.visit(conditionalStatement, newList); - } - - @Override public Expression visit(MethodCallExpression methodCallExpression, - Expression targetExpression, - List expressions) { - if (BOOLEAN_VALUEOF_BOOL.equals(methodCallExpression.method)) { - Boolean always = always(expressions.get(0)); - if (always != null) { - return always ? TRUE_EXPR : FALSE_EXPR; - } - } - return super.visit(methodCallExpression, targetExpression, expressions); - } - - private boolean isConstantNull(Expression expression) { - return expression instanceof ConstantExpression - && ((ConstantExpression) expression).value == null; - } - - /** - * Returns whether an expression always evaluates to true or false. - * Assumes that expression has already been optimized. - */ - private static Boolean always(Expression x) { - if (x.equals(FALSE_EXPR) || x.equals(BOXED_FALSE_EXPR)) { - return Boolean.FALSE; - } - if (x.equals(TRUE_EXPR) || x.equals(BOXED_TRUE_EXPR)) { - return Boolean.TRUE; - } - return null; - } - - /** - * Returns whether an expression always returns a non-null result. - * For instance, primitive types cannot contain null values. - * - * @param expression expression to test - * @return true when the expression is known to be not-null - */ - protected boolean isKnownNotNull(Expression expression) { - return Primitive.is(expression.getType()) - || always(expression) != null - || (expression instanceof MethodCallExpression - && KNOWN_NON_NULL_METHODS.contains( - ((MethodCallExpression) expression).method)); - } - - /** - * Treats two expressions equal even if they represent different null types - */ - private static boolean eq(Expression a, Expression b) { - return a.equals(b) - || (a instanceof ConstantExpression - && b instanceof ConstantExpression - && ((ConstantExpression) a).value - == ((ConstantExpression) b).value); - } -} - -// End OptimizeVisitor.java http://git-wip-us.apache.org/repos/asf/calcite/blob/267e2f3e/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ParameterExpression.java ---------------------------------------------------------------------- diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ParameterExpression.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ParameterExpression.java index a437a46..f883f50 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ParameterExpression.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ParameterExpression.java @@ -43,7 +43,11 @@ public class ParameterExpression extends Expression { this.name = name; } - @Override public Expression accept(Visitor visitor) { + @Override public Expression accept(Shuttle shuttle) { + return shuttle.visit(this); + } + + public R accept(Visitor visitor) { return visitor.visit(this); }