Skip to content

Commit

Permalink
More fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
brynrhodes committed Oct 28, 2024
1 parent 9aa414a commit 28cae24
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,10 @@ public Object visitListSelector(cqlParser.ListSelectorContext ctx) {
}

if (elementType == null) {
// In FHIRPath, the empty list is equivalent to null (i.e. { } is how you spell null in FHIRPath)
elementType =
inferredElementType == null ? libraryBuilder.resolveTypeName("System", "Any") : inferredElementType;
inferredElementType == null ? libraryBuilder.buildWildcardType() : inferredElementType;
//inferredElementType == null ? libraryBuilder.resolveTypeName("System", "Any") : inferredElementType;
}

for (Expression element : elements) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -927,29 +927,70 @@ private BinaryWrapper normalizeListTypes(Expression left, Expression right) {
&& !(leftListType.isCompatibleWith(rightListType)
|| rightListType.isCompatibleWith(leftListType))) {
Set<DataType> elementTypes = new HashSet<DataType>();
DataType wildcardType = null;
if (leftListType.getElementType() instanceof ChoiceType) {
for (DataType choice : ((ChoiceType) leftListType.getElementType()).getTypes()) {
elementTypes.add(choice);
if (choice.isWildcard()) {
if (wildcardType == null) {
wildcardType = choice;
}
} else {
elementTypes.add(choice);
}
}
} else {
elementTypes.add(leftListType.getElementType());
if (leftListType.getElementType().isWildcard()) {
if (wildcardType == null) {
wildcardType = leftListType.getElementType();
}
} else {
elementTypes.add(leftListType.getElementType());
}
}

if (rightListType.getElementType() instanceof ChoiceType) {
for (DataType choice : ((ChoiceType) rightListType.getElementType()).getTypes()) {
elementTypes.add(choice);
if (choice.isWildcard()) {
if (wildcardType == null) {
wildcardType = choice;
}
} else {
elementTypes.add(choice);
}
}
} else {
elementTypes.add(rightListType.getElementType());
if (rightListType.getElementType().isWildcard()) {
if (wildcardType == null) {
wildcardType = rightListType.getElementType();
}
} else {
elementTypes.add(rightListType.getElementType());
}
}

boolean needsCast = false;
if (elementTypes.size() == 0 && wildcardType != null) {
elementTypes.add(wildcardType);
needsCast = true;
}

if (elementTypes.size() > 1) {
ListType targetType = new ListType(new ChoiceType(elementTypes));
left = of.createAs().withOperand(left).withAsTypeSpecifier(dataTypeToTypeSpecifier(targetType));
left.setResultType(targetType);
needsCast = true;
}

if (needsCast) {
DataType targetElementType
= elementTypes.size() > 1 ? new ChoiceType(elementTypes) : elementTypes.iterator().next();
ListType targetType = new ListType(targetElementType);
if (!left.getResultType().equals(targetType)) {
left = of.createAs().withOperand(left).withAsTypeSpecifier(dataTypeToTypeSpecifier(targetType));
left.setResultType(targetType);
}

right = of.createAs().withOperand(right).withAsTypeSpecifier(dataTypeToTypeSpecifier(targetType));
right.setResultType(targetType);
if (!right.getResultType().equals(targetType)) {
right = of.createAs().withOperand(right).withAsTypeSpecifier(dataTypeToTypeSpecifier(targetType));
right.setResultType(targetType);
}
}
}
}
Expand Down Expand Up @@ -1467,6 +1508,21 @@ private FunctionRef buildFunctionRef(String libraryName, String functionName, It
return fun;
}

private Signature preserveSignature(Iterable<Expression> params) {
List<DataType> dataTypes = new ArrayList<DataType>();
for (Expression param : params) {
dataTypes.add(param.getResultType());
}
return new Signature(dataTypes.toArray(new DataType[dataTypes.size()]));
}

