Skip to content

Commit

Permalink
Adds reusable RawValueExpr::resolve method (#854)
Browse files Browse the repository at this point in the history
  • Loading branch information
zslayton authored Nov 8, 2024
1 parent f36249e commit 36c3dca
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 48 deletions.
26 changes: 24 additions & 2 deletions src/lazy/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use crate::lazy::streaming_raw_reader::RawReaderState;
use crate::read_config::ReadConfig;
use crate::result::IonFailure;
use crate::{
v1_0, v1_1, Catalog, Encoding, IonResult, IonType, LazyExpandedFieldName, LazyRawWriter,
RawSymbolRef, ValueRef,
v1_0, v1_1, Catalog, Encoding, IonResult, IonType, LazyExpandedFieldName, LazyExpandedValue,
LazyRawWriter, MacroExpr, RawSymbolRef, ValueExpr, ValueRef,
};

pub trait HasSpan<'top>: HasRange {
Expand Down Expand Up @@ -205,6 +205,28 @@ impl<V: Debug, M: Debug> RawValueExpr<V, M> {
}
}

impl<V, M> RawValueExpr<V, M> {
pub fn resolve<'top, D>(
self,
context: EncodingContextRef<'top>,
) -> IonResult<ValueExpr<'top, D>>
where
V: LazyRawValue<'top, D>,
M: RawEExpression<'top, D>,
D: Decoder<Value<'top> = V, EExp<'top> = M>,
{
let expr = match self {
RawValueExpr::ValueLiteral(value) => {
ValueExpr::ValueLiteral(LazyExpandedValue::from_literal(context, value))
}
RawValueExpr::EExp(invocation) => {
ValueExpr::MacroInvocation(MacroExpr::from_eexp(invocation.resolve(context)?))
}
};
Ok(expr)
}
}

impl<V: HasRange, M: HasRange> HasRange for RawValueExpr<V, M> {
fn range(&self) -> Range<usize> {
match self {
Expand Down
20 changes: 4 additions & 16 deletions src/lazy/expanded/e_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::lazy::expanded::template::TemplateMacroRef;
use crate::lazy::expanded::{EncodingContextRef, LazyExpandedValue};
use crate::lazy::text::raw::v1_1::arg_group::{EExpArg, EExpArgExpr};
use crate::lazy::text::raw::v1_1::reader::MacroIdRef;
use crate::{try_next, Environment, HasRange, HasSpan, IonResult, Span};
use crate::{try_next, try_or_some_err, Environment, HasRange, HasSpan, IonResult, Span};

/// An `ArgGroup` is a collection of expressions found in e-expression argument position.
/// They can only appear in positions that correspond with variadic parameters.
Expand Down Expand Up @@ -323,20 +323,8 @@ impl<'top, D: Decoder> Iterator for EExpArgGroupIterator<'top, D> {
type Item = IonResult<ValueExpr<'top, D>>;

fn next(&mut self) -> Option<Self::Item> {
let expr = try_next!(self.expressions.next());
match expr {
RawValueExpr::ValueLiteral(v) => Some(Ok(ValueExpr::ValueLiteral(
LazyExpandedValue::from_literal(self.context, v),
))),
RawValueExpr::EExp(e) => {
let resolved_eexp = match e.resolve(self.context) {
Ok(eexp) => eexp,
Err(e) => return Some(Err(e)),
};
Some(Ok(ValueExpr::MacroInvocation(MacroExpr::from_eexp(
resolved_eexp,
))))
}
}
let raw_expr: RawValueExpr<_, _> = try_next!(self.expressions.next());
let expr = try_or_some_err!(raw_expr.resolve(self.context));
Some(Ok(expr))
}
}
33 changes: 4 additions & 29 deletions src/lazy/expanded/sequence.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::element::iterators::SymbolsIterator;
use crate::lazy::decoder::{Decoder, LazyRawSequence, LazyRawValueExpr, RawValueExpr};
use crate::lazy::decoder::{Decoder, LazyRawSequence, LazyRawValueExpr};
use crate::lazy::expanded::macro_evaluator::{
MacroEvaluator, MacroExprArgsIterator, RawEExpression, ValueExpr,
};
Expand Down Expand Up @@ -396,34 +396,9 @@ fn expand_next_sequence_value<'top, D: Decoder>(
evaluator: &mut MacroEvaluator<'top, D>,
iter: &mut impl Iterator<Item = IonResult<LazyRawValueExpr<'top, D>>>,
) -> Option<IonResult<LazyExpandedValue<'top, D>>> {
loop {
// If the evaluator's stack is not empty, it's still expanding a macro.
if !evaluator.is_empty() {
let value = evaluator.next().transpose();
if value.is_some() {
// The `Some` may contain a value or an error; either way, that's the next return value.
return value;
}
// It's possible for a macro to produce zero values. If that happens, we continue on to
// pull another expression from the list iterator.
}

match iter.next() {
None => return None,
Some(Ok(RawValueExpr::ValueLiteral(value))) => {
return Some(Ok(LazyExpandedValue::from_literal(context, value)))
}
Some(Ok(RawValueExpr::EExp(invocation))) => {
let resolved_invocation = match invocation.resolve(context) {
Ok(resolved) => resolved,
Err(e) => return Some(Err(e)),
};
evaluator.push(try_or_some_err!(resolved_invocation.expand()));
continue;
}
Some(Err(e)) => return Some(Err(e)),
}
}
let mut resolving_iter =
iter.map(|result| result.and_then(|raw_expr| raw_expr.resolve(context)));
expand_next_sequence_value_from_resolved(evaluator, &mut resolving_iter)
}

fn expand_next_sequence_value_from_resolved<'top, D: Decoder>(
Expand Down
2 changes: 1 addition & 1 deletion src/lazy/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl<'top, D: Decoder> TryFrom<LazyList<'top, D>> for Sequence {
fn try_from(lazy_sequence: LazyList<'top, D>) -> Result<Self, Self::Error> {
let sequence: Sequence = lazy_sequence
.iter()
.map(|v| Element::try_from(v?))
.map(|result| result.and_then(Element::try_from))
.collect::<IonResult<Vec<_>>>()?
.into();
Ok(sequence)
Expand Down

0 comments on commit 36c3dca

Please sign in to comment.