1# 2# 3# The Nim Compiler 4# (c) Copyright 2017 Andreas Rumpf 5# 6# See the file "copying.txt", included in this 7# distribution, for details about the copyright. 8# 9 10## This module contains the data structures for the semantic checking phase. 11 12import tables 13 14import 15 intsets, options, ast, astalgo, msgs, idents, renderer, 16 magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils 17 18import ic / ic 19 20type 21 TOptionEntry* = object # entries to put on a stack for pragma parsing 22 options*: TOptions 23 defaultCC*: TCallingConvention 24 dynlib*: PLib 25 notes*: TNoteKinds 26 features*: set[Feature] 27 otherPragmas*: PNode # every pragma can be pushed 28 warningAsErrors*: TNoteKinds 29 30 POptionEntry* = ref TOptionEntry 31 PProcCon* = ref TProcCon 32 TProcCon* {.acyclic.} = object # procedure context; also used for top-level 33 # statements 34 owner*: PSym # the symbol this context belongs to 35 resultSym*: PSym # the result symbol (if we are in a proc) 36 selfSym*: PSym # the 'self' symbol (if available) 37 nestedLoopCounter*: int # whether we are in a loop or not 38 nestedBlockCounter*: int # whether we are in a block or not 39 next*: PProcCon # used for stacking procedure contexts 40 mappingExists*: bool 41 mapping*: TIdTable 42 caseContext*: seq[tuple[n: PNode, idx: int]] 43 localBindStmts*: seq[PNode] 44 45 TMatchedConcept* = object 46 candidateType*: PType 47 prev*: ptr TMatchedConcept 48 depth*: int 49 50 TInstantiationPair* = object 51 genericSym*: PSym 52 inst*: PInstantiation 53 54 TExprFlag* = enum 55 efLValue, efWantIterator, efWantIterable, efInTypeof, 56 efNeedStatic, 57 # Use this in contexts where a static value is mandatory 58 efPreferStatic, 59 # Use this in contexts where a static value could bring more 60 # information, but it's not strictly mandatory. This may become 61 # the default with implicit statics in the future. 62 efPreferNilResult, 63 # Use this if you want a certain result (e.g. static value), 64 # but you don't want to trigger a hard error. For example, 65 # you may be in position to supply a better error message 66 # to the user. 67 efWantStmt, efAllowStmt, efDetermineType, efExplain, 68 efWantValue, efOperand, efNoSemCheck, 69 efNoEvaluateGeneric, efInCall, efFromHlo, efNoSem2Check, 70 efNoUndeclared 71 # Use this if undeclared identifiers should not raise an error during 72 # overload resolution. 73 74 TExprFlags* = set[TExprFlag] 75 76 ImportMode* = enum 77 importAll, importSet, importExcept 78 ImportedModule* = object 79 m*: PSym 80 case mode*: ImportMode 81 of importAll: discard 82 of importSet: 83 imported*: IntSet # of PIdent.id 84 of importExcept: 85 exceptSet*: IntSet # of PIdent.id 86 87 PContext* = ref TContext 88 TContext* = object of TPassContext # a context represents the module 89 # that is currently being compiled 90 enforceVoidContext*: PType 91 # for `if cond: stmt else: foo`, `foo` will be evaluated under 92 # enforceVoidContext != nil 93 voidType*: PType # for typeof(stmt) 94 module*: PSym # the module sym belonging to the context 95 currentScope*: PScope # current scope 96 moduleScope*: PScope # scope for modules 97 imports*: seq[ImportedModule] # scope for all imported symbols 98 topLevelScope*: PScope # scope for all top-level symbols 99 p*: PProcCon # procedure context 100 intTypeCache*: array[-5..32, PType] # cache some common integer types 101 # to avoid type allocations 102 nilTypeCache*: PType 103 matchedConcept*: ptr TMatchedConcept # the current concept being matched 104 friendModules*: seq[PSym] # friend modules; may access private data; 105 # this is used so that generic instantiations 106 # can access private object fields 107 instCounter*: int # to prevent endless instantiations 108 templInstCounter*: ref int # gives every template instantiation a unique id 109 inGenericContext*: int # > 0 if we are in a generic type 110 inStaticContext*: int # > 0 if we are inside a static: block 111 inUnrolledContext*: int # > 0 if we are unrolling a loop 112 compilesContextId*: int # > 0 if we are in a ``compiles`` magic 113 compilesContextIdGenerator*: int 114 inGenericInst*: int # > 0 if we are instantiating a generic 115 converters*: seq[PSym] 116 patterns*: seq[PSym] # sequence of pattern matchers 117 optionStack*: seq[POptionEntry] 118 symMapping*: TIdTable # every gensym'ed symbol needs to be mapped 119 # to some new symbol in a generic instantiation 120 libs*: seq[PLib] # all libs used by this module 121 semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas 122 semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} 123 semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} 124 semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} 125 computeRequiresInit*: proc (c: PContext, t: PType): bool {.nimcall.} 126 hasUnresolvedArgs*: proc (c: PContext, n: PNode): bool 127 128 semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} 129 semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet 130 semOverloadedCall*: proc (c: PContext, n, nOrig: PNode, 131 filter: TSymKinds, flags: TExprFlags): PNode {.nimcall.} 132 semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.} 133 semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode 134 semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable, 135 info: TLineInfo): PSym 136 includedFiles*: IntSet # used to detect recursive include files 137 pureEnumFields*: TStrTable # pure enum fields that can be used unambiguously 138 userPragmas*: TStrTable 139 evalContext*: PEvalContext 140 unknownIdents*: IntSet # ids of all unknown identifiers to prevent 141 # naming it multiple times 142 generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile 143 topStmts*: int # counts the number of encountered top level statements 144 lastGenericIdx*: int # used for the generics stack 145 hloLoopDetector*: int # used to prevent endless loops in the HLO 146 inParallelStmt*: int 147 instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo; 148 op: TTypeAttachedOp; col: int): PSym {.nimcall.} 149 selfName*: PIdent 150 cache*: IdentCache 151 graph*: ModuleGraph 152 signatures*: TStrTable 153 recursiveDep*: string 154 suggestionsMade*: bool 155 isAmbiguous*: bool # little hack 156 features*: set[Feature] 157 inTypeContext*, inConceptDecl*: int 158 unusedImports*: seq[(PSym, TLineInfo)] 159 exportIndirections*: HashSet[(int, int)] # (module.id, symbol.id) 160 importModuleMap*: Table[int, int] # (module.id, module.id) 161 lastTLineInfo*: TLineInfo 162 sideEffects*: Table[int, seq[(TLineInfo, PSym)]] # symbol.id index 163 inUncheckedAssignSection*: int 164 165template config*(c: PContext): ConfigRef = c.graph.config 166 167proc getIntLitType*(c: PContext; literal: PNode): PType = 168 # we cache some common integer literal types for performance: 169 let value = literal.intVal 170 if value >= low(c.intTypeCache) and value <= high(c.intTypeCache): 171 result = c.intTypeCache[value.int] 172 if result == nil: 173 let ti = getSysType(c.graph, literal.info, tyInt) 174 result = copyType(ti, nextTypeId(c.idgen), ti.owner) 175 result.n = literal 176 c.intTypeCache[value.int] = result 177 else: 178 let ti = getSysType(c.graph, literal.info, tyInt) 179 result = copyType(ti, nextTypeId(c.idgen), ti.owner) 180 result.n = literal 181 182proc setIntLitType*(c: PContext; result: PNode) = 183 let i = result.intVal 184 case c.config.target.intSize 185 of 8: result.typ = getIntLitType(c, result) 186 of 4: 187 if i >= low(int32) and i <= high(int32): 188 result.typ = getIntLitType(c, result) 189 else: 190 result.typ = getSysType(c.graph, result.info, tyInt64) 191 of 2: 192 if i >= low(int16) and i <= high(int16): 193 result.typ = getIntLitType(c, result) 194 elif i >= low(int32) and i <= high(int32): 195 result.typ = getSysType(c.graph, result.info, tyInt32) 196 else: 197 result.typ = getSysType(c.graph, result.info, tyInt64) 198 of 1: 199 # 8 bit CPUs are insane ... 200 if i >= low(int8) and i <= high(int8): 201 result.typ = getIntLitType(c, result) 202 elif i >= low(int16) and i <= high(int16): 203 result.typ = getSysType(c.graph, result.info, tyInt16) 204 elif i >= low(int32) and i <= high(int32): 205 result.typ = getSysType(c.graph, result.info, tyInt32) 206 else: 207 result.typ = getSysType(c.graph, result.info, tyInt64) 208 else: 209 internalError(c.config, result.info, "invalid int size") 210 211proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = 212 result.genericSym = s 213 result.inst = inst 214 215proc filename*(c: PContext): string = 216 # the module's filename 217 return toFilename(c.config, FileIndex c.module.position) 218 219proc scopeDepth*(c: PContext): int {.inline.} = 220 result = if c.currentScope != nil: c.currentScope.depthLevel 221 else: 0 222 223proc getCurrOwner*(c: PContext): PSym = 224 # owner stack (used for initializing the 225 # owner field of syms) 226 # the documentation comment always gets 227 # assigned to the current owner 228 result = c.graph.owners[^1] 229 230proc pushOwner*(c: PContext; owner: PSym) = 231 c.graph.owners.add(owner) 232 233proc popOwner*(c: PContext) = 234 if c.graph.owners.len > 0: setLen(c.graph.owners, c.graph.owners.len - 1) 235 else: internalError(c.config, "popOwner") 236 237proc lastOptionEntry*(c: PContext): POptionEntry = 238 result = c.optionStack[^1] 239 240proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next 241 242proc put*(p: PProcCon; key, val: PSym) = 243 if not p.mappingExists: 244 initIdTable(p.mapping) 245 p.mappingExists = true 246 #echo "put into table ", key.info 247 p.mapping.idTablePut(key, val) 248 249proc get*(p: PProcCon; key: PSym): PSym = 250 if not p.mappingExists: return nil 251 result = PSym(p.mapping.idTableGet(key)) 252 253proc getGenSym*(c: PContext; s: PSym): PSym = 254 if sfGenSym notin s.flags: return s 255 var it = c.p 256 while it != nil: 257 result = get(it, s) 258 if result != nil: 259 #echo "got from table ", result.name.s, " ", result.info 260 return result 261 it = it.next 262 result = s 263 264proc considerGenSyms*(c: PContext; n: PNode) = 265 if n == nil: 266 discard "can happen for nkFormalParams/nkArgList" 267 elif n.kind == nkSym: 268 let s = getGenSym(c, n.sym) 269 if n.sym != s: 270 n.sym = s 271 else: 272 for i in 0..<n.safeLen: 273 considerGenSyms(c, n[i]) 274 275proc newOptionEntry*(conf: ConfigRef): POptionEntry = 276 new(result) 277 result.options = conf.options 278 result.defaultCC = ccNimCall 279 result.dynlib = nil 280 result.notes = conf.notes 281 result.warningAsErrors = conf.warningAsErrors 282 283proc pushOptionEntry*(c: PContext): POptionEntry = 284 new(result) 285 var prev = c.optionStack[^1] 286 result.options = c.config.options 287 result.defaultCC = prev.defaultCC 288 result.dynlib = prev.dynlib 289 result.notes = c.config.notes 290 result.warningAsErrors = c.config.warningAsErrors 291 result.features = c.features 292 c.optionStack.add(result) 293 294proc popOptionEntry*(c: PContext) = 295 c.config.options = c.optionStack[^1].options 296 c.config.notes = c.optionStack[^1].notes 297 c.config.warningAsErrors = c.optionStack[^1].warningAsErrors 298 c.features = c.optionStack[^1].features 299 c.optionStack.setLen(c.optionStack.len - 1) 300 301proc newContext*(graph: ModuleGraph; module: PSym): PContext = 302 new(result) 303 result.optionStack = @[newOptionEntry(graph.config)] 304 result.libs = @[] 305 result.module = module 306 result.friendModules = @[module] 307 result.converters = @[] 308 result.patterns = @[] 309 result.includedFiles = initIntSet() 310 initStrTable(result.pureEnumFields) 311 initStrTable(result.userPragmas) 312 result.generics = @[] 313 result.unknownIdents = initIntSet() 314 result.cache = graph.cache 315 result.graph = graph 316 initStrTable(result.signatures) 317 result.features = graph.config.features 318 if graph.config.symbolFiles != disabledSf: 319 let id = module.position 320 assert graph.packed[id].status in {undefined, outdated} 321 graph.packed[id].status = storing 322 graph.packed[id].module = module 323 initEncoder graph, module 324 325template packedRepr*(c): untyped = c.graph.packed[c.module.position].fromDisk 326template encoder*(c): untyped = c.graph.encoders[c.module.position] 327 328proc addIncludeFileDep*(c: PContext; f: FileIndex) = 329 if c.config.symbolFiles != disabledSf: 330 addIncludeFileDep(c.encoder, c.packedRepr, f) 331 332proc addImportFileDep*(c: PContext; f: FileIndex) = 333 if c.config.symbolFiles != disabledSf: 334 addImportFileDep(c.encoder, c.packedRepr, f) 335 336proc addPragmaComputation*(c: PContext; n: PNode) = 337 if c.config.symbolFiles != disabledSf: 338 addPragmaComputation(c.encoder, c.packedRepr, n) 339 340proc inclSym(sq: var seq[PSym], s: PSym): bool = 341 for i in 0..<sq.len: 342 if sq[i].id == s.id: return false 343 sq.add s 344 result = true 345 346proc addConverter*(c: PContext, conv: LazySym) = 347 assert conv.sym != nil 348 if inclSym(c.converters, conv.sym): 349 add(c.graph.ifaces[c.module.position].converters, conv) 350 351proc addConverterDef*(c: PContext, conv: LazySym) = 352 addConverter(c, conv) 353 if c.config.symbolFiles != disabledSf: 354 addConverter(c.encoder, c.packedRepr, conv.sym) 355 356proc addPureEnum*(c: PContext, e: LazySym) = 357 assert e.sym != nil 358 add(c.graph.ifaces[c.module.position].pureEnums, e) 359 if c.config.symbolFiles != disabledSf: 360 addPureEnum(c.encoder, c.packedRepr, e.sym) 361 362proc addPattern*(c: PContext, p: LazySym) = 363 assert p.sym != nil 364 if inclSym(c.patterns, p.sym): 365 add(c.graph.ifaces[c.module.position].patterns, p) 366 if c.config.symbolFiles != disabledSf: 367 addTrmacro(c.encoder, c.packedRepr, p.sym) 368 369proc exportSym*(c: PContext; s: PSym) = 370 strTableAdds(c.graph, c.module, s) 371 if c.config.symbolFiles != disabledSf: 372 addExported(c.encoder, c.packedRepr, s) 373 374proc reexportSym*(c: PContext; s: PSym) = 375 strTableAdds(c.graph, c.module, s) 376 if c.config.symbolFiles != disabledSf: 377 addReexport(c.encoder, c.packedRepr, s) 378 379proc newLib*(kind: TLibKind): PLib = 380 new(result) 381 result.kind = kind #initObjectSet(result.syms) 382 383proc addToLib*(lib: PLib, sym: PSym) = 384 #if sym.annex != nil and not isGenericRoutine(sym): 385 # LocalError(sym.info, errInvalidPragma) 386 sym.annex = lib 387 388proc newTypeS*(kind: TTypeKind, c: PContext): PType = 389 result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c)) 390 391proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType = 392 result = newType(tyPtr, nextTypeId(idgen), owner) 393 addSonSkipIntLit(result, baseType, idgen) 394 395proc makePtrType*(c: PContext, baseType: PType): PType = 396 makePtrType(getCurrOwner(c), baseType, c.idgen) 397 398proc makeTypeWithModifier*(c: PContext, 399 modifier: TTypeKind, 400 baseType: PType): PType = 401 assert modifier in {tyVar, tyLent, tyPtr, tyRef, tyStatic, tyTypeDesc} 402 403 if modifier in {tyVar, tyLent, tyTypeDesc} and baseType.kind == modifier: 404 result = baseType 405 else: 406 result = newTypeS(modifier, c) 407 addSonSkipIntLit(result, baseType, c.idgen) 408 409proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType = 410 if baseType.kind == kind: 411 result = baseType 412 else: 413 result = newTypeS(kind, c) 414 addSonSkipIntLit(result, baseType, c.idgen) 415 416proc makeVarType*(owner: PSym, baseType: PType; idgen: IdGenerator; kind = tyVar): PType = 417 if baseType.kind == kind: 418 result = baseType 419 else: 420 result = newType(kind, nextTypeId(idgen), owner) 421 addSonSkipIntLit(result, baseType, idgen) 422 423proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = 424 let typedesc = newTypeS(tyTypeDesc, c) 425 incl typedesc.flags, tfCheckedForDestructor 426 internalAssert(c.config, typ != nil) 427 typedesc.addSonSkipIntLit(typ, c.idgen) 428 let sym = newSym(skType, c.cache.idAnon, nextSymId(c.idgen), getCurrOwner(c), info, 429 c.config.options).linkTo(typedesc) 430 result = newSymNode(sym, info) 431 432proc makeTypeFromExpr*(c: PContext, n: PNode): PType = 433 result = newTypeS(tyFromExpr, c) 434 assert n != nil 435 result.n = n 436 437proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]; 438 idgen: IdGenerator): PType = 439 result = newType(kind, nextTypeId(idgen), owner) 440 result.sons = sons 441 442proc newTypeWithSons*(c: PContext, kind: TTypeKind, 443 sons: seq[PType]): PType = 444 result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c)) 445 result.sons = sons 446 447proc makeStaticExpr*(c: PContext, n: PNode): PNode = 448 result = newNodeI(nkStaticExpr, n.info) 449 result.sons = @[n] 450 result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ 451 else: newTypeWithSons(c, tyStatic, @[n.typ]) 452 453proc makeAndType*(c: PContext, t1, t2: PType): PType = 454 result = newTypeS(tyAnd, c) 455 result.sons = @[t1, t2] 456 propagateToOwner(result, t1) 457 propagateToOwner(result, t2) 458 result.flags.incl((t1.flags + t2.flags) * {tfHasStatic}) 459 result.flags.incl tfHasMeta 460 461proc makeOrType*(c: PContext, t1, t2: PType): PType = 462 result = newTypeS(tyOr, c) 463 if t1.kind != tyOr and t2.kind != tyOr: 464 result.sons = @[t1, t2] 465 else: 466 template addOr(t1) = 467 if t1.kind == tyOr: 468 for x in t1.sons: result.rawAddSon x 469 else: 470 result.rawAddSon t1 471 addOr(t1) 472 addOr(t2) 473 propagateToOwner(result, t1) 474 propagateToOwner(result, t2) 475 result.flags.incl((t1.flags + t2.flags) * {tfHasStatic}) 476 result.flags.incl tfHasMeta 477 478proc makeNotType*(c: PContext, t1: PType): PType = 479 result = newTypeS(tyNot, c) 480 result.sons = @[t1] 481 propagateToOwner(result, t1) 482 result.flags.incl(t1.flags * {tfHasStatic}) 483 result.flags.incl tfHasMeta 484 485proc nMinusOne(c: PContext; n: PNode): PNode = 486 result = newTreeI(nkCall, n.info, newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n) 487 488# Remember to fix the procs below this one when you make changes! 489proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType = 490 let intType = getSysType(c.graph, n.info, tyInt) 491 result = newTypeS(tyRange, c) 492 result.sons = @[intType] 493 if n.typ != nil and n.typ.n == nil: 494 result.flags.incl tfUnresolved 495 result.n = newTreeI(nkRange, n.info, newIntTypeNode(0, intType), 496 makeStaticExpr(c, nMinusOne(c, n))) 497 498template rangeHasUnresolvedStatic*(t: PType): bool = 499 tfUnresolved in t.flags 500 501proc errorType*(c: PContext): PType = 502 ## creates a type representing an error state 503 result = newTypeS(tyError, c) 504 result.flags.incl tfCheckedForDestructor 505 506proc errorNode*(c: PContext, n: PNode): PNode = 507 result = newNodeI(nkEmpty, n.info) 508 result.typ = errorType(c) 509 510# These mimic localError 511template localErrorNode*(c: PContext, n: PNode, info: TLineInfo, msg: TMsgKind, arg: string): PNode = 512 liMessage(c.config, info, msg, arg, doNothing, instLoc()) 513 errorNode(c, n) 514 515template localErrorNode*(c: PContext, n: PNode, info: TLineInfo, arg: string): PNode = 516 liMessage(c.config, info, errGenerated, arg, doNothing, instLoc()) 517 errorNode(c, n) 518 519template localErrorNode*(c: PContext, n: PNode, msg: TMsgKind, arg: string): PNode = 520 let n2 = n 521 liMessage(c.config, n2.info, msg, arg, doNothing, instLoc()) 522 errorNode(c, n2) 523 524template localErrorNode*(c: PContext, n: PNode, arg: string): PNode = 525 let n2 = n 526 liMessage(c.config, n2.info, errGenerated, arg, doNothing, instLoc()) 527 errorNode(c, n2) 528 529proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) = 530 dest.kind = kind 531 dest.owner = getCurrOwner(c) 532 dest.size = - 1 533 534proc makeRangeType*(c: PContext; first, last: BiggestInt; 535 info: TLineInfo; intType: PType = nil): PType = 536 let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt) 537 var n = newNodeI(nkRange, info) 538 n.add newIntTypeNode(first, intType) 539 n.add newIntTypeNode(last, intType) 540 result = newTypeS(tyRange, c) 541 result.n = n 542 addSonSkipIntLit(result, intType, c.idgen) # basetype of range 543 544proc markIndirect*(c: PContext, s: PSym) {.inline.} = 545 if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}: 546 incl(s.flags, sfAddrTaken) 547 # XXX add to 'c' for global analysis 548 549proc illFormedAst*(n: PNode; conf: ConfigRef) = 550 globalError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) 551 552proc illFormedAstLocal*(n: PNode; conf: ConfigRef) = 553 localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) 554 555proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) = 556 if n.len != length: illFormedAst(n, conf) 557 558proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) = 559 if n.len < length: illFormedAst(n, conf) 560 561proc isTopLevel*(c: PContext): bool {.inline.} = 562 result = c.currentScope.depthLevel <= 2 563 564proc isTopLevelInsideDeclaration*(c: PContext, sym: PSym): bool {.inline.} = 565 # for routeKinds the scope isn't closed yet: 566 c.currentScope.depthLevel <= 2 + ord(sym.kind in routineKinds) 567 568proc pushCaseContext*(c: PContext, caseNode: PNode) = 569 c.p.caseContext.add((caseNode, 0)) 570 571proc popCaseContext*(c: PContext) = 572 discard pop(c.p.caseContext) 573 574proc setCaseContextIdx*(c: PContext, idx: int) = 575 c.p.caseContext[^1].idx = idx 576 577template addExport*(c: PContext; s: PSym) = 578 ## convenience to export a symbol from the current module 579 addExport(c.graph, c.module, s) 580 581proc storeRodNode*(c: PContext, n: PNode) = 582 if c.config.symbolFiles != disabledSf: 583 toPackedNodeTopLevel(n, c.encoder, c.packedRepr) 584 585proc addToGenericProcCache*(c: PContext; s: PSym; inst: PInstantiation) = 586 c.graph.procInstCache.mgetOrPut(s.itemId, @[]).add LazyInstantiation(module: c.module.position, inst: inst) 587 if c.config.symbolFiles != disabledSf: 588 storeInstantiation(c.encoder, c.packedRepr, s, inst) 589 590proc addToGenericCache*(c: PContext; s: PSym; inst: PType) = 591 c.graph.typeInstCache.mgetOrPut(s.itemId, @[]).add LazyType(typ: inst) 592 if c.config.symbolFiles != disabledSf: 593 storeTypeInst(c.encoder, c.packedRepr, s, inst) 594 595proc sealRodFile*(c: PContext) = 596 if c.config.symbolFiles != disabledSf: 597 if c.graph.vm != nil: 598 for (m, n) in PCtx(c.graph.vm).vmstateDiff: 599 if m == c.module: 600 addPragmaComputation(c, n) 601 c.idgen.sealed = true # no further additions are allowed 602 603proc rememberExpansion*(c: PContext; info: TLineInfo; expandedSym: PSym) = 604 ## Templates and macros are very special in Nim; these have 605 ## inlining semantics so after semantic checking they leave no trace 606 ## in the sem'checked AST. This is very bad for IDE-like tooling 607 ## ("find all usages of this template" would not work). We need special 608 ## logic to remember macro/template expansions. This is done here and 609 ## delegated to the "rod" file mechanism. 610 if c.config.symbolFiles != disabledSf: 611 storeExpansion(c.encoder, c.packedRepr, info, expandedSym) 612