sem.nim 24 KB

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