c-next 0.1.62 → 0.1.64
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 +86 -63
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +3 -2
- package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +1 -1
- package/src/transpiler/__tests__/Transpiler.test.ts +0 -23
- package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +156 -70
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +31 -6
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +43 -11
- package/src/transpiler/output/codegen/CodeGenState.ts +811 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +848 -1382
- package/src/transpiler/output/codegen/TypeResolver.ts +193 -149
- package/src/transpiler/output/codegen/TypeValidator.ts +148 -370
- package/src/transpiler/output/codegen/__tests__/CodeGenState.test.ts +446 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +462 -60
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +435 -196
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +51 -67
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +495 -471
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +39 -43
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +52 -55
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +122 -62
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +101 -144
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +143 -126
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +287 -320
- package/src/transpiler/output/codegen/generators/GeneratorRegistry.ts +12 -0
- package/src/transpiler/output/codegen/generators/__tests__/GeneratorRegistry.test.ts +28 -1
- package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +67 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +121 -51
- package/src/transpiler/output/codegen/generators/declarationGenerators/StructGenerator.ts +100 -23
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +125 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +157 -4
- package/src/transpiler/output/codegen/generators/support/HelperGenerator.ts +23 -22
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +54 -61
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +21 -30
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +56 -53
- package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +22 -30
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +108 -50
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +16 -31
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +103 -96
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +9 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +58 -103
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +97 -40
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +223 -128
- package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +68 -41
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +198 -47
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +39 -37
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +191 -453
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +229 -0
- package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +60 -0
- package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +177 -0
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +336 -0
- package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +201 -0
- package/src/transpiler/output/codegen/types/ITypeResolverDeps.ts +0 -23
- package/src/transpiler/output/codegen/types/ITypeValidatorDeps.ts +0 -53
|
@@ -1466,7 +1466,7 @@ describe("CodeGenerator", () => {
|
|
|
1466
1466
|
describe("Array declarations", () => {
|
|
1467
1467
|
it("should generate array declaration", () => {
|
|
1468
1468
|
const source = `
|
|
1469
|
-
u32
|
|
1469
|
+
u32[10] arr;
|
|
1470
1470
|
void main() { }
|
|
1471
1471
|
`;
|
|
1472
1472
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -1485,7 +1485,7 @@ describe("CodeGenerator", () => {
|
|
|
1485
1485
|
|
|
1486
1486
|
it("should generate array with initializer", () => {
|
|
1487
1487
|
const source = `
|
|
1488
|
-
u32
|
|
1488
|
+
u32[3] arr <- [1, 2, 3];
|
|
1489
1489
|
void main() { }
|
|
1490
1490
|
`;
|
|
1491
1491
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -1505,7 +1505,7 @@ describe("CodeGenerator", () => {
|
|
|
1505
1505
|
|
|
1506
1506
|
it("should generate multi-dimensional array", () => {
|
|
1507
1507
|
const source = `
|
|
1508
|
-
u32
|
|
1508
|
+
u32[3] matrix[3];
|
|
1509
1509
|
void main() { }
|
|
1510
1510
|
`;
|
|
1511
1511
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -2586,7 +2586,7 @@ describe("CodeGenerator", () => {
|
|
|
2586
2586
|
describe("Array element assignment", () => {
|
|
2587
2587
|
it("should generate array element assignment", () => {
|
|
2588
2588
|
const source = `
|
|
2589
|
-
wrap u32
|
|
2589
|
+
wrap u32[10] arr;
|
|
2590
2590
|
void main() {
|
|
2591
2591
|
arr[0] <- 42;
|
|
2592
2592
|
arr[5] <- 100;
|
|
@@ -2734,7 +2734,7 @@ describe("CodeGenerator", () => {
|
|
|
2734
2734
|
it("should generate struct with array field", () => {
|
|
2735
2735
|
const source = `
|
|
2736
2736
|
struct Buffer {
|
|
2737
|
-
u8
|
|
2737
|
+
u8[64] data;
|
|
2738
2738
|
u32 length;
|
|
2739
2739
|
}
|
|
2740
2740
|
`;
|
|
@@ -3297,7 +3297,7 @@ describe("CodeGenerator", () => {
|
|
|
3297
3297
|
it("should generate struct with array member access", () => {
|
|
3298
3298
|
const source = `
|
|
3299
3299
|
struct Buffer {
|
|
3300
|
-
u8
|
|
3300
|
+
u8[64] data;
|
|
3301
3301
|
}
|
|
3302
3302
|
Buffer buf;
|
|
3303
3303
|
void main() {
|
|
@@ -3427,7 +3427,7 @@ describe("CodeGenerator", () => {
|
|
|
3427
3427
|
describe("Const array", () => {
|
|
3428
3428
|
it("should generate const array", () => {
|
|
3429
3429
|
const source = `
|
|
3430
|
-
const u32
|
|
3430
|
+
const u32[4] LOOKUP <- [10, 20, 30, 40];
|
|
3431
3431
|
void main() { }
|
|
3432
3432
|
`;
|
|
3433
3433
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -3853,7 +3853,7 @@ describe("CodeGenerator", () => {
|
|
|
3853
3853
|
describe("Array fill-all syntax", () => {
|
|
3854
3854
|
it("should generate fill-all array [0*]", () => {
|
|
3855
3855
|
const source = `
|
|
3856
|
-
u32
|
|
3856
|
+
u32[10] data <- [0*];
|
|
3857
3857
|
`;
|
|
3858
3858
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
3859
3859
|
const generator = new CodeGenerator();
|
|
@@ -3872,7 +3872,7 @@ describe("CodeGenerator", () => {
|
|
|
3872
3872
|
|
|
3873
3873
|
it("should generate fill-all array with non-zero value", () => {
|
|
3874
3874
|
const source = `
|
|
3875
|
-
u8
|
|
3875
|
+
u8[4] buffer <- [255*];
|
|
3876
3876
|
`;
|
|
3877
3877
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
3878
3878
|
const generator = new CodeGenerator();
|
|
@@ -3893,7 +3893,7 @@ describe("CodeGenerator", () => {
|
|
|
3893
3893
|
describe("Nested array initializers", () => {
|
|
3894
3894
|
it("should generate 2D array initializer", () => {
|
|
3895
3895
|
const source = `
|
|
3896
|
-
u32
|
|
3896
|
+
u32[2] matrix[3] <- [[1, 2, 3], [4, 5, 6]];
|
|
3897
3897
|
`;
|
|
3898
3898
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
3899
3899
|
const generator = new CodeGenerator();
|
|
@@ -3914,7 +3914,7 @@ describe("CodeGenerator", () => {
|
|
|
3914
3914
|
it("should generate array of struct initializers", () => {
|
|
3915
3915
|
const source = `
|
|
3916
3916
|
struct Point { i32 x; i32 y; }
|
|
3917
|
-
Point
|
|
3917
|
+
Point[2] points <- [{x: 1, y: 2}, {x: 3, y: 4}];
|
|
3918
3918
|
`;
|
|
3919
3919
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
3920
3920
|
const generator = new CodeGenerator();
|
|
@@ -4184,7 +4184,7 @@ describe("CodeGenerator", () => {
|
|
|
4184
4184
|
it("should resolve const as array dimension at file scope", () => {
|
|
4185
4185
|
const source = `
|
|
4186
4186
|
const u32 SIZE <- 10;
|
|
4187
|
-
u32
|
|
4187
|
+
u32[SIZE] data;
|
|
4188
4188
|
`;
|
|
4189
4189
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
4190
4190
|
const generator = new CodeGenerator();
|
|
@@ -4205,7 +4205,7 @@ describe("CodeGenerator", () => {
|
|
|
4205
4205
|
describe("Multi-dimensional array", () => {
|
|
4206
4206
|
it("should generate 3D array declaration", () => {
|
|
4207
4207
|
const source = `
|
|
4208
|
-
u8
|
|
4208
|
+
u8[2] cube[3][4];
|
|
4209
4209
|
`;
|
|
4210
4210
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
4211
4211
|
const generator = new CodeGenerator();
|
|
@@ -4686,7 +4686,7 @@ describe("CodeGenerator", () => {
|
|
|
4686
4686
|
describe("Array indexing with expressions", () => {
|
|
4687
4687
|
it("should generate array index with arithmetic", () => {
|
|
4688
4688
|
const source = `
|
|
4689
|
-
u32
|
|
4689
|
+
u32[10] data;
|
|
4690
4690
|
wrap u32 i <- 2;
|
|
4691
4691
|
void main() {
|
|
4692
4692
|
data[i * 2 + 1] <- 42;
|
|
@@ -4877,7 +4877,7 @@ describe("CodeGenerator", () => {
|
|
|
4877
4877
|
describe("Array length", () => {
|
|
4878
4878
|
it("should generate array length using sizeof", () => {
|
|
4879
4879
|
const source = `
|
|
4880
|
-
u32
|
|
4880
|
+
u32[10] data;
|
|
4881
4881
|
u32 len <- data.length;
|
|
4882
4882
|
`;
|
|
4883
4883
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -5285,7 +5285,7 @@ describe("CodeGenerator", () => {
|
|
|
5285
5285
|
it("should pass array without address-of operator", () => {
|
|
5286
5286
|
const source = `
|
|
5287
5287
|
void processData(u32 data[]) { }
|
|
5288
|
-
u32
|
|
5288
|
+
u32[5] myData;
|
|
5289
5289
|
void main() {
|
|
5290
5290
|
processData(myData);
|
|
5291
5291
|
}
|
|
@@ -5310,7 +5310,7 @@ describe("CodeGenerator", () => {
|
|
|
5310
5310
|
it("should generate struct with array field", () => {
|
|
5311
5311
|
const source = `
|
|
5312
5312
|
struct Buffer {
|
|
5313
|
-
u8
|
|
5313
|
+
u8[64] data;
|
|
5314
5314
|
u32 length;
|
|
5315
5315
|
}
|
|
5316
5316
|
`;
|
|
@@ -5694,7 +5694,7 @@ describe("CodeGenerator", () => {
|
|
|
5694
5694
|
describe("Array bounds checking", () => {
|
|
5695
5695
|
it("should throw error for out-of-bounds constant index", () => {
|
|
5696
5696
|
const source = `
|
|
5697
|
-
u32
|
|
5697
|
+
u32[5] data;
|
|
5698
5698
|
void main() {
|
|
5699
5699
|
data[10] <- 1;
|
|
5700
5700
|
}
|
|
@@ -5899,7 +5899,7 @@ describe("CodeGenerator", () => {
|
|
|
5899
5899
|
describe("Sizeof variable", () => {
|
|
5900
5900
|
it("should generate sizeof for variable", () => {
|
|
5901
5901
|
const source = `
|
|
5902
|
-
u32
|
|
5902
|
+
u32[10] arr;
|
|
5903
5903
|
u32 size <- sizeof(arr);
|
|
5904
5904
|
`;
|
|
5905
5905
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -5921,7 +5921,7 @@ describe("CodeGenerator", () => {
|
|
|
5921
5921
|
it("should resolve const to literal for file-scope array", () => {
|
|
5922
5922
|
const source = `
|
|
5923
5923
|
const u32 BUFFER_SIZE <- 256;
|
|
5924
|
-
u8
|
|
5924
|
+
u8[BUFFER_SIZE] buffer;
|
|
5925
5925
|
`;
|
|
5926
5926
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
5927
5927
|
const generator = new CodeGenerator();
|
|
@@ -6056,7 +6056,7 @@ describe("CodeGenerator", () => {
|
|
|
6056
6056
|
it("should generate struct with array field access", () => {
|
|
6057
6057
|
const source = `
|
|
6058
6058
|
struct Message {
|
|
6059
|
-
u8
|
|
6059
|
+
u8[8] data;
|
|
6060
6060
|
u8 length;
|
|
6061
6061
|
}
|
|
6062
6062
|
Message msg;
|
|
@@ -6166,7 +6166,7 @@ describe("CodeGenerator", () => {
|
|
|
6166
6166
|
const source = `
|
|
6167
6167
|
void setup() {
|
|
6168
6168
|
const u32 SIZE <- 5;
|
|
6169
|
-
u32
|
|
6169
|
+
u32[SIZE] data;
|
|
6170
6170
|
}
|
|
6171
6171
|
`;
|
|
6172
6172
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -6181,7 +6181,8 @@ describe("CodeGenerator", () => {
|
|
|
6181
6181
|
});
|
|
6182
6182
|
|
|
6183
6183
|
expect(code).toContain("SIZE");
|
|
6184
|
-
|
|
6184
|
+
// Const value is evaluated at compile time
|
|
6185
|
+
expect(code).toContain("data[5]");
|
|
6185
6186
|
});
|
|
6186
6187
|
});
|
|
6187
6188
|
|
|
@@ -6666,7 +6667,7 @@ describe("CodeGenerator", () => {
|
|
|
6666
6667
|
|
|
6667
6668
|
describe("Array with literal size", () => {
|
|
6668
6669
|
it("should generate array with integer literal size", () => {
|
|
6669
|
-
const source = `u32
|
|
6670
|
+
const source = `u32[100] buffer;`;
|
|
6670
6671
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
6671
6672
|
const generator = new CodeGenerator();
|
|
6672
6673
|
const symbolTable = new SymbolTable();
|
|
@@ -6793,7 +6794,7 @@ describe("CodeGenerator", () => {
|
|
|
6793
6794
|
|
|
6794
6795
|
describe("Array initialization with values", () => {
|
|
6795
6796
|
it("should generate array with initialization list", () => {
|
|
6796
|
-
const source = `u8
|
|
6797
|
+
const source = `u8[4] data <- [1, 2, 3, 4];`;
|
|
6797
6798
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
6798
6799
|
const generator = new CodeGenerator();
|
|
6799
6800
|
const symbolTable = new SymbolTable();
|
|
@@ -6814,7 +6815,7 @@ describe("CodeGenerator", () => {
|
|
|
6814
6815
|
const source = `
|
|
6815
6816
|
void process(u8 arr[]) { }
|
|
6816
6817
|
void main() {
|
|
6817
|
-
u8
|
|
6818
|
+
u8[10] local;
|
|
6818
6819
|
process(local);
|
|
6819
6820
|
}
|
|
6820
6821
|
`;
|
|
@@ -7081,7 +7082,7 @@ describe("CodeGenerator", () => {
|
|
|
7081
7082
|
it("should initialize POD arrays to {0}", () => {
|
|
7082
7083
|
const source = `
|
|
7083
7084
|
void main() {
|
|
7084
|
-
u32
|
|
7085
|
+
u32[10] values;
|
|
7085
7086
|
}
|
|
7086
7087
|
`;
|
|
7087
7088
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -7102,7 +7103,7 @@ describe("CodeGenerator", () => {
|
|
|
7102
7103
|
const source = `
|
|
7103
7104
|
struct Point { i32 x; i32 y; }
|
|
7104
7105
|
void main() {
|
|
7105
|
-
Point
|
|
7106
|
+
Point[5] points;
|
|
7106
7107
|
}
|
|
7107
7108
|
`;
|
|
7108
7109
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -7168,6 +7169,142 @@ describe("CodeGenerator", () => {
|
|
|
7168
7169
|
|
|
7169
7170
|
// Note: Template type tests skipped - template argument transformation
|
|
7170
7171
|
// (i32 -> int32_t) is a separate issue to be addressed in another PR
|
|
7172
|
+
|
|
7173
|
+
it("should generate C-Next style array params with dimensions in C++ mode", () => {
|
|
7174
|
+
const source = `
|
|
7175
|
+
void fill(u8[8] buf) {
|
|
7176
|
+
buf[0] <- 0xFF;
|
|
7177
|
+
}
|
|
7178
|
+
`;
|
|
7179
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7180
|
+
const generator = new CodeGenerator();
|
|
7181
|
+
const symbolTable = new SymbolTable();
|
|
7182
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7183
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7184
|
+
|
|
7185
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7186
|
+
symbolInfo: symbols,
|
|
7187
|
+
sourcePath: "test.cnx",
|
|
7188
|
+
cppMode: true,
|
|
7189
|
+
});
|
|
7190
|
+
|
|
7191
|
+
// C-Next style u8[8] param should generate uint8_t buf[8], not uint8_t& buf
|
|
7192
|
+
expect(code).toContain("uint8_t buf[8]");
|
|
7193
|
+
expect(code).not.toContain("uint8_t& buf");
|
|
7194
|
+
expect(code).not.toContain("uint8_t& buf");
|
|
7195
|
+
});
|
|
7196
|
+
|
|
7197
|
+
it("should generate const C-Next style array params in C++ mode", () => {
|
|
7198
|
+
const source = `
|
|
7199
|
+
u8 read(const u8[4] data) {
|
|
7200
|
+
return data[0];
|
|
7201
|
+
}
|
|
7202
|
+
`;
|
|
7203
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7204
|
+
const generator = new CodeGenerator();
|
|
7205
|
+
const symbolTable = new SymbolTable();
|
|
7206
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7207
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7208
|
+
|
|
7209
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7210
|
+
symbolInfo: symbols,
|
|
7211
|
+
sourcePath: "test.cnx",
|
|
7212
|
+
cppMode: true,
|
|
7213
|
+
});
|
|
7214
|
+
|
|
7215
|
+
// Const C-Next style array param should retain dimension
|
|
7216
|
+
expect(code).toContain("const uint8_t data[4]");
|
|
7217
|
+
expect(code).not.toContain("const uint8_t& data");
|
|
7218
|
+
});
|
|
7219
|
+
|
|
7220
|
+
it("should generate C-Next style array params in C mode too", () => {
|
|
7221
|
+
const source = `
|
|
7222
|
+
void fill(u8[8] buf) {
|
|
7223
|
+
buf[0] <- 0xFF;
|
|
7224
|
+
}
|
|
7225
|
+
`;
|
|
7226
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7227
|
+
const generator = new CodeGenerator();
|
|
7228
|
+
const symbolTable = new SymbolTable();
|
|
7229
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7230
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7231
|
+
|
|
7232
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7233
|
+
symbolInfo: symbols,
|
|
7234
|
+
sourcePath: "test.cnx",
|
|
7235
|
+
});
|
|
7236
|
+
|
|
7237
|
+
// C mode should also generate uint8_t buf[8]
|
|
7238
|
+
expect(code).toContain("uint8_t buf[8]");
|
|
7239
|
+
expect(code).not.toContain("uint8_t* buf");
|
|
7240
|
+
});
|
|
7241
|
+
|
|
7242
|
+
it("should generate primitive C-Next style arrays with {0} in C++ mode", () => {
|
|
7243
|
+
const source = `
|
|
7244
|
+
void main() {
|
|
7245
|
+
u32[8] counters;
|
|
7246
|
+
}
|
|
7247
|
+
`;
|
|
7248
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7249
|
+
const generator = new CodeGenerator();
|
|
7250
|
+
const symbolTable = new SymbolTable();
|
|
7251
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7252
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7253
|
+
|
|
7254
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7255
|
+
symbolInfo: symbols,
|
|
7256
|
+
sourcePath: "test.cnx",
|
|
7257
|
+
cppMode: true,
|
|
7258
|
+
});
|
|
7259
|
+
|
|
7260
|
+
// Primitive type arrays should still use {0}
|
|
7261
|
+
expect(code).toContain("uint32_t counters[8] = {0}");
|
|
7262
|
+
});
|
|
7263
|
+
|
|
7264
|
+
it("should generate unknown user type C-Next style arrays with {} in C++ mode", () => {
|
|
7265
|
+
const source = `
|
|
7266
|
+
void main() {
|
|
7267
|
+
UnknownType[4] items;
|
|
7268
|
+
}
|
|
7269
|
+
`;
|
|
7270
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7271
|
+
const generator = new CodeGenerator();
|
|
7272
|
+
const symbolTable = new SymbolTable();
|
|
7273
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7274
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7275
|
+
|
|
7276
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7277
|
+
symbolInfo: symbols,
|
|
7278
|
+
sourcePath: "test.cnx",
|
|
7279
|
+
cppMode: true,
|
|
7280
|
+
});
|
|
7281
|
+
|
|
7282
|
+
// Unknown types in C++ mode use {} (may have non-trivial constructors)
|
|
7283
|
+
expect(code).toContain("UnknownType items[4] = {}");
|
|
7284
|
+
});
|
|
7285
|
+
|
|
7286
|
+
it("should generate known C-Next struct arrays with {0} in C++ mode", () => {
|
|
7287
|
+
const source = `
|
|
7288
|
+
struct Point { i32 x; i32 y; }
|
|
7289
|
+
void main() {
|
|
7290
|
+
Point[3] pts;
|
|
7291
|
+
}
|
|
7292
|
+
`;
|
|
7293
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
7294
|
+
const generator = new CodeGenerator();
|
|
7295
|
+
const symbolTable = new SymbolTable();
|
|
7296
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
7297
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
7298
|
+
|
|
7299
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
7300
|
+
symbolInfo: symbols,
|
|
7301
|
+
sourcePath: "test.cnx",
|
|
7302
|
+
cppMode: true,
|
|
7303
|
+
});
|
|
7304
|
+
|
|
7305
|
+
// Known C-Next structs are POD types, {0} is correct
|
|
7306
|
+
expect(code).toContain("Point pts[3] = {0}");
|
|
7307
|
+
});
|
|
7171
7308
|
});
|
|
7172
7309
|
});
|
|
7173
7310
|
|
|
@@ -7347,7 +7484,7 @@ describe("CodeGenerator", () => {
|
|
|
7347
7484
|
it("should generate struct array member write", () => {
|
|
7348
7485
|
const source = `
|
|
7349
7486
|
struct Item { u32 value; }
|
|
7350
|
-
Item
|
|
7487
|
+
Item[3] items;
|
|
7351
7488
|
void main() {
|
|
7352
7489
|
items[0].value <- 42;
|
|
7353
7490
|
}
|
|
@@ -7932,7 +8069,7 @@ describe("CodeGenerator", () => {
|
|
|
7932
8069
|
const source = `
|
|
7933
8070
|
void callee(u32 arr[10]) { }
|
|
7934
8071
|
void test() {
|
|
7935
|
-
u32
|
|
8072
|
+
u32[10] data;
|
|
7936
8073
|
callee(data);
|
|
7937
8074
|
}
|
|
7938
8075
|
`;
|
|
@@ -7976,7 +8113,7 @@ describe("CodeGenerator", () => {
|
|
|
7976
8113
|
const source = `
|
|
7977
8114
|
void callee(u32 val) { }
|
|
7978
8115
|
void test() {
|
|
7979
|
-
u32
|
|
8116
|
+
u32[10] arr;
|
|
7980
8117
|
callee(arr[0]);
|
|
7981
8118
|
}
|
|
7982
8119
|
`;
|
|
@@ -8426,7 +8563,7 @@ describe("CodeGenerator", () => {
|
|
|
8426
8563
|
it("should handle sizeof on variable", () => {
|
|
8427
8564
|
const source = `
|
|
8428
8565
|
void test() {
|
|
8429
|
-
u32
|
|
8566
|
+
u32[10] arr;
|
|
8430
8567
|
u32 size <- sizeof(arr);
|
|
8431
8568
|
}
|
|
8432
8569
|
`;
|
|
@@ -8491,7 +8628,7 @@ describe("CodeGenerator", () => {
|
|
|
8491
8628
|
it("should handle single index array access", () => {
|
|
8492
8629
|
const source = `
|
|
8493
8630
|
void test() {
|
|
8494
|
-
u32
|
|
8631
|
+
u32[10] arr;
|
|
8495
8632
|
u32 val <- arr[5];
|
|
8496
8633
|
}
|
|
8497
8634
|
`;
|
|
@@ -8575,7 +8712,7 @@ describe("CodeGenerator", () => {
|
|
|
8575
8712
|
it("should handle C++ mode array access", () => {
|
|
8576
8713
|
const source = `
|
|
8577
8714
|
void test() {
|
|
8578
|
-
u32
|
|
8715
|
+
u32[10] arr;
|
|
8579
8716
|
u32 val <- arr[5];
|
|
8580
8717
|
}
|
|
8581
8718
|
`;
|
|
@@ -8597,7 +8734,7 @@ describe("CodeGenerator", () => {
|
|
|
8597
8734
|
it("should handle multi-dimensional array access", () => {
|
|
8598
8735
|
const source = `
|
|
8599
8736
|
void test() {
|
|
8600
|
-
u32
|
|
8737
|
+
u32[3] matrix[3];
|
|
8601
8738
|
u32 val <- matrix[1][2];
|
|
8602
8739
|
}
|
|
8603
8740
|
`;
|
|
@@ -8778,7 +8915,7 @@ describe("CodeGenerator", () => {
|
|
|
8778
8915
|
const source = `
|
|
8779
8916
|
struct Point { u32 x; u32 y; }
|
|
8780
8917
|
void test() {
|
|
8781
|
-
Point
|
|
8918
|
+
Point[10] points;
|
|
8782
8919
|
u32 x <- points[0].x;
|
|
8783
8920
|
}
|
|
8784
8921
|
`;
|
|
@@ -9141,7 +9278,7 @@ describe("CodeGenerator", () => {
|
|
|
9141
9278
|
it("should resolve const values in expressions", () => {
|
|
9142
9279
|
const source = `
|
|
9143
9280
|
const u32 MAX_SIZE <- 100;
|
|
9144
|
-
u32
|
|
9281
|
+
u32[MAX_SIZE] buffer;
|
|
9145
9282
|
`;
|
|
9146
9283
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
9147
9284
|
const generator = new CodeGenerator();
|
|
@@ -9210,7 +9347,7 @@ describe("CodeGenerator", () => {
|
|
|
9210
9347
|
it("should handle array access in assignment target", () => {
|
|
9211
9348
|
const source = `
|
|
9212
9349
|
void test() {
|
|
9213
|
-
u32
|
|
9350
|
+
u32[10] arr;
|
|
9214
9351
|
arr[5] <- 42;
|
|
9215
9352
|
}
|
|
9216
9353
|
`;
|
|
@@ -9716,7 +9853,7 @@ describe("CodeGenerator", () => {
|
|
|
9716
9853
|
it("should generate struct with array member", () => {
|
|
9717
9854
|
const source = `
|
|
9718
9855
|
struct Buffer {
|
|
9719
|
-
u8
|
|
9856
|
+
u8[64] data;
|
|
9720
9857
|
u32 size;
|
|
9721
9858
|
}
|
|
9722
9859
|
Buffer buf;
|
|
@@ -9833,7 +9970,7 @@ describe("CodeGenerator", () => {
|
|
|
9833
9970
|
it("should generate array with initializer list", () => {
|
|
9834
9971
|
const source = `
|
|
9835
9972
|
void test() {
|
|
9836
|
-
u32
|
|
9973
|
+
u32[5] arr <- [1, 2, 3, 4, 5];
|
|
9837
9974
|
}
|
|
9838
9975
|
`;
|
|
9839
9976
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -11130,7 +11267,7 @@ describe("CodeGenerator", () => {
|
|
|
11130
11267
|
data[0] <- 1;
|
|
11131
11268
|
}
|
|
11132
11269
|
void test() {
|
|
11133
|
-
u32
|
|
11270
|
+
u32[10] arr;
|
|
11134
11271
|
process(arr);
|
|
11135
11272
|
}
|
|
11136
11273
|
`;
|
|
@@ -11436,7 +11573,7 @@ describe("CodeGenerator", () => {
|
|
|
11436
11573
|
it("should handle array with size in declaration", () => {
|
|
11437
11574
|
const source = `
|
|
11438
11575
|
void test() {
|
|
11439
|
-
u8
|
|
11576
|
+
u8[10] buffer;
|
|
11440
11577
|
buffer[0] <- 0xFF;
|
|
11441
11578
|
}
|
|
11442
11579
|
`;
|
|
@@ -11458,7 +11595,7 @@ describe("CodeGenerator", () => {
|
|
|
11458
11595
|
const source = `
|
|
11459
11596
|
const u32 BUFFER_SIZE <- 64;
|
|
11460
11597
|
void test() {
|
|
11461
|
-
u8
|
|
11598
|
+
u8[BUFFER_SIZE] buffer;
|
|
11462
11599
|
buffer[0] <- 0;
|
|
11463
11600
|
}
|
|
11464
11601
|
`;
|
|
@@ -11475,6 +11612,90 @@ describe("CodeGenerator", () => {
|
|
|
11475
11612
|
|
|
11476
11613
|
expect(code).toContain("BUFFER_SIZE");
|
|
11477
11614
|
});
|
|
11615
|
+
|
|
11616
|
+
it("should reject C-style array declaration for primitive types", () => {
|
|
11617
|
+
const source = `
|
|
11618
|
+
void test() {
|
|
11619
|
+
u8 buffer[10];
|
|
11620
|
+
}
|
|
11621
|
+
`;
|
|
11622
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
11623
|
+
const generator = new CodeGenerator();
|
|
11624
|
+
const symbolTable = new SymbolTable();
|
|
11625
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
11626
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
11627
|
+
|
|
11628
|
+
expect(() => {
|
|
11629
|
+
generator.generate(tree, symbolTable, tokenStream, {
|
|
11630
|
+
symbolInfo: symbols,
|
|
11631
|
+
sourcePath: "test.cnx",
|
|
11632
|
+
});
|
|
11633
|
+
}).toThrow(/C-style array declaration is not allowed/);
|
|
11634
|
+
});
|
|
11635
|
+
|
|
11636
|
+
it("should reject C-style array declaration for user types", () => {
|
|
11637
|
+
const source = `
|
|
11638
|
+
struct Data {
|
|
11639
|
+
u32 value;
|
|
11640
|
+
}
|
|
11641
|
+
void test() {
|
|
11642
|
+
Data items[5];
|
|
11643
|
+
}
|
|
11644
|
+
`;
|
|
11645
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
11646
|
+
const generator = new CodeGenerator();
|
|
11647
|
+
const symbolTable = new SymbolTable();
|
|
11648
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
11649
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
11650
|
+
|
|
11651
|
+
expect(() => {
|
|
11652
|
+
generator.generate(tree, symbolTable, tokenStream, {
|
|
11653
|
+
symbolInfo: symbols,
|
|
11654
|
+
sourcePath: "test.cnx",
|
|
11655
|
+
});
|
|
11656
|
+
}).toThrow(/C-style array declaration is not allowed/);
|
|
11657
|
+
});
|
|
11658
|
+
|
|
11659
|
+
it("should allow empty brackets for size inference", () => {
|
|
11660
|
+
const source = `
|
|
11661
|
+
void test() {
|
|
11662
|
+
u8 data[] <- [1, 2, 3];
|
|
11663
|
+
}
|
|
11664
|
+
`;
|
|
11665
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
11666
|
+
const generator = new CodeGenerator();
|
|
11667
|
+
const symbolTable = new SymbolTable();
|
|
11668
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
11669
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
11670
|
+
|
|
11671
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
11672
|
+
symbolInfo: symbols,
|
|
11673
|
+
sourcePath: "test.cnx",
|
|
11674
|
+
});
|
|
11675
|
+
|
|
11676
|
+
expect(code).toContain("uint8_t data[3]");
|
|
11677
|
+
});
|
|
11678
|
+
|
|
11679
|
+
it("should allow multi-dimensional C-style arrays", () => {
|
|
11680
|
+
const source = `
|
|
11681
|
+
void test() {
|
|
11682
|
+
u8 matrix[4][4];
|
|
11683
|
+
matrix[0][0] <- 0;
|
|
11684
|
+
}
|
|
11685
|
+
`;
|
|
11686
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
11687
|
+
const generator = new CodeGenerator();
|
|
11688
|
+
const symbolTable = new SymbolTable();
|
|
11689
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
11690
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
11691
|
+
|
|
11692
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
11693
|
+
symbolInfo: symbols,
|
|
11694
|
+
sourcePath: "test.cnx",
|
|
11695
|
+
});
|
|
11696
|
+
|
|
11697
|
+
expect(code).toContain("uint8_t matrix[4][4]");
|
|
11698
|
+
});
|
|
11478
11699
|
});
|
|
11479
11700
|
|
|
11480
11701
|
describe("string expression type checking", () => {
|
|
@@ -12208,7 +12429,7 @@ describe("CodeGenerator", () => {
|
|
|
12208
12429
|
it("should handle sizeof on local array", () => {
|
|
12209
12430
|
const source = `
|
|
12210
12431
|
void test() {
|
|
12211
|
-
u8
|
|
12432
|
+
u8[16] buffer;
|
|
12212
12433
|
u32 size <- sizeof(buffer);
|
|
12213
12434
|
}
|
|
12214
12435
|
`;
|
|
@@ -12368,7 +12589,7 @@ describe("CodeGenerator", () => {
|
|
|
12368
12589
|
it("should resolve array element access in expression", () => {
|
|
12369
12590
|
const source = `
|
|
12370
12591
|
void test() {
|
|
12371
|
-
u32
|
|
12592
|
+
u32[10] arr;
|
|
12372
12593
|
u32 val <- arr[5];
|
|
12373
12594
|
}
|
|
12374
12595
|
`;
|
|
@@ -12389,7 +12610,7 @@ describe("CodeGenerator", () => {
|
|
|
12389
12610
|
it("should resolve array element with variable index", () => {
|
|
12390
12611
|
const source = `
|
|
12391
12612
|
void test() {
|
|
12392
|
-
u32
|
|
12613
|
+
u32[10] arr;
|
|
12393
12614
|
u32 i <- 3;
|
|
12394
12615
|
u32 val <- arr[i];
|
|
12395
12616
|
}
|
|
@@ -12802,7 +13023,7 @@ describe("CodeGenerator", () => {
|
|
|
12802
13023
|
const source = `
|
|
12803
13024
|
struct Item { u32 id; }
|
|
12804
13025
|
void test() {
|
|
12805
|
-
Item
|
|
13026
|
+
Item[10] items;
|
|
12806
13027
|
items[0].id <- 42;
|
|
12807
13028
|
}
|
|
12808
13029
|
`;
|
|
@@ -13071,7 +13292,7 @@ describe("CodeGenerator", () => {
|
|
|
13071
13292
|
it("should handle array type with user-defined struct", () => {
|
|
13072
13293
|
const source = `
|
|
13073
13294
|
struct Point { i32 x; i32 y; }
|
|
13074
|
-
Point
|
|
13295
|
+
Point[10] points;
|
|
13075
13296
|
`;
|
|
13076
13297
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
13077
13298
|
const generator = new CodeGenerator();
|
|
@@ -13089,8 +13310,8 @@ describe("CodeGenerator", () => {
|
|
|
13089
13310
|
|
|
13090
13311
|
it("should handle array type with primitive types", () => {
|
|
13091
13312
|
const source = `
|
|
13092
|
-
u8
|
|
13093
|
-
i32
|
|
13313
|
+
u8[256] buffer;
|
|
13314
|
+
i32[10] numbers;
|
|
13094
13315
|
`;
|
|
13095
13316
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
13096
13317
|
const generator = new CodeGenerator();
|
|
@@ -13590,7 +13811,7 @@ describe("CodeGenerator", () => {
|
|
|
13590
13811
|
describe("array access resolution helpers", () => {
|
|
13591
13812
|
it("should resolve simple array access", () => {
|
|
13592
13813
|
const source = `
|
|
13593
|
-
u8
|
|
13814
|
+
u8[10] buffer;
|
|
13594
13815
|
void test() {
|
|
13595
13816
|
u8 val <- buffer[5];
|
|
13596
13817
|
}
|
|
@@ -13611,7 +13832,7 @@ describe("CodeGenerator", () => {
|
|
|
13611
13832
|
|
|
13612
13833
|
it("should handle array access with variable index", () => {
|
|
13613
13834
|
const source = `
|
|
13614
|
-
u8
|
|
13835
|
+
u8[20] data;
|
|
13615
13836
|
void test() {
|
|
13616
13837
|
u32 idx <- 3;
|
|
13617
13838
|
u8 val <- data[idx];
|
|
@@ -14098,7 +14319,7 @@ describe("CodeGenerator", () => {
|
|
|
14098
14319
|
it("should register array type correctly", () => {
|
|
14099
14320
|
const source = `
|
|
14100
14321
|
void test() {
|
|
14101
|
-
u8
|
|
14322
|
+
u8[10] buffer;
|
|
14102
14323
|
buffer[0] <- 0xFF;
|
|
14103
14324
|
}
|
|
14104
14325
|
`;
|
|
@@ -14119,7 +14340,7 @@ describe("CodeGenerator", () => {
|
|
|
14119
14340
|
it("should register multi-dimensional array", () => {
|
|
14120
14341
|
const source = `
|
|
14121
14342
|
void test() {
|
|
14122
|
-
u8
|
|
14343
|
+
u8[10] matrix[20];
|
|
14123
14344
|
matrix[0][0] <- 0;
|
|
14124
14345
|
}
|
|
14125
14346
|
`;
|
|
@@ -14140,7 +14361,7 @@ describe("CodeGenerator", () => {
|
|
|
14140
14361
|
it("should handle i32 array type", () => {
|
|
14141
14362
|
const source = `
|
|
14142
14363
|
void test() {
|
|
14143
|
-
i32
|
|
14364
|
+
i32[5] values;
|
|
14144
14365
|
values[0] <- 100;
|
|
14145
14366
|
}
|
|
14146
14367
|
`;
|
|
@@ -14161,7 +14382,7 @@ describe("CodeGenerator", () => {
|
|
|
14161
14382
|
it("should handle const array type", () => {
|
|
14162
14383
|
const source = `
|
|
14163
14384
|
void test() {
|
|
14164
|
-
const u8
|
|
14385
|
+
const u8[4] data <- [1, 2, 3, 4];
|
|
14165
14386
|
}
|
|
14166
14387
|
`;
|
|
14167
14388
|
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
@@ -14177,6 +14398,111 @@ describe("CodeGenerator", () => {
|
|
|
14177
14398
|
|
|
14178
14399
|
expect(code).toContain("const uint8_t data[4]");
|
|
14179
14400
|
});
|
|
14401
|
+
|
|
14402
|
+
it("should handle struct array with C-Next syntax", () => {
|
|
14403
|
+
const source = `
|
|
14404
|
+
struct Point {
|
|
14405
|
+
i32 x;
|
|
14406
|
+
i32 y;
|
|
14407
|
+
}
|
|
14408
|
+
void test() {
|
|
14409
|
+
Point[3] points;
|
|
14410
|
+
points[0].x <- 10;
|
|
14411
|
+
}
|
|
14412
|
+
`;
|
|
14413
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
14414
|
+
const generator = new CodeGenerator();
|
|
14415
|
+
const symbolTable = new SymbolTable();
|
|
14416
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
14417
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
14418
|
+
|
|
14419
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
14420
|
+
symbolInfo: symbols,
|
|
14421
|
+
sourcePath: "test.cnx",
|
|
14422
|
+
});
|
|
14423
|
+
|
|
14424
|
+
expect(code).toContain("Point points[3]");
|
|
14425
|
+
expect(code).toContain("points[0].x = 10");
|
|
14426
|
+
});
|
|
14427
|
+
|
|
14428
|
+
it("should handle bitmap array with C-Next syntax", () => {
|
|
14429
|
+
const source = `
|
|
14430
|
+
bitmap8 Flags {
|
|
14431
|
+
active,
|
|
14432
|
+
ready,
|
|
14433
|
+
error,
|
|
14434
|
+
mode[3],
|
|
14435
|
+
priority[2]
|
|
14436
|
+
}
|
|
14437
|
+
void test() {
|
|
14438
|
+
Flags[4] flags;
|
|
14439
|
+
flags[0].active <- true;
|
|
14440
|
+
}
|
|
14441
|
+
`;
|
|
14442
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
14443
|
+
const generator = new CodeGenerator();
|
|
14444
|
+
const symbolTable = new SymbolTable();
|
|
14445
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
14446
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
14447
|
+
|
|
14448
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
14449
|
+
symbolInfo: symbols,
|
|
14450
|
+
sourcePath: "test.cnx",
|
|
14451
|
+
});
|
|
14452
|
+
|
|
14453
|
+
expect(code).toContain("Flags flags[4]");
|
|
14454
|
+
// Bitmap field access should generate bit manipulation
|
|
14455
|
+
expect(code).toContain("flags[0]");
|
|
14456
|
+
});
|
|
14457
|
+
|
|
14458
|
+
it("should handle enum array with C-Next syntax", () => {
|
|
14459
|
+
const source = `
|
|
14460
|
+
enum Color {
|
|
14461
|
+
RED,
|
|
14462
|
+
GREEN,
|
|
14463
|
+
BLUE
|
|
14464
|
+
}
|
|
14465
|
+
void test() {
|
|
14466
|
+
Color[3] colors;
|
|
14467
|
+
colors[0] <- RED;
|
|
14468
|
+
}
|
|
14469
|
+
`;
|
|
14470
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
14471
|
+
const generator = new CodeGenerator();
|
|
14472
|
+
const symbolTable = new SymbolTable();
|
|
14473
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
14474
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
14475
|
+
|
|
14476
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
14477
|
+
symbolInfo: symbols,
|
|
14478
|
+
sourcePath: "test.cnx",
|
|
14479
|
+
});
|
|
14480
|
+
|
|
14481
|
+
expect(code).toContain("Color colors[3]");
|
|
14482
|
+
expect(code).toContain("colors[0] = Color_RED");
|
|
14483
|
+
});
|
|
14484
|
+
|
|
14485
|
+
it("should handle struct array initializer with C-Next syntax", () => {
|
|
14486
|
+
const source = `
|
|
14487
|
+
struct Item {
|
|
14488
|
+
u8 id;
|
|
14489
|
+
}
|
|
14490
|
+
const Item[2] items <- [{id: 1}, {id: 2}];
|
|
14491
|
+
`;
|
|
14492
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
14493
|
+
const generator = new CodeGenerator();
|
|
14494
|
+
const symbolTable = new SymbolTable();
|
|
14495
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
14496
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
14497
|
+
|
|
14498
|
+
const code = generator.generate(tree, symbolTable, tokenStream, {
|
|
14499
|
+
symbolInfo: symbols,
|
|
14500
|
+
sourcePath: "test.cnx",
|
|
14501
|
+
});
|
|
14502
|
+
|
|
14503
|
+
expect(code).toContain("const Item items[2]");
|
|
14504
|
+
expect(code).toContain(".id = 1");
|
|
14505
|
+
});
|
|
14180
14506
|
});
|
|
14181
14507
|
|
|
14182
14508
|
describe("C++ mode member conversion", () => {
|
|
@@ -14211,7 +14537,7 @@ describe("CodeGenerator", () => {
|
|
|
14211
14537
|
u32 id;
|
|
14212
14538
|
}
|
|
14213
14539
|
void process() {
|
|
14214
|
-
Item
|
|
14540
|
+
Item[3] items;
|
|
14215
14541
|
u32 first <- items[0].id;
|
|
14216
14542
|
}
|
|
14217
14543
|
`;
|
|
@@ -14610,7 +14936,7 @@ describe("CodeGenerator", () => {
|
|
|
14610
14936
|
it("should generate array element write", () => {
|
|
14611
14937
|
const source = `
|
|
14612
14938
|
void test() {
|
|
14613
|
-
u32
|
|
14939
|
+
u32[10] arr;
|
|
14614
14940
|
arr[5] <- 42;
|
|
14615
14941
|
}
|
|
14616
14942
|
`;
|
|
@@ -15384,7 +15710,7 @@ describe("CodeGenerator", () => {
|
|
|
15384
15710
|
describe("array access via ArrayAccessHelper", () => {
|
|
15385
15711
|
it("should generate single-index array access", () => {
|
|
15386
15712
|
const source = `
|
|
15387
|
-
u32
|
|
15713
|
+
u32[10] arr;
|
|
15388
15714
|
void test() {
|
|
15389
15715
|
u32 val <- arr[5];
|
|
15390
15716
|
}
|
|
@@ -15405,7 +15731,7 @@ describe("CodeGenerator", () => {
|
|
|
15405
15731
|
|
|
15406
15732
|
it("should generate array access with variable index", () => {
|
|
15407
15733
|
const source = `
|
|
15408
|
-
u8
|
|
15734
|
+
u8[100] data;
|
|
15409
15735
|
void test(u32 idx) {
|
|
15410
15736
|
u8 val <- data[idx];
|
|
15411
15737
|
}
|
|
@@ -15546,4 +15872,80 @@ describe("CodeGenerator", () => {
|
|
|
15546
15872
|
expect(code).not.toContain("Bar_OFFSET");
|
|
15547
15873
|
});
|
|
15548
15874
|
});
|
|
15875
|
+
|
|
15876
|
+
describe("Generator registration error paths", () => {
|
|
15877
|
+
it("throws error when struct generator is not registered", () => {
|
|
15878
|
+
// First call initializes the registry
|
|
15879
|
+
const initSource = `u8 x;`;
|
|
15880
|
+
const { tree: initTree, tokenStream: initTokenStream } =
|
|
15881
|
+
CNextSourceParser.parse(initSource);
|
|
15882
|
+
const generator = new CodeGenerator();
|
|
15883
|
+
const initSymbolTable = new SymbolTable();
|
|
15884
|
+
const initTSymbols = CNextResolver.resolve(initTree, "init.cnx");
|
|
15885
|
+
const initSymbols = TSymbolInfoAdapter.convert(initTSymbols);
|
|
15886
|
+
generator.generate(initTree, initSymbolTable, initTokenStream, {
|
|
15887
|
+
symbolInfo: initSymbols,
|
|
15888
|
+
sourcePath: "init.cnx",
|
|
15889
|
+
});
|
|
15890
|
+
|
|
15891
|
+
// Unregister the struct generator to test error path
|
|
15892
|
+
const registry = (
|
|
15893
|
+
generator as unknown as {
|
|
15894
|
+
registry: { unregisterDeclaration: (kind: string) => void };
|
|
15895
|
+
}
|
|
15896
|
+
).registry;
|
|
15897
|
+
registry.unregisterDeclaration("struct");
|
|
15898
|
+
|
|
15899
|
+
// Second call should throw because struct generator is now missing
|
|
15900
|
+
const source = `struct Point { i32 x; i32 y; }`;
|
|
15901
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
15902
|
+
const symbolTable = new SymbolTable();
|
|
15903
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
15904
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
15905
|
+
|
|
15906
|
+
expect(() => {
|
|
15907
|
+
generator.generate(tree, symbolTable, tokenStream, {
|
|
15908
|
+
symbolInfo: symbols,
|
|
15909
|
+
sourcePath: "test.cnx",
|
|
15910
|
+
});
|
|
15911
|
+
}).toThrow("Error: struct generator not registered");
|
|
15912
|
+
});
|
|
15913
|
+
|
|
15914
|
+
it("throws error when enum generator is not registered", () => {
|
|
15915
|
+
// First call initializes the registry
|
|
15916
|
+
const initSource = `u8 x;`;
|
|
15917
|
+
const { tree: initTree, tokenStream: initTokenStream } =
|
|
15918
|
+
CNextSourceParser.parse(initSource);
|
|
15919
|
+
const generator = new CodeGenerator();
|
|
15920
|
+
const initSymbolTable = new SymbolTable();
|
|
15921
|
+
const initTSymbols = CNextResolver.resolve(initTree, "init.cnx");
|
|
15922
|
+
const initSymbols = TSymbolInfoAdapter.convert(initTSymbols);
|
|
15923
|
+
generator.generate(initTree, initSymbolTable, initTokenStream, {
|
|
15924
|
+
symbolInfo: initSymbols,
|
|
15925
|
+
sourcePath: "init.cnx",
|
|
15926
|
+
});
|
|
15927
|
+
|
|
15928
|
+
// Unregister the enum generator to test error path
|
|
15929
|
+
const registry = (
|
|
15930
|
+
generator as unknown as {
|
|
15931
|
+
registry: { unregisterDeclaration: (kind: string) => void };
|
|
15932
|
+
}
|
|
15933
|
+
).registry;
|
|
15934
|
+
registry.unregisterDeclaration("enum");
|
|
15935
|
+
|
|
15936
|
+
// Second call should throw because enum generator is now missing
|
|
15937
|
+
const source = `enum State { IDLE, RUNNING }`;
|
|
15938
|
+
const { tree, tokenStream } = CNextSourceParser.parse(source);
|
|
15939
|
+
const symbolTable = new SymbolTable();
|
|
15940
|
+
const tSymbols = CNextResolver.resolve(tree, "test.cnx");
|
|
15941
|
+
const symbols = TSymbolInfoAdapter.convert(tSymbols);
|
|
15942
|
+
|
|
15943
|
+
expect(() => {
|
|
15944
|
+
generator.generate(tree, symbolTable, tokenStream, {
|
|
15945
|
+
symbolInfo: symbols,
|
|
15946
|
+
sourcePath: "test.cnx",
|
|
15947
|
+
});
|
|
15948
|
+
}).toThrow("Error: enum generator not registered");
|
|
15949
|
+
});
|
|
15950
|
+
});
|
|
15549
15951
|
});
|