compiler/sem/sigmatch

    Dark Mode
Search:
  Source   Edit

This module implements the signature matching for resolving the call to overloaded procs, generic procs and operators.

Types

TCandidate = object
  c*: PContext
  exactMatches*: int         ## also misused to prefer iters over procs
  genericMatches: int        ## also misused to prefer constraints
  subtypeMatches: int
  intConvMatches: int        ## conversions to int are not as expensive
  convMatches: int
  state*: TCandidateState
  callee*: PType             ## may not be nil!
  calleeSym*: PSym           ## may be nil
  calleeScope*: int          ## scope depth:
                             ## is this a top-level symbol or a nested proc?
  call*: PNode               ## modified call
  bindings*: TIdTable        ## maps types to types
  magic*: TMagic             ## magic of operation
  baseTypeMatch: bool        ## needed for conversions from T to openarray[T]
                             ## for example
  fauxMatch*: TTypeKind      ## the match was successful only due to the use
                             ## of error or wildcard (unknown) types.
                             ## this is used to prevent instantiations.
  genericConverter*: bool    ## true if a generic converter needs to
                             ## be instantiated
  coerceDistincts*: bool     ## this is an explicit coercion that can strip away
                             ## a distrinct type
  typedescMatched*: bool
  isNoCall*: bool            ## misused for generic type instantiations C[T]
  inferredTypes: seq[PType]  ## inferred types during the current signature
                             ## matching. they will be reset if the matching
                             ## is not successful. may replace the bindings
                             ## table in the future.
  inheritancePenalty: int    ## to prefer closest father object type
  error*: SemCallMismatch
  Source   Edit
TCandidateState = enum
  csEmpty, csMatch, csNoMatch
  Source   Edit
TTypeRelFlag = enum
  trDontBind, trNoCovariance, trBindGenericParam ## bind tyGenericParam even with trDontBind
  Source   Edit

Procs

proc argtypeMatches(c: PContext; f, a: PType; fromHlo = false): bool {.
    ...raises: [Exception, KeyError, ERecoverableError],
    tags: [RootEffect, ReadIOEffect].}
  Source   Edit
proc cmpCandidates(a, b: TCandidate): int {....raises: [Exception],
    tags: [RootEffect].}
  Source   Edit
proc cmpTypes(c: PContext; f, a: PType): TTypeRelation {.
    ...raises: [KeyError, Exception, ERecoverableError], tags: [RootEffect].}
  Source   Edit
proc inferStaticParam(c: var TCandidate; lhs: PNode; rhs: BiggestInt): bool {.
    ...raises: [], tags: [].}

This is a simple integer arithimetic equation solver, capable of deriving the value of a static parameter in expressions such as (N + 5) / 2 = rhs

Preconditions:

  • The input of this proc must be semantized
    • all templates should be expanded
    • aby constant folding possible should already be performed
  • There must be exactly one unresolved static parameter
Result:
The proc will return true if the static types was successfully inferred. The result will be bound to the original static type in the TCandidate.
  Source   Edit
proc initCallCandidate(ctx: PContext; c: var TCandidate; callee: PSym;
                       calleeScope = -1) {....raises: [], tags: [].}
  Source   Edit
proc initCandidate(ctx: PContext; c: var TCandidate; callee: PType) {.
    ...raises: [], tags: [].}
  Source   Edit
proc instTypeBoundOp(c: PContext; dc: PSym; t: PType; info: TLineInfo;
                     op: TTypeAttachedOp; col: int): PSym {.nosinks,
    ...raises: [Exception, ERecoverableError, KeyError], tags: [RootEffect].}
  Source   Edit
proc matches(c: PContext; n, nOrig: PNode; m: var TCandidate) {.
    ...raises: [KeyError, Exception, ERecoverableError],
    tags: [RootEffect, ReadIOEffect, ReadDirEffect].}
  Source   Edit
proc matchesGenericParams(c: PContext; args: PNode; m: var TCandidate) {.
    ...raises: [KeyError, Exception, ERecoverableError], tags: [RootEffect].}

Matches the provided generic arguments args (stored as a nkBracketExpr) against the candidate's generic parameters. Updates m with whether or not there was a match.

The arguments must strictly match the parameters -- them not being exactly equal means no match.

XXX: this strictness might be subject to change

  Source   Edit
proc matchUserTypeClass(m: var TCandidate; ff, a: PType): PType {.
    ...raises: [Exception, ERecoverableError, KeyError], tags: [RootEffect].}
  Source   Edit
proc newCallCandidate(ctx: PContext; callee: PSym; calleeScope = -1): TCandidate {.
    ...raises: [], tags: [].}
  Source   Edit
proc newCandidate(ctx: PContext; callee: PType): TCandidate {....raises: [],
    tags: [].}
  Source   Edit
proc paramTypesMatch(candidate: var TCandidate; formal, passed: PType;
                     arg: PNode): PNode {.
    ...raises: [Exception, KeyError, ERecoverableError],
    tags: [RootEffect, ReadIOEffect].}
Try to check a single argument for the candidate function call using provided formal parmameter and passed one. arg is a node that was passed from the callsite   Source   Edit
proc partialMatch(c: PContext; n, nOrig: PNode; m: var TCandidate) {.
    ...raises: [KeyError, Exception, ERecoverableError],
    tags: [RootEffect, ReadDirEffect, ReadIOEffect].}
  Source   Edit
proc semFinishOperands(c: PContext; n: PNode) {....raises: [Exception],
    tags: [RootEffect].}
  Source   Edit
proc toDebugCallableCandidate(c: TCandidate): DebugCallableCandidate {.
    ...raises: [], tags: [].}
  Source   Edit
proc typeRel(c: var TCandidate; f, aOrig: PType; flags: TTypeRelFlags = {}): TTypeRelation {.
    ...raises: [KeyError, Exception, ERecoverableError], tags: [RootEffect].}
typeRel can be used to establish various relationships between types:
  1. When used with concrete types, it will check for type equivalence
    or a subtype relationship.
  2. When used with a concrete type against a type class (such as generic signature of a proc), it will check whether the concrete type is a member of the designated type class.
  3. When used with two type classes, it will check whether the types matching the first type class are a strict subset of the types matching the other. This allows us to compare the signatures of generic procs in order to give preferrence to the most specific one:

seq[seq[any]] is a strict subset of seq[any] and hence more specific.

  Source   Edit
proc writeMatches(c: TCandidate) {....raises: [KeyError, Exception],
                                   tags: [ReadDirEffect, RootEffect].}
  Source   Edit

Templates

template hasFauxMatch(c: TCandidate): bool
  Source   Edit