All files / TRANSPILE/3-Render/codegen/assignment/handlers SimpleHandler.ts

81.81% Statements 27/33
72.41% Branches 21/29
100% Functions 3/3
81.81% Lines 27/33

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                                                278x 241x     37x 37x   37x 28x     9x 9x       9x 278x 278x 278x                     269x 33x     236x 236x   236x 72x     164x     164x                                                     278x     278x 278x 9x       269x 269x       269x        
/**
 * Handler for simple assignments (ADR-065).
 *
 * The fallback case: generates `target = value;` or `target op= value;`
 * Used when no special handling is needed.
 *
 * Issue #845: MISRA 10.3 - For compound assignments on narrower types (i8, i16,
 * u8, u16), expands to explicit cast: `target = (type)(target OP value);`
 * Also handles int-to-float conversions with explicit casts.
 */
import IAssignmentContext from "../../../../2-Plan/types/IAssignmentContext";
import NarrowingCastHelper from "../../helpers/NarrowingCastHelper";
import TYPE_MAP from "../../types/TYPE_MAP";
import CppModeHelper from "../../helpers/CppModeHelper";
import COMPOUND_TO_BINARY from "../../types/COMPOUND_TO_BINARY";
 
/**
 * Try to handle compound assignment on narrow types (MISRA 10.3).
 * Returns the generated code if handled, null otherwise.
 */
function tryHandleCompoundNarrowingCast(
  ctx: IAssignmentContext,
  target: string,
): string | null {
  if (!ctx.isCompound || !ctx.target.typeInfo) {
    return null;
  }
 
  const baseType = ctx.target.typeInfo.baseType;
  const promotedType = NarrowingCastHelper.getPromotedType(baseType);
 
  if (promotedType !== "int" || baseType === "int") {
    return null;
  }
 
  const binaryOp = COMPOUND_TO_BINARY[ctx.cOp];
  Iif (!binaryOp) {
    return null;
  }
 
  const cType = TYPE_MAP[baseType] ?? baseType;
  const expr = `(${target} ${binaryOp} ${ctx.generatedValue})`;
  const castExpr = CppModeHelper.cast(cType, expr, ctx.state);
  return `${target} = ${castExpr};`;
}
 
/**
 * Try to handle cross-type-category conversion (int <-> float).
 * Returns the generated code if handled, null otherwise.
 */
function tryHandleIntToFloatConversion(
  ctx: IAssignmentContext,
  target: string,
): string | null {
  if (ctx.isCompound || !ctx.target.typeInfo || !ctx.hasValue) {
    return null;
  }
 
  const targetType = ctx.target.typeInfo.baseType;
  const valueType = ctx.valueExpressionType();
 
  if (!valueType) {
    return null;
  }
 
  Eif (
    !NarrowingCastHelper.isCrossTypeCategoryConversion(valueType, targetType)
  ) {
    return null;
  }
 
  if (
    !NarrowingCastHelper.isIntegerCategory(valueType) ||
    !NarrowingCastHelper.isFloatCategory(targetType)
  ) {
    return null;
  }
 
  const castedValue = NarrowingCastHelper.wrapIntToFloat(
    ctx.generatedValue,
    targetType,
    ctx.state,
  );
  return `${target} ${ctx.cOp} ${castedValue};`;
}
 
/**
 * Handle simple variable assignment.
 *
 * @example
 * x <- 5           =>  x = 5;
 * counter +<- 1    =>  counter += 1;
 * i16_val &<- 0xFF =>  i16_val = (int16_t)(i16_val & 0xFF);  // MISRA 10.3
 */
function handleSimpleAssignment(ctx: IAssignmentContext): string {
  const target = ctx.renderTarget();
 
  // Try compound assignment narrowing cast (MISRA 10.3)
  const compoundResult = tryHandleCompoundNarrowingCast(ctx, target);
  if (compoundResult) {
    return compoundResult;
  }
 
  // Try int-to-float conversion
  const conversionResult = tryHandleIntToFloatConversion(ctx, target);
  Iif (conversionResult) {
    return conversionResult;
  }
 
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
}
 
export default handleSimpleAssignment;