use super::expression::Expression;
use super::{Binding, FunctionCall, LetBinding};
use crate::ast;
use crate::types::semantic::ExtendedExpression;
#[cfg(feature = "codec")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum Condition {
Great,
Less,
Eq,
GreatEq,
LessEq,
NotEq,
}
impl From<ast::Condition> for Condition {
fn from(value: ast::Condition) -> Self {
match value {
ast::Condition::Great => Self::Great,
ast::Condition::Less => Self::Less,
ast::Condition::Eq => Self::Eq,
ast::Condition::GreatEq => Self::GreatEq,
ast::Condition::LessEq => Self::LessEq,
ast::Condition::NotEq => Self::NotEq,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum LogicCondition {
And,
Or,
}
impl From<ast::LogicCondition> for LogicCondition {
fn from(value: ast::LogicCondition) -> Self {
match value {
ast::LogicCondition::And => Self::And,
ast::LogicCondition::Or => Self::Or,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
pub struct ExpressionCondition {
pub left: Expression,
pub condition: Condition,
pub right: Expression,
}
impl<E: ExtendedExpression> From<ast::ExpressionCondition<'_, E>> for ExpressionCondition {
fn from(value: ast::ExpressionCondition<'_, E>) -> Self {
Self {
left: value.left.into(),
condition: value.condition.into(),
right: value.right.into(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
pub struct ExpressionLogicCondition {
pub left: ExpressionCondition,
pub right: Option<(LogicCondition, Box<ExpressionLogicCondition>)>,
}
impl<E: ExtendedExpression> From<ast::ExpressionLogicCondition<'_, E>>
for ExpressionLogicCondition
{
fn from(value: ast::ExpressionLogicCondition<'_, E>) -> Self {
Self {
left: value.left.into(),
right: value
.right
.map(|(v, expr)| (v.into(), Box::new(expr.as_ref().clone().into()))),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum IfCondition {
Single(Expression),
Logic(ExpressionLogicCondition),
}
impl<E: ExtendedExpression> From<ast::IfCondition<'_, E>> for IfCondition {
fn from(value: ast::IfCondition<'_, E>) -> Self {
match value {
ast::IfCondition::Single(v) => Self::Single(v.into()),
ast::IfCondition::Logic(v) => Self::Logic(v.into()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
pub struct IfStatement {
pub condition: IfCondition,
pub body: IfBodyStatements,
pub else_statement: Option<IfBodyStatements>,
pub else_if_statement: Option<Box<IfStatement>>,
}
impl<E: ExtendedExpression> From<ast::IfStatement<'_, E>> for IfStatement {
fn from(value: ast::IfStatement<'_, E>) -> Self {
Self {
condition: value.condition.into(),
body: value.body.into(),
else_statement: value.else_statement.map(Into::into),
else_if_statement: value
.else_if_statement
.map(|v| Box::new(v.as_ref().clone().into())),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum IfBodyStatements {
If(Vec<IfBodyStatement>),
Loop(Vec<IfLoopBodyStatement>),
}
impl<E: ExtendedExpression> From<ast::IfBodyStatements<'_, E>> for IfBodyStatements {
fn from(value: ast::IfBodyStatements<'_, E>) -> Self {
match value {
ast::IfBodyStatements::If(v) => Self::If(v.iter().map(|v| v.clone().into()).collect()),
ast::IfBodyStatements::Loop(v) => {
Self::Loop(v.iter().map(|v| v.clone().into()).collect())
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum LoopBodyStatement {
LetBinding(LetBinding),
Binding(Binding),
FunctionCall(FunctionCall),
If(IfStatement),
Loop(Vec<LoopBodyStatement>),
Return(Expression),
Break,
Continue,
}
impl<E: ExtendedExpression> From<ast::LoopBodyStatement<'_, E>> for LoopBodyStatement {
fn from(value: ast::LoopBodyStatement<'_, E>) -> Self {
match value {
ast::LoopBodyStatement::LetBinding(v) => Self::LetBinding(v.into()),
ast::LoopBodyStatement::Binding(v) => Self::Binding(v.into()),
ast::LoopBodyStatement::FunctionCall(v) => Self::FunctionCall(v.into()),
ast::LoopBodyStatement::If(v) => Self::If(v.into()),
ast::LoopBodyStatement::Loop(v) => {
Self::Loop(v.iter().map(|v| v.clone().into()).collect())
}
ast::LoopBodyStatement::Return(v) => Self::Return(v.into()),
ast::LoopBodyStatement::Break => Self::Break,
ast::LoopBodyStatement::Continue => Self::Continue,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum IfBodyStatement {
LetBinding(LetBinding),
Binding(Binding),
FunctionCall(FunctionCall),
If(IfStatement),
Loop(Vec<LoopBodyStatement>),
Return(Expression),
}
impl<E: ExtendedExpression> From<ast::IfBodyStatement<'_, E>> for IfBodyStatement {
fn from(value: ast::IfBodyStatement<'_, E>) -> Self {
match value {
ast::IfBodyStatement::LetBinding(v) => Self::LetBinding(v.into()),
ast::IfBodyStatement::Binding(v) => Self::Binding(v.into()),
ast::IfBodyStatement::FunctionCall(v) => Self::FunctionCall(v.into()),
ast::IfBodyStatement::If(v) => Self::If(v.into()),
ast::IfBodyStatement::Loop(v) => {
Self::Loop(v.iter().map(|v| v.clone().into()).collect())
}
ast::IfBodyStatement::Return(v) => Self::Return(v.into()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "codec",
derive(Serialize, Deserialize),
serde(tag = "type", content = "content")
)]
pub enum IfLoopBodyStatement {
LetBinding(LetBinding),
Binding(Binding),
FunctionCall(FunctionCall),
If(IfStatement),
Loop(Vec<LoopBodyStatement>),
Return(Expression),
Break,
Continue,
}
impl<E: ExtendedExpression> From<ast::IfLoopBodyStatement<'_, E>> for IfLoopBodyStatement {
fn from(value: ast::IfLoopBodyStatement<'_, E>) -> Self {
match value {
ast::IfLoopBodyStatement::LetBinding(v) => Self::LetBinding(v.into()),
ast::IfLoopBodyStatement::Binding(v) => Self::Binding(v.into()),
ast::IfLoopBodyStatement::FunctionCall(v) => Self::FunctionCall(v.into()),
ast::IfLoopBodyStatement::If(v) => Self::If(v.into()),
ast::IfLoopBodyStatement::Loop(v) => {
Self::Loop(v.iter().map(|v| v.clone().into()).collect())
}
ast::IfLoopBodyStatement::Return(v) => Self::Return(v.into()),
ast::IfLoopBodyStatement::Break => Self::Break,
ast::IfLoopBodyStatement::Continue => Self::Continue,
}
}
}