Skip to content

Commit

Permalink
Change rooted_iter to a fallible iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
CeleritasCelery committed Oct 25, 2023
1 parent 6f535a5 commit 66925a4
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 103 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ streaming-iterator = "0.1.9"
text-buffer = { version = "0.1.0", path = "crates/text-buffer" }
titlecase = "2.2.1"
fallible-iterator = "0.3.0"
fallible-streaming-iterator = "0.1.9"

# [dev-dependencies]
# backtrace-on-stack-overflow = "0.3.0"
Expand Down
3 changes: 2 additions & 1 deletion rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
single_line_let_else_max_width = 100
max_width = 100
single_line_let_else_max_width = 90
single_line_if_else_max_width = 80
chain_width = 80
fn_call_width = 80
Expand Down
24 changes: 15 additions & 9 deletions src/core/cons/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use super::super::{
};
use super::Cons;
use anyhow::Result;
use streaming_iterator::StreamingIterator;

#[derive(Clone)]
pub(crate) struct ConsIter<'ob> {
Expand Down Expand Up @@ -100,38 +99,44 @@ impl std::error::Error for ConsError {}

pub(crate) struct ElemStreamIter<'rt> {
elem: Option<&'rt mut Rt<GcObj<'static>>>,
cons: Option<&'rt mut Rt<&'static Cons>>,
cons: Option<Result<&'rt mut Rt<&'static Cons>, ConsError>>,
}

impl<'rt> ElemStreamIter<'rt> {
pub(crate) fn new(
elem: Option<&'rt mut Rt<GcObj<'static>>>,
cons: Option<&'rt mut Rt<&'static Cons>>,
) -> Self {
Self { elem, cons }
Self { elem, cons: cons.map(Ok) }
}
}

impl<'rt> StreamingIterator for ElemStreamIter<'rt> {
impl<'rt> fallible_streaming_iterator::FallibleStreamingIterator for ElemStreamIter<'rt> {
type Item = Rt<GcObj<'static>>;
type Error = ConsError;

fn advance(&mut self) {
fn advance(&mut self) -> Result<(), ConsError> {
if let Some(cons) = &mut self.cons {
let cons = match cons {
Ok(x) => x,
Err(e) => return Err(*e),
};
let elem = self.elem.as_mut().expect("Element should never be None while Cons is Some");
let car = unsafe { cons.bind_unchecked().car() };
elem.set(car);
match unsafe { cons.bind_unchecked().cdr().untag() } {
Object::Cons(next) => {
// dissociate the borrow of cons from cell
let x = unsafe { std::mem::transmute::<&Cons, &Cons>(next) };
cons.set(x);
}
_ => {
self.cons = None;
}
Object::NIL => self.cons = None,
_ => self.cons = Some(Err(ConsError::NonNilCdr)),
}
} else {
self.elem = None;
}
Ok(())
}

fn get(&self) -> Option<&Self::Item> {
Expand Down Expand Up @@ -230,6 +235,7 @@ impl<'ob> GcObj<'ob> {
#[cfg(test)]
mod test {
use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;

use super::super::super::gc::{Context, RootSet};
use crate::list;
Expand Down Expand Up @@ -288,7 +294,7 @@ mod test {
let cons = list![1, 2, 3, 4; cx];
rooted_iter!(iter, cons, cx);
for expect in 1..=4 {
let actual = iter.next().unwrap().bind(cx);
let actual = iter.next().unwrap().unwrap().bind(cx);
assert_eq!(actual, expect);
}
assert!(iter.is_empty());
Expand Down
7 changes: 0 additions & 7 deletions src/core/gc/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,6 @@ impl<T> Rt<T> {
{
unsafe { &*(slice as *const [Rt<T>] as *const [U]) }
}

/// This functions is very unsafe to call directly. The caller must ensure
/// that resulting Rt is only exposed through references and that it is
/// properly rooted.
pub(crate) unsafe fn new_unchecked(item: T) -> Rt<T> {
Rt { inner: item, _aliasable: PhantomPinned }
}
}

impl TryFrom<&Rt<GcObj<'_>>> for usize {
Expand Down
30 changes: 0 additions & 30 deletions src/core/object/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::core::gc::{GcManaged, GcMark, Rt};
use anyhow::{bail, ensure, Result};
use fn_macros::Trace;
use std::fmt::{self, Debug, Display};
use streaming_iterator::StreamingIterator;

/// A function implemented in lisp. Note that all functions are byte compiled,
/// so this contains the byte-code representation of the function.
Expand Down Expand Up @@ -111,35 +110,6 @@ impl Debug for ByteFn {
}
}

pub(crate) struct ByteFnStreamIter<'rt> {
vector: &'rt Rt<&'static ByteFn>,
elem: Option<Rt<GcObj<'static>>>,
idx: usize,
}

impl<'rt> Rt<&'static ByteFn> {
#[allow(clippy::iter_not_returning_iterator)]
pub(crate) fn iter(&'rt mut self) -> ByteFnStreamIter<'rt> {
ByteFnStreamIter { vector: self, elem: None, idx: 0 }
}
}

impl<'rt> StreamingIterator for ByteFnStreamIter<'rt> {
type Item = Rt<GcObj<'static>>;

fn advance(&mut self) {
unsafe {
let obj = self.vector.bind_unchecked().index(self.idx);
self.elem = obj.map(|x| Rt::new_unchecked(x.with_lifetime()));
self.idx += 1;
}
}

fn get(&self) -> Option<&Self::Item> {
self.elem.as_ref()
}
}

/// Argument requirments to a function.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) struct FnArgs {
Expand Down
6 changes: 3 additions & 3 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::fns::{assq, eq};
use crate::{root, rooted_iter};
use anyhow::{anyhow, bail, ensure, Result};
use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;
use fn_macros::defun;
use streaming_iterator::StreamingIterator;

#[defun]
pub(crate) fn apply<'ob>(
Expand Down Expand Up @@ -63,7 +63,7 @@ fn run_hooks<'ob>(
match val.untag() {
Object::Cons(hook_list) => {
rooted_iter!(hooks, hook_list, cx);
while let Some(hook) = hooks.next() {
while let Some(hook) = hooks.next()? {
let func: &Rt<Gc<Function>> = hook.try_into()?;
root!(args, Vec::new(), cx);
func.call(args, env, cx, None)?;
Expand Down Expand Up @@ -99,7 +99,7 @@ fn run_hook_with_args<'ob>(
match val.untag() {
Object::Cons(hook_list) => {
rooted_iter!(hooks, hook_list, cx);
while let Some(hook) = hooks.next() {
while let Some(hook) = hooks.next()? {
let func: &Rt<Gc<Function>> = hook.try_into()?;
let args = Rt::bind_slice(args, cx).to_vec();
root!(args, cx);
Expand Down
48 changes: 23 additions & 25 deletions src/fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{root, rooted_iter};
use anyhow::{bail, ensure, Result};
use bstr::ByteSlice;
use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;
use fn_macros::defun;
use streaming_iterator::StreamingIterator;

Expand Down Expand Up @@ -114,38 +115,35 @@ pub(crate) fn mapcar<'ob>(
Object::NIL => Ok(nil()),
Object::Cons(cons) => {
rooted_iter!(iter, cons, cx);
mapcar_internal(iter, function, env, cx)
root!(outputs, Vec::new(), cx);
root!(call_arg, Vec::new(), cx);
while let Some(obj) = iter.next()? {
call_arg.push(obj);
let output = function.call(call_arg, env, cx, None)?;
outputs.push(output);
call_arg.clear();
}
// TODO: remove this intermediate vector
Ok(slice_into_list(outputs.bind_ref(cx), None, cx))
}
Object::ByteFn(fun) => {
root!(fun, cx);
mapcar_internal(fun.iter(), function, env, cx)
root!(outputs, Vec::new(), cx);
root!(call_arg, Vec::new(), cx);
for i in 0..=3 {
let item = fun.bind(cx).index(i).unwrap();
call_arg.push(item);
let output = function.call(call_arg, env, cx, None)?;
outputs.push(output);
call_arg.clear();
}
// TODO: remove this intermediate vector
Ok(slice_into_list(outputs.bind_ref(cx), None, cx))
}
_ => Err(TypeError::new(Type::Sequence, sequence).into()),
}
}

fn mapcar_internal<'ob, T>(
mut iter: T,
function: &Rt<Gc<Function>>,
env: &mut Rt<Env>,
cx: &'ob mut Context,
) -> Result<GcObj<'ob>>
where
T: StreamingIterator<Item = Rt<GcObj<'static>>>,
{
root!(outputs, Vec::new(), cx);
root!(call_arg, Vec::new(), cx);
while let Some(x) = iter.next() {
let obj = x.bind(cx);
call_arg.push(obj);
let output = function.call(call_arg, env, cx, None)?;
outputs.push(output);
call_arg.clear();
}
// TODO: remove this intermediate vector
Ok(slice_into_list(outputs.bind_ref(cx), None, cx))
}

#[defun]
pub(crate) fn mapc<'ob>(
function: &Rt<Gc<Function>>,
Expand All @@ -158,7 +156,7 @@ pub(crate) fn mapc<'ob>(
List::Cons(cons) => {
root!(call_arg, Vec::new(), cx);
rooted_iter!(elements, cons, cx);
while let Some(elem) = elements.next() {
while let Some(elem) = elements.next()? {
call_arg.push(elem);
function.call(call_arg, env, cx, None)?;
call_arg.clear();
Expand Down
Loading

0 comments on commit 66925a4

Please sign in to comment.