More optimizations and snapshot integration tests

This commit is contained in:
2025-12-30 21:20:46 -07:00
parent f87fdc1b0a
commit d19a53bbee
30 changed files with 3192 additions and 842 deletions

View File

@@ -0,0 +1,175 @@
//! Integration tests for the Slang compiler with optimizer
//!
//! These tests compile Slang source code and verify both the compilation
//! and optimization passes work correctly together using snapshot testing.
#[cfg(test)]
mod tests {
use compiler::Compiler;
use indoc::indoc;
use parser::Parser;
use tokenizer::Tokenizer;
/// Compile Slang source code and return both unoptimized and optimized output
fn compile_with_and_without_optimization(source: &str) -> String {
// Compile for unoptimized output
let tokenizer = Tokenizer::from(source);
let parser = Parser::new(tokenizer);
let compiler = Compiler::new(parser, None);
let result = compiler.compile();
// Get unoptimized output
let mut unoptimized_writer = std::io::BufWriter::new(Vec::new());
result
.instructions
.write(&mut unoptimized_writer)
.expect("Failed to write unoptimized output");
let unoptimized_bytes = unoptimized_writer
.into_inner()
.expect("Failed to get bytes");
let unoptimized = String::from_utf8(unoptimized_bytes).expect("Invalid UTF-8");
// Compile again for optimized output
let tokenizer2 = Tokenizer::from(source);
let parser2 = Parser::new(tokenizer2);
let compiler2 = Compiler::new(parser2, None);
let result2 = compiler2.compile();
// Apply optimizations
let optimized_instructions = optimizer::optimize(result2.instructions);
// Get optimized output
let mut optimized_writer = std::io::BufWriter::new(Vec::new());
optimized_instructions
.write(&mut optimized_writer)
.expect("Failed to write optimized output");
let optimized_bytes = optimized_writer.into_inner().expect("Failed to get bytes");
let optimized = String::from_utf8(optimized_bytes).expect("Invalid UTF-8");
// Combine both outputs with clear separators
format!(
"## Unoptimized Output\n\n{}\n## Optimized Output\n\n{}",
unoptimized, optimized
)
}
#[test]
fn test_simple_leaf_function() {
let source = "fn test() { let x = 10; }";
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_function_with_call() {
let source = indoc! {"
fn add(a, b) { return a + b; }
fn main() { let x = add(5, 10); }
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_constant_folding() {
let source = "let x = 5 + 10;";
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_algebraic_simplification() {
let source = "let x = 5; let y = x * 1;";
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_strength_reduction() {
let source = "fn double(x) { return x * 2; }";
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_dead_code_elimination() {
let source = indoc! {"
fn compute(x) {
let unused = 20;
return x + 1;
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_peephole_comparison_fusion() {
let source = indoc! {"
fn compare(x, y) {
if (x > y) {
let z = 1;
}
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_select_optimization() {
let source = indoc! {"
fn ternary(cond) {
let result = 0;
if (cond) {
result = 10;
} else {
result = 20;
}
return result;
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_leaf_function_no_stack_frame() {
let source = indoc! {"
fn increment(x) {
x = x + 1;
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_complex_arithmetic() {
let source = indoc! {"
fn compute(a, b, c) {
let x = a * 2;
let y = b + 0;
let z = c * 1;
return x + y + z;
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
#[test]
fn test_nested_function_calls() {
let source = indoc! {"
fn add(a, b) { return a + b; }
fn multiply(x, y) { return x * 2; }
fn complex(a, b) {
let sum = add(a, b);
let doubled = multiply(sum, 2);
return doubled;
}
"};
let output = compile_with_and_without_optimization(source);
insta::assert_snapshot!(output);
}
}