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 | 15x 20x 15x 63x 6x 8x 8x 5x 5x 91x 91x 79x 12x 6x 6x 7x 3x 3x 9x | /**
* Pure utility functions for function call expression generation.
* Extracted from CallExprGenerator for testability (Issue #420).
*/
import TYPE_MAP from "../../types/TYPE_MAP";
import IFunctionSignature from "../../types/IFunctionSignature";
import SymbolTable from "../../../../logic/symbols/SymbolTable";
import ESymbolKind from "../../../../../utils/types/ESymbolKind";
/**
* Issue #315: Small primitive types that are always passed by value.
* These match the types used in Issue #269 for pass-by-value optimization.
*/
const SMALL_PRIMITIVE_TYPES = new Set(["u8", "u16", "i8", "i16", "bool"]);
class CallExprUtils {
/**
* Issue #304: Map C-Next type to C type for static_cast.
* Returns the input unchanged if not a known C-Next primitive type.
*/
static mapTypeToCType(cnxType: string): string {
return TYPE_MAP[cnxType] || cnxType;
}
/**
* Issue #315: Check if a type is a small primitive that should be passed by value.
* Used for cross-file function calls where modification info is unavailable.
*/
static isSmallPrimitiveType(typeName: string): boolean {
return SMALL_PRIMITIVE_TYPES.has(typeName);
}
/**
* Issue #551: Check if a type is a known primitive type.
* Known primitives use pass-by-reference (except floats and small types).
* Unknown types (external enums, typedefs) use pass-by-value.
*/
static isKnownPrimitiveType(typeName: string): boolean {
return !!TYPE_MAP[typeName];
}
/**
* Issue #551: Check if a type is a string type (string<N>).
* String parameters use pass-by-reference (passed as char*).
*/
static isStringType(typeName: string): boolean {
return typeName.startsWith("string<") || typeName === "string";
}
/**
* ADR-051: Generate the helper function name for safe_div/safe_mod.
*/
static generateSafeDivModHelperName(
funcName: "safe_div" | "safe_mod",
cnxType: string,
): string {
const op = funcName === "safe_div" ? "div" : "mod";
return `cnx_safe_${op}_${cnxType}`;
}
/**
* Issue #304: Generate a C++ static_cast expression.
* Used for enum class to integer conversions.
*/
static generateStaticCast(code: string, targetType: string): string {
const cType = CallExprUtils.mapTypeToCType(targetType);
return `static_cast<${cType}>(${code})`;
}
/**
* Issue #315: Resolve target parameter info from local signature or cross-file SymbolTable.
* Returns the parameter info and whether it came from a cross-file lookup.
*/
static resolveTargetParam(
sig: IFunctionSignature | undefined,
paramIndex: number,
funcName: string,
symbolTable: SymbolTable | null,
): {
param: IFunctionSignature["parameters"][0] | undefined;
isCrossFile: boolean;
} {
const localParam = sig?.parameters[paramIndex];
if (localParam) {
return { param: localParam, isCrossFile: false };
}
if (symbolTable) {
const symbols = symbolTable.getOverloads(funcName);
for (const sym of symbols) {
if (sym.kind === ESymbolKind.Function && sym.parameters?.[paramIndex]) {
const p = sym.parameters[paramIndex];
return {
param: {
name: p.name,
baseType: p.type,
isConst: p.isConst,
isArray: p.isArray,
},
isCrossFile: true,
};
}
}
}
return { param: undefined, isCrossFile: false };
}
}
export default CallExprUtils;
|