diff --git a/src/lazy/decoder.rs b/src/lazy/decoder.rs index be54a54a..7da3a159 100644 --- a/src/lazy/decoder.rs +++ b/src/lazy/decoder.rs @@ -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 { @@ -205,6 +205,28 @@ impl RawValueExpr { } } +impl RawValueExpr { + pub fn resolve<'top, D>( + self, + context: EncodingContextRef<'top>, + ) -> IonResult> + where + V: LazyRawValue<'top, D>, + M: RawEExpression<'top, D>, + D: Decoder = 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 HasRange for RawValueExpr { fn range(&self) -> Range { match self { diff --git a/src/lazy/expanded/e_expression.rs b/src/lazy/expanded/e_expression.rs index 6b198ab0..22f144f1 100644 --- a/src/lazy/expanded/e_expression.rs +++ b/src/lazy/expanded/e_expression.rs @@ -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. @@ -323,20 +323,8 @@ impl<'top, D: Decoder> Iterator for EExpArgGroupIterator<'top, D> { type Item = IonResult>; fn next(&mut self) -> Option { - 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)) } } diff --git a/src/lazy/expanded/sequence.rs b/src/lazy/expanded/sequence.rs index a9bc9774..f633235b 100644 --- a/src/lazy/expanded/sequence.rs +++ b/src/lazy/expanded/sequence.rs @@ -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, }; @@ -396,34 +396,9 @@ fn expand_next_sequence_value<'top, D: Decoder>( evaluator: &mut MacroEvaluator<'top, D>, iter: &mut impl Iterator>>, ) -> Option>> { - 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>( diff --git a/src/lazy/sequence.rs b/src/lazy/sequence.rs index 49dac948..bb158d4e 100644 --- a/src/lazy/sequence.rs +++ b/src/lazy/sequence.rs @@ -140,7 +140,7 @@ impl<'top, D: Decoder> TryFrom> for Sequence { fn try_from(lazy_sequence: LazyList<'top, D>) -> Result { let sequence: Sequence = lazy_sequence .iter() - .map(|v| Element::try_from(v?)) + .map(|result| result.and_then(Element::try_from)) .collect::>>()? .into(); Ok(sequence)