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

Next-Generation Call Resolving #704

Closed
oxisto opened this issue Feb 10, 2022 · 1 comment
Closed

Next-Generation Call Resolving #704

oxisto opened this issue Feb 10, 2022 · 1 comment
Assignees
Labels

Comments

@oxisto
Copy link
Member

oxisto commented Feb 10, 2022

Concepts

We will introduce some new concepts in call resolving

CastResult and Language.tryCast

CastResult will be the result of the function Language.tryCast and describes whether a cast of one type into another is successful according to the logic of the Language. A default implementation is provided. It also has a property that describes the "depth" of the cast needed, which is the distance in the ancestry between base and derived class.

It is a sealed class that has the following sub-classes/objects:

  • CastNotPossible, which says that the two types are incompatible and cannot be cast into each other. It has a depth of -1.
  • DirectMatchNoCastNeeded, which says that the types directly match with a depth of 0. This is mostly for languages that have no implicit casts and directly match types to interfaces (such as Go). Also for types that are basically the same or just an alias of each other.
  • ImplicitCast (as a companion object) with a depth of 1 specifies that one (implicit) cast is needed to convert between the types. This is used in most languages to cast between numeric types.
  • ImplicitCast (as a class) with a configurable depth means that an (implicit) cast is needed between object types and depth specifies the distance between the base and derived type. We probably should rename this to something else.

SignatureResult and FunctionDeclaration.matchesSignature

SignatureResult will be the result of the function FunctionDeclaration.matchesSignature which calculates whether the provided CallExpression will match the signature of the current FunctionDeclaration. It can be configured to take into account variadic and default parameters (depending on the Language).

It is a sealed class that has the following sub-classes/objects:

  • IncompatibleSignature which specifies that the signatures do not match even after implicit casts
  • SignatureMatches specifies that the signature matches, although implicit casts might be necessary, it also has a casts parameter which contains a list of CastResult, one for each parameter. This can then later be used to compare different signature match results in order to decide which function is suitable best.

CallResolutionResult and ScopeManager.resolveCall

CallResolutionResult is the result of ScopeManager.resolveCall. It holds all necessary intermediate results as well as the final result of the call resolution. Among the results we want to store:

  • a reference to the CallExpression we are resolving
  • a list of candidateFunctions, which are the starting point of the resolution and contain all symbols with the desired name of the call in scope
  • a set of viableFunctions that restrict the candidate functions to functions whose signature match
  • the signatureResults, which is a map of function declarations and their SignatureResult
  • bestViable which contains the best viable function(s) of the viable functions. Ideally this is only one, but because of ambiguities or other factors, this can contain multiple functions.

Language.bestViableResolution

This implementation of ScopeManager.resolveCall follows a very simple version of the C++ function call resolving algorithm. It can be fine-tuned by a Language by implementing the function Language.bestViableResolution. A default implementation is provided that does the following steps:

  • If the list of viableFunctions is empty, we can directly return
  • If we have only one item in viableFunctions, we can take it
  • Next, we can check for direct matches, meaning that they have a SignatureResult that only has DirectMatchNoCastNeeded casts
  • Lastly, if we have not direct matches, we need to sort the viable functions using a simple ranking. The function(s) will the best (lowest) ranking will be chosen as the best. The ranking is determined by the "depth" of all cast results in the signature results
@oxisto oxisto added epic code-quality Issues that do not require semantic changes to the code but rather cleanup, refactoring, commenting labels Feb 10, 2022
@oxisto oxisto pinned this issue Apr 3, 2024
@oxisto oxisto changed the title Major overhaul of the call resolver Next-Generation Symbol and Call Resolving Apr 3, 2024
@oxisto oxisto self-assigned this Apr 3, 2024
@oxisto oxisto removed the code-quality Issues that do not require semantic changes to the code but rather cleanup, refactoring, commenting label Apr 3, 2024
@oxisto oxisto unpinned this issue Oct 2, 2024
@oxisto oxisto changed the title Next-Generation Symbol and Call Resolving Next-Generation Call Resolving Oct 2, 2024
@oxisto
Copy link
Member Author

oxisto commented Oct 2, 2024

Closed by #1496

@oxisto oxisto closed this as completed Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant