use crate::VMConfig;
use crate::compiler::BytecodeCompiler;
use crate::executor::VirtualMachine;
use crate::type_tracking::NativeKind;
use shape_value::{KindedSlot, VMError};
pub fn eval_raw(source: &str) -> (u64, Option<NativeKind>) {
let program = shape_ast::parser::parse_program(source).expect("parse failed");
let mut compiler = BytecodeCompiler::new();
compiler.set_source(source);
let bytecode = compiler.compile(&program).expect("compile failed");
let kind = top_level_return_kind(&bytecode);
let mut vm = VirtualMachine::new(VMConfig::default());
vm.load_program(bytecode);
let bits = vm.execute_raw(None).expect("execution failed");
(bits, kind)
}
#[inline]
fn top_level_return_kind(program: &crate::bytecode::BytecodeProgram) -> Option<NativeKind> {
program.top_level_frame.as_ref()?.return_kind
}
pub fn eval(source: &str) -> KindedSlot {
let program = shape_ast::parser::parse_program(source).expect("parse failed");
let mut compiler = BytecodeCompiler::new();
compiler.set_source(source);
let bytecode = compiler.compile(&program).expect("compile failed");
let mut vm = VirtualMachine::new(VMConfig::default());
vm.load_program(bytecode);
vm.execute(None).expect("execution failed")
}
pub fn eval_result(source: &str) -> Result<KindedSlot, VMError> {
let program = shape_ast::parser::parse_program(source)
.map_err(|e| VMError::RuntimeError(format!("{:?}", e)))?;
let mut compiler = BytecodeCompiler::new();
compiler.set_source(source);
let bytecode = compiler
.compile(&program)
.map_err(|e| VMError::RuntimeError(format!("{:?}", e)))?;
let mut vm = VirtualMachine::new(VMConfig::default());
vm.load_program(bytecode);
vm.execute(None)
}
pub fn eval_with_kind(source: &str, expected: NativeKind) -> KindedSlot {
let (bits, _) = eval_raw(source);
KindedSlot::new(shape_value::ValueSlot::from_raw(bits), expected)
}
pub fn compile(source: &str) -> crate::bytecode::BytecodeProgram {
let program = shape_ast::parser::parse_program(source).expect("parse failed");
let mut compiler = BytecodeCompiler::new();
compiler.set_source(source);
compiler.compile(&program).expect("compile failed")
}
pub fn eval_with_prelude(source: &str) -> KindedSlot {
let program = shape_ast::parser::parse_program(source).expect("parse failed");
let mut loader = shape_runtime::module_loader::ModuleLoader::new();
let (graph, stdlib_names, prelude_imports) =
crate::module_resolution::build_graph_and_stdlib_names(&program, &mut loader, &[])
.expect("graph build failed");
let mut compiler = BytecodeCompiler::new();
compiler.stdlib_function_names = stdlib_names;
compiler.set_source(source);
let bytecode = compiler
.compile_with_graph_and_prelude(&program, graph, &prelude_imports)
.expect("compile failed");
let mut vm = VirtualMachine::new(VMConfig::default());
vm.load_program(bytecode);
vm.execute(None).expect("execution failed")
}
pub fn compile_with_prelude(source: &str) -> Result<crate::bytecode::BytecodeProgram, VMError> {
let program = shape_ast::parser::parse_program(source)
.map_err(|e| VMError::RuntimeError(format!("{:?}", e)))?;
let mut loader = shape_runtime::module_loader::ModuleLoader::new();
let (graph, stdlib_names, prelude_imports) =
crate::module_resolution::build_graph_and_stdlib_names(&program, &mut loader, &[])
.map_err(|e| VMError::RuntimeError(format!("{:?}", e)))?;
let mut compiler = BytecodeCompiler::new();
compiler.stdlib_function_names = stdlib_names;
compiler.set_source(source);
compiler
.compile_with_graph_and_prelude(&program, graph, &prelude_imports)
.map_err(|e| VMError::RuntimeError(format!("{:?}", e)))
}
pub fn eval_typed_i64(source: &str) -> i64 {
eval_with_kind(source, NativeKind::Int64)
.as_i64()
.expect("eval_typed_i64: result is not an integer")
}
pub fn eval_typed_f64(source: &str) -> f64 {
eval_with_kind(source, NativeKind::Float64)
.as_f64()
.expect("eval_typed_f64: result is not a float")
}
pub fn eval_typed_bool(source: &str) -> bool {
eval_with_kind(source, NativeKind::Bool)
.as_bool()
.expect("eval_typed_bool: result is not a boolean")
}