diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc index eb7be1c4b4f..55e419bb6ba 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc @@ -505,3 +505,16 @@ void resetClosureCounter(){ } str generateClosureName() = "$CLOSURE_"; + +AType getInstantiated(Tree tree, Solver s) { + AType t = s.getType(tree); + if (isInstantiated(t)) { + return t; + } else { + throw TypeUnavailable(); + } +} + +bool isInstantiated(AType t) { + return /aparameter(_, _) !:= t; +} \ No newline at end of file diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc index c4fae5bd748..34f6661e502 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc @@ -1057,6 +1057,8 @@ void collect(current: (Expression) ` . `, Col AType(Solver s){ expType = s.getType(expression); fieldType = s.getType(field); + // expType = getInstantiated(expression, s); + // fieldType = getInstantiated(field, s); if(isVoidAType(expType)) s.report(error(expression, "Base expression of field selection should not have type `void`")); if(overloadedAType(rel[loc, IdRole, AType] overloads) := expType){ diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/ComputeType.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/ComputeType.rsc index 653003a1e75..d0f4599208c 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/ComputeType.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/ComputeType.rsc @@ -119,6 +119,15 @@ void(Solver) makeVarInitRequirement(Variable var) catch invalidMatch(str reason): s.report(error(var.initial, reason)); + // if (isInstantiated(varTypeU) && !isInstantiated(initialTypeU)) { + // println("NOT READY -- : -- : "); + // facts = s.getFacts(); + // for (f <- facts, f.offset?, f.offset >= 130) { + // println(" - : "); + // } + // throw TypeUnavailable(); + // } + initialTypeU = instantiateRascalTypeParameters(var, initialTypeU, bindings, s); if(s.isFullyInstantiated(initialTypeU)){ if(overloadedAType(overloads) := initialTypeU){ diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/DataDeclarationTCTests.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/DataDeclarationTCTests.rsc index 2271b724e36..454586b2ddf 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/DataDeclarationTCTests.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/DataDeclarationTCTests.rsc @@ -441,9 +441,73 @@ test bool Escapes2() = checkModuleOK(" // ---- type parameters ------------------------------------------------------- -test bool ADTWithTypeParameter() = checkModuleOK(" - module ADTWithTypeParameter - data D[&T] = d1(&T n); +test bool Box() = checkModuleOK(" + module Box + data Box[&T] = box(&T v); + &T unbox(Box[&T] b) = b.v; + "); + +test bool NumBox() = checkModuleOK(" + module NumBox + data NumBox[&T \<: num] = box(&T v); + + &T \<: num unboxAndSum(NumBox[&T \<: num] box1, NumBox[&T \<: num] box2) { + &T v1 = box1.v; + &T v2 = box2.v; + return v1 + v2; + } + "); + +test bool ADTWithTypeParameter1() = checkModuleOK(" + module ADTWithTypeParameter1 + data D[&T] = d(&T n); + int n = d(5).n; + "); + +test bool ADTWithTypeParameter2() = checkModuleOK(" + module Bar + data D[&T] = d(&T n); + int f() { + n1 = d(5).n; + n2 = n1; + n3 = n2; + return n3 + 5; + } + "); + +test bool ADTWithTypeParameter2ButDifferentModuleName() = checkModuleOK(" + module Foo + data D[&T] = d(&T n); + int f() { + n1 = d(5).n; + n2 = n1; + n3 = n2; + return n3 + 5; + } + "); + +/* + * `d(5).n` kan van een ongeinstantieerd type zijn. Of dit toegestaan is, hangt + * in het algemeen af van de context (onduidelijk op basis van alleen de field + * access). + * + * Maw, je probeert het type te berekenen van een field access. Er komt een + * ongeinstantieerd type uit. Is dat ok? Onmogelijk om te zeggen op basis van + * alleen de access. In het geval van `Box` en `NumBox` is het ok (i.e., het + * type blijft altijd ongeinstantieerd). In het geval van `Foo` is het niet ok + * (i.e., het type wordt later geinstantieerd, en die instantiatie zou door + * moeten stromen naar afhankelijke locaties). + * + * De vraag is nu: kun je ervoor zorgen, op een of andere manier, dat `calc(useViaType, ...) pas wordt geevalueerd na `calc(n, ...)`? + * Bijvoorbeeld: type van de constructor pas kunnen berekenen als het type van de typeparameter bekend is? + */ + +test bool ADTWithTypeParameter3() = checkModuleOK(" + module ADTWithTypeParameter3 + data D1[&T] = d1(D2[&T] inner); + data D2[&T] = d2(&T n); + D1[int] outer = d1(d2(5)); + int n = outer.inner.n; "); test bool UndefinedParameter() = unexpectedTypeInModule(" @@ -484,7 +548,7 @@ test bool ADTWithTypeParameterAndKW2() = checkModuleOK(" void f() { D[int] x = d1(10); int m = x.kw; } "); -test bool ADTWithTypeParameterAndKW3() = checkModuleOK(" +test bool ADTWithTypeParameterAndKW3() = unexpectedTypeInModule(" module ADTWithTypeParameterAndKW3 data D[&T] = d1(&T n, &T kw = n); void f() { D[int] x = d1(10); str m = x.kw; } diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/StaticTestingUtils.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/StaticTestingUtils.rsc index e6f587d002b..36ae4751de0 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/StaticTestingUtils.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/tests/StaticTestingUtils.rsc @@ -175,6 +175,7 @@ bool checkModuleAndFilter(list[loc] mlocs, list[str] expected, bool matchAll = f if(matchAll) { return all(e <- expected, e in matched); } + iprintln(msgs); throw abbrev(""); } @@ -325,7 +326,8 @@ list[str] unexpectedTypeMsgs = [ "Expected a binary relation, found _", "Constructor _ is overloaded", "Expression _ is overloaded", - "Base expression _ of field selection should have a unique type" + "Base expression _ of field selection should have a unique type", + "Invalid initialization of ; type of one or more subparts could not be inferred" ]; bool unexpectedTypeInModule(str moduleText, PathConfig pathConfig = getDefaultTestingPathConfig())