summary refs log tree commit diff stats
path: root/rod
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-laptop>2010-05-28 23:32:46 +0200
committerAndreas Rumpf <andreas@andreas-laptop>2010-05-28 23:32:46 +0200
commit6c2050912166a4960b40c3825afb1a31cfdde0eb (patch)
treed753cb2baa1d18d4798d64a564fdb692c54146f7 /rod
parente90665bff2e062598b51ada915c4861db6e94a8d (diff)
downloadNim-6c2050912166a4960b40c3825afb1a31cfdde0eb.tar.gz
explicit types for generic routines
Diffstat (limited to 'rod')
-rwxr-xr-xrod/docgen.nim11
-rwxr-xr-xrod/evals.nim3
-rwxr-xr-xrod/semexprs.nim2
-rwxr-xr-xrod/seminst.nim59
-rwxr-xr-xrod/semstmts.nim5
-rwxr-xr-xrod/semtypes.nim135
-rwxr-xr-xrod/sigmatch.nim54
-rwxr-xr-xrod/transf.nim106
8 files changed, 186 insertions, 189 deletions
diff --git a/rod/docgen.nim b/rod/docgen.nim
index 10516bf73..9da191d8d 100755
--- a/rod/docgen.nim
+++ b/rod/docgen.nim
@@ -417,23 +417,20 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
   # debugging, but most code is already debugged...
   const 
     lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
-  var 
-    L: int
-    ind: PRope
   result = nil
   if n == nil: return 
-  ind = toRope(repeatChar(d.indent))
+  var ind = toRope(repeatChar(d.indent))
   case n.kind
   of rnInner: 
     result = renderRstSons(d, n)
   of rnHeadline: 
     result = renderRstSons(d, n)
-    L = ropeLen(result)
+    var L = ropeLen(result)
     result = ropef("$n$1$2$n$1$3", 
                    [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
   of rnOverline: 
     result = renderRstSons(d, n)
-    L = ropeLen(result)
+    var L = ropeLen(result)
     result = ropef("$n$1$3$n$1$2$n$1$3", 
                    [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
   of rnTransition: 
@@ -464,7 +461,7 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
     dec(d.indent, 2)
   of rnField: 
     result = renderRstToRst(d, n.sons[0])
-    L = max(ropeLen(result) + 3, 30)
+    var L = max(ropeLen(result) + 3, 30)
     inc(d.indent, L)
     result = ropef("$n$1:$2:$3$4", [ind, result, toRope(
         repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])])
diff --git a/rod/evals.nim b/rod/evals.nim
index 7306f61b1..4232bb832 100755
--- a/rod/evals.nim
+++ b/rod/evals.nim
@@ -714,8 +714,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
     var a = result
     result = newNodeIT(nkIntLit, n.info, n.typ)
     case a.kind
-    of nkEmpty..nkNilLit: 
-      nil
+    of nkEmpty..nkNilLit: nil
     else: result.intVal = sonsLen(a)
   of mNChild: 
     result = evalAux(c, n.sons[1], {efLValue})
diff --git a/rod/semexprs.nim b/rod/semexprs.nim
index 8d8b627eb..6ce1628d5 100755
--- a/rod/semexprs.nim
+++ b/rod/semexprs.nim
@@ -1022,8 +1022,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     var s = qualifiedLookup(c, n.sons[0], false)
     if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}: 
       # type parameters: partial generic specialization
-      # XXX: too implement!
-      internalError(n.info, "explicit generic instantation not implemented")
       result = partialSpecialization(c, n, s)
     else: 
       result = semArrayAccess(c, n, flags)
diff --git a/rod/seminst.nim b/rod/seminst.nim
index ba1f05cb2..417922825 100755
--- a/rod/seminst.nim
+++ b/rod/seminst.nim
@@ -1,29 +1,28 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
+
 # This module does the instantiation of generic procs and types.
 
-proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym
+proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
+                      info: TLineInfo): PSym
   # generates an instantiated proc
 proc searchInstTypes(tab: TIdTable, key: PType): PType = 
-  var 
-    t: PType
-    match: bool
   # returns nil if we need to declare this type
   result = PType(IdTableGet(tab, key))
   if (result == nil) and (tab.counter > 0): 
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
     for h in countup(0, high(tab.data)): 
-      t = PType(tab.data[h].key)
+      var t = PType(tab.data[h].key)
       if t != nil: 
         if key.containerId == t.containerID: 
-          match = true
+          var match = true
           for j in countup(0, sonsLen(t) - 1): 
             # XXX sameType is not really correct for nested generics?
             if not sameType(t.sons[j], key.sons[j]): 
@@ -39,20 +38,16 @@ proc containsGenericType(t: PType): bool =
   result = iterOverType(t, containsGenericTypeIter, nil)
 
 proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = 
-  var 
-    s, q: PSym
-    t: PType
-    a: PNode
   if (n.kind != nkGenericParams): 
     InternalError(n.info, "instantiateGenericParamList; no generic params")
   for i in countup(0, sonsLen(n) - 1): 
-    a = n.sons[i]
+    var a = n.sons[i]
     if a.kind != nkSym: 
       InternalError(a.info, "instantiateGenericParamList; no symbol")
-    q = a.sym
+    var q = a.sym
     if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue 
-    s = newSym(skType, q.name, getCurrOwner())
-    t = PType(IdTableGet(pt, q.typ))
+    var s = newSym(skType, q.name, getCurrOwner())
+    var t = PType(IdTableGet(pt, q.typ))
     if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
     if (t.kind == tyGenericParam): 
       InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
@@ -60,27 +55,26 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
     addDecl(c, s)
 
 proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym = 
-  var a, b: PSym
   result = nil
   for i in countup(0, sonsLen(c.generics) - 1): 
     if c.generics.sons[i].kind != nkExprEqExpr: 
       InternalError(genericSym.info, "GenericCacheGet")
-    a = c.generics.sons[i].sons[0].sym
+    var a = c.generics.sons[i].sons[0].sym
     if genericSym.id == a.id: 
-      b = c.generics.sons[i].sons[1].sym
+      var b = c.generics.sons[i].sons[1].sym
       if equalParams(b.typ.n, instSym.typ.n) == paramsEqual: 
         #if gVerbosity > 0 then 
         #  MessageOut('found in cache: ' + getProcHeader(instSym));
         return b
 
 proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) = 
