summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-09-20 00:56:48 +0200
committerAraq <rumpf_a@web.de>2011-09-20 00:56:48 +0200
commitfd62116f6eb80d1dd3d6cc745d80629ad32dca1a (patch)
treeac5cbd102ffa580e322eda22deeef9298babae4a /compiler
parentdc3ace4f379931f2af4dd4a3cd2a0984a94865af (diff)
downloadNim-fd62116f6eb80d1dd3d6cc745d80629ad32dca1a.tar.gz
bugfixes for generics; new threads implementation still broken
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim8
-rwxr-xr-xcompiler/astalgo.nim5
-rwxr-xr-xcompiler/nimrod.nim14
-rwxr-xr-xcompiler/pragmas.nim1
-rwxr-xr-xcompiler/sem.nim2
-rwxr-xr-xcompiler/semexprs.nim5
-rwxr-xr-xcompiler/seminst.nim15
-rwxr-xr-xcompiler/semstmts.nim7
-rwxr-xr-xcompiler/semtypes.nim75
-rwxr-xr-xcompiler/semtypinst.nim100
-rwxr-xr-xcompiler/sigmatch.nim13
-rwxr-xr-xcompiler/types.nim26
12 files changed, 187 insertions, 84 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index e9bf532b1..bb9803830 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -279,8 +279,8 @@ type
 
   TTypeFlags* = set[TTypeFlag]
 
-  TSymKind* = enum # the different symbols (start with the prefix sk);
-                   # order is important for the documentation generator!
+  TSymKind* = enum        # the different symbols (start with the prefix sk);
+                          # order is important for the documentation generator!
     skUnknown,            # unknown symbol: used for parsing assembler blocks
                           # and first phase symbol lookup in generics
     skConditional,        # symbol for the preprocessor (may become obsolete)
@@ -848,6 +848,10 @@ proc initNodeTable(x: var TNodeTable) =
 proc sonsLen(n: PType): int = 
   if isNil(n.sons): result = 0
   else: result = len(n.sons)
+
+proc len*(n: PType): int = 
+  if isNil(n.sons): result = 0
+  else: result = len(n.sons)
   
 proc newSons(father: PType, length: int) = 
   if isNil(father.sons): father.sons = @[]
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 08b502af7..17875d524 100755
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -46,7 +46,6 @@ proc StrTableContains*(t: TStrTable, n: PSym): bool
 proc StrTableAdd*(t: var TStrTable, n: PSym)
 proc StrTableGet*(t: TStrTable, name: PIdent): PSym  
   
-  # the iterator scheme:
 type 
   TTabIter*{.final.} = object # consider all fields here private
     h*: THash                 # current hash
@@ -749,6 +748,10 @@ proc IdTablePut(t: var TIdTable, key: PIdObj, val: PObject) =
     IdTableRawInsert(t.data, key, val)
     inc(t.counter)
 
+iterator IdTablePairs*(t: TIdTable): tuple[key: PIdObj, val: PObject] =
+  for i in 0 .. high(t.data):
+    if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
+
 proc writeIdNodeTable(t: TIdNodeTable) = 
   nil
 
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index 5c91329cd..3a910cfad 100755
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -49,6 +49,13 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
     if optRun notin gGlobalOptions and arguments != "": 
       rawMessage(errArgsNeedRunOption, [])
   
+proc prependCurDir(f: string): string =
+  when defined(unix):
+    if os.isAbsolute(f): result = f
+    else: result = "./" & f
+  else:
+    result = f
+  
 proc HandleCmdLine() = 
   var start = epochTime()
   if paramCount() == 0: 
@@ -79,11 +86,8 @@ proc HandleCmdLine() =
         rawMessage(hintSuccessX, [$gLinesCompiled, 
                    formatFloat(epochTime() - start, ffDecimal, 3)])
       if optRun in gGlobalOptions: 
-        when defined(unix): 
-          var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
-        else: 
-          var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
-        execExternalProgram(prog & ' ' & arguments)
+        var ex = quoteIfContainsWhite(changeFileExt(filename, "").prependCurDir)
+        execExternalProgram(ex & ' ' & arguments)
 
 #GC_disableMarkAndSweep()
 cmdLineInfo = newLineInfo("command line", -1, -1)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d5cbae4ab..039474266 100755
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -53,6 +53,7 @@ const
     wExtern, wImportcpp, wImportobjc}
   procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect,
                       wThread}
