summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-01-22 23:38:29 +0100
committerAraq <rumpf_a@web.de>2015-01-23 00:36:58 +0100
commit22318ce8ac2b720fe6b6abc9ae4385e66d96c509 (patch)
tree1d9a96084b96e91d2d88eba83bc2a256f40b4743
parent60042805222d1261592db9d782df96ae190d71d5 (diff)
downloadNim-22318ce8ac2b720fe6b6abc9ae4385e66d96c509.tar.gz
Nim can interface with C++ templates
-rw-r--r--compiler/ccgtypes.nim109
1 files changed, 63 insertions, 46 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index cfddd0efe..90996d9cd 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -199,7 +199,7 @@ const
 
 proc cacheGetType(tab: TIdTable, key: PType): PRope = 
   # returns nil if we need to declare this type
-  # since types are now unique via the ``GetUniqueType`` mechanism, this slow
+  # since types are now unique via the ``getUniqueType`` mechanism, this slow
   # linear search is not necessary anymore:
   result = PRope(idTableGet(tab, key))
 
@@ -390,7 +390,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
     for i in countup(0, sonsLen(n) - 1): 
       app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check))
   of nkRecCase: 
-    if (n.sons[0].kind != nkSym): internalError(n.info, "genRecordFieldsAux")
+    if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux")
     app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
     uname = toRope(mangle(n.sons[0].sym.name.s) & 'U')
     if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, uname])
@@ -421,12 +421,14 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
     if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, sname])
     else: ae = sname
     fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
-    let fieldType = field.loc.t
+    let fieldType = field.loc.t.skipTypes(abstractInst)
     if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
       appf(result, "$1 $2[SEQ_DECL_SIZE];$n",
           [getTypeDescAux(m, fieldType.elemType, check), sname])
     else:
-      appf(result, "$1 $2;$n", [getTypeDescAux(m, fieldType, check), sname])
+      # don't use fieldType here because we need the
+      # tyGenericInst for C++ template support
+      appf(result, "$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname])
   else: internalError(n.info, "genRecordFieldsAux()")
   
 proc getRecordFields(m: BModule, typ: PType, check: var IntSet): PRope = 
@@ -486,11 +488,7 @@ proc pushType(m: BModule, typ: PType) =
 
 proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = 
   # returns only the type's name
-  var 
-    name, rettype, desc, recdesc: PRope
-    n: BiggestInt
-    t, et: PType
-  t = getUniqueType(typ)
+  var t = getUniqueType(typ)
   if t == nil: internalError("getTypeDescAux: t == nil")
   if t.sym != nil: useHeader(m, t.sym)
   result = getTypePre(m, t)
@@ -502,35 +500,42 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
     # C type generation into an analysis and a code generation phase somehow.
   case t.kind
   of tyRef, tyPtr, tyVar: 
-    et = getUniqueType(t.lastSon)
-    if et.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: 
+    var et = t.lastSon
+    var etB = et.skipTypes(abstractInst)
+    if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: 
       # this is correct! sets have no proper base type, so we treat
       # ``var set[char]`` in `getParamTypeDesc`
-      et = getUniqueType(elemType(et))
-    case et.kind
-    of tyObject, tyTuple: 
-      # no restriction! We have a forward declaration for structs
-      name = getTypeForward(m, et)
-      result = con(name, "*")
-      idTablePut(m.typeCache, t, result)
-      pushType(m, et)
-    of tySequence: 
+      et = elemType(etB)
+      etB = et.skipTypes(abstractInst)
+    case etB.kind
+    of tyObject, tyTuple:
+      if isImportedCppType(etB) and et.kind == tyGenericInst:
+        result = con(getTypeDescAux(m, et, check), "*")
+      else:
+        # no restriction! We have a forward declaration for structs
+        let x = getUniqueType(etB)
+        let name = getTypeForward(m, x)
+        result = con(name, "*")
+        idTablePut(m.typeCache, t, result)
+        pushType(m, x)
+    of tySequence:
       # no restriction! We have a forward declaration for structs
-      name = getTypeForward(m, et)
+      let x = getUniqueType(etB)
+      let name = getTypeForward(m, x)
       result = con(name, "**")
       idTablePut(m.typeCache, t, result)
-      pushType(m, et)
-    else: 
+      pushType(m, x)
+    else:
       # else we have a strong dependency  :-(
       result = con(getTypeDescAux(m, et, check), "*")
       idTablePut(m.typeCache, t, result)
-  of tyOpenArray, tyVarargs: 
-    et = getUniqueType(t.sons[0])
-    result = con(getTypeDescAux(m, et, check), "*")
+  of tyOpenArray, tyVarargs:
+    result = con(getTypeDescAux(m, t.sons[0], check), "*")
     idTablePut(m.typeCache, t, result)
-  of tyProc: 
+  of tyProc:
     result = getTypeName(t)
     idTablePut(m.typeCache, t, result)
+    var rettype, desc: PRope
     genProcParams(m, t, rettype, desc, check)
     if not isImportedType(t): 
       if t.callConv != ccClosure: # procedure vars may need a closure!
@@ -545,7 +550,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
     # we cannot use getTypeForward here because then t would be associated
     # with the name of the struct, not with the pointer to the struct:
     result = cacheGetType(m.forwTypeCache, t)
-    if result == nil: 
+    if result == nil:
       result = getTypeName(t)
       if not isImportedType(t): 
         appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
@@ -567,27 +572,39 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
         result = toRope("TGenericSeq")
     app(result, "*")
   of tyArrayConstr, tyArray: 
-    n = lengthOrd(t)
-    if n <= 0: 
-      n = 1                   # make an array of at least one element
+    var n: BiggestInt = lengthOrd(t)
+    if n <= 0: n = 1   # make an array of at least one element
     result = getTypeName(t)
     idTablePut(m.typeCache, t, result)
-    if not isImportedType(t): 
+    if not isImportedType(t):
+      let foo = getTypeDescAux(m, t.sons[1], check)
       appf(m.s[cfsTypes], "typedef $1 $2[$3];$n", 
-           [getTypeDescAux(m, t.sons[1], check), result, toRope(n)])
-  of tyObject, tyTuple: 
-    result = cacheGetType(m.forwTypeCache, t)
-    if result == nil: 
-      result = getTypeName(t)
-      if not isImportedType(t): 
-        appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
-           [structOrUnion(t), result])
-      idTablePut(m.forwTypeCache, t, result)
-    idTablePut(m.typeCache, t, result) # always call for sideeffects:
-    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: 
+           [foo, result, toRope(n)])
+  of tyObject, tyTuple:
+    if isImportedCppType(t) and typ.kind == tyGenericInst:
+      # for instantiated templates we do not go through the type cache as the
+      # the type cache is not aware of 'tyGenericInst'.
+      result = getTypeName(t).con("<")
+      for i in 1 .. typ.len-2:
+        if i > 1: result.app(", ")
+        result.app(getTypeDescAux(m, typ.sons[i], check))
+      result.app("> ")
+      # always call for sideeffects:
+      assert t.kind != tyTuple
+      discard getRecordDesc(m, t, result, check)
+    else:
+      result = cacheGetType(m.forwTypeCache, t)
+      if result == nil:
+        result = getTypeName(t)
+        if not isImportedType(t): 
+          appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
+             [structOrUnion(t), result])
+        idTablePut(m.forwTypeCache, t, result)
+      idTablePut(m.typeCache, t, result) # always call for sideeffects:
+      let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
+                    else: getTupleDesc(m, t, result, check)
+      if not isImportedType(t): app(m.s[cfsTypes], recdesc)
+  of tySet:
     case int(getSize(t))
     of 1: result = toRope("NU8")
     of 2: result = toRope("NU16")