-  var n: PNode
-  n = newNode(nkExprEqExpr)
+  var n = newNode(nkExprEqExpr)
   addSon(n, newSymNode(genericSym))
   addSon(n, newSymNode(instSym))
   addSon(c.generics, n)
 
-proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym = 
+proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, 
+                      info: TLineInfo): PSym = 
   # generates an instantiated proc
   var 
     oldPrc, oldMod: PSym
@@ -89,8 +83,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSy
   if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
   inc(c.InstCounter)
   oldP = c.p # restore later
-             # NOTE: for access of private fields within generics from a different module
-             # and other identifiers we fake the current module temporarily!
+  # NOTE: for access of private fields within generics from a different module
+  # and other identifiers we fake the current module temporarily!
   oldMod = c.module
   c.module = getModule(fn)
   result = copySym(fn, false)
@@ -151,8 +145,6 @@ type
 proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType
 proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
 proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = 
-  var length: int
-  result = nil
   if n != nil: 
     result = copyNode(n)
     result.typ = ReplaceTypeVarsT(cl, n.typ)
@@ -162,7 +154,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
     of nkSym: 
       result.sym = ReplaceTypeVarsS(cl, n.sym)
     else: 
-      length = sonsLen(n)
+      var length = sonsLen(n)
       if length > 0: 
         newSons(result, length)
         for i in countup(0, length - 1): 
@@ -172,7 +164,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
   if s == nil: 
     return nil
   result = PSym(idTableGet(cl.symMap, s))
-  if (result == nil): 
+  if result == nil: 
     result = copySym(s, false)
     incl(result.flags, sfFromGeneric)
     idTablePut(cl.symMap, s, result)
@@ -229,8 +221,9 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
         result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
       result.n = ReplaceTypeVarsN(cl, result.n)
       if result.Kind in GenericTypes: 
-        liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) #writeln(output, ropeToStr(Typetoyaml(result)));
-                                                                               #checkConstructedType(cl.info, result);
+        liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
+        #writeln(output, ropeToStr(Typetoyaml(result)))
+        #checkConstructedType(cl.info, result)
   
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType = 
   var cl: TReplTypeVars
