diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2020-03-30 15:46:34 -0500 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2020-03-30 15:46:34 -0500 |
| commit | e06917f40f5bd3a4b4bec51d05d85dffa4eb5867 (patch) | |
| tree | 58e887f548d0a6276dcc35a686d523420f544a1c | |
| parent | 8b9c39f42eec79607392c81538e08da1b814809a (diff) | |
| download | nimterop-e06917f40f5bd3a4b4bec51d05d85dffa4eb5867.tar.gz nimterop-e06917f40f5bd3a4b4bec51d05d85dffa4eb5867.zip | |
c2nImport ret, del specials from header, cache if exec not die, ast2 type pragma improvements
| -rw-r--r-- | nimterop.nimble | 5 | ||||
| -rw-r--r-- | nimterop/ast2.nim | 138 | ||||
| -rw-r--r-- | nimterop/build.nim | 9 | ||||
| -rw-r--r-- | nimterop/cimport.nim | 2 | ||||
| -rw-r--r-- | tests/include/tast2.h | 8 | ||||
| -rw-r--r-- | tests/tast2.nim | 247 |
6 files changed, 305 insertions, 104 deletions
diff --git a/nimterop.nimble b/nimterop.nimble index 86ee029..108d935 100644 --- a/nimterop.nimble +++ b/nimterop.nimble @@ -5,8 +5,6 @@ author = "genotrance" description = "C/C++ interop for Nim" license = "MIT" -# this gives Warning: Binary 'nimterop/toast' was already installed from source directory -# when running `nimble install --verbose -y` bin = @["nimterop/toast"] installDirs = @["nimterop"] installFiles = @["config.nims"] @@ -37,7 +35,7 @@ task test, "Test": buildToastTask() execTest "tests/tast2.nim" - #execCmd "nim c -f -d:HEADER -r tests/tast2.nim" + execCmd "nim c -f -d:HEADER -r tests/tast2.nim" execTest "tests/tnimterop_c.nim" execCmd "nim cpp -f -r tests/tnimterop_cpp.nim" @@ -53,5 +51,6 @@ task test, "Test": # getHeader tests withDir("tests"): execCmd("nim e getheader.nims") + execCmd("nim e wrappers.nims") docsTask() diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim index 93b26a1..7eb22a1 100644 --- a/nimterop/ast2.nim +++ b/nimterop/ast2.nim @@ -57,7 +57,7 @@ proc getOverrideOrSkip(nimState: NimState, node: TSNode, origname: string, kind: let # Get cleaned name for symbol, set parent so that cOverride is ignored name = nimState.getIdentifier(origname, kind, parent = "override") - + override = nimState.getOverride(origname, kind) var @@ -115,7 +115,7 @@ proc newConstDef(nimState: NimState, node: TSNode, fname = "", fval = ""): PNode else: # node[0] = identifier = const name nimState.getNodeVal(node.getAtom()) - + name = nimState.getIdentifier(origname, nskConst) info = nimState.getLineInfo(node) ident = nimState.getIdent(name, info) @@ -182,7 +182,7 @@ proc addPragma(nimState: NimState, node: TSNode, pragma: PNode, name: string, va let pinfo = nimState.getLineInfo(node.getAtom()) pident = nimState.getIdent(name, pinfo, exported = false) - + if value.isNil: pragma.add pident else: @@ -248,19 +248,28 @@ proc newPragmaExpr(nimState: NimState, node: TSNode, ident: PNode, pragmas: seq[ result.add ident result.add nimState.newPragma(node, pragmas) -proc newTypeIdent(nimState: NimState, node: TSNode, kind = nskType, fname = "", pragmas: seq[string] = @[]): PNode = +proc newTypeIdent(nimState: NimState, node: TSNode, kind = nskType, fname = "", pragmas: seq[string] = @[], istype = false): PNode = # Create nkTypeDef PNode with first ident if `nskType` else just create an nkPostfix node for `nskProc` # # If `fname`, use it instead of node.getAtom() for name # If `pragmas`, add as nkPragmaExpr but only if `nskType` since procs add pragmas elsewhere + # If `istype` is set, this is a typedef, else struct/union so add {.importc: "struct/union X".} when includeHeader let - (tname, origname, info) = nimState.getNameInfo(node.getAtom(), kind) + (tname, torigname, info) = nimState.getNameInfo(node.getAtom(), kind) - name = + origname = if fname.nBl: fname else: + torigname + + # Process name if forced, getNameInfo() already runs getIdentifier() + name = + if fname.nBl: + nimState.getIdentifier(fname, kind) + else: tname + ident = nimState.getIdent(name, info) if name.Bl: @@ -277,20 +286,39 @@ proc newTypeIdent(nimState: NimState, node: TSNode, kind = nskType, fname = "", # ), # nkEmpty() # ) - let + var pragmas = - if nimState.includeHeader and tname == origname: - # Need to add impShort - pragmas & nimState.impShort + if nimState.includeHeader: + # Need to add header and importc + if istype and name == origname: + # Need to add impShort since neither struct/union nor name change + pragmas & nimState.impShort + else: + # Add header shortcut, additional pragmas added later + pragmas & (nimState.impShort & "H") else: pragmas prident = - if pragmas.nBl and not ident.isNil: + if pragmas.nBl: nimState.newPragmaExpr(node, ident, pragmas) else: ident - + + if nimState.includeHeader: + if not istype or name != origname: + # Add importc pragma since either struct/union or name changed + let + uors = + if not istype: + if "union" in pragmas: + "union " + else: + "struct " + else: + "" + nimState.addPragma(node, prident[1], "importc", newStrNode(nkStrLit, &"{uors}{origname}")) + result = newNode(nkTypeDef) result.add prident result.add newNode(nkEmpty) @@ -302,7 +330,7 @@ proc newTypeIdent(nimState: NimState, node: TSNode, kind = nskType, fname = "", # nkIdent(name) # ) result = ident - + nimState.identifierNodes[name] = result else: necho &"# $1 '{origname}' is duplicate, skipped" % getKeyword(kind) @@ -525,24 +553,37 @@ proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode = if not field.isNil: result.add field -proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname = "", union = false) = +proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname = "", istype = false, union = false) = # Add a type of object # # If `typeDef` is set, use it instead of creating new PNode # If `fname` is set, use it as the name when creating new PNode + # If `istype` is set, this is a typedef, else struct/union decho("addTypeObject()") let - pragmas = - if union: - @["union", "bycopy"] + # Object has fields or not + fdlist = node.anyChildInTree("field_declaration_list") + + pragmas = block: + var pragmas = + if union: + @["union"] + else: + @[] + if not fdlist.isNil and fdlist.len > 0: + # Object with fields should be bycopy + pragmas.add "bycopy" else: - @["bycopy"] + # Incomplete, might get forward declared + pragmas.add "incompleteStruct" + + pragmas typeDefExisting = not typeDef.isNil typeDef = if typeDef.isNil: - nimState.newTypeIdent(node, fname = fname, pragmas = pragmas) + nimState.newTypeIdent(node, fname = fname, pragmas = pragmas, istype = istype) else: typeDef @@ -567,8 +608,6 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname obj.add newNode(nkEmpty) obj.add newNode(nkEmpty) - let - fdlist = node.anyChildInTree("field_declaration_list") if not fdlist.isNil and fdlist.len > 0: # Add fields to object if present obj.add nimState.newRecListTree(name, fdlist) @@ -580,11 +619,11 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname # If typeDef was passed in, need to add pragmas if any if pragmas.nBl and typeDefExisting: if typeDef[0].kind != nkPragmaExpr: - # includeHeader already added impShort let npexpr = nimState.newPragmaExpr(node, typedef[0], pragmas) typedef[0] = npexpr else: + # includeHeader already added impShort in newTypeIdent() nimState.addPragma(node, typeDef[0][1], pragmas) # nkTypeSection.add @@ -610,6 +649,18 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname # Add fields to existing object def[2][2] = nimState.newRecListTree(name, fdlist) + # Change incompleteStruct to bycopy pragma + if def[0].kind == nkPragmaExpr and def[0].len == 2 and + def[0][1].kind == nkPragma and def[0][1].len > 0: + for i in 0 ..< def[0][1].len: + if $def[0][1][i] == "incompleteStruct": + def[0][1][i] = nimState.getIdent( + "bycopy", nimState.getLineInfo(node.getAtom()), + exported = false + ) + + nimState.printDebug(def) + proc addTypeTyped(nimState: NimState, node: TSNode, ftname = "", offset = 0) = # Add a type of a specified type # @@ -622,8 +673,8 @@ proc addTypeTyped(nimState: NimState, node: TSNode, ftname = "", offset = 0) = # Add a type of a specific type let # node[i] = identifer = name - typeDef = nimState.newTypeIdent(node[i]) - + typeDef = nimState.newTypeIdent(node[i], istype = true) + if not typeDef.isNil: let name = typeDef.getIdentName() @@ -669,7 +720,7 @@ proc addTypeTyped(nimState: NimState, node: TSNode, ftname = "", offset = 0) = nimState.printDebug(typeDef) else: - nimState.addTypeObject(node, typeDef = typeDef) + nimState.addTypeObject(node, typeDef = typeDef, istype = true) proc getTypeArray(nimState: NimState, node: TSNode, name: string): PNode = # Create array type tree @@ -728,7 +779,7 @@ proc addTypeArray(nimState: NimState, node: TSNode) = decho("addTypeArray()") let # node[1] = identifer = name - typeDef = nimState.newTypeIdent(node[1]) + typeDef = nimState.newTypeIdent(node[1], istype = true) if not typeDef.isNil: let @@ -809,7 +860,7 @@ proc addTypeProc(nimState: NimState, node: TSNode) = decho("addTypeProc()") let # node[1] = identifier = name - typeDef = nimState.newTypeIdent(node[1]) + typeDef = nimState.newTypeIdent(node[1], istype = true) if not typeDef.isNil: let @@ -1018,7 +1069,7 @@ proc addType(nimState: NimState, node: TSNode, union = false) = # First add struct as object decho("addType(): case 6") - nimState.addTypeObject(node[0], union = union) + nimState.addTypeObject(node[0], istype = true, union = union) if node.len > 1 and nimState.getNodeVal(node[1]) != "": # Add any additional names @@ -1041,7 +1092,7 @@ proc addType(nimState: NimState, node: TSNode, union = false) = name # Now add struct as object with specified name - nimState.addTypeObject(node[0], fname = name, union = union) + nimState.addTypeObject(node[0], fname = name, istype = true, union = union) if name.nBl: # Add any additional names @@ -1068,7 +1119,7 @@ proc addEnum(nimState: NimState, node: TSNode) = # Use Y as name origname = nimState.getNodeVal(node[1].getAtom()) offset = 1 - + if origname.nBl: name = nimState.getIdentifier(origname, nskType) else: @@ -1120,7 +1171,7 @@ proc addEnum(nimState: NimState, node: TSNode) = # Add fields to list of consts after processing enum so that we don't cast # enum field to itself nimState.constIdentifiers.incl fnames - + # Add other names if node.getName() == "type_definition" and node.len > 1: nimState.addTypeTyped(node, ftname = name, offset = offset) @@ -1137,7 +1188,7 @@ proc addProc(nimState: NimState, node: TSNode) = let # node[i] = identifier = name ident = nimState.newTypeIdent(node[i], kind = nskProc) - + if not ident.isNil: let # Only need the ident tree, not nkTypeDef parent @@ -1270,10 +1321,13 @@ proc searchTree(nimState: NimState, root: TSNode) = break proc setupPragmas(nimState: NimState, root: TSNode, fullpath: string) = + # Create shortcut pragmas to reduce clutter var + hdrPragma: PNode impPragma = newNode(nkPragma) impCPragma = newNode(nkPragma) + # {.importc.} nimState.addPragma(root, impPragma, "pragma", nimState.getIdent(nimState.impShort)) nimState.addPragma(root, impPragma, "importc") @@ -1281,19 +1335,29 @@ proc setupPragmas(nimState: NimState, root: TSNode, fullpath: string) = nimState.constSection.add nimState.newConstDef( root, fname = nimState.currentHeader, fval = '"' & fullpath & '"') - nimState.addPragma(root, impPragma, "header", nimState.getIdent(nimState.currentHeader)) + # {.header: "xxx".} + hdrPragma = nimState.newPragma(root, "pragma", nimState.getIdent(nimState.impShort & "H")) + nimState.addPragma(root, hdrPragma, "header", nimState.getIdent(nimState.currentHeader)) + + nimState.addPragma(root, impPragma, nimState.impShort & "H") + # {.importc.} + {.cdecl.} for procs nimState.addPragma(root, impCPragma, "pragma", nimState.getIdent(nimState.impShort & "C")) nimState.addPragma(root, impCPragma, nimState.impShort) nimState.addPragma(root, impCPragma, "cdecl") if nimState.gState.dynlib.nBl: + # {.dynlib.} for DLLs nimState.addPragma(root, impCPragma, "dynlib", nimState.getIdent(nimState.gState.dynlib)) + # Add all pragma shortcuts to output + if not hdrPragma.isNil: + nimState.pragmaSection.add hdrPragma nimState.pragmaSection.add impPragma nimState.pragmaSection.add impCPragma proc printNimHeader*(gState: State) = + # Top level output with context info gecho """# Generated at $1 # Command line: # $2 $3 @@ -1304,13 +1368,16 @@ import nimterop/types """ % [$now(), getAppFilename(), commandLineParams().join(" ")] proc printNim*(gState: State, fullpath: string, root: TSNode) = + # Generate Nim from tree-sitter AST root node let nimState = new(NimState) fp = fullpath.replace("\\", "/") + # Track identifiers already rendered and corresponding PNodes nimState.identifiers = newTable[string, string]() nimState.identifierNodes = newTable[string, PNode]() + # toast objects nimState.gState = gState nimState.currentHeader = getCurrentHeader(fullpath) nimState.impShort = nimState.currentHeader.replace("header", "imp") @@ -1321,18 +1388,23 @@ proc printNim*(gState: State, fullpath: string, root: TSNode) = nimState.config = newConfigRef() nimstate.graph = newModuleGraph(nimState.identCache, nimState.config) + # Initialize all section PNodes nimState.pragmaSection = newNode(nkStmtList) nimState.constSection = newNode(nkConstSection) nimState.enumSection = newNode(nkStmtList) nimState.procSection = newNode(nkStmtList) nimState.typeSection = newNode(nkTypeSection) + # Setup pragmas nimState.setupPragmas(root, fp) + # Search root node and render Nim nimState.searchTree(root) + # Add any unused cOverride symbols to output nimState.addAllOverrideFinal() + # Create output to Nim using Nim compiler renderer var tree = newNode(nkStmtList) tree.add nimState.enumSection diff --git a/nimterop/build.nim b/nimterop/build.nim index 9594baa..c65ec2a 100644 --- a/nimterop/build.nim +++ b/nimterop/build.nim @@ -2,6 +2,8 @@ import hashes, macros, osproc, sets, strformat, strutils, tables import os except findExe, sleep +import regex + proc sanitizePath*(path: string, noQuote = false, sep = $DirSep): string = result = path.multiReplace([("\\\\", sep), ("\\", sep), ("/", sep)]) if not noQuote: @@ -83,7 +85,7 @@ proc execAction*(cmd: string, retry = 0, die = true, cache = false, else: # Execute command and store results in cache (result.output, result.ret) = gorgeEx(ccmd) - if result.ret == 0: + if result.ret == 0 or die == false: # mkdir for execCache dir (circular dependency) let dir = cacheFile.parentDir() if not dirExists(dir): @@ -933,7 +935,8 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta ## Simply define `proc xxxPreBuild(outdir, header: string)` in the wrapper and it will get called ## prior to the build process. var - name = header.extractFilename().split(".")[0] + origname = header.extractFilename().split(".")[0] + name = origname.replace(re"[[:^alnum:]]", "") # -d:xxx for this header stdStr = name & "Std" @@ -975,7 +978,7 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta if altNames.len != 0: lre = lre % ("(" & altNames.replace(",", "|") & ")") else: - lre = lre % name + lre = lre % origname result = newNimNode(nnkStmtList) result.add(quote do: diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim index 84f7b4f..c4ebc3f 100644 --- a/nimterop/cimport.nim +++ b/nimterop/cimport.nim @@ -673,6 +673,8 @@ macro c2nImport*(filename: static string, recurse: static bool = false, dynlib: (c2nimout, ret) = execAction(cmd, cache = not gStateCT.nocache, cacheKey = getCacheValue(hpath)) + doAssert ret == 0, "\n\nc2nim codegen limitation or error - " & c2nimout + var nimout = &"const {header} = \"{fullpath}\"\n\n" & readFile(npath) diff --git a/tests/include/tast2.h b/tests/include/tast2.h index 8e84b01..db539c7 100644 --- a/tests/include/tast2.h +++ b/tests/include/tast2.h @@ -19,6 +19,10 @@ struct A0 { int f1; }; +struct A4 { + float f1; +}; + typedef char *A9p[3]; //, A9[4]; typedef char *A10[3][6]; typedef char *(*A11)[3]; @@ -127,6 +131,10 @@ struct A0 { int f1; }; +struct A4 { + float f1; +}; + typedef char *A9p[3]; //, A9[4]; typedef char *A10[3][6]; typedef char *(*A11)[3]; diff --git a/tests/tast2.nim b/tests/tast2.nim index 76e4561..4b19429 100644 --- a/tests/tast2.nim +++ b/tests/tast2.nim @@ -1,30 +1,41 @@ -import macros, sets, tables +import macros, os, sets, strutils import nimterop/[cimport] static: cDebug() -cOverride: - const - A* = 2 - - type - A1* = A0 +const + path = currentSourcePath.parentDir() / "include" / "tast2.h" when defined(HEADER): cDefine("HEADER") const - flags = " -H" - imp = @["importc", "header:headertast2"] + flags = " -H -d" + pHeader = @["header:" & path] + pHeaderImp = @["importc"] & pHeader else: const flags = "" - imp = @[] + pHeader: seq[string] = @[] + pHeaderImp: seq[string] = @[] -cImport("include/tast2.h", flags="-d -f:ast2 -ENK_" & flags) +const + pHeaderImpBy = @["bycopy"] & pHeaderImp + pHeaderBy = @["bycopy"] & pHeader + pHeaderInc = @["incompleteStruct"] & pHeader + +cOverride: + const + A* = 2 + + type + A1* = A0 + +cImport(path, flags="-f:ast2 -ENK_" & flags) proc getPragmas(n: NimNode): HashSet[string] = + # Find all pragmas in AST, return as "name" or "name:value" in set for i in 0 ..< n.len: if n[i].kind == nnkPragma: for j in 0 ..< n[i].len: @@ -35,24 +46,54 @@ proc getPragmas(n: NimNode): HashSet[string] = else: result.incl n[i].getPragmas() -macro checkPragmas(t: typed, pragmas: static[seq[string]]): untyped = - let +proc getRecList(n: NimNode): NimNode = + # Find nnkRecList in AST + for i in 0 ..< n.len: + if n[i].kind == nnkRecList: + return n[i] + elif n[i].len != 0: + let + rl = getRecList(n[i]) + if not rl.isNil: + return rl + +macro checkPragmas(t: typed, pragmas: static[seq[string]], istype: static[bool] = true): untyped = + # Verify that type has expected pragmas defined + # `istype` is true when typedef X + var ast = t.getImpl() prag = ast.getPragmas() exprag = pragmas.toHashSet() + when defined(HEADER): + if not istype: + if "union" in exprag: + exprag.incl "importc:union " & $t + else: + exprag.incl "importc:struct " & $t doAssert symmetricDifference(prag, exprag).len == 0, "\nWrong number of pragmas in " & $t & "\n" & $prag & " vs " & $exprag -proc testFields(t: typedesc, fields: Table[string, string] = initTable[string, string]()) = +macro testFields(t: typed, fields: static[string] = "") = + # Verify that type has expected fields var - obj: t - count = 0 - for name, value in obj.fieldPairs(): - count += 1 - assert name in fields, $t & "." & name & " invalid" - assert $fields[name] == $typeof(value), - "typeof(" & $t & ":" & name & ") != " & fields[name] & ", is " & $typeof(value) - assert count == fields.len, "Failed for " & $t + ast = t.getImpl() + rl = ast.getRecList() + fsplit = fields.split(":") + names = fsplit[0].split("|") + types = + if fsplit.len > 1: + fsplit[1].split("|") + else: + @[] + if not rl.isNil: + for i in 0 ..< rl.len: + let + name = ($rl[i][0]).strip(chars = {'*'}) + typ = $(rl[i][1].repr()) + n = names.find(name) + assert n != -1, $t & "." & name & " invalid" + assert types[n] == typ, + "typeof(" & $t & ":" & name & ") != " & types[n] & ", is " & typ assert A == 2 assert B == 1.0 @@ -60,114 +101,190 @@ assert C == 0x10 assert D == "hello" assert E == 'c' -const - pragmas = @["bycopy"] & imp - assert A0 is object -testFields(A0, {"f1": "cint"}.toTable()) -checkPragmas(A0, pragmas) +testFields(A0, "f1:cint") +checkPragmas(A0, pHeaderBy, istype = false) +var a0: A0 +a0.f1 = 1 assert A1 is A0 -testFields(A1, {"f1": "cint"}.toTable()) +testFields(A1, "f1:cint") +var a1: A1 +a1.f1 = 2 assert A2 is object testFields(A2) -checkPragmas(A2, pragmas) +checkPragmas(A2, pHeaderInc, istype = false) +when not defined(HEADER): + # typedef struct X; is invalid + var a2: A2 assert A3 is object testFields(A3) -checkPragmas(A3, pragmas) +checkPragmas(A3, pHeaderInc, istype = false) +var a3: A3 assert A4 is object -testFields(A4) -checkPragmas(A4, pragmas) +testFields(A4, "f1:cfloat") +checkPragmas(A4, pHeaderImpBy) +var a4: A4 +a4.f1 = 4.1 assert A4p is ptr A4 -checkPragmas(A4p, imp) +testFields(A4p, "f1:cfloat") +checkPragmas(A4p, pHeaderImp) +var a4p: A4p +a4p = addr a4 assert A5 is cint -checkPragmas(A5, imp) +checkPragmas(A5, pHeaderImp) +const a5: A5 = 5 assert A6 is ptr cint -checkPragmas(A6, imp) +checkPragmas(A6, pHeaderImp) +var + a6: A6 + a6i = 6 +a6 = cast[A6](addr a6i) assert A7 is ptr ptr A0 -checkPragmas(A7, imp) +checkPragmas(A7, pHeaderImp) +var + a7: A7 + a7a = addr a0 +a7 = addr a7a assert A8 is pointer -checkPragmas(A8, imp) +checkPragmas(A8, pHeaderImp) +var a8: A8 +a8 = nil assert A9p is array[3, cstring] -checkPragmas(A9p, imp) +checkPragmas(A9p, pHeaderImp) +var a9p: A9p +a9p[1] = nil +a9p[2] = "hello".cstring +#Not implemented yet #assert A9 is array[4, cchar] -#checkPragmas(A9, imp) +#checkPragmas(A9, pHeaderImp) +#var a9: A9 assert A10 is array[3, array[6, cstring]] -checkPragmas(A10, imp) +checkPragmas(A10, pHeaderImp) +var a10: A10 +a10[2][5] = "12345".cstring assert A11 is ptr array[3, cstring] -checkPragmas(A11, imp) +checkPragmas(A11, pHeaderImp) +var a11: A11 +a11 = addr a9p assert A111 is array[12, ptr A1] -checkPragmas(A111, imp) +checkPragmas(A111, pHeaderImp) +var a111: A111 +a111[11] = addr a1 assert A12 is proc(a1: cint, b: cint, c: ptr cint, a4: ptr cint, count: array[4, ptr cint], `func`: proc(a1: cint, a2: cint): cint): ptr ptr cint -checkPragmas(A12, imp) +checkPragmas(A12, pHeaderImp) +when not defined(HEADER): + # Unclear why this fails + # request for member ‘ClE_0’ in something not a structure or union + var a12: A12 assert A13 is proc(a1: cint, a2: cint, `func`: proc()): cint -checkPragmas(A13, imp) +checkPragmas(A13, pHeaderImp) +when not defined(HEADER): + # Unclear why this fails + # request for member ‘ClE_0’ in something not a structure or union + var a13: A13 assert A14 is object -testFields(A14, {"a1": "cchar"}.toTable()) -checkPragmas(A14, pragmas) +testFields(A14, "a1:cchar") +checkPragmas(A14, pHeaderBy, istype = false) +var a14: A14 +a14.a1 = 'a' assert A15 is object -testFields(A15, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable()) -checkPragmas(A15, pragmas) +testFields(A15, "a1|a2:cstring|array[1, ptr cint]") +checkPragmas(A15, pHeaderBy, istype = false) +var + a15: A15 + a15i = 15.cint +a15.a1 = "hello".cstring +a15.a2[0] = addr a15i assert A16 is object -testFields(A16, {"f1": "cchar"}.toTable()) -checkPragmas(A16, pragmas) +testFields(A16, "f1:cchar") +checkPragmas(A16, pHeaderImpBy) +when not defined(HEADER): + # Similar to A2 + var a16: A16 + a16.f1 = 's' assert A17 is object -testFields(A17, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable()) -checkPragmas(A17, pragmas) +testFields(A17, "a1|a2:cstring|array[1, ptr cint]") +checkPragmas(A17, pHeaderImpBy) +when not defined(HEADER): + # Similar to A2 + var a17: A17 + a17.a1 = "hello".cstring + a17.a2[0] = addr a15i assert A18 is A17 -checkPragmas(A18, imp) +checkPragmas(A18, pHeaderImp) +var a18: A18 assert A18p is ptr A17 -checkPragmas(A18p, imp) +checkPragmas(A18p, pHeaderImp) +var a18p: A18p +a18p = addr a18 assert A19 is object -testFields(A19, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable()) -checkPragmas(A19, pragmas) +testFields(A19, "a1|a2:cstring|array[1, ptr cint]") +checkPragmas(A19, pHeaderImpBy) +var a19: A19 +a19.a1 = "hello".cstring +a19.a2[0] = addr a15i assert A19p is ptr A19 -checkPragmas(A19p, imp) +checkPragmas(A19p, pHeaderImp) +var a19p: A19p +a19p = addr a19 assert A20 is object -testFields(A20, {"a1": "cchar"}.toTable()) -checkPragmas(A20, pragmas) +testFields(A20, "a1:cchar") +checkPragmas(A20, pHeaderImpBy) +var a20: A20 +a20.a1 = 'a' assert A21 is A20 -checkPragmas(A21, imp) +checkPragmas(A21, pHeaderImp) +var a21: A21 +a21 = a20 assert A21p is ptr A20 -checkPragmas(A21p, imp) +checkPragmas(A21p, pHeaderImp) +var a21p: A21p +a21p = addr a20 assert A22 is object -testFields(A22, {"f1": "ptr ptr cint", "f2": "array[0..254, ptr cint]"}.toTable()) -checkPragmas(A22, pragmas) +testFields(A22, "f1|f2:ptr ptr cint|array[123 + 132, ptr cint]") +checkPragmas(A22, pHeaderImpBy) +var a22: A22 +a22.f1 = addr a15.a2[0] assert U1 is object assert sizeof(U1) == sizeof(cfloat) -checkPragmas(U1, pragmas & @["union"]) +checkPragmas(U1, pHeaderBy & @["union"], istype = false) +var u1: U1 +u1.f1 = 5 assert U2 is object assert sizeof(U2) == 256 * sizeof(cint) -checkPragmas(U2, pragmas & @["union"]) +checkPragmas(U2, pHeaderImpBy & @["union"]) +var u2: U2 +u2.f1 = addr a15.a2[0] assert PANEL_WINDOW == 1 assert PANEL_GROUP == 2 |
