c-next 0.2.13 → 0.2.14

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/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { hideBin } from "yargs/helpers";
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "c-next",
14
- version: "0.2.13",
14
+ version: "0.2.14",
15
15
  description: "A safer C for embedded systems development. Transpiles to clean, readable C.",
16
16
  packageManager: "npm@11.9.0",
17
17
  type: "module",
@@ -195,10 +195,8 @@ var ConfigPrinter_default = ConfigPrinter;
195
195
  function configureYargs(args, argv) {
196
196
  return yargs(args).scriptName("cnext").usage(
197
197
  `Usage:
198
- cnext <file.cnx> Single file (outputs file.c)
198
+ cnext <file.cnx> Entry point file (follows includes)
199
199
  cnext <file.cnx> -o <output.c> Single file with explicit output
200
- cnext <files...> -o <dir> Multi-file mode
201
- cnext <dir> Directory mode (recursive)
202
200
 
203
201
  A safer C for embedded systems development.`
204
202
  ).option("o", {
@@ -275,10 +273,8 @@ A safer C for embedded systems development.`
275
273
  default: false
276
274
  }).epilogue(
277
275
  `Examples:
278
- cnext main.cnx # Outputs main.c (same dir)
276
+ cnext src/main.cnx # Entry point (follows includes)
279
277
  cnext main.cnx -o build/main.c # Explicit output path
280
- cnext src/*.cnx -o build/ # Multiple files to directory
281
- cnext src/ # Compile all .cnx files in src/ (recursive)
282
278
 
283
279
  Target platforms: teensy41, cortex-m7, cortex-m4, cortex-m3, cortex-m0+, cortex-m0, avr
284
280
 
@@ -415,37 +411,36 @@ var PlatformIOCommand = class {
415
411
  */
416
412
  static install() {
417
413
  const { pioIniPath, scriptPath } = getPioProjectPaths();
418
- const buildScript = `Import("env")
414
+ const buildScript = String.raw`Import("env")
419
415
  import subprocess
420
416
  import sys
421
417
  from pathlib import Path
422
418
 
423
419
  def transpile_cnext():
424
- """Transpile all .cnx files before build"""
425
- # Find all .cnx files in src directory
426
- src_dir = Path("src")
427
- if not src_dir.exists():
420
+ """Transpile from main.cnx entry point — cnext follows includes"""
421
+ entry = Path("src/main.cnx")
422
+ if not entry.exists():
428
423
  return
429
424
 
430
- cnx_files = list(src_dir.rglob("*.cnx"))
431
- if not cnx_files:
432
- return
433
-
434
- print(f"Transpiling {len(cnx_files)} c-next files...")
425
+ print("Transpiling from main.cnx...")
435
426
 
436
- for cnx_file in cnx_files:
437
- try:
438
- result = subprocess.run(
439
- ["cnext", str(cnx_file)],
440
- check=True,
441
- capture_output=True,
442
- text=True
443
- )
444
- print(f" \u2713 {cnx_file.name}")
445
- except subprocess.CalledProcessError as e:
446
- print(f" \u2717 Error: {cnx_file.name}")
447
- print(e.stderr)
448
- sys.exit(1)
427
+ try:
428
+ result = subprocess.run(
429
+ ["cnext", str(entry)],
430
+ check=True,
431
+ capture_output=True,
432
+ text=True
433
+ )
434
+ if result.stdout:
435
+ lines = result.stdout.strip().split("\n")
436
+ for line in lines:
437
+ if line.startswith(("Compiled", "Collected", "Generated")):
438
+ print(f" {line}")
439
+ print(" ✓ Transpilation complete")
440
+ except subprocess.CalledProcessError as e:
441
+ print(f" ✗ Transpilation failed")
442
+ print(e.stderr)
443
+ sys.exit(1)
449
444
 
450
445
  # Run transpilation at import time (before compilation starts)
451
446
  transpile_cnext()
@@ -475,13 +470,12 @@ transpile_cnext()
475
470
  console.log("\u2713 PlatformIO integration configured!");
476
471
  console.log("");
477
472
  console.log("Next steps:");
478
- console.log(
479
- " 1. Create .cnx files in src/ (alongside your .c/.cpp files)"
480
- );
481
- console.log(" 2. Run: pio run");
473
+ console.log(" 1. Create src/main.cnx as your entry point");
474
+ console.log(" 2. Use #include to pull in other .cnx files");
475
+ console.log(" 3. Run: pio run");
482
476
  console.log("");
483
477
  console.log(
484
- "The transpiler will automatically convert .cnx \u2192 .c before each build."
478
+ "The transpiler will follow includes from main.cnx automatically."
485
479
  );
486
480
  console.log("Commit both .cnx and generated .c files to version control.");
487
481
  }
@@ -133386,16 +133380,23 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
133386
133380
  }
133387
133381
  }
133388
133382
  const userIncludeSet = new Set(options.userIncludes ?? []);
133389
- if (options.cppMode && options.userIncludes) {
133390
- for (const inc of options.userIncludes) {
133391
- const hVersion = inc.replace(/\.hpp"/, '.h"').replace(/\.hpp>/, ".h>");
133392
- userIncludeSet.add(hVersion);
133393
- }
133394
- }
133383
+ const extractStem = (inc) => {
133384
+ const match = /["<]([^">]+)[">]/.exec(inc);
133385
+ if (!match) return inc;
133386
+ return match[1].replace(/^.*\//, "").replace(/\.(?:h|hpp)$/, "");
133387
+ };
133388
+ const userIncludeStems = new Set(
133389
+ (options.userIncludes ?? []).map(extractStem)
133390
+ );
133395
133391
  for (const directive of headersToInclude) {
133396
- if (!userIncludeSet.has(directive)) {
133397
- lines.push(directive);
133392
+ if (userIncludeSet.has(directive)) {
133393
+ continue;
133394
+ }
133395
+ const stem = extractStem(directive);
133396
+ if (stem && userIncludeStems.has(stem)) {
133397
+ continue;
133398
133398
  }
133399
+ lines.push(directive);
133399
133400
  }
133400
133401
  const hasIncludes = options.includeSystemHeaders !== false || options.userIncludes && options.userIncludes.length > 0 || headersToInclude.size > 0;
133401
133402
  if (hasIncludes) {
@@ -137760,9 +137761,16 @@ var DependencyGraph_default = DependencyGraph;
137760
137761
  // src/transpiler/data/IncludeResolver.ts
137761
137762
  var defaultFs5 = NodeFileSystem_default.instance;
137762
137763
  var IncludeResolver = class _IncludeResolver {
137763
- constructor(searchPaths, fs = defaultFs5) {
137764
+ /**
137765
+ * @param cppMode Controls .h vs .hpp extension for .cnx include directives.
137766
+ * Note: In the Transpiler, cppDetected may change after IncludeResolver runs
137767
+ * (e.g., when a .hpp header is discovered during Stage 2). HeaderGeneratorUtils
137768
+ * uses stem-based dedup to handle any resulting .h/.hpp mismatch.
137769
+ */
137770
+ constructor(searchPaths, fs = defaultFs5, cppMode = false) {
137764
137771
  this.searchPaths = searchPaths;
137765
137772
  this.fs = fs;
137773
+ this.cppMode = cppMode;
137766
137774
  }
137767
137775
  /**
137768
137776
  * Type helper for accessing IResolvedIncludes externally.
@@ -137771,6 +137779,7 @@ var IncludeResolver = class _IncludeResolver {
137771
137779
  static _resolvedIncludesType = void 0;
137772
137780
  resolvedPaths = /* @__PURE__ */ new Set();
137773
137781
  fs;
137782
+ cppMode;
137774
137783
  /**
137775
137784
  * Extract includes from source content and resolve them to files
137776
137785
  *
@@ -137835,7 +137844,8 @@ var IncludeResolver = class _IncludeResolver {
137835
137844
  }
137836
137845
  if (file.type === EFileType_default.CNext) {
137837
137846
  result.cnextIncludes.push(file);
137838
- const headerPath = includeInfo.path.replace(/\.cnx$|\.cnext$/, ".h");
137847
+ const ext = this.cppMode ? ".hpp" : ".h";
137848
+ const headerPath = includeInfo.path.replace(/\.cnx$|\.cnext$/, ext);
137839
137849
  const directive = includeInfo.isLocal ? `#include "${headerPath}"` : `#include <${headerPath}>`;
137840
137850
  result.headerIncludeDirectives.set(absolutePath, directive);
137841
137851
  }
@@ -141708,7 +141718,11 @@ var Transpiler = class {
141708
141718
  void 0,
141709
141719
  this.fs
141710
141720
  );
141711
- const resolver = new IncludeResolver_default(searchPaths, this.fs);
141721
+ const resolver = new IncludeResolver_default(
141722
+ searchPaths,
141723
+ this.fs,
141724
+ this.cppDetected
141725
+ );
141712
141726
  const resolved = resolver.resolve(source, sourcePath);
141713
141727
  this.warnings.push(...resolved.warnings);
141714
141728
  const { headers: allHeaders, warnings: headerWarnings } = IncludeResolver_default.resolveHeadersTransitively(
@@ -141980,7 +141994,11 @@ var Transpiler = class {
141980
141994
  void 0,
141981
141995
  this.fs
141982
141996
  );
141983
- const resolver = new IncludeResolver_default(searchPaths, this.fs);
141997
+ const resolver = new IncludeResolver_default(
141998
+ searchPaths,
141999
+ this.fs,
142000
+ this.cppDetected
142001
+ );
141984
142002
  const resolved = resolver.resolve(content, cnxFile.path);
141985
142003
  this._collectHeaders(resolved, cnextBaseNames, headerSet);
141986
142004
  this._processCnextIncludes(