importing of C++ nested generics like std::vector<T>::iterator, using the apostrophe operator

This commit is contained in:
Zahary Karadjov
2015-04-13 23:49:41 +03:00
parent 6c78f1a43d
commit 1ebf1aaa80
6 changed files with 101 additions and 16 deletions

View File

@@ -795,8 +795,8 @@ type
# for enum types a list of symbols
# for tyInt it can be the int literal
# for procs and tyGenericBody, it's the
# the body of the user-defined type class
# formal param list
# for concepts, the concept body
# else: unused
owner*: PSym # the 'owner' of the type
sym*: PSym # types have the sym associated with them

View File

@@ -385,18 +385,11 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
inc j
inc i
of '\'':
inc i
let stars = i
while pat[i] == '*': inc i
if pat[i] in Digits:
let j = pat[i].ord - '0'.ord
var t = typ.sons[j]
for k in 1..i-stars:
if t != nil and t.len > 0:
t = if t.kind == tyGenericInst: t.sons[1] else: t.elemType
var idx, stars: int
if scanCppGenericSlot(pat, i, idx, stars):
var t = resolveStarsInCppType(typ, idx, stars)
if t == nil: result.add(~"void")
else: result.add(getTypeDesc(p.module, t))
inc i
else:
let start = i
while i < pat.len:

View File

@@ -495,6 +495,33 @@ proc getTupleDesc(m: BModule, typ: PType, name: Rope,
else: add(result, desc)
add(result, "};" & tnl)
proc scanCppGenericSlot(pat: string, cursor, outIdx, outStars: var int): bool =
# A helper proc for handling cppimport patterns, involving numeric
# placeholders for generic types (e.g. '0, '**2, etc).
# pre: the cursor must be placed at the ' symbol
# post: the cursor will be placed after the final digit
# false will returned if the input is not recognized as a placeholder
inc cursor
let begin = cursor
while pat[cursor] == '*': inc cursor
if pat[cursor] in Digits:
outIdx = pat[cursor].ord - '0'.ord
outStars = cursor - begin
inc cursor
return true
else:
return false
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
# XXX: we should catch this earlier and report it as a semantic error
if idx >= typ.len: internalError "invalid apostrophe type parameter index"
result = typ.sons[idx]
for i in 1..stars:
if result != nil and result.len > 0:
result = if result.kind == tyGenericInst: result.sons[1]
else: result.elemType
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
# returns only the type's name
var t = getUniqueType(typ)
@@ -597,11 +624,33 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
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) & "<"
for i in 1 .. typ.len-2:
if i > 1: result.add(", ")
result.add(getTypeDescAux(m, typ.sons[i], check))
result.add("> ")
let cppName = getTypeName(t)
var i = 0
var chunkStart = 0
while i < cppName.data.len:
if cppName.data[i] == '\'':
var chunkEnd = <i
var idx, stars: int
if scanCppGenericSlot(cppName.data, i, idx, stars):
result.add cppName.data.substr(chunkStart, chunkEnd)
chunkStart = i
let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars)
if typeInSlot == nil or typeInSlot.kind == tyEmpty:
result.add(~"void")
else:
result.add getTypeDescAux(m, typeInSlot, check)
else:
inc i
if chunkStart != 0:
result.add cppName.data.substr(chunkStart)
else:
result = cppName & "<"
for i in 1 .. typ.len-2:
if i > 1: result.add(", ")
result.add(getTypeDescAux(m, typ.sons[i], check))
result.add("> ")
# always call for sideeffects:
assert t.kind != tyTuple
discard getRecordDesc(m, t, result, check)

View File

@@ -827,6 +827,9 @@ proc localError*(info: TLineInfo, msg: TMsgKind, arg = "") =
proc localError*(info: TLineInfo, arg: string) =
liMessage(info, errGenerated, arg, doNothing)
proc localError*(info: TLineInfo, format: string, params: openarray[string]) =
localError(info, format % params)
proc message*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doNothing)