c-next 0.2.16 → 0.2.18

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.
Files changed (118) hide show
  1. package/README.md +18 -2
  2. package/dist/index.js +8897 -6260
  3. package/dist/index.js.map +4 -4
  4. package/grammar/CNext.g4 +12 -0
  5. package/package.json +4 -2
  6. package/src/transpiler/Transpiler.ts +376 -48
  7. package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
  8. package/src/transpiler/__tests__/compileCommandsDiscovery.integration.test.ts +94 -0
  9. package/src/transpiler/__tests__/externalSymbolRecovery.integration.test.ts +215 -0
  10. package/src/transpiler/logic/__tests__/detectAssemblySyntax.test.ts +116 -0
  11. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +65 -10
  12. package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +186 -14
  13. package/src/transpiler/logic/analysis/MixedTypeCategoryAnalyzer.ts +408 -0
  14. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +16 -97
  15. package/src/transpiler/logic/analysis/ReturnPathAnalyzer.ts +171 -0
  16. package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +124 -12
  17. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +200 -0
  18. package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +386 -1
  19. package/src/transpiler/logic/analysis/__tests__/MixedTypeCategoryAnalyzer.test.ts +346 -0
  20. package/src/transpiler/logic/analysis/__tests__/ReturnPathAnalyzer.test.ts +232 -0
  21. package/src/transpiler/logic/analysis/__tests__/SignedShiftAnalyzer.test.ts +211 -0
  22. package/src/transpiler/logic/analysis/runAnalyzers.ts +23 -2
  23. package/src/transpiler/logic/analysis/types/IMixedTypeCategoryError.ts +17 -0
  24. package/src/transpiler/logic/analysis/types/IReturnPathError.ts +12 -0
  25. package/src/transpiler/logic/detectAssemblySyntax.ts +80 -0
  26. package/src/transpiler/logic/parser/grammar/CNext.interp +4 -1
  27. package/src/transpiler/logic/parser/grammar/CNext.tokens +169 -167
  28. package/src/transpiler/logic/parser/grammar/CNextLexer.interp +4 -1
  29. package/src/transpiler/logic/parser/grammar/CNextLexer.tokens +169 -167
  30. package/src/transpiler/logic/parser/grammar/CNextLexer.ts +545 -541
  31. package/src/transpiler/logic/parser/grammar/CNextListener.ts +11 -0
  32. package/src/transpiler/logic/parser/grammar/CNextParser.ts +1318 -1178
  33. package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +7 -0
  34. package/src/transpiler/logic/preprocessor/CompileCommandsReader.ts +332 -0
  35. package/src/transpiler/logic/preprocessor/ExternalDeclarationOracle.ts +202 -0
  36. package/src/transpiler/logic/preprocessor/Preprocessor.ts +24 -6
  37. package/src/transpiler/logic/preprocessor/ToolchainDetector.ts +42 -1
  38. package/src/transpiler/logic/preprocessor/__tests__/CompileCommandsReader.test.ts +216 -0
  39. package/src/transpiler/logic/preprocessor/__tests__/ExternalDeclarationOracle.test.ts +153 -0
  40. package/src/transpiler/logic/preprocessor/__tests__/Preprocessor.test.ts +43 -18
  41. package/src/transpiler/logic/preprocessor/__tests__/ToolchainDetector.crossCompiler.test.ts +75 -0
  42. package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/dependent.h +7 -0
  43. package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/predecessor.h +5 -0
  44. package/src/transpiler/logic/preprocessor/types/ICompileCommandsResult.ts +14 -0
  45. package/src/transpiler/logic/preprocessor/types/IPreprocessOptions.ts +17 -0
  46. package/src/transpiler/logic/symbols/SymbolTable.ts +62 -2
  47. package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +55 -4
  48. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +15 -2
  49. package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +64 -50
  50. package/src/transpiler/output/MisraSuppressionUtils.ts +52 -0
  51. package/src/transpiler/output/__tests__/MisraSuppressionUtils.test.ts +67 -0
  52. package/src/transpiler/output/codegen/CodeGenerator.ts +196 -98
  53. package/src/transpiler/output/codegen/TypeResolver.ts +148 -0
  54. package/src/transpiler/output/codegen/TypeValidator.ts +179 -81
  55. package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +165 -17
  56. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +163 -35
  57. package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +2 -2
  58. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +93 -0
  59. package/src/transpiler/output/codegen/__tests__/TypeValidator.alwaysTrueLoop.test.ts +91 -0
  60. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +97 -14
  61. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +13 -0
  62. package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +1 -1
  63. package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +20 -12
  64. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +424 -22
  65. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +31 -18
  66. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +7 -8
  67. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +6 -8
  68. package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +12 -10
  69. package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +3 -7
  70. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +7 -9
  71. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +12 -10
  72. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +479 -11
  73. package/src/transpiler/output/codegen/generators/IOrchestrator.ts +3 -0
  74. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +26 -7
  75. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +86 -0
  76. package/src/transpiler/output/codegen/generators/expressions/BinaryExprGenerator.ts +43 -24
  77. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +76 -58
  78. package/src/transpiler/output/codegen/generators/expressions/ExpressionGenerator.ts +9 -2
  79. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +26 -13
  80. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +44 -0
  81. package/src/transpiler/output/codegen/generators/expressions/__tests__/ExpressionGenerator.test.ts +82 -1
  82. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +129 -1
  83. package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +64 -8
  84. package/src/transpiler/output/codegen/generators/statements/__tests__/ControlFlowGenerator.test.ts +8 -5
  85. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +30 -2
  86. package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +17 -3
  87. package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +17 -4
  88. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +240 -42
  89. package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +0 -21
  90. package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +60 -39
  91. package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +170 -36
  92. package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +37 -39
  93. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +19 -0
  94. package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +117 -0
  95. package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +94 -2
  96. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +322 -9
  97. package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +0 -64
  98. package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +101 -0
  99. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +29 -5
  100. package/src/transpiler/output/codegen/subscript/SubscriptClassifier.ts +30 -11
  101. package/src/transpiler/output/codegen/subscript/TSubscriptKind.ts +1 -1
  102. package/src/transpiler/output/codegen/subscript/__tests__/SubscriptClassifier.test.ts +38 -6
  103. package/src/transpiler/output/codegen/types/ICallbackTypeInfo.ts +2 -1
  104. package/src/transpiler/output/codegen/types/IParameterInput.ts +7 -0
  105. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +8 -0
  106. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +140 -24
  107. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +280 -0
  108. package/src/transpiler/output/headers/generators/IHeaderTypeInput.ts +13 -0
  109. package/src/transpiler/output/headers/generators/generateStructHeader.ts +48 -28
  110. package/src/transpiler/state/CodeGenState.ts +91 -22
  111. package/src/transpiler/state/__tests__/CodeGenState.test.ts +253 -11
  112. package/src/transpiler/types/ICachedFileEntry.ts +7 -0
  113. package/src/utils/LiteralUtils.ts +23 -0
  114. package/src/utils/__tests__/LiteralUtils.test.ts +101 -0
  115. package/src/utils/cache/CacheManager.ts +13 -2
  116. package/src/utils/cache/__tests__/CacheManager.test.ts +18 -1
  117. package/src/utils/constants/TypeConstants.ts +13 -0
  118. package/src/utils/types/IParameterSymbol.ts +1 -0
@@ -306,6 +306,107 @@ describe("LiteralUtils", () => {
306
306
  });
307
307
  });
308
308
 
309
+ // ========================================================================
310
+ // isZero: Float Literals (Issue #1010)
311
+ // ========================================================================
312
+
313
+ describe("isZero - float literals (Issue #1010)", () => {
314
+ it("should return true for float zero (0.0)", () => {
315
+ const literal = extractFloatLiteral("0.0");
316
+ expect(literal).not.toBeNull();
317
+ expect(LiteralUtils.isZero(literal!)).toBe(true);
318
+ });
319
+
320
+ it("should return true for float zero with suffix (0.0f)", () => {
321
+ const literal = extractFloatLiteral("0.0f");
322
+ expect(literal).not.toBeNull();
323
+ expect(LiteralUtils.isZero(literal!)).toBe(true);
324
+ });
325
+
326
+ it("should return true for float zero with uppercase suffix (0.0F)", () => {
327
+ const literal = extractFloatLiteral("0.0F");
328
+ expect(literal).not.toBeNull();
329
+ expect(LiteralUtils.isZero(literal!)).toBe(true);
330
+ });
331
+
332
+ it("should return true for leading-dot zero (.0)", () => {
333
+ const literal = extractFloatLiteral(".0");
334
+ expect(literal).not.toBeNull();
335
+ expect(LiteralUtils.isZero(literal!)).toBe(true);
336
+ });
337
+
338
+ it("should return false for non-zero float (1.0)", () => {
339
+ const literal = extractFloatLiteral("1.0");
340
+ expect(literal).not.toBeNull();
341
+ expect(LiteralUtils.isZero(literal!)).toBe(false);
342
+ });
343
+
344
+ it("should return false for small non-zero float (0.001)", () => {
345
+ const literal = extractFloatLiteral("0.001");
346
+ expect(literal).not.toBeNull();
347
+ expect(LiteralUtils.isZero(literal!)).toBe(false);
348
+ });
349
+
350
+ it("should return false for negative float (-0.5)", () => {
351
+ const literal = extractFloatLiteral("-0.5");
352
+ // Note: -0.5 may not parse as a single literal due to negation
353
+ // This is expected - the unary minus is a separate operator
354
+ if (literal) {
355
+ expect(LiteralUtils.isZero(literal!)).toBe(false);
356
+ }
357
+ });
358
+ });
359
+
360
+ // ========================================================================
361
+ // isFloatZero (Issue #1010)
362
+ // ========================================================================
363
+
364
+ describe("isFloatZero - static method (Issue #1010)", () => {
365
+ it("should return true for 0.0", () => {
366
+ expect(LiteralUtils.isFloatZero("0.0")).toBe(true);
367
+ });
368
+
369
+ it("should return true for .0", () => {
370
+ expect(LiteralUtils.isFloatZero(".0")).toBe(true);
371
+ });
372
+
373
+ it("should return true for 0.", () => {
374
+ expect(LiteralUtils.isFloatZero("0.")).toBe(true);
375
+ });
376
+
377
+ it("should return true for 0.0f", () => {
378
+ expect(LiteralUtils.isFloatZero("0.0f")).toBe(true);
379
+ });
380
+
381
+ it("should return true for 0.0F", () => {
382
+ expect(LiteralUtils.isFloatZero("0.0F")).toBe(true);
383
+ });
384
+
385
+ it("should return true for scientific notation zero (0.0e0)", () => {
386
+ expect(LiteralUtils.isFloatZero("0.0e0")).toBe(true);
387
+ });
388
+
389
+ it("should return true for scientific notation zero (0e0)", () => {
390
+ expect(LiteralUtils.isFloatZero("0e0")).toBe(true);
391
+ });
392
+
393
+ it("should return false for 1.0", () => {
394
+ expect(LiteralUtils.isFloatZero("1.0")).toBe(false);
395
+ });
396
+
397
+ it("should return false for 0.5", () => {
398
+ expect(LiteralUtils.isFloatZero("0.5")).toBe(false);
399
+ });
400
+
401
+ it("should return false for 3.14", () => {
402
+ expect(LiteralUtils.isFloatZero("3.14")).toBe(false);
403
+ });
404
+
405
+ it("should return false for scientific notation non-zero (1e-10)", () => {
406
+ expect(LiteralUtils.isFloatZero("1e-10")).toBe(false);
407
+ });
408
+ });
409
+
309
410
  // ========================================================================
