sem.nim 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module implements the semantic checking pass.
  10. import
  11. ast, strutils, options, astalgo, trees,
  12. wordrecg, ropes, msgs, idents, renderer, types, platform, math,
  13. magicsys, nversion, nimsets, semfold, modulepaths, importer,
  14. procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
  15. intsets, transf, vmdef, vm, aliases, cgmeth, lambdalifting,
  16. evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
  17. lowerings, plugins/active, lineinfos, strtabs, int128,
  18. isolation_check, typeallowed, modulegraphs, enumtostr, concepts, astmsgs
  19. when defined(nimfix):
  20. import nimfix/prettybase
  21. when not defined(leanCompiler):
  22. import spawn
  23. # implementation
  24. proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
  25. proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
  26. proc semExprNoType(c: PContext, n: PNode): PNode
  27. proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
  28. proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode
  29. proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode
  30. proc changeType(c: PContext; n: PNode, newType: PType, check: bool)
  31. proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
  32. proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode
  33. proc semOpAux(c: PContext, n: PNode)
  34. proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
  35. proc addParams(c: PContext, n: PNode, kind: TSymKind)
  36. proc maybeAddResult(c: PContext, s: PSym, n: PNode)
  37. proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
  38. proc activate(c: PContext, n: PNode)
  39. proc semQuoteAst(c: PContext, n: PNode): PNode
  40. proc finishMethod(c: PContext, s: PSym)
  41. proc evalAtCompileTime(c: PContext, n: PNode): PNode
  42. proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
  43. proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode
  44. proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType
  45. proc semTypeOf(c: PContext; n: PNode): PNode
  46. proc computeRequiresInit(c: PContext, t: PType): bool
  47. proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo)
  48. proc hasUnresolvedArgs(c: PContext, n: PNode): bool
  49. proc isArrayConstr(n: PNode): bool {.inline.} =
  50. result = n.kind == nkBracket and
  51. n.typ.skipTypes(abstractInst).kind == tyArray
  52. template semIdeForTemplateOrGenericCheck(conf, n, requiresCheck) =
  53. # we check quickly if the node is where the cursor is
  54. when defined(nimsuggest):
  55. if n.info.fileIndex == conf.m.trackPos.fileIndex and n.info.line == conf.m.trackPos.line:
  56. requiresCheck = true
  57. template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
  58. requiresCheck: bool) =
  59. # use only for idetools support; this is pretty slow so generics and
  60. # templates perform some quick check whether the cursor is actually in
  61. # the generic or template.
  62. when defined(nimsuggest):
  63. if c.config.cmd == cmdIdeTools and requiresCheck:
  64. #if optIdeDebug in gGlobalOptions:
  65. # echo "passing to safeSemExpr: ", renderTree(n)
  66. discard safeSemExpr(c, n)
  67. proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
  68. let x = arg.skipConv
  69. if (x.kind == nkCurly and formal.kind == tySet and formal.base.kind != tyGenericParam) or
  70. (x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass, tyAnything}:
  71. changeType(c, x, formal, check=true)
  72. result = arg
  73. result = skipHiddenSubConv(result, c.graph, c.idgen)
  74. proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
  75. if arg.typ.isNil:
  76. localError(c.config, arg.info, "expression has no type: " &
  77. renderTree(arg, {renderNoComments}))
  78. # error correction:
  79. result = copyTree(arg)
  80. result.typ = formal
  81. elif arg.kind in nkSymChoices and formal.skipTypes(abstractInst).kind == tyEnum:
  82. # Pick the right 'sym' from the sym choice by looking at 'formal' type:
  83. for ch in arg:
  84. if sameType(ch.typ, formal):
  85. return getConstExpr(c.module, ch, c.idgen, c.graph)
  86. typeMismatch(c.config, info, formal, arg.typ, arg)
  87. else:
  88. result = indexTypesMatch(c, formal, arg.typ, arg)
  89. if result == nil:
  90. typeMismatch(c.config, info, formal, arg.typ, arg)
  91. # error correction:
  92. result = copyTree(arg)
  93. result.typ = formal
  94. else:
  95. result = fitNodePostMatch(c, formal, result)
  96. proc fitNodeConsiderViewType(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
  97. let a = fitNode(c, formal, arg, info)
  98. if formal.kind in {tyVar, tyLent}:
  99. #classifyViewType(formal) != noView:
  100. result = newNodeIT(nkHiddenAddr, a.info, formal)
  101. result.add a
  102. formal.flags.incl tfVarIsPtr
  103. else:
  104. result = a
  105. proc inferWithMetatype(c: PContext, formal: PType,
  106. arg: PNode, coerceDistincts = false): PNode
  107. template commonTypeBegin*(): PType = PType(kind: tyUntyped)
  108. proc commonType*(c: PContext; x, y: PType): PType =
  109. # new type relation that is used for array constructors,
  110. # if expressions, etc.:
  111. if x == nil: return x
  112. if y == nil: return y
  113. var a = skipTypes(x, {tyGenericInst, tyAlias, tySink})
  114. var b = skipTypes(y, {tyGenericInst, tyAlias, tySink})
  115. result = x
  116. if a.kind in {tyUntyped, tyNil}: result = y
  117. elif b.kind in {tyUntyped, tyNil}: result = x
  118. elif a.kind == tyTyped: result = a
  119. elif b.kind == tyTyped: result = b
  120. elif a.kind == tyTypeDesc:
  121. # turn any concrete typedesc into the abstract typedesc type
  122. if a.len == 0: result = a
  123. else:
  124. result = newType(tyTypeDesc, nextTypeId(c.idgen), a.owner)
  125. rawAddSon(result, newType(tyNone, nextTypeId(c.idgen), a.owner))
  126. elif b.kind in {tyArray, tySet, tySequence} and
  127. a.kind == b.kind:
  128. # check for seq[empty] vs. seq[int]
  129. let idx = ord(b.kind == tyArray)
  130. if a[idx].kind == tyEmpty: return y
  131. elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
  132. var nt: PType
  133. for i in 0..<a.len:
  134. let aEmpty = isEmptyContainer(a[i])
  135. let bEmpty = isEmptyContainer(b[i])
  136. if aEmpty != bEmpty:
  137. if nt.isNil:
  138. nt = copyType(a, nextTypeId(c.idgen), a.owner)
  139. copyTypeProps(c.graph, c.idgen.module, nt, a)
  140. nt[i] = if aEmpty: b[i] else: a[i]
  141. if not nt.isNil: result = nt
  142. #elif b[idx].kind == tyEmpty: return x
  143. elif a.kind == tyRange and b.kind == tyRange:
  144. # consider: (range[0..3], range[0..4]) here. We should make that
  145. # range[0..4]. But then why is (range[0..4], 6) not range[0..6]?
  146. # But then why is (2,4) not range[2..4]? But I think this would break
  147. # too much code. So ... it's the same range or the base type. This means
  148. # typeof(if b: 0 else 1) == int and not range[0..1]. For now. In the long
  149. # run people expect ranges to work properly within a tuple.
  150. if not sameType(a, b):
  151. result = skipTypes(a, {tyRange}).skipIntLit(c.idgen)
  152. when false:
  153. if a.kind != tyRange and b.kind == tyRange:
  154. # XXX This really needs a better solution, but a proper fix now breaks
  155. # code.
  156. result = a #.skipIntLit
  157. elif a.kind == tyRange and b.kind != tyRange:
  158. result = b #.skipIntLit
  159. elif a.kind in IntegralTypes and a.n != nil:
  160. result = a #.skipIntLit
  161. elif a.kind == tyProc and b.kind == tyProc:
  162. if a.callConv == ccClosure and b.callConv != ccClosure:
  163. result = x
  164. elif compatibleEffects(a, b) != efCompat or
  165. (b.flags * {tfNoSideEffect, tfGcSafe}) < (a.flags * {tfNoSideEffect, tfGcSafe}):
  166. result = y
  167. else:
  168. var k = tyNone
  169. if a.kind in {tyRef, tyPtr}:
  170. k = a.kind
  171. if b.kind != a.kind: return x
  172. # bug #7601, array construction of ptr generic
  173. a = a.lastSon.skipTypes({tyGenericInst})
  174. b = b.lastSon.skipTypes({tyGenericInst})
  175. if a.kind == tyObject and b.kind == tyObject:
  176. result = commonSuperclass(a, b)
  177. # this will trigger an error later:
  178. if result.isNil or result == a: return x
  179. if result == b: return y
  180. # bug #7906, tyRef/tyPtr + tyGenericInst of ref/ptr object ->
  181. # ill-formed AST, no need for additional tyRef/tyPtr
  182. if k != tyNone and x.kind != tyGenericInst:
  183. let r = result
  184. result = newType(k, nextTypeId(c.idgen), r.owner)
  185. result.addSonSkipIntLit(r, c.idgen)
  186. proc endsInNoReturn(n: PNode): bool =
  187. ## check if expr ends the block like raising or call of noreturn procs do
  188. result = false # assume it does return
  189. template checkBranch(branch) =
  190. if not endsInNoReturn(branch):
  191. # proved a branch returns
  192. return false
  193. var it = n
  194. # skip these beforehand, no special handling needed
  195. while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
  196. it = it.lastSon
  197. case it.kind
  198. of nkIfStmt:
  199. var hasElse = false
  200. for branch in it:
  201. checkBranch:
  202. if branch.len == 2:
  203. branch[1]
  204. elif branch.len == 1:
  205. hasElse = true
  206. branch[0]
  207. else:
  208. raiseAssert "Malformed `if` statement during endsInNoReturn"
  209. # none of the branches returned
  210. result = hasElse # Only truly a no-return when it's exhaustive
  211. of nkCaseStmt:
  212. for i in 1 ..< it.len:
  213. let branch = it[i]
  214. checkBranch:
  215. case branch.kind
  216. of nkOfBranch:
  217. branch[^1]
  218. of nkElifBranch:
  219. branch[1]
  220. of nkElse:
  221. branch[0]
  222. else:
  223. raiseAssert "Malformed `case` statement in endsInNoReturn"
  224. # none of the branches returned
  225. result = true
  226. of nkTryStmt:
  227. checkBranch(it[0])
  228. for i in 1 ..< it.len:
  229. let branch = it[i]
  230. checkBranch(branch[^1])
  231. # none of the branches returned
  232. result = true
  233. else:
  234. result = it.kind in nkLastBlockStmts or
  235. it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
  236. proc commonType*(c: PContext; x: PType, y: PNode): PType =
  237. # ignore exception raising branches in case/if expressions
  238. if endsInNoReturn(y): return x
  239. commonType(c, x, y.typ)
  240. proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
  241. result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info)
  242. when defined(nimsuggest):
  243. suggestDecl(c, n, result)
  244. proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
  245. # like newSymS, but considers gensym'ed symbols
  246. if n.kind == nkSym:
  247. # and sfGenSym in n.sym.flags:
  248. result = n.sym
  249. if result.kind notin {kind, skTemp}:
  250. localError(c.config, n.info, "cannot use symbol of kind '$1' as a '$2'" %
  251. [result.kind.toHumanStr, kind.toHumanStr])
  252. when false:
  253. if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
  254. # declarative context, so produce a fresh gensym:
  255. result = copySym(result)
  256. result.ast = n.sym.ast
  257. put(c.p, n.sym, result)
  258. # when there is a nested proc inside a template, semtmpl
  259. # will assign a wrong owner during the first pass over the
  260. # template; we must fix it here: see #909
  261. result.owner = getCurrOwner(c)
  262. else:
  263. result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info)
  264. #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
  265. # incl(result.flags, sfGlobal)
  266. when defined(nimsuggest):
  267. suggestDecl(c, n, result)
  268. proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
  269. allowed: TSymFlags): PSym
  270. # identifier with visibility
  271. proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
  272. allowed: TSymFlags): PSym
  273. proc typeAllowedCheck(c: PContext; info: TLineInfo; typ: PType; kind: TSymKind;
  274. flags: TTypeAllowedFlags = {}) =
  275. let t = typeAllowed(typ, kind, c, flags)
  276. if t != nil:
  277. var err: string
  278. if t == typ:
  279. err = "invalid type: '$1' for $2" % [typeToString(typ), toHumanStr(kind)]
  280. if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
  281. err &= ". Did you mean to call the $1 with '()'?" % [toHumanStr(typ.owner.kind)]
  282. else:
  283. err = "invalid type: '$1' in this context: '$2' for $3" % [typeToString(t),
  284. typeToString(typ), toHumanStr(kind)]
  285. localError(c.config, info, err)
  286. proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
  287. typeAllowedCheck(c, typ.n.info, typ, skProc)
  288. proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
  289. proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode
  290. proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
  291. proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
  292. flags: TExprFlags = {}; expectedType: PType = nil): PNode
  293. proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
  294. flags: TExprFlags = {}; expectedType: PType = nil): PNode
  295. proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym =
  296. if t.sym != nil: return t.sym
  297. result = newSym(skType, getIdent(c.cache, "AnonType"), nextSymId c.idgen, t.owner, info)
  298. result.flags.incl sfAnon
  299. result.typ = t
  300. proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
  301. result = newSymNode(symFromType(c, t, info), info)
  302. result.typ = makeTypeDesc(c, t)
  303. when false:
  304. proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
  305. result = newEvalContext(c.module, mode)
  306. result.getType = proc (n: PNode): PNode =
  307. result = tryExpr(c, n)
  308. if result == nil:
  309. result = newSymNode(errorSym(c, n))
  310. elif result.typ == nil:
  311. result = newSymNode(getSysSym"void")
  312. else:
  313. result.typ = makeTypeDesc(c, result.typ)
  314. result.handleIsOperator = proc (n: PNode): PNode =
  315. result = isOpImpl(c, n)
  316. proc hasCycle(n: PNode): bool =
  317. incl n.flags, nfNone
  318. for i in 0..<n.safeLen:
  319. if nfNone in n[i].flags or hasCycle(n[i]):
  320. result = true
  321. break
  322. excl n.flags, nfNone
  323. proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
  324. # recompute the types as 'eval' isn't guaranteed to construct types nor
  325. # that the types are sound:
  326. when true:
  327. if eOrig.typ.kind in {tyUntyped, tyTyped, tyTypeDesc}:
  328. result = semExprWithType(c, evaluated)
  329. else:
  330. result = evaluated
  331. let expectedType = eOrig.typ.skipTypes({tyStatic})
  332. if hasCycle(result):
  333. result = localErrorNode(c, eOrig, "the resulting AST is cyclic and cannot be processed further")
  334. else:
  335. semmacrosanity.annotateType(result, expectedType, c.config)
  336. else:
  337. result = semExprWithType(c, evaluated)
  338. #result = fitNode(c, e.typ, result) inlined with special case:
  339. let arg = result
  340. result = indexTypesMatch(c, eOrig.typ, arg.typ, arg)
  341. if result == nil:
  342. result = arg
  343. # for 'tcnstseq' we support [] to become 'seq'
  344. if eOrig.typ.skipTypes(abstractInst).kind == tySequence and
  345. isArrayConstr(arg):
  346. arg.typ = eOrig.typ
  347. proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
  348. var e = semExprWithType(c, n, expectedType = expectedType)
  349. if e == nil: return
  350. result = getConstExpr(c.module, e, c.idgen, c.graph)
  351. if result != nil: return
  352. let oldErrorCount = c.config.errorCounter
  353. let oldErrorMax = c.config.errorMax
  354. let oldErrorOutputs = c.config.m.errorOutputs
  355. c.config.m.errorOutputs = {}
  356. c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here
  357. try:
  358. result = evalConstExpr(c.module, c.idgen, c.graph, e)
  359. if result == nil or result.kind == nkEmpty:
  360. result = nil
  361. else:
  362. result = fixupTypeAfterEval(c, result, e)
  363. except ERecoverableError:
  364. result = nil
  365. c.config.errorCounter = oldErrorCount
  366. c.config.errorMax = oldErrorMax
  367. c.config.m.errorOutputs = oldErrorOutputs
  368. const
  369. errConstExprExpected = "constant expression expected"
  370. proc semConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
  371. var e = semExprWithType(c, n, expectedType = expectedType)
  372. if e == nil:
  373. localError(c.config, n.info, errConstExprExpected)
  374. return n
  375. if e.kind in nkSymChoices and e[0].typ.skipTypes(abstractInst).kind == tyEnum:
  376. return e
  377. result = getConstExpr(c.module, e, c.idgen, c.graph)
  378. if result == nil:
  379. #if e.kind == nkEmpty: globalError(n.info, errConstExprExpected)
  380. result = evalConstExpr(c.module, c.idgen, c.graph, e)
  381. if result == nil or result.kind == nkEmpty:
  382. if e.info != n.info:
  383. pushInfoContext(c.config, n.info)
  384. localError(c.config, e.info, errConstExprExpected)
  385. popInfoContext(c.config)
  386. else:
  387. localError(c.config, e.info, errConstExprExpected)
  388. # error correction:
  389. result = e
  390. else:
  391. result = fixupTypeAfterEval(c, result, e)
  392. proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
  393. if efNeedStatic in flags:
  394. if efPreferNilResult in flags:
  395. return tryConstExpr(c, n, expectedType)
  396. else:
  397. return semConstExpr(c, n, expectedType)
  398. else:
  399. result = semExprWithType(c, n, flags, expectedType)
  400. if efPreferStatic in flags:
  401. var evaluated = getConstExpr(c.module, result, c.idgen, c.graph)
  402. if evaluated != nil: return evaluated
  403. evaluated = evalAtCompileTime(c, result)
  404. if evaluated != nil: return evaluated
  405. when not defined(nimHasSinkInference):
  406. {.pragma: nosinks.}
  407. include hlo, seminst, semcall
  408. proc resetSemFlag(n: PNode) =
  409. if n != nil:
  410. excl n.flags, nfSem
  411. for i in 0..<n.safeLen:
  412. resetSemFlag(n[i])
  413. proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
  414. s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
  415. ## Semantically check the output of a macro.
  416. ## This involves processes such as re-checking the macro output for type
  417. ## coherence, making sure that variables declared with 'let' aren't
  418. ## reassigned, and binding the unbound identifiers that the macro output
  419. ## contains.
  420. inc(c.config.evalTemplateCounter)
  421. if c.config.evalTemplateCounter > evalTemplateLimit:
  422. globalError(c.config, s.info, "template instantiation too nested")
  423. c.friendModules.add(s.owner.getModule)
  424. result = macroResult
  425. resetSemFlag result
  426. if s.typ[0] == nil:
  427. result = semStmt(c, result, flags)
  428. else:
  429. var retType = s.typ[0]
  430. if retType.kind == tyTypeDesc and tfUnresolved in retType.flags and
  431. retType.len == 1:
  432. # bug #11941: template fails(T: type X, v: auto): T
  433. # does not mean we expect a tyTypeDesc.
  434. retType = retType[0]
  435. case retType.kind
  436. of tyUntyped, tyAnything:
  437. # Not expecting a type here allows templates like in ``tmodulealias.in``.
  438. result = semExpr(c, result, flags, expectedType)
  439. of tyTyped:
  440. # More restrictive version.
  441. result = semExprWithType(c, result, flags, expectedType)
  442. of tyTypeDesc:
  443. if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
  444. var typ = semTypeNode(c, result, nil)
  445. if typ == nil:
  446. localError(c.config, result.info, "expression has no type: " &
  447. renderTree(result, {renderNoComments}))
  448. result = newSymNode(errorSym(c, result))
  449. else:
  450. result.typ = makeTypeDesc(c, typ)
  451. #result = symNodeFromType(c, typ, n.info)
  452. else:
  453. if s.ast[genericParamsPos] != nil and retType.isMetaType:
  454. # The return type may depend on the Macro arguments
  455. # e.g. template foo(T: typedesc): seq[T]
  456. # We will instantiate the return type here, because
  457. # we now know the supplied arguments
  458. var paramTypes = newIdTable()
  459. for param, value in genericParamsInMacroCall(s, call):
  460. idTablePut(paramTypes, param.typ, value.typ)
  461. retType = generateTypeInstance(c, paramTypes,
  462. macroResult.info, retType)
  463. if retType.kind == tyVoid:
  464. result = semStmt(c, result, flags)
  465. else:
  466. result = semExpr(c, result, flags, expectedType)
  467. result = fitNode(c, retType, result, result.info)
  468. #globalError(s.info, errInvalidParamKindX, typeToString(s.typ[0]))
  469. dec(c.config.evalTemplateCounter)
  470. discard c.friendModules.pop()
  471. const
  472. errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
  473. errFloatToString = "cannot convert '$1' to '$2'"
  474. proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
  475. flags: TExprFlags = {}; expectedType: PType = nil): PNode =
  476. rememberExpansion(c, nOrig.info, sym)
  477. pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
  478. let info = getCallLineInfo(n)
  479. markUsed(c, info, sym)
  480. onUse(info, sym)
  481. if sym == c.p.owner:
  482. globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s)
  483. let genericParams = sym.ast[genericParamsPos].len
  484. let suppliedParams = max(n.safeLen - 1, 0)
  485. if suppliedParams < genericParams:
  486. globalError(c.config, info, errMissingGenericParamsForTemplate % n.renderTree)
  487. #if c.evalContext == nil:
  488. # c.evalContext = c.createEvalContext(emStatic)
  489. result = evalMacroCall(c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym)
  490. if efNoSemCheck notin flags:
  491. result = semAfterMacroCall(c, n, result, sym, flags, expectedType)
  492. if c.config.macrosToExpand.hasKey(sym.name.s):
  493. message(c.config, nOrig.info, hintExpandMacro, renderTree(result))
  494. result = wrapInComesFrom(nOrig.info, sym, result)
  495. popInfoContext(c.config)
  496. proc forceBool(c: PContext, n: PNode): PNode =
  497. result = fitNode(c, getSysType(c.graph, n.info, tyBool), n, n.info)
  498. if result == nil: result = n
  499. proc semConstBoolExpr(c: PContext, n: PNode): PNode =
  500. result = forceBool(c, semConstExpr(c, n, getSysType(c.graph, n.info, tyBool)))
  501. if result.kind != nkIntLit:
  502. localError(c.config, n.info, errConstExprExpected)
  503. proc semGenericStmt(c: PContext, n: PNode): PNode
  504. proc semConceptBody(c: PContext, n: PNode): PNode
  505. include semtypes
  506. proc setGenericParamsMisc(c: PContext; n: PNode) =
  507. ## used by call defs (procs, templates, macros, ...) to analyse their generic
  508. ## params, and store the originals in miscPos for better error reporting.
  509. let orig = n[genericParamsPos]
  510. doAssert orig.kind in {nkEmpty, nkGenericParams}
  511. if n[genericParamsPos].kind == nkEmpty:
  512. n[genericParamsPos] = newNodeI(nkGenericParams, n.info)
  513. else:
  514. # we keep the original params around for better error messages, see
  515. # issue https://github.com/nim-lang/Nim/issues/1713
  516. n[genericParamsPos] = semGenericParamList(c, orig)
  517. if n[miscPos].kind == nkEmpty:
  518. n[miscPos] = newTree(nkBracket, c.graph.emptyNode, orig)
  519. else:
  520. n[miscPos][1] = orig
  521. include semtempl, semgnrc, semstmts, semexprs
  522. proc addCodeForGenerics(c: PContext, n: PNode) =
  523. for i in c.lastGenericIdx..<c.generics.len:
  524. var prc = c.generics[i].inst.sym
  525. if prc.kind in {skProc, skFunc, skMethod, skConverter} and prc.magic == mNone:
  526. if prc.ast == nil or prc.ast[bodyPos] == nil:
  527. internalError(c.config, prc.info, "no code for " & prc.name.s)
  528. else:
  529. n.add prc.ast
  530. c.lastGenericIdx = c.generics.len
  531. proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
  532. var c = newContext(graph, module)
  533. c.idgen = idgen
  534. c.enforceVoidContext = newType(tyTyped, nextTypeId(idgen), nil)
  535. c.voidType = newType(tyVoid, nextTypeId(idgen), nil)
  536. if c.p != nil: internalError(graph.config, module.info, "sem.myOpen")
  537. c.semConstExpr = semConstExpr
  538. c.semExpr = semExpr
  539. c.semTryExpr = tryExpr
  540. c.semTryConstExpr = tryConstExpr
  541. c.computeRequiresInit = computeRequiresInit
  542. c.semOperand = semOperand
  543. c.semConstBoolExpr = semConstBoolExpr
  544. c.semOverloadedCall = semOverloadedCall
  545. c.semInferredLambda = semInferredLambda
  546. c.semGenerateInstance = generateInstance
  547. c.semTypeNode = semTypeNode
  548. c.instTypeBoundOp = sigmatch.instTypeBoundOp
  549. c.hasUnresolvedArgs = hasUnresolvedArgs
  550. c.templInstCounter = new int
  551. pushProcCon(c, module)
  552. pushOwner(c, c.module)
  553. c.moduleScope = openScope(c)
  554. c.moduleScope.addSym(module) # a module knows itself
  555. if sfSystemModule in module.flags:
  556. graph.systemModule = module
  557. c.topLevelScope = openScope(c)
  558. result = c
  559. proc isImportSystemStmt(g: ModuleGraph; n: PNode): bool =
  560. if g.systemModule == nil: return false
  561. case n.kind
  562. of nkImportStmt:
  563. for x in n:
  564. if x.kind == nkIdent:
  565. let f = checkModuleName(g.config, x, false)
  566. if f == g.systemModule.info.fileIndex:
  567. return true
  568. of nkImportExceptStmt, nkFromStmt:
  569. if n[0].kind == nkIdent:
  570. let f = checkModuleName(g.config, n[0], false)
  571. if f == g.systemModule.info.fileIndex:
  572. return true
  573. else: discard
  574. proc isEmptyTree(n: PNode): bool =
  575. case n.kind
  576. of nkStmtList:
  577. for it in n:
  578. if not isEmptyTree(it): return false
  579. result = true
  580. of nkEmpty, nkCommentStmt: result = true
  581. else: result = false
  582. proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
  583. if c.topStmts == 0 and not isImportSystemStmt(c.graph, n):
  584. if sfSystemModule notin c.module.flags and not isEmptyTree(n):
  585. assert c.graph.systemModule != nil
  586. c.moduleScope.addSym c.graph.systemModule # import the "System" identifier
  587. importAllSymbols(c, c.graph.systemModule)
  588. inc c.topStmts
  589. else:
  590. inc c.topStmts
  591. if sfNoForward in c.module.flags:
  592. result = semAllTypeSections(c, n)
  593. else:
  594. result = n
  595. result = semStmt(c, result, {})
  596. when false:
  597. # Code generators are lazy now and can deal with undeclared procs, so these
  598. # steps are not required anymore and actually harmful for the upcoming
  599. # destructor support.
  600. # BUGFIX: process newly generated generics here, not at the end!
  601. if c.lastGenericIdx < c.generics.len:
  602. var a = newNodeI(nkStmtList, n.info)
  603. addCodeForGenerics(c, a)
  604. if a.len > 0:
  605. # a generic has been added to `a`:
  606. if result.kind != nkEmpty: a.add result
  607. result = a
  608. result = hloStmt(c, result)
  609. if c.config.cmd == cmdInteractive and not isEmptyType(result.typ):
  610. result = buildEchoStmt(c, result)
  611. if c.config.cmd == cmdIdeTools:
  612. appendToModule(c.module, result)
  613. trackStmt(c, c.module, result, isTopLevel = true)
  614. proc recoverContext(c: PContext) =
  615. # clean up in case of a semantic error: We clean up the stacks, etc. This is
  616. # faster than wrapping every stack operation in a 'try finally' block and
  617. # requires far less code.
  618. c.currentScope = c.topLevelScope
  619. while getCurrOwner(c).kind != skModule: popOwner(c)
  620. while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
  621. proc myProcess(context: PPassContext, n: PNode): PNode {.nosinks.} =
  622. var c = PContext(context)
  623. # no need for an expensive 'try' if we stop after the first error anyway:
  624. if c.config.errorMax <= 1:
  625. result = semStmtAndGenerateGenerics(c, n)
  626. else:
  627. let oldContextLen = msgs.getInfoContextLen(c.config)
  628. let oldInGenericInst = c.inGenericInst
  629. try:
  630. result = semStmtAndGenerateGenerics(c, n)
  631. except ERecoverableError, ESuggestDone:
  632. recoverContext(c)
  633. c.inGenericInst = oldInGenericInst
  634. msgs.setInfoContextLen(c.config, oldContextLen)
  635. if getCurrentException() of ESuggestDone:
  636. c.suggestionsMade = true
  637. result = nil
  638. else:
  639. result = newNodeI(nkEmpty, n.info)
  640. #if c.config.cmd == cmdIdeTools: findSuggest(c, n)
  641. storeRodNode(c, result)
  642. proc reportUnusedModules(c: PContext) =
  643. for i in 0..high(c.unusedImports):
  644. if sfUsed notin c.unusedImports[i][0].flags:
  645. message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s)
  646. proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
  647. var c = PContext(context)
  648. if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
  649. suggestSentinel(c)
  650. closeScope(c) # close module's scope
  651. rawCloseScope(c) # imported symbols; don't check for unused ones!
  652. reportUnusedModules(c)
  653. result = newNode(nkStmtList)
  654. if n != nil:
  655. internalError(c.config, n.info, "n is not nil") #result := n;
  656. addCodeForGenerics(c, result)
  657. if c.module.ast != nil:
  658. result.add(c.module.ast)
  659. popOwner(c)
  660. popProcCon(c)
  661. sealRodFile(c)
  662. const semPass* = makePass(myOpen, myProcess, myClose,
  663. isFrontend = true)