semgnrc.nim 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This implements the first pass over the generic body; it resolves some
  10. # symbols. Thus for generics there is a two-phase symbol lookup just like
  11. # in C++.
  12. # A problem is that it cannot be detected if the symbol is introduced
  13. # as in ``var x = ...`` or used because macros/templates can hide this!
  14. # So we have to eval templates/macros right here so that symbol
  15. # lookup can be accurate.
  16. # included from sem.nim
  17. proc getIdentNode(c: PContext; n: PNode): PNode =
  18. case n.kind
  19. of nkPostfix: result = getIdentNode(c, n.sons[1])
  20. of nkPragmaExpr: result = getIdentNode(c, n.sons[0])
  21. of nkIdent, nkAccQuoted, nkSym: result = n
  22. else:
  23. illFormedAst(n, c.config)
  24. result = n
  25. type
  26. GenericCtx = object
  27. toMixin: IntSet
  28. cursorInBody: bool # only for nimsuggest
  29. bracketExpr: PNode
  30. TSemGenericFlag = enum
  31. withinBind,
  32. withinTypeDesc,
  33. withinMixin,
  34. withinConcept
  35. TSemGenericFlags = set[TSemGenericFlag]
  36. proc semGenericStmt(c: PContext, n: PNode,
  37. flags: TSemGenericFlags, ctx: var GenericCtx): PNode
  38. proc semGenericStmtScope(c: PContext, n: PNode,
  39. flags: TSemGenericFlags,
  40. ctx: var GenericCtx): PNode =
  41. openScope(c)
  42. result = semGenericStmt(c, n, flags, ctx)
  43. closeScope(c)
  44. template macroToExpand(s): untyped =
  45. s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfAllUntyped in s.flags)
  46. template macroToExpandSym(s): untyped =
  47. sfCustomPragma notin s.flags and s.kind in {skMacro, skTemplate} and
  48. (s.typ.len == 1) and not fromDotExpr
  49. template isMixedIn(sym): bool =
  50. let s = sym
  51. s.name.id in ctx.toMixin or (withinConcept in flags and
  52. s.magic == mNone and
  53. s.kind in OverloadableSyms)
  54. proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
  55. ctx: var GenericCtx; flags: TSemGenericFlags,
  56. fromDotExpr=false): PNode =
  57. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  58. incl(s.flags, sfUsed)
  59. case s.kind
  60. of skUnknown:
  61. # Introduced in this pass! Leave it as an identifier.
  62. result = n
  63. of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
  64. result = symChoice(c, n, s, scOpen)
  65. of skTemplate:
  66. if macroToExpandSym(s):
  67. onUse(n.info, s)
  68. result = semTemplateExpr(c, n, s, {efNoSemCheck})
  69. result = semGenericStmt(c, result, {}, ctx)
  70. else:
  71. result = symChoice(c, n, s, scOpen)
  72. of skMacro:
  73. if macroToExpandSym(s):
  74. onUse(n.info, s)
  75. result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  76. result = semGenericStmt(c, result, {}, ctx)
  77. else:
  78. result = symChoice(c, n, s, scOpen)
  79. of skGenericParam:
  80. if s.typ != nil and s.typ.kind == tyStatic:
  81. if s.typ.n != nil:
  82. result = s.typ.n
  83. else:
  84. result = n
  85. else:
  86. result = newSymNodeTypeDesc(s, n.info)
  87. onUse(n.info, s)
  88. of skParam:
  89. result = n
  90. onUse(n.info, s)
  91. of skType:
  92. if (s.typ != nil) and
  93. (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
  94. result = newSymNodeTypeDesc(s, n.info)
  95. else:
  96. result = n
  97. onUse(n.info, s)
  98. else:
  99. result = newSymNode(s, n.info)
  100. onUse(n.info, s)
  101. proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  102. ctx: var GenericCtx): PNode =
  103. result = n
  104. let ident = considerQuotedIdent(c, n)
  105. var s = searchInScopes(c, ident).skipAlias(n, c.config)
  106. if s == nil:
  107. s = strTableGet(c.pureEnumFields, ident)
  108. if s != nil and contains(c.ambiguousSymbols, s.id):
  109. s = nil
  110. if s == nil:
  111. if ident.id notin ctx.toMixin and withinMixin notin flags:
  112. errorUndeclaredIdentifier(c, n.info, ident.s)
  113. else:
  114. if withinBind in flags:
  115. result = symChoice(c, n, s, scClosed)
  116. elif s.isMixedIn:
  117. result = symChoice(c, n, s, scForceOpen)
  118. else:
  119. result = semGenericStmtSymbol(c, n, s, ctx, flags)
  120. # else: leave as nkIdent
  121. proc newDot(n, b: PNode): PNode =
  122. result = newNodeI(nkDotExpr, n.info)
  123. result.add(n.sons[0])
  124. result.add(b)
  125. proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  126. ctx: var GenericCtx; isMacro: var bool): PNode =
  127. assert n.kind == nkDotExpr
  128. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  129. let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule}
  130. var s = qualifiedLookUp(c, n, luf)
  131. if s != nil:
  132. result = semGenericStmtSymbol(c, n, s, ctx, flags)
  133. else:
  134. n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
  135. result = n
  136. let n = n[1]
  137. let ident = considerQuotedIdent(c, n)
  138. var s = searchInScopes(c, ident).skipAlias(n, c.config)
  139. if s != nil and s.kind in routineKinds:
  140. isMacro = s.kind in {skTemplate, skMacro}
  141. if withinBind in flags:
  142. result = newDot(result, symChoice(c, n, s, scClosed))
  143. elif s.isMixedIn:
  144. result = newDot(result, symChoice(c, n, s, scForceOpen))
  145. else:
  146. let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
  147. if syms.kind == nkSym:
  148. let choice = symChoice(c, n, s, scForceOpen)
  149. choice.kind = nkClosedSymChoice
  150. result = newDot(result, choice)
  151. else:
  152. result = newDot(result, syms)
  153. proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
  154. let s = newSymS(skUnknown, getIdentNode(c, n), c)
  155. addPrelimDecl(c, s)
  156. styleCheckDef(c.config, n.info, s, kind)
  157. onDef(n.info, s)
  158. proc semGenericStmt(c: PContext, n: PNode,
  159. flags: TSemGenericFlags, ctx: var GenericCtx): PNode =
  160. result = n
  161. when defined(nimsuggest):
  162. if withinTypeDesc in flags: inc c.inTypeContext
  163. #if conf.cmd == cmdIdeTools: suggestStmt(c, n)
  164. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  165. case n.kind
  166. of nkIdent, nkAccQuoted:
  167. result = lookup(c, n, flags, ctx)
  168. of nkDotExpr:
  169. #let luf = if withinMixin notin flags: {checkUndeclared} else: {}
  170. #var s = qualifiedLookUp(c, n, luf)
  171. #if s != nil: result = semGenericStmtSymbol(c, n, s)
  172. # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
  173. var dummy: bool
  174. result = fuzzyLookup(c, n, flags, ctx, dummy)
  175. of nkSym:
  176. let a = n.sym
  177. let b = getGenSym(c, a)
  178. if b != a: n.sym = b
  179. of nkEmpty, succ(nkSym)..nkNilLit, nkComesFrom:
  180. # see tests/compile/tgensymgeneric.nim:
  181. # We need to open the gensym'ed symbol again so that the instantiation
  182. # creates a fresh copy; but this is wrong the very first reason for gensym
  183. # is that scope rules cannot be used! So simply removing 'sfGenSym' does
  184. # not work. Copying the symbol does not work either because we're already
  185. # the owner of the symbol! What we need to do is to copy the symbol
  186. # in the generic instantiation process...
  187. discard
  188. of nkBind:
  189. result = semGenericStmt(c, n.sons[0], flags+{withinBind}, ctx)
  190. of nkMixinStmt:
  191. result = semMixinStmt(c, n, ctx.toMixin)
  192. of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit:
  193. # check if it is an expression macro:
  194. checkMinSonsLen(n, 1, c.config)
  195. let fn = n.sons[0]
  196. var s = qualifiedLookUp(c, fn, {})
  197. if s == nil and
  198. {withinMixin, withinConcept}*flags == {} and
  199. fn.kind in {nkIdent, nkAccQuoted} and
  200. considerQuotedIdent(c, fn).id notin ctx.toMixin:
  201. errorUndeclaredIdentifier(c, n.info, fn.renderTree)
  202. var first = int ord(withinConcept in flags)
  203. var mixinContext = false
  204. if s != nil:
  205. incl(s.flags, sfUsed)
  206. mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles}
  207. let sc = symChoice(c, fn, s, if s.isMixedIn: scForceOpen else: scOpen)
  208. case s.kind
  209. of skMacro:
  210. if macroToExpand(s) and sc.safeLen <= 1:
  211. onUse(fn.info, s)
  212. result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  213. result = semGenericStmt(c, result, flags, ctx)
  214. else:
  215. n.sons[0] = sc
  216. result = n
  217. mixinContext = true
  218. of skTemplate:
  219. if macroToExpand(s) and sc.safeLen <= 1:
  220. onUse(fn.info, s)
  221. result = semTemplateExpr(c, n, s, {efNoSemCheck})
  222. result = semGenericStmt(c, result, flags, ctx)
  223. else:
  224. n.sons[0] = sc
  225. result = n
  226. # BUGFIX: we must not return here, we need to do first phase of
  227. # symbol lookup. Also since templates and macros can do scope injections
  228. # we need to put the ``c`` in ``t(c)`` in a mixin context to prevent
  229. # the famous "undeclared identifier: it" bug:
  230. mixinContext = true
  231. of skUnknown, skParam:
  232. # Leave it as an identifier.
  233. discard
  234. of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
  235. result.sons[0] = sc
  236. first = 1
  237. # We're not interested in the example code during this pass so let's
  238. # skip it
  239. if s.magic == mRunnableExamples:
  240. inc first
  241. of skGenericParam:
  242. result.sons[0] = newSymNodeTypeDesc(s, fn.info)
  243. onUse(fn.info, s)
  244. first = 1
  245. of skType:
  246. # bad hack for generics:
  247. if (s.typ != nil) and (s.typ.kind != tyGenericParam):
  248. result.sons[0] = newSymNodeTypeDesc(s, fn.info)
  249. onUse(fn.info, s)
  250. first = 1
  251. else:
  252. result.sons[0] = newSymNode(s, fn.info)
  253. onUse(fn.info, s)
  254. first = 1
  255. elif fn.kind == nkDotExpr:
  256. result.sons[0] = fuzzyLookup(c, fn, flags, ctx, mixinContext)
  257. first = 1
  258. # Consider 'when declared(globalsSlot): ThreadVarSetValue(globalsSlot, ...)'
  259. # in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
  260. # is not exported and yet the generic 'threadProcWrapper' works correctly.
  261. let flags = if mixinContext: flags+{withinMixin} else: flags
  262. for i in countup(first, sonsLen(result) - 1):
  263. result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
  264. of nkCurlyExpr:
  265. result = newNodeI(nkCall, n.info)
  266. result.add newIdentNode(getIdent(c.cache, "{}"), n.info)
  267. for i in 0 ..< n.len: result.add(n[i])
  268. result = semGenericStmt(c, result, flags, ctx)
  269. of nkBracketExpr:
  270. result = newNodeI(nkCall, n.info)
  271. result.add newIdentNode(getIdent(c.cache, "[]"), n.info)
  272. for i in 0 ..< n.len: result.add(n[i])
  273. withBracketExpr ctx, n.sons[0]:
  274. result = semGenericStmt(c, result, flags, ctx)
  275. of nkAsgn, nkFastAsgn:
  276. checkSonsLen(n, 2, c.config)
  277. let a = n.sons[0]
  278. let b = n.sons[1]
  279. let k = a.kind
  280. case k
  281. of nkCurlyExpr:
  282. result = newNodeI(nkCall, n.info)
  283. result.add newIdentNode(getIdent(c.cache, "{}="), n.info)
  284. for i in 0 ..< a.len: result.add(a[i])
  285. result.add(b)
  286. result = semGenericStmt(c, result, flags, ctx)
  287. of nkBracketExpr:
  288. result = newNodeI(nkCall, n.info)
  289. result.add newIdentNode(getIdent(c.cache, "[]="), n.info)
  290. for i in 0 ..< a.len: result.add(a[i])
  291. result.add(b)
  292. withBracketExpr ctx, a.sons[0]:
  293. result = semGenericStmt(c, result, flags, ctx)
  294. else:
  295. for i in countup(0, sonsLen(n) - 1):
  296. result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  297. of nkIfStmt:
  298. for i in countup(0, sonsLen(n)-1):
  299. n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
  300. of nkWhenStmt:
  301. for i in countup(0, sonsLen(n)-1):
  302. # bug #8603: conditions of 'when' statements are not
  303. # in a 'mixin' context:
  304. let it = n[i]
  305. if it.kind in {nkElifExpr, nkElifBranch}:
  306. n.sons[i].sons[0] = semGenericStmt(c, it[0], flags, ctx)
  307. n.sons[i].sons[1] = semGenericStmt(c, it[1], flags+{withinMixin}, ctx)
  308. else:
  309. n.sons[i] = semGenericStmt(c, it, flags+{withinMixin}, ctx)
  310. of nkWhileStmt:
  311. openScope(c)
  312. for i in countup(0, sonsLen(n)-1):
  313. n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  314. closeScope(c)
  315. of nkCaseStmt:
  316. openScope(c)
  317. n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
  318. for i in countup(1, sonsLen(n)-1):
  319. var a = n.sons[i]
  320. checkMinSonsLen(a, 1, c.config)
  321. var L = sonsLen(a)
  322. for j in countup(0, L-2):
  323. a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx)
  324. a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
  325. closeScope(c)
  326. of nkForStmt, nkParForStmt:
  327. var L = sonsLen(n)
  328. openScope(c)
  329. n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
  330. for i in countup(0, L - 3):
  331. addTempDecl(c, n.sons[i], skForVar)
  332. openScope(c)
  333. n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
  334. closeScope(c)
  335. closeScope(c)
  336. of nkBlockStmt, nkBlockExpr, nkBlockType:
  337. checkSonsLen(n, 2, c.config)
  338. openScope(c)
  339. if n.sons[0].kind != nkEmpty:
  340. addTempDecl(c, n.sons[0], skLabel)
  341. n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
  342. closeScope(c)
  343. of nkTryStmt:
  344. checkMinSonsLen(n, 2, c.config)
  345. n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx)
  346. for i in countup(1, sonsLen(n)-1):
  347. var a = n.sons[i]
  348. checkMinSonsLen(a, 1, c.config)
  349. var L = sonsLen(a)
  350. openScope(c)
  351. for j in countup(0, L-2):
  352. if a.sons[j].isInfixAs():
  353. addTempDecl(c, getIdentNode(c, a.sons[j][2]), skLet)
  354. a.sons[j].sons[1] = semGenericStmt(c, a.sons[j][1], flags+{withinTypeDesc}, ctx)
  355. else:
  356. a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx)
  357. a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
  358. closeScope(c)
  359. of nkVarSection, nkLetSection:
  360. for i in countup(0, sonsLen(n) - 1):
  361. var a = n.sons[i]
  362. if a.kind == nkCommentStmt: continue
  363. if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.config)
  364. checkMinSonsLen(a, 3, c.config)
  365. var L = sonsLen(a)
  366. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  367. a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
  368. for j in countup(0, L-3):
  369. addTempDecl(c, getIdentNode(c, a.sons[j]), skVar)
  370. of nkGenericParams:
  371. for i in countup(0, sonsLen(n) - 1):
  372. var a = n.sons[i]
  373. if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
  374. checkMinSonsLen(a, 3, c.config)
  375. var L = sonsLen(a)
  376. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  377. # do not perform symbol lookup for default expressions
  378. for j in countup(0, L-3):
  379. addTempDecl(c, getIdentNode(c, a.sons[j]), skType)
  380. of nkConstSection:
  381. for i in countup(0, sonsLen(n) - 1):
  382. var a = n.sons[i]
  383. if a.kind == nkCommentStmt: continue
  384. if (a.kind != nkConstDef): illFormedAst(a, c.config)
  385. checkSonsLen(a, 3, c.config)
  386. addTempDecl(c, getIdentNode(c, a.sons[0]), skConst)
  387. a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
  388. a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx)
  389. of nkTypeSection:
  390. for i in countup(0, sonsLen(n) - 1):
  391. var a = n.sons[i]
  392. if a.kind == nkCommentStmt: continue
  393. if (a.kind != nkTypeDef): illFormedAst(a, c.config)
  394. checkSonsLen(a, 3, c.config)
  395. addTempDecl(c, getIdentNode(c, a.sons[0]), skType)
  396. for i in countup(0, sonsLen(n) - 1):
  397. var a = n.sons[i]
  398. if a.kind == nkCommentStmt: continue
  399. if (a.kind != nkTypeDef): illFormedAst(a, c.config)
  400. checkSonsLen(a, 3, c.config)
  401. if a.sons[1].kind != nkEmpty:
  402. openScope(c)
  403. a.sons[1] = semGenericStmt(c, a.sons[1], flags, ctx)
  404. a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
  405. closeScope(c)
  406. else:
  407. a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
  408. of nkEnumTy:
  409. if n.sonsLen > 0:
  410. if n.sons[0].kind != nkEmpty:
  411. n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
  412. for i in countup(1, sonsLen(n) - 1):
  413. var a: PNode
  414. case n.sons[i].kind
  415. of nkEnumFieldDef: a = n.sons[i].sons[0]
  416. of nkIdent: a = n.sons[i]
  417. else: illFormedAst(n, c.config)
  418. addDecl(c, newSymS(skUnknown, getIdentNode(c, a), c))
  419. of nkObjectTy, nkTupleTy, nkTupleClassTy:
  420. discard
  421. of nkFormalParams:
  422. checkMinSonsLen(n, 1, c.config)
  423. if n.sons[0].kind != nkEmpty:
  424. n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
  425. for i in countup(1, sonsLen(n) - 1):
  426. var a = n.sons[i]
  427. if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
  428. checkMinSonsLen(a, 3, c.config)
  429. var L = sonsLen(a)
  430. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  431. a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
  432. for j in countup(0, L-3):
  433. addTempDecl(c, getIdentNode(c, a.sons[j]), skParam)
  434. of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
  435. nkFuncDef, nkIteratorDef, nkLambdaKinds:
  436. checkSonsLen(n, bodyPos + 1, c.config)
  437. if n.sons[namePos].kind != nkEmpty:
  438. addTempDecl(c, getIdentNode(c, n.sons[0]), skProc)
  439. openScope(c)
  440. n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos],
  441. flags, ctx)
  442. if n.sons[paramsPos].kind != nkEmpty:
  443. if n.sons[paramsPos].sons[0].kind != nkEmpty:
  444. addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nil, n.info))
  445. n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, ctx)
  446. n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, ctx)
  447. var body: PNode
  448. if n.sons[namePos].kind == nkSym:
  449. let s = n.sons[namePos].sym
  450. if sfGenSym in s.flags and s.ast == nil:
  451. body = n.sons[bodyPos]
  452. else:
  453. body = s.getBody
  454. else: body = n.sons[bodyPos]
  455. n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
  456. closeScope(c)
  457. of nkPragma, nkPragmaExpr: discard
  458. of nkExprColonExpr, nkExprEqExpr:
  459. checkMinSonsLen(n, 2, c.config)
  460. result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
  461. else:
  462. for i in countup(0, sonsLen(n) - 1):
  463. result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  464. when defined(nimsuggest):
  465. if withinTypeDesc in flags: dec c.inTypeContext
  466. proc semGenericStmt(c: PContext, n: PNode): PNode =
  467. var ctx: GenericCtx
  468. ctx.toMixin = initIntset()
  469. result = semGenericStmt(c, n, {}, ctx)
  470. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)
  471. proc semConceptBody(c: PContext, n: PNode): PNode =
  472. var ctx: GenericCtx
  473. ctx.toMixin = initIntset()
  474. result = semGenericStmt(c, n, {withinConcept}, ctx)
  475. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)