sem.nim 24 KB

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