Implement conditional operators
This commit is contained in:
		
							parent
							
								
									9159c8222e
								
							
						
					
					
						commit
						4b52985992
					
				| 
						 | 
				
			
			@ -196,7 +196,7 @@ pub struct StringLiteral {
 | 
			
		|||
impl StringLiteral {
 | 
			
		||||
    /// Returns the string without the leading and trailing double quotes.
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn string_content(&self) -> &str {
 | 
			
		||||
    pub fn str_content(&self) -> &str {
 | 
			
		||||
        let string = self.span.str();
 | 
			
		||||
        &string[1..string.len() - 1]
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -247,6 +247,30 @@ impl<'a> Frame<'a> {
 | 
			
		|||
        self.get_reading(self.token_provider.token_stream().get(self.current_index))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the next significant [`Token`] after the `current_index` of the [`Frame`].
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn peek_significant(&self) -> Reading {
 | 
			
		||||
        let mut index = self.current_index;
 | 
			
		||||
        let token_stream = self.token_provider.token_stream();
 | 
			
		||||
        while index < self.token_provider.token_stream().len() {
 | 
			
		||||
            let token = self.get_reading(token_stream.get(index));
 | 
			
		||||
 | 
			
		||||
            if !matches!(
 | 
			
		||||
                token,
 | 
			
		||||
                Reading::Atomic(Token::WhiteSpaces(..) | Token::Comment(..))
 | 
			
		||||
            ) {
 | 
			
		||||
                return token;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            index += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        match self.token_provider {
 | 
			
		||||
            TokenProvider::TokenStream(..) => Reading::Eof,
 | 
			
		||||
            TokenProvider::Delimited(delimited) => Reading::DelimitedEnd(delimited.close.clone()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a [`Token`] pointing by the `current_index` with the given index offset of the
 | 
			
		||||
    /// [`Frame`].
 | 
			
		||||
    ///
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,22 +1,127 @@
 | 
			
		|||
//! Syntax tree nodes for expressions.
 | 
			
		||||
 | 
			
		||||
use std::{cmp::Ordering, collections::VecDeque};
 | 
			
		||||
 | 
			
		||||
use enum_as_inner::EnumAsInner;
 | 
			
		||||
use getset::Getters;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    base::{
 | 
			
		||||
        source_file::{SourceElement, Span},
 | 
			
		||||
        Handler,
 | 
			
		||||
        Dummy, Handler,
 | 
			
		||||
    },
 | 
			
		||||
    lexical::{
 | 
			
		||||
        token::{Punctuation, StringLiteral, Token},
 | 
			
		||||
        token_stream::Delimiter,
 | 
			
		||||
    },
 | 
			
		||||
    syntax::{
 | 
			
		||||
        error::{Error, UnexpectedSyntax},
 | 
			
		||||
        error::{Error, SyntaxKind, UnexpectedSyntax},
 | 
			
		||||
        parser::{Parser, Reading},
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
/// Expression:
 | 
			
		||||
///     Prefix
 | 
			
		||||
///     | Parenthesized
 | 
			
		||||
///     | StringLiteral
 | 
			
		||||
/// ```
 | 
			
		||||
#[allow(missing_docs)]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner)]
 | 
			
		||||
pub enum PrimaryCondition {
 | 
			
		||||
    Prefix(ConditionalPrefix),
 | 
			
		||||
    Parenthesized(ParenthesizedCondition),
 | 
			
		||||
    StringLiteral(StringLiteral),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for PrimaryCondition {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Prefix(prefix) => prefix.span(),
 | 
			
		||||
            Self::Parenthesized(parenthesized) => parenthesized.span(),
 | 
			
		||||
            Self::StringLiteral(literal) => literal.span(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
/// BinaryCondition:
 | 
			
		||||
///     Condition ConditionalBinaryOperator Condition
 | 
			
		||||
///     ;
 | 
			
		||||
/// ```
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
 | 
			
		||||
pub struct BinaryCondition {
 | 
			
		||||
    /// The left operand of the binary condition.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    left_operand: Box<Condition>,
 | 
			
		||||
    /// The operator of the binary condition.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    operator: ConditionalBinaryOperator,
 | 
			
		||||
    /// The right operand of the binary condition.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    right_operand: Box<Condition>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for BinaryCondition {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        self.left_operand
 | 
			
		||||
            .span()
 | 
			
		||||
            .join(&self.right_operand.span())
 | 
			
		||||
            .unwrap()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BinaryCondition {
 | 
			
		||||
    /// Dissolves the binary condition into its components
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn dissolve(self) -> (Condition, ConditionalBinaryOperator, Condition) {
 | 
			
		||||
        (*self.left_operand, self.operator, *self.right_operand)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
/// BinaryOperator:
 | 
			
		||||
///     '&&'
 | 
			
		||||
///     | '||'
 | 
			
		||||
///     ;
 | 
			
		||||
/// ```
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner)]
 | 
			
		||||
#[allow(missing_docs)]
 | 
			
		||||
pub enum ConditionalBinaryOperator {
 | 
			
		||||
    LogicalAnd(Punctuation, Punctuation),
 | 
			
		||||
    LogicalOr(Punctuation, Punctuation),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ConditionalBinaryOperator {
 | 
			
		||||
    /// Gets the precedence of the operator (the higher the number, the first it will be evaluated)
 | 
			
		||||
    ///
 | 
			
		||||
    /// The least operator has precedence 1.
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn get_precedence(&self) -> u8 {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::LogicalOr(..) => 1,
 | 
			
		||||
            Self::LogicalAnd(..) => 2,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for ConditionalBinaryOperator {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::LogicalAnd(a, b) | Self::LogicalOr(a, b) => a
 | 
			
		||||
                .span
 | 
			
		||||
                .join(&b.span)
 | 
			
		||||
                .expect("Invalid tokens for ConditionalBinaryOperator"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
| 
						 | 
				
			
			@ -56,32 +161,178 @@ impl SourceElement for ParenthesizedCondition {
 | 
			
		|||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
/// Condition: StringLiteral;
 | 
			
		||||
/// PrefixOperator: '!';
 | 
			
		||||
/// ```
 | 
			
		||||
#[allow(missing_docs)]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner)]
 | 
			
		||||
pub enum ConditionalPrefixOperator {
 | 
			
		||||
    LogicalNot(Punctuation),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for ConditionalPrefixOperator {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::LogicalNot(token) => token.span.clone(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ```ebnf
 | 
			
		||||
/// Prefix:
 | 
			
		||||
///     ConditionalPrefixOperator StringLiteral
 | 
			
		||||
///     ;
 | 
			
		||||
/// ```
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
 | 
			
		||||
pub struct Condition {
 | 
			
		||||
    /// The value of the condition.
 | 
			
		||||
pub struct ConditionalPrefix {
 | 
			
		||||
    /// The operator of the prefix.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    pub value: StringLiteral,
 | 
			
		||||
    operator: ConditionalPrefixOperator,
 | 
			
		||||
    /// The operand of the prefix.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    operand: Box<PrimaryCondition>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for ConditionalPrefix {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        self.operator.span().join(&self.operand.span()).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ConditionalPrefix {
 | 
			
		||||
    /// Dissolves the conditional prefix into its components
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn dissolve(self) -> (ConditionalPrefixOperator, PrimaryCondition) {
 | 
			
		||||
        (self.operator, *self.operand)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Syntax Synopsis:
 | 
			
		||||
///
 | 
			
		||||
/// ``` ebnf
 | 
			
		||||
/// Condition: PrimaryCondition;
 | 
			
		||||
/// ```
 | 
			
		||||
#[allow(missing_docs)]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner)]
 | 
			
		||||
pub enum Condition {
 | 
			
		||||
    Primary(PrimaryCondition),
 | 
			
		||||
    Binary(BinaryCondition),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceElement for Condition {
 | 
			
		||||
    fn span(&self) -> Span {
 | 
			
		||||
        self.value.span()
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Primary(primary) => primary.span(),
 | 
			
		||||
            Self::Binary(binary) => binary.span(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Parser<'a> {
 | 
			
		||||
    /// Parses a [`Condition`].
 | 
			
		||||
    pub fn parse_condition(&mut self, handler: &impl Handler<Error>) -> Option<Condition> {
 | 
			
		||||
        match self.next_significant_token() {
 | 
			
		||||
            Reading::Atomic(Token::StringLiteral(s)) => Some(Condition { value: s }),
 | 
			
		||||
        let mut lhs = Condition::Primary(self.parse_primary_condition(handler)?);
 | 
			
		||||
        let mut expressions = VecDeque::new();
 | 
			
		||||
 | 
			
		||||
        // Parses a list of binary operators and expressions
 | 
			
		||||
        while let Some(binary_operator) = self.try_parse_conditional_binary_operator() {
 | 
			
		||||
            expressions.push_back((
 | 
			
		||||
                binary_operator,
 | 
			
		||||
                Some(Condition::Primary(self.parse_primary_condition(handler)?)),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut candidate_index = 0;
 | 
			
		||||
        let mut current_precedence;
 | 
			
		||||
 | 
			
		||||
        while !expressions.is_empty() {
 | 
			
		||||
            // reset precedence
 | 
			
		||||
            current_precedence = 0;
 | 
			
		||||
 | 
			
		||||
            for (index, (binary_op, _)) in expressions.iter().enumerate() {
 | 
			
		||||
                let new_precedence = binary_op.get_precedence();
 | 
			
		||||
                match new_precedence.cmp(¤t_precedence) {
 | 
			
		||||
                    // Clear the candidate indices and set the current precedence to the
 | 
			
		||||
                    // precedence of the current binary operator.
 | 
			
		||||
                    Ordering::Greater => {
 | 
			
		||||
                        current_precedence = new_precedence;
 | 
			
		||||
                        candidate_index = index;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    Ordering::Less | Ordering::Equal => (),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // ASSUMPTION: The assignments have 1 precedence and are right associative.
 | 
			
		||||
            assert!(current_precedence > 0);
 | 
			
		||||
 | 
			
		||||
            if candidate_index == 0 {
 | 
			
		||||
                let (binary_op, rhs) = expressions.pop_front().expect("No binary operator found");
 | 
			
		||||
 | 
			
		||||
                // fold the first expression
 | 
			
		||||
                lhs = Condition::Binary(BinaryCondition {
 | 
			
		||||
                    left_operand: Box::new(lhs),
 | 
			
		||||
                    operator: binary_op,
 | 
			
		||||
                    right_operand: Box::new(rhs.unwrap()),
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
                let (binary_op, rhs) = expressions
 | 
			
		||||
                    .remove(candidate_index)
 | 
			
		||||
                    .expect("No binary operator found");
 | 
			
		||||
 | 
			
		||||
                // fold the expression at candidate_index
 | 
			
		||||
                expressions[candidate_index - 1].1 = Some(Condition::Binary(BinaryCondition {
 | 
			
		||||
                    left_operand: Box::new(expressions[candidate_index - 1].1.take().unwrap()),
 | 
			
		||||
                    operator: binary_op,
 | 
			
		||||
                    right_operand: Box::new(rhs.unwrap()),
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Some(lhs)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Parses a [`PrimaryCondition`].
 | 
			
		||||
    pub fn parse_primary_condition(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        handler: &impl Handler<Error>,
 | 
			
		||||
    ) -> Option<PrimaryCondition> {
 | 
			
		||||
        match self.stop_at_significant() {
 | 
			
		||||
            // prefixed expression
 | 
			
		||||
            Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '!' => {
 | 
			
		||||
                // eat prefix operator
 | 
			
		||||
                self.forward();
 | 
			
		||||
 | 
			
		||||
                let operator = match punc.punctuation {
 | 
			
		||||
                    '!' => ConditionalPrefixOperator::LogicalNot(punc),
 | 
			
		||||
                    _ => unreachable!(),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                let operand = Box::new(self.parse_primary_condition(handler)?);
 | 
			
		||||
 | 
			
		||||
                Some(PrimaryCondition::Prefix(ConditionalPrefix {
 | 
			
		||||
                    operator,
 | 
			
		||||
                    operand,
 | 
			
		||||
                }))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // string literal
 | 
			
		||||
            Reading::Atomic(Token::StringLiteral(literal)) => {
 | 
			
		||||
                self.forward();
 | 
			
		||||
                Some(PrimaryCondition::StringLiteral(literal))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // parenthesized condition
 | 
			
		||||
            Reading::IntoDelimited(punc) if punc.punctuation == '(' => self
 | 
			
		||||
                .parse_parenthesized_condition(handler)
 | 
			
		||||
                .map(PrimaryCondition::Parenthesized),
 | 
			
		||||
 | 
			
		||||
            unexpected => {
 | 
			
		||||
                // make progress
 | 
			
		||||
                self.forward();
 | 
			
		||||
 | 
			
		||||
                handler.receive(Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
			
		||||
                    expected: crate::syntax::error::SyntaxKind::Expression,
 | 
			
		||||
                    expected: SyntaxKind::Expression,
 | 
			
		||||
                    found: unexpected.into_token(),
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,4 +358,21 @@ impl<'a> Parser<'a> {
 | 
			
		|||
            close_paren: token_tree.close,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn try_parse_conditional_binary_operator(&mut self) -> Option<ConditionalBinaryOperator> {
 | 
			
		||||
        self.try_parse(|parser| match parser.next_significant_token() {
 | 
			
		||||
            Reading::Atomic(Token::Punctuation(punc)) => match punc.punctuation {
 | 
			
		||||
                '&' => {
 | 
			
		||||
                    let b = parser.parse_punctuation('&', false, &Dummy)?;
 | 
			
		||||
                    Some(ConditionalBinaryOperator::LogicalAnd(punc, b))
 | 
			
		||||
                }
 | 
			
		||||
                '|' => {
 | 
			
		||||
                    let b = parser.parse_punctuation('|', false, &Dummy)?;
 | 
			
		||||
                    Some(ConditionalBinaryOperator::LogicalOr(punc, b))
 | 
			
		||||
                }
 | 
			
		||||
                _ => None,
 | 
			
		||||
            },
 | 
			
		||||
            _ => None,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
//! Conversion functions for converting between tokens/ast-nodes and [`shulkerbox`] types
 | 
			
		||||
 | 
			
		||||
use shulkerbox::datapack::Condition as DpCondition;
 | 
			
		||||
 | 
			
		||||
use crate::syntax::syntax_tree::expression::{
 | 
			
		||||
    BinaryCondition, Condition, ConditionalBinaryOperator, ConditionalPrefixOperator,
 | 
			
		||||
    PrimaryCondition,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
impl From<Condition> for DpCondition {
 | 
			
		||||
    fn from(value: Condition) -> Self {
 | 
			
		||||
        match value {
 | 
			
		||||
            Condition::Primary(primary) => primary.into(),
 | 
			
		||||
            Condition::Binary(binary) => binary.into(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<PrimaryCondition> for DpCondition {
 | 
			
		||||
    fn from(value: PrimaryCondition) -> Self {
 | 
			
		||||
        match value {
 | 
			
		||||
            PrimaryCondition::StringLiteral(literal) => {
 | 
			
		||||
                Self::Atom(literal.str_content().to_string())
 | 
			
		||||
            }
 | 
			
		||||
            PrimaryCondition::Parenthesized(cond) => cond.dissolve().1.into(),
 | 
			
		||||
            PrimaryCondition::Prefix(prefix) => match prefix.operator() {
 | 
			
		||||
                ConditionalPrefixOperator::LogicalNot(_) => {
 | 
			
		||||
                    Self::Not(Box::new(prefix.dissolve().1.into()))
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<BinaryCondition> for DpCondition {
 | 
			
		||||
    fn from(value: BinaryCondition) -> Self {
 | 
			
		||||
        let (lhs, op, rhs) = value.dissolve();
 | 
			
		||||
        match op {
 | 
			
		||||
            ConditionalBinaryOperator::LogicalAnd(_, _) => {
 | 
			
		||||
                Self::And(Box::new(lhs.into()), Box::new(rhs.into()))
 | 
			
		||||
            }
 | 
			
		||||
            ConditionalBinaryOperator::LogicalOr(_, _) => {
 | 
			
		||||
                Self::Or(Box::new(lhs.into()), Box::new(rhs.into()))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,6 @@
 | 
			
		|||
//! The transpile module is responsible for transpiling the abstract syntax tree into a data pack.
 | 
			
		||||
 | 
			
		||||
#[doc(hidden)]
 | 
			
		||||
pub mod conversions;
 | 
			
		||||
pub mod error;
 | 
			
		||||
pub mod transpiler;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use shulkerbox::datapack::{Command, Datapack, Execute};
 | 
			
		||||
use shulkerbox::datapack::{self, Command, Datapack, Execute};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    base::{source_file::SourceElement, Handler},
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ pub struct Transpiler {
 | 
			
		|||
type AnnotationMap = HashMap<String, Option<String>>;
 | 
			
		||||
 | 
			
		||||
impl Transpiler {
 | 
			
		||||
    /// Creates a new compiler.
 | 
			
		||||
    /// Creates a new transpiler.
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn new() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ impl Transpiler {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Compiles the given program.
 | 
			
		||||
    /// Transpiles the given program.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Errors
 | 
			
		||||
    /// - [`TranspileError::MissingMainFunction`] If the main function is missing.
 | 
			
		||||
| 
						 | 
				
			
			@ -49,9 +49,7 @@ impl Transpiler {
 | 
			
		|||
                            let value = annotation.value();
 | 
			
		||||
                            (
 | 
			
		||||
                                key.span().str().to_string(),
 | 
			
		||||
                                value
 | 
			
		||||
                                    .as_ref()
 | 
			
		||||
                                    .map(|(_, ref v)| v.string_content().to_string()),
 | 
			
		||||
                                value.as_ref().map(|(_, ref v)| v.str_content().to_string()),
 | 
			
		||||
                            )
 | 
			
		||||
                        })
 | 
			
		||||
                        .collect();
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +120,7 @@ fn compile_statement(statement: &Statement) -> Option<Command> {
 | 
			
		|||
                    None
 | 
			
		||||
                } else {
 | 
			
		||||
                    Some(Command::Execute(Execute::If(
 | 
			
		||||
                        cond.value().string_content().into(),
 | 
			
		||||
                        datapack::Condition::from(cond),
 | 
			
		||||
                        Box::new(Execute::Runs(Vec::new())),
 | 
			
		||||
                        el,
 | 
			
		||||
                    )))
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +134,7 @@ fn compile_statement(statement: &Statement) -> Option<Command> {
 | 
			
		|||
                };
 | 
			
		||||
 | 
			
		||||
                Some(Command::Execute(Execute::If(
 | 
			
		||||
                    cond.value().string_content().into(),
 | 
			
		||||
                    datapack::Condition::from(cond),
 | 
			
		||||
                    Box::new(run),
 | 
			
		||||
                    el,
 | 
			
		||||
                )))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue