Nim can interface with C++ templates

This commit is contained in:
Araq 2015-01-22 23:38:29 +01:00
commit 22318ce8ac

View file

@ -199,7 +199,7 @@ const
proc cacheGetType(tab: TIdTable, key: PType): PRope = proc cacheGetType(tab: TIdTable, key: PType): PRope =
# returns nil if we need to declare this type # 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: # linear search is not necessary anymore:
result = PRope(idTableGet(tab, key)) result = PRope(idTableGet(tab, key))
@ -390,7 +390,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check)) app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check))
of nkRecCase: 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)) app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
uname = toRope(mangle(n.sons[0].sym.name.s) & 'U') uname = toRope(mangle(n.sons[0].sym.name.s) & 'U')
if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, uname]) 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]) if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, sname])
else: ae = sname else: ae = sname
fillLoc(field.loc, locField, field.typ, ae, OnUnknown) 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: if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
appf(result, "$1 $2[SEQ_DECL_SIZE];$n", appf(result, "$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname]) [getTypeDescAux(m, fieldType.elemType, check), sname])
else: 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()") else: internalError(n.info, "genRecordFieldsAux()")
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): PRope = 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 = proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
# returns only the type's name # returns only the type's name
var var t = getUniqueType(typ)
name, rettype, desc, recdesc: PRope
n: BiggestInt
t, et: PType
t = getUniqueType(typ)
if t == nil: internalError("getTypeDescAux: t == nil") if t == nil: internalError("getTypeDescAux: t == nil")
if t.sym != nil: useHeader(m, t.sym) if t.sym != nil: useHeader(m, t.sym)
result = getTypePre(m, t) 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. # C type generation into an analysis and a code generation phase somehow.
case t.kind case t.kind
of tyRef, tyPtr, tyVar: of tyRef, tyPtr, tyVar:
et = getUniqueType(t.lastSon) var et = t.lastSon
if et.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: 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 # this is correct! sets have no proper base type, so we treat
# ``var set[char]`` in `getParamTypeDesc` # ``var set[char]`` in `getParamTypeDesc`
et = getUniqueType(elemType(et)) et = elemType(etB)
case et.kind etB = et.skipTypes(abstractInst)
case etB.kind
of tyObject, tyTuple: of tyObject, tyTuple:
# no restriction! We have a forward declaration for structs if isImportedCppType(etB) and et.kind == tyGenericInst:
name = getTypeForward(m, et) result = con(getTypeDescAux(m, et, check), "*")
result = con(name, "*") else:
idTablePut(m.typeCache, t, result) # no restriction! We have a forward declaration for structs
pushType(m, et) let x = getUniqueType(etB)
let name = getTypeForward(m, x)
result = con(name, "*")
idTablePut(m.typeCache, t, result)
pushType(m, x)
of tySequence: of tySequence:
# no restriction! We have a forward declaration for structs # 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, "**") result = con(name, "**")
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
pushType(m, et) pushType(m, x)
else: else:
# else we have a strong dependency :-( # else we have a strong dependency :-(
result = con(getTypeDescAux(m, et, check), "*") result = con(getTypeDescAux(m, et, check), "*")
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:
et = getUniqueType(t.sons[0]) result = con(getTypeDescAux(m, t.sons[0], check), "*")
result = con(getTypeDescAux(m, et, check), "*")
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
of tyProc: of tyProc:
result = getTypeName(t) result = getTypeName(t)
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
var rettype, desc: PRope
genProcParams(m, t, rettype, desc, check) genProcParams(m, t, rettype, desc, check)
if not isImportedType(t): if not isImportedType(t):
if t.callConv != ccClosure: # procedure vars may need a closure! if t.callConv != ccClosure: # procedure vars may need a closure!
@ -567,26 +572,38 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
result = toRope("TGenericSeq") result = toRope("TGenericSeq")
app(result, "*") app(result, "*")
of tyArrayConstr, tyArray: of tyArrayConstr, tyArray:
n = lengthOrd(t) var n: BiggestInt = lengthOrd(t)
if n <= 0: if n <= 0: n = 1 # make an array of at least one element
n = 1 # make an array of at least one element
result = getTypeName(t) result = getTypeName(t)
idTablePut(m.typeCache, t, result) 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", appf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
[getTypeDescAux(m, t.sons[1], check), result, toRope(n)]) [foo, result, toRope(n)])
of tyObject, tyTuple: of tyObject, tyTuple:
result = cacheGetType(m.forwTypeCache, t) if isImportedCppType(t) and typ.kind == tyGenericInst:
if result == nil: # for instantiated templates we do not go through the type cache as the
result = getTypeName(t) # the type cache is not aware of 'tyGenericInst'.
if not isImportedType(t): result = getTypeName(t).con("<")
appf(m.s[cfsForwardTypes], getForwardStructFormat(m), for i in 1 .. typ.len-2:
[structOrUnion(t), result]) if i > 1: result.app(", ")
idTablePut(m.forwTypeCache, t, result) result.app(getTypeDescAux(m, typ.sons[i], check))
idTablePut(m.typeCache, t, result) # always call for sideeffects: result.app("> ")
if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check) # always call for sideeffects:
else: recdesc = getTupleDesc(m, t, result, check) assert t.kind != tyTuple
if not isImportedType(t): app(m.s[cfsTypes], recdesc) 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: of tySet:
case int(getSize(t)) case int(getSize(t))
of 1: result = toRope("NU8") of 1: result = toRope("NU8")