c-next 0.1.4 → 0.1.5
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 +2 -2
- package/grammar/CNext.g4 +0 -10
- package/package.json +6 -2
- package/src/analysis/FunctionCallAnalyzer.ts +78 -1
- package/src/codegen/CodeGenerator.ts +487 -61
- package/src/codegen/HeaderGenerator.ts +112 -0
- package/src/codegen/types/C_TYPE_WIDTH.ts +2 -2
- package/src/codegen/types/TParameterInfo.ts +1 -0
- package/src/codegen/types/TYPE_WIDTH.ts +1 -1
- package/src/index.ts +3 -1
- package/src/parser/grammar/CNext.interp +1 -3
- package/src/parser/grammar/CNextListener.ts +0 -22
- package/src/parser/grammar/CNextParser.ts +984 -1178
- package/src/parser/grammar/CNextVisitor.ts +0 -14
package/README.md
CHANGED
|
@@ -187,8 +187,8 @@ Your `.cnx` files and generated `.c` files remain untouched.
|
|
|
187
187
|
If you prefer manual control, you can also run the transpiler explicitly:
|
|
188
188
|
|
|
189
189
|
```bash
|
|
190
|
-
# Transpile all .cnx files in
|
|
191
|
-
cnext
|
|
190
|
+
# Transpile all .cnx files in a directory (recursive)
|
|
191
|
+
cnext src/
|
|
192
192
|
|
|
193
193
|
# Or transpile specific files
|
|
194
194
|
cnext src/ConfigStorage.cnx
|
package/grammar/CNext.g4
CHANGED
|
@@ -505,7 +505,6 @@ type
|
|
|
505
505
|
| qualifiedType // ADR-016: Scope.Type from outside scope
|
|
506
506
|
| userType
|
|
507
507
|
| arrayType
|
|
508
|
-
| genericType
|
|
509
508
|
| 'void'
|
|
510
509
|
;
|
|
511
510
|
|
|
@@ -543,15 +542,6 @@ arrayType
|
|
|
543
542
|
| userType '[' expression ']'
|
|
544
543
|
;
|
|
545
544
|
|
|
546
|
-
genericType
|
|
547
|
-
: IDENTIFIER '<' typeArgument (',' typeArgument)* '>'
|
|
548
|
-
;
|
|
549
|
-
|
|
550
|
-
typeArgument
|
|
551
|
-
: type
|
|
552
|
-
| expression // For numeric type parameters like buffer sizes
|
|
553
|
-
;
|
|
554
|
-
|
|
555
545
|
// ----------------------------------------------------------------------------
|
|
556
546
|
// Literals (ADR-024: Type suffixes OPTIONAL, validated against target type)
|
|
557
547
|
// ----------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c-next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
"oxlint:check": "oxlint src/",
|
|
27
27
|
"oxlint:fix": "oxlint src/ --fix",
|
|
28
28
|
"prepare": "husky",
|
|
29
|
-
"prepublishOnly": "npm run prettier:check && npm run oxlint:check && npm test"
|
|
29
|
+
"prepublishOnly": "npm run prettier:check && npm run oxlint:check && npm test",
|
|
30
|
+
"coverage:check": "tsx scripts/coverage-checker.ts check",
|
|
31
|
+
"coverage:report": "tsx scripts/coverage-checker.ts report",
|
|
32
|
+
"coverage:gaps": "tsx scripts/coverage-checker.ts gaps",
|
|
33
|
+
"coverage:ids": "tsx scripts/coverage-checker.ts ids"
|
|
30
34
|
},
|
|
31
35
|
"keywords": [
|
|
32
36
|
"c",
|
|
@@ -229,6 +229,42 @@ class FunctionCallListener extends CNextListener {
|
|
|
229
229
|
this.analyzer = analyzer;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
// ========================================================================
|
|
233
|
+
// ISR/Callback Variable Tracking (ADR-040)
|
|
234
|
+
// ========================================================================
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Track ISR-typed variables from variable declarations
|
|
238
|
+
* e.g., `ISR handler <- myFunction;`
|
|
239
|
+
*/
|
|
240
|
+
override enterVariableDeclaration = (
|
|
241
|
+
ctx: Parser.VariableDeclarationContext,
|
|
242
|
+
): void => {
|
|
243
|
+
const typeCtx = ctx.type();
|
|
244
|
+
const typeName = typeCtx.getText();
|
|
245
|
+
|
|
246
|
+
// Check if this is an ISR type or a callback type (function-as-type)
|
|
247
|
+
if (typeName === "ISR" || this.analyzer.isCallbackType(typeName)) {
|
|
248
|
+
const varName = ctx.IDENTIFIER().getText();
|
|
249
|
+
this.analyzer.defineCallableVariable(varName);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Track ISR-typed parameters in function declarations
|
|
255
|
+
* e.g., `void execute(ISR handler) { handler(); }`
|
|
256
|
+
*/
|
|
257
|
+
override enterParameter = (ctx: Parser.ParameterContext): void => {
|
|
258
|
+
const typeCtx = ctx.type();
|
|
259
|
+
const typeName = typeCtx.getText();
|
|
260
|
+
|
|
261
|
+
// Check if this is an ISR type or a callback type (function-as-type)
|
|
262
|
+
if (typeName === "ISR" || this.analyzer.isCallbackType(typeName)) {
|
|
263
|
+
const paramName = ctx.IDENTIFIER().getText();
|
|
264
|
+
this.analyzer.defineCallableVariable(paramName);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
232
268
|
// ========================================================================
|
|
233
269
|
// Function Definitions
|
|
234
270
|
// ========================================================================
|
|
@@ -357,6 +393,12 @@ class FunctionCallAnalyzer {
|
|
|
357
393
|
/** Current function being defined (for self-recursion detection) */
|
|
358
394
|
private currentFunctionName: string | null = null;
|
|
359
395
|
|
|
396
|
+
/** ADR-040: Variables of type ISR or callback types that can be invoked */
|
|
397
|
+
private callableVariables: Set<string> = new Set();
|
|
398
|
+
|
|
399
|
+
/** ADR-029: Callback types (function-as-type pattern) */
|
|
400
|
+
private callbackTypes: Set<string> = new Set();
|
|
401
|
+
|
|
360
402
|
/**
|
|
361
403
|
* Analyze a parsed program for function call errors
|
|
362
404
|
* @param tree The parsed program AST
|
|
@@ -373,10 +415,13 @@ class FunctionCallAnalyzer {
|
|
|
373
415
|
this.includedHeaders = new Set();
|
|
374
416
|
this.symbolTable = symbolTable ?? null;
|
|
375
417
|
this.currentFunctionName = null;
|
|
418
|
+
this.callableVariables = new Set();
|
|
419
|
+
this.callbackTypes = new Set();
|
|
376
420
|
|
|
377
|
-
// First pass: collect scope names and
|
|
421
|
+
// First pass: collect scope names, includes, and callback types
|
|
378
422
|
this.collectScopes(tree);
|
|
379
423
|
this.collectIncludes(tree);
|
|
424
|
+
this.collectCallbackTypes(tree);
|
|
380
425
|
|
|
381
426
|
// Second pass: walk tree in order, tracking definitions and checking calls
|
|
382
427
|
const listener = new FunctionCallListener(this);
|
|
@@ -424,6 +469,33 @@ class FunctionCallAnalyzer {
|
|
|
424
469
|
return false;
|
|
425
470
|
}
|
|
426
471
|
|
|
472
|
+
/**
|
|
473
|
+
* ADR-029: Collect callback types (function-as-type pattern)
|
|
474
|
+
* Any function definition creates a type that can be used for callback fields/parameters
|
|
475
|
+
*/
|
|
476
|
+
private collectCallbackTypes(tree: Parser.ProgramContext): void {
|
|
477
|
+
for (const decl of tree.declaration()) {
|
|
478
|
+
if (decl.functionDeclaration()) {
|
|
479
|
+
const name = decl.functionDeclaration()!.IDENTIFIER().getText();
|
|
480
|
+
this.callbackTypes.add(name);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* ADR-029: Check if a type name is a callback type (function-as-type)
|
|
487
|
+
*/
|
|
488
|
+
public isCallbackType(name: string): boolean {
|
|
489
|
+
return this.callbackTypes.has(name);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* ADR-040: Register a variable that holds a callable (ISR or callback)
|
|
494
|
+
*/
|
|
495
|
+
public defineCallableVariable(name: string): void {
|
|
496
|
+
this.callableVariables.add(name);
|
|
497
|
+
}
|
|
498
|
+
|
|
427
499
|
/**
|
|
428
500
|
* Register a function as defined
|
|
429
501
|
*/
|
|
@@ -488,6 +560,11 @@ class FunctionCallAnalyzer {
|
|
|
488
560
|
return; // OK - external C/C++ function
|
|
489
561
|
}
|
|
490
562
|
|
|
563
|
+
// ADR-040: Check if this is an ISR or callback variable being invoked
|
|
564
|
+
if (this.callableVariables.has(name)) {
|
|
565
|
+
return; // OK - invoking a function pointer variable
|
|
566
|
+
}
|
|
567
|
+
|
|
491
568
|
// Not defined - report error
|
|
492
569
|
this.errors.push({
|
|
493
570
|
code: "E0422",
|