c-next 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +617 -474
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +50 -29
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +2 -1
- package/src/transpiler/data/PathResolver.ts +10 -6
- package/src/transpiler/data/__tests__/PathResolver.test.ts +32 -0
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +82 -7
- package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +1 -12
- package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +239 -0
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +92 -0
- package/src/transpiler/logic/analysis/__tests__/SignedShiftAnalyzer.test.ts +414 -0
- package/src/transpiler/logic/analysis/__tests__/StructFieldAnalyzer.test.ts +15 -75
- package/src/transpiler/logic/analysis/__tests__/runAnalyzers.test.ts +3 -15
- package/src/transpiler/logic/analysis/runAnalyzers.ts +11 -2
- package/src/transpiler/logic/analysis/types/ISignedShiftError.ts +15 -0
- package/src/transpiler/logic/symbols/SymbolUtils.ts +4 -1
- package/src/transpiler/logic/symbols/__tests__/SymbolUtils.test.ts +10 -11
- package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +27 -4
- package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +11 -5
- package/src/transpiler/logic/symbols/cpp/__tests__/CppResolver.integration.test.ts +4 -4
- package/src/transpiler/output/codegen/CodeGenerator.ts +169 -11
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +132 -3
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +56 -31
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +12 -11
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +21 -21
- package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +2 -2
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +2 -2
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +2 -2
- package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +4 -4
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +4 -4
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +8 -8
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +5 -5
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +4 -4
- package/src/transpiler/output/codegen/generators/expressions/AccessExprGenerator.ts +7 -326
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +8 -1
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +14 -275
- package/src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts +13 -1
- package/src/transpiler/output/codegen/generators/expressions/__tests__/AccessExprGenerator.test.ts +0 -573
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +8 -439
- package/src/transpiler/output/codegen/generators/expressions/__tests__/UnaryExprGenerator.test.ts +196 -0
- package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +5 -0
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +7 -2
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +8 -1
- package/src/transpiler/output/codegen/helpers/TypedefParamParser.ts +34 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +11 -0
- package/src/transpiler/output/codegen/helpers/VariableModifierBuilder.ts +16 -1
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +48 -0
- package/src/transpiler/output/codegen/helpers/__tests__/TypedefParamParser.test.ts +88 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableModifierBuilder.test.ts +34 -2
- package/src/transpiler/output/codegen/types/TTypeInfo.ts +1 -0
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +15 -2
- package/src/transpiler/output/headers/__tests__/BaseHeaderGenerator.test.ts +87 -0
- package/src/utils/BitUtils.ts +17 -13
- package/src/utils/ExpressionUtils.ts +51 -0
- package/src/utils/__tests__/BitUtils.test.ts +56 -56
- package/src/utils/types/IParameterSymbol.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "c-next",
|
|
13
|
-
version: "0.2.
|
|
13
|
+
version: "0.2.7",
|
|
14
14
|
description: "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
15
15
|
packageManager: "npm@11.9.0",
|
|
16
16
|
type: "module",
|
|
@@ -770,18 +770,20 @@ var PathResolver = class {
|
|
|
770
770
|
return join(dirname(file.path), outputName);
|
|
771
771
|
}
|
|
772
772
|
/**
|
|
773
|
-
* Get output path for a header file (.h)
|
|
773
|
+
* Get output path for a header file (.h or .hpp)
|
|
774
774
|
* Uses headerOutDir if specified, otherwise falls back to outDir
|
|
775
775
|
*
|
|
776
776
|
* @param file - The discovered file to get header path for
|
|
777
|
+
* @param cppMode - If true, output .hpp; otherwise .h (Issue #933)
|
|
777
778
|
* @returns The full header output path
|
|
778
779
|
*/
|
|
779
|
-
getHeaderOutputPath(file) {
|
|
780
|
+
getHeaderOutputPath(file, cppMode = false) {
|
|
781
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
780
782
|
const headerDir = this.config.headerOutDir || this.config.outDir;
|
|
781
783
|
const relativePath = this.getRelativePathFromInputs(file.path);
|
|
782
784
|
if (relativePath) {
|
|
783
785
|
const strippedPath = this.stripBasePath(relativePath);
|
|
784
|
-
const outputRelative = strippedPath.replace(/\.cnx$|\.cnext$/,
|
|
786
|
+
const outputRelative = strippedPath.replace(/\.cnx$|\.cnext$/, ext);
|
|
785
787
|
const outputPath = join(headerDir, outputRelative);
|
|
786
788
|
const outputDir = dirname(outputPath);
|
|
787
789
|
if (!this.fs.exists(outputDir)) {
|
|
@@ -794,7 +796,7 @@ var PathResolver = class {
|
|
|
794
796
|
const relativeFromCwd = relative(cwd, file.path);
|
|
795
797
|
if (relativeFromCwd && !relativeFromCwd.startsWith("..")) {
|
|
796
798
|
const strippedPath = this.stripBasePath(relativeFromCwd);
|
|
797
|
-
const outputRelative = strippedPath.replace(/\.cnx$|\.cnext$/,
|
|
799
|
+
const outputRelative = strippedPath.replace(/\.cnx$|\.cnext$/, ext);
|
|
798
800
|
const outputPath2 = join(this.config.headerOutDir, outputRelative);
|
|
799
801
|
const outputDir = dirname(outputPath2);
|
|
800
802
|
if (!this.fs.exists(outputDir)) {
|
|
@@ -802,14 +804,14 @@ var PathResolver = class {
|
|
|
802
804
|
}
|
|
803
805
|
return outputPath2;
|
|
804
806
|
}
|
|
805
|
-
const headerName2 = basename2(file.path).replace(/\.cnx$|\.cnext$/,
|
|
807
|
+
const headerName2 = basename2(file.path).replace(/\.cnx$|\.cnext$/, ext);
|
|
806
808
|
const outputPath = join(this.config.headerOutDir, headerName2);
|
|
807
809
|
if (!this.fs.exists(this.config.headerOutDir)) {
|
|
808
810
|
this.fs.mkdir(this.config.headerOutDir, { recursive: true });
|
|
809
811
|
}
|
|
810
812
|
return outputPath;
|
|
811
813
|
}
|
|
812
|
-
const headerName = basename2(file.path).replace(/\.cnx$|\.cnext$/,
|
|
814
|
+
const headerName = basename2(file.path).replace(/\.cnx$|\.cnext$/, ext);
|
|
813
815
|
return join(dirname(file.path), headerName);
|
|
814
816
|
}
|
|
815
817
|
/**
|
|
@@ -113466,6 +113468,38 @@ var ExpressionUtils = class _ExpressionUtils {
|
|
|
113466
113468
|
const identifier = primary.IDENTIFIER();
|
|
113467
113469
|
return identifier?.getText() ?? null;
|
|
113468
113470
|
}
|
|
113471
|
+
/**
|
|
113472
|
+
* Collect all additive expressions from a ternary expression.
|
|
113473
|
+
*
|
|
113474
|
+
* Uses flatMap chains to traverse the expression grammar efficiently.
|
|
113475
|
+
* Useful for analyzers that need to examine operands at the additive level.
|
|
113476
|
+
*
|
|
113477
|
+
* @param ctx - The ternary expression context
|
|
113478
|
+
* @returns Array of all additive expression contexts in the tree
|
|
113479
|
+
*/
|
|
113480
|
+
static collectAdditiveExpressions(ctx) {
|
|
113481
|
+
return _ExpressionUtils.collectAdditiveFromOrExprs(ctx.orExpression());
|
|
113482
|
+
}
|
|
113483
|
+
/**
|
|
113484
|
+
* Collect additive expressions from an array of orExpression contexts.
|
|
113485
|
+
*
|
|
113486
|
+
* Internal helper that performs the actual flatMap traversal.
|
|
113487
|
+
*/
|
|
113488
|
+
static collectAdditiveFromOrExprs(orExprs) {
|
|
113489
|
+
return orExprs.flatMap((or) => or.andExpression()).flatMap((and) => and.equalityExpression()).flatMap((eq) => eq.relationalExpression()).flatMap((rel) => rel.bitwiseOrExpression()).flatMap((bor) => bor.bitwiseXorExpression()).flatMap((bxor) => bxor.bitwiseAndExpression()).flatMap((band) => band.shiftExpression()).flatMap((shift) => shift.additiveExpression());
|
|
113490
|
+
}
|
|
113491
|
+
/**
|
|
113492
|
+
* Collect all unary expressions from an orExpression context.
|
|
113493
|
+
*
|
|
113494
|
+
* Traverses through the entire expression hierarchy to find all unary expressions.
|
|
113495
|
+
* Useful for analyzers that need to examine leaf operands.
|
|
113496
|
+
*
|
|
113497
|
+
* @param orExpr - The orExpression context
|
|
113498
|
+
* @returns Array of all unary expression contexts in the tree
|
|
113499
|
+
*/
|
|
113500
|
+
static collectUnaryFromOrExpr(orExpr) {
|
|
113501
|
+
return _ExpressionUtils.collectAdditiveFromOrExprs([orExpr]).flatMap((add) => add.multiplicativeExpression()).flatMap((mul) => mul.unaryExpression());
|
|
113502
|
+
}
|
|
113469
113503
|
/**
|
|
113470
113504
|
* ADR-023: Check if an expression contains a function call anywhere in its tree.
|
|
113471
113505
|
*
|
|
@@ -114776,6 +114810,95 @@ var binaryExprGenerators = {
|
|
|
114776
114810
|
};
|
|
114777
114811
|
var BinaryExprGenerator_default = binaryExprGenerators;
|
|
114778
114812
|
|
|
114813
|
+
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114814
|
+
var CppModeHelper = class {
|
|
114815
|
+
/**
|
|
114816
|
+
* Get address-of expression for struct parameter passing.
|
|
114817
|
+
* C mode: `&expr` (pass pointer to struct)
|
|
114818
|
+
* C++ mode: `expr` (pass reference directly)
|
|
114819
|
+
*
|
|
114820
|
+
* @param expr - The expression to potentially wrap
|
|
114821
|
+
* @returns The expression with address-of operator in C mode
|
|
114822
|
+
*/
|
|
114823
|
+
static maybeAddressOf(expr) {
|
|
114824
|
+
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114825
|
+
}
|
|
114826
|
+
/**
|
|
114827
|
+
* Get dereference expression for struct parameter access.
|
|
114828
|
+
* C mode: `(*expr)` (dereference pointer)
|
|
114829
|
+
* C++ mode: `expr` (reference can be used directly)
|
|
114830
|
+
*
|
|
114831
|
+
* @param expr - The expression to potentially dereference
|
|
114832
|
+
* @returns The expression with dereference in C mode
|
|
114833
|
+
*/
|
|
114834
|
+
static maybeDereference(expr) {
|
|
114835
|
+
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114836
|
+
}
|
|
114837
|
+
/**
|
|
114838
|
+
* Get the type modifier for struct parameter declarations.
|
|
114839
|
+
* C mode: `*` (pointer type)
|
|
114840
|
+
* C++ mode: `&` (reference type)
|
|
114841
|
+
*
|
|
114842
|
+
* @returns The type modifier character
|
|
114843
|
+
*/
|
|
114844
|
+
static refOrPtr() {
|
|
114845
|
+
return CodeGenState.cppMode ? "&" : "*";
|
|
114846
|
+
}
|
|
114847
|
+
/**
|
|
114848
|
+
* Get the member access separator for struct parameters.
|
|
114849
|
+
* C mode: `->` (pointer member access)
|
|
114850
|
+
* C++ mode: `.` (reference member access)
|
|
114851
|
+
*
|
|
114852
|
+
* @returns The member access separator
|
|
114853
|
+
*/
|
|
114854
|
+
static memberSeparator() {
|
|
114855
|
+
return CodeGenState.cppMode ? "." : "->";
|
|
114856
|
+
}
|
|
114857
|
+
/**
|
|
114858
|
+
* Get NULL literal for the current mode.
|
|
114859
|
+
* C mode: `NULL`
|
|
114860
|
+
* C++ mode: `nullptr`
|
|
114861
|
+
*
|
|
114862
|
+
* @returns The null pointer literal
|
|
114863
|
+
*/
|
|
114864
|
+
static nullLiteral() {
|
|
114865
|
+
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114866
|
+
}
|
|
114867
|
+
/**
|
|
114868
|
+
* Generate a cast expression for the current mode.
|
|
114869
|
+
* C mode: `(type)expr`
|
|
114870
|
+
* C++ mode: `static_cast<type>(expr)`
|
|
114871
|
+
*
|
|
114872
|
+
* @param type - The target type
|
|
114873
|
+
* @param expr - The expression to cast
|
|
114874
|
+
* @returns The cast expression
|
|
114875
|
+
*/
|
|
114876
|
+
static cast(type, expr) {
|
|
114877
|
+
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114878
|
+
}
|
|
114879
|
+
/**
|
|
114880
|
+
* Generate a reinterpret cast expression for the current mode.
|
|
114881
|
+
* C mode: `(type)expr`
|
|
114882
|
+
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114883
|
+
*
|
|
114884
|
+
* @param type - The target type
|
|
114885
|
+
* @param expr - The expression to cast
|
|
114886
|
+
* @returns The cast expression
|
|
114887
|
+
*/
|
|
114888
|
+
static reinterpretCast(type, expr) {
|
|
114889
|
+
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114890
|
+
}
|
|
114891
|
+
/**
|
|
114892
|
+
* Check if we're in C++ mode.
|
|
114893
|
+
*
|
|
114894
|
+
* @returns True if generating C++ code
|
|
114895
|
+
*/
|
|
114896
|
+
static isCppMode() {
|
|
114897
|
+
return CodeGenState.cppMode;
|
|
114898
|
+
}
|
|
114899
|
+
};
|
|
114900
|
+
var CppModeHelper_default = CppModeHelper;
|
|
114901
|
+
|
|
114779
114902
|
// src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts
|
|
114780
114903
|
var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
114781
114904
|
if (node.postfixExpression()) {
|
|
@@ -114788,7 +114911,16 @@ var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
|
114788
114911
|
const text = node.getText();
|
|
114789
114912
|
if (text.startsWith("!")) return { code: `!${inner}`, effects: [] };
|
|
114790
114913
|
if (text.startsWith("-")) return { code: `-${inner}`, effects: [] };
|
|
114791
|
-
if (text.startsWith("~"))
|
|
114914
|
+
if (text.startsWith("~")) {
|
|
114915
|
+
const innerType = TypeResolver_default2.getUnaryExpressionType(
|
|
114916
|
+
node.unaryExpression()
|
|
114917
|
+
);
|
|
114918
|
+
if (innerType && TypeResolver_default2.isUnsignedType(innerType)) {
|
|
114919
|
+
const cType = TYPE_MAP_default[innerType] ?? innerType;
|
|
114920
|
+
return { code: CppModeHelper_default.cast(cType, `~${inner}`), effects: [] };
|
|
114921
|
+
}
|
|
114922
|
+
return { code: `~${inner}`, effects: [] };
|
|
114923
|
+
}
|
|
114792
114924
|
if (text.startsWith("&")) return { code: `&${inner}`, effects: [] };
|
|
114793
114925
|
return { code: inner, effects: [] };
|
|
114794
114926
|
};
|
|
@@ -114828,170 +114960,6 @@ var expressionGenerators = {
|
|
|
114828
114960
|
var ExpressionGenerator_default = expressionGenerators;
|
|
114829
114961
|
|
|
114830
114962
|
// src/transpiler/output/codegen/generators/expressions/AccessExprGenerator.ts
|
|
114831
|
-
var TYPE_WIDTH2 = {
|
|
114832
|
-
u8: 8,
|
|
114833
|
-
u16: 16,
|
|
114834
|
-
u32: 32,
|
|
114835
|
-
u64: 64,
|
|
114836
|
-
i8: 8,
|
|
114837
|
-
i16: 16,
|
|
114838
|
-
i32: 32,
|
|
114839
|
-
i64: 64,
|
|
114840
|
-
f32: 32,
|
|
114841
|
-
f64: 64,
|
|
114842
|
-
bool: 1
|
|
114843
|
-
};
|
|
114844
|
-
var C_TYPE_WIDTH = {
|
|
114845
|
-
uint8_t: 8,
|
|
114846
|
-
uint16_t: 16,
|
|
114847
|
-
uint32_t: 32,
|
|
114848
|
-
uint64_t: 64,
|
|
114849
|
-
int8_t: 8,
|
|
114850
|
-
int16_t: 16,
|
|
114851
|
-
int32_t: 32,
|
|
114852
|
-
int64_t: 64,
|
|
114853
|
-
float: 32,
|
|
114854
|
-
double: 64
|
|
114855
|
-
};
|
|
114856
|
-
function getTypeBitWidth(typeName) {
|
|
114857
|
-
return TYPE_WIDTH2[typeName] || C_TYPE_WIDTH[typeName] || 0;
|
|
114858
|
-
}
|
|
114859
|
-
function makeStrlenResult(expr, skipContinue) {
|
|
114860
|
-
return {
|
|
114861
|
-
code: `strlen(${expr})`,
|
|
114862
|
-
effects: [{ type: "include", header: "string" }],
|
|
114863
|
-
skipContinue
|
|
114864
|
-
};
|
|
114865
|
-
}
|
|
114866
|
-
function makeBitWidthResult(typeName, skipContinue, isElement = false) {
|
|
114867
|
-
const bitWidth = getTypeBitWidth(typeName);
|
|
114868
|
-
if (bitWidth > 0) {
|
|
114869
|
-
return { code: String(bitWidth), effects: [], skipContinue };
|
|
114870
|
-
}
|
|
114871
|
-
const typeLabel = isElement ? "element type" : "type";
|
|
114872
|
-
return {
|
|
114873
|
-
code: `/* .length: unsupported ${typeLabel} ${typeName} */0`,
|
|
114874
|
-
effects: [],
|
|
114875
|
-
skipContinue
|
|
114876
|
-
};
|
|
114877
|
-
}
|
|
114878
|
-
function handleStructMemberLength(ctx) {
|
|
114879
|
-
if (!ctx.previousStructType || !ctx.previousMemberName) {
|
|
114880
|
-
return null;
|
|
114881
|
-
}
|
|
114882
|
-
const fieldInfo = ctx.getStructFieldInfo(
|
|
114883
|
-
ctx.previousStructType,
|
|
114884
|
-
ctx.previousMemberName
|
|
114885
|
-
);
|
|
114886
|
-
if (!fieldInfo) {
|
|
114887
|
-
return null;
|
|
114888
|
-
}
|
|
114889
|
-
const { type: memberType, dimensions } = fieldInfo;
|
|
114890
|
-
const isStringField = memberType.startsWith("string<");
|
|
114891
|
-
if (dimensions && dimensions.length > 1 && isStringField) {
|
|
114892
|
-
if (ctx.subscriptDepth === 0) {
|
|
114893
|
-
return { code: String(dimensions[0]), effects: [], skipContinue: true };
|
|
114894
|
-
}
|
|
114895
|
-
return makeStrlenResult(ctx.result, true);
|
|
114896
|
-
}
|
|
114897
|
-
if (dimensions?.length === 1 && isStringField) {
|
|
114898
|
-
return makeStrlenResult(ctx.result, true);
|
|
114899
|
-
}
|
|
114900
|
-
if (dimensions && dimensions.length > 0 && ctx.subscriptDepth < dimensions.length) {
|
|
114901
|
-
return {
|
|
114902
|
-
code: String(dimensions[ctx.subscriptDepth]),
|
|
114903
|
-
effects: [],
|
|
114904
|
-
skipContinue: true
|
|
114905
|
-
};
|
|
114906
|
-
}
|
|
114907
|
-
if (dimensions && dimensions.length > 0 && ctx.subscriptDepth >= dimensions.length) {
|
|
114908
|
-
return makeBitWidthResult(memberType, true, true);
|
|
114909
|
-
}
|
|
114910
|
-
return makeBitWidthResult(memberType, true, false);
|
|
114911
|
-
}
|
|
114912
|
-
function handleStringLength(ctx, typeInfo) {
|
|
114913
|
-
if (typeInfo.arrayDimensions && typeInfo.arrayDimensions.length > 1) {
|
|
114914
|
-
if (ctx.subscriptDepth === 0) {
|
|
114915
|
-
return {
|
|
114916
|
-
code: String(typeInfo.arrayDimensions[0]),
|
|
114917
|
-
effects: [],
|
|
114918
|
-
skipContinue: false
|
|
114919
|
-
};
|
|
114920
|
-
}
|
|
114921
|
-
return makeStrlenResult(ctx.result, false);
|
|
114922
|
-
}
|
|
114923
|
-
if (ctx.currentIdentifier && ctx.lengthCache?.has(ctx.currentIdentifier)) {
|
|
114924
|
-
return {
|
|
114925
|
-
code: ctx.lengthCache.get(ctx.currentIdentifier),
|
|
114926
|
-
effects: [],
|
|
114927
|
-
skipContinue: false
|
|
114928
|
-
};
|
|
114929
|
-
}
|
|
114930
|
-
const target = ctx.currentIdentifier ?? ctx.result;
|
|
114931
|
-
return makeStrlenResult(target, false);
|
|
114932
|
-
}
|
|
114933
|
-
function handleFullySubscriptedArrayLength(ctx, typeInfo) {
|
|
114934
|
-
if (typeInfo.isEnum) {
|
|
114935
|
-
return { code: "32", effects: [], skipContinue: false };
|
|
114936
|
-
}
|
|
114937
|
-
if (typeInfo.baseType.startsWith("string<") || typeInfo.isString) {
|
|
114938
|
-
return makeStrlenResult(ctx.result, false);
|
|
114939
|
-
}
|
|
114940
|
-
let elementBitWidth = getTypeBitWidth(typeInfo.baseType);
|
|
114941
|
-
if (elementBitWidth === 0 && typeInfo.isBitmap && typeInfo.bitmapTypeName && ctx.getBitmapBitWidth) {
|
|
114942
|
-
elementBitWidth = ctx.getBitmapBitWidth(typeInfo.bitmapTypeName) || 0;
|
|
114943
|
-
}
|
|
114944
|
-
if (elementBitWidth > 0) {
|
|
114945
|
-
return { code: String(elementBitWidth), effects: [], skipContinue: false };
|
|
114946
|
-
}
|
|
114947
|
-
return {
|
|
114948
|
-
code: `/* .length: unsupported element type ${typeInfo.baseType} */0`,
|
|
114949
|
-
effects: [],
|
|
114950
|
-
skipContinue: false
|
|
114951
|
-
};
|
|
114952
|
-
}
|
|
114953
|
-
var generateLengthProperty = (ctx) => {
|
|
114954
|
-
if (ctx.mainArgsName && ctx.primaryId === ctx.mainArgsName) {
|
|
114955
|
-
return { code: "argc", effects: [], skipContinue: false };
|
|
114956
|
-
}
|
|
114957
|
-
const structResult = handleStructMemberLength(ctx);
|
|
114958
|
-
if (structResult) {
|
|
114959
|
-
return structResult;
|
|
114960
|
-
}
|
|
114961
|
-
const typeInfo = ctx.typeInfo;
|
|
114962
|
-
if (!typeInfo) {
|
|
114963
|
-
return {
|
|
114964
|
-
code: `/* .length: unknown type for ${ctx.result} */0`,
|
|
114965
|
-
effects: [],
|
|
114966
|
-
skipContinue: false
|
|
114967
|
-
};
|
|
114968
|
-
}
|
|
114969
|
-
if (typeInfo.isString) {
|
|
114970
|
-
return handleStringLength(ctx, typeInfo);
|
|
114971
|
-
}
|
|
114972
|
-
const hasDimensions = typeInfo.isArray && typeInfo.arrayDimensions && typeInfo.arrayDimensions.length > 0;
|
|
114973
|
-
if (hasDimensions && ctx.subscriptDepth < typeInfo.arrayDimensions.length) {
|
|
114974
|
-
return {
|
|
114975
|
-
code: String(typeInfo.arrayDimensions[ctx.subscriptDepth]),
|
|
114976
|
-
effects: [],
|
|
114977
|
-
skipContinue: false
|
|
114978
|
-
};
|
|
114979
|
-
}
|
|
114980
|
-
if (hasDimensions && ctx.subscriptDepth >= typeInfo.arrayDimensions.length) {
|
|
114981
|
-
return handleFullySubscriptedArrayLength(ctx, typeInfo);
|
|
114982
|
-
}
|
|
114983
|
-
if (typeInfo.isArray) {
|
|
114984
|
-
return {
|
|
114985
|
-
code: `/* .length unknown for ${ctx.currentIdentifier} */0`,
|
|
114986
|
-
effects: [],
|
|
114987
|
-
skipContinue: false
|
|
114988
|
-
};
|
|
114989
|
-
}
|
|
114990
|
-
if (typeInfo.isEnum) {
|
|
114991
|
-
return { code: "32", effects: [], skipContinue: false };
|
|
114992
|
-
}
|
|
114993
|
-
return { code: String(typeInfo.bitWidth), effects: [], skipContinue: false };
|
|
114994
|
-
};
|
|
114995
114963
|
var generateCapacityProperty = (typeInfo) => {
|
|
114996
114964
|
if (typeInfo?.isString && typeInfo.stringCapacity !== void 0) {
|
|
114997
114965
|
return { code: String(typeInfo.stringCapacity), effects: [] };
|
|
@@ -115016,7 +114984,6 @@ var generateBitmapFieldAccess = (result, fieldInfo) => {
|
|
|
115016
114984
|
}
|
|
115017
114985
|
};
|
|
115018
114986
|
var accessGenerators = {
|
|
115019
|
-
generateLengthProperty,
|
|
115020
114987
|
generateCapacityProperty,
|
|
115021
114988
|
generateSizeProperty,
|
|
115022
114989
|
generateBitmapFieldAccess
|
|
@@ -115104,7 +115071,7 @@ var CallExprUtils = class _CallExprUtils {
|
|
|
115104
115071
|
var CallExprUtils_default = CallExprUtils;
|
|
115105
115072
|
|
|
115106
115073
|
// src/transpiler/output/codegen/types/C_TYPE_WIDTH.ts
|
|
115107
|
-
var
|
|
115074
|
+
var C_TYPE_WIDTH = {
|
|
115108
115075
|
uint8_t: 8,
|
|
115109
115076
|
int8_t: 8,
|
|
115110
115077
|
uint16_t: 16,
|
|
@@ -115132,7 +115099,7 @@ var C_TYPE_WIDTH2 = {
|
|
|
115132
115099
|
"long long": 64,
|
|
115133
115100
|
"unsigned long long": 64
|
|
115134
115101
|
};
|
|
115135
|
-
var C_TYPE_WIDTH_default =
|
|
115102
|
+
var C_TYPE_WIDTH_default = C_TYPE_WIDTH;
|
|
115136
115103
|
|
|
115137
115104
|
// src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts
|
|
115138
115105
|
var wrapWithCppEnumCast = (argCode, argExpr, targetParamBaseType, orchestrator) => {
|
|
@@ -115165,13 +115132,17 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115165
115132
|
return wrapWithCppEnumCast(argCode, e, targetParam?.baseType, orchestrator);
|
|
115166
115133
|
}
|
|
115167
115134
|
let argType = orchestrator.getExpressionType(e);
|
|
115135
|
+
let isPointerVariable = false;
|
|
115136
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(argCode);
|
|
115168
115137
|
if (!argType && !argCode.startsWith("&")) {
|
|
115169
|
-
const typeInfo = CodeGenState.getVariableTypeInfo(argCode);
|
|
115170
115138
|
if (typeInfo) {
|
|
115171
115139
|
argType = typeInfo.baseType;
|
|
115172
115140
|
}
|
|
115173
115141
|
}
|
|
115174
|
-
|
|
115142
|
+
if (typeInfo?.isPointer) {
|
|
115143
|
+
isPointerVariable = true;
|
|
115144
|
+
}
|
|
115145
|
+
const needsAddressOf = argType && !argType.endsWith("*") && !argCode.startsWith("&") && !targetParam.isArray && !isPointerVariable && (orchestrator.isStructType(argType) || _parameterExpectsAddressOf(targetParam.baseType, argType, orchestrator));
|
|
115175
115146
|
if (needsAddressOf) {
|
|
115176
115147
|
argCode = `&${argCode}`;
|
|
115177
115148
|
}
|
|
@@ -115924,7 +115895,7 @@ var handleGlobalPrefix = (memberName, tracking, input, state, orchestrator) => {
|
|
|
115924
115895
|
}
|
|
115925
115896
|
return true;
|
|
115926
115897
|
};
|
|
115927
|
-
var handleThisScopeLength = (memberName, tracking,
|
|
115898
|
+
var handleThisScopeLength = (memberName, tracking, _input, state, orchestrator) => {
|
|
115928
115899
|
if (tracking.result !== "__THIS_SCOPE__" || memberName !== "length") {
|
|
115929
115900
|
return false;
|
|
115930
115901
|
}
|
|
@@ -116013,19 +115984,9 @@ var tryExplicitLengthProperty = (memberName, tracking, rootIdentifier, input, st
|
|
|
116013
115984
|
};
|
|
116014
115985
|
var tryPropertyAccess = (memberName, tracking, rootIdentifier, input, state, orchestrator, effects) => {
|
|
116015
115986
|
if (memberName === "length") {
|
|
116016
|
-
|
|
116017
|
-
|
|
116018
|
-
ctx,
|
|
116019
|
-
input,
|
|
116020
|
-
state,
|
|
116021
|
-
orchestrator,
|
|
116022
|
-
effects
|
|
115987
|
+
throw new Error(
|
|
115988
|
+
`Error: '.length' on '${tracking.result}' is deprecated. Use explicit properties: .bit_length (bit width), .byte_length (byte size), .element_count (array size), or .char_count (string length)`
|
|
116023
115989
|
);
|
|
116024
|
-
if (lengthResult !== null) {
|
|
116025
|
-
applyPropertyResult(tracking, lengthResult);
|
|
116026
|
-
return true;
|
|
116027
|
-
}
|
|
116028
|
-
return false;
|
|
116029
115990
|
}
|
|
116030
115991
|
const explicitProps = /* @__PURE__ */ new Set([
|
|
116031
115992
|
"bit_length",
|
|
@@ -116070,129 +116031,6 @@ var tryPropertyAccess = (memberName, tracking, rootIdentifier, input, state, orc
|
|
|
116070
116031
|
}
|
|
116071
116032
|
return false;
|
|
116072
116033
|
};
|
|
116073
|
-
var generateLengthProperty2 = (ctx, input, state, orchestrator, effects) => {
|
|
116074
|
-
if (state.mainArgsName && ctx.rootIdentifier === state.mainArgsName) {
|
|
116075
|
-
return "argc";
|
|
116076
|
-
}
|
|
116077
|
-
if (ctx.previousStructType && ctx.previousMemberName) {
|
|
116078
|
-
const fieldInfo = orchestrator.getStructFieldInfo(
|
|
116079
|
-
ctx.previousStructType,
|
|
116080
|
-
ctx.previousMemberName
|
|
116081
|
-
);
|
|
116082
|
-
if (fieldInfo) {
|
|
116083
|
-
return generateStructFieldLength(
|
|
116084
|
-
ctx.result,
|
|
116085
|
-
fieldInfo,
|
|
116086
|
-
ctx.subscriptDepth,
|
|
116087
|
-
input,
|
|
116088
|
-
orchestrator,
|
|
116089
|
-
effects
|
|
116090
|
-
);
|
|
116091
|
-
}
|
|
116092
|
-
}
|
|
116093
|
-
const typeInfo = ctx.resolvedIdentifier ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier) : void 0;
|
|
116094
|
-
if (!typeInfo) {
|
|
116095
|
-
return `/* .length: unknown type for ${ctx.result} */0`;
|
|
116096
|
-
}
|
|
116097
|
-
return generateTypeInfoLength(
|
|
116098
|
-
ctx.result,
|
|
116099
|
-
typeInfo,
|
|
116100
|
-
ctx.subscriptDepth,
|
|
116101
|
-
ctx.resolvedIdentifier,
|
|
116102
|
-
input,
|
|
116103
|
-
state,
|
|
116104
|
-
effects
|
|
116105
|
-
);
|
|
116106
|
-
};
|
|
116107
|
-
var generateStructFieldLength = (result, fieldInfo, subscriptDepth, input, orchestrator, effects) => {
|
|
116108
|
-
const memberType = fieldInfo.type;
|
|
116109
|
-
const dimensions = fieldInfo.dimensions;
|
|
116110
|
-
const isStringField = TypeCheckUtils_default.isString(memberType);
|
|
116111
|
-
if (dimensions?.length && dimensions.length > 1 && isStringField) {
|
|
116112
|
-
if (subscriptDepth === 0) {
|
|
116113
|
-
return String(dimensions[0]);
|
|
116114
|
-
} else {
|
|
116115
|
-
effects.push({ type: "include", header: "string" });
|
|
116116
|
-
return `strlen(${result})`;
|
|
116117
|
-
}
|
|
116118
|
-
} else if (dimensions?.length === 1 && isStringField) {
|
|
116119
|
-
effects.push({ type: "include", header: "string" });
|
|
116120
|
-
return `strlen(${result})`;
|
|
116121
|
-
} else if (dimensions?.length && dimensions.length > 0 && subscriptDepth < dimensions.length) {
|
|
116122
|
-
return String(dimensions[subscriptDepth]);
|
|
116123
|
-
} else if (dimensions?.length && dimensions.length > 0 && subscriptDepth >= dimensions.length) {
|
|
116124
|
-
return getTypeBitWidth2(memberType, input);
|
|
116125
|
-
} else {
|
|
116126
|
-
return getTypeBitWidth2(memberType, input);
|
|
116127
|
-
}
|
|
116128
|
-
};
|
|
116129
|
-
var generateTypeInfoLength = (result, typeInfo, subscriptDepth, resolvedIdentifier, input, state, effects) => {
|
|
116130
|
-
if (typeInfo.isString) {
|
|
116131
|
-
return generateStringLength(
|
|
116132
|
-
result,
|
|
116133
|
-
typeInfo,
|
|
116134
|
-
subscriptDepth,
|
|
116135
|
-
resolvedIdentifier,
|
|
116136
|
-
state
|
|
116137
|
-
);
|
|
116138
|
-
}
|
|
116139
|
-
if (typeInfo.isEnum && !typeInfo.isArray) {
|
|
116140
|
-
return "32";
|
|
116141
|
-
}
|
|
116142
|
-
if (!typeInfo.isArray) {
|
|
116143
|
-
return String(typeInfo.bitWidth || 0);
|
|
116144
|
-
}
|
|
116145
|
-
const dims = typeInfo.arrayDimensions;
|
|
116146
|
-
if (!dims || dims.length === 0) {
|
|
116147
|
-
return `/* .length unknown for ${resolvedIdentifier} */0`;
|
|
116148
|
-
}
|
|
116149
|
-
if (subscriptDepth < dims.length) {
|
|
116150
|
-
return String(dims[subscriptDepth]);
|
|
116151
|
-
}
|
|
116152
|
-
return generateElementTypeLength(result, typeInfo, input, effects);
|
|
116153
|
-
};
|
|
116154
|
-
var generateStringLength = (result, typeInfo, subscriptDepth, resolvedIdentifier, state) => {
|
|
116155
|
-
const dims = typeInfo.arrayDimensions;
|
|
116156
|
-
if (dims && dims.length > 1) {
|
|
116157
|
-
return subscriptDepth === 0 ? String(dims[0]) : `strlen(${result})`;
|
|
116158
|
-
}
|
|
116159
|
-
if (subscriptDepth > 0) {
|
|
116160
|
-
return `strlen(${result})`;
|
|
116161
|
-
}
|
|
116162
|
-
if (resolvedIdentifier && state.lengthCache?.has(resolvedIdentifier)) {
|
|
116163
|
-
return state.lengthCache.get(resolvedIdentifier);
|
|
116164
|
-
}
|
|
116165
|
-
return resolvedIdentifier ? `strlen(${resolvedIdentifier})` : `strlen(${result})`;
|
|
116166
|
-
};
|
|
116167
|
-
var generateElementTypeLength = (result, typeInfo, input, effects) => {
|
|
116168
|
-
if (typeInfo.isEnum) {
|
|
116169
|
-
return "32";
|
|
116170
|
-
}
|
|
116171
|
-
if (TypeCheckUtils_default.isString(typeInfo.baseType) || typeInfo.isString) {
|
|
116172
|
-
effects.push({ type: "include", header: "string" });
|
|
116173
|
-
return `strlen(${result})`;
|
|
116174
|
-
}
|
|
116175
|
-
let elementBitWidth = TYPE_WIDTH_default[typeInfo.baseType] || 0;
|
|
116176
|
-
if (elementBitWidth === 0 && typeInfo.isBitmap && typeInfo.bitmapTypeName) {
|
|
116177
|
-
elementBitWidth = input.symbols.bitmapBitWidth.get(typeInfo.bitmapTypeName) || 0;
|
|
116178
|
-
}
|
|
116179
|
-
if (elementBitWidth > 0) {
|
|
116180
|
-
return String(elementBitWidth);
|
|
116181
|
-
}
|
|
116182
|
-
return `/* .length: unsupported element type ${typeInfo.baseType} */0`;
|
|
116183
|
-
};
|
|
116184
|
-
var getTypeBitWidth2 = (typeName, input) => {
|
|
116185
|
-
let bitWidth = TYPE_WIDTH_default[typeName] || C_TYPE_WIDTH_default[typeName] || 0;
|
|
116186
|
-
if (bitWidth === 0 && input.symbolTable) {
|
|
116187
|
-
const enumWidth = input.symbolTable.getEnumBitWidth(typeName);
|
|
116188
|
-
if (enumWidth) bitWidth = enumWidth;
|
|
116189
|
-
}
|
|
116190
|
-
if (bitWidth > 0) {
|
|
116191
|
-
return String(bitWidth);
|
|
116192
|
-
} else {
|
|
116193
|
-
return `/* .length: unsupported type ${typeName} */0`;
|
|
116194
|
-
}
|
|
116195
|
-
};
|
|
116196
116034
|
var getNumericBitWidth = (typeName, input) => {
|
|
116197
116035
|
let bitWidth = TYPE_WIDTH_default[typeName] ?? C_TYPE_WIDTH_default[typeName] ?? 0;
|
|
116198
116036
|
if (bitWidth === 0 && input.symbolTable) {
|
|
@@ -116468,11 +116306,10 @@ var generateCharCountProperty = (ctx, input, state, orchestrator, effects) => {
|
|
|
116468
116306
|
);
|
|
116469
116307
|
}
|
|
116470
116308
|
effects.push({ type: "include", header: "string" });
|
|
116471
|
-
if (ctx.resolvedIdentifier && state.lengthCache?.has(ctx.resolvedIdentifier)) {
|
|
116309
|
+
if (ctx.subscriptDepth === 0 && ctx.resolvedIdentifier && state.lengthCache?.has(ctx.resolvedIdentifier)) {
|
|
116472
116310
|
return state.lengthCache.get(ctx.resolvedIdentifier);
|
|
116473
116311
|
}
|
|
116474
|
-
|
|
116475
|
-
return `strlen(${target})`;
|
|
116312
|
+
return `strlen(${ctx.result})`;
|
|
116476
116313
|
};
|
|
116477
116314
|
var initializeMemberOutput = (ctx) => ({
|
|
116478
116315
|
result: ctx.result,
|
|
@@ -116861,15 +116698,18 @@ var VariableModifierBuilder = class {
|
|
|
116861
116698
|
*
|
|
116862
116699
|
* @param ctx - Parser context with modifier methods
|
|
116863
116700
|
* @param inFunctionBody - Whether we're inside a function body (affects extern)
|
|
116701
|
+
* @param hasInitializer - Whether the variable has an initializer (affects extern in C mode)
|
|
116702
|
+
* @param cppMode - Whether we're generating C++ code (affects extern behavior)
|
|
116864
116703
|
* @returns Modifier strings ready for use in generated code
|
|
116865
116704
|
* @throws Error if both atomic and volatile are specified
|
|
116866
116705
|
*/
|
|
116867
|
-
static build(ctx, inFunctionBody) {
|
|
116706
|
+
static build(ctx, inFunctionBody, hasInitializer = false, cppMode = false) {
|
|
116868
116707
|
const hasConst = ctx.constModifier?.() ?? false;
|
|
116869
116708
|
const constMod = hasConst ? "const " : "";
|
|
116870
116709
|
const atomicMod = ctx.atomicModifier() ? "volatile " : "";
|
|
116871
116710
|
const volatileMod = ctx.volatileModifier() ? "volatile " : "";
|
|
116872
|
-
const
|
|
116711
|
+
const needsExtern = hasConst && !inFunctionBody && (cppMode || !hasInitializer);
|
|
116712
|
+
const externMod = needsExtern ? "extern " : "";
|
|
116873
116713
|
if (ctx.atomicModifier() && ctx.volatileModifier()) {
|
|
116874
116714
|
const line = ctx.start?.line ?? 0;
|
|
116875
116715
|
throw new Error(
|
|
@@ -118057,16 +117897,17 @@ var ScopeGenerator_default = generateScope;
|
|
|
118057
117897
|
// src/utils/BitUtils.ts
|
|
118058
117898
|
var BitUtils = class _BitUtils {
|
|
118059
117899
|
/**
|
|
118060
|
-
* Convert a boolean expression to an integer (
|
|
117900
|
+
* Convert a boolean expression to an unsigned integer (0U or 1U).
|
|
118061
117901
|
* Handles literal "true"/"false" and generates ternary for expressions.
|
|
117902
|
+
* Uses unsigned literals for MISRA C:2012 Rule 10.1 compliance.
|
|
118062
117903
|
*
|
|
118063
117904
|
* @param expr - The expression to convert
|
|
118064
|
-
* @returns C code string representing the integer value
|
|
117905
|
+
* @returns C code string representing the unsigned integer value
|
|
118065
117906
|
*/
|
|
118066
117907
|
static boolToInt(expr) {
|
|
118067
|
-
if (expr === "true") return "
|
|
118068
|
-
if (expr === "false") return "
|
|
118069
|
-
return `(${expr} ?
|
|
117908
|
+
if (expr === "true") return "1U";
|
|
117909
|
+
if (expr === "false") return "0U";
|
|
117910
|
+
return `(${expr} ? 1U : 0U)`;
|
|
118070
117911
|
}
|
|
118071
117912
|
/**
|
|
118072
117913
|
* Generate a bit mask for the given width.
|
|
@@ -118123,24 +117964,26 @@ var BitUtils = class _BitUtils {
|
|
|
118123
117964
|
}
|
|
118124
117965
|
}
|
|
118125
117966
|
/**
|
|
118126
|
-
* Return the appropriate "1" literal for a given type.
|
|
118127
|
-
* Uses "1ULL" for 64-bit types
|
|
117967
|
+
* Return the appropriate unsigned "1" literal for a given type.
|
|
117968
|
+
* Uses "1ULL" for 64-bit types, "1U" for others.
|
|
117969
|
+
* MISRA C:2012 Rule 10.1 requires unsigned operands for bitwise operations.
|
|
118128
117970
|
*
|
|
118129
117971
|
* @param typeName - The C-Next type name (e.g., "u64", "i32")
|
|
118130
|
-
* @returns "1ULL" for 64-bit types, "
|
|
117972
|
+
* @returns "1ULL" for 64-bit types, "1U" otherwise
|
|
118131
117973
|
*/
|
|
118132
117974
|
static oneForType(typeName) {
|
|
118133
|
-
return typeName === "u64" || typeName === "i64" ? "1ULL" : "
|
|
117975
|
+
return typeName === "u64" || typeName === "i64" ? "1ULL" : "1U";
|
|
118134
117976
|
}
|
|
118135
117977
|
/**
|
|
118136
|
-
* Format a number as an uppercase hex string (e.g., 255 -> "
|
|
117978
|
+
* Format a number as an unsigned uppercase hex string (e.g., 255 -> "0xFFU").
|
|
118137
117979
|
* Used for generating hex mask literals in generated C code.
|
|
117980
|
+
* Includes U suffix for MISRA C:2012 Rule 10.1 compliance.
|
|
118138
117981
|
*
|
|
118139
117982
|
* @param value - The numeric value to format
|
|
118140
|
-
* @returns Hex string like "
|
|
117983
|
+
* @returns Hex string like "0xFFU" or "0x1FU"
|
|
118141
117984
|
*/
|
|
118142
117985
|
static formatHex(value) {
|
|
118143
|
-
return `0x${value.toString(16).toUpperCase()}`;
|
|
117986
|
+
return `0x${value.toString(16).toUpperCase()}U`;
|
|
118144
117987
|
}
|
|
118145
117988
|
/**
|
|
118146
117989
|
* Generate code to read a single bit from a value.
|
|
@@ -118186,7 +118029,7 @@ var BitUtils = class _BitUtils {
|
|
|
118186
118029
|
static singleBitWrite(target, offset, value, targetType) {
|
|
118187
118030
|
const intValue = _BitUtils.boolToInt(value);
|
|
118188
118031
|
const is64Bit = targetType === "u64" || targetType === "i64";
|
|
118189
|
-
const one = is64Bit ? "1ULL" : "
|
|
118032
|
+
const one = is64Bit ? "1ULL" : "1U";
|
|
118190
118033
|
const valueShift = is64Bit ? `((uint64_t)${intValue} << ${offset})` : `(${intValue} << ${offset})`;
|
|
118191
118034
|
return `${target} = (${target} & ~(${one} << ${offset})) | ${valueShift};`;
|
|
118192
118035
|
}
|
|
@@ -120870,7 +120713,7 @@ function getBitmapFieldInfo(bitmapType, fieldName, ctx) {
|
|
|
120870
120713
|
function generateBitmapWrite(target, fieldInfo, value) {
|
|
120871
120714
|
const { maskHex } = calculateMask(fieldInfo.width);
|
|
120872
120715
|
if (fieldInfo.width === 1) {
|
|
120873
|
-
return `${target} = (${target} & ~(
|
|
120716
|
+
return `${target} = (${target} & ~(1U << ${fieldInfo.offset})) | (${BitUtils_default.boolToInt(value)} << ${fieldInfo.offset});`;
|
|
120874
120717
|
} else {
|
|
120875
120718
|
return `${target} = (${target} & ~(${maskHex} << ${fieldInfo.offset})) | ((${value} & ${maskHex}) << ${fieldInfo.offset});`;
|
|
120876
120719
|
}
|
|
@@ -121123,9 +120966,9 @@ function handleRegisterBit(ctx) {
|
|
|
121123
120966
|
bitIndex,
|
|
121124
120967
|
true
|
|
121125
120968
|
);
|
|
121126
|
-
return `${fullName} = (
|
|
120969
|
+
return `${fullName} = (1U << ${bitIndex});`;
|
|
121127
120970
|
}
|
|
121128
|
-
return `${fullName} = (${fullName} & ~(
|
|
120971
|
+
return `${fullName} = (${fullName} & ~(1U << ${bitIndex})) | (${BitUtils_default.boolToInt(ctx.generatedValue)} << ${bitIndex});`;
|
|
121129
120972
|
}
|
|
121130
120973
|
function handleRegisterBitRange(ctx) {
|
|
121131
120974
|
AssignmentHandlerUtils_default.validateNoCompoundForBitAccess(
|
|
@@ -121191,9 +121034,9 @@ function handleScopedRegisterBit(ctx) {
|
|
|
121191
121034
|
bitIndex,
|
|
121192
121035
|
true
|
|
121193
121036
|
);
|
|
121194
|
-
return `${regName} = (
|
|
121037
|
+
return `${regName} = (1U << ${bitIndex});`;
|
|
121195
121038
|
}
|
|
121196
|
-
return `${regName} = (${regName} & ~(
|
|
121039
|
+
return `${regName} = (${regName} & ~(1U << ${bitIndex})) | (${BitUtils_default.boolToInt(ctx.generatedValue)} << ${bitIndex});`;
|
|
121197
121040
|
}
|
|
121198
121041
|
function handleScopedRegisterBitRange(ctx) {
|
|
121199
121042
|
AssignmentHandlerUtils_default.validateScopeContext(CodeGenState.currentScope);
|
|
@@ -121439,7 +121282,7 @@ function handleStructMemberBit(ctx) {
|
|
|
121439
121282
|
validateNotCompound2(ctx);
|
|
121440
121283
|
const target = gen6().generateAssignmentTarget(ctx.targetCtx);
|
|
121441
121284
|
const bitIndex = gen6().generateExpression(ctx.subscripts.at(-1));
|
|
121442
|
-
const one = "
|
|
121285
|
+
const one = "1U";
|
|
121443
121286
|
const intValue = BitUtils_default.boolToInt(ctx.generatedValue);
|
|
121444
121287
|
return `${target} = (${target} & ~(${one} << ${bitIndex})) | (${intValue} << ${bitIndex});`;
|
|
121445
121288
|
}
|
|
@@ -121687,9 +121530,9 @@ function handleGlobalRegisterBit(ctx) {
|
|
|
121687
121530
|
`Cannot assign false to write-only register bit ${regName}[${bitIndex}]. Use the corresponding CLEAR register to clear bits.`
|
|
121688
121531
|
);
|
|
121689
121532
|
}
|
|
121690
|
-
return `${regName} = (
|
|
121533
|
+
return `${regName} = (1U << ${bitIndex});`;
|
|
121691
121534
|
}
|
|
121692
|
-
return `${regName} = (${regName} & ~(
|
|
121535
|
+
return `${regName} = (${regName} & ~(1U << ${bitIndex})) | (${BitUtils_default.boolToInt(ctx.generatedValue)} << ${bitIndex});`;
|
|
121693
121536
|
}
|
|
121694
121537
|
function handleMemberChain(ctx) {
|
|
121695
121538
|
const bitAnalysis = gen9().analyzeMemberChainForBitAccess(ctx.targetCtx);
|
|
@@ -122361,7 +122204,7 @@ var AssignmentContextBuilder_default = buildAssignmentContext;
|
|
|
122361
122204
|
// src/transpiler/output/codegen/analysis/StringLengthCounter.ts
|
|
122362
122205
|
var StringLengthCounter = class _StringLengthCounter {
|
|
122363
122206
|
/**
|
|
122364
|
-
* Count .
|
|
122207
|
+
* Count .char_count accesses in an expression.
|
|
122365
122208
|
*/
|
|
122366
122209
|
static countExpression(ctx) {
|
|
122367
122210
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -122369,7 +122212,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122369
122212
|
return counts;
|
|
122370
122213
|
}
|
|
122371
122214
|
/**
|
|
122372
|
-
* Count .
|
|
122215
|
+
* Count .char_count accesses in a block.
|
|
122373
122216
|
*/
|
|
122374
122217
|
static countBlock(ctx) {
|
|
122375
122218
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -122379,7 +122222,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122379
122222
|
return counts;
|
|
122380
122223
|
}
|
|
122381
122224
|
/**
|
|
122382
|
-
* Count .
|
|
122225
|
+
* Count .char_count accesses in a block, adding to existing counts.
|
|
122383
122226
|
*/
|
|
122384
122227
|
static countBlockInto(ctx, counts) {
|
|
122385
122228
|
for (const stmt of ctx.statement()) {
|
|
@@ -122387,7 +122230,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122387
122230
|
}
|
|
122388
122231
|
}
|
|
122389
122232
|
/**
|
|
122390
|
-
* Walk an expression tree, counting .
|
|
122233
|
+
* Walk an expression tree, counting .char_count accesses.
|
|
122391
122234
|
* Uses generic traversal - only postfix expressions need special handling.
|
|
122392
122235
|
*/
|
|
122393
122236
|
static walkExpression(ctx, counts) {
|
|
@@ -122462,7 +122305,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122462
122305
|
}
|
|
122463
122306
|
}
|
|
122464
122307
|
/**
|
|
122465
|
-
* Walk a postfix expression - this is where we detect .
|
|
122308
|
+
* Walk a postfix expression - this is where we detect .char_count accesses.
|
|
122466
122309
|
*/
|
|
122467
122310
|
static walkPostfixExpr(ctx, counts) {
|
|
122468
122311
|
const primary = ctx.primaryExpression();
|
|
@@ -122471,7 +122314,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122471
122314
|
if (primaryId && ops.length > 0) {
|
|
122472
122315
|
for (const op of ops) {
|
|
122473
122316
|
const memberName = op.IDENTIFIER()?.getText();
|
|
122474
|
-
if (memberName === "
|
|
122317
|
+
if (memberName === "char_count") {
|
|
122475
122318
|
const typeInfo = CodeGenState.getVariableTypeInfo(primaryId);
|
|
122476
122319
|
if (typeInfo?.isString) {
|
|
122477
122320
|
const currentCount = counts.get(primaryId) || 0;
|
|
@@ -122488,7 +122331,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122488
122331
|
}
|
|
122489
122332
|
}
|
|
122490
122333
|
/**
|
|
122491
|
-
* Walk a statement, counting .
|
|
122334
|
+
* Walk a statement, counting .char_count accesses.
|
|
122492
122335
|
*/
|
|
122493
122336
|
static walkStatement(ctx, counts) {
|
|
122494
122337
|
if (ctx.assignmentStatement()) {
|
|
@@ -122520,95 +122363,6 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122520
122363
|
};
|
|
122521
122364
|
var StringLengthCounter_default = StringLengthCounter;
|
|
122522
122365
|
|
|
122523
|
-
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
122524
|
-
var CppModeHelper = class {
|
|
122525
|
-
/**
|
|
122526
|
-
* Get address-of expression for struct parameter passing.
|
|
122527
|
-
* C mode: `&expr` (pass pointer to struct)
|
|
122528
|
-
* C++ mode: `expr` (pass reference directly)
|
|
122529
|
-
*
|
|
122530
|
-
* @param expr - The expression to potentially wrap
|
|
122531
|
-
* @returns The expression with address-of operator in C mode
|
|
122532
|
-
*/
|
|
122533
|
-
static maybeAddressOf(expr) {
|
|
122534
|
-
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
122535
|
-
}
|
|
122536
|
-
/**
|
|
122537
|
-
* Get dereference expression for struct parameter access.
|
|
122538
|
-
* C mode: `(*expr)` (dereference pointer)
|
|
122539
|
-
* C++ mode: `expr` (reference can be used directly)
|
|
122540
|
-
*
|
|
122541
|
-
* @param expr - The expression to potentially dereference
|
|
122542
|
-
* @returns The expression with dereference in C mode
|
|
122543
|
-
*/
|
|
122544
|
-
static maybeDereference(expr) {
|
|
122545
|
-
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
122546
|
-
}
|
|
122547
|
-
/**
|
|
122548
|
-
* Get the type modifier for struct parameter declarations.
|
|
122549
|
-
* C mode: `*` (pointer type)
|
|
122550
|
-
* C++ mode: `&` (reference type)
|
|
122551
|
-
*
|
|
122552
|
-
* @returns The type modifier character
|
|
122553
|
-
*/
|
|
122554
|
-
static refOrPtr() {
|
|
122555
|
-
return CodeGenState.cppMode ? "&" : "*";
|
|
122556
|
-
}
|
|
122557
|
-
/**
|
|
122558
|
-
* Get the member access separator for struct parameters.
|
|
122559
|
-
* C mode: `->` (pointer member access)
|
|
122560
|
-
* C++ mode: `.` (reference member access)
|
|
122561
|
-
*
|
|
122562
|
-
* @returns The member access separator
|
|
122563
|
-
*/
|
|
122564
|
-
static memberSeparator() {
|
|
122565
|
-
return CodeGenState.cppMode ? "." : "->";
|
|
122566
|
-
}
|
|
122567
|
-
/**
|
|
122568
|
-
* Get NULL literal for the current mode.
|
|
122569
|
-
* C mode: `NULL`
|
|
122570
|
-
* C++ mode: `nullptr`
|
|
122571
|
-
*
|
|
122572
|
-
* @returns The null pointer literal
|
|
122573
|
-
*/
|
|
122574
|
-
static nullLiteral() {
|
|
122575
|
-
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
122576
|
-
}
|
|
122577
|
-
/**
|
|
122578
|
-
* Generate a cast expression for the current mode.
|
|
122579
|
-
* C mode: `(type)expr`
|
|
122580
|
-
* C++ mode: `static_cast<type>(expr)`
|
|
122581
|
-
*
|
|
122582
|
-
* @param type - The target type
|
|
122583
|
-
* @param expr - The expression to cast
|
|
122584
|
-
* @returns The cast expression
|
|
122585
|
-
*/
|
|
122586
|
-
static cast(type, expr) {
|
|
122587
|
-
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
122588
|
-
}
|
|
122589
|
-
/**
|
|
122590
|
-
* Generate a reinterpret cast expression for the current mode.
|
|
122591
|
-
* C mode: `(type)expr`
|
|
122592
|
-
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
122593
|
-
*
|
|
122594
|
-
* @param type - The target type
|
|
122595
|
-
* @param expr - The expression to cast
|
|
122596
|
-
* @returns The cast expression
|
|
122597
|
-
*/
|
|
122598
|
-
static reinterpretCast(type, expr) {
|
|
122599
|
-
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
122600
|
-
}
|
|
122601
|
-
/**
|
|
122602
|
-
* Check if we're in C++ mode.
|
|
122603
|
-
*
|
|
122604
|
-
* @returns True if generating C++ code
|
|
122605
|
-
*/
|
|
122606
|
-
static isCppMode() {
|
|
122607
|
-
return CodeGenState.cppMode;
|
|
122608
|
-
}
|
|
122609
|
-
};
|
|
122610
|
-
var CppModeHelper_default = CppModeHelper;
|
|
122611
|
-
|
|
122612
122366
|
// src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts
|
|
122613
122367
|
var MemberChainAnalyzer = class _MemberChainAnalyzer {
|
|
122614
122368
|
/**
|
|
@@ -122839,6 +122593,9 @@ var ArgumentGenerator = class _ArgumentGenerator {
|
|
|
122839
122593
|
if (typeInfo?.isArray && !typeInfo.isString) {
|
|
122840
122594
|
return id;
|
|
122841
122595
|
}
|
|
122596
|
+
if (typeInfo?.isPointer) {
|
|
122597
|
+
return id;
|
|
122598
|
+
}
|
|
122842
122599
|
if (CodeGenState.currentScope) {
|
|
122843
122600
|
const members = CodeGenState.getScopeMembers(CodeGenState.currentScope);
|
|
122844
122601
|
if (members?.has(id)) {
|
|
@@ -124105,7 +123862,11 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
124105
123862
|
initValue,
|
|
124106
123863
|
arrayDims
|
|
124107
123864
|
);
|
|
124108
|
-
|
|
123865
|
+
const suppression = "// cppcheck-suppress misra-c2012-9.3\n// cppcheck-suppress misra-c2012-9.4\n";
|
|
123866
|
+
return {
|
|
123867
|
+
code: `${suppression}${decl} = ${finalInitValue};`,
|
|
123868
|
+
handled: true
|
|
123869
|
+
};
|
|
124109
123870
|
}
|
|
124110
123871
|
/**
|
|
124111
123872
|
* Handle size inference for empty array dimension.
|
|
@@ -124581,15 +124342,21 @@ ${assignments}`;
|
|
|
124581
124342
|
{ generateType: callbacks.generateType }
|
|
124582
124343
|
);
|
|
124583
124344
|
}
|
|
124345
|
+
const hasInitializer = ctx.expression() !== null;
|
|
124584
124346
|
const modifiers = VariableModifierBuilder_default.build(
|
|
124585
124347
|
ctx,
|
|
124586
|
-
CodeGenState.inFunctionBody
|
|
124348
|
+
CodeGenState.inFunctionBody,
|
|
124349
|
+
hasInitializer,
|
|
124350
|
+
CodeGenState.cppMode
|
|
124587
124351
|
);
|
|
124588
124352
|
const name = ctx.IDENTIFIER().getText();
|
|
124589
124353
|
const typeCtx = ctx.type();
|
|
124590
124354
|
_VariableDeclHelper.validateArrayDeclarationSyntax(ctx, typeCtx, name);
|
|
124591
124355
|
const type = callbacks.inferVariableType(ctx, name);
|
|
124592
124356
|
callbacks.trackLocalVariable(ctx, name);
|
|
124357
|
+
if (type.endsWith("*")) {
|
|
124358
|
+
callbacks.markVariableAsPointer(name);
|
|
124359
|
+
}
|
|
124593
124360
|
const stringResult = StringDeclHelper_default.generateStringDecl(
|
|
124594
124361
|
typeCtx,
|
|
124595
124362
|
name,
|
|
@@ -125625,6 +125392,33 @@ var TypedefParamParser = class _TypedefParamParser {
|
|
|
125625
125392
|
static shouldBeConst(typedefType, paramIndex) {
|
|
125626
125393
|
return _TypedefParamParser.getParamAt(typedefType, paramIndex)?.isConst ?? null;
|
|
125627
125394
|
}
|
|
125395
|
+
/**
|
|
125396
|
+
* Resolve callback pointer/const overrides onto an array of IParameterSymbol.
|
|
125397
|
+
*
|
|
125398
|
+
* Issue #914: This is the single point where callback typedef info is applied
|
|
125399
|
+
* to parameters — used by both .c and .h generation paths via IParameterSymbol.
|
|
125400
|
+
*
|
|
125401
|
+
* @param params - The original parameter symbols
|
|
125402
|
+
* @param callbackTypedefType - The typedef type string (e.g., "void (*)(widget_t *, const rect_t *)")
|
|
125403
|
+
* @returns New array with isCallbackPointer/isCallbackConst resolved
|
|
125404
|
+
*/
|
|
125405
|
+
static resolveCallbackParams(params, callbackTypedefType) {
|
|
125406
|
+
return params.map((param, index) => {
|
|
125407
|
+
const shouldBePointer = _TypedefParamParser.shouldBePointer(
|
|
125408
|
+
callbackTypedefType,
|
|
125409
|
+
index
|
|
125410
|
+
);
|
|
125411
|
+
const shouldBeConst = _TypedefParamParser.shouldBeConst(
|
|
125412
|
+
callbackTypedefType,
|
|
125413
|
+
index
|
|
125414
|
+
);
|
|
125415
|
+
return {
|
|
125416
|
+
...param,
|
|
125417
|
+
isCallbackPointer: shouldBePointer ?? void 0,
|
|
125418
|
+
isCallbackConst: shouldBeConst ?? void 0
|
|
125419
|
+
};
|
|
125420
|
+
});
|
|
125421
|
+
}
|
|
125628
125422
|
};
|
|
125629
125423
|
var TypedefParamParser_default = TypedefParamParser;
|
|
125630
125424
|
|
|
@@ -126396,7 +126190,7 @@ var PassByValueAnalyzer = class _PassByValueAnalyzer {
|
|
|
126396
126190
|
* Used by both function call tracking and subscript access tracking.
|
|
126397
126191
|
*/
|
|
126398
126192
|
static walkOrExpression(orExpr, handler) {
|
|
126399
|
-
|
|
126193
|
+
ExpressionUtils_default.collectUnaryFromOrExpr(orExpr).forEach(handler);
|
|
126400
126194
|
}
|
|
126401
126195
|
/**
|
|
126402
126196
|
* Walk an orExpression tree for function calls.
|
|
@@ -126751,6 +126545,7 @@ var ParameterInputAdapter = class {
|
|
|
126751
126545
|
isPassByReference: false
|
|
126752
126546
|
};
|
|
126753
126547
|
}
|
|
126548
|
+
const isCallbackPointer = param.isCallbackPointer ?? false;
|
|
126754
126549
|
return {
|
|
126755
126550
|
name: param.name,
|
|
126756
126551
|
baseType: param.type,
|
|
@@ -126760,8 +126555,10 @@ var ParameterInputAdapter = class {
|
|
|
126760
126555
|
isArray: false,
|
|
126761
126556
|
isCallback: false,
|
|
126762
126557
|
isString: false,
|
|
126763
|
-
isPassByValue: deps.isPassByValue,
|
|
126764
|
-
isPassByReference: !deps.isPassByValue
|
|
126558
|
+
isPassByValue: isCallbackPointer ? false : deps.isPassByValue,
|
|
126559
|
+
isPassByReference: isCallbackPointer ? true : !deps.isPassByValue,
|
|
126560
|
+
forcePointerSyntax: isCallbackPointer || void 0,
|
|
126561
|
+
forceConst: param.isCallbackConst || void 0
|
|
126765
126562
|
};
|
|
126766
126563
|
}
|
|
126767
126564
|
/**
|
|
@@ -127571,7 +127368,7 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
127571
127368
|
if (!arrayAccessMatch) {
|
|
127572
127369
|
return false;
|
|
127573
127370
|
}
|
|
127574
|
-
if (text.endsWith(".length") || text.endsWith(".capacity") || text.endsWith(".size")) {
|
|
127371
|
+
if (text.endsWith(".length") || text.endsWith(".capacity") || text.endsWith(".size") || text.endsWith(".bit_length") || text.endsWith(".byte_length") || text.endsWith(".element_count") || text.endsWith(".char_count")) {
|
|
127575
127372
|
return false;
|
|
127576
127373
|
}
|
|
127577
127374
|
const arrayName = arrayAccessMatch[1];
|
|
@@ -128631,7 +128428,8 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128631
128428
|
);
|
|
128632
128429
|
if (symbols.hasPublicSymbols() && CodeGenState.sourcePath) {
|
|
128633
128430
|
const pathToUse = options?.sourceRelativePath || CodeGenState.sourcePath.replace(/^.*[\\/]/, "");
|
|
128634
|
-
const
|
|
128431
|
+
const ext = CodeGenState.cppMode ? ".hpp" : ".h";
|
|
128432
|
+
const headerName = pathToUse.replace(/\.cnx$|\.cnext$/, ext);
|
|
128635
128433
|
output.push(`#include "${headerName}"`, "");
|
|
128636
128434
|
CodeGenState.selfIncludeAdded = true;
|
|
128637
128435
|
}
|
|
@@ -129771,6 +129569,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129771
129569
|
getExpressionType: (exprCtx) => this.getExpressionType(exprCtx),
|
|
129772
129570
|
inferVariableType: (varCtx, name) => this._inferVariableType(varCtx, name),
|
|
129773
129571
|
trackLocalVariable: (varCtx, name) => this._trackLocalVariable(varCtx, name),
|
|
129572
|
+
markVariableAsPointer: (name) => this._markVariableAsPointer(name),
|
|
129774
129573
|
getStringConcatOperands: (concatCtx) => this._getStringConcatOperands(concatCtx),
|
|
129775
129574
|
getSubstringOperands: (substrCtx) => this._getSubstringOperands(substrCtx),
|
|
129776
129575
|
getStringExprCapacity: (exprCode) => this.getStringExprCapacity(exprCode),
|
|
@@ -129779,20 +129578,116 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129779
129578
|
}
|
|
129780
129579
|
/**
|
|
129781
129580
|
* Issue #696: Infer variable type, handling nullable C pointer types.
|
|
129581
|
+
* Issue #895 Bug B: Infer pointer type from C function return type.
|
|
129782
129582
|
*/
|
|
129783
129583
|
_inferVariableType(ctx, name) {
|
|
129784
|
-
|
|
129785
|
-
if (!
|
|
129584
|
+
const type = this.generateType(ctx.type());
|
|
129585
|
+
if (!ctx.expression()) {
|
|
129786
129586
|
return type;
|
|
129787
129587
|
}
|
|
129788
|
-
const
|
|
129789
|
-
|
|
129790
|
-
|
|
129791
|
-
|
|
129588
|
+
const pointerType = this._inferPointerTypeFromFunctionCall(
|
|
129589
|
+
ctx.expression(),
|
|
129590
|
+
type
|
|
129591
|
+
);
|
|
129592
|
+
if (pointerType) {
|
|
129593
|
+
return pointerType;
|
|
129594
|
+
}
|
|
129595
|
+
if (name.startsWith("c_")) {
|
|
129596
|
+
const exprText = ctx.expression().getText();
|
|
129597
|
+
for (const funcName of NullCheckAnalyzer_default.getStructPointerFunctions()) {
|
|
129598
|
+
if (exprText.includes(`${funcName}(`)) {
|
|
129599
|
+
return `${type}*`;
|
|
129600
|
+
}
|
|
129792
129601
|
}
|
|
129793
129602
|
}
|
|
129794
129603
|
return type;
|
|
129795
129604
|
}
|
|
129605
|
+
/**
|
|
129606
|
+
* Issue #895 Bug B: Infer pointer type from C function return type.
|
|
129607
|
+
* If initializer is a call to a C function that returns T*, and declared
|
|
129608
|
+
* type is T, return T* instead of T.
|
|
129609
|
+
*/
|
|
129610
|
+
_inferPointerTypeFromFunctionCall(expr, declaredType) {
|
|
129611
|
+
const funcName = this._extractCFunctionName(expr);
|
|
129612
|
+
if (!funcName) {
|
|
129613
|
+
return null;
|
|
129614
|
+
}
|
|
129615
|
+
const cFunc = CodeGenState.symbolTable?.getCSymbol(funcName);
|
|
129616
|
+
if (cFunc?.kind !== "function") {
|
|
129617
|
+
return null;
|
|
129618
|
+
}
|
|
129619
|
+
const returnType = cFunc.type;
|
|
129620
|
+
if (!returnType.endsWith("*")) {
|
|
129621
|
+
return null;
|
|
129622
|
+
}
|
|
129623
|
+
const returnBaseType = returnType.replace(/\s*\*\s*$/, "").trim();
|
|
129624
|
+
if (returnBaseType === declaredType) {
|
|
129625
|
+
return `${declaredType}*`;
|
|
129626
|
+
}
|
|
129627
|
+
return null;
|
|
129628
|
+
}
|
|
129629
|
+
/**
|
|
129630
|
+
* Extract C function name from expression patterns.
|
|
129631
|
+
* Handles both:
|
|
129632
|
+
* - global.funcName(...) - explicit global access
|
|
129633
|
+
* - funcName(...) - direct call (if funcName is a known C function)
|
|
129634
|
+
* Returns null if expression doesn't match these patterns.
|
|
129635
|
+
*/
|
|
129636
|
+
_extractCFunctionName(expr) {
|
|
129637
|
+
const postfix = ExpressionUnwrapper_default.getPostfixExpression(expr);
|
|
129638
|
+
if (!postfix) {
|
|
129639
|
+
return null;
|
|
129640
|
+
}
|
|
129641
|
+
const primary = postfix.primaryExpression();
|
|
129642
|
+
const ops = postfix.postfixOp();
|
|
129643
|
+
if (primary.GLOBAL()) {
|
|
129644
|
+
return this._extractGlobalPatternFuncName(ops);
|
|
129645
|
+
}
|
|
129646
|
+
const identifier = primary.IDENTIFIER();
|
|
129647
|
+
if (identifier) {
|
|
129648
|
+
return this._extractDirectCallFuncName(identifier.getText(), ops);
|
|
129649
|
+
}
|
|
129650
|
+
return null;
|
|
129651
|
+
}
|
|
129652
|
+
/**
|
|
129653
|
+
* Extract function name from global.funcName(...) pattern.
|
|
129654
|
+
*/
|
|
129655
|
+
_extractGlobalPatternFuncName(ops) {
|
|
129656
|
+
if (ops.length < 2) {
|
|
129657
|
+
return null;
|
|
129658
|
+
}
|
|
129659
|
+
const memberOp = ops[0];
|
|
129660
|
+
if (!memberOp.IDENTIFIER()) {
|
|
129661
|
+
return null;
|
|
129662
|
+
}
|
|
129663
|
+
const callOp = ops[1];
|
|
129664
|
+
if (!this._isCallOp(callOp)) {
|
|
129665
|
+
return null;
|
|
129666
|
+
}
|
|
129667
|
+
return memberOp.IDENTIFIER().getText();
|
|
129668
|
+
}
|
|
129669
|
+
/**
|
|
129670
|
+
* Extract function name from direct funcName(...) call if it's a C function.
|
|
129671
|
+
*/
|
|
129672
|
+
_extractDirectCallFuncName(funcName, ops) {
|
|
129673
|
+
if (ops.length < 1) {
|
|
129674
|
+
return null;
|
|
129675
|
+
}
|
|
129676
|
+
if (!this._isCallOp(ops[0])) {
|
|
129677
|
+
return null;
|
|
129678
|
+
}
|
|
129679
|
+
const cFunc = CodeGenState.symbolTable?.getCSymbol(funcName);
|
|
129680
|
+
if (cFunc?.kind === "function") {
|
|
129681
|
+
return funcName;
|
|
129682
|
+
}
|
|
129683
|
+
return null;
|
|
129684
|
+
}
|
|
129685
|
+
/**
|
|
129686
|
+
* Check if a postfix op is a function call.
|
|
129687
|
+
*/
|
|
129688
|
+
_isCallOp(op) {
|
|
129689
|
+
return Boolean(op.argumentList() || op.getText().startsWith("("));
|
|
129690
|
+
}
|
|
129796
129691
|
/**
|
|
129797
129692
|
* Issue #696: Track local variable for type registry and const values.
|
|
129798
129693
|
*/
|
|
@@ -129813,6 +129708,20 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129813
129708
|
}
|
|
129814
129709
|
}
|
|
129815
129710
|
}
|
|
129711
|
+
/**
|
|
129712
|
+
* Issue #895 Bug B: Mark variable as a pointer in the type registry.
|
|
129713
|
+
* Called when type inference detects that a variable should be a pointer
|
|
129714
|
+
* (e.g., initialized from a C function returning T*).
|
|
129715
|
+
*/
|
|
129716
|
+
_markVariableAsPointer(name) {
|
|
129717
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(name);
|
|
129718
|
+
if (typeInfo) {
|
|
129719
|
+
CodeGenState.setVariableTypeInfo(name, {
|
|
129720
|
+
...typeInfo,
|
|
129721
|
+
isPointer: true
|
|
129722
|
+
});
|
|
129723
|
+
}
|
|
129724
|
+
}
|
|
129816
129725
|
// Issue #792: Methods _handleArrayDeclaration, _getArrayTypeDimension, _parseArrayTypeDimension,
|
|
129817
129726
|
// _parseFirstArrayDimension, _validateArrayDeclarationSyntax, _extractBaseTypeName,
|
|
129818
129727
|
// _generateVariableInitializer, _validateIntegerInitializer, _finalizeCppClassAssignments,
|
|
@@ -130968,10 +130877,15 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
|
|
|
130968
130877
|
}
|
|
130969
130878
|
if (options.userIncludes && options.userIncludes.length > 0) {
|
|
130970
130879
|
for (const include of options.userIncludes) {
|
|
130971
|
-
|
|
130880
|
+
const transformedInclude = options.cppMode ? include.replace(/\.h"/, '.hpp"').replace(/\.h>/, ".hpp>") : include;
|
|
130881
|
+
lines.push(transformedInclude);
|
|
130972
130882
|
}
|
|
130973
130883
|
}
|
|
130974
|
-
const userIncludeSet = new Set(
|
|
130884
|
+
const userIncludeSet = new Set(
|
|
130885
|
+
options.userIncludes?.map(
|
|
130886
|
+
(inc) => options.cppMode ? inc.replace(/\.h"/, '.hpp"').replace(/\.h>/, ".hpp>") : inc
|
|
130887
|
+
) ?? []
|
|
130888
|
+
);
|
|
130975
130889
|
for (const directive of headersToInclude) {
|
|
130976
130890
|
if (!userIncludeSet.has(directive)) {
|
|
130977
130891
|
lines.push(directive);
|
|
@@ -132785,7 +132699,7 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132785
132699
|
var TSymbolInfoAdapter_default = TSymbolInfoAdapter;
|
|
132786
132700
|
|
|
132787
132701
|
// src/transpiler/logic/symbols/SymbolUtils.ts
|
|
132788
|
-
var RESERVED_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
132702
|
+
var RESERVED_FIELD_NAMES = /* @__PURE__ */ new Set([]);
|
|
132789
132703
|
function parseArrayDimensions2(text) {
|
|
132790
132704
|
const dimensions = [];
|
|
132791
132705
|
const arrayMatches = text.match(/\[(\d+)\]/g);
|
|
@@ -133389,6 +133303,8 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133389
133303
|
const parameters = _FunctionCollector._mapParameters(
|
|
133390
133304
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133391
133305
|
);
|
|
133306
|
+
const hasPointer = declarator.pointer() !== null;
|
|
133307
|
+
const returnType = hasPointer ? `${baseType}*` : baseType;
|
|
133392
133308
|
return {
|
|
133393
133309
|
kind: "function",
|
|
133394
133310
|
name,
|
|
@@ -133396,7 +133312,7 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133396
133312
|
sourceLine: line,
|
|
133397
133313
|
sourceLanguage: ESourceLanguage_default.C,
|
|
133398
133314
|
isExported: !isExtern,
|
|
133399
|
-
type:
|
|
133315
|
+
type: returnType,
|
|
133400
133316
|
parameters: parameters.length > 0 ? parameters : void 0,
|
|
133401
133317
|
isDeclaration: true
|
|
133402
133318
|
};
|
|
@@ -137085,6 +137001,8 @@ var FunctionCallAnalyzer = class {
|
|
|
137085
137001
|
if (sym?.kind !== "type") return false;
|
|
137086
137002
|
return "type" in sym && typeof sym.type === "string" && sym.type.includes("(*)");
|
|
137087
137003
|
}
|
|
137004
|
+
/** Current scope name during callback assignment scanning */
|
|
137005
|
+
scanCurrentScope = null;
|
|
137088
137006
|
/**
|
|
137089
137007
|
* Detect functions assigned to C function pointer typedefs.
|
|
137090
137008
|
* When `PointCallback cb <- my_handler;` is found and PointCallback
|
|
@@ -137093,11 +137011,45 @@ var FunctionCallAnalyzer = class {
|
|
|
137093
137011
|
collectCallbackCompatibleFunctions(tree) {
|
|
137094
137012
|
for (const decl of tree.declaration()) {
|
|
137095
137013
|
const funcDecl = decl.functionDeclaration();
|
|
137096
|
-
if (
|
|
137097
|
-
|
|
137098
|
-
|
|
137099
|
-
|
|
137014
|
+
if (funcDecl) {
|
|
137015
|
+
this.scanStandaloneFunctionForCallbacks(funcDecl);
|
|
137016
|
+
continue;
|
|
137017
|
+
}
|
|
137018
|
+
const scopeDecl = decl.scopeDeclaration();
|
|
137019
|
+
if (scopeDecl) {
|
|
137020
|
+
this.scanScopeForCallbacks(scopeDecl);
|
|
137021
|
+
}
|
|
137022
|
+
}
|
|
137023
|
+
}
|
|
137024
|
+
/**
|
|
137025
|
+
* Scan a standalone function declaration for callback assignments.
|
|
137026
|
+
*/
|
|
137027
|
+
scanStandaloneFunctionForCallbacks(funcDecl) {
|
|
137028
|
+
const block = funcDecl.block();
|
|
137029
|
+
if (!block) return;
|
|
137030
|
+
this.scanCurrentScope = null;
|
|
137031
|
+
this.scanBlockForCallbackAssignments(block);
|
|
137032
|
+
}
|
|
137033
|
+
/**
|
|
137034
|
+
* Scan all member functions in a scope for callback assignments (Issue #895).
|
|
137035
|
+
*/
|
|
137036
|
+
scanScopeForCallbacks(scopeDecl) {
|
|
137037
|
+
const scopeName = scopeDecl.IDENTIFIER().getText();
|
|
137038
|
+
for (const member of scopeDecl.scopeMember()) {
|
|
137039
|
+
this.scanScopeMemberForCallbacks(member, scopeName);
|
|
137100
137040
|
}
|
|
137041
|
+
this.scanCurrentScope = null;
|
|
137042
|
+
}
|
|
137043
|
+
/**
|
|
137044
|
+
* Scan a single scope member for callback assignments.
|
|
137045
|
+
*/
|
|
137046
|
+
scanScopeMemberForCallbacks(member, scopeName) {
|
|
137047
|
+
const memberFunc = member.functionDeclaration();
|
|
137048
|
+
if (!memberFunc) return;
|
|
137049
|
+
const block = memberFunc.block();
|
|
137050
|
+
if (!block) return;
|
|
137051
|
+
this.scanCurrentScope = scopeName;
|
|
137052
|
+
this.scanBlockForCallbackAssignments(block);
|
|
137101
137053
|
}
|
|
137102
137054
|
/**
|
|
137103
137055
|
* Recursively scan all statements in a block for callback typedef assignments.
|
|
@@ -137182,13 +137134,30 @@ var FunctionCallAnalyzer = class {
|
|
|
137182
137134
|
}
|
|
137183
137135
|
/**
|
|
137184
137136
|
* Extract a function reference from an expression context.
|
|
137185
|
-
* Matches
|
|
137186
|
-
*
|
|
137137
|
+
* Matches:
|
|
137138
|
+
* - Bare identifiers: "my_handler"
|
|
137139
|
+
* - Qualified scope names: "MyScope.handler"
|
|
137140
|
+
* - Self-scope reference: "this.handler" (resolved using scanCurrentScope)
|
|
137141
|
+
* - Global scope reference: "global.ScopeName.handler"
|
|
137187
137142
|
* Returns null if the expression is not a function reference.
|
|
137188
137143
|
*/
|
|
137189
137144
|
extractFunctionReference(expr) {
|
|
137190
137145
|
const text = expr.getText();
|
|
137191
|
-
|
|
137146
|
+
const thisPattern = /^this\.(\w+)$/;
|
|
137147
|
+
const thisMatch = thisPattern.exec(text);
|
|
137148
|
+
if (thisMatch) {
|
|
137149
|
+
if (!this.scanCurrentScope) {
|
|
137150
|
+
return null;
|
|
137151
|
+
}
|
|
137152
|
+
return this.scanCurrentScope + "." + thisMatch[1];
|
|
137153
|
+
}
|
|
137154
|
+
const globalPattern = /^global\.(\w+)\.(\w+)$/;
|
|
137155
|
+
const globalMatch = globalPattern.exec(text);
|
|
137156
|
+
if (globalMatch) {
|
|
137157
|
+
return globalMatch[1] + "." + globalMatch[2];
|
|
137158
|
+
}
|
|
137159
|
+
const simplePattern = /^\w+(\.\w+)?$/;
|
|
137160
|
+
if (simplePattern.test(text)) {
|
|
137192
137161
|
return text;
|
|
137193
137162
|
}
|
|
137194
137163
|
return null;
|
|
@@ -137851,6 +137820,162 @@ var ArrayIndexTypeAnalyzer = class {
|
|
|
137851
137820
|
};
|
|
137852
137821
|
var ArrayIndexTypeAnalyzer_default = ArrayIndexTypeAnalyzer;
|
|
137853
137822
|
|
|
137823
|
+
// src/transpiler/logic/analysis/SignedShiftAnalyzer.ts
|
|
137824
|
+
import { ParseTreeWalker as ParseTreeWalker9 } from "antlr4ng";
|
|
137825
|
+
var SignedVariableCollector = class extends CNextListener {
|
|
137826
|
+
signedVars = /* @__PURE__ */ new Set();
|
|
137827
|
+
getSignedVars() {
|
|
137828
|
+
return this.signedVars;
|
|
137829
|
+
}
|
|
137830
|
+
/**
|
|
137831
|
+
* Track a typed identifier if it has a signed type
|
|
137832
|
+
*/
|
|
137833
|
+
trackIfSigned(typeCtx, identifier) {
|
|
137834
|
+
if (!typeCtx) return;
|
|
137835
|
+
const typeName = typeCtx.getText();
|
|
137836
|
+
if (!TypeConstants_default.SIGNED_TYPES.includes(typeName)) return;
|
|
137837
|
+
if (!identifier) return;
|
|
137838
|
+
this.signedVars.add(identifier.getText());
|
|
137839
|
+
}
|
|
137840
|
+
/**
|
|
137841
|
+
* Track variable declarations with signed types
|
|
137842
|
+
*/
|
|
137843
|
+
enterVariableDeclaration = (ctx) => {
|
|
137844
|
+
this.trackIfSigned(ctx.type(), ctx.IDENTIFIER());
|
|
137845
|
+
};
|
|
137846
|
+
/**
|
|
137847
|
+
* Track function parameters with signed types
|
|
137848
|
+
*/
|
|
137849
|
+
enterParameter = (ctx) => {
|
|
137850
|
+
this.trackIfSigned(ctx.type(), ctx.IDENTIFIER());
|
|
137851
|
+
};
|
|
137852
|
+
/**
|
|
137853
|
+
* Track for-loop variable declarations with signed types
|
|
137854
|
+
*/
|
|
137855
|
+
enterForVarDecl = (ctx) => {
|
|
137856
|
+
this.trackIfSigned(ctx.type(), ctx.IDENTIFIER());
|
|
137857
|
+
};
|
|
137858
|
+
};
|
|
137859
|
+
var SignedShiftListener = class extends CNextListener {
|
|
137860
|
+
analyzer;
|
|
137861
|
+
// eslint-disable-next-line @typescript-eslint/lines-between-class-members
|
|
137862
|
+
signedVars;
|
|
137863
|
+
constructor(analyzer, signedVars) {
|
|
137864
|
+
super();
|
|
137865
|
+
this.analyzer = analyzer;
|
|
137866
|
+
this.signedVars = signedVars;
|
|
137867
|
+
}
|
|
137868
|
+
/**
|
|
137869
|
+
* Check shift expressions for signed operands
|
|
137870
|
+
* shiftExpression: additiveExpression (('<<' | '>>') additiveExpression)*
|
|
137871
|
+
*/
|
|
137872
|
+
enterShiftExpression = (ctx) => {
|
|
137873
|
+
const operands = ctx.additiveExpression();
|
|
137874
|
+
if (operands.length < 2) return;
|
|
137875
|
+
for (let i = 0; i < operands.length - 1; i++) {
|
|
137876
|
+
const operatorToken = ctx.getChild(i * 2 + 1);
|
|
137877
|
+
if (!operatorToken) continue;
|
|
137878
|
+
const operator = operatorToken.getText();
|
|
137879
|
+
if (operator !== "<<" && operator !== ">>") continue;
|
|
137880
|
+
const leftOperand = operands[i];
|
|
137881
|
+
if (this.isSignedOperand(leftOperand)) {
|
|
137882
|
+
const { line, column } = ParserUtils_default.getPosition(leftOperand);
|
|
137883
|
+
this.analyzer.addError(line, column, operator);
|
|
137884
|
+
}
|
|
137885
|
+
}
|
|
137886
|
+
};
|
|
137887
|
+
/**
|
|
137888
|
+
* Check if an additive expression contains a signed type operand
|
|
137889
|
+
*/
|
|
137890
|
+
isSignedOperand(ctx) {
|
|
137891
|
+
const multExprs = ctx.multiplicativeExpression();
|
|
137892
|
+
for (const multExpr of multExprs) {
|
|
137893
|
+
const unaryExprs = multExpr.unaryExpression();
|
|
137894
|
+
for (const unaryExpr of unaryExprs) {
|
|
137895
|
+
if (this.isSignedUnaryExpression(unaryExpr)) {
|
|
137896
|
+
return true;
|
|
137897
|
+
}
|
|
137898
|
+
}
|
|
137899
|
+
}
|
|
137900
|
+
return false;
|
|
137901
|
+
}
|
|
137902
|
+
/**
|
|
137903
|
+
* Check if a unary expression is a signed type
|
|
137904
|
+
*/
|
|
137905
|
+
isSignedUnaryExpression(ctx) {
|
|
137906
|
+
if (ctx.MINUS()) {
|
|
137907
|
+
const nestedUnary = ctx.unaryExpression();
|
|
137908
|
+
if (nestedUnary) {
|
|
137909
|
+
const nestedPostfix = nestedUnary.postfixExpression();
|
|
137910
|
+
if (nestedPostfix) {
|
|
137911
|
+
const nestedPrimary = nestedPostfix.primaryExpression();
|
|
137912
|
+
if (nestedPrimary?.literal()) {
|
|
137913
|
+
return true;
|
|
137914
|
+
}
|
|
137915
|
+
}
|
|
137916
|
+
return this.isSignedUnaryExpression(nestedUnary);
|
|
137917
|
+
}
|
|
137918
|
+
return false;
|
|
137919
|
+
}
|
|
137920
|
+
const postfixExpr = ctx.postfixExpression();
|
|
137921
|
+
if (!postfixExpr) return false;
|
|
137922
|
+
const primaryExpr = postfixExpr.primaryExpression();
|
|
137923
|
+
if (!primaryExpr) return false;
|
|
137924
|
+
const parenExpr = primaryExpr.expression();
|
|
137925
|
+
if (parenExpr) {
|
|
137926
|
+
return this.isSignedExpression(parenExpr);
|
|
137927
|
+
}
|
|
137928
|
+
const identifier = primaryExpr.IDENTIFIER();
|
|
137929
|
+
if (identifier) {
|
|
137930
|
+
return this.signedVars.has(identifier.getText());
|
|
137931
|
+
}
|
|
137932
|
+
return false;
|
|
137933
|
+
}
|
|
137934
|
+
/**
|
|
137935
|
+
* Check if a full expression contains signed operands
|
|
137936
|
+
*/
|
|
137937
|
+
isSignedExpression(ctx) {
|
|
137938
|
+
const ternary = ctx.ternaryExpression();
|
|
137939
|
+
if (!ternary) return false;
|
|
137940
|
+
const additiveExprs = ExpressionUtils_default.collectAdditiveExpressions(ternary);
|
|
137941
|
+
return additiveExprs.some((addExpr) => this.isSignedOperand(addExpr));
|
|
137942
|
+
}
|
|
137943
|
+
};
|
|
137944
|
+
var SignedShiftAnalyzer = class {
|
|
137945
|
+
errors = [];
|
|
137946
|
+
/**
|
|
137947
|
+
* Analyze the parse tree for signed shift operations
|
|
137948
|
+
*/
|
|
137949
|
+
analyze(tree) {
|
|
137950
|
+
this.errors = [];
|
|
137951
|
+
const collector = new SignedVariableCollector();
|
|
137952
|
+
ParseTreeWalker9.DEFAULT.walk(collector, tree);
|
|
137953
|
+
const signedVars = collector.getSignedVars();
|
|
137954
|
+
const listener = new SignedShiftListener(this, signedVars);
|
|
137955
|
+
ParseTreeWalker9.DEFAULT.walk(listener, tree);
|
|
137956
|
+
return this.errors;
|
|
137957
|
+
}
|
|
137958
|
+
/**
|
|
137959
|
+
* Add a signed shift error
|
|
137960
|
+
*/
|
|
137961
|
+
addError(line, column, operator) {
|
|
137962
|
+
this.errors.push({
|
|
137963
|
+
code: "E0805",
|
|
137964
|
+
line,
|
|
137965
|
+
column,
|
|
137966
|
+
message: `Shift operator '${operator}' not allowed on signed integer types`,
|
|
137967
|
+
helpText: "Shift operations on signed integers have undefined (<<) or implementation-defined (>>) behavior. Use unsigned types (u8, u16, u32, u64) for bit manipulation."
|
|
137968
|
+
});
|
|
137969
|
+
}
|
|
137970
|
+
/**
|
|
137971
|
+
* Get all detected errors
|
|
137972
|
+
*/
|
|
137973
|
+
getErrors() {
|
|
137974
|
+
return this.errors;
|
|
137975
|
+
}
|
|
137976
|
+
};
|
|
137977
|
+
var SignedShiftAnalyzer_default = SignedShiftAnalyzer;
|
|
137978
|
+
|
|
137854
137979
|
// src/transpiler/logic/analysis/runAnalyzers.ts
|
|
137855
137980
|
function collectErrors(analyzerErrors, target, formatMessage) {
|
|
137856
137981
|
const formatter = formatMessage ?? ((e) => e.message);
|
|
@@ -137908,6 +138033,10 @@ function runAnalyzers(tree, tokenStream, options) {
|
|
|
137908
138033
|
if (collectErrors(indexTypeAnalyzer.analyze(tree), errors, formatWithCode)) {
|
|
137909
138034
|
return errors;
|
|
137910
138035
|
}
|
|
138036
|
+
const signedShiftAnalyzer = new SignedShiftAnalyzer_default();
|
|
138037
|
+
if (collectErrors(signedShiftAnalyzer.analyze(tree), errors, formatWithCode)) {
|
|
138038
|
+
return errors;
|
|
138039
|
+
}
|
|
137911
138040
|
const commentExtractor = new CommentExtractor_default(tokenStream);
|
|
137912
138041
|
collectErrors(
|
|
137913
138042
|
commentExtractor.validate(),
|
|
@@ -139003,7 +139132,8 @@ var Transpiler = class {
|
|
|
139003
139132
|
const headerContent = this.generateHeaderForFile(file);
|
|
139004
139133
|
if (headerContent) {
|
|
139005
139134
|
const headerPath = this.pathResolver.getHeaderOutputPath(
|
|
139006
|
-
file.discoveredFile
|
|
139135
|
+
file.discoveredFile,
|
|
139136
|
+
this.cppDetected
|
|
139007
139137
|
);
|
|
139008
139138
|
this.fs.writeFile(headerPath, headerContent);
|
|
139009
139139
|
result.outputFiles.push(headerPath);
|
|
@@ -139406,7 +139536,8 @@ var Transpiler = class {
|
|
|
139406
139536
|
if (exportedSymbols.length === 0) {
|
|
139407
139537
|
return null;
|
|
139408
139538
|
}
|
|
139409
|
-
const
|
|
139539
|
+
const ext = this.cppDetected ? ".hpp" : ".h";
|
|
139540
|
+
const headerName = basename5(sourcePath).replace(/\.cnx$|\.cnext$/, ext);
|
|
139410
139541
|
const typeInput = this.state.getSymbolInfo(sourcePath);
|
|
139411
139542
|
const passByValueParams = this.state.getPassByValueParams(sourcePath) ?? /* @__PURE__ */ new Map();
|
|
139412
139543
|
const userIncludes = this.state.getUserIncludes(sourcePath);
|
|
@@ -139476,19 +139607,31 @@ var Transpiler = class {
|
|
|
139476
139607
|
convertToHeaderSymbols(symbols, unmodifiedParams, knownEnums) {
|
|
139477
139608
|
return symbols.map((symbol) => {
|
|
139478
139609
|
const headerSymbol = HeaderSymbolAdapter_default.fromTSymbol(symbol);
|
|
139479
|
-
if (symbol.kind
|
|
139480
|
-
|
|
139481
|
-
|
|
139482
|
-
|
|
139483
|
-
|
|
139484
|
-
|
|
139485
|
-
|
|
139486
|
-
|
|
139487
|
-
|
|
139488
|
-
|
|
139489
|
-
|
|
139490
|
-
|
|
139491
|
-
}
|
|
139610
|
+
if (symbol.kind !== "function" || !headerSymbol.parameters || headerSymbol.parameters.length === 0) {
|
|
139611
|
+
return headerSymbol;
|
|
139612
|
+
}
|
|
139613
|
+
const typedefName = CodeGenState.callbackCompatibleFunctions.get(
|
|
139614
|
+
headerSymbol.name
|
|
139615
|
+
);
|
|
139616
|
+
const callbackTypedefType = typedefName ? CodeGenState.getTypedefType(typedefName) : void 0;
|
|
139617
|
+
if (callbackTypedefType) {
|
|
139618
|
+
const updatedParams = TypedefParamParser_default.resolveCallbackParams(
|
|
139619
|
+
headerSymbol.parameters,
|
|
139620
|
+
callbackTypedefType
|
|
139621
|
+
);
|
|
139622
|
+
return { ...headerSymbol, parameters: updatedParams };
|
|
139623
|
+
}
|
|
139624
|
+
const unmodified = unmodifiedParams.get(headerSymbol.name);
|
|
139625
|
+
if (unmodified) {
|
|
139626
|
+
const updatedParams = headerSymbol.parameters.map((param) => {
|
|
139627
|
+
const isPointerParam = !param.isConst && !param.isArray && param.type !== "f32" && param.type !== "f64" && param.type !== "ISR" && !knownEnums.has(param.type ?? "");
|
|
139628
|
+
const isArrayParam = param.isArray && !param.isConst;
|
|
139629
|
+
if ((isPointerParam || isArrayParam) && unmodified.has(param.name)) {
|
|
139630
|
+
return { ...param, isAutoConst: true };
|
|
139631
|
+
}
|
|
139632
|
+
return param;
|
|
139633
|
+
});
|
|
139634
|
+
return { ...headerSymbol, parameters: updatedParams };
|
|
139492
139635
|
}
|
|
139493
139636
|
return headerSymbol;
|
|
139494
139637
|
});
|