From 5ab4775939dfc6c2517d858a7c0aef9842e80049 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 30 Dec 2018 12:40:10 +0100 Subject: [PATCH 1/9] attempt to make 0.19 compatible --- godot/core/variants.nim | 9 ++-- godot/godotapigen.nim | 95 ++++++++++++++++++--------------- godot/internal/godotstrings.nim | 5 +- godot/nim/godotmacros.nim | 31 +++++------ godot/nim/godotnim.nim | 37 ++++++------- 5 files changed, 86 insertions(+), 91 deletions(-) diff --git a/godot/core/variants.nim b/godot/core/variants.nim index ace8aacb..8c2488d9 100644 --- a/godot/core/variants.nim +++ b/godot/core/variants.nim @@ -73,12 +73,9 @@ proc newVariant*(r: cdouble): Variant {.inline.} = proc newVariant*(s: string): Variant {.inline.} = new(result, variantFinalizer) - if s.isNil: - initGodotVariant(result.godotVariant) - else: - var godotStr = s.toGodotString() - initGodotVariant(result.godotVariant, godotStr) - godotStr.deinit() + var godotStr = s.toGodotString() + initGodotVariant(result.godotVariant, godotStr) + godotStr.deinit() import basis, nodepaths import planes, quats, rect2, aabb, rids diff --git a/godot/godotapigen.nim b/godot/godotapigen.nim index 876e770c..5ec1c73a 100644 --- a/godot/godotapigen.nim +++ b/godot/godotapigen.nim @@ -1,9 +1,15 @@ # Copyright 2018 Xored Software, Inc. -import streams, json, os, strutils, times, sets, tables +import streams, json, os, strutils, times, sets, tables, options import sequtils, algorithm import compiler.ast, compiler.renderer, compiler.idents, compiler.astalgo +when (NimMajor, NimMinor, NimPatch) >= (0, 19, 0): + var gic* = newIdentCache() + + proc getIdent(ident: string): PIdent = + getIdent(gic, ident) + proc ident(ident: string): PNode = result = newNode(nkIdent) result.ident = getIdent(ident) @@ -139,19 +145,19 @@ proc findCommonRoot(typeRegistry: Table[string, GodotType], var idx = 0 while true: - var curType: string + var curType = none(string) var allEqual = true for chain in chains: if idx >= chain.len: allEqual = false break - if curType.isNil: - curType = chain[idx] - elif curType != chain[idx]: + if curType.isNone: + curType = some(chain[idx]) + elif curType.get != chain[idx]: allEqual = false break if allEqual: - result = curType + result = curType.get else: break inc idx @@ -224,7 +230,7 @@ proc newRefTypeNode(typeSection: PNode, typ, base, doc: string, inherit.add(ident(base)) objTy.add(inherit) - if not doc.isNil: + if doc.len > 0: let recList = newNode(nkRecList) let docNode = newNode(nkCommentStmt) docNode.comment = doc @@ -275,7 +281,7 @@ type godotName: string typ: GodotType args: seq[MethodArg] - returnType: string + returnType: Option[string] isVirtual: bool isBase: bool isDiscardable: bool @@ -428,7 +434,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], newCStringLit(meth.godotName)) ) let vars = newNode(nkVarSection) - var varargsName: string + var varargsName = none(string) var isVarargs: bool var staticArgsLen: int var argLenNode = newIntLit(0) @@ -436,7 +442,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], if meth.args.len > 0: for idx, arg in meth.args: if arg.kind == ArgKind.VarArgs: - varargsName = arg.name + varargsName = some(arg.name) isVarargs = true vars.add(newIdentDefs(ident("callError"), ident("VariantCallError"))) elif arg.kind == ArgKind.Bound: @@ -450,13 +456,13 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], ident("array"), ident("MAX_ARG_COUNT"), if isVarargs: newNode(nkPtrTy).addChain(ident("GodotVariant")) else: ident("pointer")))) - staticArgsLen = if varargsName.isNil: meth.args.len + staticArgsLen = if varargsName.isSome: meth.args.len else: meth.args.len - 1 - if not varargsName.isNil: + if varargsName.isSome: argLenNode = newCall("cint", infix(newIntLit(staticArgsLen), ident("+"), - newDotExpr(ident(varargsName), ident("len")))) + newDotExpr(ident(varargsName.get), ident("len")))) argsAlloc.add(newCall("godotAlloc", newCall("cint", infix( newCall("sizeof", ident("Variant")), ident("*"), newNode(nkPar).addChain(argLenNode)))) @@ -477,12 +483,12 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], else: ident(arg.name) if arg.kind == ArgKind.VarArgs: argName = newNode(nkBracketExpr).addChain( - ident(varargsName), + ident(varargsName.get), infix(ident("idx"), ident("-"), newIntLit(staticArgsLen))) let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx) let isStandardType = arg.typ in standardTypes let isWrappedType = arg.typ in wrapperTypes - let convArg = if not varargsName.isNil: + let convArg = if varargsName.isSome: getInternalPtr(newCall("toVariant", argName), "Variant") elif isWrappedType: getInternalPtr(argName, arg.typ) elif isStandardType: newCall("unsafeAddr", argName) @@ -493,7 +499,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], raise newException(ValueError, "Non-standard type $# for varargs params of method $# of type $#" % [arg.typ, meth.godotName, meth.typ.godotName]) - if not isStandardType and varargsName.isNil: + if not isStandardType and varargsName.isNone: if arg.typ == "string": argConversions.add(newNode(nkVarSection).addChain( newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), @@ -560,31 +566,32 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], var isStringRet: bool var isWrapperRet: bool let retValIdent = if not isVarargs: ident("ptrCallVal") else: ident(retName) - if not meth.returnType.isNil and not isVarargs: + if meth.returnType.isSome and not isVarargs: + let returnType = meth.returnType.get var addrToAssign = newCall("addr", retValIdent) - if meth.returnType in smallIntTypes: + if returnType in smallIntTypes: isConversionRet = true body.add(newNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("int64"), ))) - elif meth.returnType in float32Types: + elif returnType in float32Types: isConversionRet = true body.add(newNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("float64"), ))) - elif meth.returnType in wrapperTypes: + elif returnType in wrapperTypes: isWrapperRet = true body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, ident("Godot" & meth.returnType), + retValIdent, ident("Godot" & returnType), ))) - elif meth.returnType in standardTypes: + elif returnType in standardTypes: addrToAssign = newCall("addr", ident("result")) - elif meth.returnType == "string": + elif returnType == "string": isStringRet = true body.add(newNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("GodotString"), ))) - elif meth.returnType != "void": + elif returnType != "void": isObjRet = true body.add(newNode(nkVarSection).addChain(newIdentDefs( retValIdent, newNode(nkPtrTy).addChain(ident("GodotObject")), @@ -594,7 +601,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], if not isVarargs: body.add(theCall) else: - if not meth.returnType.isNil: + if meth.returnType.isSome: isVariantRet = true let callStmt = newNode(nkLetSection).addChain( newIdentDefs( @@ -603,14 +610,14 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], newNode(nkEmpty), theCall)) body.add(callStmt) - if varargsName.isNil: + if varargsName.isNone: for idx, arg in meth.args: if arg.typ == "string": body.add(newCall("deinit", ident("argToPassToGodot" & $idx))) - if meth.args.len > 0 and not varargsName.isNil: + if meth.args.len > 0 and varargsName.isSome: body.add(freeCall) - if not varargsName.isNil: + if varargsName.isSome: let errCheck = newIfStmt( infix(newDotExpr(ident("callError"), ident("error")), ident("!="), newDotExpr(ident("VariantCallErrorType"), ident("OK"))), @@ -638,11 +645,11 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], elif isConversionRet: body.add(newNode(nkAsgn).addChain( ident("result"), - newCall(meth.returnType, retValIdent))) + newCall(meth.returnType.get, retValIdent))) elif isWrapperRet: body.add(newNode(nkAsgn).addChain( ident("result"), - newCall("new" & meth.returnType, retValIdent))) + newCall("new" & meth.returnType.get, retValIdent))) elif isObjRet: body.add(newNode(nkAsgn).addChain(ident("result"), newCall(newBracketExpr(ident("asNimGodotObject"), @@ -655,8 +662,8 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], let procType = if meth.isVirtual: nkMethodDef else: nkProcDef var params = newSeqOfCap[PNode](meth.args.len + 2) - if not meth.returnType.isNil: - params.add(ident(meth.returnType)) + if meth.returnType.isSome: + params.add(ident(meth.returnType.get)) else: params.add(newNode(nkEmpty)) if not meth.typ.isSingleton: @@ -684,7 +691,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], if meth.isVirtual and meth.isBase and meth.typ.name != "PhysicsBody": # Nim doesn't like `base` on PhysicsBody methods - wtf pragma.add(ident("base")) - if meth.isDiscardable and not meth.returnType.isNil: + if meth.isDiscardable and meth.returnType.isSome: pragma.add(ident("discardable")) procDecl.sons[4] = pragma tree.add(procDecl) @@ -729,8 +736,8 @@ proc getMethodInfo(methodObj: JsonNode, types: Table[string, GodotType], nimName = nimName & "Impl" let returnType = if methodObj["return_type"].str != "void": - toNimType(types, methodObj["return_type"].str) - else: nil + some(toNimType(types, methodObj["return_type"].str)) + else: none(string) const discardableMethods = toSet(["emit_signal"]) result = MethodInfo( name: ident(nimName), @@ -764,13 +771,13 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode, let getter = findMethod(obj, propertyObj["getter"].str) let nimType = if getter.isNil: toNimType(types, propertyObj["type"].str) - else: getMethodInfo(getter, types, typ).returnType + else: getMethodInfo(getter, types, typ).returnType.get("void") let getterInfo = MethodInfo( name: getterName, typ: typ, godotName: propertyObj["getter"].str, - args: @[], - returnType: nimType + args: newSeq[MethodArg](), + returnType: some(nimType) ) let setterInfo = MethodInfo( name: setterName, @@ -779,10 +786,12 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode, args: @[MethodArg(name: "val", typ: nimType)] ) if "index" in propertyObj and propertyObj["index"] != newJInt(-1): - getterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]), - typ: "int", kind: ArgKind.Bound)] & getterInfo.args - setterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]), - typ: "int", kind: ArgKind.Bound)] & setterInfo.args + getterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & getterInfo.args + setterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & setterInfo.args generateMethod(tree, methodBindRegistry, getterInfo, withImplementation) generateMethod(tree, methodBindRegistry, setterInfo, withImplementation) @@ -920,7 +929,7 @@ proc genApi*(targetDir: string, apiJsonFile: string) = let className = godotClassName.replace("_", "") var baseClassName = obj["base_class"].str baseClassName = toNimType(baseClassName.replace("_", "")) - if baseClassName.isNil or baseClassName.len == 0: + if baseClassName.len == 0: baseClassName = "NimGodotObject" var doc = "" for attr in classAttributes: diff --git a/godot/internal/godotstrings.nim b/godot/internal/godotstrings.nim index be18df0f..18bcf635 100644 --- a/godot/internal/godotstrings.nim +++ b/godot/internal/godotstrings.nim @@ -38,10 +38,7 @@ proc `$`*(self: GodotString): string = proc toGodotString*(s: string): GodotString {.inline.} = ## Converts the Nim string into ``GodotString`` - if s.isNil: - initGodotString(result) - else: - initGodotString(result, cstring(s), cint(s.len + 1)) + initGodotString(result, cstring(s), cint(s.len + 1)) proc toGodotString*(s: cstring): GodotString {.inline.} = ## Converts the cstring into ``GodotString`` diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 352925a5..5518dbe4 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -1,6 +1,6 @@ # Copyright 2018 Xored Software, Inc. -import macros, tables, typetraits +import macros, tables, typetraits, strutils, sets, sequtils, options import godotinternal, internal.godotvariants import godotnim, core.variants @@ -10,8 +10,8 @@ type typ: NimNode defaultValue: NimNode isNoGodot: bool - hint: string - hintStr: string + hint: Option[string] + hintStr: Option[string] usage: NimNode isExported: bool @@ -111,12 +111,12 @@ proc removePragma(statement: NimNode, pname: string): bool = return true proc removeStrPragma(statement: NimNode, - pname: string): string {.compileTime.} = + pname: string): Option[string] {.compileTime.} = ## Removes the pragma from the node and returns value of the pragma ## Works for routine nodes or nnkPragmaExpr let node = removePragmaNode(statement, pname) - result = if node.isNil: nil - else: $node + result = if node.isNil: none(string) + else: some($node) proc isExported(node: NimNode): bool {.compileTime.} = if node.kind == nnkPragmaExpr: @@ -197,7 +197,7 @@ proc parseType(definition, callSite: NimNode): ObjectDecl = parseError(option, "valid type specifier expected") result.isTool = isTool - if result.parentName.isNil: result.parentName = "Object" + if result.parentName == "": result.parentName = "Object" for statement in body: case statement.kind: of nnkVarSection: @@ -424,9 +424,6 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit, unsafeAddr attr, setFunc, getFunc) hintStrGodot.deinit() -static: - import strutils, sets, sequtils - proc toGodotStyle(s: string): string {.compileTime.} = result = newStringOfCap(s.len + 10) for c in s: @@ -447,7 +444,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = let objTy = newNimNode(nnkObjectTy) typeDef.add(newNimNode(nnkRefTy).add(objTy)) objTy.add(newEmptyNode()) - if obj.parentName.isNil: + if obj.parentName == "": objTy.add(newEmptyNode()) else: objTy.add(newNimNode(nnkOfInherit).add(ident(obj.parentName))) @@ -506,11 +503,11 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = result.add(meth.nimNode) # Register Godot object - let parentName = if obj.parentName.isNil: newStrLitNode("Object") + let parentName = if obj.parentName == "": newStrLitNode("Object") else: newStrLitNode(obj.parentName) let classNameLit = newStrLitNode(obj.name) let classNameIdent = ident(obj.name) - let isRef: bool = if obj.parentName.isNil: false + let isRef: bool = if obj.parentName == "": false else: obj.parentName in refClasses result.add(getAst( registerGodotClass(classNameIdent, classNameLit, isRef, parentName, @@ -519,10 +516,10 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = # Register fields (properties) for field in obj.fields: if field.isNoGodot: continue - let hintStr = if field.hintStr.isNil: "NIM" - else: field.hintStr - let hint = if field.hint.isNil: "NIM" - else: field.hint + let hintStr = if field.hintStr.isNone: "NIM" + else: field.hintStr.get + let hint = if field.hint.isNone: "NIM" + else: field.hint.get let usage = if field.usage.isNil: newLit(ord(GodotPropertyUsage.Default) or diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 665b715f..bcd9d526 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -1,6 +1,6 @@ # Copyright 2018 Xored Software, Inc. -import tables, typetraits, macros, unicode +import tables, typetraits, macros, unicode, strutils, sets import gdnativeapi import core.godotcoretypes, core.godotbase import core.vector2, core.rect2, @@ -101,8 +101,6 @@ var classRegistryStatic* {.compileTime.}: TableRef[FNV1Hash, ObjectInfo] static: classRegistryStatic = newTable[FNV1Hash, ObjectInfo]() -static: - import sets, strutils var nativeClasses {.compileTime.} = newSeq[string]() var refClasses* {.compileTime.} = newSeq[string]() @@ -204,7 +202,7 @@ macro baseNativeType(T: typedesc): cstring = if typeName == "NimGodotObject": break t = getType(t[1][1]) - if baseT.isNil: + if baseT == "": result = newNilLit() else: let rStr = newNimNode(nnkRStrLit) @@ -345,24 +343,21 @@ proc newRStrLit(s: string): NimNode {.compileTime.} = result = newNimNode(nnkRStrLit) result.strVal = s -static: - import strutils - macro toGodotName(T: typedesc): string = - var godotName: string - if T is GodotString or T is string: - godotName = "String" - elif T is SomeFloat: - godotName = "float" - elif T is SomeUnsignedInt or T is SomeSignedInt: - godotName = "int" - if godotName.isNil or godotName.len == 0: - let nameStr = (($T.getType()[1][1].symbol).split(':')[0]) - godotName = case nameStr: - of "File", "Directory", "Thread", "Mutex", "Semaphore": - "_" & nameStr + var godotName = + if T is GodotString or T is string: + "String" + elif T is SomeFloat: + "float" + elif T is SomeUnsignedInt or T is SomeSignedInt: + "int" else: - nameStr + let nameStr = (($T.getType()[1][1].symbol).split(':')[0]) + case nameStr: + of "File", "Directory", "Thread", "Mutex", "Semaphore": + "_" & nameStr + else: + nameStr result = newLit(godotName) @@ -717,7 +712,7 @@ proc fromVariant*(s: var string, val: Variant): ConversionResult = if val.getType() == VariantType.String: s = val.asString() elif val.getType() == VariantType.Nil: - s = nil + s = "" else: result = ConversionResult.TypeError From a536c102d612d08f69a8ead4022c090acedcbb8b Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 30 Dec 2018 15:41:44 +0100 Subject: [PATCH 2/9] workaround for nim/macro/typedesc issue --- godot/nim/godotnim.nim | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index bcd9d526..8a773036 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -343,23 +343,20 @@ proc newRStrLit(s: string): NimNode {.compileTime.} = result = newNimNode(nnkRStrLit) result.strVal = s -macro toGodotName(T: typedesc): string = - var godotName = - if T is GodotString or T is string: - "String" - elif T is SomeFloat: - "float" - elif T is SomeUnsignedInt or T is SomeSignedInt: - "int" - else: - let nameStr = (($T.getType()[1][1].symbol).split(':')[0]) - case nameStr: - of "File", "Directory", "Thread", "Mutex", "Semaphore": - "_" & nameStr - else: - nameStr - - result = newLit(godotName) +proc toGodotName(T: typedesc): string = + if T is GodotString or T is string: + "String" + elif T is SomeFloat: + "float" + elif T is SomeUnsignedInt or T is SomeSignedInt: + "int" + else: + let nameStr = (($T.getType()[1][1].symbol).split(':')[0]) + case nameStr: + of "File", "Directory", "Thread", "Mutex", "Semaphore": + "_" & nameStr + else: + nameStr macro asCString(s: static[string]): cstring = result = newNimNode(nnkCallStrLit).add( From a05b5c17766493083d1faa2e1f4c6a4c0d38c777 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 30 Dec 2018 16:32:40 +0100 Subject: [PATCH 3/9] work-around for nim-lang/Nim#7375 --- godot/nim/godotmacros.nim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 5518dbe4..63716dda 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -509,9 +509,11 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = let classNameIdent = ident(obj.name) let isRef: bool = if obj.parentName == "": false else: obj.parentName in refClasses + # Wrapping bools with a newLit is required as a temporary workaround for + # https://github.com/nim-lang/Nim/issues/7375 result.add(getAst( - registerGodotClass(classNameIdent, classNameLit, isRef, parentName, - genSym(nskProc, "createFunc"), obj.isTool))) + registerGodotClass(classNameIdent, classNameLit, newLit(isRef), parentName, + genSym(nskProc, "createFunc"), newLit(obj.isTool)))) # Register fields (properties) for field in obj.fields: From 9f29e2eec917a6cab5ed523084151f5013f59980 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 30 Dec 2018 17:09:50 +0100 Subject: [PATCH 4/9] fixed more isNil usages --- docs/docbuild.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docbuild.nim b/docs/docbuild.nim index 10823a56..477c45b5 100644 --- a/docs/docbuild.nim +++ b/docs/docbuild.nim @@ -71,7 +71,7 @@ proc fixupHrefs(file: string) = proc getGitHash(): string = result = execProcess("git rev-parse HEAD") - if not result.isNil and result.len > 0: + if result.len > 0: result = result.replace("\L", "").replace("\r", "") proc buildDocs*(outDir, godotNimDir, godotBin: string) = @@ -112,7 +112,7 @@ proc buildDocs*(outDir, godotNimDir, godotBin: string) = var gitHash: string withDir(godotBinAbs.parentDir()): gitHash = getGitHash() - if gitHash.isNil or gitHash.len == 0: + if gitHash.len == 0: raise newException(Exception, "Godot executable is not under Git repository") From 8d8d095af96e0abb40b2ed25f7d7d09a18262594 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 30 Dec 2018 18:01:10 +0100 Subject: [PATCH 5/9] fixed new name of setStackBottom --- godot/nim/godotmacros.nim | 4 ++-- godot/nim/godotnim.nim | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 63716dda..052b2fc6 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -545,7 +545,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = methodNameLit, minArgs, maxArgs, argTypes, methFuncIdent, hasReturnValue) = {.emit: """/*TYPESECTION*/ -N_NOINLINE(void, setStackBottom)(void* thestackbottom); +N_NOINLINE(void, nimGC_setStackBottom)(void* thestackbottom); """.} proc methFuncIdent(obj: ptr GodotObject, methodData: pointer, userData: pointer, numArgs: cint, @@ -553,7 +553,7 @@ N_NOINLINE(void, setStackBottom)(void* thestackbottom); GodotVariant {.noconv.} = var stackBottom {.volatile.}: pointer {.emit: """ - setStackBottom((void*)(&`stackBottom`)); + nimGC_setStackBottom((void*)(&`stackBottom`)); """.} let self = cast[classNameIdent](userData) const isStaticCall = methodNameLit == cstring"_ready" or diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 8a773036..14b788b4 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -831,7 +831,7 @@ proc fromVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: va {.emit: """/*TYPESECTION*/ N_LIB_EXPORT N_CDECL(void, NimMain)(void); -N_NOINLINE(void, setStackBottom)(void* thestackbottom); +N_NOINLINE(void, nimGC_setStackBottom)(void* thestackbottom); """.} var nativeLibHandle: pointer @@ -847,7 +847,7 @@ proc godot_nativescript_init(handle: pointer) {. var stackBottom {.volatile.}: pointer {.emit: """ NimMain(); - setStackBottom((void*)(&`stackBottom`)); + nimGC_setStackBottom((void*)(&`stackBottom`)); """.} GC_fullCollect() GC_disable() @@ -884,7 +884,7 @@ proc registerFrameCallback*(cb: proc () {.closure.}) = proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} = var stackBottom {.volatile.}: pointer {.emit: """ - setStackBottom((void*)(&`stackBottom`)); + nimGC_setStackBottom((void*)(&`stackBottom`)); """.} for cb in idleCallbacks: cb() From 027b753379a1568fac5ef13b9c97b309ec5ee2fb Mon Sep 17 00:00:00 2001 From: zetashift Date: Fri, 1 Mar 2019 02:18:00 +0100 Subject: [PATCH 6/9] Small changes to add 0.18.0 compatibility --- godot/nim/godotmacros.nim | 16 +++++++++++----- godot/nim/godotnim.nim | 30 +++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 052b2fc6..4389859e 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -197,7 +197,7 @@ proc parseType(definition, callSite: NimNode): ObjectDecl = parseError(option, "valid type specifier expected") result.isTool = isTool - if result.parentName == "": result.parentName = "Object" + if result.parentName.len == 0: result.parentName = "Object" for statement in body: case statement.kind: of nnkVarSection: @@ -444,7 +444,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = let objTy = newNimNode(nnkObjectTy) typeDef.add(newNimNode(nnkRefTy).add(objTy)) objTy.add(newEmptyNode()) - if obj.parentName == "": + if obj.parentName.len == 0: objTy.add(newEmptyNode()) else: objTy.add(newNimNode(nnkOfInherit).add(ident(obj.parentName))) @@ -503,11 +503,11 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = result.add(meth.nimNode) # Register Godot object - let parentName = if obj.parentName == "": newStrLitNode("Object") + let parentName = if obj.parentName.len == 0: newStrLitNode("Object") else: newStrLitNode(obj.parentName) let classNameLit = newStrLitNode(obj.name) let classNameIdent = ident(obj.name) - let isRef: bool = if obj.parentName == "": false + let isRef: bool = if obj.parentName.len == 0: false else: obj.parentName in refClasses # Wrapping bools with a newLit is required as a temporary workaround for # https://github.com/nim-lang/Nim/issues/7375 @@ -544,9 +544,15 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} = template registerGodotMethod(classNameLit, classNameIdent, methodNameIdent, methodNameLit, minArgs, maxArgs, argTypes, methFuncIdent, hasReturnValue) = - {.emit: """/*TYPESECTION*/ + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """/*TYPESECTION*/ +N_NOINLINE(void, setStackBottom)(void* thestackbottom); +""".} + else: + {.emit: """ N_NOINLINE(void, nimGC_setStackBottom)(void* thestackbottom); """.} + proc methFuncIdent(obj: ptr GodotObject, methodData: pointer, userData: pointer, numArgs: cint, args: var array[MAX_ARG_COUNT, ptr GodotVariant]): diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 14b788b4..ef4dc415 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -202,7 +202,7 @@ macro baseNativeType(T: typedesc): cstring = if typeName == "NimGodotObject": break t = getType(t[1][1]) - if baseT == "": + if baseT.len == 0: result = newNilLit() else: let rStr = newNimNode(nnkRStrLit) @@ -343,7 +343,7 @@ proc newRStrLit(s: string): NimNode {.compileTime.} = result = newNimNode(nnkRStrLit) result.strVal = s -proc toGodotName(T: typedesc): string = +proc toGodotName(T: typedesc): string {.compileTime.} = if T is GodotString or T is string: "String" elif T is SomeFloat: @@ -708,10 +708,16 @@ proc toVariant*(s: string): Variant {.inline.} = proc fromVariant*(s: var string, val: Variant): ConversionResult = if val.getType() == VariantType.String: s = val.asString() - elif val.getType() == VariantType.Nil: - s = "" + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + if val.getType() == VariantType.Nil: + s = nil + else: + result = ConversionResult.TypeError else: - result = ConversionResult.TypeError + if val.getType() == VariantType.Nil: + s = "" + else: + result = ConversionResult.TypeError template arrTypeInfo(T) = result.variantType = VariantType.Array @@ -829,10 +835,16 @@ proc fromVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: va else: result = ConversionResult.TypeError -{.emit: """/*TYPESECTION*/ -N_LIB_EXPORT N_CDECL(void, NimMain)(void); -N_NOINLINE(void, nimGC_setStackBottom)(void* thestackbottom); -""".} +when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """/*TYPESECTION*/ + N_LIB_EXPORT N_CDECL(void, NimMain)(void); + N_NOINLINE(void, setStackBottom)(void* thestackbottom); + """.} +else: + {.emit: """/*TYPESECTION*/ + N_LIB_EXPORT N_CDECL(void, NimMain)(void); + N_NOINLINE(void, nimGC_setStackBottom)(void* thestackbottom); + """.} var nativeLibHandle: pointer proc getNativeLibHandle*(): pointer = From a73d8bbbba84a37812003236b51de9d81a0c1292 Mon Sep 17 00:00:00 2001 From: zetashift Date: Sun, 3 Mar 2019 16:29:48 +0100 Subject: [PATCH 7/9] Bump minor version --- godot.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/godot.nimble b/godot.nimble index 8e4c8c02..6964c839 100644 --- a/godot.nimble +++ b/godot.nimble @@ -1,4 +1,4 @@ -version = "0.7.18" +version = "0.7.19" author = "Xored Software, Inc." description = "Godot Engine bindings" license = "MIT" From 7fd0fdc47de5f28f0ba9d8c8213db163905818cc Mon Sep 17 00:00:00 2001 From: zetashift Date: Wed, 13 Mar 2019 23:37:59 +0100 Subject: [PATCH 8/9] Change toGodotName back to macro because that got fixed in devel --- godot/nim/godotnim.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index ef4dc415..4a1e9adb 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -343,7 +343,7 @@ proc newRStrLit(s: string): NimNode {.compileTime.} = result = newNimNode(nnkRStrLit) result.strVal = s -proc toGodotName(T: typedesc): string {.compileTime.} = +macro toGodotName(T: typedesc): string = if T is GodotString or T is string: "String" elif T is SomeFloat: From 4cb99f406ba04d52dc45458a1ee47f95c2df253c Mon Sep 17 00:00:00 2001 From: zetashift Date: Wed, 3 Apr 2019 02:09:00 +0200 Subject: [PATCH 9/9] change isSome to isNone in godotapigen --- godot/godotapigen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/godot/godotapigen.nim b/godot/godotapigen.nim index 5ec1c73a..71a52ff1 100644 --- a/godot/godotapigen.nim +++ b/godot/godotapigen.nim @@ -456,7 +456,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], ident("array"), ident("MAX_ARG_COUNT"), if isVarargs: newNode(nkPtrTy).addChain(ident("GodotVariant")) else: ident("pointer")))) - staticArgsLen = if varargsName.isSome: meth.args.len + staticArgsLen = if varargsName.isNone: meth.args.len else: meth.args.len - 1 if varargsName.isSome: argLenNode = newCall("cint",