agency-lang 0.0.16 → 0.0.18

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.
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { functionParser, docStringParser } from "./function.js";
2
+ import { functionParser, docStringParser, graphNodeParser } from "./function.js";
3
3
  describe("docStringParser", () => {
4
4
  const testCases = [
5
5
  // Happy path - basic docstrings
@@ -124,6 +124,7 @@ describe("functionParser", () => {
124
124
  type: "function",
125
125
  functionName: "test",
126
126
  parameters: [],
127
+ returnType: null,
127
128
  docString: undefined,
128
129
  body: [
129
130
  {
@@ -143,6 +144,7 @@ describe("functionParser", () => {
143
144
  type: "function",
144
145
  functionName: "greet",
145
146
  parameters: [],
147
+ returnType: null,
146
148
  docString: undefined,
147
149
  body: [
148
150
  {
@@ -165,6 +167,7 @@ describe("functionParser", () => {
165
167
  type: "function",
166
168
  functionName: "calculate",
167
169
  parameters: [],
170
+ returnType: null,
168
171
  docString: undefined,
169
172
  body: [
170
173
  {
@@ -189,6 +192,7 @@ describe("functionParser", () => {
189
192
  type: "function",
190
193
  functionName: "empty",
191
194
  parameters: [],
195
+ returnType: null,
192
196
  docString: undefined,
193
197
  body: [],
194
198
  },
@@ -202,6 +206,7 @@ describe("functionParser", () => {
202
206
  type: "function",
203
207
  functionName: "withSpaces",
204
208
  parameters: [],
209
+ returnType: null,
205
210
  docString: undefined,
206
211
  body: [
207
212
  {
@@ -221,6 +226,7 @@ describe("functionParser", () => {
221
226
  type: "function",
222
227
  functionName: "noSpaces",
223
228
  parameters: [],
229
+ returnType: null,
224
230
  docString: undefined,
225
231
  body: [
226
232
  {
@@ -240,6 +246,7 @@ describe("functionParser", () => {
240
246
  type: "function",
241
247
  functionName: "multiline",
242
248
  parameters: [],
249
+ returnType: null,
243
250
  docString: undefined,
244
251
  body: [
245
252
  {
@@ -289,6 +296,7 @@ describe("functionParser", () => {
289
296
  type: "function",
290
297
  functionName: "test",
291
298
  parameters: [],
299
+ returnType: null,
292
300
  docString: {
293
301
  type: "docString",
294
302
  value: "This is a test function",
@@ -311,6 +319,7 @@ describe("functionParser", () => {
311
319
  type: "function",
312
320
  functionName: "greet",
313
321
  parameters: [],
322
+ returnType: null,
314
323
  docString: {
315
324
  type: "docString",
316
325
  value: "Greets the user",
@@ -336,6 +345,7 @@ describe("functionParser", () => {
336
345
  type: "function",
337
346
  functionName: "calculate",
338
347
  parameters: [],
348
+ returnType: null,
339
349
  docString: {
340
350
  type: "docString",
341
351
  value: "Calculate something",
@@ -363,6 +373,7 @@ describe("functionParser", () => {
363
373
  type: "function",
364
374
  functionName: "empty",
365
375
  parameters: [],
376
+ returnType: null,
366
377
  docString: {
367
378
  type: "docString",
368
379
  value: "Empty function with docstring",
@@ -379,6 +390,7 @@ describe("functionParser", () => {
379
390
  type: "function",
380
391
  functionName: "multilineDoc",
381
392
  parameters: [],
393
+ returnType: null,
382
394
  docString: {
383
395
  type: "docString",
384
396
  value: "This is a multi-line\n docstring",
@@ -402,6 +414,7 @@ describe("functionParser", () => {
402
414
  type: "function",
403
415
  functionName: "add",
404
416
  parameters: [{ type: "functionParameter", name: "x" }],
417
+ returnType: null,
405
418
  docString: undefined,
406
419
  body: [
407
420
  {
@@ -420,6 +433,7 @@ describe("functionParser", () => {
420
433
  type: "function",
421
434
  functionName: "greet",
422
435
  parameters: [{ type: "functionParameter", name: "name" }],
436
+ returnType: null,
423
437
  docString: undefined,
424
438
  body: [
425
439
  {
@@ -449,6 +463,7 @@ describe("functionParser", () => {
449
463
  { type: "functionParameter", name: "x" },
450
464
  { type: "functionParameter", name: "y" },
451
465
  ],
466
+ returnType: null,
452
467
  docString: undefined,
453
468
  body: [
454
469
  {
@@ -471,6 +486,7 @@ describe("functionParser", () => {
471
486
  { type: "functionParameter", name: "b" },
472
487
  { type: "functionParameter", name: "c" },
473
488
  ],
489
+ returnType: null,
474
490
  docString: undefined,
475
491
  body: [
476
492
  {
@@ -497,6 +513,7 @@ describe("functionParser", () => {
497
513
  { type: "functionParameter", name: "x" },
498
514
  { type: "functionParameter", name: "y" },
499
515
  ],
516
+ returnType: null,
500
517
  docString: undefined,
501
518
  body: [
502
519
  {
@@ -518,6 +535,7 @@ describe("functionParser", () => {
518
535
  { type: "functionParameter", name: "a" },
519
536
  { type: "functionParameter", name: "b" },
520
537
  ],
538
+ returnType: null,
521
539
  docString: undefined,
522
540
  body: [
523
541
  {
@@ -540,6 +558,7 @@ describe("functionParser", () => {
540
558
  { type: "functionParameter", name: "x" },
541
559
  { type: "functionParameter", name: "y" },
542
560
  ],
561
+ returnType: null,
543
562
  docString: {
544
563
  type: "docString",
545
564
  value: "Adds two numbers",
@@ -564,6 +583,7 @@ describe("functionParser", () => {
564
583
  { type: "functionParameter", name: "name" },
565
584
  { type: "functionParameter", name: "greeting" },
566
585
  ],
586
+ returnType: null,
567
587
  docString: {
568
588
  type: "docString",
569
589
  value: "Greets someone with a custom greeting",
@@ -604,6 +624,7 @@ describe("functionParser", () => {
604
624
  typeHint: { type: "primitiveType", value: "number" },
605
625
  },
606
626
  ],
627
+ returnType: null,
607
628
  docString: undefined,
608
629
  body: [{ type: "variableName", value: "x" }],
609
630
  },
@@ -623,6 +644,7 @@ describe("functionParser", () => {
623
644
  typeHint: { type: "primitiveType", value: "string" },
624
645
  },
625
646
  ],
647
+ returnType: null,
626
648
  docString: undefined,
627
649
  body: [{ type: "variableName", value: "name" }],
628
650
  },
@@ -642,6 +664,7 @@ describe("functionParser", () => {
642
664
  typeHint: { type: "primitiveType", value: "boolean" },
643
665
  },
644
666
  ],
667
+ returnType: null,
645
668
  docString: undefined,
646
669
  body: [{ type: "variableName", value: "active" }],
647
670
  },
@@ -661,6 +684,7 @@ describe("functionParser", () => {
661
684
  typeHint: { type: "typeAliasVariable", aliasName: "any" },
662
685
  },
663
686
  ],
687
+ returnType: null,
664
688
  docString: undefined,
665
689
  body: [{ type: "variableName", value: "data" }],
666
690
  },
@@ -680,6 +704,7 @@ describe("functionParser", () => {
680
704
  typeHint: { type: "primitiveType", value: "number" },
681
705
  },
682
706
  ],
707
+ returnType: null,
683
708
  docString: undefined,
684
709
  body: [{ type: "variableName", value: "x" }],
685
710
  },
@@ -705,6 +730,7 @@ describe("functionParser", () => {
705
730
  typeHint: { type: "primitiveType", value: "number" },
706
731
  },
707
732
  ],
733
+ returnType: null,
708
734
  docString: undefined,
709
735
  body: [{ type: "variableName", value: "x" }],
710
736
  },
@@ -734,6 +760,7 @@ describe("functionParser", () => {
734
760
  typeHint: { type: "primitiveType", value: "string" },
735
761
  },
736
762
  ],
763
+ returnType: null,
737
764
  docString: undefined,
738
765
  body: [{ type: "variableName", value: "a" }],
739
766
  },
@@ -758,6 +785,7 @@ describe("functionParser", () => {
758
785
  typeHint: { type: "primitiveType", value: "string" },
759
786
  },
760
787
  ],
788
+ returnType: null,
761
789
  docString: undefined,
762
790
  body: [{ type: "variableName", value: "x" }],
763
791
  },
@@ -782,6 +810,7 @@ describe("functionParser", () => {
782
810
  typeHint: { type: "primitiveType", value: "number" },
783
811
  },
784
812
  ],
813
+ returnType: null,
785
814
  docString: undefined,
786
815
  body: [{ type: "variableName", value: "x" }],
787
816
  },
@@ -803,6 +832,7 @@ describe("functionParser", () => {
803
832
  },
804
833
  { type: "functionParameter", name: "y" },
805
834
  ],
835
+ returnType: null,
806
836
  docString: undefined,
807
837
  body: [{ type: "variableName", value: "x" }],
808
838
  },
@@ -824,6 +854,7 @@ describe("functionParser", () => {
824
854
  },
825
855
  { type: "functionParameter", name: "c" },
826
856
  ],
857
+ returnType: null,
827
858
  docString: undefined,
828
859
  body: [{ type: "variableName", value: "a" }],
829
860
  },
@@ -844,6 +875,7 @@ describe("functionParser", () => {
844
875
  },
845
876
  { type: "functionParameter", name: "untyped" },
846
877
  ],
878
+ returnType: null,
847
879
  docString: undefined,
848
880
  body: [{ type: "variableName", value: "typed" }],
849
881
  },
@@ -867,6 +899,7 @@ describe("functionParser", () => {
867
899
  },
868
900
  },
869
901
  ],
902
+ returnType: null,
870
903
  docString: undefined,
871
904
  body: [{ type: "variableName", value: "items" }],
872
905
  },
@@ -889,6 +922,7 @@ describe("functionParser", () => {
889
922
  },
890
923
  },
891
924
  ],
925
+ returnType: null,
892
926
  docString: undefined,
893
927
  body: [{ type: "variableName", value: "names" }],
894
928
  },
@@ -908,6 +942,7 @@ describe("functionParser", () => {
908
942
  typeHint: { type: "typeAliasVariable", aliasName: "object" },
909
943
  },
910
944
  ],
945
+ returnType: null,
911
946
  docString: undefined,
912
947
  body: [{ type: "variableName", value: "obj" }],
913
948
  },
@@ -935,6 +970,7 @@ describe("functionParser", () => {
935
970
  typeHint: { type: "primitiveType", value: "number" },
936
971
  },
937
972
  ],
973
+ returnType: null,
938
974
  docString: undefined,
939
975
  body: [{ type: "variableName", value: "arr" }],
940
976
  },
@@ -960,6 +996,7 @@ describe("functionParser", () => {
960
996
  },
961
997
  },
962
998
  ],
999
+ returnType: null,
963
1000
  docString: undefined,
964
1001
  body: [{ type: "variableName", value: "matrix" }],
965
1002
  },
@@ -986,6 +1023,7 @@ describe("functionParser", () => {
986
1023
  },
987
1024
  },
988
1025
  ],
1026
+ returnType: null,
989
1027
  docString: undefined,
990
1028
  body: [{ type: "variableName", value: "value" }],
991
1029
  },
@@ -1012,6 +1050,7 @@ describe("functionParser", () => {
1012
1050
  },
1013
1051
  },
1014
1052
  ],
1053
+ returnType: null,
1015
1054
  docString: undefined,
1016
1055
  body: [{ type: "variableName", value: "x" }],
1017
1056
  },
@@ -1042,6 +1081,7 @@ describe("functionParser", () => {
1042
1081
  typeHint: { type: "primitiveType", value: "boolean" },
1043
1082
  },
1044
1083
  ],
1084
+ returnType: null,
1045
1085
  docString: undefined,
1046
1086
  body: [{ type: "variableName", value: "a" }],
1047
1087
  },
@@ -1067,6 +1107,7 @@ describe("functionParser", () => {
1067
1107
  typeHint: { type: "primitiveType", value: "number" },
1068
1108
  },
1069
1109
  ],
1110
+ returnType: null,
1070
1111
  docString: {
1071
1112
  type: "docString",
1072
1113
  value: "Adds two numbers",
@@ -1089,6 +1130,7 @@ describe("functionParser", () => {
1089
1130
  typeHint: { type: "primitiveType", value: "string" },
1090
1131
  },
1091
1132
  ],
1133
+ returnType: null,
1092
1134
  docString: {
1093
1135
  type: "docString",
1094
1136
  value: "Greets a person by name",
@@ -1112,6 +1154,7 @@ describe("functionParser", () => {
1112
1154
  },
1113
1155
  { type: "functionParameter", name: "untyped" },
1114
1156
  ],
1157
+ returnType: null,
1115
1158
  docString: {
1116
1159
  type: "docString",
1117
1160
  value: "Mix of typed and untyped params",
@@ -1135,6 +1178,7 @@ describe("functionParser", () => {
1135
1178
  typeHint: { type: "primitiveType", value: "number" },
1136
1179
  },
1137
1180
  ],
1181
+ returnType: null,
1138
1182
  docString: undefined,
1139
1183
  body: [{ type: "variableName", value: "x" }],
1140
1184
  },
@@ -1159,6 +1203,7 @@ describe("functionParser", () => {
1159
1203
  typeHint: { type: "primitiveType", value: "string" },
1160
1204
  },
1161
1205
  ],
1206
+ returnType: null,
1162
1207
  docString: undefined,
1163
1208
  body: [{ type: "variableName", value: "x" }],
1164
1209
  },
@@ -1178,6 +1223,7 @@ describe("functionParser", () => {
1178
1223
  typeHint: { type: "primitiveType", value: "string" },
1179
1224
  },
1180
1225
  ],
1226
+ returnType: null,
1181
1227
  docString: undefined,
1182
1228
  body: [{ type: "variableName", value: "my_var" }],
1183
1229
  },
@@ -1194,32 +1240,842 @@ describe("functionParser", () => {
1194
1240
  {
1195
1241
  type: "functionParameter",
1196
1242
  name: "data",
1197
- typeHint: { type: "typeAliasVariable", aliasName: "SomeLongTypeName" },
1243
+ typeHint: {
1244
+ type: "typeAliasVariable",
1245
+ aliasName: "SomeLongTypeName",
1246
+ },
1247
+ },
1248
+ ],
1249
+ returnType: null,
1250
+ docString: undefined,
1251
+ body: [{ type: "variableName", value: "data" }],
1252
+ },
1253
+ },
1254
+ },
1255
+ // Failure cases for type hints
1256
+ {
1257
+ input: "def bad(x:) { x }",
1258
+ expected: { success: false },
1259
+ },
1260
+ {
1261
+ input: "def bad(: number) { x }",
1262
+ expected: { success: false },
1263
+ },
1264
+ {
1265
+ input: "def bad(x: number y: string) { x }",
1266
+ expected: { success: false },
1267
+ },
1268
+ // Functions with return types - primitive types
1269
+ {
1270
+ input: "def getNumber(): number { 42 }",
1271
+ expected: {
1272
+ success: true,
1273
+ result: {
1274
+ type: "function",
1275
+ functionName: "getNumber",
1276
+ parameters: [],
1277
+ returnType: { type: "primitiveType", value: "number" },
1278
+ docString: undefined,
1279
+ body: [{ type: "number", value: "42" }],
1280
+ },
1281
+ },
1282
+ },
1283
+ {
1284
+ input: "def getString(): string { name }",
1285
+ expected: {
1286
+ success: true,
1287
+ result: {
1288
+ type: "function",
1289
+ functionName: "getString",
1290
+ parameters: [],
1291
+ returnType: { type: "primitiveType", value: "string" },
1292
+ docString: undefined,
1293
+ body: [{ type: "variableName", value: "name" }],
1294
+ },
1295
+ },
1296
+ },
1297
+ {
1298
+ input: "def getBoolean(): boolean { true }",
1299
+ expected: {
1300
+ success: true,
1301
+ result: {
1302
+ type: "function",
1303
+ functionName: "getBoolean",
1304
+ parameters: [],
1305
+ returnType: { type: "primitiveType", value: "boolean" },
1306
+ docString: undefined,
1307
+ body: [{ type: "variableName", value: "true" }],
1308
+ },
1309
+ },
1310
+ },
1311
+ // Functions with return types and parameters
1312
+ {
1313
+ input: "def add(x: number, y: number): number { x }",
1314
+ expected: {
1315
+ success: true,
1316
+ result: {
1317
+ type: "function",
1318
+ functionName: "add",
1319
+ parameters: [
1320
+ {
1321
+ type: "functionParameter",
1322
+ name: "x",
1323
+ typeHint: { type: "primitiveType", value: "number" },
1324
+ },
1325
+ {
1326
+ type: "functionParameter",
1327
+ name: "y",
1328
+ typeHint: { type: "primitiveType", value: "number" },
1329
+ },
1330
+ ],
1331
+ returnType: { type: "primitiveType", value: "number" },
1332
+ docString: undefined,
1333
+ body: [{ type: "variableName", value: "x" }],
1334
+ },
1335
+ },
1336
+ },
1337
+ {
1338
+ input: "def greet(name: string): string { name }",
1339
+ expected: {
1340
+ success: true,
1341
+ result: {
1342
+ type: "function",
1343
+ functionName: "greet",
1344
+ parameters: [
1345
+ {
1346
+ type: "functionParameter",
1347
+ name: "name",
1348
+ typeHint: { type: "primitiveType", value: "string" },
1349
+ },
1350
+ ],
1351
+ returnType: { type: "primitiveType", value: "string" },
1352
+ docString: undefined,
1353
+ body: [{ type: "variableName", value: "name" }],
1354
+ },
1355
+ },
1356
+ },
1357
+ {
1358
+ input: "def check(value): boolean { value }",
1359
+ expected: {
1360
+ success: true,
1361
+ result: {
1362
+ type: "function",
1363
+ functionName: "check",
1364
+ parameters: [{ type: "functionParameter", name: "value" }],
1365
+ returnType: { type: "primitiveType", value: "boolean" },
1366
+ docString: undefined,
1367
+ body: [{ type: "variableName", value: "value" }],
1368
+ },
1369
+ },
1370
+ },
1371
+ // Functions with array return types
1372
+ {
1373
+ input: "def getNumbers(): number[] { items }",
1374
+ expected: {
1375
+ success: true,
1376
+ result: {
1377
+ type: "function",
1378
+ functionName: "getNumbers",
1379
+ parameters: [],
1380
+ returnType: {
1381
+ type: "arrayType",
1382
+ elementType: { type: "primitiveType", value: "number" },
1383
+ },
1384
+ docString: undefined,
1385
+ body: [{ type: "variableName", value: "items" }],
1386
+ },
1387
+ },
1388
+ },
1389
+ {
1390
+ input: "def getStrings(): string[] { names }",
1391
+ expected: {
1392
+ success: true,
1393
+ result: {
1394
+ type: "function",
1395
+ functionName: "getStrings",
1396
+ parameters: [],
1397
+ returnType: {
1398
+ type: "arrayType",
1399
+ elementType: { type: "primitiveType", value: "string" },
1400
+ },
1401
+ docString: undefined,
1402
+ body: [{ type: "variableName", value: "names" }],
1403
+ },
1404
+ },
1405
+ },
1406
+ {
1407
+ input: "def processArray(items: number[]): number[] { items }",
1408
+ expected: {
1409
+ success: true,
1410
+ result: {
1411
+ type: "function",
1412
+ functionName: "processArray",
1413
+ parameters: [
1414
+ {
1415
+ type: "functionParameter",
1416
+ name: "items",
1417
+ typeHint: {
1418
+ type: "arrayType",
1419
+ elementType: { type: "primitiveType", value: "number" },
1420
+ },
1421
+ },
1422
+ ],
1423
+ returnType: {
1424
+ type: "arrayType",
1425
+ elementType: { type: "primitiveType", value: "number" },
1426
+ },
1427
+ docString: undefined,
1428
+ body: [{ type: "variableName", value: "items" }],
1429
+ },
1430
+ },
1431
+ },
1432
+ // Functions with union return types
1433
+ {
1434
+ input: "def getValue(): string | number { value }",
1435
+ expected: {
1436
+ success: true,
1437
+ result: {
1438
+ type: "function",
1439
+ functionName: "getValue",
1440
+ parameters: [],
1441
+ returnType: {
1442
+ type: "unionType",
1443
+ types: [
1444
+ { type: "primitiveType", value: "string" },
1445
+ { type: "primitiveType", value: "number" },
1446
+ ],
1447
+ },
1448
+ docString: undefined,
1449
+ body: [{ type: "variableName", value: "value" }],
1450
+ },
1451
+ },
1452
+ },
1453
+ {
1454
+ input: "def flexible(x: number): string | number | boolean { x }",
1455
+ expected: {
1456
+ success: true,
1457
+ result: {
1458
+ type: "function",
1459
+ functionName: "flexible",
1460
+ parameters: [
1461
+ {
1462
+ type: "functionParameter",
1463
+ name: "x",
1464
+ typeHint: { type: "primitiveType", value: "number" },
1465
+ },
1466
+ ],
1467
+ returnType: {
1468
+ type: "unionType",
1469
+ types: [
1470
+ { type: "primitiveType", value: "string" },
1471
+ { type: "primitiveType", value: "number" },
1472
+ { type: "primitiveType", value: "boolean" },
1473
+ ],
1474
+ },
1475
+ docString: undefined,
1476
+ body: [{ type: "variableName", value: "x" }],
1477
+ },
1478
+ },
1479
+ },
1480
+ // Functions with return types and docstrings
1481
+ {
1482
+ input: 'def add(x: number, y: number): number {\n """Adds two numbers"""\n x\n}',
1483
+ expected: {
1484
+ success: true,
1485
+ result: {
1486
+ type: "function",
1487
+ functionName: "add",
1488
+ parameters: [
1489
+ {
1490
+ type: "functionParameter",
1491
+ name: "x",
1492
+ typeHint: { type: "primitiveType", value: "number" },
1493
+ },
1494
+ {
1495
+ type: "functionParameter",
1496
+ name: "y",
1497
+ typeHint: { type: "primitiveType", value: "number" },
1498
+ },
1499
+ ],
1500
+ returnType: { type: "primitiveType", value: "number" },
1501
+ docString: {
1502
+ type: "docString",
1503
+ value: "Adds two numbers",
1504
+ },
1505
+ body: [{ type: "variableName", value: "x" }],
1506
+ },
1507
+ },
1508
+ },
1509
+ {
1510
+ input: 'def greet(name: string): string {\n """Greets a person"""\n name\n}',
1511
+ expected: {
1512
+ success: true,
1513
+ result: {
1514
+ type: "function",
1515
+ functionName: "greet",
1516
+ parameters: [
1517
+ {
1518
+ type: "functionParameter",
1519
+ name: "name",
1520
+ typeHint: { type: "primitiveType", value: "string" },
1521
+ },
1522
+ ],
1523
+ returnType: { type: "primitiveType", value: "string" },
1524
+ docString: {
1525
+ type: "docString",
1526
+ value: "Greets a person",
1527
+ },
1528
+ body: [{ type: "variableName", value: "name" }],
1529
+ },
1530
+ },
1531
+ },
1532
+ // Functions with whitespace variations in return types
1533
+ {
1534
+ input: "def foo():number { 1 }",
1535
+ expected: {
1536
+ success: true,
1537
+ result: {
1538
+ type: "function",
1539
+ functionName: "foo",
1540
+ parameters: [],
1541
+ returnType: { type: "primitiveType", value: "number" },
1542
+ docString: undefined,
1543
+ body: [{ type: "number", value: "1" }],
1544
+ },
1545
+ },
1546
+ },
1547
+ {
1548
+ input: "def bar() : string { name }",
1549
+ expected: {
1550
+ success: true,
1551
+ result: {
1552
+ type: "function",
1553
+ functionName: "bar",
1554
+ parameters: [],
1555
+ returnType: { type: "primitiveType", value: "string" },
1556
+ docString: undefined,
1557
+ body: [{ type: "variableName", value: "name" }],
1558
+ },
1559
+ },
1560
+ },
1561
+ {
1562
+ input: "def baz(x: number) : number { x }",
1563
+ expected: {
1564
+ success: true,
1565
+ result: {
1566
+ type: "function",
1567
+ functionName: "baz",
1568
+ parameters: [
1569
+ {
1570
+ type: "functionParameter",
1571
+ name: "x",
1572
+ typeHint: { type: "primitiveType", value: "number" },
1573
+ },
1574
+ ],
1575
+ returnType: { type: "primitiveType", value: "number" },
1576
+ docString: undefined,
1577
+ body: [{ type: "variableName", value: "x" }],
1578
+ },
1579
+ },
1580
+ },
1581
+ // Functions with type alias return types
1582
+ {
1583
+ input: "def getPoint(): Point { point }",
1584
+ expected: {
1585
+ success: true,
1586
+ result: {
1587
+ type: "function",
1588
+ functionName: "getPoint",
1589
+ parameters: [],
1590
+ returnType: { type: "typeAliasVariable", aliasName: "Point" },
1591
+ docString: undefined,
1592
+ body: [{ type: "variableName", value: "point" }],
1593
+ },
1594
+ },
1595
+ },
1596
+ {
1597
+ input: "def getData(id: number): UserData { data }",
1598
+ expected: {
1599
+ success: true,
1600
+ result: {
1601
+ type: "function",
1602
+ functionName: "getData",
1603
+ parameters: [
1604
+ {
1605
+ type: "functionParameter",
1606
+ name: "id",
1607
+ typeHint: { type: "primitiveType", value: "number" },
1608
+ },
1609
+ ],
1610
+ returnType: { type: "typeAliasVariable", aliasName: "UserData" },
1611
+ docString: undefined,
1612
+ body: [{ type: "variableName", value: "data" }],
1613
+ },
1614
+ },
1615
+ },
1616
+ // Functions with object return types
1617
+ {
1618
+ input: "def getCoords(): { x: number; y: number } { coords }",
1619
+ expected: {
1620
+ success: true,
1621
+ result: {
1622
+ type: "function",
1623
+ functionName: "getCoords",
1624
+ parameters: [],
1625
+ returnType: {
1626
+ type: "objectType",
1627
+ properties: [
1628
+ {
1629
+ key: "x",
1630
+ value: { type: "primitiveType", value: "number" },
1631
+ },
1632
+ {
1633
+ key: "y",
1634
+ value: { type: "primitiveType", value: "number" },
1635
+ },
1636
+ ],
1637
+ },
1638
+ docString: undefined,
1639
+ body: [{ type: "variableName", value: "coords" }],
1640
+ },
1641
+ },
1642
+ },
1643
+ // Failure cases for return types
1644
+ {
1645
+ input: "def bad(): { x }",
1646
+ expected: { success: false },
1647
+ },
1648
+ {
1649
+ input: "def bad() : { x }",
1650
+ expected: { success: false },
1651
+ },
1652
+ ];
1653
+ testCases.forEach(({ input, expected }) => {
1654
+ if (expected.success) {
1655
+ it(`should parse "${input.replace(/\n/g, "\\n")}" successfully`, () => {
1656
+ const result = functionParser(input);
1657
+ expect(result.success).toBe(true);
1658
+ if (result.success) {
1659
+ expect(result.result).toEqual(expected.result);
1660
+ }
1661
+ });
1662
+ }
1663
+ else {
1664
+ it(`should fail to parse "${input.replace(/\n/g, "\\n")}"`, () => {
1665
+ const result = functionParser(input);
1666
+ expect(result.success).toBe(false);
1667
+ });
1668
+ }
1669
+ });
1670
+ });
1671
+ describe("graphNodeParser", () => {
1672
+ const testCases = [
1673
+ // Basic graph nodes without return types
1674
+ {
1675
+ input: "node main() { x = 1 }",
1676
+ expected: {
1677
+ success: true,
1678
+ result: {
1679
+ type: "graphNode",
1680
+ nodeName: "main",
1681
+ parameters: [],
1682
+ returnType: null,
1683
+ body: [
1684
+ {
1685
+ type: "assignment",
1686
+ variableName: "x",
1687
+ value: { type: "number", value: "1" },
1198
1688
  },
1199
1689
  ],
1200
- docString: undefined,
1690
+ },
1691
+ },
1692
+ },
1693
+ {
1694
+ input: "node greet() { message = `hello` }",
1695
+ expected: {
1696
+ success: true,
1697
+ result: {
1698
+ type: "graphNode",
1699
+ nodeName: "greet",
1700
+ parameters: [],
1701
+ returnType: null,
1702
+ body: [
1703
+ {
1704
+ type: "assignment",
1705
+ variableName: "message",
1706
+ value: {
1707
+ type: "prompt",
1708
+ segments: [{ type: "text", value: "hello" }],
1709
+ },
1710
+ },
1711
+ ],
1712
+ },
1713
+ },
1714
+ },
1715
+ {
1716
+ input: "node empty() {}",
1717
+ expected: {
1718
+ success: true,
1719
+ result: {
1720
+ type: "graphNode",
1721
+ nodeName: "empty",
1722
+ parameters: [],
1723
+ returnType: null,
1724
+ body: [],
1725
+ },
1726
+ },
1727
+ },
1728
+ // Graph nodes with parameters
1729
+ {
1730
+ input: "node process(input) { x = input }",
1731
+ expected: {
1732
+ success: true,
1733
+ result: {
1734
+ type: "graphNode",
1735
+ nodeName: "process",
1736
+ parameters: ["input"],
1737
+ returnType: null,
1738
+ body: [
1739
+ {
1740
+ type: "assignment",
1741
+ variableName: "x",
1742
+ value: { type: "variableName", value: "input" },
1743
+ },
1744
+ ],
1745
+ },
1746
+ },
1747
+ },
1748
+ {
1749
+ input: "node calculate(a, b) { result = 42 }",
1750
+ expected: {
1751
+ success: true,
1752
+ result: {
1753
+ type: "graphNode",
1754
+ nodeName: "calculate",
1755
+ parameters: ["a", "b"],
1756
+ returnType: null,
1757
+ body: [
1758
+ {
1759
+ type: "assignment",
1760
+ variableName: "result",
1761
+ value: { type: "number", value: "42" },
1762
+ },
1763
+ ],
1764
+ },
1765
+ },
1766
+ },
1767
+ // Graph nodes with return types - primitive types
1768
+ {
1769
+ input: "node getNumber(): number { 42 }",
1770
+ expected: {
1771
+ success: true,
1772
+ result: {
1773
+ type: "graphNode",
1774
+ nodeName: "getNumber",
1775
+ parameters: [],
1776
+ returnType: { type: "primitiveType", value: "number" },
1777
+ body: [{ type: "number", value: "42" }],
1778
+ },
1779
+ },
1780
+ },
1781
+ {
1782
+ input: "node getString(): string { name }",
1783
+ expected: {
1784
+ success: true,
1785
+ result: {
1786
+ type: "graphNode",
1787
+ nodeName: "getString",
1788
+ parameters: [],
1789
+ returnType: { type: "primitiveType", value: "string" },
1790
+ body: [{ type: "variableName", value: "name" }],
1791
+ },
1792
+ },
1793
+ },
1794
+ {
1795
+ input: "node getBoolean(): boolean { true }",
1796
+ expected: {
1797
+ success: true,
1798
+ result: {
1799
+ type: "graphNode",
1800
+ nodeName: "getBoolean",
1801
+ parameters: [],
1802
+ returnType: { type: "primitiveType", value: "boolean" },
1803
+ body: [{ type: "variableName", value: "true" }],
1804
+ },
1805
+ },
1806
+ },
1807
+ // Graph nodes with parameters and return types
1808
+ {
1809
+ input: "node add(x, y): number { result = 10 }",
1810
+ expected: {
1811
+ success: true,
1812
+ result: {
1813
+ type: "graphNode",
1814
+ nodeName: "add",
1815
+ parameters: ["x", "y"],
1816
+ returnType: { type: "primitiveType", value: "number" },
1817
+ body: [
1818
+ {
1819
+ type: "assignment",
1820
+ variableName: "result",
1821
+ value: { type: "number", value: "10" },
1822
+ },
1823
+ ],
1824
+ },
1825
+ },
1826
+ },
1827
+ {
1828
+ input: "node greet(name): string { message = `hello` }",
1829
+ expected: {
1830
+ success: true,
1831
+ result: {
1832
+ type: "graphNode",
1833
+ nodeName: "greet",
1834
+ parameters: ["name"],
1835
+ returnType: { type: "primitiveType", value: "string" },
1836
+ body: [
1837
+ {
1838
+ type: "assignment",
1839
+ variableName: "message",
1840
+ value: {
1841
+ type: "prompt",
1842
+ segments: [{ type: "text", value: "hello" }],
1843
+ },
1844
+ },
1845
+ ],
1846
+ },
1847
+ },
1848
+ },
1849
+ {
1850
+ input: "node process(input): boolean { result }",
1851
+ expected: {
1852
+ success: true,
1853
+ result: {
1854
+ type: "graphNode",
1855
+ nodeName: "process",
1856
+ parameters: ["input"],
1857
+ returnType: { type: "primitiveType", value: "boolean" },
1858
+ body: [{ type: "variableName", value: "result" }],
1859
+ },
1860
+ },
1861
+ },
1862
+ // Graph nodes with array return types
1863
+ {
1864
+ input: "node getNumbers(): number[] { items }",
1865
+ expected: {
1866
+ success: true,
1867
+ result: {
1868
+ type: "graphNode",
1869
+ nodeName: "getNumbers",
1870
+ parameters: [],
1871
+ returnType: {
1872
+ type: "arrayType",
1873
+ elementType: { type: "primitiveType", value: "number" },
1874
+ },
1875
+ body: [{ type: "variableName", value: "items" }],
1876
+ },
1877
+ },
1878
+ },
1879
+ {
1880
+ input: "node getStrings(): string[] { names }",
1881
+ expected: {
1882
+ success: true,
1883
+ result: {
1884
+ type: "graphNode",
1885
+ nodeName: "getStrings",
1886
+ parameters: [],
1887
+ returnType: {
1888
+ type: "arrayType",
1889
+ elementType: { type: "primitiveType", value: "string" },
1890
+ },
1891
+ body: [{ type: "variableName", value: "names" }],
1892
+ },
1893
+ },
1894
+ },
1895
+ {
1896
+ input: "node processArray(items): number[] { items }",
1897
+ expected: {
1898
+ success: true,
1899
+ result: {
1900
+ type: "graphNode",
1901
+ nodeName: "processArray",
1902
+ parameters: ["items"],
1903
+ returnType: {
1904
+ type: "arrayType",
1905
+ elementType: { type: "primitiveType", value: "number" },
1906
+ },
1907
+ body: [{ type: "variableName", value: "items" }],
1908
+ },
1909
+ },
1910
+ },
1911
+ // Graph nodes with union return types
1912
+ {
1913
+ input: "node getValue(): string | number { value }",
1914
+ expected: {
1915
+ success: true,
1916
+ result: {
1917
+ type: "graphNode",
1918
+ nodeName: "getValue",
1919
+ parameters: [],
1920
+ returnType: {
1921
+ type: "unionType",
1922
+ types: [
1923
+ { type: "primitiveType", value: "string" },
1924
+ { type: "primitiveType", value: "number" },
1925
+ ],
1926
+ },
1927
+ body: [{ type: "variableName", value: "value" }],
1928
+ },
1929
+ },
1930
+ },
1931
+ {
1932
+ input: "node flexible(x): string | number | boolean { x }",
1933
+ expected: {
1934
+ success: true,
1935
+ result: {
1936
+ type: "graphNode",
1937
+ nodeName: "flexible",
1938
+ parameters: ["x"],
1939
+ returnType: {
1940
+ type: "unionType",
1941
+ types: [
1942
+ { type: "primitiveType", value: "string" },
1943
+ { type: "primitiveType", value: "number" },
1944
+ { type: "primitiveType", value: "boolean" },
1945
+ ],
1946
+ },
1947
+ body: [{ type: "variableName", value: "x" }],
1948
+ },
1949
+ },
1950
+ },
1951
+ // Graph nodes with whitespace variations in return types
1952
+ {
1953
+ input: "node foo():number { 1 }",
1954
+ expected: {
1955
+ success: true,
1956
+ result: {
1957
+ type: "graphNode",
1958
+ nodeName: "foo",
1959
+ parameters: [],
1960
+ returnType: { type: "primitiveType", value: "number" },
1961
+ body: [{ type: "number", value: "1" }],
1962
+ },
1963
+ },
1964
+ },
1965
+ {
1966
+ input: "node bar() : string { name }",
1967
+ expected: {
1968
+ success: true,
1969
+ result: {
1970
+ type: "graphNode",
1971
+ nodeName: "bar",
1972
+ parameters: [],
1973
+ returnType: { type: "primitiveType", value: "string" },
1974
+ body: [{ type: "variableName", value: "name" }],
1975
+ },
1976
+ },
1977
+ },
1978
+ {
1979
+ input: "node baz(x) : number { x }",
1980
+ expected: {
1981
+ success: true,
1982
+ result: {
1983
+ type: "graphNode",
1984
+ nodeName: "baz",
1985
+ parameters: ["x"],
1986
+ returnType: { type: "primitiveType", value: "number" },
1987
+ body: [{ type: "variableName", value: "x" }],
1988
+ },
1989
+ },
1990
+ },
1991
+ // Graph nodes with type alias return types
1992
+ {
1993
+ input: "node getPoint(): Point { point }",
1994
+ expected: {
1995
+ success: true,
1996
+ result: {
1997
+ type: "graphNode",
1998
+ nodeName: "getPoint",
1999
+ parameters: [],
2000
+ returnType: { type: "typeAliasVariable", aliasName: "Point" },
2001
+ body: [{ type: "variableName", value: "point" }],
2002
+ },
2003
+ },
2004
+ },
2005
+ {
2006
+ input: "node getData(id): UserData { data }",
2007
+ expected: {
2008
+ success: true,
2009
+ result: {
2010
+ type: "graphNode",
2011
+ nodeName: "getData",
2012
+ parameters: ["id"],
2013
+ returnType: { type: "typeAliasVariable", aliasName: "UserData" },
1201
2014
  body: [{ type: "variableName", value: "data" }],
1202
2015
  },
1203
2016
  },
1204
2017
  },
1205
- // Failure cases for type hints
2018
+ // Graph nodes with object return types
1206
2019
  {
1207
- input: "def bad(x:) { x }",
2020
+ input: "node getCoords(): { x: number; y: number } { coords }",
2021
+ expected: {
2022
+ success: true,
2023
+ result: {
2024
+ type: "graphNode",
2025
+ nodeName: "getCoords",
2026
+ parameters: [],
2027
+ returnType: {
2028
+ type: "objectType",
2029
+ properties: [
2030
+ {
2031
+ key: "x",
2032
+ value: { type: "primitiveType", value: "number" },
2033
+ },
2034
+ {
2035
+ key: "y",
2036
+ value: { type: "primitiveType", value: "number" },
2037
+ },
2038
+ ],
2039
+ },
2040
+ body: [{ type: "variableName", value: "coords" }],
2041
+ },
2042
+ },
2043
+ },
2044
+ // Failure cases
2045
+ {
2046
+ input: "main() { x = 1 }",
1208
2047
  expected: { success: false },
1209
2048
  },
1210
2049
  {
1211
- input: "def bad(: number) { x }",
2050
+ input: "node { x = 1 }",
1212
2051
  expected: { success: false },
1213
2052
  },
1214
2053
  {
1215
- input: "def bad(x: number y: string) { x }",
2054
+ input: "node main() x = 1",
2055
+ expected: { success: false },
2056
+ },
2057
+ {
2058
+ input: "node main() {",
2059
+ expected: { success: false },
2060
+ },
2061
+ {
2062
+ input: "",
2063
+ expected: { success: false },
2064
+ },
2065
+ // Failure cases for return types
2066
+ {
2067
+ input: "node bad(): { x }",
2068
+ expected: { success: false },
2069
+ },
2070
+ {
2071
+ input: "node bad() : { x }",
1216
2072
  expected: { success: false },
1217
2073
  },
1218
2074
  ];
1219
2075
  testCases.forEach(({ input, expected }) => {
1220
2076
  if (expected.success) {
1221
2077
  it(`should parse "${input.replace(/\n/g, "\\n")}" successfully`, () => {
1222
- const result = functionParser(input);
2078
+ const result = graphNodeParser(input);
1223
2079
  expect(result.success).toBe(true);
1224
2080
  if (result.success) {
1225
2081
  expect(result.result).toEqual(expected.result);
@@ -1228,7 +2084,7 @@ describe("functionParser", () => {
1228
2084
  }
1229
2085
  else {
1230
2086
  it(`should fail to parse "${input.replace(/\n/g, "\\n")}"`, () => {
1231
- const result = functionParser(input);
2087
+ const result = graphNodeParser(input);
1232
2088
  expect(result.success).toBe(false);
1233
2089
  });
1234
2090
  }