+  allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
 
 proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
 proc pragmaAsm*(c: PContext, n: PNode): char
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 5d2e1069f..c0ea23d2e 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -146,7 +146,7 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
       addSon(n, prc.ast)
   lastGenericIdx = Len(generics)
 
-proc semExprNoFlags(c: PContext, n: PNode): PNode = 
+proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} = 
   result = semExpr(c, n, {})
 
 proc myOpen(module: PSym, filename: string): PPassContext = 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d116ede2e..f86a4f60d 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1178,9 +1178,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif n.sons[0].kind == nkSymChoice: 
+    elif n.sons[0].kind == nkSymChoice or n[0].kind == nkBracketExpr and 
+        n[0][0].kind == nkSymChoice:
       result = semDirectOp(c, n, flags)
-    else: 
+    else:
       result = semIndirectOp(c, n, flags)
   of nkMacroStmt: 
     result = semMacroStmt(c, n)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 87f988ed9..d53d33898 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -29,6 +29,10 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
       break
     if t.kind == tyGenericParam: 
       InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
+    elif t.kind == tyGenericInvokation:
+      #t = instGenericContainer(c, a, t)
+      t = generateTypeInstance(c, pt, a, t)
+      #t = ReplaceTypeVarsT(cl, t)
     s.typ = t
     addDecl(c, s)
     entry.concreteTypes[i] = t
@@ -94,6 +98,14 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
       closeScope(c.tab)
       popInfoContext()
 
+proc sideEffectsCheck(c: PContext, s: PSym) = 
+  if {sfNoSideEffect, sfSideEffect} * s.flags ==
+      {sfNoSideEffect, sfSideEffect}: 
+    LocalError(s.info, errXhasSideEffects, s.name.s)
+  elif sfThread in s.flags and semthreads.needsGlobalAnalysis() and 
+      s.ast.sons[genericParamsPos].kind == nkEmpty:
+    c.threadEntries.add(s)
+
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, 
                       info: TLineInfo): PSym = 
   # generates an instantiated proc
@@ -133,7 +145,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   var oldPrc = GenericCacheGet(c, entry)
   if oldPrc == nil:
     generics.add(entry)
+    if n.sons[pragmasPos].kind != nkEmpty:
+      pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
     instantiateBody(c, n, result)
+    sideEffectsCheck(c, result)
   else:
     result = oldPrc
   popInfoContext()
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c37706f3a..ce870a3ad 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -554,13 +554,6 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
     n.sons[codePos] = newSymNode(b)
   else:
     LocalError(n.info, errNoSymbolToBorrowFromFound) 
-
-proc sideEffectsCheck(c: PContext, s: PSym) = 
-  if {sfNoSideEffect, sfSideEffect} * s.flags ==
-      {sfNoSideEffect, sfSideEffect}: 
-    LocalError(s.info, errXhasSideEffects, s.name.s)
-  elif sfThread in s.flags and semthreads.needsGlobalAnalysis():
-    c.threadEntries.add(s)
   
 proc addResult(c: PContext, t: PType, info: TLineInfo) = 
   if t != nil: 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 7cdb32c79..9ff7ea27f 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -216,23 +216,6 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
       addSon(result.n, newSymNode(field))
       addSon(result, typ)
 
-proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = 
-  if s.typ == nil or s.typ.kind != tyGenericBody: 
-    GlobalError(n.info, errCannotInstantiateX, s.name.s)
-  result = newOrPrevType(tyGenericInvokation, prev, c)
-  if s.typ.containerID == 0: InternalError(n.info, "semtypes.semGeneric")
-  if sonsLen(n) != sonsLen(s.typ): 
-    GlobalError(n.info, errWrongNumberOfArguments)
-  addSon(result, s.typ)
-  var isConcrete = true # iterate over arguments:
-  for i in countup(1, sonsLen(n)-1): 
-    var elem = semTypeNode(c, n.sons[i], nil)
-    if elem.kind in {tyGenericParam, tyGenericInvokation}: isConcrete = false
-    addSon(result, elem)
-  if isConcrete:
-    if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
-    result = instGenericContainer(c, n, result)
-
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
                  allowed: TSymFlags): PSym = 
   # identifier with visibility
