semgnrc.nim 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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[1])
  20. of nkPragmaExpr: result = getIdentNode(c, n[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, toBind: 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 isMixedIn(sym): bool =
  45. let s = sym
  46. s.name.id in ctx.toMixin or (withinConcept in flags and
  47. s.magic == mNone and
  48. s.kind in OverloadableSyms)
  49. proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
  50. ctx: var GenericCtx; flags: TSemGenericFlags,
  51. fromDotExpr=false): PNode =
  52. result = nil
  53. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  54. incl(s.flags, sfUsed)
  55. template maybeDotChoice(c: PContext, n: PNode, s: PSym, fromDotExpr: bool) =
  56. if fromDotExpr:
  57. result = symChoice(c, n, s, scForceOpen)
  58. if result.kind == nkOpenSymChoice and result.len == 1:
  59. result.transitionSonsKind(nkClosedSymChoice)
  60. else:
  61. result = symChoice(c, n, s, scOpen)
  62. case s.kind
  63. of skUnknown:
  64. # Introduced in this pass! Leave it as an identifier.
  65. result = n
  66. of skProc, skFunc, skMethod, skIterator, skConverter, skModule, skEnumField:
  67. maybeDotChoice(c, n, s, fromDotExpr)
  68. of skTemplate, skMacro:
  69. # alias syntax, see semSym for skTemplate, skMacro
  70. if sfNoalias notin s.flags and not fromDotExpr:
  71. onUse(n.info, s)
  72. case s.kind
  73. of skTemplate: result = semTemplateExpr(c, n, s, {efNoSemCheck})
  74. of skMacro: result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  75. else: discard # unreachable
  76. c.friendModules.add(s.owner.getModule)
  77. result = semGenericStmt(c, result, {}, ctx)
  78. discard c.friendModules.pop()
  79. else:
  80. maybeDotChoice(c, n, s, fromDotExpr)
  81. of skGenericParam:
  82. if s.typ != nil and s.typ.kind == tyStatic:
  83. if s.typ.n != nil:
  84. result = s.typ.n
  85. else:
  86. result = n
  87. else:
  88. result = newSymNodeTypeDesc(s, c.idgen, n.info)
  89. onUse(n.info, s)
  90. of skParam:
  91. result = n
  92. onUse(n.info, s)
  93. of skType:
  94. if (s.typ != nil) and
  95. (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
  96. result = newSymNodeTypeDesc(s, c.idgen, n.info)
  97. else:
  98. result = n
  99. onUse(n.info, s)
  100. else:
  101. result = newSymNode(s, n.info)
  102. onUse(n.info, s)
  103. proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  104. ctx: var GenericCtx): PNode =
  105. result = n
  106. let ident = considerQuotedIdent(c, n)
  107. var amb = false
  108. var s = searchInScopes(c, ident, amb)
  109. if s == nil:
  110. s = strTableGet(c.pureEnumFields, ident)
  111. #if s != nil and contains(c.ambiguousSymbols, s.id):
  112. # s = nil
  113. if s == nil:
  114. if ident.id notin ctx.toMixin and withinMixin notin flags:
  115. errorUndeclaredIdentifier(c, n.info, ident.s)
  116. else:
  117. if withinBind in flags or s.id in ctx.toBind:
  118. result = symChoice(c, n, s, scClosed)
  119. elif s.isMixedIn:
  120. result = symChoice(c, n, s, scForceOpen)
  121. else:
  122. result = semGenericStmtSymbol(c, n, s, ctx, flags)
  123. # else: leave as nkIdent
  124. proc newDot(n, b: PNode): PNode =
  125. result = newNodeI(nkDotExpr, n.info)
  126. result.add(n[0])
  127. result.add(b)
  128. proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  129. ctx: var GenericCtx; isMacro: var bool;
  130. inCall = false): PNode =
  131. assert n.kind == nkDotExpr
  132. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  133. let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule}
  134. var s = qualifiedLookUp(c, n, luf)
  135. if s != nil:
  136. result = semGenericStmtSymbol(c, n, s, ctx, flags)
  137. else:
  138. n[0] = semGenericStmt(c, n[0], flags, ctx)
  139. result = n
  140. let n = n[1]
  141. let ident = considerQuotedIdent(c, n)
  142. # could be type conversion if like a.T and not a.T()
  143. let symKinds = if inCall: routineKinds else: routineKinds+{skType}
  144. var candidates = searchInScopesFilterBy(c, ident, symKinds)
  145. if candidates.len > 0:
  146. let s = candidates[0] # XXX take into account the other candidates!
  147. isMacro = s.kind in {skTemplate, skMacro}
  148. if withinBind in flags or s.id in ctx.toBind:
  149. if s.kind == skType: # don't put types in sym choice
  150. result = newDot(result, semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true))
  151. else:
  152. result = newDot(result, symChoice(c, n, s, scClosed))
  153. elif s.isMixedIn:
  154. result = newDot(result, symChoice(c, n, s, scForceOpen))
  155. else:
  156. if s.kind == skType and candidates.len > 1:
  157. var ambig = false
  158. let s2 = searchInScopes(c, ident, ambig)
  159. if ambig:
  160. # this is a type conversion like a.T where T is ambiguous with
  161. # other types or routines
  162. # in regular code, this never considers a type conversion and
  163. # skips to routine overloading
  164. # so symchoices are used which behave similarly with type symbols
  165. result = newDot(result, symChoice(c, n, s, scForceOpen))
  166. return
  167. let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
  168. result = newDot(result, syms)
  169. proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
  170. let s = newSymS(skUnknown, getIdentNode(c, n), c)
  171. addPrelimDecl(c, s)
  172. styleCheckDef(c, n.info, s, kind)
  173. onDef(n.info, s)
  174. proc semGenericStmt(c: PContext, n: PNode,
  175. flags: TSemGenericFlags, ctx: var GenericCtx): PNode =
  176. result = n
  177. when defined(nimsuggest):
  178. if withinTypeDesc in flags: inc c.inTypeContext
  179. #if conf.cmd == cmdIdeTools: suggestStmt(c, n)
  180. semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
  181. case n.kind
  182. of nkIdent, nkAccQuoted:
  183. result = lookup(c, n, flags, ctx)
  184. if result != nil and result.kind == nkSym:
  185. assert result.sym != nil
  186. markUsed(c, n.info, result.sym)
  187. of nkDotExpr:
  188. #let luf = if withinMixin notin flags: {checkUndeclared} else: {}
  189. #var s = qualifiedLookUp(c, n, luf)
  190. #if s != nil: result = semGenericStmtSymbol(c, n, s)
  191. # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
  192. var dummy: bool
  193. result = fuzzyLookup(c, n, flags, ctx, dummy)
  194. of nkSym:
  195. let a = n.sym
  196. let b = getGenSym(c, a)
  197. if b != a: n.sym = b
  198. of nkEmpty, succ(nkSym)..nkNilLit, nkComesFrom:
  199. # see tests/compile/tgensymgeneric.nim:
  200. # We need to open the gensym'ed symbol again so that the instantiation
  201. # creates a fresh copy; but this is wrong the very first reason for gensym
  202. # is that scope rules cannot be used! So simply removing 'sfGenSym' does
  203. # not work. Copying the symbol does not work either because we're already
  204. # the owner of the symbol! What we need to do is to copy the symbol
  205. # in the generic instantiation process...
  206. discard
  207. of nkBind:
  208. result = semGenericStmt(c, n[0], flags+{withinBind}, ctx)
  209. of nkMixinStmt:
  210. result = semMixinStmt(c, n, ctx.toMixin)
  211. of nkBindStmt:
  212. result = semBindStmt(c, n, ctx.toBind)
  213. of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit:
  214. # check if it is an expression macro:
  215. checkMinSonsLen(n, 1, c.config)
  216. let fn = n[0]
  217. var s = qualifiedLookUp(c, fn, {})
  218. if s == nil and
  219. {withinMixin, withinConcept}*flags == {} and
  220. fn.kind in {nkIdent, nkAccQuoted} and
  221. considerQuotedIdent(c, fn).id notin ctx.toMixin:
  222. errorUndeclaredIdentifier(c, n.info, fn.renderTree)
  223. var first = int ord(withinConcept in flags)
  224. var mixinContext = false
  225. if s != nil:
  226. incl(s.flags, sfUsed)
  227. mixinContext = s.magic in {mDefined, mDeclared, mDeclaredInScope, mCompiles, mAstToStr}
  228. let whichChoice = if s.id in ctx.toBind: scClosed
  229. elif s.isMixedIn: scForceOpen
  230. else: scOpen
  231. let sc = symChoice(c, fn, s, whichChoice)
  232. case s.kind
  233. of skMacro, skTemplate:
  234. # unambiguous macros/templates are expanded if all params are untyped
  235. if sfAllUntyped in s.flags and sc.safeLen <= 1:
  236. onUse(fn.info, s)
  237. case s.kind
  238. of skMacro: result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  239. of skTemplate: result = semTemplateExpr(c, n, s, {efNoSemCheck})
  240. else: discard # unreachable
  241. c.friendModules.add(s.owner.getModule)
  242. result = semGenericStmt(c, result, flags, ctx)
  243. discard c.friendModules.pop()
  244. else:
  245. n[0] = sc
  246. result = n
  247. # BUGFIX: we must not return here, we need to do first phase of
  248. # symbol lookup. Also since templates and macros can do scope injections
  249. # we need to put the ``c`` in ``t(c)`` in a mixin context to prevent
  250. # the famous "undeclared identifier: it" bug:
  251. mixinContext = true
  252. of skUnknown, skParam:
  253. # Leave it as an identifier.
  254. discard
  255. of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
  256. result[0] = sc
  257. first = 1
  258. # We're not interested in the example code during this pass so let's
  259. # skip it
  260. if s.magic == mRunnableExamples:
  261. first = result.safeLen # see trunnableexamples.fun3
  262. of skGenericParam:
  263. result[0] = newSymNodeTypeDesc(s, c.idgen, fn.info)
  264. onUse(fn.info, s)
  265. first = 1
  266. of skType:
  267. # bad hack for generics:
  268. if (s.typ != nil) and (s.typ.kind != tyGenericParam):
  269. result[0] = newSymNodeTypeDesc(s, c.idgen, fn.info)
  270. onUse(fn.info, s)
  271. first = 1
  272. else:
  273. result[0] = newSymNode(s, fn.info)
  274. onUse(fn.info, s)
  275. first = 1
  276. elif fn.kind == nkDotExpr:
  277. result[0] = fuzzyLookup(c, fn, flags, ctx, mixinContext, inCall = true)
  278. first = 1
  279. # Consider 'when declared(globalsSlot): ThreadVarSetValue(globalsSlot, ...)'
  280. # in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
  281. # is not exported and yet the generic 'threadProcWrapper' works correctly.
  282. let flags = if mixinContext: flags+{withinMixin} else: flags
  283. for i in first..<result.safeLen:
  284. result[i] = semGenericStmt(c, result[i], flags, ctx)
  285. of nkCurlyExpr:
  286. result = newNodeI(nkCall, n.info)
  287. result.add newIdentNode(getIdent(c.cache, "{}"), n.info)
  288. for i in 0..<n.len: result.add(n[i])
  289. result = semGenericStmt(c, result, flags, ctx)
  290. of nkBracketExpr:
  291. result = newNodeI(nkCall, n.info)
  292. result.add newIdentNode(getIdent(c.cache, "[]"), n.info)
  293. for i in 0..<n.len: result.add(n[i])
  294. result = semGenericStmt(c, result, flags, ctx)
  295. of nkAsgn, nkFastAsgn, nkSinkAsgn:
  296. checkSonsLen(n, 2, c.config)
  297. let a = n[0]
  298. let b = n[1]
  299. let k = a.kind
  300. case k
  301. of nkCurlyExpr:
  302. result = newNodeI(nkCall, n.info)
  303. result.add newIdentNode(getIdent(c.cache, "{}="), n.info)
  304. for i in 0..<a.len: result.add(a[i])
  305. result.add(b)
  306. result = semGenericStmt(c, result, flags, ctx)
  307. of nkBracketExpr:
  308. result = newNodeI(nkCall, n.info)
  309. result.add newIdentNode(getIdent(c.cache, "[]="), n.info)
  310. for i in 0..<a.len: result.add(a[i])
  311. result.add(b)
  312. result = semGenericStmt(c, result, flags, ctx)
  313. else:
  314. for i in 0..<n.len:
  315. result[i] = semGenericStmt(c, n[i], flags, ctx)
  316. of nkIfStmt:
  317. for i in 0..<n.len:
  318. n[i] = semGenericStmtScope(c, n[i], flags, ctx)
  319. of nkWhenStmt:
  320. for i in 0..<n.len:
  321. # bug #8603: conditions of 'when' statements are not
  322. # in a 'mixin' context:
  323. let it = n[i]
  324. if it.kind in {nkElifExpr, nkElifBranch}:
  325. n[i][0] = semGenericStmt(c, it[0], flags, ctx)
  326. n[i][1] = semGenericStmt(c, it[1], flags+{withinMixin}, ctx)
  327. else:
  328. n[i] = semGenericStmt(c, it, flags+{withinMixin}, ctx)
  329. of nkWhileStmt:
  330. openScope(c)
  331. for i in 0..<n.len:
  332. n[i] = semGenericStmt(c, n[i], flags, ctx)
  333. closeScope(c)
  334. of nkCaseStmt:
  335. openScope(c)
  336. n[0] = semGenericStmt(c, n[0], flags, ctx)
  337. for i in 1..<n.len:
  338. var a = n[i]
  339. checkMinSonsLen(a, 1, c.config)
  340. for j in 0..<a.len-1:
  341. a[j] = semGenericStmt(c, a[j], flags, ctx)
  342. a[^1] = semGenericStmtScope(c, a[^1], flags, ctx)
  343. closeScope(c)
  344. of nkForStmt, nkParForStmt:
  345. openScope(c)
  346. n[^2] = semGenericStmt(c, n[^2], flags, ctx)
  347. for i in 0..<n.len - 2:
  348. if (n[i].kind == nkVarTuple):
  349. for s in n[i]:
  350. if (s.kind == nkIdent):
  351. addTempDecl(c,s,skForVar)
  352. else:
  353. addTempDecl(c, n[i], skForVar)
  354. openScope(c)
  355. n[^1] = semGenericStmt(c, n[^1], flags, ctx)
  356. closeScope(c)
  357. closeScope(c)
  358. of nkBlockStmt, nkBlockExpr, nkBlockType:
  359. checkSonsLen(n, 2, c.config)
  360. openScope(c)
  361. if n[0].kind != nkEmpty:
  362. addTempDecl(c, n[0], skLabel)
  363. n[1] = semGenericStmt(c, n[1], flags, ctx)
  364. closeScope(c)
  365. of nkTryStmt, nkHiddenTryStmt:
  366. checkMinSonsLen(n, 2, c.config)
  367. n[0] = semGenericStmtScope(c, n[0], flags, ctx)
  368. for i in 1..<n.len:
  369. var a = n[i]
  370. checkMinSonsLen(a, 1, c.config)
  371. openScope(c)
  372. for j in 0..<a.len-1:
  373. if a[j].isInfixAs():
  374. addTempDecl(c, getIdentNode(c, a[j][2]), skLet)
  375. a[j][1] = semGenericStmt(c, a[j][1], flags+{withinTypeDesc}, ctx)
  376. else:
  377. a[j] = semGenericStmt(c, a[j], flags+{withinTypeDesc}, ctx)
  378. a[^1] = semGenericStmtScope(c, a[^1], flags, ctx)
  379. closeScope(c)
  380. of nkVarSection, nkLetSection, nkConstSection:
  381. let varKind =
  382. case n.kind
  383. of nkVarSection: skVar
  384. of nkLetSection: skLet
  385. else: skConst
  386. for i in 0..<n.len:
  387. var a = n[i]
  388. case a.kind:
  389. of nkCommentStmt: continue
  390. of nkIdentDefs, nkVarTuple, nkConstDef:
  391. checkMinSonsLen(a, 3, c.config)
  392. a[^2] = semGenericStmt(c, a[^2], flags+{withinTypeDesc}, ctx)
  393. a[^1] = semGenericStmt(c, a[^1], flags, ctx)
  394. for j in 0..<a.len-2:
  395. addTempDecl(c, getIdentNode(c, a[j]), varKind)
  396. else:
  397. illFormedAst(a, c.config)
  398. of nkGenericParams:
  399. for i in 0..<n.len:
  400. var a = n[i]
  401. if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
  402. checkMinSonsLen(a, 3, c.config)
  403. a[^2] = semGenericStmt(c, a[^2], flags+{withinTypeDesc}, ctx)
  404. # do not perform symbol lookup for default expressions
  405. for j in 0..<a.len-2:
  406. addTempDecl(c, getIdentNode(c, a[j]), skType)
  407. of nkTypeSection:
  408. for i in 0..<n.len:
  409. var a = n[i]
  410. if a.kind == nkCommentStmt: continue
  411. if (a.kind != nkTypeDef): illFormedAst(a, c.config)
  412. checkSonsLen(a, 3, c.config)
  413. addTempDecl(c, getIdentNode(c, a[0]), skType)
  414. for i in 0..<n.len:
  415. var a = n[i]
  416. if a.kind == nkCommentStmt: continue
  417. if (a.kind != nkTypeDef): illFormedAst(a, c.config)
  418. checkSonsLen(a, 3, c.config)
  419. if a[1].kind != nkEmpty:
  420. openScope(c)
  421. a[1] = semGenericStmt(c, a[1], flags, ctx)
  422. a[2] = semGenericStmt(c, a[2], flags+{withinTypeDesc}, ctx)
  423. closeScope(c)
  424. else:
  425. a[2] = semGenericStmt(c, a[2], flags+{withinTypeDesc}, ctx)
  426. of nkEnumTy:
  427. if n.len > 0:
  428. if n[0].kind != nkEmpty:
  429. n[0] = semGenericStmt(c, n[0], flags+{withinTypeDesc}, ctx)
  430. for i in 1..<n.len:
  431. var a: PNode = nil
  432. case n[i].kind
  433. of nkEnumFieldDef: a = n[i][0]
  434. of nkIdent: a = n[i]
  435. else: illFormedAst(n, c.config)
  436. addDecl(c, newSymS(skUnknown, getIdentNode(c, a), c))
  437. of nkObjectTy, nkTupleTy, nkTupleClassTy:
  438. discard
  439. of nkFormalParams:
  440. checkMinSonsLen(n, 1, c.config)
  441. for i in 1..<n.len:
  442. var a = n[i]
  443. if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
  444. checkMinSonsLen(a, 3, c.config)
  445. a[^2] = semGenericStmt(c, a[^2], flags+{withinTypeDesc}, ctx)
  446. a[^1] = semGenericStmt(c, a[^1], flags, ctx)
  447. for j in 0..<a.len-2:
  448. addTempDecl(c, getIdentNode(c, a[j]), skParam)
  449. # XXX: last change was moving this down here, search for "1.." to keep
  450. # going from this file onward
  451. if n[0].kind != nkEmpty:
  452. n[0] = semGenericStmt(c, n[0], flags+{withinTypeDesc}, ctx)
  453. of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
  454. nkFuncDef, nkIteratorDef, nkLambdaKinds:
  455. checkSonsLen(n, bodyPos + 1, c.config)
  456. if n[namePos].kind != nkEmpty:
  457. addTempDecl(c, getIdentNode(c, n[0]), skProc)
  458. openScope(c)
  459. n[genericParamsPos] = semGenericStmt(c, n[genericParamsPos],
  460. flags, ctx)
  461. if n[paramsPos].kind != nkEmpty:
  462. if n[paramsPos][0].kind != nkEmpty:
  463. addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), c.idgen, nil, n.info))
  464. n[paramsPos] = semGenericStmt(c, n[paramsPos], flags, ctx)
  465. n[pragmasPos] = semGenericStmt(c, n[pragmasPos], flags, ctx)
  466. var body: PNode
  467. if n[namePos].kind == nkSym:
  468. let s = n[namePos].sym
  469. if sfGenSym in s.flags and s.ast == nil:
  470. body = n[bodyPos]
  471. else:
  472. body = getBody(c.graph, s)
  473. else: body = n[bodyPos]
  474. n[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
  475. closeScope(c)
  476. of nkPragma, nkPragmaExpr: discard
  477. of nkExprColonExpr, nkExprEqExpr:
  478. checkMinSonsLen(n, 2, c.config)
  479. result[1] = semGenericStmt(c, n[1], flags, ctx)
  480. of nkObjConstr:
  481. for i in 0..<n.len:
  482. result[i] = semGenericStmt(c, n[i], flags, ctx)
  483. if result[0].kind == nkSym:
  484. let fmoduleId = getModule(result[0].sym).id
  485. var isVisable = false
  486. for module in c.friendModules:
  487. if module.id == fmoduleId:
  488. isVisable = true
  489. break
  490. if isVisable:
  491. for i in 1..<result.len:
  492. if result[i].kind == nkExprColonExpr:
  493. result[i][1].flags.incl nfSkipFieldChecking
  494. else:
  495. for i in 0..<n.len:
  496. result[i] = semGenericStmt(c, n[i], flags, ctx)
  497. when defined(nimsuggest):
  498. if withinTypeDesc in flags: dec c.inTypeContext
  499. proc semGenericStmt(c: PContext, n: PNode): PNode =
  500. var ctx: GenericCtx
  501. ctx.toMixin = initIntSet()
  502. ctx.toBind = initIntSet()
  503. result = semGenericStmt(c, n, {}, ctx)
  504. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)
  505. proc semConceptBody(c: PContext, n: PNode): PNode =
  506. var ctx: GenericCtx
  507. ctx.toMixin = initIntSet()
  508. ctx.toBind = initIntSet()
  509. result = semGenericStmt(c, n, {withinConcept}, ctx)
  510. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)