c-next 0.2.10 → 0.2.11

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
@@ -10,7 +10,7 @@ import { hideBin } from "yargs/helpers";
10
10
  // package.json
11
11
  var package_default = {
12
12
  name: "c-next",
13
- version: "0.2.10",
13
+ version: "0.2.11",
14
14
  description: "A safer C for embedded systems development. Transpiles to clean, readable C.",
15
15
  packageManager: "npm@11.9.0",
16
16
  type: "module",
@@ -109971,6 +109971,14 @@ var SymbolTable = class {
109971
109971
  * These are "opaque" types that can only be used as pointers.
109972
109972
  */
109973
109973
  opaqueTypes = /* @__PURE__ */ new Set();
109974
+ /**
109975
+ * Issue #958: Track typedef struct type names with their source files.
109976
+ * Maps typeName -> sourceFile. Used for scope variables which should be pointers
109977
+ * when the struct definition comes from a different file than the typedef.
109978
+ * If definition is in the same file as typedef, the entry is removed (value type).
109979
+ * If definition is in a different file, the entry remains (pointer type).
109980
+ */
109981
+ typedefStructTypes = /* @__PURE__ */ new Map();
109974
109982
  /**
109975
109983
  * Issue #948: Track struct tag -> typedef name relationships.
109976
109984
  * When a typedef declares an alias for a struct tag (e.g., typedef struct _foo foo_t),
@@ -110666,6 +110674,56 @@ Rename the C-Next symbol to resolve.`
110666
110674
  return this.structTagAliases.get(structTag);
110667
110675
  }
110668
110676
  // ========================================================================
110677
+ // Issue #958: Typedef Struct Type Tracking
110678
+ // ========================================================================
110679
+ /**
110680
+ * Issue #958: Mark a typedef as aliasing a struct type.
110681
+ * Records the source file to enable same-file vs cross-file distinction.
110682
+ * @param typedefName The typedef name (e.g., "widget_t")
110683
+ * @param sourceFile The file where the typedef was declared
110684
+ */
110685
+ markTypedefStructType(typedefName, sourceFile) {
110686
+ this.typedefStructTypes.set(typedefName, sourceFile);
110687
+ }
110688
+ /**
110689
+ * Issue #958: Unmark a typedef struct type when full definition is found.
110690
+ * Only unmarks if the definition is in the SAME file as the typedef declaration.
110691
+ * Cross-file definitions keep the typedef marked (pointer semantics).
110692
+ * @param typeName The typedef name to unmark
110693
+ * @param sourceFile The file where the definition was found
110694
+ */
110695
+ unmarkTypedefStructType(typeName, sourceFile) {
110696
+ const typedefFile = this.typedefStructTypes.get(typeName);
110697
+ if (typedefFile === sourceFile) {
110698
+ this.typedefStructTypes.delete(typeName);
110699
+ }
110700
+ }
110701
+ /**
110702
+ * Issue #958: Check if a typedef aliases a struct type.
110703
+ * Used for scope variables which should be pointers for external struct types.
110704
+ * @param typeName The type name to check
110705
+ * @returns true if this is a typedef'd struct type from C headers
110706
+ */
110707
+ isTypedefStructType(typeName) {
110708
+ return this.typedefStructTypes.has(typeName);
110709
+ }
110710
+ /**
110711
+ * Issue #958: Get all typedef struct types for cache serialization.
110712
+ * @returns Map entries as [typeName, sourceFile] pairs
110713
+ */
110714
+ getAllTypedefStructTypes() {
110715
+ return Array.from(this.typedefStructTypes.entries());
110716
+ }
110717
+ /**
110718
+ * Issue #958: Restore typedef struct types from cache.
110719
+ * @param entries Array of [typeName, sourceFile] pairs
110720
+ */
110721
+ restoreTypedefStructTypes(entries) {
110722
+ for (const [name, sourceFile] of entries) {
110723
+ this.typedefStructTypes.set(name, sourceFile);
110724
+ }
110725
+ }
110726
+ // ========================================================================
110669
110727
  // Enum Bit Width Tracking
110670
110728
  // ========================================================================
110671
110729
  /**
@@ -110785,6 +110843,7 @@ Rename the C-Next symbol to resolve.`
110785
110843
  this.opaqueTypes.clear();
110786
110844
  this.structTagAliases.clear();
110787
110845
  this.enumBitWidth.clear();
110846
+ this.typedefStructTypes.clear();
110788
110847
  }
110789
110848
  };
110790
110849
  var SymbolTable_default = SymbolTable;
@@ -111136,6 +111195,14 @@ var CodeGenState = class {
111136
111195
  static isOpaqueType(typeName) {
111137
111196
  return this.symbols?.opaqueTypes.has(typeName) ?? false;
111138
111197
  }
111198
+ /**
111199
+ * Issue #958: Check if a type name is an external typedef struct type.
111200
+ * External typedef struct types should use pointer semantics for scope variables.
111201
+ * Unlike isOpaqueType, this returns true for both forward-declared and complete structs.
111202
+ */
111203
+ static isTypedefStructType(typeName) {
111204
+ return this.symbolTable?.isTypedefStructType(typeName) ?? false;
111205
+ }
111139
111206
  /**
111140
111207
  * Get type info for a variable.
111141
111208
  * Checks local typeRegistry first, then falls back to SymbolTable
@@ -118067,7 +118134,8 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
118067
118134
  let type = orchestrator.generateType(varDecl.type());
118068
118135
  const fullName = QualifiedNameGenerator_default.forMember(scopeName, varName);
118069
118136
  const isOpaque = orchestrator.isOpaqueType(type);
118070
- if (isOpaque) {
118137
+ const isExternalStruct = orchestrator.isTypedefStructType(type);
118138
+ if (isOpaque || isExternalStruct) {
118071
118139
  type = `${type}*`;
118072
118140
  orchestrator.markOpaqueScopeVariable(fullName);
118073
118141
  }
@@ -118082,7 +118150,7 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
118082
118150
  decl += orchestrator.generateArrayDimensions(arrayDims);
118083
118151
  }
118084
118152
  decl += ArrayDimensionUtils_default.generateStringCapacityDim(varDecl.type());
118085
- if (isOpaque) {
118153
+ if (isOpaque || isExternalStruct) {
118086
118154
  decl += " = NULL";
118087
118155
  } else {
118088
118156
  decl += generateInitializer(varDecl, isArray, orchestrator);
@@ -128797,6 +128865,14 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
128797
128865
  isOpaqueType(typeName) {
128798
128866
  return CodeGenState.isOpaqueType(typeName);
128799
128867
  }
128868
+ /**
128869
+ * Issue #958: Check if a type is an external typedef struct type.
128870
+ * Used for scope variables which should always be pointers for external struct types.
128871
+ * Part of IOrchestrator interface.
128872
+ */
128873
+ isTypedefStructType(typeName) {
128874
+ return CodeGenState.isTypedefStructType(typeName);
128875
+ }
128800
128876
  /**
128801
128877
  * Issue #948: Mark a scope variable as having an opaque type.
128802
128878
  * These variables are generated as pointers with NULL initialization.
@@ -133680,6 +133756,18 @@ var DeclaratorUtils = class _DeclaratorUtils {
133680
133756
  if (!firstDeclarator) return void 0;
133681
133757
  return _DeclaratorUtils.extractDeclaratorName(firstDeclarator) ?? void 0;
133682
133758
  }
133759
+ /**
133760
+ * Check if the first declarator in an init-declarator-list has a pointer.
133761
+ * For "typedef struct X *handle_t;", the declarator is "*handle_t" which has a pointer.
133762
+ * Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
133763
+ */
133764
+ static firstDeclaratorHasPointer(initDeclList) {
133765
+ const initDeclarators = initDeclList.initDeclarator?.();
133766
+ if (!initDeclarators || initDeclarators.length === 0) return false;
133767
+ const firstDeclarator = initDeclarators[0].declarator?.();
133768
+ if (!firstDeclarator) return false;
133769
+ return Boolean(firstDeclarator.pointer?.());
133770
+ }
133683
133771
  };
133684
133772
  var DeclaratorUtils_default = DeclaratorUtils;
133685
133773
 
@@ -133692,11 +133780,10 @@ var StructCollector2 = class _StructCollector {
133692
133780
  * @param sourceFile Source file path
133693
133781
  * @param line Source line number
133694
133782
  * @param symbolTable Optional symbol table for field tracking
133695
- * @param typedefName Optional typedef name for anonymous structs
133696
- * @param isTypedef Whether this is part of a typedef declaration
133697
- * @param warnings Array to collect warnings
133783
+ * @param options Optional collection options (typedef info, warnings)
133698
133784
  */
133699
- static collect(structSpec, sourceFile, line, symbolTable, typedefName, isTypedef, warnings) {
133785
+ static collect(structSpec, sourceFile, line, symbolTable, options = {}) {
133786
+ const { typedefName, isTypedef, warnings, isPointerTypedef } = options;
133700
133787
  const identifier = structSpec.Identifier();
133701
133788
  const name = identifier?.getText() || typedefName;
133702
133789
  if (!name) return null;
@@ -133710,15 +133797,14 @@ var StructCollector2 = class _StructCollector {
133710
133797
  );
133711
133798
  const needsStructKeyword = Boolean(identifier && !isTypedef);
133712
133799
  if (symbolTable) {
133713
- _StructCollector.updateSymbolTable(
133714
- symbolTable,
133715
- name,
133800
+ _StructCollector.updateSymbolTable(symbolTable, name, sourceFile, {
133716
133801
  needsStructKeyword,
133717
133802
  hasBody,
133718
133803
  isTypedef,
133719
133804
  typedefName,
133720
- identifier?.getText()
133721
- );
133805
+ structTag: identifier?.getText(),
133806
+ isPointerTypedef
133807
+ });
133722
133808
  }
133723
133809
  return {
133724
133810
  kind: "struct",
@@ -133736,38 +133822,54 @@ var StructCollector2 = class _StructCollector {
133736
133822
  * Update symbol table with struct metadata.
133737
133823
  * Extracted to reduce cognitive complexity of collect().
133738
133824
  */
133739
- static updateSymbolTable(symbolTable, name, needsStructKeyword, hasBody, isTypedef, typedefName, structTag) {
133825
+ static updateSymbolTable(symbolTable, name, sourceFile, options) {
133826
+ const {
133827
+ needsStructKeyword,
133828
+ hasBody,
133829
+ isTypedef,
133830
+ typedefName,
133831
+ structTag,
133832
+ isPointerTypedef
133833
+ } = options;
133740
133834
  if (needsStructKeyword) {
133741
133835
  symbolTable.markNeedsStructKeyword(name);
133742
133836
  }
133743
- if (isTypedef && !hasBody && typedefName) {
133837
+ if (isTypedef && !hasBody && typedefName && !isPointerTypedef) {
133744
133838
  symbolTable.markOpaqueType(typedefName);
133745
133839
  if (structTag) {
133746
133840
  symbolTable.registerStructTagAlias(structTag, typedefName);
133747
133841
  }
133748
133842
  }
133843
+ if (isTypedef && typedefName && !isPointerTypedef) {
133844
+ symbolTable.markTypedefStructType(typedefName, sourceFile);
133845
+ }
133749
133846
  if (hasBody) {
133750
133847
  _StructCollector.unmarkOpaqueTypesOnDefinition(
133751
133848
  symbolTable,
133849
+ sourceFile,
133752
133850
  structTag,
133753
133851
  typedefName
133754
133852
  );
133755
133853
  }
133756
133854
  }
133757
133855
  /**
133758
- * Unmark opaque types when a full struct definition is encountered.
133856
+ * Unmark opaque and typedef struct types when a full struct definition is encountered.
133759
133857
  * Handles: typedef struct _foo foo; struct _foo { ... };
133858
+ * Issue #958: Only unmarks typedefStructTypes when definition is in SAME file.
133760
133859
  */
133761
- static unmarkOpaqueTypesOnDefinition(symbolTable, structTag, typedefName) {
133860
+ static unmarkOpaqueTypesOnDefinition(symbolTable, sourceFile, structTag, typedefName) {
133762
133861
  if (structTag) {
133763
- symbolTable.unmarkOpaqueType(structTag);
133764
133862
  const typedefAlias = symbolTable.getStructTagAlias(structTag);
133863
+ symbolTable.unmarkOpaqueType(structTag);
133864
+ symbolTable.unmarkTypedefStructType(structTag, sourceFile);
133765
133865
  if (typedefAlias) {
133766
133866
  symbolTable.unmarkOpaqueType(typedefAlias);
133867
+ symbolTable.unmarkTypedefStructType(typedefAlias, sourceFile);
133767
133868
  }
133768
133869
  }
133769
133870
  if (typedefName) {
133770
133871
  symbolTable.unmarkOpaqueType(typedefName);
133872
+ symbolTable.unmarkTypedefStructType(typedefName, sourceFile);
133771
133873
  }
133772
133874
  }
133773
133875
  /**
@@ -134154,14 +134256,18 @@ var CResolver = class _CResolver {
134154
134256
  */
134155
134257
  static collectStructSymbol(structSpec, decl, declSpecs, ctx, symbolTable, warnings) {
134156
134258
  const typedefName = ctx.isTypedef ? _CResolver.extractTypedefName(decl, declSpecs) : void 0;
134259
+ const isPointerTypedef = ctx.isTypedef ? _CResolver.isPointerTypedef(decl) : false;
134157
134260
  const structSymbol = StructCollector_default2.collect(
134158
134261
  structSpec,
134159
134262
  ctx.sourceFile,
134160
134263
  ctx.line,
134161
134264
  symbolTable,
134162
- typedefName,
134163
- ctx.isTypedef,
134164
- warnings
134265
+ {
134266
+ typedefName,
134267
+ isTypedef: ctx.isTypedef,
134268
+ warnings,
134269
+ isPointerTypedef
134270
+ }
134165
134271
  );
134166
134272
  if (structSymbol) {
134167
134273
  ctx.symbols.push(structSymbol);
@@ -134179,6 +134285,16 @@ var CResolver = class _CResolver {
134179
134285
  }
134180
134286
  return DeclaratorUtils_default.extractTypedefNameFromSpecs(declSpecs);
134181
134287
  }
134288
+ /**
134289
+ * Check if a typedef declaration has a pointer declarator.
134290
+ * For "typedef struct X *Y", the declarator is "*Y" which has a pointer.
134291
+ * Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
134292
+ */
134293
+ static isPointerTypedef(decl) {
134294
+ const initDeclList = decl.initDeclaratorList();
134295
+ if (!initDeclList) return false;
134296
+ return DeclaratorUtils_default.firstDeclaratorHasPointer(initDeclList);
134297
+ }
134182
134298
  /**
134183
134299
  * Collect enum symbols from an enum specifier.
134184
134300
  * Extracted to reduce cognitive complexity of collectDeclaration().
@@ -138880,7 +138996,7 @@ var CacheKeyGenerator_default = CacheKeyGenerator;
138880
138996
 
138881
138997
  // src/utils/cache/CacheManager.ts
138882
138998
  var defaultFs7 = NodeFileSystem_default.instance;
138883
- var CACHE_VERSION = 5;
138999
+ var CACHE_VERSION = 6;
138884
139000
  var TRANSPILER_VERSION = package_default.version;
138885
139001
  var CacheManager = class {
138886
139002
  projectRoot;
@@ -138981,14 +139097,15 @@ var CacheManager = class {
138981
139097
  structFields,
138982
139098
  needsStructKeyword: cachedEntry.needsStructKeyword ?? [],
138983
139099
  enumBitWidth,
138984
- opaqueTypes: cachedEntry.opaqueTypes ?? []
139100
+ opaqueTypes: cachedEntry.opaqueTypes ?? [],
139101
+ typedefStructTypes: cachedEntry.typedefStructTypes ?? []
138985
139102
  };
138986
139103
  }
138987
139104
  /**
138988
139105
  * Store symbols and struct fields for a file
138989
139106
  * ADR-055 Phase 7: Takes ISerializedSymbol[] directly
138990
139107
  */
138991
- setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth, opaqueTypes) {
139108
+ setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth, opaqueTypes, typedefStructTypes) {
138992
139109
  if (!this.cache) return;
138993
139110
  let cacheKey;
138994
139111
  try {
@@ -139017,7 +139134,8 @@ var CacheManager = class {
139017
139134
  structFields: serializedFields,
139018
139135
  needsStructKeyword,
139019
139136
  enumBitWidth: serializedEnumBitWidth,
139020
- opaqueTypes
139137
+ opaqueTypes,
139138
+ typedefStructTypes
139021
139139
  };
139022
139140
  this.cache.setKey(filePath, entry);
139023
139141
  this.dirty = true;
@@ -139046,13 +139164,15 @@ var CacheManager = class {
139046
139164
  symbolTable
139047
139165
  );
139048
139166
  const opaqueTypes = symbolTable.getAllOpaqueTypes();
139167
+ const typedefStructTypes = symbolTable.getAllTypedefStructTypes();
139049
139168
  this.setSymbols(
139050
139169
  filePath,
139051
139170
  symbols,
139052
139171
  structFields,
139053
139172
  needsStructKeyword,
139054
139173
  enumBitWidth,
139055
- opaqueTypes
139174
+ opaqueTypes,
139175
+ typedefStructTypes
139056
139176
  );
139057
139177
  }
139058
139178
  /**
@@ -140109,6 +140229,9 @@ var Transpiler = class {
140109
140229
  );
140110
140230
  CodeGenState.symbolTable.restoreEnumBitWidths(cached.enumBitWidth);
140111
140231
  CodeGenState.symbolTable.restoreOpaqueTypes(cached.opaqueTypes);
140232
+ CodeGenState.symbolTable.restoreTypedefStructTypes(
140233
+ cached.typedefStructTypes
140234
+ );
140112
140235
  this.detectCppFromFileType(file);
140113
140236
  return true;
140114
140237
  }