c-next 0.2.17 → 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 (81) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +7645 -5941
  3. package/dist/index.js.map +4 -4
  4. package/grammar/CNext.g4 +8 -0
  5. package/package.json +1 -3
  6. package/src/transpiler/Transpiler.ts +286 -26
  7. package/src/transpiler/__tests__/compileCommandsDiscovery.integration.test.ts +94 -0
  8. package/src/transpiler/__tests__/externalSymbolRecovery.integration.test.ts +215 -0
  9. package/src/transpiler/logic/__tests__/detectAssemblySyntax.test.ts +116 -0
  10. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +8 -0
  11. package/src/transpiler/logic/analysis/MixedTypeCategoryAnalyzer.ts +408 -0
  12. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +16 -97
  13. package/src/transpiler/logic/analysis/ReturnPathAnalyzer.ts +171 -0
  14. package/src/transpiler/logic/analysis/__tests__/MixedTypeCategoryAnalyzer.test.ts +346 -0
  15. package/src/transpiler/logic/analysis/__tests__/ReturnPathAnalyzer.test.ts +232 -0
  16. package/src/transpiler/logic/analysis/runAnalyzers.ts +23 -2
  17. package/src/transpiler/logic/analysis/types/IMixedTypeCategoryError.ts +17 -0
  18. package/src/transpiler/logic/analysis/types/IReturnPathError.ts +12 -0
  19. package/src/transpiler/logic/detectAssemblySyntax.ts +80 -0
  20. package/src/transpiler/logic/parser/grammar/CNext.interp +4 -1
  21. package/src/transpiler/logic/parser/grammar/CNext.tokens +169 -167
  22. package/src/transpiler/logic/parser/grammar/CNextLexer.interp +4 -1
  23. package/src/transpiler/logic/parser/grammar/CNextLexer.tokens +169 -167
  24. package/src/transpiler/logic/parser/grammar/CNextLexer.ts +545 -541
  25. package/src/transpiler/logic/parser/grammar/CNextListener.ts +11 -0
  26. package/src/transpiler/logic/parser/grammar/CNextParser.ts +1257 -1185
  27. package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +7 -0
  28. package/src/transpiler/logic/preprocessor/CompileCommandsReader.ts +332 -0
  29. package/src/transpiler/logic/preprocessor/ExternalDeclarationOracle.ts +202 -0
  30. package/src/transpiler/logic/preprocessor/Preprocessor.ts +24 -6
  31. package/src/transpiler/logic/preprocessor/ToolchainDetector.ts +42 -1
  32. package/src/transpiler/logic/preprocessor/__tests__/CompileCommandsReader.test.ts +216 -0
  33. package/src/transpiler/logic/preprocessor/__tests__/ExternalDeclarationOracle.test.ts +153 -0
  34. package/src/transpiler/logic/preprocessor/__tests__/Preprocessor.test.ts +43 -18
  35. package/src/transpiler/logic/preprocessor/__tests__/ToolchainDetector.crossCompiler.test.ts +75 -0
  36. package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/dependent.h +7 -0
  37. package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/predecessor.h +5 -0
  38. package/src/transpiler/logic/preprocessor/types/ICompileCommandsResult.ts +14 -0
  39. package/src/transpiler/logic/preprocessor/types/IPreprocessOptions.ts +17 -0
  40. package/src/transpiler/logic/symbols/SymbolTable.ts +45 -0
  41. package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +49 -0
  42. package/src/transpiler/output/MisraSuppressionUtils.ts +52 -0
  43. package/src/transpiler/output/__tests__/MisraSuppressionUtils.test.ts +67 -0
  44. package/src/transpiler/output/codegen/CodeGenerator.ts +45 -4
  45. package/src/transpiler/output/codegen/TypeResolver.ts +148 -0
  46. package/src/transpiler/output/codegen/TypeValidator.ts +179 -81
  47. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +13 -1
  48. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +93 -0
  49. package/src/transpiler/output/codegen/__tests__/TypeValidator.alwaysTrueLoop.test.ts +91 -0
  50. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +86 -14
  51. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +13 -0
  52. package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +1 -1
  53. package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +20 -12
  54. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +424 -22
  55. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +31 -18
  56. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +7 -8
  57. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +6 -8
  58. package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +12 -10
  59. package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +3 -7
  60. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +7 -9
  61. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +12 -10
  62. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +479 -11
  63. package/src/transpiler/output/codegen/generators/IOrchestrator.ts +3 -0
  64. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +28 -15
  65. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +26 -13
  66. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +129 -1
  67. package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +64 -8
  68. package/src/transpiler/output/codegen/generators/statements/__tests__/ControlFlowGenerator.test.ts +8 -5
  69. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +30 -2
  70. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +16 -13
  71. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +19 -0
  72. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +57 -11
  73. package/src/transpiler/output/codegen/subscript/SubscriptClassifier.ts +30 -11
  74. package/src/transpiler/output/codegen/subscript/TSubscriptKind.ts +1 -1
  75. package/src/transpiler/output/codegen/subscript/__tests__/SubscriptClassifier.test.ts +38 -6
  76. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +65 -24
  77. package/src/transpiler/state/CodeGenState.ts +20 -16
  78. package/src/transpiler/types/ICachedFileEntry.ts +7 -0
  79. package/src/utils/cache/CacheManager.ts +13 -2
  80. package/src/utils/cache/__tests__/CacheManager.test.ts +18 -1
  81. package/src/utils/constants/TypeConstants.ts +13 -0