310
411
  // isFloat
311
412
  // ========================================================================
@@ -32,7 +32,7 @@ import ESourceLanguage from "../types/ESourceLanguage";
32
32
  const defaultFs = NodeFileSystem.instance;
33
33
 
34
34
  /** Current cache format version - increment when serialization format changes */
35
- const CACHE_VERSION = 7; // Issue #958: Add structTagAliases, structTagsWithBodies to cache
35
+ const CACHE_VERSION = 8; // Issue #985: Add preprocessFailed marker to cache
36
36
 
37
37
  const TRANSPILER_VERSION = packageJson.version;
38
38
 
@@ -138,6 +138,7 @@ class CacheManager {
138
138
  typedefStructTypes: Array<[string, string]>;
139
139
  structTagAliases: Array<[string, string]>;
140
140
  structTagsWithBodies: string[];
141
+ preprocessFailed: boolean;
141
142
  } | null {
142
143
  if (!this.cache) return null;
143
144
 
@@ -181,6 +182,7 @@ class CacheManager {
181
182
  typedefStructTypes: cachedEntry.typedefStructTypes ?? [],
182
183
  structTagAliases: cachedEntry.structTagAliases ?? [],
183
184
  structTagsWithBodies: cachedEntry.structTagsWithBodies ?? [],
185
+ preprocessFailed: cachedEntry.preprocessFailed ?? false,
184
186
  };
185
187
  }
186
188
 
@@ -199,6 +201,7 @@ class CacheManager {
199
201
  typedefStructTypes?: Array<[string, string]>;
200
202
  structTagAliases?: Array<[string, string]>;
201
203
  structTagsWithBodies?: string[];
204
+ preprocessFailed?: boolean;
202
205
  },
