More efficient and GC-safe conversions in API generator
This commit is contained in:
parent
ed9ede5cb3
commit
031774f54f
3 changed files with 61 additions and 13 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
version = "0.7.27"
|
version = "0.7.28"
|
||||||
author = "Xored Software, Inc."
|
author = "Xored Software, Inc."
|
||||||
description = "Godot Engine bindings"
|
description = "Godot Engine bindings"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,13 @@ const standardTypes = toHashSet(
|
||||||
"PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
|
"PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
|
||||||
"PoolVector2Array", "PoolVector3Array", "PoolColorArray"])
|
"PoolVector2Array", "PoolVector3Array", "PoolColorArray"])
|
||||||
|
|
||||||
|
const variantPrimitives = [
|
||||||
|
"bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32",
|
||||||
|
"uint64", "Error",
|
||||||
|
"int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2",
|
||||||
|
"Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
|
||||||
|
"Color", "RID"]
|
||||||
|
|
||||||
const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32",
|
const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32",
|
||||||
"int32", "cint", "int", "Error"])
|
"int32", "cint", "int", "Error"])
|
||||||
const int64Types = toHashSet(["uint64", "int64"])
|
const int64Types = toHashSet(["uint64", "int64"])
|
||||||
|
|
@ -322,7 +329,7 @@ const wrapperTypes = union(arrayTypes,
|
||||||
toHashSet(["NodePath", "Dictionary", "Variant"]))
|
toHashSet(["NodePath", "Dictionary", "Variant"]))
|
||||||
|
|
||||||
proc getInternalPtr(varName: PNode, typ: string): PNode =
|
proc getInternalPtr(varName: PNode, typ: string): PNode =
|
||||||
assert(typ in wrapperTypes)
|
assert(typ in wrapperTypes or typ == "Object")
|
||||||
result = newDotExpr(varName, ident("godot" & typ))
|
result = newDotExpr(varName, ident("godot" & typ))
|
||||||
|
|
||||||
proc newNilCheck(ident, toAssign: PNode): PNode =
|
proc newNilCheck(ident, toAssign: PNode): PNode =
|
||||||
|
|
@ -479,7 +486,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
ident("+"),
|
ident("+"),
|
||||||
newDotExpr(ident(varargsName.get), ident("len"))))
|
newDotExpr(ident(varargsName.get), ident("len"))))
|
||||||
argsAlloc.add(newCall("godotAlloc", newCall("cint", infix(
|
argsAlloc.add(newCall("godotAlloc", newCall("cint", infix(
|
||||||
newCall("sizeof", ident("Variant")), ident("*"),
|
newCall("sizeof", newPNode(nkPtrTy).addChain(ident("GodotVariant"))), ident("*"),
|
||||||
newPNode(nkPar).addChain(argLenNode))))
|
newPNode(nkPar).addChain(argLenNode))))
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
@ -493,6 +500,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
vars.add(newIdentDefs(argsName, newPNode(nkEmpty), argsAlloc))
|
vars.add(newIdentDefs(argsName, newPNode(nkEmpty), argsAlloc))
|
||||||
|
|
||||||
let argConversions = newPNode(nkStmtList)
|
let argConversions = newPNode(nkStmtList)
|
||||||
|
let destructors = newPNode(nkStmtList)
|
||||||
for idx, arg in meth.args:
|
for idx, arg in meth.args:
|
||||||
var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx))
|
var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx))
|
||||||
else: ident(arg.name)
|
else: ident(arg.name)
|
||||||
|
|
@ -503,13 +511,48 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx)
|
let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx)
|
||||||
let isStandardType = arg.typ in standardTypes
|
let isStandardType = arg.typ in standardTypes
|
||||||
let isWrappedType = arg.typ in wrapperTypes
|
let isWrappedType = arg.typ in wrapperTypes
|
||||||
let convArg = if varargsName.isSome:
|
let convArg =
|
||||||
getInternalPtr(newCall("toVariant", argName), "Variant")
|
if varargsName.isSome:
|
||||||
elif isWrappedType: getInternalPtr(argName, arg.typ)
|
let isAlreadyVariant = arg.typ == "Variant"
|
||||||
elif isStandardType: newCall("unsafeAddr", argName)
|
let variantIdent = if isAlreadyVariant: getInternalPtr(argName, "Variant")
|
||||||
elif arg.typ == "string": newCall("unsafeAddr",
|
else: ident("variant" & $idx)
|
||||||
ident("argToPassToGodot" & $idx))
|
if not isAlreadyVariant:
|
||||||
else: ident("argToPassToGodot" & $idx) # object
|
argConversions.add(newPNode(nkVarSection).addChain(
|
||||||
|
newIdentDefs(variantIdent, ident("GodotVariant"), newEmptyNode())
|
||||||
|
))
|
||||||
|
destructors.add(
|
||||||
|
newCall("deinit", variantIdent)
|
||||||
|
)
|
||||||
|
if arg.typ in variantPrimitives:
|
||||||
|
argConversions.add(
|
||||||
|
newCall("initGodotVariant", variantIdent, argName)
|
||||||
|
)
|
||||||
|
elif arg.typ in wrapperTypes or arg.typ == "Object":
|
||||||
|
argConversions.add(
|
||||||
|
newCall("initGodotVariant", variantIdent, getInternalPtr(argName, arg.typ))
|
||||||
|
)
|
||||||
|
elif arg.typ == "string":
|
||||||
|
let stringIdent = ident("variantString" & $idx)
|
||||||
|
argConversions.addChain(
|
||||||
|
newPNode(nkVarSection).addChain(
|
||||||
|
newIdentDefs(stringIdent, ident("GodotString"), newCall("toGodotString", argName))
|
||||||
|
)
|
||||||
|
).addChain(
|
||||||
|
newCall("initGodotVariant", variantIdent, stringIdent)
|
||||||
|
)
|
||||||
|
destructors.add(newCall("deinit", stringIdent))
|
||||||
|
else:
|
||||||
|
raise newException(ValueError,
|
||||||
|
"Non-standard type $# for varargs params of method $# of type $#" %
|
||||||
|
[arg.typ, meth.godotName, meth.typ.godotName])
|
||||||
|
|
||||||
|
if isAlreadyVariant: variantIdent
|
||||||
|
else: newCall("addr", variantIdent)
|
||||||
|
elif isWrappedType: getInternalPtr(argName, arg.typ)
|
||||||
|
elif isStandardType: newCall("unsafeAddr", argName)
|
||||||
|
elif arg.typ == "string": newCall("unsafeAddr",
|
||||||
|
ident("argToPassToGodot" & $idx))
|
||||||
|
else: ident("argToPassToGodot" & $idx) # object
|
||||||
if not isStandardType and arg.kind == ArgKind.VarArgs:
|
if not isStandardType and arg.kind == ArgKind.VarArgs:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"Non-standard type $# for varargs params of method $# of type $#" %
|
"Non-standard type $# for varargs params of method $# of type $#" %
|
||||||
|
|
@ -630,9 +673,10 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
if arg.typ == "string":
|
if arg.typ == "string":
|
||||||
body.add(newCall("deinit", ident("argToPassToGodot" & $idx)))
|
body.add(newCall("deinit", ident("argToPassToGodot" & $idx)))
|
||||||
|
|
||||||
if meth.args.len > 0 and varargsName.isSome:
|
|
||||||
body.add(freeCall)
|
|
||||||
if varargsName.isSome:
|
if varargsName.isSome:
|
||||||
|
if meth.args.len > 0:
|
||||||
|
body.add(freeCall)
|
||||||
|
body.add(destructors)
|
||||||
let errCheck = newIfStmt(
|
let errCheck = newIfStmt(
|
||||||
infix(newDotExpr(ident("callError"), ident("error")), ident("!="),
|
infix(newDotExpr(ident("callError"), ident("error")), ident("!="),
|
||||||
newDotExpr(ident("VariantCallErrorType"), ident("OK"))),
|
newDotExpr(ident("VariantCallErrorType"), ident("OK"))),
|
||||||
|
|
|
||||||
|
|
@ -272,8 +272,12 @@ macro invokeVarArgs(procIdent, objIdent;
|
||||||
invocation = newNimNode(nnkCall).add(ident("procCall"), invocation)
|
invocation = newNimNode(nnkCall).add(ident("procCall"), invocation)
|
||||||
|
|
||||||
if hasReturnValue:
|
if hasReturnValue:
|
||||||
|
let resultVariant = genSym(nskLet, "ret")
|
||||||
|
branchBody.add(
|
||||||
|
newNimNode(nnkLetSection).add(
|
||||||
|
newIdentDefs(resultVariant, ident("Variant"), newCall("toVariant", invocation))))
|
||||||
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
|
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
|
||||||
newCall("toVariant", invocation), ident("godotVariant")))
|
resultVariant, ident("godotVariant")))
|
||||||
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
|
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
|
||||||
else:
|
else:
|
||||||
branchBody.add(invocation)
|
branchBody.add(invocation)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue