
com.tangosol.dev.compiler.java.IfStatement 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.Goto;
import com.tangosol.dev.assembler.Label;
import com.tangosol.dev.assembler.Ifeq;
import com.tangosol.dev.assembler.Ifne;
import com.tangosol.dev.compiler.CompilerException;
import com.tangosol.dev.compiler.Context;
import com.tangosol.dev.component.DataType;
import com.tangosol.util.ErrorList;
import com.tangosol.util.DeltaSet;
import java.util.Set;
import java.util.Map;
/**
* This class implements the if/then and if/then/else constructs.
*
* IfThenStatement:
* if ( Expression ) Statement
* IfThenElseStatement:
* if ( Expression ) StatementNoShortIf else Statement
*
* @version 1.00, 09/21/98
* @author Cameron Purdy
*/
public class IfStatement extends ConditionalStatement
{
// ----- construction ---------------------------------------------------
/**
* Construct an "if/then" or "if/then/else" statement.
*
* @param stmt the statement within which this element exists
* @param token the first token of the statement
*/
public IfStatement(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
{
// pre-compile the test
Expression exprTest = precompileTest(ctx, setUVars, setFVars, mapThrown, errlist);
// pre-compile the "then"
Statement stmtThen = getThenStatement();
DualSet setUThen = new DualSet(setUVars.getTrueSet());
DualSet setFThen = new DualSet(setFVars.getTrueSet());
stmtThen.precompile(ctx, setUThen, setFThen, mapThrown, errlist);
setUThen.resolve();
setFThen.resolve();
// pre-compile the "else"
Statement stmtElse = getElseStatement();
if (stmtElse != null)
{
DualSet setUElse = new DualSet(setUVars.getFalseSet());
DualSet setFElse = new DualSet(setFVars.getFalseSet());
stmtElse.precompile(ctx, setUElse, setFElse, mapThrown, errlist);
setUElse.resolve();
setFElse.resolve();
}
// JLS 16.2.6: V is definitely assigned after if (e) S iff V is
// definitely assigned after S and V is definitely assigned after e
// when false. V is definitely assigned before e iff V is definitely
// assigned before if (e) S else T. V is definitely assigned before S
// iff V is definitely assigned after e when true. V is definitely
// assigned before T iff V is definitely assigned after e when false.
setUVars.merge();
setFVars.merge();
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
{
Expression exprTest = getTest();
Statement stmtThen = getThenStatement();
Statement stmtElse = getElseStatement();
if (exprTest instanceof BooleanExpression || !ctx.isDebug() && exprTest.isConstant())
{
// JLS 14.19: An optimizing compiler may realize that the
// [inner statement] will never be executed and may choose to
// omit the code for that statement from the generated class
// file, but [that statement] is not regarded as unreachable
// in the technical sense specified here.
if (!((Boolean) exprTest.getValue()).booleanValue())
{
stmtThen = stmtElse;
}
if (stmtThen != null)
{
stmtThen.compile(ctx, code, fReached, errlist);
}
// this if statement being reachable infers the compiled block/statement
// (then or else) is reachable
return fReached;
}
// compilation of "if () ":
//
// [expr]
// ifeq else // or "ifne" if "then" replaced with "else"
// [stmt]
// else:
//
// compilation of "if () else ":
//
// [expr]
// ifeq else
// [stmt] // then
// goto exit
// else:
// [stmt]
// exit:
Label lblElse = new Label();
Label lblExit = getEndLabel();
// conditional test
exprTest.compile(ctx, code, fReached, errlist);
code.add(new Ifeq(lblElse));
// "then" portion
boolean fCompletes = stmtThen.compile(ctx, code, fReached, errlist);
// "else" portion
if (stmtElse == null)
{
code.add(lblElse);
// JLS 14.19: An if-then statement can complete normally iff it
// is reachable. The then statement is reachable iff the if-then
// statement is reachable.
fCompletes = fReached;
}
else
{
code.add(new Goto(lblExit));
code.add(lblElse);
// JLS 14.19: An if-then-else statement can complete normally
// iff the then statement can complete normally or the else
// statement can complete normally. The then-statement is
// reachable iff the if-then-else statement is reachable. The
// else-statement is reachable iff the if-then-else statement
// is reachable.
fCompletes |= stmtElse.compile(ctx, code, fReached, errlist);
}
return fCompletes;
}
// ----- accessors ------------------------------------------------------
/**
* Get the "then" statement.
*
* @return the statement to execute if the test is true
*/
public Statement getThenStatement()
{
return getInnerStatement();
}
/**
* Set the "then" statement.
*
* @param stmt the statement to execute if the test is true
*/
protected void setThenStatement(Statement stmt)
{
setInnerStatement(stmt);
// the "then" has the last token if there is no else
if (stmtElse == null)
{
setEndToken(stmt.getEndToken());
}
}
/**
* Get the "else" statement.
*
* @return the statement to execute if the test is false, or null if no
* else statement is present
*/
public Statement getElseStatement()
{
return stmtElse;
}
/**
* Set the "else" statement.
*
* @param stmt the statement to execute if the test is false
*/
protected void setElseStatement(Statement stmt)
{
this.stmtElse = stmt;
// the "else" has the last token
setEndToken(stmt.getEndToken());
}
// ----- data members ---------------------------------------------------
/**
* The class name.
*/
private static final String CLASS = "IfStatement";
/**
* The else clause.
*/
private Statement stmtElse;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy