summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-12-13 15:58:03 +0100
committerAraq <rumpf_a@web.de>2013-12-13 15:58:03 +0100
commit8c553fa8a2e9476c67c6348bf64c02ea0f19a679 (patch)
treece32cf3cd815f4dbb7e5f0f00942f43e1a7871c0 /compiler
parent328f1932925889d5bb7f91c68fb1504b9b26ba8c (diff)
parent01661daf76daa713d25d06d202f83c842a6f1fe3 (diff)
downloadNim-8c553fa8a2e9476c67c6348bf64c02ea0f19a679.tar.gz
Merge branch 'master' into vm2
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim11
-rw-r--r--compiler/ccgutils.nim2
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/evals.nim4
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/main.nim4
-rw-r--r--compiler/nimrod.nim6
-rw-r--r--compiler/nimrod.nimrod.cfg1
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/seminst.nim5
-rw-r--r--compiler/semtypes.nim9
-rw-r--r--compiler/sigmatch.nim248
-rw-r--r--compiler/testability.nim5
-rw-r--r--compiler/types.nim25
14 files changed, 283 insertions, 43 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 1eb5bffc4..a3e034140 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -335,12 +335,19 @@ type
     tyConst, tyMutable, tyVarargs, 
     tyIter, # unused
     tyProxy # used as errornous type (for idetools)
-    tyTypeClass,
+    tyTypeClass
+    tyAnd
+    tyOr
+    tyNot
+    tyAnything
+    tyParametricTypeClass # structured similarly to tyGenericInst
+                          # lastSon is the body of the type class
 
 const
   tyPureObject* = tyTuple
   GcTypeKinds* = {tyRef, tySequence, tyString}
   tyError* = tyProxy # as an errornous node should match everything
+  tyTypeClasses* = {tyTypeClass, tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
 
 type
   TTypeKinds* = set[TTypeKind]
@@ -378,6 +385,7 @@ type
                       # used as return types for return type inference)
     tfAll,            # type class requires all constraints to be met (default)
     tfAny,            # type class requires any constraint to be met
+    tfNot,            # type class with a negative check
     tfCapturesEnv,    # whether proc really captures some environment
     tfByCopy,         # pass object/tuple by copy (C backend)
     tfByRef,          # pass object/tuple by reference (C backend)
@@ -1417,3 +1425,4 @@ proc isAtom*(n: PNode): bool {.inline.} =
 proc isEmptyType*(t: PType): bool {.inline.} =
   ## 'void' and 'stmt' types are often equivalent to 'nil' these days:
   result = t == nil or t.kind in {tyEmpty, tyStmt}
+
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index c37754511..310f7204a 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -86,7 +86,7 @@ proc GetUniqueType*(key: PType): PType =
     if result == nil:
       gCanonicalTypes[k] = key
       result = key
-  of tyTypeDesc, tyTypeClass:
+  of tyTypeDesc, tyTypeClasses:
     InternalError("value expected, but got a type")
   of tyGenericParam:
     InternalError("GetUniqueType")
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index ad9ade63c..b0c90de76 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -944,9 +944,9 @@ proc genMainProc(m: BModule) =
   const 
     CommonMainBody =
         "\tsystemDatInit();$n" &
+        "\tsystemInit();$n" &
         "$1" &
         "$2" &
-        "\tsystemInit();$n" &
         "$3" &
         "$4"
     PosixNimMain = 
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 7e2c8a41d..b4ea973e8 100644
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -550,9 +550,7 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   of skProc, skConverter, skMacro, skType:
     result = n
     #result = s.getBody
-  of skForVar:
-    result = evalGlobalVar(c, s, flags)
-  of skVar, skLet, skTemp, skResult:
+  of skVar, skLet, skForVar, skTemp, skResult:
     if sfGlobal notin s.flags:
       result = evalVariable(c.tos, s, flags)
     else:
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 54ee43069..a3c88824d 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -130,7 +130,7 @@ proc mapType(typ: PType): TJSTypeKind =
     result = etyObject
   of tyNil: result = etyNull
   of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone, 
-     tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: 
+     tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClasses: 
     result = etyNone
   of tyProc: result = etyProc
   of tyCString: result = etyString
diff --git a/compiler/main.nim b/compiler/main.nim
index 7124b6984..2a4143823 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -432,7 +432,9 @@ proc MainCommand* =
   else:
     rawMessage(errInvalidCommandX, command)
   
-  if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun, cmdDump}:
+  if (msgs.gErrorCounter == 0 and
+      gCmd notin {cmdInterpret, cmdRun, cmdDump} and
+      gVerbosity > 0):
     rawMessage(hintSuccessX, [$gLinesCompiled,
                formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
                formatSize(getTotalMem())])
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index 3fa80cebb..2f10e32e3 100644
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -76,5 +76,7 @@ when compileOption("gc", "v2") or compileOption("gc", "refc"):
   # the new correct mark&sweet collector is too slow :-/
   GC_disableMarkAndSweep()
 condsyms.InitDefines()
