Skip to content

Commit

Permalink
Specialized assignment into tuples with literal subscripts, resolves #…
Browse files Browse the repository at this point in the history
  • Loading branch information
mahills committed Apr 19, 2016
1 parent a51c0b5 commit 9fd63a2
Showing 1 changed file with 37 additions and 13 deletions.
50 changes: 37 additions & 13 deletions src/org/rascalmpl/library/lang/rascal/types/CheckTypes.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -1240,18 +1240,20 @@ public CheckResult checkExp(Expression exp:(Expression)`<Expression e> [ <{Expre
else
return markLocationType(c,exp@\loc,Symbol::\value());
} else if (isTupleType(t1)) {
if (size(tl) != 1)
if (size(tl) != 1) {
return markLocationFailed(c,exp@\loc,makeFailType("Expected only 1 subscript for a tuple expression, not <size(tl)>",exp@\loc));
else if (!isIntType(tl[0]))
} else if (!isIntType(tl[0])) {
return markLocationFailed(c,exp@\loc,makeFailType("Expected subscript of type int, not <prettyPrintType(tl[0])>",exp@\loc));
else if ((Expression)`<DecimalIntegerLiteral dil>` := head(eslist)) {
} else if ((Expression)`<DecimalIntegerLiteral dil>` := head(eslist)) {
tupleIndex = toInt("<dil>");
if (tupleIndex < 0 || tupleIndex >= size(getTupleFields(t1)))
if (tupleIndex < 0 || tupleIndex >= size(getTupleFields(t1))) {
return markLocationFailed(c,exp@\loc,makeFailType("Tuple index must be between 0 and <size(getTupleFields(t1))-1>",exp@\loc));
else
} else {
return markLocationType(c,exp@\loc,getTupleFields(t1)[tupleIndex]);
} else
}
} else {
return markLocationType(c,exp@\loc,lubList(getTupleFields(t1)));
}
} else if (isStrType(t1)) {
if (size(tl) != 1)
return markLocationFailed(c,exp@\loc,makeFailType("Expected only 1 subscript for a string expression, not <size(tl)>",exp@\loc));
Expand Down Expand Up @@ -5144,6 +5146,7 @@ public anno set[int] AssignableTree@defs;
@doc{Allows AssignableTree nodes to be annotated with types.}
public anno Symbol AssignableTree@otype;
public anno Symbol AssignableTree@atype;
public anno int AssignableTree@literalIndex;
@doc{Result of building the assignable tree.}
alias ATResult = tuple[Configuration, AssignableTree];
Expand Down Expand Up @@ -5197,22 +5200,36 @@ public ATResult buildAssignableTree(Assignable assn:(Assignable)`<Assignable ar>
< c, atree > = buildAssignableTree(ar, false, c);
< c, tsub > = checkExp(sub, c);
if (isFailType(atree@atype) || isFailType(tsub))
if (isFailType(atree@atype) || isFailType(tsub)) {
return < c, subscriptNode(atree,tsub)[@atype=collapseFailTypes({atree@atype,tsub})][@at=assn@\loc] >;
}
if (!concreteType(atree@atype)) {
failtype = makeFailType("Assignable <ar> must have an actual type before subscripting", assn@\loc);
return < c, subscriptNode(atree,tsub)[@atype=failtype][@at=assn@\loc] >;
}
if (isListType(atree@atype) && isIntType(tsub))
if (isListType(atree@atype) && isIntType(tsub)) {
return < c, subscriptNode(atree,tsub)[@atype=getListElementType(atree@atype)][@at=assn@\loc] >;
}
if (isNodeType(atree@atype) && isIntType(tsub))
if (isNodeType(atree@atype) && isIntType(tsub)) {
return < c, subscriptNode(atree,tsub)[@atype=Symbol::\value()][@at=assn@\loc] >;
}
if (isTupleType(atree@atype) && isIntType(tsub))
return < c, subscriptNode(atree,tsub)[@atype=Symbol::\value()][@at=assn@\loc] >;
if (isTupleType(atree@atype) && isIntType(tsub)) {
if ((Expression)`<DecimalIntegerLiteral dil>` := sub) {
tupleIndex = toInt("<dil>");
if (tupleIndex < 0 || tupleIndex >= size(getTupleFields(atree@atype))) {
failtype = makeFailType("Tuple index must be between 0 and <size(getTupleFields(atree@atype))-1>", sub@\loc);
return < c, subscriptNode(atree,tsub)[@atype=failtype][@at=assn@\loc] >;
} else {
return < c, subscriptNode(atree,tsub)[@atype=getTupleFields(atree@atype)[tupleIndex]][@at=assn@\loc][@literalIndex=tupleIndex] >;
}
} else {
return < c, subscriptNode(atree,tsub)[@atype=Symbol::\value()][@at=assn@\loc] >;
}
}
if (isMapType(atree@atype)) {
if (avar:variableNode(vname) := atree) {
Expand All @@ -5232,8 +5249,9 @@ public ATResult buildAssignableTree(Assignable assn:(Assignable)`<Assignable ar>
return < c, subscriptNode(atree,tsub)[@atype=(isMapType(atree@atype))?getMapRangeType(atree@atype):atree@atype][@at=assn@\loc] >;
}
if (isRelType(atree@atype) && size(getRelFields(atree@atype)) == 2 && subtype(tsub,getRelFields(atree@atype)[0]))
if (isRelType(atree@atype) && size(getRelFields(atree@atype)) == 2 && subtype(tsub,getRelFields(atree@atype)[0])) {
return < c, subscriptNode(atree,tsub)[@atype=getRelFields(atree@atype)[1]][@at=assn@\loc] >;
}
return < c, subscriptNode(atree,tsub)[@atype=makeFailType("Cannot subscript assignable of type <prettyPrintType(atree@atype)>",assn@\loc)][@at=assn@\loc] >;
}
Expand Down Expand Up @@ -5709,7 +5727,13 @@ public ATResult bindAssignable(AssignableTree atree:subscriptNode(AssignableTree
// in range, all we can infer about the resulting type is that, since
// we could assign to each field, each field could have a type based
// on the lub of the existing field type and the subject type.
< c, receiver > = bindAssignable(receiver, \tuple([lub(tupleFields[idx],st) | idx <- index(tupleFields)]), c);
if ( (atree@literalIndex)?) {
updatedTupleFields = tupleFields;
updatedTupleFields[atree@literalIndex] = lub(atree@atype,st);
< c, receiver > = bindAssignable(receiver, \tuple(updatedTupleFields), c);
} else {
< c, receiver > = bindAssignable(receiver, \tuple([lub(tupleFields[idx],st) | idx <- index(tupleFields)]), c);
}
return < c, atree[receiver=receiver][@otype=receiver@otype][@atype=Symbol::\value()] >;
} else if (isMapType(receiver@atype)) {
< c, receiver > = bindAssignable(receiver, \map(getMapDomainType(receiver@atype), lub(st,getMapRangeType(receiver@atype))), c);
Expand Down

0 comments on commit 9fd63a2

Please sign in to comment.