c-next 0.1.65 → 0.1.67
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 +5 -1
- package/src/transpiler/Transpiler.ts +49 -42
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +129 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +27 -3
- package/src/transpiler/output/codegen/CodeGenerator.ts +131 -186
- package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/TypeValidator.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1087 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +665 -1315
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +1 -1
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +1 -1
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +1 -1
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +1 -1
- package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +24 -27
- package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +25 -18
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +27 -33
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +39 -42
- package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +39 -97
- package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +75 -0
- package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +9 -6
- package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +30 -22
- package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +42 -50
- package/src/transpiler/output/codegen/assignment/handlers/TAssignmentHandler.ts +6 -5
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +81 -134
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +85 -124
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +82 -124
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +135 -297
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +105 -227
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterUtils.test.ts +214 -1
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +66 -127
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/StringHandlers.test.ts +37 -83
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +162 -0
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +618 -12
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +1 -1
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/types/ICodeGenApi.ts +57 -0
- package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
- package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
- package/src/transpiler/{output/codegen → state}/CodeGenState.ts +46 -26
- package/src/transpiler/{output/codegen → state}/__tests__/CodeGenState.test.ts +12 -2
- package/src/transpiler/output/codegen/assignment/handlers/IHandlerDeps.ts +0 -161
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { CommonTokenStream, ParserRuleContext } from "antlr4ng";
|
|
7
7
|
import * as Parser from "../../logic/parser/grammar/CNextParser";
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import ESymbolKind from "../../../utils/types/ESymbolKind";
|
|
10
10
|
import CommentExtractor from "../../logic/analysis/CommentExtractor";
|
|
11
11
|
import CommentFormatter from "./CommentFormatter";
|
|
@@ -67,7 +67,7 @@ import memberAccessChain from "./memberAccessChain";
|
|
|
67
67
|
import AssignmentHandlerRegistry from "./assignment/index";
|
|
68
68
|
import AssignmentClassifier from "./assignment/AssignmentClassifier";
|
|
69
69
|
import buildAssignmentContext from "./assignment/AssignmentContextBuilder";
|
|
70
|
-
|
|
70
|
+
// IHandlerDeps removed - handlers now use CodeGenState.generator directly
|
|
71
71
|
// Issue #461: LiteralUtils for parsing const values from symbol table
|
|
72
72
|
import LiteralUtils from "../../../utils/LiteralUtils";
|
|
73
73
|
// Issue #644: Extracted string length counter for strlen caching optimization
|
|
@@ -133,7 +133,10 @@ import TypeGenerationHelper from "./helpers/TypeGenerationHelper";
|
|
|
133
133
|
// Phase 5: Cast validation helper for improved testability
|
|
134
134
|
import CastValidator from "./helpers/CastValidator";
|
|
135
135
|
// Global state for code generation (simplifies debugging, eliminates DI complexity)
|
|
136
|
-
import CodeGenState from "
|
|
136
|
+
import CodeGenState from "../../state/CodeGenState";
|
|
137
|
+
// Unified parameter generation (Phase 1)
|
|
138
|
+
import ParameterInputAdapter from "./helpers/ParameterInputAdapter";
|
|
139
|
+
import ParameterSignatureBuilder from "./helpers/ParameterSignatureBuilder";
|
|
137
140
|
// Extracted resolvers that use CodeGenState
|
|
138
141
|
import SizeofResolver from "./resolution/SizeofResolver";
|
|
139
142
|
import EnumTypeResolver from "./resolution/EnumTypeResolver";
|
|
@@ -676,7 +679,7 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
676
679
|
currentScope: CodeGenState.currentScope,
|
|
677
680
|
isCppScopeSymbol: (name) => this.isCppScopeSymbol(name),
|
|
678
681
|
checkNeedsStructKeyword: (name) =>
|
|
679
|
-
CodeGenState.symbolTable
|
|
682
|
+
CodeGenState.symbolTable.checkNeedsStructKeyword(name),
|
|
680
683
|
validateCrossScopeVisibility: (scope, member) =>
|
|
681
684
|
ScopeResolver.validateCrossScopeVisibility(scope, member),
|
|
682
685
|
});
|
|
@@ -802,30 +805,54 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
802
805
|
}
|
|
803
806
|
|
|
804
807
|
// Issue #137: Check for array element access (e.g., names[0], arr[i])
|
|
808
|
+
return this._isArrayAccessStringExpression(text);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Check if array access expression evaluates to a string.
|
|
813
|
+
* Extracted from isStringExpression to reduce cognitive complexity.
|
|
814
|
+
*/
|
|
815
|
+
private _isArrayAccessStringExpression(text: string): boolean {
|
|
805
816
|
// Pattern: identifier[expression] or identifier[expression][expression]...
|
|
806
817
|
// BUT NOT if accessing .length/.capacity/.size (those return numbers, not strings)
|
|
807
818
|
const arrayAccessMatch = /^([a-zA-Z_]\w*)\[/.exec(text);
|
|
808
|
-
if (arrayAccessMatch) {
|
|
809
|
-
|
|
810
|
-
if (
|
|
811
|
-
text.endsWith(".length") ||
|
|
812
|
-
text.endsWith(".capacity") ||
|
|
813
|
-
text.endsWith(".size")
|
|
814
|
-
) {
|
|
815
|
-
return false;
|
|
816
|
-
}
|
|
817
|
-
const arrayName = arrayAccessMatch[1];
|
|
818
|
-
const typeInfo = CodeGenState.typeRegistry.get(arrayName);
|
|
819
|
-
// Check if base type is a string type
|
|
820
|
-
if (
|
|
821
|
-
typeInfo?.isString ||
|
|
822
|
-
(typeInfo?.baseType && TypeCheckUtils.isString(typeInfo.baseType))
|
|
823
|
-
) {
|
|
824
|
-
return true;
|
|
825
|
-
}
|
|
819
|
+
if (!arrayAccessMatch) {
|
|
820
|
+
return false;
|
|
826
821
|
}
|
|
827
822
|
|
|
828
|
-
return
|
|
823
|
+
// ADR-045: String properties return numeric values, not strings
|
|
824
|
+
if (
|
|
825
|
+
text.endsWith(".length") ||
|
|
826
|
+
text.endsWith(".capacity") ||
|
|
827
|
+
text.endsWith(".size")
|
|
828
|
+
) {
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
const arrayName = arrayAccessMatch[1];
|
|
833
|
+
const typeInfo = CodeGenState.typeRegistry.get(arrayName);
|
|
834
|
+
if (!typeInfo) {
|
|
835
|
+
return false;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Check if it's an ARRAY OF STRINGS (not a single string being indexed)
|
|
839
|
+
// A single string<50> has arrayDimensions=[51] (just the char buffer)
|
|
840
|
+
// An array of strings string<50>[10] has arrayDimensions=[10, 51]
|
|
841
|
+
// Single string indexing (e.g., userName[i]) returns a char, not a string
|
|
842
|
+
// Array of strings indexing (e.g., names[0]) returns a string
|
|
843
|
+
if (typeInfo.isString) {
|
|
844
|
+
// For strings, only treat as string expression if it's an array of strings
|
|
845
|
+
// (arrayDimensions.length > 1 means it's string<N>[M], not just string<N>)
|
|
846
|
+
const dims = typeInfo.arrayDimensions;
|
|
847
|
+
return Array.isArray(dims) && dims.length > 1;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Non-string array with string base type
|
|
851
|
+
return Boolean(
|
|
852
|
+
typeInfo.isArray &&
|
|
853
|
+
typeInfo.baseType &&
|
|
854
|
+
TypeCheckUtils.isString(typeInfo.baseType),
|
|
855
|
+
);
|
|
829
856
|
}
|
|
830
857
|
|
|
831
858
|
/**
|
|
@@ -1505,7 +1532,9 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
1505
1532
|
return `${constMod}${p.type} ${p.name}${p.arrayDims}`;
|
|
1506
1533
|
} else if (p.isPointer) {
|
|
1507
1534
|
// ADR-006: Non-array, non-callback parameters become pointers
|
|
1508
|
-
|
|
1535
|
+
// In C++ mode, use reference (&) instead of pointer (*)
|
|
1536
|
+
const ptrOrRef = this.isCppMode() ? "&" : "*";
|
|
1537
|
+
return `${constMod}${p.type}${ptrOrRef}`;
|
|
1509
1538
|
} else {
|
|
1510
1539
|
// ADR-029: Callback parameters are already function pointers
|
|
1511
1540
|
return `${p.type}`;
|
|
@@ -2088,13 +2117,11 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
2088
2117
|
/**
|
|
2089
2118
|
* Generate C code from a C-Next program
|
|
2090
2119
|
* @param tree The parsed C-Next program
|
|
2091
|
-
* @param symbolTable Optional symbol table for cross-language interop
|
|
2092
2120
|
* @param tokenStream Optional token stream for comment preservation (ADR-043)
|
|
2093
2121
|
* @param options Optional code generator options (e.g., debugMode)
|
|
2094
2122
|
*/
|
|
2095
2123
|
generate(
|
|
2096
2124
|
tree: Parser.ProgramContext,
|
|
2097
|
-
symbolTable?: SymbolTable,
|
|
2098
2125
|
tokenStream?: CommonTokenStream,
|
|
2099
2126
|
options?: ICodeGeneratorOptions,
|
|
2100
2127
|
): string {
|
|
@@ -2116,9 +2143,6 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
2116
2143
|
// Initialize options and configuration (after reset)
|
|
2117
2144
|
this.initializeGenerateOptions(options, tokenStream);
|
|
2118
2145
|
|
|
2119
|
-
// Store symbol table for function lookup (after reset)
|
|
2120
|
-
CodeGenState.symbolTable = symbolTable ?? null;
|
|
2121
|
-
|
|
2122
2146
|
// ADR-055: Use pre-collected symbolInfo from Pipeline (TSymbolInfoAdapter)
|
|
2123
2147
|
if (!options?.symbolInfo) {
|
|
2124
2148
|
throw new Error(
|
|
@@ -2169,6 +2193,9 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
2169
2193
|
// Reset global state first
|
|
2170
2194
|
CodeGenState.reset(targetCapabilities);
|
|
2171
2195
|
|
|
2196
|
+
// Set generator reference for handlers to use
|
|
2197
|
+
CodeGenState.generator = this;
|
|
2198
|
+
|
|
2172
2199
|
// Reset local context (will gradually migrate to CodeGenState)
|
|
2173
2200
|
this.context = CodeGenerator.createDefaultContext(targetCapabilities);
|
|
2174
2201
|
|
|
@@ -2373,9 +2400,13 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
2373
2400
|
*/
|
|
2374
2401
|
private addGeneratedHelpers(output: string[]): void {
|
|
2375
2402
|
if (CodeGenState.needsFloatStaticAssert) {
|
|
2403
|
+
// Use static_assert for C++ (standard), _Static_assert for C11
|
|
2404
|
+
const assertKeyword = this.isCppMode()
|
|
2405
|
+
? "static_assert"
|
|
2406
|
+
: "_Static_assert";
|
|
2376
2407
|
output.push(
|
|
2377
|
-
|
|
2378
|
-
|
|
2408
|
+
`${assertKeyword}(sizeof(float) == 4, "Float bit indexing requires 32-bit float");`,
|
|
2409
|
+
`${assertKeyword}(sizeof(double) == 8, "Float bit indexing requires 64-bit double");`,
|
|
2379
2410
|
"",
|
|
2380
2411
|
);
|
|
2381
2412
|
}
|
|
@@ -5273,16 +5304,47 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
5273
5304
|
}
|
|
5274
5305
|
|
|
5275
5306
|
private generateParameter(ctx: Parser.ParameterContext): string {
|
|
5276
|
-
const constMod = ctx.constModifier() ? "const " : "";
|
|
5277
5307
|
const typeName = this.getTypeName(ctx.type());
|
|
5278
5308
|
const name = ctx.IDENTIFIER().getText();
|
|
5279
|
-
const dims = ctx.arrayDimension();
|
|
5280
5309
|
|
|
5281
|
-
// Reject
|
|
5282
|
-
|
|
5283
|
-
|
|
5310
|
+
// Validate: Reject C-style array parameters
|
|
5311
|
+
this._validateCStyleArrayParam(ctx, typeName, name);
|
|
5312
|
+
|
|
5313
|
+
// Validate: Reject unbounded array dimensions
|
|
5314
|
+
this._validateUnboundedArrayParam(ctx);
|
|
5315
|
+
|
|
5316
|
+
// Pre-compute CodeGenState-dependent values
|
|
5317
|
+
const isModified = this._isCurrentParameterModified(name);
|
|
5318
|
+
const isPassByValue = this._isPassByValueType(typeName, name);
|
|
5319
|
+
|
|
5320
|
+
// Build normalized input using adapter
|
|
5321
|
+
const input = ParameterInputAdapter.fromAST(ctx, {
|
|
5322
|
+
getTypeName: (t) => this.getTypeName(t),
|
|
5323
|
+
generateType: (t) => this.generateType(t),
|
|
5324
|
+
generateExpression: (e) => this.generateExpression(e),
|
|
5325
|
+
callbackTypes: CodeGenState.callbackTypes,
|
|
5326
|
+
isKnownStruct: (t) => this.isKnownStruct(t),
|
|
5327
|
+
typeMap: TYPE_MAP,
|
|
5328
|
+
isModified,
|
|
5329
|
+
isPassByValue,
|
|
5330
|
+
});
|
|
5331
|
+
|
|
5332
|
+
// Use shared builder with C/C++ mode
|
|
5333
|
+
return ParameterSignatureBuilder.build(input, CppModeHelper.refOrPtr());
|
|
5334
|
+
}
|
|
5335
|
+
|
|
5336
|
+
/**
|
|
5337
|
+
* Validate: Reject C-style array parameters
|
|
5338
|
+
* C-style: u8 data[8], u8 data[4][4], u8 data[]
|
|
5339
|
+
* C-Next: u8[8] data, u8[4][4] data, u8[] data
|
|
5340
|
+
*/
|
|
5341
|
+
private _validateCStyleArrayParam(
|
|
5342
|
+
ctx: Parser.ParameterContext,
|
|
5343
|
+
typeName: string,
|
|
5344
|
+
name: string,
|
|
5345
|
+
): void {
|
|
5346
|
+
const dims = ctx.arrayDimension();
|
|
5284
5347
|
if (dims.length > 0) {
|
|
5285
|
-
const baseType = typeName;
|
|
5286
5348
|
const dimensions = dims
|
|
5287
5349
|
.map((dim) => `[${dim.expression()?.getText() ?? ""}]`)
|
|
5288
5350
|
.join("");
|
|
@@ -5290,73 +5352,28 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
5290
5352
|
const col = ctx.start?.column ?? 0;
|
|
5291
5353
|
throw new Error(
|
|
5292
5354
|
`${line}:${col} C-style array parameter is not allowed. ` +
|
|
5293
|
-
`Use '${
|
|
5355
|
+
`Use '${typeName}${dimensions} ${name}' instead of '${typeName} ${name}${dimensions}'`,
|
|
5294
5356
|
);
|
|
5295
5357
|
}
|
|
5358
|
+
}
|
|
5296
5359
|
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
}
|
|
5302
|
-
|
|
5303
|
-
const type = this.generateType(ctx.type());
|
|
5304
|
-
|
|
5305
|
-
// Handle C-Next style array type in parameter (e.g., u8[8] param, u8[4][4] param, string<32>[5] param)
|
|
5360
|
+
/**
|
|
5361
|
+
* Validate: Reject unbounded array dimensions for memory safety
|
|
5362
|
+
*/
|
|
5363
|
+
private _validateUnboundedArrayParam(ctx: Parser.ParameterContext): void {
|
|
5306
5364
|
const arrayTypeCtx = ctx.type().arrayType();
|
|
5307
|
-
if (arrayTypeCtx)
|
|
5308
|
-
// Check for unbounded dimensions - reject for memory safety
|
|
5309
|
-
const allDims = arrayTypeCtx.arrayTypeDimension();
|
|
5310
|
-
const hasUnboundedDim = allDims.some((d) => !d.expression());
|
|
5311
|
-
if (hasUnboundedDim) {
|
|
5312
|
-
const line = ctx.start?.line ?? 0;
|
|
5313
|
-
const col = ctx.start?.column ?? 0;
|
|
5314
|
-
throw new Error(
|
|
5315
|
-
`${line}:${col} Unbounded array parameters are not allowed. ` +
|
|
5316
|
-
`All dimensions must have explicit sizes for memory safety.`,
|
|
5317
|
-
);
|
|
5318
|
-
}
|
|
5365
|
+
if (!arrayTypeCtx) return;
|
|
5319
5366
|
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
5330
|
-
if (intLiteral) {
|
|
5331
|
-
const capacity = Number.parseInt(intLiteral.getText(), 10);
|
|
5332
|
-
dims += `[${capacity + 1}]`;
|
|
5333
|
-
}
|
|
5334
|
-
}
|
|
5335
|
-
const wasModified = this._isCurrentParameterModified(name);
|
|
5336
|
-
const autoConst = !wasModified && !constMod ? "const " : "";
|
|
5337
|
-
return `${autoConst}${constMod}${type} ${name}${dims}`;
|
|
5338
|
-
}
|
|
5339
|
-
|
|
5340
|
-
// Pass-by-value types
|
|
5341
|
-
if (this._isPassByValueType(typeName, name)) {
|
|
5342
|
-
return `${constMod}${type} ${name}`;
|
|
5367
|
+
const allDims = arrayTypeCtx.arrayTypeDimension();
|
|
5368
|
+
const hasUnboundedDim = allDims.some((d) => !d.expression());
|
|
5369
|
+
if (hasUnboundedDim) {
|
|
5370
|
+
const line = ctx.start?.line ?? 0;
|
|
5371
|
+
const col = ctx.start?.column ?? 0;
|
|
5372
|
+
throw new Error(
|
|
5373
|
+
`${line}:${col} Unbounded array parameters are not allowed. ` +
|
|
5374
|
+
`All dimensions must have explicit sizes for memory safety.`,
|
|
5375
|
+
);
|
|
5343
5376
|
}
|
|
5344
|
-
|
|
5345
|
-
// Non-array string parameters
|
|
5346
|
-
const stringResult = this._tryGenerateStringParam(
|
|
5347
|
-
ctx,
|
|
5348
|
-
constMod,
|
|
5349
|
-
name,
|
|
5350
|
-
dims,
|
|
5351
|
-
);
|
|
5352
|
-
if (stringResult) return stringResult;
|
|
5353
|
-
|
|
5354
|
-
// Pass-by-reference types
|
|
5355
|
-
const refResult = this._tryGenerateRefParam(constMod, type, typeName, name);
|
|
5356
|
-
if (refResult) return refResult;
|
|
5357
|
-
|
|
5358
|
-
// Unknown types use pass-by-value (standard C semantics)
|
|
5359
|
-
return `${constMod}${type} ${name}`;
|
|
5360
5377
|
}
|
|
5361
5378
|
|
|
5362
5379
|
/**
|
|
@@ -5366,7 +5383,7 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
5366
5383
|
// ISR, float, enum types
|
|
5367
5384
|
if (typeName === "ISR") return true;
|
|
5368
5385
|
if (this._isFloatType(typeName)) return true;
|
|
5369
|
-
if (CodeGenState.symbols
|
|
5386
|
+
if (CodeGenState.symbols?.knownEnums.has(typeName)) return true;
|
|
5370
5387
|
|
|
5371
5388
|
// Small unmodified primitives
|
|
5372
5389
|
if (
|
|
@@ -5379,43 +5396,6 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
5379
5396
|
return false;
|
|
5380
5397
|
}
|
|
5381
5398
|
|
|
5382
|
-
/**
|
|
5383
|
-
* Try to generate non-array string parameter: string<N> -> char*
|
|
5384
|
-
*/
|
|
5385
|
-
private _tryGenerateStringParam(
|
|
5386
|
-
ctx: Parser.ParameterContext,
|
|
5387
|
-
constMod: string,
|
|
5388
|
-
name: string,
|
|
5389
|
-
dims: Parser.ArrayDimensionContext[],
|
|
5390
|
-
): string | null {
|
|
5391
|
-
if (!ctx.type().stringType() || dims.length !== 0) {
|
|
5392
|
-
return null;
|
|
5393
|
-
}
|
|
5394
|
-
|
|
5395
|
-
const wasModified = this._isCurrentParameterModified(name);
|
|
5396
|
-
const autoConst = !wasModified && !constMod ? "const " : "";
|
|
5397
|
-
return `${autoConst}${constMod}char* ${name}`;
|
|
5398
|
-
}
|
|
5399
|
-
|
|
5400
|
-
/**
|
|
5401
|
-
* Try to generate pass-by-reference parameter for known types
|
|
5402
|
-
*/
|
|
5403
|
-
private _tryGenerateRefParam(
|
|
5404
|
-
constMod: string,
|
|
5405
|
-
type: string,
|
|
5406
|
-
typeName: string,
|
|
5407
|
-
name: string,
|
|
5408
|
-
): string | null {
|
|
5409
|
-
if (!this.isKnownStruct(typeName) && !this._isKnownPrimitive(typeName)) {
|
|
5410
|
-
return null;
|
|
5411
|
-
}
|
|
5412
|
-
|
|
5413
|
-
const wasModified = this._isCurrentParameterModified(name);
|
|
5414
|
-
const autoConst = !wasModified && !constMod ? "const " : "";
|
|
5415
|
-
const refOrPtr = CppModeHelper.refOrPtr();
|
|
5416
|
-
return `${autoConst}${constMod}${type}${refOrPtr} ${name}`;
|
|
5417
|
-
}
|
|
5418
|
-
|
|
5419
5399
|
// ========================================================================
|
|
5420
5400
|
// Variables
|
|
5421
5401
|
// ========================================================================
|
|
@@ -6044,54 +6024,14 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
6044
6024
|
// Issue #644: _generateBitMask removed, now delegating to BitUtils.generateMask
|
|
6045
6025
|
// ========================================================================
|
|
6046
6026
|
|
|
6047
|
-
// ADR-109:
|
|
6048
|
-
private buildHandlerDeps(): IHandlerDeps {
|
|
6049
|
-
return {
|
|
6050
|
-
symbols: CodeGenState.symbols!,
|
|
6051
|
-
typeRegistry: CodeGenState.typeRegistry,
|
|
6052
|
-
currentScope: CodeGenState.currentScope,
|
|
6053
|
-
currentParameters: CodeGenState.currentParameters,
|
|
6054
|
-
targetCapabilities: CodeGenState.targetCapabilities,
|
|
6055
|
-
generateExpression: (ctx) => this.generateExpression(ctx),
|
|
6056
|
-
tryEvaluateConstant: (ctx) => this.tryEvaluateConstant(ctx),
|
|
6057
|
-
generateAssignmentTarget: (ctx) => this.generateAssignmentTarget(ctx),
|
|
6058
|
-
isKnownStruct: (name) => this.isKnownStruct(name),
|
|
6059
|
-
isKnownScope: (name) => this.isKnownScope(name),
|
|
6060
|
-
getMemberTypeInfo: (structType, memberName) =>
|
|
6061
|
-
this.getMemberTypeInfo(structType, memberName),
|
|
6062
|
-
validateBitmapFieldLiteral: (expr, width, fieldName) =>
|
|
6063
|
-
TypeValidator.validateBitmapFieldLiteral(expr, width, fieldName),
|
|
6064
|
-
validateCrossScopeVisibility: (scopeName, memberName) =>
|
|
6065
|
-
this.validateCrossScopeVisibility(scopeName, memberName),
|
|
6066
|
-
checkArrayBounds: (arrayName, dimensions, indexExprs, line) =>
|
|
6067
|
-
TypeValidator.checkArrayBounds(
|
|
6068
|
-
arrayName,
|
|
6069
|
-
[...dimensions],
|
|
6070
|
-
[...indexExprs],
|
|
6071
|
-
line,
|
|
6072
|
-
(expr) => this.tryEvaluateConstant(expr),
|
|
6073
|
-
),
|
|
6074
|
-
analyzeMemberChainForBitAccess: (targetCtx) =>
|
|
6075
|
-
this.analyzeMemberChainForBitAccess(targetCtx),
|
|
6076
|
-
generateFloatBitWrite: (name, typeInfo, bitIndex, width, value) =>
|
|
6077
|
-
this.generateFloatBitWrite(name, typeInfo, bitIndex, width, value),
|
|
6078
|
-
foldBooleanToInt: (expr) => this.foldBooleanToInt(expr),
|
|
6079
|
-
markNeedsString: () => {
|
|
6080
|
-
this.requireInclude("string");
|
|
6081
|
-
},
|
|
6082
|
-
markClampOpUsed: (op, typeName) => this.markClampOpUsed(op, typeName),
|
|
6083
|
-
generateAtomicRMW: (target, cOp, value, typeInfo) =>
|
|
6084
|
-
this.generateAtomicRMW(target, cOp, value, typeInfo),
|
|
6085
|
-
};
|
|
6086
|
-
}
|
|
6027
|
+
// ADR-109: buildHandlerDeps removed - handlers now use CodeGenState.generator directly
|
|
6087
6028
|
|
|
6088
6029
|
/**
|
|
6089
6030
|
* Analyze a member chain target to detect bit access at the end.
|
|
6090
6031
|
* Issue #644: Delegates to MemberChainAnalyzer.
|
|
6091
6032
|
*/
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
): {
|
|
6033
|
+
/** Public for handler access via CodeGenState.generator */
|
|
6034
|
+
analyzeMemberChainForBitAccess(targetCtx: Parser.AssignmentTargetContext): {
|
|
6095
6035
|
isBitAccess: boolean;
|
|
6096
6036
|
baseTarget?: string;
|
|
6097
6037
|
bitIndex?: string;
|
|
@@ -6107,7 +6047,8 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
6107
6047
|
* Generate float bit write using shadow variable + memcpy.
|
|
6108
6048
|
* Issue #644: Delegates to FloatBitHelper.
|
|
6109
6049
|
*/
|
|
6110
|
-
|
|
6050
|
+
/** Public for handler access via CodeGenState.generator */
|
|
6051
|
+
generateFloatBitWrite(
|
|
6111
6052
|
name: string,
|
|
6112
6053
|
typeInfo: TTypeInfo,
|
|
6113
6054
|
bitIndex: string,
|
|
@@ -6180,17 +6121,18 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
6180
6121
|
typeRegistry: CodeGenState.typeRegistry,
|
|
6181
6122
|
generateExpression: () => value,
|
|
6182
6123
|
});
|
|
6183
|
-
|
|
6124
|
+
// ADR-109: Handlers access CodeGenState directly, no deps needed
|
|
6184
6125
|
const assignmentKind = AssignmentClassifier.classify(assignCtx);
|
|
6185
6126
|
const handler = AssignmentHandlerRegistry.getHandler(assignmentKind);
|
|
6186
|
-
return handler(assignCtx
|
|
6127
|
+
return handler(assignCtx);
|
|
6187
6128
|
}
|
|
6188
6129
|
|
|
6189
6130
|
/**
|
|
6190
6131
|
* ADR-049: Generate atomic Read-Modify-Write operation
|
|
6191
6132
|
* Uses LDREX/STREX on platforms that support it, otherwise PRIMASK
|
|
6192
6133
|
*/
|
|
6193
|
-
|
|
6134
|
+
/** Public for handler access via CodeGenState.generator */
|
|
6135
|
+
generateAtomicRMW(
|
|
6194
6136
|
target: string,
|
|
6195
6137
|
cOp: string,
|
|
6196
6138
|
value: string,
|
|
@@ -6440,7 +6382,7 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
6440
6382
|
return null;
|
|
6441
6383
|
}
|
|
6442
6384
|
|
|
6443
|
-
// No expected enum type -
|
|
6385
|
+
// No expected enum type - bare enum members are not allowed without context
|
|
6444
6386
|
const matchingEnums: string[] = [];
|
|
6445
6387
|
for (const [enumName, members] of CodeGenState.symbols!.enumMembers) {
|
|
6446
6388
|
if (members.has(id)) {
|
|
@@ -6449,11 +6391,14 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
6449
6391
|
}
|
|
6450
6392
|
|
|
6451
6393
|
if (matchingEnums.length === 1) {
|
|
6452
|
-
|
|
6394
|
+
throw new Error(
|
|
6395
|
+
`error[E0424]: '${id}' is not defined; did you mean '${matchingEnums[0]}.${id}'?`,
|
|
6396
|
+
);
|
|
6453
6397
|
}
|
|
6454
6398
|
if (matchingEnums.length > 1) {
|
|
6399
|
+
const suggestions = matchingEnums.map((e) => `'${e}.${id}'`).join(" or ");
|
|
6455
6400
|
throw new Error(
|
|
6456
|
-
`
|
|
6401
|
+
`error[E0424]: '${id}' is not defined; did you mean ${suggestions}?`,
|
|
6457
6402
|
);
|
|
6458
6403
|
}
|
|
6459
6404
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Static class that reads from CodeGenState directly.
|
|
4
4
|
*/
|
|
5
5
|
import * as Parser from "../../logic/parser/grammar/CNextParser";
|
|
6
|
-
import CodeGenState from "
|
|
6
|
+
import CodeGenState from "../../state/CodeGenState";
|
|
7
7
|
import INTEGER_TYPES from "./types/INTEGER_TYPES";
|
|
8
8
|
import FLOAT_TYPES from "./types/FLOAT_TYPES";
|
|
9
9
|
import SIGNED_TYPES from "./types/SIGNED_TYPES";
|
|
@@ -73,7 +73,7 @@ class TypeResolver {
|
|
|
73
73
|
if (CodeGenState.symbols?.knownBitmaps.has(typeName)) {
|
|
74
74
|
return true;
|
|
75
75
|
}
|
|
76
|
-
if (CodeGenState.symbolTable
|
|
76
|
+
if (CodeGenState.symbolTable.getStructFields(typeName)) {
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
79
79
|
return false;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { dirname, resolve, join } from "node:path";
|
|
8
8
|
import * as Parser from "../../logic/parser/grammar/CNextParser";
|
|
9
|
-
import CodeGenState from "
|
|
9
|
+
import CodeGenState from "../../state/CodeGenState";
|
|
10
10
|
import TypeResolver from "./TypeResolver";
|
|
11
11
|
import ExpressionUtils from "../../../utils/ExpressionUtils";
|
|
12
12
|
// SonarCloud S3776: Extracted literal parsing to reduce complexity
|