
com.tangosol.dev.compiler.java.DeclarationStatement Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.dev.compiler.java;
import com.tangosol.dev.assembler.CodeAttribute;
import com.tangosol.dev.assembler.OpDeclare;
import com.tangosol.dev.assembler.Ivar;
import com.tangosol.dev.assembler.Lvar;
import com.tangosol.dev.assembler.Fvar;
import com.tangosol.dev.assembler.Dvar;
import com.tangosol.dev.assembler.Avar;
import com.tangosol.dev.compiler.CompilerException;
import com.tangosol.dev.compiler.Context;
import com.tangosol.dev.component.DataType;
import com.tangosol.util.ErrorList;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ArrayList;
/**
* This class implements a Java local variable declaration statement.
*
* LocalVariableDeclarationStatement:
* LocalVariableDeclaration ;
* LocalVariableDeclaration: (modified for JDK 1.1 to allow "final")
* Modifiers-opt Type VariableDeclarators
* VariableDeclarators:
* VariableDeclarator
* VariableDeclarators , VariableDeclarator
* VariableDeclarator:
* VariableDeclaratorId
* VariableDeclaratorId = VariableInitializer
* VariableDeclaratorId:
* Identifier
* VariableDeclaratorId [ ]
* VariableInitializer:
* Expression
* ArrayInitializer
* ArrayInitializer:
* { VariableInitializers-opt , -opt }
* VariableInitializers:
* VariableInitializer
* VariableInitializers , VariableInitializer
*
* Before precompilation, the DeclarationStatement can provide:
* - The type of the declaration as parsed
* - Whether the declaration is a parameter
* - Whether the declaration is final
* - What declarators are present
*
* A declarator is an expression. Considering various types of declarations,
* a declarator will always fall into one of the following categories:
*
* Category Examples Description
* ------------ ---------- -------------------------------------------------
* Name i A simple variable without an initializer
* Dim'd Expr i[] A dimensioned variable
* Assign Expr i=0 A simple variable with an initializer
* i[]={0,1} A dimensioned variable with an initializer
*
* After pre-compilation, the DeclarationStatement can provide:
* - What variable(s) are declared
*
* @version 1.00, 09/21/98
* @author Cameron Purdy
*/
public class DeclarationStatement extends Statement
{
// ----- construction ---------------------------------------------------
/**
* Construct a declaration statement.
*
* @param stmt the statement within which this element exists
* @param token the first token of the statement
*/
public DeclarationStatement(Statement stmt, Token token)
{
super(stmt, token);
}
// ----- code generation ------------------------------------------------
/**
* Perform semantic checks, parse tree re-organization, name binding,
* and optimizations.
*
* @param ctx the compiler context
* @param setUVars the set of potentially unassigned variables
* @param setFVars the set of potentially assigned final variables
* @param mapThrown the set of potentially thrown checked exceptions
* @param errlist the error list
*
* @exception CompilerException thrown if an error occurs that should
* stop the compilation process
*/
protected Element precompile(Context ctx, DualSet setUVars, DualSet setFVars, Map mapThrown, ErrorList errlist)
throws CompilerException
{
// JLS 16.2.3 Local Variable Declaration Statements
// - V is definitely assigned after a local variable declaration
// statement that contains no initializers iff it is definitely
// assigned before the local variable declaration statement.
// - V is definitely assigned after a local variable declaration
// statement that contains initializers iff either it is
// definitely assigned after the last initializer expression in
// the local variable declaration statement or the last
// initializer expression in the declaration is in the declarator
// that declares V.
// - V is definitely assigned before the first initializer
// expression iff it is definitely assigned before the local
// variable declaration statement.
// - V is definitely assigned before any other initializer
// expression e iff either it is definitely assigned after the
// initializer expression immediately preceding e in the local
// variable declaration statement or the initializer expression
// immediately preceding e in the local variable declaration
// statement is in the declarator that declares V.
// pre-compile the type expression (to validate its type information)
TypeExpression exprType = this.exprType;
exprType = (TypeExpression) exprType.precompile(ctx, null, null, null, errlist);
this.exprType = exprType;
// variable declarations must be immediately contained by a block
Block block = getBlock();
if (block != getOuterStatement())
{
logError(ERROR, DECL_NOT_IMMED, null, errlist);
}
// get the type of the declaration statement (which may not be the
// type of each declarator)
DataType dtStmt = exprType.getType();
boolean fFinal = isFinal();
boolean fParam = isParameter();
// process each declarator
List listVars = new ArrayList();
for (Iterator iter = getDeclarators(); iter.hasNext(); )
{
ExpressionStatement stmtDeclarator = (ExpressionStatement) iter.next();
AssignExpression exprAssignment = null;
Expression exprDeclarator = (Expression) stmtDeclarator.getExpression();
Expression exprInitializer = null;
DataType dtDeclarator = dtStmt;
// unwrap any initializer
if (exprDeclarator instanceof AssignExpression)
{
exprAssignment = (AssignExpression) exprDeclarator;
exprDeclarator = exprAssignment.getLeftExpression();
exprInitializer = exprAssignment.getRightExpression();
}
// unwrap any dims ("[]")
boolean fDimensioned = false;
while (exprDeclarator instanceof DimensionedExpression)
{
dtDeclarator = dtDeclarator.getArrayType();
exprDeclarator = ((DimensionedExpression) exprDeclarator).getTypeExpression();
fDimensioned = true;
}
if (fDimensioned && exprDeclarator instanceof TypeExpression)
{
// the name was accidently parsed as a type because it was
// followed by brackets
exprType = (TypeExpression) exprDeclarator;
if (exprType.getNameExpression() != null)
{
exprDeclarator = exprType.getNameExpression();
}
}
// the remaining expression must be a simple name
if (!(exprDeclarator instanceof NameExpression))
{
exprDeclarator.logError(ERROR, DECL_BAD_NAME, null, errlist);
continue;
}
NameExpression exprName = (NameExpression) exprDeclarator;
if (exprName.isQualified())
{
exprDeclarator.logError(ERROR, DECL_BAD_NAME, null, errlist);
continue;
}
// create and register the variable
String sName = exprName.getName();
Variable var = new Variable(block, sName, dtDeclarator, fParam, fFinal);
if (!block.registerVariable(var))
{
// this variable name hides another variable
logError(ERROR, VAR_DUPLICATE, new String[] {var.getName()}, errlist);
}
// if it is a parameter, then it is assigned, otherwise ...
if (fParam)
{
if (fFinal)
{
// potentially assigned (actually, all parameters are
// definitely assigned)
setFVars.add(var);
}
}
else
{
// local variables are potentially unassigned
setUVars.add(var);
}
// process the declarator initializer
if (exprAssignment != null)
{
// update the left side of the assign expression
exprAssignment.setLeftExpression(exprName);
// if an array initializer is used, its type is determined
// by the variable declaration
if (dtDeclarator.isArray() && exprInitializer instanceof ArrayExpression)
{
((ArrayExpression) exprInitializer).setType(dtDeclarator);
}
// pre-compile the assignment statement
stmtDeclarator.precompile(ctx, setUVars, setFVars, mapThrown, errlist);
// final variables may have a determinable constant value
if (fFinal)
{
Expression exprValue = ((AssignExpression)
stmtDeclarator.getExpression()).getRightExpression();
if (exprValue.isConstant())
{
var.setValue(exprValue.getValue());
}
}
}
listVars.add(var);
}
avar = (Variable[]) listVars.toArray(NO_VARS);
return this;
}
/**
* Perform final optimizations and code generation.
*
* @param ctx the compiler context
* @param code the assembler code attribute to compile to
* @param fReached true if this language element is reached (JLS 14.19)
* @param errlist the error list to log errors to
*
* @return true if the element can complete normally (JLS 14.1)
*
* @exception CompilerException thrown if an error occurs that should
* stop the compilation process
*/
protected boolean compileImpl(Context ctx, CodeAttribute code, boolean fReached, ErrorList errlist)
throws CompilerException
{
// compilation for variable declaration:
// start:
// ?var
// [init-opt]
// end:
for (Iterator iterDecl = getDeclarators(), iterVars = getVariables(); iterDecl.hasNext(); )
{
ExpressionStatement stmt = (ExpressionStatement) iterDecl.next();
Variable var = (Variable ) iterVars.next();
String sName = var.getName();
DataType dt = var.getType();
OpDeclare op;
switch (dt.getTypeString().charAt(0))
{
case 'Z':
case 'B':
case 'C':
case 'S':
case 'I':
op = new Ivar(sName, dt.getJVMSignature());
break;
case 'J':
op = new Lvar(sName);
break;
case 'F':
op = new Fvar(sName);
break;
case 'D':
op = new Dvar(sName);
break;
case 'L':
case 'R':
case '[':
op = new Avar(sName, dt.getJVMSignature());
break;
default:
throw new IllegalStateException();
}
code.add(op);
// store the declaring op with the variable as well; any
// expression that uses the variable will need it
var.setOp(op);
if (stmt.getExpression() instanceof AssignExpression)
{
stmt.compile(ctx, code, fReached, errlist);
}
}
// JLS 14.19: A local variable declaration statement can complete
// normally iff it is reach-able.
return fReached;
}
// ----- accessors ------------------------------------------------------
/**
* Determine if the declaration is for a parameter.
*
* @return true if this declaration statement declares a parameter
*/
public boolean isParameter()
{
return fParam;
}
/**
* Specify that the declaration is for a parameter.
*
* @param fParam true if this declaration statement declares a parameter
*/
protected void setParameter(boolean fParam)
{
this.fParam = fParam;
}
/**
* Determine if the variable is declared as final.
*
* @return true if this declaration statement declares a final variable
*/
public boolean isFinal()
{
// currently only modifier supported is final
return tokMod != null; // && mod.getID() == TokenConstants.KEY_FINAL;
}
/**
* Get the declaration modifier if any.
*
* @return the declaration modifier or null
*/
public Token getModifier()
{
return tokMod;
}
/**
* Specify the declaration modifier.
*
* @param tokMod a modifier
*/
protected void setModifier(Token tokMod)
{
this.tokMod = tokMod;
}
/**
* Get the declaration type.
*
* @return the declaration type
*/
public TypeExpression getTypeExpression()
{
return exprType;
}
/**
* Set the declaration type.
*
* @param exprType the declaration type
*/
protected void setTypeExpression(TypeExpression exprType)
{
this.exprType = exprType;
}
/**
* Determine if only one variable is being declared.
*
* @return true if only one variable is being declared
*/
public boolean isSingleDeclaration()
{
// declarations are organized as inner expression statements
return getInnerStatement().getNextStatement() == null;
}
/**
* Determine if there is assignment as part of the declaration.
*
* @return true if there is assignment as part of the declaration
*/
public boolean isAssignmentDeclaration()
{
ExpressionStatement stmt = (ExpressionStatement) getInnerStatement();
while (stmt != null)
{
if (stmt.getExpression() instanceof AssignExpression)
{
return true;
}
stmt = (ExpressionStatement) stmt.getNextStatement();
}
return false;
}
/**
* Enumerate the declarators of the local variable declaration statement.
*
* @return an iterator of declarator statements
*/
protected Iterator getDeclarators()
{
return new Iterator()
{
/**
* The next statement containing a declarator expression.
*/
private Statement stmt = getInnerStatement();
/**
* @return true if there are more declarators
*/
public boolean hasNext()
{
return stmt != null;
}
/**
* @return the next declarator expression
*/
public Object next()
{
Statement stmtRet = stmt;
if (stmtRet == null)
{
throw new NoSuchElementException();
}
stmt = stmtRet.getNextStatement();
return stmtRet;
}
/**
* Immutable iterator.
*/
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
/**
* After pre-compilation, the declaration statement variables.
*
* @return an iterator of variables declared by the declaration statement
*/
public Iterator getVariables()
{
return new Iterator()
{
/**
* The next variable.
*/
private int i = 0;
/**
* @return true if there are more variables
*/
public boolean hasNext()
{
return i < avar.length;
}
/**
* @return the next variable
*/
public Object next()
{
try
{
return avar[i++];
}
catch (RuntimeException e)
{
throw new NoSuchElementException();
}
}
/**
* Immutable iterator.
*/
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
/**
* The first variable.
*
* @return the first variable declared by the declaration statement
*/
protected Variable getVariable()
{
return avar[0];
}
// ----- Element methods ------------------------------------------------
/**
* Print the statement information.
*
* @param sIndent
*/
public void print(String sIndent)
{
out(sIndent + toString()
+ " (" + (tokMod != null ? tokMod.text + " " : "")
+ (fParam ? "parameter" : "local") + ")");
if (exprType != null)
{
out(sIndent + " Type:");
exprType.print(sIndent + " ");
}
Statement inner = getInnerStatement();
if (inner != null)
{
out(sIndent + " Declarations:");
inner.printList(sIndent + " ");
}
}
// ----- data members ---------------------------------------------------
/**
* The class name.
*/
private static final String CLASS = "DeclarationStatement";
/**
* True if a parameter, false otherwise.
*/
private boolean fParam;
/**
* The final modifier, if any.
*/
private Token tokMod;
/**
* The type of the declaration.
*/
private TypeExpression exprType;
/**
* An empty array of variables.
*/
private static final Variable[] NO_VARS = new Variable[0];
/**
* The declared variables.
*/
private Variable[] avar = NO_VARS;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy