sem.nim 21 KB

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