@@ -240,7 +233,8 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
   cl.c = c
   result = ReplaceTypeVarsT(cl, header)
 
-proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PType = 
+proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, 
+                          t: PType): PType = 
   var cl: TReplTypeVars
   InitIdTable(cl.symMap)
   copyIdTable(cl.typeMap, pt)
@@ -251,4 +245,9 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PTyp
   popInfoContext()
 
 proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode = 
+  for i in 1..sonsLen(n)-1:
+    n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
+  # we cannot check for the proper number of type parameters because in
+  # `f[a,b](x, y)` `f` is not resolved yet properly.
+  # XXX: BUG this should be checked somehow!
   result = n
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index b07e724bc..0f96e5b94 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -6,6 +6,7 @@
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
+
 # this module does the semantic checking of statements
 
 proc semExprNoType(c: PContext, n: PNode): PNode =
@@ -267,14 +268,13 @@ proc SemReturn(c: PContext, n: PNode): PNode =
       liMessage(n.info, errCannotReturnExpr)
   
 proc SemYield(c: PContext, n: PNode): PNode = 
-  var restype: PType
   result = n
   checkSonsLen(n, 1)
   if (c.p.owner == nil) or (c.p.owner.kind != skIterator): 
     liMessage(n.info, errYieldNotAllowedHere)
   if (n.sons[0] != nil): 
     n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
-    restype = c.p.owner.typ.sons[0]
+    var restype = c.p.owner.typ.sons[0]
     if (restype != nil): 
       n.sons[0] = fitNode(c, restype, n.sons[0])
       if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
@@ -477,6 +477,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
         s = newSymS(skType, a.sons[j], c)
         s.typ = newTypeS(tyGenericParam, c)
       else: 
+        # not a type param, but an expression
         s = newSymS(skGenericParam, a.sons[j], c)
         s.typ = typ
       s.ast = def
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index f4b17f071..a88490ce0 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -6,6 +6,7 @@
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
+
 # this module does the semantic checking of type declarations
 
 proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = 
@@ -63,10 +64,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
     inc(counter)
 
 proc semSet(c: PContext, n: PNode, prev: PType): PType = 
-  var base: PType
   result = newOrPrevType(tySet, prev, c)
   if sonsLen(n) == 2: 
-    base = semTypeNode(c, n.sons[1], nil)
+    var base = semTypeNode(c, n.sons[1], nil)
     addSon(result, base)
     if base.kind == tyGenericInst: base = lastSon(base)
     if base.kind != tyGenericParam: 
@@ -77,29 +77,26 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
   
 proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
                   prev: PType): PType = 
-  var base: PType
   result = newOrPrevType(kind, prev, c)
   if sonsLen(n) == 2: 
-    base = semTypeNode(c, n.sons[1], nil)
+    var base = semTypeNode(c, n.sons[1], nil)
     addSon(result, base)
   else: 
     liMessage(n.info, errXExpectsOneTypeParam, kindStr)
   
 proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
                prev: PType): PType = 
-  var base: PType
   result = newOrPrevType(kind, prev, c)
   if sonsLen(n) == 1: 
-    base = semTypeNode(c, n.sons[0], nil)
+    var base = semTypeNode(c, n.sons[0], nil)
     addSon(result, base)
   else: 
     liMessage(n.info, errXExpectsOneTypeParam, kindStr)
   
 proc semVarType(c: PContext, n: PNode, prev: PType): PType = 
-  var base: PType
   result = newOrPrevType(tyVar, prev, c)
   if sonsLen(n) == 1: 
-    base = semTypeNode(c, n.sons[0], nil)
+    var base = semTypeNode(c, n.sons[0], nil)
     if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
     addSon(result, base)
   else: 
@@ -111,15 +108,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
   else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
   
 proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 
-  var a, b: PNode
   if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
   checkSonsLen(n, 2)
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
   if (n.sons[0] == nil) or (n.sons[1] == nil): 
     liMessage(n.Info, errRangeIsEmpty)
