No destructors

This commit is contained in:
Ruslan Mustakov 2017-07-28 00:28:17 +07:00
commit f5769045fc
34 changed files with 1701 additions and 1216 deletions

View file

@ -1,8 +1,8 @@
# Copyright 2017 Xored Software, Inc.
import macros, tables, typetraits
import "../core/godotcore.nim"
import godotnim
import "../godotinternal.nim", "../internal/godotvariants.nim"
import godotnim, "../core/variants.nim"
type
VarDecl = ref object
@ -64,18 +64,6 @@ iterator pragmas(node: NimNode):
elif node[index].kind == nnkIdent:
yield (node[index].ident, nil, index)
proc hasPragma(statement: NimNode, pname: string): bool =
## Checks if the pragma is present in the `statement`
if not (RoutineNodes.contains(statement.kind) or
statement.kind == nnkPragmaExpr):
return false
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
else: statement[1]
let pnameIdent = !pname
for ident, val, i in pragmas(pragmas):
if ident == pnameIdent:
return true
proc removePragma(statement: NimNode, pname: string): bool =
## Removes the pragma from the node and returns whether pragma was removed
if not (RoutineNodes.contains(statement.kind) or
@ -205,7 +193,9 @@ macro invokeVarArgs(procIdent, objIdent;
## error(...)
template conv(procLit, argT, argSeq, idx, argIdent, errIdent) =
let (argIdent, errIdent) = godotToNim[argT](argSeq[idx])
let v = newVariant(argSeq[idx])
v.markNoDeinit() # args should be destroyed externally
let (argIdent, errIdent) = godotToNim[argT](v)
if errIdent != ConversionResult.OK:
let errorKind = if errIdent == ConversionResult.TypeError: "a type error"
else: "a range error"
@ -215,6 +205,14 @@ macro invokeVarArgs(procIdent, objIdent;
" of Godot type " & $argSeq[idx].getType())
return
# these help to avoid exporting internal modules
# thanks to closed symbol binding
template initGodotVariantCall(result) =
initGodotVariant(result)
template initGodotVariantCall(result, src) =
initGodotVariant(result, src)
result = newNimNode(nnkCaseStmt)
result.add(numArgsIdent)
for i in minArgs..maxArgs:
@ -231,12 +229,13 @@ macro invokeVarArgs(procIdent, objIdent;
argSeqIdent, idx, argIdent, errIdent)))
invocation.add(argIdent)
if hasReturnValue:
branchBody.add(newNimNode(nnkAsgn).add(ident("result"),
newCall("toGodot", invocation)))
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
newCall("toGodot", newCall("newVariant", invocation)),
ident("godotVariant")))
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
else:
branchBody.add(invocation)
branchBody.add(newNimNode(nnkAsgn).add(ident("result"),
newCall("variant")))
branchBody.add(getAst(initGodotVariantCall(ident("result"))))
branch.add(branchBody)
result.add(branch)
@ -306,8 +305,10 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
hintIdent, usageIdent, hasDefaultValue,
defaultValueNode) =
proc setFuncIdent(obj: ptr GodotObject, methData: pointer,
nimPtr: pointer, val: Variant) {.noconv.} =
let (nimVal, err) = godotToNim[propTypeIdent](val)
nimPtr: pointer, val: GodotVariant) {.noconv.} =
let variant = newVariant(val)
variant.markNoDeinit()
let (nimVal, err) = godotToNim[propTypeIdent](variant)
case err:
of ConversionResult.OK:
cast[classNameIdent](nimPtr).propNameIdent = nimVal
@ -321,8 +322,10 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
printError(errStr)
proc getFuncIdent(obj: ptr GodotObject, methData: pointer,
nimPtr: pointer): Variant {.noconv.} =
result = nimToGodot(cast[classNameIdent](nimPtr).propNameIdent)
nimPtr: pointer): GodotVariant {.noconv.} =
let variant = nimToGodot(cast[classNameIdent](nimPtr).propNameIdent)
variant.markNoDeinit()
result = variant.godotVariant[]
let setFunc = GodotPropertySetFunc(
setFunc: setFuncIdent
@ -436,8 +439,8 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
argTypes, methFuncIdent, hasReturnValue) =
proc methFuncIdent(obj: ptr GodotObject, methodData: pointer,
userData: pointer, numArgs: cint,
args: var ptr array[MAX_ARG_COUNT, Variant]):
Variant {.noconv.} =
args: var ptr array[MAX_ARG_COUNT, GodotVariant]):
GodotVariant {.noconv.} =
let self = cast[classNameIdent](userData)
when defined(release):
invokeVarArgs(methodNameIdent, self, minArgs, maxArgs, numArgs,
@ -448,8 +451,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
args, argTypes, hasReturnValue)
except:
let ex = getCurrentException()
printError("Unhandled Nim exception (" &
$ex.name & "): " &
printError("Unhandled Nim exception (" & $ex.name & "): " &
ex.msg & "\n" & ex.getStackTrace())
let meth = GodotInstanceMethod(

View file

@ -1,13 +1,14 @@
# Copyright 2017 Xored Software, Inc.
import tables, typetraits, macros
import "../core/godotbase.nim", "../core/godotcore.nim"
import "../core/strings.nim", "../core/vector2.nim", "../core/rect2.nim",
import "../core/godotbase.nim"
import "../core/vector2.nim", "../core/rect2.nim",
"../core/vector3.nim", "../core/transform2d.nim",
"../core/plane.nim", "../core/quat.nim", "../core/rect3.nim",
"../core/basis.nim", "../core/transform.nim", "../core/color.nim",
"../core/nodepath.nim", "../core/rid.nim", "../core/dictionary.nim",
"../core/arrays.nim", "../core/poolarray.nim", "../core/variant.nim"
"../core/planes.nim", "../core/quats.nim", "../core/rect3.nim",
"../core/basis.nim", "../core/transforms.nim", "../core/colors.nim",
"../core/nodepaths.nim", "../core/rids.nim", "../core/dictionaries.nim",
"../core/arrays.nim", "../core/poolarrays.nim", "../core/variants.nim"
import "../godotinternal.nim"
## Definition of NimGodotObject and converters for built-in types.
@ -48,6 +49,24 @@ type
isNative: bool
isRef: bool
template printWarning*(warn: typed) =
let (filename, line) = instantiationInfo()
godotPrintWarning(cstring($warn), nil, cstring(filename), line.cint)
template printError*(err: typed) =
let (filename, line) = instantiationInfo()
godotPrintError(cstring($err), nil, cstring(filename), line.cint)
proc print*(message: string) {.inline.} =
var s = message.toGodotString()
godotPrint(s)
s.deinit()
proc print*(message: cstring) {.inline.} =
var s = message.toGodotString()
godotPrint(s)
s.deinit()
var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo]
static:
@ -55,16 +74,8 @@ static:
var nativeClasses {.compileTime.} = newSeq[string]()
var refClasses* {.compileTime.} = newSeq[string]()
var getClassMethodBind {.threadvar.}: ptr GodotMethodBind
proc getClassName*(o: ptr GodotObject): string =
if getClassMethodBind.isNil:
getClassMethodBind = getMethod(cstring"Object", cstring"get_class")
var ret: GodotString
getClassMethodBind.ptrCall(o, nil, addr ret)
result = $ret
if result.endsWith("SW"):
# There are physics type not known by ClassDB
result = result[0..result.len-3]
proc getClassName*(o: NimGodotObject): string =
o.godotObject.getClassName()
var unreferenceMethodBind {.threadvar.}: ptr GodotMethodBind
proc unreference(o: ptr GodotObject): bool =
@ -176,6 +187,15 @@ proc asNimGodotObject*[T: NimGodotObject](godotObject: ptr GodotObject): T =
result = newNimGodotObject[T](
godotObject, cstring(godotObject.getClassName()))
proc newVariant*(obj: NimGodotObject): Variant {.inline.} =
newVariant(obj.godotObject)
proc asObject*[T: NimGodotObject](v: Variant): T {.inline.} =
asNimGodotObject[T](v.asGodotObject())
proc asObject*(v: Variant, T: typedesc[NimGodotObject]): T {.inline.} =
asNimGodotObject[T](v.asGodotObject())
proc `as`*[T: NimGodotObject](obj: NimGodotObject, t: typedesc[T]): T =
## Converts the ``obj`` into the specified type.
## Returns ``nil`` if the conversion cannot be performed
@ -250,7 +270,7 @@ proc newConversionError*(err: ConversionResult): ref ValueError =
result = newException(ValueError, msg)
proc removeGodotObject*(nimObj: NimGodotObject) =
proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} =
## Used from destructor
nimObj.godotObject = nil
@ -269,12 +289,12 @@ proc godotVariantType*(T: typedesc[NimGodotObject]): VariantType {.inline.} =
VariantType.Object
proc toGodot*(self: NimGodotObject): Variant {.inline.} =
variant(self.godotObject)
newVariant(self.godotObject)
proc fromGodot*[T: NimGodotObject](self: var T,
val: Variant): ConversionResult =
if val.getType() == VariantType.Object:
let objPtr = val.asObject()
let objPtr = val.asGodotObject()
self = asNimGodotObject[T](objPtr)
if self.isNil:
result = ConversionResult.TypeError
@ -287,19 +307,21 @@ proc godotVariantType*(T: typedesc[enum]): VariantType {.inline.} =
VariantType.Int
proc toGodot*[T: enum](self: T): Variant {.inline.} =
variant(int64(ord(self)))
newVariant(int64(ord(self)))
proc fromGodot*[T: enum](self: var T, val: Variant): ConversionResult =
proc fromGodot*[T: enum](self: var T,
val: Variant): ConversionResult {.inline.} =
if val.getType() == VariantType.Int:
self = T(val.asInt())
else:
result = ConversionResult.TypeError
proc toGodot*(self: Variant): Variant {.inline.} =
result = self
self
proc fromGodot*(self: var Variant, val: Variant): ConversionResult {.inline.} =
self = val
proc fromGodot*(self: var Variant,
val: Variant): ConversionResult {.inline.} =
self = newVariant(val)
proc godotVariantType*(T: typedesc[SomeGodotOrNum]): VariantType {.inline.} =
when T is SomeSignedInt or T is SomeUnsignedInt:
@ -330,12 +352,12 @@ proc godotVariantType*(T: typedesc[SomeGodotOrNum]): VariantType {.inline.} =
VariantType.Transform
elif T is Color:
VariantType.Color
elif T is NodePath:
VariantType.NodePath
elif T is RID:
VariantType.RID
elif T is GodotObject:
elif T is ptr GodotObject:
VariantType.Object
elif T is NodePath:
VariantType.NodePath
elif T is Dictionary:
VariantType.Dictionary
elif T is Array:
@ -358,7 +380,7 @@ proc godotVariantType*(T: typedesc[SomeGodotOrNum]): VariantType {.inline.} =
VariantType.Nil
proc toGodot*[T: SomeGodotOrNum](val: T): Variant {.inline.} =
result = variant(val)
newVariant(val)
proc fromGodot*[T: SomeSignedInt or SomeUnsignedInt](
self: var T, val: Variant): ConversionResult =
@ -376,7 +398,7 @@ proc fromGodot*[T: SomeSignedInt or SomeUnsignedInt](
proc fromGodot*[T: SomeFloat](self: var T, val: Variant): ConversionResult =
if val.getType() == VariantType.Real:
self = val.asReal()
self = T(val.asReal())
elif val.getType() == VariantType.Int:
self = T(val.asInt())
else:
@ -441,13 +463,15 @@ proc godotVariantType*(T: typedesc[string]): VariantType {.inline.} =
VariantType.String
proc toGodot*(s: string): Variant {.inline.} =
variant(s.toGodotString())
newVariant(s)
proc fromGodot*(s: var string, val: Variant): ConversionResult =
if val.getType() != VariantType.String:
result = ConversionResult.TypeError
if val.getType() == VariantType.String:
s = val.asString()
elif val.getType() == VariantType.Nil:
s = nil
else:
s = $val.asGodotString()
result = ConversionResult.TypeError
proc godotVariantType*(T: typedesc[seq]): VariantType =
VariantType.Array
@ -456,11 +480,11 @@ proc godotVariantType*(T: typedesc[array]): VariantType =
VariantType.Array
proc toGodot*[T](s: openarray[T]): Variant =
var arr = initArray()
var arr = newArray()
mixin toGodot
for item in s:
arr.add(toGodot(item))
result = variant(arr)
result = newVariant(arr)
proc fromGodot*[T](s: var seq[T], val: Variant): ConversionResult =
if val.getType() != VariantType.Array:
@ -492,11 +516,11 @@ proc godotVariantType*(T: typedesc[Table|TableRef]): VariantType {.inline.} =
VariantType.Dictionary
proc toGodot*[T: Table or TableRef](t: T): Variant =
var dict = initDictionary()
var dict = newDictionary()
mixin toGodot
for k, v in t.pairs():
dict[toGodot(k)] = toGodot(v)
result = variant(dict)
result = newVariant(dict)
proc fromGodot*[T: Table or TableRef](t: var T, val: Variant): ConversionResult =
if val.getType() != VariantType.Dictionary:
@ -563,7 +587,7 @@ proc godot_gdnative_init(options: ptr GodotNativeInitOptions) {.
proc godot_gdnative_terminate(options: ptr GodotNativeTerminateOptions) {.
cdecl, exportc, dynlib.} =
deallocHeap(runFinalizers = false, allowGcAfterwards = false)
deallocHeap(runFinalizers = not options[].inEditor, allowGcAfterwards = false)
proc godot_nativescript_thread_enter() {.
cdecl, exportc, dynlib.} =