c-next 0.1.64 → 0.1.66
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/grammar/CNext.g4 +9 -2
- package/package.json +5 -1
- package/src/transpiler/logic/parser/grammar/CNext.interp +2 -1
- package/src/transpiler/logic/parser/grammar/CNextListener.ts +11 -0
- package/src/transpiler/logic/parser/grammar/CNextParser.ts +992 -870
- package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +7 -0
- package/src/transpiler/logic/symbols/cnext/__tests__/FunctionCollector.test.ts +6 -6
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +179 -0
- package/src/transpiler/logic/symbols/cnext/__tests__/VariableCollector.test.ts +55 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +76 -8
- package/src/transpiler/logic/symbols/cnext/collectors/FunctionCollector.ts +9 -10
- package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +7 -1
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +33 -14
- package/src/transpiler/output/codegen/CodeGenerator.ts +243 -166
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1086 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +254 -22
- package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +17 -9
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +5 -3
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +12 -7
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +624 -12
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +4 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
- package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
- package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
|
@@ -2071,4 +2071,823 @@ describe("PostfixExpressionGenerator", () => {
|
|
|
2071
2071
|
expect(result.code).toBe("matrix[0][1]");
|
|
2072
2072
|
});
|
|
2073
2073
|
});
|
|
2074
|
+
|
|
2075
|
+
// ========================================================================
|
|
2076
|
+
// ADR-058: Explicit Length Properties
|
|
2077
|
+
// ========================================================================
|
|
2078
|
+
|
|
2079
|
+
describe(".bit_length property (ADR-058)", () => {
|
|
2080
|
+
it("returns bit width for integer type", () => {
|
|
2081
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2082
|
+
[
|
|
2083
|
+
"val",
|
|
2084
|
+
{
|
|
2085
|
+
baseType: "u32",
|
|
2086
|
+
bitWidth: 32,
|
|
2087
|
+
isArray: false,
|
|
2088
|
+
isConst: false,
|
|
2089
|
+
},
|
|
2090
|
+
],
|
|
2091
|
+
]);
|
|
2092
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2093
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2094
|
+
]);
|
|
2095
|
+
const input = createMockInput({ typeRegistry });
|
|
2096
|
+
const state = createMockState();
|
|
2097
|
+
const orchestrator = createMockOrchestrator({
|
|
2098
|
+
generatePrimaryExpr: () => "val",
|
|
2099
|
+
});
|
|
2100
|
+
|
|
2101
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2102
|
+
expect(result.code).toBe("32");
|
|
2103
|
+
});
|
|
2104
|
+
|
|
2105
|
+
it("returns 32 for enum type", () => {
|
|
2106
|
+
const symbols = createMockSymbols({
|
|
2107
|
+
knownEnums: new Set(["Color"]),
|
|
2108
|
+
});
|
|
2109
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2110
|
+
[
|
|
2111
|
+
"color",
|
|
2112
|
+
{
|
|
2113
|
+
baseType: "Color",
|
|
2114
|
+
bitWidth: 32,
|
|
2115
|
+
isArray: false,
|
|
2116
|
+
isConst: false,
|
|
2117
|
+
isEnum: true,
|
|
2118
|
+
},
|
|
2119
|
+
],
|
|
2120
|
+
]);
|
|
2121
|
+
const ctx = createMockPostfixExpressionContext("color", [
|
|
2122
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2123
|
+
]);
|
|
2124
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2125
|
+
const state = createMockState();
|
|
2126
|
+
const orchestrator = createMockOrchestrator({
|
|
2127
|
+
generatePrimaryExpr: () => "color",
|
|
2128
|
+
});
|
|
2129
|
+
|
|
2130
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2131
|
+
expect(result.code).toBe("32");
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2134
|
+
it("returns total bits for array type", () => {
|
|
2135
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2136
|
+
[
|
|
2137
|
+
"arr",
|
|
2138
|
+
{
|
|
2139
|
+
baseType: "u32",
|
|
2140
|
+
bitWidth: 32,
|
|
2141
|
+
isArray: true,
|
|
2142
|
+
arrayDimensions: [16],
|
|
2143
|
+
isConst: false,
|
|
2144
|
+
},
|
|
2145
|
+
],
|
|
2146
|
+
]);
|
|
2147
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2148
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2149
|
+
]);
|
|
2150
|
+
const input = createMockInput({ typeRegistry });
|
|
2151
|
+
const state = createMockState();
|
|
2152
|
+
const orchestrator = createMockOrchestrator({
|
|
2153
|
+
generatePrimaryExpr: () => "arr",
|
|
2154
|
+
});
|
|
2155
|
+
|
|
2156
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2157
|
+
expect(result.code).toBe("512"); // 16 * 32 = 512
|
|
2158
|
+
});
|
|
2159
|
+
|
|
2160
|
+
it("returns buffer bits for string type", () => {
|
|
2161
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2162
|
+
[
|
|
2163
|
+
"str",
|
|
2164
|
+
{
|
|
2165
|
+
baseType: "char",
|
|
2166
|
+
bitWidth: 8,
|
|
2167
|
+
isArray: false,
|
|
2168
|
+
isConst: false,
|
|
2169
|
+
isString: true,
|
|
2170
|
+
stringCapacity: 64,
|
|
2171
|
+
},
|
|
2172
|
+
],
|
|
2173
|
+
]);
|
|
2174
|
+
const ctx = createMockPostfixExpressionContext("str", [
|
|
2175
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2176
|
+
]);
|
|
2177
|
+
const input = createMockInput({ typeRegistry });
|
|
2178
|
+
const state = createMockState();
|
|
2179
|
+
const orchestrator = createMockOrchestrator({
|
|
2180
|
+
generatePrimaryExpr: () => "str",
|
|
2181
|
+
});
|
|
2182
|
+
|
|
2183
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2184
|
+
expect(result.code).toBe("520"); // (64 + 1) * 8 = 520
|
|
2185
|
+
});
|
|
2186
|
+
});
|
|
2187
|
+
|
|
2188
|
+
describe(".byte_length property (ADR-058)", () => {
|
|
2189
|
+
it("returns byte size for integer type", () => {
|
|
2190
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2191
|
+
[
|
|
2192
|
+
"val",
|
|
2193
|
+
{
|
|
2194
|
+
baseType: "u32",
|
|
2195
|
+
bitWidth: 32,
|
|
2196
|
+
isArray: false,
|
|
2197
|
+
isConst: false,
|
|
2198
|
+
},
|
|
2199
|
+
],
|
|
2200
|
+
]);
|
|
2201
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2202
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2203
|
+
]);
|
|
2204
|
+
const input = createMockInput({ typeRegistry });
|
|
2205
|
+
const state = createMockState();
|
|
2206
|
+
const orchestrator = createMockOrchestrator({
|
|
2207
|
+
generatePrimaryExpr: () => "val",
|
|
2208
|
+
});
|
|
2209
|
+
|
|
2210
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2211
|
+
expect(result.code).toBe("4"); // 32 / 8 = 4
|
|
2212
|
+
});
|
|
2213
|
+
|
|
2214
|
+
it("returns total bytes for array type", () => {
|
|
2215
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2216
|
+
[
|
|
2217
|
+
"arr",
|
|
2218
|
+
{
|
|
2219
|
+
baseType: "u32",
|
|
2220
|
+
bitWidth: 32,
|
|
2221
|
+
isArray: true,
|
|
2222
|
+
arrayDimensions: [16],
|
|
2223
|
+
isConst: false,
|
|
2224
|
+
},
|
|
2225
|
+
],
|
|
2226
|
+
]);
|
|
2227
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2228
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2229
|
+
]);
|
|
2230
|
+
const input = createMockInput({ typeRegistry });
|
|
2231
|
+
const state = createMockState();
|
|
2232
|
+
const orchestrator = createMockOrchestrator({
|
|
2233
|
+
generatePrimaryExpr: () => "arr",
|
|
2234
|
+
});
|
|
2235
|
+
|
|
2236
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2237
|
+
expect(result.code).toBe("64"); // 16 * 4 = 64
|
|
2238
|
+
});
|
|
2239
|
+
|
|
2240
|
+
it("returns buffer bytes for string type", () => {
|
|
2241
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2242
|
+
[
|
|
2243
|
+
"str",
|
|
2244
|
+
{
|
|
2245
|
+
baseType: "char",
|
|
2246
|
+
bitWidth: 8,
|
|
2247
|
+
isArray: false,
|
|
2248
|
+
isConst: false,
|
|
2249
|
+
isString: true,
|
|
2250
|
+
stringCapacity: 64,
|
|
2251
|
+
},
|
|
2252
|
+
],
|
|
2253
|
+
]);
|
|
2254
|
+
const ctx = createMockPostfixExpressionContext("str", [
|
|
2255
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2256
|
+
]);
|
|
2257
|
+
const input = createMockInput({ typeRegistry });
|
|
2258
|
+
const state = createMockState();
|
|
2259
|
+
const orchestrator = createMockOrchestrator({
|
|
2260
|
+
generatePrimaryExpr: () => "str",
|
|
2261
|
+
});
|
|
2262
|
+
|
|
2263
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2264
|
+
expect(result.code).toBe("65"); // 64 + 1 = 65
|
|
2265
|
+
});
|
|
2266
|
+
});
|
|
2267
|
+
|
|
2268
|
+
describe(".element_count property (ADR-058)", () => {
|
|
2269
|
+
it("returns element count for array type", () => {
|
|
2270
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2271
|
+
[
|
|
2272
|
+
"arr",
|
|
2273
|
+
{
|
|
2274
|
+
baseType: "u32",
|
|
2275
|
+
bitWidth: 32,
|
|
2276
|
+
isArray: true,
|
|
2277
|
+
arrayDimensions: [16],
|
|
2278
|
+
isConst: false,
|
|
2279
|
+
},
|
|
2280
|
+
],
|
|
2281
|
+
]);
|
|
2282
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2283
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2284
|
+
]);
|
|
2285
|
+
const input = createMockInput({ typeRegistry });
|
|
2286
|
+
const state = createMockState();
|
|
2287
|
+
const orchestrator = createMockOrchestrator({
|
|
2288
|
+
generatePrimaryExpr: () => "arr",
|
|
2289
|
+
});
|
|
2290
|
+
|
|
2291
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2292
|
+
expect(result.code).toBe("16");
|
|
2293
|
+
});
|
|
2294
|
+
|
|
2295
|
+
it("returns argc for main args", () => {
|
|
2296
|
+
const ctx = createMockPostfixExpressionContext("args", [
|
|
2297
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2298
|
+
]);
|
|
2299
|
+
const input = createMockInput();
|
|
2300
|
+
const state = createMockState({ mainArgsName: "args" });
|
|
2301
|
+
const orchestrator = createMockOrchestrator({
|
|
2302
|
+
generatePrimaryExpr: () => "args",
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2306
|
+
expect(result.code).toBe("argc");
|
|
2307
|
+
});
|
|
2308
|
+
|
|
2309
|
+
it("throws error for non-array type", () => {
|
|
2310
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2311
|
+
[
|
|
2312
|
+
"val",
|
|
2313
|
+
{
|
|
2314
|
+
baseType: "u32",
|
|
2315
|
+
bitWidth: 32,
|
|
2316
|
+
isArray: false,
|
|
2317
|
+
isConst: false,
|
|
2318
|
+
},
|
|
2319
|
+
],
|
|
2320
|
+
]);
|
|
2321
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2322
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2323
|
+
]);
|
|
2324
|
+
const input = createMockInput({ typeRegistry });
|
|
2325
|
+
const state = createMockState();
|
|
2326
|
+
const orchestrator = createMockOrchestrator({
|
|
2327
|
+
generatePrimaryExpr: () => "val",
|
|
2328
|
+
});
|
|
2329
|
+
|
|
2330
|
+
expect(() =>
|
|
2331
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2332
|
+
).toThrow(".element_count is only available on arrays");
|
|
2333
|
+
});
|
|
2334
|
+
});
|
|
2335
|
+
|
|
2336
|
+
describe(".char_count property (ADR-058)", () => {
|
|
2337
|
+
it("returns strlen for string type", () => {
|
|
2338
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2339
|
+
[
|
|
2340
|
+
"str",
|
|
2341
|
+
{
|
|
2342
|
+
baseType: "char",
|
|
2343
|
+
bitWidth: 8,
|
|
2344
|
+
isArray: false,
|
|
2345
|
+
isConst: false,
|
|
2346
|
+
isString: true,
|
|
2347
|
+
stringCapacity: 64,
|
|
2348
|
+
},
|
|
2349
|
+
],
|
|
2350
|
+
]);
|
|
2351
|
+
const ctx = createMockPostfixExpressionContext("str", [
|
|
2352
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2353
|
+
]);
|
|
2354
|
+
const input = createMockInput({ typeRegistry });
|
|
2355
|
+
const state = createMockState();
|
|
2356
|
+
const orchestrator = createMockOrchestrator({
|
|
2357
|
+
generatePrimaryExpr: () => "str",
|
|
2358
|
+
});
|
|
2359
|
+
|
|
2360
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2361
|
+
expect(result.code).toBe("strlen(str)");
|
|
2362
|
+
expect(result.effects).toContainEqual({
|
|
2363
|
+
type: "include",
|
|
2364
|
+
header: "string",
|
|
2365
|
+
});
|
|
2366
|
+
});
|
|
2367
|
+
|
|
2368
|
+
it("throws error for non-string type", () => {
|
|
2369
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2370
|
+
[
|
|
2371
|
+
"val",
|
|
2372
|
+
{
|
|
2373
|
+
baseType: "u32",
|
|
2374
|
+
bitWidth: 32,
|
|
2375
|
+
isArray: false,
|
|
2376
|
+
isConst: false,
|
|
2377
|
+
},
|
|
2378
|
+
],
|
|
2379
|
+
]);
|
|
2380
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2381
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2382
|
+
]);
|
|
2383
|
+
const input = createMockInput({ typeRegistry });
|
|
2384
|
+
const state = createMockState();
|
|
2385
|
+
const orchestrator = createMockOrchestrator({
|
|
2386
|
+
generatePrimaryExpr: () => "val",
|
|
2387
|
+
});
|
|
2388
|
+
|
|
2389
|
+
expect(() =>
|
|
2390
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2391
|
+
).toThrow(".char_count is only available on strings");
|
|
2392
|
+
});
|
|
2393
|
+
|
|
2394
|
+
it("throws error for args", () => {
|
|
2395
|
+
const ctx = createMockPostfixExpressionContext("args", [
|
|
2396
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2397
|
+
]);
|
|
2398
|
+
const input = createMockInput();
|
|
2399
|
+
const state = createMockState({ mainArgsName: "args" });
|
|
2400
|
+
const orchestrator = createMockOrchestrator({
|
|
2401
|
+
generatePrimaryExpr: () => "args",
|
|
2402
|
+
});
|
|
2403
|
+
|
|
2404
|
+
expect(() =>
|
|
2405
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2406
|
+
).toThrow(".char_count is only available on strings");
|
|
2407
|
+
});
|
|
2408
|
+
});
|
|
2409
|
+
|
|
2410
|
+
describe("explicit length edge cases (ADR-058)", () => {
|
|
2411
|
+
it("returns dynamic dimension comment for array with C macro size", () => {
|
|
2412
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2413
|
+
[
|
|
2414
|
+
"arr",
|
|
2415
|
+
{
|
|
2416
|
+
baseType: "u32",
|
|
2417
|
+
bitWidth: 32,
|
|
2418
|
+
isArray: true,
|
|
2419
|
+
arrayDimensions: ["BUFFER_SIZE" as unknown as number], // C macro
|
|
2420
|
+
isConst: false,
|
|
2421
|
+
},
|
|
2422
|
+
],
|
|
2423
|
+
]);
|
|
2424
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2425
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2426
|
+
]);
|
|
2427
|
+
const input = createMockInput({ typeRegistry });
|
|
2428
|
+
const state = createMockState();
|
|
2429
|
+
const orchestrator = createMockOrchestrator({
|
|
2430
|
+
generatePrimaryExpr: () => "arr",
|
|
2431
|
+
});
|
|
2432
|
+
|
|
2433
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2434
|
+
expect(result.code).toContain("dynamic dimension BUFFER_SIZE");
|
|
2435
|
+
});
|
|
2436
|
+
|
|
2437
|
+
it("returns C macro name for element_count with dynamic dimension", () => {
|
|
2438
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2439
|
+
[
|
|
2440
|
+
"arr",
|
|
2441
|
+
{
|
|
2442
|
+
baseType: "u32",
|
|
2443
|
+
bitWidth: 32,
|
|
2444
|
+
isArray: true,
|
|
2445
|
+
arrayDimensions: ["BUFFER_SIZE" as unknown as number], // C macro
|
|
2446
|
+
isConst: false,
|
|
2447
|
+
},
|
|
2448
|
+
],
|
|
2449
|
+
]);
|
|
2450
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2451
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2452
|
+
]);
|
|
2453
|
+
const input = createMockInput({ typeRegistry });
|
|
2454
|
+
const state = createMockState();
|
|
2455
|
+
const orchestrator = createMockOrchestrator({
|
|
2456
|
+
generatePrimaryExpr: () => "arr",
|
|
2457
|
+
});
|
|
2458
|
+
|
|
2459
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2460
|
+
expect(result.code).toBe("BUFFER_SIZE");
|
|
2461
|
+
});
|
|
2462
|
+
|
|
2463
|
+
it("throws error for bit_length on args", () => {
|
|
2464
|
+
const ctx = createMockPostfixExpressionContext("args", [
|
|
2465
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2466
|
+
]);
|
|
2467
|
+
const input = createMockInput();
|
|
2468
|
+
const state = createMockState({ mainArgsName: "args" });
|
|
2469
|
+
const orchestrator = createMockOrchestrator({
|
|
2470
|
+
generatePrimaryExpr: () => "args",
|
|
2471
|
+
});
|
|
2472
|
+
|
|
2473
|
+
expect(() =>
|
|
2474
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2475
|
+
).toThrow(".bit_length is not supported on 'args'");
|
|
2476
|
+
});
|
|
2477
|
+
|
|
2478
|
+
it("throws error for byte_length on args", () => {
|
|
2479
|
+
const ctx = createMockPostfixExpressionContext("args", [
|
|
2480
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2481
|
+
]);
|
|
2482
|
+
const input = createMockInput();
|
|
2483
|
+
const state = createMockState({ mainArgsName: "args" });
|
|
2484
|
+
const orchestrator = createMockOrchestrator({
|
|
2485
|
+
generatePrimaryExpr: () => "args",
|
|
2486
|
+
});
|
|
2487
|
+
|
|
2488
|
+
expect(() =>
|
|
2489
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2490
|
+
).toThrow(".byte_length is not supported on 'args'");
|
|
2491
|
+
});
|
|
2492
|
+
|
|
2493
|
+
it("throws error for unknown type bit_length", () => {
|
|
2494
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2495
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2496
|
+
]);
|
|
2497
|
+
const input = createMockInput({ typeRegistry: new Map() });
|
|
2498
|
+
const state = createMockState();
|
|
2499
|
+
const orchestrator = createMockOrchestrator({
|
|
2500
|
+
generatePrimaryExpr: () => "val",
|
|
2501
|
+
});
|
|
2502
|
+
|
|
2503
|
+
expect(() =>
|
|
2504
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2505
|
+
).toThrow("type not found in registry");
|
|
2506
|
+
});
|
|
2507
|
+
|
|
2508
|
+
it("throws error for unknown type byte_length", () => {
|
|
2509
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2510
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2511
|
+
]);
|
|
2512
|
+
const input = createMockInput({ typeRegistry: new Map() });
|
|
2513
|
+
const state = createMockState();
|
|
2514
|
+
const orchestrator = createMockOrchestrator({
|
|
2515
|
+
generatePrimaryExpr: () => "val",
|
|
2516
|
+
});
|
|
2517
|
+
|
|
2518
|
+
expect(() =>
|
|
2519
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2520
|
+
).toThrow("type not found in registry");
|
|
2521
|
+
});
|
|
2522
|
+
|
|
2523
|
+
it("throws error for unknown type element_count", () => {
|
|
2524
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2525
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2526
|
+
]);
|
|
2527
|
+
const input = createMockInput({ typeRegistry: new Map() });
|
|
2528
|
+
const state = createMockState();
|
|
2529
|
+
const orchestrator = createMockOrchestrator({
|
|
2530
|
+
generatePrimaryExpr: () => "val",
|
|
2531
|
+
});
|
|
2532
|
+
|
|
2533
|
+
expect(() =>
|
|
2534
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2535
|
+
).toThrow("type not found in registry");
|
|
2536
|
+
});
|
|
2537
|
+
|
|
2538
|
+
it("throws error for string without capacity", () => {
|
|
2539
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2540
|
+
[
|
|
2541
|
+
"str",
|
|
2542
|
+
{
|
|
2543
|
+
baseType: "char",
|
|
2544
|
+
bitWidth: 8,
|
|
2545
|
+
isArray: false,
|
|
2546
|
+
isConst: false,
|
|
2547
|
+
isString: true,
|
|
2548
|
+
// No stringCapacity set
|
|
2549
|
+
},
|
|
2550
|
+
],
|
|
2551
|
+
]);
|
|
2552
|
+
const ctx = createMockPostfixExpressionContext("str", [
|
|
2553
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2554
|
+
]);
|
|
2555
|
+
const input = createMockInput({ typeRegistry });
|
|
2556
|
+
const state = createMockState();
|
|
2557
|
+
const orchestrator = createMockOrchestrator({
|
|
2558
|
+
generatePrimaryExpr: () => "str",
|
|
2559
|
+
});
|
|
2560
|
+
|
|
2561
|
+
expect(() =>
|
|
2562
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2563
|
+
).toThrow("unknown capacity");
|
|
2564
|
+
});
|
|
2565
|
+
|
|
2566
|
+
it("handles struct field bit_length for string member", () => {
|
|
2567
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2568
|
+
[
|
|
2569
|
+
"obj",
|
|
2570
|
+
{
|
|
2571
|
+
baseType: "MyStruct",
|
|
2572
|
+
bitWidth: 0,
|
|
2573
|
+
isArray: false,
|
|
2574
|
+
isConst: false,
|
|
2575
|
+
},
|
|
2576
|
+
],
|
|
2577
|
+
]);
|
|
2578
|
+
const symbols = createMockSymbols({
|
|
2579
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2580
|
+
});
|
|
2581
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2582
|
+
createMockPostfixOp({ identifier: "name" }),
|
|
2583
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2584
|
+
]);
|
|
2585
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2586
|
+
const state = createMockState();
|
|
2587
|
+
const orchestrator = createMockOrchestrator({
|
|
2588
|
+
generatePrimaryExpr: () => "obj",
|
|
2589
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2590
|
+
getStructFieldInfo: () => ({
|
|
2591
|
+
type: "string<32>",
|
|
2592
|
+
}),
|
|
2593
|
+
});
|
|
2594
|
+
|
|
2595
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2596
|
+
expect(result.code).toBe("264"); // (32 + 1) * 8 = 264
|
|
2597
|
+
});
|
|
2598
|
+
|
|
2599
|
+
it("handles struct field byte_length", () => {
|
|
2600
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2601
|
+
[
|
|
2602
|
+
"obj",
|
|
2603
|
+
{
|
|
2604
|
+
baseType: "MyStruct",
|
|
2605
|
+
bitWidth: 0,
|
|
2606
|
+
isArray: false,
|
|
2607
|
+
isConst: false,
|
|
2608
|
+
},
|
|
2609
|
+
],
|
|
2610
|
+
]);
|
|
2611
|
+
const symbols = createMockSymbols({
|
|
2612
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2613
|
+
});
|
|
2614
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2615
|
+
createMockPostfixOp({ identifier: "value" }),
|
|
2616
|
+
createMockPostfixOp({ identifier: "byte_length" }),
|
|
2617
|
+
]);
|
|
2618
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2619
|
+
const state = createMockState();
|
|
2620
|
+
const orchestrator = createMockOrchestrator({
|
|
2621
|
+
generatePrimaryExpr: () => "obj",
|
|
2622
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2623
|
+
getStructFieldInfo: () => ({
|
|
2624
|
+
type: "u16",
|
|
2625
|
+
}),
|
|
2626
|
+
});
|
|
2627
|
+
|
|
2628
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2629
|
+
expect(result.code).toBe("2"); // 16 / 8 = 2
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2632
|
+
it("handles struct field element_count for array member", () => {
|
|
2633
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2634
|
+
[
|
|
2635
|
+
"obj",
|
|
2636
|
+
{
|
|
2637
|
+
baseType: "MyStruct",
|
|
2638
|
+
bitWidth: 0,
|
|
2639
|
+
isArray: false,
|
|
2640
|
+
isConst: false,
|
|
2641
|
+
},
|
|
2642
|
+
],
|
|
2643
|
+
]);
|
|
2644
|
+
const symbols = createMockSymbols({
|
|
2645
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2646
|
+
});
|
|
2647
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2648
|
+
createMockPostfixOp({ identifier: "data" }),
|
|
2649
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2650
|
+
]);
|
|
2651
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2652
|
+
const state = createMockState();
|
|
2653
|
+
const orchestrator = createMockOrchestrator({
|
|
2654
|
+
generatePrimaryExpr: () => "obj",
|
|
2655
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2656
|
+
getStructFieldInfo: () => ({
|
|
2657
|
+
type: "u8",
|
|
2658
|
+
dimensions: [64],
|
|
2659
|
+
}),
|
|
2660
|
+
});
|
|
2661
|
+
|
|
2662
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2663
|
+
expect(result.code).toBe("64");
|
|
2664
|
+
});
|
|
2665
|
+
|
|
2666
|
+
it("throws for struct field element_count on non-array member", () => {
|
|
2667
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2668
|
+
[
|
|
2669
|
+
"obj",
|
|
2670
|
+
{
|
|
2671
|
+
baseType: "MyStruct",
|
|
2672
|
+
bitWidth: 0,
|
|
2673
|
+
isArray: false,
|
|
2674
|
+
isConst: false,
|
|
2675
|
+
},
|
|
2676
|
+
],
|
|
2677
|
+
]);
|
|
2678
|
+
const symbols = createMockSymbols({
|
|
2679
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2680
|
+
});
|
|
2681
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2682
|
+
createMockPostfixOp({ identifier: "value" }),
|
|
2683
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2684
|
+
]);
|
|
2685
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2686
|
+
const state = createMockState();
|
|
2687
|
+
const orchestrator = createMockOrchestrator({
|
|
2688
|
+
generatePrimaryExpr: () => "obj",
|
|
2689
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2690
|
+
getStructFieldInfo: () => ({
|
|
2691
|
+
type: "u32",
|
|
2692
|
+
}),
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2695
|
+
expect(() =>
|
|
2696
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2697
|
+
).toThrow(".element_count is only available on arrays");
|
|
2698
|
+
});
|
|
2699
|
+
|
|
2700
|
+
it("handles struct field char_count for string member", () => {
|
|
2701
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2702
|
+
[
|
|
2703
|
+
"obj",
|
|
2704
|
+
{
|
|
2705
|
+
baseType: "MyStruct",
|
|
2706
|
+
bitWidth: 0,
|
|
2707
|
+
isArray: false,
|
|
2708
|
+
isConst: false,
|
|
2709
|
+
},
|
|
2710
|
+
],
|
|
2711
|
+
]);
|
|
2712
|
+
const symbols = createMockSymbols({
|
|
2713
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2714
|
+
});
|
|
2715
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2716
|
+
createMockPostfixOp({ identifier: "name" }),
|
|
2717
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2718
|
+
]);
|
|
2719
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2720
|
+
const state = createMockState();
|
|
2721
|
+
const orchestrator = createMockOrchestrator({
|
|
2722
|
+
generatePrimaryExpr: () => "obj",
|
|
2723
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2724
|
+
getStructFieldInfo: () => ({
|
|
2725
|
+
type: "string<32>",
|
|
2726
|
+
}),
|
|
2727
|
+
});
|
|
2728
|
+
|
|
2729
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2730
|
+
expect(result.code).toBe("strlen(obj.name)");
|
|
2731
|
+
});
|
|
2732
|
+
|
|
2733
|
+
it("throws for struct field char_count on non-string member", () => {
|
|
2734
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2735
|
+
[
|
|
2736
|
+
"obj",
|
|
2737
|
+
{
|
|
2738
|
+
baseType: "MyStruct",
|
|
2739
|
+
bitWidth: 0,
|
|
2740
|
+
isArray: false,
|
|
2741
|
+
isConst: false,
|
|
2742
|
+
},
|
|
2743
|
+
],
|
|
2744
|
+
]);
|
|
2745
|
+
const symbols = createMockSymbols({
|
|
2746
|
+
knownStructs: new Set(["MyStruct"]),
|
|
2747
|
+
});
|
|
2748
|
+
const ctx = createMockPostfixExpressionContext("obj", [
|
|
2749
|
+
createMockPostfixOp({ identifier: "value" }),
|
|
2750
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2751
|
+
]);
|
|
2752
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2753
|
+
const state = createMockState();
|
|
2754
|
+
const orchestrator = createMockOrchestrator({
|
|
2755
|
+
generatePrimaryExpr: () => "obj",
|
|
2756
|
+
isKnownStruct: (name) => name === "MyStruct",
|
|
2757
|
+
getStructFieldInfo: () => ({
|
|
2758
|
+
type: "u32",
|
|
2759
|
+
}),
|
|
2760
|
+
});
|
|
2761
|
+
|
|
2762
|
+
expect(() =>
|
|
2763
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2764
|
+
).toThrow(".char_count is only available on strings");
|
|
2765
|
+
});
|
|
2766
|
+
|
|
2767
|
+
it("throws error for unknown type char_count", () => {
|
|
2768
|
+
const ctx = createMockPostfixExpressionContext("val", [
|
|
2769
|
+
createMockPostfixOp({ identifier: "char_count" }),
|
|
2770
|
+
]);
|
|
2771
|
+
const input = createMockInput({ typeRegistry: new Map() });
|
|
2772
|
+
const state = createMockState();
|
|
2773
|
+
const orchestrator = createMockOrchestrator({
|
|
2774
|
+
generatePrimaryExpr: () => "val",
|
|
2775
|
+
});
|
|
2776
|
+
|
|
2777
|
+
expect(() =>
|
|
2778
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2779
|
+
).toThrow("type not found in registry");
|
|
2780
|
+
});
|
|
2781
|
+
|
|
2782
|
+
it("throws error for array with unknown dimensions for element_count", () => {
|
|
2783
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2784
|
+
[
|
|
2785
|
+
"arr",
|
|
2786
|
+
{
|
|
2787
|
+
baseType: "u32",
|
|
2788
|
+
bitWidth: 32,
|
|
2789
|
+
isArray: true,
|
|
2790
|
+
arrayDimensions: [], // Empty dimensions
|
|
2791
|
+
isConst: false,
|
|
2792
|
+
},
|
|
2793
|
+
],
|
|
2794
|
+
]);
|
|
2795
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2796
|
+
createMockPostfixOp({ identifier: "element_count" }),
|
|
2797
|
+
]);
|
|
2798
|
+
const input = createMockInput({ typeRegistry });
|
|
2799
|
+
const state = createMockState();
|
|
2800
|
+
const orchestrator = createMockOrchestrator({
|
|
2801
|
+
generatePrimaryExpr: () => "arr",
|
|
2802
|
+
});
|
|
2803
|
+
|
|
2804
|
+
expect(() =>
|
|
2805
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2806
|
+
).toThrow("unknown dimensions");
|
|
2807
|
+
});
|
|
2808
|
+
|
|
2809
|
+
it("throws error for array with unknown dimensions for bit_length", () => {
|
|
2810
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2811
|
+
[
|
|
2812
|
+
"arr",
|
|
2813
|
+
{
|
|
2814
|
+
baseType: "u32",
|
|
2815
|
+
bitWidth: 32,
|
|
2816
|
+
isArray: true,
|
|
2817
|
+
arrayDimensions: [], // Empty dimensions
|
|
2818
|
+
isConst: false,
|
|
2819
|
+
},
|
|
2820
|
+
],
|
|
2821
|
+
]);
|
|
2822
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2823
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2824
|
+
]);
|
|
2825
|
+
const input = createMockInput({ typeRegistry });
|
|
2826
|
+
const state = createMockState();
|
|
2827
|
+
const orchestrator = createMockOrchestrator({
|
|
2828
|
+
generatePrimaryExpr: () => "arr",
|
|
2829
|
+
});
|
|
2830
|
+
|
|
2831
|
+
expect(() =>
|
|
2832
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2833
|
+
).toThrow("unknown dimensions");
|
|
2834
|
+
});
|
|
2835
|
+
|
|
2836
|
+
it("handles enum array bit_length", () => {
|
|
2837
|
+
const symbols = createMockSymbols({
|
|
2838
|
+
knownEnums: new Set(["Color"]),
|
|
2839
|
+
});
|
|
2840
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2841
|
+
[
|
|
2842
|
+
"colors",
|
|
2843
|
+
{
|
|
2844
|
+
baseType: "Color",
|
|
2845
|
+
bitWidth: 0, // Not set, should infer from isEnum
|
|
2846
|
+
isArray: true,
|
|
2847
|
+
arrayDimensions: [4],
|
|
2848
|
+
isConst: false,
|
|
2849
|
+
isEnum: true,
|
|
2850
|
+
},
|
|
2851
|
+
],
|
|
2852
|
+
]);
|
|
2853
|
+
const ctx = createMockPostfixExpressionContext("colors", [
|
|
2854
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2855
|
+
]);
|
|
2856
|
+
const input = createMockInput({ symbols, typeRegistry });
|
|
2857
|
+
const state = createMockState();
|
|
2858
|
+
const orchestrator = createMockOrchestrator({
|
|
2859
|
+
generatePrimaryExpr: () => "colors",
|
|
2860
|
+
});
|
|
2861
|
+
|
|
2862
|
+
const result = generatePostfixExpression(ctx, input, state, orchestrator);
|
|
2863
|
+
expect(result.code).toBe("128"); // 4 * 32 = 128
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
it("throws error for unsupported element type in array", () => {
|
|
2867
|
+
const typeRegistry = new Map<string, TTypeInfo>([
|
|
2868
|
+
[
|
|
2869
|
+
"arr",
|
|
2870
|
+
{
|
|
2871
|
+
baseType: "void", // Unsupported type
|
|
2872
|
+
bitWidth: 0,
|
|
2873
|
+
isArray: true,
|
|
2874
|
+
arrayDimensions: [4],
|
|
2875
|
+
isConst: false,
|
|
2876
|
+
},
|
|
2877
|
+
],
|
|
2878
|
+
]);
|
|
2879
|
+
const ctx = createMockPostfixExpressionContext("arr", [
|
|
2880
|
+
createMockPostfixOp({ identifier: "bit_length" }),
|
|
2881
|
+
]);
|
|
2882
|
+
const input = createMockInput({ typeRegistry });
|
|
2883
|
+
const state = createMockState();
|
|
2884
|
+
const orchestrator = createMockOrchestrator({
|
|
2885
|
+
generatePrimaryExpr: () => "arr",
|
|
2886
|
+
});
|
|
2887
|
+
|
|
2888
|
+
expect(() =>
|
|
2889
|
+
generatePostfixExpression(ctx, input, state, orchestrator),
|
|
2890
|
+
).toThrow("unsupported element type");
|
|
2891
|
+
});
|
|
2892
|
+
});
|
|
2074
2893
|
});
|