@@ -2153,3 +2153,248 @@ TEST(LLVMTypeAnalyzer_VariableType, SelfAssignmentWithTypeChange_After)
21532153 // Should return number because it's assigned after the no-op
21542154 ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::String), Compiler::StaticType::Number);
21552155}
2156+
2157+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_AddNumbers)
2158+ {
2159+ LLVMTypeAnalyzer analyzer;
2160+ LLVMInstructionList list;
2161+ Variable var1 (" " , " " );
2162+
2163+ // Create add instruction: 5 + 3
2164+ auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr , false );
2165+ LLVMConstantRegister operand1 (Compiler::StaticType::Number, 5 );
2166+ LLVMConstantRegister operand2 (Compiler::StaticType::Number, 3 );
2167+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand1 });
2168+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand2 });
2169+
2170+ // Set up return register for add instruction
2171+ LLVMRegister addResult (Compiler::StaticType::Number);
2172+ addResult.isRawValue = true ;
2173+ addResult.instruction = addInstruction;
2174+ addInstruction->functionReturnReg = &addResult;
2175+ list.addInstruction (addInstruction);
2176+
2177+ // Assign add result to variable: var1 = (5 + 3)
2178+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2179+ setVar1->workVariable = &var1;
2180+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &addResult });
2181+ list.addInstruction (setVar1);
2182+
2183+ // Query position after the assignment
2184+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2185+ list.addInstruction (queryPos);
2186+
2187+ // var1 should have Number type from add instruction return
2188+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::String), Compiler::StaticType::Number);
2189+ }
2190+
2191+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_StringConcat)
2192+ {
2193+ LLVMTypeAnalyzer analyzer;
2194+ LLVMInstructionList list;
2195+ Variable var1 (" " , " " );
2196+
2197+ // Create string concatenation instruction: "hello" + "world"
2198+ auto concatInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::StringConcat, nullptr , false );
2199+ LLVMConstantRegister str1 (Compiler::StaticType::String, " hello" );
2200+ LLVMConstantRegister str2 (Compiler::StaticType::String, " world" );
2201+ concatInstruction->args .push_back ({ Compiler::StaticType::String, &str1 });
2202+ concatInstruction->args .push_back ({ Compiler::StaticType::String, &str2 });
2203+
2204+ // Set up return register for concat instruction
2205+ LLVMRegister concatResult (Compiler::StaticType::String);
2206+ concatResult.isRawValue = true ;
2207+ concatResult.instruction = concatInstruction;
2208+ concatInstruction->functionReturnReg = &concatResult;
2209+ list.addInstruction (concatInstruction);
2210+
2211+ // Assign concat result to variable: var1 = ("hello" + "world")
2212+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2213+ setVar1->workVariable = &var1;
2214+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &concatResult });
2215+ list.addInstruction (setVar1);
2216+
2217+ // Query position after the assignment
2218+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2219+ list.addInstruction (queryPos);
2220+
2221+ // var1 should have String type from concat instruction return
2222+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::Number), Compiler::StaticType::String);
2223+ }
2224+
2225+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_MathFunction)
2226+ {
2227+ LLVMTypeAnalyzer analyzer;
2228+ LLVMInstructionList list;
2229+ Variable var1 (" " , " " );
2230+
2231+ // Create sqrt instruction: sqrt(16)
2232+ auto sqrtInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Sqrt, nullptr , false );
2233+ LLVMConstantRegister operand (Compiler::StaticType::Number, 16 );
2234+ sqrtInstruction->args .push_back ({ Compiler::StaticType::Number, &operand });
2235+
2236+ // Set up return register for sqrt instruction
2237+ LLVMRegister sqrtResult (Compiler::StaticType::Number);
2238+ sqrtResult.isRawValue = true ;
2239+ sqrtResult.instruction = sqrtInstruction;
2240+ sqrtInstruction->functionReturnReg = &sqrtResult;
2241+ list.addInstruction (sqrtInstruction);
2242+
2243+ // Assign sqrt result to variable: var1 = sqrt(16)
2244+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2245+ setVar1->workVariable = &var1;
2246+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &sqrtResult });
2247+ list.addInstruction (setVar1);
2248+
2249+ // Query position after the assignment
2250+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2251+ list.addInstruction (queryPos);
2252+
2253+ // var1 should have Number type from sqrt instruction return
2254+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::String), Compiler::StaticType::Number);
2255+ }
2256+
2257+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_Comparison)
2258+ {
2259+ LLVMTypeAnalyzer analyzer;
2260+ LLVMInstructionList list;
2261+ Variable var1 (" " , " " );
2262+
2263+ // Create comparison instruction: 5 > 3
2264+ auto cmpInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::CmpGT, nullptr , false );
2265+ LLVMConstantRegister operand1 (Compiler::StaticType::Number, 5 );
2266+ LLVMConstantRegister operand2 (Compiler::StaticType::Number, 3 );
2267+ cmpInstruction->args .push_back ({ Compiler::StaticType::Number, &operand1 });
2268+ cmpInstruction->args .push_back ({ Compiler::StaticType::Number, &operand2 });
2269+
2270+ // Set up return register for comparison instruction
2271+ LLVMRegister cmpResult (Compiler::StaticType::Bool);
2272+ cmpResult.isRawValue = true ;
2273+ cmpResult.instruction = cmpInstruction;
2274+ cmpInstruction->functionReturnReg = &cmpResult;
2275+ list.addInstruction (cmpInstruction);
2276+
2277+ // Assign comparison result to variable: var1 = (5 > 3)
2278+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2279+ setVar1->workVariable = &var1;
2280+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &cmpResult });
2281+ list.addInstruction (setVar1);
2282+
2283+ // Query position after the assignment
2284+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2285+ list.addInstruction (queryPos);
2286+
2287+ // var1 should have Bool type from comparison instruction return
2288+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::Number), Compiler::StaticType::Bool);
2289+ }
2290+
2291+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_FunctionCall)
2292+ {
2293+ LLVMTypeAnalyzer analyzer;
2294+ LLVMInstructionList list;
2295+ Variable var1 (" " , " " );
2296+
2297+ // Create function call instruction
2298+ auto funcInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2299+ funcInstruction->functionName = " some_reporter_function" ;
2300+ LLVMConstantRegister arg (Compiler::StaticType::Number, 42 );
2301+ funcInstruction->args .push_back ({ Compiler::StaticType::Number, &arg });
2302+
2303+ // Set up return register for function call
2304+ LLVMRegister funcResult (Compiler::StaticType::String);
2305+ funcResult.isRawValue = true ;
2306+ funcResult.instruction = funcInstruction;
2307+ funcInstruction->functionReturnReg = &funcResult;
2308+ list.addInstruction (funcInstruction);
2309+
2310+ // Assign function result to variable: var1 = some_reporter_function(42)
2311+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2312+ setVar1->workVariable = &var1;
2313+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &funcResult });
2314+ list.addInstruction (setVar1);
2315+
2316+ // Query position after the assignment
2317+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2318+ list.addInstruction (queryPos);
2319+
2320+ // var1 should have String type from function call return
2321+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::Number), Compiler::StaticType::String);
2322+ }
2323+
2324+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_ChainedOperations)
2325+ {
2326+ LLVMTypeAnalyzer analyzer;
2327+ LLVMInstructionList list;
2328+ Variable var1 (" " , " " );
2329+
2330+ // First operation: 5 + 3
2331+ auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr , false );
2332+ LLVMConstantRegister operand1 (Compiler::StaticType::Number, 5 );
2333+ LLVMConstantRegister operand2 (Compiler::StaticType::Number, 3 );
2334+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand1 });
2335+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand2 });
2336+
2337+ LLVMRegister addResult (Compiler::StaticType::Number);
2338+ addResult.isRawValue = true ;
2339+ addResult.instruction = addInstruction;
2340+ addInstruction->functionReturnReg = &addResult;
2341+ list.addInstruction (addInstruction);
2342+
2343+ // Second operation: (5 + 3) * 2
2344+ auto mulInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Mul, nullptr , false );
2345+ LLVMConstantRegister multiplier (Compiler::StaticType::Number, 2 );
2346+ mulInstruction->args .push_back ({ Compiler::StaticType::Unknown, &addResult });
2347+ mulInstruction->args .push_back ({ Compiler::StaticType::Number, &multiplier });
2348+
2349+ LLVMRegister mulResult (Compiler::StaticType::Number);
2350+ mulResult.isRawValue = true ;
2351+ mulResult.instruction = mulInstruction;
2352+ mulInstruction->functionReturnReg = &mulResult;
2353+ list.addInstruction (mulInstruction);
2354+
2355+ // Assign final result to variable: var1 = ((5 + 3) * 2)
2356+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2357+ setVar1->workVariable = &var1;
2358+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &mulResult });
2359+ list.addInstruction (setVar1);
2360+
2361+ // Query position after the assignment
2362+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2363+ list.addInstruction (queryPos);
2364+
2365+ // var1 should have Number type from chained operations
2366+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::String), Compiler::StaticType::Number);
2367+ }
2368+
2369+ TEST (LLVMTypeAnalyzer_VariableType, InstructionReturnType_QueryBeforeAssignment)
2370+ {
2371+ LLVMTypeAnalyzer analyzer;
2372+ LLVMInstructionList list;
2373+ Variable var1 (" " , " " );
2374+
2375+ // Query position before any operations
2376+ auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr , false );
2377+ list.addInstruction (queryPos);
2378+
2379+ // Create add instruction: 5 + 3 (after query position)
2380+ auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr , false );
2381+ LLVMConstantRegister operand1 (Compiler::StaticType::Number, 5 );
2382+ LLVMConstantRegister operand2 (Compiler::StaticType::Number, 3 );
2383+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand1 });
2384+ addInstruction->args .push_back ({ Compiler::StaticType::Number, &operand2 });
2385+
2386+ LLVMRegister addResult (Compiler::StaticType::Number);
2387+ addResult.isRawValue = true ;
2388+ addResult.instruction = addInstruction;
2389+ addInstruction->functionReturnReg = &addResult;
2390+ list.addInstruction (addInstruction);
2391+
2392+ // Assign add result to variable: var1 = (5 + 3) (after query position)
2393+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
2394+ setVar1->workVariable = &var1;
2395+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &addResult });
2396+ list.addInstruction (setVar1);
2397+
2398+ // var1 should have the previous type since assignment is after query position
2399+ ASSERT_EQ (analyzer.variableType (&var1, queryPos.get (), Compiler::StaticType::String), Compiler::StaticType::String);
2400+ }
0 commit comments