use super::*;
#[derive(Debug, Clone, PartialEq)]
pub enum VmResult {
Value(VmValue),
Request(VmRequest),
}
#[derive(Debug, Clone, PartialEq)]
pub enum VmValue {
Int(String),
Float(String),
String(StringTree),
Bytes(BytesTree),
Path(Rc<PathBuf>),
FileHandle(VmFileHandle),
Bool(bool),
Unit,
List(ListTree<Rc<VmValue>>),
Tuple(Vec<VmValue>),
Record(BTreeMap<typed_ir::Name, VmValue>),
Variant {
tag: typed_ir::Name,
value: Option<Box<VmValue>>,
},
EffectOp(typed_ir::Path),
PrimitiveOp(Rc<VmPrimitive>),
Resume(Rc<VmResume>),
Closure(Rc<VmClosure>),
Thunk(Rc<VmThunk>),
EffectId(u64),
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmFileHandle {
pub(crate) state: Rc<std::cell::RefCell<VmFileHandleState>>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct VmFileHandleState {
pub(crate) path: Rc<PathBuf>,
pub(crate) text: StringTree,
pub(crate) dirty: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmRequest {
pub effect: typed_ir::Path,
pub payload: VmValue,
pub continuation: VmContinuation,
pub blocked_id: Option<u64>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmPrimitive {
pub op: typed_ir::PrimitiveOp,
pub args: Vec<VmValue>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmClosure {
pub(super) param: typed_ir::Name,
pub(super) param_ty: Type,
pub(super) body: Expr,
pub(super) ret: Type,
pub(super) env: Env,
pub(super) guard_stack: GuardStack,
pub(super) self_name: Option<typed_ir::Path>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmThunk {
pub(super) body: ThunkBody,
pub(super) env: Env,
pub(super) guard_stack: GuardStack,
pub(super) blocked: Vec<BlockedEffect>,
}
#[derive(Debug, Clone, PartialEq)]
pub(super) enum ThunkBody {
Value(VmValue),
Expr(Expr),
Emit {
effect: typed_ir::Path,
payload: VmValue,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct VmResume {
pub(super) continuation: VmContinuation,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct VmContinuation {
pub(super) frames: Vec<Frame>,
pub(super) guard_stack: GuardStack,
pub(super) blocked_ids: Vec<u64>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct VmProfile {
pub eval_expr_calls: usize,
pub direct_known_closure_calls: usize,
pub direct_binary_primitive_calls: usize,
pub max_eval_depth: usize,
pub continuation_steps: usize,
pub max_continuation_frames: usize,
pub continuation_clones: usize,
pub continuation_clone_frames: usize,
pub continuation_splits: usize,
pub continuation_split_frames: usize,
pub continuation_prepends: usize,
pub continuation_prepend_frames: usize,
pub primitive_apps: usize,
pub list_merge_calls: usize,
pub list_view_raw_calls: usize,
pub string_concat_calls: usize,
pub string_concat_input_chars: usize,
pub string_to_string_calls: usize,
}
impl VmProfile {
pub fn merge(&mut self, other: Self) {
self.eval_expr_calls += other.eval_expr_calls;
self.direct_known_closure_calls += other.direct_known_closure_calls;
self.direct_binary_primitive_calls += other.direct_binary_primitive_calls;
self.max_eval_depth = self.max_eval_depth.max(other.max_eval_depth);
self.continuation_steps += other.continuation_steps;
self.max_continuation_frames = self
.max_continuation_frames
.max(other.max_continuation_frames);
self.continuation_clones += other.continuation_clones;
self.continuation_clone_frames += other.continuation_clone_frames;
self.continuation_splits += other.continuation_splits;
self.continuation_split_frames += other.continuation_split_frames;
self.continuation_prepends += other.continuation_prepends;
self.continuation_prepend_frames += other.continuation_prepend_frames;
self.primitive_apps += other.primitive_apps;
self.list_merge_calls += other.list_merge_calls;
self.list_view_raw_calls += other.list_view_raw_calls;
self.string_concat_calls += other.string_concat_calls;
self.string_concat_input_chars += other.string_concat_input_chars;
self.string_to_string_calls += other.string_to_string_calls;
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub(super) struct GuardStack(pub(super) PersistentVector<GuardEntry>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct PersistentVector<T> {
pub(super) len: usize,
pub(super) tail: Option<Rc<PersistentVectorChunk<T>>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct GuardEntry {
pub(super) var: EffectIdVar,
pub(super) id: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct PersistentVectorChunk<T> {
pub(super) items: Rc<[T]>,
pub(super) parent: Option<Rc<PersistentVectorChunk<T>>>,
}
#[derive(Debug, Clone, PartialEq)]
pub(super) struct BlockedEffect {
pub(super) guard_id: u64,
pub(super) allowed: typed_ir::Type,
pub(super) active: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub(super) enum Frame {
BindHere,
ApplyCallee {
arg: Expr,
env: Env,
delay_arg: bool,
},
ApplyArg {
callee: VmValue,
},
If {
then_branch: Expr,
else_branch: Expr,
env: Env,
},
Tuple {
done: Vec<VmValue>,
remaining: Vec<Expr>,
env: Env,
force_items: bool,
},
Select {
field: typed_ir::Name,
},
Match {
arms: Vec<MatchArm>,
env: Env,
},
Variant {
tag: typed_ir::Name,
},
BlockLet {
pattern: Pattern,
remaining: Vec<Stmt>,
tail: Option<Expr>,
env: Env,
},
BlockExpr {
remaining: Vec<Stmt>,
tail: Option<Expr>,
env: Env,
},
Handle {
id: u64,
arms: Vec<HandleArm>,
env: Env,
guard_stack: GuardStack,
expected_ty: Type,
},
HandleGuard {
id: u64,
request: VmRequest,
outer: VmContinuation,
handler_guard_stack: GuardStack,
arms: Vec<HandleArm>,
env: Env,
arm_env: Env,
body: Expr,
expected_ty: Type,
},
LocalPushId {
parent: GuardStack,
},
BlockedEffects {
blocked: Vec<BlockedEffect>,
active: bool,
},
Coerce {
to: typed_ir::Type,
},
WrapThunkResult {
expected_ty: Type,
},
}
pub(super) type Env = HashMap<typed_ir::Path, VmValue>;