@@ -489,7 +472,6 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
   if ContainsOrIncl(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): 
@@ -505,11 +487,9 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
       addSon(genericParams, newSymNode(s))
       addSon(result, t.sons[i])
   of tyGenericInst: 
-    #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: 
@@ -520,7 +500,6 @@ 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 = 
@@ -546,6 +525,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     var length = sonsLen(a)
     if a.sons[length-2].kind != nkEmpty: 
       typ = paramType(c, a.sons[length-2], genericParams, cl)
+      #if matchType(typ, [(tyVar, 0)], tyGenericInvokation):
+      #  debug a.sons[length-2][0][1]
+        
     else: 
       typ = nil
     if a.sons[length-1].kind != nkEmpty:
@@ -557,8 +539,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
         # and def.typ != nil and def.typ.kind != tyNone:
         # example code that triggers it:
         # proc sort[T](cmp: proc(a, b: T): int = cmp)
-        def = fitNode(c, typ, def)
-    else: 
+        if not containsGenericType(typ):
+          def = fitNode(c, typ, def)
+    else:
       def = ast.emptyNode
     if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
     for j in countup(0, length-3): 
@@ -578,6 +561,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
       result.sons[0] = r
       res.typ = result.sons[0]
+  #if matchType(result, [(tyProc, 1), (tyVar, 0)], tyGenericInvokation):
+  #  debug result
 
 proc semStmtListType(c: PContext, n: PNode, prev: PType): PType = 
   checkMinSonsLen(n, 1)
@@ -603,6 +588,50 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   closeScope(c.tab)
   Dec(c.p.nestedBlockCounter)
 
+proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
+  # XXX hack 1022 for generics ... would have been nice if the compiler had
+  # been designed with them in mind from start ...
+  when false:
+    if n.kind == nkSym:
+      # for generics we need to lookup the type var again:
+      var s = SymtabGet(c.Tab, n.sym.name)
+      if s != nil:
+        if s.kind == skType and s.typ != nil:
+          var t = n.sym.typ
+          echo "came here"
+          return t
+        else:
+          echo "s is crap:"
+          debug(s)
+      else:
+        echo "s is nil!!!!"
+  result = semTypeNode(c, n, nil)
+
+proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = 
+  if s.typ == nil or s.typ.kind != tyGenericBody: 
+    GlobalError(n.info, errCannotInstantiateX, s.name.s)
+  result = newOrPrevType(tyGenericInvokation, prev, c)
+  if s.typ.containerID == 0: InternalError(n.info, "semtypes.semGeneric")
+  if sonsLen(n) != sonsLen(s.typ): 
+    GlobalError(n.info, errWrongNumberOfArguments)
+  addSon(result, s.typ)
+  var isConcrete = true # iterate over arguments:
+  for i in countup(1, sonsLen(n)-1):
+    var elem = semGenericParamInInvokation(c, n.sons[i])
+    if containsGenericType(elem): isConcrete = false
+    #if elem.kind in {tyGenericParam, tyGenericInvokation}: isConcrete = false
+    addSon(result, elem)
+  if isConcrete:
+    if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
+    result = instGenericContainer(c, n, result)
+
+proc FixupRemainingGenericInvokations(c: PContext, n: PNode, 
+                                      typ: PType): PType =
+  if typ.kind == tyGenericInvokation:
+    nil
+  else:
+    result = typ
+
 proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = 
   result = nil
   if gCmd == cmdIdeTools: suggestExpr(c, n)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 41ec8ddac..88697dc85 100755
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -92,51 +92,90 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
 
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
-  if result == nil: 
+  if result == nil:
     GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t))
   elif result.kind == tyGenericParam: 
     InternalError(cl.info, "substitution with generic parameter")
   
 proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = 
+  # tyGenericInvokation[A, tyGenericInvokation[A, B]]
+  # is difficult to handle: 
   var body = t.sons[0]
   if body.kind != tyGenericBody: InternalError(cl.info, "no generic body")
   var header: PType = nil
