Skip to content

Commit

Permalink
Number type variables left-to-right
Browse files Browse the repository at this point in the history
  • Loading branch information
julianhyde committed Dec 24, 2024
1 parent b10fe6e commit d6579fb
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
7 changes: 1 addition & 6 deletions src/main/java/net/hydromatic/morel/compile/Pretty.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private StringBuilder pretty2(@NonNull StringBuilder buf,
0, 0);
buf.append(' ');
pretty1(buf, indent + 2, lineEnd, depth, PrimitiveType.BOOL,
new TypeVal(": ", unqualified(typedVal.type)), 0, 0);
new TypeVal(": ", typeSystem.unqualified(typedVal.type)), 0, 0);
return buf;
}

Expand Down Expand Up @@ -381,11 +381,6 @@ private static List<Object> toList(Object value) {
return (List<Object>) value;
}

private static Type unqualified(Type type) {
return type instanceof ForallType ? unqualified(((ForallType) type).type)
: type;
}

private StringBuilder printList(@NonNull StringBuilder buf,
int indent, int[] lineEnd, int depth, @NonNull Type elementType,
@NonNull List<Object> list) {
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/net/hydromatic/morel/type/TypeSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,41 @@ public TypeVar get(int index) {
};
}

/** Removes any "forall" qualifier of a type, and renumbers the remaining
* type variables.
*
* <p>Examples:
* <ul>
* <li>{@code forall 'a. 'a list}
* &rarr; {@code 'a list}
* <li>{@code forall 'a 'b. 'b list}
* &rarr; {@code 'a list}
* <li>{@code forall 'a 'b 'c. 'c * 'a -> {x:'a, y:'c} }
* &rarr; {@code 'a * 'b -> {x:b, y:a'} }
* </ul>
*
* @param type
* @return
*/
public Type unqualified(Type type) {
while (type instanceof ForallType) {
type = ((ForallType) type).type;
}
// Renumber type variables:
// 'b list -> 'a list
// ('b * 'a * 'b) -> ('a * 'b * 'a)
// ('a * 'c * 'a) -> ('a * 'b * 'a)
return type.accept(
new TypeShuttle(this) {
final Map<Integer, TypeVar> map = new HashMap<>();

@Override public Type visit(TypeVar typeVar) {
return map.computeIfAbsent(typeVar.ordinal,
i -> typeVariable(map.size()));
}
});
}

public Pair<DataType, Type.Key> lookupTyCon(String tyConName) {
return typeConstructorByName.get(tyConName);
}
Expand Down
10 changes: 10 additions & 0 deletions src/test/resources/script/type.smli
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,14 @@ fun r0 a b c d e f g h i j k l m n p q r s = {a=a,b=b,c=c};
> -> 'q
> -> 'r -> {a:'a, b:'b, c:'c}

(*) When printing a type, 'forall' is omitted. Sometimes that eliminates
(*) type variables. The following tests make sure that type variables are
(*) contiguous and numbered left-to-right.
[[], []];
> val it = [[],[]] : 'a list list
let val r = {a=[], b=[]} in r.b end;
> val it = [] : 'a list
fun f (a, b, c) = {x=c, y=a};
> val f = fn : 'a * 'b * 'c -> {x:'c, y:'a}

(*) End type.smli

0 comments on commit d6579fb

Please sign in to comment.