/* * Copyright 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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 com.google.dart.engine.ast; import com.google.dart.engine.element.ParameterElement; import com.google.dart.engine.internal.type.DynamicTypeImpl; import com.google.dart.engine.type.Type; /** * Instances of the class {@code Expression} defines the behavior common to nodes that represent an * expression. * * <pre> * expression ::= * {@link AssignmentExpression assignmentExpression} * | {@link ConditionalExpression conditionalExpression} cascadeSection* * | {@link ThrowExpression throwExpression} * </pre> * * @coverage dart.engine.ast */ public abstract class Expression extends AstNode { /** * An empty array of expressions. */ public static final Expression[] EMPTY_ARRAY = new Expression[0]; /** * The static type of this expression, or {@code null} if the AST structure has not been resolved. */ private Type staticType; /** * The propagated type of this expression, or {@code null} if type propagation has not been * performed on the AST structure. */ private Type propagatedType; /** * Return the best parameter element information available for this expression. If type * propagation was able to find a better parameter element than static analysis, that type will be * returned. Otherwise, the result of static analysis will be returned. * * @return the parameter element representing the parameter to which the value of this expression * will be bound */ public ParameterElement getBestParameterElement() { ParameterElement propagatedElement = getPropagatedParameterElement(); if (propagatedElement != null) { return propagatedElement; } return getStaticParameterElement(); } /** * Return the best type information available for this expression. If type propagation was able to * find a better type than static analysis, that type will be returned. Otherwise, the result of * static analysis will be returned. If no type analysis has been performed, then the type * 'dynamic' will be returned. * * @return the best type information available for this expression */ public Type getBestType() { if (propagatedType != null) { return propagatedType; } else if (staticType != null) { return staticType; } return DynamicTypeImpl.getInstance(); } /** * Return the precedence of this expression. The precedence is a positive integer value that * defines how the source code is parsed into an AST. For example {@code a * b + c} is parsed as * {@code (a * b) + c} because the precedence of {@code *} is greater than the precedence of * {@code +}. * <p> * You should not assume that returned values will stay the same, they might change as result of * specification change. Only relative order should be used. * * @return the precedence of this expression */ public abstract int getPrecedence(); /** * If this expression is an argument to an invocation, and the AST structure has been resolved, * and the function being invoked is known based on propagated type information, and this * expression corresponds to one of the parameters of the function being invoked, then return the * parameter element representing the parameter to which the value of this expression will be * bound. Otherwise, return {@code null}. * * @return the parameter element representing the parameter to which the value of this expression * will be bound */ public ParameterElement getPropagatedParameterElement() { AstNode parent = getParent(); if (parent instanceof ArgumentList) { return ((ArgumentList) parent).getPropagatedParameterElementFor(this); } else if (parent instanceof IndexExpression) { IndexExpression indexExpression = (IndexExpression) parent; if (indexExpression.getIndex() == this) { return indexExpression.getPropagatedParameterElementForIndex(); } } else if (parent instanceof BinaryExpression) { BinaryExpression binaryExpression = (BinaryExpression) parent; if (binaryExpression.getRightOperand() == this) { return binaryExpression.getPropagatedParameterElementForRightOperand(); } } else if (parent instanceof AssignmentExpression) { AssignmentExpression assignmentExpression = (AssignmentExpression) parent; if (assignmentExpression.getRightHandSide() == this) { return assignmentExpression.getPropagatedParameterElementForRightHandSide(); } } else if (parent instanceof PrefixExpression) { return ((PrefixExpression) parent).getPropagatedParameterElementForOperand(); } else if (parent instanceof PostfixExpression) { return ((PostfixExpression) parent).getPropagatedParameterElementForOperand(); } return null; } /** * Return the propagated type of this expression, or {@code null} if type propagation has not been * performed on the AST structure. * * @return the propagated type of this expression */ public Type getPropagatedType() { return propagatedType; } /** * If this expression is an argument to an invocation, and the AST structure has been resolved, * and the function being invoked is known based on static type information, and this expression * corresponds to one of the parameters of the function being invoked, then return the parameter * element representing the parameter to which the value of this expression will be bound. * Otherwise, return {@code null}. * * @return the parameter element representing the parameter to which the value of this expression * will be bound */ public ParameterElement getStaticParameterElement() { AstNode parent = getParent(); if (parent instanceof ArgumentList) { return ((ArgumentList) parent).getStaticParameterElementFor(this); } else if (parent instanceof IndexExpression) { IndexExpression indexExpression = (IndexExpression) parent; if (indexExpression.getIndex() == this) { return indexExpression.getStaticParameterElementForIndex(); } } else if (parent instanceof BinaryExpression) { BinaryExpression binaryExpression = (BinaryExpression) parent; if (binaryExpression.getRightOperand() == this) { return binaryExpression.getStaticParameterElementForRightOperand(); } } else if (parent instanceof AssignmentExpression) { AssignmentExpression assignmentExpression = (AssignmentExpression) parent; if (assignmentExpression.getRightHandSide() == this) { return assignmentExpression.getStaticParameterElementForRightHandSide(); } } else if (parent instanceof PrefixExpression) { return ((PrefixExpression) parent).getStaticParameterElementForOperand(); } else if (parent instanceof PostfixExpression) { return ((PostfixExpression) parent).getStaticParameterElementForOperand(); } return null; } /** * Return the static type of this expression, or {@code null} if the AST structure has not been * resolved. * * @return the static type of this expression */ public Type getStaticType() { return staticType; } /** * Return {@code true} if this expression is syntactically valid for the LHS of an * {@link AssignmentExpression assignment expression}. * * @return {@code true} if this expression matches the {@code assignableExpression} production */ public boolean isAssignable() { return false; } /** * Set the propagated type of this expression to the given type. * * @param propagatedType the propagated type of this expression */ public void setPropagatedType(Type propagatedType) { this.propagatedType = propagatedType; } /** * Set the static type of this expression to the given type. * * @param staticType the static type of this expression */ public void setStaticType(Type staticType) { this.staticType = staticType; } }