All files / transpiler/logic/symbols/cnext/collectors BitmapCollector.ts

100% Statements 17/17
87.5% Branches 7/8
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 70 71 72 73 74                                                        26x 26x 26x 26x 26x 26x     26x 26x   26x 122x 122x 122x       122x 122x       26x 2x         24x                                
/**
 * BitmapCollector - Extracts bitmap type declarations from parse trees.
 * ADR-034: Bitmaps provide named access to bit regions within an integer backing type.
 */
 
import * as Parser from "../../../parser/grammar/CNextParser";
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
import ESymbolKind from "../../../../../utils/types/ESymbolKind";
import IBitmapSymbol from "../../types/IBitmapSymbol";
import IBitmapFieldInfo from "../../types/IBitmapFieldInfo";
import BITMAP_SIZE from "../../../../types/BITMAP_SIZE";
import BITMAP_BACKING_TYPE from "../../../../types/BITMAP_BACKING_TYPE";
 
class BitmapCollector {
  /**
   * Collect a bitmap declaration and return an IBitmapSymbol.
   *
   * @param ctx The bitmap declaration context
   * @param sourceFile Source file path
   * @param scopeName Optional scope name for nested bitmaps
   * @returns The bitmap symbol
   * @throws Error if total bits don't match bitmap size
   */
  static collect(
    ctx: Parser.BitmapDeclarationContext,
    sourceFile: string,
    scopeName?: string,
  ): IBitmapSymbol {
    const name = ctx.IDENTIFIER().getText();
    const fullName = scopeName ? `${scopeName}_${name}` : name;
    const bitmapType = ctx.bitmapType().getText();
    const expectedBits = BITMAP_SIZE[bitmapType];
    const backingType = BITMAP_BACKING_TYPE[bitmapType];
    const line = ctx.start?.line ?? 0;
 
    // Collect fields with running bit offset
    const fields = new Map<string, IBitmapFieldInfo>();
    let totalBits = 0;
 
    for (const member of ctx.bitmapMember()) {
      const fieldName = member.IDENTIFIER().getText();
      const widthLiteral = member.INTEGER_LITERAL();
      const width = widthLiteral
        ? Number.parseInt(widthLiteral.getText(), 10)
        : 1;
 
      fields.set(fieldName, { offset: totalBits, width });
      totalBits += width;
    }
 
    // Validate total bits equals bitmap size
    if (totalBits !== expectedBits) {
      throw new Error(
        `Error: Bitmap '${fullName}' has ${totalBits} bits but ${bitmapType} requires exactly ${expectedBits} bits`,
      );
    }
 
    return {
      name: fullName,
      parent: scopeName,
      sourceFile,
      sourceLine: line,
      sourceLanguage: ESourceLanguage.CNext,
      isExported: true,
      kind: ESymbolKind.Bitmap,
      backingType,
      bitWidth: expectedBits,
      fields,
    };
  }
}
 
export default BitmapCollector;