Last active
August 29, 2015 14:12
-
-
Save jovial/fb944c2bbbcb533c05f6 to your computer and use it in GitHub Desktop.
supertype for generics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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