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 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
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.4",
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",