/*! * Phase 7 MIR Builder & VM Test - Async Operations (nowait/await) * * Tests AST → MIR lowering and VM execution for Phase 7 async operations */ use nyash_rust::ast::{ASTNode, LiteralValue, Span}; use nyash_rust::backend::VM; use nyash_rust::mir::{MirBuilder, MirPrinter}; use std::collections::HashMap; #[test] #[ignore = "MIR13 async: await result wrapping semantics under revision"] fn test_mir_phase7_basic_nowait_await() { // Build AST equivalent to: // static box Main { // main() { // nowait f1 = 42; // local result = await f1; // return result // } // } let mut main_methods = HashMap::new(); // Create main method body let main_body = vec![ // nowait f1 = 42 ASTNode::Nowait { variable: "f1".to_string(), expression: Box::new(ASTNode::Literal { value: LiteralValue::Integer(42), span: Span::unknown(), }), span: Span::unknown(), }, // local result = await f1 ASTNode::Local { variables: vec!["result".to_string()], initial_values: vec![Some(Box::new(ASTNode::AwaitExpression { expression: Box::new(ASTNode::Variable { name: "f1".to_string(), span: Span::unknown(), }), span: Span::unknown(), }))], span: Span::unknown(), }, // return result ASTNode::Return { value: Some(Box::new(ASTNode::Variable { name: "result".to_string(), span: Span::unknown(), })), span: Span::unknown(), }, ]; // Create main method let main_method = ASTNode::FunctionDeclaration { name: "main".to_string(), params: vec![], body: main_body, is_static: false, is_override: false, span: Span::unknown(), }; main_methods.insert("main".to_string(), main_method); // Create static box Main let ast = ASTNode::BoxDeclaration { name: "Main".to_string(), fields: vec![], public_fields: vec![], private_fields: vec![], methods: main_methods, constructors: HashMap::new(), init_fields: vec![], weak_fields: vec![], is_interface: false, extends: vec![], implements: vec![], type_parameters: vec![], is_static: true, static_init: None, span: Span::unknown(), }; // Build MIR let mut builder = MirBuilder::new(); let result = builder.build_module(ast); if let Err(e) = &result { println!("MIR build error: {}", e); } assert!(result.is_ok(), "MIR build should succeed"); let module = result.unwrap(); // Print MIR for debugging let printer = MirPrinter::new(); let mir_output = printer.print_module(&module); println!("Generated MIR:"); println!("{}", mir_output); // Verify MIR contains expected instructions let function = module.get_function("main").unwrap(); let instructions: Vec<_> = function .blocks .values() .flat_map(|block| &block.instructions) .collect(); // Should contain FutureNew instruction let has_future_new = instructions .iter() .any(|inst| matches!(inst, nyash_rust::mir::MirInstruction::FutureNew { .. })); assert!(has_future_new, "MIR should contain FutureNew instruction"); // Should contain Await instruction let has_await = instructions .iter() .any(|inst| matches!(inst, nyash_rust::mir::MirInstruction::Await { .. })); assert!(has_await, "MIR should contain Await instruction"); // Test VM execution let mut vm = VM::new(); let execution_result = vm.execute_module(&module); if let Err(e) = &execution_result { println!("VM execution error: {}", e); } assert!(execution_result.is_ok(), "VM execution should succeed"); let final_value = execution_result.unwrap(); println!("VM execution result: {}", final_value.to_string_box().value); // Should return 42 assert_eq!(final_value.to_string_box().value, "42"); } #[test] #[ignore = "MIR13 async: multiple await aggregation semantics under revision"] fn test_mir_phase7_multiple_nowait_await() { // Build AST equivalent to: // static box Main { // main() { // nowait f1 = 10; // nowait f2 = 20; // local result1 = await f1; // local result2 = await f2; // return result1 + result2 // } // } let mut main_methods = HashMap::new(); // Create main method body let main_body = vec![ // nowait f1 = 10 ASTNode::Nowait { variable: "f1".to_string(), expression: Box::new(ASTNode::Literal { value: LiteralValue::Integer(10), span: Span::unknown(), }), span: Span::unknown(), }, // nowait f2 = 20 ASTNode::Nowait { variable: "f2".to_string(), expression: Box::new(ASTNode::Literal { value: LiteralValue::Integer(20), span: Span::unknown(), }), span: Span::unknown(), }, // local result1 = await f1 ASTNode::Local { variables: vec!["result1".to_string()], initial_values: vec![Some(Box::new(ASTNode::AwaitExpression { expression: Box::new(ASTNode::Variable { name: "f1".to_string(), span: Span::unknown(), }), span: Span::unknown(), }))], span: Span::unknown(), }, // local result2 = await f2 ASTNode::Local { variables: vec!["result2".to_string()], initial_values: vec![Some(Box::new(ASTNode::AwaitExpression { expression: Box::new(ASTNode::Variable { name: "f2".to_string(), span: Span::unknown(), }), span: Span::unknown(), }))], span: Span::unknown(), }, // return result1 + result2 ASTNode::Return { value: Some(Box::new(ASTNode::BinaryOp { left: Box::new(ASTNode::Variable { name: "result1".to_string(), span: Span::unknown(), }), operator: nyash_rust::ast::BinaryOperator::Add, right: Box::new(ASTNode::Variable { name: "result2".to_string(), span: Span::unknown(), }), span: Span::unknown(), })), span: Span::unknown(), }, ]; // Create main method let main_method = ASTNode::FunctionDeclaration { name: "main".to_string(), params: vec![], body: main_body, is_static: false, is_override: false, span: Span::unknown(), }; main_methods.insert("main".to_string(), main_method); // Create static box Main let ast = ASTNode::BoxDeclaration { name: "Main".to_string(), fields: vec![], public_fields: vec![], private_fields: vec![], methods: main_methods, constructors: HashMap::new(), init_fields: vec![], weak_fields: vec![], is_interface: false, extends: vec![], implements: vec![], type_parameters: vec![], is_static: true, static_init: None, span: Span::unknown(), }; // Build MIR let mut builder = MirBuilder::new(); let result = builder.build_module(ast); assert!(result.is_ok(), "MIR build should succeed"); let module = result.unwrap(); // Print MIR for debugging let printer = MirPrinter::new(); let mir_output = printer.print_module(&module); println!("Generated MIR for multiple nowait/await:"); println!("{}", mir_output); // Test VM execution let mut vm = VM::new(); let execution_result = vm.execute_module(&module); assert!(execution_result.is_ok(), "VM execution should succeed"); let final_value = execution_result.unwrap(); println!("VM execution result: {}", final_value.to_string_box().value); // Should return 30 (10 + 20) assert_eq!(final_value.to_string_box().value, "30"); } #[test] #[ignore = "MIR13 async: nested await semantics under revision"] fn test_mir_phase7_nested_await() { // Build AST equivalent to: // static box Main { // main() { // nowait outer = { // nowait inner = 5; // await inner * 2 // }; // return await outer // } // } let mut main_methods = HashMap::new(); // Create inner computation: nowait inner = 5; await inner * 2 let inner_computation = ASTNode::Program { statements: vec![ ASTNode::Nowait { variable: "inner".to_string(), expression: Box::new(ASTNode::Literal { value: LiteralValue::Integer(5), span: Span::unknown(), }), span: Span::unknown(), }, ASTNode::BinaryOp { left: Box::new(ASTNode::AwaitExpression { expression: Box::new(ASTNode::Variable { name: "inner".to_string(), span: Span::unknown(), }), span: Span::unknown(), }), operator: nyash_rust::ast::BinaryOperator::Multiply, right: Box::new(ASTNode::Literal { value: LiteralValue::Integer(2), span: Span::unknown(), }), span: Span::unknown(), }, ], span: Span::unknown(), }; // Create main method body let main_body = vec![ // nowait outer = { ... } ASTNode::Nowait { variable: "outer".to_string(), expression: Box::new(inner_computation), span: Span::unknown(), }, // return await outer ASTNode::Return { value: Some(Box::new(ASTNode::AwaitExpression { expression: Box::new(ASTNode::Variable { name: "outer".to_string(), span: Span::unknown(), }), span: Span::unknown(), })), span: Span::unknown(), }, ]; // Create main method let main_method = ASTNode::FunctionDeclaration { name: "main".to_string(), params: vec![], body: main_body, is_static: false, is_override: false, span: Span::unknown(), }; main_methods.insert("main".to_string(), main_method); // Create static box Main let ast = ASTNode::BoxDeclaration { name: "Main".to_string(), fields: vec![], public_fields: vec![], private_fields: vec![], methods: main_methods, constructors: HashMap::new(), init_fields: vec![], weak_fields: vec![], is_interface: false, extends: vec![], implements: vec![], type_parameters: vec![], is_static: true, static_init: None, span: Span::unknown(), }; // Build MIR let mut builder = MirBuilder::new(); let result = builder.build_module(ast); assert!(result.is_ok(), "MIR build should succeed"); let module = result.unwrap(); // Print MIR for debugging let printer = MirPrinter::new(); let mir_output = printer.print_module(&module); println!("Generated MIR for nested await:"); println!("{}", mir_output); // Test VM execution let mut vm = VM::new(); let execution_result = vm.execute_module(&module); assert!(execution_result.is_ok(), "VM execution should succeed"); let final_value = execution_result.unwrap(); println!("VM execution result: {}", final_value.to_string_box().value); // Should return 10 (5 * 2) assert_eq!(final_value.to_string_box().value, "10"); }