/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* TypeExpr_Test.java
* Creation date: Mar 1, 2005.
* By: Joseph Wong
*/
package org.openquark.cal.compiler;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeSet;
import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.openquark.cal.CALPlatformTestModuleNames;
import org.openquark.cal.internal.serialization.RecordInputStream;
import org.openquark.cal.internal.serialization.RecordOutputStream;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.runtime.MachineType;
import org.openquark.cal.services.BasicCALServices;
import org.openquark.cal.services.CALServicesTestUtilities;
import org.openquark.cal.services.GemEntity;
import org.openquark.util.NakedByteArrayOutputStream;
/**
* A set of JUnit test cases for verifying the correctness of the type expression classes.
*
* @author Joseph Wong
*/
public class TypeExpr_Test extends TestCase {
private static final String Prelude_Boolean = CAL_Prelude.TypeConstructors.Boolean.getQualifiedName();
private static final String Prelude_Char = CAL_Prelude.TypeConstructors.Char.getQualifiedName();
private static final String Prelude_Int = CAL_Prelude.TypeConstructors.Int.getQualifiedName();
private static final String Prelude_Double = CAL_Prelude.TypeConstructors.Double.getQualifiedName();
private static final String Prelude_String = CAL_Prelude.TypeConstructors.String.getQualifiedName();
private static final String Prelude_Function = CAL_Prelude.TypeConstructors.Function.getQualifiedName();
private static final String Prelude_JObject = CAL_Prelude.TypeConstructors.JObject.getQualifiedName();
private static final String Prelude_Maybe = CAL_Prelude.TypeConstructors.Maybe.getQualifiedName();
private static final String Prelude_Either = CAL_Prelude.TypeConstructors.Either.getQualifiedName();
private static final String Prelude_Eq = CAL_Prelude.TypeClasses.Eq.getQualifiedName();
private static final String Prelude_Num = CAL_Prelude.TypeClasses.Num.getQualifiedName();
private static final String Prelude_Enum = CAL_Prelude.TypeClasses.Enum.getQualifiedName();
private static final String Prelude_Ord = CAL_Prelude.TypeClasses.Ord.getQualifiedName();
private static final String Prelude_Inputable = CAL_Prelude.TypeClasses.Inputable.getQualifiedName();
private static final String Prelude_Outputable = CAL_Prelude.TypeClasses.Outputable.getQualifiedName();
/**
* A copy of CAL services for use in the test cases.
*/
private static BasicCALServices leccCALServices;
/**
* The default module for all tests
*/
private static final ModuleName testModule = CALServicesTestUtilities.DEFAULT_UNIT_TEST_MODULE;
/**
* Set this flag to true if debugging output is desired regardless of
* whether a test fails or succeeds.
*/
private static final boolean SHOW_DEBUGGING_OUTPUT = false;
/**
* @return a test suite containing all the test cases for testing CAL source
* generation.
*/
public static Test suite() {
TestSuite suite = new TestSuite(TypeExpr_Test.class);
return new TestSetup(suite) {
protected void setUp() {
oneTimeSetUp();
}
protected void tearDown() {
oneTimeTearDown();
}
};
}
/**
* Get the type info for the testing module
* @return the test module type info
*/
private static ModuleTypeInfo getTestModuleTypeInfo() {
return leccCALServices.getCALWorkspace().getMetaModule(testModule).getTypeInfo();
}
/**
* Performs the setup for the test suite.
*/
private static void oneTimeSetUp() {
leccCALServices = CALServicesTestUtilities.getCommonCALServices(MachineType.LECC, "cal.platform.test.cws");
}
/**
* Performs the tear down for the test suite.
*/
private static void oneTimeTearDown() {
leccCALServices = null;
}
/**
* Constructor for TypeExpr_Test.
*
* @param name
* the name of the test.
*/
public TypeExpr_Test(String name) {
super(name);
}
/**
* A helper function to show that algorithms work with instantiated type variables.
* @param instanceType
* @return TypeVar
*/
private static TypeVar makeInstantiatedTypeVar(TypeExpr instanceType) {
TypeVar result = new TypeVar();
result.setInstance(instanceType);
return result;
}
private static void assertTypeArrayEquals(TypeExpr[] ta1, TypeExpr[] ta2) {
int length = ta1.length;
assertEquals(length, ta2.length);
for (int i = 0; i < length; ++i) {
assertTrue(ta1[i] == ta2[i]);
}
}
/**
* Various tests of the TypeApp class. This was introduced to support higher kinded type variables.
*
* This particular test checks that the multiple ways of encoding the type Int -> Char result in
* consistent answers for various TypeExpr api functions.
*
* It also makes some checks on an unsaturated application of Prelude.Function i.e. Function Int.
*/
public void testTypeApp1() {
TypeExpr intType = leccCALServices.getTypeFromString(testModule, Prelude_Int);
TypeExpr charType = leccCALServices.getTypeFromString(testModule, Prelude_Char);
//3 basic ways of encoding the type Int -> Char
TypeExpr intToChar1 =
new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[]{intType, charType});
TypeExpr intToChar2 =
new TypeApp(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[]{intType}), charType);
TypeExpr intToChar3 =
new TypeApp(new TypeApp(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[0]), intType), charType);
//a few more ways, with instantiated type variables
TypeExpr intToChar4 =
makeInstantiatedTypeVar(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[]{makeInstantiatedTypeVar(intType), makeInstantiatedTypeVar(charType)}));
TypeExpr intToChar5 =
makeInstantiatedTypeVar(new TypeApp(makeInstantiatedTypeVar(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[]{makeInstantiatedTypeVar(intType)})), makeInstantiatedTypeVar(charType)));
TypeExpr intToChar6 =
makeInstantiatedTypeVar(new TypeApp(makeInstantiatedTypeVar(new TypeApp(makeInstantiatedTypeVar(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[0])), makeInstantiatedTypeVar(intType))), makeInstantiatedTypeVar(charType)));
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar1.toString());
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar2.toString());
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar3.toString());
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar4.toString());
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar5.toString());
assertEquals(Prelude_Int + " -> " + Prelude_Char, intToChar6.toString());
assertEquals(1, intToChar1.getArity());
assertEquals(1, intToChar2.getArity());
assertEquals(1, intToChar3.getArity());
assertEquals(1, intToChar4.getArity());
assertEquals(1, intToChar5.getArity());
assertEquals(1, intToChar6.getArity());
assertTrue(intToChar1.isFunctionType());
assertTrue(intToChar2.isFunctionType());
assertTrue(intToChar3.isFunctionType());
assertTrue(intToChar4.isFunctionType());
assertTrue(intToChar5.isFunctionType());
assertTrue(intToChar6.isFunctionType());
TypeExpr[] intToCharPieces = new TypeExpr[] {intType, charType};
assertTypeArrayEquals(intToChar1.getTypePieces(), intToCharPieces);
assertTypeArrayEquals(intToChar2.getTypePieces(), intToCharPieces);
assertTypeArrayEquals(intToChar3.getTypePieces(), intToCharPieces);
assertTypeArrayEquals(intToChar4.getTypePieces(), intToCharPieces);
assertTypeArrayEquals(intToChar5.getTypePieces(), intToCharPieces);
assertTypeArrayEquals(intToChar6.getTypePieces(), intToCharPieces);
ModuleTypeInfo moduleTypeInfo = getTestModuleTypeInfo();
assertTrue(TypeExpr.canUnifyType(intToChar1, intToChar2, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intToChar1, intToChar3, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intToChar2, intToChar3, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intToChar4, intToChar5, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intToChar4, intToChar6, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intToChar5, intToChar6, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar1, intToChar2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar1, intToChar3, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar2, intToChar3, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar4, intToChar5, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar4, intToChar6, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar5, intToChar6, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar2, intToChar1, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar3, intToChar1, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar3, intToChar2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar5, intToChar4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar6, intToChar4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intToChar6, intToChar5, moduleTypeInfo));
//2 ways of representing the type Function Int
TypeExpr intTo1 =
new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[]{intType});
TypeExpr intTo2 =
new TypeApp(new TypeConsApp(TypeConstructor.FUNCTION, new TypeExpr[0]), intType);
assertEquals(Prelude_Function + " " + Prelude_Int, intTo1.toString());
assertEquals(Prelude_Function + " " + Prelude_Int, intTo2.toString());
assertEquals(0, intTo1.getArity());
assertEquals(0, intTo2.getArity());
assertFalse(intTo1.isFunctionType());
assertFalse(intTo2.isFunctionType());
assertTypeArrayEquals(intTo1.getTypePieces(), new TypeExpr[] {intTo1});
assertTypeArrayEquals(intTo2.getTypePieces(), new TypeExpr[] {intTo2});
assertTrue(TypeExpr.canUnifyType(intTo1, intTo2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intTo1, intTo2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intTo2, intTo1, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo1, intToChar1, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo1, intToChar2, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo1, intToChar3, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo2, intToChar1, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo2, intToChar2, moduleTypeInfo));
assertFalse(TypeExpr.canUnifyType(intTo2, intToChar3, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo1, intToChar1, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo1, intToChar2, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo1, intToChar3, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo2, intToChar1, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo2, intToChar2, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intTo2, intToChar3, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar1, intTo1, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar2, intTo2, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar3, intTo1, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar1, intTo2, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar2, intTo1, moduleTypeInfo));
assertFalse(TypeExpr.canPatternMatch(intToChar3, intTo2, moduleTypeInfo));
}
/**
* Various tests of the TypeApp class. This was introduced to support higher kinded type variables.
*
* This particular test checks that the multiple ways of encoding the type [Int] result in
* consistent answers for various TypeExpr api functions.
*/
public void testTypeApp2() {
TypeExpr intType = leccCALServices.getTypeFromString(testModule, Prelude_Int);
ModuleTypeInfo moduleTypeInfo = getTestModuleTypeInfo();
TypeConstructor listTypeCons = moduleTypeInfo.getVisibleTypeConstructor(CAL_Prelude.TypeConstructors.List);
//2 basic ways of encoding the type Int -> Char
TypeExpr intList1 =
new TypeConsApp(listTypeCons, new TypeExpr[]{intType});
TypeExpr intList2 =
new TypeApp(new TypeConsApp(listTypeCons, new TypeExpr[0]), intType);
//a few more ways, with instantiated type variables
TypeExpr intList3 =
makeInstantiatedTypeVar(new TypeConsApp(listTypeCons, new TypeExpr[]{makeInstantiatedTypeVar(intType)}));
TypeExpr intList4 =
makeInstantiatedTypeVar(new TypeApp(makeInstantiatedTypeVar(new TypeConsApp(listTypeCons, new TypeExpr[0])), makeInstantiatedTypeVar(intType)));
assertEquals("[" + Prelude_Int + "]", intList1.toString());
assertEquals("[" + Prelude_Int + "]", intList2.toString());
assertEquals("[" + Prelude_Int + "]", intList3.toString());
assertEquals("[" + Prelude_Int + "]", intList4.toString());
assertEquals(0, intList1.getArity());
assertEquals(0, intList2.getArity());
assertEquals(0, intList3.getArity());
assertEquals(0, intList4.getArity());
assertTrue(TypeExpr.canUnifyType(intList1, intList2, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intList1, intList3, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intList1, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intList2, intList3, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intList2, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canUnifyType(intList3, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList1, intList2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList1, intList3, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList1, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList2, intList3, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList2, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList3, intList4, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList2, intList1, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList3, intList1, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList4, intList1, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList3, intList2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList4, intList2, moduleTypeInfo));
assertTrue(TypeExpr.canPatternMatch(intList4, intList3, moduleTypeInfo));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match Int with Double.
*/
public void testCanPatternMatch_failureCase_Int_Double() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match Int->Double with a->a.
*
* Regression test for bug identified in changelist 60611.
*/
public void testCanPatternMatch_failureCase_Int2Double_A2A() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "a -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match Int->Double with Num a => a->a.
*/
public void testCanPatternMatch_failureCase_Int2Double_NumA2A() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Int with Int.
*/
public void testCanPatternMatch_successCase_Int_Int() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Int with Num a => a.
*/
public void testCanPatternMatch_successCase_Int_Num() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Int->Double with (Num a, Num b) => a->b.
*/
public void testCanPatternMatch_successCase_Int2Double_NumA2NumB() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Int->Int with (Num a, Num b) => a->b.
*/
public void testCanPatternMatch_successCase_Int2Int_NumA2NumB() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Int->Double with Num a => a->b.
*/
public void testCanPatternMatch_successCase_Int2Double_NumA2B() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching {#3 :: Int}->Double with {#3 :: a}->b.
*/
public void testCanPatternMatch_successCase_RecordWithIntField_RecordWithParametricField() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching (r\#3, r\foo) => {r | #3 :: Int}->Double with r\#3 => {r | #3 :: a}->b.
*/
public void testCanPatternMatch_successCase_ParametricRecordWithIntField_ParametricRecordWithParametricField() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching (r\#3, r\foo) => {r | #3 :: Int}->{r | foo :: Double} with
* (r\#3, r\foo) => {r | #3 :: a}->{r | foo :: b}.
*/
public void testCanPatternMatch_successCase_SharedBaseRecordVar() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching (r\#3, r\foo) => {r | #3 :: Int}->{r | foo :: Double} with
* itself.
*/
public void testCanPatternMatch_successCase_SharedBaseRecordVar2() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching c->c with a->b.
*/
public void testCanPatternMatch_successCase_C2C_A2B() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, "a -> b"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching Num a => a with Eq a => a.
*/
public void testCanPatternMatch_successCase_Num_Eq() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return true,
* for pattern matching [String] -> Boolean with Eq a => a -> Boolean.
*
* Regression test for bug identified in changelist 181772.
*/
public void testCanPatternMatch_successCase_ListOfString2Boolean_EqA2Boolean() {
assertTrue(TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "[" + Prelude_String + "] -> " + Prelude_Boolean),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a -> " + Prelude_Boolean),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match [JObject] -> Boolean with Eq a => a -> Boolean.
*
* Regression test for bug identified in changelist 181772.
*/
public void testCanPatternMatch_failureCase_ListOfObject2Boolean_EqA2Boolean() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "[" + Prelude_JObject + "] -> " + Prelude_Boolean),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a -> " + Prelude_Boolean),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match a\abc => {a} -> {abc :: String} with
* a\abc => {a} -> {a | abc :: String}.
*
* Regression test for bug identified in changelist 157605.
*/
public void testCanPatternMatch_failureCase_PolymorphicRecord1() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "a\\abc => {a} -> {abc :: " + Prelude_String + "}"),
leccCALServices.getTypeFromString(testModule, "a\\abc => {a} -> {a | abc :: " + Prelude_String + "}"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match r\felix => {r | felix :: a} -> {r} with
* r\felix => {r | felix :: a} -> a.
*
* Regression test for bug identified in changelist 157605.
*/
public void testCanPatternMatch_failureCase_PolymorphicRecord2() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "r\\felix => {r | felix :: a} -> {r}"),
leccCALServices.getTypeFromString(testModule, "r\\felix => {r | felix :: a} -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match r\felix => {r | felix :: a} -> Char with
* r\felix => {r | felix :: a} -> a.
*
* Regression test for bug identified in changelist 157605.
*/
public void testCanPatternMatch_failureCase_PolymorphicRecord3() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "r\\felix => {r | felix :: a} -> " + Prelude_Char),
leccCALServices.getTypeFromString(testModule, "r\\felix => {r | felix :: a} -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match [a] -> Char with [a] -> a.
*
* Regression test for bug identified in changelist 157605.
*/
public void testCanPatternMatch_failureCase_ListOfA2Char_ListOfA2A() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "[a] -> " + Prelude_Char),
leccCALServices.getTypeFromString(testModule, "[a] -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match a -> b with a -> a.
*
* Regression test for bug identified in changelist 157605.
*/
public void testCanPatternMatch_failureCase_A2B_A2A() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, "a -> a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatch() for a case where it should return false,
* for failing to pattern match (a,b) -> b with (c,d) -> c.
*
* Regression test for bug identified in changelist 62801.
*/
public void testCanPatternMatch_failureCase_TupleAB2B_TupleCD2C() {
assertTrue(!TypeExpr.canPatternMatch(
leccCALServices.getTypeFromString(testModule, "(a,b) -> b"),
leccCALServices.getTypeFromString(testModule, "(c,d) -> c"),
getTestModuleTypeInfo()));
}
/**
* Tests to make sure that a base record variable must have the proper lacks constraints.
*
* Regression test for bug identified in changelist 207861.
*/
public void testGetTypeFromString_failureCase_PolymorphicRecordMissingLacksConstraint() {
assertNull(leccCALServices.getTypeFromString(testModule, "{r | field1 :: Double}"));
}
/**
* Tests the package-scope method TypeExpr.patternMatch() for a case where it should throw
* a TypeException, for failing to pattern match [b] with a, where a is a non-generic variable.
*
* Regression test for bug identified in changelist 87040.
*
* This test case arises in real life for certain situations involving local type declarations,
* for example, in:
*
* test x =
* let
* y :: [a];
* y = x;
* in
* y;
*/
public void testPatternMatch_failureCase_nonGenericVar() {
TypeVar typeVarA = new TypeVar();
boolean caughtException = false;
try {
TypeExpr.patternMatch(
leccCALServices.getTypeFromString(testModule, "[b]"),
typeVarA,
NonGenericVars.extend(null, typeVarA),
getTestModuleTypeInfo());
} catch (TypeException e) {
caughtException = true;
}
assertTrue(caughtException);
}
/**
* Tests the package-scope method TypeExpr.patternMatch() for a case where it should throw
* a TypeException, for failing to pattern match a base record variable with a non-generic
* variable.
*
* Regression test for bug identified in changelist 248484.
*
* This test case arises in real life for certain situations involving local type declarations,
* for example, in:
*
* gb s =
* let
* y :: (r\#1, r\#2) => {r | #1 :: Prelude.Double, #2 :: Prelude.Char};
* y = {s | #1 = 10.0, #2 = 'y'};
* in
* y;
*/
public void testPatternMatch_failureCase_nonGenericVar_Record() {
HashSet<FieldName> lacksSet = new HashSet<FieldName>();
lacksSet.add(FieldName.makeOrdinalField(1));
lacksSet.add(FieldName.makeOrdinalField(2));
RecordVar lacks12 = RecordVar.makeRecordVar(null, lacksSet, new TreeSet<TypeClass>(), false);
RecordVar recordVar = RecordVar.makePolymorphicRecordVar(null);
recordVar.setInstance(new RecordType(lacks12, Collections.<FieldName, TypeExpr>emptyMap()));
TypeVar typeVar = new TypeVar();
RecordType recordType = new RecordType(recordVar, Collections.<FieldName, TypeExpr>emptyMap());
typeVar.setInstance(recordType);
RecordVar inferredRecordVar = RecordVar.makePolymorphicRecordVar(null);
inferredRecordVar.setInstance(recordType);
HashMap<FieldName, TypeExpr> fieldsMap = new HashMap<FieldName, TypeExpr>();
fieldsMap.put(FieldName.makeOrdinalField(1), leccCALServices.getTypeFromString(testModule, Prelude_Double));
fieldsMap.put(FieldName.makeOrdinalField(2), leccCALServices.getTypeFromString(testModule, Prelude_Char));
RecordType inferredType = new RecordType(inferredRecordVar, fieldsMap);
boolean caughtException = false;
try {
TypeExpr.patternMatch(
leccCALServices.getTypeFromString(testModule, "(a\\#1, a\\#2) => {a | #1 :: " + Prelude_Double + ", #2 :: " + Prelude_Char + "}"),
inferredType,
NonGenericVars.extend(null, typeVar),
getTestModuleTypeInfo());
} catch (TypeException e) {
caughtException = true;
}
assertTrue(caughtException);
}
/**
* Tests the method TypeExpr.canPatternMatchPieces() for a case where it should return false,
* for failing to pattern match Int->Double with Num a => a->a.
*/
public void testCanPatternMatchPieces_failureCase_Int2Double_NumA2A() {
assertTrue(!TypeExpr.canPatternMatchPieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double)
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> a")
},
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatchPieces() for a case where it should return true,
* for pattern matching two arrays of types that can be pattern-matched componentwise.
*/
public void testCanPatternMatchPieces_successCase() {
assertTrue(TypeExpr.canPatternMatchPieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a")
},
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatchPieces() for a case where it should return true,
* for a case where there is a null value in the first argument array.
*/
public void testCanPatternMatchPieces_successCase_nullValueInFirstArgumentArray() {
// (null values are accepted in the first argument array)
assertTrue(TypeExpr.canPatternMatchPieces(
new TypeExpr[] { null },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canPatternMatchPieces() for a case where it should return true,
* for a case where the second argument array is longer than the first argument array.
*/
public void testCanPatternMatchPieces_successCase_secondArgumentArrayLonger() {
// (the second argument array can be longer than the first argument array)
assertTrue(TypeExpr.canPatternMatchPieces(
new TypeExpr[] { },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return false,
* for failing to unify Int with Double.
*/
public void testCanUnifyType_failureCase_Int_Double() {
assertTrue(!TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return false,
* for failing to unify Num a => a->a with Int->Double.
*/
public void testCanUnifyType_failureCase_NumA2A_Int2Double() {
assertTrue(!TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> a"),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying Num a => a with Int.
*/
public void testCanUnifyType_successCase_NumA_Int() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, Prelude_Int),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying (Num a, Num b) => a->b with Int->Double.
*/
public void testCanUnifyType_successCase_NumA2NumB_Int2Double() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying (Num a, Num b) => a->b with Int->Int.
*/
public void testCanUnifyType_successCase_NumA2NumB_Int2Int() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying Num a => a->b with Int->Double.
*/
public void testCanUnifyType_successCase_NumA2B_Int2Double() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying {#3 :: a}->b with {#3 :: Int}->Double .
*/
public void testCanUnifyType_successCase_RecordWithParametricField_RecordWithIntField() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying r\#3 => {r | #3 :: a}->b with (r\#3, r\foo) => {r | #3 :: Int}->Double.
*/
public void testCanUnifyType_successCase_ParametricRecordWithParametricField_ParametricRecordWithIntField() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying (r\#3, r\foo) => {r | #3 :: a}->{r | foo :: b} with
* (r\#3, r\foo) => {r | #3 :: Int}->{r | foo :: Double}.
*/
public void testCanUnifyType_successCase_SharedBaseRecordVar() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying (r\#3, r\foo) => {r | #3 :: Int}->{r | foo :: Double} with
* itself.
*/
public void testCanUnifyType_successCase_SharedBaseRecordVar2() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying a->b with c->c.
*/
public void testCanUnifyType_successCase_A2B_C2C() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return true,
* for unifying Eq a => a with Num a => a.
*/
public void testCanUnifyType_successCase_Eq_Num() {
assertTrue(TypeExpr.canUnifyType(
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyType() for a case where it should return false,
* for failing to unify (a, Int) with (Char, a).
*
* Regression test for bug identified in changelist 115495.
*/
public void testCanUnifyType_failureCase_TupleAInt_TupleCharA() {
TypeExpr typeVarA = TypeExpr.makeParametricType();
assertTrue(!TypeExpr.canUnifyType(
TypeExpr.makeFunType(typeVarA, leccCALServices.getTypeFromString(testModule, Prelude_Int)),
TypeExpr.makeFunType(leccCALServices.getTypeFromString(testModule, Prelude_Char), typeVarA),
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyTypePieces() for a case where it should return false,
* for failing to unify (a, Int) with (Char, a).
*/
public void testCanUnifyTypePieces_failureCase_TupleAInt_TupleCharA() {
TypeExpr typeVarA = TypeExpr.makeParametricType();
assertTrue(!TypeExpr.canUnifyTypePieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
TypeExpr.makeFunType(typeVarA, leccCALServices.getTypeFromString(testModule, Prelude_Int)),
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
TypeExpr.makeFunType(leccCALServices.getTypeFromString(testModule, Prelude_Char), typeVarA),
},
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyTypePieces() for a case where it should return true,
* for unifying two arrays of types that are componentwise unifyable.
*/
public void testCanUnifyTypePieces_successCase() {
assertTrue(TypeExpr.canUnifyTypePieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a")
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
},
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyTypePieces() for a case where it should return true,
* for a case where there is a null value in the first argument array.
*/
public void testCanUnifyTypePieces_successCase_nullValueInFirstArgumentArray() {
assertTrue(TypeExpr.canUnifyTypePieces(
new TypeExpr[] { null },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.canUnifyTypePieces() for a case where it should return true,
* for a case where the second argument array is longer than the first argument array.
*/
public void testCanUnifyTypePieces_successCase_secondArgumentArrayLonger() {
assertTrue(TypeExpr.canUnifyTypePieces(
new TypeExpr[] { },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo()));
}
/**
* Helper function for the type closeness tests.
*
* @param typeStr1 Type signature string
* @param typeStr2 Type signature string
* @return The type closeness of the two types
*/
private static int typeCloseness(String typeStr1, String typeStr2) {
return TypeExpr.getTypeCloseness(
leccCALServices.getTypeFromString(testModule, typeStr1),
leccCALServices.getTypeFromString(testModule, typeStr2),
getTestModuleTypeInfo());
}
/**
* Helper function for type closeness tests. Asserts that type closeness of
* typeStr1's type to typeStr2's type is assertedCloseness, and then asserts that
* the type closeness of typeStr2's type to typeStr1's type is also assertedCloseness.
* This provides a convenient way for us to verify the reflexivity of type closeness
* at the same time as we verify other properties of the type closeness heuristic.
*
* @param typeStr1 Type signature string
* @param typeStr2 Type signature string
* @param assertedCloseness Asserted value of typecloseness of typeStr1's type to
* typeStr2's type (and vice versa).
*/
private static void assertTypeCloseness(String typeStr1, String typeStr2, int assertedCloseness) {
assertEquals(assertedCloseness, typeCloseness(typeStr1, typeStr2));
assertEquals(assertedCloseness, typeCloseness(typeStr2, typeStr1));
}
/**
* Tests the method TypeExpr.getTypeCloseness() for a case where the types can
* be unified.
*/
public void testGetTypeCloseness_Unifyable_NumA_Int() {
assertTrue(typeCloseness(Prelude_Num + " a => a", Prelude_Int) >= 0);
assertTrue(typeCloseness(Prelude_Int, Prelude_Num + " a => a") >= 0);
}
/**
* Tests the method TypeExpr.getTypeCloseness() for a case where the types can
* not be unified.
*/
public void testGetTypeCloseness_NotUnifyable_NumA_String() {
assertTrue(typeCloseness(Prelude_Num + " a => a", Prelude_String) < 0);
assertTrue(typeCloseness(Prelude_String, Prelude_Num + " a => a") < 0);
}
/**
* Tests the method TypeExpr.getTypeCloseness() for a case where the types can
* be unified because the first argument is an unconstrained type variable.
*/
public void testGetTypeCloseness_Unifyable_A_Int() {
assertTrue(typeCloseness("a", Prelude_Int) >= 0);
assertTrue(typeCloseness(Prelude_Int, "a") >= 0);
}
/**
* Tests the method TypeExpr.getTypeCloseness() for returning a measure of
* type closeness. In this test, the pair of types [Num a => a, Int] is closer
* to each other than the pair [a, Int], and getTypeCloseness() should therefore
* return a higher value for the former pair than the value returned for the latter
* pair.
*/
public void testGetTypeCloseness_RelativeComparison() {
assertTrue(typeCloseness(Prelude_Num + " a => a", Prelude_Int) >
typeCloseness("a", Prelude_Int));
assertTrue(typeCloseness(Prelude_Int, Prelude_Num + " a => a") >
typeCloseness(Prelude_Int, "a"));
}
/**
* Verifies that the type closeness heuristic gives the specific numeric values
* that we expect.
*
* The intuition behind the heuristic is that it represents how many "coincidences"
* there are between two types. So every time we encounter two things that are the
* same without being totally uninstantiated type variables, we add a point.
*
* The current heuristic gives 1 point for each time it matches:
*
* - a type constructor
* - a record type
* - a record field name that was present in both "original" types
*
* to something other than an uninstantiated variable.
*
* There are a couple of subtleties here:
*
* 1. Matching a constrained type variable to a type that meets the contraint
* is just as good as matching the type itself. So for example the type
* closeness of "Int" to "Num a => a" is 1, just like the closeness of
* "Int" to "Int".
* 2. Variables are instantiated as the type closeness check proceeds. For
* example, the type closeness of "a -> a" to "Int -> Int" is 2:
* - 1 point for matching "->" type constructor
* - 0 points for matching first a to first Int, since a is uninstantiated
* - 1 point for matching second a to second Int, because by that point a
* has been instantiated to Int.
* 3. Field types (in records) are sometimes matched against intermediate types,
* but field names are only matched against original types. For example,
* when calculating the closeness of "Eq a => a" to "{x :: Int, y :: Char}",
* the type closeness is 3:
* - First we replace "Eq a => a" with the intermediate type
* "(Eq b, Eq c) => {x :: b, y :: c}"
* - 1 point for matching record types
* - 1 point for matching type "Eq b => b" to Int
* - 1 point for matching type "Eq c => c" to Char
* - 0 points for matching field names (x and y), because the field names
* were not present in both original types
*/
public void testGetTypeCloseness_ExpectedValues() {
// 0 points for matching Int to a, because a is uninstantiated
assertTypeCloseness("Int", "a", 0);
// 0 points for matching Num a => a to b, because b is uninstantiated
assertTypeCloseness("Num a => a", "b", 0);
// 1 point for matching Int to Int
assertTypeCloseness("Int", "Int", 1);
// 0 points for matching Num a => a to Enum a => a, because neither class is
// a superclass of the other.
assertTypeCloseness("Num a => a", "Enum a => a", 0);
// 1 point for matching Int to a class that it is an instance of
assertTypeCloseness("Num a => a", "Int", 1);
assertTypeCloseness("Ord a => a", "Int", 1);
// 1 point for matching Num a => a to Num b => b, because Num b => b is an
// instance of Num a no matter what Num type we pick for it.
assertTypeCloseness("Num a => a", "Num b => b", 1);
// 1 point for matching Int to any number of classes that it is an instance of
assertTypeCloseness("(Enum a, Num a) => a", "Int", 1);
// 1 point for matching one type class to another that it is a superclass of
assertTypeCloseness("Num a => a", "Ord a => a", 1);
// 0 points for matching record with uninstantiated variable
assertTypeCloseness("{x :: Double, y :: String}", "a", 0);
assertTypeCloseness("{x :: a, y :: b}", "c", 0);
// 1 point for matching record type
assertTypeCloseness("{x :: Double, y :: String}", "{a}", 1);
assertTypeCloseness("{x :: a, y :: b}", "{c}", 1);
// 1 point for matching record type, 1 for each field name
assertTypeCloseness("{x :: Int, y :: String}", "{x :: c, y :: d}", 3);
assertTypeCloseness("{x :: a, y :: b}", "{x :: c, y :: d}", 3);
// 1 point for matching record type, 1 for each field name, 1 for each field type
assertTypeCloseness("{x :: Double, y :: Double}", "(a\\x, a\\y) => {a | x :: Double, y :: Double}", 5);
// 1 point for matching record type, 1 for each field name, 1 for matching x field type, 0 for matching y field type
assertTypeCloseness("{x :: Double, y :: Double}", "(a\\x, a\\y) => {a | x :: Double, y :: a}", 4);
// 1 point for matching record type, 1 for field name x, 1 for matching x field type
assertTypeCloseness("{x :: Double, y :: Double}", "(a\\x) => {a | x :: Double}", 3);
// 1 point for matching record type, 1 for field name x
assertTypeCloseness("{x :: Double, y :: Double}", "(a\\x) => {a | x :: b}", 2);
assertTypeCloseness("{x :: a, y :: b}", "(c\\x) => {c | x :: d}", 2);
// 1 point for matching record type, 1 for field name x, 1 for matching x type (Num b => b with Double)
assertTypeCloseness("{x :: Double, y :: Double}", "(a\\x, Num b) => {a | x :: b}", 3);
// 1 point for matching record type
assertTypeCloseness("{x :: Double, y :: Double}", "{a}", 1);
// Right-hand record is expanded to have x and y fields with Eq types.
// 1 point for matching record type, 1 point each for matching Int and String to Eq
// 0 points for the field names; only field names that match before unification are given a point.
assertTypeCloseness("{x :: Int, y :: String}" , "Eq a => {a}", 3);
// a gets instantiated to (Eq b, Eq c) => {x :: b, y :: c}, at which point we give
// 1 point for matching record type, 1 point each for matching Int and String
// 0 points for the field names; only field names that are present in the original type (rather than the intermediate
// constructed type) are given a point.
assertTypeCloseness("{x :: Int, y :: String}" , "Eq a => a", 3);
// Right-hand record is expanded to have x and y fields with Eq types.
// 1 point for matching record type, 0 points for matching a and b (since they are uninistantiated and unconstrained)
// 0 points for the field names; only field names that are present in the original type (rather than the intermediate
// constructed type) are given a point.
assertTypeCloseness("{x :: a, y :: b}" , "Eq c => {c}", 1);
// c gets instantiated to (Eq b, Eq c) => {x :: b, y :: c}, at which point we give
// 1 point for matching record type, 0 points for matching a and b (since they are uninistantiated and unconstrained)
// 0 points for the field names; only field names that are present in the original type (rather than the intermediate
// constructed type) are given a point.
assertTypeCloseness("{x :: a, y :: b}" , "Eq c => c", 1);
// b is instantiated to (Ord c) => {c}, at which point we give
// 1 point for matching record type, one point for matching Ord c to Eq a (Ord is a subclass of Eq)
assertTypeCloseness("Eq a => {a}", "Ord b => b", 2);
// b is instantiated to Typeable c => {c}, at which point we give
// 1 point for matching record type, 0 points for matching Ord a with Typeable c (Ord and Typeable are unrelated)
assertTypeCloseness("Ord a => {a}", "Typeable b => b", 1);
// 1 point for matching record type, 0 points for matching Ord a with Typeable b (Ord and Typeable are unrelated)
assertTypeCloseness("Ord a => {a}", "Typeable b => {b}", 1);
// 1 point for matching function type
assertTypeCloseness("a->b", "c->d", 1);
// 1 point for matching function type
// Note that the first a and b are not the same type variable as the second a and b, even though they use the same letters).
assertTypeCloseness("a->b", "a->b", 1);
// 1 point for matching function type, 1 point for matching second b (which has been instantiated to a)
assertTypeCloseness("a->a", "b->b", 2);
// a in second type is not the same a as in the first type. Referring to second a as a':
// 1 point for matching function type, 1 point for matching second a' (which has been instantiated to a)
assertTypeCloseness("a->a", "a->a", 2);
// 2 points for matching function types, 1 point for matching second and third b (which have been instantiated a)
assertTypeCloseness("a->a->a", "b->b->b", 4);
// This used to be 1 when tuples were a distinct type constructor from records. We'd give 1
// point for the Tuple3 type constructor matching.
// Now that tuples are a special case of records, we also give 1 point each for matching
// the field names (#1, #2, #3), so the expected value is 4.
assertTypeCloseness("(a,b,c)", "(d,e,f)", 4);
// 1 point for matching record type, 1 point for matching each field name (#1,#2,#3), and 1 point
// for matching second e (which has been instantiated to b)
assertTypeCloseness("(a,b,b)", "(d,e,e)", 5);
// 1 point for matching record type, one point for each field name (#1,#2,#3), and 3 points for
// matching second b (which has been instantiated to Char->String) to Char->String (1 point for
// matching function type, 1 for Char, and 1 for String).
assertTypeCloseness("(a,b,b)", "(Int,Char->String,Char->String)", 7);
// 1 point for matching record type, one point for each field name (#1,#2,#3), 2 points for
// matching function types on last 2 elements, 1 point for matching second b (which has been
// instantiated to Char), 1 point for matching second c (which has been instantiated to c).
assertTypeCloseness("(a,b->c,b->c)", "(Int,Char->String,Char->String)", 8);
// 1 point for matching record type, 1 point for matching outer field names (#1,#2), 1 point
// for matching record type of second element, 1 point for each of the second element's
// field names (#1,#2).
assertTypeCloseness("(a,(b,c))", "(Int, (Char,Char))", 6);
// a gets expanded into (Eq b, Eq c) => (b,c) at which point we give
// 1 point for matching record type, 1 point each for matching Int and Char to Eq
// 0 points for the field names; only field names that match before unification are given a point.
assertTypeCloseness("(Int,Char)", "Eq a => a", 3);
// a gets expanded into (Eq b, Eq c, d) => (b,c,d) at which point we give
// 1 point for matching record type, 1 point each for matching Int, String, and Char to Eq
// 0 points for the field names; only field names that match before unification are given a point.
assertTypeCloseness("(Int,String,Char)", "Eq a => a", 4);
// 1 point for matching record types, 1 point each for matching Int and Char to Eq,
// 1 point each for field names (#1, #2) since they are both present in original type signature.
assertTypeCloseness("(Int,Char)", "(Eq a, Eq b) => (a,b)", 5);
// 1 point for matching record types, 1 point each for matching Int and Char to Eq,
// 1 point each for field names (#1, #2, #3) since they are both present in original type signature.
assertTypeCloseness("(Int,String,Char)", "(Eq a, Eq b, Eq c) => (a,b,c)", 7);
// a is uninstantiated, so no points
assertTypeCloseness("Maybe Int", "a", 0);
// 1 point for matching Maybe
assertTypeCloseness("Maybe Int", "Maybe a", 1);
// 1 point for matching Maybe, 1 point for matching Int
assertTypeCloseness("Maybe Int", "Maybe Int", 2);
// 1 point for matching Either
assertTypeCloseness("Either Int Int", "Either a b", 1);
// 1 point for matching Either, 1 point for matching second a (instantiated to Int)
assertTypeCloseness("Either Int Int", "Either a a", 2);
// 1 point for matching Either, 1 point each for matching Int to Num a => a
assertTypeCloseness("Either Int Int", "Num a => Either a a", 3);
// 1 point for matching Either, 1 point for matching Int to Num a => a, 1 point for matching Int to Int
assertTypeCloseness("Either Int Int", "Num a => Either a Int", 3);
// 1 point for matching Either, 1 point for matching Int to Int
assertTypeCloseness("Either Int Int", "Either a Int", 2);
// a gets expanded to (Eq b,c) => Either b c, at which point we give
// 1 point for matching Either, 1 point for matching Eq b to Int, 1 point for matching Eq c to Char
assertTypeCloseness("Either Int Char", "Eq a => a", 3);
}
/**
* Test that we treat coincidences in name (ie, two signatures happen to use the variable 'a'
* even though they don't mean the same a) differently from variables that are actually the
* same (ie, two signatures use the variable 'a' because they really mean the variable 'a') for
* the purposes of type closeness calculations.
*/
public void testGetTypeCloseness_RelatedTypeVariables() {
TypeExpr a = TypeExpr.makeParametricType();
TypeExpr aToa = TypeExpr.makeFunType(a, a);
TypeExpr bTob = aToa.copyTypeExpr();
assertEquals(3, TypeExpr.getTypeCloseness(aToa, aToa, getTestModuleTypeInfo()));
assertEquals(2, TypeExpr.getTypeCloseness(aToa, bTob, getTestModuleTypeInfo()));
}
/**
* Tests the method TypeExpr.makeFunType().
*/
public void testMakeFunType() {
TypeExpr typeDomain = leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Outputable + " a) => " + Prelude_Maybe + " a -> a");
TypeExpr typeCodomain = leccCALServices.getTypeFromString(testModule, "(" + Prelude_Eq + " a, " + Prelude_Outputable + " a) => a -> " + Prelude_Maybe + " a");
TypeExpr typeFun = TypeExpr.makeFunType(typeDomain, typeCodomain);
assertEquals(typeFun.toString(), "(" + Prelude_Num + " a, " + Prelude_Outputable + " a, " + Prelude_Eq + " b, " + Prelude_Outputable + " b) => (" + Prelude_Maybe + " a -> a) -> b -> " + Prelude_Maybe + " b");
}
/**
* Tests the method PreludeTypeConstants.makeListType() for an unconstrained element type.
*/
public void testMakeListType_UnconstrainedElementType() {
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
TypeExpr typeListInt = leccCALServices.getPreludeTypeConstants().makeListType(typeInt);
assertEquals(typeListInt.toString(), "[" + Prelude_Int + "]");
}
/**
* Tests the method PreludeTypeConstants.makeListType() for a constrained element type.
*/
public void testMakeListType_ConstrainedElementType() {
TypeExpr typeComplexElement = leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Outputable + " a) => " + Prelude_Maybe + " a -> a");
TypeExpr typeListOfComplexElements = leccCALServices.getPreludeTypeConstants().makeListType(typeComplexElement);
assertEquals(typeListOfComplexElements.toString(), "(" + Prelude_Num + " a, " + Prelude_Outputable + " a) => [" + Prelude_Maybe + " a -> a]");
}
/**
* Tests the method TypeExpr.makeNonParametricType().
*/
public void testMakeNonParametricType() {
TypeConstructor intEntity = leccCALServices.getTypeFromString(testModule, Prelude_Int).rootTypeConsApp().getRoot();
TypeExpr typeInt = TypeExpr.makeNonParametricType(intEntity);
assertEquals(typeInt.toString(), Prelude_Int);
}
/**
* Tests the creation of a non-parametric algebraic type.
*/
public void testNonParametricAlgebraicType() {
TypeExpr typeMaybeInt = leccCALServices.getTypeFromString(testModule, Prelude_Maybe + " " + Prelude_Int);
assertEquals(typeMaybeInt.toString(), Prelude_Maybe + " " + Prelude_Int);
}
/**
* Tests the method TypeExpr.makeParametricType().
*/
public void testMakeParametricType() {
TypeExpr typeA = TypeExpr.makeParametricType();
assertEquals(typeA.toString(), "a");
}
/**
* Tests the creation of a parametric algebraic type.
*/
public void testParametricAlgebraicType() {
TypeExpr typeMaybeA = leccCALServices.getTypeFromString(testModule, Prelude_Maybe + " a");
assertEquals(typeMaybeA.toString(), Prelude_Maybe + " a");
}
/**
* Tests the method TypeExpr.makeTupleDataConsType().
*/
public void testMakeTupleDataConsType() {
TypeExpr typeTuple3 = TypeExpr.makeTupleDataConsType(3);
assertEquals(typeTuple3.toString(), "a -> b -> c -> (a, b, c)");
}
/**
* Tests the method TypeExpr.makeTupleType(int).
*/
public void testMakeTupleType_int() {
TypeExpr type3Tuple = TypeExpr.makeTupleType(3);
assertEquals(type3Tuple.toString(), "(a, b, c)");
}
/**
* Tests the method TypeExpr.makeTupleType(List).
*/
public void testMakeTupleType_List() {
TypeExpr type1 = leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]");
TypeExpr type2 = leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]");
TypeExpr type3 = leccCALServices.getTypeFromString(testModule, Prelude_Either + " (" + Prelude_Either + " a b) " + Prelude_Int);
TypeExpr type3Tuple = TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {type1, type2, type3}));
assertEquals(type3Tuple.toString(), "(" + Prelude_Num + " a, " + Prelude_Num + " b) => ([a], [b], " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ")");
}
/**
* Tests the method TypeExpr.makeFreeRecordType().
*/
public void testMakeFreeRecordType() {
TypeExpr typeFreeRecord = TypeExpr.makeFreeRecordType(new HashSet<FieldName>(Arrays.asList(new FieldName[] {
FieldName.makeTextualField("a"), FieldName.makeOrdinalField(5), FieldName.makeTextualField("b"), FieldName.makeOrdinalField(3)})));
assertEquals(typeFreeRecord.toString(), "(a\\#3, a\\#5, a\\a, a\\b) => {a | #3 :: b, #5 :: c, a :: d, b :: e}");
}
/**
* Tests the method TypeExpr.makePolymorphicRecordType().
*/
public void testMakePolymorphicRecordType() {
Map<FieldName, TypeExpr> fieldNameToTypeMap = new HashMap<FieldName, TypeExpr>();
fieldNameToTypeMap.put(FieldName.makeTextualField("a"), leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]"));
fieldNameToTypeMap.put(FieldName.makeOrdinalField(5), leccCALServices.getTypeFromString(testModule, Prelude_Either + " (" + Prelude_Either + " a b) " + Prelude_Int));
fieldNameToTypeMap.put(FieldName.makeTextualField("b"), leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]"));
fieldNameToTypeMap.put(FieldName.makeOrdinalField(3), TypeExpr.makeParametricType());
TypeExpr typePolymorphicRecord = TypeExpr.makePolymorphicRecordType(fieldNameToTypeMap);
assertEquals(typePolymorphicRecord.toString(), "(a\\#3, a\\#5, a\\a, a\\b, " + Prelude_Num + " e, " + Prelude_Num + " f) => {a | #3 :: b, #5 :: " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ", a :: [e], b :: [f]}");
}
/**
* Tests the method TypeExpr.makePolymorphicRecordType() when the argument is an empty map.
*/
public void testMakePolymorphicRecordType_EmptyMapArgument() {
assertEquals(TypeExpr.makePolymorphicRecordType(Collections.<FieldName, TypeExpr>emptyMap()).toString(), "{a}");
}
/**
* Tests the method TypeExpr.makeNonPolymorphicRecordType().
*/
public void testMakeNonPolymorphicRecordType() {
Map<FieldName, TypeExpr> fieldNameToTypeMap = new HashMap<FieldName, TypeExpr>();
fieldNameToTypeMap.put(FieldName.makeTextualField("a"), leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]"));
fieldNameToTypeMap.put(FieldName.makeOrdinalField(5), leccCALServices.getTypeFromString(testModule, Prelude_Either + " (" + Prelude_Either + " a b) " + Prelude_Int));
fieldNameToTypeMap.put(FieldName.makeTextualField("b"), leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => [a]"));
fieldNameToTypeMap.put(FieldName.makeOrdinalField(3), leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b -> a -> b"));
TypeExpr typeNonPolymorphicRecord = TypeExpr.makeNonPolymorphicRecordType(fieldNameToTypeMap);
assertEquals(typeNonPolymorphicRecord.toString(), "(" + Prelude_Num + " a, " + Prelude_Num + " b, " + Prelude_Num + " e, " + Prelude_Num + " f) => {#3 :: a -> b -> a -> b, #5 :: " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ", a :: [e], b :: [f]}");
}
/**
* Tests the method TypeExpr.makeNonPolymorphicRecordType() when the argument is an empty map.
*/
public void testMakeNonPolymorphicRecordType_EmptyMapArgument() {
assertEquals(TypeExpr.makeNonPolymorphicRecordType(Collections.<FieldName, TypeExpr>emptyMap()).toString(), "{}");
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of type variables
* that appear in more than one element of one/both of the argument arrays. This test
* case's intent is to verify that:
*
* patternMatchPieces([Int->Double, a, (a, Double, Boolean)], [a->b, a, (a, b, c)])
* = [Int->Double, Int, (Int, Double, Boolean)]
*/
public void testPatternMatchPieces_successCase_Int2Double_A_TupleADoubleBoolean__A2B_A_TupleABC() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeVarB = TypeExpr.makeParametricType();
TypeExpr typeVarC = TypeExpr.makeParametricType();
TypeExpr typeBoolean = leccCALServices.getTypeFromString(testModule, Prelude_Boolean);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
TypeExpr typeDouble = leccCALServices.getTypeFromString(testModule, Prelude_Double);
assertEquals(
Arrays.asList(
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeDouble),
typeInt,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeInt, typeDouble, typeBoolean}))
}).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeDouble),
typeVarA,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeVarA, typeDouble, typeBoolean}))
},
new TypeExpr[] {
TypeExpr.makeFunType(typeVarA, typeVarB),
typeVarA,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeVarA, typeVarB, typeVarC}))
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of type variables
* that appear in more than one element of one/both of the argument arrays, and also
* for its handling of the second argument array being longer than the first. This test
* case's intent is to verify that:
*
* patternMatchPieces([Int], [a, a->Char]) = [Int, Int->Char]
*/
public void testPatternMatchPieces_successCase_Int__A_A2Char() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeChar = leccCALServices.getTypeFromString(testModule, Prelude_Char);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
assertEquals(
Arrays.asList(
new TypeExpr[] {
typeInt,
TypeExpr.makeFunType(typeInt, typeChar)
}).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] {
typeInt,
},
new TypeExpr[] {
typeVarA,
TypeExpr.makeFunType(typeVarA, typeChar)
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of type variables
* that appear in more than one element of one/both of the argument arrays, and also
* for its handling of the second argument array being longer than the first. This test
* case's intent is to verify that:
*
* patternMatchPieces([c->c], [a->b, [a->b]]) = [d->d, [d->d]]
*/
public void testPatternMatchPieces_successCase_C2C__A2B_ListOfA2B() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeVarB = TypeExpr.makeParametricType();
TypeExpr typeVarC = TypeExpr.makeParametricType();
TypeExpr typeVarD = TypeExpr.makeParametricType();
assertEquals(
Arrays.asList(
new TypeExpr[] {
TypeExpr.makeFunType(typeVarD, typeVarD),
leccCALServices.getPreludeTypeConstants().makeListType(TypeExpr.makeFunType(typeVarD, typeVarD))
}).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] {
TypeExpr.makeFunType(typeVarC, typeVarC),
},
new TypeExpr[] {
TypeExpr.makeFunType(typeVarA, typeVarB),
leccCALServices.getPreludeTypeConstants().makeListType(TypeExpr.makeFunType(typeVarA, typeVarB))
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of type variables
* that appear in more than one element of one/both of the argument arrays, and also
* for its handling of first argument array containing null values. This test
* case's intent is to verify that:
*
* patternMatchPieces([null, Int], [a->Char, a]) = [Int->Char, Int]
*/
public void testPatternMatchPieces_successCase_Null_Int__A2Char_A() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeChar = leccCALServices.getTypeFromString(testModule, Prelude_Char);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
assertEquals(
Arrays.asList(
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeChar),
typeInt
}).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] {
null,
typeInt
},
new TypeExpr[] {
TypeExpr.makeFunType(typeVarA, typeChar),
typeVarA
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for pattern matching
* two arrays of types that can be pattern-matched componentwise.
*/
public void testPatternMatchPieces_successCase_Simple() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
}).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a")
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of first argument
* array containing null values.
*/
public void testPatternMatchPieces_nullValueInFirstArgumentArray() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") }).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] { null },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for its handling of the second
* argument array being longer than the first.
*/
public void testPatternMatchPieces_successCase_secondArgumentArrayLonger() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") }).toString(),
Arrays.asList(TypeExpr.patternMatchPieces(
new TypeExpr[] { },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.patternMatchPieces() for throwing a TypeException on
* failing to pattern-match Int->Double with Num a => a->a.
*/
public void testPatternMatchPieces_failureCase_Int2Double_NumA2A() {
boolean exceptionCaught = false;
try {
TypeExpr.patternMatchPieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double)
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> a")
},
getTestModuleTypeInfo());
} catch (TypeException e) {
exceptionCaught = true;
}
assertTrue(exceptionCaught);
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its handling of type variables
* that appear in more than one element of one/both of the argument arrays. This test
* case's intent is to verify that:
*
* unifyTypePieces([a->b, a, (a, b, Boolean)], [Int->Double, a, (a, c, d)])
* = [Int->Double, Int, (Int, Double, Boolean)]
*/
public void testUnifyTypePieces_successCase_A2B_A_TupleABBoolean__Int2Double_A_TupleACD() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeVarB = TypeExpr.makeParametricType();
TypeExpr typeVarC = TypeExpr.makeParametricType();
TypeExpr typeVarD = TypeExpr.makeParametricType();
TypeExpr typeBoolean = leccCALServices.getTypeFromString(testModule, Prelude_Boolean);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
TypeExpr typeDouble = leccCALServices.getTypeFromString(testModule, Prelude_Double);
assertEquals(
Arrays.asList(
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeDouble),
typeInt,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeInt, typeDouble, typeBoolean}))
}).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] {
TypeExpr.makeFunType(typeVarA, typeVarB),
typeVarA,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeVarA, typeVarB, typeBoolean}))
},
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeDouble),
typeVarA,
TypeExpr.makeTupleType(Arrays.asList(new TypeExpr[] {typeVarA, typeVarC, typeVarD}))
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its handling of type variables that
* are shared between the two arguments, and also for its handling of the second argument
* array being longer than the first. This test case's intent is to verify that:
*
* unifyTypePieces([a], [Int, a->Char]) = [Int, Int->Char]
*/
public void testUnifyTypePieces_successCase_A__Int_A2Char() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeChar = leccCALServices.getTypeFromString(testModule, Prelude_Char);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
assertEquals(
Arrays.asList(
new TypeExpr[] {
typeInt,
TypeExpr.makeFunType(typeInt, typeChar)
}).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] {
typeVarA,
},
new TypeExpr[] {
typeInt,
TypeExpr.makeFunType(typeVarA, typeChar)
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its handling of type variables that
* are shared between the two arguments, and also for its handling of first argument array
* containing null values. This test case's intent is to verify that:
*
* unifyTypePieces([null, a], [a->Char, Int]) = [Int->Char, Int]
*/
public void testUnifyTypePieces_successCase_Null_A__A2Char_Int() throws TypeException {
TypeExpr typeVarA = TypeExpr.makeParametricType();
TypeExpr typeChar = leccCALServices.getTypeFromString(testModule, Prelude_Char);
TypeExpr typeInt = leccCALServices.getTypeFromString(testModule, Prelude_Int);
assertEquals(
Arrays.asList(
new TypeExpr[] {
TypeExpr.makeFunType(typeInt, typeChar),
typeInt
}).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] {
null,
typeVarA
},
new TypeExpr[] {
TypeExpr.makeFunType(typeVarA, typeChar),
typeInt
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for unifying
* two arrays of types that are componentwise unifyable.
*/
public void testUnifyTypePieces_successCase_Simple() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
}).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a -> b"),
leccCALServices.getTypeFromString(testModule, "{#3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "r\\#3 => {r | #3 :: a} -> b"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: a} -> {r | foo :: b}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "a -> b"),
leccCALServices.getTypeFromString(testModule, Prelude_Eq + " a => a")
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "{#3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> " + Prelude_Double),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "(r\\#3, r\\foo) => {r | #3 :: " + Prelude_Int + "} -> {r | foo :: " + Prelude_Double + "}"),
leccCALServices.getTypeFromString(testModule, "c -> c"),
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a")
},
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its handling of first argument
* array containing null values.
*/
public void testUnifyTypePieces_successCase_nullValueInFirstArgumentArray() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") }).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] { null },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its handling of the second
* argument array being longer than the first.
*/
public void testUnifyTypePieces_successCase_secondArgumentArrayLonger() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") }).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] { },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for its of 2 uninstantiated constrained type
* variables, one appearing in the first argument, and the other in the second argument. In
* particular, we check that Enum a => a and Num a => a unify to (Enum a, Num a) => a.
*
* Regression test for bug identified in changelist 49949.
*/
public void testUnifyTypePieces_successCase_EnumA_NumA() throws TypeException {
assertEquals(
Arrays.asList(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, "(" + Prelude_Enum + " a, " + Prelude_Num + " a) => a") }).toString(),
Arrays.asList(TypeExpr.unifyTypePieces(
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Enum + " a => a") },
new TypeExpr[] { leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a") },
getTestModuleTypeInfo())).toString());
}
/**
* Tests the method TypeExpr.unifyTypePieces() for throwing a TypeException on
* failing to unify (a, Int) with (Char, a).
*/
public void testUnifyTypePieces_failureCase_TupleAInt_TupleCharA() {
TypeExpr typeVarA = TypeExpr.makeParametricType();
boolean exceptionCaught = false;
try {
TypeExpr.unifyTypePieces(
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Int),
leccCALServices.getTypeFromString(testModule, Prelude_Int + " -> " + Prelude_Double),
TypeExpr.makeFunType(typeVarA, leccCALServices.getTypeFromString(testModule, Prelude_Int)),
},
new TypeExpr[] {
leccCALServices.getTypeFromString(testModule, Prelude_Num + " a => a"),
leccCALServices.getTypeFromString(testModule, "(" + Prelude_Num + " a, " + Prelude_Num + " b) => a -> b"),
TypeExpr.makeFunType(leccCALServices.getTypeFromString(testModule, Prelude_Char), typeVarA),
},
getTestModuleTypeInfo());
} catch (TypeException e) {
exceptionCaught = true;
}
assertTrue(exceptionCaught);
}
/**
* Tests the method TypeExpr.toString() for converting a TypeExpr into a string with
* only fully-qualified names.
*/
public void testToString_Qualified() {
String typeString = "(a\\#3, a\\#5, a\\a, a\\b, a\\z, " + Prelude_Num + " e, " + Prelude_Num + " f, g\\name) => {a | #3 :: b, #5 :: " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ", a :: [(e -> f) -> d -> (c, d) -> [[(b, b)]]], b :: [f], z :: {g | name :: " + Prelude_String + "}}";
assertEquals(typeString, leccCALServices.getTypeFromString(testModule, typeString).toString());
}
/**
* Tests the method TypeExpr.toString() for converting a TypeExpr into a string with
* only unqualified names.
*/
public void testToString_Unqualified() {
String typeString = "(a\\#3, a\\#5, a\\a, a\\b, a\\z, " + Prelude_Num + " e, " + Prelude_Num + " f, g\\name) => {a | #3 :: b, #5 :: " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ", a :: [(e -> f) -> d -> (c, d) -> [[(b, b)]]], b :: [f], z :: {g | name :: " + Prelude_String + "}}";
String unqualifiedTypeString = "(a\\#3, a\\#5, a\\a, a\\b, a\\z, Num e, Num f, g\\name) => {a | #3 :: b, #5 :: Either (Either c d) Int, a :: [(e -> f) -> d -> (c, d) -> [[(b, b)]]], b :: [f], z :: {g | name :: String}}";
assertEquals(unqualifiedTypeString, leccCALServices.getTypeFromString(testModule, typeString).toString(ScopedEntityNamingPolicy.UNQUALIFIED));
}
/**
* Tests the method TypeExpr.toString() for converting a TypeExpr into a string with
* names that are unqualified unless they are ambiguous. Here, we use M3 as
* the target module, where the type definition of TestTypeShadowing shadows that by the same
* name in the M1 module. This constitutes an ambiguity, and hence both
* M3.TestTypeShadowing and M1.TestTypeShadowing will be rendered as fully qualified names, whereas
* an unambiguous name like Prelude.Int will simply be rendered as Int.
*/
public void testToString_UnqualifiedUnlessAmbiguous() {
ModuleTypeInfo m3ModuleTypeInfo = leccCALServices.getWorkspaceManager().getWorkspace().getMetaModule(CALPlatformTestModuleNames.M3).getTypeInfo();
String typeString = CALPlatformTestModuleNames.M3 + ".TestTypeShadowing -> " + CALPlatformTestModuleNames.M1 + ".TestTypeShadowing -> " + Prelude_Int;
String m1 = m3ModuleTypeInfo.getModuleNameResolver().getMinimallyQualifiedModuleName(CALPlatformTestModuleNames.M1).toSourceText();
String m3 = m3ModuleTypeInfo.getModuleNameResolver().getMinimallyQualifiedModuleName(CALPlatformTestModuleNames.M3).toSourceText();
String unqualifiedUnlessAmbiguousTypeString = m3 + ".TestTypeShadowing -> " + m1 + ".TestTypeShadowing -> Int";
assertEquals(unqualifiedUnlessAmbiguousTypeString, leccCALServices.getTypeChecker().getTypeFromString(typeString, CALPlatformTestModuleNames.M3, null).toString(new ScopedEntityNamingPolicy.UnqualifiedUnlessAmbiguous(m3ModuleTypeInfo)));
}
/**
* Tests the method TypeExpr.toSourceModel() for its TypeExpr-to-source-model conversion functionality.
*/
public void testToSourceModel() {
String typeString = "(a\\#3, a\\#5, a\\a, a\\b, a\\z, " + Prelude_Num + " e, " + Prelude_Num + " f, g\\name) => {a | #3 :: b, #5 :: " + Prelude_Either + " (" + Prelude_Either + " c d) " + Prelude_Int + ", a :: [(e -> f) -> d -> (c, d) -> [[(b, b)]]], b :: [f], z :: {g | name :: " + Prelude_String + "}}";
assertEquals(
typeString.replaceAll("[\n\r \t]*", ""),
leccCALServices.getTypeFromString(testModule, typeString).toSourceModel().toSourceText().replaceAll("[\n\r \t]*", ""));
}
/**
* A regression test for TypeExpr.toSourceModel().
*/
public void testToSourceModelNotFavoringPreferredNames() {
final GemEntity entity = leccCALServices.getGemEntity(QualifiedName.make("Cal.Test.JUnitSupport.TypeExpr_Test_Support", "allPairs"));
final String typeString = entity.getTypeExpr().toString(false, ScopedEntityNamingPolicy.FULLY_QUALIFIED);
final SourceModel.TypeSignature typeSourceModel = entity.getTypeExpr().toSourceModel(false, ScopedEntityNamingPolicy.FULLY_QUALIFIED);
final String typeStringFromSourceModel = typeSourceModel.toSourceText();
assertEquals(typeString, typeStringFromSourceModel);
}
/**
* A regression test for TypeExpr.toSourceModel().
*/
public void testToSourceModelFavoringPreferredNames() {
final GemEntity entity = leccCALServices.getGemEntity(QualifiedName.make("Cal.Test.JUnitSupport.TypeExpr_Test_Support", "allPairs"));
final String typeString = entity.getTypeExpr().toString(true, ScopedEntityNamingPolicy.FULLY_QUALIFIED);
final SourceModel.TypeSignature typeSourceModel = entity.getTypeExpr().toSourceModel(true, ScopedEntityNamingPolicy.FULLY_QUALIFIED);
final String typeStringFromSourceModel = typeSourceModel.toSourceText();
assertEquals(typeString, typeStringFromSourceModel);
}
/**
* Serializes inTypeExpr into an in-memory buffer, and then deserializes from
* the same buffer and returns the result.
* @param inTypeExpr
* @return TypeExpr
* @throws IOException
*/
private TypeExpr serializeDeserialize(TypeExpr inTypeExpr) throws IOException {
NakedByteArrayOutputStream bos = new NakedByteArrayOutputStream(128);
RecordOutputStream ros = new RecordOutputStream(bos);
inTypeExpr.write(ros);
ros.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.getByteArray());
RecordInputStream ris = new RecordInputStream(bis);
CompilerMessageLogger msgLogger = new MessageLogger();
TypeExpr outTypeExpr = TypeExpr.load(ris, getTestModuleTypeInfo(), msgLogger);
ris.close();
assertTrue(msgLogger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0);
return outTypeExpr;
}
/**
* Converts typeExprString to a TypeExpr, serializes it out, serializes it back in,
* and asserts that the result is equivalent (ie, has an identical String representation)
* to the original.
* @param typeExprString
* @throws IOException
*/
private void checkRoundTripSerialization(String typeExprString) throws IOException {
TypeExpr typeExpr = leccCALServices.getTypeFromString(testModule, typeExprString);
assertEquals(typeExpr.toString(), serializeDeserialize(typeExpr).toString());
}
/**
* Check that we properly serialize and deserialize TypeExprs that contain multiple
* instances of record vars with type-class constraints
* @throws IOException
*/
public void testSerialization_classConstrainedRecordVar() throws IOException {
checkRoundTripSerialization(Prelude_Eq + " r => {r} -> {r}");
checkRoundTripSerialization("(" + Prelude_Ord + " r, " + Prelude_Eq + " s) => ({r}, {r}, {s}, {s}) -> ({r}, {s})");
}
/**
* Check that we properly serialize and deserialize TypeExprs that contain multiple
* instances of record vars with lacks-field constraints
* @throws IOException
*/
public void testSerialization_lacksConstrainedRecordVar() throws IOException {
checkRoundTripSerialization("r\\foo => {r | foo} -> {r}");
checkRoundTripSerialization("(r\\#1, s\\#2, t\\#3) => {r | #1 :: a} -> {s | #2 :: b} -> {t | #3 :: b} -> (a, b, b)");
checkRoundTripSerialization("(r\\foo, s\\bar) => " + Prelude_Maybe + " {r} -> " + Prelude_Maybe + " {s} -> ({r}, {s})");
}
/**
* Check that we serialize the special NO_FIELDS case properly
*/
public void testSerializaton_noFields() throws IOException {
checkRoundTripSerialization("{foo :: a, bar :: b} -> ({}, {foo :: a}, {bar :: b})");
checkRoundTripSerialization(Prelude_Num + " a => {foo :: a, bar :: b} -> ({}, {foo :: a}, {bar :: b})");
checkRoundTripSerialization("{foo :: " + Prelude_Maybe + " a, bar :: " + Prelude_Maybe + " b} -> ({}, {foo :: " + Prelude_Maybe + " a}, {bar :: " + Prelude_Maybe + " b}, {foo :: " + Prelude_Maybe + " a, bar :: " + Prelude_Maybe + " b})");
}
/**
* Check that we serialize TypeConstructors properly
*/
public void testSerialization_typeConstructor() throws IOException {
checkRoundTripSerialization(Prelude_Maybe + " " + Prelude_String);
checkRoundTripSerialization(Prelude_Either + " " + Prelude_String + " " + Prelude_String);
checkRoundTripSerialization(Prelude_Either + " " + Prelude_String + " " + Prelude_Char);
checkRoundTripSerialization(Prelude_Either + " a a");
checkRoundTripSerialization(Prelude_Either + " a b");
checkRoundTripSerialization(Prelude_Either + " (" + Prelude_Either + " a a) (" + Prelude_Either + " a b)");
checkRoundTripSerialization(Prelude_Num + " a => " + Prelude_Either + " (" + Prelude_Either + " a a) (" + Prelude_Either + " a b)");
checkRoundTripSerialization("(" + Prelude_Num + " a, " + Prelude_Num + " b) => " + Prelude_Either + " (" + Prelude_Either + " a a) (" + Prelude_Either + " a b)");
checkRoundTripSerialization("(" + Prelude_Num + " a, " + Prelude_Inputable + " a, " + Prelude_Outputable + " a) => " + Prelude_Either + " (" + Prelude_Either + " a a) (" + Prelude_Either + " a b)");
}
}