sem.nim 24 KB

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