/*
* #%~
* The VDM Type Checker
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.typechecker.utilities;
import java.util.Collection;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.analysis.AnswerAdaptor;
import org.overture.ast.factory.AstFactory;
import org.overture.ast.node.INode;
import org.overture.ast.statements.AAlwaysStm;
import org.overture.ast.statements.AAssignmentStm;
import org.overture.ast.statements.ACallObjectStm;
import org.overture.ast.statements.ACallStm;
import org.overture.ast.statements.ACaseAlternativeStm;
import org.overture.ast.statements.ACasesStm;
import org.overture.ast.statements.AElseIfStm;
import org.overture.ast.statements.AExitStm;
import org.overture.ast.statements.AForAllStm;
import org.overture.ast.statements.AForIndexStm;
import org.overture.ast.statements.AForPatternBindStm;
import org.overture.ast.statements.AIfStm;
import org.overture.ast.statements.ALetBeStStm;
import org.overture.ast.statements.ALetStm;
import org.overture.ast.statements.AReturnStm;
import org.overture.ast.statements.ATixeStm;
import org.overture.ast.statements.ATixeStmtAlternative;
import org.overture.ast.statements.ATrapStm;
import org.overture.ast.statements.AWhileStm;
import org.overture.ast.statements.PStm;
import org.overture.ast.statements.SSimpleBlockStm;
import org.overture.ast.types.PType;
import org.overture.ast.util.PTypeSet;
import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
/**
* This class implements a way collect the exit types of a statement. This is to be used with exception handling in VDM
*
* @author kel
*/
public class ExitTypeCollector extends AnswerAdaptor<PTypeSet>
{
protected ITypeCheckerAssistantFactory af;
public ExitTypeCollector(ITypeCheckerAssistantFactory af)
{
this.af = af;
}
@Override
public PTypeSet caseAAlwaysStm(AAlwaysStm statement)
throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
types.addAll(statement.getBody().apply(THIS));
types.addAll(statement.getAlways().apply(THIS));
return types;
}
@Override
public PTypeSet caseAAssignmentStm(AAssignmentStm statement)
throws AnalysisException
{
// TODO We don't know what an expression call will raise
return new PTypeSet(AstFactory.newAUnknownType(statement.getLocation()), af);
}
@Override
public PTypeSet caseACallStm(ACallStm statement) throws AnalysisException
{
// TODO We don't know what an operation call will raise
return new PTypeSet(AstFactory.newAUnknownType(statement.getLocation()), af);
}
@Override
public PTypeSet caseACallObjectStm(ACallObjectStm statement)
throws AnalysisException
{
// TODO We don't know what an operation call will raise
return new PTypeSet(AstFactory.newAUnknownType(statement.getLocation()), af);
}
@Override
public PTypeSet caseACasesStm(ACasesStm statement) throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
for (ACaseAlternativeStm c : statement.getCases())
{
types.addAll(c.apply(THIS));
}
return types;
}
@Override
public PTypeSet caseACaseAlternativeStm(ACaseAlternativeStm statement)
throws AnalysisException
{
return statement.getResult().apply(THIS);
}
@Override
public PTypeSet caseAElseIfStm(AElseIfStm statement)
throws AnalysisException
{
return statement.getThenStm().apply(THIS);
}
@Override
public PTypeSet caseAExitStm(AExitStm statement) throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
if (statement.getExpression() == null)
{
types.add(AstFactory.newAVoidType(statement.getLocation()));
} else
{
types.add(statement.getExpType());
}
return types;
}
@Override
public PTypeSet caseAForAllStm(AForAllStm statement)
throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet caseAForIndexStm(AForIndexStm statement)
throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet caseAForPatternBindStm(AForPatternBindStm statement)
throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet caseAIfStm(AIfStm statement) throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
types.addAll(statement.getThenStm().apply(THIS));
for (AElseIfStm stmt : statement.getElseIf())
{
types.addAll(stmt.apply(THIS));
}
if (statement.getElseStm() != null)
{
types.addAll(statement.getElseStm().apply(THIS));
}
return types;
}
@Override
public PTypeSet caseALetBeStStm(ALetBeStStm statement)
throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet caseALetStm(ALetStm statement) throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet caseAReturnStm(AReturnStm statement)
throws AnalysisException
{
if (statement.getExpression() != null)
{
// TODO We don't know what an expression will raise
return new PTypeSet(AstFactory.newAUnknownType(statement.getLocation()), af);
} else
{
return new PTypeSet(af);
}
}
@Override
public PTypeSet defaultSSimpleBlockStm(SSimpleBlockStm statement)
throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
for (PStm stmt : statement.getStatements())
{
types.addAll(stmt.apply(THIS));
}
return types;
}
@Override
public PTypeSet caseATixeStm(ATixeStm statement) throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
types.addAll(statement.getBody().apply(THIS));
for (ATixeStmtAlternative tsa : statement.getTraps())
{
types.addAll(exitCheck(tsa));
}
return types;
}
private Collection<? extends PType> exitCheck(ATixeStmtAlternative tsa)
throws AnalysisException
{
return tsa.getStatement().apply(THIS);
}
@Override
public PTypeSet caseATrapStm(ATrapStm statement) throws AnalysisException
{
PTypeSet types = new PTypeSet(af);
types.addAll(statement.getBody().apply(THIS));
types.addAll(statement.getWith().apply(THIS));
return types;
}
@Override
public PTypeSet caseAWhileStm(AWhileStm statement) throws AnalysisException
{
return statement.getStatement().apply(THIS);
}
@Override
public PTypeSet defaultPStm(PStm statement) throws AnalysisException
{
return new PTypeSet(af);
}
@Override
public PTypeSet createNewReturnValue(INode node)
{
assert false : "should not happen";
return null;
}
@Override
public PTypeSet createNewReturnValue(Object node)
{
assert false : "should not happen";
return null;
}
}