/**
* 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.typesystem;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.*;
import org.junit.Test;
import abs.frontend.FrontendTest;
import abs.frontend.analyser.ErrorMessage;
import abs.frontend.analyser.SemanticError;
import abs.frontend.ast.ClassDecl;
import abs.frontend.ast.ExpFunctionDef;
import abs.frontend.ast.FieldDecl;
import abs.frontend.ast.Model;
import abs.frontend.ast.ParametricFunctionDecl;
import abs.frontend.ast.ReturnStmt;
import abs.frontend.ast.TypeParameterDecl;
import abs.frontend.ast.TypeUse;
import abs.frontend.typechecker.DataTypeType;
import abs.frontend.typechecker.KindedName;
import abs.frontend.typechecker.Type;
import abs.frontend.typechecker.TypeParameter;
import abs.frontend.typechecker.UnionType;
import abs.frontend.typechecker.KindedName.Kind;
public class TypingTest extends FrontendTest {
@Test
public void testContextDecl() {
Model m = assertParseOk("class C implements I { I m() { return this; } } interface I { }");
ClassDecl d = (ClassDecl) m.getDecls().iterator().next();
ReturnStmt s = (ReturnStmt) d.getMethod(0).getBlock().getStmt(0);
assertEquals(d, s.getRetExp().getContextDecl());
}
@Test
public void testThisTyping() {
Model m = assertParseOk("class C implements I { I m() { return this; } } interface I { }");
ClassDecl d = (ClassDecl) m.lookupModule("UnitTest").getDecl(0);
ReturnStmt s = (ReturnStmt) d.getMethod(0).getBlock().getStmt(0);
assertEquals(m.lookupModule("UnitTest").getDecl(1),
((UnionType) s.getRetExp().getType()).getType(0).getDecl());
}
@Test
public void testInterfaceType() {
Model m = assertParseOk("interface I { } class C {} { I i = new local C(); I i2 = i; }");
assertEquals(m.lookupModule("UnitTest").getDecl(0).getType(), getTypeOfNthAssignment(m, 2));
}
@Test
public void testDataTypeBoolLit() {
Model m = assertParseOkStdLib("{ Bool i = True; }");
assertEquals(m.getBoolType(), getTypeOfFirstAssignment(m));
}
@Test
public void testDataTypeIntLit() {
Model m = assertParseOkStdLib("{ Int i = 5; }");
assertEquals(m.getIntType(), getTypeOfFirstAssignment(m));
}
@Test
public void testDataTypeStringLit() {
Model m = assertParseOkStdLib("{ String i = \"5\"; }");
assertEquals(m.getStringType(), getTypeOfFirstAssignment(m));
}
@Test
public void testLetExp() {
Model m = assertParseOkStdLib("def Bool f() = let (Bool b) = True in b;");
assertEquals(m.getBoolType(), getFirstFunctionExpr(m).getType());
}
@Test
public void testCase() {
Model m = assertParseOkStdLib("def Bool f(Bool x) = case x { True => False; False => True; };");
assertEquals(m.getBoolType(), getFirstFunctionExpr(m).getType());
}
@Test
public void testCase2() {
Model m = assertParseOkStdLib("def Bool f(Bool x) = case x { True => x; False => x; };");
assertEquals(m.getBoolType(), getFirstFunctionExpr(m).getType());
}
@Test
public void testFnApp() {
Model m = assertParseOkStdLib("def Bool f() = f();");
assertEquals(m.getBoolType(), getFirstFunctionExpr(m).getType());
}
@Test
public void testNew() {
Model m = assertParseOk("interface I {} class C implements I {} { I i; i = new local C(); }");
assertEquals(m.lookup(new KindedName(Kind.TYPE_DECL, "UnitTest.I")).getType(),
((UnionType) getTypeOfFirstAssignment(m)).getType(0));
}
@Test
public void testFieldUse() {
Model m = assertParseOkStdLib(" class C { Bool f; Bool m() { return this.f; } }");
ClassDecl d = (ClassDecl) m.lookup(new KindedName(Kind.CLASS, "UnitTest.C"));
FieldDecl f = d.getField(0);
ReturnStmt s = (ReturnStmt) d.getMethod(0).getBlock().getStmt(0);
assertEquals(f.getType(), s.getRetExp().getType());
}
@Test
public void testSyncCall() {
Model m = assertParseOkStdLib(" interface I { Bool m(); } { I i; i.m(); }");
assertEquals(m.getBoolType(), getSecondExp(m).getType());
}
@Test
public void testAsyncCall() {
Model m = assertParseOkStdLib(" interface I { Bool m(); } { I i; i!m(); }");
assertEquals(m.getFutType(m.getBoolType()), getSecondExp(m).getType());
}
@Test
public void functionTypeParams() {
Model m = assertParseOkStdLib(" def A f<A>(A a) = a ;");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
assertEquals(d.getTypeParameter(0),
((TypeParameter) ((ExpFunctionDef) d.getFunctionDef()).getRhs().getType()).getDecl());
}
@Test
public void functionTypeArgs() {
Model m = assertParseOkStdLib(" def Maybe<A> f<A>() = None ;");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
DataTypeType t = (DataTypeType) d.getTypeUse().getType();
TypeParameter typeArg = (TypeParameter) t.getTypeArg(0);
assertEquals(typeArg.getDecl(), d.getTypeParameter(0));
}
@Test
public void functionTypeArgs2() {
Model m = assertParseOkStdLib(" def Maybe<A> f<A>(Maybe<A> o) = o ;");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
assertEquals(d.getTypeUse().getType(), ((ExpFunctionDef) d.getFunctionDef()).getRhs().getType());
}
@Test
public void functionTypeArgs3() {
Model m = assertParseOkStdLib(" def A f<A>(Maybe<A> o) = case o { Just(a) => a; } ;");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
TypeParameterDecl typeParameter = d.getTypeParameter(0);
TypeParameter type = (TypeParameter) ((ExpFunctionDef) d.getFunctionDef()).getRhs().getType();
TypeParameterDecl decl = type.getDecl();
assertEquals(typeParameter, decl);
}
@Test
public void functionTypeArgs4() {
Model m = assertParseOkStdLib(" data Foo<A> = Bar(A,Bool); "
+ "def Bool f<A>(Foo<A> o) = case o { Bar(a,b) => b; } ;");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
Type type = ((ExpFunctionDef) d.getFunctionDef()).getRhs().getType();
assertEquals(m.getBoolType(), type);
}
@Test
public void functionTypeArgs5() {
Model m = assertParseOkStdLib("def B nth<B>(List<B> list, Int n) = nth(tail(list), n-1) ; ");
ParametricFunctionDecl d = getLastParametricFunctionDecl(m);
TypeParameterDecl typeParameter = d.getTypeParameter(0);
TypeParameter type = (TypeParameter) ((ExpFunctionDef) d.getFunctionDef()).getRhs().getType();
assertEquals(typeParameter.getName(), type.getDecl().getName());
}
@Test
public void testFutST1() {
assertTypeOK("interface A {} interface B extends A {} interface I { A mA(); B mB(); } { I o = null; Fut<A> f = o!mB(); }");
}
@Test
public void testFutST2() {
assertTypeOK("interface A {} interface B extends A {} interface I { A mA(); B mB(); } { I o = null; A f = o.mB(); }");
}
@Test
public void testFutST3() {
assertTypeOK("interface A {} interface B extends A {} interface I { A mA(); B mB(); } { I o = null; Fut<B> f = o!mB(); A a = f.get;}");
}
@Test
public void test_DuplicateFeature() {
assertTypeErrors("productline Bar; features A,A;", ErrorMessage.DUPLICATE_FEATURE);
}
}