c-next 0.1.8 → 0.1.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/README.md +20 -0
- package/package.json +6 -4
- package/src/analysis/ParameterNamingAnalyzer.ts +121 -0
- package/src/analysis/types/IParameterNamingError.ts +22 -0
- package/src/codegen/HeaderGenerator.ts +64 -61
- package/src/codegen/generators/GeneratorRegistry.ts +15 -6
- package/src/codegen/generators/declarationGenerators/ScopeGenerator.ts +1 -1
- package/src/codegen/generators/expressions/CallExprGenerator.ts +6 -3
- package/src/codegen/headerGenerators/IHeaderTypeInput.ts +32 -0
- package/src/codegen/headerGenerators/generateBitmapHeader.test.ts +212 -0
- package/src/codegen/headerGenerators/generateBitmapHeader.ts +58 -0
- package/src/codegen/headerGenerators/generateEnumHeader.test.ts +167 -0
- package/src/codegen/headerGenerators/generateEnumHeader.ts +53 -0
- package/src/codegen/headerGenerators/generateStructHeader.test.ts +177 -0
- package/src/codegen/headerGenerators/generateStructHeader.ts +60 -0
- package/src/codegen/headerGenerators/index.ts +18 -0
- package/src/codegen/headerGenerators/mapType.test.ts +94 -0
- package/src/codegen/headerGenerators/mapType.ts +63 -0
- package/src/pipeline/Pipeline.ts +12 -0
- package/src/pipeline/runAnalyzers.ts +25 -7
- package/src/symbols/CNextSymbolCollector.ts +57 -10
- package/src/symbols/SymbolTable.test.ts +201 -0
- package/src/symbols/SymbolTable.ts +38 -9
package/README.md
CHANGED
|
@@ -773,6 +773,26 @@ npm run coverage:grammar:check # Grammar coverage with threshold check (CI)
|
|
|
773
773
|
|
|
774
774
|
**Note:** C-Next runs directly via `tsx` without a build step. The `typecheck` command validates types only and does not generate any output files.
|
|
775
775
|
|
|
776
|
+
### Formatting C-Next Files
|
|
777
|
+
|
|
778
|
+
The project includes a Prettier plugin for formatting `.cnx` files with consistent style (4-space indentation, same-line braces).
|
|
779
|
+
|
|
780
|
+
```bash
|
|
781
|
+
# Format a single file
|
|
782
|
+
npx prettier --plugin ./prettier-plugin/dist/index.js --write myfile.cnx
|
|
783
|
+
|
|
784
|
+
# Format all .cnx files in tests/
|
|
785
|
+
npx prettier --plugin ./prettier-plugin/dist/index.js --write "tests/**/*.cnx"
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
To build the plugin from source (after making changes):
|
|
789
|
+
|
|
790
|
+
```bash
|
|
791
|
+
cd prettier-plugin
|
|
792
|
+
npm install
|
|
793
|
+
npm run build
|
|
794
|
+
```
|
|
795
|
+
|
|
776
796
|
## Contributing
|
|
777
797
|
|
|
778
798
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for the complete development workflow, testing requirements, and PR process.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c-next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"coverage:ids": "tsx scripts/coverage-checker.ts ids",
|
|
35
35
|
"coverage:grammar": "tsx scripts/grammar-coverage.ts report",
|
|
36
36
|
"coverage:grammar:check": "tsx scripts/grammar-coverage.ts check",
|
|
37
|
-
"coverage:grammar:console": "tsx scripts/grammar-coverage.ts console"
|
|
37
|
+
"coverage:grammar:console": "tsx scripts/grammar-coverage.ts console",
|
|
38
|
+
"unit": "vitest run",
|
|
39
|
+
"unit:watch": "vitest",
|
|
40
|
+
"test:all": "npm run unit && npm test"
|
|
38
41
|
},
|
|
39
42
|
"keywords": [
|
|
40
43
|
"c",
|
|
@@ -67,11 +70,10 @@
|
|
|
67
70
|
"@types/node": "^25.0.3",
|
|
68
71
|
"antlr4ng-cli": "^2.0.0",
|
|
69
72
|
"husky": "^9.1.7",
|
|
70
|
-
"jest": "^30.2.0",
|
|
71
73
|
"lint-staged": "^16.2.7",
|
|
72
74
|
"oxlint": "^1.39.0",
|
|
73
75
|
"prettier": "^3.7.4",
|
|
74
|
-
"
|
|
76
|
+
"vitest": "^3.0.0"
|
|
75
77
|
},
|
|
76
78
|
"dependencies": {
|
|
77
79
|
"antlr4ng": "^3.0.16",
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter Naming Analyzer
|
|
3
|
+
* Issue #227: Validates that function parameters don't use reserved naming patterns
|
|
4
|
+
*
|
|
5
|
+
* Parameters cannot start with their containing function's name followed by underscore.
|
|
6
|
+
* This naming pattern is reserved for scope-level variables and would bypass the
|
|
7
|
+
* conflict detection heuristic in SymbolTable.detectConflict().
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ParseTreeWalker } from "antlr4ng";
|
|
11
|
+
import { CNextListener } from "../parser/grammar/CNextListener";
|
|
12
|
+
import * as Parser from "../parser/grammar/CNextParser";
|
|
13
|
+
import IParameterNamingError from "./types/IParameterNamingError";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Pure function to check if a parameter name uses a reserved pattern
|
|
17
|
+
*
|
|
18
|
+
* @param parameterName - The parameter name to check
|
|
19
|
+
* @param functionName - The name of the containing function (without scope prefix)
|
|
20
|
+
* @returns true if the parameter name is problematic
|
|
21
|
+
*/
|
|
22
|
+
function isReservedParameterName(
|
|
23
|
+
parameterName: string,
|
|
24
|
+
functionName: string,
|
|
25
|
+
): boolean {
|
|
26
|
+
return parameterName.startsWith(functionName + "_");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Pure function to create the error message
|
|
31
|
+
*
|
|
32
|
+
* @param parameterName - The parameter name
|
|
33
|
+
* @param functionName - The containing function name
|
|
34
|
+
* @returns The formatted error message
|
|
35
|
+
*/
|
|
36
|
+
function formatParameterNamingError(
|
|
37
|
+
parameterName: string,
|
|
38
|
+
functionName: string,
|
|
39
|
+
): string {
|
|
40
|
+
return (
|
|
41
|
+
`Parameter '${parameterName}' cannot start with function name prefix ` +
|
|
42
|
+
`'${functionName}_'. This naming pattern is reserved for scope-level variables.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Listener that walks the parse tree to find parameter naming violations
|
|
48
|
+
*/
|
|
49
|
+
class ParameterNamingListener extends CNextListener {
|
|
50
|
+
private analyzer: ParameterNamingAnalyzer;
|
|
51
|
+
|
|
52
|
+
constructor(analyzer: ParameterNamingAnalyzer) {
|
|
53
|
+
super();
|
|
54
|
+
this.analyzer = analyzer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override enterFunctionDeclaration = (
|
|
58
|
+
ctx: Parser.FunctionDeclarationContext,
|
|
59
|
+
): void => {
|
|
60
|
+
const functionName = ctx.IDENTIFIER().getText();
|
|
61
|
+
const paramList = ctx.parameterList();
|
|
62
|
+
|
|
63
|
+
if (paramList) {
|
|
64
|
+
for (const param of paramList.parameter()) {
|
|
65
|
+
const paramIdentifier = param.IDENTIFIER();
|
|
66
|
+
const paramName = paramIdentifier.getText();
|
|
67
|
+
// Use the identifier's position for more precise error location
|
|
68
|
+
const line = paramIdentifier.symbol.line;
|
|
69
|
+
const column = paramIdentifier.symbol.column;
|
|
70
|
+
|
|
71
|
+
if (isReservedParameterName(paramName, functionName)) {
|
|
72
|
+
this.analyzer.addError(paramName, functionName, line, column);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Analyzer for parameter naming violations
|
|
81
|
+
*/
|
|
82
|
+
class ParameterNamingAnalyzer {
|
|
83
|
+
private errors: IParameterNamingError[] = [];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Analyze the parse tree for parameter naming violations
|
|
87
|
+
*
|
|
88
|
+
* @param tree - The parsed program AST
|
|
89
|
+
* @returns Array of errors (empty if all pass)
|
|
90
|
+
*/
|
|
91
|
+
public analyze(tree: Parser.ProgramContext): IParameterNamingError[] {
|
|
92
|
+
this.errors = [];
|
|
93
|
+
|
|
94
|
+
const listener = new ParameterNamingListener(this);
|
|
95
|
+
ParseTreeWalker.DEFAULT.walk(listener, tree);
|
|
96
|
+
|
|
97
|
+
return this.errors;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Add a parameter naming error
|
|
102
|
+
*/
|
|
103
|
+
public addError(
|
|
104
|
+
parameterName: string,
|
|
105
|
+
functionName: string,
|
|
106
|
+
line: number,
|
|
107
|
+
column: number,
|
|
108
|
+
): void {
|
|
109
|
+
this.errors.push({
|
|
110
|
+
code: "E0227",
|
|
111
|
+
parameterName,
|
|
112
|
+
functionName,
|
|
113
|
+
line,
|
|
114
|
+
column,
|
|
115
|
+
message: formatParameterNamingError(parameterName, functionName),
|
|
116
|
+
helpText: `Consider renaming to a name that doesn't start with '${functionName}_'`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export default ParameterNamingAnalyzer;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error reported when a function parameter has a reserved naming pattern
|
|
3
|
+
* Issue #227: Parameters cannot start with their function name followed by underscore
|
|
4
|
+
*/
|
|
5
|
+
interface IParameterNamingError {
|
|
6
|
+
/** Error code (E0227) - matches issue number */
|
|
7
|
+
code: string;
|
|
8
|
+
/** Name of the parameter */
|
|
9
|
+
parameterName: string;
|
|
10
|
+
/** Name of the containing function */
|
|
11
|
+
functionName: string;
|
|
12
|
+
/** Line number where the parameter is declared */
|
|
13
|
+
line: number;
|
|
14
|
+
/** Column number where the parameter is declared */
|
|
15
|
+
column: number;
|
|
16
|
+
/** Human-readable error message */
|
|
17
|
+
message: string;
|
|
18
|
+
/** Optional help text with suggested fix */
|
|
19
|
+
helpText?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default IParameterNamingError;
|
|
@@ -8,25 +8,13 @@ import ESymbolKind from "../types/ESymbolKind";
|
|
|
8
8
|
import ESourceLanguage from "../types/ESourceLanguage";
|
|
9
9
|
import SymbolTable from "../symbols/SymbolTable";
|
|
10
10
|
import IHeaderOptions from "./types/IHeaderOptions";
|
|
11
|
+
import IHeaderTypeInput from "./headerGenerators/IHeaderTypeInput";
|
|
12
|
+
import typeUtils from "./headerGenerators/mapType";
|
|
13
|
+
import generateEnumHeader from "./headerGenerators/generateEnumHeader";
|
|
14
|
+
import generateStructHeader from "./headerGenerators/generateStructHeader";
|
|
15
|
+
import generateBitmapHeader from "./headerGenerators/generateBitmapHeader";
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
* Maps C-Next types to C types
|
|
14
|
-
*/
|
|
15
|
-
const TYPE_MAP: Record<string, string> = {
|
|
16
|
-
u8: "uint8_t",
|
|
17
|
-
u16: "uint16_t",
|
|
18
|
-
u32: "uint32_t",
|
|
19
|
-
u64: "uint64_t",
|
|
20
|
-
i8: "int8_t",
|
|
21
|
-
i16: "int16_t",
|
|
22
|
-
i32: "int32_t",
|
|
23
|
-
i64: "int64_t",
|
|
24
|
-
f32: "float",
|
|
25
|
-
f64: "double",
|
|
26
|
-
bool: "bool",
|
|
27
|
-
void: "void",
|
|
28
|
-
ISR: "ISR", // ADR-040: Interrupt Service Routine function pointer
|
|
29
|
-
};
|
|
17
|
+
const { TYPE_MAP, mapType } = typeUtils;
|
|
30
18
|
|
|
31
19
|
/**
|
|
32
20
|
* Generates C header files from symbol information
|
|
@@ -34,11 +22,17 @@ const TYPE_MAP: Record<string, string> = {
|
|
|
34
22
|
class HeaderGenerator {
|
|
35
23
|
/**
|
|
36
24
|
* Generate a header file from symbols
|
|
25
|
+
*
|
|
26
|
+
* @param symbols - Array of symbols to include in header
|
|
27
|
+
* @param filename - Output filename (used for include guard)
|
|
28
|
+
* @param options - Header generation options
|
|
29
|
+
* @param typeInput - Optional type information for full definitions (enums, structs, bitmaps)
|
|
37
30
|
*/
|
|
38
31
|
generate(
|
|
39
32
|
symbols: ISymbol[],
|
|
40
33
|
filename: string,
|
|
41
34
|
options: IHeaderOptions = {},
|
|
35
|
+
typeInput?: IHeaderTypeInput,
|
|
42
36
|
): string {
|
|
43
37
|
const lines: string[] = [];
|
|
44
38
|
const guard = this.makeGuard(filename, options.guardPrefix);
|
|
@@ -86,17 +80,22 @@ class HeaderGenerator {
|
|
|
86
80
|
);
|
|
87
81
|
const enums = exportedSymbols.filter((s) => s.kind === ESymbolKind.Enum);
|
|
88
82
|
const types = exportedSymbols.filter((s) => s.kind === ESymbolKind.Type);
|
|
83
|
+
const bitmaps = exportedSymbols.filter(
|
|
84
|
+
(s) => s.kind === ESymbolKind.Bitmap,
|
|
85
|
+
);
|
|
89
86
|
|
|
90
87
|
// Issue #121: Collect external type dependencies from function signatures
|
|
91
88
|
const localStructNames = new Set(structs.map((s) => s.name));
|
|
92
89
|
const localEnumNames = new Set(enums.map((s) => s.name));
|
|
93
90
|
const localTypeNames = new Set(types.map((s) => s.name));
|
|
91
|
+
const localBitmapNames = new Set(bitmaps.map((s) => s.name));
|
|
94
92
|
const externalTypes = this.collectExternalTypes(
|
|
95
93
|
functions,
|
|
96
94
|
variables,
|
|
97
95
|
localStructNames,
|
|
98
96
|
localEnumNames,
|
|
99
97
|
localTypeNames,
|
|
98
|
+
localBitmapNames,
|
|
100
99
|
);
|
|
101
100
|
|
|
102
101
|
// Emit forward declarations for external types
|
|
@@ -110,25 +109,52 @@ class HeaderGenerator {
|
|
|
110
109
|
lines.push("");
|
|
111
110
|
}
|
|
112
111
|
|
|
113
|
-
//
|
|
112
|
+
// Struct definitions or forward declarations
|
|
114
113
|
if (structs.length > 0 || classes.length > 0) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
if (typeInput) {
|
|
115
|
+
lines.push("/* Struct definitions */");
|
|
116
|
+
for (const sym of structs) {
|
|
117
|
+
lines.push(generateStructHeader(sym.name, typeInput));
|
|
118
|
+
}
|
|
119
|
+
for (const sym of classes) {
|
|
120
|
+
lines.push(generateStructHeader(sym.name, typeInput));
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
lines.push("/* Forward declarations */");
|
|
124
|
+
for (const sym of structs) {
|
|
125
|
+
lines.push(`typedef struct ${sym.name} ${sym.name};`);
|
|
126
|
+
}
|
|
127
|
+
for (const sym of classes) {
|
|
128
|
+
lines.push(`typedef struct ${sym.name} ${sym.name};`);
|
|
129
|
+
}
|
|
122
130
|
}
|
|
123
131
|
lines.push("");
|
|
124
132
|
}
|
|
125
133
|
|
|
126
|
-
// Enum
|
|
134
|
+
// Enum definitions or comments
|
|
127
135
|
if (enums.length > 0) {
|
|
128
136
|
lines.push("/* Enumerations */");
|
|
129
137
|
for (const sym of enums) {
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
if (typeInput) {
|
|
139
|
+
lines.push(generateEnumHeader(sym.name, typeInput));
|
|
140
|
+
} else {
|
|
141
|
+
lines.push(`/* Enum: ${sym.name} (see implementation for values) */`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
lines.push("");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Bitmap definitions (only when typeInput is available)
|
|
148
|
+
if (bitmaps.length > 0) {
|
|
149
|
+
lines.push("/* Bitmaps */");
|
|
150
|
+
for (const sym of bitmaps) {
|
|
151
|
+
if (typeInput) {
|
|
152
|
+
lines.push(generateBitmapHeader(sym.name, typeInput));
|
|
153
|
+
} else {
|
|
154
|
+
lines.push(
|
|
155
|
+
`/* Bitmap: ${sym.name} (see implementation for layout) */`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
132
158
|
}
|
|
133
159
|
lines.push("");
|
|
134
160
|
}
|
|
@@ -138,7 +164,7 @@ class HeaderGenerator {
|
|
|
138
164
|
lines.push("/* Type aliases */");
|
|
139
165
|
for (const sym of types) {
|
|
140
166
|
if (sym.type) {
|
|
141
|
-
const cType =
|
|
167
|
+
const cType = mapType(sym.type);
|
|
142
168
|
lines.push(`typedef ${cType} ${sym.name};`);
|
|
143
169
|
}
|
|
144
170
|
}
|
|
@@ -149,7 +175,7 @@ class HeaderGenerator {
|
|
|
149
175
|
if (variables.length > 0) {
|
|
150
176
|
lines.push("/* External variables */");
|
|
151
177
|
for (const sym of variables) {
|
|
152
|
-
const cType = sym.type ?
|
|
178
|
+
const cType = sym.type ? mapType(sym.type) : "int";
|
|
153
179
|
lines.push(`extern ${cType} ${sym.name};`);
|
|
154
180
|
}
|
|
155
181
|
lines.push("");
|
|
@@ -224,47 +250,20 @@ class HeaderGenerator {
|
|
|
224
250
|
return `${sanitized}_H`;
|
|
225
251
|
}
|
|
226
252
|
|
|
227
|
-
/**
|
|
228
|
-
* Map a C-Next type to C type
|
|
229
|
-
*/
|
|
230
|
-
private mapType(type: string): string {
|
|
231
|
-
// Check direct mapping first
|
|
232
|
-
if (TYPE_MAP[type]) {
|
|
233
|
-
return TYPE_MAP[type];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Handle pointer types
|
|
237
|
-
if (type.endsWith("*")) {
|
|
238
|
-
const baseType = type.slice(0, -1).trim();
|
|
239
|
-
return `${this.mapType(baseType)}*`;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Handle array types (simplified)
|
|
243
|
-
const arrayMatch = type.match(/^(\w+)\[(\d*)\]$/);
|
|
244
|
-
if (arrayMatch) {
|
|
245
|
-
const baseType = this.mapType(arrayMatch[1]);
|
|
246
|
-
const size = arrayMatch[2] || "";
|
|
247
|
-
return `${baseType}[${size}]`;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// User-defined types pass through
|
|
251
|
-
return type;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
253
|
/**
|
|
255
254
|
* Generate a function prototype from symbol info
|
|
256
255
|
* Handles all parameter edge cases per ADR-006, ADR-029, and ADR-040
|
|
257
256
|
*/
|
|
258
257
|
private generateFunctionPrototype(sym: ISymbol): string | null {
|
|
259
258
|
// Map return type from C-Next to C
|
|
260
|
-
const returnType = sym.type ?
|
|
259
|
+
const returnType = sym.type ? mapType(sym.type) : "void";
|
|
261
260
|
|
|
262
261
|
// Build parameter list with proper C semantics
|
|
263
262
|
let params = "void"; // Default for no parameters
|
|
264
263
|
|
|
265
264
|
if (sym.parameters && sym.parameters.length > 0) {
|
|
266
265
|
const translatedParams = sym.parameters.map((p) => {
|
|
267
|
-
const baseType =
|
|
266
|
+
const baseType = mapType(p.type);
|
|
268
267
|
const constMod = p.isConst ? "const " : "";
|
|
269
268
|
|
|
270
269
|
// Handle array parameters (pass naturally as pointers per C semantics)
|
|
@@ -301,7 +300,7 @@ class HeaderGenerator {
|
|
|
301
300
|
* Issue #121: Collect external type dependencies from function signatures and variables
|
|
302
301
|
* Returns types that are:
|
|
303
302
|
* - Not primitive types (not in TYPE_MAP)
|
|
304
|
-
* - Not locally defined structs, enums, or type aliases
|
|
303
|
+
* - Not locally defined structs, enums, bitmaps, or type aliases
|
|
305
304
|
*/
|
|
306
305
|
private collectExternalTypes(
|
|
307
306
|
functions: ISymbol[],
|
|
@@ -309,6 +308,7 @@ class HeaderGenerator {
|
|
|
309
308
|
localStructs: Set<string>,
|
|
310
309
|
localEnums: Set<string>,
|
|
311
310
|
localTypes: Set<string>,
|
|
311
|
+
localBitmaps: Set<string>,
|
|
312
312
|
): Set<string> {
|
|
313
313
|
const externalTypes = new Set<string>();
|
|
314
314
|
|
|
@@ -328,6 +328,9 @@ class HeaderGenerator {
|
|
|
328
328
|
if (localTypes.has(typeName)) {
|
|
329
329
|
return false;
|
|
330
330
|
}
|
|
331
|
+
if (localBitmaps.has(typeName)) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
331
334
|
|
|
332
335
|
// Skip pointer markers and array brackets
|
|
333
336
|
if (typeName === "" || typeName === "*") {
|
|
@@ -62,8 +62,11 @@ export default class GeneratorRegistry {
|
|
|
62
62
|
* @param kind - Declaration kind (e.g., 'struct', 'enum', 'function')
|
|
63
63
|
* @param fn - Generator function
|
|
64
64
|
*/
|
|
65
|
-
registerDeclaration
|
|
66
|
-
|
|
65
|
+
registerDeclaration<T extends ParserRuleContext>(
|
|
66
|
+
kind: string,
|
|
67
|
+
fn: TGeneratorFn<T>,
|
|
68
|
+
): void {
|
|
69
|
+
this.declarations.set(kind, fn as TGeneratorFn<ParserRuleContext>);
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
/**
|
|
@@ -71,8 +74,11 @@ export default class GeneratorRegistry {
|
|
|
71
74
|
* @param kind - Statement kind (e.g., 'if', 'while', 'assignment')
|
|
72
75
|
* @param fn - Generator function
|
|
73
76
|
*/
|
|
74
|
-
registerStatement
|
|
75
|
-
|
|
77
|
+
registerStatement<T extends ParserRuleContext>(
|
|
78
|
+
kind: string,
|
|
79
|
+
fn: TGeneratorFn<T>,
|
|
80
|
+
): void {
|
|
81
|
+
this.statements.set(kind, fn as TGeneratorFn<ParserRuleContext>);
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
/**
|
|
@@ -80,8 +86,11 @@ export default class GeneratorRegistry {
|
|
|
80
86
|
* @param kind - Expression kind (e.g., 'ternary', 'binary', 'call')
|
|
81
87
|
* @param fn - Generator function
|
|
82
88
|
*/
|
|
83
|
-
registerExpression
|
|
84
|
-
|
|
89
|
+
registerExpression<T extends ParserRuleContext>(
|
|
90
|
+
kind: string,
|
|
91
|
+
fn: TGeneratorFn<T>,
|
|
92
|
+
): void {
|
|
93
|
+
this.expressions.set(kind, fn as TGeneratorFn<ParserRuleContext>);
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
// =========================================================================
|
|
@@ -268,7 +268,7 @@ function generateScopedBitmapInline(
|
|
|
268
268
|
lines.push(" */");
|
|
269
269
|
} else {
|
|
270
270
|
// Fall back to AST parsing
|
|
271
|
-
const fields = node.
|
|
271
|
+
const fields = node.bitmapMember();
|
|
272
272
|
if (fields.length > 0) {
|
|
273
273
|
lines.push("/* Fields:");
|
|
274
274
|
let bitOffset = 0;
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
* - C function calls with pass-by-value semantics
|
|
8
8
|
* - Const-to-non-const validation (ADR-013)
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
ArgumentListContext,
|
|
12
|
+
ExpressionContext,
|
|
13
|
+
} from "../../../parser/grammar/CNextParser";
|
|
11
14
|
import IGeneratorOutput from "../IGeneratorOutput";
|
|
12
15
|
import TGeneratorEffect from "../TGeneratorEffect";
|
|
13
16
|
import IGeneratorInput from "../IGeneratorInput";
|
|
@@ -94,7 +97,7 @@ const generateFunctionCall = (
|
|
|
94
97
|
*/
|
|
95
98
|
const generateSafeDivMod = (
|
|
96
99
|
funcName: string,
|
|
97
|
-
argExprs:
|
|
100
|
+
argExprs: ExpressionContext[],
|
|
98
101
|
input: IGeneratorInput,
|
|
99
102
|
orchestrator: IOrchestrator,
|
|
100
103
|
effects: TGeneratorEffect[],
|
|
@@ -157,7 +160,7 @@ const generateSafeDivMod = (
|
|
|
157
160
|
*/
|
|
158
161
|
const validateConstToNonConst = (
|
|
159
162
|
funcName: string,
|
|
160
|
-
argExprs:
|
|
163
|
+
argExprs: ExpressionContext[],
|
|
161
164
|
input: IGeneratorInput,
|
|
162
165
|
orchestrator: IOrchestrator,
|
|
163
166
|
): void => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input interface for header type generators.
|
|
3
|
+
* Provides read-only access to symbol data needed for generating
|
|
4
|
+
* type definitions in C headers.
|
|
5
|
+
*
|
|
6
|
+
* This interface is a subset of ISymbolInfo, containing only
|
|
7
|
+
* the data needed for generating enums, structs, and bitmaps.
|
|
8
|
+
*/
|
|
9
|
+
interface IHeaderTypeInput {
|
|
10
|
+
/** Enum members and values: enumName -> (memberName -> value) */
|
|
11
|
+
readonly enumMembers: ReadonlyMap<string, ReadonlyMap<string, number>>;
|
|
12
|
+
|
|
13
|
+
/** Struct field types: structName -> (fieldName -> typeName) */
|
|
14
|
+
readonly structFields: ReadonlyMap<string, ReadonlyMap<string, string>>;
|
|
15
|
+
|
|
16
|
+
/** Array dimensions for struct fields: structName -> (fieldName -> dimensions) */
|
|
17
|
+
readonly structFieldDimensions: ReadonlyMap<
|
|
18
|
+
string,
|
|
19
|
+
ReadonlyMap<string, readonly number[]>
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
/** Backing type for each bitmap: bitmapName -> typeName (e.g., "uint8_t") */
|
|
23
|
+
readonly bitmapBackingType: ReadonlyMap<string, string>;
|
|
24
|
+
|
|
25
|
+
/** Bitmap field info: bitmapName -> (fieldName -> {offset, width}) */
|
|
26
|
+
readonly bitmapFields: ReadonlyMap<
|
|
27
|
+
string,
|
|
28
|
+
ReadonlyMap<string, { readonly offset: number; readonly width: number }>
|
|
29
|
+
>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default IHeaderTypeInput;
|