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 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 src/
191
- cnext --project src
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 | 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 |
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",
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 included headers
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",