semtempl.nim 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  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. # included from sem.nim
  10. discard """
  11. hygienic templates:
  12. template `||` (a, b: untyped): untyped =
  13. let aa = a
  14. if aa: aa else: b
  15. var
  16. a, b: T
  17. echo a || b || a
  18. Each evaluation context has to be different and we need to perform
  19. some form of preliminary symbol lookup in template definitions. Hygiene is
  20. a way to achieve lexical scoping at compile time.
  21. """
  22. const
  23. errImplOfXNotAllowed = "implementation of '$1' is not allowed"
  24. type
  25. TSymBinding = enum
  26. spNone, spGenSym, spInject
  27. proc symBinding(n: PNode): TSymBinding =
  28. result = spNone
  29. for i in 0..<n.len:
  30. var it = n[i]
  31. var key = if it.kind == nkExprColonExpr: it[0] else: it
  32. if key.kind == nkIdent:
  33. case whichKeyword(key.ident)
  34. of wGensym: return spGenSym
  35. of wInject: return spInject
  36. else: discard
  37. type
  38. TSymChoiceRule = enum
  39. scClosed, scOpen, scForceOpen
  40. proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
  41. isField = false): PNode =
  42. var
  43. a: PSym
  44. o: TOverloadIter = default(TOverloadIter)
  45. var i = 0
  46. a = initOverloadIter(o, c, n)
  47. while a != nil:
  48. if a.kind != skModule:
  49. inc(i)
  50. if i > 1: break
  51. a = nextOverloadIter(o, c, n)
  52. let info = getCallLineInfo(n)
  53. if i <= 1 and r != scForceOpen:
  54. # XXX this makes more sense but breaks bootstrapping for now:
  55. # (s.kind notin routineKinds or s.magic != mNone):
  56. # for instance 'nextTry' is both in tables.nim and astalgo.nim ...
  57. if not isField or sfGenSym notin s.flags:
  58. result = newSymNode(s, info)
  59. markUsed(c, info, s)
  60. onUse(info, s)
  61. else:
  62. result = n
  63. elif i == 0:
  64. # forced open but symbol not in scope, retain information
  65. result = n
  66. else:
  67. # semantic checking requires a type; ``fitNode`` deals with it
  68. # appropriately
  69. let kind = if r == scClosed or n.kind == nkDotExpr: nkClosedSymChoice
  70. else: nkOpenSymChoice
  71. result = newNodeIT(kind, info, newTypeS(tyNone, c))
  72. a = initOverloadIter(o, c, n)
  73. while a != nil:
  74. if a.kind != skModule and (not isField or sfGenSym notin a.flags):
  75. incl(a.flags, sfUsed)
  76. markOwnerModuleAsUsed(c, a)
  77. result.add newSymNode(a, info)
  78. onUse(info, a)
  79. a = nextOverloadIter(o, c, n)
  80. proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
  81. result = copyNode(n)
  82. for i in 0..<n.len:
  83. var a = n[i]
  84. # If 'a' is an overloaded symbol, we used to use the first symbol
  85. # as a 'witness' and use the fact that subsequent lookups will yield
  86. # the same symbol!
  87. # This is however not true anymore for hygienic templates as semantic
  88. # processing for them changes the symbol table...
  89. let s = qualifiedLookUp(c, a, {checkUndeclared})
  90. if s != nil:
  91. # we need to mark all symbols:
  92. let sc = symChoice(c, n, s, scClosed)
  93. if sc.kind == nkSym:
  94. toBind.incl(sc.sym.id)
  95. result.add sc
  96. else:
  97. for x in items(sc):
  98. toBind.incl(x.sym.id)
  99. result.add x
  100. else:
  101. illFormedAst(a, c.config)
  102. proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
  103. result = copyNode(n)
  104. for i in 0..<n.len:
  105. toMixin.incl(considerQuotedIdent(c, n[i]).id)
  106. let x = symChoice(c, n[i], nil, scForceOpen)
  107. result.add x
  108. proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
  109. case n.kind
  110. of nkPostfix: replaceIdentBySym(c, n[1], s)
  111. of nkPragmaExpr: replaceIdentBySym(c, n[0], s)
  112. of nkIdent, nkAccQuoted, nkSym: n = s
  113. else: illFormedAst(n, c.config)
  114. type
  115. TemplCtx = object
  116. c: PContext
  117. toBind, toMixin, toInject: IntSet
  118. owner: PSym
  119. cursorInBody: bool # only for nimsuggest
  120. scopeN: int
  121. noGenSym: int
  122. inTemplateHeader: int
  123. proc isTemplParam(c: TemplCtx, s: PSym): bool {.inline.} =
  124. result = s.kind == skParam and
  125. s.owner == c.owner and sfTemplateParam in s.flags
  126. proc getIdentReplaceParams(c: var TemplCtx, n: var PNode): tuple[node: PNode, hasParam: bool] =
  127. case n.kind
  128. of nkPostfix: result = getIdentReplaceParams(c, n[1])
  129. of nkPragmaExpr: result = getIdentReplaceParams(c, n[0])
  130. of nkIdent:
  131. result = (n, false)
  132. let s = qualifiedLookUp(c.c, n, {})
  133. if s != nil and isTemplParam(c, s):
  134. n = newSymNode(s, n.info)
  135. result = (n, true)
  136. of nkSym:
  137. result = (n, isTemplParam(c, n.sym))
  138. of nkAccQuoted:
  139. result = (n, false)
  140. for i in 0..<n.safeLen:
  141. let (ident, hasParam) = getIdentReplaceParams(c, n[i])
  142. if hasParam:
  143. result.node[i] = ident
  144. result.hasParam = true
  145. else:
  146. illFormedAst(n, c.c.config)
  147. result = (n, false)
  148. proc semTemplBody(c: var TemplCtx, n: PNode): PNode
  149. proc openScope(c: var TemplCtx) =
  150. openScope(c.c)
  151. proc closeScope(c: var TemplCtx) =
  152. closeScope(c.c)
  153. proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
  154. openScope(c)
  155. result = semTemplBody(c, n)
  156. closeScope(c)
  157. proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
  158. result = newSym(kind, considerQuotedIdent(c.c, n), c.c.idgen, c.owner, n.info)
  159. incl(result.flags, sfGenSym)
  160. incl(result.flags, sfShadowed)
  161. proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
  162. # locals default to 'gensym', fields default to 'inject':
  163. if (n.kind == nkPragmaExpr and symBinding(n[1]) == spInject) or
  164. k == skField:
  165. # even if injected, don't produce a sym choice here:
  166. #n = semTemplBody(c, n)
  167. let (ident, hasParam) = getIdentReplaceParams(c, n)
  168. if not hasParam:
  169. if k != skField:
  170. c.toInject.incl(considerQuotedIdent(c.c, ident).id)
  171. else:
  172. if (n.kind == nkPragmaExpr and n.len >= 2 and n[1].kind == nkPragma):
  173. let pragmaNode = n[1]
  174. for i in 0..<pragmaNode.len:
  175. let ni = pragmaNode[i]
  176. # see D20210801T100514
  177. var found = false
  178. if ni.kind == nkIdent:
  179. for a in templatePragmas:
  180. if ni.ident.id == ord(a):
  181. found = true
  182. break
  183. if not found:
  184. openScope(c)
  185. pragmaNode[i] = semTemplBody(c, pragmaNode[i])
  186. closeScope(c)
  187. let (ident, hasParam) = getIdentReplaceParams(c, n)
  188. if not hasParam:
  189. if n.kind != nkSym and not (n.kind == nkIdent and n.ident.id == ord(wUnderscore)):
  190. let local = newGenSym(k, ident, c)
  191. addPrelimDecl(c.c, local)
  192. styleCheckDef(c.c, n.info, local)
  193. onDef(n.info, local)
  194. replaceIdentBySym(c.c, n, newSymNode(local, n.info))
  195. if k == skParam and c.inTemplateHeader > 0:
  196. local.flags.incl sfTemplateParam
  197. proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bool): PNode =
  198. incl(s.flags, sfUsed)
  199. # bug #12885; ideally sem'checking is performed again afterwards marking
  200. # the symbol as used properly, but the nfSem mechanism currently prevents
  201. # that from happening, so we mark the module as used here already:
  202. markOwnerModuleAsUsed(c.c, s)
  203. # we do not call onUse here, as the identifier is not really
  204. # resolved here. We will fixup the used identifiers later.
  205. case s.kind
  206. of skUnknown:
  207. # Introduced in this pass! Leave it as an identifier.
  208. result = n
  209. of OverloadableSyms:
  210. result = symChoice(c.c, n, s, scOpen, isField)
  211. if not isField and result.kind in {nkSym, nkOpenSymChoice}:
  212. if {openSym, templateOpenSym} * c.c.features != {}:
  213. if result.kind == nkSym:
  214. result = newOpenSym(result)
  215. else:
  216. result.typ = nil
  217. else:
  218. result.flags.incl nfDisabledOpenSym
  219. result.typ = nil
  220. of skGenericParam:
  221. if isField and sfGenSym in s.flags: result = n
  222. else:
  223. result = newSymNodeTypeDesc(s, c.c.idgen, n.info)
  224. if not isField and s.owner != c.owner:
  225. if {openSym, templateOpenSym} * c.c.features != {}:
  226. result = newOpenSym(result)
  227. else:
  228. result.flags.incl nfDisabledOpenSym
  229. result.typ = nil
  230. of skParam:
  231. result = n
  232. of skType:
  233. if isField and sfGenSym in s.flags: result = n
  234. else:
  235. if isAmbiguous:
  236. # ambiguous types should be symchoices since lookup behaves
  237. # differently for them in regular expressions
  238. result = symChoice(c.c, n, s, scOpen, isField)
  239. else: result = newSymNodeTypeDesc(s, c.c.idgen, n.info)
  240. if not isField and not (s.owner == c.owner and
  241. s.typ != nil and s.typ.kind == tyGenericParam) and
  242. result.kind in {nkSym, nkOpenSymChoice}:
  243. if {openSym, templateOpenSym} * c.c.features != {}:
  244. if result.kind == nkSym:
  245. result = newOpenSym(result)
  246. else:
  247. result.typ = nil
  248. else:
  249. result.flags.incl nfDisabledOpenSym
  250. result.typ = nil
  251. else:
  252. if isField and sfGenSym in s.flags: result = n
  253. else:
  254. result = newSymNode(s, n.info)
  255. if not isField:
  256. if {openSym, templateOpenSym} * c.c.features != {}:
  257. result = newOpenSym(result)
  258. else:
  259. result.flags.incl nfDisabledOpenSym
  260. result.typ = nil
  261. # Issue #12832
  262. when defined(nimsuggest):
  263. suggestSym(c.c.graph, n.info, s, c.c.graph.usageSym, false)
  264. # field access (dot expr) will be handled by builtinFieldAccess
  265. if not isField:
  266. styleCheckUse(c.c, n.info, s)
  267. proc semRoutineInTemplName(c: var TemplCtx, n: PNode, explicitInject: bool): PNode =
  268. result = n
  269. if n.kind == nkIdent:
  270. let s = qualifiedLookUp(c.c, n, {})
  271. if s != nil:
  272. if s.owner == c.owner and (s.kind == skParam or
  273. (sfGenSym in s.flags and not explicitInject)):
  274. incl(s.flags, sfUsed)
  275. result = newSymNode(s, n.info)
  276. onUse(n.info, s)
  277. else:
  278. for i in 0..<n.safeLen:
  279. result[i] = semRoutineInTemplName(c, n[i], explicitInject)
  280. proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
  281. result = n
  282. checkSonsLen(n, bodyPos + 1, c.c.config)
  283. if n.kind notin nkLambdaKinds:
  284. # routines default to 'inject':
  285. let binding = symBinding(n[pragmasPos])
  286. if binding == spGenSym:
  287. let (ident, hasParam) = getIdentReplaceParams(c, n[namePos])
  288. if not hasParam:
  289. var s = newGenSym(k, ident, c)
  290. s.ast = n
  291. addPrelimDecl(c.c, s)
  292. styleCheckDef(c.c, n.info, s)
  293. onDef(n.info, s)
  294. n[namePos] = newSymNode(s, n[namePos].info)
  295. else:
  296. n[namePos] = ident
  297. else:
  298. n[namePos] = semRoutineInTemplName(c, n[namePos], binding == spInject)
  299. # open scope for parameters
  300. openScope(c)
  301. for i in patternPos..paramsPos-1:
  302. n[i] = semTemplBody(c, n[i])
  303. if k == skTemplate: inc(c.inTemplateHeader)
  304. n[paramsPos] = semTemplBody(c, n[paramsPos])
  305. if k == skTemplate: dec(c.inTemplateHeader)
  306. for i in paramsPos+1..miscPos:
  307. n[i] = semTemplBody(c, n[i])
  308. # open scope for locals
  309. inc c.scopeN
  310. openScope(c)
  311. n[bodyPos] = semTemplBody(c, n[bodyPos])
  312. # close scope for locals
  313. closeScope(c)
  314. dec c.scopeN
  315. # close scope for parameters
  316. closeScope(c)
  317. proc semTemplIdentDef(c: var TemplCtx, a: PNode, symKind: TSymKind) =
  318. checkMinSonsLen(a, 3, c.c.config)
  319. when defined(nimsuggest):
  320. inc c.c.inTypeContext
  321. a[^2] = semTemplBody(c, a[^2])
  322. when defined(nimsuggest):
  323. dec c.c.inTypeContext
  324. a[^1] = semTemplBody(c, a[^1])
  325. for j in 0..<a.len-2:
  326. addLocalDecl(c, a[j], symKind)
  327. proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start = 0) =
  328. for i in start..<n.len:
  329. var a = n[i]
  330. case a.kind:
  331. of nkCommentStmt: continue
  332. of nkIdentDefs, nkVarTuple, nkConstDef:
  333. semTemplIdentDef(c, a, symKind)
  334. else:
  335. illFormedAst(a, c.c.config)
  336. proc semPattern(c: PContext, n: PNode; s: PSym): PNode
  337. proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
  338. result = n
  339. for i in 0..<n.len:
  340. result[i] = semTemplBody(c, n[i])
  341. proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
  342. result = n
  343. semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
  344. case n.kind
  345. of nkIdent:
  346. if n.ident.id in c.toInject: return n
  347. c.c.isAmbiguous = false
  348. let s = qualifiedLookUp(c.c, n, {})
  349. if s != nil:
  350. if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
  351. incl(s.flags, sfUsed)
  352. result = newSymNode(s, n.info)
  353. onUse(n.info, s)
  354. elif contains(c.toBind, s.id):
  355. result = symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
  356. elif contains(c.toMixin, s.name.id):
  357. result = symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
  358. elif s.owner == c.owner and sfGenSym in s.flags and c.noGenSym == 0:
  359. # template tmp[T](x: var seq[T]) =
  360. # var yz: T
  361. incl(s.flags, sfUsed)
  362. result = newSymNode(s, n.info)
  363. onUse(n.info, s)
  364. else:
  365. if s.kind in {skVar, skLet, skConst}:
  366. discard qualifiedLookUp(c.c, n, {checkAmbiguity, checkModule})
  367. result = semTemplSymbol(c, n, s, c.noGenSym > 0, c.c.isAmbiguous)
  368. of nkBind:
  369. result = semTemplBody(c, n[0])
  370. of nkBindStmt:
  371. result = semBindStmt(c.c, n, c.toBind)
  372. of nkMixinStmt:
  373. if c.scopeN > 0: result = semTemplBodySons(c, n)
  374. else: result = semMixinStmt(c.c, n, c.toMixin)
  375. of nkEmpty, nkSym..nkNilLit, nkComesFrom:
  376. discard
  377. of nkIfStmt:
  378. for i in 0..<n.len:
  379. var it = n[i]
  380. if it.len == 2:
  381. openScope(c)
  382. it[0] = semTemplBody(c, it[0])
  383. it[1] = semTemplBody(c, it[1])
  384. closeScope(c)
  385. else:
  386. n[i] = semTemplBodyScope(c, it)
  387. of nkWhileStmt:
  388. openScope(c)
  389. for i in 0..<n.len:
  390. n[i] = semTemplBody(c, n[i])
  391. closeScope(c)
  392. of nkCaseStmt:
  393. openScope(c)
  394. n[0] = semTemplBody(c, n[0])
  395. for i in 1..<n.len:
  396. var a = n[i]
  397. checkMinSonsLen(a, 1, c.c.config)
  398. for j in 0..<a.len-1:
  399. a[j] = semTemplBody(c, a[j])
  400. a[^1] = semTemplBodyScope(c, a[^1])
  401. closeScope(c)
  402. of nkForStmt, nkParForStmt:
  403. openScope(c)
  404. n[^2] = semTemplBody(c, n[^2])
  405. for i in 0..<n.len - 2:
  406. if n[i].kind == nkVarTuple:
  407. for j in 0..<n[i].len-1:
  408. addLocalDecl(c, n[i][j], skForVar)
  409. else:
  410. addLocalDecl(c, n[i], skForVar)
  411. openScope(c)
  412. n[^1] = semTemplBody(c, n[^1])
  413. closeScope(c)
  414. closeScope(c)
  415. of nkBlockStmt, nkBlockExpr, nkBlockType:
  416. checkSonsLen(n, 2, c.c.config)
  417. openScope(c)
  418. if n[0].kind != nkEmpty:
  419. addLocalDecl(c, n[0], skLabel)
  420. when false:
  421. # labels are always 'gensym'ed:
  422. let s = newGenSym(skLabel, n[0], c)
  423. addPrelimDecl(c.c, s)
  424. styleCheckDef(c.c, s)
  425. onDef(n[0].info, s)
  426. n[0] = newSymNode(s, n[0].info)
  427. n[1] = semTemplBody(c, n[1])
  428. closeScope(c)
  429. of nkTryStmt, nkHiddenTryStmt:
  430. checkMinSonsLen(n, 2, c.c.config)
  431. n[0] = semTemplBodyScope(c, n[0])
  432. for i in 1..<n.len:
  433. var a = n[i]
  434. checkMinSonsLen(a, 1, c.c.config)
  435. openScope(c)
  436. for j in 0..<a.len-1:
  437. if a[j].isInfixAs():
  438. addLocalDecl(c, a[j][2], skLet)
  439. a[j][1] = semTemplBody(c, a[j][1])
  440. else:
  441. a[j] = semTemplBody(c, a[j])
  442. a[^1] = semTemplBodyScope(c, a[^1])
  443. closeScope(c)
  444. of nkVarSection: semTemplSomeDecl(c, n, skVar)
  445. of nkLetSection: semTemplSomeDecl(c, n, skLet)
  446. of nkFormalParams:
  447. checkMinSonsLen(n, 1, c.c.config)
  448. semTemplSomeDecl(c, n, skParam, 1)
  449. n[0] = semTemplBody(c, n[0])
  450. of nkConstSection: semTemplSomeDecl(c, n, skConst)
  451. of nkTypeSection:
  452. for i in 0..<n.len:
  453. var a = n[i]
  454. if a.kind == nkCommentStmt: continue
  455. if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
  456. checkSonsLen(a, 3, c.c.config)
  457. addLocalDecl(c, a[0], skType)
  458. for i in 0..<n.len:
  459. var a = n[i]
  460. if a.kind == nkCommentStmt: continue
  461. if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
  462. checkSonsLen(a, 3, c.c.config)
  463. if a[1].kind != nkEmpty:
  464. openScope(c)
  465. a[1] = semTemplBody(c, a[1])
  466. a[2] = semTemplBody(c, a[2])
  467. closeScope(c)
  468. else:
  469. a[2] = semTemplBody(c, a[2])
  470. of nkObjectTy:
  471. openScope(c)
  472. result = semTemplBodySons(c, n)
  473. closeScope(c)
  474. of nkRecList:
  475. for i in 0..<n.len:
  476. var a = n[i]
  477. case a.kind:
  478. of nkCommentStmt, nkNilLit, nkSym, nkEmpty: continue
  479. of nkIdentDefs:
  480. semTemplIdentDef(c, a, skField)
  481. of nkRecCase, nkRecWhen:
  482. n[i] = semTemplBody(c, a)
  483. else:
  484. illFormedAst(a, c.c.config)
  485. of nkRecCase:
  486. semTemplIdentDef(c, n[0], skField)
  487. for i in 1..<n.len:
  488. n[i] = semTemplBody(c, n[i])
  489. of nkProcDef, nkLambdaKinds:
  490. result = semRoutineInTemplBody(c, n, skProc)
  491. of nkFuncDef:
  492. result = semRoutineInTemplBody(c, n, skFunc)
  493. of nkMethodDef:
  494. result = semRoutineInTemplBody(c, n, skMethod)
  495. of nkIteratorDef:
  496. result = semRoutineInTemplBody(c, n, skIterator)
  497. of nkTemplateDef:
  498. result = semRoutineInTemplBody(c, n, skTemplate)
  499. of nkMacroDef:
  500. result = semRoutineInTemplBody(c, n, skMacro)
  501. of nkConverterDef:
  502. result = semRoutineInTemplBody(c, n, skConverter)
  503. of nkPragmaExpr:
  504. result[0] = semTemplBody(c, n[0])
  505. of nkPostfix:
  506. result[1] = semTemplBody(c, n[1])
  507. of nkPragma:
  508. for x in n:
  509. if x.kind == nkExprColonExpr:
  510. x[1] = semTemplBody(c, x[1])
  511. of nkBracketExpr:
  512. if n.typ == nil:
  513. # if a[b] is nested inside a typed expression, don't convert it
  514. # back to `[]`(a, b), prepareOperand will not typecheck it again
  515. # and so `[]` will not be resolved
  516. # checking if a[b] is typed should be enough to cover this case
  517. result = newNodeI(nkCall, n.info)
  518. result.add newIdentNode(getIdent(c.c.cache, "[]"), n.info)
  519. for i in 0..<n.len: result.add(n[i])
  520. result = semTemplBodySons(c, result)
  521. of nkCurlyExpr:
  522. if n.typ == nil:
  523. # see nkBracketExpr case for explanation
  524. result = newNodeI(nkCall, n.info)
  525. result.add newIdentNode(getIdent(c.c.cache, "{}"), n.info)
  526. for i in 0..<n.len: result.add(n[i])
  527. result = semTemplBodySons(c, result)
  528. of nkAsgn, nkFastAsgn, nkSinkAsgn:
  529. checkSonsLen(n, 2, c.c.config)
  530. let a = n[0]
  531. let b = n[1]
  532. let k = a.kind
  533. case k
  534. of nkBracketExpr:
  535. if a.typ == nil:
  536. # see nkBracketExpr case above for explanation
  537. result = newNodeI(nkCall, n.info)
  538. result.add newIdentNode(getIdent(c.c.cache, "[]="), n.info)
  539. for i in 0..<a.len: result.add(a[i])
  540. result.add(b)
  541. let a0 = semTemplBody(c, a[0])
  542. result = semTemplBodySons(c, result)
  543. of nkCurlyExpr:
  544. if a.typ == nil:
  545. # see nkBracketExpr case above for explanation
  546. result = newNodeI(nkCall, n.info)
  547. result.add newIdentNode(getIdent(c.c.cache, "{}="), n.info)
  548. for i in 0..<a.len: result.add(a[i])
  549. result.add(b)
  550. result = semTemplBodySons(c, result)
  551. else:
  552. result = semTemplBodySons(c, n)
  553. of nkCallKinds-{nkPostfix}:
  554. # do not transform runnableExamples (bug #9143)
  555. if not isRunnableExamples(n[0]):
  556. result = semTemplBodySons(c, n)
  557. of nkDotExpr, nkAccQuoted:
  558. # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
  559. # so we use the generic code for nkDotExpr too
  560. c.c.isAmbiguous = false
  561. let s = qualifiedLookUp(c.c, n, {})
  562. if s != nil:
  563. # mirror the nkIdent case
  564. # do not symchoice a quoted template parameter (bug #2390):
  565. if s.owner == c.owner and s.kind == skParam and
  566. n.kind == nkAccQuoted and n.len == 1:
  567. incl(s.flags, sfUsed)
  568. onUse(n.info, s)
  569. return newSymNode(s, n.info)
  570. elif contains(c.toBind, s.id):
  571. return symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
  572. elif contains(c.toMixin, s.name.id):
  573. return symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
  574. else:
  575. if s.kind in {skVar, skLet, skConst}:
  576. discard qualifiedLookUp(c.c, n, {checkAmbiguity, checkModule})
  577. return semTemplSymbol(c, n, s, c.noGenSym > 0, c.c.isAmbiguous)
  578. if n.kind == nkDotExpr:
  579. result = n
  580. result[0] = semTemplBody(c, n[0])
  581. inc c.noGenSym
  582. result[1] = semTemplBody(c, n[1])
  583. dec c.noGenSym
  584. if result[1].kind == nkSym and result[1].sym.kind in routineKinds:
  585. # prevent `dotTransformation` from rewriting this node to `nkIdent`
  586. # by making it a symchoice
  587. # in generics this becomes `nkClosedSymChoice` but this breaks code
  588. # as the old behavior here was that this became `nkIdent`
  589. var choice = newNodeIT(nkOpenSymChoice, n[1].info, newTypeS(tyNone, c.c))
  590. choice.add result[1]
  591. result[1] = choice
  592. else:
  593. result = semTemplBodySons(c, n)
  594. of nkExprColonExpr, nkExprEqExpr:
  595. if n.len == 2:
  596. inc c.noGenSym
  597. result[0] = semTemplBody(c, n[0])
  598. dec c.noGenSym
  599. result[1] = semTemplBody(c, n[1])
  600. else:
  601. result = semTemplBodySons(c, n)
  602. of nkTableConstr:
  603. # also transform the keys (bug #12595)
  604. for i in 0..<n.len:
  605. result[i] = semTemplBodySons(c, n[i])
  606. else:
  607. result = semTemplBodySons(c, n)
  608. proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
  609. result = n
  610. semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
  611. case n.kind
  612. of nkIdent:
  613. let s = qualifiedLookUp(c.c, n, {})
  614. if s != nil:
  615. if s.owner == c.owner and s.kind == skParam:
  616. result = newSymNode(s, n.info)
  617. elif contains(c.toBind, s.id):
  618. result = symChoice(c.c, n, s, scClosed)
  619. of nkBind:
  620. result = semTemplBodyDirty(c, n[0])
  621. of nkBindStmt:
  622. result = semBindStmt(c.c, n, c.toBind)
  623. of nkEmpty, nkSym..nkNilLit, nkComesFrom:
  624. discard
  625. else:
  626. # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
  627. # so we use the generic code for nkDotExpr too
  628. if n.kind == nkDotExpr or n.kind == nkAccQuoted:
  629. let s = qualifiedLookUp(c.c, n, {})
  630. if s != nil and contains(c.toBind, s.id):
  631. return symChoice(c.c, n, s, scClosed)
  632. result = n
  633. for i in 0..<n.len:
  634. result[i] = semTemplBodyDirty(c, n[i])
  635. # in semstmts.nim:
  636. proc semProcAnnotation(c: PContext, prc: PNode; validPragmas: TSpecialWords): PNode
  637. proc semTemplateDef(c: PContext, n: PNode): PNode =
  638. result = semProcAnnotation(c, n, templatePragmas)
  639. if result != nil: return result
  640. result = n
  641. var s: PSym
  642. if isTopLevel(c):
  643. s = semIdentVis(c, skTemplate, n[namePos], {sfExported})
  644. incl(s.flags, sfGlobal)
  645. else:
  646. s = semIdentVis(c, skTemplate, n[namePos], {})
  647. assert s.kind == skTemplate
  648. styleCheckDef(c, s)
  649. onDef(n[namePos].info, s)
  650. # check parameter list:
  651. #s.scope = c.currentScope
  652. # push noalias flag at first to prevent unwanted recursive calls:
  653. incl(s.flags, sfNoalias)
  654. pushOwner(c, s)
  655. openScope(c)
  656. n[namePos] = newSymNode(s)
  657. pragmaCallable(c, s, n, templatePragmas)
  658. implicitPragmas(c, s, n.info, templatePragmas)
  659. setGenericParamsMisc(c, n)
  660. # process parameters:
  661. var allUntyped = true
  662. var nullary = true
  663. if n[paramsPos].kind != nkEmpty:
  664. semParamList(c, n[paramsPos], n[genericParamsPos], s)
  665. # a template's parameters are not gensym'ed even if that was originally the
  666. # case as we determine whether it's a template parameter in the template
  667. # body by the absence of the sfGenSym flag:
  668. let retType = s.typ.returnType
  669. if retType != nil and retType.kind != tyUntyped:
  670. allUntyped = false
  671. for i in 1..<s.typ.n.len:
  672. let param = s.typ.n[i].sym
  673. if param.name.id != ord(wUnderscore):
  674. param.flags.incl sfTemplateParam
  675. param.flags.excl sfGenSym
  676. if param.typ.kind != tyUntyped: allUntyped = false
  677. # no default value, parameters required in call
  678. if param.ast == nil: nullary = false
  679. else:
  680. s.typ = newTypeS(tyProc, c)
  681. # XXX why do we need tyTyped as a return type again?
  682. s.typ.n = newNodeI(nkFormalParams, n.info)
  683. rawAddSon(s.typ, newTypeS(tyTyped, c))
  684. s.typ.n.add newNodeIT(nkType, n.info, s.typ.returnType)
  685. if n[genericParamsPos].safeLen == 0:
  686. # restore original generic type params as no explicit or implicit were found
  687. n[genericParamsPos] = n[miscPos][1]
  688. n[miscPos] = c.graph.emptyNode
  689. if allUntyped: incl(s.flags, sfAllUntyped)
  690. if nullary and
  691. n[genericParamsPos].kind == nkEmpty and
  692. n[bodyPos].kind != nkEmpty:
  693. # template can be called with alias syntax, remove pushed noalias flag
  694. excl(s.flags, sfNoalias)
  695. if n[patternPos].kind != nkEmpty:
  696. n[patternPos] = semPattern(c, n[patternPos], s)
  697. var ctx = TemplCtx(
  698. toBind: initIntSet(),
  699. toMixin: initIntSet(),
  700. toInject: initIntSet(),
  701. c: c,
  702. owner: s
  703. )
  704. # handle default params:
  705. for i in 1..<s.typ.n.len:
  706. let param = s.typ.n[i].sym
  707. if param.ast != nil:
  708. # param default values need to be treated like template body:
  709. if sfDirty in s.flags:
  710. param.ast = semTemplBodyDirty(ctx, param.ast)
  711. else:
  712. param.ast = semTemplBody(ctx, param.ast)
  713. if param.ast.referencesAnotherParam(s):
  714. param.ast.flags.incl nfDefaultRefsParam
  715. if sfDirty in s.flags:
  716. n[bodyPos] = semTemplBodyDirty(ctx, n[bodyPos])
  717. else:
  718. n[bodyPos] = semTemplBody(ctx, n[bodyPos])
  719. # only parameters are resolved, no type checking is performed
  720. semIdeForTemplateOrGeneric(c, n[bodyPos], ctx.cursorInBody)
  721. closeScope(c)
  722. popOwner(c)
  723. # set the symbol AST after pragmas, at least. This stops pragma that have
  724. # been pushed (implicit) to be explicitly added to the template definition
  725. # and misapplied to the body. see #18113
  726. s.ast = n
  727. if sfCustomPragma in s.flags:
  728. if n[bodyPos].kind != nkEmpty:
  729. localError(c.config, n[bodyPos].info, errImplOfXNotAllowed % s.name.s)
  730. elif n[bodyPos].kind == nkEmpty:
  731. localError(c.config, n.info, "implementation of '$1' expected" % s.name.s)
  732. var (proto, comesFromShadowscope) = searchForProc(c, c.currentScope, s)
  733. if proto == nil:
  734. addInterfaceOverloadableSymAt(c, c.currentScope, s)
  735. elif not comesFromShadowscope:
  736. if {sfTemplateRedefinition, sfGenSym} * s.flags == {}:
  737. #wrongRedefinition(c, n.info, proto.name.s, proto.info)
  738. message(c.config, n.info, warnImplicitTemplateRedefinition, s.name.s)
  739. symTabReplace(c.currentScope.symbols, proto, s)
  740. if n[patternPos].kind != nkEmpty:
  741. c.patterns.add(s)
  742. proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
  743. template templToExpand(s: untyped): untyped =
  744. s.kind == skTemplate and (s.typ.len == 1 or sfAllUntyped in s.flags)
  745. proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode =
  746. # the param added in the current scope is actually wrong here for
  747. # macros because they have a shadowed param of type 'PNimNode' (see
  748. # semtypes.addParamOrResult). Within the pattern we have to ensure
  749. # to use the param with the proper type though:
  750. incl(s.flags, sfUsed)
  751. onUse(n.info, s)
  752. let x = c.owner.typ.n[s.position+1].sym
  753. assert x.name == s.name
  754. result = newSymNode(x, n.info)
  755. proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
  756. result = n
  757. if s != nil:
  758. if s.owner == c.owner and s.kind == skParam:
  759. result = newParam(c, n, s)
  760. elif contains(c.toBind, s.id):
  761. result = symChoice(c.c, n, s, scClosed)
  762. elif templToExpand(s):
  763. result = semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
  764. else:
  765. discard
  766. # we keep the ident unbound for matching instantiated symbols and
  767. # more flexibility
  768. proc expectParam(c: var TemplCtx, n: PNode): PNode =
  769. let s = qualifiedLookUp(c.c, n, {})
  770. if s != nil and s.owner == c.owner and s.kind == skParam:
  771. result = newParam(c, n, s)
  772. else:
  773. localError(c.c.config, n.info, "invalid expression")
  774. result = n
  775. result = n
  776. case n.kind
  777. of nkIdent:
  778. let s = qualifiedLookUp(c.c, n, {})
  779. result = handleSym(c, n, s)
  780. of nkBindStmt:
  781. result = semBindStmt(c.c, n, c.toBind)
  782. of nkEmpty, nkSym..nkNilLit: discard
  783. of nkCurlyExpr:
  784. # we support '(pattern){x}' to bind a subpattern to a parameter 'x';
  785. # '(pattern){|x}' does the same but the matches will be gathered in 'x'
  786. if n.len != 2:
  787. localError(c.c.config, n.info, "invalid expression")
  788. elif n[1].kind == nkIdent:
  789. n[0] = semPatternBody(c, n[0])
  790. n[1] = expectParam(c, n[1])
  791. elif n[1].kind == nkPrefix and n[1][0].kind == nkIdent:
  792. let opr = n[1][0]
  793. if opr.ident.s == "|":
  794. n[0] = semPatternBody(c, n[0])
  795. n[1][1] = expectParam(c, n[1][1])
  796. else:
  797. localError(c.c.config, n.info, "invalid expression")
  798. else:
  799. localError(c.c.config, n.info, "invalid expression")
  800. of nkStmtList, nkStmtListExpr:
  801. if stupidStmtListExpr(n):
  802. result = semPatternBody(c, n.lastSon)
  803. else:
  804. for i in 0..<n.len:
  805. result[i] = semPatternBody(c, n[i])
  806. of nkCallKinds:
  807. let s = qualifiedLookUp(c.c, n[0], {})
  808. if s != nil:
  809. if s.owner == c.owner and s.kind == skParam: discard
  810. elif contains(c.toBind, s.id): discard
  811. elif templToExpand(s):
  812. return semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
  813. if n.kind == nkInfix and (let id = considerQuotedIdent(c.c, n[0]); id != nil):
  814. # we interpret `*` and `|` only as pattern operators if they occur in
  815. # infix notation, so that '`*`(a, b)' can be used for verbatim matching:
  816. if id.s == "*" or id.s == "**":
  817. result = newNodeI(nkPattern, n.info, n.len)
  818. result[0] = newIdentNode(id, n.info)
  819. result[1] = semPatternBody(c, n[1])
  820. result[2] = expectParam(c, n[2])
  821. return
  822. elif id.s == "|":
  823. result = newNodeI(nkPattern, n.info, n.len)
  824. result[0] = newIdentNode(id, n.info)
  825. result[1] = semPatternBody(c, n[1])
  826. result[2] = semPatternBody(c, n[2])
  827. return
  828. if n.kind == nkPrefix and (let id = considerQuotedIdent(c.c, n[0]); id != nil):
  829. if id.s == "~":
  830. result = newNodeI(nkPattern, n.info, n.len)
  831. result[0] = newIdentNode(id, n.info)
  832. result[1] = semPatternBody(c, n[1])
  833. return
  834. for i in 0..<n.len:
  835. result[i] = semPatternBody(c, n[i])
  836. else:
  837. # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
  838. # so we use the generic code for nkDotExpr too
  839. case n.kind
  840. of nkDotExpr, nkAccQuoted:
  841. let s = qualifiedLookUp(c.c, n, {})
  842. if s != nil:
  843. if contains(c.toBind, s.id):
  844. return symChoice(c.c, n, s, scClosed)
  845. else:
  846. return newIdentNode(s.name, n.info)
  847. of nkPar:
  848. if n.len == 1: return semPatternBody(c, n[0])
  849. else: discard
  850. for i in 0..<n.len:
  851. result[i] = semPatternBody(c, n[i])
  852. proc semPattern(c: PContext, n: PNode; s: PSym): PNode =
  853. openScope(c)
  854. var ctx = TemplCtx(
  855. toBind: initIntSet(),
  856. toMixin: initIntSet(),
  857. toInject: initIntSet(),
  858. c: c,
  859. owner: getCurrOwner(c)
  860. )
  861. result = flattenStmts(semPatternBody(ctx, n))
  862. if result.kind in {nkStmtList, nkStmtListExpr}:
  863. if result.len == 1:
  864. result = result[0]
  865. elif result.len == 0:
  866. localError(c.config, n.info, "a pattern cannot be empty")
  867. closeScope(c)
  868. addPattern(c, LazySym(sym: s))