-HandleCmdLine()
-quit(int8(msgs.gErrorCounter > 0))
+
+when not defined(selftest):
+  HandleCmdLine()
+  quit(int8(msgs.gErrorCounter > 0))
diff --git a/compiler/nimrod.nimrod.cfg b/compiler/nimrod.nimrod.cfg
index 0affe86d9..b2ae97686 100644
--- a/compiler/nimrod.nimrod.cfg
+++ b/compiler/nimrod.nimrod.cfg
@@ -11,6 +11,7 @@ path:"$projectPath/.."
 path:"$lib/packages/docutils"
 
 define:booting
+import:testability
 
 @if windows:
   cincludes: "$lib/wrappers/libffi/common"
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 4b263b3a3..450acbf29 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -322,7 +322,7 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
     var match: bool
     let t2 = n[2].typ
     case t2.kind
-    of tyTypeClass:
+    of tyTypeClasses:
       var m: TCandidate
       InitCandidate(m, t2)
       match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 0cf5086a8..d7d64fd54 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -20,7 +20,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
     if a.kind != nkSym: 
       InternalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
-    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyTypeClass, tyExpr}: continue
+    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyExpr}+tyTypeClasses:
+      continue
     var s = newSym(skType, q.name, getCurrOwner(), q.info)
     s.flags = s.flags + {sfUsed, sfFromGeneric}
     var t = PType(IdTableGet(pt, q.typ))