203
206
  ): void {
204
207
  if (!this.cache) return;
@@ -247,6 +250,7 @@ class CacheManager {
247
250
  typedefStructTypes: options?.typedefStructTypes,
248
251
  structTagAliases: options?.structTagAliases,
249
252
  structTagsWithBodies: options?.structTagsWithBodies,
253
+ preprocessFailed: options?.preprocessFailed,
250
254
  };
251
255
 
252
256
  this.cache.setKey(filePath, entry);
@@ -263,8 +267,14 @@ class CacheManager {
263
267
  *
264
268
  * @param filePath - Path to the file being cached
265
269
  * @param symbolTable - SymbolTable containing all parsed symbols
270
+ * @param preprocessFailed - Issue #985: header fell back to raw content, so its
271
+ * symbols are degraded and a warm-cache build must re-run recovery
266
272
  */
267
- setSymbolsFromTable(filePath: string, symbolTable: SymbolTable): void {
273
+ setSymbolsFromTable(
274
+ filePath: string,
275
+ symbolTable: SymbolTable,
276
+ preprocessFailed = false,
277
+ ): void {
268
278
  // ADR-055 Phase 7: Serialize TAnySymbol directly to ISerializedSymbol
269
279
  const typedSymbols = symbolTable.getSymbolsByFile(filePath);
270
280
  const symbols = typedSymbols.map((s) => this.serializeTypedSymbol(s));
@@ -302,6 +312,7 @@ class CacheManager {
302
312
  typedefStructTypes,
303
313
  structTagAliases,
304
314
  structTagsWithBodies,
315
+ preprocessFailed,
305
316
  });
306
317
  }
307
318
 
@@ -200,6 +200,23 @@ describe("CacheManager", () => {
200
200
  });
201
201
  });
202
202
 
203
+ it("defaults preprocessFailed to false and round-trips it when set", async () => {
204
+ const cleanFile = join(testDir, "clean.h");
205
+ const failedFile = join(testDir, "failed.h");
206
+ writeFileSync(cleanFile, "// test");
207
+ writeFileSync(failedFile, "// test");
208
+
209
+ // Issue #985: a header that fell back to raw content records that fact so
210
+ // a warm-cache build re-runs external-declaration recovery.
211
+ cacheManager.setSymbols(cleanFile, [], new Map());
212
+ cacheManager.setSymbols(failedFile, [], new Map(), {
213
+ preprocessFailed: true,
214
+ });
215
+
216
+ expect(cacheManager.getSymbols(cleanFile)!.preprocessFailed).toBe(false);
217
+ expect(cacheManager.getSymbols(failedFile)!.preprocessFailed).toBe(true);
218
+ });
219
+
203
220
  it("should preserve optional symbol fields", async () => {
204
221
  const testFile = join(testDir, "test.h");
205
222
  writeFileSync(testFile, "// test");
@@ -1494,7 +1511,7 @@ describe("CacheManager", () => {
1494
1511
  const content = mockFs.getWrittenContent("/project/.cnx/config.json");
1495
1512
  expect(content).toBeDefined();
1496
1513
  const newConfig = JSON.parse(content!);
1497
- expect(newConfig.version).toBe(7); // Current CACHE_VERSION (Issue #958 structTagAliases, structTagsWithBodies)
1514
+ expect(newConfig.version).toBe(8); // Current CACHE_VERSION (Issue #985 preprocessFailed marker)
1498
1515
  });
1499
1516
 
1500
1517
  it("should not cache files that do not exist in IFileSystem", async () => {
@@ -42,6 +42,19 @@ class TypeConstants {
42
42
  * - ArrayIndexTypeAnalyzer: detecting signed integer subscript indexes
43
43
  */
44
44
  static readonly SIGNED_TYPES: readonly string[] = ["i8", "i16", "i32", "i64"];
45
+
46
+ /**
47
+ * Unsigned integer types (excludes `bool`, unlike `UNSIGNED_INDEX_TYPES`).
48
+ *
49
+ * Used by:
50
+ * - MixedTypeCategoryAnalyzer: classifying an operand's essential type category
51
+ */
52
+ static readonly UNSIGNED_INT_TYPES: readonly string[] = [
53
+ "u8",
54
+ "u16",
55
+ "u32",
56
+ "u64",
57
+ ];
45
58
  }
46
59
 
47
60
  export default TypeConstants;
@@ -10,6 +10,7 @@ interface IParameterSymbol {
10
10
  isAutoConst?: boolean; // Issue #268: true if parameter should get auto-const (unmodified pointer)
11
11
  isCallbackPointer?: boolean; // Issue #914: typedef says this param must be a pointer
12
12
  isCallbackConst?: boolean; // Issue #914: typedef says this param must be const
13
+ isOpaqueHandle?: boolean; // Issue #995: type is opaque (incomplete struct), needs pointer not reference
13
14
  }
14
15
 
15
16
  export default IParameterSymbol;