From 7b0fb9b43f5fb76177603788e078acea418171e1 Mon Sep 17 00:00:00 2001 From: haxscramper Date: Wed, 13 Oct 2021 15:51:59 +0300 Subject: [PATCH] [FEATURE] Store wrapped type mappings Partially implement https://github.com/haxscramper/hcparse/issues/14 - allow `type_import.json` to be created when wrapgen script is executed. - ADDED :: - Properly implement anonymous type generation - Write and read dependency type import mappings --- src/hcparse.nim | 3 ++ src/hcparse/hc_codegen.nim | 75 +++++++++++++++++---------- src/hcparse/hc_grouping.nim | 10 ++-- src/hcparse/hc_parsefront.nim | 75 ++++++++++++++++++++++----- src/hcparse/hc_tsreader.nim | 67 ++++++++++++++---------- src/hcparse/interop_ir/wrap_store.nim | 73 ++++++++++++++++++++++---- 6 files changed, 222 insertions(+), 81 deletions(-) diff --git a/src/hcparse.nim b/src/hcparse.nim index 868ddb0..1288811 100644 --- a/src/hcparse.nim +++ b/src/hcparse.nim @@ -10,3 +10,6 @@ export hc_visitors, hc_impls, hc_parsefront + +import hmisc/core/debug +export debug diff --git a/src/hcparse/hc_codegen.nim b/src/hcparse/hc_codegen.nim index a712f82..ef5bbc7 100644 --- a/src/hcparse/hc_codegen.nim +++ b/src/hcparse/hc_codegen.nim @@ -42,27 +42,32 @@ func toNNode*[N](lib: CxxLibImport, asImport: bool): N = func toNNode*[N](libs: seq[CxxLibImport], asImport: bool): N = - let libs = sortedByIt(libs, it) - if asImport: - result = newNTree[N](nnkImportStmt) - for lib in libs: - result.add lib.getPathNoExt().mapIt(newNIdent[N](it)).foldl(newXCall("/", a, b)): + if libs.len == 0: + result = newEmptyNNode[N]() else: - result = newNTree[N](nnkExportStmt) - for lib in libs: - result.add newNIdent[N](lib.getFilename()) + let libs = sortedByIt(libs, it) + if asImport: + result = newNTree[N](nnkImportStmt) + for lib in libs: + result.add lib.getPathNoExt().mapIt(newNIdent[N](it)).foldl(newXCall("/", a, b)): + + else: + result = newNTree[N](nnkExportStmt) + for lib in libs: + result.add newNIdent[N](lib.getFilename()) proc toNNode*[N]( arg: CxxArg, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): NIdentDefs[N] + proc toNNode*[N]( t: CxxTypeUse, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): NType[N] = case t.kind: @@ -94,19 +99,25 @@ proc toNNode*[N]( toNNode[N](t.wrapped, conf, anon)])]) of ctkAnonObject: - let anon = toNNode[N](t.objDef, conf, anon) - result = newNNType[N]("ANON_OBJECT") + var def = t.objDef + def.decl.name = t.objParent & t.objUser + let gen = toNNode[N](def, conf, anon) + anon.add gen + result = newNNType[N](def.nimName) of ctkAnonEnum: - let anon = toNNode[N](t.enumDef, conf) - result = newNNType[N]("ANON_ENUM") + var def = t.enumDef + def.decl.name = t.enumParent & t.enumUser + let gen = toNNode[N](def, conf) + anon.add gen + result = newNNType[N](def.nimName) else: raise newImplementKindError(t) proc toNNode*[N]( t: CxxTypeDecl, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): NType[N] = newNType[N]( @@ -115,7 +126,7 @@ proc toNNode*[N]( proc toNNode*[N]( arg: CxxArg, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): NIdentDefs[N] = newNIdentDefs[N]( @@ -130,7 +141,7 @@ proc toNimComment*(com: seq[CxxComment]): string = proc toNNode*[N]( field: CxxField, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): ObjectField[N] = result = ObjectField[N]( @@ -197,7 +208,7 @@ proc toNNode*[N](header: CxxBind, conf: CodegenConf, name: string): seq[N] = proc toNNode*[N]( def: CxxAlias, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): tuple[alias: AliasDecl[N], extra: seq[NimDecl[N]]] = result.alias = newAliasDecl( @@ -226,7 +237,7 @@ proc toNNode*[N]( proc toNNode*[N]( def: CxxProc, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]], + anon: var seq[NimDecl[N]], onConstructor: CxxTypeKind = ctkIdent ): ProcDecl[N] = @@ -259,12 +270,14 @@ proc toNNode*[N]( proc toNNode*[N]( obj: CxxObject, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): seq[NimDecl[N]] = var res = newObjectDecl[N](obj.nimName) res.docComment = obj.docComment.toNimComment() res.addPragma("bycopy") + if obj.kind == cokUnion: + res.addPragma("union") # res.addPragma("inheritable") # res.addPragma("byref") @@ -313,7 +326,7 @@ proc toNNode*[N](en: CxxEnum, conf: CodegenConf): EnumDecl[N] = proc toNNode*[N]( entry: CxxEntry, conf: CodegenConf, - anon: var seq[NimTypeDecl[N]] + anon: var seq[NimDecl[N]] ): seq[NimDecl[N]] = case entry.kind: @@ -350,9 +363,12 @@ proc toNNode*[N]( raise newImplementKindError(entry) proc toNNode*[N](entries: seq[CxxEntry], conf: CodegenConf): seq[NimDecl[N]] = - var types: seq[NimTypeDecl[N]] - var other: seq[NimDecl[N]] - var visited: HashSet[CxxNamePair] + var + types: seq[NimTypeDecl[N]] + other: seq[NimDecl[N]] + anon: seq[NimDecl[N]] + visited: HashSet[CxxNamePair] + for item in entries: if item of cekEmpty: discard @@ -361,13 +377,20 @@ proc toNNode*[N](entries: seq[CxxEntry], conf: CodegenConf): seq[NimDecl[N]] = if item of cekForward: visited.incl item.name - for conv in toNNode[N](item, conf, types): - if conv of {nekObjectDecl, nekAliasDecl, nekEnumDecl}: + for conv in toNNode[N](item, conf, anon): + if conv of nekTypeKinds: types.add toNimTypeDecl(conv) else: other.add conv + for conv in anon: + if conv of nekTypeKinds: + types.add toNimTypeDecl(conv) + + else: + other.add conv + result.add toNimDecl(sortedByIt(types, it.getName())) result.add other diff --git a/src/hcparse/hc_grouping.nim b/src/hcparse/hc_grouping.nim index 6935800..7d2db3b 100644 --- a/src/hcparse/hc_grouping.nim +++ b/src/hcparse/hc_grouping.nim @@ -35,12 +35,6 @@ type inProcs: UsedSet inTypes: UsedSet -func mgetOrDefault*[K, V](table: var Table[K, V], key: K): var V = - if key notin table: - table[key] = default(V) - - return table[key] - proc registerUse*(ctype: CxxTypeUse, used: var UsedSet) = ## Register type and all it's inner used types (proctype arguments, ## generic parameters etc) in the used set. @@ -52,6 +46,10 @@ proc registerUse*(ctype: CxxTypeUse, used: var UsedSet) = if decl.isSome(): used.cursors.mgetOrDefault(decl.get()).incl use + elif use.hasExternalImport(): + let lib = use.getExternalImport() + used.libs.mgetOrDefault(lib).incl use + proc registerUsedTypes*(genProc: CxxProc, used: var UsedSet) = ## Register return type and all argument's types in used set diff --git a/src/hcparse/hc_parsefront.nim b/src/hcparse/hc_parsefront.nim index 267abc5..52e453c 100644 --- a/src/hcparse/hc_parsefront.nim +++ b/src/hcparse/hc_parsefront.nim @@ -1,6 +1,9 @@ import std/[sequtils, strformat, bitops, strutils, tables] +import + pkg/[jsony] + import ./cxtypes, ./hc_types, @@ -202,7 +205,7 @@ proc wrapViaTs*( ): CxxFile = assertRef conf.typeStore let relative = file.string.dropPrefix(libRoot.string) - let lib = cxxLibImport(conf.libName, relative.split("/")) + let lib = cxxLibImport(conf.libName, relative.split("/").filterIt(it.len > 0)) wrapViaTs(file.readFile(), conf, lib, some file).cxxFile(lib) proc wrapViaTsWave*( @@ -281,20 +284,49 @@ proc expandViaWave*( if not exists(resFile) or force: resFile.writeFile(expandViaWave(file, cache, conf)) + +const importMapFile* = "type_import.json" + +proc getImportMap*(files: seq[CxxFile]): CxxTypeImportMap = + for file in files: + for entry in file.entries: + if entry of {cekObject, cekAlias, cekEnum}: + result[CxxNameString(entry.cxxName.scopes.join("::"))] = file.savePath + +func `$`*(s: CxxNameString): string = s.string + +proc readImportMap*(store: var CxxTypeStore, file: AbsFile) = + assertExists(file) + let j = readFile(file) + let map = j.fromJson(Table[string, CxxLibImport]) + for key, val in map: + store.importDecls[cxxName(key.split("::"))] = val + +proc readImportMap*(store: var CxxTypeStore, dirs: seq[AbsDir]) = + for dir in dirs: + for file in walkDir(dir, AbsFile, exts = @["json"]): + if file.name() == "type_import": + readImportMap(store, file) + break + + + proc initCSharedLibFixConf*( lib: string, + packageName: string, isIcpp: bool, libRoot: AbsDir, expandMap: CxxExpandMap, configFiles: seq[string] = @["lib" & lib & "_config"], - base: CxxFixConf = baseFixConf, + base: CxxFixConf = baseFixConf, libIncludePrefix: string = lib, - nameStyle: IdentStyle = idsSnake + nameStyle: IdentStyle = idsSnake, + depDirs: seq[AbsDir] = @[] ): CxxFixConf = var fixConf = base fixConf.isIcpp = isIcpp - fixConf.libName = lib + fixConf.libName = packageName fixConf.onGetBind(): case entry.kind: @@ -315,6 +347,8 @@ proc initCSharedLibFixConf*( cache.fixContextedName(name, fixConf.libNameStyle) fixConf.typeStore = newTypeStore() + fixConf.typeStore.readImportMap(depDirs) + return fixConf proc wrapViaTs*( @@ -331,28 +365,43 @@ proc wrapViaTs*( err.msg.add "\nException raised while processing file " & file.string raise err +type + GenFiles = object + genNim*: seq[AbsFile] + genTypeMap*: Option[AbsFile] proc writeFiles*( outDir: AbsDir, files: seq[CxxFile], - codegenConf: CodegenConf - ): seq[AbsFile] = + codegenConf: CodegenConf, + extraTypes: seq[(CxxName, CxxLibImport)] = @[] + ): GenFiles = + + let mapFile = outDir /. importMapFile + result.genTypeMap = some mapFile + var map = getImportMap(files) + for (ctype, cimport) in extraTypes: + map[CxxNameString(ctype.scopes.join("::"))] = cimport + + writeFile(mapFile, toJson(map)) let group = regroupFiles(files) for fix in group: let res = outDir / fix.getFile().withExt("nim") res.writeFile(toNNode[PNode](fix, codegenConf).toPString()) - result.add res + result.genNim.add res proc wrapCSharedLibViaTsWave*( inDir, tmpDir, outDir: AbsDir, - libName: string, + libName, packageName: string, ignoreIn: seq[string] = @[], persistentOut: seq[string] = @[ "hcparse_generate", "lib" & libName & "_config"], - ): seq[AbsFile] = + depDirs: seq[AbsDir] = @[], + extraTypes: seq[(CxxName, CxxLibImport)] = @[] + ): GenFiles = var expandMap = expandViaWave( listFiles(inDir, ignoreNames = ignoreIn), tmpDir, baseCParseConf @@ -362,15 +411,15 @@ proc wrapCSharedLibViaTsWave*( let fixConf = initCSharedLibFixConf( - libName, false, inDir, expandMap) + libName, packageName, false, inDir, expandMap, depDirs = depDirs) resultWrapped = tmpDir.wrapViaTs(fixConf) - resultGrouped = writeFiles(outDir, resultWrapped, cCodegenConf) + resultGrouped = writeFiles(outDir, resultWrapped, cCodegenConf, extraTypes = extraTypes) return resultGrouped -proc validateGenerated*(files: seq[AbsFile]) = - for file in items(files): +proc validateGenerated*(files: GenFiles) = + for file in items(files.genNim): try: execShell shellCmd(nim, check, errormax = 3, $file) diff --git a/src/hcparse/hc_tsreader.nim b/src/hcparse/hc_tsreader.nim index 6e0a6ab..4c36dac 100644 --- a/src/hcparse/hc_tsreader.nim +++ b/src/hcparse/hc_tsreader.nim @@ -66,11 +66,9 @@ proc toCxxArg*(node: CppNode, idx: int): CxxArg proc toCxxEnum*(node: CppNode, coms): CxxEnum proc toCxxObject*(node: CppNode, coms): CxxObject -proc toCxxType*(node: CppNode): CxxTypeUse = +proc toCxxType*(node: CppNode, parent, user: Option[CxxNamePair]): CxxTypeUse = case node.kind: - of cppTypeIdentifier, - cppSizedTypeSpecifier, - cppPrimitiveType: + of cppTypeIdentifier, cppSizedTypeSpecifier, cppPrimitiveType: result = cxxTypeUse(cxxPair( mapTypeName(node), cxxName(@[node.strVal()]))) @@ -84,16 +82,16 @@ proc toCxxType*(node: CppNode): CxxTypeUse = var coms: seq[CxxComment] case node.kind: of cppEnumSpecifier: - result = cxxTypeUse(toCxxEnum(node, coms)) + result = cxxTypeUse(toCxxEnum(node, coms), parent.get(), user.get()) of cppUnionSpecifier, cppStructSpecifier: - result = cxxTypeUse(toCxxObject(node, coms)) + result = cxxTypeUse(toCxxObject(node, coms), parent.get(), user.get()) else: raise newUnexpectedKindError(node) else: - result = toCxxType(node[0]) + result = toCxxType(node[0], parent, user) of cppFieldDeclaration: var args: seq[CxxArg] @@ -102,7 +100,7 @@ proc toCxxType*(node: CppNode): CxxTypeUse = args.add toCxxArg(param, idx) inc idx - result = cxxTypeUse(args, toCxxType(node["type"])) + result = cxxTypeUse(args, toCxxType(node["type"], parent, user)) else: raise newImplementKindError(node, node.treeRepr()) @@ -259,19 +257,21 @@ proc toCxxArg*(node: CppNode, idx: int): CxxArg = assertKind(node, {cppParameterDeclaration}) var name: CxxNamePair - argt: CxxTypeUse = toCxxType(node["type"]) + argt: CxxTypeUse if "declarator" in node: if node["declarator"] of cppAbstractPointerDeclarator: - name = cxxPair("a" & $idx) - argt = argt.wrap(ctkPtr) + name = cxxPair("a" & $idx, cncArg) + argt = toCxxType(node["type"], none CxxNamePair, some name).wrap(ctkPtr) else: - name = cxxPair(getName(node["declarator"])) + name = cxxPair(getName(node["declarator"]), cncArg) + argt = toCxxType(node["type"], none CxxNamePair, some name) pointerWraps(node["declarator"], argt) else: - name = cxxPair("a" & $idx) + name = cxxPair("a" & $idx, cncArg) + argt = toCxxType(node["type"], none CxxNamePair, some name) result = cxxArg(name, argt) @@ -283,7 +283,11 @@ proc toCxxProc*( ): CxxProc = result = cxxProc(cxxPair(node["declarator"].getName())) - result.returnType = toCxxType(node["type"]) + result.returnType = toCxxType( + node["type"], + some result.head.name, + some result.head.name + ) if parent.isSome(): result.methodOf = some parent.get().decl.cxxTypeUse() @@ -313,18 +317,16 @@ proc toCxxProc*( argComs.clear() -proc toCxxField*(node: CppNode, coms): CxxField = +proc toCxxField*(node: CppNode, coms; parent: CxxNamePair): CxxField = assertKind(node, {cppFieldDeclaration}) let decl = node["declarator"] + let name = cxxPair(getName(decl)) if decl of cppFunctionDeclarator: - result = cxxField(cxxPair(getName(decl)), toCxxType(node)) + result = cxxField(name, toCxxType(node, some parent, some name)) else: - result = cxxField( - cxxPair(getName(decl)), - toCxxType(node["type"])) - + result = cxxField(name, toCxxType(node["type"], some parent, some name)) pointerWraps(decl, result.nimType) proc toCxxForwardType*(node: CppNode, coms): CxxForward = @@ -353,17 +355,20 @@ proc toCxxObject*(node: CppNode, coms): CxxObject = if field["declarator"] of cppFunctionDeclarator: let name = field["declarator"]["declarator"] if name of cppParenthesizedDeclarator: - result.mfields.add toCxxField(field, coms).withIt do: + result.mfields.add toCxxField( + field, coms, result.decl.name).withIt do: it.add coms coms.clear() else: - result.methods.add toCxxProc(field, coms, some result).withIt do: + result.methods.add toCxxProc( + field, coms, some result).withIt do: it.add coms coms.clear() else: - result.mfields.add toCxxField(field, coms).withIt do: + result.mfields.add toCxxField( + field, coms, result.decl.name).withIt do: it.add coms coms.clear() @@ -390,7 +395,11 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] = of cppTypeIdentifier, cppPointerDeclarator, cppPrimitiveType: - let newType = toCxxType(node["declarator"]).toDecl() + let newType = toCxxType( + node["declarator"], + parent = none CxxNamePair, + user = none CxxNamePair).toDecl() + let baseBody = node[0] if baseBody of { cppSizedTypeSpecifier, cppPrimitiveType, cppTypeIdentifier @@ -399,7 +408,10 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] = cppStructSpecifier, cppUnionSpecifier, cppEnumSpecifier} and "body" notin baseBody ): - var alias = cxxAlias(newType, toCxxType(node["type"])).withIt do: + var alias = cxxAlias( + newType, + toCxxType(node["type"], none CxxNamePair, none CxxNamePair) + ).withIt do: it.add coms coms.clear() pointerWraps(node["declarator"], alias.baseType) @@ -464,7 +476,7 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] = "" - var t = toCxxType(arg["type"]) + var t = toCxxType(arg["type"], none CxxNamePair, none CxxNamePair) if d in arg: pointerWraps(arg[d], t) @@ -474,7 +486,8 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] = result.add cxxAlias( body[d].getName().cxxPair().cxxTypeDecl(), - cxxTypeUse(args, toCxxType(node["type"]))) + cxxTypeUse( + args, toCxxType(node["type"], none CxxNamePair, none CxxNamePair))) else: raise newImplementKindError(node, node.treeRepr()) diff --git a/src/hcparse/interop_ir/wrap_store.nim b/src/hcparse/interop_ir/wrap_store.nim index 9faaa45..0f5cc8c 100644 --- a/src/hcparse/interop_ir/wrap_store.nim +++ b/src/hcparse/interop_ir/wrap_store.nim @@ -90,10 +90,14 @@ type isAnonymous*: bool isPromotedForward*: bool + CxxNameString* = distinct string + CxxTypeImportMap* = OrderedTable[CxxNameString, CxxLibImport] CxxName* = object scopes*: seq[string] CxxNameContext* = enum + cncNone + cncType cncArg cncVar @@ -130,6 +134,7 @@ type forwardDecls*: Table[CxxName, seq[CxxTypeDecl]] classDecls*: Table[CxxName, seq[CxxObject]] + importDecls*: Table[CxxName, CxxLibImport] CxxTypeRef* = object ## Reference to used C++ type @@ -210,9 +215,13 @@ type ## } ## ``` objDef*: CxxObject + objParent*: CxxNamePair + objUser*: CxxNamePair of ctkAnonEnum: enumDef*: CxxEnum + enumParent*: CxxNamePair + enumUser*: CxxNamePair @@ -680,6 +689,7 @@ iterator items*(use: CxxTypeUse): CxxTypeUse = yield use[i] +func `==`*(s1, s2: CxxNameString): bool = s1.string == s2.string func `==`*(n1, n2: CxxName): bool = n1.scopes == n2.scopes func `==`*(l1, l2: CxxLibImport): bool = l1.library == l2.library and l1.importPath == l2.importPath @@ -697,6 +707,7 @@ func `<`*(l1, l2: CxxLibImport): bool = else: return l1.library < l2.library +func hash*(s: CxxNameString): Hash = hash(s.string) func hash*(name: CxxName): Hash = hash(name.scopes) func hash*[T](opt: Option[T]): Hash = @@ -800,6 +811,8 @@ func name*(e: CxxEntry): CxxNamePair = else: raise newImplementKindError(e) +func cxxName*(e: CxxEntry): CxxName = e.name.cxx + func getLocation*(e: CxxEntry): CxxSpellingLocation = var tmp: Option[CxxSpellingLocation] case e.kind: @@ -817,10 +830,24 @@ func getLocation*(e: CxxEntry): CxxSpellingLocation = assertOption tmp, $e return tmp.get -func cxxPair*(nim: string, cxx: CxxName): CxxNamePair = - CxxNamePair(nim: nim, cxx: cxx) +func cxxPair*( + nim: string, cxx: CxxName, + context: CxxNameContext = cncNone + ): CxxNamePair = + + CxxNamePair(nim: nim, cxx: cxx, context: context) + +func cxxPair*( + name: string, + context: CxxNameContext = cncNone + ): CxxNamePair = -func cxxPair*(name: string): CxxNamePair = cxxPair(name, cxxName(@[name])) + cxxPair(name, cxxName(@[name]), context) + +func `&`*(p1, p2: CxxNamePair): CxxNamePair = + CxxNamePair( + context: p2.context, nim: p1.nim & p2.nim, + cxx: CxxName(scopes: p1.cxx.scopes & p2.cxx.scopes)) func isConst*(pr: CxxProc): bool = cpfConst in pr.flags func isConstructor*(pr: CxxProc): bool = pr.constructorOf.isSome() @@ -907,11 +934,19 @@ func cxxTypeUse*( CxxTypeUse( kind: ctkIdent, cxxType: cxxTypeRef(head, store), genParams: @genParams) -func cxxTypeUse*(objDef: CxxObject): CxxTypeUse = - CxxTypeUse(kind: ctkAnonObject, objDef: objDef) +func cxxTypeUse*( + objDef: CxxObject, parent, user: CxxNamePair + ): CxxTypeUse = + CxxTypeUse( + kind: ctkAnonObject, objDef: objDef, + objParent: parent, objUser: user) -func cxxTypeUse*(enumDef: CxxEnum): CxxTypeUse = - CxxTypeUse(kind: ctkAnonEnum, enumDef: enumDef) +func cxxTypeUse*( + enumDef: CxxEnum, parent, user: CxxNamePair + ): CxxTypeUse = + CxxTypeUse( + kind: ctkAnonEnum, enumDef: enumDef, + enumParent: parent, enumUser: user) func toDecl*(use: CxxTypeUse): CxxTypeDecl = assertKind(use, {ctkIdent}) @@ -961,10 +996,20 @@ func getDecl*(use: CxxTypeUse): Option[CxxTypeDecl] = return use.cxxType.typeStore.getDecl( use.cxxName(), use.cxxType.typeLib) +func hasExternalImport*(use: CxxTypeuse): bool = + if use of ctkIdent: + let store = use.cxxType.typeStore + result = use.cxxName() in store.importDecls + +func getExternalImport*(use: CxxTypeUse): CxxLibImport = + assertKind(use, ctkIdent) + use.cxxType.typeStore.importDecls.getOr( + use.cxxName(), "missing mapping for type in external import list") + func hasImport*(use: CxxTypeUse): bool = if use of ctkIdent: let decl = use.getDecl() - result = decl.isSome() and decl.get().typeImport.isSome() + result = decl.get().typeImport.isSome() else: result = false @@ -985,6 +1030,10 @@ func hasFullDecl*(decl: CxxTypeDecl): bool = func cxxLibImport*(library: string, path: seq[string]): CxxLibImport = + for item in path: + if item.len == 0: + raise newArgumentError("Lib import path cannot contain elements of length 0") + CxxLibImport(library: library, importPath: path) func getImport*(decl: CxxTypeDecl): CxxLibImport = decl.typeImport.get() @@ -1382,13 +1431,19 @@ proc fixIdentsRec*( proc auxArg(use: var CxxTypeUse, cache: var StringNameCache) = case use.kind: of ctkWrapKinds: auxArg(use.wrapped, cache) - of ctkStaticParam, ctkAnonEnum: discard + of ctkStaticParam: discard + of ctkAnonEnum: + aux(use.enumParent) + aux(use.enumUser) + of ctkArrayKinds: auxArg(use.arrayElement, cache) of ctkIdent: for param in mitems(use.genParams): auxArg(param, cache) of ctkAnonObject: + aux(use.objParent) + aux(use.objUser) for field in mitems(use.objDef.mfields): aux(field.nimType, cache)