c-next 0.2.6 → 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 +387 -433
- 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/PassByValueAnalyzer.ts +1 -12
- package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +239 -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 +4 -4
- package/src/transpiler/logic/symbols/cpp/__tests__/CppResolver.integration.test.ts +4 -4
- package/src/transpiler/output/codegen/CodeGenerator.ts +12 -4
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +3 -3
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +26 -26
- 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/generators/expressions/AccessExprGenerator.ts +7 -326
- 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/ParameterInputAdapter.ts +7 -2
- package/src/transpiler/output/codegen/helpers/TypedefParamParser.ts +34 -0
- 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/headers/HeaderGeneratorUtils.ts +15 -2
- package/src/transpiler/output/headers/__tests__/BaseHeaderGenerator.test.ts +87 -0
- package/src/utils/ExpressionUtils.ts +51 -0
- 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) => {
|
|
@@ -115928,7 +115895,7 @@ var handleGlobalPrefix = (memberName, tracking, input, state, orchestrator) => {
|
|
|
115928
115895
|
}
|
|
115929
115896
|
return true;
|
|
115930
115897
|
};
|
|
115931
|
-
var handleThisScopeLength = (memberName, tracking,
|
|
115898
|
+
var handleThisScopeLength = (memberName, tracking, _input, state, orchestrator) => {
|
|
115932
115899
|
if (tracking.result !== "__THIS_SCOPE__" || memberName !== "length") {
|
|
115933
115900
|
return false;
|
|
115934
115901
|
}
|
|
@@ -116017,19 +115984,9 @@ var tryExplicitLengthProperty = (memberName, tracking, rootIdentifier, input, st
|
|
|
116017
115984
|
};
|
|
116018
115985
|
var tryPropertyAccess = (memberName, tracking, rootIdentifier, input, state, orchestrator, effects) => {
|
|
116019
115986
|
if (memberName === "length") {
|
|
116020
|
-
|
|
116021
|
-
|
|
116022
|
-
ctx,
|
|
116023
|
-
input,
|
|
116024
|
-
state,
|
|
116025
|
-
orchestrator,
|
|
116026
|
-
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)`
|
|
116027
115989
|
);
|
|
116028
|
-
if (lengthResult !== null) {
|
|
116029
|
-
applyPropertyResult(tracking, lengthResult);
|
|
116030
|
-
return true;
|
|
116031
|
-
}
|
|
116032
|
-
return false;
|
|
116033
115990
|
}
|
|
116034
115991
|
const explicitProps = /* @__PURE__ */ new Set([
|
|
116035
115992
|
"bit_length",
|
|
@@ -116074,129 +116031,6 @@ var tryPropertyAccess = (memberName, tracking, rootIdentifier, input, state, orc
|
|
|
116074
116031
|
}
|
|
116075
116032
|
return false;
|
|
116076
116033
|
};
|
|
116077
|
-
var generateLengthProperty2 = (ctx, input, state, orchestrator, effects) => {
|
|
116078
|
-
if (state.mainArgsName && ctx.rootIdentifier === state.mainArgsName) {
|
|
116079
|
-
return "argc";
|
|
116080
|
-
}
|
|
116081
|
-
if (ctx.previousStructType && ctx.previousMemberName) {
|
|
116082
|
-
const fieldInfo = orchestrator.getStructFieldInfo(
|
|
116083
|
-
ctx.previousStructType,
|
|
116084
|
-
ctx.previousMemberName
|
|
116085
|
-
);
|
|
116086
|
-
if (fieldInfo) {
|
|
116087
|
-
return generateStructFieldLength(
|
|
116088
|
-
ctx.result,
|
|
116089
|
-
fieldInfo,
|
|
116090
|
-
ctx.subscriptDepth,
|
|
116091
|
-
input,
|
|
116092
|
-
orchestrator,
|
|
116093
|
-
effects
|
|
116094
|
-
);
|
|
116095
|
-
}
|
|
116096
|
-
}
|
|
116097
|
-
const typeInfo = ctx.resolvedIdentifier ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier) : void 0;
|
|
116098
|
-
if (!typeInfo) {
|
|
116099
|
-
return `/* .length: unknown type for ${ctx.result} */0`;
|
|
116100
|
-
}
|
|
116101
|
-
return generateTypeInfoLength(
|
|
116102
|
-
ctx.result,
|
|
116103
|
-
typeInfo,
|
|
116104
|
-
ctx.subscriptDepth,
|
|
116105
|
-
ctx.resolvedIdentifier,
|
|
116106
|
-
input,
|
|
116107
|
-
state,
|
|
116108
|
-
effects
|
|
116109
|
-
);
|
|
116110
|
-
};
|
|
116111
|
-
var generateStructFieldLength = (result, fieldInfo, subscriptDepth, input, orchestrator, effects) => {
|
|
116112
|
-
const memberType = fieldInfo.type;
|
|
116113
|
-
const dimensions = fieldInfo.dimensions;
|
|
116114
|
-
const isStringField = TypeCheckUtils_default.isString(memberType);
|
|
116115
|
-
if (dimensions?.length && dimensions.length > 1 && isStringField) {
|
|
116116
|
-
if (subscriptDepth === 0) {
|
|
116117
|
-
return String(dimensions[0]);
|
|
116118
|
-
} else {
|
|
116119
|
-
effects.push({ type: "include", header: "string" });
|
|
116120
|
-
return `strlen(${result})`;
|
|
116121
|
-
}
|
|
116122
|
-
} else if (dimensions?.length === 1 && isStringField) {
|
|
116123
|
-
effects.push({ type: "include", header: "string" });
|
|
116124
|
-
return `strlen(${result})`;
|
|
116125
|
-
} else if (dimensions?.length && dimensions.length > 0 && subscriptDepth < dimensions.length) {
|
|
116126
|
-
return String(dimensions[subscriptDepth]);
|
|
116127
|
-
} else if (dimensions?.length && dimensions.length > 0 && subscriptDepth >= dimensions.length) {
|
|
116128
|
-
return getTypeBitWidth2(memberType, input);
|
|
116129
|
-
} else {
|
|
116130
|
-
return getTypeBitWidth2(memberType, input);
|
|
116131
|
-
}
|
|
116132
|
-
};
|
|
116133
|
-
var generateTypeInfoLength = (result, typeInfo, subscriptDepth, resolvedIdentifier, input, state, effects) => {
|
|
116134
|
-
if (typeInfo.isString) {
|
|
116135
|
-
return generateStringLength(
|
|
116136
|
-
result,
|
|
116137
|
-
typeInfo,
|
|
116138
|
-
subscriptDepth,
|
|
116139
|
-
resolvedIdentifier,
|
|
116140
|
-
state
|
|
116141
|
-
);
|
|
116142
|
-
}
|
|
116143
|
-
if (typeInfo.isEnum && !typeInfo.isArray) {
|
|
116144
|
-
return "32";
|
|
116145
|
-
}
|
|
116146
|
-
if (!typeInfo.isArray) {
|
|
116147
|
-
return String(typeInfo.bitWidth || 0);
|
|
116148
|
-
}
|
|
116149
|
-
const dims = typeInfo.arrayDimensions;
|
|
116150
|
-
if (!dims || dims.length === 0) {
|
|
116151
|
-
return `/* .length unknown for ${resolvedIdentifier} */0`;
|
|
116152
|
-
}
|
|
116153
|
-
if (subscriptDepth < dims.length) {
|
|
116154
|
-
return String(dims[subscriptDepth]);
|
|
116155
|
-
}
|
|
116156
|
-
return generateElementTypeLength(result, typeInfo, input, effects);
|
|
116157
|
-
};
|
|
116158
|
-
var generateStringLength = (result, typeInfo, subscriptDepth, resolvedIdentifier, state) => {
|
|
116159
|
-
const dims = typeInfo.arrayDimensions;
|
|
116160
|
-
if (dims && dims.length > 1) {
|
|
116161
|
-
return subscriptDepth === 0 ? String(dims[0]) : `strlen(${result})`;
|
|
116162
|
-
}
|
|
116163
|
-
if (subscriptDepth > 0) {
|
|
116164
|
-
return `strlen(${result})`;
|
|
116165
|
-
}
|
|
116166
|
-
if (resolvedIdentifier && state.lengthCache?.has(resolvedIdentifier)) {
|
|
116167
|
-
return state.lengthCache.get(resolvedIdentifier);
|
|
116168
|
-
}
|
|
116169
|
-
return resolvedIdentifier ? `strlen(${resolvedIdentifier})` : `strlen(${result})`;
|
|
116170
|
-
};
|
|
116171
|
-
var generateElementTypeLength = (result, typeInfo, input, effects) => {
|
|
116172
|
-
if (typeInfo.isEnum) {
|
|
116173
|
-
return "32";
|
|
116174
|
-
}
|
|
116175
|
-
if (TypeCheckUtils_default.isString(typeInfo.baseType) || typeInfo.isString) {
|
|
116176
|
-
effects.push({ type: "include", header: "string" });
|
|
116177
|
-
return `strlen(${result})`;
|
|
116178
|
-
}
|
|
116179
|
-
let elementBitWidth = TYPE_WIDTH_default[typeInfo.baseType] || 0;
|
|
116180
|
-
if (elementBitWidth === 0 && typeInfo.isBitmap && typeInfo.bitmapTypeName) {
|
|
116181
|
-
elementBitWidth = input.symbols.bitmapBitWidth.get(typeInfo.bitmapTypeName) || 0;
|
|
116182
|
-
}
|
|
116183
|
-
if (elementBitWidth > 0) {
|
|
116184
|
-
return String(elementBitWidth);
|
|
116185
|
-
}
|
|
116186
|
-
return `/* .length: unsupported element type ${typeInfo.baseType} */0`;
|
|
116187
|
-
};
|
|
116188
|
-
var getTypeBitWidth2 = (typeName, input) => {
|
|
116189
|
-
let bitWidth = TYPE_WIDTH_default[typeName] || C_TYPE_WIDTH_default[typeName] || 0;
|
|
116190
|
-
if (bitWidth === 0 && input.symbolTable) {
|
|
116191
|
-
const enumWidth = input.symbolTable.getEnumBitWidth(typeName);
|
|
116192
|
-
if (enumWidth) bitWidth = enumWidth;
|
|
116193
|
-
}
|
|
116194
|
-
if (bitWidth > 0) {
|
|
116195
|
-
return String(bitWidth);
|
|
116196
|
-
} else {
|
|
116197
|
-
return `/* .length: unsupported type ${typeName} */0`;
|
|
116198
|
-
}
|
|
116199
|
-
};
|
|
116200
116034
|
var getNumericBitWidth = (typeName, input) => {
|
|
116201
116035
|
let bitWidth = TYPE_WIDTH_default[typeName] ?? C_TYPE_WIDTH_default[typeName] ?? 0;
|
|
116202
116036
|
if (bitWidth === 0 && input.symbolTable) {
|
|
@@ -116472,11 +116306,10 @@ var generateCharCountProperty = (ctx, input, state, orchestrator, effects) => {
|
|
|
116472
116306
|
);
|
|
116473
116307
|
}
|
|
116474
116308
|
effects.push({ type: "include", header: "string" });
|
|
116475
|
-
if (ctx.resolvedIdentifier && state.lengthCache?.has(ctx.resolvedIdentifier)) {
|
|
116309
|
+
if (ctx.subscriptDepth === 0 && ctx.resolvedIdentifier && state.lengthCache?.has(ctx.resolvedIdentifier)) {
|
|
116476
116310
|
return state.lengthCache.get(ctx.resolvedIdentifier);
|
|
116477
116311
|
}
|
|
116478
|
-
|
|
116479
|
-
return `strlen(${target})`;
|
|
116312
|
+
return `strlen(${ctx.result})`;
|
|
116480
116313
|
};
|
|
116481
116314
|
var initializeMemberOutput = (ctx) => ({
|
|
116482
116315
|
result: ctx.result,
|
|
@@ -122371,7 +122204,7 @@ var AssignmentContextBuilder_default = buildAssignmentContext;
|
|
|
122371
122204
|
// src/transpiler/output/codegen/analysis/StringLengthCounter.ts
|
|
122372
122205
|
var StringLengthCounter = class _StringLengthCounter {
|
|
122373
122206
|
/**
|
|
122374
|
-
* Count .
|
|
122207
|
+
* Count .char_count accesses in an expression.
|
|
122375
122208
|
*/
|
|
122376
122209
|
static countExpression(ctx) {
|
|
122377
122210
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -122379,7 +122212,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122379
122212
|
return counts;
|
|
122380
122213
|
}
|
|
122381
122214
|
/**
|
|
122382
|
-
* Count .
|
|
122215
|
+
* Count .char_count accesses in a block.
|
|
122383
122216
|
*/
|
|
122384
122217
|
static countBlock(ctx) {
|
|
122385
122218
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -122389,7 +122222,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122389
122222
|
return counts;
|
|
122390
122223
|
}
|
|
122391
122224
|
/**
|
|
122392
|
-
* Count .
|
|
122225
|
+
* Count .char_count accesses in a block, adding to existing counts.
|
|
122393
122226
|
*/
|
|
122394
122227
|
static countBlockInto(ctx, counts) {
|
|
122395
122228
|
for (const stmt of ctx.statement()) {
|
|
@@ -122397,7 +122230,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122397
122230
|
}
|
|
122398
122231
|
}
|
|
122399
122232
|
/**
|
|
122400
|
-
* Walk an expression tree, counting .
|
|
122233
|
+
* Walk an expression tree, counting .char_count accesses.
|
|
122401
122234
|
* Uses generic traversal - only postfix expressions need special handling.
|
|
122402
122235
|
*/
|
|
122403
122236
|
static walkExpression(ctx, counts) {
|
|
@@ -122472,7 +122305,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122472
122305
|
}
|
|
122473
122306
|
}
|
|
122474
122307
|
/**
|
|
122475
|
-
* Walk a postfix expression - this is where we detect .
|
|
122308
|
+
* Walk a postfix expression - this is where we detect .char_count accesses.
|
|
122476
122309
|
*/
|
|
122477
122310
|
static walkPostfixExpr(ctx, counts) {
|
|
122478
122311
|
const primary = ctx.primaryExpression();
|
|
@@ -122481,7 +122314,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122481
122314
|
if (primaryId && ops.length > 0) {
|
|
122482
122315
|
for (const op of ops) {
|
|
122483
122316
|
const memberName = op.IDENTIFIER()?.getText();
|
|
122484
|
-
if (memberName === "
|
|
122317
|
+
if (memberName === "char_count") {
|
|
122485
122318
|
const typeInfo = CodeGenState.getVariableTypeInfo(primaryId);
|
|
122486
122319
|
if (typeInfo?.isString) {
|
|
122487
122320
|
const currentCount = counts.get(primaryId) || 0;
|
|
@@ -122498,7 +122331,7 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122498
122331
|
}
|
|
122499
122332
|
}
|
|
122500
122333
|
/**
|
|
122501
|
-
* Walk a statement, counting .
|
|
122334
|
+
* Walk a statement, counting .char_count accesses.
|
|
122502
122335
|
*/
|
|
122503
122336
|
static walkStatement(ctx, counts) {
|
|
122504
122337
|
if (ctx.assignmentStatement()) {
|
|
@@ -122530,95 +122363,6 @@ var StringLengthCounter = class _StringLengthCounter {
|
|
|
122530
122363
|
};
|
|
122531
122364
|
var StringLengthCounter_default = StringLengthCounter;
|
|
122532
122365
|
|
|
122533
|
-
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
122534
|
-
var CppModeHelper = class {
|
|
122535
|
-
/**
|
|
122536
|
-
* Get address-of expression for struct parameter passing.
|
|
122537
|
-
* C mode: `&expr` (pass pointer to struct)
|
|
122538
|
-
* C++ mode: `expr` (pass reference directly)
|
|
122539
|
-
*
|
|
122540
|
-
* @param expr - The expression to potentially wrap
|
|
122541
|
-
* @returns The expression with address-of operator in C mode
|
|
122542
|
-
*/
|
|
122543
|
-
static maybeAddressOf(expr) {
|
|
122544
|
-
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
122545
|
-
}
|
|
122546
|
-
/**
|
|
122547
|
-
* Get dereference expression for struct parameter access.
|
|
122548
|
-
* C mode: `(*expr)` (dereference pointer)
|
|
122549
|
-
* C++ mode: `expr` (reference can be used directly)
|
|
122550
|
-
*
|
|
122551
|
-
* @param expr - The expression to potentially dereference
|
|
122552
|
-
* @returns The expression with dereference in C mode
|
|
122553
|
-
*/
|
|
122554
|
-
static maybeDereference(expr) {
|
|
122555
|
-
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
122556
|
-
}
|
|
122557
|
-
/**
|
|
122558
|
-
* Get the type modifier for struct parameter declarations.
|
|
122559
|
-
* C mode: `*` (pointer type)
|
|
122560
|
-
* C++ mode: `&` (reference type)
|
|
122561
|
-
*
|
|
122562
|
-
* @returns The type modifier character
|
|
122563
|
-
*/
|
|
122564
|
-
static refOrPtr() {
|
|
122565
|
-
return CodeGenState.cppMode ? "&" : "*";
|
|
122566
|
-
}
|
|
122567
|
-
/**
|
|
122568
|
-
* Get the member access separator for struct parameters.
|
|
122569
|
-
* C mode: `->` (pointer member access)
|
|
122570
|
-
* C++ mode: `.` (reference member access)
|
|
122571
|
-
*
|
|
122572
|
-
* @returns The member access separator
|
|
122573
|
-
*/
|
|
122574
|
-
static memberSeparator() {
|
|
122575
|
-
return CodeGenState.cppMode ? "." : "->";
|
|
122576
|
-
}
|
|
122577
|
-
/**
|
|
122578
|
-
* Get NULL literal for the current mode.
|
|
122579
|
-
* C mode: `NULL`
|
|
122580
|
-
* C++ mode: `nullptr`
|
|
122581
|
-
*
|
|
122582
|
-
* @returns The null pointer literal
|
|
122583
|
-
*/
|
|
122584
|
-
static nullLiteral() {
|
|
122585
|
-
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
122586
|
-
}
|
|
122587
|
-
/**
|
|
122588
|
-
* Generate a cast expression for the current mode.
|
|
122589
|
-
* C mode: `(type)expr`
|
|
122590
|
-
* C++ mode: `static_cast<type>(expr)`
|
|
122591
|
-
*
|
|
122592
|
-
* @param type - The target type
|
|
122593
|
-
* @param expr - The expression to cast
|
|
122594
|
-
* @returns The cast expression
|
|
122595
|
-
*/
|
|
122596
|
-
static cast(type, expr) {
|
|
122597
|
-
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
122598
|
-
}
|
|
122599
|
-
/**
|
|
122600
|
-
* Generate a reinterpret cast expression for the current mode.
|
|
122601
|
-
* C mode: `(type)expr`
|
|
122602
|
-
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
122603
|
-
*
|
|
122604
|
-
* @param type - The target type
|
|
122605
|
-
* @param expr - The expression to cast
|
|
122606
|
-
* @returns The cast expression
|
|
122607
|
-
*/
|
|
122608
|
-
static reinterpretCast(type, expr) {
|
|
122609
|
-
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
122610
|
-
}
|
|
122611
|
-
/**
|
|
122612
|
-
* Check if we're in C++ mode.
|
|
122613
|
-
*
|
|
122614
|
-
* @returns True if generating C++ code
|
|
122615
|
-
*/
|
|
122616
|
-
static isCppMode() {
|
|
122617
|
-
return CodeGenState.cppMode;
|
|
122618
|
-
}
|
|
122619
|
-
};
|
|
122620
|
-
var CppModeHelper_default = CppModeHelper;
|
|
122621
|
-
|
|
122622
122366
|
// src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts
|
|
122623
122367
|
var MemberChainAnalyzer = class _MemberChainAnalyzer {
|
|
122624
122368
|
/**
|
|
@@ -125648,6 +125392,33 @@ var TypedefParamParser = class _TypedefParamParser {
|
|
|
125648
125392
|
static shouldBeConst(typedefType, paramIndex) {
|
|
125649
125393
|
return _TypedefParamParser.getParamAt(typedefType, paramIndex)?.isConst ?? null;
|
|
125650
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
|
+
}
|
|
125651
125422
|
};
|
|
125652
125423
|
var TypedefParamParser_default = TypedefParamParser;
|
|
125653
125424
|
|
|
@@ -126419,7 +126190,7 @@ var PassByValueAnalyzer = class _PassByValueAnalyzer {
|
|
|
126419
126190
|
* Used by both function call tracking and subscript access tracking.
|
|
126420
126191
|
*/
|
|
126421
126192
|
static walkOrExpression(orExpr, handler) {
|
|
126422
|
-
|
|
126193
|
+
ExpressionUtils_default.collectUnaryFromOrExpr(orExpr).forEach(handler);
|
|
126423
126194
|
}
|
|
126424
126195
|
/**
|
|
126425
126196
|
* Walk an orExpression tree for function calls.
|
|
@@ -126774,6 +126545,7 @@ var ParameterInputAdapter = class {
|
|
|
126774
126545
|
isPassByReference: false
|
|
126775
126546
|
};
|
|
126776
126547
|
}
|
|
126548
|
+
const isCallbackPointer = param.isCallbackPointer ?? false;
|
|
126777
126549
|
return {
|
|
126778
126550
|
name: param.name,
|
|
126779
126551
|
baseType: param.type,
|
|
@@ -126783,8 +126555,10 @@ var ParameterInputAdapter = class {
|
|
|
126783
126555
|
isArray: false,
|
|
126784
126556
|
isCallback: false,
|
|
126785
126557
|
isString: false,
|
|
126786
|
-
isPassByValue: deps.isPassByValue,
|
|
126787
|
-
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
|
|
126788
126562
|
};
|
|
126789
126563
|
}
|
|
126790
126564
|
/**
|
|
@@ -127594,7 +127368,7 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
127594
127368
|
if (!arrayAccessMatch) {
|
|
127595
127369
|
return false;
|
|
127596
127370
|
}
|
|
127597
|
-
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")) {
|
|
127598
127372
|
return false;
|
|
127599
127373
|
}
|
|
127600
127374
|
const arrayName = arrayAccessMatch[1];
|
|
@@ -128654,7 +128428,8 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128654
128428
|
);
|
|
128655
128429
|
if (symbols.hasPublicSymbols() && CodeGenState.sourcePath) {
|
|
128656
128430
|
const pathToUse = options?.sourceRelativePath || CodeGenState.sourcePath.replace(/^.*[\\/]/, "");
|
|
128657
|
-
const
|
|
128431
|
+
const ext = CodeGenState.cppMode ? ".hpp" : ".h";
|
|
128432
|
+
const headerName = pathToUse.replace(/\.cnx$|\.cnext$/, ext);
|
|
128658
128433
|
output.push(`#include "${headerName}"`, "");
|
|
128659
128434
|
CodeGenState.selfIncludeAdded = true;
|
|
128660
128435
|
}
|
|
@@ -131102,10 +130877,15 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
|
|
|
131102
130877
|
}
|
|
131103
130878
|
if (options.userIncludes && options.userIncludes.length > 0) {
|
|
131104
130879
|
for (const include of options.userIncludes) {
|
|
131105
|
-
|
|
130880
|
+
const transformedInclude = options.cppMode ? include.replace(/\.h"/, '.hpp"').replace(/\.h>/, ".hpp>") : include;
|
|
130881
|
+
lines.push(transformedInclude);
|
|
131106
130882
|
}
|
|
131107
130883
|
}
|
|
131108
|
-
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
|
+
);
|
|
131109
130889
|
for (const directive of headersToInclude) {
|
|
131110
130890
|
if (!userIncludeSet.has(directive)) {
|
|
131111
130891
|
lines.push(directive);
|
|
@@ -132919,7 +132699,7 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132919
132699
|
var TSymbolInfoAdapter_default = TSymbolInfoAdapter;
|
|
132920
132700
|
|
|
132921
132701
|
// src/transpiler/logic/symbols/SymbolUtils.ts
|
|
132922
|
-
var RESERVED_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
132702
|
+
var RESERVED_FIELD_NAMES = /* @__PURE__ */ new Set([]);
|
|
132923
132703
|
function parseArrayDimensions2(text) {
|
|
132924
132704
|
const dimensions = [];
|
|
132925
132705
|
const arrayMatches = text.match(/\[(\d+)\]/g);
|
|
@@ -138040,6 +137820,162 @@ var ArrayIndexTypeAnalyzer = class {
|
|
|
138040
137820
|
};
|
|
138041
137821
|
var ArrayIndexTypeAnalyzer_default = ArrayIndexTypeAnalyzer;
|
|
138042
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
|
+
|
|
138043
137979
|
// src/transpiler/logic/analysis/runAnalyzers.ts
|
|
138044
137980
|
function collectErrors(analyzerErrors, target, formatMessage) {
|
|
138045
137981
|
const formatter = formatMessage ?? ((e) => e.message);
|
|
@@ -138097,6 +138033,10 @@ function runAnalyzers(tree, tokenStream, options) {
|
|
|
138097
138033
|
if (collectErrors(indexTypeAnalyzer.analyze(tree), errors, formatWithCode)) {
|
|
138098
138034
|
return errors;
|
|
138099
138035
|
}
|
|
138036
|
+
const signedShiftAnalyzer = new SignedShiftAnalyzer_default();
|
|
138037
|
+
if (collectErrors(signedShiftAnalyzer.analyze(tree), errors, formatWithCode)) {
|
|
138038
|
+
return errors;
|
|
138039
|
+
}
|
|
138100
138040
|
const commentExtractor = new CommentExtractor_default(tokenStream);
|
|
138101
138041
|
collectErrors(
|
|
138102
138042
|
commentExtractor.validate(),
|
|
@@ -139192,7 +139132,8 @@ var Transpiler = class {
|
|
|
139192
139132
|
const headerContent = this.generateHeaderForFile(file);
|
|
139193
139133
|
if (headerContent) {
|
|
139194
139134
|
const headerPath = this.pathResolver.getHeaderOutputPath(
|
|
139195
|
-
file.discoveredFile
|
|
139135
|
+
file.discoveredFile,
|
|
139136
|
+
this.cppDetected
|
|
139196
139137
|
);
|
|
139197
139138
|
this.fs.writeFile(headerPath, headerContent);
|
|
139198
139139
|
result.outputFiles.push(headerPath);
|
|
@@ -139595,7 +139536,8 @@ var Transpiler = class {
|
|
|
139595
139536
|
if (exportedSymbols.length === 0) {
|
|
139596
139537
|
return null;
|
|
139597
139538
|
}
|
|
139598
|
-
const
|
|
139539
|
+
const ext = this.cppDetected ? ".hpp" : ".h";
|
|
139540
|
+
const headerName = basename5(sourcePath).replace(/\.cnx$|\.cnext$/, ext);
|
|
139599
139541
|
const typeInput = this.state.getSymbolInfo(sourcePath);
|
|
139600
139542
|
const passByValueParams = this.state.getPassByValueParams(sourcePath) ?? /* @__PURE__ */ new Map();
|
|
139601
139543
|
const userIncludes = this.state.getUserIncludes(sourcePath);
|
|
@@ -139665,19 +139607,31 @@ var Transpiler = class {
|
|
|
139665
139607
|
convertToHeaderSymbols(symbols, unmodifiedParams, knownEnums) {
|
|
139666
139608
|
return symbols.map((symbol) => {
|
|
139667
139609
|
const headerSymbol = HeaderSymbolAdapter_default.fromTSymbol(symbol);
|
|
139668
|
-
if (symbol.kind
|
|
139669
|
-
|
|
139670
|
-
|
|
139671
|
-
|
|
139672
|
-
|
|
139673
|
-
|
|
139674
|
-
|
|
139675
|
-
|
|
139676
|
-
|
|
139677
|
-
|
|
139678
|
-
|
|
139679
|
-
|
|
139680
|
-
}
|
|
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 };
|
|
139681
139635
|
}
|
|
139682
139636
|
return headerSymbol;
|
|
139683
139637
|
});
|