All files / types TConstResult.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                                                                                                                                     
import type ISourcePosition from "../utils/types/ISourcePosition";
 
/**
 * What a `TConstExpr` is worth, by the one rule (#1175, #1669): the value the
 * same expression has when the program runs (ADR-044 "Values fixed at compile
 * time").
 *
 * - `value`: computed. `typeName` is the type the arithmetic happened at, or
 *   null when no operand gave it one.
 * - `notConstant`: something in it has no value while the program compiles.
 * - `overflow`: the arithmetic happens at `typeName`, which cannot hold the
 *   result, so at run time the program would clamp or wrap there.
 * - `foreign`: it depends on a name only C knows the value of -- a macro, or
 *   `sizeof` of a type whose size the target decides. C can evaluate it where C
 *   allows (an array dimension); C-Next cannot use it where it needs the value.
 */
type TConstResult =
  | {
      readonly kind: "value";
      readonly value: bigint;
      readonly typeName: string | null;
    }
  | {
      readonly kind: "notConstant";
      readonly reason:
        | "variable"
        | "parameter"
        | "function"
        | "call"
        | "scope"
        | "unfolded"
        | "laterMember"
        | "selfMember"
        | "unknown"
        | "subscript"
        | "float"
        | "string"
        | "character"
        | "initializer"
        | "address"
        | "member"
        | "undeclaredMember"
        | "leadingZero"
        | "sizeofExpression"
        | "divisionByZero"
        | "negativeShift";
      /** The offending part as the source spells it, for a message */
      readonly spelling: string;
      readonly at: ISourcePosition | null;
      /** For an `unfolded` const: why its own initializer has no value */
      readonly because?: Exclude<TConstResult, { readonly kind: "value" }>;
    }
  | { readonly kind: "overflow"; readonly typeName: string }
  | {
      readonly kind: "foreign";
      /** What only C knows, as the source spells it, for a message */
      readonly spelling: string;
      /**
       * A name a header declares; a name no C-Next declaration binds, in a
       * file that includes a header, which may be a macro (a `#define` never
       * reaches the symbol model); or a size the target decides
       */
      readonly why: "header" | "maybeHeader" | "targetSize";
    };
 
export default TConstResult;