use std::path::PathBuf;
use compile_state::state::{CompileState, SloshVm, SloshVmTrait};
use sl_compiler::pass1::pass1;
use sl_compiler::{compile, Reader};
use slosh_lib::new_slosh_vm_with_builtins;
use slvm::{
Chunk, VMError, VMResult, Value, Vm, ADD, CONST, DIV, GET, INC, JMPLT, MUL, RET, SETCOL, VECMKD,
};
use std::sync::Arc;
pub fn load_one_expression(
vm: &mut SloshVm,
exp: Value,
name: &'static str,
doc_string: Option<Value>,
) -> VMResult<(Arc<Chunk>, Option<Value>)> {
let line_num = vm.line_num();
let mut state = CompileState::new_state(name, line_num, None);
state.chunk.dbg_args = Some(Vec::new());
state.doc_string = doc_string;
if let Err(e) = pass1(vm, &mut state, exp) {
println!(
"Compile error (pass one), {}, line {}: {}",
name,
vm.line_num(),
e
);
return Err(e);
}
if let Err(e) = compile(vm, &mut state, exp, 0) {
println!(
"Compile error, {} line {}: {} exp: {}",
name,
vm.line_num(),
e,
exp.display_value(vm)
);
return Err(e);
}
if let Err(e) = state.chunk.encode0(RET, vm.own_line()) {
println!("Compile error, {} line {}: {}", name, vm.line_num(), e);
return Err(e);
}
state.chunk.extra_regs = state.max_regs;
Ok((Arc::new(state.chunk), state.doc_string))
}
pub fn run_float_bench(n: usize, m: f32) -> String {
format!("(eval-pol {} {})", n, m)
}
pub fn run_reader(reader: &mut Reader) -> VMResult<Value> {
let mut last = Value::False;
while let Some(exp) = reader.next() {
let reader_vm = reader.vm();
let exp = exp
.map_err(|e| VMError::new("read", e.to_string()))
.unwrap();
reader_vm.heap_sticky(exp);
let result = load_one_expression(reader_vm, exp, "", None);
reader_vm.heap_unsticky(exp);
let (chunk, _new_doc_string) = result.unwrap();
last = reader_vm.execute(chunk)?;
}
Ok(last)
}
pub fn get_benches_directory() -> PathBuf {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("benches");
path
}
pub fn get_float_benchmark() -> PathBuf {
get_benches_directory().join("float-bench.slosh")
}
pub fn load_file(fname: PathBuf, vm: &mut SloshVm) {
match std::fs::File::open(fname) {
Ok(file) => {
let mut reader = Reader::from_file(file, vm, "", 1, 0);
let _ = run_reader(&mut reader);
}
Err(e) => {
panic!("Could not open file: {:?}", e);
}
}
}
pub fn run_float_script(n: usize, m: f32, expected: f64) {
let vm = &mut new_slosh_vm_with_builtins();
let fname = get_float_benchmark();
load_file(fname, vm);
let mut reader = Reader::from_string(run_float_bench(n, m), vm, "", 1, 0);
let last = run_reader(&mut reader);
match last {
Ok(Value::Float(f)) => {
assert_eq!(expected as f32, f32::from(f));
}
_ => {
panic!("Not a float");
}
}
}
pub fn get_search_benchmark() -> PathBuf {
get_benches_directory().join("vec-search-bench.slosh")
}
pub fn run_recursive_search_bench(n: usize) -> String {
format!("(run-recursive {})", n)
}
pub fn run_continuation_search_bench(n: usize) -> String {
format!("(run-continuation {})", n)
}
pub fn run_bench_assert_true(n: usize, f: fn(n: usize) -> String, vm: &mut SloshVm) {
let mut reader = Reader::from_string(f(n), vm, "", 1, 0);
let last = run_reader(&mut reader);
match last {
Ok(v) => {
assert_eq!(Value::True, v);
}
_ => {
panic!("Not true");
}
}
}
pub fn run_recursive_search_script(n: usize) {
let vm = &mut new_slosh_vm_with_builtins();
let fname = get_search_benchmark();
load_file(fname, vm);
run_bench_assert_true(n, run_recursive_search_bench, vm);
}
pub fn run_continuation_search_script(n: usize) {
let vm = &mut new_slosh_vm_with_builtins();
let fname = get_search_benchmark();
load_file(fname, vm);
run_bench_assert_true(n, run_continuation_search_bench, vm);
}
pub fn eval_pol(n: i32, x: f32, expected: f32) -> VMResult<()> {
let mut vm = Vm::new();
vm.pause_gc();
let mut chunk = Chunk::new("no_file", 1);
let n = chunk.add_constant(n.into()) as u16;
let x = chunk.add_constant(x.into()) as u16;
let su = chunk.add_constant(0.0.into()) as u16;
let mu = chunk.add_constant(10.0.into()) as u16;
let pu = chunk.add_constant(0.0.into()) as u16;
let zero = chunk.add_constant(0.into()) as u16;
let zerof = chunk.add_constant(0.0.into()) as u16;
let twof = chunk.add_constant(2.0.into()) as u16;
let hundred = chunk.add_constant(100.into()) as u16;
let one = chunk.add_constant(1.into()) as u16;
let line = 1;
chunk.encode2(CONST, 1, n, Some(line))?;
chunk.encode2(CONST, 2, x, Some(line))?;
chunk.encode2(CONST, 3, su, Some(line))?;
chunk.encode2(CONST, 4, mu, Some(line))?;
chunk.encode2(CONST, 5, pu, Some(line))?;
chunk.encode2(CONST, 6, zero, Some(line))?; chunk.encode2(CONST, 7, zero, Some(line))?; chunk.encode2(CONST, 8, twof, Some(line))?; chunk.encode2(CONST, 100, hundred, Some(line))?;
chunk.encode2(CONST, 101, one, Some(line))?;
chunk.encode2(CONST, 103, zerof, Some(line))?;
chunk.encode3(VECMKD, 10, 100, 103, Some(line))?; let jmp0_idx = chunk.add_jump(chunk.code.len() as u32);
chunk.encode2(CONST, 3, zerof, Some(line))?;
chunk.encode2(CONST, 7, zero, Some(line))?; let jmp1_idx = chunk.add_jump(chunk.code.len() as u32);
chunk.encode2(ADD, 4, 8, Some(line))?;
chunk.encode2(DIV, 4, 8, Some(line))?;
chunk.encode3(SETCOL, 4, 10, 7, Some(line))?;
chunk.encode2(INC, 7, 1, Some(line))?;
chunk.encode3(JMPLT, 7, 100, jmp1_idx as u16, Some(line))?;
chunk.encode2(CONST, 7, zero, Some(line))?; let jmp2_idx = chunk.add_jump(chunk.code.len() as u32);
chunk.encode2(MUL, 3, 2, Some(line))?; chunk.encode3(GET, 51, 10, 7, Some(line))?;
chunk.encode2(ADD, 3, 51, Some(line))?;
chunk.encode2(INC, 7, 1, Some(line))?;
chunk.encode3(JMPLT, 7, 100, jmp2_idx as u16, Some(line))?;
chunk.encode2(ADD, 5, 3, Some(line))?;
chunk.encode2(INC, 6, 1, Some(line))?;
chunk.encode3(JMPLT, 6, 1, jmp0_idx as u16, Some(line))?;
chunk.encode0(RET, Some(line))?;
let chunk = Arc::new(chunk);
vm.execute(chunk)?;
let result = vm.stack(5).get_float(&vm)?;
assert_eq!(result as f32, expected);
Ok(())
}