#![allow(non_camel_case_types)]
use std::fmt::{Debug, Formatter};
use std::ops::Range;
use crate::element::iterators::SymbolsIterator;
use crate::lazy::decoder::{Decoder, RawValueExpr};
use crate::lazy::expanded::compiler::{ExpansionAnalysis, ExpansionSingleton};
use crate::lazy::expanded::macro_evaluator::{
AnnotateExpansion, ConditionalExpansion, DeltaExpansion, EExpressionArgGroup,
ExprGroupExpansion, FlattenExpansion, IsExhaustedIterator, MacroExpansion, MacroExpansionKind,
MacroExpr, MacroExprArgsIterator, MakeDecimalExpansion, MakeFieldExpansion,
MakeStructExpansion, MakeTextExpansion, MakeTimestampExpansion, RawEExpression,
RepeatExpansion, SumExpansion, TemplateExpansion, ValueExpr,
};
use crate::lazy::expanded::macro_table::{MacroKind, MacroRef};
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, try_or_some_err, Environment, HasRange, HasSpan, IonResult, Span};
#[derive(Copy, Clone)]
pub struct EExpArgGroup<'top, D: Decoder> {
context: EncodingContextRef<'top>,
raw_arg_group: <D::EExp<'top> as RawEExpression<'top, D>>::ArgGroup,
}
impl<'top, D: Decoder> EExpArgGroup<'top, D> {
pub fn new(
raw_arg_group: <D::EExp<'top> as RawEExpression<'top, D>>::ArgGroup,
context: EncodingContextRef<'top>,
) -> Self {
Self {
context,
raw_arg_group,
}
}
pub fn context(&self) -> EncodingContextRef<'top> {
self.context
}
pub fn raw_arg_group(&self) -> <D::EExp<'top> as RawEExpression<'top, D>>::ArgGroup {
self.raw_arg_group
}
pub fn expressions(&self) -> EExpArgGroupIterator<'top, D> {
EExpArgGroupIterator::new(self.context, self.raw_arg_group())
}
pub fn expand(&self) -> IonResult<MacroExpansion<'top, D>> {
let context = self.context();
let arguments = MacroExprArgsIterator::from_eexp_arg_group(self.expressions());
let expansion_kind = MacroExpansionKind::ExprGroup(ExprGroupExpansion::new(arguments));
Ok(MacroExpansion::new(
context,
Environment::empty(),
expansion_kind,
))
}
}
impl<D: Decoder> HasRange for EExpArgGroup<'_, D> {
fn range(&self) -> Range<usize> {
self.raw_arg_group.range()
}
}
impl<'top, D: Decoder> HasSpan<'top> for EExpArgGroup<'top, D> {
fn span(&self) -> Span<'top> {
self.raw_arg_group.span()
}
}
impl<D: Decoder> Debug for EExpArgGroup<'_, D> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(: {:?}", self.raw_arg_group)?;
for expr in self.expressions() {
write!(f, " {expr:?}")?;
}
write!(f, ")")
}
}
#[derive(Copy, Clone)]
pub struct EExpression<'top, D: Decoder> {
pub(crate) raw_invocation: D::EExp<'top>,
pub(crate) invoked_macro: MacroRef<'top>,
}
impl<'top, D: Decoder> EExpression<'top, D> {
pub fn context(&self) -> EncodingContextRef<'top> {
self.raw_invocation().context()
}
pub fn raw_invocation(&self) -> D::EExp<'top> {
self.raw_invocation
}
pub fn invoked_macro(&self) -> MacroRef<'top> {
self.invoked_macro
}
pub(crate) fn new_evaluation_environment(&self) -> IonResult<Environment<'top, D>> {
self.raw_invocation
.make_evaluation_environment(self.context())
}
pub(crate) fn expand(&self) -> IonResult<MacroExpansion<'top, D>> {
let invoked_macro = self.invoked_macro;
let arguments = MacroExprArgsIterator::from_eexp(self.arguments());
let mut environment = Environment::empty();
let expansion_kind = match invoked_macro.kind() {
MacroKind::None => MacroExpansionKind::None,
MacroKind::ExprGroup => {
MacroExpansionKind::ExprGroup(ExprGroupExpansion::new(arguments))
}
MacroKind::MakeDecimal => {
MacroExpansionKind::MakeDecimal(MakeDecimalExpansion::new(arguments))
}
MacroKind::MakeString => {
MacroExpansionKind::MakeString(MakeTextExpansion::string_maker(arguments))
}
MacroKind::MakeSymbol => {
MacroExpansionKind::MakeSymbol(MakeTextExpansion::symbol_maker(arguments))
}
MacroKind::MakeStruct => {
MacroExpansionKind::MakeStruct(MakeStructExpansion::new(arguments))
}
MacroKind::MakeTimestamp => {
MacroExpansionKind::MakeTimestamp(MakeTimestampExpansion::new(arguments))
}
MacroKind::MakeField => {
MacroExpansionKind::MakeField(MakeFieldExpansion::new(arguments))
}
MacroKind::Annotate => MacroExpansionKind::Annotate(AnnotateExpansion::new(arguments)),
MacroKind::Flatten => MacroExpansionKind::Flatten(FlattenExpansion::new(
self.context(),
environment,
arguments,
)),
MacroKind::Template(template_body) => {
let template_ref = TemplateMacroRef::new(invoked_macro.definition(), template_body);
environment = self.new_evaluation_environment()?;
MacroExpansionKind::Template(TemplateExpansion::new(template_ref))
}
MacroKind::ToDo => todo!("system macro {}", invoked_macro.name().unwrap()),
MacroKind::IfNone => {
MacroExpansionKind::Conditional(ConditionalExpansion::if_none(arguments))
}
MacroKind::IfSome => {
MacroExpansionKind::Conditional(ConditionalExpansion::if_some(arguments))
}
MacroKind::IfSingle => {
MacroExpansionKind::Conditional(ConditionalExpansion::if_single(arguments))
}
MacroKind::IfMulti => {
MacroExpansionKind::Conditional(ConditionalExpansion::if_multi(arguments))
}
MacroKind::Delta => MacroExpansionKind::Delta(DeltaExpansion::new(
self.context(),
environment,
arguments,
)),
MacroKind::Repeat => MacroExpansionKind::Repeat(RepeatExpansion::new(arguments)),
MacroKind::Sum => MacroExpansionKind::Sum(SumExpansion::new(arguments)),
};
Ok(MacroExpansion::new(
self.context(),
environment,
expansion_kind,
))
}
pub(crate) fn expand_to_single_value(&self) -> IonResult<LazyExpandedValue<'top, D>> {
MacroExpr::from_eexp(*self).expand()?.expand_singleton()
}
pub fn expansion_analysis(&self) -> ExpansionAnalysis {
self.invoked_macro.expansion_analysis()
}
pub fn is_singleton(&self) -> bool {
self.expansion_singleton().is_some()
}
pub fn expansion_singleton(&self) -> Option<ExpansionSingleton> {
self.expansion_analysis().expansion_singleton()
}
pub fn require_expansion_singleton(&self) -> ExpansionSingleton {
self.expansion_singleton().unwrap()
}
pub fn require_singleton_annotations(&self) -> SymbolsIterator<'top> {
let storage = self
.invoked_macro
.require_template()
.body()
.annotations_storage();
self.expansion_singleton().unwrap().annotations(storage)
}
}
impl<D: Decoder> Debug for EExpression<'_, D> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"(:{}",
self.invoked_macro().name().unwrap_or("<anonymous>")
)?;
for arg in self.arguments() {
write!(f, " {:?}", arg?)?;
}
write!(f, ")")
}
}
impl<D: Decoder> HasRange for EExpression<'_, D> {
fn range(&self) -> Range<usize> {
self.raw_invocation.range()
}
}
impl<'top, D: Decoder> HasSpan<'top> for EExpression<'top, D> {
fn span(&self) -> Span<'top> {
self.raw_invocation.span()
}
}
impl<'top, D: Decoder> EExpression<'top, D> {
pub fn new(raw_invocation: D::EExp<'top>, invoked_macro: MacroRef<'top>) -> Self {
Self {
raw_invocation,
invoked_macro,
}
}
}
impl<'top, D: Decoder> EExpression<'top, D> {
pub fn id(&self) -> MacroIdRef<'top> {
self.raw_invocation.id()
}
pub fn arguments(&self) -> EExpressionArgsIterator<'top, D> {
EExpressionArgsIterator {
context: self.context(),
raw_args: self.raw_invocation.raw_arguments(),
num_args: self.invoked_macro.signature().len() as u32,
index: 0,
}
}
}
impl<'top, D: Decoder> From<EExpression<'top, D>> for MacroExpr<'top, D> {
fn from(value: EExpression<'top, D>) -> Self {
MacroExpr::from_eexp(value)
}
}
#[derive(Copy, Clone, Debug)]
pub struct EExpressionArgsIterator<'top, D: Decoder> {
context: EncodingContextRef<'top>,
raw_args: <D::EExp<'top> as RawEExpression<'top, D>>::RawArgumentsIterator,
num_args: u32,
index: u32,
}
impl<D: Decoder> EExpressionArgsIterator<'_, D> {
pub fn is_exhausted(&self) -> bool {
self.index == self.num_args
}
}
impl<'top, D: Decoder> Iterator for EExpressionArgsIterator<'top, D> {
type Item = IonResult<ValueExpr<'top, D>>;
fn next(&mut self) -> Option<Self::Item> {
let raw_arg: EExpArg<'top, D> = match self.raw_args.next()? {
Ok(arg) => {
debug_assert!(self.index < self.num_args);
arg
}
Err(e) => {
debug_assert!(self.index == self.num_args);
return Some(Err(e));
}
};
self.index += 1;
let expr = match raw_arg.expr() {
EExpArgExpr::<D>::ValueLiteral(value) => {
ValueExpr::ValueLiteral(LazyExpandedValue::from_literal(self.context, *value))
}
EExpArgExpr::<D>::EExp(raw_invocation) => {
let invocation = match raw_invocation.resolve(self.context) {
Ok(invocation) => invocation,
Err(e) => return Some(Err(e)),
};
ValueExpr::MacroInvocation(invocation.into())
}
EExpArgExpr::<D>::ArgGroup(group) => {
let arg_group = group.resolve(self.context);
ValueExpr::MacroInvocation(MacroExpr::from_eexp_arg_group(arg_group))
}
};
Some(Ok(expr))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.raw_args.size_hint()
}
}
#[derive(Copy, Clone, Debug)]
pub struct EExpArgGroupIterator<'top, D: Decoder> {
context: EncodingContextRef<'top>,
expressions: <<<D as Decoder>::EExp<'top> as RawEExpression<'top, D>>::ArgGroup as EExpressionArgGroup<'top, D>>::Iterator,
}
impl<'top, D: Decoder> EExpArgGroupIterator<'top, D> {
pub fn new(
context: EncodingContextRef<'top>,
arg_group: <<D as Decoder>::EExp<'top> as RawEExpression<'top, D>>::ArgGroup,
) -> Self {
Self {
context,
expressions: arg_group.iter(),
}
}
pub fn is_exhausted(&self) -> bool {
self.expressions.is_exhausted()
}
}
impl<'top, D: Decoder> Iterator for EExpArgGroupIterator<'top, D> {
type Item = IonResult<ValueExpr<'top, D>>;
fn next(&mut self) -> Option<Self::Item> {
let raw_expr: RawValueExpr<_, _> = try_next!(self.expressions.next());
let expr = try_or_some_err!(raw_expr.resolve(self.context));
Some(Ok(expr))
}
}