Skip to content

Commit

Permalink
Fix Dependently typed functions
Browse files Browse the repository at this point in the history
  • Loading branch information
heshanpadmasiri committed Oct 13, 2024
1 parent c312015 commit 5b8e663
Show file tree
Hide file tree
Showing 21 changed files with 216 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.ballerina.runtime.internal.values.ReadOnlyUtils;

import java.util.Optional;
import java.util.Set;

import static io.ballerina.runtime.api.types.semtype.Builder.getNeverType;
import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED;
Expand Down Expand Up @@ -253,6 +254,11 @@ public void resetSemType() {
super.resetSemType();
}

Check warning on line 255 in bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java

View check run for this annotation

Codecov / codecov/patch

bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java#L253-L255

Added lines #L253 - L255 were not covered by tests

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return elementType instanceof MayBeDependentType eType && eType.isDependentlyTyped(visited);
}

@Override
public Optional<SemType> inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) {
if (!couldInherentTypeBeDifferent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.ballerina.runtime.internal.values.MapValueImpl;

import java.util.Optional;
import java.util.Set;

/**
* {@code BErrorType} represents error type in Ballerina.
Expand Down Expand Up @@ -139,6 +140,12 @@ public synchronized SemType createSemType() {
return distinctIdSupplier.get().stream().map(ErrorUtils::errorDistinct).reduce(err, Core::intersect);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return detailType instanceof MayBeDependentType mayBeDependentType &&
mayBeDependentType.isDependentlyTyped(visited);
}

private boolean isTopType() {
return detailType == PredefinedTypes.TYPE_DETAIL;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.util.Arrays;
import java.util.Objects;
import java.util.Set;

/**
* {@code {@link BFunctionType }} represents a function type in ballerina.
Expand Down Expand Up @@ -233,7 +234,6 @@ public synchronized SemType createSemType() {
FunctionDefinition fd = new FunctionDefinition();
this.defn = fd;
SemType[] params = new SemType[parameters.length];
boolean hasBType = false;
for (int i = 0; i < parameters.length; i++) {
params[i] = getSemType(parameters[i].type);
}
Expand All @@ -244,12 +244,7 @@ public synchronized SemType createSemType() {
rest = Builder.getNeverType();
}

SemType returnType;
if (retType != null) {
returnType = getSemType(retType);
} else {
returnType = Builder.getNilType();
}
SemType returnType = resolveReturnType();
ListDefinition paramListDefinition = new ListDefinition();
SemType paramType = paramListDefinition.defineListTypeWrapped(env, params, params.length, rest,
CellAtomicType.CellMutability.CELL_MUT_NONE);
Expand Down Expand Up @@ -281,4 +276,33 @@ public synchronized void resetSemType() {
defn = null;
super.resetSemType();
}

Check warning on line 278 in bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java

View check run for this annotation

Codecov / codecov/patch

bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java#L276-L278

Added lines #L276 - L278 were not covered by tests

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return (restType instanceof BType rest && rest.isDependentlyTyped(visited)) ||
(retType instanceof BType ret && ret.isDependentlyTyped(visited)) ||
isDependentlyTypeParameters(visited);
}

private boolean isDependentlyTypeParameters(Set<MayBeDependentType> visited) {
if (parameters == null) {
return false;
}
return Arrays.stream(parameters).map(each -> each.type).filter(each -> each instanceof MayBeDependentType)
.anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited));
}

private SemType resolveReturnType() {
if (retType == null) {
return Builder.getNilType();

Check warning on line 297 in bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java

View check run for this annotation

Codecov / codecov/patch

bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java#L297

Added line #L297 was not covered by tests
}
MayBeDependentType retBType = (MayBeDependentType) retType;
SemType returnType = getSemType(retType);
ListDefinition ld = new ListDefinition();
SemType dependentlyTypedBit =
retBType.isDependentlyTyped() ? Builder.getBooleanConst(true) : Builder.getBooleanType();
SemType[] innerType = new SemType[]{dependentlyTypedBit, returnType};
return ld.defineListTypeWrapped(env, innerType, 2, Builder.getNeverType(),
CellAtomicType.CellMutability.CELL_MUT_NONE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import io.ballerina.runtime.internal.TypeChecker;
import io.ballerina.runtime.internal.types.semtype.FutureUtils;

import java.util.Set;

/**
* {@code BFutureType} represents a future value in Ballerina.
*
Expand Down Expand Up @@ -111,4 +113,9 @@ public boolean shouldCache() {
// {@code equals} depends on the type checker this is to avoid a possible infinite recursion
return false;
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Function;

Expand Down Expand Up @@ -232,6 +233,12 @@ public SemType createSemType() {
return createSemTypeInner(SemType::tryInto);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return constituentTypes.stream().filter(each -> each instanceof MayBeDependentType)
.anyMatch(type -> ((MayBeDependentType) type).isDependentlyTyped(visited));
}

private SemType createSemTypeInner(Function<Type, SemType> semTypeFunction) {
if (constituentTypes.isEmpty()) {
return Builder.getNeverType();

Check warning on line 244 in bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java

View check run for this annotation

Codecov / codecov/patch

bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java#L244

Added line #L244 was not covered by tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE;
import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED;
Expand Down Expand Up @@ -272,4 +273,9 @@ public BMapType clone() {
clone.defn = null;
return clone;
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,10 @@ static MethodData fromResourceMethod(BResourceMethodType method) {
return new MethodData(methodName, method.getFlags(), semType);
}
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return fields.values().stream().map(Field::getFieldType).filter(each -> each instanceof MayBeDependentType)
.anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.types.semtype.SemType;

import java.util.Set;

/**
* {@code ParameterizedType} represents the parameterized type in dependently-typed functions.
*
Expand Down Expand Up @@ -86,4 +88,9 @@ public int getParamIndex() {
public SemType createSemType() {
return SemType.tryInto(this.paramValueType);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ public void resetSemType() {
super.resetSemType();
}

@Override
public boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return fields.values().stream().map(Field::getFieldType).filter(each -> each instanceof MayBeDependentType)
.anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited));
}

@Override
public Optional<SemType> inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) {
if (!couldInherentTypeBeDifferent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.ballerina.runtime.internal.types.semtype.ImmutableSemType;

import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;

/**
Expand All @@ -39,7 +40,7 @@
* @param <E> The type of the {@code BType} that is being wrapped.
* @since 2201.11.0
*/
public sealed class BSemTypeWrapper<E extends BType> extends ImmutableSemType implements Type
public sealed class BSemTypeWrapper<E extends BType> extends ImmutableSemType implements Type, MayBeDependentType
permits BAnyType, BBooleanType, BByteType, BDecimalType, BFloatType, BHandleType, BIntegerType, BNullType,
BReadonlyType, BStringType {

Expand Down Expand Up @@ -192,4 +193,14 @@ public Type getCachedImpliedType() {
protected E getbType() {
return bTypeSupplier.get();
}

@Override
public boolean isDependentlyTyped() {
return false;
}

@Override
public boolean isDependentlyTyped(Set<MayBeDependentType> visited) {
return isDependentlyTyped();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.ballerina.runtime.internal.values.StreamValue;

import java.util.Objects;
import java.util.Set;

/**
* {@link BStreamType} represents streaming data in Ballerina.
Expand Down Expand Up @@ -155,4 +156,12 @@ public synchronized SemType createSemType() {
definition = sd;
return sd.define(env, tryInto(constraint), tryInto(completionType));
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return (constraint instanceof MayBeDependentType constrainedType &&
constrainedType.isDependentlyTyped(visited)) ||
(completionType instanceof MayBeDependentType completionType &&
completionType.isDependentlyTyped(visited));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.ballerina.runtime.internal.values.TableValueImpl;

import java.util.Optional;
import java.util.Set;

/**
* {@code BTableType} represents tabular data in Ballerina.
Expand Down Expand Up @@ -246,4 +247,9 @@ public boolean shouldCache() {
// TODO: remove this once we have fixed equals
return false;
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -363,6 +364,12 @@ public void resetSemType() {
super.resetSemType();
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return tupleTypes.stream().filter(each -> each instanceof MayBeDependentType)
.anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited));
}

@Override
public Optional<SemType> inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) {
if (!couldInherentTypeBeDifferent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
import io.ballerina.runtime.internal.TypeChecker;
import io.ballerina.runtime.internal.types.semtype.MutableSemType;

import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
* {@code BType} represents a type in Ballerina.
Expand All @@ -44,7 +46,7 @@
* @since 0.995.0
*/
public abstract non-sealed class BType extends SemType
implements Type, MutableSemType, Cloneable, CacheableTypeDescriptor {
implements Type, MutableSemType, Cloneable, CacheableTypeDescriptor, MayBeDependentType {

protected String typeName;
protected Module pkg;
Expand Down Expand Up @@ -309,4 +311,20 @@ public final void cacheTypeCheckResult(CacheableTypeDescriptor other, boolean re
typeCheckCache.cacheTypeCheckResult(other, result);
}

@Override
public final boolean isDependentlyTyped() {
return isDependentlyTyped(new HashSet<>());
}

@Override
public final boolean isDependentlyTyped(Set<MayBeDependentType> visited) {
if (!visited.add(this)) {
return false;
}
return isDependentlyTypedInner(visited);
}

protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
* {@code TypeReferencedType} represents a type description which refers to another type.
Expand Down Expand Up @@ -136,6 +137,11 @@ public SemType createSemType() {
return tryInto(referredType);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return getReferredType() instanceof MayBeDependentType refType && refType.isDependentlyTyped(visited);
}

@Override
public Optional<SemType> inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) {
if (!couldInherentTypeBeDifferent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import io.ballerina.runtime.internal.values.TypedescValue;
import io.ballerina.runtime.internal.values.TypedescValueImpl;

import java.util.Set;

/**
* {@code BTypedescType} represents a type of a type in the Ballerina type system.
*
Expand Down Expand Up @@ -101,4 +103,10 @@ public SemType createSemType() {
Context cx = TypeChecker.context();
return TypedescUtils.typedescContaining(cx.env, constraint);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return constraint instanceof MayBeDependentType constraintType &&
constraintType.isDependentlyTyped(visited);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,13 @@ public SemType createSemType() {
return memberTypes.stream().map(SemType::tryInto).reduce(Builder.getNeverType(), Core::union);
}

@Override
protected boolean isDependentlyTypedInner(Set<MayBeDependentType> visited) {
return memberTypes.stream()
.filter(each -> each instanceof MayBeDependentType)
.anyMatch(type -> ((MayBeDependentType) type).isDependentlyTyped(visited));
}

@Override
public Optional<SemType> acceptedTypeOf(Context cx) {
return Optional.of(memberTypes.stream().map(each -> ShapeAnalyzer.acceptedTypeOf(cx, each).orElseThrow())
Expand Down
Loading

0 comments on commit 5b8e663

Please sign in to comment.