c-next 0.1.3 → 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 +39 -38
- package/grammar/CNext.g4 +2 -12
- package/package.json +6 -2
- package/src/analysis/FunctionCallAnalyzer.ts +78 -1
- package/src/codegen/CodeGenerator.ts +658 -110
- package/src/codegen/HeaderGenerator.ts +112 -0
- package/src/codegen/TypeResolver.ts +30 -3
- 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 +1022 -1189
- 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
|
|
@@ -661,42 +661,43 @@ Decisions are documented in `/docs/decisions/`:
|
|
|
661
661
|
|
|
662
662
|
### Implemented
|
|
663
663
|
|
|
664
|
-
| ADR
|
|
665
|
-
|
|
|
666
|
-
| [ADR-001](docs/decisions/adr-001-assignment-operator.md)
|
|
667
|
-
| [ADR-003](docs/decisions/adr-003-static-allocation.md)
|
|
668
|
-
| [ADR-004](docs/decisions/adr-004-register-bindings.md)
|
|
669
|
-
| [ADR-006](docs/decisions/adr-006-simplified-references.md)
|
|
670
|
-
| [ADR-007](docs/decisions/adr-007-type-aware-bit-indexing.md)
|
|
671
|
-
| [ADR-010](docs/decisions/adr-010-c-interoperability.md)
|
|
672
|
-
| [ADR-011](docs/decisions/adr-011-vscode-extension.md)
|
|
673
|
-
| [ADR-012](docs/decisions/adr-012-static-analysis.md)
|
|
674
|
-
| [ADR-013](docs/decisions/adr-013-const-qualifier.md)
|
|
675
|
-
| [ADR-014](docs/decisions/adr-014-structs.md)
|
|
676
|
-
| [ADR-015](docs/decisions/adr-015-null-state.md)
|
|
677
|
-
| [ADR-016](docs/decisions/adr-016-scope.md)
|
|
678
|
-
| [ADR-017](docs/decisions/adr-017-enums.md)
|
|
679
|
-
| [ADR-030](docs/decisions/adr-030-forward-declarations.md)
|
|
680
|
-
| [ADR-037](docs/decisions/adr-037-preprocessor.md)
|
|
681
|
-
| [ADR-043](docs/decisions/adr-043-comments.md)
|
|
682
|
-
| [ADR-044](docs/decisions/adr-044-primitive-types.md)
|
|
683
|
-
| [ADR-024](docs/decisions/adr-024-type-casting.md)
|
|
684
|
-
| [ADR-022](docs/decisions/adr-022-conditional-expressions.md)
|
|
685
|
-
| [ADR-025](docs/decisions/adr-025-switch-statements.md)
|
|
686
|
-
| [ADR-029](docs/decisions/adr-029-function-pointers.md)
|
|
687
|
-
| [ADR-045](docs/decisions/adr-045-string-type.md)
|
|
688
|
-
| [ADR-023](docs/decisions/adr-023-sizeof.md)
|
|
689
|
-
| [ADR-027](docs/decisions/adr-027-do-while.md)
|
|
690
|
-
| [ADR-032](docs/decisions/adr-032-nested-structs.md)
|
|
691
|
-
| [ADR-035](docs/decisions/adr-035-array-initializers.md)
|
|
692
|
-
| [ADR-036](docs/decisions/adr-036-multidimensional-arrays.md)
|
|
693
|
-
| [ADR-040](docs/decisions/adr-040-isr-declaration.md)
|
|
694
|
-
| [ADR-034](docs/decisions/adr-034-bit-fields.md)
|
|
695
|
-
| [ADR-048](docs/decisions/adr-048-cli-executable.md)
|
|
696
|
-
| [ADR-049](docs/decisions/adr-049-atomic-types.md)
|
|
697
|
-
| [ADR-050](docs/decisions/adr-050-critical-sections.md)
|
|
698
|
-
| [ADR-108](docs/decisions/adr-108-volatile-keyword.md)
|
|
699
|
-
| [ADR-047](docs/decisions/adr-047-nullable-types.md)
|
|
664
|
+
| ADR | Title | Description |
|
|
665
|
+
| -------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------ |
|
|
666
|
+
| [ADR-001](docs/decisions/adr-001-assignment-operator.md) | Assignment Operator | `<-` for assignment, `=` for comparison |
|
|
667
|
+
| [ADR-003](docs/decisions/adr-003-static-allocation.md) | Static Allocation | No dynamic memory after init |
|
|
668
|
+
| [ADR-004](docs/decisions/adr-004-register-bindings.md) | Register Bindings | Type-safe hardware access |
|
|
669
|
+
| [ADR-006](docs/decisions/adr-006-simplified-references.md) | Simplified References | Pass by reference, no pointer syntax |
|
|
670
|
+
| [ADR-007](docs/decisions/adr-007-type-aware-bit-indexing.md) | Type-Aware Bit Indexing | Integers as bit arrays, `.length` property |
|
|
671
|
+
| [ADR-010](docs/decisions/adr-010-c-interoperability.md) | C Interoperability | Unified ANTLR parser architecture |
|
|
672
|
+
| [ADR-011](docs/decisions/adr-011-vscode-extension.md) | VS Code Extension | Live C preview with syntax highlighting |
|
|
673
|
+
| [ADR-012](docs/decisions/adr-012-static-analysis.md) | Static Analysis | cppcheck integration for generated C |
|
|
674
|
+
| [ADR-013](docs/decisions/adr-013-const-qualifier.md) | Const Qualifier | Compile-time const enforcement |
|
|
675
|
+
| [ADR-014](docs/decisions/adr-014-structs.md) | Structs | Data containers without methods |
|
|
676
|
+
| [ADR-015](docs/decisions/adr-015-null-state.md) | Null State | Zero initialization for all variables |
|
|
677
|
+
| [ADR-016](docs/decisions/adr-016-scope.md) | Scope | `this.`/`global.` explicit qualification |
|
|
678
|
+
| [ADR-017](docs/decisions/adr-017-enums.md) | Enums | Type-safe enums with C-style casting |
|
|
679
|
+
| [ADR-030](docs/decisions/adr-030-forward-declarations.md) | Define-Before-Use | Functions must be defined before called |
|
|
680
|
+
| [ADR-037](docs/decisions/adr-037-preprocessor.md) | Preprocessor | Flag-only defines, const for values |
|
|
681
|
+
| [ADR-043](docs/decisions/adr-043-comments.md) | Comments | Comment preservation with MISRA compliance |
|
|
682
|
+
| [ADR-044](docs/decisions/adr-044-primitive-types.md) | Primitive Types | Fixed-width types with `clamp`/`wrap` overflow |
|
|
683
|
+
| [ADR-024](docs/decisions/adr-024-type-casting.md) | Type Casting | Widening implicit, narrowing uses bit indexing |
|
|
684
|
+
| [ADR-022](docs/decisions/adr-022-conditional-expressions.md) | Conditional Expressions | Ternary with required parens, boolean condition, no nesting |
|
|
685
|
+
| [ADR-025](docs/decisions/adr-025-switch-statements.md) | Switch Statements | Safe switch with braces, `\|\|` syntax, counted `default(n)` |
|
|
686
|
+
| [ADR-029](docs/decisions/adr-029-function-pointers.md) | Callbacks | Function-as-Type pattern with nominal typing |
|
|
687
|
+
| [ADR-045](docs/decisions/adr-045-string-type.md) | Bounded Strings | `string<N>` with compile-time safety |
|
|
688
|
+
| [ADR-023](docs/decisions/adr-023-sizeof.md) | Sizeof | Type/value size queries with safety checks |
|
|
689
|
+
| [ADR-027](docs/decisions/adr-027-do-while.md) | Do-While | `do { } while ()` with boolean condition (E0701) |
|
|
690
|
+
| [ADR-032](docs/decisions/adr-032-nested-structs.md) | Nested Structs | Named nested structs only (no anonymous) |
|
|
691
|
+
| [ADR-035](docs/decisions/adr-035-array-initializers.md) | Array Initializers | `[1, 2, 3]` syntax with `[0*]` fill-all |
|
|
692
|
+
| [ADR-036](docs/decisions/adr-036-multidimensional-arrays.md) | Multi-dim Arrays | `arr[i][j]` with compile-time bounds enforcement |
|
|
693
|
+
| [ADR-040](docs/decisions/adr-040-isr-declaration.md) | ISR Type | Built-in `ISR` type for `void(void)` function pointers |
|
|
694
|
+
| [ADR-034](docs/decisions/adr-034-bit-fields.md) | Bitmap Types | `bitmap8`/`bitmap16`/`bitmap32` for portable bit-packed data |
|
|
695
|
+
| [ADR-048](docs/decisions/adr-048-cli-executable.md) | CLI Executable | `cnext` command with smart defaults |
|
|
696
|
+
| [ADR-049](docs/decisions/adr-049-atomic-types.md) | Atomic Types | `atomic` keyword with LDREX/STREX or PRIMASK fallback |
|
|
697
|
+
| [ADR-050](docs/decisions/adr-050-critical-sections.md) | Critical Sections | `critical { }` blocks with PRIMASK save/restore |
|
|
698
|
+
| [ADR-108](docs/decisions/adr-108-volatile-keyword.md) | Volatile Variables | `volatile` keyword prevents compiler optimization |
|
|
699
|
+
| [ADR-047](docs/decisions/adr-047-nullable-types.md) | NULL for C Interop | `NULL` keyword for C stream function comparisons |
|
|
700
|
+
| [ADR-052](docs/decisions/adr-052-safe-numeric-literal-generation.md) | Safe Numeric Literals | `type_MIN`/`type_MAX` constants + safe hex conversion |
|
|
700
701
|
|
|
701
702
|
### Research (v1 Roadmap)
|
|
702
703
|
|
package/grammar/CNext.g4
CHANGED
|
@@ -345,8 +345,8 @@ switchCase
|
|
|
345
345
|
caseLabel
|
|
346
346
|
: qualifiedType // Enum value: EState.IDLE
|
|
347
347
|
| IDENTIFIER // Const or enum member
|
|
348
|
-
| INTEGER_LITERAL
|
|
349
|
-
| HEX_LITERAL
|
|
348
|
+
| '-'? INTEGER_LITERAL // Allow negative integers
|
|
349
|
+
| '-'? HEX_LITERAL // Allow negative hex (e.g., -0x80)
|
|
350
350
|
| BINARY_LITERAL
|
|
351
351
|
| CHAR_LITERAL
|
|
352
352
|
;
|
|
@@ -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",
|