123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- discard """
- """
- import macros
- proc symToIdent(x: NimNode): NimNode =
- case x.kind:
- of nnkCharLit..nnkUInt64Lit:
- result = newNimNode(x.kind)
- result.intVal = x.intVal
- of nnkFloatLit..nnkFloat64Lit:
- result = newNimNode(x.kind)
- result.floatVal = x.floatVal
- of nnkStrLit..nnkTripleStrLit:
- result = newNimNode(x.kind)
- result.strVal = x.strVal
- of nnkIdent, nnkSym:
- result = newIdentNode($x)
- else:
- result = newNimNode(x.kind)
- for c in x:
- result.add symToIdent(c)
- # check getTypeInst and getTypeImpl for given symbol x
- macro testX(x,inst0: typed; recurse: static[bool]; implX: typed) =
- # check that getTypeInst(x) equals inst0
- let inst = x.getTypeInst
- let instr = inst.symToIdent.treeRepr
- let inst0r = inst0.symToIdent.treeRepr
- if instr != inst0r:
- echo "instr:\n", instr
- echo "inst0r:\n", inst0r
- doAssert(instr == inst0r)
- # check that getTypeImpl(x) is correct
- # if implX is nil then compare to inst0
- # else we expect implX to be a type definition
- # and we extract the implementation from that
- let impl = x.getTypeImpl
- var impl0 =
- if implX.kind == nnkNilLit: inst0
- else: implX[0][2]
- let implr = impl.symToIdent.treerepr
- let impl0r = impl0.symToIdent.treerepr
- if implr != impl0r:
- echo "implr:\n", implr
- echo "impl0r:\n", impl0r
- doAssert(implr == impl0r)
- result = newStmtList()
- #template echoString(s: string) = echo s.replace("\n","\n ")
- #result.add getAst(echoString(" " & inst0.repr))
- #result.add getAst(echoString(" " & inst.repr))
- #result.add getAst(echoString(" " & impl0.repr))
- #result.add getAst(echoString(" " & impl.repr))
- if recurse:
- # now test using a newly formed variable of type getTypeInst(x)
- template testDecl(n,m: typed) =
- testV(n, false):
- type _ = m
- result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
- # test with a variable (instance) of type
- template testV(inst, recurse, impl) =
- block:
- #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
- var x: inst
- testX(x, inst, recurse, impl)
- # test with a newly created typedesc (myType)
- # using the passed type as the implementation
- template testT(impl, recurse) =
- block:
- type myType = impl
- testV(myType, recurse):
- type _ = impl
- # test a built-in type whose instance is equal to the implementation
- template test(inst) =
- testT(inst, false)
- testV(inst, true, nil)
- # test a custom type with provided implementation
- template test(inst, impl) =
- testV(inst, true, impl)
- type
- Model = object of RootObj
- User = object of Model
- name : string
- password : string
- Tree = object of RootObj
- value : int
- left,right : ref Tree
- MyEnum = enum
- valueA, valueB, valueC
- MySet = set[MyEnum]
- MySeq = seq[int]
- MyIntPtr = ptr int
- MyIntRef = ref int
- GenericObject[T] = object
- value:T
- Foo[N:static[int],T] = object
- Bar[N:static[int],T] = object
- #baz:Foo[N+1,GenericObject[T]] # currently fails
- baz:Foo[N,GenericObject[T]]
- Generic[T] = seq[int]
- Concrete = Generic[int]
- Generic2[T1, T2] = seq[T1]
- Concrete2 = Generic2[int, float]
- Alias1 = float
- Alias2 = Concrete
- Alias3 = Concrete2
- Vec[N: static[int],T] = object
- arr: array[N,T]
- Vec4[T] = Vec[4,T]
- test(bool)
- test(char)
- test(int)
- test(float)
- test(ptr int)
- test(ref int)
- test(array[1..10,Bar[2,Foo[3,float]]])
- test(array[MyEnum,Bar[2,Foo[3,float]]])
- test(distinct Bar[2,Foo[3,float]])
- test(tuple[a:int,b:Foo[-1,float]])
- test(seq[int])
- test(set[MyEnum])
- test(proc (a: int, b: Foo[2,float]))
- test(proc (a: int, b: Foo[2,float]): Bar[3,int])
- test(MyEnum):
- type _ = enum
- valueA, valueB, valueC
- test(Bar[2,Foo[3,float]]):
- type _ = object
- baz: Foo[2, GenericObject[Foo[3, float]]]
- test(Model):
- type _ = object of RootObj
- test(User):
- type _ = object of Model
- name: string
- password: string
- test(Tree):
- type _ = object of RootObj
- value: int
- left: ref Tree
- right: ref Tree
- test(Concrete):
- type _ = seq[int]
- test(Generic[int]):
- type _ = seq[int]
- test(Generic[float]):
- type _ = seq[int]
- test(Concrete2):
- type _ = seq[int]
- test(Generic2[int,float]):
- type _ = seq[int]
- test(Alias1):
- type _ = float
- test(Alias2):
- type _ = seq[int]
- test(Alias3):
- type _ = seq[int]
- test(Vec[4,float32]):
- type _ = object
- arr: array[0..3,float32]
- test(Vec4[float32]):
- type _ = object
- arr: array[0..3,float32]
- # bug #4862
- static:
- discard typedesc[(int, int)].getTypeImpl
- # custom pragmas
- template myAttr() {.pragma.}
- template myAttr2() {.pragma.}
- template myAttr3() {.pragma.}
- template serializationKey(key: string) {.pragma.}
- type
- MyObj = object {.packed,myAttr,serializationKey: "one".}
- myField {.myAttr2,serializationKey: "two".}: int
- myField2 {.myAttr3,serializationKey: "three".}: float
- # field pragmas not currently supported
- test(MyObj):
- type
- _ = object {.packed,myAttr,serializationKey: "one".}
- myField: int
- myField2: float
- block t9600:
- type
- Apple = ref object of RootObj
- macro mixer(x: typed): untyped =
- let w = getType(x)
- let v = getTypeImpl(w[1])
- var z: Apple
- mixer(z)
|