/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed 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.codehaus.groovy.ast.expr;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.GroovyCodeVisitor;
import org.codehaus.groovy.syntax.Token;
/**
* Represents one or more local variables. Typically it is a single local variable
* declared by name with an expression like "def foo" or with type "String foo". However,
* the multiple assignment feature allows you to create two or more variables using using
* an expression like "def (x, y) = [1, 2]". <br/><br/>
*
* You can access the left hand side of a declaration using either the
* "getLeftExpression() : Expression" or "getVariableExpression() : VariableExpression" API.
* If the declaration is a multiple assignment statement then getVariableExpression will
* throw a ClassCastException because the left hand side is not a VariableExpression. The
* safe way to access the VariableExpression on the left hand side is to use
* "getLeftExpression()" with an instanceof check afterwards or to invoke the
* "isMultipleAssignmentDeclaration() : boolean" method. If "isMultipleAssignmentDeclaration"
* returns true then it is always safe to call "getVariableExpression()". If
* "isMultipleAssignmentDeclaration" returns false then it is never safe to call
* "getVariableExpression()".
*
* @author Jochen Theodorou
* @author Hamlet D'Arcy
* @version $Revision: 21301 $
*/
public class DeclarationExpression extends BinaryExpression {
/**
* Creates a DeclarationExpression for VariableExpressions like "def x" or "String y = 'foo'".
* @param left
* the left hand side of a variable declaration
* @param operation
* the operation, typically an assignment operator
* @param right
* the right hand side of a declaration
*/
public DeclarationExpression(VariableExpression left, Token operation, Expression right) {
super(left,operation,right);
}
/**
* Creates a DeclarationExpression for Expressions like "def (x, y) = [1, 2]"
* @param left
* the left hand side of a declaration. Must be either a VariableExpression or
* a TupleExpression with at least one element.
* @param operation
* the operation, typically an assignment operator
* @param right
* the right hand side of a declaration
*/
public DeclarationExpression(Expression left, Token operation, Expression right) {
super(left,operation,right);
check(left);
}
private void check(Expression left) {
if (left instanceof VariableExpression) {
//nothing
} else if (left instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) left;
if (tuple.getExpressions().size()==0) throw new GroovyBugError("one element required for left side");
} else {
throw new GroovyBugError("illegal left expression for declaration: "+left);
}
}
public void visit(GroovyCodeVisitor visitor) {
visitor.visitDeclarationExpression(this);
}
/**
* This method returns the left hand side of the declaration cast to the VariableExpression type.
* This is an unsafe method to call. In a multiple assignment statement, the left hand side will
* be a TupleExpression and a ClassCastException will occur. If you invoke this method then
* be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
* If that method returns true then this method is safe to call.
* @return
* left hand side of normal variable declarations
* @throws ClassCastException
* if the left hand side is not a VariableExpression (and is probably a multiple assignment statement).
*
*/
public VariableExpression getVariableExpression() {
return (VariableExpression) this.getLeftExpression();
}
/**
* This method returns the left hand side of the declaration cast to the TupleExpression type.
* This is an unsafe method to call. In a single assignment statement, the left hand side will
* be a VariableExpression and a ClassCastException will occur. If you invoke this method then
* be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
* If that method returns true then this method is safe to call.
* @return
* left hand side of multiple assignment declarations
* @throws ClassCastException
* if the left hand side is not a TupleExpression (and is probably a VariableExpression).
*
*/
public TupleExpression getTupleExpression() {
return (TupleExpression) this.getLeftExpression();
}
/**
* This method sets the leftExpression for this BinaryExpression. The parameter must be
* either a VariableExpression or a TupleExpression with one or more elements.
* @param leftExpression
* either a VariableExpression or a TupleExpression with one or more elements.
*/
public void setLeftExpression(Expression leftExpression) {
check(leftExpression);
super.setLeftExpression(leftExpression);
}
public void setRightExpression(Expression rightExpression) {
super.setRightExpression(rightExpression);
}
public Expression transformExpression(ExpressionTransformer transformer) {
Expression ret = new DeclarationExpression(transformer.transform(getLeftExpression()),
getOperation(), transformer.transform(getRightExpression()));
ret.setSourcePosition(this);
ret.addAnnotations(getAnnotations());
ret.setDeclaringClass(getDeclaringClass());
return ret;
}
/**
* This method tells you if this declaration is a multiple assignment declaration, which
* has the form "def (x, y) = ..." in Groovy. If this method returns true, then the left
* hand side is an ArgumentListExpression. Do not call "getVariableExpression()" on this
* object if this method returns true, instead use "getLeftExpression()".
* @return
* true if this declaration is a multiple assignment declaration, which means the
* left hand side is an ArgumentListExpression.
*/
public boolean isMultipleAssignmentDeclaration() {
return getLeftExpression() instanceof TupleExpression;
}
}