| /* |
| * |
| * 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.flex.compiler.internal.tree.as; |
| |
| import static org.apache.flex.compiler.internal.parsing.as.ASTokenTypes.*; |
| |
| import org.apache.flex.compiler.constants.IASLanguageConstants.BuiltinType; |
| import org.apache.flex.compiler.definitions.ITypeDefinition; |
| import org.apache.flex.compiler.parsing.IASToken; |
| import org.apache.flex.compiler.projects.ICompilerProject; |
| import org.apache.flex.compiler.tree.as.IASNode; |
| import org.apache.flex.compiler.tree.as.IExpressionNode; |
| import org.apache.flex.compiler.tree.as.IOperatorNode; |
| import org.apache.flex.compiler.tree.as.IUnaryOperatorNode; |
| |
| /** |
| * Abstract base class for all unary operator nodes. |
| */ |
| public abstract class UnaryOperatorNodeBase extends OperatorNodeBase implements IUnaryOperatorNode |
| { |
| /** |
| * Factory method for various kinds of unary prefix operator nodes. |
| */ |
| public static UnaryOperatorNodeBase createPrefix(IASToken operatorToken, ExpressionNodeBase operand) |
| { |
| switch (operatorToken.getType()) |
| { |
| case TOKEN_OPERATOR_PLUS: |
| return new UnaryOperatorPlusNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_MINUS: |
| return new UnaryOperatorMinusNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_INCREMENT: |
| return new UnaryOperatorPreIncrementNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_DECREMENT: |
| return new UnaryOperatorPreDecrementNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_LOGICAL_NOT: |
| return new UnaryOperatorLogicalNotNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_BITWISE_NOT: |
| return new UnaryOperatorBitwiseNotNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_ATSIGN: |
| return new UnaryOperatorAtNode(operatorToken, operand); |
| |
| case TOKEN_KEYWORD_DELETE: |
| return new UnaryOperatorDeleteNode(operatorToken, operand); |
| |
| case TOKEN_KEYWORD_TYPEOF: |
| return new UnaryOperatorTypeOfNode(operatorToken, operand); |
| |
| case TOKEN_KEYWORD_VOID: |
| return new UnaryOperatorVoidNode(operatorToken, operand); |
| } |
| |
| assert false : "Token '" + operatorToken.getText() + "' unexpected in UnaryOperatorNodeBase.createPrefix()"; |
| return null; |
| } |
| |
| /** |
| * Factory method for various kinds of unary prefix operator nodes. |
| */ |
| public static UnaryOperatorNodeBase createPostfix(IASToken operatorToken, ExpressionNodeBase operand) |
| { |
| switch (operatorToken.getType()) |
| { |
| case TOKEN_OPERATOR_INCREMENT: |
| return new UnaryOperatorPostIncrementNode(operatorToken, operand); |
| |
| case TOKEN_OPERATOR_DECREMENT: |
| return new UnaryOperatorPostDecrementNode(operatorToken, operand); |
| } |
| |
| assert false : "Token '" + operatorToken.getText() + "' unexpected in UnaryOperatorNodeBase.createPostfix()"; |
| return null; |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param operatorToken The token representing the unary operator. |
| * @param operandNode The expresson node representing the operand. |
| */ |
| public UnaryOperatorNodeBase(IASToken operatorToken, ExpressionNodeBase operandNode) |
| { |
| super(operatorToken); |
| this.operandNode = operandNode; |
| } |
| |
| /** |
| * Copy constructor. |
| * |
| * @param other The node to copy. |
| */ |
| protected UnaryOperatorNodeBase(UnaryOperatorNodeBase other) |
| { |
| super(other); |
| this.operandNode = other.operandNode != null ? other.operandNode.copy() : null; |
| } |
| |
| private ExpressionNodeBase operandNode; |
| |
| // |
| // NodeBase overrides |
| // |
| |
| @Override |
| public int getChildCount() |
| { |
| return operandNode != null ? 1 : 0; |
| } |
| |
| @Override |
| public IASNode getChild(int i) |
| { |
| return i == 0 ? operandNode : null; |
| } |
| |
| @Override |
| protected void setChildren(boolean fillInOffsets) |
| { |
| if (operandNode != null) |
| operandNode.setParent(this); |
| } |
| |
| @Override |
| protected void fillInOffsets() |
| { |
| if (operandNode == null && operatorStart != -1) |
| { |
| span(operatorStart, operatorStart + 1, -1, -1); |
| } |
| else |
| { |
| super.fillInOffsets(); |
| } |
| } |
| |
| // |
| // ExpressionNodeBase overrides |
| // |
| |
| @Override |
| public ITypeDefinition resolveType(ICompilerProject project) |
| { |
| // Various subclasses override this default behavior. |
| return project.getBuiltinType(BuiltinType.ANY_TYPE); |
| } |
| |
| @Override |
| public boolean isDynamicExpression(ICompilerProject project) |
| { |
| return false; |
| } |
| |
| /** |
| * Determine if e is part of an attribue expression (@name). |
| * |
| * @param e the expression to test |
| * @return true if e if the sub-expr of the unary expression, and the |
| * operator is '@' |
| */ |
| @Override |
| boolean isAttributeExpr(ExpressionNodeBase e) |
| { |
| return this.getOperator() == IOperatorNode.OperatorType.AT && |
| e == this.getOperandNode(); |
| } |
| |
| /* |
| * Get the ExpressionNodeBase representing the Base of the operand of an @ |
| * operator. This would be the Node for 'a' in the expression 'a.@b', |
| * assuming you asked for the base of 'b'. |
| * |
| * @param e The ExpressionNodeBase representing b. |
| * @return The ExpressionNodeBase representing the base expression of e, or null |
| * if there is no base |
| */ |
| @Override |
| ExpressionNodeBase getBaseForMemberRef(ExpressionNodeBase e) |
| { |
| if (isAttributeExpr(e)) |
| { |
| ExpressionNodeBase p = getParentExpression(); |
| if (p != null) |
| return p.getBaseForMemberRef(this); |
| } |
| |
| return null; |
| } |
| // |
| // OperatorNodeBase overrides |
| // |
| |
| @Override |
| public ExpressionType getExpressionType() |
| { |
| // Most unary operators are prefix. |
| // The two that aren't (a++ and a--) override this method to return POSTFIX. |
| return ExpressionType.PREFIX; |
| } |
| |
| // |
| // IUnaryOperatorNode implementations |
| // |
| |
| @Override |
| public IExpressionNode getOperandNode() |
| { |
| return operandNode; |
| } |
| |
| // |
| // Other methods |
| // |
| |
| public void setExpression(ExpressionNodeBase operandNode) |
| { |
| this.operandNode = operandNode; |
| } |
| |
| /** |
| * Utility method called by {@link #resolveType(ICompilerProject)} in subclasses |
| * for the <code>++</code> and <code>--</code> operators. |
| */ |
| protected ITypeDefinition resolveIncrementOrDecrementType(ICompilerProject project) |
| { |
| ITypeDefinition exprType = operandNode.resolveType(project); |
| |
| if (exprType != null) |
| { |
| ITypeDefinition intType = project.getBuiltinType(BuiltinType.INT); |
| ITypeDefinition uintType = project.getBuiltinType(BuiltinType.UINT); |
| |
| if (exprType.equals(intType)) |
| return intType; |
| else if (exprType.equals(uintType)) |
| return uintType; |
| } |
| |
| return project.getBuiltinType(BuiltinType.NUMBER); |
| } |
| } |