-  a = semConstExpr(c, n.sons[0])
-  b = semConstExpr(c, n.sons[1])
+  var a = semConstExpr(c, n.sons[0])
+  var b = semConstExpr(c, n.sons[1])
   if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
   if not (a.typ.kind in
       {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): 
@@ -159,10 +155,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     liMessage(n.info, errArrayExpectsTwoTypeParams)
   
 proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = 
-  var base: PType
   result = newOrPrevType(tyOrdinal, prev, c)
   if sonsLen(n) == 2: 
-    base = semTypeNode(c, n.sons[1], nil)
+    var base = semTypeNode(c, n.sons[1], nil)
     if base.kind != tyGenericParam: 
       if not isOrdinalType(base): 
         liMessage(n.sons[1].info, errOrdinalTypeExpected)
@@ -231,7 +226,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
                  allowed: TSymFlags): PSym = 
   # identifier with visibility
   if n.kind == nkPostfix: 
-    if (sonsLen(n) == 2) and (n.sons[0].kind == nkIdent): 
+    if sonsLen(n) == 2 and n.sons[0].kind == nkIdent: 
       result = newSymS(kind, n.sons[1], c)
       var v = n.sons[0].ident
       if (sfStar in allowed) and (v.id == ord(wStar)): 
@@ -426,7 +421,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
     base: PType
     pos: int
   IntSetInit(check)
-  pos = 0                     # n.sons[0] contains the pragmas (if any). We process these later...
+  pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
   checkSonsLen(n, 3)
   if n.sons[1] != nil: 
     base = semTypeNode(c, n.sons[1].sons[0], nil)
@@ -444,28 +439,30 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   
 proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode, 
                               cl: var TIntSet): PType = 
-  var 
-    L: int
-    s: PSym
   result = t
-  if (t == nil): return 
+  if t == nil: return 
   if IntSetContainsOrIncl(cl, t.id): return 
   case t.kind
   of tyGenericBody: 
+    #debug(t)
     result = newTypeS(tyGenericInvokation, c)
     addSon(result, t)
     for i in countup(0, sonsLen(t) - 2): 
       if t.sons[i].kind != tyGenericParam: 
         InternalError("addTypeVarsOfGenericBody")
-      s = copySym(t.sons[i].sym)
+      # do not declare ``TKey`` twice:
+      #if not IntSetContainsOrIncl(cl, t.sons[i].sym.ident.id):
+      var s = copySym(t.sons[i].sym)
       s.position = sonsLen(genericParams)
       addDecl(c, s)
       addSon(genericParams, newSymNode(s))
       addSon(result, t.sons[i])
   of tyGenericInst: 
-    L = sonsLen(t) - 1
+    #debug(t)
+    var L = sonsLen(t) - 1
     t.sons[L] = addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl)
   of tyGenericInvokation: 
+    #debug(t)
     for i in countup(1, sonsLen(t) - 1): 
       t.sons[i] = addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl)
   else: 
@@ -476,13 +473,12 @@ proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType =
   result = semTypeNode(c, n, nil)
   if (genericParams != nil) and (sonsLen(genericParams) == 0): 
     result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
+    #if result.kind == tyGenericInvokation: debug(result)
   
 proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType = 
   var 
-    length, counter: int
-    a, def, res: PNode
+    def, res: PNode
     typ: PType
-    arg: PSym
     check, cl: TIntSet
   checkMinSonsLen(n, 1)
   result = newOrPrevType(tyProc, prev, c)
@@ -491,27 +487,29 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
   if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl)
   if n.sons[0] == nil: 
     addSon(result, nil)       # return type
-    addSon(result.n, newNodeI(nkType, n.info)) # BUGFIX: nkType must exist!
-                                               # XXX but it does not, if n.sons[paramsPos] == nil?
+    addSon(result.n, newNodeI(nkType, n.info)) 
+    # BUGFIX: nkType must exist!
+    # XXX but it does not, if n.sons[paramsPos] == nil?
   else: 
     addSon(result, nil)
     res = newNodeI(nkType, n.info)
     addSon(result.n, res)
   IntSetInit(check)
-  counter = 0
+  var counter = 0
   for i in countup(1, sonsLen(n) - 1): 
-    a = n.sons[i]
-    if (a.kind != nkIdentDefs): IllFormedAst(a)
+    var a = n.sons[i]
+    if a.kind != nkIdentDefs: IllFormedAst(a)
     checkMinSonsLen(a, 3)
