c-next 0.1.49 → 0.1.50
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/package.json +1 -1
- package/src/codegen/CodeGenerator.ts +60 -1
- package/src/pipeline/Pipeline.ts +41 -0
package/package.json
CHANGED
|
@@ -1178,6 +1178,57 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
1178
1178
|
return this.functionParamLists;
|
|
1179
1179
|
}
|
|
1180
1180
|
|
|
1181
|
+
/**
|
|
1182
|
+
* Issue #561: Analyze modifications in a parse tree without full code generation.
|
|
1183
|
+
* Used by Pipeline.transpileSource() to collect modification info from includes
|
|
1184
|
+
* for cross-file const inference (unified with Pipeline.run() behavior).
|
|
1185
|
+
*
|
|
1186
|
+
* Returns the modifications and param lists discovered in this tree.
|
|
1187
|
+
*/
|
|
1188
|
+
analyzeModificationsOnly(tree: Parser.ProgramContext): {
|
|
1189
|
+
modifications: Map<string, Set<string>>;
|
|
1190
|
+
paramLists: Map<string, string[]>;
|
|
1191
|
+
} {
|
|
1192
|
+
// Save current state
|
|
1193
|
+
const savedModifications = new Map(this.modifiedParameters);
|
|
1194
|
+
const savedParamLists = new Map(this.functionParamLists);
|
|
1195
|
+
const savedCallGraph = new Map(this.functionCallGraph);
|
|
1196
|
+
|
|
1197
|
+
// Clear for fresh analysis
|
|
1198
|
+
this.modifiedParameters.clear();
|
|
1199
|
+
this.functionParamLists.clear();
|
|
1200
|
+
this.functionCallGraph.clear();
|
|
1201
|
+
|
|
1202
|
+
// Run modification analysis on the tree
|
|
1203
|
+
this.collectFunctionParametersAndModifications(tree);
|
|
1204
|
+
|
|
1205
|
+
// Capture results before restoring state
|
|
1206
|
+
const modifications = new Map<string, Set<string>>();
|
|
1207
|
+
for (const [funcName, params] of this.modifiedParameters) {
|
|
1208
|
+
modifications.set(funcName, new Set(params));
|
|
1209
|
+
}
|
|
1210
|
+
const paramLists = new Map<string, string[]>();
|
|
1211
|
+
for (const [funcName, params] of this.functionParamLists) {
|
|
1212
|
+
paramLists.set(funcName, [...params]);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// Restore previous state by clearing and repopulating (readonly maps)
|
|
1216
|
+
this.modifiedParameters.clear();
|
|
1217
|
+
for (const [k, v] of savedModifications) {
|
|
1218
|
+
this.modifiedParameters.set(k, v);
|
|
1219
|
+
}
|
|
1220
|
+
this.functionParamLists.clear();
|
|
1221
|
+
for (const [k, v] of savedParamLists) {
|
|
1222
|
+
this.functionParamLists.set(k, v);
|
|
1223
|
+
}
|
|
1224
|
+
this.functionCallGraph.clear();
|
|
1225
|
+
for (const [k, v] of savedCallGraph) {
|
|
1226
|
+
this.functionCallGraph.set(k, v);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
return { modifications, paramLists };
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1181
1232
|
/**
|
|
1182
1233
|
* Issue #268: Check if a callee function's parameter at given index is modified.
|
|
1183
1234
|
* Returns true if the callee modifies that parameter (should not have const).
|
|
@@ -2473,9 +2524,17 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
2473
2524
|
const memberNames: string[] = [];
|
|
2474
2525
|
|
|
2475
2526
|
// Start with primary identifier if it's a scope name (not 'global' or 'this')
|
|
2527
|
+
// Issue #561: When 'this' is used, resolve to the current scope name from funcName
|
|
2476
2528
|
const primaryId = primary.IDENTIFIER()?.getText();
|
|
2477
|
-
if (primaryId && primaryId !== "global"
|
|
2529
|
+
if (primaryId && primaryId !== "global") {
|
|
2478
2530
|
memberNames.push(primaryId);
|
|
2531
|
+
} else if (primary.THIS()) {
|
|
2532
|
+
// Issue #561: 'this' keyword - resolve to current scope name from funcName
|
|
2533
|
+
// funcName format: "ScopeName_methodName" -> extract "ScopeName"
|
|
2534
|
+
const scopeName = funcName.split("_")[0];
|
|
2535
|
+
if (scopeName && scopeName !== funcName) {
|
|
2536
|
+
memberNames.push(scopeName);
|
|
2537
|
+
}
|
|
2479
2538
|
}
|
|
2480
2539
|
|
|
2481
2540
|
// Collect member access names until we hit a function call
|
package/src/pipeline/Pipeline.ts
CHANGED
|
@@ -599,6 +599,7 @@ class Pipeline {
|
|
|
599
599
|
|
|
600
600
|
/**
|
|
601
601
|
* Stage 3: Collect symbols from a C-Next file
|
|
602
|
+
* Issue #561: Also collects modification analysis in C++ mode for unified cross-file const inference
|
|
602
603
|
*/
|
|
603
604
|
private collectCNextSymbols(file: IDiscoveredFile): void {
|
|
604
605
|
const content = readFileSync(file.path, "utf-8");
|
|
@@ -640,6 +641,32 @@ class Pipeline {
|
|
|
640
641
|
// This ensures enum member info is available for all files before code generation
|
|
641
642
|
const symbolInfo = TSymbolInfoAdapter.convert(tSymbols);
|
|
642
643
|
this.symbolInfoByFile.set(file.path, symbolInfo);
|
|
644
|
+
|
|
645
|
+
// Issue #561: Collect modification analysis in C++ mode for cross-file const inference
|
|
646
|
+
// This unifies behavior between run() and transpileSource() code paths
|
|
647
|
+
if (this.cppDetected) {
|
|
648
|
+
const { modifications, paramLists } =
|
|
649
|
+
this.codeGenerator.analyzeModificationsOnly(tree);
|
|
650
|
+
|
|
651
|
+
// Accumulate modifications
|
|
652
|
+
for (const [funcName, params] of modifications) {
|
|
653
|
+
const existing = this.accumulatedModifications.get(funcName);
|
|
654
|
+
if (existing) {
|
|
655
|
+
for (const param of params) {
|
|
656
|
+
existing.add(param);
|
|
657
|
+
}
|
|
658
|
+
} else {
|
|
659
|
+
this.accumulatedModifications.set(funcName, new Set(params));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Accumulate param lists
|
|
664
|
+
for (const [funcName, params] of paramLists) {
|
|
665
|
+
if (!this.accumulatedParamLists.has(funcName)) {
|
|
666
|
+
this.accumulatedParamLists.set(funcName, [...params]);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
643
670
|
}
|
|
644
671
|
|
|
645
672
|
/**
|
|
@@ -1241,6 +1268,11 @@ class Pipeline {
|
|
|
1241
1268
|
await this.cacheManager.initialize();
|
|
1242
1269
|
}
|
|
1243
1270
|
|
|
1271
|
+
// Issue #561: Clear cross-file modification tracking for fresh analysis
|
|
1272
|
+
// This ensures each transpileSource() call starts with a clean slate
|
|
1273
|
+
this.accumulatedModifications.clear();
|
|
1274
|
+
this.accumulatedParamLists.clear();
|
|
1275
|
+
|
|
1244
1276
|
// Step 1: Build search paths using unified IncludeResolver
|
|
1245
1277
|
const searchPaths = IncludeResolver.buildSearchPaths(
|
|
1246
1278
|
workingDir,
|
|
@@ -1415,6 +1447,15 @@ class Pipeline {
|
|
|
1415
1447
|
);
|
|
1416
1448
|
}
|
|
1417
1449
|
|
|
1450
|
+
// Issue #561: Inject cross-file modification data for const inference
|
|
1451
|
+
// This unifies behavior with run() - both paths now share modifications from includes
|
|
1452
|
+
if (this.cppDetected && this.accumulatedModifications.size > 0) {
|
|
1453
|
+
this.codeGenerator.setCrossFileModifications(
|
|
1454
|
+
this.accumulatedModifications,
|
|
1455
|
+
this.accumulatedParamLists,
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1418
1459
|
const code = this.codeGenerator.generate(
|
|
1419
1460
|
tree,
|
|
1420
1461
|
this.symbolTable,
|