All files / TRANSPILE/3-Render/codegen/types IPlannedStringInit.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                                                                                                                                                 
import type IStringConcatOps from "./IStringConcatOps";
import type ISubstringOps from "./ISubstringOps";
 
/**
 * How a bounded string's initializer is rendered (ADR-045).
 *
 * `string<N> s <- ...` admits four initializers and they are distinguished in
 * a FIXED ORDER: concatenation, then substring extraction, then a literal,
 * then a copy from another string. The order is not cosmetic -- each question
 * is asked of the same expression, and the first that answers wins -- so this
 * is a record whose fields are consulted in declaration order rather than a
 * union whose arm is already chosen.
 *
 * ## Why the last two questions are thunks
 *
 * Generating an expression registers effects: it can request an include and it
 * can allocate a C++ temp into `pendingTempDeclarations`, which the enclosing
 * block then emits. An effect raised for a value that is afterwards discarded
 * changes the emitted C. So a field whose answer is needed on only SOME arms
 * comes over unevaluated, and the renderer pays for exactly the arm it takes.
 *
 * `concat` is the exception and is eager: deciding it reads the type registry
 * by name and generates nothing (`StringOperationsHelper.getStringConcatOperands`
 * takes two source texts), so asking it always costs what asking it once cost.
 *
 * `renderSubstring` is the sharp one. `getSubstringOperands` asks the source's
 * capacity FIRST -- that lookup is what makes `s[i]` a substring rather than an
 * array index -- and generates the index expressions only once the answer is
 * yes. Calling it is therefore free when it declines and raises effects when
 * it does not, which is precisely the combination that must not be hoisted to
 * plan time on the chance that a caller wants it.
 */
interface IPlannedStringInit {
  /**
   * ADR-045 concatenation operands, or null.
   *
   * Asked FIRST. Pure -- see the class comment.
   */
  readonly concat: IStringConcatOps | null;
 
  /**
   * ADR-045 substring operands, or null when the source is not a string.
   *
   * Asked SECOND, and only when `concat` is null. Raises effects when it
   * answers, none when it declines.
   */
  readonly renderSubstring: () => ISubstringOps | null;
 
  /**
   * The initializer's SOURCE text.
   *
   * What decides literal-versus-copy, and what the capacity diagnostics quote.
   * It is deliberately not generated code: a string literal's length and a
   * declared string's capacity are both answered from the spelling.
   */
  readonly text: string;
 
  /**
   * #1668 (C7): the initializer's string capacity -- a literal's length, or
   * a string variable's declared capacity -- or null when it is neither
   */
  readonly sourceCapacity: number | null;
 
  /**
   * The initializer as generated C.
   *
   * Asked LAST, on the literal and copy arms only.
   */
  readonly render: () => string;
}
 
export default IPlannedStringInit;