Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Last active August 29, 2015 14:20
Show Gist options
  • Save fowlmouth/dbb43f560cdc67cc3601 to your computer and use it in GitHub Desktop.
Save fowlmouth/dbb43f560cdc67cc3601 to your computer and use it in GitHub Desktop.
import macros
macro super (x:typed): untyped =
## returns `x` with a type conv to its parent type,
## keeping ptr/ref info. `x` may be be an object,
## ptr or ref to an object, or a typedesc
var ty = getType(x)
var isTypedesc = ty.typekind == ntyTypedesc
if isTypedesc: ty = ty[1]
var ptrTy = 0.NimTypeKind
if ty.typekind in {ntyRef,ntyPtr}:
ptrTy = ty.typekind
ty = ty[1]
assert ty.typekind == ntyObject
ty = ty.getType # this is the base type where the parent is found
let parent = ty[0]
if parent.typekind in {ntyNone,ntyEmpty}:
# no parent
result = x
else:
let T =
if ptrTy == ntyPtr: newTree(nnkPtrTy, parent)
elif ptrTy == ntyRef: newTree(nnkRefTy, parent)
else: parent
result =
if isTypedesc: `T`
else: quote do: `T`(`x`)
when defined(debug):
echo "super() result: ", treerepr result
when isMainModule:
type T1 = ref object of RootRef
type T2 = ref object of T1
var a = T2()
var b = super(a)
static:
assert b is T1
assert super(b) is ref RootObj
assert super(super(b)) is ref RootObj
# typedescs work too
type NonRef = object of RootObj
static:
assert super(NonRef) is RootObj, "super() works on typedescs"
assert super(ref NonRef) is ref RootObj, "ref is preserved"
assert super(ptr NonRef) is ptr RootObj, "ptr is preserved"
assert super(RootObj) is RootObj, "if x has no parent type, x is returned"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment