242 lines
7.1 KiB
Rust
242 lines
7.1 KiB
Rust
/*!
|
|
* Phase 6.1 MIR Builder Lowering Test - RefNew/RefGet/RefSet
|
|
*
|
|
* Tests AST → MIR lowering for Phase 6 reference operations
|
|
*/
|
|
|
|
use nyash_rust::ast::{ASTNode, LiteralValue, Span};
|
|
use nyash_rust::mir::{MirBuilder, MirPrinter};
|
|
use std::collections::HashMap;
|
|
|
|
#[test]
|
|
#[ignore = "MIR13: ref_new/ref_get/ref_set removed; test targets legacy ops"]
|
|
fn test_mir_phase6_lowering_ref_ops() {
|
|
// Build AST equivalent to:
|
|
// static box Main {
|
|
// main() {
|
|
// local o;
|
|
// o = new Obj();
|
|
// o.x = 1;
|
|
// local y;
|
|
// y = o.x;
|
|
// return y
|
|
// }
|
|
// }
|
|
|
|
let mut main_methods = HashMap::new();
|
|
|
|
// Create main method body
|
|
let main_body = vec![
|
|
// local o
|
|
ASTNode::Local {
|
|
variables: vec!["o".to_string()],
|
|
initial_values: vec![None],
|
|
span: Span::unknown(),
|
|
},
|
|
// o = new Obj()
|
|
ASTNode::Assignment {
|
|
target: Box::new(ASTNode::Variable {
|
|
name: "o".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
value: Box::new(ASTNode::New {
|
|
class: "Obj".to_string(),
|
|
arguments: vec![],
|
|
type_arguments: vec![],
|
|
span: Span::unknown(),
|
|
}),
|
|
span: Span::unknown(),
|
|
},
|
|
// o.x = 1
|
|
ASTNode::Assignment {
|
|
target: Box::new(ASTNode::FieldAccess {
|
|
object: Box::new(ASTNode::Variable {
|
|
name: "o".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
field: "x".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
value: Box::new(ASTNode::Literal {
|
|
value: LiteralValue::Integer(1),
|
|
span: Span::unknown(),
|
|
}),
|
|
span: Span::unknown(),
|
|
},
|
|
// local y
|
|
ASTNode::Local {
|
|
variables: vec!["y".to_string()],
|
|
initial_values: vec![None],
|
|
span: Span::unknown(),
|
|
},
|
|
// y = o.x
|
|
ASTNode::Assignment {
|
|
target: Box::new(ASTNode::Variable {
|
|
name: "y".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
value: Box::new(ASTNode::FieldAccess {
|
|
object: Box::new(ASTNode::Variable {
|
|
name: "o".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
field: "x".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
span: Span::unknown(),
|
|
},
|
|
// return y
|
|
ASTNode::Return {
|
|
value: Some(Box::new(ASTNode::Variable {
|
|
name: "y".to_string(),
|
|
span: Span::unknown(),
|
|
})),
|
|
span: Span::unknown(),
|
|
},
|
|
];
|
|
|
|
// Create main function declaration
|
|
let main_function = 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_function);
|
|
|
|
// 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 from AST
|
|
let mut builder = MirBuilder::new();
|
|
let result = builder.build_module(ast);
|
|
assert!(result.is_ok(), "MIR building should succeed");
|
|
|
|
let module = result.unwrap();
|
|
|
|
// Print MIR to string for verification
|
|
let printer = MirPrinter::new();
|
|
let mir_text = printer.print_module(&module);
|
|
|
|
println!("Generated MIR:\n{}", mir_text);
|
|
|
|
// Verify that the MIR contains the expected Phase 6 reference operations
|
|
assert!(
|
|
mir_text.contains("ref_new"),
|
|
"MIR should contain ref_new instruction"
|
|
);
|
|
assert!(
|
|
mir_text.contains("ref_set"),
|
|
"MIR should contain ref_set instruction"
|
|
);
|
|
assert!(
|
|
mir_text.contains("ref_get"),
|
|
"MIR should contain ref_get instruction"
|
|
);
|
|
|
|
// Verify specific patterns
|
|
assert!(
|
|
mir_text.contains("ref_new") && mir_text.contains("\"Obj\""),
|
|
"MIR should contain ref_new with Obj class"
|
|
);
|
|
assert!(
|
|
mir_text.contains("ref_set") && mir_text.contains(".x"),
|
|
"MIR should contain ref_set with field x"
|
|
);
|
|
assert!(
|
|
mir_text.contains("ref_get") && mir_text.contains(".x"),
|
|
"MIR should contain ref_get with field x"
|
|
);
|
|
|
|
// Verify module structure
|
|
assert_eq!(
|
|
module.function_names().len(),
|
|
1,
|
|
"Module should have one function"
|
|
);
|
|
assert!(
|
|
module.get_function("main").is_some(),
|
|
"Module should have main function"
|
|
);
|
|
|
|
// Verify function has instructions
|
|
let main_function = module.get_function("main").unwrap();
|
|
let stats = main_function.stats();
|
|
assert!(
|
|
stats.instruction_count > 5,
|
|
"Function should have multiple instructions (got {})",
|
|
stats.instruction_count
|
|
);
|
|
|
|
println!("✅ Phase 6.1 MIR lowering test passed! Found all required ref operations.");
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "MIR13: legacy ref ops program; verification expectations differ"]
|
|
fn test_mir_verification_phase6_ref_ops() {
|
|
// Build simple AST with new and field access
|
|
let ast = ASTNode::Program {
|
|
statements: vec![ASTNode::Assignment {
|
|
target: Box::new(ASTNode::Variable {
|
|
name: "obj".to_string(),
|
|
span: Span::unknown(),
|
|
}),
|
|
value: Box::new(ASTNode::New {
|
|
class: "TestObj".to_string(),
|
|
arguments: vec![],
|
|
type_arguments: vec![],
|
|
span: Span::unknown(),
|
|
}),
|
|
span: Span::unknown(),
|
|
}],
|
|
span: Span::unknown(),
|
|
};
|
|
|
|
// Build and verify module
|
|
let mut builder = MirBuilder::new();
|
|
let result = builder.build_module(ast);
|
|
assert!(result.is_ok(), "MIR building should succeed");
|
|
|
|
let module = result.unwrap();
|
|
|
|
// Verify module passes verification
|
|
use nyash_rust::mir::MirVerifier;
|
|
let mut verifier = MirVerifier::new();
|
|
let verification_result = verifier.verify_module(&module);
|
|
|
|
match verification_result {
|
|
Ok(()) => {
|
|
println!("✅ MIR verification passed for Phase 6 reference operations");
|
|
}
|
|
Err(errors) => {
|
|
println!("❌ MIR verification failed with {} errors:", errors.len());
|
|
for error in &errors {
|
|
println!(" - {:?}", error);
|
|
}
|
|
// Don't fail the test for verification errors, as the verifier may be incomplete
|
|
println!(
|
|
"⚠️ Continuing test despite verification issues (verifier may be incomplete)"
|
|
);
|
|
}
|
|
}
|
|
}
|