c-next 0.2.8 → 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 +1019 -267
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +101 -8
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +170 -0
- package/src/transpiler/__tests__/needsConditionalPreprocessing.test.ts +246 -0
- package/src/transpiler/logic/IncludeExtractor.ts +12 -6
- package/src/transpiler/logic/__tests__/IncludeExtractor.test.ts +24 -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 +55 -25
- package/src/transpiler/output/codegen/TypeResolver.ts +14 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +3 -3
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +35 -30
- 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 +25 -3
- 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 +26 -6
- package/src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts +31 -2
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +72 -13
- package/src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts +25 -1
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +2 -1
- package/src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts +2 -17
- package/src/transpiler/output/codegen/generators/support/IncludeGenerator.ts +19 -7
- package/src/transpiler/output/codegen/generators/support/__tests__/IncludeGenerator.test.ts +68 -0
- package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +14 -2
- package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +3 -0
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +3 -5
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +56 -8
- 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 -5
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +131 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +61 -2
- 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/output/headers/HeaderGeneratorUtils.ts +14 -16
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +25 -0
- package/src/transpiler/state/CodeGenState.ts +89 -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
|
};
|
|
@@ -110828,6 +110902,13 @@ var CodeGenState = class {
|
|
|
110828
110902
|
static inFunctionBody = false;
|
|
110829
110903
|
/** Expected type for struct initializers and enum inference */
|
|
110830
110904
|
static expectedType = null;
|
|
110905
|
+
/**
|
|
110906
|
+
* Suppress bare enum resolution even when expectedType is set.
|
|
110907
|
+
* Issue #872: MISRA 7.2 requires expectedType for U suffix on function args,
|
|
110908
|
+
* but bare enum resolution in function args was never allowed and changing
|
|
110909
|
+
* that would require ADR approval.
|
|
110910
|
+
*/
|
|
110911
|
+
static suppressBareEnumResolution = false;
|
|
110831
110912
|
/** Track args parameter name for main() translation */
|
|
110832
110913
|
static mainArgsName = null;
|
|
110833
110914
|
/** ADR-044: Current assignment context for overflow behavior */
|
|
@@ -110864,6 +110945,16 @@ var CodeGenState = class {
|
|
|
110864
110945
|
/** Issue #473: IRQ wrappers for critical sections */
|
|
110865
110946
|
static needsIrqWrappers = false;
|
|
110866
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
|
+
// ===========================================================================
|
|
110867
110958
|
// C++ MODE STATE (Issue #250)
|
|
110868
110959
|
// ===========================================================================
|
|
110869
110960
|
/** Use temp vars instead of compound literals */
|
|
@@ -110922,6 +111013,7 @@ var CodeGenState = class {
|
|
|
110922
111013
|
this.indentLevel = 0;
|
|
110923
111014
|
this.inFunctionBody = false;
|
|
110924
111015
|
this.expectedType = null;
|
|
111016
|
+
this.suppressBareEnumResolution = false;
|
|
110925
111017
|
this.mainArgsName = null;
|
|
110926
111018
|
this.assignmentContext = {
|
|
110927
111019
|
targetName: null,
|
|
@@ -110946,6 +111038,7 @@ var CodeGenState = class {
|
|
|
110946
111038
|
this.tempVarCounter = 0;
|
|
110947
111039
|
this.pendingCppClassAssignments = [];
|
|
110948
111040
|
this.selfIncludeAdded = false;
|
|
111041
|
+
this.opaqueScopeVariables = /* @__PURE__ */ new Set();
|
|
110949
111042
|
this.sourcePath = null;
|
|
110950
111043
|
this.includeDirs = [];
|
|
110951
111044
|
this.inputs = [];
|
|
@@ -110972,6 +111065,32 @@ var CodeGenState = class {
|
|
|
110972
111065
|
this.floatBitShadows.clear();
|
|
110973
111066
|
this.floatShadowCurrent.clear();
|
|
110974
111067
|
}
|
|
111068
|
+
/**
|
|
111069
|
+
* Execute a function with a temporary expectedType, restoring on completion.
|
|
111070
|
+
* Issue #872: Extracted to eliminate duplicate save/restore pattern and add exception safety.
|
|
111071
|
+
*
|
|
111072
|
+
* @param type - The expected type to set (if falsy, no change is made)
|
|
111073
|
+
* @param fn - The function to execute
|
|
111074
|
+
* @param suppressEnumResolution - If true, suppress bare enum resolution (for MISRA-only contexts)
|
|
111075
|
+
* @returns The result of the function
|
|
111076
|
+
*/
|
|
111077
|
+
static withExpectedType(type, fn, suppressEnumResolution = false) {
|
|
111078
|
+
if (!type) {
|
|
111079
|
+
return fn();
|
|
111080
|
+
}
|
|
111081
|
+
const savedType = this.expectedType;
|
|
111082
|
+
const savedSuppress = this.suppressBareEnumResolution;
|
|
111083
|
+
this.expectedType = type;
|
|
111084
|
+
if (suppressEnumResolution) {
|
|
111085
|
+
this.suppressBareEnumResolution = true;
|
|
111086
|
+
}
|
|
111087
|
+
try {
|
|
111088
|
+
return fn();
|
|
111089
|
+
} finally {
|
|
111090
|
+
this.expectedType = savedType;
|
|
111091
|
+
this.suppressBareEnumResolution = savedSuppress;
|
|
111092
|
+
}
|
|
111093
|
+
}
|
|
110975
111094
|
// ===========================================================================
|
|
110976
111095
|
// CONVENIENCE LOOKUP METHODS
|
|
110977
111096
|
// ===========================================================================
|
|
@@ -111009,6 +111128,14 @@ var CodeGenState = class {
|
|
|
111009
111128
|
static isKnownRegister(name) {
|
|
111010
111129
|
return this.symbols?.knownRegisters.has(name) ?? false;
|
|
111011
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
|
+
}
|
|
111012
111139
|
/**
|
|
111013
111140
|
* Get type info for a variable.
|
|
111014
111141
|
* Checks local typeRegistry first, then falls back to SymbolTable
|
|
@@ -111448,6 +111575,28 @@ var CodeGenState = class {
|
|
|
111448
111575
|
return this.floatShadowCurrent.has(name);
|
|
111449
111576
|
}
|
|
111450
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
|
+
// ===========================================================================
|
|
111451
111600
|
// C++ MODE HELPERS
|
|
111452
111601
|
// ===========================================================================
|
|
111453
111602
|
/**
|
|
@@ -113157,6 +113306,12 @@ var TypeResolver2 = class _TypeResolver {
|
|
|
113157
113306
|
if (floatMatch) {
|
|
113158
113307
|
return "f" + floatMatch[1];
|
|
113159
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
|
+
}
|
|
113160
113315
|
return null;
|
|
113161
113316
|
}
|
|
113162
113317
|
/**
|
|
@@ -114416,6 +114571,229 @@ var GeneratorRegistry = class {
|
|
|
114416
114571
|
}
|
|
114417
114572
|
};
|
|
114418
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
|
+
|
|
114419
114797
|
// src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts
|
|
114420
114798
|
var UNSIGNED_64_TYPES = /* @__PURE__ */ new Set(["u64", "uint64_t"]);
|
|
114421
114799
|
var UNSIGNED_TYPES3 = /* @__PURE__ */ new Set([
|
|
@@ -114424,8 +114802,14 @@ var UNSIGNED_TYPES3 = /* @__PURE__ */ new Set([
|
|
|
114424
114802
|
"u32",
|
|
114425
114803
|
"uint8_t",
|
|
114426
114804
|
"uint16_t",
|
|
114427
|
-
"uint32_t"
|
|
114805
|
+
"uint32_t",
|
|
114806
|
+
"size_t"
|
|
114807
|
+
// Array indices (MISRA 7.2)
|
|
114428
114808
|
]);
|
|
114809
|
+
function resolveTypedef(typeName) {
|
|
114810
|
+
const underlyingType = CodeGenState.getTypedefType(typeName);
|
|
114811
|
+
return underlyingType ?? typeName;
|
|
114812
|
+
}
|
|
114429
114813
|
function isNumericIntegerLiteral(text) {
|
|
114430
114814
|
if (text.startsWith('"') || text.startsWith("'")) {
|
|
114431
114815
|
return false;
|
|
@@ -114450,6 +114834,18 @@ var generateLiteral = (node, _input, state, _orchestrator) => {
|
|
|
114450
114834
|
effects.push({ type: "include", header: "stdbool" });
|
|
114451
114835
|
return { code: literalText, effects };
|
|
114452
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
|
+
}
|
|
114453
114849
|
if (/[fF]32$/.test(literalText)) {
|
|
114454
114850
|
literalText = literalText.replace(/[fF]32$/, "f");
|
|
114455
114851
|
return { code: literalText, effects };
|
|
@@ -114471,9 +114867,10 @@ var generateLiteral = (node, _input, state, _orchestrator) => {
|
|
|
114471
114867
|
}
|
|
114472
114868
|
const expectedType = state?.expectedType;
|
|
114473
114869
|
if (expectedType && isNumericIntegerLiteral(literalText) && !hasUnsignedSuffix(literalText)) {
|
|
114474
|
-
|
|
114870
|
+
const resolvedType = resolveTypedef(expectedType);
|
|
114871
|
+
if (UNSIGNED_64_TYPES.has(resolvedType)) {
|
|
114475
114872
|
literalText = literalText + "ULL";
|
|
114476
|
-
} else if (UNSIGNED_TYPES3.has(
|
|
114873
|
+
} else if (UNSIGNED_TYPES3.has(resolvedType)) {
|
|
114477
114874
|
literalText = literalText + "U";
|
|
114478
114875
|
}
|
|
114479
114876
|
}
|
|
@@ -114810,96 +115207,9 @@ var binaryExprGenerators = {
|
|
|
114810
115207
|
};
|
|
114811
115208
|
var BinaryExprGenerator_default = binaryExprGenerators;
|
|
114812
115209
|
|
|
114813
|
-
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114814
|
-
var CppModeHelper = class {
|
|
114815
|
-
/**
|
|
114816
|
-
* Get address-of expression for struct parameter passing.
|
|
114817
|
-
* C mode: `&expr` (pass pointer to struct)
|
|
114818
|
-
* C++ mode: `expr` (pass reference directly)
|
|
114819
|
-
*
|
|
114820
|
-
* @param expr - The expression to potentially wrap
|
|
114821
|
-
* @returns The expression with address-of operator in C mode
|
|
114822
|
-
*/
|
|
114823
|
-
static maybeAddressOf(expr) {
|
|
114824
|
-
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114825
|
-
}
|
|
114826
|
-
/**
|
|
114827
|
-
* Get dereference expression for struct parameter access.
|
|
114828
|
-
* C mode: `(*expr)` (dereference pointer)
|
|
114829
|
-
* C++ mode: `expr` (reference can be used directly)
|
|
114830
|
-
*
|
|
114831
|
-
* @param expr - The expression to potentially dereference
|
|
114832
|
-
* @returns The expression with dereference in C mode
|
|
114833
|
-
*/
|
|
114834
|
-
static maybeDereference(expr) {
|
|
114835
|
-
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114836
|
-
}
|
|
114837
|
-
/**
|
|
114838
|
-
* Get the type modifier for struct parameter declarations.
|
|
114839
|
-
* C mode: `*` (pointer type)
|
|
114840
|
-
* C++ mode: `&` (reference type)
|
|
114841
|
-
*
|
|
114842
|
-
* @returns The type modifier character
|
|
114843
|
-
*/
|
|
114844
|
-
static refOrPtr() {
|
|
114845
|
-
return CodeGenState.cppMode ? "&" : "*";
|
|
114846
|
-
}
|
|
114847
|
-
/**
|
|
114848
|
-
* Get the member access separator for struct parameters.
|
|
114849
|
-
* C mode: `->` (pointer member access)
|
|
114850
|
-
* C++ mode: `.` (reference member access)
|
|
114851
|
-
*
|
|
114852
|
-
* @returns The member access separator
|
|
114853
|
-
*/
|
|
114854
|
-
static memberSeparator() {
|
|
114855
|
-
return CodeGenState.cppMode ? "." : "->";
|
|
114856
|
-
}
|
|
114857
|
-
/**
|
|
114858
|
-
* Get NULL literal for the current mode.
|
|
114859
|
-
* C mode: `NULL`
|
|
114860
|
-
* C++ mode: `nullptr`
|
|
114861
|
-
*
|
|
114862
|
-
* @returns The null pointer literal
|
|
114863
|
-
*/
|
|
114864
|
-
static nullLiteral() {
|
|
114865
|
-
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114866
|
-
}
|
|
114867
|
-
/**
|
|
114868
|
-
* Generate a cast expression for the current mode.
|
|
114869
|
-
* C mode: `(type)expr`
|
|
114870
|
-
* C++ mode: `static_cast<type>(expr)`
|
|
114871
|
-
*
|
|
114872
|
-
* @param type - The target type
|
|
114873
|
-
* @param expr - The expression to cast
|
|
114874
|
-
* @returns The cast expression
|
|
114875
|
-
*/
|
|
114876
|
-
static cast(type, expr) {
|
|
114877
|
-
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114878
|
-
}
|
|
114879
|
-
/**
|
|
114880
|
-
* Generate a reinterpret cast expression for the current mode.
|
|
114881
|
-
* C mode: `(type)expr`
|
|
114882
|
-
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114883
|
-
*
|
|
114884
|
-
* @param type - The target type
|
|
114885
|
-
* @param expr - The expression to cast
|
|
114886
|
-
* @returns The cast expression
|
|
114887
|
-
*/
|
|
114888
|
-
static reinterpretCast(type, expr) {
|
|
114889
|
-
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114890
|
-
}
|
|
114891
|
-
/**
|
|
114892
|
-
* Check if we're in C++ mode.
|
|
114893
|
-
*
|
|
114894
|
-
* @returns True if generating C++ code
|
|
114895
|
-
*/
|
|
114896
|
-
static isCppMode() {
|
|
114897
|
-
return CodeGenState.cppMode;
|
|
114898
|
-
}
|
|
114899
|
-
};
|
|
114900
|
-
var CppModeHelper_default = CppModeHelper;
|
|
114901
|
-
|
|
114902
115210
|
// src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts
|
|
115211
|
+
var INT32_MIN_LITERAL = "2147483648";
|
|
115212
|
+
var INT64_MIN_LITERAL = "9223372036854775808";
|
|
114903
115213
|
var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
114904
115214
|
if (node.postfixExpression()) {
|
|
114905
115215
|
return {
|
|
@@ -114910,7 +115220,18 @@ var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
|
114910
115220
|
const inner = orchestrator.generateUnaryExpr(node.unaryExpression());
|
|
114911
115221
|
const text = node.getText();
|
|
114912
115222
|
if (text.startsWith("!")) return { code: `!${inner}`, effects: [] };
|
|
114913
|
-
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
|
+
}
|
|
114914
115235
|
if (text.startsWith("~")) {
|
|
114915
115236
|
const innerType = TypeResolver_default2.getUnaryExpressionType(
|
|
114916
115237
|
node.unaryExpression()
|
|
@@ -114973,15 +115294,18 @@ var generateSizeProperty = (typeInfo) => {
|
|
|
114973
115294
|
throw new Error(`Error: .size is only available on string types`);
|
|
114974
115295
|
};
|
|
114975
115296
|
var generateBitmapFieldAccess = (result, fieldInfo) => {
|
|
115297
|
+
let expr;
|
|
114976
115298
|
if (fieldInfo.width === 1) {
|
|
114977
|
-
|
|
115299
|
+
expr = `((${result} >> ${fieldInfo.offset}) & 1)`;
|
|
114978
115300
|
} else {
|
|
114979
115301
|
const mask = (1 << fieldInfo.width) - 1;
|
|
114980
|
-
|
|
114981
|
-
|
|
114982
|
-
|
|
114983
|
-
|
|
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);
|
|
114984
115307
|
}
|
|
115308
|
+
return { code: expr, effects: [] };
|
|
114985
115309
|
};
|
|
114986
115310
|
var accessGenerators = {
|
|
114987
115311
|
generateCapacityProperty,
|
|
@@ -115138,7 +115462,12 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115138
115462
|
orchestrator
|
|
115139
115463
|
);
|
|
115140
115464
|
}
|
|
115141
|
-
|
|
115465
|
+
const argCode = CodeGenState.withExpectedType(
|
|
115466
|
+
targetParam?.baseType,
|
|
115467
|
+
() => orchestrator.generateExpression(e),
|
|
115468
|
+
true
|
|
115469
|
+
// suppressEnumResolution
|
|
115470
|
+
);
|
|
115142
115471
|
if (!targetParam?.baseType?.endsWith("*")) {
|
|
115143
115472
|
return wrapWithCppEnumCast(argCode, e, targetParam?.baseType, orchestrator);
|
|
115144
115473
|
}
|
|
@@ -115153,11 +115482,15 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115153
115482
|
if (typeInfo?.isPointer) {
|
|
115154
115483
|
isPointerVariable = true;
|
|
115155
115484
|
}
|
|
115156
|
-
const
|
|
115157
|
-
|
|
115158
|
-
|
|
115159
|
-
|
|
115160
|
-
|
|
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));
|
|
115487
|
+
const finalArgCode = needsAddressOf ? `&${argCode}` : argCode;
|
|
115488
|
+
return wrapWithCppEnumCast(
|
|
115489
|
+
finalArgCode,
|
|
115490
|
+
e,
|
|
115491
|
+
targetParam?.baseType,
|
|
115492
|
+
orchestrator
|
|
115493
|
+
);
|
|
115161
115494
|
};
|
|
115162
115495
|
var _shouldPassByValue = (funcExpr, idx, targetParam, isCrossFile, orchestrator) => {
|
|
115163
115496
|
if (!targetParam) return false;
|
|
@@ -115204,7 +115537,12 @@ var generateFunctionCall = (funcExpr, argCtx, input, _state, orchestrator) => {
|
|
|
115204
115537
|
resolved.isCrossFile,
|
|
115205
115538
|
orchestrator
|
|
115206
115539
|
)) {
|
|
115207
|
-
const argCode =
|
|
115540
|
+
const argCode = CodeGenState.withExpectedType(
|
|
115541
|
+
targetParam?.baseType,
|
|
115542
|
+
() => orchestrator.generateExpression(e),
|
|
115543
|
+
true
|
|
115544
|
+
// suppressEnumResolution
|
|
115545
|
+
);
|
|
115208
115546
|
return wrapWithCppEnumCast(
|
|
115209
115547
|
argCode,
|
|
115210
115548
|
e,
|
|
@@ -115283,7 +115621,7 @@ var trackPassThroughModifications = (funcName, argExprs, orchestrator) => {
|
|
|
115283
115621
|
var CallExprGenerator_default = generateFunctionCall;
|
|
115284
115622
|
|
|
115285
115623
|
// src/utils/TypeCheckUtils.ts
|
|
115286
|
-
var
|
|
115624
|
+
var INTEGER_TYPES3 = [
|
|
115287
115625
|
"u8",
|
|
115288
115626
|
"u16",
|
|
115289
115627
|
"u32",
|
|
@@ -115295,7 +115633,7 @@ var INTEGER_TYPES2 = [
|
|
|
115295
115633
|
];
|
|
115296
115634
|
var UNSIGNED_TYPES4 = ["u8", "u16", "u32", "u64"];
|
|
115297
115635
|
var SIGNED_TYPES3 = ["i8", "i16", "i32", "i64"];
|
|
115298
|
-
var
|
|
115636
|
+
var FLOAT_TYPES3 = ["f32", "f64"];
|
|
115299
115637
|
var STANDARD_WIDTHS = [8, 16, 32];
|
|
115300
115638
|
var TypeCheckUtils = class {
|
|
115301
115639
|
/**
|
|
@@ -115305,7 +115643,7 @@ var TypeCheckUtils = class {
|
|
|
115305
115643
|
* @returns true if it's u8, u16, u32, u64, i8, i16, i32, or i64
|
|
115306
115644
|
*/
|
|
115307
115645
|
static isInteger(typeName) {
|
|
115308
|
-
return
|
|
115646
|
+
return INTEGER_TYPES3.includes(typeName);
|
|
115309
115647
|
}
|
|
115310
115648
|
/**
|
|
115311
115649
|
* Check if a type name is an unsigned integer type.
|
|
@@ -115332,7 +115670,7 @@ var TypeCheckUtils = class {
|
|
|
115332
115670
|
* @returns true if it's f32 or f64
|
|
115333
115671
|
*/
|
|
115334
115672
|
static isFloat(typeName) {
|
|
115335
|
-
return
|
|
115673
|
+
return FLOAT_TYPES3.includes(typeName);
|
|
115336
115674
|
}
|
|
115337
115675
|
/**
|
|
115338
115676
|
* Check if a type name is a string type (string<N>).
|
|
@@ -116556,12 +116894,20 @@ var generateSubscriptAccess = (ctx, input, state, orchestrator, effects) => {
|
|
|
116556
116894
|
return output;
|
|
116557
116895
|
};
|
|
116558
116896
|
var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
116559
|
-
const index =
|
|
116897
|
+
const index = CodeGenState.withExpectedType(
|
|
116898
|
+
"size_t",
|
|
116899
|
+
() => orchestrator.generateExpression(expr)
|
|
116900
|
+
);
|
|
116560
116901
|
validateNotBitmapMember(ctx, input);
|
|
116561
116902
|
const isRegisterAccess = checkRegisterAccess(ctx, input);
|
|
116562
116903
|
const identifierTypeInfo = getIdentifierTypeInfo(ctx, input);
|
|
116563
116904
|
if (isRegisterAccess) {
|
|
116564
|
-
|
|
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;
|
|
116565
116911
|
return output;
|
|
116566
116912
|
}
|
|
116567
116913
|
if (ctx.currentMemberIsArray) {
|
|
@@ -116575,7 +116921,12 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116575
116921
|
}
|
|
116576
116922
|
const isPrimitiveIntMember = ctx.currentStructType && TypeCheckUtils_default.isInteger(ctx.currentStructType);
|
|
116577
116923
|
if (isPrimitiveIntMember) {
|
|
116578
|
-
|
|
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;
|
|
116579
116930
|
output.currentStructType = void 0;
|
|
116580
116931
|
return output;
|
|
116581
116932
|
}
|
|
@@ -116633,12 +116984,23 @@ var handleDefaultSubscript = (ctx, index, typeInfo, output) => {
|
|
|
116633
116984
|
subscriptCount: 1,
|
|
116634
116985
|
isRegisterAccess: false
|
|
116635
116986
|
});
|
|
116636
|
-
|
|
116987
|
+
if (subscriptKind === "bit_single") {
|
|
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;
|
|
116994
|
+
} else {
|
|
116995
|
+
output.result = `${ctx.result}[${index}]`;
|
|
116996
|
+
}
|
|
116637
116997
|
return output;
|
|
116638
116998
|
};
|
|
116639
116999
|
var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects, output) => {
|
|
116640
|
-
const start =
|
|
116641
|
-
|
|
117000
|
+
const [start, width] = CodeGenState.withExpectedType("size_t", () => [
|
|
117001
|
+
orchestrator.generateExpression(exprs[0]),
|
|
117002
|
+
orchestrator.generateExpression(exprs[1])
|
|
117003
|
+
]);
|
|
116642
117004
|
const isFloatType = ctx.primaryTypeInfo?.baseType === "f32" || ctx.primaryTypeInfo?.baseType === "f64";
|
|
116643
117005
|
if (isFloatType && ctx.rootIdentifier) {
|
|
116644
117006
|
output.result = handleFloatBitRange(
|
|
@@ -116655,10 +117017,24 @@ var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects,
|
|
|
116655
117017
|
);
|
|
116656
117018
|
} else {
|
|
116657
117019
|
const mask = orchestrator.generateBitMask(width);
|
|
116658
|
-
|
|
116659
|
-
|
|
117020
|
+
let expr;
|
|
117021
|
+
if (start === "0" || start === "0U") {
|
|
117022
|
+
expr = `((${ctx.result}) & ${mask})`;
|
|
116660
117023
|
} else {
|
|
116661
|
-
|
|
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;
|
|
116662
117038
|
}
|
|
116663
117039
|
}
|
|
116664
117040
|
return output;
|
|
@@ -116690,7 +117066,7 @@ var handleFloatBitRange = (ctx, state, orchestrator, effects) => {
|
|
|
116690
117066
|
if (!shadowIsCurrent) {
|
|
116691
117067
|
orchestrator.addPendingTempDeclaration(`${shadowName}.f = ${ctx.result};`);
|
|
116692
117068
|
}
|
|
116693
|
-
if (ctx.start === "0") {
|
|
117069
|
+
if (ctx.start === "0" || ctx.start === "0U") {
|
|
116694
117070
|
return `(${shadowName}.u & ${mask})`;
|
|
116695
117071
|
}
|
|
116696
117072
|
return `((${shadowName}.u >> ${ctx.start}) & ${mask})`;
|
|
@@ -116968,6 +117344,21 @@ var generateCriticalStatement = (node, _input, _state, orchestrator) => {
|
|
|
116968
117344
|
};
|
|
116969
117345
|
var CriticalGenerator_default = generateCriticalStatement;
|
|
116970
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
|
+
|
|
116971
117362
|
// src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts
|
|
116972
117363
|
var TYPE_MAP2 = {
|
|
116973
117364
|
u8: "uint8_t",
|
|
@@ -116995,18 +117386,6 @@ var STREX_MAP = {
|
|
|
116995
117386
|
u32: "__STREXW",
|
|
116996
117387
|
i32: "__STREXW"
|
|
116997
117388
|
};
|
|
116998
|
-
var SIMPLE_OP_MAP = {
|
|
116999
|
-
"+=": "+",
|
|
117000
|
-
"-=": "-",
|
|
117001
|
-
"*=": "*",
|
|
117002
|
-
"/=": "/",
|
|
117003
|
-
"%=": "%",
|
|
117004
|
-
"&=": "&",
|
|
117005
|
-
"|=": "|",
|
|
117006
|
-
"^=": "^",
|
|
117007
|
-
"<<=": "<<",
|
|
117008
|
-
">>=": ">>"
|
|
117009
|
-
};
|
|
117010
117389
|
var CLAMP_OP_MAP = {
|
|
117011
117390
|
"+=": "add",
|
|
117012
117391
|
"-=": "sub",
|
|
@@ -117020,7 +117399,7 @@ function getClampHelperOp(cOp, typeInfo) {
|
|
|
117020
117399
|
}
|
|
117021
117400
|
function generateInnerAtomicOp(cOp, value, typeInfo) {
|
|
117022
117401
|
const effects = [];
|
|
117023
|
-
const simpleOp =
|
|
117402
|
+
const simpleOp = COMPOUND_TO_BINARY_default[cOp] || "+";
|
|
117024
117403
|
const helperOp = getClampHelperOp(cOp, typeInfo);
|
|
117025
117404
|
if (helperOp) {
|
|
117026
117405
|
effects.push({
|
|
@@ -117612,7 +117991,11 @@ var FunctionGenerator_default = generateFunction;
|
|
|
117612
117991
|
// src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts
|
|
117613
117992
|
function generateInitializer(varDecl, isArray, orchestrator) {
|
|
117614
117993
|
if (varDecl.expression()) {
|
|
117615
|
-
|
|
117994
|
+
const typeName = orchestrator.generateType(varDecl.type());
|
|
117995
|
+
return CodeGenState.withExpectedType(
|
|
117996
|
+
typeName,
|
|
117997
|
+
() => ` = ${orchestrator.generateExpression(varDecl.expression())}`
|
|
117998
|
+
);
|
|
117616
117999
|
}
|
|
117617
118000
|
return ` = ${orchestrator.getZeroInitializer(varDecl.type(), isArray)}`;
|
|
117618
118001
|
}
|
|
@@ -117681,8 +118064,13 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117681
118064
|
const arrayDims = varDecl.arrayDimension();
|
|
117682
118065
|
const arrayTypeCtx = varDecl.type().arrayType?.() ?? null;
|
|
117683
118066
|
const isArray = arrayDims.length > 0 || arrayTypeCtx !== null;
|
|
117684
|
-
|
|
118067
|
+
let type = orchestrator.generateType(varDecl.type());
|
|
117685
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
|
+
}
|
|
117686
118074
|
const constPrefix = isConst ? "const " : "";
|
|
117687
118075
|
const prefix = isPrivate ? "static " : "";
|
|
117688
118076
|
let decl = `${prefix}${constPrefix}${type} ${fullName}`;
|
|
@@ -117694,7 +118082,11 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117694
118082
|
decl += orchestrator.generateArrayDimensions(arrayDims);
|
|
117695
118083
|
}
|
|
117696
118084
|
decl += ArrayDimensionUtils_default.generateStringCapacityDim(varDecl.type());
|
|
117697
|
-
|
|
118085
|
+
if (isOpaque) {
|
|
118086
|
+
decl += " = NULL";
|
|
118087
|
+
} else {
|
|
118088
|
+
decl += generateInitializer(varDecl, isArray, orchestrator);
|
|
118089
|
+
}
|
|
117698
118090
|
return decl + ";";
|
|
117699
118091
|
}
|
|
117700
118092
|
function generateScopeFunction(funcDecl, scopeName, isPrivate, orchestrator) {
|
|
@@ -117906,6 +118298,7 @@ function generateScopedStructInline(node, scopeName, _input, orchestrator) {
|
|
|
117906
118298
|
var ScopeGenerator_default = generateScope;
|
|
117907
118299
|
|
|
117908
118300
|
// src/utils/BitUtils.ts
|
|
118301
|
+
var NARROW_TYPES = /* @__PURE__ */ new Set(["u8", "u16", "i8", "i16"]);
|
|
117909
118302
|
var BitUtils = class _BitUtils {
|
|
117910
118303
|
/**
|
|
117911
118304
|
* Convert a boolean expression to an unsigned integer (0U or 1U).
|
|
@@ -117996,6 +118389,21 @@ var BitUtils = class _BitUtils {
|
|
|
117996
118389
|
static formatHex(value) {
|
|
117997
118390
|
return `0x${value.toString(16).toUpperCase()}U`;
|
|
117998
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
|
+
}
|
|
117999
118407
|
/**
|
|
118000
118408
|
* Generate code to read a single bit from a value.
|
|
118001
118409
|
* Pattern: ((target >> offset) & 1)
|
|
@@ -118042,7 +118450,8 @@ var BitUtils = class _BitUtils {
|
|
|
118042
118450
|
const is64Bit = targetType === "u64" || targetType === "i64";
|
|
118043
118451
|
const one = is64Bit ? "1ULL" : "1U";
|
|
118044
118452
|
const valueShift = is64Bit ? `((uint64_t)${intValue} << ${offset})` : `(${intValue} << ${offset})`;
|
|
118045
|
-
|
|
118453
|
+
const rhs = `(${target} & ~(${one} << ${offset})) | ${valueShift}`;
|
|
118454
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118046
118455
|
}
|
|
118047
118456
|
/**
|
|
118048
118457
|
* Generate read-modify-write code for multi-bit assignment.
|
|
@@ -118057,7 +118466,8 @@ var BitUtils = class _BitUtils {
|
|
|
118057
118466
|
*/
|
|
118058
118467
|
static multiBitWrite(target, offset, width, value, targetType) {
|
|
118059
118468
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118060
|
-
|
|
118469
|
+
const rhs = `(${target} & ~(${mask} << ${offset})) | ((${value} & ${mask}) << ${offset})`;
|
|
118470
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118061
118471
|
}
|
|
118062
118472
|
/**
|
|
118063
118473
|
* Generate write-only register code for single bit assignment.
|
|
@@ -118073,7 +118483,8 @@ var BitUtils = class _BitUtils {
|
|
|
118073
118483
|
static writeOnlySingleBit(target, offset, value, targetType) {
|
|
118074
118484
|
const intValue = _BitUtils.boolToInt(value);
|
|
118075
118485
|
const castPrefix = targetType === "u64" || targetType === "i64" ? "(uint64_t)" : "";
|
|
118076
|
-
|
|
118486
|
+
const rhs = `(${castPrefix}${intValue} << ${offset})`;
|
|
118487
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118077
118488
|
}
|
|
118078
118489
|
/**
|
|
118079
118490
|
* Generate write-only register code for multi-bit assignment.
|
|
@@ -118089,7 +118500,8 @@ var BitUtils = class _BitUtils {
|
|
|
118089
118500
|
*/
|
|
118090
118501
|
static writeOnlyMultiBit(target, offset, width, value, targetType) {
|
|
118091
118502
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118092
|
-
|
|
118503
|
+
const rhs = `((${value} & ${mask}) << ${offset})`;
|
|
118504
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118093
118505
|
}
|
|
118094
118506
|
};
|
|
118095
118507
|
var BitUtils_default = BitUtils;
|
|
@@ -118804,7 +119216,7 @@ var CnxFileResolver = class {
|
|
|
118804
119216
|
var CnxFileResolver_default = CnxFileResolver;
|
|
118805
119217
|
|
|
118806
119218
|
// src/transpiler/output/codegen/generators/support/IncludeGenerator.ts
|
|
118807
|
-
var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs) => {
|
|
119219
|
+
var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs, cppMode) => {
|
|
118808
119220
|
if (inputs.length === 0) {
|
|
118809
119221
|
return null;
|
|
118810
119222
|
}
|
|
@@ -118818,25 +119230,33 @@ var resolveAngleIncludePath = (filename, sourcePath, includeDirs, inputs) => {
|
|
|
118818
119230
|
foundPath,
|
|
118819
119231
|
inputs
|
|
118820
119232
|
);
|
|
118821
|
-
|
|
119233
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
119234
|
+
return relativePath ? relativePath.replace(/\.cnx$/, ext) : null;
|
|
118822
119235
|
};
|
|
118823
119236
|
var transformAngleInclude = (includeText, filename, options) => {
|
|
118824
|
-
const {
|
|
119237
|
+
const {
|
|
119238
|
+
sourcePath,
|
|
119239
|
+
includeDirs = [],
|
|
119240
|
+
inputs = [],
|
|
119241
|
+
cppMode = false
|
|
119242
|
+
} = options;
|
|
118825
119243
|
if (sourcePath) {
|
|
118826
119244
|
const resolvedPath = resolveAngleIncludePath(
|
|
118827
119245
|
filename,
|
|
118828
119246
|
sourcePath,
|
|
118829
119247
|
includeDirs,
|
|
118830
|
-
inputs
|
|
119248
|
+
inputs,
|
|
119249
|
+
cppMode
|
|
118831
119250
|
);
|
|
118832
119251
|
if (resolvedPath) {
|
|
118833
119252
|
return includeText.replace(`<${filename}.cnx>`, `<${resolvedPath}>`);
|
|
118834
119253
|
}
|
|
118835
119254
|
}
|
|
118836
|
-
|
|
119255
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
119256
|
+
return includeText.replace(`<${filename}.cnx>`, `<${filename}${ext}>`);
|
|
118837
119257
|
};
|
|
118838
119258
|
var transformQuoteInclude = (includeText, filepath, options) => {
|
|
118839
|
-
const { sourcePath } = options;
|
|
119259
|
+
const { sourcePath, cppMode = false } = options;
|
|
118840
119260
|
if (sourcePath) {
|
|
118841
119261
|
const sourceDir = path.dirname(sourcePath);
|
|
118842
119262
|
const cnxPath = path.resolve(sourceDir, `${filepath}.cnx`);
|
|
@@ -118848,7 +119268,8 @@ var transformQuoteInclude = (includeText, filepath, options) => {
|
|
|
118848
119268
|
);
|
|
118849
119269
|
}
|
|
118850
119270
|
}
|
|
118851
|
-
|
|
119271
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
119272
|
+
return includeText.replace(`"${filepath}.cnx"`, `"${filepath}${ext}"`);
|
|
118852
119273
|
};
|
|
118853
119274
|
var transformIncludeDirective = (includeText, options) => {
|
|
118854
119275
|
const angleMatch = /#\s*include\s*<([^>]+)\.cnx>/.exec(includeText);
|
|
@@ -120641,8 +121062,10 @@ var AssignmentKind = /* @__PURE__ */ ((AssignmentKind2) => {
|
|
|
120641
121062
|
AssignmentKind2[AssignmentKind2["GLOBAL_REGISTER_BIT"] = 28] = "GLOBAL_REGISTER_BIT";
|
|
120642
121063
|
AssignmentKind2[AssignmentKind2["THIS_MEMBER"] = 29] = "THIS_MEMBER";
|
|
120643
121064
|
AssignmentKind2[AssignmentKind2["THIS_ARRAY"] = 30] = "THIS_ARRAY";
|
|
120644
|
-
AssignmentKind2[AssignmentKind2["
|
|
120645
|
-
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";
|
|
120646
121069
|
return AssignmentKind2;
|
|
120647
121070
|
})(AssignmentKind || {});
|
|
120648
121071
|
var AssignmentKind_default = AssignmentKind;
|
|
@@ -120684,8 +121107,55 @@ var handlers_default = AssignmentHandlerRegistry;
|
|
|
120684
121107
|
function gen() {
|
|
120685
121108
|
return CodeGenState.generator;
|
|
120686
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
|
+
}
|
|
120687
121149
|
function handleSimpleAssignment(ctx) {
|
|
120688
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
|
+
}
|
|
120689
121159
|
return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
|
|
120690
121160
|
}
|
|
120691
121161
|
var SimpleHandler_default = handleSimpleAssignment;
|
|
@@ -121338,6 +121808,8 @@ function handleStructChainBitRange(ctx) {
|
|
|
121338
121808
|
var bitAccessHandlers = [
|
|
121339
121809
|
[AssignmentKind_default.INTEGER_BIT, handleIntegerBit],
|
|
121340
121810
|
[AssignmentKind_default.INTEGER_BIT_RANGE, handleIntegerBitRange],
|
|
121811
|
+
[AssignmentKind_default.THIS_BIT, handleIntegerBit],
|
|
121812
|
+
[AssignmentKind_default.THIS_BIT_RANGE, handleIntegerBitRange],
|
|
121341
121813
|
[AssignmentKind_default.STRUCT_MEMBER_BIT, handleStructMemberBit],
|
|
121342
121814
|
[AssignmentKind_default.ARRAY_ELEMENT_BIT, handleArrayElementBit],
|
|
121343
121815
|
[AssignmentKind_default.STRUCT_CHAIN_BIT_RANGE, handleStructChainBitRange]
|
|
@@ -121889,14 +122361,28 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
121889
122361
|
return AssignmentKind_default.THIS_MEMBER;
|
|
121890
122362
|
}
|
|
121891
122363
|
/**
|
|
121892
|
-
* 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.
|
|
121893
122366
|
*/
|
|
121894
122367
|
static classifyThisWithArrayAccess(ctx, scopedRegName) {
|
|
121895
122368
|
if (CodeGenState.symbols.knownRegisters.has(scopedRegName)) {
|
|
121896
122369
|
const hasBitRange = ctx.postfixOps.some((op) => op.COMMA() !== null);
|
|
121897
122370
|
return hasBitRange ? AssignmentKind_default.SCOPED_REGISTER_BIT_RANGE : AssignmentKind_default.SCOPED_REGISTER_BIT;
|
|
121898
122371
|
}
|
|
121899
|
-
|
|
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
|
+
}
|
|
121900
122386
|
}
|
|
121901
122387
|
/**
|
|
121902
122388
|
* Classify simple array/bit access (no prefix, no member access).
|
|
@@ -121969,7 +122455,8 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
121969
122455
|
if (isGlobalAtomic) {
|
|
121970
122456
|
return AssignmentKind_default.ATOMIC_RMW;
|
|
121971
122457
|
}
|
|
121972
|
-
|
|
122458
|
+
const ARITHMETIC_COMPOUND_OPS = /* @__PURE__ */ new Set(["+=", "-=", "*="]);
|
|
122459
|
+
if (typeInfo.overflowBehavior === "clamp" && TypeCheckUtils_default.isInteger(typeInfo.baseType) && ARITHMETIC_COMPOUND_OPS.has(ctx.cOp)) {
|
|
121973
122460
|
return AssignmentKind_default.OVERFLOW_CLAMP;
|
|
121974
122461
|
}
|
|
121975
122462
|
return null;
|
|
@@ -122618,6 +123105,7 @@ var ArgumentGenerator = class _ArgumentGenerator {
|
|
|
122618
123105
|
}
|
|
122619
123106
|
/**
|
|
122620
123107
|
* Handle rvalue argument (literals or complex expressions).
|
|
123108
|
+
* Issue #872: Sets expectedType for MISRA 7.2 U suffix on unsigned literals.
|
|
122621
123109
|
*/
|
|
122622
123110
|
static handleRvalueArg(ctx, targetParamBaseType, callbacks) {
|
|
122623
123111
|
if (!targetParamBaseType) {
|
|
@@ -122625,9 +123113,19 @@ var ArgumentGenerator = class _ArgumentGenerator {
|
|
|
122625
123113
|
}
|
|
122626
123114
|
const cType = TYPE_MAP_default[targetParamBaseType];
|
|
122627
123115
|
if (!cType || cType === "void") {
|
|
122628
|
-
return
|
|
123116
|
+
return CodeGenState.withExpectedType(
|
|
123117
|
+
targetParamBaseType,
|
|
123118
|
+
() => callbacks.generateExpression(ctx),
|
|
123119
|
+
true
|
|
123120
|
+
// suppressEnumResolution
|
|
123121
|
+
);
|
|
122629
123122
|
}
|
|
122630
|
-
const value =
|
|
123123
|
+
const value = CodeGenState.withExpectedType(
|
|
123124
|
+
targetParamBaseType,
|
|
123125
|
+
() => callbacks.generateExpression(ctx),
|
|
123126
|
+
true
|
|
123127
|
+
// suppressEnumResolution
|
|
123128
|
+
);
|
|
122631
123129
|
if (CodeGenState.cppMode) {
|
|
122632
123130
|
return value;
|
|
122633
123131
|
}
|
|
@@ -123046,6 +123544,14 @@ var AssignmentExpectedTypeResolver = class _AssignmentExpectedTypeResolver {
|
|
|
123046
123544
|
identifiers
|
|
123047
123545
|
);
|
|
123048
123546
|
}
|
|
123547
|
+
if (identifiers.length === 1 && hasSubscript) {
|
|
123548
|
+
return _AssignmentExpectedTypeResolver.resolveForArrayElement(baseId);
|
|
123549
|
+
}
|
|
123550
|
+
if (identifiers.length >= 2 && hasSubscript) {
|
|
123551
|
+
return _AssignmentExpectedTypeResolver.resolveForMemberArrayElement(
|
|
123552
|
+
identifiers
|
|
123553
|
+
);
|
|
123554
|
+
}
|
|
123049
123555
|
}
|
|
123050
123556
|
return { expectedType: null, assignmentContext: null };
|
|
123051
123557
|
}
|
|
@@ -123072,8 +123578,40 @@ var AssignmentExpectedTypeResolver = class _AssignmentExpectedTypeResolver {
|
|
|
123072
123578
|
*
|
|
123073
123579
|
* Issue #452: Enables type-aware resolution of unqualified enum members
|
|
123074
123580
|
* for nested access (e.g., config.nested.field).
|
|
123581
|
+
*
|
|
123582
|
+
* Delegates to walkMemberChain shared implementation.
|
|
123075
123583
|
*/
|
|
123076
123584
|
static resolveForMemberChain(identifiers) {
|
|
123585
|
+
return _AssignmentExpectedTypeResolver.walkMemberChain(identifiers);
|
|
123586
|
+
}
|
|
123587
|
+
/**
|
|
123588
|
+
* Resolve expected type for array element access.
|
|
123589
|
+
* Issue #872: arr[i] <- value needs baseType for MISRA 7.2 U suffix.
|
|
123590
|
+
*/
|
|
123591
|
+
static resolveForArrayElement(id) {
|
|
123592
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(id);
|
|
123593
|
+
if (!typeInfo?.isArray) {
|
|
123594
|
+
return { expectedType: null, assignmentContext: null };
|
|
123595
|
+
}
|
|
123596
|
+
return { expectedType: typeInfo.baseType, assignmentContext: null };
|
|
123597
|
+
}
|
|
123598
|
+
/**
|
|
123599
|
+
* Resolve expected type for member chain ending with array access.
|
|
123600
|
+
* Issue #872: struct.arr[i] <- value needs element type for MISRA 7.2.
|
|
123601
|
+
*
|
|
123602
|
+
* Delegates to walkMemberChain which handles both member chain and
|
|
123603
|
+
* member-array-element patterns identically (both return final field type).
|
|
123604
|
+
*/
|
|
123605
|
+
static resolveForMemberArrayElement(identifiers) {
|
|
123606
|
+
return _AssignmentExpectedTypeResolver.walkMemberChain(identifiers);
|
|
123607
|
+
}
|
|
123608
|
+
/**
|
|
123609
|
+
* Walk a struct member chain to find the final field's type.
|
|
123610
|
+
* Shared implementation for both member chain and member-array-element patterns.
|
|
123611
|
+
*
|
|
123612
|
+
* Issue #831: Uses SymbolTable as single source of truth for struct fields.
|
|
123613
|
+
*/
|
|
123614
|
+
static walkMemberChain(identifiers) {
|
|
123077
123615
|
if (identifiers.length < 2) {
|
|
123078
123616
|
return { expectedType: null, assignmentContext: null };
|
|
123079
123617
|
}
|
|
@@ -123619,11 +124157,10 @@ var ArrayInitHelper = class _ArrayInitHelper {
|
|
|
123619
124157
|
*/
|
|
123620
124158
|
static _generateArrayInitValue(typeCtx, expression, callbacks) {
|
|
123621
124159
|
const typeName = callbacks.getTypeName(typeCtx);
|
|
123622
|
-
|
|
123623
|
-
|
|
123624
|
-
|
|
123625
|
-
|
|
123626
|
-
return initValue;
|
|
124160
|
+
return CodeGenState.withExpectedType(
|
|
124161
|
+
typeName,
|
|
124162
|
+
() => callbacks.generateExpression(expression)
|
|
124163
|
+
);
|
|
123627
124164
|
}
|
|
123628
124165
|
/**
|
|
123629
124166
|
* Check if the last expression was an array initializer
|
|
@@ -124316,15 +124853,24 @@ ${assignments}`;
|
|
|
124316
124853
|
return `${decl} = ${callbacks.getZeroInitializer(typeCtx, isArray)}`;
|
|
124317
124854
|
}
|
|
124318
124855
|
const typeName = callbacks.getTypeName(typeCtx);
|
|
124319
|
-
const savedExpectedType = CodeGenState.expectedType;
|
|
124320
|
-
CodeGenState.expectedType = typeName;
|
|
124321
124856
|
EnumAssignmentValidator_default.validateEnumAssignment(typeName, ctx.expression());
|
|
124322
124857
|
_VariableDeclHelper.validateIntegerInitializer(ctx, typeName, {
|
|
124323
124858
|
getExpressionType: callbacks.getExpressionType
|
|
124324
124859
|
});
|
|
124325
|
-
|
|
124326
|
-
|
|
124327
|
-
|
|
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
|
+
});
|
|
124328
124874
|
}
|
|
124329
124875
|
// ========================================================================
|
|
124330
124876
|
// Tier 4: Orchestrators (main entry points)
|
|
@@ -125185,7 +125731,7 @@ var TypeGenerationHelper_default = TypeGenerationHelper;
|
|
|
125185
125731
|
var SIGNED_INTEGERS = /* @__PURE__ */ new Set(["i8", "i16", "i32", "i64"]);
|
|
125186
125732
|
var UNSIGNED_INTEGERS = /* @__PURE__ */ new Set(["u8", "u16", "u32", "u64"]);
|
|
125187
125733
|
var ALL_INTEGERS = /* @__PURE__ */ new Set([...SIGNED_INTEGERS, ...UNSIGNED_INTEGERS]);
|
|
125188
|
-
var
|
|
125734
|
+
var FLOAT_TYPES4 = /* @__PURE__ */ new Set(["f32", "f64"]);
|
|
125189
125735
|
var CastValidator = class _CastValidator {
|
|
125190
125736
|
/**
|
|
125191
125737
|
* Check if a type is an integer type.
|
|
@@ -125197,7 +125743,7 @@ var CastValidator = class _CastValidator {
|
|
|
125197
125743
|
* Check if a type is a floating-point type.
|
|
125198
125744
|
*/
|
|
125199
125745
|
static isFloatType(typeName) {
|
|
125200
|
-
return
|
|
125746
|
+
return FLOAT_TYPES4.has(typeName);
|
|
125201
125747
|
}
|
|
125202
125748
|
/**
|
|
125203
125749
|
* Check if a type is signed.
|
|
@@ -127245,13 +127791,16 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
127245
127791
|
/**
|
|
127246
127792
|
* Issue #477: Generate expression with a specific expected type context.
|
|
127247
127793
|
* Used by return statements to resolve unqualified enum values.
|
|
127794
|
+
* Note: Uses explicit save/restore (not withExpectedType) to support null values.
|
|
127248
127795
|
*/
|
|
127249
127796
|
generateExpressionWithExpectedType(ctx, expectedType) {
|
|
127250
|
-
const
|
|
127797
|
+
const saved = CodeGenState.expectedType;
|
|
127251
127798
|
CodeGenState.expectedType = expectedType;
|
|
127252
|
-
|
|
127253
|
-
|
|
127254
|
-
|
|
127799
|
+
try {
|
|
127800
|
+
return this.generateExpression(ctx);
|
|
127801
|
+
} finally {
|
|
127802
|
+
CodeGenState.expectedType = saved;
|
|
127803
|
+
}
|
|
127255
127804
|
}
|
|
127256
127805
|
/**
|
|
127257
127806
|
* Generate type translation (C-Next type -> C type).
|
|
@@ -128240,6 +128789,22 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128240
128789
|
isFloatShadowCurrent(shadowName) {
|
|
128241
128790
|
return CodeGenState.floatShadowCurrent.has(shadowName);
|
|
128242
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
|
+
}
|
|
128243
128808
|
// ===========================================================================
|
|
128244
128809
|
// End IOrchestrator Implementation
|
|
128245
128810
|
// ===========================================================================
|
|
@@ -128596,15 +129161,17 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128596
129161
|
return DEFAULT_TARGET2;
|
|
128597
129162
|
}
|
|
128598
129163
|
/**
|
|
128599
|
-
* ADR-010: Transform #include directives, converting .cnx to .h
|
|
129164
|
+
* ADR-010: Transform #include directives, converting .cnx to .h or .hpp
|
|
128600
129165
|
* ADR-053 A5: Delegates to IncludeGenerator
|
|
128601
129166
|
* Issue #349: Now passes includeDirs and inputs for angle-bracket resolution
|
|
129167
|
+
* Issue #941: Now passes cppMode for .hpp extension in C++ mode
|
|
128602
129168
|
*/
|
|
128603
129169
|
transformIncludeDirective(includeText) {
|
|
128604
129170
|
return includeTransformIncludeDirective(includeText, {
|
|
128605
129171
|
sourcePath: CodeGenState.sourcePath,
|
|
128606
129172
|
includeDirs: CodeGenState.includeDirs,
|
|
128607
|
-
inputs: CodeGenState.inputs
|
|
129173
|
+
inputs: CodeGenState.inputs,
|
|
129174
|
+
cppMode: CodeGenState.cppMode
|
|
128608
129175
|
});
|
|
128609
129176
|
}
|
|
128610
129177
|
// Issue #63: validateIncludeNotImplementationFile moved to TypeValidator
|
|
@@ -129342,19 +129909,20 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129342
129909
|
const structFieldTypes = CodeGenState.symbolTable?.getStructFieldTypes(typeName);
|
|
129343
129910
|
const fields = fieldList.fieldInitializer().map((field) => {
|
|
129344
129911
|
const fieldName = field.IDENTIFIER().getText();
|
|
129345
|
-
|
|
129912
|
+
let fieldType;
|
|
129346
129913
|
if (structFieldTypes?.has(fieldName)) {
|
|
129347
|
-
|
|
129914
|
+
fieldType = structFieldTypes.get(fieldName);
|
|
129348
129915
|
if (fieldType.includes("_")) {
|
|
129349
129916
|
const parts = fieldType.split("_");
|
|
129350
129917
|
if (parts.length > 1 && this.isCppScopeSymbol(parts[0])) {
|
|
129351
129918
|
fieldType = parts.join("::");
|
|
129352
129919
|
}
|
|
129353
129920
|
}
|
|
129354
|
-
CodeGenState.expectedType = fieldType;
|
|
129355
129921
|
}
|
|
129356
|
-
const value =
|
|
129357
|
-
|
|
129922
|
+
const value = CodeGenState.withExpectedType(
|
|
129923
|
+
fieldType,
|
|
129924
|
+
() => this.generateExpression(field.expression())
|
|
129925
|
+
);
|
|
129358
129926
|
return { fieldName, value };
|
|
129359
129927
|
});
|
|
129360
129928
|
if (isCppClass) {
|
|
@@ -129869,18 +130437,20 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
129869
130437
|
// ADR-001: <- becomes = in C, with compound assignment operators
|
|
129870
130438
|
generateAssignment(ctx) {
|
|
129871
130439
|
const targetCtx = ctx.assignmentTarget();
|
|
129872
|
-
const savedExpectedType = CodeGenState.expectedType;
|
|
129873
130440
|
const savedAssignmentContext = { ...CodeGenState.assignmentContext };
|
|
129874
130441
|
const resolved = AssignmentExpectedTypeResolver_default.resolve(targetCtx);
|
|
129875
|
-
if (resolved.expectedType) {
|
|
129876
|
-
CodeGenState.expectedType = resolved.expectedType;
|
|
129877
|
-
}
|
|
129878
130442
|
if (resolved.assignmentContext) {
|
|
129879
130443
|
CodeGenState.assignmentContext = resolved.assignmentContext;
|
|
129880
130444
|
}
|
|
129881
|
-
|
|
129882
|
-
|
|
129883
|
-
|
|
130445
|
+
let value;
|
|
130446
|
+
try {
|
|
130447
|
+
value = CodeGenState.withExpectedType(
|
|
130448
|
+
resolved.expectedType,
|
|
130449
|
+
() => this.generateExpression(ctx.expression())
|
|
130450
|
+
);
|
|
130451
|
+
} finally {
|
|
130452
|
+
CodeGenState.assignmentContext = savedAssignmentContext;
|
|
130453
|
+
}
|
|
129884
130454
|
const operatorCtx = ctx.assignmentOperator();
|
|
129885
130455
|
const cnextOp = operatorCtx.getText();
|
|
129886
130456
|
const cOp = ASSIGNMENT_OPERATOR_MAP2[cnextOp] || "=";
|
|
@@ -130090,7 +130660,11 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130090
130660
|
* @returns The qualified enum member access, or null if not an enum member
|
|
130091
130661
|
*/
|
|
130092
130662
|
_resolveUnqualifiedEnumMember(id) {
|
|
130093
|
-
if (CodeGenState.
|
|
130663
|
+
if (CodeGenState.suppressBareEnumResolution) {
|
|
130664
|
+
} else if (
|
|
130665
|
+
// Type-aware resolution: check only the expected enum type
|
|
130666
|
+
CodeGenState.expectedType && CodeGenState.symbols.knownEnums.has(CodeGenState.expectedType)
|
|
130667
|
+
) {
|
|
130094
130668
|
const members = CodeGenState.symbols.enumMembers.get(
|
|
130095
130669
|
CodeGenState.expectedType
|
|
130096
130670
|
);
|
|
@@ -130197,7 +130771,9 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130197
130771
|
const minComparison = minValue === "0" ? `0.0${floatSuffix}` : `((${floatCastType})${minValue})`;
|
|
130198
130772
|
const maxComparison = `((${floatCastType})${maxValue})`;
|
|
130199
130773
|
const finalCast = CppModeHelper_default.cast(targetType, `(${expr})`);
|
|
130200
|
-
|
|
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})`;
|
|
130201
130777
|
}
|
|
130202
130778
|
/**
|
|
130203
130779
|
* ADR-023: Generate sizeof expression
|
|
@@ -130888,15 +131464,16 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
|
|
|
130888
131464
|
}
|
|
130889
131465
|
if (options.userIncludes && options.userIncludes.length > 0) {
|
|
130890
131466
|
for (const include of options.userIncludes) {
|
|
130891
|
-
|
|
130892
|
-
|
|
131467
|
+
lines.push(include);
|
|
131468
|
+
}
|
|
131469
|
+
}
|
|
131470
|
+
const userIncludeSet = new Set(options.userIncludes ?? []);
|
|
131471
|
+
if (options.cppMode && options.userIncludes) {
|
|
131472
|
+
for (const inc of options.userIncludes) {
|
|
131473
|
+
const hVersion = inc.replace(/\.hpp"/, '.h"').replace(/\.hpp>/, ".h>");
|
|
131474
|
+
userIncludeSet.add(hVersion);
|
|
130893
131475
|
}
|
|
130894
131476
|
}
|
|
130895
|
-
const userIncludeSet = new Set(
|
|
130896
|
-
options.userIncludes?.map(
|
|
130897
|
-
(inc) => options.cppMode ? inc.replace(/\.h"/, '.hpp"').replace(/\.h>/, ".hpp>") : inc
|
|
130898
|
-
) ?? []
|
|
130899
|
-
);
|
|
130900
131477
|
for (const directive of headersToInclude) {
|
|
130901
131478
|
if (!userIncludeSet.has(directive)) {
|
|
130902
131479
|
lines.push(directive);
|
|
@@ -131274,18 +131851,21 @@ var IncludeExtractor = class {
|
|
|
131274
131851
|
/**
|
|
131275
131852
|
* Extract user includes from a parsed C-Next program.
|
|
131276
131853
|
*
|
|
131277
|
-
* Extracts #include directives for .cnx files and transforms them to .h includes.
|
|
131854
|
+
* Extracts #include directives for .cnx files and transforms them to .h or .hpp includes.
|
|
131855
|
+
* Issue #941: Uses .hpp extension when cppMode is true.
|
|
131278
131856
|
* This enables cross-file type definitions in generated headers.
|
|
131279
131857
|
*
|
|
131280
131858
|
* @param tree The parsed C-Next program
|
|
131281
|
-
* @
|
|
131859
|
+
* @param cppMode Whether to use .hpp extension (C++ mode)
|
|
131860
|
+
* @returns Array of transformed include strings (e.g., '#include "types.h"' or '#include "types.hpp"')
|
|
131282
131861
|
*/
|
|
131283
|
-
static collectUserIncludes(tree) {
|
|
131862
|
+
static collectUserIncludes(tree, cppMode = false) {
|
|
131284
131863
|
const userIncludes = [];
|
|
131864
|
+
const ext = cppMode ? ".hpp" : ".h";
|
|
131285
131865
|
for (const includeDir of tree.includeDirective()) {
|
|
131286
131866
|
const includeText = includeDir.getText();
|
|
131287
131867
|
if (includeText.includes(".cnx")) {
|
|
131288
|
-
const transformedInclude = includeText.replace(/\.cnx"/,
|
|
131868
|
+
const transformedInclude = includeText.replace(/\.cnx"/, `${ext}"`).replace(/\.cnx>/, `${ext}>`);
|
|
131289
131869
|
userIncludes.push(transformedInclude);
|
|
131290
131870
|
}
|
|
131291
131871
|
}
|
|
@@ -132386,6 +132966,7 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132386
132966
|
const registerMemberCTypes = /* @__PURE__ */ new Map();
|
|
132387
132967
|
const scopePrivateConstValues = /* @__PURE__ */ new Map();
|
|
132388
132968
|
const functionReturnTypes = /* @__PURE__ */ new Map();
|
|
132969
|
+
const opaqueTypes = /* @__PURE__ */ new Set();
|
|
132389
132970
|
for (const symbol of symbols) {
|
|
132390
132971
|
switch (symbol.kind) {
|
|
132391
132972
|
case "struct":
|
|
@@ -132473,6 +133054,8 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132473
133054
|
scopePrivateConstValues,
|
|
132474
133055
|
// Function return types
|
|
132475
133056
|
functionReturnTypes,
|
|
133057
|
+
// Issue #948: Opaque types
|
|
133058
|
+
opaqueTypes,
|
|
132476
133059
|
// Methods
|
|
132477
133060
|
getSingleFunctionForVariable: (scopeName, varName) => _TSymbolInfoAdapter.getSingleFunctionForVariable(
|
|
132478
133061
|
scopeVariableUsage,
|
|
@@ -132670,42 +133253,35 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132670
133253
|
);
|
|
132671
133254
|
}
|
|
132672
133255
|
return {
|
|
132673
|
-
|
|
133256
|
+
...base,
|
|
132674
133257
|
knownScopes: mergedKnownScopes,
|
|
132675
|
-
knownStructs: base.knownStructs,
|
|
132676
133258
|
knownEnums: mergedKnownEnums,
|
|
132677
|
-
knownBitmaps: base.knownBitmaps,
|
|
132678
|
-
knownRegisters: base.knownRegisters,
|
|
132679
|
-
// Scope info
|
|
132680
|
-
scopeMembers: base.scopeMembers,
|
|
132681
|
-
scopeMemberVisibility: base.scopeMemberVisibility,
|
|
132682
|
-
scopeVariableUsage: base.scopeVariableUsage,
|
|
132683
|
-
// Struct info
|
|
132684
|
-
structFields: base.structFields,
|
|
132685
|
-
structFieldArrays: base.structFieldArrays,
|
|
132686
|
-
structFieldDimensions: base.structFieldDimensions,
|
|
132687
|
-
// Enum info - merged
|
|
132688
133259
|
enumMembers: mergedEnumMembers,
|
|
132689
|
-
|
|
132690
|
-
bitmapFields: base.bitmapFields,
|
|
132691
|
-
bitmapBackingType: base.bitmapBackingType,
|
|
132692
|
-
bitmapBitWidth: base.bitmapBitWidth,
|
|
132693
|
-
// Register info
|
|
132694
|
-
scopedRegisters: base.scopedRegisters,
|
|
132695
|
-
registerMemberAccess: base.registerMemberAccess,
|
|
132696
|
-
registerMemberTypes: base.registerMemberTypes,
|
|
132697
|
-
registerBaseAddresses: base.registerBaseAddresses,
|
|
132698
|
-
registerMemberOffsets: base.registerMemberOffsets,
|
|
132699
|
-
registerMemberCTypes: base.registerMemberCTypes,
|
|
132700
|
-
// Private const values
|
|
132701
|
-
scopePrivateConstValues: base.scopePrivateConstValues,
|
|
132702
|
-
// Function return types - merged
|
|
132703
|
-
functionReturnTypes: mergedFunctionReturnTypes,
|
|
132704
|
-
// Methods - delegate to base's implementation
|
|
132705
|
-
getSingleFunctionForVariable: base.getSingleFunctionForVariable,
|
|
132706
|
-
hasPublicSymbols: base.hasPublicSymbols
|
|
133260
|
+
functionReturnTypes: mergedFunctionReturnTypes
|
|
132707
133261
|
};
|
|
132708
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
|
+
}
|
|
132709
133285
|
};
|
|
132710
133286
|
var TSymbolInfoAdapter_default = TSymbolInfoAdapter;
|
|
132711
133287
|
|
|
@@ -133092,6 +133668,18 @@ var DeclaratorUtils = class _DeclaratorUtils {
|
|
|
133092
133668
|
}
|
|
133093
133669
|
return void 0;
|
|
133094
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
|
+
}
|
|
133095
133683
|
};
|
|
133096
133684
|
var DeclaratorUtils_default = DeclaratorUtils;
|
|
133097
133685
|
|
|
@@ -133113,6 +133701,7 @@ var StructCollector2 = class _StructCollector {
|
|
|
133113
133701
|
const name = identifier?.getText() || typedefName;
|
|
133114
133702
|
if (!name) return null;
|
|
133115
133703
|
const isUnion = structSpec.structOrUnion()?.getText() === "union";
|
|
133704
|
+
const hasBody = structSpec.structDeclarationList() !== null;
|
|
133116
133705
|
const fields = _StructCollector.collectFields(
|
|
133117
133706
|
structSpec,
|
|
133118
133707
|
name,
|
|
@@ -133120,8 +133709,16 @@ var StructCollector2 = class _StructCollector {
|
|
|
133120
133709
|
warnings
|
|
133121
133710
|
);
|
|
133122
133711
|
const needsStructKeyword = Boolean(identifier && !isTypedef);
|
|
133123
|
-
if (symbolTable
|
|
133124
|
-
|
|
133712
|
+
if (symbolTable) {
|
|
133713
|
+
_StructCollector.updateSymbolTable(
|
|
133714
|
+
symbolTable,
|
|
133715
|
+
name,
|
|
133716
|
+
needsStructKeyword,
|
|
133717
|
+
hasBody,
|
|
133718
|
+
isTypedef,
|
|
133719
|
+
typedefName,
|
|
133720
|
+
identifier?.getText()
|
|
133721
|
+
);
|
|
133125
133722
|
}
|
|
133126
133723
|
return {
|
|
133127
133724
|
kind: "struct",
|
|
@@ -133135,6 +133732,44 @@ var StructCollector2 = class _StructCollector {
|
|
|
133135
133732
|
fields: fields.size > 0 ? fields : void 0
|
|
133136
133733
|
};
|
|
133137
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
|
+
}
|
|
133138
133773
|
/**
|
|
133139
133774
|
* Collect fields from a struct/union definition.
|
|
133140
133775
|
*/
|
|
@@ -133271,6 +133906,15 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133271
133906
|
isArray: p.isArray
|
|
133272
133907
|
}));
|
|
133273
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
|
+
}
|
|
133274
133918
|
/**
|
|
133275
133919
|
* Collect a function symbol from a function definition.
|
|
133276
133920
|
*
|
|
@@ -133284,7 +133928,11 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133284
133928
|
if (!name) return null;
|
|
133285
133929
|
const line = funcDef.start?.line ?? 0;
|
|
133286
133930
|
const declSpecs = funcDef.declarationSpecifiers();
|
|
133287
|
-
const
|
|
133931
|
+
const baseType = declSpecs ? DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs) : "int";
|
|
133932
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
133933
|
+
baseType,
|
|
133934
|
+
declarator
|
|
133935
|
+
);
|
|
133288
133936
|
const parameters = _FunctionCollector._mapParameters(
|
|
133289
133937
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133290
133938
|
);
|
|
@@ -133314,8 +133962,10 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133314
133962
|
const parameters = _FunctionCollector._mapParameters(
|
|
133315
133963
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133316
133964
|
);
|
|
133317
|
-
const
|
|
133318
|
-
|
|
133965
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
133966
|
+
baseType,
|
|
133967
|
+
declarator
|
|
133968
|
+
);
|
|
133319
133969
|
return {
|
|
133320
133970
|
kind: "function",
|
|
133321
133971
|
name,
|
|
@@ -133458,39 +134108,33 @@ var CResolver = class _CResolver {
|
|
|
133458
134108
|
const line = decl.start?.line ?? 0;
|
|
133459
134109
|
const isTypedef = DeclaratorUtils_default.hasStorageClass(declSpecs, "typedef");
|
|
133460
134110
|
const isExtern = DeclaratorUtils_default.hasStorageClass(declSpecs, "extern");
|
|
134111
|
+
const ctx = {
|
|
134112
|
+
sourceFile,
|
|
134113
|
+
line,
|
|
134114
|
+
isTypedef,
|
|
134115
|
+
isExtern,
|
|
134116
|
+
symbols
|
|
134117
|
+
};
|
|
133461
134118
|
const structSpec = DeclaratorUtils_default.findStructOrUnionSpecifier(declSpecs);
|
|
133462
134119
|
if (structSpec) {
|
|
133463
|
-
|
|
133464
|
-
const structSymbol = StructCollector_default2.collect(
|
|
134120
|
+
_CResolver.collectStructSymbol(
|
|
133465
134121
|
structSpec,
|
|
133466
|
-
|
|
133467
|
-
|
|
134122
|
+
decl,
|
|
134123
|
+
declSpecs,
|
|
134124
|
+
ctx,
|
|
133468
134125
|
symbolTable,
|
|
133469
|
-
typedefName,
|
|
133470
|
-
isTypedef,
|
|
133471
134126
|
warnings
|
|
133472
134127
|
);
|
|
133473
|
-
if (structSymbol) {
|
|
133474
|
-
symbols.push(structSymbol);
|
|
133475
|
-
}
|
|
133476
134128
|
}
|
|
133477
134129
|
const enumSpec = DeclaratorUtils_default.findEnumSpecifier(declSpecs);
|
|
133478
134130
|
if (enumSpec) {
|
|
133479
|
-
|
|
133480
|
-
|
|
133481
|
-
|
|
133482
|
-
|
|
133483
|
-
|
|
133484
|
-
|
|
133485
|
-
}
|
|
134131
|
+
_CResolver.collectEnumSymbols(
|
|
134132
|
+
enumSpec,
|
|
134133
|
+
ctx.sourceFile,
|
|
134134
|
+
ctx.line,
|
|
134135
|
+
ctx.symbols
|
|
134136
|
+
);
|
|
133486
134137
|
}
|
|
133487
|
-
const ctx = {
|
|
133488
|
-
sourceFile,
|
|
133489
|
-
line,
|
|
133490
|
-
isTypedef,
|
|
133491
|
-
isExtern,
|
|
133492
|
-
symbols
|
|
133493
|
-
};
|
|
133494
134138
|
const initDeclList = decl.initDeclaratorList();
|
|
133495
134139
|
if (initDeclList) {
|
|
133496
134140
|
const baseType = DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs);
|
|
@@ -133504,6 +134148,49 @@ var CResolver = class _CResolver {
|
|
|
133504
134148
|
);
|
|
133505
134149
|
}
|
|
133506
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
|
+
}
|
|
133507
134194
|
/**
|
|
133508
134195
|
* Collect symbols from init declarator list.
|
|
133509
134196
|
*/
|
|
@@ -137697,6 +138384,9 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137697
138384
|
if (TypeConstants_default.UNSIGNED_INDEX_TYPES.includes(resolvedType)) {
|
|
137698
138385
|
continue;
|
|
137699
138386
|
}
|
|
138387
|
+
if (CodeGenState.isKnownEnum(resolvedType)) {
|
|
138388
|
+
continue;
|
|
138389
|
+
}
|
|
137700
138390
|
const { line, column } = ParserUtils_default.getPosition(ctx);
|
|
137701
138391
|
this.analyzer.addError(line, column, "E0852", resolvedType);
|
|
137702
138392
|
return;
|
|
@@ -137786,6 +138476,10 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137786
138476
|
if (TypeConstants_default.SIGNED_TYPES.includes(currentType)) {
|
|
137787
138477
|
return "bool";
|
|
137788
138478
|
}
|
|
138479
|
+
const strippedType = currentType.replace(/\[[^\]]*\]$/, "");
|
|
138480
|
+
if (strippedType !== currentType) {
|
|
138481
|
+
return strippedType;
|
|
138482
|
+
}
|
|
137789
138483
|
return currentType;
|
|
137790
138484
|
}
|
|
137791
138485
|
if (op.LPAREN()) {
|
|
@@ -138186,7 +138880,7 @@ var CacheKeyGenerator_default = CacheKeyGenerator;
|
|
|
138186
138880
|
|
|
138187
138881
|
// src/utils/cache/CacheManager.ts
|
|
138188
138882
|
var defaultFs7 = NodeFileSystem_default.instance;
|
|
138189
|
-
var CACHE_VERSION =
|
|
138883
|
+
var CACHE_VERSION = 5;
|
|
138190
138884
|
var TRANSPILER_VERSION = package_default.version;
|
|
138191
138885
|
var CacheManager = class {
|
|
138192
138886
|
projectRoot;
|
|
@@ -138286,14 +138980,15 @@ var CacheManager = class {
|
|
|
138286
138980
|
symbols,
|
|
138287
138981
|
structFields,
|
|
138288
138982
|
needsStructKeyword: cachedEntry.needsStructKeyword ?? [],
|
|
138289
|
-
enumBitWidth
|
|
138983
|
+
enumBitWidth,
|
|
138984
|
+
opaqueTypes: cachedEntry.opaqueTypes ?? []
|
|
138290
138985
|
};
|
|
138291
138986
|
}
|
|
138292
138987
|
/**
|
|
138293
138988
|
* Store symbols and struct fields for a file
|
|
138294
138989
|
* ADR-055 Phase 7: Takes ISerializedSymbol[] directly
|
|
138295
138990
|
*/
|
|
138296
|
-
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth) {
|
|
138991
|
+
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth, opaqueTypes) {
|
|
138297
138992
|
if (!this.cache) return;
|
|
138298
138993
|
let cacheKey;
|
|
138299
138994
|
try {
|
|
@@ -138321,7 +139016,8 @@ var CacheManager = class {
|
|
|
138321
139016
|
symbols: serializedSymbols,
|
|
138322
139017
|
structFields: serializedFields,
|
|
138323
139018
|
needsStructKeyword,
|
|
138324
|
-
enumBitWidth: serializedEnumBitWidth
|
|
139019
|
+
enumBitWidth: serializedEnumBitWidth,
|
|
139020
|
+
opaqueTypes
|
|
138325
139021
|
};
|
|
138326
139022
|
this.cache.setKey(filePath, entry);
|
|
138327
139023
|
this.dirty = true;
|
|
@@ -138349,12 +139045,14 @@ var CacheManager = class {
|
|
|
138349
139045
|
filePath,
|
|
138350
139046
|
symbolTable
|
|
138351
139047
|
);
|
|
139048
|
+
const opaqueTypes = symbolTable.getAllOpaqueTypes();
|
|
138352
139049
|
this.setSymbols(
|
|
138353
139050
|
filePath,
|
|
138354
139051
|
symbols,
|
|
138355
139052
|
structFields,
|
|
138356
139053
|
needsStructKeyword,
|
|
138357
|
-
enumBitWidth
|
|
139054
|
+
enumBitWidth,
|
|
139055
|
+
opaqueTypes
|
|
138358
139056
|
);
|
|
138359
139057
|
}
|
|
138360
139058
|
/**
|
|
@@ -138797,7 +139495,7 @@ var Transpiler = class {
|
|
|
138797
139495
|
* Stage 6: Generate headers (per-file)
|
|
138798
139496
|
*/
|
|
138799
139497
|
async _executePipeline(input, result) {
|
|
138800
|
-
this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
139498
|
+
await this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
138801
139499
|
CodeGenState.buildExternalStructFields();
|
|
138802
139500
|
if (!this._collectAllCNextSymbolsFromPipeline(input.cnextFiles, result)) {
|
|
138803
139501
|
return;
|
|
@@ -138906,6 +139604,13 @@ var Transpiler = class {
|
|
|
138906
139604
|
externalEnumSources
|
|
138907
139605
|
);
|
|
138908
139606
|
}
|
|
139607
|
+
const externalOpaqueTypes = CodeGenState.symbolTable.getAllOpaqueTypes();
|
|
139608
|
+
if (externalOpaqueTypes.length > 0) {
|
|
139609
|
+
symbolInfo = TSymbolInfoAdapter_default.mergeOpaqueTypes(
|
|
139610
|
+
symbolInfo,
|
|
139611
|
+
externalOpaqueTypes
|
|
139612
|
+
);
|
|
139613
|
+
}
|
|
138909
139614
|
CodeGenState.symbols = symbolInfo;
|
|
138910
139615
|
const analyzerErrors = runAnalyzers_default(tree, tokenStream);
|
|
138911
139616
|
if (analyzerErrors.length > 0) {
|
|
@@ -138923,7 +139628,10 @@ var Transpiler = class {
|
|
|
138923
139628
|
cppMode: this.cppDetected,
|
|
138924
139629
|
symbolInfo
|
|
138925
139630
|
});
|
|
138926
|
-
const userIncludes = IncludeExtractor_default.collectUserIncludes(
|
|
139631
|
+
const userIncludes = IncludeExtractor_default.collectUserIncludes(
|
|
139632
|
+
tree,
|
|
139633
|
+
this.cppDetected
|
|
139634
|
+
);
|
|
138927
139635
|
const passByValue = this.codeGenerator.getPassByValueParams();
|
|
138928
139636
|
const passByValueCopy = MapUtils_default.deepCopyStringSetMap(passByValue);
|
|
138929
139637
|
this.state.setSymbolInfo(sourcePath, symbolInfo);
|
|
@@ -139076,11 +139784,12 @@ var Transpiler = class {
|
|
|
139076
139784
|
}
|
|
139077
139785
|
/**
|
|
139078
139786
|
* Stage 2: Collect symbols from all C/C++ headers
|
|
139787
|
+
* Issue #945: Made async for preprocessing support.
|
|
139079
139788
|
*/
|
|
139080
|
-
_collectAllHeaderSymbols(headerFiles, result) {
|
|
139789
|
+
async _collectAllHeaderSymbols(headerFiles, result) {
|
|
139081
139790
|
for (const file of headerFiles) {
|
|
139082
139791
|
try {
|
|
139083
|
-
this.doCollectHeaderSymbols(file);
|
|
139792
|
+
await this.doCollectHeaderSymbols(file);
|
|
139084
139793
|
result.filesProcessed++;
|
|
139085
139794
|
} catch (err) {
|
|
139086
139795
|
this.warnings.push(`Failed to process header ${file.path}: ${err}`);
|
|
@@ -139359,15 +140068,16 @@ var Transpiler = class {
|
|
|
139359
140068
|
/**
|
|
139360
140069
|
* Stage 2: Collect symbols from a single C/C++ header
|
|
139361
140070
|
* Issue #592: Recursive include processing moved to IncludeResolver.resolveHeadersTransitively()
|
|
140071
|
+
* Issue #945: Added preprocessing support for conditional compilation
|
|
139362
140072
|
* SonarCloud S3776: Refactored to use helper methods for reduced complexity.
|
|
139363
140073
|
*/
|
|
139364
|
-
doCollectHeaderSymbols(file) {
|
|
140074
|
+
async doCollectHeaderSymbols(file) {
|
|
139365
140075
|
const absolutePath = resolve12(file.path);
|
|
139366
140076
|
this.state.markHeaderProcessed(absolutePath);
|
|
139367
140077
|
if (this.tryRestoreFromCache(file)) {
|
|
139368
140078
|
return;
|
|
139369
140079
|
}
|
|
139370
|
-
const content = this.
|
|
140080
|
+
const content = await this.getHeaderContent(file);
|
|
139371
140081
|
this.parseHeaderFile(file, content);
|
|
139372
140082
|
if (this.config.debugMode) {
|
|
139373
140083
|
const symbols = CodeGenState.symbolTable.getSymbolsByFile(file.path);
|
|
@@ -139398,9 +140108,51 @@ var Transpiler = class {
|
|
|
139398
140108
|
cached.needsStructKeyword
|
|
139399
140109
|
);
|
|
139400
140110
|
CodeGenState.symbolTable.restoreEnumBitWidths(cached.enumBitWidth);
|
|
140111
|
+
CodeGenState.symbolTable.restoreOpaqueTypes(cached.opaqueTypes);
|
|
139401
140112
|
this.detectCppFromFileType(file);
|
|
139402
140113
|
return true;
|
|
139403
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
|
+
}
|
|
139404
140156
|
/**
|
|
139405
140157
|
* Restore cached symbols to the symbol table.
|
|
139406
140158
|
* ADR-055 Phase 7: Converts ISerializedSymbol[] from cache to typed symbols.
|