/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.statements;
import gw.lang.parser.IStackProvider;
import gw.lang.parser.statements.IStatementList;
import gw.lang.parser.statements.ITerminalStatement;
import gw.internal.gosu.parser.Statement;
import gw.internal.gosu.parser.CannotExecuteGosuException;
import gw.lang.reflect.TypeSystem;
import gw.internal.gosu.parser.expressions.EvalExpression;
import java.util.List;
/**
* Represents a statement-list as specified in the Gosu grammar:
* <pre>
* <i>statement-list</i>
* <statement>
* <statement-list> <statement>
* </pre>
* <p/>
*
* @see gw.lang.parser.IGosuParser
*/
public final class StatementList extends Statement implements IStatementList
{
protected Statement[] _statements;
protected IStackProvider _stackProvider;
/**
* Constructs a StatementList given an ISymbolTable instance.
*/
public StatementList( IStackProvider stackProvider )
{
_stackProvider = stackProvider;
}
@Override
public void clearParseTreeInformation()
{
TypeSystem.lock();
try
{
super.clearParseTreeInformation();
if( _statements != null )
{
for( int i = 0; i < _statements.length; i++ )
{
Statement statement = _statements[i];
statement.clearParseTreeInformation();
}
}
}
finally
{
TypeSystem.unlock();
}
}
/**
* @return A list of Statements representing this statement-list.
*/
public Statement[] getStatements()
{
return _statements;
}
/**
* @param statements A list of Statements representing this statement-list.
*/
public void setStatements( List<Statement> statements )
{
if( statements.size() == 0 )
{
_statements = null;
}
else
{
_statements = statements.toArray( new Statement[statements.size()] );
tryToEliminateTheScope();
}
}
public int indexOf( Statement stmt )
{
for( int i = 0; i < _statements.length; i++ )
{
if( stmt == _statements[i] )
{
return i;
}
}
return -1;
}
/**
* A statement-list needs to push a new scope on the symbol table to provide
* a for local variable scoping. Since this is a relatively expensive
* operation we avoid pushing the scope if we know none of the statements
* declare variables.
*/
private void tryToEliminateTheScope()
{
for( int i = 0; i < _statements.length; i++ )
{
Statement statement = _statements[i];
if( statement instanceof VarStatement ||
(!(statement instanceof StatementList) &&
statement.getContainedParsedElementsByType( EvalExpression.class, null )) )
{
return;
}
}
setNoScope();
}
public void setNoScope()
{
_stackProvider = null;
}
/**
* for testing
*/
public boolean hasScope()
{
return _stackProvider != null;
}
/**
* Execute the list of statements.
*/
public Object execute()
{
if( !isCompileTimeConstant() )
{
return super.execute();
}
throw new CannotExecuteGosuException();
}
@Override
protected ITerminalStatement getLeastSignificantTerminalStatement_internal( boolean[] bAbsolute )
{
bAbsolute[0] = false;
return getLeastSignificantTerminalStatementAfter( null, bAbsolute );
}
public ITerminalStatement getLeastSignificantTerminalStatementAfter( Statement fromStmt, boolean[] bAbsolute )
{
if( _statements == null )
{
return null;
}
ITerminalStatement ret = null;
for( int i = fromStmt == null ? 0 : indexOf( fromStmt )+1; i < _statements.length; i++ )
{
boolean[] bCsr = {false};
ITerminalStatement terminalStmt = _statements[i].getLeastSignificantTerminalStatement( bCsr );
if( terminalStmt != null )
{
ret = getLeastSignificant( ret, terminalStmt );
if( ret == terminalStmt ) {
bAbsolute[0] = bCsr[0];
}
}
}
return ret;
}
@Override
public String toString()
{
String strStatements = "{\n";
if( _statements != null )
{
int iSize = _statements.length;
for( int i = 0; i < iSize; i++ )
{
Statement stmt = _statements[i];
strStatements += " " + stmt.toString() + "\n";
}
}
return strStatements + "}\n";
}
public Statement getSelfOrSingleStatement()
{
if( _statements != null && _statements.length == 1 && !hasScope() )
{
_statements[0].addExceptionsFrom( this );
return _statements[0];
}
else
{
return this;
}
}
}