Nim/tests/macros/tgettypeinst.nim
metagn 86f7f4ffa5
remove deprecated type pragma syntax, fix bugs that required it (#20199)
* remove deprecated pragma syntax from 0.20.0

closes #4651, closes #16653 with a cheap fix for now due to
how early `tfFinal` is set

* remove type pragma between name and generics

* undo removal, try removing bind expression (0.8.14)

* fix test, unremove bind expr

* remove again

* Update changelog.md

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>

* dependencies @ HEAD & weave test dependencies

* try fix package ci

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
2022-09-03 09:52:13 +02:00

214 lines
5.1 KiB
Nim

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 {.packed,myAttr,serializationKey: "one".} = object
myField {.myAttr2,serializationKey: "two".}: int
myField2 {.myAttr3,serializationKey: "three".}: float
# field pragmas not currently supported
test(MyObj):
type
_ {.packed,myAttr,serializationKey: "one".} = object
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)