File: tgettypeinst.nim

package info (click to toggle)
nim 0.19.4-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 462,356 kB
  • sloc: sh: 11,089; ansic: 4,699; makefile: 706; python: 309; sql: 297; asm: 141; xml: 13
file content (185 lines) | stat: -rw-r--r-- 4,550 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
discard """
"""

import macros, strUtils

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): 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