All files / transpiler/output/codegen/generators/expressions LiteralGenerator.ts

100% Statements 16/16
100% Branches 14/14
100% Functions 1/1
100% Lines 16/16

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                                                  13x           1044x 1044x     1044x 32x           1044x 1x 1043x 1x             1044x 2x 1042x 1x 1041x   1x     1044x        
/**
 * Literal Generator (ADR-053 A2)
 *
 * Generates C code for literal values:
 * - Boolean literals (true/false) → needs stdbool.h
 * - Float literals with C-Next suffixes (f32 → f, f64 → no suffix)
 * - Integer literals with C-Next suffixes (u64 → ULL, i64 → LL, strip 8/16/32)
 * - String and numeric literals pass through unchanged
 */
import { LiteralContext } from "../../../../logic/parser/grammar/CNextParser";
import IGeneratorOutput from "../IGeneratorOutput";
import TGeneratorEffect from "../TGeneratorEffect";
import IGeneratorInput from "../IGeneratorInput";
import IGeneratorState from "../IGeneratorState";
import IOrchestrator from "../IOrchestrator";
 
/**
 * Generate C code for a literal value.
 *
 * @param node - The LiteralContext AST node
 * @param _input - Read-only context (unused for literals)
 * @param _state - Current generation state (unused for literals)
 * @param _orchestrator - For delegating to other generators (unused for literals)
 * @returns Generated code and effects (stdbool include for bool literals)
 */
const generateLiteral = (
  node: LiteralContext,
  _input: IGeneratorInput,
  _state: IGeneratorState,
  _orchestrator: IOrchestrator,
): IGeneratorOutput => {
  const effects: TGeneratorEffect[] = [];
  let literalText = node.getText();
 
  // Track boolean literal usage to include stdbool.h
  if (literalText === "true" || literalText === "false") {
    effects.push({ type: "include", header: "stdbool" });
  }
 
  // ADR-024: Transform C-Next float suffixes to standard C syntax
  // 3.14f32 -> 3.14f (C float)
  // 3.14f64 -> 3.14 (C double, no suffix needed)
  if (/[fF]32$/.exec(literalText)) {
    literalText = literalText.replace(/[fF]32$/, "f");
  } else if (/[fF]64$/.exec(literalText)) {
    literalText = literalText.replace(/[fF]64$/, "");
  }
 
  // Issue #130: Transform C-Next integer suffixes to standard C syntax
  // u8/u16/u32 and i8/i16/i32 suffixes are stripped (C infers from context)
  // u64 -> ULL suffix for 64-bit unsigned
  // i64 -> LL suffix for 64-bit signed
  if (/[uU]64$/.exec(literalText)) {
    literalText = literalText.replace(/[uU]64$/, "ULL");
  } else if (/[iI]64$/.exec(literalText)) {
    literalText = literalText.replace(/[iI]64$/, "LL");
  } else if (/[uUiI](8|16|32)$/.exec(literalText)) {
    // Strip 8/16/32-bit suffixes - C handles these without explicit suffix
    literalText = literalText.replace(/[uUiI](8|16|32)$/, "");
  }
 
  return { code: literalText, effects };
};
 
export default generateLiteral;