pub mod buffer;
pub mod builtins;
pub mod frame;
pub mod gc;
pub mod hash;
pub mod libs;
pub mod machine;
pub mod ops;
pub mod table;
pub mod value;
pub use machine::VM;
use std::fs;
pub use table::TableKey;
pub use value::Value;
use crate::bytecode::deserialize;
pub fn execute_bytecode(bytes: &[u8]) -> Result<Value, String> {
execute_bytecode_at(bytes, None)
}
fn execute_bytecode_at(bytes: &[u8], path: Option<&str>) -> Result<Value, String> {
let proto = deserialize(bytes)?;
let mut vm = VM::new();
vm.script_dir = path.and_then(script_dir);
vm.execute_program(proto)
}
fn script_dir(path: &str) -> Option<std::path::PathBuf> {
std::path::Path::new(path)
.parent()
.map(|dir| dir.to_path_buf())
}
pub fn run_file_with_options(path: &str, options: crate::compiler::Options) -> Result<(), String> {
let bytes = fs::read(path).map_err(|e| format!("failed to read {}: {}", path, e))?;
run_bytes(path, bytes, options)
}
pub fn run_bytes(
path: &str,
bytes: Vec<u8>,
options: crate::compiler::Options,
) -> Result<(), String> {
if bytes.starts_with(crate::bytecode::MAGIC) {
return execute_bytecode_at(&bytes, Some(path)).map(|_| ());
}
let source = String::from_utf8(bytes)
.map_err(|_| format!("failed to read {}: file is not valid UTF-8", path))?;
let proto = crate::compiler::compile_program(&source, path, options)?;
let mut vm = VM::new();
vm.script_dir = script_dir(path);
vm.execute_program(proto)
.map(|_| ())
.map_err(|err| vm.describe_error(&err))
}
pub fn run_file(path: &str) -> Result<(), String> {
run_file_with_options(path, crate::compiler::Options::RUN)
}