refactor: reorganize crate hierarchy
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
use fix_bytecode::PrimOpPhase;
|
||||
use fix_runtime::{BytecodeReader, List, Machine, MachineExt, NixType, Step, StrictValue, Value};
|
||||
use gc_arena::Mutation;
|
||||
|
||||
pub fn filter_force_list<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(0, reader, mc)?;
|
||||
let list = match m.peek_forced(0).expect_gc::<List>() {
|
||||
Ok(list) => list,
|
||||
Err(got) => return m.finish_type_err(NixType::List, got),
|
||||
};
|
||||
if list.inner.borrow().is_empty() {
|
||||
let val = m.pop();
|
||||
let _pred = m.pop();
|
||||
return m.return_from_primop(val, reader);
|
||||
}
|
||||
// prepare stack layout: [ pred list idx acc ]
|
||||
m.push(Value::new_inline(0));
|
||||
m.push(Value::new_gc(List::new_gc(mc)));
|
||||
reader.set_pc(PrimOpPhase::FilterCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn filter_call_pred<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(3, reader, mc)?;
|
||||
let pred = m.peek_forced(3);
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(1).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let elem = m.peek_forced(2).as_gc::<List>().unwrap().inner.borrow()[idx as usize];
|
||||
m.push(pred.relax());
|
||||
m.call(reader, mc, elem, PrimOpPhase::FilterCheck.ip() as usize)
|
||||
}
|
||||
|
||||
pub fn filter_check<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let ret = m.force_and_retry::<bool>(reader, mc)?;
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(1).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let list = m.peek_forced(2).as_gc::<List>().unwrap();
|
||||
let list = list.inner.borrow();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let acc = m.peek_forced(0).as_gc::<List>().unwrap();
|
||||
if ret {
|
||||
let mut acc = acc.unlock(mc).borrow_mut();
|
||||
acc.push(list[idx as usize]);
|
||||
}
|
||||
if idx as usize == list.len() - 1 {
|
||||
let acc = m.pop();
|
||||
let _ = m.pop(); // idx
|
||||
let _ = m.pop(); // list
|
||||
let _ = m.pop(); // pred
|
||||
return m.return_from_primop(acc, reader);
|
||||
}
|
||||
m.replace(1, Value::new_inline(idx + 1));
|
||||
reader.set_pc(PrimOpPhase::FilterCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
// foldl' op nul list
|
||||
//
|
||||
// Stack layouts across phases:
|
||||
// Entry: [op, nul, list]
|
||||
// Empty: [op, nul]
|
||||
// Call1: [op, list, idx, acc]
|
||||
// Call2: [op, list, idx, acc, intermediate]
|
||||
// Update: [op, list, idx, acc, result]
|
||||
pub fn foldl_strict_entry<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(0, reader, mc)?;
|
||||
let list_val = m.peek_forced(0);
|
||||
let Some(list) = list_val.as_gc::<List>() else {
|
||||
return m.finish_type_err(NixType::List, list_val.ty());
|
||||
};
|
||||
if list.inner.borrow().is_empty() {
|
||||
let _ = m.pop(); // list
|
||||
reader.set_pc(PrimOpPhase::FoldlStrictEmpty.ip() as usize);
|
||||
return Step::Continue(());
|
||||
}
|
||||
let list_val = m.pop();
|
||||
let nul_val = m.pop();
|
||||
m.push(list_val);
|
||||
m.push(Value::new_inline(0i32));
|
||||
m.push(nul_val);
|
||||
reader.set_pc(PrimOpPhase::FoldlStrictCall1.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn foldl_strict_empty<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let nul = m.force_and_retry::<StrictValue>(reader, mc)?;
|
||||
let _ = m.pop(); // op
|
||||
m.return_from_primop(nul.relax(), reader)
|
||||
}
|
||||
|
||||
pub fn foldl_strict_call1<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(3, reader, mc)?;
|
||||
let op = m.peek_forced(3);
|
||||
let acc = m.peek(0);
|
||||
m.push(op.relax());
|
||||
m.call(reader, mc, acc, PrimOpPhase::FoldlStrictCall2.ip() as usize)
|
||||
}
|
||||
|
||||
pub fn foldl_strict_call2<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(2).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let list = m.peek_forced(3).as_gc::<List>().unwrap();
|
||||
let elem = list.inner.borrow()[idx as usize];
|
||||
m.call(
|
||||
reader,
|
||||
mc,
|
||||
elem,
|
||||
PrimOpPhase::FoldlStrictUpdate.ip() as usize,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn foldl_strict_update<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
_mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let result = m.pop();
|
||||
m.replace(0, result);
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(1).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let list = m.peek_forced(2).as_gc::<List>().unwrap();
|
||||
let len = list.inner.borrow().len();
|
||||
if (idx as usize) + 1 == len {
|
||||
let acc = m.pop();
|
||||
let _ = m.pop(); // idx
|
||||
let _ = m.pop(); // list
|
||||
let _ = m.pop(); // op
|
||||
return m.return_from_primop(acc, reader);
|
||||
}
|
||||
m.replace(1, Value::new_inline(idx + 1));
|
||||
reader.set_pc(PrimOpPhase::FoldlStrictCall1.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn all_entry<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(0, reader, mc)?;
|
||||
let list = match m.peek_forced(0).expect_gc::<List>() {
|
||||
Ok(list) => list,
|
||||
Err(got) => return m.finish_type_err(NixType::List, got),
|
||||
};
|
||||
// FIXME: force callable
|
||||
m.force_slot(1, reader, mc)?;
|
||||
if list.inner.borrow().is_empty() {
|
||||
let _list = m.pop();
|
||||
let _pred = m.pop();
|
||||
return m.return_from_primop(Value::new_inline(true), reader);
|
||||
}
|
||||
// prepare stack layout: [ pred list idx ]
|
||||
m.push(Value::new_inline(0));
|
||||
reader.set_pc(PrimOpPhase::AllCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn all_call_pred<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let pred = m.peek_forced(2);
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(0).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let elem = m.peek_forced(1).as_gc::<List>().unwrap().inner.borrow()[idx as usize];
|
||||
m.push(pred.relax());
|
||||
m.call(reader, mc, elem, PrimOpPhase::AllCheck.ip() as usize)
|
||||
}
|
||||
|
||||
pub fn all_check<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let ret = m.force_and_retry::<bool>(reader, mc)?;
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(0).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let list = m.peek_forced(1).as_gc::<List>().unwrap();
|
||||
let list = list.inner.borrow();
|
||||
if idx as usize == list.len() - 1 || !ret {
|
||||
let _ = m.pop(); // idx
|
||||
let _ = m.pop(); // list
|
||||
let _ = m.pop(); // pred
|
||||
return m.return_from_primop(Value::new_inline(ret), reader);
|
||||
}
|
||||
m.replace(0, Value::new_inline(idx + 1));
|
||||
reader.set_pc(PrimOpPhase::AllCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn any_entry<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
m.force_slot(0, reader, mc)?;
|
||||
let list = match m.peek_forced(0).expect_gc::<List>() {
|
||||
Ok(list) => list,
|
||||
Err(got) => return m.finish_type_err(NixType::List, got),
|
||||
};
|
||||
// FIXME: force callable
|
||||
m.force_slot(1, reader, mc)?;
|
||||
if list.inner.borrow().is_empty() {
|
||||
let _list = m.pop();
|
||||
let _pred = m.pop();
|
||||
return m.return_from_primop(Value::new_inline(false), reader);
|
||||
}
|
||||
// prepare stack layout: [ pred list idx ]
|
||||
m.push(Value::new_inline(0));
|
||||
reader.set_pc(PrimOpPhase::AnyCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
pub fn any_call_pred<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let pred = m.peek_forced(2);
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(0).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let elem = m.peek_forced(1).as_gc::<List>().unwrap().inner.borrow()[idx as usize];
|
||||
m.push(pred.relax());
|
||||
m.call(reader, mc, elem, PrimOpPhase::AnyCheck.ip() as usize)
|
||||
}
|
||||
|
||||
pub fn any_check<'gc, M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
let ret = m.force_and_retry::<bool>(reader, mc)?;
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let idx = m.peek(0).as_inline::<i32>().unwrap();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let list = m.peek_forced(1).as_gc::<List>().unwrap();
|
||||
let list = list.inner.borrow();
|
||||
if idx as usize == list.len() - 1 || ret {
|
||||
let _ = m.pop(); // idx
|
||||
let _ = m.pop(); // list
|
||||
let _ = m.pop(); // pred
|
||||
return m.return_from_primop(Value::new_inline(ret), reader);
|
||||
}
|
||||
m.replace(0, Value::new_inline(idx + 1));
|
||||
reader.set_pc(PrimOpPhase::AnyCallPred.ip() as usize);
|
||||
Step::Continue(())
|
||||
}
|
||||
Reference in New Issue
Block a user