improve length/2 (#1325)
This commit is contained in:
@@ -4119,6 +4119,14 @@ impl Machine {
|
||||
self.cpu_now();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallDeterministicLengthRundown(_) => {
|
||||
try_or_throw!(self.machine_st, self.det_length_rundown());
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteDeterministicLengthRundown(_) => {
|
||||
try_or_throw!(self.machine_st, self.det_length_rundown());
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallCurrentTime(_) => {
|
||||
self.current_time();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
|
||||
@@ -257,6 +257,19 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn resource_error(&mut self, value: HeapCellValue) -> MachineError {
|
||||
let stub = functor!(
|
||||
atom!("resource_error"),
|
||||
[atom(atom!("finite_memory")), cell(value)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn type_error<T: TypeError>(
|
||||
&mut self,
|
||||
valid_type: ValidType,
|
||||
|
||||
@@ -3231,6 +3231,38 @@ impl Machine {
|
||||
self.machine_st.unify_f64(secs, self.machine_st.registers[1]);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn det_length_rundown(&mut self) -> CallResult {
|
||||
let stub_gen = || functor_stub(atom!("length"), 2);
|
||||
let len = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
|
||||
|
||||
let n = match Number::try_from(len) {
|
||||
Ok(Number::Fixnum(n)) => n.get_num() as usize,
|
||||
Ok(Number::Integer(n)) => match n.to_usize() {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
let err = self.machine_st.resource_error(len);
|
||||
return Err(self.machine_st.error_form(err, stub_gen()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
let h = self.machine_st.heap.len();
|
||||
|
||||
iter_to_heap_list(
|
||||
&mut self.machine_st.heap,
|
||||
(0 .. n).map(|i| heap_loc_as_cell!(h + 2 * i + 1)),
|
||||
);
|
||||
|
||||
let tail = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
||||
self.machine_st.bind(tail.as_var().unwrap(), heap_loc_as_cell!(h));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn current_time(&mut self) {
|
||||
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
|
||||
|
||||
Reference in New Issue
Block a user