/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.frontend;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.Set;
import abs.ABSTest;
import abs.common.WrongProgramArgumentException;
import abs.frontend.analyser.ErrorMessage;
import abs.frontend.analyser.SemanticCondition;
import abs.frontend.analyser.SemanticConditionList;
import abs.frontend.ast.AssignStmt;
import abs.frontend.ast.CaseBranch;
import abs.frontend.ast.CaseExp;
import abs.frontend.ast.ClassDecl;
import abs.frontend.ast.Decl;
import abs.frontend.ast.Exp;
import abs.frontend.ast.ExpFunctionDef;
import abs.frontend.ast.ExpressionStmt;
import abs.frontend.ast.FunctionDecl;
import abs.frontend.ast.Model;
import abs.frontend.ast.ParametricFunctionDecl;
import abs.frontend.ast.Pattern;
import abs.frontend.ast.Stmt;
import abs.frontend.ast.VarDeclStmt;
import abs.frontend.typechecker.Type;
import static abs.ABSTest.Config.*;
public class FrontendTest extends ABSTest {
protected Model assertParseOkStdLib(String s) {
return assertParse(s, WITH_STD_LIB);
}
protected Model assertParseFileOk(String fileName, boolean withStdLib) throws IOException, WrongProgramArgumentException {
if (withStdLib) {
return assertParseFileOk(fileName, WITH_STD_LIB);
} else {
return assertParseFileOk(fileName);
}
}
protected Model assertParseFilesOk(Set<String> fileNames, boolean withStdLib) throws IOException {
if (withStdLib) {
return assertParseFilesOk(fileNames, WITH_STD_LIB);
} else {
return assertParseFilesOk(fileNames);
}
}
protected Model assertTypeCheckFileOk(String fileName, boolean withStdLib) throws IOException, WrongProgramArgumentException {
if (withStdLib) {
return assertParseFileOk(fileName, TYPE_CHECK, WITH_STD_LIB);
} else {
return assertParseFileOk(fileName, TYPE_CHECK);
}
}
protected Exp getFirstExp(String absCode) {
Model m = assertParse(absCode);
return getFirstExp(m);
}
protected Exp getSecondExp(String absCode) {
return getSecondExp(assertParse(absCode));
}
protected Exp getExp(String absCode, int i) {
return getExp(assertParse(absCode), i);
}
protected Exp getSecondExp(Model m) {
return getExp(m, 1);
}
protected Exp getFirstExp(Model m) {
return getExp(m, 0);
}
protected Exp getExp(Model m, int i) {
Stmt s = m.getMainBlock().getStmt(i);
if (s instanceof AssignStmt)
return ((AssignStmt) s).getValue();
if (s instanceof ExpressionStmt)
return ((ExpressionStmt) s).getExp();
if (s instanceof VarDeclStmt)
return ((VarDeclStmt) s).getVarDecl().getInitExp();
throw new IllegalArgumentException();
}
protected ClassDecl getFirstClassDecl(Model m) {
for (Decl d : m.getCompilationUnit(m.getNumCompilationUnit()-1).getModuleDecl(0).getDecls()) {
if (d instanceof ClassDecl)
return (ClassDecl) d;
}
throw new IllegalArgumentException("No ClassDecl found");
}
protected Exp getFirstCaseExpr(Model m) {
CaseExp ce = (CaseExp) getFirstFunctionExpr(m);
CaseBranch b = ce.getBranch(0);
return b.getRight();
}
protected Exp getSecondCaseExpr(Model m) {
CaseExp ce = (CaseExp) getFirstFunctionExpr(m);
CaseBranch b = ce.getBranch(1);
return b.getRight();
}
protected Pattern getFirstCasePattern(Model m) {
CaseExp ce = (CaseExp) getFirstFunctionExpr(m);
CaseBranch b = ce.getBranch(0);
return b.getLeft();
}
protected Decl getLastDecl(Model m, Class<?> clazz) {
Decl lastMatching = null;
for (Decl d : m.getDecls()) {
if (clazz.isInstance(d)) {
lastMatching = d;
}
}
if (lastMatching == null)
throw new IllegalArgumentException("The model does not contain any " + clazz.getSimpleName());
else
return lastMatching;
}
protected FunctionDecl getLastFunctionDecl(Model m) {
return (FunctionDecl) getLastDecl(m, FunctionDecl.class);
}
protected ParametricFunctionDecl getLastParametricFunctionDecl(Model m) {
return (ParametricFunctionDecl) getLastDecl(m, ParametricFunctionDecl.class);
}
protected Exp getFirstFunctionExpr(Model m) {
return ((ExpFunctionDef) getLastFunctionDecl(m).getFunctionDef()).getRhs();
}
protected Type getTypeOfFirstAssignment(Model m) {
return getTypeOfNthAssignment(m, 1);
}
protected Type getTypeOfNthAssignment(Model m, int n) {
int count = 0;
for (Stmt s : m.getMainBlock().getStmts()) {
Type t = null;
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
t = as.getValue().getType();
} else if (s instanceof VarDeclStmt) {
VarDeclStmt vd = (VarDeclStmt) s;
if (vd.getVarDecl().hasInitExp()) {
t = vd.getVarDecl().getInitExp().getType();
}
}
if (t != null) {
count++;
if (count == n) {
return t;
}
}
}
return null;
}
protected void assertNoTypeErrorsNoLib(String absCode) {
assertTypeErrors(absCode, new Config[0]);
}
protected void assertTypeOK(String absCode) {
assertTypeErrors(absCode, WITH_STD_LIB);
}
protected SemanticCondition assertTypeErrors(String absCode) {
return assertTypeErrors(absCode, EXPECT_TYPE_ERROR, WITH_STD_LIB);
}
protected void assertTypeErrors(String absCode, ErrorMessage expected) {
SemanticCondition e = assertTypeErrors(absCode, EXPECT_TYPE_ERROR, WITH_STD_LIB);
assertEquals(expected,e.msg);
}
/**
* Check for and return the first error occurring in 'absCode', or null if
* none found. If EXPECT_WARNING is set, and EXPECT_TYPE_ERROR is not
* set, return the first warning instead. Produces a test failure if
* 'config' contains EXPECT_TYPE_ERROR but no error found. Produces a
* test failure if 'config' contains EXPECT_WARNING but no warning found.
* @param absCode - the test case source code
* @param config - flags
* @return
*/
protected SemanticCondition assertTypeErrors(String absCode, Config... config) {
Model m = assertParse(absCode, config);
String msg = "";
SemanticConditionList l = m.typeCheck();
if (l.containsErrors()) {
msg = l.getFirstError().getMsgWithHint(absCode);
} else if (l.containsWarnings() && isSet(EXPECT_WARNING, config)) {
msg = l.getFirstWarning().getMsgWithHint(absCode);
}
assertEquals(msg, isSet(EXPECT_TYPE_ERROR, config), l.containsErrors());
if (isSet(EXPECT_WARNING, config)) {
assertEquals(msg, isSet(EXPECT_WARNING, config), l.containsWarnings());
}
return l.containsErrors() ? l.getFirstError() : null;
}
protected SemanticCondition assertWarnings(String absCode) {
return assertTypeErrors(absCode, EXPECT_WARNING, WITH_STD_LIB);
}
protected void assertWarnings(String absCode, ErrorMessage expected) {
SemanticCondition e = assertTypeErrors(absCode, EXPECT_WARNING, WITH_STD_LIB);
assertEquals(expected,e.msg);
}
}