c-next 0.2.9 → 0.2.10
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 +814 -206
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +97 -7
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +170 -0
- package/src/transpiler/__tests__/needsConditionalPreprocessing.test.ts +246 -0
- package/src/transpiler/logic/analysis/ArrayIndexTypeAnalyzer.ts +12 -1
- package/src/transpiler/logic/analysis/__tests__/ArrayIndexTypeAnalyzer.test.ts +172 -0
- package/src/transpiler/logic/symbols/SymbolTable.ts +84 -0
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +43 -0
- package/src/transpiler/logic/symbols/__tests__/TransitiveEnumCollector.test.ts +1 -0
- package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +98 -1
- package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +23 -5
- package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +69 -2
- package/src/transpiler/logic/symbols/c/index.ts +85 -30
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +18 -0
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolInfoAdapter.test.ts +90 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolInfoAdapter.ts +40 -39
- package/src/transpiler/output/codegen/CodeGenerator.ts +23 -1
- package/src/transpiler/output/codegen/TypeResolver.ts +14 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +19 -14
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +7 -7
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +1 -0
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +27 -4
- package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +6 -0
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +73 -0
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +4 -0
- package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +92 -0
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +5 -2
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +1 -0
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +14 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +17 -2
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +49 -0
- package/src/transpiler/output/codegen/generators/expressions/AccessExprGenerator.ts +17 -5
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +5 -0
- package/src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts +16 -0
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +41 -5
- package/src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts +25 -1
- package/src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts +2 -17
- package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +3 -0
- package/src/transpiler/output/codegen/helpers/BitRangeHelper.ts +19 -3
- package/src/transpiler/output/codegen/helpers/NarrowingCastHelper.ts +191 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +35 -4
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +131 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/BitRangeHelper.test.ts +53 -2
- package/src/transpiler/output/codegen/helpers/__tests__/FunctionContextManager.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/NarrowingCastHelper.test.ts +159 -0
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +1 -0
- package/src/transpiler/output/codegen/types/COMPOUND_TO_BINARY.ts +21 -0
- package/src/transpiler/output/codegen/types/IArrayAccessInfo.ts +2 -0
- package/src/transpiler/state/CodeGenState.ts +49 -0
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +53 -0
- package/src/transpiler/state/__tests__/TranspilerState.test.ts +1 -0
- package/src/transpiler/types/ICachedFileEntry.ts +2 -0
- package/src/transpiler/types/ICodeGenSymbols.ts +8 -0
- package/src/utils/BitUtils.ts +33 -4
- package/src/utils/cache/CacheManager.ts +9 -1
- package/src/utils/cache/__tests__/CacheManager.test.ts +1 -1
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.
|
|
13
|
+
version: "0.2.10",
|
|
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",
|
|
@@ -109966,6 +109966,18 @@ var SymbolTable = class {
|
|
|
109966
109966
|
* In C, they must be referred to as 'struct Name', not just 'Name'
|
|
109967
109967
|
*/
|
|
109968
109968
|
needsStructKeyword = /* @__PURE__ */ new Set();
|
|
109969
|
+
/**
|
|
109970
|
+
* Issue #948: Track typedef names that alias incomplete (forward-declared) struct types.
|
|
109971
|
+
* These are "opaque" types that can only be used as pointers.
|
|
109972
|
+
*/
|
|
109973
|
+
opaqueTypes = /* @__PURE__ */ new Set();
|
|
109974
|
+
/**
|
|
109975
|
+
* Issue #948: Track struct tag -> typedef name relationships.
|
|
109976
|
+
* When a typedef declares an alias for a struct tag (e.g., typedef struct _foo foo_t),
|
|
109977
|
+
* we record structTagAliases["_foo"] = "foo_t". This allows us to unmark the typedef
|
|
109978
|
+
* as opaque when the full struct definition is later found.
|
|
109979
|
+
*/
|
|
109980
|
+
structTagAliases = /* @__PURE__ */ new Map();
|
|
109969
109981
|
/**
|
|
109970
109982
|
* Issue #208: Track enum backing type bit widths
|
|
109971
109983
|
* C++14 typed enums: enum Name : uint8_t { ... } have explicit bit widths
|
|
@@ -110594,6 +110606,66 @@ Rename the C-Next symbol to resolve.`
|
|
|
110594
110606
|
}
|
|
110595
110607
|
}
|
|
110596
110608
|
// ========================================================================
|
|
110609
|
+
// Opaque Type Tracking (Issue #948)
|
|
110610
|
+
// ========================================================================
|
|
110611
|
+
/**
|
|
110612
|
+
* Issue #948: Mark a typedef as aliasing an opaque (forward-declared) struct type.
|
|
110613
|
+
* @param typeName Typedef name (e.g., "widget_t")
|
|
110614
|
+
*/
|
|
110615
|
+
markOpaqueType(typeName) {
|
|
110616
|
+
this.opaqueTypes.add(typeName);
|
|
110617
|
+
}
|
|
110618
|
+
/**
|
|
110619
|
+
* Issue #948: Unmark a typedef when full struct definition is found.
|
|
110620
|
+
* Handles edge case: typedef before definition.
|
|
110621
|
+
* @param typeName Typedef name
|
|
110622
|
+
*/
|
|
110623
|
+
unmarkOpaqueType(typeName) {
|
|
110624
|
+
this.opaqueTypes.delete(typeName);
|
|
110625
|
+
}
|
|
110626
|
+
/**
|
|
110627
|
+
* Issue #948: Check if a typedef aliases an opaque struct type.
|
|
110628
|
+
* @param typeName Typedef name
|
|
110629
|
+
* @returns true if the type is opaque (forward-declared)
|
|
110630
|
+
*/
|
|
110631
|
+
isOpaqueType(typeName) {
|
|
110632
|
+
return this.opaqueTypes.has(typeName);
|
|
110633
|
+
}
|
|
110634
|
+
/**
|
|
110635
|
+
* Issue #948: Get all opaque type names for cache serialization.
|
|
110636
|
+
* @returns Array of opaque typedef names
|
|
110637
|
+
*/
|
|
110638
|
+
getAllOpaqueTypes() {
|
|
110639
|
+
return Array.from(this.opaqueTypes);
|
|
110640
|
+
}
|
|
110641
|
+
/**
|
|
110642
|
+
* Issue #948: Restore opaque types from cache.
|
|
110643
|
+
* @param typeNames Array of opaque typedef names
|
|
110644
|
+
*/
|
|
110645
|
+
restoreOpaqueTypes(typeNames) {
|
|
110646
|
+
for (const name of typeNames) {
|
|
110647
|
+
this.opaqueTypes.add(name);
|
|
110648
|
+
}
|
|
110649
|
+
}
|
|
110650
|
+
/**
|
|
110651
|
+
* Issue #948: Register a struct tag -> typedef name relationship.
|
|
110652
|
+
* Called when processing: typedef struct _foo foo_t;
|
|
110653
|
+
* This allows unmarking foo_t when struct _foo { ... } is later defined.
|
|
110654
|
+
* @param structTag The struct tag name (e.g., "_foo")
|
|
110655
|
+
* @param typedefName The typedef alias name (e.g., "foo_t")
|
|
110656
|
+
*/
|
|
110657
|
+
registerStructTagAlias(structTag, typedefName) {
|
|
110658
|
+
this.structTagAliases.set(structTag, typedefName);
|
|
110659
|
+
}
|
|
110660
|
+
/**
|
|
110661
|
+
* Issue #948: Get the typedef alias for a struct tag, if any.
|
|
110662
|
+
* @param structTag The struct tag name
|
|
110663
|
+
* @returns The typedef alias name, or undefined if none registered
|
|
110664
|
+
*/
|
|
110665
|
+
getStructTagAlias(structTag) {
|
|
110666
|
+
return this.structTagAliases.get(structTag);
|
|
110667
|
+
}
|
|
110668
|
+
// ========================================================================
|
|
110597
110669
|
// Enum Bit Width Tracking
|
|
110598
110670
|
// ========================================================================
|
|
110599
110671
|
/**
|
|
@@ -110710,6 +110782,8 @@ Rename the C-Next symbol to resolve.`
|
|
|
110710
110782
|
this.cppSymbolsByFile.clear();
|
|
110711
110783
|
this.structFields.clear();
|
|
110712
110784
|
this.needsStructKeyword.clear();
|
|
110785
|
+
this.opaqueTypes.clear();
|
|
110786
|
+
this.structTagAliases.clear();
|
|
110713
110787
|
this.enumBitWidth.clear();
|
|
110714
110788
|
}
|
|
110715
110789
|
};
|
|
@@ -110871,6 +110945,16 @@ var CodeGenState = class {
|
|
|
110871
110945
|
/** Issue #473: IRQ wrappers for critical sections */
|
|
110872
110946
|
static needsIrqWrappers = false;
|
|
110873
110947
|
// ===========================================================================
|
|
110948
|
+
// OPAQUE TYPE SCOPE VARIABLES (Issue #948)
|
|
110949
|
+
// ===========================================================================
|
|
110950
|
+
/**
|
|
110951
|
+
* Tracks scope variables with opaque (forward-declared) struct types.
|
|
110952
|
+
* These are generated as pointers with NULL initialization and should
|
|
110953
|
+
* be passed directly (not with &) since they're already pointers.
|
|
110954
|
+
* Maps qualified name (e.g., "MyScope_widget") to true.
|
|
110955
|
+
*/
|
|
110956
|
+
static opaqueScopeVariables = /* @__PURE__ */ new Set();
|
|
110957
|
+
// ===========================================================================
|
|
110874
110958
|
// C++ MODE STATE (Issue #250)
|
|
110875
110959
|
// ===========================================================================
|
|
110876
110960
|
/** Use temp vars instead of compound literals */
|
|
@@ -110954,6 +111038,7 @@ var CodeGenState = class {
|
|
|
110954
111038
|
this.tempVarCounter = 0;
|
|
110955
111039
|
this.pendingCppClassAssignments = [];
|
|
110956
111040
|
this.selfIncludeAdded = false;
|
|
111041
|
+
this.opaqueScopeVariables = /* @__PURE__ */ new Set();
|
|
110957
111042
|
this.sourcePath = null;
|
|
110958
111043
|
this.includeDirs = [];
|
|
110959
111044
|
this.inputs = [];
|
|
@@ -111043,6 +111128,14 @@ var CodeGenState = class {
|
|
|
111043
111128
|
static isKnownRegister(name) {
|
|
111044
111129
|
return this.symbols?.knownRegisters.has(name) ?? false;
|
|
111045
111130
|
}
|
|
111131
|
+
/**
|
|
111132
|
+
* Issue #948: Check if a type name is an opaque (forward-declared) struct type.
|
|
111133
|
+
* Opaque types are incomplete types that can only be used as pointers.
|
|
111134
|
+
* Example: `typedef struct _widget_t widget_t;` without a body makes `widget_t` opaque.
|
|
111135
|
+
*/
|
|
111136
|
+
static isOpaqueType(typeName) {
|
|
111137
|
+
return this.symbols?.opaqueTypes.has(typeName) ?? false;
|
|
111138
|
+
}
|
|
111046
111139
|
/**
|
|
111047
111140
|
* Get type info for a variable.
|
|
111048
111141
|
* Checks local typeRegistry first, then falls back to SymbolTable
|
|
@@ -111482,6 +111575,28 @@ var CodeGenState = class {
|
|
|
111482
111575
|
return this.floatShadowCurrent.has(name);
|
|
111483
111576
|
}
|
|
111484
111577
|
// ===========================================================================
|
|
111578
|
+
// OPAQUE SCOPE VARIABLE HELPERS (Issue #948)
|
|
111579
|
+
// ===========================================================================
|
|
111580
|
+
/**
|
|
111581
|
+
* Mark a scope variable as having an opaque (forward-declared) struct type.
|
|
111582
|
+
* These are generated as pointers with NULL initialization.
|
|
111583
|
+
*
|
|
111584
|
+
* @param qualifiedName - The fully qualified variable name (e.g., "MyScope_widget")
|
|
111585
|
+
*/
|
|
111586
|
+
static markOpaqueScopeVariable(qualifiedName) {
|
|
111587
|
+
this.opaqueScopeVariables.add(qualifiedName);
|
|
111588
|
+
}
|
|
111589
|
+
/**
|
|
111590
|
+
* Check if a scope variable has an opaque type (and is thus a pointer).
|
|
111591
|
+
* Used during access generation to determine if & prefix is needed.
|
|
111592
|
+
*
|
|
111593
|
+
* @param qualifiedName - The fully qualified variable name (e.g., "MyScope_widget")
|
|
111594
|
+
* @returns true if this is an opaque scope variable (already a pointer)
|
|
111595
|
+
*/
|
|
111596
|
+
static isOpaqueScopeVariable(qualifiedName) {
|
|
111597
|
+
return this.opaqueScopeVariables.has(qualifiedName);
|
|
111598
|
+
}
|
|
111599
|
+
// ===========================================================================
|
|
111485
111600
|
// C++ MODE HELPERS
|
|
111486
111601
|
// ===========================================================================
|
|
111487
111602
|
/**
|
|
@@ -113191,6 +113306,12 @@ var TypeResolver2 = class _TypeResolver {
|
|
|
113191
113306
|
if (floatMatch) {
|
|
113192
113307
|
return "f" + floatMatch[1];
|
|
113193
113308
|
}
|
|
113309
|
+
if (/^\d+$/.test(text) || /^0[xXbBoO][\da-fA-F]+$/.test(text)) {
|
|
113310
|
+
return "int";
|
|
113311
|
+
}
|
|
113312
|
+
if (/^\d*\.\d+([eE][+-]?\d+)?$/.test(text) || /^\d+[eE][+-]?\d+$/.test(text)) {
|
|
113313
|
+
return "f64";
|
|
113314
|
+
}
|
|
113194
113315
|
return null;
|
|
113195
113316
|
}
|
|
113196
113317
|
/**
|
|
@@ -114450,6 +114571,229 @@ var GeneratorRegistry = class {
|
|
|
114450
114571
|
}
|
|
114451
114572
|
};
|
|
114452
114573
|
|
|
114574
|
+
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114575
|
+
var CppModeHelper = class {
|
|
114576
|
+
/**
|
|
114577
|
+
* Get address-of expression for struct parameter passing.
|
|
114578
|
+
* C mode: `&expr` (pass pointer to struct)
|
|
114579
|
+
* C++ mode: `expr` (pass reference directly)
|
|
114580
|
+
*
|
|
114581
|
+
* @param expr - The expression to potentially wrap
|
|
114582
|
+
* @returns The expression with address-of operator in C mode
|
|
114583
|
+
*/
|
|
114584
|
+
static maybeAddressOf(expr) {
|
|
114585
|
+
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114586
|
+
}
|
|
114587
|
+
/**
|
|
114588
|
+
* Get dereference expression for struct parameter access.
|
|
114589
|
+
* C mode: `(*expr)` (dereference pointer)
|
|
114590
|
+
* C++ mode: `expr` (reference can be used directly)
|
|
114591
|
+
*
|
|
114592
|
+
* @param expr - The expression to potentially dereference
|
|
114593
|
+
* @returns The expression with dereference in C mode
|
|
114594
|
+
*/
|
|
114595
|
+
static maybeDereference(expr) {
|
|
114596
|
+
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114597
|
+
}
|
|
114598
|
+
/**
|
|
114599
|
+
* Get the type modifier for struct parameter declarations.
|
|
114600
|
+
* C mode: `*` (pointer type)
|
|
114601
|
+
* C++ mode: `&` (reference type)
|
|
114602
|
+
*
|
|
114603
|
+
* @returns The type modifier character
|
|
114604
|
+
*/
|
|
114605
|
+
static refOrPtr() {
|
|
114606
|
+
return CodeGenState.cppMode ? "&" : "*";
|
|
114607
|
+
}
|
|
114608
|
+
/**
|
|
114609
|
+
* Get the member access separator for struct parameters.
|
|
114610
|
+
* C mode: `->` (pointer member access)
|
|
114611
|
+
* C++ mode: `.` (reference member access)
|
|
114612
|
+
*
|
|
114613
|
+
* @returns The member access separator
|
|
114614
|
+
*/
|
|
114615
|
+
static memberSeparator() {
|
|
114616
|
+
return CodeGenState.cppMode ? "." : "->";
|
|
114617
|
+
}
|
|
114618
|
+
/**
|
|
114619
|
+
* Get NULL literal for the current mode.
|
|
114620
|
+
* C mode: `NULL`
|
|
114621
|
+
* C++ mode: `nullptr`
|
|
114622
|
+
*
|
|
114623
|
+
* @returns The null pointer literal
|
|
114624
|
+
*/
|
|
114625
|
+
static nullLiteral() {
|
|
114626
|
+
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114627
|
+
}
|
|
114628
|
+
/**
|
|
114629
|
+
* Generate a cast expression for the current mode.
|
|
114630
|
+
* C mode: `(type)expr`
|
|
114631
|
+
* C++ mode: `static_cast<type>(expr)`
|
|
114632
|
+
*
|
|
114633
|
+
* @param type - The target type
|
|
114634
|
+
* @param expr - The expression to cast
|
|
114635
|
+
* @returns The cast expression
|
|
114636
|
+
*/
|
|
114637
|
+
static cast(type, expr) {
|
|
114638
|
+
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114639
|
+
}
|
|
114640
|
+
/**
|
|
114641
|
+
* Generate a reinterpret cast expression for the current mode.
|
|
114642
|
+
* C mode: `(type)expr`
|
|
114643
|
+
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114644
|
+
*
|
|
114645
|
+
* @param type - The target type
|
|
114646
|
+
* @param expr - The expression to cast
|
|
114647
|
+
* @returns The cast expression
|
|
114648
|
+
*/
|
|
114649
|
+
static reinterpretCast(type, expr) {
|
|
114650
|
+
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114651
|
+
}
|
|
114652
|
+
/**
|
|
114653
|
+
* Check if we're in C++ mode.
|
|
114654
|
+
*
|
|
114655
|
+
* @returns True if generating C++ code
|
|
114656
|
+
*/
|
|
114657
|
+
static isCppMode() {
|
|
114658
|
+
return CodeGenState.cppMode;
|
|
114659
|
+
}
|
|
114660
|
+
};
|
|
114661
|
+
var CppModeHelper_default = CppModeHelper;
|
|
114662
|
+
|
|
114663
|
+
// src/transpiler/output/codegen/helpers/NarrowingCastHelper.ts
|
|
114664
|
+
var EXTENDED_TYPE_WIDTH = {
|
|
114665
|
+
...TYPE_WIDTH_default,
|
|
114666
|
+
int: 32
|
|
114667
|
+
// C's int after promotion
|
|
114668
|
+
};
|
|
114669
|
+
var PROMOTED_TO_INT = /* @__PURE__ */ new Set(["u8", "i8", "u16", "i16", "bool"]);
|
|
114670
|
+
var FLOAT_TYPES2 = /* @__PURE__ */ new Set(["f32", "f64", "float", "double"]);
|
|
114671
|
+
var INTEGER_TYPES2 = /* @__PURE__ */ new Set([
|
|
114672
|
+
"u8",
|
|
114673
|
+
"u16",
|
|
114674
|
+
"u32",
|
|
114675
|
+
"u64",
|
|
114676
|
+
"i8",
|
|
114677
|
+
"i16",
|
|
114678
|
+
"i32",
|
|
114679
|
+
"i64",
|
|
114680
|
+
"uint8_t",
|
|
114681
|
+
"uint16_t",
|
|
114682
|
+
"uint32_t",
|
|
114683
|
+
"uint64_t",
|
|
114684
|
+
"int8_t",
|
|
114685
|
+
"int16_t",
|
|
114686
|
+
"int32_t",
|
|
114687
|
+
"int64_t",
|
|
114688
|
+
"int"
|
|
114689
|
+
]);
|
|
114690
|
+
var NarrowingCastHelper = class _NarrowingCastHelper {
|
|
114691
|
+
/**
|
|
114692
|
+
* Check if a cast is needed for MISRA 10.3 compliance.
|
|
114693
|
+
* Returns true if:
|
|
114694
|
+
* - Source is wider than target (narrowing)
|
|
114695
|
+
* - Source and target are different essential type categories
|
|
114696
|
+
*
|
|
114697
|
+
* @param sourceType - Type of the expression (C-Next type or "int" for promoted)
|
|
114698
|
+
* @param targetType - Type of the target variable (C-Next type)
|
|
114699
|
+
*/
|
|
114700
|
+
static needsCast(sourceType, targetType) {
|
|
114701
|
+
if (sourceType === targetType) {
|
|
114702
|
+
return false;
|
|
114703
|
+
}
|
|
114704
|
+
if (targetType === "bool" && sourceType !== "bool") {
|
|
114705
|
+
return true;
|
|
114706
|
+
}
|
|
114707
|
+
const sourceWidth = EXTENDED_TYPE_WIDTH[sourceType];
|
|
114708
|
+
const targetWidth = EXTENDED_TYPE_WIDTH[targetType];
|
|
114709
|
+
if (sourceWidth === void 0 || targetWidth === void 0) {
|
|
114710
|
+
return false;
|
|
114711
|
+
}
|
|
114712
|
+
return sourceWidth > targetWidth;
|
|
114713
|
+
}
|
|
114714
|
+
/**
|
|
114715
|
+
* Wrap expression with cast if needed for MISRA 10.3 compliance.
|
|
114716
|
+
*
|
|
114717
|
+
* @param expr - The generated C expression
|
|
114718
|
+
* @param sourceType - Type of the expression (C-Next type or "int")
|
|
114719
|
+
* @param targetType - Type of the assignment target (C-Next type)
|
|
114720
|
+
* @returns Expression with cast wrapper if needed, or original expression
|
|
114721
|
+
*/
|
|
114722
|
+
static wrap(expr, sourceType, targetType) {
|
|
114723
|
+
if (!_NarrowingCastHelper.needsCast(sourceType, targetType)) {
|
|
114724
|
+
return expr;
|
|
114725
|
+
}
|
|
114726
|
+
if (targetType === "bool") {
|
|
114727
|
+
return `((${expr}) != 0U)`;
|
|
114728
|
+
}
|
|
114729
|
+
const cType = TYPE_MAP_default[targetType] ?? targetType;
|
|
114730
|
+
return CppModeHelper_default.cast(cType, expr);
|
|
114731
|
+
}
|
|
114732
|
+
/**
|
|
114733
|
+
* Determine the result type of C integer promotion for a given type.
|
|
114734
|
+
*
|
|
114735
|
+
* In C, operations on types smaller than int are promoted:
|
|
114736
|
+
* - u8, i8, u16, i16, bool -> int (32-bit)
|
|
114737
|
+
* - u32, i32, u64, i64 -> no promotion (already >= int width)
|
|
114738
|
+
*
|
|
114739
|
+
* @param baseType - The C-Next type of the operand
|
|
114740
|
+
* @returns "int" for promoted types, or the original type
|
|
114741
|
+
*/
|
|
114742
|
+
static getPromotedType(baseType) {
|
|
114743
|
+
if (PROMOTED_TO_INT.has(baseType)) {
|
|
114744
|
+
return "int";
|
|
114745
|
+
}
|
|
114746
|
+
return baseType;
|
|
114747
|
+
}
|
|
114748
|
+
/**
|
|
114749
|
+
* Check if a type is a floating-point type.
|
|
114750
|
+
*/
|
|
114751
|
+
static isFloatType(typeName) {
|
|
114752
|
+
return FLOAT_TYPES2.has(typeName);
|
|
114753
|
+
}
|
|
114754
|
+
/**
|
|
114755
|
+
* Check if a type is an integer type.
|
|
114756
|
+
*/
|
|
114757
|
+
static isIntegerType(typeName) {
|
|
114758
|
+
return INTEGER_TYPES2.has(typeName);
|
|
114759
|
+
}
|
|
114760
|
+
/**
|
|
114761
|
+
* Check if conversion between source and target is a cross-type-category conversion.
|
|
114762
|
+
* MISRA 10.3 requires explicit casts for different essential type categories.
|
|
114763
|
+
*/
|
|
114764
|
+
static isCrossTypeCategoryConversion(sourceType, targetType) {
|
|
114765
|
+
const sourceIsFloat = _NarrowingCastHelper.isFloatType(sourceType);
|
|
114766
|
+
const targetIsFloat = _NarrowingCastHelper.isFloatType(targetType);
|
|
114767
|
+
const sourceIsInt = _NarrowingCastHelper.isIntegerType(sourceType);
|
|
114768
|
+
const targetIsInt = _NarrowingCastHelper.isIntegerType(targetType);
|
|
114769
|
+
return sourceIsFloat && targetIsInt || sourceIsInt && targetIsFloat;
|
|
114770
|
+
}
|
|
114771
|
+
/**
|
|
114772
|
+
* Get the appropriate C float type for a C-Next type.
|
|
114773
|
+
*/
|
|
114774
|
+
static getCFloatType(typeName) {
|
|
114775
|
+
if (typeName === "f32" || typeName === "float") {
|
|
114776
|
+
return "float";
|
|
114777
|
+
}
|
|
114778
|
+
if (typeName === "f64" || typeName === "double") {
|
|
114779
|
+
return "double";
|
|
114780
|
+
}
|
|
114781
|
+
return "double";
|
|
114782
|
+
}
|
|
114783
|
+
/**
|
|
114784
|
+
* Wrap int-to-float conversion with explicit cast for MISRA 10.3.
|
|
114785
|
+
*
|
|
114786
|
+
* @param expr - The integer expression
|
|
114787
|
+
* @param targetType - The float target type (f32/f64)
|
|
114788
|
+
* @returns Expression with cast
|
|
114789
|
+
*/
|
|
114790
|
+
static wrapIntToFloat(expr, targetType) {
|
|
114791
|
+
const floatType = _NarrowingCastHelper.getCFloatType(targetType);
|
|
114792
|
+
return CppModeHelper_default.cast(floatType, expr);
|
|
114793
|
+
}
|
|
114794
|
+
};
|
|
114795
|
+
var NarrowingCastHelper_default = NarrowingCastHelper;
|
|
114796
|
+
|
|
114453
114797
|
// src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts
|
|
114454
114798
|
var UNSIGNED_64_TYPES = /* @__PURE__ */ new Set(["u64", "uint64_t"]);
|
|
114455
114799
|
var UNSIGNED_TYPES3 = /* @__PURE__ */ new Set([
|
|
@@ -114490,6 +114834,18 @@ var generateLiteral = (node, _input, state, _orchestrator) => {
|
|
|
114490
114834
|
effects.push({ type: "include", header: "stdbool" });
|
|
114491
114835
|
return { code: literalText, effects };
|
|
114492
114836
|
}
|
|
114837
|
+
if (literalText.startsWith("'")) {
|
|
114838
|
+
const expectedType2 = state?.expectedType;
|
|
114839
|
+
if (expectedType2) {
|
|
114840
|
+
const wrappedCode = NarrowingCastHelper_default.wrap(
|
|
114841
|
+
literalText,
|
|
114842
|
+
"int",
|
|
114843
|
+
expectedType2
|
|
114844
|
+
);
|
|
114845
|
+
return { code: wrappedCode, effects };
|
|
114846
|
+
}
|
|
114847
|
+
return { code: literalText, effects };
|
|
114848
|
+
}
|
|
114493
114849
|
if (/[fF]32$/.test(literalText)) {
|
|
114494
114850
|
literalText = literalText.replace(/[fF]32$/, "f");
|
|
114495
114851
|
return { code: literalText, effects };
|
|
@@ -114851,96 +115207,9 @@ var binaryExprGenerators = {
|
|
|
114851
115207
|
};
|
|
114852
115208
|
var BinaryExprGenerator_default = binaryExprGenerators;
|
|
114853
115209
|
|
|
114854
|
-
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114855
|
-
var CppModeHelper = class {
|
|
114856
|
-
/**
|
|
114857
|
-
* Get address-of expression for struct parameter passing.
|
|
114858
|
-
* C mode: `&expr` (pass pointer to struct)
|
|
114859
|
-
* C++ mode: `expr` (pass reference directly)
|
|
114860
|
-
*
|
|
114861
|
-
* @param expr - The expression to potentially wrap
|
|
114862
|
-
* @returns The expression with address-of operator in C mode
|
|
114863
|
-
*/
|
|
114864
|
-
static maybeAddressOf(expr) {
|
|
114865
|
-
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114866
|
-
}
|
|
114867
|
-
/**
|
|
114868
|
-
* Get dereference expression for struct parameter access.
|
|
114869
|
-
* C mode: `(*expr)` (dereference pointer)
|
|
114870
|
-
* C++ mode: `expr` (reference can be used directly)
|
|
114871
|
-
*
|
|
114872
|
-
* @param expr - The expression to potentially dereference
|
|
114873
|
-
* @returns The expression with dereference in C mode
|
|
114874
|
-
*/
|
|
114875
|
-
static maybeDereference(expr) {
|
|
114876
|
-
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114877
|
-
}
|
|
114878
|
-
/**
|
|
114879
|
-
* Get the type modifier for struct parameter declarations.
|
|
114880
|
-
* C mode: `*` (pointer type)
|
|
114881
|
-
* C++ mode: `&` (reference type)
|
|
114882
|
-
*
|
|
114883
|
-
* @returns The type modifier character
|
|
114884
|
-
*/
|
|
114885
|
-
static refOrPtr() {
|
|
114886
|
-
return CodeGenState.cppMode ? "&" : "*";
|
|
114887
|
-
}
|
|
114888
|
-
/**
|
|
114889
|
-
* Get the member access separator for struct parameters.
|
|
114890
|
-
* C mode: `->` (pointer member access)
|
|
114891
|
-
* C++ mode: `.` (reference member access)
|
|
114892
|
-
*
|
|
114893
|
-
* @returns The member access separator
|
|
114894
|
-
*/
|
|
114895
|
-
static memberSeparator() {
|
|
114896
|
-
return CodeGenState.cppMode ? "." : "->";
|
|
114897
|
-
}
|
|
114898
|
-
/**
|
|
114899
|
-
* Get NULL literal for the current mode.
|
|
114900
|
-
* C mode: `NULL`
|
|
114901
|
-
* C++ mode: `nullptr`
|
|
114902
|
-
*
|
|
114903
|
-
* @returns The null pointer literal
|
|
114904
|
-
*/
|
|
114905
|
-
static nullLiteral() {
|
|
114906
|
-
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114907
|
-
}
|
|
114908
|
-
/**
|
|
114909
|
-
* Generate a cast expression for the current mode.
|
|
114910
|
-
* C mode: `(type)expr`
|
|
114911
|
-
* C++ mode: `static_cast<type>(expr)`
|
|
114912
|
-
*
|
|
114913
|
-
* @param type - The target type
|
|
114914
|
-
* @param expr - The expression to cast
|
|
114915
|
-
* @returns The cast expression
|
|
114916
|
-
*/
|
|
114917
|
-
static cast(type, expr) {
|
|
114918
|
-
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114919
|
-
}
|
|
114920
|
-
/**
|
|
114921
|
-
* Generate a reinterpret cast expression for the current mode.
|
|
114922
|
-
* C mode: `(type)expr`
|
|
114923
|
-
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114924
|
-
*
|
|
114925
|
-
* @param type - The target type
|
|
114926
|
-
* @param expr - The expression to cast
|
|
114927
|
-
* @returns The cast expression
|
|
114928
|
-
*/
|
|
114929
|
-
static reinterpretCast(type, expr) {
|
|
114930
|
-
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114931
|
-
}
|
|
114932
|
-
/**
|
|
114933
|
-
* Check if we're in C++ mode.
|
|
114934
|
-
*
|
|
114935
|
-
* @returns True if generating C++ code
|
|
114936
|
-
*/
|
|
114937
|
-
static isCppMode() {
|
|
114938
|
-
return CodeGenState.cppMode;
|
|
114939
|
-
}
|
|
114940
|
-
};
|
|
114941
|
-
var CppModeHelper_default = CppModeHelper;
|
|
114942
|
-
|
|
114943
115210
|
// src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts
|
|
115211
|
+
var INT32_MIN_LITERAL = "2147483648";
|
|
115212
|
+
var INT64_MIN_LITERAL = "9223372036854775808";
|
|
114944
115213
|
var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
114945
115214
|
if (node.postfixExpression()) {
|
|
114946
115215
|
return {
|
|
@@ -114951,7 +115220,18 @@ var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
|
114951
115220
|
const inner = orchestrator.generateUnaryExpr(node.unaryExpression());
|
|
114952
115221
|
const text = node.getText();
|
|
114953
115222
|
if (text.startsWith("!")) return { code: `!${inner}`, effects: [] };
|
|
114954
|
-
if (text.startsWith("-"))
|
|
115223
|
+
if (text.startsWith("-")) {
|
|
115224
|
+
const effects = [];
|
|
115225
|
+
if (inner === INT32_MIN_LITERAL) {
|
|
115226
|
+
effects.push({ type: "include", header: "limits" });
|
|
115227
|
+
return { code: "(int32_t)INT32_MIN", effects };
|
|
115228
|
+
}
|
|
115229
|
+
if (inner === INT64_MIN_LITERAL || inner === INT64_MIN_LITERAL + "LL") {
|
|
115230
|
+
effects.push({ type: "include", header: "limits" });
|
|
115231
|
+
return { code: "(int64_t)INT64_MIN", effects };
|
|
115232
|
+
}
|
|
115233
|
+
return { code: `-${inner}`, effects };
|
|
115234
|
+
}
|
|
114955
115235
|
if (text.startsWith("~")) {
|
|
114956
115236
|
const innerType = TypeResolver_default2.getUnaryExpressionType(
|
|
114957
115237
|
node.unaryExpression()
|
|
@@ -115014,15 +115294,18 @@ var generateSizeProperty = (typeInfo) => {
|
|
|
115014
115294
|
throw new Error(`Error: .size is only available on string types`);
|
|
115015
115295
|
};
|
|
115016
115296
|
var generateBitmapFieldAccess = (result, fieldInfo) => {
|
|
115297
|
+
let expr;
|
|
115017
115298
|
if (fieldInfo.width === 1) {
|
|
115018
|
-
|
|
115299
|
+
expr = `((${result} >> ${fieldInfo.offset}) & 1)`;
|
|
115019
115300
|
} else {
|
|
115020
115301
|
const mask = (1 << fieldInfo.width) - 1;
|
|
115021
|
-
|
|
115022
|
-
|
|
115023
|
-
|
|
115024
|
-
|
|
115302
|
+
expr = `((${result} >> ${fieldInfo.offset}) & 0x${mask.toString(16).toUpperCase()})`;
|
|
115303
|
+
}
|
|
115304
|
+
const targetType = CodeGenState.expectedType;
|
|
115305
|
+
if (targetType) {
|
|
115306
|
+
expr = NarrowingCastHelper_default.wrap(expr, "int", targetType);
|
|
115025
115307
|
}
|
|
115308
|
+
return { code: expr, effects: [] };
|
|
115026
115309
|
};
|
|
115027
115310
|
var accessGenerators = {
|
|
115028
115311
|
generateCapacityProperty,
|
|
@@ -115199,7 +115482,8 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115199
115482
|
if (typeInfo?.isPointer) {
|
|
115200
115483
|
isPointerVariable = true;
|
|
115201
115484
|
}
|
|
115202
|
-
const
|
|
115485
|
+
const isOpaqueScopeVar = CodeGenState.isOpaqueScopeVariable(argCode);
|
|
115486
|
+
const needsAddressOf = argType && !argType.endsWith("*") && !argCode.startsWith("&") && !targetParam.isArray && !isPointerVariable && !isOpaqueScopeVar && (orchestrator.isStructType(argType) || _parameterExpectsAddressOf(targetParam.baseType, argType, orchestrator));
|
|
115203
115487
|
const finalArgCode = needsAddressOf ? `&${argCode}` : argCode;
|
|
115204
115488
|
return wrapWithCppEnumCast(
|
|
115205
115489
|
finalArgCode,
|
|
@@ -115337,7 +115621,7 @@ var trackPassThroughModifications = (funcName, argExprs, orchestrator) => {
|
|
|
115337
115621
|
var CallExprGenerator_default = generateFunctionCall;
|
|
115338
115622
|
|
|
115339
115623
|
// src/utils/TypeCheckUtils.ts
|
|
115340
|
-
var
|
|
115624
|
+
var INTEGER_TYPES3 = [
|
|
115341
115625
|
"u8",
|
|
115342
115626
|
"u16",
|
|
115343
115627
|
"u32",
|
|
@@ -115349,7 +115633,7 @@ var INTEGER_TYPES2 = [
|
|
|
115349
115633
|
];
|
|
115350
115634
|
var UNSIGNED_TYPES4 = ["u8", "u16", "u32", "u64"];
|
|
115351
115635
|
var SIGNED_TYPES3 = ["i8", "i16", "i32", "i64"];
|
|
115352
|
-
var
|
|
115636
|
+
var FLOAT_TYPES3 = ["f32", "f64"];
|
|
115353
115637
|
var STANDARD_WIDTHS = [8, 16, 32];
|
|
115354
115638
|
var TypeCheckUtils = class {
|
|
115355
115639
|
/**
|
|
@@ -115359,7 +115643,7 @@ var TypeCheckUtils = class {
|
|
|
115359
115643
|
* @returns true if it's u8, u16, u32, u64, i8, i16, i32, or i64
|
|
115360
115644
|
*/
|
|
115361
115645
|
static isInteger(typeName) {
|
|
115362
|
-
return
|
|
115646
|
+
return INTEGER_TYPES3.includes(typeName);
|
|
115363
115647
|
}
|
|
115364
115648
|
/**
|
|
115365
115649
|
* Check if a type name is an unsigned integer type.
|
|
@@ -115386,7 +115670,7 @@ var TypeCheckUtils = class {
|
|
|
115386
115670
|
* @returns true if it's f32 or f64
|
|
115387
115671
|
*/
|
|
115388
115672
|
static isFloat(typeName) {
|
|
115389
|
-
return
|
|
115673
|
+
return FLOAT_TYPES3.includes(typeName);
|
|
115390
115674
|
}
|
|
115391
115675
|
/**
|
|
115392
115676
|
* Check if a type name is a string type (string<N>).
|
|
@@ -116618,7 +116902,12 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116618
116902
|
const isRegisterAccess = checkRegisterAccess(ctx, input);
|
|
116619
116903
|
const identifierTypeInfo = getIdentifierTypeInfo(ctx, input);
|
|
116620
116904
|
if (isRegisterAccess) {
|
|
116621
|
-
|
|
116905
|
+
let expr2 = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116906
|
+
const targetType = CodeGenState.expectedType;
|
|
116907
|
+
if (targetType) {
|
|
116908
|
+
expr2 = NarrowingCastHelper_default.wrap(expr2, "int", targetType);
|
|
116909
|
+
}
|
|
116910
|
+
output.result = expr2;
|
|
116622
116911
|
return output;
|
|
116623
116912
|
}
|
|
116624
116913
|
if (ctx.currentMemberIsArray) {
|
|
@@ -116632,7 +116921,12 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116632
116921
|
}
|
|
116633
116922
|
const isPrimitiveIntMember = ctx.currentStructType && TypeCheckUtils_default.isInteger(ctx.currentStructType);
|
|
116634
116923
|
if (isPrimitiveIntMember) {
|
|
116635
|
-
|
|
116924
|
+
let expr2 = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116925
|
+
const targetType = CodeGenState.expectedType;
|
|
116926
|
+
if (targetType) {
|
|
116927
|
+
expr2 = NarrowingCastHelper_default.wrap(expr2, "int", targetType);
|
|
116928
|
+
}
|
|
116929
|
+
output.result = expr2;
|
|
116636
116930
|
output.currentStructType = void 0;
|
|
116637
116931
|
return output;
|
|
116638
116932
|
}
|
|
@@ -116691,7 +116985,12 @@ var handleDefaultSubscript = (ctx, index, typeInfo, output) => {
|
|
|
116691
116985
|
isRegisterAccess: false
|
|
116692
116986
|
});
|
|
116693
116987
|
if (subscriptKind === "bit_single") {
|
|
116694
|
-
|
|
116988
|
+
let expr = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116989
|
+
const targetType = CodeGenState.expectedType;
|
|
116990
|
+
if (targetType) {
|
|
116991
|
+
expr = NarrowingCastHelper_default.wrap(expr, "int", targetType);
|
|
116992
|
+
}
|
|
116993
|
+
output.result = expr;
|
|
116695
116994
|
} else {
|
|
116696
116995
|
output.result = `${ctx.result}[${index}]`;
|
|
116697
116996
|
}
|
|
@@ -116718,10 +117017,24 @@ var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects,
|
|
|
116718
117017
|
);
|
|
116719
117018
|
} else {
|
|
116720
117019
|
const mask = orchestrator.generateBitMask(width);
|
|
117020
|
+
let expr;
|
|
116721
117021
|
if (start === "0" || start === "0U") {
|
|
116722
|
-
|
|
117022
|
+
expr = `((${ctx.result}) & ${mask})`;
|
|
116723
117023
|
} else {
|
|
116724
|
-
|
|
117024
|
+
expr = `((${ctx.result} >> ${start}) & ${mask})`;
|
|
117025
|
+
}
|
|
117026
|
+
const targetType = CodeGenState.expectedType;
|
|
117027
|
+
if (targetType && ctx.primaryTypeInfo?.baseType) {
|
|
117028
|
+
const promotedSourceType = NarrowingCastHelper_default.getPromotedType(
|
|
117029
|
+
ctx.primaryTypeInfo.baseType
|
|
117030
|
+
);
|
|
117031
|
+
output.result = NarrowingCastHelper_default.wrap(
|
|
117032
|
+
expr,
|
|
117033
|
+
promotedSourceType,
|
|
117034
|
+
targetType
|
|
117035
|
+
);
|
|
117036
|
+
} else {
|
|
117037
|
+
output.result = expr;
|
|
116725
117038
|
}
|
|
116726
117039
|
}
|
|
116727
117040
|
return output;
|
|
@@ -117031,6 +117344,21 @@ var generateCriticalStatement = (node, _input, _state, orchestrator) => {
|
|
|
117031
117344
|
};
|
|
117032
117345
|
var CriticalGenerator_default = generateCriticalStatement;
|
|
117033
117346
|
|
|
117347
|
+
// src/transpiler/output/codegen/types/COMPOUND_TO_BINARY.ts
|
|
117348
|
+
var COMPOUND_TO_BINARY = {
|
|
117349
|
+
"+=": "+",
|
|
117350
|
+
"-=": "-",
|
|
117351
|
+
"*=": "*",
|
|
117352
|
+
"/=": "/",
|
|
117353
|
+
"%=": "%",
|
|
117354
|
+
"&=": "&",
|
|
117355
|
+
"|=": "|",
|
|
117356
|
+
"^=": "^",
|
|
117357
|
+
"<<=": "<<",
|
|
117358
|
+
">>=": ">>"
|
|
117359
|
+
};
|
|
117360
|
+
var COMPOUND_TO_BINARY_default = COMPOUND_TO_BINARY;
|
|
117361
|
+
|
|
117034
117362
|
// src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts
|
|
117035
117363
|
var TYPE_MAP2 = {
|
|
117036
117364
|
u8: "uint8_t",
|
|
@@ -117058,18 +117386,6 @@ var STREX_MAP = {
|
|
|
117058
117386
|
u32: "__STREXW",
|
|
117059
117387
|
i32: "__STREXW"
|
|
117060
117388
|
};
|
|
117061
|
-
var SIMPLE_OP_MAP = {
|
|
117062
|
-
"+=": "+",
|
|
117063
|
-
"-=": "-",
|
|
117064
|
-
"*=": "*",
|
|
117065
|
-
"/=": "/",
|
|
117066
|
-
"%=": "%",
|
|
117067
|
-
"&=": "&",
|
|
117068
|
-
"|=": "|",
|
|
117069
|
-
"^=": "^",
|
|
117070
|
-
"<<=": "<<",
|
|
117071
|
-
">>=": ">>"
|
|
117072
|
-
};
|
|
117073
117389
|
var CLAMP_OP_MAP = {
|
|
117074
117390
|
"+=": "add",
|
|
117075
117391
|
"-=": "sub",
|
|
@@ -117083,7 +117399,7 @@ function getClampHelperOp(cOp, typeInfo) {
|
|
|
117083
117399
|
}
|
|
117084
117400
|
function generateInnerAtomicOp(cOp, value, typeInfo) {
|
|
117085
117401
|
const effects = [];
|
|
117086
|
-
const simpleOp =
|
|
117402
|
+
const simpleOp = COMPOUND_TO_BINARY_default[cOp] || "+";
|
|
117087
117403
|
const helperOp = getClampHelperOp(cOp, typeInfo);
|
|
117088
117404
|
if (helperOp) {
|
|
117089
117405
|
effects.push({
|
|
@@ -117748,8 +118064,13 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117748
118064
|
const arrayDims = varDecl.arrayDimension();
|
|
117749
118065
|
const arrayTypeCtx = varDecl.type().arrayType?.() ?? null;
|
|
117750
118066
|
const isArray = arrayDims.length > 0 || arrayTypeCtx !== null;
|
|
117751
|
-
|
|
118067
|
+
let type = orchestrator.generateType(varDecl.type());
|
|
117752
118068
|
const fullName = QualifiedNameGenerator_default.forMember(scopeName, varName);
|
|
118069
|
+
const isOpaque = orchestrator.isOpaqueType(type);
|
|
118070
|
+
if (isOpaque) {
|
|
118071
|
+
type = `${type}*`;
|
|
118072
|
+
orchestrator.markOpaqueScopeVariable(fullName);
|
|
118073
|
+
}
|
|
117753
118074
|
const constPrefix = isConst ? "const " : "";
|
|
117754
118075
|
const prefix = isPrivate ? "static " : "";
|
|
117755
118076
|
let decl = `${prefix}${constPrefix}${type} ${fullName}`;
|
|
@@ -117761,7 +118082,11 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117761
118082
|
decl += orchestrator.generateArrayDimensions(arrayDims);
|
|
117762
118083
|
}
|
|
117763
118084
|
decl += ArrayDimensionUtils_default.generateStringCapacityDim(varDecl.type());
|
|
117764
|
-
|
|
118085
|
+
if (isOpaque) {
|
|
118086
|
+
decl += " = NULL";
|
|
118087
|
+
} else {
|
|
118088
|
+
decl += generateInitializer(varDecl, isArray, orchestrator);
|
|
118089
|
+
}
|
|
117765
118090
|
return decl + ";";
|
|
117766
118091
|
}
|
|
117767
118092
|
function generateScopeFunction(funcDecl, scopeName, isPrivate, orchestrator) {
|
|
@@ -117973,6 +118298,7 @@ function generateScopedStructInline(node, scopeName, _input, orchestrator) {
|
|
|
117973
118298
|
var ScopeGenerator_default = generateScope;
|
|
117974
118299
|
|
|
117975
118300
|
// src/utils/BitUtils.ts
|
|
118301
|
+
var NARROW_TYPES = /* @__PURE__ */ new Set(["u8", "u16", "i8", "i16"]);
|
|
117976
118302
|
var BitUtils = class _BitUtils {
|
|
117977
118303
|
/**
|
|
117978
118304
|
* Convert a boolean expression to an unsigned integer (0U or 1U).
|
|
@@ -118063,6 +118389,21 @@ var BitUtils = class _BitUtils {
|
|
|
118063
118389
|
static formatHex(value) {
|
|
118064
118390
|
return `0x${value.toString(16).toUpperCase()}U`;
|
|
118065
118391
|
}
|
|
118392
|
+
/**
|
|
118393
|
+
* Wrap an expression with a cast for MISRA 10.3 compliance on narrow types.
|
|
118394
|
+
* Bit manipulation operations promote to int; this casts back to the target type.
|
|
118395
|
+
*
|
|
118396
|
+
* @param expr - The expression to potentially wrap
|
|
118397
|
+
* @param targetType - The C-Next type name (e.g., "u8", "u16")
|
|
118398
|
+
* @returns Expression wrapped with cast if narrow, or original expression
|
|
118399
|
+
*/
|
|
118400
|
+
static wrapNarrowCast(expr, targetType) {
|
|
118401
|
+
if (!targetType || !NARROW_TYPES.has(targetType)) {
|
|
118402
|
+
return expr;
|
|
118403
|
+
}
|
|
118404
|
+
const cType = TYPE_MAP_default[targetType] ?? targetType;
|
|
118405
|
+
return `(${cType})(${expr})`;
|
|
118406
|
+
}
|
|
118066
118407
|
/**
|
|
118067
118408
|
* Generate code to read a single bit from a value.
|
|
118068
118409
|
* Pattern: ((target >> offset) & 1)
|
|
@@ -118109,7 +118450,8 @@ var BitUtils = class _BitUtils {
|
|
|
118109
118450
|
const is64Bit = targetType === "u64" || targetType === "i64";
|
|
118110
118451
|
const one = is64Bit ? "1ULL" : "1U";
|
|
118111
118452
|
const valueShift = is64Bit ? `((uint64_t)${intValue} << ${offset})` : `(${intValue} << ${offset})`;
|
|
118112
|
-
|
|
118453
|
+
const rhs = `(${target} & ~(${one} << ${offset})) | ${valueShift}`;
|
|
118454
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118113
118455
|
}
|
|
118114
118456
|
/**
|
|
118115
118457
|
* Generate read-modify-write code for multi-bit assignment.
|
|
@@ -118124,7 +118466,8 @@ var BitUtils = class _BitUtils {
|
|
|
118124
118466
|
*/
|
|
118125
118467
|
static multiBitWrite(target, offset, width, value, targetType) {
|
|
118126
118468
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118127
|
-
|
|
118469
|
+
const rhs = `(${target} & ~(${mask} << ${offset})) | ((${value} & ${mask}) << ${offset})`;
|
|
118470
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118128
118471
|
}
|
|
118129
118472
|
/**
|
|
118130
118473
|
* Generate write-only register code for single bit assignment.
|
|
@@ -118140,7 +118483,8 @@ var BitUtils = class _BitUtils {
|
|
|
118140
118483
|
static writeOnlySingleBit(target, offset, value, targetType) {
|
|
118141
118484
|
const intValue = _BitUtils.boolToInt(value);
|
|
118142
118485
|
const castPrefix = targetType === "u64" || targetType === "i64" ? "(uint64_t)" : "";
|
|
118143
|
-
|
|
118486
|
+
const rhs = `(${castPrefix}${intValue} << ${offset})`;
|
|
118487
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118144
118488
|
}
|
|
118145
118489
|
/**
|
|
118146
118490
|
* Generate write-only register code for multi-bit assignment.
|
|
@@ -118156,7 +118500,8 @@ var BitUtils = class _BitUtils {
|
|
|
118156
118500
|
*/
|
|
118157
118501
|
static writeOnlyMultiBit(target, offset, width, value, targetType) {
|
|
118158
118502
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118159
|
-
|
|
118503
|
+
const rhs = `((${value} & ${mask}) << ${offset})`;
|
|
118504
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118160
118505
|
}
|
|
118161
118506
|
};
|
|
118162
118507
|
var BitUtils_default = BitUtils;
|
|
@@ -120717,8 +121062,10 @@ var AssignmentKind = /* @__PURE__ */ ((AssignmentKind2) => {
|
|
|
120717
121062
|
AssignmentKind2[AssignmentKind2["GLOBAL_REGISTER_BIT"] = 28] = "GLOBAL_REGISTER_BIT";
|
|
120718
121063
|
AssignmentKind2[AssignmentKind2["THIS_MEMBER"] = 29] = "THIS_MEMBER";
|
|
120719
121064
|
AssignmentKind2[AssignmentKind2["THIS_ARRAY"] = 30] = "THIS_ARRAY";
|
|
120720
|
-
AssignmentKind2[AssignmentKind2["
|
|
120721
|
-
AssignmentKind2[AssignmentKind2["
|
|
121065
|
+
AssignmentKind2[AssignmentKind2["THIS_BIT"] = 31] = "THIS_BIT";
|
|
121066
|
+
AssignmentKind2[AssignmentKind2["THIS_BIT_RANGE"] = 32] = "THIS_BIT_RANGE";
|
|
121067
|
+
AssignmentKind2[AssignmentKind2["MEMBER_CHAIN"] = 33] = "MEMBER_CHAIN";
|
|
121068
|
+
AssignmentKind2[AssignmentKind2["SIMPLE"] = 34] = "SIMPLE";
|
|
120722
121069
|
return AssignmentKind2;
|
|
120723
121070
|
})(AssignmentKind || {});
|
|
120724
121071
|
var AssignmentKind_default = AssignmentKind;
|
|
@@ -120760,8 +121107,55 @@ var handlers_default = AssignmentHandlerRegistry;
|
|
|
120760
121107
|
function gen() {
|
|
120761
121108
|
return CodeGenState.generator;
|
|
120762
121109
|
}
|
|
121110
|
+
function tryHandleCompoundNarrowingCast(ctx, target) {
|
|
121111
|
+
if (!ctx.isCompound || !ctx.firstIdTypeInfo) {
|
|
121112
|
+
return null;
|
|
121113
|
+
}
|
|
121114
|
+
const baseType = ctx.firstIdTypeInfo.baseType;
|
|
121115
|
+
const promotedType = NarrowingCastHelper_default.getPromotedType(baseType);
|
|
121116
|
+
if (promotedType !== "int" || baseType === "int") {
|
|
121117
|
+
return null;
|
|
121118
|
+
}
|
|
121119
|
+
const binaryOp = COMPOUND_TO_BINARY_default[ctx.cOp];
|
|
121120
|
+
if (!binaryOp) {
|
|
121121
|
+
return null;
|
|
121122
|
+
}
|
|
121123
|
+
const cType = TYPE_MAP_default[baseType] ?? baseType;
|
|
121124
|
+
const expr = `(${target} ${binaryOp} ${ctx.generatedValue})`;
|
|
121125
|
+
const castExpr = CppModeHelper_default.cast(cType, expr);
|
|
121126
|
+
return `${target} = ${castExpr};`;
|
|
121127
|
+
}
|
|
121128
|
+
function tryHandleIntToFloatConversion(ctx, target) {
|
|
121129
|
+
if (ctx.isCompound || !ctx.firstIdTypeInfo || !ctx.valueCtx) {
|
|
121130
|
+
return null;
|
|
121131
|
+
}
|
|
121132
|
+
const targetType = ctx.firstIdTypeInfo.baseType;
|
|
121133
|
+
const valueType = TypeResolver_default2.getExpressionType(ctx.valueCtx);
|
|
121134
|
+
if (!valueType) {
|
|
121135
|
+
return null;
|
|
121136
|
+
}
|
|
121137
|
+
if (!NarrowingCastHelper_default.isCrossTypeCategoryConversion(valueType, targetType)) {
|
|
121138
|
+
return null;
|
|
121139
|
+
}
|
|
121140
|
+
if (!NarrowingCastHelper_default.isIntegerType(valueType) || !NarrowingCastHelper_default.isFloatType(targetType)) {
|
|
121141
|
+
return null;
|
|
121142
|
+
}
|
|
121143
|
+
const castedValue = NarrowingCastHelper_default.wrapIntToFloat(
|
|
121144
|
+
ctx.generatedValue,
|
|
121145
|
+
targetType
|
|
121146
|
+
);
|
|
121147
|
+
return `${target} ${ctx.cOp} ${castedValue};`;
|
|
121148
|
+
}
|
|
120763
121149
|
function handleSimpleAssignment(ctx) {
|
|
120764
121150
|
const target = gen().generateAssignmentTarget(ctx.targetCtx);
|
|
121151
|
+
const compoundResult = tryHandleCompoundNarrowingCast(ctx, target);
|
|
121152
|
+
if (compoundResult) {
|
|
121153
|
+
return compoundResult;
|
|
121154
|
+
}
|
|
121155
|
+
const conversionResult = tryHandleIntToFloatConversion(ctx, target);
|
|
121156
|
+
if (conversionResult) {
|
|
121157
|
+
return conversionResult;
|
|
121158
|
+
}
|
|
120765
121159
|
return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
|
|
120766
121160
|
}
|
|
120767
121161
|
var SimpleHandler_default = handleSimpleAssignment;
|
|
@@ -121414,6 +121808,8 @@ function handleStructChainBitRange(ctx) {
|
|
|
121414
121808
|
var bitAccessHandlers = [
|
|
121415
121809
|
[AssignmentKind_default.INTEGER_BIT, handleIntegerBit],
|
|
121416
121810
|
[AssignmentKind_default.INTEGER_BIT_RANGE, handleIntegerBitRange],
|
|
121811
|
+
[AssignmentKind_default.THIS_BIT, handleIntegerBit],
|
|
121812
|
+
[AssignmentKind_default.THIS_BIT_RANGE, handleIntegerBitRange],
|
|
121417
121813
|
[AssignmentKind_default.STRUCT_MEMBER_BIT, handleStructMemberBit],
|
|
121418
121814
|
[AssignmentKind_default.ARRAY_ELEMENT_BIT, handleArrayElementBit],
|
|
121419
121815
|
[AssignmentKind_default.STRUCT_CHAIN_BIT_RANGE, handleStructChainBitRange]
|
|
@@ -121965,14 +122361,28 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
121965
122361
|
return AssignmentKind_default.THIS_MEMBER;
|
|
121966
122362
|
}
|
|
121967
122363
|
/**
|
|
121968
|
-
* Classify this.reg[bit] / this.arr[i] patterns with array access.
|
|
122364
|
+
* Classify this.reg[bit] / this.arr[i] / this.flags[3] patterns with array access.
|
|
122365
|
+
* Issue #954: Uses SubscriptClassifier to distinguish array vs bit access.
|
|
121969
122366
|
*/
|
|
121970
122367
|
static classifyThisWithArrayAccess(ctx, scopedRegName) {
|
|
121971
122368
|
if (CodeGenState.symbols.knownRegisters.has(scopedRegName)) {
|
|
121972
122369
|
const hasBitRange = ctx.postfixOps.some((op) => op.COMMA() !== null);
|
|
121973
122370
|
return hasBitRange ? AssignmentKind_default.SCOPED_REGISTER_BIT_RANGE : AssignmentKind_default.SCOPED_REGISTER_BIT;
|
|
121974
122371
|
}
|
|
121975
|
-
|
|
122372
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(scopedRegName);
|
|
122373
|
+
const subscriptKind = SubscriptClassifier_default.classify({
|
|
122374
|
+
typeInfo: typeInfo ?? null,
|
|
122375
|
+
subscriptCount: ctx.lastSubscriptExprCount,
|
|
122376
|
+
isRegisterAccess: false
|
|
122377
|
+
});
|
|
122378
|
+
switch (subscriptKind) {
|
|
122379
|
+
case "bit_single":
|
|
122380
|
+
return AssignmentKind_default.THIS_BIT;
|
|
122381
|
+
case "bit_range":
|
|
122382
|
+
return AssignmentKind_default.THIS_BIT_RANGE;
|
|
122383
|
+
default:
|
|
122384
|
+
return AssignmentKind_default.THIS_ARRAY;
|
|
122385
|
+
}
|
|
121976
122386
|
}
|
|
121977
122387
|
/**
|
|
121978
122388
|
* Classify simple array/bit access (no prefix, no member access).
|
|
@@ -122045,7 +122455,8 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
122045
122455
|
if (isGlobalAtomic) {
|
|
122046
122456
|
return AssignmentKind_default.ATOMIC_RMW;
|
|
122047
122457
|
}
|
|
122048
|
-
|
|
122458
|
+
const ARITHMETIC_COMPOUND_OPS = /* @__PURE__ */ new Set(["+=", "-=", "*="]);
|
|
122459
|
+
if (typeInfo.overflowBehavior === "clamp" && TypeCheckUtils_default.isInteger(typeInfo.baseType) && ARITHMETIC_COMPOUND_OPS.has(ctx.cOp)) {
|
|
122049
122460
|
return AssignmentKind_default.OVERFLOW_CLAMP;
|
|
122050
122461
|
}
|
|
122051
122462
|
return null;
|
|
@@ -124446,10 +124857,20 @@ ${assignments}`;
|
|
|
124446
124857
|
_VariableDeclHelper.validateIntegerInitializer(ctx, typeName, {
|
|
124447
124858
|
getExpressionType: callbacks.getExpressionType
|
|
124448
124859
|
});
|
|
124449
|
-
return CodeGenState.withExpectedType(
|
|
124450
|
-
|
|
124451
|
-
|
|
124452
|
-
|
|
124860
|
+
return CodeGenState.withExpectedType(typeName, () => {
|
|
124861
|
+
let exprCode = callbacks.generateExpression(ctx.expression());
|
|
124862
|
+
const exprType = callbacks.getExpressionType(ctx.expression());
|
|
124863
|
+
if (exprType && NarrowingCastHelper_default.isCrossTypeCategoryConversion(exprType, typeName)) {
|
|
124864
|
+
if (NarrowingCastHelper_default.isIntegerType(exprType) && NarrowingCastHelper_default.isFloatType(typeName)) {
|
|
124865
|
+
exprCode = NarrowingCastHelper_default.wrapIntToFloat(exprCode, typeName);
|
|
124866
|
+
}
|
|
124867
|
+
if (NarrowingCastHelper_default.isFloatType(exprType) && NarrowingCastHelper_default.isIntegerType(typeName)) {
|
|
124868
|
+
const cType = TYPE_MAP_default[typeName] ?? typeName;
|
|
124869
|
+
exprCode = CppModeHelper_default.cast(cType, exprCode);
|
|
124870
|
+
}
|
|
124871
|
+
}
|
|
124872
|
+
return `${decl} = ${exprCode}`;
|
|
124873
|
+
});
|
|
124453
124874
|
}
|
|
124454
124875
|
// ========================================================================
|
|
124455
124876
|
// Tier 4: Orchestrators (main entry points)
|
|
@@ -125310,7 +125731,7 @@ var TypeGenerationHelper_default = TypeGenerationHelper;
|
|
|
125310
125731
|
var SIGNED_INTEGERS = /* @__PURE__ */ new Set(["i8", "i16", "i32", "i64"]);
|
|
125311
125732
|
var UNSIGNED_INTEGERS = /* @__PURE__ */ new Set(["u8", "u16", "u32", "u64"]);
|
|
125312
125733
|
var ALL_INTEGERS = /* @__PURE__ */ new Set([...SIGNED_INTEGERS, ...UNSIGNED_INTEGERS]);
|
|
125313
|
-
var
|
|
125734
|
+
var FLOAT_TYPES4 = /* @__PURE__ */ new Set(["f32", "f64"]);
|
|
125314
125735
|
var CastValidator = class _CastValidator {
|
|
125315
125736
|
/**
|
|
125316
125737
|
* Check if a type is an integer type.
|
|
@@ -125322,7 +125743,7 @@ var CastValidator = class _CastValidator {
|
|
|
125322
125743
|
* Check if a type is a floating-point type.
|
|
125323
125744
|
*/
|
|
125324
125745
|
static isFloatType(typeName) {
|
|
125325
|
-
return
|
|
125746
|
+
return FLOAT_TYPES4.has(typeName);
|
|
125326
125747
|
}
|
|
125327
125748
|
/**
|
|
125328
125749
|
* Check if a type is signed.
|
|
@@ -128368,6 +128789,22 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128368
128789
|
isFloatShadowCurrent(shadowName) {
|
|
128369
128790
|
return CodeGenState.floatShadowCurrent.has(shadowName);
|
|
128370
128791
|
}
|
|
128792
|
+
/**
|
|
128793
|
+
* Issue #948: Check if a type is an opaque (forward-declared) struct type.
|
|
128794
|
+
* Opaque types can only be used as pointers (cannot be instantiated).
|
|
128795
|
+
* Part of IOrchestrator interface.
|
|
128796
|
+
*/
|
|
128797
|
+
isOpaqueType(typeName) {
|
|
128798
|
+
return CodeGenState.isOpaqueType(typeName);
|
|
128799
|
+
}
|
|
128800
|
+
/**
|
|
128801
|
+
* Issue #948: Mark a scope variable as having an opaque type.
|
|
128802
|
+
* These variables are generated as pointers with NULL initialization.
|
|
128803
|
+
* Part of IOrchestrator interface.
|
|
128804
|
+
*/
|
|
128805
|
+
markOpaqueScopeVariable(qualifiedName) {
|
|
128806
|
+
CodeGenState.markOpaqueScopeVariable(qualifiedName);
|
|
128807
|
+
}
|
|
128371
128808
|
// ===========================================================================
|
|
128372
128809
|
// End IOrchestrator Implementation
|
|
128373
128810
|
// ===========================================================================
|
|
@@ -130334,7 +130771,9 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130334
130771
|
const minComparison = minValue === "0" ? `0.0${floatSuffix}` : `((${floatCastType})${minValue})`;
|
|
130335
130772
|
const maxComparison = `((${floatCastType})${maxValue})`;
|
|
130336
130773
|
const finalCast = CppModeHelper_default.cast(targetType, `(${expr})`);
|
|
130337
|
-
|
|
130774
|
+
const castMax = CppModeHelper_default.cast(targetType, maxValue);
|
|
130775
|
+
const castMin = minValue === "0" ? "0" : CppModeHelper_default.cast(targetType, minValue);
|
|
130776
|
+
return `((${expr}) > ${maxComparison} ? ${castMax} : (${expr}) < ${minComparison} ? ${castMin} : ${finalCast})`;
|
|
130338
130777
|
}
|
|
130339
130778
|
/**
|
|
130340
130779
|
* ADR-023: Generate sizeof expression
|
|
@@ -132527,6 +132966,7 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132527
132966
|
const registerMemberCTypes = /* @__PURE__ */ new Map();
|
|
132528
132967
|
const scopePrivateConstValues = /* @__PURE__ */ new Map();
|
|
132529
132968
|
const functionReturnTypes = /* @__PURE__ */ new Map();
|
|
132969
|
+
const opaqueTypes = /* @__PURE__ */ new Set();
|
|
132530
132970
|
for (const symbol of symbols) {
|
|
132531
132971
|
switch (symbol.kind) {
|
|
132532
132972
|
case "struct":
|
|
@@ -132614,6 +133054,8 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132614
133054
|
scopePrivateConstValues,
|
|
132615
133055
|
// Function return types
|
|
132616
133056
|
functionReturnTypes,
|
|
133057
|
+
// Issue #948: Opaque types
|
|
133058
|
+
opaqueTypes,
|
|
132617
133059
|
// Methods
|
|
132618
133060
|
getSingleFunctionForVariable: (scopeName, varName) => _TSymbolInfoAdapter.getSingleFunctionForVariable(
|
|
132619
133061
|
scopeVariableUsage,
|
|
@@ -132811,42 +133253,35 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132811
133253
|
);
|
|
132812
133254
|
}
|
|
132813
133255
|
return {
|
|
132814
|
-
|
|
133256
|
+
...base,
|
|
132815
133257
|
knownScopes: mergedKnownScopes,
|
|
132816
|
-
knownStructs: base.knownStructs,
|
|
132817
133258
|
knownEnums: mergedKnownEnums,
|
|
132818
|
-
knownBitmaps: base.knownBitmaps,
|
|
132819
|
-
knownRegisters: base.knownRegisters,
|
|
132820
|
-
// Scope info
|
|
132821
|
-
scopeMembers: base.scopeMembers,
|
|
132822
|
-
scopeMemberVisibility: base.scopeMemberVisibility,
|
|
132823
|
-
scopeVariableUsage: base.scopeVariableUsage,
|
|
132824
|
-
// Struct info
|
|
132825
|
-
structFields: base.structFields,
|
|
132826
|
-
structFieldArrays: base.structFieldArrays,
|
|
132827
|
-
structFieldDimensions: base.structFieldDimensions,
|
|
132828
|
-
// Enum info - merged
|
|
132829
133259
|
enumMembers: mergedEnumMembers,
|
|
132830
|
-
|
|
132831
|
-
bitmapFields: base.bitmapFields,
|
|
132832
|
-
bitmapBackingType: base.bitmapBackingType,
|
|
132833
|
-
bitmapBitWidth: base.bitmapBitWidth,
|
|
132834
|
-
// Register info
|
|
132835
|
-
scopedRegisters: base.scopedRegisters,
|
|
132836
|
-
registerMemberAccess: base.registerMemberAccess,
|
|
132837
|
-
registerMemberTypes: base.registerMemberTypes,
|
|
132838
|
-
registerBaseAddresses: base.registerBaseAddresses,
|
|
132839
|
-
registerMemberOffsets: base.registerMemberOffsets,
|
|
132840
|
-
registerMemberCTypes: base.registerMemberCTypes,
|
|
132841
|
-
// Private const values
|
|
132842
|
-
scopePrivateConstValues: base.scopePrivateConstValues,
|
|
132843
|
-
// Function return types - merged
|
|
132844
|
-
functionReturnTypes: mergedFunctionReturnTypes,
|
|
132845
|
-
// Methods - delegate to base's implementation
|
|
132846
|
-
getSingleFunctionForVariable: base.getSingleFunctionForVariable,
|
|
132847
|
-
hasPublicSymbols: base.hasPublicSymbols
|
|
133260
|
+
functionReturnTypes: mergedFunctionReturnTypes
|
|
132848
133261
|
};
|
|
132849
133262
|
}
|
|
133263
|
+
/**
|
|
133264
|
+
* Issue #948: Merge opaque types from an external source (e.g., SymbolTable)
|
|
133265
|
+
* into an existing ICodeGenSymbols.
|
|
133266
|
+
*
|
|
133267
|
+
* Opaque types are forward-declared struct types (like `typedef struct _foo foo;`)
|
|
133268
|
+
* that come from C headers and need to be tracked for correct scope variable
|
|
133269
|
+
* generation (as pointers with NULL initialization).
|
|
133270
|
+
*
|
|
133271
|
+
* @param base The ICodeGenSymbols from the current file
|
|
133272
|
+
* @param externalOpaqueTypes Array of opaque type names from external sources
|
|
133273
|
+
* @returns New ICodeGenSymbols with merged opaque types
|
|
133274
|
+
*/
|
|
133275
|
+
static mergeOpaqueTypes(base, externalOpaqueTypes) {
|
|
133276
|
+
if (externalOpaqueTypes.length === 0) {
|
|
133277
|
+
return base;
|
|
133278
|
+
}
|
|
133279
|
+
const mergedOpaqueTypes = new Set(base.opaqueTypes);
|
|
133280
|
+
for (const typeName of externalOpaqueTypes) {
|
|
133281
|
+
mergedOpaqueTypes.add(typeName);
|
|
133282
|
+
}
|
|
133283
|
+
return { ...base, opaqueTypes: mergedOpaqueTypes };
|
|
133284
|
+
}
|
|
132850
133285
|
};
|
|
132851
133286
|
var TSymbolInfoAdapter_default = TSymbolInfoAdapter;
|
|
132852
133287
|
|
|
@@ -133233,6 +133668,18 @@ var DeclaratorUtils = class _DeclaratorUtils {
|
|
|
133233
133668
|
}
|
|
133234
133669
|
return void 0;
|
|
133235
133670
|
}
|
|
133671
|
+
/**
|
|
133672
|
+
* Extract the first declarator name from an init-declarator-list.
|
|
133673
|
+
* For "typedef struct _widget_t widget_t;", this returns "widget_t".
|
|
133674
|
+
* Used for Issue #948 opaque type detection.
|
|
133675
|
+
*/
|
|
133676
|
+
static extractFirstDeclaratorName(initDeclList) {
|
|
133677
|
+
const initDeclarators = initDeclList.initDeclarator?.();
|
|
133678
|
+
if (!initDeclarators || initDeclarators.length === 0) return void 0;
|
|
133679
|
+
const firstDeclarator = initDeclarators[0].declarator?.();
|
|
133680
|
+
if (!firstDeclarator) return void 0;
|
|
133681
|
+
return _DeclaratorUtils.extractDeclaratorName(firstDeclarator) ?? void 0;
|
|
133682
|
+
}
|
|
133236
133683
|
};
|
|
133237
133684
|
var DeclaratorUtils_default = DeclaratorUtils;
|
|
133238
133685
|
|
|
@@ -133254,6 +133701,7 @@ var StructCollector2 = class _StructCollector {
|
|
|
133254
133701
|
const name = identifier?.getText() || typedefName;
|
|
133255
133702
|
if (!name) return null;
|
|
133256
133703
|
const isUnion = structSpec.structOrUnion()?.getText() === "union";
|
|
133704
|
+
const hasBody = structSpec.structDeclarationList() !== null;
|
|
133257
133705
|
const fields = _StructCollector.collectFields(
|
|
133258
133706
|
structSpec,
|
|
133259
133707
|
name,
|
|
@@ -133261,8 +133709,16 @@ var StructCollector2 = class _StructCollector {
|
|
|
133261
133709
|
warnings
|
|
133262
133710
|
);
|
|
133263
133711
|
const needsStructKeyword = Boolean(identifier && !isTypedef);
|
|
133264
|
-
if (symbolTable
|
|
133265
|
-
|
|
133712
|
+
if (symbolTable) {
|
|
133713
|
+
_StructCollector.updateSymbolTable(
|
|
133714
|
+
symbolTable,
|
|
133715
|
+
name,
|
|
133716
|
+
needsStructKeyword,
|
|
133717
|
+
hasBody,
|
|
133718
|
+
isTypedef,
|
|
133719
|
+
typedefName,
|
|
133720
|
+
identifier?.getText()
|
|
133721
|
+
);
|
|
133266
133722
|
}
|
|
133267
133723
|
return {
|
|
133268
133724
|
kind: "struct",
|
|
@@ -133276,6 +133732,44 @@ var StructCollector2 = class _StructCollector {
|
|
|
133276
133732
|
fields: fields.size > 0 ? fields : void 0
|
|
133277
133733
|
};
|
|
133278
133734
|
}
|
|
133735
|
+
/**
|
|
133736
|
+
* Update symbol table with struct metadata.
|
|
133737
|
+
* Extracted to reduce cognitive complexity of collect().
|
|
133738
|
+
*/
|
|
133739
|
+
static updateSymbolTable(symbolTable, name, needsStructKeyword, hasBody, isTypedef, typedefName, structTag) {
|
|
133740
|
+
if (needsStructKeyword) {
|
|
133741
|
+
symbolTable.markNeedsStructKeyword(name);
|
|
133742
|
+
}
|
|
133743
|
+
if (isTypedef && !hasBody && typedefName) {
|
|
133744
|
+
symbolTable.markOpaqueType(typedefName);
|
|
133745
|
+
if (structTag) {
|
|
133746
|
+
symbolTable.registerStructTagAlias(structTag, typedefName);
|
|
133747
|
+
}
|
|
133748
|
+
}
|
|
133749
|
+
if (hasBody) {
|
|
133750
|
+
_StructCollector.unmarkOpaqueTypesOnDefinition(
|
|
133751
|
+
symbolTable,
|
|
133752
|
+
structTag,
|
|
133753
|
+
typedefName
|
|
133754
|
+
);
|
|
133755
|
+
}
|
|
133756
|
+
}
|
|
133757
|
+
/**
|
|
133758
|
+
* Unmark opaque types when a full struct definition is encountered.
|
|
133759
|
+
* Handles: typedef struct _foo foo; struct _foo { ... };
|
|
133760
|
+
*/
|
|
133761
|
+
static unmarkOpaqueTypesOnDefinition(symbolTable, structTag, typedefName) {
|
|
133762
|
+
if (structTag) {
|
|
133763
|
+
symbolTable.unmarkOpaqueType(structTag);
|
|
133764
|
+
const typedefAlias = symbolTable.getStructTagAlias(structTag);
|
|
133765
|
+
if (typedefAlias) {
|
|
133766
|
+
symbolTable.unmarkOpaqueType(typedefAlias);
|
|
133767
|
+
}
|
|
133768
|
+
}
|
|
133769
|
+
if (typedefName) {
|
|
133770
|
+
symbolTable.unmarkOpaqueType(typedefName);
|
|
133771
|
+
}
|
|
133772
|
+
}
|
|
133279
133773
|
/**
|
|
133280
133774
|
* Collect fields from a struct/union definition.
|
|
133281
133775
|
*/
|
|
@@ -133412,6 +133906,15 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133412
133906
|
isArray: p.isArray
|
|
133413
133907
|
}));
|
|
133414
133908
|
}
|
|
133909
|
+
/**
|
|
133910
|
+
* Resolve return type, appending '*' if declarator has a pointer.
|
|
133911
|
+
* Issue #895 Bug B / Issue #945: C grammar puts pointer before directDeclarator
|
|
133912
|
+
* (e.g., `widget_t *func()` has declarator.pointer() !== null)
|
|
133913
|
+
*/
|
|
133914
|
+
static _resolveReturnType(baseType, declarator) {
|
|
133915
|
+
const hasPointer = declarator.pointer() !== null;
|
|
133916
|
+
return hasPointer ? `${baseType}*` : baseType;
|
|
133917
|
+
}
|
|
133415
133918
|
/**
|
|
133416
133919
|
* Collect a function symbol from a function definition.
|
|
133417
133920
|
*
|
|
@@ -133425,7 +133928,11 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133425
133928
|
if (!name) return null;
|
|
133426
133929
|
const line = funcDef.start?.line ?? 0;
|
|
133427
133930
|
const declSpecs = funcDef.declarationSpecifiers();
|
|
133428
|
-
const
|
|
133931
|
+
const baseType = declSpecs ? DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs) : "int";
|
|
133932
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
133933
|
+
baseType,
|
|
133934
|
+
declarator
|
|
133935
|
+
);
|
|
133429
133936
|
const parameters = _FunctionCollector._mapParameters(
|
|
133430
133937
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133431
133938
|
);
|
|
@@ -133455,8 +133962,10 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133455
133962
|
const parameters = _FunctionCollector._mapParameters(
|
|
133456
133963
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133457
133964
|
);
|
|
133458
|
-
const
|
|
133459
|
-
|
|
133965
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
133966
|
+
baseType,
|
|
133967
|
+
declarator
|
|
133968
|
+
);
|
|
133460
133969
|
return {
|
|
133461
133970
|
kind: "function",
|
|
133462
133971
|
name,
|
|
@@ -133599,39 +134108,33 @@ var CResolver = class _CResolver {
|
|
|
133599
134108
|
const line = decl.start?.line ?? 0;
|
|
133600
134109
|
const isTypedef = DeclaratorUtils_default.hasStorageClass(declSpecs, "typedef");
|
|
133601
134110
|
const isExtern = DeclaratorUtils_default.hasStorageClass(declSpecs, "extern");
|
|
134111
|
+
const ctx = {
|
|
134112
|
+
sourceFile,
|
|
134113
|
+
line,
|
|
134114
|
+
isTypedef,
|
|
134115
|
+
isExtern,
|
|
134116
|
+
symbols
|
|
134117
|
+
};
|
|
133602
134118
|
const structSpec = DeclaratorUtils_default.findStructOrUnionSpecifier(declSpecs);
|
|
133603
134119
|
if (structSpec) {
|
|
133604
|
-
|
|
133605
|
-
const structSymbol = StructCollector_default2.collect(
|
|
134120
|
+
_CResolver.collectStructSymbol(
|
|
133606
134121
|
structSpec,
|
|
133607
|
-
|
|
133608
|
-
|
|
134122
|
+
decl,
|
|
134123
|
+
declSpecs,
|
|
134124
|
+
ctx,
|
|
133609
134125
|
symbolTable,
|
|
133610
|
-
typedefName,
|
|
133611
|
-
isTypedef,
|
|
133612
134126
|
warnings
|
|
133613
134127
|
);
|
|
133614
|
-
if (structSymbol) {
|
|
133615
|
-
symbols.push(structSymbol);
|
|
133616
|
-
}
|
|
133617
134128
|
}
|
|
133618
134129
|
const enumSpec = DeclaratorUtils_default.findEnumSpecifier(declSpecs);
|
|
133619
134130
|
if (enumSpec) {
|
|
133620
|
-
|
|
133621
|
-
|
|
133622
|
-
|
|
133623
|
-
|
|
133624
|
-
|
|
133625
|
-
|
|
133626
|
-
}
|
|
134131
|
+
_CResolver.collectEnumSymbols(
|
|
134132
|
+
enumSpec,
|
|
134133
|
+
ctx.sourceFile,
|
|
134134
|
+
ctx.line,
|
|
134135
|
+
ctx.symbols
|
|
134136
|
+
);
|
|
133627
134137
|
}
|
|
133628
|
-
const ctx = {
|
|
133629
|
-
sourceFile,
|
|
133630
|
-
line,
|
|
133631
|
-
isTypedef,
|
|
133632
|
-
isExtern,
|
|
133633
|
-
symbols
|
|
133634
|
-
};
|
|
133635
134138
|
const initDeclList = decl.initDeclaratorList();
|
|
133636
134139
|
if (initDeclList) {
|
|
133637
134140
|
const baseType = DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs);
|
|
@@ -133645,6 +134148,49 @@ var CResolver = class _CResolver {
|
|
|
133645
134148
|
);
|
|
133646
134149
|
}
|
|
133647
134150
|
}
|
|
134151
|
+
/**
|
|
134152
|
+
* Collect struct symbol from a struct specifier.
|
|
134153
|
+
* Extracted to reduce cognitive complexity of collectDeclaration().
|
|
134154
|
+
*/
|
|
134155
|
+
static collectStructSymbol(structSpec, decl, declSpecs, ctx, symbolTable, warnings) {
|
|
134156
|
+
const typedefName = ctx.isTypedef ? _CResolver.extractTypedefName(decl, declSpecs) : void 0;
|
|
134157
|
+
const structSymbol = StructCollector_default2.collect(
|
|
134158
|
+
structSpec,
|
|
134159
|
+
ctx.sourceFile,
|
|
134160
|
+
ctx.line,
|
|
134161
|
+
symbolTable,
|
|
134162
|
+
typedefName,
|
|
134163
|
+
ctx.isTypedef,
|
|
134164
|
+
warnings
|
|
134165
|
+
);
|
|
134166
|
+
if (structSymbol) {
|
|
134167
|
+
ctx.symbols.push(structSymbol);
|
|
134168
|
+
}
|
|
134169
|
+
}
|
|
134170
|
+
/**
|
|
134171
|
+
* Extract typedef name from declaration.
|
|
134172
|
+
* First try from init-declarator-list, then fall back to specifiers.
|
|
134173
|
+
*/
|
|
134174
|
+
static extractTypedefName(decl, declSpecs) {
|
|
134175
|
+
const initDeclList = decl.initDeclaratorList();
|
|
134176
|
+
if (initDeclList) {
|
|
134177
|
+
const name = DeclaratorUtils_default.extractFirstDeclaratorName(initDeclList);
|
|
134178
|
+
if (name) return name;
|
|
134179
|
+
}
|
|
134180
|
+
return DeclaratorUtils_default.extractTypedefNameFromSpecs(declSpecs);
|
|
134181
|
+
}
|
|
134182
|
+
/**
|
|
134183
|
+
* Collect enum symbols from an enum specifier.
|
|
134184
|
+
* Extracted to reduce cognitive complexity of collectDeclaration().
|
|
134185
|
+
*/
|
|
134186
|
+
static collectEnumSymbols(enumSpec, sourceFile, line, symbols) {
|
|
134187
|
+
const enumResult = EnumCollector_default2.collect(enumSpec, sourceFile, line);
|
|
134188
|
+
if (!enumResult) return;
|
|
134189
|
+
symbols.push(enumResult.enum);
|
|
134190
|
+
for (const member of enumResult.members) {
|
|
134191
|
+
symbols.push(member);
|
|
134192
|
+
}
|
|
134193
|
+
}
|
|
133648
134194
|
/**
|
|
133649
134195
|
* Collect symbols from init declarator list.
|
|
133650
134196
|
*/
|
|
@@ -137838,6 +138384,9 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137838
138384
|
if (TypeConstants_default.UNSIGNED_INDEX_TYPES.includes(resolvedType)) {
|
|
137839
138385
|
continue;
|
|
137840
138386
|
}
|
|
138387
|
+
if (CodeGenState.isKnownEnum(resolvedType)) {
|
|
138388
|
+
continue;
|
|
138389
|
+
}
|
|
137841
138390
|
const { line, column } = ParserUtils_default.getPosition(ctx);
|
|
137842
138391
|
this.analyzer.addError(line, column, "E0852", resolvedType);
|
|
137843
138392
|
return;
|
|
@@ -137927,6 +138476,10 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137927
138476
|
if (TypeConstants_default.SIGNED_TYPES.includes(currentType)) {
|
|
137928
138477
|
return "bool";
|
|
137929
138478
|
}
|
|
138479
|
+
const strippedType = currentType.replace(/\[[^\]]*\]$/, "");
|
|
138480
|
+
if (strippedType !== currentType) {
|
|
138481
|
+
return strippedType;
|
|
138482
|
+
}
|
|
137930
138483
|
return currentType;
|
|
137931
138484
|
}
|
|
137932
138485
|
if (op.LPAREN()) {
|
|
@@ -138327,7 +138880,7 @@ var CacheKeyGenerator_default = CacheKeyGenerator;
|
|
|
138327
138880
|
|
|
138328
138881
|
// src/utils/cache/CacheManager.ts
|
|
138329
138882
|
var defaultFs7 = NodeFileSystem_default.instance;
|
|
138330
|
-
var CACHE_VERSION =
|
|
138883
|
+
var CACHE_VERSION = 5;
|
|
138331
138884
|
var TRANSPILER_VERSION = package_default.version;
|
|
138332
138885
|
var CacheManager = class {
|
|
138333
138886
|
projectRoot;
|
|
@@ -138427,14 +138980,15 @@ var CacheManager = class {
|
|
|
138427
138980
|
symbols,
|
|
138428
138981
|
structFields,
|
|
138429
138982
|
needsStructKeyword: cachedEntry.needsStructKeyword ?? [],
|
|
138430
|
-
enumBitWidth
|
|
138983
|
+
enumBitWidth,
|
|
138984
|
+
opaqueTypes: cachedEntry.opaqueTypes ?? []
|
|
138431
138985
|
};
|
|
138432
138986
|
}
|
|
138433
138987
|
/**
|
|
138434
138988
|
* Store symbols and struct fields for a file
|
|
138435
138989
|
* ADR-055 Phase 7: Takes ISerializedSymbol[] directly
|
|
138436
138990
|
*/
|
|
138437
|
-
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth) {
|
|
138991
|
+
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth, opaqueTypes) {
|
|
138438
138992
|
if (!this.cache) return;
|
|
138439
138993
|
let cacheKey;
|
|
138440
138994
|
try {
|
|
@@ -138462,7 +139016,8 @@ var CacheManager = class {
|
|
|
138462
139016
|
symbols: serializedSymbols,
|
|
138463
139017
|
structFields: serializedFields,
|
|
138464
139018
|
needsStructKeyword,
|
|
138465
|
-
enumBitWidth: serializedEnumBitWidth
|
|
139019
|
+
enumBitWidth: serializedEnumBitWidth,
|
|
139020
|
+
opaqueTypes
|
|
138466
139021
|
};
|
|
138467
139022
|
this.cache.setKey(filePath, entry);
|
|
138468
139023
|
this.dirty = true;
|
|
@@ -138490,12 +139045,14 @@ var CacheManager = class {
|
|
|
138490
139045
|
filePath,
|
|
138491
139046
|
symbolTable
|
|
138492
139047
|
);
|
|
139048
|
+
const opaqueTypes = symbolTable.getAllOpaqueTypes();
|
|
138493
139049
|
this.setSymbols(
|
|
138494
139050
|
filePath,
|
|
138495
139051
|
symbols,
|
|
138496
139052
|
structFields,
|
|
138497
139053
|
needsStructKeyword,
|
|
138498
|
-
enumBitWidth
|
|
139054
|
+
enumBitWidth,
|
|
139055
|
+
opaqueTypes
|
|
138499
139056
|
);
|
|
138500
139057
|
}
|
|
138501
139058
|
/**
|
|
@@ -138938,7 +139495,7 @@ var Transpiler = class {
|
|
|
138938
139495
|
* Stage 6: Generate headers (per-file)
|
|
138939
139496
|
*/
|
|
138940
139497
|
async _executePipeline(input, result) {
|
|
138941
|
-
this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
139498
|
+
await this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
138942
139499
|
CodeGenState.buildExternalStructFields();
|
|
138943
139500
|
if (!this._collectAllCNextSymbolsFromPipeline(input.cnextFiles, result)) {
|
|
138944
139501
|
return;
|
|
@@ -139047,6 +139604,13 @@ var Transpiler = class {
|
|
|
139047
139604
|
externalEnumSources
|
|
139048
139605
|
);
|
|
139049
139606
|
}
|
|
139607
|
+
const externalOpaqueTypes = CodeGenState.symbolTable.getAllOpaqueTypes();
|
|
139608
|
+
if (externalOpaqueTypes.length > 0) {
|
|
139609
|
+
symbolInfo = TSymbolInfoAdapter_default.mergeOpaqueTypes(
|
|
139610
|
+
symbolInfo,
|
|
139611
|
+
externalOpaqueTypes
|
|
139612
|
+
);
|
|
139613
|
+
}
|
|
139050
139614
|
CodeGenState.symbols = symbolInfo;
|
|
139051
139615
|
const analyzerErrors = runAnalyzers_default(tree, tokenStream);
|
|
139052
139616
|
if (analyzerErrors.length > 0) {
|
|
@@ -139220,11 +139784,12 @@ var Transpiler = class {
|
|
|
139220
139784
|
}
|
|
139221
139785
|
/**
|
|
139222
139786
|
* Stage 2: Collect symbols from all C/C++ headers
|
|
139787
|
+
* Issue #945: Made async for preprocessing support.
|
|
139223
139788
|
*/
|
|
139224
|
-
_collectAllHeaderSymbols(headerFiles, result) {
|
|
139789
|
+
async _collectAllHeaderSymbols(headerFiles, result) {
|
|
139225
139790
|
for (const file of headerFiles) {
|
|
139226
139791
|
try {
|
|
139227
|
-
this.doCollectHeaderSymbols(file);
|
|
139792
|
+
await this.doCollectHeaderSymbols(file);
|
|
139228
139793
|
result.filesProcessed++;
|
|
139229
139794
|
} catch (err) {
|
|
139230
139795
|
this.warnings.push(`Failed to process header ${file.path}: ${err}`);
|
|
@@ -139503,15 +140068,16 @@ var Transpiler = class {
|
|
|
139503
140068
|
/**
|
|
139504
140069
|
* Stage 2: Collect symbols from a single C/C++ header
|
|
139505
140070
|
* Issue #592: Recursive include processing moved to IncludeResolver.resolveHeadersTransitively()
|
|
140071
|
+
* Issue #945: Added preprocessing support for conditional compilation
|
|
139506
140072
|
* SonarCloud S3776: Refactored to use helper methods for reduced complexity.
|
|
139507
140073
|
*/
|
|
139508
|
-
doCollectHeaderSymbols(file) {
|
|
140074
|
+
async doCollectHeaderSymbols(file) {
|
|
139509
140075
|
const absolutePath = resolve12(file.path);
|
|
139510
140076
|
this.state.markHeaderProcessed(absolutePath);
|
|
139511
140077
|
if (this.tryRestoreFromCache(file)) {
|
|
139512
140078
|
return;
|
|
139513
140079
|
}
|
|
139514
|
-
const content = this.
|
|
140080
|
+
const content = await this.getHeaderContent(file);
|
|
139515
140081
|
this.parseHeaderFile(file, content);
|
|
139516
140082
|
if (this.config.debugMode) {
|
|
139517
140083
|
const symbols = CodeGenState.symbolTable.getSymbolsByFile(file.path);
|
|
@@ -139542,9 +140108,51 @@ var Transpiler = class {
|
|
|
139542
140108
|
cached.needsStructKeyword
|
|
139543
140109
|
);
|
|
139544
140110
|
CodeGenState.symbolTable.restoreEnumBitWidths(cached.enumBitWidth);
|
|
140111
|
+
CodeGenState.symbolTable.restoreOpaqueTypes(cached.opaqueTypes);
|
|
139545
140112
|
this.detectCppFromFileType(file);
|
|
139546
140113
|
return true;
|
|
139547
140114
|
}
|
|
140115
|
+
/**
|
|
140116
|
+
* Get header content, optionally preprocessed.
|
|
140117
|
+
* Issue #945: Evaluates #if/#ifdef directives using system preprocessor.
|
|
140118
|
+
*
|
|
140119
|
+
* Only preprocesses when necessary to avoid side effects from full expansion.
|
|
140120
|
+
* Preprocessing is needed when the file has conditional compilation patterns
|
|
140121
|
+
* like #if MACRO != 0 that require expression evaluation.
|
|
140122
|
+
*/
|
|
140123
|
+
async getHeaderContent(file) {
|
|
140124
|
+
const rawContent = this.fs.readFile(file.path);
|
|
140125
|
+
if (this.config.preprocess === false) {
|
|
140126
|
+
return rawContent;
|
|
140127
|
+
}
|
|
140128
|
+
if (!this.preprocessor.isAvailable()) {
|
|
140129
|
+
return rawContent;
|
|
140130
|
+
}
|
|
140131
|
+
if (!this.needsConditionalPreprocessing(rawContent)) {
|
|
140132
|
+
return rawContent;
|
|
140133
|
+
}
|
|
140134
|
+
const result = await this.preprocessor.preprocess(file.path, {
|
|
140135
|
+
defines: this.config.defines,
|
|
140136
|
+
includePaths: this.config.includeDirs,
|
|
140137
|
+
keepLineDirectives: false
|
|
140138
|
+
// We don't need line mappings for symbol collection
|
|
140139
|
+
});
|
|
140140
|
+
if (!result.success) {
|
|
140141
|
+
this.warnings.push(
|
|
140142
|
+
`Preprocessing failed for ${file.path}: ${result.error}. Using raw content.`
|
|
140143
|
+
);
|
|
140144
|
+
return rawContent;
|
|
140145
|
+
}
|
|
140146
|
+
return result.content;
|
|
140147
|
+
}
|
|
140148
|
+
/**
|
|
140149
|
+
* Check if a header file needs conditional preprocessing.
|
|
140150
|
+
* Issue #945: Only preprocess files with #if expressions that need evaluation.
|
|
140151
|
+
*/
|
|
140152
|
+
needsConditionalPreprocessing(content) {
|
|
140153
|
+
const ifExpressionPattern = /#(?:if|elif)\s+(?!defined\s*\()(?![01]\s*(?:$|\n|\/\*|\/\/))\w+/m;
|
|
140154
|
+
return ifExpressionPattern.test(content);
|
|
140155
|
+
}
|
|
139548
140156
|
/**
|
|
139549
140157
|
* Restore cached symbols to the symbol table.
|
|
139550
140158
|
* ADR-055 Phase 7: Converts ISerializedSymbol[] from cache to typed symbols.
|