-    length = sonsLen(a)
+    var length = sonsLen(a)
     if a.sons[length - 2] != nil: 
       typ = paramType(c, a.sons[length - 2], genericParams, cl)
     else: 
       typ = nil
     if a.sons[length - 1] != nil: 
-      def = semExprWithType(c, a.sons[length - 1]) # check type compability between def.typ and typ:
-      if (typ != nil): 
-        if (cmpTypes(typ, def.typ) < isConvertible): 
+      def = semExprWithType(c, a.sons[length - 1]) 
+      # check type compability between def.typ and typ:
+      if typ != nil: 
+        if cmpTypes(typ, def.typ) < isConvertible: 
           typeMismatch(a.sons[length - 1], typ, def.typ)
         def = fitNode(c, typ, def)
       else: 
@@ -519,7 +517,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
     else: 
       def = nil
     for j in countup(0, length - 3): 
-      arg = newSymS(skParam, a.sons[j], c)
+      var arg = newSymS(skParam, a.sons[j], c)
       arg.typ = typ
       arg.position = counter
       inc(counter)
@@ -600,21 +598,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       markUsed(n, n.sym)
     else: 
       liMessage(n.info, errTypeExpected)
-  of nkObjectTy: 
-    result = semObjectNode(c, n, prev)
-  of nkTupleTy: 
-    result = semTuple(c, n, prev)
-  of nkRefTy: 
-    result = semAnyRef(c, n, tyRef, "ref", prev)
-  of nkPtrTy: 
-    result = semAnyRef(c, n, tyPtr, "ptr", prev)
-  of nkVarTy: 
-    result = semVarType(c, n, prev)
-  of nkDistinctTy: 
-    result = semDistinct(c, n, prev)
+  of nkObjectTy: result = semObjectNode(c, n, prev)
+  of nkTupleTy: result = semTuple(c, n, prev)
+  of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
+  of nkPtrTy: result = semAnyRef(c, n, tyPtr, "ptr", prev)
+  of nkVarTy: result = semVarType(c, n, prev)
+  of nkDistinctTy: result = semDistinct(c, n, prev)
   of nkProcTy: 
     checkSonsLen(n, 2)
-    result = semProcTypeNode(c, n.sons[0], nil, prev) # dummy symbol for `pragma`:
+    result = semProcTypeNode(c, n.sons[0], nil, prev) 
+    # dummy symbol for `pragma`:
     s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
     s.typ = result
     pragma(c, s, n.sons[1], procTypePragmas)
@@ -636,49 +629,33 @@ proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
   
 proc processMagicType(c: PContext, m: PSym) = 
   case m.magic                #registerSysType(m.typ);
-  of mInt: 
-    setMagicType(m, tyInt, intSize)
-  of mInt8: 
-    setMagicType(m, tyInt8, 1)
-  of mInt16: 
-    setMagicType(m, tyInt16, 2)
-  of mInt32: 
-    setMagicType(m, tyInt32, 4)
-  of mInt64: 
-    setMagicType(m, tyInt64, 8)
-  of mFloat: 
-    setMagicType(m, tyFloat, floatSize)
-  of mFloat32: 
-    setMagicType(m, tyFloat32, 4)
-  of mFloat64: 
-    setMagicType(m, tyFloat64, 8)
-  of mBool: 
-    setMagicType(m, tyBool, 1)
-  of mChar: 
-    setMagicType(m, tyChar, 1)
+  of mInt: setMagicType(m, tyInt, intSize)
+  of mInt8: setMagicType(m, tyInt8, 1)
+  of mInt16: setMagicType(m, tyInt16, 2)
+  of mInt32: setMagicType(m, tyInt32, 4)
+  of mInt64: setMagicType(m, tyInt64, 8)
+  of mFloat: setMagicType(m, tyFloat, floatSize)
+  of mFloat32: setMagicType(m, tyFloat32, 4)
+  of mFloat64: setMagicType(m, tyFloat64, 8)
+  of mBool: setMagicType(m, tyBool, 1)
+  of mChar: setMagicType(m, tyChar, 1)
   of mString: 
     setMagicType(m, tyString, ptrSize)
     addSon(m.typ, getSysType(tyChar))
   of mCstring: 
     setMagicType(m, tyCString, ptrSize)
     addSon(m.typ, getSysType(tyChar))
