semgnrc.nim 19 KB

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