@@ -193,7 +194,7 @@ proc fixupProcType(c: PContext, genericType: PType,
   if result == nil: return
 
   case genericType.kind
-  of tyGenericParam, tyTypeClass:
+  of tyGenericParam, tyTypeClasses:
     result = inst.concreteTypes[genericType.sym.position]
   of tyTypeDesc:
     result = inst.concreteTypes[genericType.sym.position]
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 92f47f585..6c9c476d9 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -676,8 +676,13 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
       if lifted != nil:
         paramType.sons[i] = lifted
         result = paramType
-    
-    if result != nil:
+
+    if paramType.lastSon.kind == tyTypeClass:
+      result = paramType
+      result.kind = tyParametricTypeClass
+      result = addImplicitGeneric(copyType(result,
+                                           getCurrOwner(), false))
+    elif result != nil:
       result.kind = tyGenericInvokation
       result.sons.setLen(result.sons.len - 1)
   of tyTypeClass:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 00f3b2b10..cacf4782e 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -203,7 +203,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
     add(result, argTypeToString(arg))
     if i != sonsLen(n) - 1: add(result, ", ")
 
-proc typeRel*(c: var TCandidate, f, a: PType): TTypeRelation
+proc typeRel*(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation
 proc concreteType(c: TCandidate, t: PType): PType = 
   case t.kind
   of tyArrayConstr: 
@@ -213,7 +213,7 @@ proc concreteType(c: TCandidate, t: PType): PType =
     addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type?
   of tyNil:
     result = nil              # what should it be?
-  of tyGenericParam: 
+  of tyGenericParam, tyAnything:
     result = t
     while true: 
       result = PType(idTableGet(c.bindings, t))
@@ -385,8 +385,23 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
   else:
     result = isNone
 
-proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = 
-  # is a subtype of f?
+proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
+  # 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.
+  
   result = isNone
   assert(f != nil)
   assert(a != nil)
@@ -397,6 +412,50 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
     return typeRel(c, f, lastSon(a))
   if a.kind == tyVar and f.kind != tyVar:
     return typeRel(c, f, a.sons[0])
+  
+  template bindingRet(res) =
+    when res == isGeneric: put(c.bindings, f, a)
+    return res
+ 
+  case a.kind
+  of tyOr:
+    # seq[int|string] vs seq[number]
+    # both int and string must match against number
+    for branch in a.sons:
+      if typeRel(c, f, branch, false) == isNone:
+        return isNone
+
+    return isGeneric
+
+  of tyAnd:
+    # seq[Sortable and Iterable] vs seq[Sortable]
+    # only one match is enough
+    for branch in a.sons:
+      if typeRel(c, f, branch, false) != isNone:
+        return isGeneric
+
+    return isNone
+
+  of tyNot:
+    case f.kind
+    of tyNot:
+      # seq[!int] vs seq[!number]
+      # seq[float] matches the first, but not the second
+      # we must turn the problem around:
+      # is number a subset of int? 
+      return typeRel(c, a.lastSon, f.lastSon)
+ 
+    else:
+      # negative type classes are essentially infinite,
+      # so only the `any` type class is their superset
+      return if f.kind == tyAnything: isGeneric
+             else: isNone
+
+  of tyAnything:
+    return if f.kind == tyAnything: isGeneric
+           else: isNone
+  else: nil
+
   case f.kind
   of tyEnum: 
     if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual
@@ -485,9 +544,12 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
   of tyOrdinal:
     if isOrdinalType(a):
       var x = if a.kind == tyOrdinal: a.sons[0] else: a
-      
-      result = typeRel(c, f.sons[0], x)
-      if result < isGeneric: result = isNone
+     
+      if f.sonsLen == 0:
+        result = isGeneric
+      else:
+        result = typeRel(c, f.sons[0], x)
+        if result < isGeneric: result = isNone
     elif a.kind == tyGenericParam:
       result = isGeneric
   of tyForward: InternalError("forward type in typeRel()")
@@ -574,13 +636,17 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
           (a.sons[1].kind == tyChar): 
         result = isConvertible
     else: nil
-  of tyEmpty: 
+
+  of tyEmpty:
     if a.kind == tyEmpty: result = isEqual
-  of tyGenericInst: 
+
+  of tyGenericInst:
     result = typeRel(c, lastSon(f), a)
-  of tyGenericBody: 
+
+  of tyGenericBody:
     let ff = lastSon(f)
     if ff != nil: result = typeRel(c, ff, a)
+
   of tyGenericInvokation:
     var x = a.skipGenericAlias
     if x.kind == tyGenericInvokation or f.sons[0].kind != tyGenericBody:
@@ -604,6 +670,38 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
           if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
             InternalError("wrong instantiated type!")
           put(c.bindings, f.sons[i], x)
+  
+  of tyAnd:
+    for branch in f.sons:
+      if typeRel(c, branch, a) == isNone:
+        return isNone
+
+    bindingRet isGeneric
+
+  of tyOr:
+    for branch in f.sons:
+      if typeRel(c, branch, a) != isNone:
+        bindingRet isGeneric
+
+    return isNone
+
+  of tyNot:
+    for branch in f.sons:
+      if typeRel(c, branch, a) != isNone:
+        return isNone
+    
+    bindingRet isGeneric
+
+  of tyAnything:
+    var prev = PType(idTableGet(c.bindings, f))
+    if prev == nil:
+      var concrete = concreteType(c, a)
+      if concrete != nil and doBind:
+        put(c.bindings, f, concrete)
+      return isGeneric
+    else:
+      return typeRel(c, prev, a)
+    
   of tyGenericParam, tyTypeClass:
     var x = PType(idTableGet(c.bindings, f))
     if x == nil:
@@ -634,7 +732,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
         if concrete == nil:
           result = isNone
         else:
-          put(c.bindings, f, concrete)
+          if doBind: put(c.bindings, f, concrete)
     elif a.kind == tyEmpty:
       result = isGeneric
     elif x.kind == tyGenericParam:
@@ -809,8 +907,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
         InternalAssert a.len > 0
         r = typeRel(m, f.lastSon, a.lastSon)
       else:
-        let match = matchTypeClass(m, fMaybeExpr, a)
-        if match != isGeneric: r = isNone
+        let match = matchTypeClass(m.bindings, fMaybeExpr, a)
+        if not match: r = isNone
         else:
           # XXX: Ideally, this should happen much earlier somewhere near 
           # semOpAux, but to do that, we need to be able to query the 
@@ -827,7 +925,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
         
     if r == isGeneric:
       put(m.bindings, f, arg.typ)
-  of tyTypeClass:
+  of tyTypeClass, tyParametricTypeClass:
     if fMaybeExpr.n != nil:
       let match = matchUserTypeClass(c, m, arg, fMaybeExpr, a)
       if match != nil:
@@ -1130,7 +1228,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   var f = 1
   while f < sonsLen(m.callee.n):
     var formal = m.callee.n.sons[f].sym
-    if not ContainsOrIncl(marker, formal.position): 
+    if not ContainsOrIncl(marker, formal.position):
       if formal.ast == nil:
         if formal.typ.kind == tyVarargs:
           var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
@@ -1145,7 +1243,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
         setSon(m.call, formal.position + 1, copyTree(formal.ast))
     inc(f)
 
-proc argtypeMatches*(c: PContext, f, a: PType): bool = 
+proc argtypeMatches*(c: PContext, f, a: PType): bool =
   var m: TCandidate
   initCandidate(m, f)
   let res = paramTypesMatch(c, m, f, a, ast.emptyNode, nil)
@@ -1155,3 +1253,121 @@ proc argtypeMatches*(c: PContext, f, a: PType): bool =
   result = res != nil
 
 include suggest
+
+tests:
+  var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
+  
+  proc `|` (t1, t2: PType): PType =
+    result = newType(tyOr, dummyOwner)
+    result.rawAddSon(t1)
+    result.rawAddSon(t2)
+
+  proc `&` (t1, t2: PType): PType =
+    result = newType(tyAnd, dummyOwner)
+    result.rawAddSon(t1)
+    result.rawAddSon(t2)
+
+  proc `!` (t: PType): PType =
+    result = newType(tyNot, dummyOwner)
+    result.rawAddSon(t)
+
+  proc seq(t: PType): PType =
+    result = newType(tySequence, dummyOwner)
+    result.rawAddSon(t)
+
+  proc array(x: int, t: PType): PType =
+    result = newType(tyArray, dummyOwner)
+    
+    var n = newNodeI(nkRange, UnknownLineInfo())
+    addSon(n, newIntNode(nkIntLit, 0))
+    addSon(n, newIntNode(nkIntLit, x))
+    let range = newType(tyRange, dummyOwner)
+    
+    result.rawAddSon(range)
+    result.rawAddSon(t)
+
+  suite "type classes":
+    let
+      int = newType(tyInt, dummyOwner)
+      float = newType(tyFloat, dummyOwner)
+      string = newType(tyString, dummyOwner)
+      ordinal = newType(tyOrdinal, dummyOwner)
+      any = newType(tyAnything, dummyOwner)
+      number = int | float
+
+    var TFoo = newType(tyObject, dummyOwner)
+    TFoo.sym = newSym(skType, getIdent"TFoo", dummyOwner, UnknownLineInfo())
+
+    var T1 = newType(tyGenericParam, dummyOwner)
+    T1.sym = newSym(skType, getIdent"T1", dummyOwner, UnknownLineInfo())
+    T1.sym.position = 0
+
+    var T2 = newType(tyGenericParam, dummyOwner)
+    T2.sym = newSym(skType, getIdent"T2", dummyOwner, UnknownLineInfo())
+    T2.sym.position = 1
+
+    setup:
+      var c: TCandidate
+      InitCandidate(c, nil)
+
+    template yes(x, y) =
+      test astToStr(x) & " is " & astToStr(y):
+        check typeRel(c, y, x) == isGeneric
+
+    template no(x, y) =
+      test astToStr(x) & " is not " & astToStr(y):
+        check typeRel(c, y, x) == isNone
+    
+    yes seq(any), array(10, int) | seq(any)
+    # Sure, seq[any] is directly included
+
+    yes seq(int), seq(any)
+    yes seq(int), seq(number)
+    # Sure, the int sequence is certainly
+    # part of the number sequences (and all sequences)
+    
+    no seq(any), seq(float)
+    # Nope, seq[any] includes types that are not seq[float] (e.g. seq[int])
+
+    yes seq(int|string), seq(any)
+    # Sure
+ 
+    yes seq(int&string), seq(any)
+    # Again
+    
+    yes seq(int&string), seq(int)
+    # A bit more complicated
+    # seq[int&string] is not a real type, but it's analogous to
+    # seq[Sortable and Iterable], which is certainly a subset of seq[Sortable]
+
+    no seq(int|string), seq(int|float)
+    # Nope, seq[string] is not included in not included in
+    # the seq[int|float] set
+    
+    no seq(!(int|string)), seq(string)
+    # A sequence that is neither seq[int] or seq[string]
+    # is obviously not seq[string]
+     
+    no seq(!int), seq(number)
+    # Now your head should start to hurt a bit
+    # A sequence that is not seq[int] is not necessarily a number sequence
+    # it could well be seq[string] for example
+    
+    yes seq(!(int|string)), seq(!string)
+    # all sequnece types besides seq[int] and seq[string]
+    # are subset of all sequence types that are not seq[string]
+
+    no seq(!(int|string)), seq(!(string|TFoo))
+    # Nope, seq[TFoo] is included in the first set, but not in the second
+    
+    no seq(!string), seq(!number)
+    # Nope, seq[int] in included in the first set, but not in the second
+
+    yes seq(!number), seq(any)
+    yes seq(!int), seq(any)
+    no seq(any), seq(!any)
+    no seq(!int), seq(!any)
+    
+    yes int, ordinal
+    no  string, ordinal
+
diff --git a/compiler/testability.nim b/compiler/testability.nim
new file mode 100644
index 000000000..ceefd0a5e
--- /dev/null
+++ b/compiler/testability.nim
@@ -0,0 +1,5 @@
+template tests*(body: stmt) {.immediate.} =
+  when defined(selftest):
+    when not defined(unittest): import unittest
+    body
+
diff --git a/compiler/types.nim b/compiler/types.nim
index 4dec9ea2f..7e07a0667 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -382,33 +382,34 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
     if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
   assert(result != nil)
 
-proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType = 
+proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
   var marker = InitIntSet()
   result = mutateTypeAux(marker, t, iter, closure)
 
-proc ValueToString(a: PNode): string = 
+proc ValueToString(a: PNode): string =
   case a.kind
   of nkCharLit..nkUInt64Lit: result = $(a.intVal)
   of nkFloatLit..nkFloat128Lit: result = $(a.floatVal)
   of nkStrLit..nkTripleStrLit: result = a.strVal
   else: result = "<invalid value>"
 
-proc rangeToStr(n: PNode): string = 
+proc rangeToStr(n: PNode): string =
   assert(n.kind == nkRange)
   result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
 
 const 
-  typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty", 
-    "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc", 
-    "GenericInvokation", "GenericBody", "GenericInst", "GenericParam", 
-    "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple", 
-    "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc", 
+  typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
+    "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
+    "GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
+    "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
+    "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
     "pointer", "OpenArray[$1]", "string", "CString", "Forward",
     "int", "int8", "int16", "int32", "int64",
     "float", "float32", "float64", "float128",
     "uint", "uint8", "uint16", "uint32", "uint64",
     "bignum", "const ",
-    "!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"]
+    "!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
+    "ParametricTypeClass", "and", "or", "not", "any"]
 
 proc consToStr(t: PType): string =
   if t.len > 0: result = t.typeToString
@@ -421,7 +422,7 @@ proc constraintsToStr(t: PType): string =
     if i > 0: result.add(sep)
     result.add(t.sons[i].consToStr)
 
-proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = 
+proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
   if t == nil: return 
@@ -861,7 +862,7 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
   of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence,
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
      tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
-     tyOrdinal, tyTypeClass:
+     tyOrdinal, tyTypeClasses:
     CycleCheck()    
     result = sameChildrenAux(a, b, c) and sameFlags(a, b)
     if result and (a.kind == tyProc):
@@ -1042,7 +1043,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
     # XXX er ... no? these should not be allowed!
   of tyEmpty:
     result = taField in flags
-  of tyTypeClass:
+  of tyTypeClasses:
     result = true
   of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation:
     result = false