Skip to content

Commit

Permalink
Make Error generic over contained value.
Browse files Browse the repository at this point in the history
  • Loading branch information
01mf02 committed Apr 17, 2024
1 parent 9fecbb1 commit 231da3a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 29 deletions.
12 changes: 6 additions & 6 deletions jaq-interpret/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ use core::fmt;
/// Each variant shows an example of how it can be produced.
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
pub enum Error<V = Val> {
/// `0 | error`
Val(Val),
Val(V),

/// Expected a value of given type, but got something else
Type(Val, Type),
Type(V, Type),
/// `1 - "a"`
MathOp(Val, jaq_syn::MathOp, Val),
MathOp(V, jaq_syn::MathOp, V),
/// `{} | .[0]` or `[] | has("a")` or `{} | has(0)`
Index(Val, Val),
Index(V, V),

/// `[] | .[0] = 0`
IndexOutOfBounds(isize),
Expand All @@ -28,7 +28,7 @@ pub enum Error {
///
/// This is used internally to execute tail-recursive filters.
/// If this can be observed by users, then this is a bug.
TailCall(crate::filter::TailCall),
TailCall(crate::filter::TailCall<V>),
}

/// Types and sets of types.
Expand Down
21 changes: 10 additions & 11 deletions jaq-interpret/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::box_iter::{box_once, flat_map_with, map_with, BoxIter};
use crate::results::then;
use crate::val::ValT;
use crate::Error;
use crate::val::{ValR2, ValT};
use alloc::{boxed::Box, vec::Vec};
pub use jaq_syn::path::Opt;

Expand Down Expand Up @@ -42,13 +41,13 @@ impl<'a, U: Clone + 'a> Path<U> {
}

impl<'a, V: ValT + 'a> Path<V> {
pub fn run(self, v: V) -> Box<dyn Iterator<Item = Result<V, Error>> + 'a> {
pub fn run(self, v: V) -> Box<dyn Iterator<Item = ValR2<V>> + 'a> {
run(self.0.into_iter(), v)
}

pub fn update<F>(mut self, v: V, f: F) -> Result<V, Error>
pub fn update<F>(mut self, v: V, f: F) -> ValR2<V>
where
F: Fn(V) -> Box<dyn Iterator<Item = Result<V, Error>> + 'a>,
F: Fn(V) -> Box<dyn Iterator<Item = ValR2<V>> + 'a>,
{
if let Some(last) = self.0.pop() {
update(self.0.into_iter(), last, v, &f)
Expand All @@ -59,7 +58,7 @@ impl<'a, V: ValT + 'a> Path<V> {
}
}

fn run<'a, V: ValT + 'a, I>(mut iter: I, val: V) -> Box<dyn Iterator<Item = Result<V, Error>> + 'a>
fn run<'a, V: ValT + 'a, I>(mut iter: I, val: V) -> Box<dyn Iterator<Item = ValR2<V>> + 'a>
where
I: Iterator<Item = (Part<V>, Opt)> + Clone + 'a,
{
Expand All @@ -72,10 +71,10 @@ where
}
}

fn update<'a, V: ValT, P, F>(mut iter: P, last: (Part<V>, Opt), v: V, f: &F) -> Result<V, Error>
fn update<'a, V: ValT, P, F>(mut iter: P, last: (Part<V>, Opt), v: V, f: &F) -> ValR2<V>
where
P: Iterator<Item = (Part<V>, Opt)> + Clone,
F: Fn(V) -> Box<dyn Iterator<Item = Result<V, Error>> + 'a>,
F: Fn(V) -> Box<dyn Iterator<Item = ValR2<V>> + 'a>,
{
if let Some((part, opt)) = iter.next() {
use core::iter::once;
Expand All @@ -86,18 +85,18 @@ where
}

impl<'a, V: ValT + 'a> Part<V> {
fn run(&self, v: V) -> impl Iterator<Item = Result<V, Error>> + 'a {
fn run(&self, v: V) -> impl Iterator<Item = ValR2<V>> + 'a {
match self {
Self::Index(idx) => box_once(v.index(idx)),
Self::Range(None, None) => Box::new(v.values()),
Self::Range(from, upto) => box_once(v.range(from.as_ref()..upto.as_ref())),
}
}

fn update<F, I>(&self, v: V, opt: Opt, f: F) -> Result<V, Error>
fn update<F, I>(&self, v: V, opt: Opt, f: F) -> ValR2<V>
where
F: Fn(V) -> I,
I: Iterator<Item = Result<V, Error>>,
I: Iterator<Item = ValR2<V>>,
{
match self {
Self::Index(idx) => v.map_index(idx, opt, f),
Expand Down
33 changes: 21 additions & 12 deletions jaq-interpret/src/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,40 +55,49 @@ fn rc_unwrap_or_clone<T: Clone>(a: Rc<T>) -> T {
Rc::try_unwrap(a).unwrap_or_else(|a| (*a).clone())
}

pub(crate) trait ValT:
Clone + From<bool> + From<isize> + From<String> + FromIterator<Self>
pub type ValR2<V> = Result<V, Error<V>>;

pub trait ValT:
Clone + fmt::Display + From<bool> + From<isize> + From<String> + FromIterator<Self>
{
fn from_map<I: IntoIterator<Item = (Self, Self)>>(iter: I) -> ValR2<Self>;

/// If `Ok(k)` is in `v.keys()`, then
/// `v.index(k)` must be `Ok(_)` and in `v.range(Range::default())`.
fn values(self) -> Box<dyn Iterator<Item = Result<Self, Error>>>;
fn index(self, index: &Self) -> Result<Self, Error>;
fn range(self, range: Range<&Self>) -> Result<Self, Error>;
fn values(self) -> Box<dyn Iterator<Item = ValR2<Self>>>;
fn index(self, index: &Self) -> ValR2<Self>;
fn range(self, range: Range<&Self>) -> ValR2<Self>;

fn map_values<I: Iterator<Item = Result<Self, Error>>>(
fn map_values<I: Iterator<Item = ValR2<Self>>>(
self,
opt: Opt,
f: impl Fn(Self) -> I,
) -> Result<Self, Error>;
fn map_index<I: Iterator<Item = Result<Self, Error>>>(
) -> ValR2<Self>;
fn map_index<I: Iterator<Item = ValR2<Self>>>(
self,
index: &Self,
opt: Opt,
f: impl Fn(Self) -> I,
) -> Result<Self, Error>;
fn map_range<I: Iterator<Item = Result<Self, Error>>>(
) -> ValR2<Self>;
fn map_range<I: Iterator<Item = ValR2<Self>>>(
self,
range: Range<&Self>,
opt: Opt,
f: impl Fn(Self) -> I,
) -> Result<Self, Error>;
) -> ValR2<Self>;

fn as_bool(&self) -> bool;
}

type Range<V> = core::ops::Range<Option<V>>;

impl ValT for Val {
fn values(self) -> Box<dyn Iterator<Item = ValR>> {
fn from_map<I: IntoIterator<Item = (Self, Self)>>(iter: I) -> ValR2<Self> {
let iter = iter.into_iter().map(|(k, v)| Ok((k.to_str()?, v)));
Ok(Self::obj(iter.collect::<Result<_, _>>()?))
}

fn values(self) -> Box<dyn Iterator<Item = ValR2<Self>>> {
match self {
Self::Arr(a) => Box::new(rc_unwrap_or_clone(a).into_iter().map(Ok)),
Self::Obj(o) => Box::new(rc_unwrap_or_clone(o).into_iter().map(|(_k, v)| Ok(v))),
Expand Down

0 comments on commit 231da3a

Please sign in to comment.