use crate::lexer::Span;
use thiserror::Error;
mod access;
mod cache;
mod compiler;
mod entry_points;
mod format;
mod host;
mod instruction;
mod json;
mod ops;
mod record;
mod schema;
mod state;
mod value;
mod vm;
pub use cache::{CompiledProgramCache, CompiledProgramCacheStats};
#[allow(unused_imports)]
pub(crate) use compiler::*;
pub use entry_points::{
compile_program, compile_source, execute_compiled, execute_compiled_traced,
execute_compiled_traced_with_projected_bindings, execute_compiled_traced_with_scratch,
execute_compiled_traced_with_scratch_and_projected_bindings,
execute_compiled_with_projected_bindings, execute_compiled_with_scratch,
execute_compiled_with_scratch_and_projected_bindings, execute_program, prewarm,
profile_compiled, profile_compiled_with_projected_bindings, profile_compiled_with_scratch,
profile_compiled_with_scratch_and_projected_bindings,
};
pub use host::{ToolHost, ToolHostCall, ToolHostError};
#[allow(unused_imports)]
pub(crate) use instruction::*;
pub use json::from_json;
pub use record::Record;
#[allow(unused_imports)]
pub(crate) use record::{Symbol, intern_symbol, lookup_symbol, record_with_capacity, symbol_name};
#[allow(unused_imports)]
pub(crate) use schema::{
ValidationPlan, compile_schema_value, execute_validate_builtin, execute_validation_plan,
};
#[allow(unused_imports)]
pub(crate) use vm::*;
#[allow(unused_imports)]
pub(crate) use access::*;
#[allow(unused_imports)]
pub(crate) use format::*;
#[allow(unused_imports)]
pub(crate) use json::*;
#[allow(unused_imports)]
pub(crate) use ops::*;
pub use state::{Snapshot, State};
pub use value::{
ImageValue, LASH_TYPE_KEY, ListValue, ProjectedBindingError, ProjectedBindings,
ProjectedFuture, ProjectedHostValue, ProjectedReadRequest, ProjectedReadResponse,
ProjectedValue, Value,
};
use vm::IterState;
#[derive(Debug, Error, PartialEq)]
pub enum RuntimeError {
#[error("unknown name `{name}`")]
UndefinedVariable { name: String },
#[error("`for` expects a list")]
NonListIteration,
#[error("`submit` can't be used inside `parallel`")]
FinishInsideParallel,
#[error("`parallel` assigns `{name}` more than once")]
ParallelConflict { name: String },
#[error("unknown builtin `{name}`")]
UnknownBuiltin { name: String },
#[error("{message}")]
TypeError { message: String },
#[error("{message}")]
ValueError { message: String },
}
#[derive(Debug, Error, PartialEq)]
#[error("{error}")]
pub struct RuntimeFailure {
pub error: RuntimeError,
pub span: Option<Span>,
}
#[derive(Default)]
pub struct ExecutionScratch {
stack: Vec<Value>,
iter_stack: Vec<IterState>,
slot_values: Vec<Option<Value>>,
}
impl ExecutionScratch {
pub fn new() -> Self {
Self::default()
}
}
pub(crate) const COOPERATIVE_YIELD_INSTRUCTION_BUDGET: usize = 1024;
#[derive(Clone)]
pub struct CompiledProgram {
pub(crate) chunk: Chunk,
pub(crate) compile_stats: CompileStats,
}
impl CompiledProgram {
pub fn compile_stats(&self) -> &CompileStats {
&self.compile_stats
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ExecutionOutcome {
Continued,
Finished(Value),
}
#[derive(Clone, Debug, Default)]
pub struct ProfileReport {
instruction_stats: Vec<ProfileStat>,
builtin_stats: Vec<ProfileStat>,
compile_stats: CompileStats,
}
impl ProfileReport {
pub fn instruction_stats(&self) -> &[ProfileStat] {
&self.instruction_stats
}
pub fn builtin_stats(&self) -> &[ProfileStat] {
&self.builtin_stats
}
pub fn compile_stats(&self) -> &CompileStats {
&self.compile_stats
}
pub fn merge(&mut self, other: &Self) {
merge_stats(&mut self.instruction_stats, &other.instruction_stats);
merge_stats(&mut self.builtin_stats, &other.builtin_stats);
self.compile_stats.merge(&other.compile_stats);
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct CompileStats {
pub type_literals_total: u64,
pub type_literals_const_folded: u64,
pub type_literals_dynamic: u64,
pub type_ref_sites: u64,
}
impl CompileStats {
pub fn merge(&mut self, other: &Self) {
self.type_literals_total += other.type_literals_total;
self.type_literals_const_folded += other.type_literals_const_folded;
self.type_literals_dynamic += other.type_literals_dynamic;
self.type_ref_sites += other.type_ref_sites;
}
}
#[derive(Clone, Debug, Default)]
pub struct ProfileStat {
pub name: &'static str,
pub count: u64,
pub total_ns: u128,
}
impl ProfileStat {
pub fn avg_ns(&self) -> u128 {
if self.count == 0 {
0
} else {
self.total_ns / self.count as u128
}
}
}
pub fn unwrap_type_value(value: &Value) -> Option<&Value> {
let record = value.as_record()?;
if record.len() != 1 {
return None;
}
record.get(LASH_TYPE_KEY)
}
#[cfg(test)]
mod tests;