Skip to content

Instantly share code, notes, and snippets.

@jovial
Last active August 29, 2015 14:12
Show Gist options
  • Save jovial/fb944c2bbbcb533c05f6 to your computer and use it in GitHub Desktop.
Save jovial/fb944c2bbbcb533c05f6 to your computer and use it in GitHub Desktop.
supertype for generics
import tables
import typetraits
import macros
import strutils
import parseutils
import sequtils
type QObject* = ref object of RootObj
name*: string
data*: pointer
slots*: Table[string, cint]
signals*: Table[string, cint]
properties*: Table[string, cint]
type Test = object of RootObj
type A = ref object of QObject
type B[T] = ref object of A
tee: T
type C[T] = ref object of B[T]
#proc getSuperString[T](a: typedesc[C[T]]): string {.compileTime.} =
# return "B[$1]" % [T.type.name]
#### must generate these from type definition
proc getSuperGenericParams[T](a: typedesc[C[T]]): seq[string] {.compileTime.} =
# convert all generic params to strings and return them in a seq
result = @[T.name]
template getGenericSuper(paramatised: typedesc[C], T: typedesc): expr =
# given paramatised type and type constraints return super type
B[T]
template superType(paramatised: typedesc[C]): typedesc =
macro helper(): expr {.genSym.} =
# if macros.typ worked we wouldn't have to nest helper
# we would just pass it the typedesc
let typDesc = parseExpr(paramatised.name)
let params = getSuperGenericParams(paramatised)
var args = newSeq[PNimrodNode]()
args.add typDesc
for param in params:
let asIdent = ident param
args.add asIdent
result = newCall("getGenericSuper", args)
helper()
# these are the generated procedures for each of the supertypes
template superType(typ: typedesc[B]): typedesc[A] =
A
template superType(typ: typedesc[A]): typedesc[QObject] =
# gotcha with this one as name is defined as a field,
# you can't use ``typetraits.name`` as a dotExpr
QObject
####
# this one could be hard coded
template superType(typ: typedesc[QObject]): typedesc[RootObj] =
RootObj
echo superType(C[string]).name
echo superType(C[int]).name
echo superType(C[Test]).name
echo name(C[Test].superType.superType.superType)
# on instance (doesn't work for generics)
var x = A()
echo ((type x).superType.superType.name)
var y = B[int]()
echo ((type y).superType.name)
var z = C[int]()
#echo ((type z).superType.name) # doesn't work
echo ((type z).getGenericSuper(int).name) # works, but poor ergonomics
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment