summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-06-02 19:52:06 +0300
committerZahary Karadjov <zahary@gmail.com>2012-06-02 19:52:06 +0300
commit88f7b7bc500325cc7399022c3dc137539d0f2640 (patch)
treed9e0d97895dc413b52c3eb9f9b523618fe76bfdc /compiler
parenta1da1f987b28ed041c3f3ad2317e756e2125aa30 (diff)
parent232ab71f208e341da327e54afa8a6d287141836b (diff)
downloadNim-88f7b7bc500325cc7399022c3dc137539d0f2640.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod into upstream
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim3
-rw-r--r--compiler/ccgcalls.nim15
-rwxr-xr-xcompiler/ccgexprs.nim36
-rwxr-xr-xcompiler/ccgstmts.nim31
-rwxr-xr-xcompiler/ccgtypes.nim11
-rwxr-xr-xcompiler/ccgutils.nim9
-rwxr-xr-xcompiler/ecmasgen.nim3
-rwxr-xr-xcompiler/evals.nim2
-rwxr-xr-xcompiler/lookups.nim21
-rwxr-xr-xcompiler/renderer.nim2
-rwxr-xr-xcompiler/semgnrc.nim2
-rwxr-xr-xcompiler/semstmts.nim8
-rwxr-xr-xcompiler/transf.nim6
-rwxr-xr-xcompiler/types.nim13
14 files changed, 111 insertions, 51 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index c59c47453..d9ec70450 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -145,6 +145,7 @@ type
     nkIfStmt,             # an if statement
     nkWhenStmt,           # a when expression or statement
     nkForStmt,            # a for statement
+    nkParForStmt,         # a parallel for statement
     nkWhileStmt,          # a while statement
     nkCaseStmt,           # a case statement
     nkTypeSection,        # a type section (consists of type definitions)
@@ -396,7 +397,7 @@ type
     mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, 
     mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, 
     mConTArr, mConTT, mSlice, 
-    mFields, mFieldPairs,
+    mFields, mFieldPairs, mOmpParFor,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem, 
     mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
     mIsPartOf, mAstToStr, mRand, 
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index f2fa6a280..17139f055 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -20,7 +20,8 @@ proc hasNoInit(call: PNode): bool {.inline.} =
 
 proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
   var pl = pl
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   if typ.sons[0] != nil:
     if isInvalidReturnType(typ.sons[0]):
       if sonsLen(ri) > 1: app(pl, ", ")
@@ -124,7 +125,8 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   # this is a hotspot in the compiler
   initLocExpr(p, ri.sons[0], op)
   var pl = con(op.r, "(")
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
@@ -150,7 +152,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var op: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl: PRope
-  var typ = ri.sons[0].typ
+  
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
@@ -201,7 +204,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var op, a: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl: PRope = nil
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   assert(sonsLen(typ) == sonsLen(typ.n))
@@ -228,7 +232,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   var op, a: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl = toRope"["
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   assert(sonsLen(typ) == sonsLen(typ.n))
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index eb20153fc..7a0face5e 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -283,7 +283,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
 
 proc expr(p: BProc, e: PNode, d: var TLoc)
 proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
-  initLoc(result, locNone, getUniqueType(e.typ), OnUnknown)
+  initLoc(result, locNone, e.typ, OnUnknown)
   expr(p, e, result)
 
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
@@ -543,17 +543,17 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
 
 proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
   initLocExpr(p, e.sons[0], a)
-  if (e.sons[1].kind != nkSym): InternalError(e.info, "genRecordFieldAux")
+  if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
   if d.k == locNone: d.s = a.s
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
-  result = getUniqueType(a.t)
+  result = a.t
 
 proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
   var a: TLoc
   var ty = genRecordFieldAux(p, e, d, a)
   var r = rdLoc(a)
   var f = e.sons[1].sym
-  if ty.n == nil:
+  if ty.kind == tyTuple:
     # we found a unique tuple type which lacks field information
     # so we use Field$i
     appf(r, ".Field$1", [toRope(f.position)])
@@ -561,14 +561,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
   else:
     var field: PSym = nil
     while ty != nil:
-      if not (ty.kind in {tyTuple, tyObject}):
+      if ty.kind notin {tyTuple, tyObject}:
         InternalError(e.info, "genRecordField")
       field = lookupInRecord(ty.n, f.name)
       if field != nil: break
       if gCmd != cmdCompileToCpp: app(r, ".Sup")
       ty = GetUniqueType(ty.sons[0])
-    if field == nil: InternalError(e.info, "genRecordField")
-    if field.loc.r == nil: InternalError(e.info, "genRecordField")
+    if field == nil: InternalError(e.info, "genRecordField 2 ")
+    if field.loc.r == nil: InternalError(e.info, "genRecordField 3")
     appf(r, ".$1", [field.loc.r])
     putIntoDest(p, d, field.typ, r)
 
@@ -579,16 +579,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   initLocExpr(p, e.sons[0], a)
   if d.k == locNone: d.s = a.s
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
-  var ty = getUniqueType(a.t)
+  var ty = a.t
   var r = rdLoc(a)
   case e.sons[1].kind
   of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
   else: internalError(e.info, "genTupleElem")
-  if ty.n != nil:
-    var field = ty.n.sons[i].sym
-    if field == nil: InternalError(e.info, "genTupleElem")
-    if field.loc.r == nil: InternalError(e.info, "genTupleElem")
-    appf(r, ".$1", [field.loc.r])
+  when false:
+    if ty.n != nil:
+      var field = ty.n.sons[i].sym
+      if field == nil: InternalError(e.info, "genTupleElem")
+      if field.loc.r == nil: InternalError(e.info, "genTupleElem")
+      appf(r, ".$1", [field.loc.r])
   else:
     appf(r, ".Field$1", [toRope(i)])
   putIntoDest(p, d, ty.sons[i], r)
@@ -1510,11 +1511,10 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
     for i in countup(0, sonsLen(n) - 1):
       var it = n.sons[i]
       if it.kind == nkExprColonExpr: it = it.sons[1]
-      if t.n == nil:
-        initLoc(rec, locExpr, it.typ, d.s)
-        rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
-        expr(p, it, rec)
-      else:
+      initLoc(rec, locExpr, it.typ, d.s)
+      rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
+      expr(p, it, rec)
+      when false:
         initLoc(rec, locExpr, it.typ, d.s)
         if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
         rec.r = ropef("$1.$2",
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index db6d5bd67..46e4f75df 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -32,7 +32,7 @@ proc genVarTuple(p: BProc, n: PNode) =
       assignLocalVar(p, v)
       initLocalVar(p, v, immediateAsgn=true)
     initLoc(field, locExpr, t.sons[i], tup.s)
-    if t.n == nil: 
+    if t.kind == tyTuple: 
       field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
     else: 
       if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
@@ -258,6 +258,34 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
     else: genStmts(p, t.sons[1])
     endBlock(p)
   
+proc genParForStmt(p: BProc, t: PNode) =
+  assert(sonsLen(t) == 3)
+  inc(p.withinLoop)
+  genLineDir(p, t)
+
+  preserveBreakIdx:
+    let forLoopVar = t.sons[0].sym
+    var rangeA, rangeB: TLoc
+    assignLocalVar(P, forLoopVar)
+    #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
+    #discard mangleName(forLoopVar)
+    let call = t.sons[1]
+    initLocExpr(p, call.sons[1], rangeA)
+    initLocExpr(p, call.sons[2], rangeB)
+    
+    appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" &
+                        "for ($1 = $2; $1 <= $3; ++$1)", 
+                        forLoopVar.loc.rdLoc,
+                        rangeA.rdLoc, rangeB.rdLoc,
+                        call.sons[3].getStr.toRope)
+    
+    p.breakIdx = startBlock(p)
+    p.blocks[p.breakIdx].isLoop = true
+    genStmts(p, t.sons[2])
+    endBlock(p)
+
+  dec(p.withinLoop)
+  
 proc genBreakStmt(p: BProc, t: PNode) = 
   var idx = p.breakIdx
   if t.sons[0].kind != nkEmpty: 
@@ -815,5 +843,6 @@ proc genStmts(p: BProc, t: PNode) =
         # we have not only the header: 
         if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags: 
           genProc(p.module, prc)
+  of nkParForStmt: genParForStmt(p, t)
   else: internalError(t.info, "genStmts(" & $t.kind & ')')
   
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 1b3e84cc4..4492c2fea 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -144,7 +144,7 @@ proc mapSetType(typ: PType): TCTypeKind =
 
 proc mapType(typ: PType): TCTypeKind = 
   case typ.kind
-  of tyNone: result = ctVoid
+  of tyNone, tyStmt: result = ctVoid
   of tyBool: result = ctBool
   of tyChar: result = ctChar
   of tySet: result = mapSetType(typ)
@@ -561,7 +561,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
         appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
       IdTablePut(m.forwTypeCache, t, result)
     IdTablePut(m.typeCache, t, result) # always call for sideeffects:
-    if t.n != nil: recdesc = getRecordDesc(m, t, result, check)
+    if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check)
     else: recdesc = getTupleDesc(m, t, result, check)
     if not isImportedType(t): app(m.s[cfsTypes], recdesc)
   of tySet: 
@@ -889,8 +889,11 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
   of tyEnum: genEnumInfo(gNimDat, t, result)
   of tyObject: genObjectInfo(gNimDat, t, result)
   of tyTuple: 
-    if t.n != nil: genObjectInfo(gNimDat, t, result)
-    else: genTupleInfo(gNimDat, t, result)
+    # if t.n != nil: genObjectInfo(gNimDat, t, result)
+    # else:
+    # BUGFIX: use consistently RTTI without proper field names; otherwise
+    # results are not deterministic!
+    genTupleInfo(gNimDat, t, result)
   else: InternalError("genTypeInfo(" & $t.kind & ')')
 
 proc genTypeSection(m: BModule, n: PNode) = 
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 12795358a..5ba523070 100755
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -87,14 +87,19 @@ proc GetUniqueType*(key: PType): PType =
   of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
     result = GetUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
-     tyOpenArray, tyArray, tyTuple, tySet, tyRange, 
+     tyOpenArray, tyArray, tySet, tyRange, tyTuple,
      tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
+    # tuples are quite horrible as C does not support them directly and
+    # tuple[string, string] is a (strange) subtype of
+    # tuple[nameA, nameB: string]. This bites us here, so we 
+    # use 'sameBackendType' instead of 'sameType'.
+
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
     if IdTableHasObjectAsKey(gTypeTable[k], key): return key 
     for h in countup(0, high(gTypeTable[k].data)): 
       var t = PType(gTypeTable[k].data[h].key)
-      if t != nil and sameType(t, key): 
+      if t != nil and sameBackendType(t, key): 
         return t
     IdTablePut(gTypeTable[k], key, key)
     result = key
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 9c9c01734..07754ee13 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -1343,7 +1343,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
   of nkWhileStmt: genWhileStmt(p, n, r)
   of nkVarSection, nkLetSection: genVarStmt(p, n, r)
   of nkConstSection: genConstStmt(p, n, r)
-  of nkForStmt: internalError(n.info, "for statement not eliminated")
+  of nkForStmt, nkParForStmt: 
+    internalError(n.info, "for statement not eliminated")
   of nkCaseStmt: genCaseStmt(p, n, r)
   of nkReturnStmt: genReturnStmt(p, n, r)
   of nkBreakStmt: genBreakStmt(p, n, r)
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 002fed194..5c77a4d94 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -1331,7 +1331,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   of nkPragmaBlock:
     result = evalAux(c, n.sons[1], flags)
   of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, 
-     nkLambdaKinds, nkContinueStmt, nkIdent: 
+     nkLambdaKinds, nkContinueStmt, nkIdent, nkParForStmt: 
     result = raiseCannotEval(c, n.info)
   of nkRefTy:
     result = evalAux(c, n.sons[0], flags)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 62f4a3391..d9725eedf 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -21,18 +21,19 @@ proc considerAcc*(n: PNode): PIdent =
     case n.len
     of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
     of 1: result = considerAcc(n.sons[0])
-    of 2:
-      if n[0].ident.id == ord(wStar):
+    else:
+      if n.len == 2 and n[0].kind == nkIdent and n[0].ident.id == ord(wStar):
+        # XXX find a better way instead of `*x` for 'genSym'
         result = genSym(n[1].ident.s)
       else:
-        result = getIdent(n[0].ident.s & n[1].ident.s)
-    else:
-      var id = ""
-      for i in 0.. <n.len:
-        if n.sons[i].kind != nkIdent:
-          GlobalError(n.info, errIdentifierExpected, renderTree(n))
-        id.add(n.sons[i].ident.s)
-      result = getIdent(id)
+        var id = ""
+        for i in 0.. <n.len:
+          let x = n.sons[i]
+          case x.kind
+          of nkIdent: id.add(x.ident.s)
+          of nkSym: id.add(x.sym.name.s)
+          else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
+        result = getIdent(id)
   else:
     GlobalError(n.info, errIdentifierExpected, renderTree(n))
 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 67b657657..a5e79762c 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -984,7 +984,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkCaseStmt, nkRecCase: gcase(g, n)
   of nkMacroStmt: gmacro(g, n)
   of nkTryStmt: gtry(g, n)
-  of nkForStmt: gfor(g, n)
+  of nkForStmt, nkParForStmt: gfor(g, n)
   of nkBlockStmt, nkBlockExpr: gblock(g, n)
   of nkStaticStmt: gstaticStmt(g, n)
   of nkAsmStmt: gasm(g, n)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index d8f017c4c..f7e64bdee 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -142,7 +142,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         a.sons[j] = semGenericStmt(c, a.sons[j], flags, toBind)
       a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind)
     closeScope(c.tab)
-  of nkForStmt: 
+  of nkForStmt, nkParForStmt: 
     var L = sonsLen(n)
     openScope(c.tab)
     n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, toBind)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 943c49bad..82f43e787 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -465,7 +465,11 @@ proc semFor(c: PContext, n: PNode): PNode =
     else:
       GlobalError(n.sons[length - 2].info, errIteratorExpected)
   elif call.sons[0].sym.magic != mNone:
-    result = semForFields(c, n, call.sons[0].sym.magic)
+    if call.sons[0].sym.magic == mOmpParFor:
+      result = semForVars(c, n)
+      result.kind = nkParForStmt
+    else:
+      result = semForFields(c, n, call.sons[0].sym.magic)
   else:
     result = semForVars(c, n)
   closeScope(c.tab)
@@ -979,7 +983,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
   of nkWhileStmt: result = semWhile(c, n)
   of nkTryStmt: result = semTry(c, n)
   of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
-  of nkForStmt: result = semFor(c, n)
+  of nkForStmt, nkParForStmt: result = semFor(c, n)
   of nkCaseStmt: result = semCase(c, n)
   of nkReturnStmt: result = semReturn(c, n)
   of nkAsmStmt: result = semAsm(c, n)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9e0d4051f..0ab8bc8d3 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -247,7 +247,7 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
 
 proc hasContinue(n: PNode): bool = 
   case n.kind
-  of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
+  of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: nil
   of nkContinueStmt: result = true
   else: 
     for i in countup(0, sonsLen(n) - 1): 
@@ -659,6 +659,10 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     inc c.inLoop
     result = transformFor(c, n)
     dec c.inLoop
+  of nkParForStmt:
+    inc c.inLoop
+    result = transformSons(c, n)
+    dec c.inLoop
   of nkCaseStmt: result = transformCase(c, n)
   of nkContinueStmt:
     result = PTransNode(newNode(nkBreakStmt))
diff --git a/compiler/types.nim b/compiler/types.nim
index 633524eff..2f201b9de 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -550,6 +550,7 @@ type
 
   TSameTypeClosure = object {.pure.}
     cmp: TDistinctCompare
+    ignoreTupleFields: bool
     recCheck: int
     s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
                             # (few elements expected)
@@ -645,7 +646,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
     for i in countup(0, sonsLen(a) - 1): 
       result = SameTypeAux(a.sons[i], b.sons[i], c)
       if not result: return 
-    if a.n != nil and b.n != nil: 
+    if a.n != nil and b.n != nil and not c.ignoreTupleFields: 
       for i in countup(0, sonsLen(a.n) - 1): 
         # check field names: 
         if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
@@ -787,6 +788,11 @@ proc SameType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   result = sameTypeAux(x, y, c)
   
+proc sameBackendType*(x, y: PType): bool =
+  var c = initSameTypeClosure()
+  c.ignoreTupleFields = true
+  result = sameTypeAux(x, y, c)
+  
 proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
   ## compares two type for equality (modulo type distinction)
   var c = initSameTypeClosure()
@@ -863,8 +869,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
       result = typeAllowedAux(marker, t.sons[0], skResult)
   of tyExpr, tyStmt, tyTypeDesc: 
     result = true
-  of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, tyTypeClass:
-    result = false            #InternalError('shit found');
+  of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, 
+      tyTypeClass:
+    result = false
   of tyEmpty, tyNil:
     result = kind == skConst
   of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: