@@ -351,6 +351,167 @@ TEST(LLVMCodeAnalyzer_ListTypeAnalysis, LoopSingleWrite_AfterClear)
351351 ASSERT_EQ (appendList->targetType , Compiler::StaticType::Number);
352352}
353353
354+ TEST (LLVMCodeAnalyzer_ListTypeAnalysis, ClearAndWriteInIfStatement_IfBranch)
355+ {
356+ LLVMCodeAnalyzer analyzer;
357+ LLVMInstructionList list;
358+ List targetList (" " , " " );
359+
360+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, false );
361+ list.addInstruction (ifStart);
362+
363+ auto clearList = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
364+ clearList->targetList = &targetList;
365+ list.addInstruction (clearList);
366+
367+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
368+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 1.25 );
369+ appendList1->targetList = &targetList;
370+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
371+ list.addInstruction (appendList1);
372+
373+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, false );
374+ list.addInstruction (ifEnd);
375+
376+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
377+ LLVMConstantRegister value2 (Compiler::StaticType::Bool, true );
378+ appendList2->targetList = &targetList;
379+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
380+ list.addInstruction (appendList2);
381+
382+ analyzer.analyzeScript (list);
383+
384+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
385+
386+ // The type is Unknown because the if statement might not run at all
387+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::Unknown);
388+ }
389+
390+ TEST (LLVMCodeAnalyzer_ListTypeAnalysis, ClearAndWriteInIfStatement_ElseBranch)
391+ {
392+ LLVMCodeAnalyzer analyzer;
393+ LLVMInstructionList list;
394+ List targetList (" " , " " );
395+
396+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, false );
397+ list.addInstruction (ifStart);
398+
399+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, false );
400+ list.addInstruction (elseStart);
401+
402+ auto clearList = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
403+ clearList->targetList = &targetList;
404+ list.addInstruction (clearList);
405+
406+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
407+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 1.25 );
408+ appendList1->targetList = &targetList;
409+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
410+ list.addInstruction (appendList1);
411+
412+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, false );
413+ list.addInstruction (ifEnd);
414+
415+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
416+ LLVMConstantRegister value2 (Compiler::StaticType::Bool, true );
417+ appendList2->targetList = &targetList;
418+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
419+ list.addInstruction (appendList2);
420+
421+ analyzer.analyzeScript (list);
422+
423+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
424+
425+ // The type is Unknown because the if statement might not run at all
426+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::Unknown);
427+ }
428+
429+ TEST (LLVMCodeAnalyzer_ListTypeAnalysis, ClearAndWriteInIfElse)
430+ {
431+ LLVMCodeAnalyzer analyzer;
432+ LLVMInstructionList list;
433+ List targetList (" " , " " );
434+
435+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, false );
436+ list.addInstruction (ifStart);
437+
438+ auto clearList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
439+ clearList1->targetList = &targetList;
440+ list.addInstruction (clearList1);
441+
442+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
443+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 1.25 );
444+ appendList1->targetList = &targetList;
445+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
446+ list.addInstruction (appendList1);
447+
448+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, false );
449+ list.addInstruction (elseStart);
450+
451+ auto clearList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
452+ clearList2->targetList = &targetList;
453+ list.addInstruction (clearList2);
454+
455+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
456+ LLVMConstantRegister value2 (Compiler::StaticType::String, " hello" );
457+ appendList2->targetList = &targetList;
458+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
459+ list.addInstruction (appendList2);
460+
461+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, false );
462+ list.addInstruction (ifEnd);
463+
464+ auto appendList3 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
465+ LLVMConstantRegister value3 (Compiler::StaticType::Bool, true );
466+ appendList3->targetList = &targetList;
467+ appendList3->args .push_back ({ Compiler::StaticType::Unknown, &value3 });
468+ list.addInstruction (appendList3);
469+
470+ analyzer.analyzeScript (list);
471+
472+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
473+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::Void);
474+
475+ // The type is Number | String because any of the branches may run
476+ ASSERT_EQ (appendList3->targetType , Compiler::StaticType::Number | Compiler::StaticType::String);
477+ }
478+
479+ TEST (LLVMCodeAnalyzer_ListTypeAnalysis, ClearAndWriteInLoop)
480+ {
481+ LLVMCodeAnalyzer analyzer;
482+ LLVMInstructionList list;
483+ List targetList (" " , " " );
484+
485+ auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, false );
486+ list.addInstruction (loopStart);
487+
488+ auto clearList = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
489+ clearList->targetList = &targetList;
490+ list.addInstruction (clearList);
491+
492+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
493+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 1.25 );
494+ appendList1->targetList = &targetList;
495+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
496+ list.addInstruction (appendList1);
497+
498+ auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, false );
499+ list.addInstruction (loopEnd);
500+
501+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
502+ LLVMConstantRegister value2 (Compiler::StaticType::Bool, true );
503+ appendList2->targetList = &targetList;
504+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
505+ list.addInstruction (appendList2);
506+
507+ analyzer.analyzeScript (list);
508+
509+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
510+
511+ // The type is Unknown because the loop might not run at all
512+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::Unknown);
513+ }
514+
354515TEST (LLVMCodeAnalyzer_ListTypeAnalysis, ClearAfterWriteInLoop)
355516{
356517 LLVMCodeAnalyzer analyzer;
0 commit comments