-  for i in countup(1, sonsLen(t) - 1):
-    var x = replaceTypeVarsT(cl, t.sons[i])
-    if t.sons[i].kind == tyGenericParam: 
-      if header == nil: header = copyType(t, t.owner, false)
+  when true:
+    # search for some instantiation here:
+    result = searchInstTypes(gInstTypes, t)
+    if result != nil: return
+    for i in countup(1, sonsLen(t) - 1):
+      var x = t.sons[i]
+      if x.kind == tyGenericParam: 
+        x = lookupTypeVar(cl, x)
+        if header == nil: header = copyType(t, t.owner, false)
+        header.sons[i] = x
+        #idTablePut(cl.typeMap, body.sons[i-1], x)
+    if header != nil:
+      # search again after first pass:
+      result = searchInstTypes(gInstTypes, header)
+      if result != nil: return
+    else:
+      header = copyType(t, t.owner, false)
+    # ugh need another pass for deeply recursive generic types (e.g. PActor)
+    # we need to add the candidate here, before it's fully instantiated for
+    # recursive instantions:
+    result = newType(tyGenericInst, t.sons[0].owner)
+    idTablePut(gInstTypes, header, result)
+
+    for i in countup(1, sonsLen(t) - 1):
+      var x = replaceTypeVarsT(cl, t.sons[i])
+      assert x.kind != tyGenericInvokation
       header.sons[i] = x
-    when false:
-      var x: PType
+      idTablePut(cl.typeMap, body.sons[i-1], x)
+    
+    for i in countup(0, sonsLen(t) - 1): 
+      # if one of the params is not concrete, we cannot do anything
+      # but we already raised an error!
+      addSon(result, header.sons[i])
+    
+    var newbody = ReplaceTypeVarsT(cl, lastSon(body))
+    newbody.flags = newbody.flags + t.flags + body.flags
+    result.flags = result.flags + newbody.flags
+    newbody.callConv = body.callConv
+    newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
+    addSon(result, newbody)
+    checkPartialConstructedType(cl.info, newbody)
+  else:
+    for i in countup(1, sonsLen(t) - 1):
+      if PType(idTableGet(cl.typeMap, t.sons[i])) == nil: debug(t)
+      var x = replaceTypeVarsT(cl, t.sons[i])
       if t.sons[i].kind == tyGenericParam: 
-        x = lookupTypeVar(cl, t.sons[i])
         if header == nil: header = copyType(t, t.owner, false)
         header.sons[i] = x
-      else: 
-        x = t.sons[i]
-    idTablePut(cl.typeMap, body.sons[i-1], x)
-  if header == nil: header = t
-  result = searchInstTypes(gInstTypes, header)
-  if result != nil: return 
-  result = newType(tyGenericInst, t.sons[0].owner)
-  for i in countup(0, sonsLen(t) - 1): 
-    # if one of the params is not concrete, we cannot do anything
-    # but we already raised an error!
-    addSon(result, header.sons[i])
-  idTablePut(gInstTypes, header, result)
-  var newbody = ReplaceTypeVarsT(cl, lastSon(body))
-  newbody.flags = newbody.flags + t.flags + body.flags
-  newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
-  addSon(result, newbody)
-  #writeln(output, ropeToStr(Typetoyaml(newbody)));
-  checkPartialConstructedType(cl.info, newbody)
+      assert x.kind != tyGenericInvokation
+      idTablePut(cl.typeMap, body.sons[i-1], x)
+    if header == nil: header = t
+    result = searchInstTypes(gInstTypes, header)
+    if result != nil: return 
+    result = newType(tyGenericInst, t.sons[0].owner)
+    for i in countup(0, sonsLen(t) - 1): 
+      # if one of the params is not concrete, we cannot do anything
+      # but we already raised an error!
+      addSon(result, header.sons[i])
+    idTablePut(gInstTypes, header, result)
+    var newbody = ReplaceTypeVarsT(cl, lastSon(body))
+    newbody.flags = newbody.flags + t.flags + body.flags
+    newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
+    addSon(result, newbody)
+    checkPartialConstructedType(cl.info, newbody)
   
 proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = 
   result = t
   if t == nil: return 
   case t.kind
-  of tyGenericParam: 
+  of tyGenericParam:
     result = lookupTypeVar(cl, t)
+    if result.kind == tyGenericInvokation:
+      result = handleGenericInvokation(cl, result)
   of tyGenericInvokation: 
     result = handleGenericInvokation(cl, t)
   of tyGenericBody: 
@@ -151,9 +190,10 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
       result.n = ReplaceTypeVarsN(cl, result.n)
       if result.Kind in GenericTypes:
         LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
