deimos-lang/e2e-tests/src/lib.rs
2026-03-09 19:22:35 -05:00

140 lines
4.0 KiB
Rust

#[cfg(test)]
mod e2e_tests {
use dmc_lib::constants_table::ConstantsTable;
use dmc_lib::diagnostic::Diagnostic;
use dmc_lib::parser::parse_compilation_unit;
use dmc_lib::symbol_table::SymbolTable;
use dvm_lib::vm::constant::{Constant, StringConstant};
use dvm_lib::vm::function::Function;
use dvm_lib::vm::value::Value;
use dvm_lib::vm::{CallStack, DvmContext, call};
use std::rc::Rc;
const REGISTER_COUNT: usize = 8;
fn report_diagnostics(diagnostics: &[Diagnostic]) -> ! {
eprintln!(
"{}",
diagnostics
.iter()
.map(|d| format!("{:?}", d))
.collect::<Vec<_>>()
.join("\n")
);
panic!("There were diagnostics.");
}
fn assert_result(input: &str, function_name: &str, arguments: &[Value], expected_value: Value) {
let parse_result = parse_compilation_unit(input);
let mut compilation_unit = match parse_result {
Ok(compilation_unit) => compilation_unit,
Err(diagnostics) => {
report_diagnostics(&diagnostics);
}
};
let mut symbol_table = SymbolTable::new();
match compilation_unit.gather_declared_names(&mut symbol_table) {
Ok(_) => {}
Err(diagnostics) => {
report_diagnostics(&diagnostics);
}
}
match compilation_unit.check_name_usages(&symbol_table) {
Ok(_) => {}
Err(diagnostics) => {
report_diagnostics(&diagnostics);
}
}
match compilation_unit.type_check(&symbol_table) {
Ok(_) => {}
Err(diagnostics) => {
report_diagnostics(&diagnostics);
}
}
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
let mut functions: Vec<Function> = vec![];
let mut constants_table = ConstantsTable::new();
for ir_function in &mut ir_functions {
let (_, stack_size) = ir_function.assign_registers(REGISTER_COUNT);
let function = ir_function.assemble(stack_size, &mut constants_table);
functions.push(function);
}
let mut dvm_context = DvmContext::new();
for function in functions {
dvm_context
.functions_mut()
.insert(function.name_owned(), function);
}
for (name, content) in &constants_table.string_constants() {
dvm_context.constants_mut().insert(
name.clone(),
Constant::String(StringConstant::new(name.clone(), content.clone())),
);
}
let mut registers: Vec<Value> = vec![Value::Null; REGISTER_COUNT];
let mut call_stack = CallStack::new();
let result = call(
&dvm_context,
&mut registers,
&mut call_stack,
function_name,
&arguments,
);
match result {
None => panic!("Call returned no value"),
Some(result_value) => {
assert_eq!(result_value, expected_value);
}
}
}
#[test]
fn add_1_2() {
assert_result(
"
fn add(a: Int, b: Int) -> Int
a + b
end
",
"add",
&vec![Value::Int(1), Value::Int(2)],
Value::Int(3),
);
}
#[test]
fn bunch_of_adding() {
assert_result(
"
fn add(a: Int, b: Int) -> Int
a + b
end
fn greetAndAdd(a: Int, b: Int) -> String
\"Hello. \" + a + \" plus \" + b + \" is \" + add(a, b)
end
",
"greetAndAdd",
&vec![Value::Int(1), Value::Int(2)],
Value::String(Rc::from("Hello. 1 plus 2 is 3")),
);
}
#[test]
fn simple_subtract() {
assert_result("fn sub() -> Int 3 - 2 end", "sub", &vec![], Value::Int(1))
}
}