Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overloaded forward declarations fail to resolve #1191

Closed
JPercival opened this issue Aug 20, 2023 · 0 comments · Fixed by #1213
Closed

Overloaded forward declarations fail to resolve #1191

JPercival opened this issue Aug 20, 2023 · 0 comments · Fixed by #1213
Labels

Comments

@JPercival
Copy link
Contributor

CQL allows overloaded functions and forward declarations but not recursion. This means that it's valid for a function to reference a "yet to be defined" overload of itself. Here's an example:

define function toString(value Concept):
  if value is null
    then 'null'
  // The reference here to toString(value List<System.Code>) should _not_ result in a circular reference error
  // The function signature is distinct, therefore is should be considered a different function.
  else 'Concept { ' + toString(value.codes) + ' display: ' + value.display + ' }'

define function toString(value List<System.Code>):
    Combine(
        value C return 'Code: ' + C.display,
        ', '
    )

Here there are two overloads for "toString", one for a Concept and one for a List<System.Code>
If this file is compiled top-down, the definition for the Concept overload is encountered first. At the point in compilation of the Concept overload where it needs to work out the reference to the List<System.Code> overload, it should determine that the List<System.Code> overload is yet to be defined and compile that function.

The current buggy behavior is that the compiler tries to pick from the set of "toString" delcarations in the CQL file, finds the function that it's currently compiling, and throws a circular reference error. In other words, the function that's currently being compiled is incorrectly detected as a candidate for a forward declaration.

There's a test already set up that reproduces this behavior here:

The bug is likely in the forward declaration code which is here:

boolean checkForward = libraryName == null || libraryName.equals("") || libraryName.equals(this.libraryInfo.getLibraryName());
Expression result = libraryBuilder.resolveFunction(libraryName, functionName, expressions, !checkForward, allowPromotionAndDemotion, allowFluent);
if (result == null) {
Iterable<FunctionDefinitionInfo> functionInfos = libraryInfo.resolveFunctionReference(functionName);
if (functionInfos != null) {
for (FunctionDefinitionInfo functionInfo : functionInfos) {
String saveContext = currentContext;
currentContext = functionInfo.getContext();
try {
Stack<Chunk> saveChunks = chunks;
chunks = new Stack<Chunk>();
forwardFunctions.push(functionInfo);
try {
// Have to call the visit to allow the outer processing to occur
visit(functionInfo.getDefinition());
}
finally {
forwardFunctions.pop();
chunks = saveChunks;
}
} finally {
currentContext = saveContext;
}
}
}
result = libraryBuilder.resolveFunction(libraryName, functionName, expressions, mustResolve, allowPromotionAndDemotion, allowFluent);
}
return result;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
1 participant