All files / TRANSPILE/1-Analyze/types IAnalysisContext.ts

0% Statements 0/0
0% Branches 0/0
0% Functions 0/0
0% Lines 0/0

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74                                                                                                                                                   
import type ICodeGenSymbols from "../../../types/ICodeGenSymbols";
import type IProgram from "../../../types/IProgram";
import type SymbolTable from "../../../PARSE/3-Declare/SymbolTable";
 
/**
 * What 2.1 Analyze is allowed to know about the program it is judging.
 *
 * #1456. These four facts were reached through the render state (then
 * `CodeGenState`, now `TranspileState`), which is the
 * render pass's state container and is reachable from every pass at once. That
 * is the shape `docs/architecture/README.md` forbids -- *"a container that
 * outlives a pass is how facts come to be stashed instead of carried"* -- and
 * the cost is not theoretical: #1430 and #1432 are both an analyzer reading a
 * field a LATER pass fills, getting the previous file's answer or the previous
 * run's.
 *
 * Carrying them makes the boundary checkable. An analyzer can only read what
 * is on this object, and what is on this object is settled before 2.1 begins.
 *
 * ## Why `program` is not nullable here
 *
 * `CodeGenState.program` is `IProgram | null`, so all thirteen analyzer reads
 * spelled `CodeGenState.program?.x() ?? fallback`. Every one of those was a
 * guard that could not fire and a wrong answer if it ever did: `Transpiler`
 * asserts the artifact with `invariant` before it calls `runAnalyzers`, so by
 * 2.1 it always exists -- and a `?? []` for "what consts does this scope have"
 * is a REAL answer meaning "none", not a missing one.
 */
interface IAnalysisContext {
  /**
   * What THIS file can see: its own declarations plus its `.cnx` includes.
   *
   * Non-null, like `program`. There is one producer --
   * `Transpiler._requireSymbolInfo` -- and it returns `ICodeGenSymbols` or
   * throws, so 2.1 never runs without a view.
   *
   * Six analyzers used to guard on `if (!symbols)` with "no evidence is not
   * evidence of absence". That reads as intentional behavior and was not: the
   * state they guarded against is one production cannot enter, and the only
   * caller that could construct it was a unit test. A guard for an
   * unrepresentable state is dead code that a test keeps alive (#1418), so the
   * type forbids the state instead and the guards are gone.
   */
  readonly symbols: ICodeGenSymbols;
 
  /** 1.4 Resolve's artifact -- every cross-file fact, settled before 2.1. */
  readonly program: IProgram;
 
  /** What the program declares, C and C++ headers included. */
  readonly symbolTable: SymbolTable;
 
  /**
   * Whether this file can see a C/C++ header, which is what decides if an
   * unresolved name is a defect or a type the compiler will supply.
   *
   * 1.1 Discover decides it once per file (`IPipelineFile.reachesForeignHeader`,
   * required since the #1863 review, when 1.4 began reading it too and the
   * orchestrator had come to default it at two sites). #1430 had forced it into
   * a single site; discovery is that site, and this copies its answer. It travels on the context rather than on
   * the state for the same reason as the rest: 2.1 reads it, and 2.3 happens to
   * be where it was parked.
   */
  readonly reachesForeignHeader: boolean;
 
  /**
   * #1668: the file being analyzed. With it this context is the one
   * operand typer's `ITypingContext`, so 2.1 types an operand from exactly
   * the facts 2.2 does.
   */
  readonly sourceFile: string;
}
 
export default IAnalysisContext;