c-next 0.2.8 → 0.2.9
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 +213 -69
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +4 -1
- package/src/transpiler/logic/IncludeExtractor.ts +12 -6
- package/src/transpiler/logic/__tests__/IncludeExtractor.test.ts +24 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +32 -24
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +3 -3
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +16 -16
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +8 -1
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +21 -6
- package/src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts +15 -2
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +34 -11
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +2 -1
- package/src/transpiler/output/codegen/generators/support/IncludeGenerator.ts +19 -7
- package/src/transpiler/output/codegen/generators/support/__tests__/IncludeGenerator.test.ts +68 -0
- package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +14 -2
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +3 -5
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +56 -8
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +5 -6
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +60 -2
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +14 -16
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +25 -0
- package/src/transpiler/state/CodeGenState.ts +40 -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.9",
|
|
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",
|
|
@@ -110828,6 +110828,13 @@ var CodeGenState = class {
|
|
|
110828
110828
|
static inFunctionBody = false;
|
|
110829
110829
|
/** Expected type for struct initializers and enum inference */
|
|
110830
110830
|
static expectedType = null;
|
|
110831
|
+
/**
|
|
110832
|
+
* Suppress bare enum resolution even when expectedType is set.
|
|
110833
|
+
* Issue #872: MISRA 7.2 requires expectedType for U suffix on function args,
|
|
110834
|
+
* but bare enum resolution in function args was never allowed and changing
|
|
110835
|
+
* that would require ADR approval.
|
|
110836
|
+
*/
|
|
110837
|
+
static suppressBareEnumResolution = false;
|
|
110831
110838
|
/** Track args parameter name for main() translation */
|
|
110832
110839
|
static mainArgsName = null;
|
|
110833
110840
|
/** ADR-044: Current assignment context for overflow behavior */
|
|
@@ -110922,6 +110929,7 @@ var CodeGenState = class {
|
|
|
110922
110929
|
this.indentLevel = 0;
|
|
110923
110930
|
this.inFunctionBody = false;
|
|
110924
110931
|
this.expectedType = null;
|
|
110932
|
+
this.suppressBareEnumResolution = false;
|
|
110925
110933
|
this.mainArgsName = null;
|
|
110926
110934
|
this.assignmentContext = {
|
|
110927
110935
|
targetName: null,
|
|
@@ -110972,6 +110980,32 @@ var CodeGenState = class {
|
|
|
110972
110980
|
this.floatBitShadows.clear();
|
|
110973
110981
|
this.floatShadowCurrent.clear();
|
|
110974
110982
|
}
|
|
110983
|
+
/**
|
|
110984
|
+
* Execute a function with a temporary expectedType, restoring on completion.
|
|
110985
|
+
* Issue #872: Extracted to eliminate duplicate save/restore pattern and add exception safety.
|
|
110986
|
+
*
|
|
110987
|
+
* @param type - The expected type to set (if falsy, no change is made)
|
|
110988
|
+
* @param fn - The function to execute
|
|
110989
|
+
* @param suppressEnumResolution - If true, suppress bare enum resolution (for MISRA-only contexts)
|
|
110990
|
+
* @returns The result of the function
|
|
110991
|
+
*/
|
|
110992
|
+
static withExpectedType(type, fn, suppressEnumResolution = false) {
|
|
110993
|
+
if (!type) {
|
|
110994
|
+
return fn();
|
|
110995
|
+
}
|
|
110996
|
+
const savedType = this.expectedType;
|
|
110997
|
+
const savedSuppress = this.suppressBareEnumResolution;
|
|
110998
|
+
this.expectedType = type;
|
|
110999
|
+
if (suppressEnumResolution) {
|
|
111000
|
+
this.suppressBareEnumResolution = true;
|
|
111001
|
+
}
|
|
111002
|
+
try {
|
|
111003
|
+
return fn();
|
|
111004
|
+
} finally {
|
|
111005
|
+
this.expectedType = savedType;
|
|
111006
|
+
this.suppressBareEnumResolution = savedSuppress;
|
|
111007
|
+
}
|
|
111008
|
+
}
|
|
110975
111009
|
// ===========================================================================
|
|
110976
111010
|
// CONVENIENCE LOOKUP METHODS
|
|
110977
111011
|
// ===========================================================================
|
|
@@ -114424,8 +114458,14 @@ var UNSIGNED_TYPES3 = /* @__PURE__ */ new Set([
|
|
|
114424
114458
|
"u32",
|
|
114425
114459
|
"uint8_t",
|
|
114426
114460
|
"uint16_t",
|
|
114427
|
-
"uint32_t"
|
|
114461
|
+
"uint32_t",
|
|
114462
|
+
"size_t"
|
|
114463
|
+
// Array indices (MISRA 7.2)
|
|
114428
114464
|
]);
|
|
114465
|
+
function resolveTypedef(typeName) {
|
|
114466
|
+
const underlyingType = CodeGenState.getTypedefType(typeName);
|
|
114467
|
+
return underlyingType ?? typeName;
|
|
114468
|
+
}
|
|
114429
114469
|
function isNumericIntegerLiteral(text) {
|
|
114430
114470
|
if (text.startsWith('"') || text.startsWith("'")) {
|
|
114431
114471
|
return false;
|
|
@@ -114471,9 +114511,10 @@ var generateLiteral = (node, _input, state, _orchestrator) => {
|
|
|
114471
114511
|
}
|
|
114472
114512
|
const expectedType = state?.expectedType;
|
|
114473
114513
|
if (expectedType && isNumericIntegerLiteral(literalText) && !hasUnsignedSuffix(literalText)) {
|
|
114474
|
-
|
|
114514
|
+
const resolvedType = resolveTypedef(expectedType);
|
|
114515
|
+
if (UNSIGNED_64_TYPES.has(resolvedType)) {
|
|
114475
114516
|
literalText = literalText + "ULL";
|
|
114476
|
-
} else if (UNSIGNED_TYPES3.has(
|
|
114517
|
+
} else if (UNSIGNED_TYPES3.has(resolvedType)) {
|
|
114477
114518
|
literalText = literalText + "U";
|
|
114478
114519
|
}
|
|
114479
114520
|
}
|
|
@@ -115138,7 +115179,12 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115138
115179
|
orchestrator
|
|
115139
115180
|
);
|
|
115140
115181
|
}
|
|
115141
|
-
|
|
115182
|
+
const argCode = CodeGenState.withExpectedType(
|
|
115183
|
+
targetParam?.baseType,
|
|
115184
|
+
() => orchestrator.generateExpression(e),
|
|
115185
|
+
true
|
|
115186
|
+
// suppressEnumResolution
|
|
115187
|
+
);
|
|
115142
115188
|
if (!targetParam?.baseType?.endsWith("*")) {
|
|
115143
115189
|
return wrapWithCppEnumCast(argCode, e, targetParam?.baseType, orchestrator);
|
|
115144
115190
|
}
|
|
@@ -115154,10 +115200,13 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115154
115200
|
isPointerVariable = true;
|
|
115155
115201
|
}
|
|
115156
115202
|
const needsAddressOf = argType && !argType.endsWith("*") && !argCode.startsWith("&") && !targetParam.isArray && !isPointerVariable && (orchestrator.isStructType(argType) || _parameterExpectsAddressOf(targetParam.baseType, argType, orchestrator));
|
|
115157
|
-
|
|
115158
|
-
|
|
115159
|
-
|
|
115160
|
-
|
|
115203
|
+
const finalArgCode = needsAddressOf ? `&${argCode}` : argCode;
|
|
115204
|
+
return wrapWithCppEnumCast(
|
|
115205
|
+
finalArgCode,
|
|
115206
|
+
e,
|
|
115207
|
+
targetParam?.baseType,
|
|
115208
|
+
orchestrator
|
|
115209
|
+
);
|
|
115161
115210
|
};
|
|
115162
115211
|
var _shouldPassByValue = (funcExpr, idx, targetParam, isCrossFile, orchestrator) => {
|
|
115163
115212
|
if (!targetParam) return false;
|
|
@@ -115204,7 +115253,12 @@ var generateFunctionCall = (funcExpr, argCtx, input, _state, orchestrator) => {
|
|
|
115204
115253
|
resolved.isCrossFile,
|
|
115205
115254
|
orchestrator
|
|
115206
115255
|
)) {
|
|
115207
|
-
const argCode =
|
|
115256
|
+
const argCode = CodeGenState.withExpectedType(
|
|
115257
|
+
targetParam?.baseType,
|
|
115258
|
+
() => orchestrator.generateExpression(e),
|
|
115259
|
+
true
|
|
115260
|
+
// suppressEnumResolution
|
|
115261
|
+
);
|
|
115208
115262
|
return wrapWithCppEnumCast(
|
|
115209
115263
|
argCode,
|
|
115210
115264
|
e,
|
|
@@ -116556,12 +116610,15 @@ var generateSubscriptAccess = (ctx, input, state, orchestrator, effects) => {
|
|
|
116556
116610
|
return output;
|
|
116557
116611
|
};
|
|
116558
116612
|
var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
116559
|
-
const index =
|
|
116613
|
+
const index = CodeGenState.withExpectedType(
|
|
116614
|
+
"size_t",
|
|
116615
|
+
() => orchestrator.generateExpression(expr)
|
|
116616
|
+
);
|
|
116560
116617
|
validateNotBitmapMember(ctx, input);
|
|
116561
116618
|
const isRegisterAccess = checkRegisterAccess(ctx, input);
|
|
116562
116619
|
const identifierTypeInfo = getIdentifierTypeInfo(ctx, input);
|
|
116563
116620
|
if (isRegisterAccess) {
|
|
116564
|
-
output.result = `((${ctx.result} >> ${index}) & 1)`;
|
|
116621
|
+
output.result = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116565
116622
|
return output;
|
|
116566
116623
|
}
|
|
116567
116624
|
if (ctx.currentMemberIsArray) {
|
|
@@ -116575,7 +116632,7 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116575
116632
|
}
|
|
116576
116633
|
const isPrimitiveIntMember = ctx.currentStructType && TypeCheckUtils_default.isInteger(ctx.currentStructType);
|
|
116577
116634
|
if (isPrimitiveIntMember) {
|
|
116578
|
-
output.result = `((${ctx.result} >> ${index}) & 1)`;
|
|
116635
|
+
output.result = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116579
116636
|
output.currentStructType = void 0;
|
|
116580
116637
|
return output;
|
|
116581
116638
|
}
|
|
@@ -116633,12 +116690,18 @@ var handleDefaultSubscript = (ctx, index, typeInfo, output) => {
|
|
|
116633
116690
|
subscriptCount: 1,
|
|
116634
116691
|
isRegisterAccess: false
|
|
116635
116692
|
});
|
|
116636
|
-
|
|
116693
|
+
if (subscriptKind === "bit_single") {
|
|
116694
|
+
output.result = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116695
|
+
} else {
|
|
116696
|
+
output.result = `${ctx.result}[${index}]`;
|
|
116697
|
+
}
|
|
116637
116698
|
return output;
|
|
116638
116699
|
};
|
|
116639
116700
|
var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects, output) => {
|
|
116640
|
-
const start =
|
|
116641
|
-
|
|
116701
|
+
const [start, width] = CodeGenState.withExpectedType("size_t", () => [
|
|
116702
|
+
orchestrator.generateExpression(exprs[0]),
|
|
116703
|
+
orchestrator.generateExpression(exprs[1])
|
|
116704
|
+
]);
|
|
116642
116705
|
const isFloatType = ctx.primaryTypeInfo?.baseType === "f32" || ctx.primaryTypeInfo?.baseType === "f64";
|
|
116643
116706
|
if (isFloatType && ctx.rootIdentifier) {
|
|
116644
116707
|
output.result = handleFloatBitRange(
|
|
@@ -116655,7 +116718,7 @@ var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects,
|
|
|
116655
116718
|
);
|
|
116656
116719
|
} else {
|
|
116657
116720
|
const mask = orchestrator.generateBitMask(width);
|
|
116658
|
-
if (start === "0") {
|
|
116721
|
+
if (start === "0" || start === "0U") {
|
|
116659
116722
|
output.result = `((${ctx.result}) & ${mask})`;
|
|
116660
116723
|
} else {
|
|
116661
116724
|
output.result = `((${ctx.result} >> ${start}) & ${mask})`;
|
|
@@ -116690,7 +116753,7 @@ var handleFloatBitRange = (ctx, state, orchestrator, effects) => {
|
|
|
116690
116753
|
if (!shadowIsCurrent) {
|
|
116691
116754
|
orchestrator.addPendingTempDeclaration(`${shadowName}.f = ${ctx.result};`);
|
|
116692
116755
|
}
|
|
116693
|
-
if (ctx.start === "0") {
|
|
116756
|
+
if (ctx.start === "0" || ctx.start === "0U") {
|
|
116694
116757
|
return `(${shadowName}.u & ${mask})`;
|
|
116695
116758
|
}
|
|
116696
116759
|
return `((${shadowName}.u >> ${ctx.start}) & ${mask})`;
|
|
@@ -117612,7 +117675,11 @@ var FunctionGenerator_default = generateFunction;
|
|
|
117612
117675
|
// src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts
|
|
117613
117676
|
function generateInitializer(varDecl, isArray, orchestrator) {
|
|
117614
117677
|
if (varDecl.expression()) {
|
|
117615
|
-
|
|
117678
|
+
const typeName = orchestrator.generateType(varDecl.type());
|
|
117679
|
+
return CodeGenState.withExpectedType(
|
|
117680
|
+
typeName,
|
|
117681
|
+
() => ` = ${orchestrator.generateExpression(varDecl.expression())}`
|
|
117682
|
+
);
|
|
117616
117683
|
}
|
|
117617
117684
|
return ` = ${orchestrator.getZeroInitializer(varDecl.type(), isArray)}`;
|
|
117618
117685
|
}
|
|
@@ -118804,7 +118871,7 @@ var CnxFileResolver = class {
|
|
|
118804
118871
|
var CnxFileResolver_default = CnxFileResolver;
|
|
118805
118872
|
|
|
118806
118873
|
// src/transpiler/output/codegen/generators/support/IncludeGenerator.ts
|
|
118807
|
-
var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs) => {
|
|
118874
|
+
var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs, cppMode) => {
|
|
118808
118875
|
if (inputs.length === 0) {
|
|
118809
118876
|
return null;
|
|
118810
118877
|
}
|
|
@@ -118818,25 +118885,33 @@ var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs) => {
|
|
|
118818
118885
|
foundPath,
|
|
118819
118886
|
inputs
|
|
118820
118887
|
);
|
|
118821
|
-
|
|
118888
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
118889
|
+
return relativePath ? relativePath.replace(/\.cnx$/, ext) : null;
|
|
118822
118890
|
};
|
|
118823
118891
|
var transformAngleInclude = (includeText, filename, options) => {
|
|
118824
|
-
const {
|
|
118892
|
+
const {
|
|
118893
|
+
sourcePath,
|
|
118894
|
+
includeDirs = [],
|
|
118895
|
+
inputs = [],
|
|
118896
|
+
cppMode = false
|
|
118897
|
+
} = options;
|
|
118825
118898
|
if (sourcePath) {
|
|
118826
118899
|
const resolvedPath = resolveAngleIncludePath(
|
|
118827
118900
|
filename,
|
|
118828
118901
|
sourcePath,
|
|
118829
118902
|
includeDirs,
|
|
118830
|
-
inputs
|
|
118903
|
+
inputs,
|
|
118904
|
+
cppMode
|
|
118831
118905
|
);
|
|
118832
118906
|
if (resolvedPath) {
|
|
118833
118907
|
return includeText.replace(`<${filename}.cnx>`, `<${resolvedPath}>`);
|
|
118834
118908
|
}
|
|
118835
118909
|
}
|
|
118836
|
-
|
|
118910
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
118911
|
+
return includeText.replace(`<${filename}.cnx>`, `<${filename}${ext}>`);
|
|
118837
118912
|
};
|
|
118838
118913
|
var transformQuoteInclude = (includeText, filepath, options) => {
|
|
118839
|
-
const { sourcePath } = options;
|
|
118914
|
+
const { sourcePath, cppMode = false } = options;
|
|
118840
118915
|
if (sourcePath) {
|
|
118841
118916
|
const sourceDir = path.dirname(sourcePath);
|
|
118842
118917
|
const cnxPath = path.resolve(sourceDir, `${filepath}.cnx`);
|
|
@@ -118848,7 +118923,8 @@ var transformQuoteInclude = (includeText, filepath, options) => {
|
|
|
118848
118923
|
);
|
|
118849
118924
|
}
|
|
118850
118925
|
}
|
|
118851
|
-
|
|
118926
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
118927
|
+
return includeText.replace(`"${filepath}.cnx"`, `"${filepath}${ext}"`);
|
|
118852
118928
|
};
|
|
118853
118929
|
var transformIncludeDirective = (includeText, options) => {
|
|
118854
118930
|
const angleMatch = /#\s*include\s*<([^>]+)\.cnx>/.exec(includeText);
|
|
@@ -122618,6 +122694,7 @@ var ArgumentGenerator = class _ArgumentGenerator {
|
|
|
122618
122694
|
}
|
|
122619
122695
|
/**
|
|
122620
122696
|
* Handle rvalue argument (literals or complex expressions).
|
|
122697
|
+
* Issue #872: Sets expectedType for MISRA 7.2 U suffix on unsigned literals.
|
|
122621
122698
|
*/
|
|
122622
122699
|
static handleRvalueArg(ctx, targetParamBaseType, callbacks) {
|
|
122623
122700
|
if (!targetParamBaseType) {
|
|
@@ -122625,9 +122702,19 @@ var ArgumentGenerator = class _ArgumentGenerator {
|
|
|
122625
122702
|
}
|
|
122626
122703
|
const cType = TYPE_MAP_default[targetParamBaseType];
|
|
122627
122704
|
if (!cType || cType === "void") {
|
|
122628
|
-
return
|
|
122705
|
+
return CodeGenState.withExpectedType(
|
|
122706
|
+
targetParamBaseType,
|
|
122707
|
+
() => callbacks.generateExpression(ctx),
|
|
122708
|
+
true
|
|
122709
|
+
// suppressEnumResolution
|
|
122710
|
+
);
|
|
122629
122711
|
}
|
|
122630
|
-
const value =
|
|
122712
|
+
const value = CodeGenState.withExpectedType(
|
|
122713
|
+
targetParamBaseType,
|
|
122714
|
+
() => callbacks.generateExpression(ctx),
|
|
122715
|
+
true
|
|
122716
|
+
// suppressEnumResolution
|
|
122717
|
+
);
|
|
122631
122718
|
if (CodeGenState.cppMode) {
|
|
122632
122719
|
return value;
|
|
122633
122720
|
}
|
|
@@ -123046,6 +123133,14 @@ var AssignmentExpectedTypeResolver = class _AssignmentExpectedTypeResolver {
|
|
|
123046
123133
|
identifiers
|
|
123047
123134
|
);
|
|
123048
123135
|
}
|
|
123136
|
+
if (identifiers.length === 1 && hasSubscript) {
|
|
123137
|
+
return _AssignmentExpectedTypeResolver.resolveForArrayElement(baseId);
|
|
123138
|
+
}
|
|
123139
|
+
if (identifiers.length >= 2 && hasSubscript) {
|
|
123140
|
+
return _AssignmentExpectedTypeResolver.resolveForMemberArrayElement(
|
|
123141
|
+
identifiers
|
|
123142
|
+
);
|
|
123143
|
+
}
|
|
123049
123144
|
}
|
|
123050
123145
|
return { expectedType: null, assignmentContext: null };
|
|
123051
123146
|
}
|
|
@@ -123072,8 +123167,40 @@ var AssignmentExpectedTypeResolver = class _AssignmentExpectedTypeResolver {
|
|
|
123072
123167
|
*
|
|
123073
123168
|
* Issue #452: Enables type-aware resolution of unqualified enum members
|
|
123074
123169
|
* for nested access (e.g., config.nested.field).
|
|
123170
|
+
*
|
|
123171
|
+
* Delegates to walkMemberChain shared implementation.
|
|
123075
123172
|
*/
|
|
123076
123173
|
static resolveForMemberChain(identifiers) {
|
|
123174
|
+
return _AssignmentExpectedTypeResolver.walkMemberChain(identifiers);
|
|
123175
|
+
}
|
|
123176
|
+
/**
|
|
123177
|
+
* Resolve expected type for array element access.
|
|
123178
|
+
* Issue #872: arr[i] <- value needs baseType for MISRA 7.2 U suffix.
|
|
123179
|
+
*/
|
|
123180
|
+
static resolveForArrayElement(id) {
|
|
123181
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(id);
|
|
123182
|
+
if (!typeInfo?.isArray) {
|
|
123183
|
+
return { expectedType: null, assignmentContext: null };
|
|
123184
|
+
}
|
|
123185
|
+
return { expectedType: typeInfo.baseType, assignmentContext: null };
|
|
123186
|
+
}
|
|
123187
|
+
/**
|
|
123188
|
+
* Resolve expected type for member chain ending with array access.
|
|
123189
|
+
* Issue #872: struct.arr[i] <- value needs element type for MISRA 7.2.
|
|
123190
|
+
*
|
|
123191
|
+
* Delegates to walkMemberChain which handles both member chain and
|
|
123192
|
+
* member-array-element patterns identically (both return final field type).
|
|
123193
|
+
*/
|
|
123194
|
+
static resolveForMemberArrayElement(identifiers) {
|
|
123195
|
+
return _AssignmentExpectedTypeResolver.walkMemberChain(identifiers);
|
|
123196
|
+
}
|
|
123197
|
+
/**
|
|
123198
|
+
* Walk a struct member chain to find the final field's type.
|
|
123199
|
+
* Shared implementation for both member chain and member-array-element patterns.
|
|
123200
|
+
*
|
|
123201
|
+
* Issue #831: Uses SymbolTable as single source of truth for struct fields.
|
|
123202
|
+
*/
|
|
123203
|
+
static walkMemberChain(identifiers) {
|
|
123077
123204
|
if (identifiers.length < 2) {
|
|
123078
123205
|
return { expectedType: null, assignmentContext: null };
|
|
123079
123206
|
}
|
|
@@ -123619,11 +123746,10 @@ var ArrayInitHelper = class _ArrayInitHelper {
|
|
|
123619
123746
|
*/
|
|
123620
123747
|
static _generateArrayInitValue(typeCtx, expression, callbacks) {
|
|
123621
123748
|
const typeName = callbacks.getTypeName(typeCtx);
|
|
123622
|
-
|
|
123623
|
-
|
|
123624
|
-
|
|
123625
|
-
|
|
123626
|
-
return initValue;
|
|
123749
|
+
return CodeGenState.withExpectedType(
|
|
123750
|
+
typeName,
|
|
123751
|
+
() => callbacks.generateExpression(expression)
|
|
123752
|
+
);
|
|
123627
123753
|
}
|
|
123628
123754
|
/**
|
|
123629
123755
|
* Check if the last expression was an array initializer
|
|
@@ -124316,15 +124442,14 @@ ${assignments}`;
|
|
|
124316
124442
|
return `${decl} = ${callbacks.getZeroInitializer(typeCtx, isArray)}`;
|
|
124317
124443
|
}
|
|
124318
124444
|
const typeName = callbacks.getTypeName(typeCtx);
|
|
124319
|
-
const savedExpectedType = CodeGenState.expectedType;
|
|
124320
|
-
CodeGenState.expectedType = typeName;
|
|
124321
124445
|
EnumAssignmentValidator_default.validateEnumAssignment(typeName, ctx.expression());
|
|
124322
124446
|
_VariableDeclHelper.validateIntegerInitializer(ctx, typeName, {
|
|
124323
124447
|
getExpressionType: callbacks.getExpressionType
|
|
124324
124448
|
});
|
|
124325
|
-
|
|
124326
|
-
|
|
124327
|
-
|
|
124449
|
+
return CodeGenState.withExpectedType(
|
|
124450
|
+
typeName,
|
|
124451
|
+
() => `${decl} = ${callbacks.generateExpression(ctx.expression())}`
|
|
124452
|
+
);
|
|
124328
124453
|
}
|
|
124329
124454
|
// ========================================================================
|
|
124330
124455
|
// Tier 4: Orchestrators (main entry points)
|
|
@@ -127245,13 +127370,16 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
127245
127370
|
/**
|
|
127246
127371
|
* Issue #477: Generate expression with a specific expected type context.
|
|
127247
127372
|
* Used by return statements to resolve unqualified enum values.
|
|
127373
|
+
* Note: Uses explicit save/restore (not withExpectedType) to support null values.
|
|
127248
127374
|
*/
|
|
127249
127375
|
generateExpressionWithExpectedType(ctx, expectedType) {
|
|
127250
|
-
const
|
|
127376
|
+
const saved = CodeGenState.expectedType;
|
|
127251
127377
|
CodeGenState.expectedType = expectedType;
|
|
127252
|
-
|
|
127253
|
-
|
|
127254
|
-
|
|
127378
|
+
try {
|
|
127379
|
+
return this.generateExpression(ctx);
|
|
127380
|
+
} finally {
|
|
127381
|
+
CodeGenState.expectedType = saved;
|
|
127382
|
+
}
|
|
127255
127383
|
}
|
|
127256
127384
|
/**
|
|
127257
127385
|
* Generate type translation (C-Next type -> C type).
|
|
@@ -128596,15 +128724,17 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128596
128724
|
return DEFAULT_TARGET2;
|
|
128597
128725
|
}
|
|
128598
128726
|
/**
|
|
128599
|
-
* ADR-010: Transform #include directives, converting .cnx to .h
|
|
128727
|
+
* ADR-010: Transform #include directives, converting .cnx to .h or .hpp
|
|
128600
128728
|
* ADR-053 A5: Delegates to IncludeGenerator
|
|
128601
128729
|
* Issue #349: Now passes includeDirs and inputs for angle-bracket resolution
|
|
128730
|
+
* Issue #941: Now passes cppMode for .hpp extension in C++ mode
|
|
128602
128731
|
*/
|
|
128603
128732
|
transformIncludeDirective(includeText) {
|
|
128604
128733
|
return includeTransformIncludeDirective(includeText, {
|
|
128605
128734
|
sourcePath: CodeGenState.sourcePath,
|
|
128606
128735
|
includeDirs: CodeGenState.includeDirs,
|
|
128607
|
-
inputs: CodeGenState.inputs
|
|
128736
|
+
inputs: CodeGenState.inputs,
|
|
128737
|
+
cppMode: CodeGenState.cppMode
|
|
128608
128738
|
});
|
|
128609
128739
|
}
|
|
128610
128740
|
// Issue #63: validateIncludeNotImplementationFile moved to TypeValidator
|
|
@@ -129342,19 +129472,20 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129342
129472
|
const structFieldTypes = CodeGenState.symbolTable?.getStructFieldTypes(typeName);
|
|
129343
129473
|
const fields = fieldList.fieldInitializer().map((field) => {
|
|
129344
129474
|
const fieldName = field.IDENTIFIER().getText();
|
|
129345
|
-
|
|
129475
|
+
let fieldType;
|
|
129346
129476
|
if (structFieldTypes?.has(fieldName)) {
|
|
129347
|
-
|
|
129477
|
+
fieldType = structFieldTypes.get(fieldName);
|
|
129348
129478
|
if (fieldType.includes("_")) {
|
|
129349
129479
|
const parts = fieldType.split("_");
|
|
129350
129480
|
if (parts.length > 1 && this.isCppScopeSymbol(parts[0])) {
|
|
129351
129481
|
fieldType = parts.join("::");
|
|
129352
129482
|
}
|
|
129353
129483
|
}
|
|
129354
|
-
CodeGenState.expectedType = fieldType;
|
|
129355
129484
|
}
|
|
129356
|
-
const value =
|
|
129357
|
-
|
|
129485
|
+
const value = CodeGenState.withExpectedType(
|
|
129486
|
+
fieldType,
|
|
129487
|
+
() => this.generateExpression(field.expression())
|
|
129488
|
+
);
|
|
129358
129489
|
return { fieldName, value };
|
|
129359
129490
|
});
|
|
129360
129491
|
if (isCppClass) {
|
|
@@ -129869,18 +130000,20 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129869
130000
|
// ADR-001: <- becomes = in C, with compound assignment operators
|
|
129870
130001
|
generateAssignment(ctx) {
|
|
129871
130002
|
const targetCtx = ctx.assignmentTarget();
|
|
129872
|
-
const savedExpectedType = CodeGenState.expectedType;
|
|
129873
130003
|
const savedAssignmentContext = { ...CodeGenState.assignmentContext };
|
|
129874
130004
|
const resolved = AssignmentExpectedTypeResolver_default.resolve(targetCtx);
|
|
129875
|
-
if (resolved.expectedType) {
|
|
129876
|
-
CodeGenState.expectedType = resolved.expectedType;
|
|
129877
|
-
}
|
|
129878
130005
|
if (resolved.assignmentContext) {
|
|
129879
130006
|
CodeGenState.assignmentContext = resolved.assignmentContext;
|
|
129880
130007
|
}
|
|
129881
|
-
|
|
129882
|
-
|
|
129883
|
-
|
|
130008
|
+
let value;
|
|
130009
|
+
try {
|
|
130010
|
+
value = CodeGenState.withExpectedType(
|
|
130011
|
+
resolved.expectedType,
|
|
130012
|
+
() => this.generateExpression(ctx.expression())
|
|
130013
|
+
);
|
|
130014
|
+
} finally {
|
|
130015
|
+
CodeGenState.assignmentContext = savedAssignmentContext;
|
|
130016
|
+
}
|
|
129884
130017
|
const operatorCtx = ctx.assignmentOperator();
|
|
129885
130018
|
const cnextOp = operatorCtx.getText();
|
|
129886
130019
|
const cOp = ASSIGNMENT_OPERATOR_MAP2[cnextOp] || "=";
|
|
@@ -130090,7 +130223,11 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130090
130223
|
* @returns The qualified enum member access, or null if not an enum member
|
|
130091
130224
|
*/
|
|
130092
130225
|
_resolveUnqualifiedEnumMember(id) {
|
|
130093
|
-
if (CodeGenState.
|
|
130226
|
+
if (CodeGenState.suppressBareEnumResolution) {
|
|
130227
|
+
} else if (
|
|
130228
|
+
// Type-aware resolution: check only the expected enum type
|
|
130229
|
+
CodeGenState.expectedType && CodeGenState.symbols.knownEnums.has(CodeGenState.expectedType)
|
|
130230
|
+
) {
|
|
130094
130231
|
const members = CodeGenState.symbols.enumMembers.get(
|
|
130095
130232
|
CodeGenState.expectedType
|
|
130096
130233
|
);
|
|
@@ -130888,15 +131025,16 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
|
|
|
130888
131025
|
}
|
|
130889
131026
|
if (options.userIncludes && options.userIncludes.length > 0) {
|
|
130890
131027
|
for (const include of options.userIncludes) {
|
|
130891
|
-
|
|
130892
|
-
|
|
131028
|
+
lines.push(include);
|
|
131029
|
+
}
|
|
131030
|
+
}
|
|
131031
|
+
const userIncludeSet = new Set(options.userIncludes ?? []);
|
|
131032
|
+
if (options.cppMode && options.userIncludes) {
|
|
131033
|
+
for (const inc of options.userIncludes) {
|
|
131034
|
+
const hVersion = inc.replace(/\.hpp"/, '.h"').replace(/\.hpp>/, ".h>");
|
|
131035
|
+
userIncludeSet.add(hVersion);
|
|
130893
131036
|
}
|
|
130894
131037
|
}
|
|
130895
|
-
const userIncludeSet = new Set(
|
|
130896
|
-
options.userIncludes?.map(
|
|
130897
|
-
(inc) => options.cppMode ? inc.replace(/\.h"/, '.hpp"').replace(/\.h>/, ".hpp>") : inc
|
|
130898
|
-
) ?? []
|
|
130899
|
-
);
|
|
130900
131038
|
for (const directive of headersToInclude) {
|
|
130901
131039
|
if (!userIncludeSet.has(directive)) {
|
|
130902
131040
|
lines.push(directive);
|
|
@@ -131274,18 +131412,21 @@ var IncludeExtractor = class {
|
|
|
131274
131412
|
/**
|
|
131275
131413
|
* Extract user includes from a parsed C-Next program.
|
|
131276
131414
|
*
|
|
131277
|
-
* Extracts #include directives for .cnx files and transforms them to .h includes.
|
|
131415
|
+
* Extracts #include directives for .cnx files and transforms them to .h or .hpp includes.
|
|
131416
|
+
* Issue #941: Uses .hpp extension when cppMode is true.
|
|
131278
131417
|
* This enables cross-file type definitions in generated headers.
|
|
131279
131418
|
*
|
|
131280
131419
|
* @param tree The parsed C-Next program
|
|
131281
|
-
* @
|
|
131420
|
+
* @param cppMode Whether to use .hpp extension (C++ mode)
|
|
131421
|
+
* @returns Array of transformed include strings (e.g., '#include "types.h"' or '#include "types.hpp"')
|
|
131282
131422
|
*/
|
|
131283
|
-
static collectUserIncludes(tree) {
|
|
131423
|
+
static collectUserIncludes(tree, cppMode = false) {
|
|
131284
131424
|
const userIncludes = [];
|
|
131425
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
131285
131426
|
for (const includeDir of tree.includeDirective()) {
|
|
131286
131427
|
const includeText = includeDir.getText();
|
|
131287
131428
|
if (includeText.includes(".cnx")) {
|
|
131288
|
-
const transformedInclude = includeText.replace(/\.cnx"/,
|
|
131429
|
+
const transformedInclude = includeText.replace(/\.cnx"/, `${ext}"`).replace(/\.cnx>/, `${ext}>`);
|
|
131289
131430
|
userIncludes.push(transformedInclude);
|
|
131290
131431
|
}
|
|
131291
131432
|
}
|
|
@@ -138923,7 +139064,10 @@ var Transpiler = class {
|
|
|
138923
139064
|
cppMode: this.cppDetected,
|
|
138924
139065
|
symbolInfo
|
|
138925
139066
|
});
|
|
138926
|
-
const userIncludes = IncludeExtractor_default.collectUserIncludes(
|
|
139067
|
+
const userIncludes = IncludeExtractor_default.collectUserIncludes(
|
|
139068
|
+
tree,
|
|
139069
|
+
this.cppDetected
|
|
139070
|
+
);
|
|
138927
139071
|
const passByValue = this.codeGenerator.getPassByValueParams();
|
|
138928
139072
|
const passByValueCopy = MapUtils_default.deepCopyStringSetMap(passByValue);
|
|
138929
139073
|
this.state.setSymbolInfo(sourcePath, symbolInfo);
|