c-next 0.2.16 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/index.js +1347 -414
- package/dist/index.js.map +3 -3
- package/grammar/CNext.g4 +4 -0
- package/package.json +5 -1
- package/src/transpiler/Transpiler.ts +90 -22
- package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +57 -10
- package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +186 -14
- package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +124 -12
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +200 -0
- package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +386 -1
- package/src/transpiler/logic/analysis/__tests__/SignedShiftAnalyzer.test.ts +211 -0
- package/src/transpiler/logic/parser/grammar/CNext.interp +1 -1
- package/src/transpiler/logic/parser/grammar/CNextParser.ts +154 -86
- package/src/transpiler/logic/symbols/SymbolTable.ts +17 -2
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +6 -4
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +15 -2
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +64 -50
- package/src/transpiler/output/codegen/CodeGenerator.ts +151 -94
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +165 -17
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +150 -34
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +2 -2
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +11 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +26 -7
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +86 -0
- package/src/transpiler/output/codegen/generators/expressions/BinaryExprGenerator.ts +43 -24
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +48 -43
- package/src/transpiler/output/codegen/generators/expressions/ExpressionGenerator.ts +9 -2
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +44 -0
- package/src/transpiler/output/codegen/generators/expressions/__tests__/ExpressionGenerator.test.ts +82 -1
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +17 -3
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +17 -4
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +227 -32
- package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +0 -21
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +60 -39
- package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +170 -36
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +37 -39
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +117 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +94 -2
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +268 -1
- package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +0 -64
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +101 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +29 -5
- package/src/transpiler/output/codegen/types/ICallbackTypeInfo.ts +2 -1
- package/src/transpiler/output/codegen/types/IParameterInput.ts +7 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +8 -0
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +75 -0
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +280 -0
- package/src/transpiler/output/headers/generators/IHeaderTypeInput.ts +13 -0
- package/src/transpiler/output/headers/generators/generateStructHeader.ts +48 -28
- package/src/transpiler/state/CodeGenState.ts +71 -6
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +253 -11
- package/src/utils/LiteralUtils.ts +23 -0
- package/src/utils/__tests__/LiteralUtils.test.ts +101 -0
- package/src/utils/types/IParameterSymbol.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "c-next",
|
|
14
|
-
version: "0.2.
|
|
14
|
+
version: "0.2.17",
|
|
15
15
|
description: "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
16
16
|
packageManager: "npm@11.9.0",
|
|
17
17
|
type: "module",
|
|
@@ -35,6 +35,10 @@ var package_default = {
|
|
|
35
35
|
"test:update": "tsx scripts/test.ts --update",
|
|
36
36
|
"integration:transpile": "tsx scripts/test.ts --transpile-only",
|
|
37
37
|
"integration:execute": "tsx scripts/test.ts --execute-only",
|
|
38
|
+
"test:bugs": "tsx scripts/test.ts -- bugs",
|
|
39
|
+
"test:bugs:q": "tsx scripts/test.ts -- bugs -q",
|
|
40
|
+
"integration:bugs:transpile": "tsx scripts/test.ts -- bugs --transpile-only",
|
|
41
|
+
"integration:bugs:execute": "tsx scripts/test.ts -- bugs --execute-only",
|
|
38
42
|
analyze: "./scripts/static-analysis.sh",
|
|
39
43
|
clean: "rm -rf dist src/transpiler/logic/parser/grammar src/transpiler/logic/parser/c/grammar src/transpiler/logic/parser/cpp/grammar",
|
|
40
44
|
"prettier:check": "prettier --check .",
|
|
@@ -16039,21 +16043,10 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16039
16043
|
this.enterRule(localContext, 170, _CNextParser.RULE_arrayType);
|
|
16040
16044
|
let _la;
|
|
16041
16045
|
try {
|
|
16042
|
-
this.state =
|
|
16046
|
+
this.state = 939;
|
|
16043
16047
|
this.errorHandler.sync(this);
|
|
16044
|
-
switch (this.tokenStream.
|
|
16045
|
-
case
|
|
16046
|
-
case _CNextParser.U16:
|
|
16047
|
-
case _CNextParser.U32:
|
|
16048
|
-
case _CNextParser.U64:
|
|
16049
|
-
case _CNextParser.I8:
|
|
16050
|
-
case _CNextParser.I16:
|
|
16051
|
-
case _CNextParser.I32:
|
|
16052
|
-
case _CNextParser.I64:
|
|
16053
|
-
case _CNextParser.F32:
|
|
16054
|
-
case _CNextParser.F64:
|
|
16055
|
-
case _CNextParser.BOOL:
|
|
16056
|
-
case _CNextParser.ISR_TYPE:
|
|
16048
|
+
switch (this.interpreter.adaptivePredict(this.tokenStream, 98, this.context)) {
|
|
16049
|
+
case 1:
|
|
16057
16050
|
this.enterOuterAlt(localContext, 1);
|
|
16058
16051
|
{
|
|
16059
16052
|
this.state = 903;
|
|
@@ -16074,7 +16067,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16074
16067
|
} while (_la === 100);
|
|
16075
16068
|
}
|
|
16076
16069
|
break;
|
|
16077
|
-
case
|
|
16070
|
+
case 2:
|
|
16078
16071
|
this.enterOuterAlt(localContext, 2);
|
|
16079
16072
|
{
|
|
16080
16073
|
this.state = 909;
|
|
@@ -16095,7 +16088,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16095
16088
|
} while (_la === 100);
|
|
16096
16089
|
}
|
|
16097
16090
|
break;
|
|
16098
|
-
case
|
|
16091
|
+
case 3:
|
|
16099
16092
|
this.enterOuterAlt(localContext, 3);
|
|
16100
16093
|
{
|
|
16101
16094
|
this.state = 915;
|
|
@@ -16116,8 +16109,69 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16116
16109
|
} while (_la === 100);
|
|
16117
16110
|
}
|
|
16118
16111
|
break;
|
|
16119
|
-
|
|
16120
|
-
|
|
16112
|
+
case 4:
|
|
16113
|
+
this.enterOuterAlt(localContext, 4);
|
|
16114
|
+
{
|
|
16115
|
+
this.state = 921;
|
|
16116
|
+
this.scopedType();
|
|
16117
|
+
this.state = 923;
|
|
16118
|
+
this.errorHandler.sync(this);
|
|
16119
|
+
_la = this.tokenStream.LA(1);
|
|
16120
|
+
do {
|
|
16121
|
+
{
|
|
16122
|
+
{
|
|
16123
|
+
this.state = 922;
|
|
16124
|
+
this.arrayTypeDimension();
|
|
16125
|
+
}
|
|
16126
|
+
}
|
|
16127
|
+
this.state = 925;
|
|
16128
|
+
this.errorHandler.sync(this);
|
|
16129
|
+
_la = this.tokenStream.LA(1);
|
|
16130
|
+
} while (_la === 100);
|
|
16131
|
+
}
|
|
16132
|
+
break;
|
|
16133
|
+
case 5:
|
|
16134
|
+
this.enterOuterAlt(localContext, 5);
|
|
16135
|
+
{
|
|
16136
|
+
this.state = 927;
|
|
16137
|
+
this.qualifiedType();
|
|
16138
|
+
this.state = 929;
|
|
16139
|
+
this.errorHandler.sync(this);
|
|
16140
|
+
_la = this.tokenStream.LA(1);
|
|
16141
|
+
do {
|
|
16142
|
+
{
|
|
16143
|
+
{
|
|
16144
|
+
this.state = 928;
|
|
16145
|
+
this.arrayTypeDimension();
|
|
16146
|
+
}
|
|
16147
|
+
}
|
|
16148
|
+
this.state = 931;
|
|
16149
|
+
this.errorHandler.sync(this);
|
|
16150
|
+
_la = this.tokenStream.LA(1);
|
|
16151
|
+
} while (_la === 100);
|
|
16152
|
+
}
|
|
16153
|
+
break;
|
|
16154
|
+
case 6:
|
|
16155
|
+
this.enterOuterAlt(localContext, 6);
|
|
16156
|
+
{
|
|
16157
|
+
this.state = 933;
|
|
16158
|
+
this.globalType();
|
|
16159
|
+
this.state = 935;
|
|
16160
|
+
this.errorHandler.sync(this);
|
|
16161
|
+
_la = this.tokenStream.LA(1);
|
|
16162
|
+
do {
|
|
16163
|
+
{
|
|
16164
|
+
{
|
|
16165
|
+
this.state = 934;
|
|
16166
|
+
this.arrayTypeDimension();
|
|
16167
|
+
}
|
|
16168
|
+
}
|
|
16169
|
+
this.state = 937;
|
|
16170
|
+
this.errorHandler.sync(this);
|
|
16171
|
+
_la = this.tokenStream.LA(1);
|
|
16172
|
+
} while (_la === 100);
|
|
16173
|
+
}
|
|
16174
|
+
break;
|
|
16121
16175
|
}
|
|
16122
16176
|
} catch (re) {
|
|
16123
16177
|
if (re instanceof antlr2.RecognitionException) {
|
|
@@ -16138,18 +16192,18 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16138
16192
|
try {
|
|
16139
16193
|
this.enterOuterAlt(localContext, 1);
|
|
16140
16194
|
{
|
|
16141
|
-
this.state =
|
|
16195
|
+
this.state = 941;
|
|
16142
16196
|
this.match(_CNextParser.LBRACKET);
|
|
16143
|
-
this.state =
|
|
16197
|
+
this.state = 943;
|
|
16144
16198
|
this.errorHandler.sync(this);
|
|
16145
16199
|
_la = this.tokenStream.LA(1);
|
|
16146
16200
|
if ((_la & ~31) === 0 && (1 << _la & 2147532800) !== 0 || (_la - 32 & ~31) === 0 && (1 << _la - 32 & 1966091) !== 0 || (_la - 83 & ~31) === 0 && (1 << _la - 83 & 2130879681) !== 0) {
|
|
16147
16201
|
{
|
|
16148
|
-
this.state =
|
|
16202
|
+
this.state = 942;
|
|
16149
16203
|
this.expression();
|
|
16150
16204
|
}
|
|
16151
16205
|
}
|
|
16152
|
-
this.state =
|
|
16206
|
+
this.state = 945;
|
|
16153
16207
|
this.match(_CNextParser.RBRACKET);
|
|
16154
16208
|
}
|
|
16155
16209
|
} catch (re) {
|
|
@@ -16171,7 +16225,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16171
16225
|
try {
|
|
16172
16226
|
this.enterOuterAlt(localContext, 1);
|
|
16173
16227
|
{
|
|
16174
|
-
this.state =
|
|
16228
|
+
this.state = 947;
|
|
16175
16229
|
_la = this.tokenStream.LA(1);
|
|
16176
16230
|
if (!((_la - 31 & ~31) === 0 && (1 << _la - 31 & 3932167) !== 0 || (_la - 107 & ~31) === 0 && (1 << _la - 107 & 63) !== 0)) {
|
|
16177
16231
|
this.errorHandler.recoverInline(this);
|
|
@@ -16196,7 +16250,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
16196
16250
|
4,
|
|
16197
16251
|
1,
|
|
16198
16252
|
117,
|
|
16199
|
-
|
|
16253
|
+
950,
|
|
16200
16254
|
2,
|
|
16201
16255
|
0,
|
|
16202
16256
|
7,
|
|
@@ -18171,9 +18225,51 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
18171
18225
|
12,
|
|
18172
18226
|
85,
|
|
18173
18227
|
919,
|
|
18228
|
+
1,
|
|
18229
|
+
85,
|
|
18230
|
+
1,
|
|
18231
|
+
85,
|
|
18232
|
+
4,
|
|
18233
|
+
85,
|
|
18234
|
+
924,
|
|
18235
|
+
8,
|
|
18236
|
+
85,
|
|
18237
|
+
11,
|
|
18238
|
+
85,
|
|
18239
|
+
12,
|
|
18240
|
+
85,
|
|
18241
|
+
925,
|
|
18242
|
+
1,
|
|
18243
|
+
85,
|
|
18244
|
+
1,
|
|
18245
|
+
85,
|
|
18246
|
+
4,
|
|
18247
|
+
85,
|
|
18248
|
+
930,
|
|
18249
|
+
8,
|
|
18250
|
+
85,
|
|
18251
|
+
11,
|
|
18252
|
+
85,
|
|
18253
|
+
12,
|
|
18254
|
+
85,
|
|
18255
|
+
931,
|
|
18256
|
+
1,
|
|
18257
|
+
85,
|
|
18258
|
+
1,
|
|
18259
|
+
85,
|
|
18260
|
+
4,
|
|
18261
|
+
85,
|
|
18262
|
+
936,
|
|
18263
|
+
8,
|
|
18264
|
+
85,
|
|
18265
|
+
11,
|
|
18266
|
+
85,
|
|
18267
|
+
12,
|
|
18268
|
+
85,
|
|
18269
|
+
937,
|
|
18174
18270
|
3,
|
|
18175
18271
|
85,
|
|
18176
|
-
|
|
18272
|
+
940,
|
|
18177
18273
|
8,
|
|
18178
18274
|
85,
|
|
18179
18275
|
1,
|
|
@@ -18182,7 +18278,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
18182
18278
|
86,
|
|
18183
18279
|
3,
|
|
18184
18280
|
86,
|
|
18185
|
-
|
|
18281
|
+
944,
|
|
18186
18282
|
8,
|
|
18187
18283
|
86,
|
|
18188
18284
|
1,
|
|
@@ -18348,7 +18444,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
18348
18444
|
52,
|
|
18349
18445
|
107,
|
|
18350
18446
|
112,
|
|
18351
|
-
|
|
18447
|
+
1012,
|
|
18352
18448
|
0,
|
|
18353
18449
|
180,
|
|
18354
18450
|
1,
|
|
@@ -18860,19 +18956,19 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
18860
18956
|
0,
|
|
18861
18957
|
0,
|
|
18862
18958
|
170,
|
|
18863
|
-
|
|
18959
|
+
939,
|
|
18864
18960
|
1,
|
|
18865
18961
|
0,
|
|
18866
18962
|
0,
|
|
18867
18963
|
0,
|
|
18868
18964
|
172,
|
|
18869
|
-
|
|
18965
|
+
941,
|
|
18870
18966
|
1,
|
|
18871
18967
|
0,
|
|
18872
18968
|
0,
|
|
18873
18969
|
0,
|
|
18874
18970
|
174,
|
|
18875
|
-
|
|
18971
|
+
947,
|
|
18876
18972
|
1,
|
|
18877
18973
|
0,
|
|
18878
18974
|
0,
|
|
@@ -24110,7 +24206,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
24110
24206
|
0,
|
|
24111
24207
|
0,
|
|
24112
24208
|
908,
|
|
24113
|
-
|
|
24209
|
+
940,
|
|
24114
24210
|
1,
|
|
24115
24211
|
0,
|
|
24116
24212
|
0,
|
|
@@ -24152,7 +24248,7 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
24152
24248
|
0,
|
|
24153
24249
|
0,
|
|
24154
24250
|
914,
|
|
24155
|
-
|
|
24251
|
+
940,
|
|
24156
24252
|
1,
|
|
24157
24253
|
0,
|
|
24158
24254
|
0,
|
|
@@ -24194,90 +24290,234 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
24194
24290
|
0,
|
|
24195
24291
|
0,
|
|
24196
24292
|
920,
|
|
24197
|
-
|
|
24293
|
+
940,
|
|
24198
24294
|
1,
|
|
24199
24295
|
0,
|
|
24200
24296
|
0,
|
|
24201
24297
|
0,
|
|
24202
24298
|
921,
|
|
24299
|
+
923,
|
|
24300
|
+
3,
|
|
24301
|
+
152,
|
|
24302
|
+
76,
|
|
24303
|
+
0,
|
|
24304
|
+
922,
|
|
24305
|
+
924,
|
|
24306
|
+
3,
|
|
24307
|
+
172,
|
|
24308
|
+
86,
|
|
24309
|
+
0,
|
|
24310
|
+
923,
|
|
24311
|
+
922,
|
|
24312
|
+
1,
|
|
24313
|
+
0,
|
|
24314
|
+
0,
|
|
24315
|
+
0,
|
|
24316
|
+
924,
|
|
24317
|
+
925,
|
|
24318
|
+
1,
|
|
24319
|
+
0,
|
|
24320
|
+
0,
|
|
24321
|
+
0,
|
|
24322
|
+
925,
|
|
24323
|
+
923,
|
|
24324
|
+
1,
|
|
24325
|
+
0,
|
|
24326
|
+
0,
|
|
24327
|
+
0,
|
|
24328
|
+
925,
|
|
24329
|
+
926,
|
|
24330
|
+
1,
|
|
24331
|
+
0,
|
|
24332
|
+
0,
|
|
24333
|
+
0,
|
|
24334
|
+
926,
|
|
24335
|
+
940,
|
|
24336
|
+
1,
|
|
24337
|
+
0,
|
|
24338
|
+
0,
|
|
24339
|
+
0,
|
|
24340
|
+
927,
|
|
24341
|
+
929,
|
|
24342
|
+
3,
|
|
24343
|
+
156,
|
|
24344
|
+
78,
|
|
24345
|
+
0,
|
|
24346
|
+
928,
|
|
24347
|
+
930,
|
|
24348
|
+
3,
|
|
24349
|
+
172,
|
|
24350
|
+
86,
|
|
24351
|
+
0,
|
|
24352
|
+
929,
|
|
24353
|
+
928,
|
|
24354
|
+
1,
|
|
24355
|
+
0,
|
|
24356
|
+
0,
|
|
24357
|
+
0,
|
|
24358
|
+
930,
|
|
24359
|
+
931,
|
|
24360
|
+
1,
|
|
24361
|
+
0,
|
|
24362
|
+
0,
|
|
24363
|
+
0,
|
|
24364
|
+
931,
|
|
24365
|
+
929,
|
|
24366
|
+
1,
|
|
24367
|
+
0,
|
|
24368
|
+
0,
|
|
24369
|
+
0,
|
|
24370
|
+
931,
|
|
24371
|
+
932,
|
|
24372
|
+
1,
|
|
24373
|
+
0,
|
|
24374
|
+
0,
|
|
24375
|
+
0,
|
|
24376
|
+
932,
|
|
24377
|
+
940,
|
|
24378
|
+
1,
|
|
24379
|
+
0,
|
|
24380
|
+
0,
|
|
24381
|
+
0,
|
|
24382
|
+
933,
|
|
24383
|
+
935,
|
|
24384
|
+
3,
|
|
24385
|
+
154,
|
|
24386
|
+
77,
|
|
24387
|
+
0,
|
|
24388
|
+
934,
|
|
24389
|
+
936,
|
|
24390
|
+
3,
|
|
24391
|
+
172,
|
|
24392
|
+
86,
|
|
24393
|
+
0,
|
|
24394
|
+
935,
|
|
24395
|
+
934,
|
|
24396
|
+
1,
|
|
24397
|
+
0,
|
|
24398
|
+
0,
|
|
24399
|
+
0,
|
|
24400
|
+
936,
|
|
24401
|
+
937,
|
|
24402
|
+
1,
|
|
24403
|
+
0,
|
|
24404
|
+
0,
|
|
24405
|
+
0,
|
|
24406
|
+
937,
|
|
24407
|
+
935,
|
|
24408
|
+
1,
|
|
24409
|
+
0,
|
|
24410
|
+
0,
|
|
24411
|
+
0,
|
|
24412
|
+
937,
|
|
24413
|
+
938,
|
|
24414
|
+
1,
|
|
24415
|
+
0,
|
|
24416
|
+
0,
|
|
24417
|
+
0,
|
|
24418
|
+
938,
|
|
24419
|
+
940,
|
|
24420
|
+
1,
|
|
24421
|
+
0,
|
|
24422
|
+
0,
|
|
24423
|
+
0,
|
|
24424
|
+
939,
|
|
24203
24425
|
903,
|
|
24204
24426
|
1,
|
|
24205
24427
|
0,
|
|
24206
24428
|
0,
|
|
24207
24429
|
0,
|
|
24208
|
-
|
|
24430
|
+
939,
|
|
24209
24431
|
909,
|
|
24210
24432
|
1,
|
|
24211
24433
|
0,
|
|
24212
24434
|
0,
|
|
24213
24435
|
0,
|
|
24214
|
-
|
|
24436
|
+
939,
|
|
24215
24437
|
915,
|
|
24216
24438
|
1,
|
|
24217
24439
|
0,
|
|
24218
24440
|
0,
|
|
24219
24441
|
0,
|
|
24220
|
-
|
|
24442
|
+
939,
|
|
24443
|
+
921,
|
|
24444
|
+
1,
|
|
24445
|
+
0,
|
|
24446
|
+
0,
|
|
24447
|
+
0,
|
|
24448
|
+
939,
|
|
24449
|
+
927,
|
|
24450
|
+
1,
|
|
24451
|
+
0,
|
|
24452
|
+
0,
|
|
24453
|
+
0,
|
|
24454
|
+
939,
|
|
24455
|
+
933,
|
|
24456
|
+
1,
|
|
24457
|
+
0,
|
|
24458
|
+
0,
|
|
24459
|
+
0,
|
|
24460
|
+
940,
|
|
24221
24461
|
171,
|
|
24222
24462
|
1,
|
|
24223
24463
|
0,
|
|
24224
24464
|
0,
|
|
24225
24465
|
0,
|
|
24226
|
-
|
|
24227
|
-
|
|
24466
|
+
941,
|
|
24467
|
+
943,
|
|
24228
24468
|
5,
|
|
24229
24469
|
100,
|
|
24230
24470
|
0,
|
|
24231
24471
|
0,
|
|
24232
|
-
|
|
24233
|
-
|
|
24472
|
+
942,
|
|
24473
|
+
944,
|
|
24234
24474
|
3,
|
|
24235
24475
|
102,
|
|
24236
24476
|
51,
|
|
24237
24477
|
0,
|
|
24238
|
-
|
|
24239
|
-
|
|
24478
|
+
943,
|
|
24479
|
+
942,
|
|
24240
24480
|
1,
|
|
24241
24481
|
0,
|
|
24242
24482
|
0,
|
|
24243
24483
|
0,
|
|
24244
|
-
|
|
24245
|
-
|
|
24484
|
+
943,
|
|
24485
|
+
944,
|
|
24246
24486
|
1,
|
|
24247
24487
|
0,
|
|
24248
24488
|
0,
|
|
24249
24489
|
0,
|
|
24250
|
-
|
|
24251
|
-
|
|
24490
|
+
944,
|
|
24491
|
+
945,
|
|
24252
24492
|
1,
|
|
24253
24493
|
0,
|
|
24254
24494
|
0,
|
|
24255
24495
|
0,
|
|
24256
|
-
|
|
24257
|
-
|
|
24496
|
+
945,
|
|
24497
|
+
946,
|
|
24258
24498
|
5,
|
|
24259
24499
|
101,
|
|
24260
24500
|
0,
|
|
24261
24501
|
0,
|
|
24262
|
-
|
|
24502
|
+
946,
|
|
24263
24503
|
173,
|
|
24264
24504
|
1,
|
|
24265
24505
|
0,
|
|
24266
24506
|
0,
|
|
24267
24507
|
0,
|
|
24268
|
-
|
|
24269
|
-
|
|
24508
|
+
947,
|
|
24509
|
+
948,
|
|
24270
24510
|
7,
|
|
24271
24511
|
13,
|
|
24272
24512
|
0,
|
|
24273
24513
|
0,
|
|
24274
|
-
|
|
24514
|
+
948,
|
|
24275
24515
|
175,
|
|
24276
24516
|
1,
|
|
24277
24517
|
0,
|
|
24278
24518
|
0,
|
|
24279
24519
|
0,
|
|
24280
|
-
|
|
24520
|
+
100,
|
|
24281
24521
|
178,
|
|
24282
24522
|
180,
|
|
24283
24523
|
186,
|
|
@@ -24373,8 +24613,11 @@ var CNextParser = class _CNextParser extends antlr2.Parser {
|
|
|
24373
24613
|
907,
|
|
24374
24614
|
913,
|
|
24375
24615
|
919,
|
|
24376
|
-
|
|
24377
|
-
|
|
24616
|
+
925,
|
|
24617
|
+
931,
|
|
24618
|
+
937,
|
|
24619
|
+
939,
|
|
24620
|
+
943
|
|
24378
24621
|
];
|
|
24379
24622
|
static __ATN;
|
|
24380
24623
|
static get _ATN() {
|
|
@@ -27875,6 +28118,15 @@ var ArrayTypeContext = class extends antlr2.ParserRuleContext {
|
|
|
27875
28118
|
stringType() {
|
|
27876
28119
|
return this.getRuleContext(0, StringTypeContext);
|
|
27877
28120
|
}
|
|
28121
|
+
scopedType() {
|
|
28122
|
+
return this.getRuleContext(0, ScopedTypeContext);
|
|
28123
|
+
}
|
|
28124
|
+
qualifiedType() {
|
|
28125
|
+
return this.getRuleContext(0, QualifiedTypeContext);
|
|
28126
|
+
}
|
|
28127
|
+
globalType() {
|
|
28128
|
+
return this.getRuleContext(0, GlobalTypeContext);
|
|
28129
|
+
}
|
|
27878
28130
|
get ruleIndex() {
|
|
27879
28131
|
return CNextParser.RULE_arrayType;
|
|
27880
28132
|
}
|
|
@@ -111383,7 +111635,7 @@ var ESourceLanguage = /* @__PURE__ */ ((ESourceLanguage2) => {
|
|
|
111383
111635
|
var ESourceLanguage_default = ESourceLanguage;
|
|
111384
111636
|
|
|
111385
111637
|
// src/utils/LiteralUtils.ts
|
|
111386
|
-
var LiteralUtils = class {
|
|
111638
|
+
var LiteralUtils = class _LiteralUtils {
|
|
111387
111639
|
/**
|
|
111388
111640
|
* Check if a literal represents zero.
|
|
111389
111641
|
*
|
|
@@ -111418,8 +111670,25 @@ var LiteralUtils = class {
|
|
|
111418
111670
|
if (ctx.SUFFIXED_BINARY()) {
|
|
111419
111671
|
return text.startsWith("0b0u") || text.startsWith("0b0i") || text.startsWith("0B0u") || text.startsWith("0B0i");
|
|
111420
111672
|
}
|
|
111673
|
+
if (ctx.FLOAT_LITERAL()) {
|
|
111674
|
+
return _LiteralUtils.isFloatZero(text);
|
|
111675
|
+
}
|
|
111421
111676
|
return false;
|
|
111422
111677
|
}
|
|
111678
|
+
/**
|
|
111679
|
+
* Check if a float literal string represents zero.
|
|
111680
|
+
* Issue #1010: Detect float zero for division-by-zero checking.
|
|
111681
|
+
*
|
|
111682
|
+
* Handles: 0.0, .0, 0., 0.0f, 0.0F, 0.0e0, 0.0E0, etc.
|
|
111683
|
+
*
|
|
111684
|
+
* @param text - The float literal text
|
|
111685
|
+
* @returns true if the float is zero
|
|
111686
|
+
*/
|
|
111687
|
+
static isFloatZero(text) {
|
|
111688
|
+
const withoutSuffix = text.replace(/[fF]$/, "");
|
|
111689
|
+
const value = Number.parseFloat(withoutSuffix);
|
|
111690
|
+
return value === 0;
|
|
111691
|
+
}
|
|
111423
111692
|
/**
|
|
111424
111693
|
* Check if a literal is a floating-point number.
|
|
111425
111694
|
*
|
|
@@ -112539,12 +112808,23 @@ Rename the C-Next symbol to resolve.`
|
|
|
112539
112808
|
* Issue #958: Check if a typedef aliases a struct type.
|
|
112540
112809
|
* Used for scope variables, function parameters, and local variables
|
|
112541
112810
|
* which should be pointers for C-header struct types.
|
|
112811
|
+
*
|
|
112812
|
+
* Issue #948: Performs query-time resolution - if the underlying struct
|
|
112813
|
+
* tag has a full body definition, this is NOT an external typedef struct
|
|
112814
|
+
* (it's a complete type that can use value semantics).
|
|
112815
|
+
*
|
|
112542
112816
|
* @param typeName The type name to check
|
|
112543
112817
|
* @returns true if this is a typedef'd struct type from C headers
|
|
112544
112818
|
*/
|
|
112545
112819
|
isTypedefStructType(typeName) {
|
|
112546
|
-
|
|
112547
|
-
|
|
112820
|
+
if (!this.structState.typedefStructTypes.has(typeName)) {
|
|
112821
|
+
return false;
|
|
112822
|
+
}
|
|
112823
|
+
const tag = this.structState.typedefToTag.get(typeName);
|
|
112824
|
+
if (tag && this.structState.structTagsWithBodies.has(tag)) {
|
|
112825
|
+
return false;
|
|
112826
|
+
}
|
|
112827
|
+
return true;
|
|
112548
112828
|
}
|
|
112549
112829
|
/**
|
|
112550
112830
|
* Issue #958: Get all typedef struct types for cache serialization.
|
|
@@ -112798,6 +113078,11 @@ var CodeGenState = class _CodeGenState {
|
|
|
112798
113078
|
static indentLevel = 0;
|
|
112799
113079
|
/** Whether we're inside a function body */
|
|
112800
113080
|
static inFunctionBody = false;
|
|
113081
|
+
/** Whether we're generating the RHS of a variable declaration initializer.
|
|
113082
|
+
* When true, struct literals use { .field = value } instead of (Type){ .field = value }
|
|
113083
|
+
* because plain designated initializers are valid C99 at any scope, while compound
|
|
113084
|
+
* literals are not constant expressions and fail at file scope on GCC < 13. */
|
|
113085
|
+
static inDeclarationInit = false;
|
|
112801
113086
|
/** Expected type for struct initializers and enum inference */
|
|
112802
113087
|
static expectedType = null;
|
|
112803
113088
|
/**
|
|
@@ -112910,6 +113195,7 @@ var CodeGenState = class _CodeGenState {
|
|
|
112910
113195
|
this.floatShadowCurrent = /* @__PURE__ */ new Set();
|
|
112911
113196
|
this.indentLevel = 0;
|
|
112912
113197
|
this.inFunctionBody = false;
|
|
113198
|
+
this.inDeclarationInit = false;
|
|
112913
113199
|
this.expectedType = null;
|
|
112914
113200
|
this.suppressBareEnumResolution = false;
|
|
112915
113201
|
this.mainArgsName = null;
|
|
@@ -112989,6 +113275,46 @@ var CodeGenState = class _CodeGenState {
|
|
|
112989
113275
|
this.suppressBareEnumResolution = savedSuppress;
|
|
112990
113276
|
}
|
|
112991
113277
|
}
|
|
113278
|
+
/** Execute fn with inDeclarationInit=true, restoring prior value on exit. */
|
|
113279
|
+
static withDeclarationInit(fn) {
|
|
113280
|
+
const saved = this.inDeclarationInit;
|
|
113281
|
+
this.inDeclarationInit = true;
|
|
113282
|
+
try {
|
|
113283
|
+
return fn();
|
|
113284
|
+
} finally {
|
|
113285
|
+
this.inDeclarationInit = saved;
|
|
113286
|
+
}
|
|
113287
|
+
}
|
|
113288
|
+
/** Execute fn with inDeclarationInit=false, restoring prior value on exit.
|
|
113289
|
+
* Used in sub-expression contexts (function args, ternary arms) where
|
|
113290
|
+
* plain designated initializers are not valid C. */
|
|
113291
|
+
static withoutDeclarationInit(fn) {
|
|
113292
|
+
const saved = this.inDeclarationInit;
|
|
113293
|
+
this.inDeclarationInit = false;
|
|
113294
|
+
try {
|
|
113295
|
+
return fn();
|
|
113296
|
+
} finally {
|
|
113297
|
+
this.inDeclarationInit = saved;
|
|
113298
|
+
}
|
|
113299
|
+
}
|
|
113300
|
+
/**
|
|
113301
|
+
* Execute fn with expectedType=null, restoring prior value on exit.
|
|
113302
|
+
* Issue #1032: Used in comparison contexts (relational/equality expressions)
|
|
113303
|
+
* where MISRA 7.2 U suffix should NOT be applied - comparing `i32 < 0`
|
|
113304
|
+
* should not generate `signedIdx < 0U` which changes comparison semantics.
|
|
113305
|
+
*/
|
|
113306
|
+
static withoutExpectedType(fn) {
|
|
113307
|
+
const savedType = this.expectedType;
|
|
113308
|
+
const savedSuppress = this.suppressBareEnumResolution;
|
|
113309
|
+
this.expectedType = null;
|
|
113310
|
+
this.suppressBareEnumResolution = false;
|
|
113311
|
+
try {
|
|
113312
|
+
return fn();
|
|
113313
|
+
} finally {
|
|
113314
|
+
this.expectedType = savedType;
|
|
113315
|
+
this.suppressBareEnumResolution = savedSuppress;
|
|
113316
|
+
}
|
|
113317
|
+
}
|
|
112992
113318
|
// ===========================================================================
|
|
112993
113319
|
// CONVENIENCE LOOKUP METHODS
|
|
112994
113320
|
// ===========================================================================
|
|
@@ -113525,14 +113851,27 @@ var CodeGenState = class _CodeGenState {
|
|
|
113525
113851
|
this.opaqueScopeVariables.add(qualifiedName);
|
|
113526
113852
|
}
|
|
113527
113853
|
/**
|
|
113528
|
-
* Check if
|
|
113529
|
-
* Used during
|
|
113854
|
+
* Check if generated code accesses an opaque scope variable (and is thus
|
|
113855
|
+
* already a pointer). Used during argument generation to decide whether an
|
|
113856
|
+
* address-of (&) prefix is needed.
|
|
113530
113857
|
*
|
|
113531
|
-
*
|
|
113532
|
-
*
|
|
113858
|
+
* Handles two forms:
|
|
113859
|
+
* - Direct access: "MyScope_widget" → the handle itself (pointer)
|
|
113860
|
+
* - Array-element access: "MyScope_widgets[i]" → an element of an opaque
|
|
113861
|
+
* handle array, which is itself a pointer (Issue #996)
|
|
113862
|
+
*
|
|
113863
|
+
* @param generatedCode - The generated access expression (e.g. "UI_widgets[i]")
|
|
113864
|
+
* @returns true if this resolves to an opaque scope variable (already a pointer)
|
|
113533
113865
|
*/
|
|
113534
|
-
static
|
|
113535
|
-
|
|
113866
|
+
static isOpaqueScopeVariableAccess(generatedCode) {
|
|
113867
|
+
if (this.opaqueScopeVariables.has(generatedCode)) {
|
|
113868
|
+
return true;
|
|
113869
|
+
}
|
|
113870
|
+
const bracketIndex = generatedCode.indexOf("[");
|
|
113871
|
+
if (bracketIndex === -1) {
|
|
113872
|
+
return false;
|
|
113873
|
+
}
|
|
113874
|
+
return this.opaqueScopeVariables.has(generatedCode.slice(0, bracketIndex));
|
|
113536
113875
|
}
|
|
113537
113876
|
// ===========================================================================
|
|
113538
113877
|
// C++ MODE HELPERS
|
|
@@ -114442,41 +114781,73 @@ var TypeRegistrationEngine = class _TypeRegistrationEngine {
|
|
|
114442
114781
|
});
|
|
114443
114782
|
return true;
|
|
114444
114783
|
}
|
|
114784
|
+
/**
|
|
114785
|
+
* Issue #1029: Register type info for string arrays (string<N>[M]).
|
|
114786
|
+
*
|
|
114787
|
+
* String arrays are parsed as arrayType with stringType inside:
|
|
114788
|
+
* arrayType -> stringType arrayTypeDimension+
|
|
114789
|
+
*
|
|
114790
|
+
* For `string<32>[4] items`:
|
|
114791
|
+
* - stringType gives capacity 32
|
|
114792
|
+
* - arrayTypeDimension gives [4]
|
|
114793
|
+
* - Result: char items[4][33] with dimensions [4, 33]
|
|
114794
|
+
*/
|
|
114795
|
+
static _registerStringArrayType(registryName, arrayTypeCtx, arrayDim, isConst, overflowBehavior, isAtomic, callbacks) {
|
|
114796
|
+
const stringCtx = arrayTypeCtx.stringType();
|
|
114797
|
+
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
114798
|
+
if (!intLiteral) {
|
|
114799
|
+
return;
|
|
114800
|
+
}
|
|
114801
|
+
const capacity = Number.parseInt(intLiteral.getText(), 10);
|
|
114802
|
+
callbacks.requireInclude("string");
|
|
114803
|
+
const stringDim = capacity + 1;
|
|
114804
|
+
const arrayTypeDims = arrayTypeCtx.arrayTypeDimension().map((dim) => dim.expression()).filter((expr) => expr !== null).map((expr) => Number.parseInt(expr.getText(), 10)).filter((size) => !Number.isNaN(size));
|
|
114805
|
+
const additionalDims = ArrayDimensionParser_default.parseSimpleDimensions(arrayDim);
|
|
114806
|
+
const dimensions = [...arrayTypeDims, ...additionalDims, stringDim];
|
|
114807
|
+
CodeGenState.setVariableTypeInfo(registryName, {
|
|
114808
|
+
baseType: "char",
|
|
114809
|
+
bitWidth: 8,
|
|
114810
|
+
isArray: true,
|
|
114811
|
+
arrayDimensions: dimensions,
|
|
114812
|
+
isConst,
|
|
114813
|
+
isString: true,
|
|
114814
|
+
stringCapacity: capacity,
|
|
114815
|
+
overflowBehavior,
|
|
114816
|
+
isAtomic
|
|
114817
|
+
});
|
|
114818
|
+
}
|
|
114445
114819
|
// ============================================================================
|
|
114446
114820
|
// Array and standard type registration
|
|
114447
114821
|
// ============================================================================
|
|
114448
114822
|
static _registerArrayTypeVariable(registryName, arrayTypeCtx, arrayDim, isConst, overflowBehavior, isAtomic, callbacks) {
|
|
114449
|
-
|
|
114450
|
-
|
|
114451
|
-
if (arrayTypeCtx.primitiveType()) {
|
|
114452
|
-
baseType = arrayTypeCtx.primitiveType().getText();
|
|
114453
|
-
bitWidth = TYPE_WIDTH_default[baseType] || 0;
|
|
114454
|
-
} else if (arrayTypeCtx.userType()) {
|
|
114455
|
-
baseType = arrayTypeCtx.userType().getText();
|
|
114456
|
-
const combinedArrayDim = arrayDim ?? [];
|
|
114457
|
-
if (_TypeRegistrationEngine._tryRegisterEnumOrBitmapType(
|
|
114823
|
+
if (arrayTypeCtx.stringType()) {
|
|
114824
|
+
_TypeRegistrationEngine._registerStringArrayType(
|
|
114458
114825
|
registryName,
|
|
114459
|
-
|
|
114826
|
+
arrayTypeCtx,
|
|
114827
|
+
arrayDim,
|
|
114460
114828
|
isConst,
|
|
114461
|
-
combinedArrayDim,
|
|
114462
114829
|
overflowBehavior,
|
|
114463
114830
|
isAtomic,
|
|
114464
114831
|
callbacks
|
|
114465
|
-
)
|
|
114466
|
-
|
|
114467
|
-
|
|
114468
|
-
|
|
114469
|
-
|
|
114470
|
-
|
|
114471
|
-
|
|
114472
|
-
|
|
114473
|
-
|
|
114474
|
-
|
|
114475
|
-
|
|
114832
|
+
);
|
|
114833
|
+
return;
|
|
114834
|
+
}
|
|
114835
|
+
if (arrayTypeCtx.userType()) {
|
|
114836
|
+
const registered = _TypeRegistrationEngine._tryRegisterUserTypeArray(
|
|
114837
|
+
registryName,
|
|
114838
|
+
arrayTypeCtx,
|
|
114839
|
+
arrayDim,
|
|
114840
|
+
isConst,
|
|
114841
|
+
overflowBehavior,
|
|
114842
|
+
isAtomic,
|
|
114843
|
+
callbacks
|
|
114844
|
+
);
|
|
114845
|
+
if (registered) {
|
|
114476
114846
|
return;
|
|
114477
114847
|
}
|
|
114478
114848
|
}
|
|
114479
|
-
|
|
114849
|
+
const typeInfo = _TypeRegistrationEngine._extractArrayBaseTypeInfo(arrayTypeCtx);
|
|
114850
|
+
if (!typeInfo.baseType) {
|
|
114480
114851
|
return;
|
|
114481
114852
|
}
|
|
114482
114853
|
const arrayDimensions = _TypeRegistrationEngine._collectArrayDimensions(
|
|
@@ -114485,8 +114856,8 @@ var TypeRegistrationEngine = class _TypeRegistrationEngine {
|
|
|
114485
114856
|
callbacks
|
|
114486
114857
|
);
|
|
114487
114858
|
CodeGenState.setVariableTypeInfo(registryName, {
|
|
114488
|
-
baseType,
|
|
114489
|
-
bitWidth,
|
|
114859
|
+
baseType: typeInfo.baseType,
|
|
114860
|
+
bitWidth: typeInfo.bitWidth,
|
|
114490
114861
|
isArray: true,
|
|
114491
114862
|
arrayDimensions: arrayDimensions.length > 0 ? arrayDimensions : void 0,
|
|
114492
114863
|
isConst,
|
|
@@ -114494,6 +114865,64 @@ var TypeRegistrationEngine = class _TypeRegistrationEngine {
|
|
|
114494
114865
|
isAtomic
|
|
114495
114866
|
});
|
|
114496
114867
|
}
|
|
114868
|
+
/**
|
|
114869
|
+
* Extract base type and bit width from an array type context.
|
|
114870
|
+
* Handles primitive, qualified, scoped, and user types.
|
|
114871
|
+
*/
|
|
114872
|
+
static _extractArrayBaseTypeInfo(arrayTypeCtx) {
|
|
114873
|
+
if (arrayTypeCtx.primitiveType()) {
|
|
114874
|
+
const baseType = arrayTypeCtx.primitiveType().getText();
|
|
114875
|
+
return { baseType, bitWidth: TYPE_WIDTH_default[baseType] || 0 };
|
|
114876
|
+
}
|
|
114877
|
+
if (arrayTypeCtx.qualifiedType()) {
|
|
114878
|
+
const parts = arrayTypeCtx.qualifiedType().IDENTIFIER();
|
|
114879
|
+
return { baseType: parts.map((p) => p.getText()).join("_"), bitWidth: 0 };
|
|
114880
|
+
}
|
|
114881
|
+
if (arrayTypeCtx.scopedType()) {
|
|
114882
|
+
const typeName = arrayTypeCtx.scopedType().IDENTIFIER().getText();
|
|
114883
|
+
const baseType = CodeGenState.currentScope ? `${CodeGenState.currentScope}_${typeName}` : typeName;
|
|
114884
|
+
return { baseType, bitWidth: 0 };
|
|
114885
|
+
}
|
|
114886
|
+
if (arrayTypeCtx.globalType()) {
|
|
114887
|
+
const typeName = arrayTypeCtx.globalType().IDENTIFIER().getText();
|
|
114888
|
+
return { baseType: typeName, bitWidth: 0 };
|
|
114889
|
+
}
|
|
114890
|
+
if (arrayTypeCtx.userType()) {
|
|
114891
|
+
return { baseType: arrayTypeCtx.userType().getText(), bitWidth: 0 };
|
|
114892
|
+
}
|
|
114893
|
+
return { baseType: "", bitWidth: 0 };
|
|
114894
|
+
}
|
|
114895
|
+
/**
|
|
114896
|
+
* Try to register a user type array as enum or bitmap.
|
|
114897
|
+
* Returns true if registration was handled, false if it should fall through.
|
|
114898
|
+
*/
|
|
114899
|
+
static _tryRegisterUserTypeArray(registryName, arrayTypeCtx, arrayDim, isConst, overflowBehavior, isAtomic, callbacks) {
|
|
114900
|
+
const baseType = arrayTypeCtx.userType().getText();
|
|
114901
|
+
const combinedArrayDim = arrayDim ?? [];
|
|
114902
|
+
const registered = _TypeRegistrationEngine._tryRegisterEnumOrBitmapType(
|
|
114903
|
+
registryName,
|
|
114904
|
+
baseType,
|
|
114905
|
+
isConst,
|
|
114906
|
+
combinedArrayDim,
|
|
114907
|
+
overflowBehavior,
|
|
114908
|
+
isAtomic,
|
|
114909
|
+
callbacks
|
|
114910
|
+
);
|
|
114911
|
+
if (!registered) {
|
|
114912
|
+
return false;
|
|
114913
|
+
}
|
|
114914
|
+
const existingInfo = CodeGenState.getVariableTypeInfo(registryName);
|
|
114915
|
+
if (existingInfo) {
|
|
114916
|
+
const arrayTypeDim = _TypeRegistrationEngine.parseArrayTypeDimension(arrayTypeCtx);
|
|
114917
|
+
const allDims = arrayTypeDim ? [arrayTypeDim, ...existingInfo.arrayDimensions ?? []] : existingInfo.arrayDimensions;
|
|
114918
|
+
CodeGenState.setVariableTypeInfo(registryName, {
|
|
114919
|
+
...existingInfo,
|
|
114920
|
+
isArray: true,
|
|
114921
|
+
arrayDimensions: allDims
|
|
114922
|
+
});
|
|
114923
|
+
}
|
|
114924
|
+
return true;
|
|
114925
|
+
}
|
|
114497
114926
|
static _collectArrayDimensions(arrayTypeCtx, arrayDim, callbacks) {
|
|
114498
114927
|
const arrayDimensions = [];
|
|
114499
114928
|
for (const dim of arrayTypeCtx.arrayTypeDimension()) {
|
|
@@ -116989,18 +117418,10 @@ var generateEqualityExpr = (node, input, state, orchestrator) => {
|
|
|
116989
117418
|
const rightIsString = orchestrator.isStringExpression(exprs[1]);
|
|
116990
117419
|
if (leftIsString || rightIsString) {
|
|
116991
117420
|
effects.push({ type: "include", header: "string" });
|
|
116992
|
-
const leftResult =
|
|
116993
|
-
exprs[0],
|
|
116994
|
-
input,
|
|
116995
|
-
|
|
116996
|
-
orchestrator
|
|
116997
|
-
);
|
|
116998
|
-
const rightResult = generateRelationalExpr(
|
|
116999
|
-
exprs[1],
|
|
117000
|
-
input,
|
|
117001
|
-
state,
|
|
117002
|
-
orchestrator
|
|
117003
|
-
);
|
|
117421
|
+
const [leftResult, rightResult] = CodeGenState.withoutExpectedType(() => [
|
|
117422
|
+
generateRelationalExpr(exprs[0], input, state, orchestrator),
|
|
117423
|
+
generateRelationalExpr(exprs[1], input, state, orchestrator)
|
|
117424
|
+
]);
|
|
117004
117425
|
effects.push(...leftResult.effects, ...rightResult.effects);
|
|
117005
117426
|
const fullText = node.getText();
|
|
117006
117427
|
const isNotEqual = fullText.includes("!=");
|
|
@@ -117015,13 +117436,15 @@ var generateEqualityExpr = (node, input, state, orchestrator) => {
|
|
|
117015
117436
|
}
|
|
117016
117437
|
}
|
|
117017
117438
|
const operators = orchestrator.getOperatorsFromChildren(node);
|
|
117018
|
-
return
|
|
117019
|
-
|
|
117020
|
-
|
|
117021
|
-
|
|
117022
|
-
|
|
117023
|
-
|
|
117024
|
-
|
|
117439
|
+
return CodeGenState.withoutExpectedType(
|
|
117440
|
+
() => accumulateBinaryExprs(
|
|
117441
|
+
exprs,
|
|
117442
|
+
operators,
|
|
117443
|
+
"=",
|
|
117444
|
+
generateRelationalExpr,
|
|
117445
|
+
{ input, state, orchestrator },
|
|
117446
|
+
BinaryExprUtils_default.mapEqualityOperator
|
|
117447
|
+
)
|
|
117025
117448
|
);
|
|
117026
117449
|
};
|
|
117027
117450
|
var generateRelationalExpr = (node, input, state, orchestrator) => {
|
|
@@ -117030,11 +117453,13 @@ var generateRelationalExpr = (node, input, state, orchestrator) => {
|
|
|
117030
117453
|
return generateBitwiseOrExpr(exprs[0], input, state, orchestrator);
|
|
117031
117454
|
}
|
|
117032
117455
|
const operators = orchestrator.getOperatorsFromChildren(node);
|
|
117033
|
-
return
|
|
117034
|
-
|
|
117035
|
-
|
|
117036
|
-
|
|
117037
|
-
|
|
117456
|
+
return CodeGenState.withoutExpectedType(
|
|
117457
|
+
() => accumulateBinaryExprs(exprs, operators, "<", generateBitwiseOrExpr, {
|
|
117458
|
+
input,
|
|
117459
|
+
state,
|
|
117460
|
+
orchestrator
|
|
117461
|
+
})
|
|
117462
|
+
);
|
|
117038
117463
|
};
|
|
117039
117464
|
var generateBitwiseOrExpr = (node, input, state, orchestrator) => {
|
|
117040
117465
|
const effects = [];
|
|
@@ -117224,8 +117649,12 @@ var generateTernaryExpr = (node, _input, _state, orchestrator) => {
|
|
|
117224
117649
|
orchestrator.validateNoNestedTernary(falseExpr, "false branch");
|
|
117225
117650
|
orchestrator.validateTernaryConditionNoFunctionCall(condition);
|
|
117226
117651
|
const condCode = orchestrator.generateOrExpr(condition);
|
|
117227
|
-
const trueCode =
|
|
117228
|
-
|
|
117652
|
+
const trueCode = CodeGenState.withoutDeclarationInit(
|
|
117653
|
+
() => orchestrator.generateOrExpr(trueExpr)
|
|
117654
|
+
);
|
|
117655
|
+
const falseCode = CodeGenState.withoutDeclarationInit(
|
|
117656
|
+
() => orchestrator.generateOrExpr(falseExpr)
|
|
117657
|
+
);
|
|
117229
117658
|
return { code: `(${condCode}) ? ${trueCode} : ${falseCode}`, effects };
|
|
117230
117659
|
};
|
|
117231
117660
|
var expressionGenerators = {
|
|
@@ -117436,7 +117865,7 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
117436
117865
|
if (typeInfo?.isPointer) {
|
|
117437
117866
|
isPointerVariable = true;
|
|
117438
117867
|
}
|
|
117439
|
-
const isOpaqueScopeVar = CodeGenState.
|
|
117868
|
+
const isOpaqueScopeVar = CodeGenState.isOpaqueScopeVariableAccess(argCode);
|
|
117440
117869
|
const needsAddressOf = argType && !argType.endsWith("*") && !argCode.startsWith("&") && !targetParam.isArray && !isPointerVariable && !isOpaqueScopeVar && (orchestrator.isStructType(argType) || _parameterExpectsAddressOf(targetParam.baseType, argType, orchestrator));
|
|
117441
117870
|
const finalArgCode = needsAddressOf ? `&${argCode}` : argCode;
|
|
117442
117871
|
return wrapWithCppEnumCast(
|
|
@@ -117473,39 +117902,41 @@ var generateFunctionCall = (funcExpr, argCtx, input, _state, orchestrator) => {
|
|
|
117473
117902
|
trackPassThroughModifications(funcExpr, argExprs, orchestrator);
|
|
117474
117903
|
}
|
|
117475
117904
|
const sig = input.functionSignatures.get(funcExpr);
|
|
117476
|
-
const args =
|
|
117477
|
-
|
|
117478
|
-
|
|
117479
|
-
|
|
117480
|
-
|
|
117481
|
-
|
|
117482
|
-
|
|
117483
|
-
const targetParam = resolved.param;
|
|
117484
|
-
if (!isCNextFunc) {
|
|
117485
|
-
return _generateCFunctionArg(e, targetParam, input, orchestrator);
|
|
117486
|
-
}
|
|
117487
|
-
if (_shouldPassByValue(
|
|
117488
|
-
funcExpr,
|
|
117489
|
-
idx,
|
|
117490
|
-
targetParam,
|
|
117491
|
-
resolved.isCrossFile,
|
|
117492
|
-
orchestrator
|
|
117493
|
-
)) {
|
|
117494
|
-
const argCode = CodeGenState.withExpectedType(
|
|
117495
|
-
targetParam?.baseType,
|
|
117496
|
-
() => orchestrator.generateExpression(e),
|
|
117497
|
-
true
|
|
117498
|
-
// suppressEnumResolution
|
|
117905
|
+
const args = CodeGenState.withoutDeclarationInit(
|
|
117906
|
+
() => argExprs.map((e, idx) => {
|
|
117907
|
+
const resolved = CallExprUtils_default.resolveTargetParam(
|
|
117908
|
+
sig,
|
|
117909
|
+
idx,
|
|
117910
|
+
funcExpr,
|
|
117911
|
+
input.symbolTable
|
|
117499
117912
|
);
|
|
117500
|
-
|
|
117501
|
-
|
|
117502
|
-
e,
|
|
117503
|
-
|
|
117913
|
+
const targetParam = resolved.param;
|
|
117914
|
+
if (!isCNextFunc) {
|
|
117915
|
+
return _generateCFunctionArg(e, targetParam, input, orchestrator);
|
|
117916
|
+
}
|
|
117917
|
+
if (_shouldPassByValue(
|
|
117918
|
+
funcExpr,
|
|
117919
|
+
idx,
|
|
117920
|
+
targetParam,
|
|
117921
|
+
resolved.isCrossFile,
|
|
117504
117922
|
orchestrator
|
|
117505
|
-
)
|
|
117506
|
-
|
|
117507
|
-
|
|
117508
|
-
|
|
117923
|
+
)) {
|
|
117924
|
+
const argCode = CodeGenState.withExpectedType(
|
|
117925
|
+
targetParam?.baseType,
|
|
117926
|
+
() => orchestrator.generateExpression(e),
|
|
117927
|
+
true
|
|
117928
|
+
// suppressEnumResolution
|
|
117929
|
+
);
|
|
117930
|
+
return wrapWithCppEnumCast(
|
|
117931
|
+
argCode,
|
|
117932
|
+
e,
|
|
117933
|
+
targetParam?.baseType,
|
|
117934
|
+
orchestrator
|
|
117935
|
+
);
|
|
117936
|
+
}
|
|
117937
|
+
return orchestrator.generateFunctionArg(e, targetParam?.baseType);
|
|
117938
|
+
}).join(", ")
|
|
117939
|
+
);
|
|
117509
117940
|
return { code: `${funcExpr}(${args})`, effects };
|
|
117510
117941
|
};
|
|
117511
117942
|
var generateSafeDivMod = (funcName, argExprs, input, orchestrator, effects) => {
|
|
@@ -119948,7 +120379,9 @@ function generateInitializer(varDecl, isArray, orchestrator) {
|
|
|
119948
120379
|
const typeName = orchestrator.generateType(varDecl.type());
|
|
119949
120380
|
return CodeGenState.withExpectedType(
|
|
119950
120381
|
typeName,
|
|
119951
|
-
() =>
|
|
120382
|
+
() => CodeGenState.withDeclarationInit(
|
|
120383
|
+
() => ` = ${orchestrator.generateExpression(varDecl.expression())}`
|
|
120384
|
+
)
|
|
119952
120385
|
);
|
|
119953
120386
|
}
|
|
119954
120387
|
return ` = ${orchestrator.getZeroInitializer(varDecl.type(), isArray)}`;
|
|
@@ -120026,9 +120459,19 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
120026
120459
|
type = `${type}*`;
|
|
120027
120460
|
orchestrator.markOpaqueScopeVariable(fullName);
|
|
120028
120461
|
}
|
|
120462
|
+
const modifiers = VariableModifierBuilder_default.build(
|
|
120463
|
+
varDecl,
|
|
120464
|
+
false,
|
|
120465
|
+
// inFunctionBody - scope vars are file scope
|
|
120466
|
+
false,
|
|
120467
|
+
// hasInitializer - doesn't affect volatile/atomic handling
|
|
120468
|
+
false
|
|
120469
|
+
// cppMode - doesn't affect volatile/atomic handling
|
|
120470
|
+
);
|
|
120471
|
+
const staticPrefix = isPrivate ? "static " : "";
|
|
120472
|
+
const volatilePrefix = modifiers.atomic || modifiers.volatile;
|
|
120029
120473
|
const constPrefix = isConst ? "const " : "";
|
|
120030
|
-
|
|
120031
|
-
let decl = `${prefix}${constPrefix}${type} ${fullName}`;
|
|
120474
|
+
let decl = `${staticPrefix}${volatilePrefix}${constPrefix}${type} ${fullName}`;
|
|
120032
120475
|
decl += ArrayDimensionUtils_default.generateArrayTypeDimension(
|
|
120033
120476
|
arrayTypeCtx,
|
|
120034
120477
|
orchestrator
|
|
@@ -120037,7 +120480,7 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
120037
120480
|
decl += orchestrator.generateArrayDimensions(arrayDims);
|
|
120038
120481
|
}
|
|
120039
120482
|
decl += ArrayDimensionUtils_default.generateStringCapacityDim(varDecl.type());
|
|
120040
|
-
if (isOpaque || isExternalStruct) {
|
|
120483
|
+
if ((isOpaque || isExternalStruct) && !isArray) {
|
|
120041
120484
|
decl += " = NULL";
|
|
120042
120485
|
} else {
|
|
120043
120486
|
decl += generateInitializer(varDecl, isArray, orchestrator);
|
|
@@ -125872,19 +126315,6 @@ var SymbolLookupHelper = class _SymbolLookupHelper {
|
|
|
125872
126315
|
const symbols = symbolTable.getOverloads(name);
|
|
125873
126316
|
return symbols.some((sym) => sym.kind === "namespace");
|
|
125874
126317
|
}
|
|
125875
|
-
/**
|
|
125876
|
-
* Check if a type name is from a C++ header.
|
|
125877
|
-
* Issue #304: Used to determine whether to use {} or {0} for initialization.
|
|
125878
|
-
* C++ types with constructors may fail with {0} but work with {}.
|
|
125879
|
-
*/
|
|
125880
|
-
static isCppType(symbolTable, typeName) {
|
|
125881
|
-
if (!symbolTable) return false;
|
|
125882
|
-
const symbols = symbolTable.getOverloads(typeName);
|
|
125883
|
-
const cppTypeKinds = /* @__PURE__ */ new Set(["struct", "class", "type"]);
|
|
125884
|
-
return symbols.some(
|
|
125885
|
-
(sym) => sym.sourceLanguage === ESourceLanguage_default.Cpp && cppTypeKinds.has(sym.kind)
|
|
125886
|
-
);
|
|
125887
|
-
}
|
|
125888
126318
|
/**
|
|
125889
126319
|
* Check if a function is a C-Next function (uses pass-by-reference semantics).
|
|
125890
126320
|
* Returns true if the function is found in symbol table as C-Next.
|
|
@@ -126224,6 +126654,18 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126224
126654
|
* Returns { handled: false } if not a string type.
|
|
126225
126655
|
*/
|
|
126226
126656
|
static generateStringDecl(typeCtx, name, expression, arrayDims, modifiers, isConst, callbacks) {
|
|
126657
|
+
const arrayTypeCtx = typeCtx.arrayType?.();
|
|
126658
|
+
if (arrayTypeCtx?.stringType?.()) {
|
|
126659
|
+
return _StringDeclHelper._generateStringArrayFromArrayType(
|
|
126660
|
+
name,
|
|
126661
|
+
arrayTypeCtx,
|
|
126662
|
+
expression,
|
|
126663
|
+
arrayDims,
|
|
126664
|
+
modifiers,
|
|
126665
|
+
isConst,
|
|
126666
|
+
callbacks
|
|
126667
|
+
);
|
|
126668
|
+
}
|
|
126227
126669
|
const stringCtx = typeCtx.stringType();
|
|
126228
126670
|
if (!stringCtx) {
|
|
126229
126671
|
return { code: "", handled: false };
|
|
@@ -126250,6 +126692,122 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126250
126692
|
);
|
|
126251
126693
|
}
|
|
126252
126694
|
}
|
|
126695
|
+
/**
|
|
126696
|
+
* Issue #1029: Generate string array declaration from arrayType syntax.
|
|
126697
|
+
* Handles: string<32>[4] items -> char items[4][33] = {0};
|
|
126698
|
+
*/
|
|
126699
|
+
static _generateStringArrayFromArrayType(name, arrayTypeCtx, expression, trailingArrayDims, modifiers, isConst, callbacks) {
|
|
126700
|
+
const stringCtx = arrayTypeCtx.stringType();
|
|
126701
|
+
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
126702
|
+
if (!intLiteral) {
|
|
126703
|
+
throw new Error(
|
|
126704
|
+
"Error: String arrays require explicit capacity, e.g., string<64>[4]"
|
|
126705
|
+
);
|
|
126706
|
+
}
|
|
126707
|
+
const capacity = Number.parseInt(intLiteral.getText(), 10);
|
|
126708
|
+
callbacks.requireStringInclude();
|
|
126709
|
+
const {
|
|
126710
|
+
extern,
|
|
126711
|
+
const: constMod,
|
|
126712
|
+
atomic,
|
|
126713
|
+
volatile: volatileMod
|
|
126714
|
+
} = modifiers;
|
|
126715
|
+
let arrayDimStr = "";
|
|
126716
|
+
for (const dim of arrayTypeCtx.arrayTypeDimension()) {
|
|
126717
|
+
const sizeExpr = dim.expression();
|
|
126718
|
+
if (sizeExpr) {
|
|
126719
|
+
arrayDimStr += `[${sizeExpr.getText()}]`;
|
|
126720
|
+
} else {
|
|
126721
|
+
arrayDimStr += "[]";
|
|
126722
|
+
}
|
|
126723
|
+
}
|
|
126724
|
+
arrayDimStr += callbacks.generateArrayDimensions(trailingArrayDims);
|
|
126725
|
+
arrayDimStr += `[${capacity + 1}]`;
|
|
126726
|
+
let decl = `${extern}${constMod}${atomic}${volatileMod}char ${name}${arrayDimStr}`;
|
|
126727
|
+
CodeGenState.localArrays.add(name);
|
|
126728
|
+
if (!expression) {
|
|
126729
|
+
return { code: `${decl} = {0};`, handled: true };
|
|
126730
|
+
}
|
|
126731
|
+
CodeGenState.lastArrayInitCount = 0;
|
|
126732
|
+
CodeGenState.lastArrayFillValue = void 0;
|
|
126733
|
+
const initValue = callbacks.generateExpression(expression);
|
|
126734
|
+
const isArrayInit = CodeGenState.lastArrayInitCount > 0 || CodeGenState.lastArrayFillValue !== void 0;
|
|
126735
|
+
if (!isArrayInit) {
|
|
126736
|
+
throw new Error(
|
|
126737
|
+
`Error: String array initialization from variables not supported`
|
|
126738
|
+
);
|
|
126739
|
+
}
|
|
126740
|
+
const declaredSize = _StringDeclHelper._getArrayTypeDeclaredSize(arrayTypeCtx);
|
|
126741
|
+
if (declaredSize !== null) {
|
|
126742
|
+
const isFillAll = CodeGenState.lastArrayFillValue !== void 0;
|
|
126743
|
+
const elementCount = CodeGenState.lastArrayInitCount;
|
|
126744
|
+
if (!isFillAll && elementCount !== declaredSize) {
|
|
126745
|
+
throw new Error(
|
|
126746
|
+
`Error: Array size mismatch - declared [${declaredSize}] but got ${elementCount} elements`
|
|
126747
|
+
);
|
|
126748
|
+
}
|
|
126749
|
+
}
|
|
126750
|
+
const finalInitValue = _StringDeclHelper._expandFillAllForArrayType(
|
|
126751
|
+
initValue,
|
|
126752
|
+
arrayTypeCtx
|
|
126753
|
+
);
|
|
126754
|
+
const suppression = "// cppcheck-suppress misra-c2012-9.3\n// cppcheck-suppress misra-c2012-9.4\n";
|
|
126755
|
+
return {
|
|
126756
|
+
code: `${suppression}${decl} = ${finalInitValue};`,
|
|
126757
|
+
handled: true
|
|
126758
|
+
};
|
|
126759
|
+
}
|
|
126760
|
+
/**
|
|
126761
|
+
* Get the numeric size from the first arrayTypeDimension, or null if not numeric.
|
|
126762
|
+
* Used by arrayType-based string arrays (string<N>[M]).
|
|
126763
|
+
*/
|
|
126764
|
+
static _getArrayTypeDeclaredSize(arrayTypeCtx) {
|
|
126765
|
+
const dims = arrayTypeCtx.arrayTypeDimension();
|
|
126766
|
+
if (dims.length === 0) {
|
|
126767
|
+
return null;
|
|
126768
|
+
}
|
|
126769
|
+
const firstDimExpr = dims[0].expression();
|
|
126770
|
+
return _StringDeclHelper._parseNumericSize(firstDimExpr);
|
|
126771
|
+
}
|
|
126772
|
+
/**
|
|
126773
|
+
* Expand fill-all syntax for arrayType-based string arrays.
|
|
126774
|
+
* Delegates to the common fill-all expansion logic with size from arrayType.
|
|
126775
|
+
*/
|
|
126776
|
+
static _expandFillAllForArrayType(initValue, arrayTypeCtx) {
|
|
126777
|
+
const declaredSize = _StringDeclHelper._getArrayTypeDeclaredSize(arrayTypeCtx);
|
|
126778
|
+
return _StringDeclHelper._expandFillAll(initValue, declaredSize);
|
|
126779
|
+
}
|
|
126780
|
+
/**
|
|
126781
|
+
* Common fill-all expansion logic shared between arrayType and arrayDimension paths.
|
|
126782
|
+
*/
|
|
126783
|
+
static _expandFillAll(initValue, declaredSize) {
|
|
126784
|
+
const fillVal = CodeGenState.lastArrayFillValue;
|
|
126785
|
+
if (fillVal === void 0) {
|
|
126786
|
+
return initValue;
|
|
126787
|
+
}
|
|
126788
|
+
if (fillVal === '""') {
|
|
126789
|
+
return initValue;
|
|
126790
|
+
}
|
|
126791
|
+
if (declaredSize === null) {
|
|
126792
|
+
return initValue;
|
|
126793
|
+
}
|
|
126794
|
+
const elements = new Array(declaredSize).fill(fillVal);
|
|
126795
|
+
return `{${elements.join(", ")}}`;
|
|
126796
|
+
}
|
|
126797
|
+
/**
|
|
126798
|
+
* Parse a numeric size from an expression, or return null if not numeric.
|
|
126799
|
+
* Shared helper to eliminate duplicate parsing logic.
|
|
126800
|
+
*/
|
|
126801
|
+
static _parseNumericSize(expr) {
|
|
126802
|
+
if (!expr) {
|
|
126803
|
+
return null;
|
|
126804
|
+
}
|
|
126805
|
+
const sizeText = expr.getText();
|
|
126806
|
+
if (!/^\d+$/.exec(sizeText)) {
|
|
126807
|
+
return null;
|
|
126808
|
+
}
|
|
126809
|
+
return Number.parseInt(sizeText, 10);
|
|
126810
|
+
}
|
|
126253
126811
|
/**
|
|
126254
126812
|
* Generate bounded string declaration (string<N>).
|
|
126255
126813
|
*/
|
|
@@ -126303,16 +126861,33 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126303
126861
|
constMod
|
|
126304
126862
|
);
|
|
126305
126863
|
}
|
|
126306
|
-
|
|
126307
|
-
|
|
126864
|
+
const exprText = expression.getText();
|
|
126865
|
+
const isLiteral = _StringDeclHelper._validateStringInit(
|
|
126866
|
+
exprText,
|
|
126308
126867
|
capacity,
|
|
126309
126868
|
callbacks
|
|
126310
126869
|
);
|
|
126311
|
-
|
|
126312
|
-
|
|
126870
|
+
if (isLiteral) {
|
|
126871
|
+
const code = `${extern}${constMod}char ${name}[${capacity + 1}] = ${callbacks.generateExpression(expression)};`;
|
|
126872
|
+
return { code, handled: true };
|
|
126873
|
+
}
|
|
126874
|
+
if (!CodeGenState.inFunctionBody) {
|
|
126875
|
+
throw new Error(
|
|
126876
|
+
`Error: String initialization from variable cannot be used at global scope. Move the declaration inside a function, or use an empty initializer and assign later.`
|
|
126877
|
+
);
|
|
126878
|
+
}
|
|
126879
|
+
const srcExpr = callbacks.generateExpression(expression);
|
|
126880
|
+
const indent = FormatUtils_default.indent(CodeGenState.indentLevel);
|
|
126881
|
+
const lines = [];
|
|
126882
|
+
lines.push(
|
|
126883
|
+
`${constMod}char ${name}[${capacity + 1}] = "";`,
|
|
126884
|
+
`${indent}strcpy(${name}, ${srcExpr});`
|
|
126885
|
+
);
|
|
126886
|
+
return { code: lines.join("\n"), handled: true };
|
|
126313
126887
|
}
|
|
126314
126888
|
/**
|
|
126315
126889
|
* Validate string initialization (literal length and variable capacity)
|
|
126890
|
+
* Returns true if the expression is a string literal, false if it's a variable.
|
|
126316
126891
|
*/
|
|
126317
126892
|
static _validateStringInit(exprText, capacity, callbacks) {
|
|
126318
126893
|
if (exprText.startsWith('"') && exprText.endsWith('"')) {
|
|
@@ -126322,6 +126897,7 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126322
126897
|
`Error: String literal (${content} chars) exceeds string<${capacity}> capacity`
|
|
126323
126898
|
);
|
|
126324
126899
|
}
|
|
126900
|
+
return true;
|
|
126325
126901
|
}
|
|
126326
126902
|
const srcCapacity = callbacks.getStringExprCapacity(exprText);
|
|
126327
126903
|
if (srcCapacity !== null && srcCapacity > capacity) {
|
|
@@ -126329,6 +126905,7 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126329
126905
|
`Error: Cannot assign string<${srcCapacity}> to string<${capacity}> (potential truncation)`
|
|
126330
126906
|
);
|
|
126331
126907
|
}
|
|
126908
|
+
return false;
|
|
126332
126909
|
}
|
|
126333
126910
|
/**
|
|
126334
126911
|
* Generate string array declaration.
|
|
@@ -126416,35 +126993,19 @@ var StringDeclHelper = class _StringDeclHelper {
|
|
|
126416
126993
|
/**
|
|
126417
126994
|
* Expand fill-all syntax if needed.
|
|
126418
126995
|
* ["Hello"*] with size 3 -> {"Hello", "Hello", "Hello"}
|
|
126996
|
+
* Delegates to the common fill-all expansion logic with size from arrayDimension.
|
|
126419
126997
|
*/
|
|
126420
126998
|
static _expandFillAllIfNeeded(initValue, arrayDims) {
|
|
126421
|
-
const fillVal = CodeGenState.lastArrayFillValue;
|
|
126422
|
-
if (fillVal === void 0) {
|
|
126423
|
-
return initValue;
|
|
126424
|
-
}
|
|
126425
|
-
if (fillVal === '""') {
|
|
126426
|
-
return initValue;
|
|
126427
|
-
}
|
|
126428
126999
|
const declaredSize = _StringDeclHelper._getFirstDimNumericSize(arrayDims);
|
|
126429
|
-
|
|
126430
|
-
return initValue;
|
|
126431
|
-
}
|
|
126432
|
-
const elements = new Array(declaredSize).fill(fillVal);
|
|
126433
|
-
return `{${elements.join(", ")}}`;
|
|
127000
|
+
return _StringDeclHelper._expandFillAll(initValue, declaredSize);
|
|
126434
127001
|
}
|
|
126435
127002
|
/**
|
|
126436
127003
|
* Get the numeric size from the first array dimension, or null if not numeric.
|
|
127004
|
+
* Used by arrayDimension-based string arrays (string<N> arr[M]).
|
|
126437
127005
|
*/
|
|
126438
127006
|
static _getFirstDimNumericSize(arrayDims) {
|
|
126439
127007
|
const firstDimExpr = arrayDims[0]?.expression();
|
|
126440
|
-
|
|
126441
|
-
return null;
|
|
126442
|
-
}
|
|
126443
|
-
const sizeText = firstDimExpr.getText();
|
|
126444
|
-
if (!/^\d+$/.exec(sizeText)) {
|
|
126445
|
-
return null;
|
|
126446
|
-
}
|
|
126447
|
-
return Number.parseInt(sizeText, 10);
|
|
127008
|
+
return _StringDeclHelper._parseNumericSize(firstDimExpr);
|
|
126448
127009
|
}
|
|
126449
127010
|
/**
|
|
126450
127011
|
* Generate string concatenation declaration.
|
|
@@ -126638,24 +127199,14 @@ var VariableDeclHelper = class _VariableDeclHelper {
|
|
|
126638
127199
|
if (arrayDims.length === 0) {
|
|
126639
127200
|
return;
|
|
126640
127201
|
}
|
|
126641
|
-
if (typeCtx.arrayType()) {
|
|
126642
|
-
return;
|
|
126643
|
-
}
|
|
126644
|
-
if (arrayDims.length === 1 && !arrayDims[0].expression()) {
|
|
126645
|
-
return;
|
|
126646
|
-
}
|
|
126647
|
-
if (arrayDims.length > 1) {
|
|
126648
|
-
return;
|
|
126649
|
-
}
|
|
126650
|
-
if (typeCtx.qualifiedType() || typeCtx.scopedType() || typeCtx.globalType() || typeCtx.stringType()) {
|
|
126651
|
-
return;
|
|
126652
|
-
}
|
|
126653
127202
|
const baseType = _VariableDeclHelper.extractBaseTypeName(typeCtx);
|
|
126654
|
-
const
|
|
127203
|
+
const existingDims = typeCtx.arrayType() ? typeCtx.arrayType().arrayTypeDimension().map((d) => `[${d.expression()?.getText() ?? ""}]`).join("") : "";
|
|
127204
|
+
const trailingDims = arrayDims.map((dim) => `[${dim.expression()?.getText() ?? ""}]`).join("");
|
|
127205
|
+
const allDims = existingDims + trailingDims;
|
|
126655
127206
|
const line = ctx.start?.line ?? 0;
|
|
126656
127207
|
const col = ctx.start?.column ?? 0;
|
|
126657
127208
|
throw new Error(
|
|
126658
|
-
`${line}:${col} C-style array declaration is not allowed. Use '${baseType}${
|
|
127209
|
+
`${line}:${col} C-style array declaration is not allowed. Use '${baseType}${allDims} ${name}' instead of '${baseType}${existingDims} ${name}${trailingDims}'`
|
|
126659
127210
|
);
|
|
126660
127211
|
}
|
|
126661
127212
|
/**
|
|
@@ -126762,7 +127313,8 @@ ${assignments}`;
|
|
|
126762
127313
|
typeCtx,
|
|
126763
127314
|
callbacks
|
|
126764
127315
|
);
|
|
126765
|
-
const hasEmptyArrayDim = arrayDims.some((dim) => !dim.expression());
|
|
127316
|
+
const hasEmptyArrayDim = arrayDims.some((dim) => !dim.expression()) || (typeCtx.arrayType()?.arrayTypeDimension().some((dim) => !dim.expression()) ?? false);
|
|
127317
|
+
const hasEmptyArrayTypeDim = typeCtx.arrayType()?.arrayTypeDimension().some((dim) => !dim.expression()) ?? false;
|
|
126766
127318
|
const declaredSize = _VariableDeclHelper.parseArrayTypeDimension(typeCtx) ?? _VariableDeclHelper.parseFirstArrayDimension(arrayDims);
|
|
126767
127319
|
if (ctx.expression()) {
|
|
126768
127320
|
const arrayInitResult = ArrayInitHelper_default.processArrayInit(
|
|
@@ -126780,7 +127332,7 @@ ${assignments}`;
|
|
|
126780
127332
|
);
|
|
126781
127333
|
if (arrayInitResult) {
|
|
126782
127334
|
CodeGenState.localArrays.add(name);
|
|
126783
|
-
const fullDimSuffix = arrayTypeDimStr + arrayInitResult.dimensionSuffix;
|
|
127335
|
+
const fullDimSuffix = hasEmptyArrayTypeDim ? arrayInitResult.dimensionSuffix : arrayTypeDimStr + arrayInitResult.dimensionSuffix;
|
|
126784
127336
|
return {
|
|
126785
127337
|
handled: true,
|
|
126786
127338
|
code: `${decl}${fullDimSuffix} = ${arrayInitResult.initValue};`,
|
|
@@ -126815,7 +127367,9 @@ ${assignments}`;
|
|
|
126815
127367
|
getExpressionType: callbacks.getExpressionType
|
|
126816
127368
|
});
|
|
126817
127369
|
return CodeGenState.withExpectedType(typeName, () => {
|
|
126818
|
-
let exprCode =
|
|
127370
|
+
let exprCode = CodeGenState.withDeclarationInit(
|
|
127371
|
+
() => callbacks.generateExpression(ctx.expression())
|
|
127372
|
+
);
|
|
126819
127373
|
const exprType = callbacks.getExpressionType(ctx.expression());
|
|
126820
127374
|
if (exprType && NarrowingCastHelper_default.isCrossTypeCategoryConversion(exprType, typeName)) {
|
|
126821
127375
|
if (NarrowingCastHelper_default.isIntegerType(exprType) && NarrowingCastHelper_default.isFloatType(typeName)) {
|
|
@@ -127603,31 +128157,29 @@ var TypeGenerationHelper = class _TypeGenerationHelper {
|
|
|
127603
128157
|
return "char";
|
|
127604
128158
|
}
|
|
127605
128159
|
/**
|
|
127606
|
-
*
|
|
127607
|
-
*
|
|
128160
|
+
* Dispatch type generation for contexts that share common type accessors.
|
|
128161
|
+
* Handles scoped, qualified, global, primitive, string, and user types.
|
|
128162
|
+
* Used by both bare type contexts and array element type contexts.
|
|
128163
|
+
*
|
|
128164
|
+
* @returns The resolved C type string, or null if no matching type accessor found
|
|
127608
128165
|
*/
|
|
127609
|
-
static
|
|
127610
|
-
if (
|
|
127611
|
-
const type = ctx.primitiveType().getText();
|
|
127612
|
-
const result = _TypeGenerationHelper.generatePrimitiveType(type);
|
|
127613
|
-
return result.cType;
|
|
127614
|
-
}
|
|
127615
|
-
if (ctx.stringType()) {
|
|
128166
|
+
static dispatchTypeGeneration(accessors, deps) {
|
|
128167
|
+
if (accessors.stringType()) {
|
|
127616
128168
|
return _TypeGenerationHelper.generateStringType();
|
|
127617
128169
|
}
|
|
127618
|
-
if (
|
|
127619
|
-
const typeName =
|
|
128170
|
+
if (accessors.scopedType()) {
|
|
128171
|
+
const typeName = accessors.scopedType().IDENTIFIER().getText();
|
|
127620
128172
|
return _TypeGenerationHelper.generateScopedType(
|
|
127621
128173
|
typeName,
|
|
127622
128174
|
deps.currentScope
|
|
127623
128175
|
);
|
|
127624
128176
|
}
|
|
127625
|
-
if (
|
|
127626
|
-
const typeName =
|
|
128177
|
+
if (accessors.globalType()) {
|
|
128178
|
+
const typeName = accessors.globalType().IDENTIFIER().getText();
|
|
127627
128179
|
return _TypeGenerationHelper.generateGlobalType(typeName);
|
|
127628
128180
|
}
|
|
127629
|
-
if (
|
|
127630
|
-
const identifiers =
|
|
128181
|
+
if (accessors.qualifiedType()) {
|
|
128182
|
+
const identifiers = accessors.qualifiedType().IDENTIFIER();
|
|
127631
128183
|
const identifierNames = identifiers.map((id) => id.getText());
|
|
127632
128184
|
const isCpp = deps.isCppScopeSymbol(identifierNames[0]);
|
|
127633
128185
|
return _TypeGenerationHelper.generateQualifiedType(
|
|
@@ -127636,24 +128188,36 @@ var TypeGenerationHelper = class _TypeGenerationHelper {
|
|
|
127636
128188
|
deps.validateCrossScopeVisibility
|
|
127637
128189
|
);
|
|
127638
128190
|
}
|
|
127639
|
-
if (
|
|
127640
|
-
const
|
|
128191
|
+
if (accessors.primitiveType()) {
|
|
128192
|
+
const type = accessors.primitiveType().getText();
|
|
128193
|
+
return TYPE_MAP_default[type] || type;
|
|
128194
|
+
}
|
|
128195
|
+
if (accessors.userType()) {
|
|
128196
|
+
const typeName = accessors.userType().getText();
|
|
128197
|
+
if (typeName === "cstring") {
|
|
128198
|
+
return "char*";
|
|
128199
|
+
}
|
|
127641
128200
|
const needsStruct = deps.checkNeedsStructKeyword(typeName);
|
|
127642
128201
|
return _TypeGenerationHelper.generateUserType(typeName, needsStruct);
|
|
127643
128202
|
}
|
|
128203
|
+
return null;
|
|
128204
|
+
}
|
|
128205
|
+
/**
|
|
128206
|
+
* Full type generation using all dependencies.
|
|
128207
|
+
* This is the main entry point that handles all type contexts.
|
|
128208
|
+
*/
|
|
128209
|
+
static generate(ctx, deps) {
|
|
127644
128210
|
if (ctx.arrayType()) {
|
|
127645
128211
|
const arrCtx = ctx.arrayType();
|
|
127646
|
-
|
|
127647
|
-
|
|
127648
|
-
|
|
127649
|
-
|
|
127650
|
-
|
|
127651
|
-
|
|
127652
|
-
|
|
127653
|
-
|
|
127654
|
-
|
|
127655
|
-
needsStruct
|
|
127656
|
-
);
|
|
128212
|
+
const result2 = _TypeGenerationHelper.dispatchTypeGeneration(arrCtx, deps);
|
|
128213
|
+
if (result2 !== null) {
|
|
128214
|
+
return result2;
|
|
128215
|
+
}
|
|
128216
|
+
return ctx.getText();
|
|
128217
|
+
}
|
|
128218
|
+
const result = _TypeGenerationHelper.dispatchTypeGeneration(ctx, deps);
|
|
128219
|
+
if (result !== null) {
|
|
128220
|
+
return result;
|
|
127657
128221
|
}
|
|
127658
128222
|
if (ctx.getText() === "void") {
|
|
127659
128223
|
return "void";
|
|
@@ -129014,6 +129578,7 @@ var ParameterInputAdapter = class {
|
|
|
129014
129578
|
const isKnownStruct = deps.isKnownStruct(typeName);
|
|
129015
129579
|
const isKnownPrimitive = !!deps.typeMap[typeName];
|
|
129016
129580
|
const isTypedefStruct = deps.isTypedefStructType(typeName);
|
|
129581
|
+
const isOpaque = deps.isOpaqueType?.(typeName) ?? false;
|
|
129017
129582
|
const isAutoConst = !deps.isCallbackCompatible && !deps.isModified && !isConst;
|
|
129018
129583
|
const isPassByReference = deps.forcePassByReference || isKnownStruct || isKnownPrimitive || isTypedefStruct;
|
|
129019
129584
|
return {
|
|
@@ -129031,7 +129596,9 @@ var ParameterInputAdapter = class {
|
|
|
129031
129596
|
// and typedef struct params (C types expect pointers, not C++ references)
|
|
129032
129597
|
forcePointerSyntax: deps.forcePassByReference || isTypedefStruct || void 0,
|
|
129033
129598
|
// Issue #895: Preserve const from callback typedef signature
|
|
129034
|
-
forceConst: deps.forceConst
|
|
129599
|
+
forceConst: deps.forceConst,
|
|
129600
|
+
// Issue #995: Pass through opaque handle detection — rule applied in builder
|
|
129601
|
+
isOpaqueHandle: isOpaque || void 0
|
|
129035
129602
|
};
|
|
129036
129603
|
}
|
|
129037
129604
|
/**
|
|
@@ -129078,7 +129645,9 @@ var ParameterInputAdapter = class {
|
|
|
129078
129645
|
isPassByValue: isCallbackPointer ? false : deps.isPassByValue,
|
|
129079
129646
|
isPassByReference: isCallbackPointer ? true : !deps.isPassByValue,
|
|
129080
129647
|
forcePointerSyntax: isCallbackPointer || void 0,
|
|
129081
|
-
forceConst: param.isCallbackConst || void 0
|
|
129648
|
+
forceConst: param.isCallbackConst || void 0,
|
|
129649
|
+
// Issue #995: Pass through opaque handle detection — rule applied in builder
|
|
129650
|
+
isOpaqueHandle: param.isOpaqueHandle || void 0
|
|
129082
129651
|
};
|
|
129083
129652
|
}
|
|
129084
129653
|
/**
|
|
@@ -129120,13 +129689,12 @@ var ParameterInputAdapter = class {
|
|
|
129120
129689
|
dims.push(String(capacity + 1));
|
|
129121
129690
|
}
|
|
129122
129691
|
}
|
|
129123
|
-
const isAutoConst = !deps.isModified && !isConst;
|
|
129124
129692
|
return {
|
|
129125
129693
|
name,
|
|
129126
129694
|
baseType: typeName,
|
|
129127
129695
|
mappedType,
|
|
129128
129696
|
isConst,
|
|
129129
|
-
isAutoConst,
|
|
129697
|
+
isAutoConst: false,
|
|
129130
129698
|
isArray: true,
|
|
129131
129699
|
arrayDimensions: dims,
|
|
129132
129700
|
isCallback: false,
|
|
@@ -129204,6 +129772,9 @@ var ParameterSignatureBuilder = class {
|
|
|
129204
129772
|
if (param.isString && !param.isArray) {
|
|
129205
129773
|
return this._buildStringParam(param);
|
|
129206
129774
|
}
|
|
129775
|
+
if (param.isOpaqueHandle) {
|
|
129776
|
+
return this._buildRefParam(param, refSuffix);
|
|
129777
|
+
}
|
|
129207
129778
|
if (param.isPassByReference) {
|
|
129208
129779
|
return this._buildRefParam(param, refSuffix);
|
|
129209
129780
|
}
|
|
@@ -129248,14 +129819,16 @@ var ParameterSignatureBuilder = class {
|
|
|
129248
129819
|
/**
|
|
129249
129820
|
* Build pass-by-reference parameter signature.
|
|
129250
129821
|
* C mode: const Point* p
|
|
129251
|
-
* C++ mode: const Point& p (unless forcePointerSyntax)
|
|
129822
|
+
* C++ mode: const Point& p (unless forcePointerSyntax or isOpaqueHandle)
|
|
129252
129823
|
*
|
|
129253
129824
|
* Issue #895: When forcePointerSyntax is set, always use pointer syntax
|
|
129254
129825
|
* because C callback typedefs expect pointers, not C++ references.
|
|
129826
|
+
* Issue #995: Opaque handles must use pointer syntax because C APIs
|
|
129827
|
+
* expect pointers to incomplete struct types (e.g., widget_t*).
|
|
129255
129828
|
*/
|
|
129256
129829
|
static _buildRefParam(param, refSuffix) {
|
|
129257
129830
|
const constPrefix = this._getConstPrefix(param);
|
|
129258
|
-
const actualSuffix = param.forcePointerSyntax ? "*" : refSuffix;
|
|
129831
|
+
const actualSuffix = param.forcePointerSyntax || param.isOpaqueHandle ? "*" : refSuffix;
|
|
129259
129832
|
return `${constPrefix}${param.mappedType}${actualSuffix} ${param.name}`;
|
|
129260
129833
|
}
|
|
129261
129834
|
/**
|
|
@@ -129269,9 +129842,12 @@ var ParameterSignatureBuilder = class {
|
|
|
129269
129842
|
* Get const prefix combining explicit const, auto-const, and forced const.
|
|
129270
129843
|
* Priority: forceConst > isConst > isAutoConst
|
|
129271
129844
|
* Issue #895: forceConst preserves const from callback typedef signature.
|
|
129845
|
+
* Issue #995: Opaque handles suppress auto-const (they must be passed to
|
|
129846
|
+
* C APIs that expect non-const pointers).
|
|
129272
129847
|
*/
|
|
129273
129848
|
static _getConstPrefix(param) {
|
|
129274
|
-
|
|
129849
|
+
const effectiveAutoConst = param.isOpaqueHandle ? false : param.isAutoConst;
|
|
129850
|
+
if (param.forceConst || param.isConst || effectiveAutoConst) {
|
|
129275
129851
|
return "const ";
|
|
129276
129852
|
}
|
|
129277
129853
|
return "";
|
|
@@ -129868,6 +130444,7 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
129868
130444
|
* Part of IOrchestrator interface.
|
|
129869
130445
|
* ADR-045: Used to detect string comparisons and generate strcmp().
|
|
129870
130446
|
* Issue #137: Extended to handle array element access (e.g., names[0])
|
|
130447
|
+
* Issue #1030: Extended to handle struct member access (e.g., person.name)
|
|
129871
130448
|
*/
|
|
129872
130449
|
isStringExpression(ctx) {
|
|
129873
130450
|
const text = ctx.getText();
|
|
@@ -129880,6 +130457,9 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
129880
130457
|
return true;
|
|
129881
130458
|
}
|
|
129882
130459
|
}
|
|
130460
|
+
if (this._isStructMemberStringExpression(text)) {
|
|
130461
|
+
return true;
|
|
130462
|
+
}
|
|
129883
130463
|
return this._isArrayAccessStringExpression(text);
|
|
129884
130464
|
}
|
|
129885
130465
|
/**
|
|
@@ -129907,6 +130487,36 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
129907
130487
|
typeInfo.isArray && typeInfo.baseType && TypeCheckUtils_default.isString(typeInfo.baseType)
|
|
129908
130488
|
);
|
|
129909
130489
|
}
|
|
130490
|
+
/**
|
|
130491
|
+
* Check if struct member access expression evaluates to a string.
|
|
130492
|
+
* Issue #1030: Handles patterns like person.name, config.key
|
|
130493
|
+
*/
|
|
130494
|
+
_isStructMemberStringExpression(text) {
|
|
130495
|
+
if (text.endsWith(".char_count") || text.endsWith(".capacity") || text.endsWith(".size") || text.endsWith(".length") || text.endsWith(".bit_length") || text.endsWith(".byte_length") || text.endsWith(".element_count")) {
|
|
130496
|
+
return false;
|
|
130497
|
+
}
|
|
130498
|
+
const memberMatch = /^([a-zA-Z_]\w*)\.([a-zA-Z_]\w*)$/.exec(text);
|
|
130499
|
+
if (!memberMatch) {
|
|
130500
|
+
return false;
|
|
130501
|
+
}
|
|
130502
|
+
const [, varName, fieldName] = memberMatch;
|
|
130503
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(varName);
|
|
130504
|
+
if (!typeInfo) {
|
|
130505
|
+
return false;
|
|
130506
|
+
}
|
|
130507
|
+
const structTypeName = typeInfo.baseType;
|
|
130508
|
+
if (!structTypeName) {
|
|
130509
|
+
return false;
|
|
130510
|
+
}
|
|
130511
|
+
const fieldType = CodeGenState.getStructFieldType(
|
|
130512
|
+
structTypeName,
|
|
130513
|
+
fieldName
|
|
130514
|
+
);
|
|
130515
|
+
if (!fieldType) {
|
|
130516
|
+
return false;
|
|
130517
|
+
}
|
|
130518
|
+
return fieldType.startsWith("string");
|
|
130519
|
+
}
|
|
129910
130520
|
/**
|
|
129911
130521
|
* Get type of additive expression.
|
|
129912
130522
|
* Part of IOrchestrator interface - delegates to private implementation.
|
|
@@ -130304,21 +130914,21 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
130304
130914
|
*/
|
|
130305
130915
|
getZeroInitializer(typeCtx, isArray) {
|
|
130306
130916
|
if (isArray) {
|
|
130307
|
-
return this.
|
|
130917
|
+
return this._getAggregateZeroInitBrace();
|
|
130308
130918
|
}
|
|
130309
130919
|
const resolved = this._resolveTypeNameFromContext(typeCtx);
|
|
130310
130920
|
if (resolved) {
|
|
130311
130921
|
if (CodeGenState.symbols.knownEnums.has(resolved.name)) {
|
|
130312
130922
|
return this._getEnumZeroValue(resolved.name, resolved.separator);
|
|
130313
130923
|
}
|
|
130314
|
-
|
|
130315
|
-
return "{}";
|
|
130316
|
-
}
|
|
130317
|
-
return "{0}";
|
|
130924
|
+
return this._getAggregateZeroInitBrace();
|
|
130318
130925
|
}
|
|
130319
130926
|
if (typeCtx.templateType()) {
|
|
130320
130927
|
return "{}";
|
|
130321
130928
|
}
|
|
130929
|
+
if (typeCtx.stringType()) {
|
|
130930
|
+
return '""';
|
|
130931
|
+
}
|
|
130322
130932
|
if (typeCtx.primitiveType()) {
|
|
130323
130933
|
const primType = typeCtx.primitiveType().getText();
|
|
130324
130934
|
return _CodeGenerator.PRIMITIVE_ZERO_VALUES.get(primType) ?? "0";
|
|
@@ -130430,7 +131040,7 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
130430
131040
|
const constMod = p.isConst ? "const " : "";
|
|
130431
131041
|
if (p.isArray) {
|
|
130432
131042
|
return `${constMod}${p.type} ${p.name}${p.arrayDims}`;
|
|
130433
|
-
} else if (p.
|
|
131043
|
+
} else if (p.isStruct) {
|
|
130434
131044
|
const ptrOrRef = this.isCppMode() ? "&" : "*";
|
|
130435
131045
|
return `${constMod}${p.type}${ptrOrRef}`;
|
|
130436
131046
|
} else {
|
|
@@ -130630,7 +131240,15 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130630
131240
|
return "__GLOBAL_PREFIX__";
|
|
130631
131241
|
}
|
|
130632
131242
|
if (ctx.IDENTIFIER()) {
|
|
130633
|
-
|
|
131243
|
+
const id = ctx.IDENTIFIER().getText();
|
|
131244
|
+
if (id === "break" || id === "continue") {
|
|
131245
|
+
const line = ctx.start?.line ?? 0;
|
|
131246
|
+
const col = ctx.start?.column ?? 0;
|
|
131247
|
+
throw new Error(
|
|
131248
|
+
`${line}:${col} error[E0703]: '${id}' is not supported in C-Next - use structured conditions instead`
|
|
131249
|
+
);
|
|
131250
|
+
}
|
|
131251
|
+
return this._resolveIdentifierExpression(id);
|
|
130634
131252
|
}
|
|
130635
131253
|
if (ctx.literal()) {
|
|
130636
131254
|
return this._generateLiteralExpression(ctx.literal());
|
|
@@ -130875,14 +131493,6 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130875
131493
|
}
|
|
130876
131494
|
return identifiers.join("_");
|
|
130877
131495
|
}
|
|
130878
|
-
/**
|
|
130879
|
-
* Issue #304: Check if a type name is from a C++ header
|
|
130880
|
-
* Used to determine whether to use {} or {0} for initialization.
|
|
130881
|
-
* C++ types with constructors may fail with {0} but work with {}.
|
|
130882
|
-
*/
|
|
130883
|
-
isCppType(typeName) {
|
|
130884
|
-
return SymbolLookupHelper_default.isCppType(CodeGenState.symbolTable, typeName);
|
|
130885
|
-
}
|
|
130886
131496
|
/**
|
|
130887
131497
|
* Generate C code from a C-Next program
|
|
130888
131498
|
* @param tree The parsed C-Next program
|
|
@@ -131313,6 +131923,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131313
131923
|
const arrayTypeCtx = param.type().arrayType();
|
|
131314
131924
|
const isArray = dims.length > 0 || arrayTypeCtx !== null;
|
|
131315
131925
|
const isCallbackParam = CodeGenState.callbackTypes.has(typeName);
|
|
131926
|
+
const isStruct = this.isStructType(typeName);
|
|
131316
131927
|
let paramType;
|
|
131317
131928
|
let isPointer;
|
|
131318
131929
|
if (isCallbackParam) {
|
|
@@ -131321,7 +131932,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131321
131932
|
isPointer = false;
|
|
131322
131933
|
} else {
|
|
131323
131934
|
paramType = this.generateType(param.type());
|
|
131324
|
-
isPointer = !isArray;
|
|
131935
|
+
isPointer = !isArray && isStruct;
|
|
131325
131936
|
}
|
|
131326
131937
|
let arrayDims;
|
|
131327
131938
|
if (dims.length > 0) {
|
|
@@ -131339,6 +131950,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131339
131950
|
type: paramType,
|
|
131340
131951
|
isConst,
|
|
131341
131952
|
isPointer,
|
|
131953
|
+
isStruct,
|
|
131342
131954
|
isArray,
|
|
131343
131955
|
arrayDims
|
|
131344
131956
|
});
|
|
@@ -131684,7 +132296,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131684
132296
|
}
|
|
131685
132297
|
decl += this._getStringCapacityDimension(varDecl.type());
|
|
131686
132298
|
if (varDecl.expression()) {
|
|
131687
|
-
decl += ` = ${this.generateExpression(varDecl.expression())}`;
|
|
132299
|
+
decl += ` = ${CodeGenState.withDeclarationInit(() => this.generateExpression(varDecl.expression()))}`;
|
|
131688
132300
|
} else {
|
|
131689
132301
|
decl += ` = ${this.getZeroInitializer(varDecl.type(), isArray)}`;
|
|
131690
132302
|
}
|
|
@@ -131877,21 +132489,13 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131877
132489
|
needsStructKeyword
|
|
131878
132490
|
);
|
|
131879
132491
|
if (!fieldList) {
|
|
131880
|
-
|
|
132492
|
+
if (isCppClass) return "{}";
|
|
132493
|
+
return CodeGenState.inDeclarationInit ? "{ 0 }" : `(${castType}){ 0 }`;
|
|
131881
132494
|
}
|
|
131882
132495
|
const structFieldTypes = CodeGenState.symbolTable?.getStructFieldTypes(typeName);
|
|
131883
132496
|
const fields = fieldList.fieldInitializer().map((field) => {
|
|
131884
132497
|
const fieldName = field.IDENTIFIER().getText();
|
|
131885
|
-
|
|
131886
|
-
if (structFieldTypes?.has(fieldName)) {
|
|
131887
|
-
fieldType = structFieldTypes.get(fieldName);
|
|
131888
|
-
if (fieldType.includes("_")) {
|
|
131889
|
-
const parts = fieldType.split("_");
|
|
131890
|
-
if (parts.length > 1 && this.isCppScopeSymbol(parts[0])) {
|
|
131891
|
-
fieldType = parts.join("::");
|
|
131892
|
-
}
|
|
131893
|
-
}
|
|
131894
|
-
}
|
|
132498
|
+
const fieldType = this._resolveFieldType(fieldName, structFieldTypes);
|
|
131895
132499
|
const value = CodeGenState.withExpectedType(
|
|
131896
132500
|
fieldType,
|
|
131897
132501
|
() => this.generateExpression(field.expression())
|
|
@@ -131907,10 +132511,35 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
131907
132511
|
return "{}";
|
|
131908
132512
|
}
|
|
131909
132513
|
const fieldInits = fields.map((f) => `.${f.fieldName} = ${f.value}`);
|
|
132514
|
+
return this.formatStructInitializer(typeName, castType, fieldInits);
|
|
132515
|
+
}
|
|
132516
|
+
formatStructInitializer(typeName, castType, fieldInits) {
|
|
132517
|
+
const initializer = `{ ${fieldInits.join(", ")} }`;
|
|
132518
|
+
if (CodeGenState.inDeclarationInit) {
|
|
132519
|
+
return initializer;
|
|
132520
|
+
}
|
|
131910
132521
|
if (CodeGenState.cppMode && (typeName.startsWith("struct {") || typeName.startsWith("union {"))) {
|
|
131911
|
-
return
|
|
132522
|
+
return initializer;
|
|
131912
132523
|
}
|
|
131913
|
-
|
|
132524
|
+
if (!CodeGenState.inFunctionBody) {
|
|
132525
|
+
return initializer;
|
|
132526
|
+
}
|
|
132527
|
+
return `(${castType})${initializer}`;
|
|
132528
|
+
}
|
|
132529
|
+
/**
|
|
132530
|
+
* Resolve the C type string for a named struct field, converting C++ underscore-separated
|
|
132531
|
+
* names to :: notation. Returns undefined if the field is not in the type map.
|
|
132532
|
+
* Issue #502: C-Next stores C++ types with _ separator; codegen needs ::.
|
|
132533
|
+
*/
|
|
132534
|
+
_resolveFieldType(fieldName, structFieldTypes) {
|
|
132535
|
+
if (!structFieldTypes?.has(fieldName)) return void 0;
|
|
132536
|
+
const fieldType = structFieldTypes.get(fieldName);
|
|
132537
|
+
if (!fieldType.includes("_")) return fieldType;
|
|
132538
|
+
const parts = fieldType.split("_");
|
|
132539
|
+
if (parts.length > 1 && this.isCppScopeSymbol(parts[0])) {
|
|
132540
|
+
return parts.join("::");
|
|
132541
|
+
}
|
|
132542
|
+
return fieldType;
|
|
131914
132543
|
}
|
|
131915
132544
|
/**
|
|
131916
132545
|
* ADR-035: Generate array initializer
|
|
@@ -132053,7 +132682,9 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
132053
132682
|
isCallbackCompatible,
|
|
132054
132683
|
forcePassByReference,
|
|
132055
132684
|
forceConst,
|
|
132056
|
-
isTypedefStructType: (t) => CodeGenState.symbolTable?.isTypedefStructType(t) ?? false
|
|
132685
|
+
isTypedefStructType: (t) => CodeGenState.symbolTable?.isTypedefStructType(t) ?? false,
|
|
132686
|
+
// Issue #995: Opaque handles should not get auto-const
|
|
132687
|
+
isOpaqueType: (t) => CodeGenState.isOpaqueType(t)
|
|
132057
132688
|
});
|
|
132058
132689
|
return ParameterSignatureBuilder_default.build(input, CppModeHelper_default.refOrPtr());
|
|
132059
132690
|
}
|
|
@@ -132284,26 +132915,13 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
132284
132915
|
// _generateVariableInitializer, _validateIntegerInitializer, _finalizeCppClassAssignments,
|
|
132285
132916
|
// and _generateConstructorDecl have been extracted to VariableDeclHelper.ts
|
|
132286
132917
|
/**
|
|
132287
|
-
*
|
|
132288
|
-
* Issue #379: C++
|
|
132918
|
+
* Brace initializer that zero-initializes an aggregate (struct or array).
|
|
132919
|
+
* Issue #379 / #1004: C++ uses value-initialization ({}), which is valid for
|
|
132920
|
+
* any aggregate element type (POD, struct, class) including enum-first
|
|
132921
|
+
* structs where {0} is an invalid int->enum narrowing; C uses {0}.
|
|
132289
132922
|
*/
|
|
132290
|
-
|
|
132291
|
-
|
|
132292
|
-
const typeName = typeCtx.userType().getText();
|
|
132293
|
-
if (this._needsEmptyBraceInit(typeName)) {
|
|
132294
|
-
return "{}";
|
|
132295
|
-
}
|
|
132296
|
-
}
|
|
132297
|
-
if (typeCtx.arrayType()?.userType()) {
|
|
132298
|
-
const typeName = typeCtx.arrayType().userType().getText();
|
|
132299
|
-
if (this._needsEmptyBraceInit(typeName)) {
|
|
132300
|
-
return "{}";
|
|
132301
|
-
}
|
|
132302
|
-
}
|
|
132303
|
-
if (typeCtx.templateType()) {
|
|
132304
|
-
return "{}";
|
|
132305
|
-
}
|
|
132306
|
-
return "{0}";
|
|
132923
|
+
_getAggregateZeroInitBrace() {
|
|
132924
|
+
return CodeGenState.cppMode ? "{}" : "{0}";
|
|
132307
132925
|
}
|
|
132308
132926
|
/**
|
|
132309
132927
|
* Get zero initializer for an enum type.
|
|
@@ -132328,49 +132946,35 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
132328
132946
|
}
|
|
132329
132947
|
/**
|
|
132330
132948
|
* Resolve full type name from any TypeContext variant.
|
|
132331
|
-
* Returns { name, separator
|
|
132949
|
+
* Returns { name, separator } or null if not a named type.
|
|
132332
132950
|
* ADR-016: Handles scoped, global, qualified, and user types
|
|
132333
|
-
* checkCppType: only true for userType (original behavior preserved)
|
|
132334
132951
|
*/
|
|
132335
132952
|
_resolveTypeNameFromContext(typeCtx) {
|
|
132336
132953
|
if (typeCtx.scopedType()) {
|
|
132337
132954
|
const localName = typeCtx.scopedType().IDENTIFIER().getText();
|
|
132338
132955
|
const name = CodeGenState.currentScope ? `${CodeGenState.currentScope}_${localName}` : localName;
|
|
132339
|
-
return { name, separator: "_"
|
|
132956
|
+
return { name, separator: "_" };
|
|
132340
132957
|
}
|
|
132341
132958
|
if (typeCtx.globalType()) {
|
|
132342
132959
|
return {
|
|
132343
132960
|
name: typeCtx.globalType().IDENTIFIER().getText(),
|
|
132344
|
-
separator: "_"
|
|
132345
|
-
checkCppType: false
|
|
132961
|
+
separator: "_"
|
|
132346
132962
|
};
|
|
132347
132963
|
}
|
|
132348
132964
|
if (typeCtx.qualifiedType()) {
|
|
132349
132965
|
const parts = typeCtx.qualifiedType().IDENTIFIER();
|
|
132350
132966
|
const name = this.resolveQualifiedType(parts.map((id) => id.getText()));
|
|
132351
132967
|
const separator = name.includes("::") ? "::" : "_";
|
|
132352
|
-
return { name, separator
|
|
132968
|
+
return { name, separator };
|
|
132353
132969
|
}
|
|
132354
132970
|
if (typeCtx.userType()) {
|
|
132355
132971
|
return {
|
|
132356
132972
|
name: typeCtx.userType().getText(),
|
|
132357
|
-
separator: "_"
|
|
132358
|
-
checkCppType: true
|
|
132973
|
+
separator: "_"
|
|
132359
132974
|
};
|
|
132360
132975
|
}
|
|
132361
132976
|
return null;
|
|
132362
132977
|
}
|
|
132363
|
-
/**
|
|
132364
|
-
* Check if a type needs empty brace initialization {}.
|
|
132365
|
-
* Issue #304: C++ types with constructors may fail with {0}
|
|
132366
|
-
* Issue #309: Unknown user types in C++ mode may have non-trivial constructors
|
|
132367
|
-
*/
|
|
132368
|
-
_needsEmptyBraceInit(typeName) {
|
|
132369
|
-
if (this.isCppType(typeName)) {
|
|
132370
|
-
return true;
|
|
132371
|
-
}
|
|
132372
|
-
return CodeGenState.cppMode && !this.isKnownStruct(typeName);
|
|
132373
|
-
}
|
|
132374
132978
|
/**
|
|
132375
132979
|
* Generate a safe bit mask expression.
|
|
132376
132980
|
* Avoids undefined behavior when width >= 32 for 32-bit integers.
|
|
@@ -132750,7 +133354,7 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
132750
133354
|
const maxComparison = `((${floatCastType})${maxValue})`;
|
|
132751
133355
|
const finalCast = CppModeHelper_default.cast(targetType, `(${expr})`);
|
|
132752
133356
|
const castMax = CppModeHelper_default.cast(targetType, maxValue);
|
|
132753
|
-
const castMin =
|
|
133357
|
+
const castMin = CppModeHelper_default.cast(targetType, minValue);
|
|
132754
133358
|
return `((${expr}) > ${maxComparison} ? ${castMax} : (${expr}) < ${minComparison} ? ${castMin} : ${finalCast})`;
|
|
132755
133359
|
}
|
|
132756
133360
|
/**
|
|
@@ -133126,6 +133730,30 @@ var generateEnumHeader_default = generateEnumHeader;
|
|
|
133126
133730
|
|
|
133127
133731
|
// src/transpiler/output/headers/generators/generateStructHeader.ts
|
|
133128
133732
|
var { mapType: mapType2 } = mapType_default;
|
|
133733
|
+
function resolveFieldCType(fieldType, input) {
|
|
133734
|
+
const callbackInfo = input.callbackTypes?.get(fieldType);
|
|
133735
|
+
if (callbackInfo) {
|
|
133736
|
+
return callbackInfo.typedefName;
|
|
133737
|
+
}
|
|
133738
|
+
const convertedType = CppNamespaceUtils_default.convertToCppNamespace(
|
|
133739
|
+
fieldType,
|
|
133740
|
+
input.symbolTable
|
|
133741
|
+
);
|
|
133742
|
+
return mapType2(convertedType);
|
|
133743
|
+
}
|
|
133744
|
+
function generateFieldLine(fieldName, cType, dims) {
|
|
133745
|
+
const dimSuffix = dims && dims.length > 0 ? dims.map((d) => `[${d}]`).join("") : "";
|
|
133746
|
+
const embeddedMatch = /^(\w+)\[(\d+)\]$/.exec(cType);
|
|
133747
|
+
if (!embeddedMatch) {
|
|
133748
|
+
return ` ${cType} ${fieldName}${dimSuffix};`;
|
|
133749
|
+
}
|
|
133750
|
+
const baseType = embeddedMatch[1];
|
|
133751
|
+
const embeddedDim = embeddedMatch[2];
|
|
133752
|
+
if (dims && dims.length > 0) {
|
|
133753
|
+
return ` ${baseType} ${fieldName}${dimSuffix};`;
|
|
133754
|
+
}
|
|
133755
|
+
return ` ${baseType} ${fieldName}[${embeddedDim}];`;
|
|
133756
|
+
}
|
|
133129
133757
|
function generateStructHeader(name, input) {
|
|
133130
133758
|
const fields = input.structFields.get(name);
|
|
133131
133759
|
if (!fields || fields.size === 0) {
|
|
@@ -133135,25 +133763,9 @@ function generateStructHeader(name, input) {
|
|
|
133135
133763
|
const lines = [];
|
|
133136
133764
|
lines.push(`typedef struct ${name} {`);
|
|
133137
133765
|
for (const [fieldName, fieldType] of fields) {
|
|
133138
|
-
const
|
|
133139
|
-
fieldType,
|
|
133140
|
-
input.symbolTable
|
|
133141
|
-
);
|
|
133142
|
-
const cType = mapType2(convertedType);
|
|
133766
|
+
const cType = resolveFieldCType(fieldType, input);
|
|
133143
133767
|
const dims = dimensions?.get(fieldName);
|
|
133144
|
-
|
|
133145
|
-
const embeddedMatch = /^(\w+)\[(\d+)\]$/.exec(cType);
|
|
133146
|
-
if (embeddedMatch) {
|
|
133147
|
-
const baseType = embeddedMatch[1];
|
|
133148
|
-
const embeddedDim = embeddedMatch[2];
|
|
133149
|
-
if (dims && dims.length > 0) {
|
|
133150
|
-
lines.push(` ${baseType} ${fieldName}${dimSuffix};`);
|
|
133151
|
-
} else {
|
|
133152
|
-
lines.push(` ${baseType} ${fieldName}[${embeddedDim}];`);
|
|
133153
|
-
}
|
|
133154
|
-
} else {
|
|
133155
|
-
lines.push(` ${cType} ${fieldName}${dimSuffix};`);
|
|
133156
|
-
}
|
|
133768
|
+
lines.push(generateFieldLine(fieldName, cType, dims));
|
|
133157
133769
|
}
|
|
133158
133770
|
lines.push(`} ${name};`);
|
|
133159
133771
|
return lines.join("\n");
|
|
@@ -133546,6 +134158,59 @@ var HeaderGeneratorUtils = class _HeaderGeneratorUtils {
|
|
|
133546
134158
|
lines.push("");
|
|
133547
134159
|
return lines;
|
|
133548
134160
|
}
|
|
134161
|
+
/**
|
|
134162
|
+
* ADR-029: Generate forward declarations for structs used in callback typedefs.
|
|
134163
|
+
* This ensures struct types can be used in callback parameter types before
|
|
134164
|
+
* the full struct definition.
|
|
134165
|
+
*/
|
|
134166
|
+
static generateCallbackStructForwardDecls(structs, typeInput) {
|
|
134167
|
+
if (!typeInput?.callbackTypes || typeInput.callbackTypes.size === 0) {
|
|
134168
|
+
return [];
|
|
134169
|
+
}
|
|
134170
|
+
const usedStructTypes = /* @__PURE__ */ new Set();
|
|
134171
|
+
for (const [, cbInfo] of typeInput.callbackTypes) {
|
|
134172
|
+
for (const p of cbInfo.parameters) {
|
|
134173
|
+
if (p.isStruct) {
|
|
134174
|
+
usedStructTypes.add(p.type);
|
|
134175
|
+
}
|
|
134176
|
+
}
|
|
134177
|
+
}
|
|
134178
|
+
if (usedStructTypes.size === 0) {
|
|
134179
|
+
return [];
|
|
134180
|
+
}
|
|
134181
|
+
const localStructNames = new Set(structs.map((s) => s.name));
|
|
134182
|
+
const lines = [];
|
|
134183
|
+
for (const structType of usedStructTypes) {
|
|
134184
|
+
if (localStructNames.has(structType)) {
|
|
134185
|
+
lines.push(`typedef struct ${structType} ${structType};`);
|
|
134186
|
+
}
|
|
134187
|
+
}
|
|
134188
|
+
return lines.length > 0 ? [...lines, ""] : [];
|
|
134189
|
+
}
|
|
134190
|
+
/**
|
|
134191
|
+
* ADR-029: Generate callback typedef section
|
|
134192
|
+
* Generates function pointer typedefs for callbacks used as struct field types
|
|
134193
|
+
*/
|
|
134194
|
+
static generateCallbackTypedefSection(typeInput, isCppMode) {
|
|
134195
|
+
if (!typeInput?.callbackTypes || typeInput.callbackTypes.size === 0) {
|
|
134196
|
+
return [];
|
|
134197
|
+
}
|
|
134198
|
+
const lines = ["/* Callback typedefs */"];
|
|
134199
|
+
for (const [, cbInfo] of typeInput.callbackTypes) {
|
|
134200
|
+
const params = cbInfo.parameters.length > 0 ? cbInfo.parameters.map((p) => {
|
|
134201
|
+
if (p.isStruct) {
|
|
134202
|
+
const ptrOrRef = isCppMode ? "&" : "*";
|
|
134203
|
+
return `${p.type}${ptrOrRef}`;
|
|
134204
|
+
}
|
|
134205
|
+
return p.type;
|
|
134206
|
+
}).join(", ") : "void";
|
|
134207
|
+
lines.push(
|
|
134208
|
+
`typedef ${cbInfo.returnType} (*${cbInfo.typedefName})(${params});`
|
|
134209
|
+
);
|
|
134210
|
+
}
|
|
134211
|
+
lines.push("");
|
|
134212
|
+
return lines;
|
|
134213
|
+
}
|
|
133549
134214
|
/**
|
|
133550
134215
|
* Generate struct and class definitions section
|
|
133551
134216
|
*/
|
|
@@ -133673,6 +134338,14 @@ var BaseHeaderGenerator = class {
|
|
|
133673
134338
|
...HeaderGeneratorUtils_default.generateEnumSection(groups.enums, typeInput),
|
|
133674
134339
|
...HeaderGeneratorUtils_default.generateBitmapSection(groups.bitmaps, typeInput),
|
|
133675
134340
|
...HeaderGeneratorUtils_default.generateTypeAliasSection(groups.types),
|
|
134341
|
+
...HeaderGeneratorUtils_default.generateCallbackStructForwardDecls(
|
|
134342
|
+
groups.structs,
|
|
134343
|
+
typeInput
|
|
134344
|
+
),
|
|
134345
|
+
...HeaderGeneratorUtils_default.generateCallbackTypedefSection(
|
|
134346
|
+
typeInput,
|
|
134347
|
+
options.cppMode
|
|
134348
|
+
),
|
|
133676
134349
|
...HeaderGeneratorUtils_default.generateStructSection(
|
|
133677
134350
|
groups.structs,
|
|
133678
134351
|
groups.classes,
|
|
@@ -134011,24 +134684,32 @@ var EnumCollector = class {
|
|
|
134011
134684
|
var EnumCollector_default = EnumCollector;
|
|
134012
134685
|
|
|
134013
134686
|
// src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts
|
|
134014
|
-
function resolveScopedType(scopedTypeCtx, scopeName) {
|
|
134015
|
-
const typeName = scopedTypeCtx.IDENTIFIER().getText();
|
|
134016
|
-
return scopeName ? `${scopeName}_${typeName}` : typeName;
|
|
134017
|
-
}
|
|
134018
134687
|
function resolveStringType(stringCtx) {
|
|
134019
134688
|
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
134020
134689
|
return intLiteral ? `string<${intLiteral.getText()}>` : "string";
|
|
134021
134690
|
}
|
|
134022
|
-
function
|
|
134023
|
-
if (
|
|
134024
|
-
|
|
134691
|
+
function dispatchTypeResolution(accessors, scopeName) {
|
|
134692
|
+
if (accessors.scopedType()) {
|
|
134693
|
+
const typeName = accessors.scopedType().IDENTIFIER().getText();
|
|
134694
|
+
return scopeName ? `${scopeName}_${typeName}` : typeName;
|
|
134695
|
+
}
|
|
134696
|
+
if (accessors.globalType()) {
|
|
134697
|
+
return accessors.globalType().IDENTIFIER().getText();
|
|
134698
|
+
}
|
|
134699
|
+
if (accessors.qualifiedType()) {
|
|
134700
|
+
const identifiers = accessors.qualifiedType().IDENTIFIER();
|
|
134701
|
+
return identifiers.map((id) => id.getText()).join("_");
|
|
134025
134702
|
}
|
|
134026
|
-
if (
|
|
134027
|
-
return
|
|
134703
|
+
if (accessors.userType()) {
|
|
134704
|
+
return accessors.userType().getText();
|
|
134028
134705
|
}
|
|
134029
|
-
|
|
134030
|
-
|
|
134031
|
-
|
|
134706
|
+
if (accessors.primitiveType()) {
|
|
134707
|
+
return accessors.primitiveType().getText();
|
|
134708
|
+
}
|
|
134709
|
+
if (accessors.stringType()) {
|
|
134710
|
+
return resolveStringType(accessors.stringType());
|
|
134711
|
+
}
|
|
134712
|
+
return null;
|
|
134032
134713
|
}
|
|
134033
134714
|
var TypeUtils = class {
|
|
134034
134715
|
/**
|
|
@@ -134042,27 +134723,18 @@ var TypeUtils = class {
|
|
|
134042
134723
|
*/
|
|
134043
134724
|
static getTypeName(ctx, scopeName) {
|
|
134044
134725
|
if (!ctx) return "void";
|
|
134045
|
-
if (ctx.scopedType()) {
|
|
134046
|
-
return resolveScopedType(ctx.scopedType(), scopeName);
|
|
134047
|
-
}
|
|
134048
|
-
if (ctx.globalType()) {
|
|
134049
|
-
return ctx.globalType().IDENTIFIER().getText();
|
|
134050
|
-
}
|
|
134051
|
-
if (ctx.qualifiedType()) {
|
|
134052
|
-
const identifiers = ctx.qualifiedType().IDENTIFIER();
|
|
134053
|
-
return identifiers.map((id) => id.getText()).join("_");
|
|
134054
|
-
}
|
|
134055
|
-
if (ctx.userType()) {
|
|
134056
|
-
return ctx.userType().getText();
|
|
134057
|
-
}
|
|
134058
|
-
if (ctx.primitiveType()) {
|
|
134059
|
-
return ctx.primitiveType().getText();
|
|
134060
|
-
}
|
|
134061
|
-
if (ctx.stringType()) {
|
|
134062
|
-
return resolveStringType(ctx.stringType());
|
|
134063
|
-
}
|
|
134064
134726
|
if (ctx.arrayType()) {
|
|
134065
|
-
|
|
134727
|
+
const result2 = dispatchTypeResolution(ctx.arrayType(), scopeName);
|
|
134728
|
+
if (result2 !== null) {
|
|
134729
|
+
return result2;
|
|
134730
|
+
}
|
|
134731
|
+
const text = ctx.arrayType().getText();
|
|
134732
|
+
const bracketIdx = text.indexOf("[");
|
|
134733
|
+
return bracketIdx > 0 ? text.substring(0, bracketIdx) : text;
|
|
134734
|
+
}
|
|
134735
|
+
const result = dispatchTypeResolution(ctx, scopeName);
|
|
134736
|
+
if (result !== null) {
|
|
134737
|
+
return result;
|
|
134066
134738
|
}
|
|
134067
134739
|
return ctx.getText();
|
|
134068
134740
|
}
|
|
@@ -134428,13 +135100,22 @@ var VariableCollector = class _VariableCollector {
|
|
|
134428
135100
|
return dimensions;
|
|
134429
135101
|
}
|
|
134430
135102
|
/**
|
|
134431
|
-
* Collect dimensions from C-Next style arrayType syntax (u16[8] arr, u16[4][4] arr).
|
|
135103
|
+
* Collect dimensions from C-Next style arrayType syntax (u16[8] arr, u16[4][4] arr, u16[] arr).
|
|
135104
|
+
* Handles size inference from initializer when dimension is empty.
|
|
134432
135105
|
*/
|
|
134433
|
-
static collectArrayTypeDimensions(arrayTypeCtx, constValues) {
|
|
135106
|
+
static collectArrayTypeDimensions(arrayTypeCtx, constValues, initExpr) {
|
|
134434
135107
|
const dimensions = [];
|
|
134435
135108
|
for (const dim of arrayTypeCtx.arrayTypeDimension()) {
|
|
134436
135109
|
const sizeExpr = dim.expression();
|
|
134437
|
-
if (!sizeExpr)
|
|
135110
|
+
if (!sizeExpr) {
|
|
135111
|
+
if (initExpr) {
|
|
135112
|
+
const inferredSize = ArrayInitializerUtils_default.getInferredSize(initExpr);
|
|
135113
|
+
if (inferredSize !== void 0) {
|
|
135114
|
+
dimensions.push(inferredSize);
|
|
135115
|
+
}
|
|
135116
|
+
}
|
|
135117
|
+
continue;
|
|
135118
|
+
}
|
|
134438
135119
|
const dimText = sizeExpr.getText();
|
|
134439
135120
|
const literalSize = LiteralUtils_default.parseIntegerLiteral(dimText);
|
|
134440
135121
|
if (literalSize !== void 0) {
|
|
@@ -134476,7 +135157,8 @@ var VariableCollector = class _VariableCollector {
|
|
|
134476
135157
|
arrayDimensions.push(
|
|
134477
135158
|
..._VariableCollector.collectArrayTypeDimensions(
|
|
134478
135159
|
arrayTypeCtx,
|
|
134479
|
-
constValues
|
|
135160
|
+
constValues,
|
|
135161
|
+
initExpr
|
|
134480
135162
|
)
|
|
134481
135163
|
);
|
|
134482
135164
|
}
|
|
@@ -138838,19 +139520,28 @@ var InitializationListener = class extends CNextListener {
|
|
|
138838
139520
|
if (!baseId) {
|
|
138839
139521
|
return;
|
|
138840
139522
|
}
|
|
139523
|
+
const target = this._resolveAssignmentTarget(baseId, postfixOps);
|
|
139524
|
+
const isCompoundAssignment = ctx.assignmentOperator().ASSIGN() === null;
|
|
139525
|
+
if (isCompoundAssignment) {
|
|
139526
|
+
const { line, column } = ParserUtils_default.getPosition(ctx);
|
|
139527
|
+
this.analyzer.checkRead(target.varName, line, column, target.fieldName);
|
|
139528
|
+
}
|
|
139529
|
+
this.analyzer.recordAssignment(target.varName, target.fieldName);
|
|
139530
|
+
};
|
|
139531
|
+
/**
|
|
139532
|
+
* Resolve an assignment target to its variable name and optional field name.
|
|
139533
|
+
* Single classification path used by both read checks and assignment recording.
|
|
139534
|
+
*/
|
|
139535
|
+
_resolveAssignmentTarget(baseId, postfixOps) {
|
|
138841
139536
|
if (postfixOps.length === 0) {
|
|
138842
|
-
|
|
138843
|
-
return;
|
|
139537
|
+
return { varName: baseId };
|
|
138844
139538
|
}
|
|
138845
139539
|
const { identifiers, hasSubscript } = PostfixAnalysisUtils_default(baseId, postfixOps);
|
|
138846
139540
|
if (identifiers.length >= 2 && !hasSubscript) {
|
|
138847
|
-
|
|
138848
|
-
const fieldName = identifiers[1];
|
|
138849
|
-
this.analyzer.recordAssignment(varName, fieldName);
|
|
138850
|
-
} else {
|
|
138851
|
-
this.analyzer.recordAssignment(baseId);
|
|
139541
|
+
return { varName: identifiers[0], fieldName: identifiers[1] };
|
|
138852
139542
|
}
|
|
138853
|
-
|
|
139543
|
+
return { varName: baseId };
|
|
139544
|
+
}
|
|
138854
139545
|
// ========================================================================
|
|
138855
139546
|
// Function Call Arguments (ADR-006: pass-by-reference may initialize)
|
|
138856
139547
|
// ========================================================================
|
|
@@ -139088,27 +139779,128 @@ var InitializationAnalyzer = class {
|
|
|
139088
139779
|
}
|
|
139089
139780
|
/**
|
|
139090
139781
|
* Process scope member variable declarations (ADR-016)
|
|
139782
|
+
* Issue #1019: Scope members require explicit initialization like locals
|
|
139091
139783
|
*/
|
|
139092
139784
|
_processScopeMembers(decl) {
|
|
139093
139785
|
const scopeDecl = decl.scopeDeclaration();
|
|
139094
139786
|
if (!scopeDecl) return;
|
|
139095
139787
|
const scopeName = scopeDecl.IDENTIFIER().getText();
|
|
139788
|
+
const assignedMembers = this._findAssignedScopeMembers(scopeDecl);
|
|
139096
139789
|
for (const member of scopeDecl.scopeMember()) {
|
|
139097
|
-
this._processScopeMemberVariable(member, scopeName);
|
|
139790
|
+
this._processScopeMemberVariable(member, scopeName, assignedMembers);
|
|
139791
|
+
}
|
|
139792
|
+
}
|
|
139793
|
+
/**
|
|
139794
|
+
* Scan all functions in a scope to find which members are assigned.
|
|
139795
|
+
* Issue #1019: A member assigned in ANY function is considered initialized
|
|
139796
|
+
* for reads in other functions within the same scope.
|
|
139797
|
+
*/
|
|
139798
|
+
_findAssignedScopeMembers(scopeDecl) {
|
|
139799
|
+
const assigned = /* @__PURE__ */ new Set();
|
|
139800
|
+
for (const member of scopeDecl.scopeMember()) {
|
|
139801
|
+
const funcDecl = member.functionDeclaration();
|
|
139802
|
+
if (!funcDecl) continue;
|
|
139803
|
+
const body = funcDecl.block();
|
|
139804
|
+
if (!body) continue;
|
|
139805
|
+
this._collectAssignmentsInBlock(body, assigned);
|
|
139806
|
+
}
|
|
139807
|
+
return assigned;
|
|
139808
|
+
}
|
|
139809
|
+
/**
|
|
139810
|
+
* Recursively collect variable names that are assigned in a block.
|
|
139811
|
+
* Looks for assignment statements targeting bare identifiers or this.member.
|
|
139812
|
+
*/
|
|
139813
|
+
_collectAssignmentsInBlock(block, assigned) {
|
|
139814
|
+
for (const stmt of block.statement()) {
|
|
139815
|
+
this._collectAssignmentsInStatement(stmt, assigned);
|
|
139816
|
+
}
|
|
139817
|
+
}
|
|
139818
|
+
/**
|
|
139819
|
+
* Collect assignments from a single statement, recursing into nested blocks.
|
|
139820
|
+
*/
|
|
139821
|
+
_collectAssignmentsInStatement(stmt, assigned) {
|
|
139822
|
+
this._collectDirectAssignment(stmt, assigned);
|
|
139823
|
+
this._collectFromControlFlow(stmt, assigned);
|
|
139824
|
+
this._collectFromSwitch(stmt, assigned);
|
|
139825
|
+
this._collectFromBlock(stmt, assigned);
|
|
139826
|
+
}
|
|
139827
|
+
/**
|
|
139828
|
+
* Collect assignment from the statement itself (if it's an assignment).
|
|
139829
|
+
*/
|
|
139830
|
+
_collectDirectAssignment(stmt, assigned) {
|
|
139831
|
+
const assignStmt = stmt.assignmentStatement();
|
|
139832
|
+
if (!assignStmt) return;
|
|
139833
|
+
const target = assignStmt.assignmentTarget();
|
|
139834
|
+
if (!target) return;
|
|
139835
|
+
const id = target.IDENTIFIER()?.getText();
|
|
139836
|
+
if (id) {
|
|
139837
|
+
assigned.add(id);
|
|
139838
|
+
}
|
|
139839
|
+
}
|
|
139840
|
+
/**
|
|
139841
|
+
* Recurse into control flow statements (if, while, do-while, for).
|
|
139842
|
+
*/
|
|
139843
|
+
_collectFromControlFlow(stmt, assigned) {
|
|
139844
|
+
const ifStmt = stmt.ifStatement();
|
|
139845
|
+
if (ifStmt) {
|
|
139846
|
+
for (const childStmt of ifStmt.statement()) {
|
|
139847
|
+
this._collectAssignmentsInStatement(childStmt, assigned);
|
|
139848
|
+
}
|
|
139849
|
+
}
|
|
139850
|
+
const whileBody = stmt.whileStatement()?.statement();
|
|
139851
|
+
if (whileBody) {
|
|
139852
|
+
this._collectAssignmentsInStatement(whileBody, assigned);
|
|
139853
|
+
}
|
|
139854
|
+
const doWhileBody = stmt.doWhileStatement()?.block();
|
|
139855
|
+
if (doWhileBody) {
|
|
139856
|
+
this._collectAssignmentsInBlock(doWhileBody, assigned);
|
|
139857
|
+
}
|
|
139858
|
+
const forBody = stmt.forStatement()?.statement();
|
|
139859
|
+
if (forBody) {
|
|
139860
|
+
this._collectAssignmentsInStatement(forBody, assigned);
|
|
139861
|
+
}
|
|
139862
|
+
}
|
|
139863
|
+
/**
|
|
139864
|
+
* Recurse into switch statement cases.
|
|
139865
|
+
*/
|
|
139866
|
+
_collectFromSwitch(stmt, assigned) {
|
|
139867
|
+
const switchStmt = stmt.switchStatement();
|
|
139868
|
+
if (!switchStmt) return;
|
|
139869
|
+
for (const switchCase of switchStmt.switchCase()) {
|
|
139870
|
+
const caseBlock = switchCase.block();
|
|
139871
|
+
if (caseBlock) {
|
|
139872
|
+
this._collectAssignmentsInBlock(caseBlock, assigned);
|
|
139873
|
+
}
|
|
139874
|
+
}
|
|
139875
|
+
const defaultBlock = switchStmt.defaultCase()?.block();
|
|
139876
|
+
if (defaultBlock) {
|
|
139877
|
+
this._collectAssignmentsInBlock(defaultBlock, assigned);
|
|
139878
|
+
}
|
|
139879
|
+
}
|
|
139880
|
+
/**
|
|
139881
|
+
* Recurse into standalone block statement.
|
|
139882
|
+
*/
|
|
139883
|
+
_collectFromBlock(stmt, assigned) {
|
|
139884
|
+
const block = stmt.block();
|
|
139885
|
+
if (block) {
|
|
139886
|
+
this._collectAssignmentsInBlock(block, assigned);
|
|
139098
139887
|
}
|
|
139099
139888
|
}
|
|
139100
139889
|
/**
|
|
139101
139890
|
* Process a single scope member variable
|
|
139102
139891
|
*/
|
|
139103
|
-
_processScopeMemberVariable(member, scopeName) {
|
|
139892
|
+
_processScopeMemberVariable(member, scopeName, assignedMembers) {
|
|
139104
139893
|
const memberVar = member.variableDeclaration();
|
|
139105
139894
|
if (!memberVar) return;
|
|
139106
139895
|
const varName = memberVar.IDENTIFIER().getText();
|
|
139107
139896
|
const fullName = `${scopeName}_${varName}`;
|
|
139108
139897
|
const { line, column } = ParserUtils_default.getPosition(memberVar);
|
|
139109
139898
|
const typeName = this._extractUserTypeName(memberVar.type());
|
|
139110
|
-
|
|
139111
|
-
|
|
139899
|
+
const hasInlineInit = memberVar.expression() !== null;
|
|
139900
|
+
const isAssignedInScope = assignedMembers.has(varName);
|
|
139901
|
+
const hasInitializer = hasInlineInit || isAssignedInScope;
|
|
139902
|
+
this.declareVariable(varName, line, column, hasInitializer, typeName);
|
|
139903
|
+
this.declareVariable(fullName, line, column, hasInitializer, typeName);
|
|
139112
139904
|
}
|
|
139113
139905
|
/**
|
|
139114
139906
|
* Extract user type name from a type context
|
|
@@ -139607,14 +140399,18 @@ var FunctionCallListener = class extends CNextListener {
|
|
|
139607
140399
|
const primary = ctx.primaryExpression();
|
|
139608
140400
|
const baseName = this.extractBaseName(primary);
|
|
139609
140401
|
if (!baseName) return;
|
|
139610
|
-
const { resolvedName, foundCall } = this.resolveCallTarget(
|
|
140402
|
+
const { resolvedName, foundCall, isGlobalCall } = this.resolveCallTarget(
|
|
140403
|
+
ops,
|
|
140404
|
+
baseName
|
|
140405
|
+
);
|
|
139611
140406
|
if (!foundCall) return;
|
|
139612
140407
|
const { line, column } = ParserUtils_default.getPosition(ctx);
|
|
139613
140408
|
this.analyzer.checkFunctionCall(
|
|
139614
140409
|
resolvedName,
|
|
139615
140410
|
line,
|
|
139616
140411
|
column,
|
|
139617
|
-
this.currentScope
|
|
140412
|
+
this.currentScope,
|
|
140413
|
+
isGlobalCall
|
|
139618
140414
|
);
|
|
139619
140415
|
};
|
|
139620
140416
|
/**
|
|
@@ -139627,6 +140423,9 @@ var FunctionCallListener = class extends CNextListener {
|
|
|
139627
140423
|
if (primary.THIS()) {
|
|
139628
140424
|
return "this";
|
|
139629
140425
|
}
|
|
140426
|
+
if (primary.GLOBAL()) {
|
|
140427
|
+
return "global";
|
|
140428
|
+
}
|
|
139630
140429
|
return null;
|
|
139631
140430
|
}
|
|
139632
140431
|
/**
|
|
@@ -139636,11 +140435,15 @@ var FunctionCallListener = class extends CNextListener {
|
|
|
139636
140435
|
*/
|
|
139637
140436
|
resolveCallTarget(ops, baseName) {
|
|
139638
140437
|
let resolvedName = baseName;
|
|
140438
|
+
let isGlobalCall = baseName === "global";
|
|
139639
140439
|
for (const op of ops) {
|
|
139640
140440
|
if (op.IDENTIFIER()) {
|
|
139641
140441
|
const resolved = this.resolveMemberAccess(resolvedName, op);
|
|
139642
140442
|
if (resolved === null) {
|
|
139643
|
-
return { resolvedName, foundCall: false };
|
|
140443
|
+
return { resolvedName, foundCall: false, isGlobalCall };
|
|
140444
|
+
}
|
|
140445
|
+
if (isGlobalCall && this.analyzer.isScope(resolvedName)) {
|
|
140446
|
+
isGlobalCall = false;
|
|
139644
140447
|
}
|
|
139645
140448
|
resolvedName = resolved;
|
|
139646
140449
|
continue;
|
|
@@ -139648,11 +140451,11 @@ var FunctionCallListener = class extends CNextListener {
|
|
|
139648
140451
|
if (op.argumentList() || op.getChildCount() === 2) {
|
|
139649
140452
|
const text = op.getText();
|
|
139650
140453
|
if (text.startsWith("(")) {
|
|
139651
|
-
return { resolvedName, foundCall: true };
|
|
140454
|
+
return { resolvedName, foundCall: true, isGlobalCall };
|
|
139652
140455
|
}
|
|
139653
140456
|
}
|
|
139654
140457
|
}
|
|
139655
|
-
return { resolvedName, foundCall: false };
|
|
140458
|
+
return { resolvedName, foundCall: false, isGlobalCall };
|
|
139656
140459
|
}
|
|
139657
140460
|
/**
|
|
139658
140461
|
* Resolve member access pattern. Returns new name or null if not a C-Next function.
|
|
@@ -139662,6 +140465,9 @@ var FunctionCallListener = class extends CNextListener {
|
|
|
139662
140465
|
if (resolvedName === "this" && this.currentScope) {
|
|
139663
140466
|
return `${this.currentScope}_${memberName}`;
|
|
139664
140467
|
}
|
|
140468
|
+
if (resolvedName === "global") {
|
|
140469
|
+
return memberName;
|
|
140470
|
+
}
|
|
139665
140471
|
if (this.analyzer.isScope(resolvedName)) {
|
|
139666
140472
|
return `${resolvedName}_${memberName}`;
|
|
139667
140473
|
}
|
|
@@ -140060,8 +140866,9 @@ var FunctionCallAnalyzer = class {
|
|
|
140060
140866
|
* @param line Source line number
|
|
140061
140867
|
* @param column Source column number
|
|
140062
140868
|
* @param currentScope The current scope name (if inside a scope)
|
|
140869
|
+
* @param isGlobalCall Whether the call used global. prefix
|
|
140063
140870
|
*/
|
|
140064
|
-
checkFunctionCall(name, line, column, currentScope) {
|
|
140871
|
+
checkFunctionCall(name, line, column, currentScope, isGlobalCall = false) {
|
|
140065
140872
|
if (this.currentFunctionName && name === this.currentFunctionName) {
|
|
140066
140873
|
this.errors.push({
|
|
140067
140874
|
code: "E0423",
|
|
@@ -140087,17 +140894,19 @@ var FunctionCallAnalyzer = class {
|
|
|
140087
140894
|
if (this.callableVariables.has(name)) {
|
|
140088
140895
|
return;
|
|
140089
140896
|
}
|
|
140090
|
-
if (currentScope) {
|
|
140897
|
+
if (currentScope && !isGlobalCall) {
|
|
140091
140898
|
const qualifiedName = `${currentScope}_${name}`;
|
|
140092
140899
|
if (this.definedFunctions.has(qualifiedName)) {
|
|
140093
140900
|
return;
|
|
140094
140901
|
}
|
|
140095
140902
|
}
|
|
140903
|
+
const isLocalFunction = this.allLocalFunctions.has(name);
|
|
140096
140904
|
const header = this.findStdlibHeader(name);
|
|
140097
|
-
|
|
140098
|
-
|
|
140099
|
-
|
|
140100
|
-
|
|
140905
|
+
const message = this.buildUndefinedFunctionMessage(
|
|
140906
|
+
name,
|
|
140907
|
+
header,
|
|
140908
|
+
isGlobalCall && !isLocalFunction
|
|
140909
|
+
);
|
|
140101
140910
|
this.errors.push({
|
|
140102
140911
|
code: "E0422",
|
|
140103
140912
|
functionName: name,
|
|
@@ -140106,6 +140915,23 @@ var FunctionCallAnalyzer = class {
|
|
|
140106
140915
|
message
|
|
140107
140916
|
});
|
|
140108
140917
|
}
|
|
140918
|
+
/**
|
|
140919
|
+
* Issue #985: Build error message for undefined function calls.
|
|
140920
|
+
* Adjusts hint based on whether the call used global. prefix.
|
|
140921
|
+
*/
|
|
140922
|
+
buildUndefinedFunctionMessage(name, header, isGlobalCall) {
|
|
140923
|
+
if (isGlobalCall && header) {
|
|
140924
|
+
return `'${name}' is not declared in any included header; add #include <${header}>`;
|
|
140925
|
+
}
|
|
140926
|
+
if (isGlobalCall) {
|
|
140927
|
+
return `'${name}' is not declared in any included header`;
|
|
140928
|
+
}
|
|
140929
|
+
let message = `function '${name}' called before definition`;
|
|
140930
|
+
if (header) {
|
|
140931
|
+
message += `; hint: '${name}' is available from ${header} \u2014 try global.${name}()`;
|
|
140932
|
+
}
|
|
140933
|
+
return message;
|
|
140934
|
+
}
|
|
140109
140935
|
/**
|
|
140110
140936
|
* Check if a function is defined externally (from included files)
|
|
140111
140937
|
* This includes C/C++ headers AND C-Next includes.
|
|
@@ -140631,46 +141457,56 @@ var ArrayIndexTypeAnalyzer_default = ArrayIndexTypeAnalyzer;
|
|
|
140631
141457
|
import { ParseTreeWalker as ParseTreeWalker9 } from "antlr4ng";
|
|
140632
141458
|
var SignedVariableCollector = class extends CNextListener {
|
|
140633
141459
|
signedVars = /* @__PURE__ */ new Set();
|
|
141460
|
+
// Track all variable types (for resolving struct member chains)
|
|
141461
|
+
varTypes = /* @__PURE__ */ new Map();
|
|
140634
141462
|
getSignedVars() {
|
|
140635
141463
|
return this.signedVars;
|
|
140636
141464
|
}
|
|
141465
|
+
getVarTypes() {
|
|
141466
|
+
return this.varTypes;
|
|
141467
|
+
}
|
|
140637
141468
|
/**
|
|
140638
|
-
* Track a typed identifier
|
|
141469
|
+
* Track a typed identifier - add to signedVars if signed, always track type
|
|
140639
141470
|
*/
|
|
140640
|
-
|
|
140641
|
-
if (!typeCtx) return;
|
|
141471
|
+
trackType(typeCtx, identifier) {
|
|
141472
|
+
if (!typeCtx || !identifier) return;
|
|
140642
141473
|
const typeName = typeCtx.getText();
|
|
140643
|
-
|
|
140644
|
-
|
|
140645
|
-
|
|
141474
|
+
const varName = identifier.getText();
|
|
141475
|
+
this.varTypes.set(varName, typeName);
|
|
141476
|
+
if (TypeConstants_default.SIGNED_TYPES.includes(typeName)) {
|
|
141477
|
+
this.signedVars.add(varName);
|
|
141478
|
+
}
|
|
140646
141479
|
}
|
|
140647
141480
|
/**
|
|
140648
141481
|
* Track variable declarations with signed types
|
|
140649
141482
|
*/
|
|
140650
141483
|
enterVariableDeclaration = (ctx) => {
|
|
140651
|
-
this.
|
|
141484
|
+
this.trackType(ctx.type(), ctx.IDENTIFIER());
|
|
140652
141485
|
};
|
|
140653
141486
|
/**
|
|
140654
141487
|
* Track function parameters with signed types
|
|
140655
141488
|
*/
|
|
140656
141489
|
enterParameter = (ctx) => {
|
|
140657
|
-
this.
|
|
141490
|
+
this.trackType(ctx.type(), ctx.IDENTIFIER());
|
|
140658
141491
|
};
|
|
140659
141492
|
/**
|
|
140660
141493
|
* Track for-loop variable declarations with signed types
|
|
140661
141494
|
*/
|
|
140662
141495
|
enterForVarDecl = (ctx) => {
|
|
140663
|
-
this.
|
|
141496
|
+
this.trackType(ctx.type(), ctx.IDENTIFIER());
|
|
140664
141497
|
};
|
|
140665
141498
|
};
|
|
140666
141499
|
var SignedShiftListener = class extends CNextListener {
|
|
140667
141500
|
analyzer;
|
|
140668
141501
|
// eslint-disable-next-line @typescript-eslint/lines-between-class-members
|
|
140669
141502
|
signedVars;
|
|
140670
|
-
|
|
141503
|
+
// eslint-disable-next-line @typescript-eslint/lines-between-class-members
|
|
141504
|
+
varTypes;
|
|
141505
|
+
constructor(analyzer, signedVars, varTypes) {
|
|
140671
141506
|
super();
|
|
140672
141507
|
this.analyzer = analyzer;
|
|
140673
141508
|
this.signedVars = signedVars;
|
|
141509
|
+
this.varTypes = varTypes;
|
|
140674
141510
|
}
|
|
140675
141511
|
/**
|
|
140676
141512
|
* Check shift expressions for signed operands
|
|
@@ -140691,6 +141527,69 @@ var SignedShiftListener = class extends CNextListener {
|
|
|
140691
141527
|
}
|
|
140692
141528
|
}
|
|
140693
141529
|
};
|
|
141530
|
+
/**
|
|
141531
|
+
* Check compound shift-assign statements for signed targets
|
|
141532
|
+
* assignmentStatement: assignmentTarget assignmentOperator expression ';'
|
|
141533
|
+
* Issue #1008: <<<- and >><- must also be rejected on signed types
|
|
141534
|
+
*
|
|
141535
|
+
* Handles both simple identifiers (x <<<- 2) and member chains (s.x <<<- 2)
|
|
141536
|
+
*/
|
|
141537
|
+
enterAssignmentStatement = (ctx) => {
|
|
141538
|
+
const opCtx = ctx.assignmentOperator();
|
|
141539
|
+
if (!opCtx) return;
|
|
141540
|
+
const isLeftShiftAssign = opCtx.LSHIFT_ASSIGN() !== null;
|
|
141541
|
+
const isRightShiftAssign = opCtx.RSHIFT_ASSIGN() !== null;
|
|
141542
|
+
if (!isLeftShiftAssign && !isRightShiftAssign) return;
|
|
141543
|
+
const target = ctx.assignmentTarget();
|
|
141544
|
+
if (!target) return;
|
|
141545
|
+
const identifier = target.IDENTIFIER();
|
|
141546
|
+
if (!identifier) return;
|
|
141547
|
+
const baseName = identifier.getText();
|
|
141548
|
+
const postfixOps = target.postfixTargetOp();
|
|
141549
|
+
if (this.isSignedTarget(baseName, postfixOps)) {
|
|
141550
|
+
const operator = isLeftShiftAssign ? "<<<-" : ">><-";
|
|
141551
|
+
const { line, column } = ParserUtils_default.getPosition(target);
|
|
141552
|
+
this.analyzer.addError(line, column, operator);
|
|
141553
|
+
}
|
|
141554
|
+
};
|
|
141555
|
+
/**
|
|
141556
|
+
* Resolve the final type of an assignment target, handling member chains.
|
|
141557
|
+
* Returns true if the final target is a signed type.
|
|
141558
|
+
*
|
|
141559
|
+
* Examples:
|
|
141560
|
+
* - "x" with no postfix ops → check if x is signed
|
|
141561
|
+
* - "s" with postfixOps [".x"] → check if s.x field is signed
|
|
141562
|
+
* - "arr" with postfixOps ["[0]", ".field"] → check if field is signed
|
|
141563
|
+
*/
|
|
141564
|
+
isSignedTarget(baseName, postfixOps) {
|
|
141565
|
+
if (postfixOps.length === 0) {
|
|
141566
|
+
return this.signedVars.has(baseName);
|
|
141567
|
+
}
|
|
141568
|
+
let currentType = this.varTypes.get(baseName);
|
|
141569
|
+
if (!currentType) {
|
|
141570
|
+
return false;
|
|
141571
|
+
}
|
|
141572
|
+
for (const op of postfixOps) {
|
|
141573
|
+
const memberIdent = op.IDENTIFIER();
|
|
141574
|
+
if (memberIdent) {
|
|
141575
|
+
const fieldName = memberIdent.getText();
|
|
141576
|
+
const fieldType = CodeGenState.getStructFieldType(
|
|
141577
|
+
currentType,
|
|
141578
|
+
fieldName
|
|
141579
|
+
);
|
|
141580
|
+
if (!fieldType) {
|
|
141581
|
+
return false;
|
|
141582
|
+
}
|
|
141583
|
+
currentType = fieldType;
|
|
141584
|
+
} else {
|
|
141585
|
+
const bracketIndex = currentType.indexOf("[");
|
|
141586
|
+
if (bracketIndex !== -1) {
|
|
141587
|
+
currentType = currentType.substring(0, bracketIndex);
|
|
141588
|
+
}
|
|
141589
|
+
}
|
|
141590
|
+
}
|
|
141591
|
+
return TypeConstants_default.SIGNED_TYPES.includes(currentType);
|
|
141592
|
+
}
|
|
140694
141593
|
/**
|
|
140695
141594
|
* Check if an additive expression contains a signed type operand
|
|
140696
141595
|
*/
|
|
@@ -140758,7 +141657,8 @@ var SignedShiftAnalyzer = class {
|
|
|
140758
141657
|
const collector = new SignedVariableCollector();
|
|
140759
141658
|
ParseTreeWalker9.DEFAULT.walk(collector, tree);
|
|
140760
141659
|
const signedVars = collector.getSignedVars();
|
|
140761
|
-
const
|
|
141660
|
+
const varTypes = collector.getVarTypes();
|
|
141661
|
+
const listener = new SignedShiftListener(this, signedVars, varTypes);
|
|
140762
141662
|
ParseTreeWalker9.DEFAULT.walk(listener, tree);
|
|
140763
141663
|
return this.errors;
|
|
140764
141664
|
}
|
|
@@ -142466,7 +143366,12 @@ var Transpiler = class {
|
|
|
142466
143366
|
this.state.getAllHeaderDirectives(),
|
|
142467
143367
|
CodeGenState.symbolTable
|
|
142468
143368
|
);
|
|
142469
|
-
const
|
|
143369
|
+
const callbackTypesForHeader = this._buildCallbackTypesForHeader();
|
|
143370
|
+
const typeInputWithSymbolTable = typeInput ? {
|
|
143371
|
+
...typeInput,
|
|
143372
|
+
symbolTable: CodeGenState.symbolTable,
|
|
143373
|
+
callbackTypes: callbackTypesForHeader
|
|
143374
|
+
} : void 0;
|
|
142470
143375
|
const unmodifiedParams = this.codeGenerator.getFunctionUnmodifiedParams();
|
|
142471
143376
|
const headerSymbols = this.convertToHeaderSymbols(
|
|
142472
143377
|
exportedSymbols,
|
|
@@ -142488,6 +143393,32 @@ var Transpiler = class {
|
|
|
142488
143393
|
basename6(sourcePath)
|
|
142489
143394
|
);
|
|
142490
143395
|
}
|
|
143396
|
+
/**
|
|
143397
|
+
* ADR-029: Build callback types for header generation.
|
|
143398
|
+
* Only includes callbacks that are actually used as struct field types.
|
|
143399
|
+
* Converts CodeGenState.callbackTypes to the format expected by IHeaderTypeInput.
|
|
143400
|
+
*/
|
|
143401
|
+
_buildCallbackTypesForHeader() {
|
|
143402
|
+
const result = /* @__PURE__ */ new Map();
|
|
143403
|
+
const usedCallbackTypes = /* @__PURE__ */ new Set();
|
|
143404
|
+
for (const [, funcName] of CodeGenState.callbackFieldTypes) {
|
|
143405
|
+
usedCallbackTypes.add(funcName);
|
|
143406
|
+
}
|
|
143407
|
+
for (const funcName of usedCallbackTypes) {
|
|
143408
|
+
const cbInfo = CodeGenState.callbackTypes.get(funcName);
|
|
143409
|
+
if (cbInfo) {
|
|
143410
|
+
result.set(funcName, {
|
|
143411
|
+
typedefName: cbInfo.typedefName,
|
|
143412
|
+
returnType: cbInfo.returnType,
|
|
143413
|
+
parameters: cbInfo.parameters.map((p) => ({
|
|
143414
|
+
type: p.type,
|
|
143415
|
+
isStruct: p.isStruct
|
|
143416
|
+
}))
|
|
143417
|
+
});
|
|
143418
|
+
}
|
|
143419
|
+
}
|
|
143420
|
+
return result;
|
|
143421
|
+
}
|
|
142491
143422
|
/**
|
|
142492
143423
|
* Collect external enum sources from included C-Next files.
|
|
142493
143424
|
*/
|
|
@@ -142534,25 +143465,27 @@ var Transpiler = class {
|
|
|
142534
143465
|
);
|
|
142535
143466
|
const callbackTypedefType = typedefName ? CodeGenState.getTypedefType(typedefName) : void 0;
|
|
142536
143467
|
if (callbackTypedefType) {
|
|
142537
|
-
const
|
|
143468
|
+
const updatedParams2 = TypedefParamParser_default.resolveCallbackParams(
|
|
142538
143469
|
headerSymbol.parameters,
|
|
142539
143470
|
callbackTypedefType
|
|
142540
143471
|
);
|
|
142541
|
-
return { ...headerSymbol, parameters:
|
|
143472
|
+
return { ...headerSymbol, parameters: updatedParams2 };
|
|
142542
143473
|
}
|
|
142543
143474
|
const unmodified = unmodifiedParams.get(headerSymbol.name);
|
|
142544
|
-
|
|
142545
|
-
const
|
|
142546
|
-
|
|
142547
|
-
|
|
142548
|
-
|
|
142549
|
-
|
|
142550
|
-
|
|
142551
|
-
|
|
142552
|
-
|
|
142553
|
-
|
|
142554
|
-
|
|
142555
|
-
|
|
143475
|
+
const updatedParams = headerSymbol.parameters.map((param) => {
|
|
143476
|
+
const isOpaque = CodeGenState.isOpaqueType(param.type ?? "");
|
|
143477
|
+
const isPointerParam = !param.isConst && !param.isArray && param.type !== "f32" && param.type !== "f64" && param.type !== "ISR" && !knownEnums.has(param.type ?? "");
|
|
143478
|
+
const shouldAutoConst = unmodified && isPointerParam && unmodified.has(param.name);
|
|
143479
|
+
if (shouldAutoConst || isOpaque) {
|
|
143480
|
+
return {
|
|
143481
|
+
...param,
|
|
143482
|
+
isAutoConst: shouldAutoConst || void 0,
|
|
143483
|
+
isOpaqueHandle: isOpaque || void 0
|
|
143484
|
+
};
|
|
143485
|
+
}
|
|
143486
|
+
return param;
|
|
143487
|
+
});
|
|
143488
|
+
return { ...headerSymbol, parameters: updatedParams };
|
|
142556
143489
|
});
|
|
142557
143490
|
}
|
|
142558
143491
|
// ===========================================================================
|