All files / TRANSPILE/3-Render/codegen/helpers CppModeHelper.ts

100% Statements 7/7
100% Branches 12/12
100% Functions 7/7
100% Lines 7/7

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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                    60x                       65x                     337x                     4x                                           110x             103x                                 10x              
import CExpression from "../../../../utils/CExpression";
import type TranspileState from "../../../TranspileState";
/**
 * CppModeHelper - Utilities for C/C++ mode-specific code generation
 *
 * Issue #644: Extracted from CodeGenerator to consolidate cppMode conditionals.
 *
 * In C mode, struct parameters are passed by pointer (need & for address, * for type).
 * In C++ mode, struct parameters are passed by reference (no & needed, & for type).
 *
 * Migrated to use CodeGenState instead of constructor DI.
 */
 
/**
 * Static helper class for C/C++ mode-specific code generation patterns.
 */
class CppModeHelper {
  /**
   * Get address-of expression for struct parameter passing.
   * C mode: `&expr` (pass pointer to struct)
   * C++ mode: `expr` (pass reference directly)
   *
   * @param expr - The expression to potentially wrap
   * @returns The expression with address-of operator in C mode
   */
  static maybeAddressOf(expr: string, state: TranspileState): string {
    return state.cppMode ? expr : `&${expr}`;
  }
 
  /**
   * Get dereference expression for struct parameter access.
   * C mode: `(*expr)` (dereference pointer)
   * C++ mode: `expr` (reference can be used directly)
   *
   * @param expr - The expression to potentially dereference
   * @returns The expression with dereference in C mode
   */
  static maybeDereference(expr: string, state: TranspileState): string {
    return state.cppMode ? expr : `(*${expr})`;
  }
 
  /**
   * Get the type modifier for struct parameter declarations.
   * C mode: `*` (pointer type)
   * C++ mode: `&` (reference type)
   *
   * @returns The type modifier character
   */
  static refOrPtr(state: TranspileState): string {
    return state.cppMode ? "&" : "*";
  }
 
  /**
   * Get NULL literal for the current mode.
   * C mode: `NULL`
   * C++ mode: `nullptr`
   *
   * @returns The null pointer literal
   */
  static nullLiteral(state: TranspileState): string {
    return state.cppMode ? "nullptr" : "NULL";
  }
 
  /**
   * Generate a cast expression for the current mode.
   * C mode: `(type)expr`, or `(type)(expr)` when expr has an operator
   * C++ mode: `static_cast<type>(expr)`
   *
   * @param type - The target type
   * @param expr - The expression to cast
   * @returns The cast expression
   */
  static cast(
    type: string,
    expr: string,
    mode: Pick<TranspileState, "cppMode">,
  ): string {
    // The two modes cast the whole expression. A C cast binds tighter than
    // any binary operator, so `(float)x << 1` shifted a float, which C
    // rejects, where C++ shifted and then converted (#1760 review). A caller
    // that holds the mode rather than the state -- a helper emitted once per
    // file (#1668) -- passes `{ cppMode }`.
    return mode.cppMode
      ? `static_cast<${type}>(${expr})`
      : CppModeHelper.cStyleCast(type, expr);
  }
 
  /** A C cast of the whole of `expr`: parenthesized when it has an operator */
  private static cStyleCast(type: string, expr: string): string {
    return `(${type})${CExpression.operand(expr)}`;
  }
 
  /**
   * Generate a reinterpret cast expression for the current mode.
   * C mode: `(type)expr`
   * C++ mode: `reinterpret_cast<type>(expr)`
   *
   * @param type - The target type
   * @param expr - The expression to cast
   * @returns The cast expression
   */
  static reinterpretCast(
    type: string,
    expr: string,
    state: TranspileState,
  ): string {
    return state.cppMode
      ? `reinterpret_cast<${type}>(${expr})`
      : CppModeHelper.cStyleCast(type, expr);
  }
}
 
export default CppModeHelper;