private void restoreSignature(Iterable<Expression> params, Signature preservedSignature) {
Iterator<DataType> operandTypes = preservedSignature.getOperandTypes().iterator();
for (Expression param : params) {
param.setResultType(operandTypes.next());
}
}

public Invocation resolveFunction(
String libraryName,
String functionName,
Expand All @@ -1478,6 +1534,7 @@ public Invocation resolveFunction(

// Attempt normal resolution, but don't require one
Invocation invocation = new FunctionRefInvocation(fun);
Signature preservedSignature = preserveSignature(paramList);
fun = (FunctionRef) resolveCall(
fun.getLibraryName(), fun.getName(), invocation, false, allowPromotionAndDemotion, allowFluent);
if (fun != null) {
Expand All @@ -1488,16 +1545,23 @@ public Invocation resolveFunction(
// In this case, we preserve the invocation result type from the resolution and use it
DataType invocationResultType = invocation.getResolution().getInvocationResultType();
if ("System".equals(invocation.getResolution().getOperator().getLibraryName())) {
// Save the resolvedSignature so it can be restored in case the system function call does not resolve
Signature resolvedSignature = preserveSignature(paramList);
// Rebuild the fun from the original arguments, restoring the original signature,
// otherwise it will resolve with conversions in place
restoreSignature(paramList, preservedSignature);
FunctionRef systemFun = buildFunctionRef(
libraryName,
functionName,
paramList); // Rebuild the fun from the original arguments, otherwise it will resolve with
// conversions in place
paramList);
Invocation systemFunctionInvocation = systemFunctionResolver.resolveSystemFunction(systemFun);
if (systemFunctionInvocation != null) {
systemFunctionInvocation.getResolution().setInvocationResultType(invocationResultType);
systemFunctionInvocation.setResultType(invocationResultType);
return systemFunctionInvocation;
} else {
// Restore the originally resolved signature
restoreSignature(paramList, resolvedSignature);
}
} else {
// If the invocation is to a local function or a function in a non-system library, check literal context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ static void setup() throws IOException {
@Test
void union() {
ExpressionDef def = defs.get("Union123AndEmpty");
assertThat(def, hasTypeAndResult(Union.class, "list<System.Any>"));
assertThat(def, hasTypeAndResult(Union.class, "list<System.Integer>"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ codesystem "LOINC": 'http://loinc.org'

//Combine
define CombineNull : Combine(null)
define CombineEmptyList : Combine({})
define CombineEmptyList : Combine({} as List<String>)
define CombineABC : Combine({'a', 'b', 'c'})
define CombineABCSepDash : Combine({'a', 'b', 'c'}, '-')

Expand Down
12 changes: 12 additions & 0 deletions Src/java/model/src/main/java/org/hl7/cql/model/IntervalType.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public boolean isSuperTypeOf(DataType other) {
return super.isSuperTypeOf(other);
}

@Override
public boolean isCompatibleWith(DataType other) {
if (other instanceof IntervalType) {
IntervalType otherIntervalType = (IntervalType)other;
if (pointType.isCompatibleWith(otherIntervalType.pointType)) {
return true;
}
}

return super.isCompatibleWith(other);
}

@Override
public String toString() {
return String.format("interval<%s>", pointType.toString());
Expand Down
12 changes: 12 additions & 0 deletions Src/java/model/src/main/java/org/hl7/cql/model/ListType.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public boolean isSuperTypeOf(DataType other) {
return super.isSuperTypeOf(other);
}

@Override
public boolean isCompatibleWith(DataType other) {
if (other instanceof ListType) {
ListType otherListType = (ListType)other;
if (elementType.isCompatibleWith(otherListType.elementType)) {
return true;
}
}

return super.isCompatibleWith(other);
}

@Override
public String toString() {
return String.format("list<%s>", elementType.toString());
Expand Down

0 comments on commit 28cae24

Please sign in to comment.