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 | 14x 14x 14x 2051x 2009x 42x 42x 42x 36x 24x 24x 1x 1x 23x 23x 12x 10x 10x 8x 8x 2x 2x | /**
* Unary Expression Generator (ADR-053 A2)
*
* Generates C code for unary expressions:
* - Prefix operators: !, -, ~, &
* - Recursive unary (e.g., !!x, --x)
* - Delegates to postfix for base case
*/
import { UnaryExpressionContext } 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";
import TypeResolver from "../../TypeResolver";
import TYPE_MAP from "../../types/TYPE_MAP";
import CppModeHelper from "../../helpers/CppModeHelper";
/**
* Problematic negative literals that overflow their signed types in C.
* -2147483648 is parsed as -(2147483648) where 2147483648 > INT32_MAX.
* These need to be rewritten to avoid the overflow issue.
*/
const INT32_MIN_LITERAL = "2147483648";
const INT64_MIN_LITERAL = "9223372036854775808";
/**
* Generate C code for a unary expression.
*
* Handles prefix operators (!, -, ~, &) and delegates to postfix
* expression for the base case (no prefix operator).
*/
const generateUnaryExpr = (
node: UnaryExpressionContext,
_input: IGeneratorInput,
_state: IGeneratorState,
orchestrator: IOrchestrator,
): IGeneratorOutput => {
// Base case: no unary operator, delegate to postfix
if (node.postfixExpression()) {
// Delegate to orchestrator for postfix expression
// This allows CodeGenerator to handle postfix until it's extracted
return {
code: orchestrator.generatePostfixExpr(node.postfixExpression()!),
effects: [],
};
}
// Recursive case: unary operator applied
// Call orchestrator.generateUnaryExpr for the inner expression
// (this may come back to us or use CodeGenerator's version)
const inner = orchestrator.generateUnaryExpr(node.unaryExpression()!);
const text = node.getText();
// Determine the operator and generate output
if (text.startsWith("!")) return { code: `!${inner}`, effects: [] };
if (text.startsWith("-")) {
// MISRA 10.3: Handle problematic negative literals that overflow in C
// -2147483648 is parsed as -(2147483648) where 2147483648 > INT32_MAX
// Must use INT32_MIN or INT64_MIN to avoid the overflow
// Cast is needed because INT32_MIN has type 'int', not 'int32_t'
const effects: TGeneratorEffect[] = [];
if (inner === INT32_MIN_LITERAL) {
effects.push({ type: "include", header: "limits" });
return { code: "(int32_t)INT32_MIN", effects };
}
Iif (inner === INT64_MIN_LITERAL || inner === INT64_MIN_LITERAL + "LL") {
effects.push({ type: "include", header: "limits" });
return { code: "(int64_t)INT64_MIN", effects };
}
return { code: `-${inner}`, effects };
}
if (text.startsWith("~")) {
const innerType = TypeResolver.getUnaryExpressionType(
node.unaryExpression()!,
);
if (innerType && TypeResolver.isUnsignedType(innerType)) {
const cType = TYPE_MAP[innerType] ?? innerType;
return { code: CppModeHelper.cast(cType, `~${inner}`), effects: [] };
}
return { code: `~${inner}`, effects: [] };
}
Eif (text.startsWith("&")) return { code: `&${inner}`, effects: [] };
// Fallback (shouldn't happen with valid grammar)
return { code: inner, effects: [] };
};
export default generateUnaryExpr;
|