summary refs log tree commit diff stats
path: root/rod/sigmatch.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/sigmatch.nim')
-rw-r--r--rod/sigmatch.nim750
1 files changed, 0 insertions, 750 deletions
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim
deleted file mode 100644
index 1bb68ef1a..000000000
--- a/rod/sigmatch.nim
+++ /dev/null
@@ -1,750 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-# This module implements the signature matching for resolving
-# the call to overloaded procs, generic procs and operators.
-
-type 
-  TCandidateState = enum 
-    csEmpty, csMatch, csNoMatch
-  TCandidate{.final.} = object 
-    exactMatches*: int
-    subtypeMatches*: int
-    intConvMatches*: int      # conversions to int are not as expensive
-    convMatches*: int
-    genericMatches*: int
-    state*: TCandidateState
-    callee*: PType            # may not be nil!
-    calleeSym*: PSym          # may be nil
-    call*: PNode              # modified call
-    bindings*: TIdTable       # maps sym-ids to types
-    baseTypeMatch*: bool      # needed for conversions from T to openarray[T]
-                              # for example
-  
-  TTypeRelation = enum        # order is important!
-    isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
-
-proc initCandidate(c: var TCandidate, callee: PType) = 
-  c.exactMatches = 0
-  c.subtypeMatches = 0
-  c.convMatches = 0
-  c.intConvMatches = 0
-  c.genericMatches = 0
-  c.state = csEmpty
-  c.callee = callee
-  c.calleeSym = nil
-  c.call = nil
-  c.baseTypeMatch = false
-  initIdTable(c.bindings)     #assert(c.callee <> nil);
-  
-proc copyCandidate(a: var TCandidate, b: TCandidate) = 
-  a.exactMatches = b.exactMatches
-  a.subtypeMatches = b.subtypeMatches
-  a.convMatches = b.convMatches
-  a.intConvMatches = b.intConvMatches
-  a.genericMatches = b.genericMatches
-  a.state = b.state
-  a.callee = b.callee
-  a.calleeSym = b.calleeSym
-  a.call = copyTree(b.call)
-  a.baseTypeMatch = b.baseTypeMatch
-  copyIdTable(a.bindings, b.bindings)
-
-proc cmpCandidates(a, b: TCandidate): int = 
-  result = a.exactMatches - b.exactMatches
-  if result != 0: return 
-  result = a.genericMatches - b.genericMatches
-  if result != 0: return 
-  result = a.subtypeMatches - b.subtypeMatches
-  if result != 0: return 
-  result = a.intConvMatches - b.intConvMatches
-  if result != 0: return 
-  result = a.convMatches - b.convMatches
-
-proc writeMatches(c: TCandidate) = 
-  Writeln(stdout, "exact matches: " & $(c.exactMatches))
-  Writeln(stdout, "subtype matches: " & $(c.subtypeMatches))
-  Writeln(stdout, "conv matches: " & $(c.convMatches))
-  Writeln(stdout, "intconv matches: " & $(c.intConvMatches))
-  Writeln(stdout, "generic matches: " & $(c.genericMatches))
-
-proc getNotFoundError(c: PContext, n: PNode): string = 
-  # Gives a detailed error message; this is seperated from semDirectCall,
-  # as semDirectCall is already pretty slow (and we need this information only
-  # in case of an error).
-  var 
-    sym: PSym
-    o: TOverloadIter
-    candidates: string
-  result = msgKindToString(errTypeMismatch)
-  for i in countup(1, sonsLen(n) - 1): 
-    #debug(n.sons[i].typ);
-    add(result, typeToString(n.sons[i].typ))
-    if i != sonsLen(n) - 1: add(result, ", ")
-  add(result, ')')
-  candidates = ""
-  sym = initOverloadIter(o, c, n.sons[0])
-  while sym != nil: 
-    if sym.kind in {skProc, skMethod, skIterator, skConverter}: 
-      add(candidates, getProcHeader(sym))
-      add(candidates, "\n")
-    sym = nextOverloadIter(o, c, n.sons[0])
-  if candidates != "": 
-    add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
-  
-proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation
-proc concreteType(mapping: TIdTable, t: PType): PType = 
-  case t.kind
-  of tyArrayConstr: 
-    # make it an array
-    result = newType(tyArray, t.owner)
-    addSon(result, t.sons[0]) # XXX: t.owner is wrong for ID!
-    addSon(result, t.sons[1]) # XXX: semantic checking for the type?
-  of tyNil: 
-    result = nil              # what should it be?
-  of tyGenericParam: 
-    result = t
-    while true: 
-      result = PType(idTableGet(mapping, t))
-      if result == nil: InternalError("lookup failed")
-      if result.kind != tyGenericParam: break 
-  else: 
-    result = t                # Note: empty is valid here
-  
-proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = 
-  var k: TTypeKind
-  if a.kind == f.kind: 
-    result = isEqual
-  else: 
-    k = skipTypes(a, {tyRange}).kind
-    if k == f.kind: result = isSubtype
-    elif (f.kind == tyInt) and (k in {tyInt..tyInt32}): result = isIntConv
-    elif (k >= min) and (k <= max): result = isConvertible
-    else: result = isNone
-  
-proc handleFloatRange(f, a: PType): TTypeRelation = 
-  var k: TTypeKind
-  if a.kind == f.kind: 
-    result = isEqual
-  else: 
-    k = skipTypes(a, {tyRange}).kind
-    if k == f.kind: result = isSubtype
-    elif (k >= tyFloat) and (k <= tyFloat128): result = isConvertible
-    else: result = isNone
-  
-proc isObjectSubtype(a, f: PType): bool = 
-  var t: PType
-  t = a
-  while (t != nil) and (t.id != f.id): t = base(t)
-  result = t != nil
-
-proc minRel(a, b: TTypeRelation): TTypeRelation = 
-  if a <= b: result = a
-  else: result = b
-  
-proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation = 
-  var 
-    x, y: PSym
-    m: TTypeRelation
-  result = isNone
-  if sonsLen(a) == sonsLen(f): 
-    result = isEqual
-    for i in countup(0, sonsLen(f) - 1): 
-      m = typeRel(mapping, f.sons[i], a.sons[i])
-      if m < isSubtype: 
-        return isNone
-      result = minRel(result, m)
-    if (f.n != nil) and (a.n != nil): 
-      for i in countup(0, sonsLen(f.n) - 1): 
-        # check field names:
-        if f.n.sons[i].kind != nkSym: InternalError(f.n.info, "tupleRel")
-        if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
-        x = f.n.sons[i].sym
-        y = a.n.sons[i].sym
-        if x.name.id != y.name.id: 
-          return isNone
-
-proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = 
-  var 
-    x, concrete: PType
-    m: TTypeRelation
-  # is a subtype of f?
-  result = isNone
-  assert(f != nil)
-  assert(a != nil)
-  if (a.kind == tyGenericInst) and
-      not (skipTypes(f, {tyVar}).kind in {tyGenericBody, tyGenericInvokation}): 
-    return typeRel(mapping, f, lastSon(a))
-  if (a.kind == tyVar) and (f.kind != tyVar): 
-    return typeRel(mapping, f, a.sons[0])
-  case f.kind
-  of tyEnum: 
-    if (a.kind == f.kind) and (a.id == f.id): result = isEqual
-    elif (skipTypes(a, {tyRange}).id == f.id): result = isSubtype
-  of tyBool, tyChar: 
-    if (a.kind == f.kind): result = isEqual
-    elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
-  of tyRange: 
-    if (a.kind == f.kind): 
-      result = typeRel(mapping, base(a), base(f))
-      if result < isGeneric: result = isNone
-    elif skipTypes(f, {tyRange}).kind == a.kind: 
-      result = isConvertible  # a convertible to f
-  of tyInt: 
-    result = handleRange(f, a, tyInt8, tyInt32)
-  of tyInt8: 
-    result = handleRange(f, a, tyInt8, tyInt8)
-  of tyInt16: 
-    result = handleRange(f, a, tyInt8, tyInt16)
-  of tyInt32: 
-    result = handleRange(f, a, tyInt, tyInt32)
-  of tyInt64: 
-    result = handleRange(f, a, tyInt, tyInt64)
-  of tyFloat: 
-    result = handleFloatRange(f, a)
-  of tyFloat32: 
-    result = handleFloatRange(f, a)
-  of tyFloat64: 
-    result = handleFloatRange(f, a)
-  of tyFloat128: 
-    result = handleFloatRange(f, a)
-  of tyVar: 
-    if (a.kind == f.kind): result = typeRel(mapping, base(f), base(a))
-    else: result = typeRel(mapping, base(f), a)
-  of tyArray, tyArrayConstr: 
-    # tyArrayConstr cannot happen really, but
-    # we wanna be safe here
-    case a.kind
-    of tyArray: 
-      result = minRel(typeRel(mapping, f.sons[0], a.sons[0]), 
-                      typeRel(mapping, f.sons[1], a.sons[1]))
-      if result < isGeneric: result = isNone
-    of tyArrayConstr: 
-      result = typeRel(mapping, f.sons[1], a.sons[1])
-      if result < isGeneric: 
-        result = isNone
-      else: 
-        if (result != isGeneric) and (lengthOrd(f) != lengthOrd(a)): 
-          result = isNone
-        elif f.sons[0].kind in GenericTypes: 
-          result = minRel(result, typeRel(mapping, f.sons[0], a.sons[0]))
-    else: 
-      nil
-  of tyOpenArray: 
-    case a.Kind
-    of tyOpenArray: 
-      result = typeRel(mapping, base(f), base(a))
-      if result < isGeneric: result = isNone
-    of tyArrayConstr: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
-        result = isSubtype    # [] is allowed here
-      elif typeRel(mapping, base(f), a.sons[1]) >= isGeneric: 
-        result = isSubtype
-    of tyArray: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
-        result = isSubtype
-      elif typeRel(mapping, base(f), a.sons[1]) >= isGeneric: 
-        result = isConvertible
-    of tySequence: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
-        result = isConvertible
-      elif typeRel(mapping, base(f), a.sons[0]) >= isGeneric: 
-        result = isConvertible
-    else: 
-      nil
-  of tySequence: 
-    case a.Kind
-    of tyNil: 
-      result = isSubtype
-    of tySequence: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
-        result = isSubtype
-      else: 
-        result = typeRel(mapping, f.sons[0], a.sons[0])
-        if result < isGeneric: result = isNone
-    else: 
-      nil
-  of tyOrdinal: 
-    if isOrdinalType(a): 
-      if a.kind == tyOrdinal: x = a.sons[0]
-      else: x = a
-      result = typeRel(mapping, f.sons[0], x)
-      if result < isGeneric: result = isNone
-  of tyForward: 
-    InternalError("forward type in typeRel()")
-  of tyNil: 
-    if a.kind == f.kind: result = isEqual
-  of tyTuple: 
-    if a.kind == tyTuple: result = tupleRel(mapping, f, a)
-  of tyObject: 
-    if a.kind == tyObject: 
-      if a.id == f.id: result = isEqual
-      elif isObjectSubtype(a, f): result = isSubtype
-  of tyDistinct: 
-    if (a.kind == tyDistinct) and (a.id == f.id): result = isEqual
-  of tySet: 
-    if a.kind == tySet: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
-        result = isSubtype
-      else: 
-        result = typeRel(mapping, f.sons[0], a.sons[0])
-        if result <= isConvertible: 
-          result = isNone     # BUGFIX!
-  of tyPtr: 
-    case a.kind
-    of tyPtr: 
-      result = typeRel(mapping, base(f), base(a))
-      if result <= isConvertible: result = isNone
-    of tyNil: 
-      result = isSubtype
-    else: 
-      nil
-  of tyRef: 
-    case a.kind
-    of tyRef: 
-      result = typeRel(mapping, base(f), base(a))
-      if result <= isConvertible: result = isNone
-    of tyNil: 
-      result = isSubtype
-    else: 
-      nil
-  of tyProc: 
-    case a.kind
-    of tyNil: 
-      result = isSubtype
-    of tyProc: 
-      if (sonsLen(f) == sonsLen(a)) and (f.callconv == a.callconv): 
-        # Note: We have to do unification for the parameters before the
-        # return type!
-        result = isEqual      # start with maximum; also correct for no
-                              # params at all
-        for i in countup(1, sonsLen(f) - 1): 
-          m = typeRel(mapping, f.sons[i], a.sons[i])
-          if (m == isNone) and
-              (typeRel(mapping, a.sons[i], f.sons[i]) == isSubtype): 
-            # allow ``f.son`` as subtype of ``a.son``!
-            result = isConvertible
-          elif m < isSubtype: 
-            return isNone
-          else: 
-            result = minRel(m, result)
-        if f.sons[0] != nil: 
-          if a.sons[0] != nil: 
-            m = typeRel(mapping, f.sons[0], a.sons[0]) # Subtype is sufficient for return types!
-            if m < isSubtype: result = isNone
-            elif m == isSubtype: result = isConvertible
-            else: result = minRel(m, result)
-          else: 
-            result = isNone
-        elif a.sons[0] != nil: 
-          result = isNone
-        if (tfNoSideEffect in f.flags) and not (tfNoSideEffect in a.flags): 
-          result = isNone
-    else: 
-      nil
-  of tyPointer: 
-    case a.kind
-    of tyPointer: result = isEqual
-    of tyNil: result = isSubtype
-    of tyRef, tyPtr, tyProc, tyCString: result = isConvertible
-    else: 
-      nil
-  of tyString: 
-    case a.kind
-    of tyString: result = isEqual
-    of tyNil: result = isSubtype
-    else: 
-      nil
-  of tyCString: 
-    # conversion from string to cstring is automatic:
-    case a.Kind
-    of tyCString: 
-      result = isEqual
-    of tyNil: 
-      result = isSubtype
-    of tyString: 
-      result = isConvertible
-    of tyPtr: 
-      if a.sons[0].kind == tyChar: result = isConvertible
-    of tyArray: 
-      if (firstOrd(a.sons[0]) == 0) and
-          (skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
-          (a.sons[1].kind == tyChar): 
-        result = isConvertible
-    else: 
-      nil
-  of tyEmpty: 
-    if a.kind == tyEmpty: result = isEqual
-  of tyGenericInst: 
-    result = typeRel(mapping, lastSon(f), a)
-  of tyGenericBody: 
-    result = typeRel(mapping, lastSon(f), a)
-  of tyGenericInvokation: 
-    assert(f.sons[0].kind == tyGenericBody)
-    if a.kind == tyGenericInvokation: 
-      InternalError("typeRel: tyGenericInvokation -> tyGenericInvokation")
-    if (a.kind == tyGenericInst): 
-      if (f.sons[0].containerID == a.sons[0].containerID) and
-          (sonsLen(a) - 1 == sonsLen(f)): 
-        assert(a.sons[0].kind == tyGenericBody)
-        for i in countup(1, sonsLen(f) - 1): 
-          if a.sons[i].kind == tyGenericParam: 
-            InternalError("wrong instantiated type!")
-          if typeRel(mapping, f.sons[i], a.sons[i]) < isGeneric: return 
-        result = isGeneric
-    else: 
-      result = typeRel(mapping, f.sons[0], a)
-      if result != isNone: 
-        # we steal the generic parameters from the tyGenericBody:
-        for i in countup(1, sonsLen(f) - 1): 
-          x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
-          if (x == nil) or (x.kind == tyGenericParam): 
-            InternalError("wrong instantiated type!")
-          idTablePut(mapping, f.sons[i], x)
-  of tyGenericParam: 
-    x = PType(idTableGet(mapping, f))
-    if x == nil: 
-      if sonsLen(f) == 0: 
-        # no constraints
-        concrete = concreteType(mapping, a)
-        if concrete != nil: 
-          #MessageOut('putting: ' + f.sym.name.s);
-          idTablePut(mapping, f, concrete)
-          result = isGeneric
-      else: 
-        InternalError(f.sym.info, "has constraints: " & f.sym.name.s) # check 
-                                                                      # constraints:
-        for i in countup(0, sonsLen(f) - 1): 
-          if typeRel(mapping, f.sons[i], a) >= isSubtype: 
-            concrete = concreteType(mapping, a)
-            if concrete != nil: 
-              idTablePut(mapping, f, concrete)
-              result = isGeneric
-            break 
-    elif a.kind == tyEmpty: 
-      result = isGeneric
-    elif x.kind == tyGenericParam: 
-      result = isGeneric
-    else: 
-      result = typeRel(mapping, x, a) # check if it fits
-  of tyExpr, tyStmt, tyTypeDesc: 
-    if a.kind == f.kind: 
-      result = isEqual
-    else: 
-      case a.kind
-      of tyExpr, tyStmt, tyTypeDesc: result = isGeneric
-      of tyNil: result = isSubtype
-      else: 
-        nil
-  else: internalError("typeRel(" & $f.kind & ')')
-  
-proc cmpTypes(f, a: PType): TTypeRelation = 
-  var mapping: TIdTable
-  InitIdTable(mapping)
-  result = typeRel(mapping, f, a)
-
-proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, 
-                         f: PType): PType = 
-  result = PType(idTableGet(m.bindings, f))
-  if result == nil: 
-    result = generateTypeInstance(c, m.bindings, arg, f)
-  if result == nil: InternalError(arg.info, "getInstantiatedType")
-  
-proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, 
-                  c: PContext): PNode = 
-  result = newNodeI(kind, arg.info)
-  if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
-  else: result.typ = f
-  if result.typ == nil: InternalError(arg.info, "implicitConv")
-  addSon(result, nil)
-  addSon(result, arg)
-
-proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                   arg: PNode): PNode = 
-  result = nil
-  for i in countup(0, len(c.converters) - 1): 
-    var src = c.converters[i].typ.sons[1]
-    var dest = c.converters[i].typ.sons[0]
-    if (typeRel(m.bindings, f, dest) == isEqual) and
-        (typeRel(m.bindings, src, a) == isEqual): 
-      var s = newSymNode(c.converters[i])
-      s.typ = c.converters[i].typ
-      s.info = arg.info
-      result = newNodeIT(nkHiddenCallConv, arg.info, s.typ.sons[0])
-      addSon(result, s)
-      addSon(result, copyTree(arg))
-      inc(m.convMatches)
-      return 
-
-proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, 
-                        arg: PNode): PNode = 
-  var r = typeRel(m.bindings, f, a)
-  case r
-  of isConvertible: 
-    inc(m.convMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isIntConv: 
-    inc(m.intConvMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isSubtype: 
-    inc(m.subtypeMatches)
-    result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
-  of isGeneric: 
-    inc(m.genericMatches)
-    result = copyTree(arg)
-    result.typ = getInstantiatedType(c, arg, m, f) 
-    # BUG: f may not be the right key!
-    if (skipTypes(result.typ, abstractVar).kind in {tyTuple, tyOpenArray}): 
-      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) 
-      # BUGFIX: use ``result.typ`` and not `f` here
-  of isEqual: 
-    inc(m.exactMatches)
-    result = copyTree(arg)
-    if (skipTypes(f, abstractVar).kind in {tyTuple, tyOpenArray}): 
-      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isNone: 
-    result = userConvMatch(c, m, f, a, arg) 
-    # check for a base type match, which supports openarray[T] without []
-    # constructor in a call:
-    if (result == nil) and (f.kind == tyOpenArray): 
-      r = typeRel(m.bindings, base(f), a)
-      if r >= isGeneric: 
-        inc(m.convMatches)
-        result = copyTree(arg)
-        if r == isGeneric: result.typ = getInstantiatedType(c, arg, m, base(f))
-        m.baseTypeMatch = true
-      else: 
-        result = userConvMatch(c, m, base(f), a, arg)
-  
-proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                     arg: PNode): PNode = 
-  var 
-    cmp, best: int
-    x, y, z: TCandidate
-    r: TTypeRelation
-  if (arg == nil) or (arg.kind != nkSymChoice): 
-    result = ParamTypesMatchAux(c, m, f, a, arg)
-  else: 
-    # CAUTION: The order depends on the used hashing scheme. Thus it is
-    # incorrect to simply use the first fitting match. However, to implement
-    # this correctly is inefficient. We have to copy `m` here to be able to
-    # roll back the side effects of the unification algorithm.
-    initCandidate(x, m.callee)
-    initCandidate(y, m.callee)
-    initCandidate(z, m.callee)
-    x.calleeSym = m.calleeSym
-    y.calleeSym = m.calleeSym
-    z.calleeSym = m.calleeSym
-    best = - 1
-    for i in countup(0, sonsLen(arg) - 1): 
-      # iterators are not first class yet, so ignore them
-      if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}: 
-        copyCandidate(z, m)
-        r = typeRel(z.bindings, f, arg.sons[i].typ)
-        if r != isNone: 
-          case x.state
-          of csEmpty, csNoMatch: 
-            x = z
-            best = i
-            x.state = csMatch
-          of csMatch: 
-            cmp = cmpCandidates(x, z)
-            if cmp < 0: 
-              best = i
-              x = z
-            elif cmp == 0: 
-              y = z           # z is as good as x
-            else: 
-              nil
-    if x.state == csEmpty: 
-      result = nil
-    elif (y.state == csMatch) and (cmpCandidates(x, y) == 0): 
-      if x.state != csMatch: 
-        InternalError(arg.info, "x.state is not csMatch") 
-      # ambiguous: more than one symbol fits
-      result = nil
-    else: 
-      # only one valid interpretation found:
-      markUsed(arg, arg.sons[best].sym)
-      result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best])
-
-proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode = 
-  var m: TCandidate
-  initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, a, arg)
-
-proc setSon(father: PNode, at: int, son: PNode) = 
-  if sonsLen(father) <= at: setlen(father.sons, at + 1)
-  father.sons[at] = son
-
-proc matches(c: PContext, n: PNode, m: var TCandidate) = 
-  var f = 1 # iterates over formal parameters
-  var a = 1 # iterates over the actual given arguments
-  m.state = csMatch           # until proven otherwise
-  m.call = newNodeI(nkCall, n.info)
-  m.call.typ = base(m.callee) # may be nil
-  var formalLen = sonsLen(m.callee.n)
-  addSon(m.call, copyTree(n.sons[0]))
-  var marker: TIntSet
-  IntSetInit(marker)
-  var container: PNode = nil # constructed container
-  var formal: PSym = nil
-  while a < sonsLen(n): 
-    if n.sons[a].kind == nkExprEqExpr: 
-      # named param
-      # check if m.callee has such a param:
-      if n.sons[a].sons[0].kind != nkIdent: 
-        liMessage(n.sons[a].info, errNamedParamHasToBeIdent)
-        m.state = csNoMatch
-        return 
-      formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
-      if formal == nil: 
-        # no error message!
-        m.state = csNoMatch
-        return 
-      if IntSetContainsOrIncl(marker, formal.position): 
-        # already in namedParams:
-        liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
-        m.state = csNoMatch
-        return 
-      m.baseTypeMatch = false
-      var arg = ParamTypesMatch(c, m, formal.typ, 
-                                      n.sons[a].typ, n.sons[a].sons[1])
-      if (arg == nil): 
-        m.state = csNoMatch
-        return 
-      if m.baseTypeMatch: 
-        assert(container == nil)
-        container = newNodeI(nkBracket, n.sons[a].info)
-        addSon(container, arg)
-        setSon(m.call, formal.position + 1, container)
-        if f != formalLen - 1: container = nil
-      else: 
-        setSon(m.call, formal.position + 1, arg)
-    else: 
-      # unnamed param
-      if f >= formalLen: 
-        # too many arguments?
-        if tfVarArgs in m.callee.flags: 
-          # is ok... but don't increment any counters...
-          if skipTypes(n.sons[a].typ, abstractVar).kind == tyString: 
-            addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString), 
-                                        copyTree(n.sons[a]), m, c))
-          else: 
-            addSon(m.call, copyTree(n.sons[a]))
-        elif formal != nil: 
-          m.baseTypeMatch = false
-          var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
-          if (arg != nil) and m.baseTypeMatch and (container != nil): 
-            addSon(container, arg)
-          else: 
-            m.state = csNoMatch
-            return 
-        else: 
-          m.state = csNoMatch
-          return 
-      else: 
-        if m.callee.n.sons[f].kind != nkSym: 
-          InternalError(n.sons[a].info, "matches")
-        formal = m.callee.n.sons[f].sym
-        if IntSetContainsOrIncl(marker, formal.position): 
-          # already in namedParams:
-          liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
-          m.state = csNoMatch
-          return 
-        m.baseTypeMatch = false
-        var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
-        if (arg == nil): 
-          m.state = csNoMatch
-          return 
-        if m.baseTypeMatch: 
-          assert(container == nil)
-          container = newNodeI(nkBracket, n.sons[a].info)
-          addSon(container, arg)
-          setSon(m.call, formal.position + 1, 
-                 implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
-          if f != formalLen - 1: container = nil
-        else: 
-          setSon(m.call, formal.position + 1, arg)
-    inc(a)
-    inc(f)
-  f = 1
-  while f < sonsLen(m.callee.n): 
-    formal = m.callee.n.sons[f].sym
-    if not IntSetContainsOrIncl(marker, formal.position): 
-      if formal.ast == nil: 
-        # no default value
-        m.state = csNoMatch
-        break 
-      else: 
-        # use default value:
-        setSon(m.call, formal.position + 1, copyTree(formal.ast))
-    inc(f)
-
-proc sameMethodDispatcher(a, b: PSym): bool = 
-  result = false
-  if (a.kind == skMethod) and (b.kind == skMethod): 
-    var aa = lastSon(a.ast)
-    var bb = lastSon(b.ast)
-    if (aa.kind == nkSym) and (bb.kind == nkSym) and (aa.sym == bb.sym): 
-      result = true
-  
-proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = 
-  var 
-    o: TOverloadIter
-    x, y, z: TCandidate
-  #liMessage(n.info, warnUser, renderTree(n));
-  var sym = initOverloadIter(o, c, n.sons[0])
-  result = nil
-  if sym == nil: return 
-  initCandidate(x, sym.typ)
-  x.calleeSym = sym
-  initCandidate(y, sym.typ)
-  y.calleeSym = sym
-  while sym != nil: 
-    if sym.kind in filter: 
-      initCandidate(z, sym.typ)
-      z.calleeSym = sym
-      matches(c, n, z)
-      if z.state == csMatch: 
-        case x.state
-        of csEmpty, csNoMatch: 
-          x = z
-        of csMatch: 
-          var cmp = cmpCandidates(x, z)
-          if cmp < 0: 
-            x = z             # z is better than x
-          elif cmp == 0: 
-            y = z             # z is as good as x
-          else: 
-            nil
-    sym = nextOverloadIter(o, c, n.sons[0])
-  if x.state == csEmpty: 
-    # no overloaded proc found
-    # do not generate an error yet; the semantic checking will check for
-    # an overloaded () operator
-  elif (y.state == csMatch) and (cmpCandidates(x, y) == 0) and
-      not sameMethodDispatcher(x.calleeSym, y.calleeSym): 
-    if x.state != csMatch: 
-      InternalError(n.info, "x.state is not csMatch") #writeMatches(x);
-                                                      #writeMatches(y);
-    liMessage(n.Info, errGenerated, `%`(msgKindToString(errAmbiguousCallXYZ), [
-        getProcHeader(x.calleeSym), getProcHeader(y.calleeSym), 
-        x.calleeSym.Name.s]))
-  else: 
-    # only one valid interpretation found:
-    markUsed(n, x.calleeSym)
-    if x.calleeSym.ast == nil: 
-      internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
-    if x.calleeSym.ast.sons[genericParamsPos] != nil: 
-      # a generic proc!
-      x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
-      x.callee = x.calleeSym.typ
-    result = x.call
-    result.sons[0] = newSymNode(x.calleeSym)
-    result.typ = x.callee.sons[0]