Skip to content

Commit 031774f

Browse files
committed
More efficient and GC-safe conversions in API generator
1 parent ed9ede5 commit 031774f

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

godot.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version = "0.7.27"
1+
version = "0.7.28"
22
author = "Xored Software, Inc."
33
description = "Godot Engine bindings"
44
license = "MIT"

godot/godotapigen.nim

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,13 @@ const standardTypes = toHashSet(
308308
"PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
309309
"PoolVector2Array", "PoolVector3Array", "PoolColorArray"])
310310

311+
const variantPrimitives = [
312+
"bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32",
313+
"uint64", "Error",
314+
"int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2",
315+
"Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
316+
"Color", "RID"]
317+
311318
const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32",
312319
"int32", "cint", "int", "Error"])
313320
const int64Types = toHashSet(["uint64", "int64"])
@@ -322,7 +329,7 @@ const wrapperTypes = union(arrayTypes,
322329
toHashSet(["NodePath", "Dictionary", "Variant"]))
323330

324331
proc getInternalPtr(varName: PNode, typ: string): PNode =
325-
assert(typ in wrapperTypes)
332+
assert(typ in wrapperTypes or typ == "Object")
326333
result = newDotExpr(varName, ident("godot" & typ))
327334

328335
proc newNilCheck(ident, toAssign: PNode): PNode =
@@ -479,7 +486,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
479486
ident("+"),
480487
newDotExpr(ident(varargsName.get), ident("len"))))
481488
argsAlloc.add(newCall("godotAlloc", newCall("cint", infix(
482-
newCall("sizeof", ident("Variant")), ident("*"),
489+
newCall("sizeof", newPNode(nkPtrTy).addChain(ident("GodotVariant"))), ident("*"),
483490
newPNode(nkPar).addChain(argLenNode))))
484491
)
485492
else:
@@ -493,6 +500,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
493500
vars.add(newIdentDefs(argsName, newPNode(nkEmpty), argsAlloc))
494501

495502
let argConversions = newPNode(nkStmtList)
503+
let destructors = newPNode(nkStmtList)
496504
for idx, arg in meth.args:
497505
var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx))
498506
else: ident(arg.name)
@@ -503,13 +511,48 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
503511
let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx)
504512
let isStandardType = arg.typ in standardTypes
505513
let isWrappedType = arg.typ in wrapperTypes
506-
let convArg = if varargsName.isSome:
507-
getInternalPtr(newCall("toVariant", argName), "Variant")
508-
elif isWrappedType: getInternalPtr(argName, arg.typ)
509-
elif isStandardType: newCall("unsafeAddr", argName)
510-
elif arg.typ == "string": newCall("unsafeAddr",
511-
ident("argToPassToGodot" & $idx))
512-
else: ident("argToPassToGodot" & $idx) # object
514+
let convArg =
515+
if varargsName.isSome:
516+
let isAlreadyVariant = arg.typ == "Variant"
517+
let variantIdent = if isAlreadyVariant: getInternalPtr(argName, "Variant")
518+
else: ident("variant" & $idx)
519+
if not isAlreadyVariant:
520+
argConversions.add(newPNode(nkVarSection).addChain(
521+
newIdentDefs(variantIdent, ident("GodotVariant"), newEmptyNode())
522+
))
523+
destructors.add(
524+
newCall("deinit", variantIdent)
525+
)
526+
if arg.typ in variantPrimitives:
527+
argConversions.add(
528+
newCall("initGodotVariant", variantIdent, argName)
529+
)
530+
elif arg.typ in wrapperTypes or arg.typ == "Object":
531+
argConversions.add(
532+
newCall("initGodotVariant", variantIdent, getInternalPtr(argName, arg.typ))
533+
)
534+
elif arg.typ == "string":
535+
let stringIdent = ident("variantString" & $idx)
536+
argConversions.addChain(
537+
newPNode(nkVarSection).addChain(
538+
newIdentDefs(stringIdent, ident("GodotString"), newCall("toGodotString", argName))
539+
)
540+
).addChain(
541+
newCall("initGodotVariant", variantIdent, stringIdent)
542+
)
543+
destructors.add(newCall("deinit", stringIdent))
544+
else:
545+
raise newException(ValueError,
546+
"Non-standard type $# for varargs params of method $# of type $#" %
547+
[arg.typ, meth.godotName, meth.typ.godotName])
548+
549+
if isAlreadyVariant: variantIdent
550+
else: newCall("addr", variantIdent)
551+
elif isWrappedType: getInternalPtr(argName, arg.typ)
552+
elif isStandardType: newCall("unsafeAddr", argName)
553+
elif arg.typ == "string": newCall("unsafeAddr",
554+
ident("argToPassToGodot" & $idx))
555+
else: ident("argToPassToGodot" & $idx) # object
513556
if not isStandardType and arg.kind == ArgKind.VarArgs:
514557
raise newException(ValueError,
515558
"Non-standard type $# for varargs params of method $# of type $#" %
@@ -630,9 +673,10 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
630673
if arg.typ == "string":
631674
body.add(newCall("deinit", ident("argToPassToGodot" & $idx)))
632675

633-
if meth.args.len > 0 and varargsName.isSome:
634-
body.add(freeCall)
635676
if varargsName.isSome:
677+
if meth.args.len > 0:
678+
body.add(freeCall)
679+
body.add(destructors)
636680
let errCheck = newIfStmt(
637681
infix(newDotExpr(ident("callError"), ident("error")), ident("!="),
638682
newDotExpr(ident("VariantCallErrorType"), ident("OK"))),

godot/nim/godotmacros.nim

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,12 @@ macro invokeVarArgs(procIdent, objIdent;
272272
invocation = newNimNode(nnkCall).add(ident("procCall"), invocation)
273273

274274
if hasReturnValue:
275+
let resultVariant = genSym(nskLet, "ret")
276+
branchBody.add(
277+
newNimNode(nnkLetSection).add(
278+
newIdentDefs(resultVariant, ident("Variant"), newCall("toVariant", invocation))))
275279
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
276-
newCall("toVariant", invocation), ident("godotVariant")))
280+
resultVariant, ident("godotVariant")))
277281
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
278282
else:
279283
branchBody.add(invocation)

0 commit comments

Comments
 (0)