@@ -1740,15 +1740,37 @@ describe("TypeValidator", () => {
1740
1740
  // ========================================================================
1741
1741
 
1742
1742
  describe("validateTernaryCondition", () => {
1743
- it("allows conditions with || operator", () => {
1743
+ it("throws for || of bare value operands (each operand must be a comparison)", () => {
1744
1744
  setupState();
1745
1745
  const ctx = createMockOrExpression("a || b", { hasOr: true });
1746
+ expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1747
+ "E0701",
1748
+ );
1749
+ });
1750
+
1751
+ it("allows || of comparison operands", () => {
1752
+ setupState();
1753
+ const ctx = createMockOrExpression("a = 1 || b = 2", {
1754
+ hasOr: true,
1755
+ hasEquality: true,
1756
+ });
1746
1757
  expect(() => TypeValidator.validateTernaryCondition(ctx)).not.toThrow();
1747
1758
  });
1748
1759
 
1749
- it("allows conditions with && operator", () => {
1760
+ it("throws for && of bare value operands (each operand must be a comparison)", () => {
1750
1761
  setupState();
1751
1762
  const ctx = createMockOrExpression("a && b", { hasAnd: true });
1763
+ expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1764
+ "E0701",
1765
+ );
1766
+ });
1767
+
1768
+ it("allows && of comparison operands", () => {
1769
+ setupState();
1770
+ const ctx = createMockOrExpression("a = 1 && b = 2", {
1771
+ hasAnd: true,
1772
+ hasEquality: true,
1773
+ });
1752
1774
  expect(() => TypeValidator.validateTernaryCondition(ctx)).not.toThrow();
1753
1775
  });
1754
1776
 
@@ -1768,7 +1790,7 @@ describe("TypeValidator", () => {
1768
1790
  setupState();
1769
1791
  const ctx = createMockOrExpression("flag");
1770
1792
  expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1771
- "Ternary condition must be a boolean expression",
1793
+ "E0701",
1772
1794
  );
1773
1795
  });
1774
1796
 
@@ -1779,7 +1801,7 @@ describe("TypeValidator", () => {
1779
1801
  andExpression: antlrArray([]),
1780
1802
  } as unknown as Parser.OrExpressionContext;
1781
1803
  expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1782
- "Ternary condition must be a boolean expression",
1804
+ "E0701",
1783
1805
  );
1784
1806
  });
1785
1807
 
@@ -1791,7 +1813,7 @@ describe("TypeValidator", () => {
1791
1813
  andExpression: antlrArray([andExpr]),
1792
1814
  } as unknown as Parser.OrExpressionContext;
1793
1815
  expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1794
- "Ternary condition must be a boolean expression",
1816
+ "E0701",
1795
1817
  );
1796
1818
  });
1797
1819
 
@@ -1804,7 +1826,7 @@ describe("TypeValidator", () => {
1804
1826
  andExpression: antlrArray([andExpr]),
1805
1827
  } as unknown as Parser.OrExpressionContext;
1806
1828
  expect(() => TypeValidator.validateTernaryCondition(ctx)).toThrow(
1807
- "Ternary condition must be a boolean expression",
1829
+ "E0701",
1808
1830
  );
1809
1831
  });
