semgnrc.nim 22 KB

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