All files / transpiler/output/codegen/generators/declarationGenerators EnumGenerator.ts

100% Statements 18/18
100% Branches 6/6
100% Functions 1/1
100% Lines 17/17

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                                                      13x           50x     50x 50x   50x 50x     50x 50x 1x     49x   49x 129x   129x 129x 129x     49x     49x              
/**
 * EnumGenerator - ADR-017 Enum Declaration Generation
 *
 * Generates C typedef enum declarations from C-Next enum syntax.
 *
 * Example:
 *   enum State { IDLE, RUNNING, ERROR <- 255 }
 *   ->
 *   typedef enum {
 *       State_IDLE = 0,
 *       State_RUNNING = 1,
 *       State_ERROR = 255
 *   } State;
 */
import * as Parser from "../../../../logic/parser/grammar/CNextParser";
import IGeneratorInput from "../IGeneratorInput";
import IGeneratorState from "../IGeneratorState";
import IGeneratorOutput from "../IGeneratorOutput";
import IOrchestrator from "../IOrchestrator";
import TGeneratorFn from "../TGeneratorFn";
 
/**
 * Generate a C typedef enum from a C-Next enum declaration.
 *
 * ADR-017: Enums are strongly-typed with explicit integer backing.
 * Members are prefixed with the enum name to avoid C namespace collisions.
 */
const generateEnum: TGeneratorFn<Parser.EnumDeclarationContext> = (
  node: Parser.EnumDeclarationContext,
  input: IGeneratorInput,
  state: IGeneratorState,
  _orchestrator: IOrchestrator,
): IGeneratorOutput => {
  const name = node.IDENTIFIER().getText();
 
  // ADR-016: Apply scope prefix if inside a scope
  const prefix = state.currentScope ? `${state.currentScope}_` : "";
  const fullName = `${prefix}${name}`;
 
  const lines: string[] = [];
  lines.push(`typedef enum {`);
 
  // Look up enum members from symbols (collected by SymbolCollector)
  const members = input.symbols?.enumMembers.get(fullName);
  if (!members) {
    throw new Error(`Error: Enum ${fullName} not found in registry`);
  }
 
  const memberEntries = Array.from(members.entries());
 
  for (let i = 0; i < memberEntries.length; i++) {
    const [memberName, value] = memberEntries[i];
    // Prefix member names to avoid C namespace collisions
    const fullMemberName = `${fullName}_${memberName}`;
    const comma = i < memberEntries.length - 1 ? "," : "";
    lines.push(`    ${fullMemberName} = ${value}${comma}`);
  }
 
  lines.push(`} ${fullName};`, "");
 
  // No side effects needed for enum generation
  return {
    code: lines.join("\n"),
    effects: [],
  };
};
 
export default generateEnum;