-  of mPointer: 
-    setMagicType(m, tyPointer, ptrSize)
+  of mPointer: setMagicType(m, tyPointer, ptrSize)
   of mEmptySet: 
     setMagicType(m, tySet, 1)
     addSon(m.typ, newTypeS(tyEmpty, c))
   of mIntSetBaseType: 
     setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ;
     return 
-  of mNil: 
-    setMagicType(m, tyNil, ptrSize)
-  of mExpr: 
-    setMagicType(m, tyExpr, 0)
-  of mStmt: 
-    setMagicType(m, tyStmt, 0)
-  of mTypeDesc: 
-    setMagicType(m, tyTypeDesc, 0)
-  of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: 
-    return 
+  of mNil: setMagicType(m, tyNil, ptrSize)
+  of mExpr: setMagicType(m, tyExpr, 0)
+  of mStmt: setMagicType(m, tyStmt, 0)
+  of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
+  of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return 
   else: liMessage(m.info, errTypeExpected)
   
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim
index 0698bf18d..a1b322d86 100755
--- a/rod/sigmatch.nim
+++ b/rod/sigmatch.nim
@@ -30,7 +30,7 @@ type
   TTypeRelation = enum        # order is important!
     isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
 
-proc initCandidate(c: var TCandidate, callee: PType) = 
+proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = 
   c.exactMatches = 0
   c.subtypeMatches = 0
   c.convMatches = 0
@@ -38,11 +38,25 @@ proc initCandidate(c: var TCandidate, callee: PType) =
   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 initCandidate(c: var TCandidate, callee: PType) = 
+  initCandidateAux(c, callee)
+  c.calleeSym = nil
+  initIdTable(c.bindings)
+
+proc initCandidate(c: var TCandidate, callee: PSym, binding: PNode) = 
+  initCandidateAux(c, callee.typ)
+  c.calleeSym = callee
+  initIdTable(c.bindings)
+  if binding != nil:
+    var typeParams = callee.ast[genericParamsPos]
+    for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
+      var formalTypeParam = typeParams.sons[i-1].typ
+      #debug(formalTypeParam)
+      IdTablePut(c.bindings, formalTypeParam, binding[i].typ)
+
 proc copyCandidate(a: var TCandidate, b: TCandidate) = 
   a.exactMatches = b.exactMatches
   a.subtypeMatches = b.subtypeMatches
@@ -326,7 +340,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
     case a.kind
     of tyPointer: result = isEqual
     of tyNil: result = isSubtype
-    of tyRef, tyPtr, tyProc, tyCString: result = isConvertible
+    of tyPtr, tyProc, tyCString: result = isConvertible
     else: nil
   of tyString: 
     case a.kind
@@ -664,21 +678,20 @@ proc sameMethodDispatcher(a, b: PSym): bool =
     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 
+proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
+                              initialBinding: PNode): PNode = 
+  var
     o: TOverloadIter
     x, y, z: TCandidate
   #liMessage(n.info, warnUser, renderTree(n));
-  var sym = initOverloadIter(o, c, n.sons[0])
+  var sym = initOverloadIter(o, c, f)
   result = nil
   if sym == nil: return 
-  initCandidate(x, sym.typ)
-  x.calleeSym = sym
-  initCandidate(y, sym.typ)
-  y.calleeSym = sym
+  initCandidate(x, sym, initialBinding)
+  initCandidate(y, sym, initialBinding)
   while sym != nil: 
     if sym.kind in filter: 
-      initCandidate(z, sym.typ)
+      initCandidate(z, sym, initialBinding)
       z.calleeSym = sym
       matches(c, n, z)
       if z.state == csMatch: 
@@ -689,7 +702,7 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
           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])
+    sym = nextOverloadIter(o, c, f)
   if x.state == csEmpty: 
     # no overloaded proc found
     # do not generate an error yet; the semantic checking will check for
@@ -714,3 +727,16 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
     result = x.call
     result.sons[0] = newSymNode(x.calleeSym)
     result.typ = x.callee.sons[0]
