blob: bdf3527f3869dc95fa1d30704e591a29ebb361dd [file] [log] [blame]
/*
*
* 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);
}
}