@@ -1306,6 +1306,260 @@ TEST(LLVMTypeAnalyzer_ListType, IfElseWithEqualTypes_DifferentTypes_Empty)
13061306 ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, true ), Compiler::StaticType::String);
13071307}
13081308
1309+ TEST (LLVMTypeAnalyzer_ListType, IfStatementAfterLoop_SameTypes_NonEmpty)
1310+ {
1311+ LLVMTypeAnalyzer analyzer;
1312+ LLVMInstructionList instructionList;
1313+ List list (" " , " " );
1314+
1315+ auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
1316+ instructionList.addInstruction (loopStart);
1317+
1318+ // First write - does not change type
1319+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1320+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1321+ appendList1->workList = &list;
1322+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1323+ instructionList.addInstruction (appendList1);
1324+
1325+ auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
1326+ instructionList.addInstruction (loopEnd);
1327+
1328+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1329+ instructionList.addInstruction (ifStart);
1330+
1331+ // Second write - does not change type
1332+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1333+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 2 );
1334+ appendList2->workList = &list;
1335+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1336+ instructionList.addInstruction (appendList2);
1337+
1338+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1339+ instructionList.addInstruction (ifEnd);
1340+
1341+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1342+ instructionList.addInstruction (funcCall);
1343+
1344+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, false ), Compiler::StaticType::Number);
1345+ }
1346+
1347+ TEST (LLVMTypeAnalyzer_ListType, IfStatementAfterLoop_SameTypes_Empty)
1348+ {
1349+ LLVMTypeAnalyzer analyzer;
1350+ LLVMInstructionList instructionList;
1351+ List list (" " , " " );
1352+
1353+ auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
1354+ instructionList.addInstruction (loopStart);
1355+
1356+ // First write - establishes type for empty list
1357+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1358+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1359+ appendList1->workList = &list;
1360+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1361+ instructionList.addInstruction (appendList1);
1362+
1363+ auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
1364+ instructionList.addInstruction (loopEnd);
1365+
1366+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1367+ instructionList.addInstruction (ifStart);
1368+
1369+ // Second write - same type
1370+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1371+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 2 );
1372+ appendList2->workList = &list;
1373+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1374+ instructionList.addInstruction (appendList2);
1375+
1376+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1377+ instructionList.addInstruction (ifEnd);
1378+
1379+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1380+ instructionList.addInstruction (funcCall);
1381+
1382+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, true ), Compiler::StaticType::Number);
1383+ }
1384+
1385+ TEST (LLVMTypeAnalyzer_ListType, IfStatementAfterLoop_DifferentTypes_NonEmpty)
1386+ {
1387+ LLVMTypeAnalyzer analyzer;
1388+ LLVMInstructionList instructionList;
1389+ List list (" " , " " );
1390+
1391+ auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
1392+ instructionList.addInstruction (loopStart);
1393+
1394+ // First write - does not change type
1395+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1396+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1397+ appendList1->workList = &list;
1398+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1399+ instructionList.addInstruction (appendList1);
1400+
1401+ auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
1402+ instructionList.addInstruction (loopEnd);
1403+
1404+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1405+ instructionList.addInstruction (ifStart);
1406+
1407+ // Second write - changes type
1408+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1409+ LLVMConstantRegister value2 (Compiler::StaticType::String, " test" );
1410+ appendList2->workList = &list;
1411+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1412+ instructionList.addInstruction (appendList2);
1413+
1414+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1415+ instructionList.addInstruction (ifEnd);
1416+
1417+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1418+ instructionList.addInstruction (funcCall);
1419+
1420+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, false ), Compiler::StaticType::Unknown);
1421+ }
1422+
1423+ TEST (LLVMTypeAnalyzer_ListType, IfStatementAfterLoop_DifferentTypes_Empty)
1424+ {
1425+ LLVMTypeAnalyzer analyzer;
1426+ LLVMInstructionList instructionList;
1427+ List list (" " , " " );
1428+
1429+ auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
1430+ instructionList.addInstruction (loopStart);
1431+
1432+ // First write - establishes Number type for empty list
1433+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1434+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1435+ appendList1->workList = &list;
1436+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1437+ instructionList.addInstruction (appendList1);
1438+
1439+ auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
1440+ instructionList.addInstruction (loopEnd);
1441+
1442+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1443+ instructionList.addInstruction (ifStart);
1444+
1445+ // Second write - adds string
1446+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1447+ LLVMConstantRegister value2 (Compiler::StaticType::String, " test" );
1448+ appendList2->workList = &list;
1449+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1450+ instructionList.addInstruction (appendList2);
1451+
1452+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1453+ instructionList.addInstruction (ifEnd);
1454+
1455+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1456+ instructionList.addInstruction (funcCall);
1457+
1458+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, true ), Compiler::StaticType::Unknown);
1459+ }
1460+
1461+ TEST (LLVMTypeAnalyzer_ListType, TwoIfStatements_DifferentTypes_NonEmpty)
1462+ {
1463+ LLVMTypeAnalyzer analyzer;
1464+ LLVMInstructionList instructionList;
1465+ List list (" " , " " );
1466+
1467+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1468+ instructionList.addInstruction (ifStart);
1469+
1470+ // First write - does not change type
1471+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1472+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1473+ appendList1->workList = &list;
1474+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1475+ instructionList.addInstruction (appendList1);
1476+
1477+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
1478+ instructionList.addInstruction (elseStart);
1479+
1480+ // Second write - does not change type
1481+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1482+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 4 );
1483+ appendList2->workList = &list;
1484+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1485+ instructionList.addInstruction (appendList2);
1486+
1487+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1488+ instructionList.addInstruction (ifEnd);
1489+
1490+ ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1491+ instructionList.addInstruction (ifStart);
1492+
1493+ elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
1494+ instructionList.addInstruction (elseStart);
1495+
1496+ // Third write - adds string (in else branch)
1497+ auto appendList3 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1498+ LLVMConstantRegister value3 (Compiler::StaticType::String, " test" );
1499+ appendList3->workList = &list;
1500+ appendList3->args .push_back ({ Compiler::StaticType::Unknown, &value3 });
1501+ instructionList.addInstruction (appendList3);
1502+
1503+ ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1504+ instructionList.addInstruction (ifEnd);
1505+
1506+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1507+ instructionList.addInstruction (funcCall);
1508+
1509+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, false ), Compiler::StaticType::Unknown);
1510+ }
1511+
1512+ TEST (LLVMTypeAnalyzer_ListType, TwoIfStatements_DifferentTypes_Empty)
1513+ {
1514+ LLVMTypeAnalyzer analyzer;
1515+ LLVMInstructionList instructionList;
1516+ List list (" " , " " );
1517+
1518+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1519+ instructionList.addInstruction (ifStart);
1520+
1521+ // First write - establishes Number type
1522+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1523+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 5 );
1524+ appendList1->workList = &list;
1525+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
1526+ instructionList.addInstruction (appendList1);
1527+
1528+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
1529+ instructionList.addInstruction (elseStart);
1530+
1531+ // Second write - same Number type
1532+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1533+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 4 );
1534+ appendList2->workList = &list;
1535+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
1536+ instructionList.addInstruction (appendList2);
1537+
1538+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1539+ instructionList.addInstruction (ifEnd);
1540+
1541+ ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
1542+ instructionList.addInstruction (ifStart);
1543+
1544+ elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
1545+ instructionList.addInstruction (elseStart);
1546+
1547+ // Third write - adds String (in else branch)
1548+ auto appendList3 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, nullptr , false );
1549+ LLVMConstantRegister value3 (Compiler::StaticType::String, " test" );
1550+ appendList3->workList = &list;
1551+ appendList3->args .push_back ({ Compiler::StaticType::Unknown, &value3 });
1552+ instructionList.addInstruction (appendList3);
1553+
1554+ ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
1555+ instructionList.addInstruction (ifEnd);
1556+
1557+ auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
1558+ instructionList.addInstruction (funcCall);
1559+
1560+ ASSERT_EQ (analyzer.listType (&list, funcCall.get (), Compiler::StaticType::Number, true ), Compiler::StaticType::Unknown);
1561+ }
1562+
13091563TEST (LLVMTypeAnalyzer_ListType, NestedLoopWithTypeChange_Before_NonEmpty)
13101564{
13111565 LLVMTypeAnalyzer analyzer;
0 commit comments