+        
+proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = 
+  # process the bindings once:
+  var initialBinding: PNode
+  var f = n.sons[0]
+  if f.kind == nkBracketExpr:
+    # fill in the bindings:
+    initialBinding = f
+    f = f.sons[0]
+  else: 
+    initialBinding = nil
+  result = semDirectCallWithBinding(c, n, f, filter, initialBinding)
+
diff --git a/rod/transf.nim b/rod/transf.nim
index ac746f834..16c279c80 100755
--- a/rod/transf.nim
+++ b/rod/transf.nim
@@ -63,55 +63,55 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym =
   incl(result.flags, sfFromGeneric)
 
 proc transform(c: PTransf, n: PNode): PNode
-  #
-  #
-  #Transforming iterators into non-inlined versions is pretty hard, but
-  #unavoidable for not bloating the code too much. If we had direct access to
-  #the program counter, things'd be much easier.
-  #::
-  #
-  #  iterator items(a: string): char =
-  #    var i = 0
-  #    while i < length(a):
-  #      yield a[i]
-  #      inc(i)
-  #
-  #  for ch in items("hello world"): # `ch` is an iteration variable
-  #    echo(ch)
-  #
-  #Should be transformed into::
-  #
-  #  type
-  #    TItemsClosure = record
-  #      i: int
-  #      state: int
-  #  proc items(a: string, c: var TItemsClosure): char =
-  #    case c.state
-  #    of 0: goto L0 # very difficult without goto!
-  #    of 1: goto L1 # can be implemented by GCC's computed gotos
-  #
-  #    block L0:
-  #      c.i = 0
-  #      while c.i < length(a):
-  #        c.state = 1
-  #        return a[i]
-  #        block L1: inc(c.i)
-  #
-  #More efficient, but not implementable::
-  #
-  #  type
-  #    TItemsClosure = record
-  #      i: int
-  #      pc: pointer
-  #
-  #  proc items(a: string, c: var TItemsClosure): char =
-  #    goto c.pc
-  #    c.i = 0
-  #    while c.i < length(a):
-  #      c.pc = label1
-  #      return a[i]
-  #      label1: inc(c.i)
-  #
+
+# Transforming iterators into non-inlined versions is pretty hard, but
+# unavoidable for not bloating the code too much. If we had direct access to
+# the program counter, things'd be much easier.
+# ::
+#
+#  iterator items(a: string): char =
+#    var i = 0
+#    while i < length(a):
+#      yield a[i]
+#      inc(i)
+#
+#  for ch in items("hello world"): # `ch` is an iteration variable
+#    echo(ch)
+#
+# Should be transformed into::
+#
+#  type
+#    TItemsClosure = record
+#      i: int
+#      state: int
+#  proc items(a: string, c: var TItemsClosure): char =
+#    case c.state
+#    of 0: goto L0 # very difficult without goto!
+#    of 1: goto L1 # can be implemented by GCC's computed gotos
+#
+#    block L0:
+#      c.i = 0
+#      while c.i < length(a):
+#        c.state = 1
+#        return a[i]
+#        block L1: inc(c.i)
+#
+# More efficient, but not implementable::
+#
+#  type
+#    TItemsClosure = record
+#      i: int
+#      pc: pointer
+#
+#  proc items(a: string, c: var TItemsClosure): char =
+#    goto c.pc
+#    c.i = 0
+#    while c.i < length(a):
+#      c.pc = label1
+#      return a[i]
+#      label1: inc(c.i)
+#
+
 proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode = 
   result = newNodeI(nkFastAsgn, ri.info)
   addSon(result, le)
@@ -290,8 +290,8 @@ proc transformConv(c: PTransf, n: PNode): PNode =
     if not isOrdinalType(source):
       # XXX int64 -> float conversion?
       result = n
-    elif (firstOrd(dest) <= firstOrd(source)) and
-        (lastOrd(source) <= lastOrd(dest)): 
+    elif firstOrd(dest) <= firstOrd(source) and
+        lastOrd(source) <= lastOrd(dest): 
       # BUGFIX: simply leave n as it is; we need a nkConv node,
       # but no range check:
       result = n
@@ -540,8 +540,8 @@ proc getMergeOp(n: PNode): PSym =
 
 proc flattenTreeAux(d, a: PNode, op: PSym) = 
   var op2 = getMergeOp(a)
-  if (op2 != nil) and
-      ((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)): 
+  if op2 != nil and
+      (op2.id == op.id or op.magic != mNone and op2.magic == op.magic): 
     for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op)
   else: 
     addSon(d, copyTree(a))