c-next 0.1.69 → 0.1.70
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/package.json +1 -1
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -204
- package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +693 -0
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +86 -5
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
- package/src/transpiler/output/codegen/CodeGenerator.ts +35 -607
- package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
- package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/TypeValidator.ts +5 -5
- package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +3 -3
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +11 -11
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +23 -17
- package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +2 -2
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +3 -3
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +3 -3
- package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
- package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +23 -25
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +20 -36
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +18 -18
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +42 -32
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +21 -4
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
- package/src/transpiler/state/CodeGenState.ts +122 -4
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +269 -1
- /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
- /package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/TransitiveModificationPropagator.test.ts +0 -0
package/package.json
CHANGED
|
@@ -11,7 +11,6 @@ import { ParseTreeWalker } from "antlr4ng";
|
|
|
11
11
|
import { CNextListener } from "../parser/grammar/CNextListener";
|
|
12
12
|
import * as Parser from "../parser/grammar/CNextParser";
|
|
13
13
|
import SymbolTable from "../symbols/SymbolTable";
|
|
14
|
-
import ESourceLanguage from "../../../utils/types/ESourceLanguage";
|
|
15
14
|
import ESymbolKind from "../../../utils/types/ESymbolKind";
|
|
16
15
|
import IFunctionCallError from "./types/IFunctionCallError";
|
|
17
16
|
import ParserUtils from "../../../utils/ParserUtils";
|
|
@@ -26,195 +25,178 @@ const CNEXT_BUILTINS: Set<string> = new Set([
|
|
|
26
25
|
]);
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
|
-
* Standard library functions
|
|
30
|
-
*
|
|
28
|
+
* Standard library functions mapped to their header files.
|
|
29
|
+
* Flat structure: function name → header file.
|
|
30
|
+
* These are considered "external" and don't need to be defined in C-Next.
|
|
31
31
|
*/
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
new Set([
|
|
183
|
-
"time",
|
|
184
|
-
"clock",
|
|
185
|
-
"difftime",
|
|
186
|
-
"mktime",
|
|
187
|
-
"strftime",
|
|
188
|
-
"localtime",
|
|
189
|
-
"gmtime",
|
|
190
|
-
"asctime",
|
|
191
|
-
"ctime",
|
|
192
|
-
]),
|
|
193
|
-
],
|
|
194
|
-
["assert.h", new Set(["assert"])],
|
|
32
|
+
const STDLIB_FUNCTION_HEADERS: Record<string, string> = {
|
|
33
|
+
// stdio.h
|
|
34
|
+
printf: "stdio.h",
|
|
35
|
+
fprintf: "stdio.h",
|
|
36
|
+
sprintf: "stdio.h",
|
|
37
|
+
snprintf: "stdio.h",
|
|
38
|
+
scanf: "stdio.h",
|
|
39
|
+
fscanf: "stdio.h",
|
|
40
|
+
sscanf: "stdio.h",
|
|
41
|
+
fopen: "stdio.h",
|
|
42
|
+
fclose: "stdio.h",
|
|
43
|
+
fread: "stdio.h",
|
|
44
|
+
fwrite: "stdio.h",
|
|
45
|
+
fgets: "stdio.h",
|
|
46
|
+
fputs: "stdio.h",
|
|
47
|
+
fgetc: "stdio.h",
|
|
48
|
+
fputc: "stdio.h",
|
|
49
|
+
puts: "stdio.h",
|
|
50
|
+
putchar: "stdio.h",
|
|
51
|
+
getchar: "stdio.h",
|
|
52
|
+
gets: "stdio.h",
|
|
53
|
+
perror: "stdio.h",
|
|
54
|
+
fflush: "stdio.h",
|
|
55
|
+
fseek: "stdio.h",
|
|
56
|
+
ftell: "stdio.h",
|
|
57
|
+
rewind: "stdio.h",
|
|
58
|
+
feof: "stdio.h",
|
|
59
|
+
ferror: "stdio.h",
|
|
60
|
+
clearerr: "stdio.h",
|
|
61
|
+
remove: "stdio.h",
|
|
62
|
+
rename: "stdio.h",
|
|
63
|
+
tmpfile: "stdio.h",
|
|
64
|
+
tmpnam: "stdio.h",
|
|
65
|
+
setbuf: "stdio.h",
|
|
66
|
+
setvbuf: "stdio.h",
|
|
67
|
+
// stdlib.h
|
|
68
|
+
malloc: "stdlib.h",
|
|
69
|
+
calloc: "stdlib.h",
|
|
70
|
+
realloc: "stdlib.h",
|
|
71
|
+
free: "stdlib.h",
|
|
72
|
+
atoi: "stdlib.h",
|
|
73
|
+
atof: "stdlib.h",
|
|
74
|
+
atol: "stdlib.h",
|
|
75
|
+
atoll: "stdlib.h",
|
|
76
|
+
strtol: "stdlib.h",
|
|
77
|
+
strtoul: "stdlib.h",
|
|
78
|
+
strtoll: "stdlib.h",
|
|
79
|
+
strtoull: "stdlib.h",
|
|
80
|
+
strtof: "stdlib.h",
|
|
81
|
+
strtod: "stdlib.h",
|
|
82
|
+
strtold: "stdlib.h",
|
|
83
|
+
rand: "stdlib.h",
|
|
84
|
+
srand: "stdlib.h",
|
|
85
|
+
exit: "stdlib.h",
|
|
86
|
+
abort: "stdlib.h",
|
|
87
|
+
atexit: "stdlib.h",
|
|
88
|
+
system: "stdlib.h",
|
|
89
|
+
getenv: "stdlib.h",
|
|
90
|
+
abs: "stdlib.h",
|
|
91
|
+
labs: "stdlib.h",
|
|
92
|
+
llabs: "stdlib.h",
|
|
93
|
+
div: "stdlib.h",
|
|
94
|
+
ldiv: "stdlib.h",
|
|
95
|
+
lldiv: "stdlib.h",
|
|
96
|
+
qsort: "stdlib.h",
|
|
97
|
+
bsearch: "stdlib.h",
|
|
98
|
+
// string.h
|
|
99
|
+
strlen: "string.h",
|
|
100
|
+
strcpy: "string.h",
|
|
101
|
+
strncpy: "string.h",
|
|
102
|
+
strcat: "string.h",
|
|
103
|
+
strncat: "string.h",
|
|
104
|
+
strcmp: "string.h",
|
|
105
|
+
strncmp: "string.h",
|
|
106
|
+
strchr: "string.h",
|
|
107
|
+
strrchr: "string.h",
|
|
108
|
+
strstr: "string.h",
|
|
109
|
+
strtok: "string.h",
|
|
110
|
+
memcpy: "string.h",
|
|
111
|
+
memmove: "string.h",
|
|
112
|
+
memset: "string.h",
|
|
113
|
+
memcmp: "string.h",
|
|
114
|
+
memchr: "string.h",
|
|
115
|
+
// math.h
|
|
116
|
+
sin: "math.h",
|
|
117
|
+
cos: "math.h",
|
|
118
|
+
tan: "math.h",
|
|
119
|
+
asin: "math.h",
|
|
120
|
+
acos: "math.h",
|
|
121
|
+
atan: "math.h",
|
|
122
|
+
atan2: "math.h",
|
|
123
|
+
sinh: "math.h",
|
|
124
|
+
cosh: "math.h",
|
|
125
|
+
tanh: "math.h",
|
|
126
|
+
exp: "math.h",
|
|
127
|
+
log: "math.h",
|
|
128
|
+
log10: "math.h",
|
|
129
|
+
log2: "math.h",
|
|
130
|
+
pow: "math.h",
|
|
131
|
+
sqrt: "math.h",
|
|
132
|
+
cbrt: "math.h",
|
|
133
|
+
ceil: "math.h",
|
|
134
|
+
floor: "math.h",
|
|
135
|
+
round: "math.h",
|
|
136
|
+
trunc: "math.h",
|
|
137
|
+
fabs: "math.h",
|
|
138
|
+
fmod: "math.h",
|
|
139
|
+
remainder: "math.h",
|
|
140
|
+
fmax: "math.h",
|
|
141
|
+
fmin: "math.h",
|
|
142
|
+
hypot: "math.h",
|
|
143
|
+
ldexp: "math.h",
|
|
144
|
+
frexp: "math.h",
|
|
145
|
+
modf: "math.h",
|
|
146
|
+
// C99 classification macros (also functions in C++)
|
|
147
|
+
isnan: "math.h",
|
|
148
|
+
isinf: "math.h",
|
|
149
|
+
isfinite: "math.h",
|
|
150
|
+
isnormal: "math.h",
|
|
151
|
+
signbit: "math.h",
|
|
152
|
+
fpclassify: "math.h",
|
|
153
|
+
nan: "math.h",
|
|
154
|
+
nanf: "math.h",
|
|
155
|
+
nanl: "math.h",
|
|
156
|
+
// ctype.h
|
|
157
|
+
isalnum: "ctype.h",
|
|
158
|
+
isalpha: "ctype.h",
|
|
159
|
+
isdigit: "ctype.h",
|
|
160
|
+
isxdigit: "ctype.h",
|
|
161
|
+
islower: "ctype.h",
|
|
162
|
+
isupper: "ctype.h",
|
|
163
|
+
isspace: "ctype.h",
|
|
164
|
+
ispunct: "ctype.h",
|
|
165
|
+
isprint: "ctype.h",
|
|
166
|
+
isgraph: "ctype.h",
|
|
167
|
+
iscntrl: "ctype.h",
|
|
168
|
+
tolower: "ctype.h",
|
|
169
|
+
toupper: "ctype.h",
|
|
170
|
+
// time.h
|
|
171
|
+
time: "time.h",
|
|
172
|
+
clock: "time.h",
|
|
173
|
+
difftime: "time.h",
|
|
174
|
+
mktime: "time.h",
|
|
175
|
+
strftime: "time.h",
|
|
176
|
+
localtime: "time.h",
|
|
177
|
+
gmtime: "time.h",
|
|
178
|
+
asctime: "time.h",
|
|
179
|
+
ctime: "time.h",
|
|
180
|
+
// assert.h
|
|
181
|
+
assert: "assert.h",
|
|
195
182
|
// Arduino framework
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
"Wire",
|
|
214
|
-
"SPI",
|
|
215
|
-
]),
|
|
216
|
-
],
|
|
217
|
-
]);
|
|
183
|
+
pinMode: "Arduino.h",
|
|
184
|
+
digitalWrite: "Arduino.h",
|
|
185
|
+
digitalRead: "Arduino.h",
|
|
186
|
+
analogRead: "Arduino.h",
|
|
187
|
+
analogWrite: "Arduino.h",
|
|
188
|
+
delay: "Arduino.h",
|
|
189
|
+
delayMicroseconds: "Arduino.h",
|
|
190
|
+
millis: "Arduino.h",
|
|
191
|
+
micros: "Arduino.h",
|
|
192
|
+
attachInterrupt: "Arduino.h",
|
|
193
|
+
detachInterrupt: "Arduino.h",
|
|
194
|
+
noInterrupts: "Arduino.h",
|
|
195
|
+
interrupts: "Arduino.h",
|
|
196
|
+
Serial: "Arduino.h",
|
|
197
|
+
Wire: "Arduino.h",
|
|
198
|
+
SPI: "Arduino.h",
|
|
199
|
+
};
|
|
218
200
|
|
|
219
201
|
/**
|
|
220
202
|
* Listener that walks the parse tree and checks function calls
|
|
@@ -424,6 +406,9 @@ class FunctionCallAnalyzer {
|
|
|
424
406
|
/** Functions that have been defined (in order of appearance) */
|
|
425
407
|
private definedFunctions: Set<string> = new Set();
|
|
426
408
|
|
|
409
|
+
/** All functions that will be defined in this file (for distinguishing local vs cross-file) */
|
|
410
|
+
private allLocalFunctions: Set<string> = new Set();
|
|
411
|
+
|
|
427
412
|
/** Known scopes (for Scope.member -> Scope_member resolution) */
|
|
428
413
|
private knownScopes: Set<string> = new Set();
|
|
429
414
|
|
|
@@ -454,6 +439,7 @@ class FunctionCallAnalyzer {
|
|
|
454
439
|
): IFunctionCallError[] {
|
|
455
440
|
this.errors = [];
|
|
456
441
|
this.definedFunctions = new Set();
|
|
442
|
+
this.allLocalFunctions = new Set();
|
|
457
443
|
this.knownScopes = new Set();
|
|
458
444
|
this.includedHeaders = new Set();
|
|
459
445
|
this.symbolTable = symbolTable ?? null;
|
|
@@ -461,10 +447,11 @@ class FunctionCallAnalyzer {
|
|
|
461
447
|
this.callableVariables = new Set();
|
|
462
448
|
this.callbackTypes = new Set();
|
|
463
449
|
|
|
464
|
-
// First pass: collect scope names, includes, and
|
|
450
|
+
// First pass: collect scope names, includes, callback types, and all local functions
|
|
465
451
|
this.collectScopes(tree);
|
|
466
452
|
this.collectIncludes(tree);
|
|
467
453
|
this.collectCallbackTypes(tree);
|
|
454
|
+
this.collectAllLocalFunctions(tree);
|
|
468
455
|
|
|
469
456
|
// Second pass: walk tree in order, tracking definitions and checking calls
|
|
470
457
|
const listener = new FunctionCallListener(this);
|
|
@@ -503,13 +490,17 @@ class FunctionCallAnalyzer {
|
|
|
503
490
|
* Check if a function is from an included standard library header
|
|
504
491
|
*/
|
|
505
492
|
private isStdlibFunction(name: string): boolean {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
493
|
+
const header = STDLIB_FUNCTION_HEADERS[name];
|
|
494
|
+
return header !== undefined && this.includedHeaders.has(header);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Issue #787: Find which header a stdlib function belongs to (if any).
|
|
499
|
+
* Returns the header name if found, or null if not a known stdlib function.
|
|
500
|
+
* Checks ALL stdlib functions, not just from included headers.
|
|
501
|
+
*/
|
|
502
|
+
private findStdlibHeader(name: string): string | null {
|
|
503
|
+
return STDLIB_FUNCTION_HEADERS[name] ?? null;
|
|
513
504
|
}
|
|
514
505
|
|
|
515
506
|
/**
|
|
@@ -525,6 +516,35 @@ class FunctionCallAnalyzer {
|
|
|
525
516
|
}
|
|
526
517
|
}
|
|
527
518
|
|
|
519
|
+
/**
|
|
520
|
+
* Issue #786: Pre-collect all function names defined in this file.
|
|
521
|
+
* Used to distinguish between local functions (subject to define-before-use)
|
|
522
|
+
* and cross-file functions from includes (allowed without local definition).
|
|
523
|
+
*/
|
|
524
|
+
private collectAllLocalFunctions(tree: Parser.ProgramContext): void {
|
|
525
|
+
for (const decl of tree.declaration()) {
|
|
526
|
+
// Standalone functions
|
|
527
|
+
if (decl.functionDeclaration()) {
|
|
528
|
+
const name = decl.functionDeclaration()!.IDENTIFIER().getText();
|
|
529
|
+
this.allLocalFunctions.add(name);
|
|
530
|
+
}
|
|
531
|
+
// Scope member functions
|
|
532
|
+
if (decl.scopeDeclaration()) {
|
|
533
|
+
const scopeDecl = decl.scopeDeclaration()!;
|
|
534
|
+
const scopeName = scopeDecl.IDENTIFIER().getText();
|
|
535
|
+
for (const member of scopeDecl.scopeMember()) {
|
|
536
|
+
if (member.functionDeclaration()) {
|
|
537
|
+
const funcName = member
|
|
538
|
+
.functionDeclaration()!
|
|
539
|
+
.IDENTIFIER()
|
|
540
|
+
.getText();
|
|
541
|
+
this.allLocalFunctions.add(`${scopeName}_${funcName}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
528
548
|
/**
|
|
529
549
|
* ADR-029: Check if a type name is a callback type (function-as-type)
|
|
530
550
|
*/
|
|
@@ -627,31 +647,47 @@ class FunctionCallAnalyzer {
|
|
|
627
647
|
}
|
|
628
648
|
}
|
|
629
649
|
|
|
630
|
-
// Not defined - report error
|
|
650
|
+
// Not defined - report error with optional hint
|
|
651
|
+
const header = this.findStdlibHeader(name);
|
|
652
|
+
let message = `function '${name}' called before definition`;
|
|
653
|
+
if (header) {
|
|
654
|
+
message += `; hint: '${name}' is available from ${header} — try global.${name}()`;
|
|
655
|
+
}
|
|
656
|
+
|
|
631
657
|
this.errors.push({
|
|
632
658
|
code: "E0422",
|
|
633
659
|
functionName: name,
|
|
634
660
|
line,
|
|
635
661
|
column,
|
|
636
|
-
message
|
|
662
|
+
message,
|
|
637
663
|
});
|
|
638
664
|
}
|
|
639
665
|
|
|
640
666
|
/**
|
|
641
|
-
* Check if a function is defined externally (
|
|
667
|
+
* Check if a function is defined externally (from included files)
|
|
668
|
+
* This includes C/C++ headers AND C-Next includes.
|
|
669
|
+
*
|
|
670
|
+
* Issue #786: Only considers a function "external" if it's NOT defined
|
|
671
|
+
* in the current file. Functions defined locally are subject to
|
|
672
|
+
* define-before-use checking, even if they exist in the SymbolTable.
|
|
642
673
|
*/
|
|
643
674
|
private isExternalFunction(name: string): boolean {
|
|
675
|
+
// If the function is defined in this file, it's not external
|
|
676
|
+
// (even if it's also in the SymbolTable from symbol collection)
|
|
677
|
+
if (this.allLocalFunctions.has(name)) {
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
680
|
+
|
|
644
681
|
if (!this.symbolTable) {
|
|
645
682
|
return false;
|
|
646
683
|
}
|
|
647
684
|
|
|
648
685
|
const symbols = this.symbolTable.getOverloads(name);
|
|
649
686
|
for (const sym of symbols) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
) {
|
|
687
|
+
// Accept functions from any source language:
|
|
688
|
+
// - C/C++ functions from header includes
|
|
689
|
+
// - C-Next functions from .cnx file includes
|
|
690
|
+
if (sym.kind === ESymbolKind.Function) {
|
|
655
691
|
return true;
|
|
656
692
|
}
|
|
657
693
|
}
|