From 5f9eb43361e34cf9ecc7ad0bcedebc345b5539dd Mon Sep 17 00:00:00 2001 From: Julian Hyde Date: Sun, 24 Dec 2023 18:22:25 -0800 Subject: [PATCH] Add Type.isProgressive --- .../net/hydromatic/morel/compile/Pretty.java | 5 +---- .../net/hydromatic/morel/compile/Resolver.java | 17 ++++++----------- .../net/hydromatic/morel/compile/TypeMap.java | 9 ++------- .../hydromatic/morel/compile/TypeResolver.java | 12 +----------- .../hydromatic/morel/type/RecordLikeType.java | 10 ---------- .../net/hydromatic/morel/type/RecordType.java | 4 ++++ .../java/net/hydromatic/morel/type/Type.java | 10 ++++++++++ 7 files changed, 24 insertions(+), 43 deletions(-) diff --git a/src/main/java/net/hydromatic/morel/compile/Pretty.java b/src/main/java/net/hydromatic/morel/compile/Pretty.java index 717bbe81b..1559a09ef 100644 --- a/src/main/java/net/hydromatic/morel/compile/Pretty.java +++ b/src/main/java/net/hydromatic/morel/compile/Pretty.java @@ -323,10 +323,7 @@ private StringBuilder prettyType(StringBuilder buf, int indent, int[] lineEnd, case RECORD_TYPE: case PROGRESSIVE_RECORD_TYPE: final RecordType recordType = (RecordType) typeVal.type; - final boolean progressive = - type.op() == Op.PROGRESSIVE_RECORD_TYPE - || recordType.argNameTypes.containsKey( - ProgressiveRecordType.DUMMY); + final boolean progressive = typeVal.type.isProgressive(); buf.append("{"); start = buf.length(); recordType.argNameTypes.forEach((name, elementType) -> { diff --git a/src/main/java/net/hydromatic/morel/compile/Resolver.java b/src/main/java/net/hydromatic/morel/compile/Resolver.java index 4fee47d94..f050321ce 100644 --- a/src/main/java/net/hydromatic/morel/compile/Resolver.java +++ b/src/main/java/net/hydromatic/morel/compile/Resolver.java @@ -32,7 +32,6 @@ import net.hydromatic.morel.type.FnType; import net.hydromatic.morel.type.ForallType; import net.hydromatic.morel.type.ListType; -import net.hydromatic.morel.type.ProgressiveRecordType; import net.hydromatic.morel.type.RecordLikeType; import net.hydromatic.morel.type.RecordType; import net.hydromatic.morel.type.TupleType; @@ -416,13 +415,9 @@ private Core.Apply toCore(Ast.Apply apply) { makeProgressive(coreArg), recordSelector.name); if (type.op() == Op.TY_VAR && coreFn.type.op() == Op.FUNCTION_TYPE - || type instanceof RecordType - && ((RecordLikeType) type).argNameTypes().containsKey( - ProgressiveRecordType.DUMMY) + || type.isProgressive() || type instanceof ListType - && ((ListType) type).elementType instanceof RecordType - && ((RecordLikeType) ((ListType) type).elementType) - .argNameTypes().containsKey(ProgressiveRecordType.DUMMY)) { + && ((ListType) type).elementType.isProgressive()) { // If we are dereferencing a field in a progressive type, the type // available now may be more precise than the deduced type. type = ((FnType) coreFn.type).resultType; @@ -438,7 +433,7 @@ private Core.Apply toCore(Ast.Apply apply) { * type. */ private RecordLikeType makeProgressive(Core.Exp coreArg) { final RecordLikeType recordLikeType = (RecordLikeType) coreArg.type; - if (recordLikeType.argNameTypes().containsKey(ProgressiveRecordType.DUMMY)) { + if (coreArg.type.isProgressive()) { Object o = valueOf(coreArg); if (o instanceof Codes.TypedValue) { final Codes.TypedValue typedValue = (Codes.TypedValue) o; @@ -701,13 +696,13 @@ private static boolean subsumes(Type actualType, Type expectedType) { if (expectedType.op() != Op.RECORD_TYPE) { return false; } + if (actualType.isProgressive()) { + return true; + } final SortedMap actualMap = ((RecordType) actualType).argNameTypes(); final SortedMap expectedMap = ((RecordType) expectedType).argNameTypes(); - if (actualMap.containsKey(ProgressiveRecordType.DUMMY)) { - return true; - } final Iterator> actualIterator = actualMap.entrySet().iterator(); final Iterator> expectedIterator = diff --git a/src/main/java/net/hydromatic/morel/compile/TypeMap.java b/src/main/java/net/hydromatic/morel/compile/TypeMap.java index 7226e149e..7d333eb79 100644 --- a/src/main/java/net/hydromatic/morel/compile/TypeMap.java +++ b/src/main/java/net/hydromatic/morel/compile/TypeMap.java @@ -19,7 +19,6 @@ package net.hydromatic.morel.compile; import net.hydromatic.morel.ast.AstNode; -import net.hydromatic.morel.type.ProgressiveRecordType; import net.hydromatic.morel.type.RecordType; import net.hydromatic.morel.type.Type; import net.hydromatic.morel.type.TypeSystem; @@ -98,12 +97,8 @@ public boolean typeIsVariable(AstNode node) { final Unifier.Term term = nodeTypeTerms.get(node); if (term instanceof Unifier.Variable) { final Type type = termToType(term); - if (type instanceof TypeVar - || type instanceof RecordType - && ((RecordType) type).argNameTypes.containsKey( - ProgressiveRecordType.DUMMY)) { - return true; - } + return type instanceof TypeVar + || type.isProgressive(); } return false; } diff --git a/src/main/java/net/hydromatic/morel/compile/TypeResolver.java b/src/main/java/net/hydromatic/morel/compile/TypeResolver.java index 41729d554..48fb7ce44 100644 --- a/src/main/java/net/hydromatic/morel/compile/TypeResolver.java +++ b/src/main/java/net/hydromatic/morel/compile/TypeResolver.java @@ -32,8 +32,6 @@ import net.hydromatic.morel.type.Keys; import net.hydromatic.morel.type.ListType; import net.hydromatic.morel.type.PrimitiveType; -import net.hydromatic.morel.type.ProgressiveRecordType; -import net.hydromatic.morel.type.RecordLikeType; import net.hydromatic.morel.type.RecordType; import net.hydromatic.morel.type.TupleType; import net.hydromatic.morel.type.Type; @@ -186,7 +184,7 @@ private Resolved deduceType_(@Nullable Session session, Environment env, List applies = new ArrayList<>(); forEachUnresolvedField(node2, typeMap, apply -> { final Type type = typeMap.getType(apply.arg); - if (isProgressive(type)) { + if (type.isProgressive()) { applies.add(apply); } }); @@ -201,14 +199,6 @@ private Resolved deduceType_(@Nullable Session session, Environment env, } } - // TODO: centralize and simplify the following logic - private static boolean isProgressive(Type type) { - return type instanceof ProgressiveRecordType - || type instanceof RecordLikeType - && ((RecordLikeType) type).argNameTypes() - .containsKey(ProgressiveRecordType.DUMMY); - } - private Codes.@Nullable TypedValue expandField(Environment env, Ast.Exp exp) { switch (exp.op) { case APPLY: diff --git a/src/main/java/net/hydromatic/morel/type/RecordLikeType.java b/src/main/java/net/hydromatic/morel/type/RecordLikeType.java index dda6fadcb..23c96f1fa 100644 --- a/src/main/java/net/hydromatic/morel/type/RecordLikeType.java +++ b/src/main/java/net/hydromatic/morel/type/RecordLikeType.java @@ -31,16 +31,6 @@ public interface RecordLikeType extends Type { /** Returns the type of the {@code i}th field, or throws. */ Type argType(int i); - /** Returns whether this type is progressive. - * - *

Progressive types are records, but can have additional fields each time - * you look. - * - *

The "file" value is an example. */ - default boolean isProgressive() { - return false; - } - /** Returns a {@link net.hydromatic.morel.eval.Codes.TypedValue} if this * type wraps a single dynamically typed value, otherwise null. */ default Codes.@Nullable TypedValue asTypedValue() { diff --git a/src/main/java/net/hydromatic/morel/type/RecordType.java b/src/main/java/net/hydromatic/morel/type/RecordType.java index 8d4fed290..f8fd6feb4 100644 --- a/src/main/java/net/hydromatic/morel/type/RecordType.java +++ b/src/main/java/net/hydromatic/morel/type/RecordType.java @@ -74,6 +74,10 @@ public Key key() { : (RecordType) typeSystem.recordType(argNameTypes2.build()); } + @Override public boolean isProgressive() { + return argNameTypes.containsKey(ProgressiveRecordType.DUMMY); + } + /** Ordering that compares integer values numerically, * string values lexicographically, * and integer values before string values. diff --git a/src/main/java/net/hydromatic/morel/type/Type.java b/src/main/java/net/hydromatic/morel/type/Type.java index bc5205ab3..4add83ab5 100644 --- a/src/main/java/net/hydromatic/morel/type/Type.java +++ b/src/main/java/net/hydromatic/morel/type/Type.java @@ -66,6 +66,16 @@ default Type substitute(TypeSystem typeSystem, List types) { }); } + /** Returns whether this type is progressive. + * + *

Progressive types are records, but can have additional fields each time + * you look. + * + *

The "file" value is an example. */ + default boolean isProgressive() { + return false; + } + /** Structural identifier of a type. */ abstract class Key { public final Op op;