140 lines
4.0 KiB
Rust
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))
|
|
}
|
|
}
|