This module contains the data structures for the semantic checking phase.
Types
ExecutionCon = object nestedLoopCounter*: int ## whether we are in a loop or not nestedBlockCounter*: int ## whether we are in a block or not caseContext*: seq[tuple[n: PNode, idx: int]] ## the stack of enclosing ``nkCastStmt`` nodes flags*: set[ExecutionConFlag] ## additional flags describing the context. Initialized once when ## creating an ``ExecutionCon`` and only queried after that.
-
Stores information about an abstract execution context, that is the context in which analyzed code will later be run in.
In most cases all code within the body of a procedure will be run in the same context (i.e., at run-time, when executing the procedure). However, the code placed in, for example, a static block, while analysed as part of the procedure, is executed at compile-time, separately from the other code.
Source Edit ExecutionConFlag = enum ecfStatic, ## the context is that of a ``static`` block/expression or of ## a `const`'s initializer ecfExplicit ## the context is explicit. Sub-compilation (``compiles``) ## always picks the closest explicit context
- Source Edit
ImportedModule = object m*: PSym case mode*: ImportMode of importAll: nil of importSet: imported*: IntSet of importExcept: exceptSet*: IntSet
- Source Edit
ImportMode = enum importAll, importSet, importExcept
- Source Edit
POptionEntry = ref TOptionEntry
- Source Edit
TContext = object of TPassContext enforceVoidContext*: PType ## for `if cond: stmt else: foo`, `foo` will be evaluated under ## enforceVoidContext != nil; meaning we infered the `if` to contain a ## `stmt` (void) and so `foo` must result in an expression that can be ## `void`. Which plays into discard checks. ## ## It's used as a sentinel value, setting a node's typ field to this can ## then be compared with later to raise errors or to see if something is ## meant to be in the void context. ## ## `enforceVoidContext` is not the `void` type, see `voidType` ## ## written: once at sem start ## read: ## - semExprWithType: check if an expr has no type ## - semAsgn: ensure assignments aren't an expression ## - semstmts: for/while/etc stmt enforcement currentScope*: PScope ## current scope based on semantic analysis' traversal through the ast, ## then read during lookups of various symbols/idents ## ## written: sem/exprs/call/... ## read: lookups p*: PProcCon ## procedure context used all over semantic analysis. Tracks various ## aspects of when traversal is in a proc, top level module, blocks, ## loops, etc ## ## written: all over sem ## read: all over sem executionCons*: seq[ExecutionCon] ## the stack of execution contexts. Only the last item represents the ## active context. ## ## written: when pushing/popping a new procedure context, or when ## analysing a nested out-of-phase expression/statement ## read: all over sem matchedConcept*: ptr TMatchedConcept ## the current concept being matched ## ## written: ## - seminst: start of generateInstance save old one, at end restore it ## - sigmatch matchUserTypeClass ## read: ## - afterCallActions ## - semExpr after ident/sym lookup and type nodes nkTypeOfExpr, etc ## - semstmts var/let, discard, list ## - sigmatch: typeRel and friends inTypeContext*: int ## track whether we're in a "type context", eg: type section, used by ## `suggest`, but that might leak into other parts of sem. ## ## written: semgnrc, semstmts, semtempl, semtypes ## read: suggest inConceptDecl*: int ## whether we're in a concept declaration, `concepts` tracks this so we ## can differentiate whether it's the concept description vs the concept ## check (hence need implementations and should error without one) ## ## written: concepts ## read: semIterator (one line for errors, seems janky) ## ## xxx: some refactoring should allow for removal templInstCounter*: ref int ## gives each template instantiation a unique id ## ## written: ## - init once at sem start per module ## - strung along to each new context per macro ## or template eval; it's mutable ## - evalTemplate increments it ## read: captured and read in `TemplCtx` instCounter*: int ## To prevent endless macro pragma and generic instantiations. ## ## written: ## - pragmas: track macro pragmas expansions ## - seminst: track generic instantiations ## read: ## - pragmas: check count and error ## - seminst: check count and error inGenericContext*: int ## > 0 if we are in a generic type ## ## written: ## - semexprs: save/restore in `tryExpr` ## - semstmts: ## `typeSectionRighSidePass`, guard `semTypeNode` ## read: ## - semexprs: checked in `semIs` ## - semInst: `generateInstance` guard instantiation until we're out ## ## - semtypes: `semTypeNode` and friends guard instantiation inGenericInst*: int ## > 0 if we are instantiating a generic, weird this seems an awful lot ## ## like `instCounter` ## ## written: ## - semexprs: save/restore in `tryExpr` ## - semstmts: ## `typeSectionRighSidePass`, guard `semTypeNode` ## read: ## - semexprs: checked in `semIs` ## - semInst: `generateInstance` guard instantiation until we're out ## ## - semtypes: `semTypeNode` and friends guard instantiation generics*: seq[TInstantiationPair] ## pending list of instantiated generics to compile accumulates generics ## to compile for the backend on module close ## ## written: ## - semexprs: save/restore in `tryExpr` ## - seminst: `fixupInsantiatedSymbols` scan generics looking for a ## match based on symbol id ## read: ## - sem: module close read and add to module ast ## - seminst: `fixupInsantiatedSymbols` updates the generic, one reason ## it's mutated is to support forward declarations lastGenericIdx*: int ## used for the generics stack (`generics`) ## ## written/read: ## - sem: updated after each close of a module, ## why? xxx: is this because of suggest? ## NB this isn't preserved restored in `tryExpr`, ## but it's not mutated anywhere else, suggest ## seems to be the only thing that might need ## this and it's likely a leak -- growing over ## time. inUnrolledContext*: int ## > 0 if we are unrolling a loop ## ## written: ## - semexprs: save/restore in `tryExpr` ## - semfields: inc/dec guards in ## semForFields ## and semForObjectFields ## read: ## `semVarOrLet` to determine if the var ## or let is shadowed ## xxx: we don't read it for const, but prior to ## ## evaluation aren't they shadowed? compilesContextId*: int ## > 0 if we are in a ``compiles`` magic ## ## written: ## - semexprs: save/restore in `tryExpr` ## xxx: only for 1 level nesting some generics related hacks ## ## - suggest: inc/dec likely used to supress excessive error output ## ## read: ## - lookups: guard error output and cascading errors during compiles ## ## - semcall: guard diagnostic/errors during compiles ## - ## semexpr: check imports are top level ## - seminst: use to set/fetch from the generic cache ## ## - sempass2: guard diagnostics during compiles context ## ## xxx: much of this simplifies with nkError compilesContextIdGenerator*: int ## sequence to generate `compilesContextId` values, only gets bumped when ## we go from a non-compilesContext to a compiles context, but not from ## compiles to compiles context. ## ## written: ## - semexprs: save/restore in `tryExpr`; increment if we're heading ## into a nested compile from the level ## xxx: only for 1 level nesting some generics related hacks ## read: ## - `tryExpr`: read and assigned to `compilesContextId` optionStack*: seq[POptionEntry] ## when pragmas are pushed/popped ## ## written: ## - pragmas: pushed calling convention, dyn lib, etc or process pop ## - semdata: setters used to init compiler settings etc ## read: ## - pragmas: check to see if proc should remove from stacktrace and ## which implicit pragmas to include ## - semtypes: if there are options then create a dummy proc type node ## to merge pragmas... xxx: this seems silly inUncheckedAssignSection*: int ## if we're in an unassigned check, via a pragma block ## ## written: ## - sempragmablock in semstmts ## read: ## - sigmatch: islvalue ## - semobjconstr: errors for case object/discriminator assignments ## - analyseIfAddressTakenInCall: check to see if we're in an unsafe ## assignment block signatures*: TStrTable ## stores types for params in `using` statements ## ## written: ## - semUsing: adds an skParam symbol for lookup in semProcTypeNode ## read: ## - semProcTypeNode: lookup of params defined via the `using` statement module*: PSym ## the module sym belonging to the context used everywhere topLevelScope*: PScope ## scope for all top-level symbols of the module as in the module's scope ## ## written: ## - sem: `myopen` is called per module, and we open a new module scope ## and reset in `recoverContext` for exception recovery ## read: ## - lookups: for symbol search and check if a sym is at the top level ## - semexprs: `semexpr` guard for no top level defer stmts and in ## `lookupForDeclared` for module qualified symbols ## - suggest: iterate through top level symbols for suggestions imports*: seq[ImportedModule] ## scope for all imported symbols ## ## written: ## - importer: written when adding imports ## read: ## - importer: look for duplicate imports ## - lookups: to scan for imported symbols friendModules*: seq[PSym] ## friend modules; may access private data; this is used so that generic ## instantiations can access private object fields. ## ## written: ## - semdata: for each `newContext` a module is its own friend ## - semAfterMacroCall: calling a macro declared in another macro adds ## the declaring module as a friend for the life of ## the `semAfterMacroCall`, then we remove it ## - generateInstance: instancing a generic, like macro above, makes the ## declaring module a friend for the lifetime of the ## instancing, then we remove it ## read: ## - suggest: scan for visible fields in `fieldVisible` which is used ## beyond suggestions moduleScope*: PScope ## scope where we shove module symbols, the module itself, and other ## modules that are imported. ## ## written: ## - lookups: push error symbols here to avoid cascading errors in ## interactive or outside of nested compilation contexts ## - sem: init in `myopen`, then add itself, during system import add ## the system module symbol ## read: ## - implicitly read as it's part of the chain of scopes topStmts*: int ## counts the number of encountered top level statements ## ## written: ## - sem: incremented in semStmtAndGenerateGenerics ## read: ## - semData: query if it's the first top level statement includedFiles*: IntSet ## used to detect recursive include files ## ## written: ## - semdata: initialized ## - semstmts: remove included file after processing ## xxx: this is buggy and leads to bad error messages, we ## should instead mark it as already processed for nice ## errors about duplicate includes and declarations ## read: ## - semstmts: check for recursive includes unusedImports*: seq[(PSym, TLineInfo)] ## tracks which imports are unused, assume all new imports are unused, ## then remove them from here as we encounter usages. ## ## written: ## - importer: add all imported module as unused ## - suggest: `markOwnerModuleAsUsed`, used beyond suggestions ## read: ## - sem: on pass close report all unused modules features*: set[Feature] ## compiler feature flags, can be varied via pragmas, so per module; ## maybe that shouldn't be a thing? ## ## written: ## - pragmas: `processExperimental` enable experimental features ## - semdata: init, push/pop pragma options ## - sempass2: save/restore features during strict nil checks ## - nileval: initialized for the interpreter ## read: ## - lexer: for unicode operators ## - semcall: implicit deref ## - lookups: query overloadable enums ## - semgnrc: query overloadable enums ## - semtempl: query overloadable enums ## - semtypes: query overloadable enums and strict not nil ## - options: query nil checks enabled ## - sempass2: query strict effects, views, funcs, and not nil ## - typeallowed: query views ## - semmagic: query dynamic bind sym ## - semstmts: query dot and call operators ## - vm/gen/ops: query allowInfiniteLoops and vmopsDanger importModuleMap*: Table[int, int] ## module.id => module.id; the key is an imported module, and the value ## is the real module in case of alias ## ## written: ## - importer: track imported module/alias and the real module ## read: ## - suggest: `markOwnerModuleAsUsed`, used beyond suggestions, query ## imported module to exclude from unused modules exportIndirections*: HashSet[(int, int)] ## (module.id, symbol.id); the first is the exporting/origin module and ## the second is the exported symbol ## ## written: ## - importer: track if we're reexporting a symbol ## read: ## - suggest: `markOwnerModuleAsUsed`, used beyond suggestions, query ## export indirections to track usage info recursiveDep*: seq[tuple[importer, importee: FileIndex]] ## used to detect recursive `importer` issues populated by importer and ## used by `lookups` ## ## written: ## - importer: add dependency ## - lookups: truncated to avoid excessive nim check errors ## read: ## - lookups: query if for possible recursive dependencies cache*: IdentCache ## used everywhere for identifier caching graph*: ModuleGraph ## access to the compilation graph, used everywhere voidType*: PType ## for typeof(stmt) ## ## written: sem: initialized ## read: semExprWithType: set type for ast to void intTypeCache*: array[-5 .. 32, PType] ## cache some common integer types to avoid type allocations ## ## written/read entirely in semdata `getIntLitType` nilTypeCache*: PType ## store the nil type ## ## written/read in semexprs getNilType converters*: seq[PSym] ## track current converters and then look them up during dispatch in ## `sigmatch`. ## ## written: ## - semdata: init and append in `addConverter` which is used when a ## converter is defined or imported ## read: ## - sigmatch: to query converters pureEnumFields*: TStrTable ## pure enum fields that can be used unambiguously ## ## written: ## - importer: add when a pure enum field is declared or imported ## - semdata: init ## read: ## - lookups: search for pure enums if all else fails ## - semgnrc: lookup pure enums patterns*: seq[PSym] ## sequence of pattern matchers used for term rewriting and also `hlo`, ## where highlevel optimizations are effectively pattern matches. ## ## written: ## - semdata: init and updated via addPattern, which isn't used by hlo?? ## - hlo: `applyPatterns` add patterns for optimizations ## read: ## - hlo: check len to see if there are patterns to apply userPragmas*: TStrTable ## user pragma symbols ## ## written: ## - pragmas: add user defined pragmas as encountered ## - semdata: init ## read: ## - pragmas: query user pragmas to see if we need to process it now ## - semstmts: query user pragmas for proc/conv/etc annotation lookup ## - semtypes: query user pragmas for type section pragmas isAmbiguous*: bool ## track whether ident lookups are in ambiguous mode ## ## written: ## - lookups: set so it can be fetched in `semexpr` ## - semexpr: set prior to lookup ## read: ## - semexpr: queried to see how to treat symbol ambiguity semConstExpr*: proc (c: PContext; n: PNode): PNode {.nimcall.} ## used to break cyclic dependencies, init in sem during module open and ## read in pragmas, semmagic, and semtypinst semExpr*: proc (c: PContext; n: PNode; flags: TExprFlags = {}): PNode {. nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in concepts, pragmas, semtypinst, sigmatch, and suggest semTryExpr*: proc (c: PContext; n: PNode; flags: TExprFlags = {}): PNode {. nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in sigmatch tryEvalStaticArgument*: proc (c: PContext; n: PNode): PNode {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in sigmatch computeRequiresInit*: proc (c: PContext; t: PType): bool {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in semtypinst hasUnresolvedArgs*: proc (c: PContext; n: PNode): bool ## read to break cyclic dependencies, init in sem during module open and ## read in pragmas semOperand*: proc (c: PContext; n: PNode; flags: TExprFlags = {}): PNode {. nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in semcall and sigmatch semConstBoolExpr*: proc (c: PContext; n: PNode): PNode {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in pragmas semOverloadedCall*: proc (c: PContext; n, nOrig: PNode; filter: TSymKinds; flags: TExprFlags): PNode {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in pragmas and semtypinst semTypeNode*: proc (c: PContext; n: PNode; prev: PType): PType {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in pragmas semInferredLambda*: proc (c: PContext; pt: TIdTable; n: PNode): PNode ## read to break cyclic dependencies, init in sem during module open and ## read in sigmatch semGenerateInstance*: proc (c: PContext; fn: PSym; pt: TIdTable; info: TLineInfo): PSym ## read to break cyclic dependencies, init in sem during module open and ## read in sigmatch instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo; op: TTypeAttachedOp; col: int): PSym {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in liftdestructors and semtypinst semGenericExpr*: proc (c: PContext; n: PNode): PNode {.nimcall.} ## read to break cyclic dependencies, init in sem during module open and ## read in sigmatch sideEffects*: Table[int, seq[(TLineInfo, PSym)]] ## symbol.id => (info, sym); indexed on symbol id, tracks effects per sym ## ## written/read in sempass2, for marking and listing side effects hloLoopDetector*: int ## used to prevent endless loops in the HLO ## ## written/read in hlo, detect if hlo pattern ## applications are looping suggestionsMade*: bool ## track whether suggestion were made, written/read in sem lastTLineInfo*: TLineInfo ## last line info used in suggest by `markUsed` to track deprecated ## symbol locations
- a context represents the module that is currently being compiled Source Edit
TInstantiationPair = object genericSym*: PSym inst*: PInstantiation
- Source Edit
TMatchedConcept = object candidateType*: PType prev*: ptr TMatchedConcept depth*: int
- Source Edit
TOptionEntry = object options*: TOptions defaultCC*: TCallingConvention dynlib*: LibId notes*: ReportKinds features*: set[Feature] otherPragmas*: PNode ## every pragma can be pushed warningAsErrors*: ReportKinds
- entries to put on a stack for pragma parsing Source Edit
TProcCon {.acyclic.} = object owner*: PSym ## the symbol this context belongs to resultSym*: PSym ## the result symbol (if we are in a proc) next*: PProcCon ## used for stacking procedure contexts mappingExists*: bool mapping*: TIdTable localBindStmts*: seq[PNode]
- procedure context; also used for top-level statements Source Edit
Procs
proc addConverter(c: PContext; conv: LazySym) {....raises: [], tags: [].}
- Source Edit
proc addConverterDef(c: PContext; conv: LazySym) {....raises: [], tags: [].}
- Source Edit
proc addImportFileDep(c: PContext; f: FileIndex) {....raises: [], tags: [].}
- Source Edit
proc addIncludeFileDep(c: PContext; f: FileIndex) {....raises: [IOError], tags: [ReadIOEffect].}
- Source Edit
proc addPattern(c: PContext; p: LazySym) {....raises: [], tags: [].}
- Source Edit
proc addPragmaComputation(c: PContext; n: PNode) {....raises: [], tags: [].}
- Source Edit
proc addPureEnum(c: PContext; e: LazySym) {....raises: [], tags: [].}
- Source Edit
proc addToGenericProcCache(c: PContext; s: PSym; inst: PInstantiation) {. ...raises: [], tags: [].}
- Source Edit
proc checkMinSonsLen(n: PNode; length: int; conf: ConfigRef) {. ...raises: [Exception, ERecoverableError, ValueError], tags: [RootEffect].}
- Source Edit
proc checkSonsLen(n: PNode; length: int; conf: ConfigRef) {. ...raises: [Exception, ERecoverableError, ValueError], tags: [RootEffect].}
- Source Edit
proc considerGenSyms(c: PContext; n: PNode) {....raises: [], tags: [].}
- Source Edit
proc errorType(c: PContext): PType {....raises: [], tags: [].}
- creates a type representing an error state Source Edit
proc getCurrOwner(c: PContext): PSym {....raises: [], tags: [].}
- owner stack (used for initializing the owner field of syms) the documentation comment always gets assigned to the current owner Source Edit
proc getIntLitType(c: PContext; literal: PNode): PType {. ...raises: [KeyError, Exception, ERecoverableError], tags: [ReadDirEffect, RootEffect].}
- Source Edit
proc inCompileTimeOnlyContext(c: PContext): bool {....raises: [], tags: [].}
- Returns whether the current analysis happens for code that can only run at compile-time Source Edit
func isfirstTopLevelStmt(c: PContext): bool {....raises: [], tags: [].}
- true if this is the first top level statement encountered for this module pass. Source Edit
proc isTopLevel(c: PContext): bool {.inline, ...raises: [], tags: [].}
- Source Edit
proc isTopLevelInsideDeclaration(c: PContext; sym: PSym): bool {.inline, ...raises: [], tags: [].}
- Source Edit
proc lastOptionEntry(c: PContext): POptionEntry {....raises: [], tags: [].}
- Source Edit
proc makeInstPair(s: PSym; inst: PInstantiation): TInstantiationPair {. ...raises: [], tags: [].}
- Source Edit
proc makePtrType(owner: PSym; baseType: PType; idgen: IdGenerator): PType {. ...raises: [], tags: [].}
- Source Edit
proc makeRangeType(c: PContext; first, last: BiggestInt; info: TLineInfo; intType: PType = nil): PType {. ...raises: [KeyError, Exception, ERecoverableError], tags: [ReadDirEffect, RootEffect].}
- Source Edit
proc makeRangeWithStaticExpr(c: PContext; n: PNode): PType {. ...raises: [KeyError, Exception, ERecoverableError], tags: [ReadDirEffect, RootEffect].}
- Source Edit
proc makeRefType(conf: ConfigRef; typ: PType; idgen: IdGenerator): PType {. ...raises: [], tags: [].}
- Creates a ref <typ> type. Source Edit
proc makeTypeSymNode(c: PContext; typ: PType; info: TLineInfo): PNode {. ...raises: [Exception, ERecoverableError], tags: [RootEffect].}
- Source Edit
proc makeTypeWithModifier(c: PContext; modifier: TTypeKind; baseType: PType): PType {. ...raises: [], tags: [].}
- Source Edit
proc makeVarType(c: PContext; baseType: PType; kind = tyVar): PType {. ...raises: [], tags: [].}
- Source Edit
proc makeVarType(owner: PSym; baseType: PType; idgen: IdGenerator; kind = tyVar): PType {. ...raises: [], tags: [].}
- Source Edit
proc markIndirect(c: PContext; s: PSym) {.inline, ...raises: [], tags: [].}
- Source Edit
proc markOwnerModuleAsUsed(c: PContext; s: PSym) {....raises: [], tags: [].}
- Source Edit
proc markUsed(c: PContext; info: TLineInfo; s: PSym) {. ...raises: [Exception, ERecoverableError], tags: [RootEffect, ReadIOEffect].}
- Source Edit
proc newContext(graph: ModuleGraph; module: PSym): PContext {....raises: [IOError], tags: [ReadIOEffect].}
- Source Edit
proc newOptionEntry(conf: ConfigRef): POptionEntry {....raises: [], tags: [].}
- Source Edit
proc newTypeWithSons(c: PContext; kind: TTypeKind; sons: seq[PType]): PType {. ...raises: [], tags: [].}
- Source Edit
proc newTypeWithSons(owner: PSym; kind: TTypeKind; sons: seq[PType]; idgen: IdGenerator): PType {....raises: [], tags: [].}
- Source Edit
proc popCaseContext(c: PContext) {....raises: [], tags: [].}
- Source Edit
proc popExecCon(c: PContext) {.inline, ...raises: [], tags: [].}
- Pops the top-most ExecutionCon from the stack. Source Edit
proc popOptionEntry(c: PContext) {....raises: [], tags: [].}
- Source Edit
proc popOwner(c: PContext) {....raises: [Exception, ERecoverableError], tags: [RootEffect].}
- Source Edit
proc popProcCon(c: PContext) {.inline, ...raises: [], tags: [].}
- Source Edit
proc pushCaseContext(c: PContext; caseNode: PNode) {....raises: [], tags: [].}
- Source Edit
proc pushExecCon(c: PContext; flags: set[ExecutionConFlag]) {.inline, ...raises: [], tags: [].}
- Pushes a new ExecutionCon to the stack. Source Edit
proc pushOptionEntry(c: PContext): POptionEntry {....raises: [], tags: [].}
- Source Edit
proc pushProcCon(c: PContext; owner: PSym) {.inline, ...raises: [Exception, ERecoverableError], tags: [RootEffect].}
- Source Edit
proc reexportSym(c: PContext; s: PSym) {....raises: [], tags: [].}
- Source Edit
proc rememberExpansion(c: PContext; info: TLineInfo; expandedSym: PSym) {. ...raises: [], tags: [].}
- Templates and macros are very special in Nim; these have inlining semantics so after semantic checking they leave no trace in the sem'checked AST. This is very bad for IDE-like tooling ("find all usages of this template" would not work). We need special logic to remember macro/template expansions. This is done here and delegated to the "rod" file mechanism. Source Edit
proc scopeDepth(c: PContext): int {.inline, ...raises: [], tags: [].}
- Source Edit
proc setCaseContextIdx(c: PContext; idx: int) {....raises: [], tags: [].}
- Source Edit
proc setIntLitType(c: PContext; result: PNode) {. ...raises: [KeyError, Exception, ERecoverableError], tags: [ReadDirEffect, RootEffect].}
- Source Edit
proc storeRodNode(c: PContext; n: PNode) {....raises: [Exception], tags: [RootEffect].}
- Source Edit
Templates
template addExport(c: PContext; s: PSym)
- convenience to export a symbol from the current module Source Edit
template execCon(c: PContext): ExecutionCon
- Returns the current execution context. Source Edit
template packedRepr(c): untyped
- Source Edit
template rangeHasUnresolvedStatic(t: PType): bool
- Source Edit