#[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::>() .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 = 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 = 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)) } }