semgnrc.nim 24 KB

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