1810
1832
  });
@@ -1898,17 +1920,39 @@ describe("TypeValidator", () => {
1898
1920
  ).not.toThrow();
1899
1921
  });
1900
1922
 
1901
- it("allows conditions with && operator", () => {
1923
+ it("throws for && of bare value operands (each operand must be a comparison)", () => {
1902
1924
  setupState();
1903
1925
  const ctx = createFullDoWhileExpression("a && b", { hasAnd: true });
1926
+ expect(() =>
1927
+ TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
1928
+ ).toThrow("E0701");
1929
+ });
1930
+
1931
+ it("allows && of comparison operands", () => {
1932
+ setupState();
1933
+ const ctx = createFullDoWhileExpression("a = 1 && b = 2", {
1934
+ hasAnd: true,
1935
+ hasEquality: true,
1936
+ });
1904
1937
  expect(() =>
1905
1938
  TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
1906
1939
  ).not.toThrow();
1907
1940
  });
1908
1941
 
1909
- it("allows conditions with || operator", () => {
1942
+ it("throws for || of bare value operands (each operand must be a comparison)", () => {
1910
1943
  setupState();
1911
1944
  const ctx = createFullDoWhileExpression("a || b", { hasOr: true });
1945
+ expect(() =>
1946
+ TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
1947
+ ).toThrow("E0701");
1948
+ });
1949
+
1950
+ it("allows || of comparison operands", () => {
1951
+ setupState();
1952
+ const ctx = createFullDoWhileExpression("a = 1 || b = 2", {
1953
+ hasOr: true,
1954
+ hasEquality: true,
1955
+ });
1912
1956
  expect(() =>
1913
1957
  TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
1914
1958
  ).not.toThrow();
@@ -1938,7 +1982,7 @@ describe("TypeValidator", () => {
1938
1982
  ).toThrow("E0701");
1939
1983
  });
1940
1984
 
1941
- it("allows boolean literals", () => {
1985
+ it("throws for boolean literal condition (Issue #1042)", () => {
1942
1986
  setupState();
1943
1987
  // Create full mock expression tree where getText returns "true"
1944
1988
  const bitwiseOrExpr = {
@@ -1969,10 +2013,10 @@ describe("TypeValidator", () => {
1969
2013
  } as unknown as Parser.ExpressionContext;
1970
2014
  expect(() =>
1971
2015
  TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
1972
- ).not.toThrow();
2016
+ ).toThrow("E0701");
1973
2017
  });
1974
2018
 
1975
- it("allows negation expressions", () => {
2019
+ it("throws for negation expression (Issue #1042)", () => {
1976
2020
  setupState();
1977
2021
  const bitwiseOrExpr = {
1978
2022
  bitwiseXorExpression: antlrArray([]),
@@ -2002,10 +2046,10 @@ describe("TypeValidator", () => {
2002
2046
  } as unknown as Parser.ExpressionContext;
2003
2047
  expect(() =>
2004
2048
  TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
2005
- ).not.toThrow();
2049
+ ).toThrow("E0701");
2006
2050
  });
2007
2051
 
2008
- it("allows bool type variables", () => {
2052
+ it("throws for bare bool type variable (Issue #1042)", () => {
2009
2053
  const typeRegistry = new Map<string, TTypeInfo>([
2010
2054
  [
2011
2055
  "isReady",
@@ -2041,7 +2085,7 @@ describe("TypeValidator", () => {
2041
2085
  } as unknown as Parser.ExpressionContext;
2042
2086
  expect(() =>
2043
2087
  TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
2044
- ).not.toThrow();
2088
+ ).toThrow("E0701");
2045
2089
  });
2046
2090
 
2047
2091
  it("shows help message in error", () => {
@@ -2052,6 +2096,34 @@ describe("TypeValidator", () => {
2052
2096
  ).toThrow("help: use explicit comparison: count > 0 or count != 0");
2053
2097
  });
2054
2098
 
2099
+ it("suggests `= true` for a bare bool operand (Issue #1042)", () => {
2100
+ const typeRegistry = new Map<string, TTypeInfo>([
2101
+ [
2102
+ "ready",
2103
+ { baseType: "bool", bitWidth: 8, isArray: false, isConst: false },
2104
+ ],
2105
+ ]);
2106
+ setupState({ typeRegistry });
2107
+ const ctx = createFullDoWhileExpression("ready");
2108
+ expect(() =>
2109
+ TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
2110
+ ).toThrow("help: use explicit comparison: ready = true");
2111
+ });
2112
+
2113
+ it("suggests `= false` for a negated bool operand (Issue #1042)", () => {
2114
+ const typeRegistry = new Map<string, TTypeInfo>([
2115
+ [
2116
+ "ready",
2117
+ { baseType: "bool", bitWidth: 8, isArray: false, isConst: false },
2118
+ ],
2119
+ ]);
2120
+ setupState({ typeRegistry });
2121
+ const ctx = createFullDoWhileExpression("!ready");
2122
+ expect(() =>
2123
+ TypeValidator.validateConditionIsBoolean(ctx, "do-while"),
2124
+ ).toThrow("help: use explicit comparison: ready = false");
2125
+ });
2126
+
2055
2127
  it("throws when no andExpression", () => {
2056
2128
  setupState();
2057
2129
  const orExpr = {
@@ -415,9 +415,22 @@ class AssignmentClassifier {
415
415
  const firstId = ctx.identifiers[0];
416
416
 
417
417
  if (ctx.hasArrayAccess) {
418
+ // Direct register: global.REG.MEMBER[bit]
418
419
  if (CodeGenState.symbols!.knownRegisters.has(firstId)) {
419
420
  return AssignmentKind.GLOBAL_REGISTER_BIT;
420
421
  }
422
+ // Scoped register: global.Scope.REG.MEMBER[bit] — mirror
423
+ // classifyRegisterBitAccess so the bit-range mask/shift is expanded
424
+ // rather than emitting a literal subscript (Issue #1052).
425
+ if (
426
+ CodeGenState.isKnownScope(firstId) &&
427
+ ctx.identifiers.length >= 3 &&
428
+ CodeGenState.symbols!.knownRegisters.has(
429
+ `${firstId}_${ctx.identifiers[1]}`,
430
+ )
431
+ ) {
432
+ return AssignmentKind.GLOBAL_REGISTER_BIT;
433
+ }
421
434
  return AssignmentKind.GLOBAL_ARRAY;
422
435
  }
423
436
 
@@ -85,7 +85,7 @@ enum AssignmentKind {
85
85
  /** matrix[i][j] <- value (multi-dimensional array element) */
86
86
  MULTI_DIM_ARRAY_ELEMENT,
87
87
 
88
- /** buffer[0, 10] <- source (slice assignment with memcpy) */
88
+ /** buffer[0, 10] <- source (slice assignment: per-element little-endian writes, ADR-007/#1081) */
89
89
  ARRAY_SLICE,
90
90
 
91
91
  // === Special operations ===
@@ -15,12 +15,6 @@ import BitUtils from "../../../../../utils/BitUtils";
15
15
  import TAssignmentHandler from "./TAssignmentHandler";
16
16
  import RegisterUtils from "./RegisterUtils";
17
17
  import CodeGenState from "../../../../state/CodeGenState";
18
- import type ICodeGenApi from "../../types/ICodeGenApi";
19
-
20
- /** Get typed generator reference */
21
- function gen(): ICodeGenApi {
22
- return CodeGenState.generator as ICodeGenApi;
23
- }
24
18
 
25
19
  /**
26
20
  * Common handler for global access patterns (GLOBAL_MEMBER and GLOBAL_ARRAY).
@@ -32,10 +26,15 @@ function handleGlobalAccess(ctx: IAssignmentContext): string {
32
26
 
33
27
  // Validate cross-scope visibility if first id is a scope
34
28
  if (CodeGenState.isKnownScope(firstId) && ctx.identifiers.length >= 2) {
35
- gen().validateCrossScopeVisibility(firstId, ctx.identifiers[1]);
29
+ CodeGenState.requireGenerator().validateCrossScopeVisibility(
30
+ firstId,
31
+ ctx.identifiers[1],
32
+ );
36
33
  }
37
34
 
38
- const target = gen().generateAssignmentTarget(ctx.targetCtx);
35
+ const target = CodeGenState.requireGenerator().generateAssignmentTarget(
36
+ ctx.targetCtx,
37
+ );
39
38
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
40
39
  }
41
40
 
@@ -49,7 +48,9 @@ function handleThisAccess(ctx: IAssignmentContext): string {
49
48
  throw new Error("Error: 'this' can only be used inside a scope");
50
49
  }
51
50
 
52
- const target = gen().generateAssignmentTarget(ctx.targetCtx);
51
+ const target = CodeGenState.requireGenerator().generateAssignmentTarget(
52
+ ctx.targetCtx,
53
+ );
53
54
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
54
55
  }
55
56
 
@@ -100,7 +101,9 @@ function handleGlobalRegisterBit(ctx: IAssignmentContext): string {
100
101
  }
101
102
 
102
103
  // Single bit
103
- const bitIndex = gen().generateExpression(ctx.subscripts[0]);
104
+ const bitIndex = CodeGenState.requireGenerator().generateExpression(
105
+ ctx.subscripts[0],
106
+ );
104
107
 
105
108
  if (isWriteOnly) {
106
109
  if (ctx.generatedValue === "false" || ctx.generatedValue === "0") {
@@ -126,7 +129,10 @@ function handleGlobalRegisterBit(ctx: IAssignmentContext): string {
126
129
  */
127
130
  function handleMemberChain(ctx: IAssignmentContext): string {
128
131
  // Check if this is bit access on a struct member
129
- const bitAnalysis = gen().analyzeMemberChainForBitAccess(ctx.targetCtx);
132
+ const bitAnalysis =
133
+ CodeGenState.requireGenerator().analyzeMemberChainForBitAccess(
134
+ ctx.targetCtx,
135
+ );
130
136
 
131
137
  if (bitAnalysis.isBitAccess) {
132
138
  // Validate compound operators not supported for bit access
@@ -144,7 +150,9 @@ function handleMemberChain(ctx: IAssignmentContext): string {
144
150
  }
145
151
 
146
152
  // Normal member chain assignment
147
- const target = gen().generateAssignmentTarget(ctx.targetCtx);
153
+ const target = CodeGenState.requireGenerator().generateAssignmentTarget(
154
+ ctx.targetCtx,
155
+ );
148
156
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
149
157
  }
150
158