-        #writeln(output, ropeToStr(Typetoyaml(result)))
-        #checkConstructedType(cl.info, result)
-
+      if result.kind == tyProc and result.sons[0] != nil:
+        if result.sons[0].kind == tyEmpty:
+          result.sons[0] = nil
+  
 proc generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode, 
                            t: PType): PType = 
   var cl: TReplTypeVars
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9acf83a46..1e93385d9 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -137,6 +137,8 @@ proc concreteType(mapping: TIdTable, t: PType): PType =
         # example code that triggers it:
         # proc sort[T](cmp: proc(a, b: T): int = cmp)
       if result.kind != tyGenericParam: break
+  of tyGenericInvokation:
+    assert false
   else: 
     result = t                # Note: empty is valid here
   
@@ -388,8 +390,10 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
   of tyGenericInvokation: 
     assert(f.sons[0].kind == tyGenericBody)
     if a.kind == tyGenericInvokation: 
-      InternalError("typeRel: tyGenericInvokation -> tyGenericInvokation")
-    if (a.kind == tyGenericInst): 
+      #InternalError("typeRel: tyGenericInvokation -> tyGenericInvokation")
+      # simply no match for now:
+      nil
+    elif a.kind == tyGenericInst:
       if (f.sons[0].containerID == a.sons[0].containerID) and
           (sonsLen(a) - 1 == sonsLen(f)): 
         assert(a.sons[0].kind == tyGenericBody)
@@ -404,7 +408,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
         # we steal the generic parameters from the tyGenericBody:
         for i in countup(1, sonsLen(f) - 1):
           var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
-          if x == nil or x.kind == tyGenericParam:
+          if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
             InternalError("wrong instantiated type!")
           idTablePut(mapping, f.sons[i], x)
   of tyGenericParam: 
@@ -413,8 +417,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
       if sonsLen(f) == 0: 
         # no constraints
         var concrete = concreteType(mapping, a)
-        if concrete != nil: 
-          #MessageOut('putting: ' + f.sym.name.s);
+        if concrete != nil:
           idTablePut(mapping, f, concrete)
           result = isGeneric
       else: 
diff --git a/compiler/types.nim b/compiler/types.nim
index 692b7f61b..d8d0caf35 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -728,7 +728,16 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool =
       else: 
         for i in countup(0, sonsLen(n) - 1): 
           result = typeAllowedNode(marker, n.sons[i], kind)
-          if not result: return 
+          if not result: break
+
+proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]],
+                last: TTypeKind): bool =
+  var a = a
+  for k, i in pattern.items:
+    if a.kind != k: return false
+    if i >= a.sonslen or a.sons[i] == nil: return false
+    a = a.sons[i]
+  result = a.kind == last
   
 proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   assert(kind in {skVar, skConst, skParam, skResult})
@@ -751,13 +760,14 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   of tyProc: 
     for i in countup(1, sonsLen(t) - 1): 
       result = typeAllowedAux(marker, t.sons[i], skParam)
-      if not result: return 
-    if t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skResult)
+      if not result: break 
+    if result and t.sons[0] != nil:
+      result = typeAllowedAux(marker, t.sons[0], skResult)
   of tyExpr, tyStmt, tyTypeDesc: 
     result = true
   of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation: 
     result = false            #InternalError('shit found');
-  of tyEmpty, tyNil: 
+  of tyEmpty, tyNil:
     result = kind == skConst
   of tyString, tyBool, tyChar, tyEnum, tyInt..tyFloat128, tyCString, tyPointer: 
     result = true
@@ -781,13 +791,13 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   of tyArrayConstr, tyTuple, tySet: 
     for i in countup(0, sonsLen(t) - 1): 
       result = typeAllowedAux(marker, t.sons[i], kind)
-      if not result: return 
+      if not result: break 
   of tyObject: 
     for i in countup(0, sonsLen(t) - 1): 
       result = typeAllowedAux(marker, t.sons[i], skVar)
-      if not result: return 
-    if t.n != nil: result = typeAllowedNode(marker, t.n, skVar)
-  
+      if not result: break 
+    if result and t.n != nil: result = typeAllowedNode(marker, t.n, skVar)
+    
 proc typeAllowed(t: PType, kind: TSymKind): bool = 
   var marker = InitIntSet()
   result = typeAllowedAux(marker, t, kind)