1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

differentiate between if-expression and ternary expression in typed_absy

This commit is contained in:
dark64 2021-09-29 18:46:12 +02:00
parent 3a54229f9b
commit ef7183cae0
14 changed files with 336 additions and 212 deletions

View file

@ -375,6 +375,7 @@ impl<'ast> From<pest::Expression<'ast>> for absy::ExpressionNode<'ast> {
match expression {
pest::Expression::Binary(e) => absy::ExpressionNode::from(e),
pest::Expression::Ternary(e) => absy::ExpressionNode::from(e),
pest::Expression::IfElse(e) => absy::ExpressionNode::from(e),
pest::Expression::Literal(e) => absy::ExpressionNode::from(e),
pest::Expression::Identifier(e) => absy::ExpressionNode::from(e),
pest::Expression::Postfix(e) => absy::ExpressionNode::from(e),
@ -475,13 +476,27 @@ impl<'ast> From<pest::BinaryExpression<'ast>> for absy::ExpressionNode<'ast> {
}
}
impl<'ast> From<pest::IfElseExpression<'ast>> for absy::ExpressionNode<'ast> {
fn from(expression: pest::IfElseExpression<'ast>) -> absy::ExpressionNode<'ast> {
use crate::absy::NodeValue;
absy::Expression::Conditional(
box absy::ExpressionNode::from(*expression.condition),
box absy::ExpressionNode::from(*expression.consequence),
box absy::ExpressionNode::from(*expression.alternative),
absy::ConditionalKind::IfElse,
)
.span(expression.span)
}
}
impl<'ast> From<pest::TernaryExpression<'ast>> for absy::ExpressionNode<'ast> {
fn from(expression: pest::TernaryExpression<'ast>) -> absy::ExpressionNode<'ast> {
use crate::absy::NodeValue;
absy::Expression::IfElse(
box absy::ExpressionNode::from(*expression.first),
box absy::ExpressionNode::from(*expression.second),
box absy::ExpressionNode::from(*expression.third),
absy::Expression::Conditional(
box absy::ExpressionNode::from(*expression.condition),
box absy::ExpressionNode::from(*expression.consequence),
box absy::ExpressionNode::from(*expression.alternative),
absy::ConditionalKind::Ternary,
)
.span(expression.span)
}

View file

@ -454,6 +454,12 @@ impl<'ast> fmt::Display for Range<'ast> {
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ConditionalKind {
IfElse,
Ternary,
}
/// An expression
#[derive(Debug, Clone, PartialEq)]
pub enum Expression<'ast> {
@ -473,10 +479,11 @@ pub enum Expression<'ast> {
Pow(Box<ExpressionNode<'ast>>, Box<ExpressionNode<'ast>>),
Neg(Box<ExpressionNode<'ast>>),
Pos(Box<ExpressionNode<'ast>>),
IfElse(
Conditional(
Box<ExpressionNode<'ast>>,
Box<ExpressionNode<'ast>>,
Box<ExpressionNode<'ast>>,
ConditionalKind,
),
FunctionCall(
FunctionIdentifier<'ast>,
@ -524,11 +531,18 @@ impl<'ast> fmt::Display for Expression<'ast> {
Expression::Neg(ref e) => write!(f, "(-{})", e),
Expression::Pos(ref e) => write!(f, "(+{})", e),
Expression::BooleanConstant(b) => write!(f, "{}", b),
Expression::IfElse(ref condition, ref consequent, ref alternative) => write!(
f,
"if {} then {} else {} fi",
condition, consequent, alternative
),
Expression::Conditional(ref condition, ref consequent, ref alternative, ref kind) => {
match kind {
ConditionalKind::IfElse => write!(
f,
"if {} then {} else {} fi",
condition, consequent, alternative
),
ConditionalKind::Ternary => {
write!(f, "{} ? {} : {}", condition, consequent, alternative)
}
}
}
Expression::FunctionCall(ref i, ref g, ref p) => {
if let Some(g) = g {
write!(

View file

@ -2213,7 +2213,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
}),
}
}
Expression::IfElse(box condition, box consequence, box alternative) => {
Expression::Conditional(box condition, box consequence, box alternative, kind) => {
let condition_checked = self.check_expression(condition, module_id, types)?;
let consequence_checked = self.check_expression(consequence, module_id, types)?;
let alternative_checked = self.check_expression(alternative, module_id, types)?;
@ -2228,26 +2228,35 @@ impl<'ast, T: Field> Checker<'ast, T> {
message: format!("{{consequence}} and {{alternative}} in conditional expression should have the same type, found {}, {}", e1.get_type(), e2.get_type()),
})?;
let kind = match kind {
crate::absy::ConditionalKind::IfElse => {
crate::typed_absy::ConditionalKind::IfElse
}
crate::absy::ConditionalKind::Ternary => {
crate::typed_absy::ConditionalKind::Ternary
}
};
match condition_checked {
TypedExpression::Boolean(condition) => {
match (consequence_checked, alternative_checked) {
(TypedExpression::FieldElement(consequence), TypedExpression::FieldElement(alternative)) => {
Ok(FieldElementExpression::if_else(condition, consequence, alternative).into())
Ok(FieldElementExpression::conditional(condition, consequence, alternative, kind).into())
},
(TypedExpression::Boolean(consequence), TypedExpression::Boolean(alternative)) => {
Ok(BooleanExpression::if_else(condition, consequence, alternative).into())
Ok(BooleanExpression::conditional(condition, consequence, alternative, kind).into())
},
(TypedExpression::Array(consequence), TypedExpression::Array(alternative)) => {
Ok(ArrayExpression::if_else(condition, consequence, alternative).into())
Ok(ArrayExpression::conditional(condition, consequence, alternative, kind).into())
},
(TypedExpression::Struct(consequence), TypedExpression::Struct(alternative)) => {
Ok(StructExpression::if_else(condition, consequence, alternative).into())
Ok(StructExpression::conditional(condition, consequence, alternative, kind).into())
},
(TypedExpression::Uint(consequence), TypedExpression::Uint(alternative)) => {
Ok(UExpression::if_else(condition, consequence, alternative).into())
Ok(UExpression::conditional(condition, consequence, alternative, kind).into())
},
(TypedExpression::Int(consequence), TypedExpression::Int(alternative)) => {
Ok(IntExpression::if_else(condition, consequence, alternative).into())
Ok(IntExpression::conditional(condition, consequence, alternative, kind).into())
},
(c, a) => Err(ErrorInner {
pos: Some(pos),

View file

@ -17,17 +17,18 @@ impl Isolator {
}
impl<'ast, T: Field> Folder<'ast, T> for Isolator {
fn fold_if_else_expression<
E: Expr<'ast, T> + Block<'ast, T> + Fold<'ast, T> + IfElse<'ast, T>,
fn fold_conditional_expression<
E: Expr<'ast, T> + Block<'ast, T> + Fold<'ast, T> + Conditional<'ast, T>,
>(
&mut self,
_: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> IfElseOrExpression<'ast, T, E> {
IfElseOrExpression::IfElse(IfElseExpression::new(
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
ConditionalOrExpression::Conditional(ConditionalExpression::new(
self.fold_boolean_expression(*e.condition),
E::block(vec![], e.consequence.fold(self)),
E::block(vec![], e.alternative.fold(self)),
e.kind,
))
}
}

View file

@ -281,12 +281,12 @@ impl<'ast, T: Field> Flattener<T> {
}
}
fn fold_if_else_expression<E: Flatten<'ast, T>>(
fn fold_conditional_expression<E: Flatten<'ast, T>>(
&mut self,
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
c: typed_absy::IfElseExpression<'ast, T, E>,
c: typed_absy::ConditionalExpression<'ast, T, E>,
) -> Vec<zir::ZirExpression<'ast, T>> {
fold_if_else_expression(self, statements_buffer, c)
fold_conditional_expression(self, statements_buffer, c)
}
fn fold_member_expression<E>(
@ -442,8 +442,8 @@ fn fold_array_expression_inner<'ast, T: Field>(
exprs
}
typed_absy::ArrayExpressionInner::FunctionCall(..) => unreachable!(),
typed_absy::ArrayExpressionInner::IfElse(c) => {
f.fold_if_else_expression(statements_buffer, c)
typed_absy::ArrayExpressionInner::Conditional(c) => {
f.fold_conditional_expression(statements_buffer, c)
}
typed_absy::ArrayExpressionInner::Member(m) => {
f.fold_member_expression(statements_buffer, m)
@ -517,8 +517,8 @@ fn fold_struct_expression_inner<'ast, T: Field>(
.flat_map(|e| f.fold_expression(statements_buffer, e))
.collect(),
typed_absy::StructExpressionInner::FunctionCall(..) => unreachable!(),
typed_absy::StructExpressionInner::IfElse(c) => {
f.fold_if_else_expression(statements_buffer, c)
typed_absy::StructExpressionInner::Conditional(c) => {
f.fold_conditional_expression(statements_buffer, c)
}
typed_absy::StructExpressionInner::Member(m) => {
f.fold_member_expression(statements_buffer, m)
@ -640,10 +640,10 @@ fn fold_select_expression<'ast, T: Field, E>(
}
}
fn fold_if_else_expression<'ast, T: Field, E: Flatten<'ast, T>>(
fn fold_conditional_expression<'ast, T: Field, E: Flatten<'ast, T>>(
f: &mut Flattener<T>,
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
c: typed_absy::IfElseExpression<'ast, T, E>,
c: typed_absy::ConditionalExpression<'ast, T, E>,
) -> Vec<zir::ZirExpression<'ast, T>> {
let mut consequence_statements = vec![];
let mut alternative_statements = vec![];
@ -736,8 +736,8 @@ fn fold_field_expression<'ast, T: Field>(
typed_absy::FieldElementExpression::Pos(box e) => {
f.fold_field_expression(statements_buffer, e)
}
typed_absy::FieldElementExpression::IfElse(c) => f
.fold_if_else_expression(statements_buffer, c)
typed_absy::FieldElementExpression::Conditional(c) => f
.fold_conditional_expression(statements_buffer, c)
.pop()
.unwrap()
.try_into()
@ -902,8 +902,8 @@ fn fold_boolean_expression<'ast, T: Field>(
let e = f.fold_boolean_expression(statements_buffer, e);
zir::BooleanExpression::Not(box e)
}
typed_absy::BooleanExpression::IfElse(c) => f
.fold_if_else_expression(statements_buffer, c)
typed_absy::BooleanExpression::Conditional(c) => f
.fold_conditional_expression(statements_buffer, c)
.pop()
.unwrap()
.try_into()
@ -1064,8 +1064,8 @@ fn fold_uint_expression_inner<'ast, T: Field>(
)
.unwrap()
.into_inner(),
typed_absy::UExpressionInner::IfElse(c) => zir::UExpression::try_from(
f.fold_if_else_expression(statements_buffer, c)
typed_absy::UExpressionInner::Conditional(c) => zir::UExpression::try_from(
f.fold_conditional_expression(statements_buffer, c)
.pop()
.unwrap(),
)

View file

@ -173,13 +173,13 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
fold_function(self, f)
}
fn fold_if_else_expression<
E: Expr<'ast, T> + IfElse<'ast, T> + PartialEq + ResultFold<'ast, T>,
fn fold_conditional_expression<
E: Expr<'ast, T> + Conditional<'ast, T> + PartialEq + ResultFold<'ast, T>,
>(
&mut self,
_: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> Result<IfElseOrExpression<'ast, T, E>, Self::Error> {
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, Self::Error> {
Ok(
match (
self.fold_boolean_expression(*e.condition)?,
@ -187,16 +187,16 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
e.alternative.fold(self)?,
) {
(BooleanExpression::Value(true), consequence, _) => {
IfElseOrExpression::Expression(consequence.into_inner())
ConditionalOrExpression::Expression(consequence.into_inner())
}
(BooleanExpression::Value(false), _, alternative) => {
IfElseOrExpression::Expression(alternative.into_inner())
ConditionalOrExpression::Expression(alternative.into_inner())
}
(_, consequence, alternative) if consequence == alternative => {
IfElseOrExpression::Expression(consequence.into_inner())
ConditionalOrExpression::Expression(consequence.into_inner())
}
(condition, consequence, alternative) => IfElseOrExpression::IfElse(
IfElseExpression::new(condition, consequence, alternative),
(condition, consequence, alternative) => ConditionalOrExpression::Conditional(
ConditionalExpression::new(condition, consequence, alternative, e.kind),
),
},
)
@ -1431,7 +1431,7 @@ mod tests {
#[test]
fn if_else_true() {
let e = FieldElementExpression::if_else(
let e = FieldElementExpression::conditional(
BooleanExpression::Value(true),
FieldElementExpression::Number(Bn128Field::from(2)),
FieldElementExpression::Number(Bn128Field::from(3)),
@ -1445,7 +1445,7 @@ mod tests {
#[test]
fn if_else_false() {
let e = FieldElementExpression::if_else(
let e = FieldElementExpression::conditional(
BooleanExpression::Value(false),
FieldElementExpression::Number(Bn128Field::from(2)),
FieldElementExpression::Number(Bn128Field::from(3)),

View file

@ -55,7 +55,7 @@ impl<'ast> VariableWriteRemover {
(0..size)
.map(|i| match inner_ty {
Type::Int => unreachable!(),
Type::Array(..) => ArrayExpression::if_else(
Type::Array(..) => ArrayExpression::conditional(
BooleanExpression::UintEq(
box i.into(),
box head.clone(),
@ -73,9 +73,10 @@ impl<'ast> VariableWriteRemover {
),
},
ArrayExpression::select(base.clone(), i),
ConditionalKind::IfElse,
)
.into(),
Type::Struct(..) => StructExpression::if_else(
Type::Struct(..) => StructExpression::conditional(
BooleanExpression::UintEq(
box i.into(),
box head.clone(),
@ -93,9 +94,10 @@ impl<'ast> VariableWriteRemover {
),
},
StructExpression::select(base.clone(), i),
ConditionalKind::IfElse,
)
.into(),
Type::FieldElement => FieldElementExpression::if_else(
Type::FieldElement => FieldElementExpression::conditional(
BooleanExpression::UintEq(
box i.into(),
box head.clone(),
@ -114,9 +116,10 @@ impl<'ast> VariableWriteRemover {
),
},
FieldElementExpression::select(base.clone(), i),
ConditionalKind::IfElse,
)
.into(),
Type::Boolean => BooleanExpression::if_else(
Type::Boolean => BooleanExpression::conditional(
BooleanExpression::UintEq(
box i.into(),
box head.clone(),
@ -134,9 +137,10 @@ impl<'ast> VariableWriteRemover {
),
},
BooleanExpression::select(base.clone(), i),
ConditionalKind::IfElse,
)
.into(),
Type::Uint(..) => UExpression::if_else(
Type::Uint(..) => UExpression::conditional(
BooleanExpression::UintEq(
box i.into(),
box head.clone(),
@ -154,6 +158,7 @@ impl<'ast> VariableWriteRemover {
),
},
UExpression::select(base.clone(), i),
ConditionalKind::IfElse,
)
.into(),
})

View file

@ -258,18 +258,18 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_block_expression(self, block)
}
fn fold_if_else_expression<
fn fold_conditional_expression<
E: Expr<'ast, T>
+ Fold<'ast, T>
+ Block<'ast, T>
+ IfElse<'ast, T>
+ Conditional<'ast, T>
+ From<TypedExpression<'ast, T>>,
>(
&mut self,
ty: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> IfElseOrExpression<'ast, T, E> {
fold_if_else_expression(self, ty, e)
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
fold_conditional_expression(self, ty, e)
}
fn fold_member_expression<
@ -293,7 +293,7 @@ pub trait Folder<'ast, T: Field>: Sized {
}
fn fold_select_expression<
E: Expr<'ast, T> + Select<'ast, T> + IfElse<'ast, T> + From<TypedExpression<'ast, T>>,
E: Expr<'ast, T> + Select<'ast, T> + Conditional<'ast, T> + From<TypedExpression<'ast, T>>,
>(
&mut self,
ty: &E::Ty,
@ -459,9 +459,9 @@ pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
ArrayExpressionInner::IfElse(c) => match f.fold_if_else_expression(ty, c) {
IfElseOrExpression::IfElse(s) => ArrayExpressionInner::IfElse(s),
IfElseOrExpression::Expression(u) => u,
ArrayExpressionInner::Conditional(c) => match f.fold_conditional_expression(ty, c) {
ConditionalOrExpression::Conditional(s) => ArrayExpressionInner::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
ArrayExpressionInner::Select(select) => match f.fold_select_expression(ty, select) {
SelectOrExpression::Select(s) => ArrayExpressionInner::Select(s),
@ -506,9 +506,9 @@ pub fn fold_struct_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
StructExpressionInner::IfElse(c) => match f.fold_if_else_expression(ty, c) {
IfElseOrExpression::IfElse(s) => StructExpressionInner::IfElse(s),
IfElseOrExpression::Expression(u) => u,
StructExpressionInner::Conditional(c) => match f.fold_conditional_expression(ty, c) {
ConditionalOrExpression::Conditional(s) => StructExpressionInner::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
StructExpressionInner::Select(select) => match f.fold_select_expression(ty, select) {
SelectOrExpression::Select(s) => StructExpressionInner::Select(s),
@ -568,10 +568,10 @@ pub fn fold_field_expression<'ast, T: Field, F: Folder<'ast, T>>(
FieldElementExpression::Pos(box e)
}
FieldElementExpression::IfElse(c) => {
match f.fold_if_else_expression(&Type::FieldElement, c) {
IfElseOrExpression::IfElse(s) => FieldElementExpression::IfElse(s),
IfElseOrExpression::Expression(u) => u,
FieldElementExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::FieldElement, c) {
ConditionalOrExpression::Conditional(s) => FieldElementExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
}
}
FieldElementExpression::FunctionCall(function_call) => {
@ -596,20 +596,21 @@ pub fn fold_field_expression<'ast, T: Field, F: Folder<'ast, T>>(
}
}
pub fn fold_if_else_expression<
pub fn fold_conditional_expression<
'ast,
T: Field,
E: Expr<'ast, T> + Fold<'ast, T> + IfElse<'ast, T> + From<TypedExpression<'ast, T>>,
E: Expr<'ast, T> + Fold<'ast, T> + Conditional<'ast, T> + From<TypedExpression<'ast, T>>,
F: Folder<'ast, T>,
>(
f: &mut F,
_: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> IfElseOrExpression<'ast, T, E> {
IfElseOrExpression::IfElse(IfElseExpression::new(
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
ConditionalOrExpression::Conditional(ConditionalExpression::new(
f.fold_boolean_expression(*e.condition),
e.consequence.fold(f),
e.alternative.fold(f),
e.kind,
))
}
@ -632,7 +633,7 @@ pub fn fold_member_expression<
pub fn fold_select_expression<
'ast,
T: Field,
E: Expr<'ast, T> + Select<'ast, T> + IfElse<'ast, T> + From<TypedExpression<'ast, T>>,
E: Expr<'ast, T> + Select<'ast, T> + Conditional<'ast, T> + From<TypedExpression<'ast, T>>,
F: Folder<'ast, T>,
>(
f: &mut F,
@ -747,9 +748,10 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
BooleanExpression::IfElse(c) => match f.fold_if_else_expression(&Type::Boolean, c) {
IfElseOrExpression::IfElse(s) => BooleanExpression::IfElse(s),
IfElseOrExpression::Expression(u) => u,
BooleanExpression::Conditional(c) => match f.fold_conditional_expression(&Type::Boolean, c)
{
ConditionalOrExpression::Conditional(s) => BooleanExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
BooleanExpression::Select(select) => match f.fold_select_expression(&Type::Boolean, select)
{
@ -875,9 +877,9 @@ pub fn fold_uint_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
SelectOrExpression::Select(s) => UExpressionInner::Select(s),
SelectOrExpression::Expression(u) => u,
},
UExpressionInner::IfElse(c) => match f.fold_if_else_expression(&ty, c) {
IfElseOrExpression::IfElse(s) => UExpressionInner::IfElse(s),
IfElseOrExpression::Expression(u) => u,
UExpressionInner::Conditional(c) => match f.fold_conditional_expression(&ty, c) {
ConditionalOrExpression::Conditional(s) => UExpressionInner::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
UExpressionInner::Member(m) => match f.fold_member_expression(&ty, m) {
MemberOrExpression::Member(m) => UExpressionInner::Member(m),

View file

@ -5,9 +5,10 @@ use crate::typed_absy::types::{
};
use crate::typed_absy::UBitwidth;
use crate::typed_absy::{
ArrayExpression, ArrayExpressionInner, BooleanExpression, Expr, FieldElementExpression, IfElse,
IfElseExpression, Select, SelectExpression, StructExpression, StructExpressionInner, Typed,
TypedExpression, TypedExpressionOrSpread, TypedSpread, UExpression, UExpressionInner,
ArrayExpression, ArrayExpressionInner, BooleanExpression, Conditional, ConditionalExpression,
Expr, FieldElementExpression, Select, SelectExpression, StructExpression,
StructExpressionInner, Typed, TypedExpression, TypedExpressionOrSpread, TypedSpread,
UExpression, UExpressionInner,
};
use num_bigint::BigUint;
use std::convert::TryFrom;
@ -239,7 +240,7 @@ pub enum IntExpression<'ast, T> {
Div(Box<IntExpression<'ast, T>>, Box<IntExpression<'ast, T>>),
Rem(Box<IntExpression<'ast, T>>, Box<IntExpression<'ast, T>>),
Pow(Box<IntExpression<'ast, T>>, Box<IntExpression<'ast, T>>),
IfElse(IfElseExpression<'ast, T, IntExpression<'ast, T>>),
Conditional(ConditionalExpression<'ast, T, IntExpression<'ast, T>>),
Select(SelectExpression<'ast, T, IntExpression<'ast, T>>),
Xor(Box<IntExpression<'ast, T>>, Box<IntExpression<'ast, T>>),
And(Box<IntExpression<'ast, T>>, Box<IntExpression<'ast, T>>),
@ -354,7 +355,7 @@ impl<'ast, T: fmt::Display> fmt::Display for IntExpression<'ast, T> {
IntExpression::RightShift(ref e, ref by) => write!(f, "({} >> {})", e, by),
IntExpression::LeftShift(ref e, ref by) => write!(f, "({} << {})", e, by),
IntExpression::Not(ref e) => write!(f, "!{}", e),
IntExpression::IfElse(ref c) => write!(f, "{}", c),
IntExpression::Conditional(ref c) => write!(f, "{}", c),
}
}
}
@ -404,10 +405,11 @@ impl<'ast, T: Field> FieldElementExpression<'ast, T> {
)),
IntExpression::Pos(box e) => Ok(Self::Pos(box Self::try_from_int(e)?)),
IntExpression::Neg(box e) => Ok(Self::Neg(box Self::try_from_int(e)?)),
IntExpression::IfElse(c) => Ok(Self::IfElse(IfElseExpression::new(
IntExpression::Conditional(c) => Ok(Self::Conditional(ConditionalExpression::new(
*c.condition,
Self::try_from_int(*c.consequence)?,
Self::try_from_int(*c.alternative)?,
c.kind,
))),
IntExpression::Select(select) => {
let array = *select.array;
@ -523,10 +525,11 @@ impl<'ast, T: Field> UExpression<'ast, T> {
Self::try_from_int(e1, bitwidth)?,
e2,
)),
IfElse(c) => Ok(UExpression::if_else(
Conditional(c) => Ok(UExpression::conditional(
*c.condition,
Self::try_from_int(*c.consequence, bitwidth)?,
Self::try_from_int(*c.alternative, bitwidth)?,
c.kind,
)),
Select(select) => {
let array = *select.array;
@ -714,7 +717,7 @@ mod tests {
n.clone() * n.clone(),
IntExpression::pow(n.clone(), n.clone()),
n.clone() / n.clone(),
IntExpression::if_else(c.clone(), n.clone(), n.clone()),
IntExpression::conditional(c.clone(), n.clone(), n.clone()),
IntExpression::select(n_a.clone(), i.clone()),
];
@ -725,7 +728,7 @@ mod tests {
t.clone() * t.clone(),
FieldElementExpression::pow(t.clone(), i.clone()),
t.clone() / t.clone(),
FieldElementExpression::if_else(c.clone(), t.clone(), t.clone()),
FieldElementExpression::conditional(c.clone(), t.clone(), t.clone()),
FieldElementExpression::select(t_a.clone(), i.clone()),
];
@ -780,7 +783,7 @@ mod tests {
IntExpression::left_shift(n.clone(), i.clone()),
IntExpression::right_shift(n.clone(), i.clone()),
!n.clone(),
IntExpression::if_else(c.clone(), n.clone(), n.clone()),
IntExpression::conditional(c.clone(), n.clone(), n.clone()),
IntExpression::select(n_a.clone(), i.clone()),
];
@ -797,7 +800,7 @@ mod tests {
UExpression::left_shift(t.clone(), i.clone()),
UExpression::right_shift(t.clone(), i.clone()),
!t.clone(),
UExpression::if_else(c.clone(), t.clone(), t.clone()),
UExpression::conditional(c.clone(), t.clone(), t.clone()),
UExpression::select(t_a.clone(), i.clone()),
];

View file

@ -660,7 +660,7 @@ impl<'ast, T: fmt::Display> fmt::Display for StructExpression<'ast, T> {
StructExpressionInner::FunctionCall(ref function_call) => {
write!(f, "{}", function_call)
}
StructExpressionInner::IfElse(ref c) => write!(f, "{}", c),
StructExpressionInner::Conditional(ref c) => write!(f, "{}", c),
StructExpressionInner::Member(ref m) => write!(f, "{}", m),
StructExpressionInner::Select(ref select) => write!(f, "{}", select),
}
@ -805,30 +805,50 @@ impl<'ast, T: fmt::Display, E> fmt::Display for SelectExpression<'ast, T, E> {
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub enum ConditionalKind {
IfElse,
Ternary,
}
#[derive(Clone, PartialEq, Debug, Hash, Eq)]
pub struct IfElseExpression<'ast, T, E> {
pub struct ConditionalExpression<'ast, T, E> {
pub condition: Box<BooleanExpression<'ast, T>>,
pub consequence: Box<E>,
pub alternative: Box<E>,
pub kind: ConditionalKind,
}
impl<'ast, T, E> IfElseExpression<'ast, T, E> {
pub fn new(condition: BooleanExpression<'ast, T>, consequence: E, alternative: E) -> Self {
IfElseExpression {
impl<'ast, T, E> ConditionalExpression<'ast, T, E> {
pub fn new(
condition: BooleanExpression<'ast, T>,
consequence: E,
alternative: E,
kind: ConditionalKind,
) -> Self {
ConditionalExpression {
condition: box condition,
consequence: box consequence,
alternative: box alternative,
kind,
}
}
}
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for IfElseExpression<'ast, T, E> {
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for ConditionalExpression<'ast, T, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"if {} then {} else {} fi",
self.condition, self.consequence, self.alternative
)
match self.kind {
ConditionalKind::IfElse => write!(
f,
"if {} then {} else {} fi",
self.condition, self.consequence, self.alternative
),
ConditionalKind::Ternary => write!(
f,
"{} ? {} : {}",
self.condition, self.consequence, self.alternative
),
}
}
}
@ -910,7 +930,7 @@ pub enum FieldElementExpression<'ast, T> {
Box<FieldElementExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
),
IfElse(IfElseExpression<'ast, T, Self>),
Conditional(ConditionalExpression<'ast, T, Self>),
Neg(Box<FieldElementExpression<'ast, T>>),
Pos(Box<FieldElementExpression<'ast, T>>),
FunctionCall(FunctionCallExpression<'ast, T, Self>),
@ -1010,7 +1030,7 @@ pub enum BooleanExpression<'ast, T> {
Box<BooleanExpression<'ast, T>>,
),
Not(Box<BooleanExpression<'ast, T>>),
IfElse(IfElseExpression<'ast, T, Self>),
Conditional(ConditionalExpression<'ast, T, Self>),
Member(MemberExpression<'ast, T, Self>),
FunctionCall(FunctionCallExpression<'ast, T, Self>),
Select(SelectExpression<'ast, T, Self>),
@ -1117,7 +1137,7 @@ pub enum ArrayExpressionInner<'ast, T> {
Identifier(Identifier<'ast>),
Value(ArrayValue<'ast, T>),
FunctionCall(FunctionCallExpression<'ast, T, ArrayExpression<'ast, T>>),
IfElse(IfElseExpression<'ast, T, ArrayExpression<'ast, T>>),
Conditional(ConditionalExpression<'ast, T, ArrayExpression<'ast, T>>),
Member(MemberExpression<'ast, T, ArrayExpression<'ast, T>>),
Select(SelectExpression<'ast, T, ArrayExpression<'ast, T>>),
Slice(
@ -1181,7 +1201,7 @@ pub enum StructExpressionInner<'ast, T> {
Identifier(Identifier<'ast>),
Value(Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionCallExpression<'ast, T, StructExpression<'ast, T>>),
IfElse(IfElseExpression<'ast, T, StructExpression<'ast, T>>),
Conditional(ConditionalExpression<'ast, T, StructExpression<'ast, T>>),
Member(MemberExpression<'ast, T, StructExpression<'ast, T>>),
Select(SelectExpression<'ast, T, StructExpression<'ast, T>>),
}
@ -1323,7 +1343,7 @@ impl<'ast, T: fmt::Display> fmt::Display for FieldElementExpression<'ast, T> {
FieldElementExpression::Pow(ref lhs, ref rhs) => write!(f, "{}**{}", lhs, rhs),
FieldElementExpression::Neg(ref e) => write!(f, "(-{})", e),
FieldElementExpression::Pos(ref e) => write!(f, "(+{})", e),
FieldElementExpression::IfElse(ref c) => write!(f, "{}", c),
FieldElementExpression::Conditional(ref c) => write!(f, "{}", c),
FieldElementExpression::FunctionCall(ref function_call) => {
write!(f, "{}", function_call)
}
@ -1357,7 +1377,7 @@ impl<'ast, T: fmt::Display> fmt::Display for UExpression<'ast, T> {
UExpressionInner::Pos(ref e) => write!(f, "(+{})", e),
UExpressionInner::Select(ref select) => write!(f, "{}", select),
UExpressionInner::FunctionCall(ref function_call) => write!(f, "{}", function_call),
UExpressionInner::IfElse(ref c) => write!(f, "{}", c),
UExpressionInner::Conditional(ref c) => write!(f, "{}", c),
UExpressionInner::Member(ref m) => write!(f, "{}", m),
}
}
@ -1386,7 +1406,7 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
BooleanExpression::Not(ref exp) => write!(f, "!{}", exp),
BooleanExpression::Value(b) => write!(f, "{}", b),
BooleanExpression::FunctionCall(ref function_call) => write!(f, "{}", function_call),
BooleanExpression::IfElse(ref c) => write!(f, "{}", c),
BooleanExpression::Conditional(ref c) => write!(f, "{}", c),
BooleanExpression::Member(ref m) => write!(f, "{}", m),
BooleanExpression::Select(ref select) => write!(f, "{}", select),
}
@ -1408,7 +1428,7 @@ impl<'ast, T: fmt::Display> fmt::Display for ArrayExpressionInner<'ast, T> {
.join(", ")
),
ArrayExpressionInner::FunctionCall(ref function_call) => write!(f, "{}", function_call),
ArrayExpressionInner::IfElse(ref c) => write!(f, "{}", c),
ArrayExpressionInner::Conditional(ref c) => write!(f, "{}", c),
ArrayExpressionInner::Member(ref m) => write!(f, "{}", m),
ArrayExpressionInner::Select(ref select) => write!(f, "{}", select),
ArrayExpressionInner::Slice(ref a, ref from, ref to) => {
@ -1648,81 +1668,121 @@ pub enum MemberOrExpression<'ast, T, E: Expr<'ast, T>> {
Expression(E::Inner),
}
pub enum IfElseOrExpression<'ast, T, E: Expr<'ast, T>> {
IfElse(IfElseExpression<'ast, T, E>),
pub enum ConditionalOrExpression<'ast, T, E: Expr<'ast, T>> {
Conditional(ConditionalExpression<'ast, T, E>),
Expression(E::Inner),
}
pub trait IfElse<'ast, T> {
fn if_else(condition: BooleanExpression<'ast, T>, consequence: Self, alternative: Self)
-> Self;
}
impl<'ast, T> IfElse<'ast, T> for FieldElementExpression<'ast, T> {
fn if_else(
pub trait Conditional<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self;
}
impl<'ast, T> Conditional<'ast, T> for FieldElementExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
FieldElementExpression::IfElse(IfElseExpression::new(condition, consequence, alternative))
FieldElementExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
}
}
impl<'ast, T> IfElse<'ast, T> for IntExpression<'ast, T> {
fn if_else(
impl<'ast, T> Conditional<'ast, T> for IntExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
IntExpression::IfElse(IfElseExpression::new(condition, consequence, alternative))
IntExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
}
}
impl<'ast, T> IfElse<'ast, T> for BooleanExpression<'ast, T> {
fn if_else(
impl<'ast, T> Conditional<'ast, T> for BooleanExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
BooleanExpression::IfElse(IfElseExpression::new(condition, consequence, alternative))
BooleanExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
}
}
impl<'ast, T> IfElse<'ast, T> for UExpression<'ast, T> {
fn if_else(
impl<'ast, T> Conditional<'ast, T> for UExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
let bitwidth = consequence.bitwidth;
UExpressionInner::IfElse(IfElseExpression::new(condition, consequence, alternative))
.annotate(bitwidth)
UExpressionInner::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
.annotate(bitwidth)
}
}
impl<'ast, T: Clone> IfElse<'ast, T> for ArrayExpression<'ast, T> {
fn if_else(
impl<'ast, T: Clone> Conditional<'ast, T> for ArrayExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
let ty = consequence.inner_type().clone();
let size = consequence.size();
ArrayExpressionInner::IfElse(IfElseExpression::new(condition, consequence, alternative))
.annotate(ty, size)
ArrayExpressionInner::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
.annotate(ty, size)
}
}
impl<'ast, T: Clone> IfElse<'ast, T> for StructExpression<'ast, T> {
fn if_else(
impl<'ast, T: Clone> Conditional<'ast, T> for StructExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
kind: ConditionalKind,
) -> Self {
let ty = consequence.ty().clone();
StructExpressionInner::IfElse(IfElseExpression::new(condition, consequence, alternative))
.annotate(ty)
StructExpressionInner::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
kind,
))
.annotate(ty)
}
}

View file

@ -164,14 +164,14 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
fold_types(self, tys)
}
fn fold_if_else_expression<
E: Expr<'ast, T> + PartialEq + IfElse<'ast, T> + ResultFold<'ast, T>,
fn fold_conditional_expression<
E: Expr<'ast, T> + PartialEq + Conditional<'ast, T> + ResultFold<'ast, T>,
>(
&mut self,
ty: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> Result<IfElseOrExpression<'ast, T, E>, Self::Error> {
fold_if_else_expression(self, ty, e)
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, Self::Error> {
fold_conditional_expression(self, ty, e)
}
fn fold_block_expression<E: ResultFold<'ast, T>>(
@ -491,9 +491,9 @@ pub fn fold_array_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
ArrayExpressionInner::IfElse(c) => match f.fold_if_else_expression(ty, c)? {
IfElseOrExpression::IfElse(c) => ArrayExpressionInner::IfElse(c),
IfElseOrExpression::Expression(u) => u,
ArrayExpressionInner::Conditional(c) => match f.fold_conditional_expression(ty, c)? {
ConditionalOrExpression::Conditional(c) => ArrayExpressionInner::Conditional(c),
ConditionalOrExpression::Expression(u) => u,
},
ArrayExpressionInner::Member(m) => match f.fold_member_expression(ty, m)? {
MemberOrExpression::Member(m) => ArrayExpressionInner::Member(m),
@ -542,9 +542,9 @@ pub fn fold_struct_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
StructExpressionInner::IfElse(c) => match f.fold_if_else_expression(ty, c)? {
IfElseOrExpression::IfElse(c) => StructExpressionInner::IfElse(c),
IfElseOrExpression::Expression(u) => u,
StructExpressionInner::Conditional(c) => match f.fold_conditional_expression(ty, c)? {
ConditionalOrExpression::Conditional(c) => StructExpressionInner::Conditional(c),
ConditionalOrExpression::Expression(u) => u,
},
StructExpressionInner::Member(m) => match f.fold_member_expression(ty, m)? {
MemberOrExpression::Member(m) => StructExpressionInner::Member(m),
@ -605,10 +605,10 @@ pub fn fold_field_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
FieldElementExpression::Pos(box e)
}
FieldElementExpression::IfElse(c) => {
match f.fold_if_else_expression(&Type::FieldElement, c)? {
IfElseOrExpression::IfElse(c) => FieldElementExpression::IfElse(c),
IfElseOrExpression::Expression(u) => u,
FieldElementExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::FieldElement, c)? {
ConditionalOrExpression::Conditional(c) => FieldElementExpression::Conditional(c),
ConditionalOrExpression::Expression(u) => u,
}
}
FieldElementExpression::FunctionCall(function_call) => {
@ -659,11 +659,11 @@ pub fn fold_block_expression<'ast, T: Field, E: ResultFold<'ast, T>, F: ResultFo
})
}
pub fn fold_if_else_expression<
pub fn fold_conditional_expression<
'ast,
T: Field,
E: Expr<'ast, T>
+ IfElse<'ast, T>
+ Conditional<'ast, T>
+ PartialEq
+ ResultFold<'ast, T>
+ From<TypedExpression<'ast, T>>,
@ -671,13 +671,16 @@ pub fn fold_if_else_expression<
>(
f: &mut F,
_: &E::Ty,
e: IfElseExpression<'ast, T, E>,
) -> Result<IfElseOrExpression<'ast, T, E>, F::Error> {
Ok(IfElseOrExpression::IfElse(IfElseExpression::new(
f.fold_boolean_expression(*e.condition)?,
e.consequence.fold(f)?,
e.alternative.fold(f)?,
)))
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, F::Error> {
Ok(ConditionalOrExpression::Conditional(
ConditionalExpression::new(
f.fold_boolean_expression(*e.condition)?,
e.consequence.fold(f)?,
e.alternative.fold(f)?,
e.kind,
),
))
}
pub fn fold_member_expression<
@ -830,10 +833,12 @@ pub fn fold_boolean_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
FunctionCallOrExpression::Expression(u) => u,
}
}
BooleanExpression::IfElse(c) => match f.fold_if_else_expression(&Type::Boolean, c)? {
IfElseOrExpression::IfElse(c) => BooleanExpression::IfElse(c),
IfElseOrExpression::Expression(u) => u,
},
BooleanExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::Boolean, c)? {
ConditionalOrExpression::Conditional(c) => BooleanExpression::Conditional(c),
ConditionalOrExpression::Expression(u) => u,
}
}
BooleanExpression::Select(select) => {
match f.fold_select_expression(&Type::Boolean, select)? {
SelectOrExpression::Select(s) => BooleanExpression::Select(s),
@ -958,9 +963,9 @@ pub fn fold_uint_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
SelectOrExpression::Select(s) => UExpressionInner::Select(s),
SelectOrExpression::Expression(u) => u,
},
UExpressionInner::IfElse(c) => match f.fold_if_else_expression(&ty, c)? {
IfElseOrExpression::IfElse(c) => UExpressionInner::IfElse(c),
IfElseOrExpression::Expression(u) => u,
UExpressionInner::Conditional(c) => match f.fold_conditional_expression(&ty, c)? {
ConditionalOrExpression::Conditional(c) => UExpressionInner::Conditional(c),
ConditionalOrExpression::Expression(u) => u,
},
UExpressionInner::Member(m) => match f.fold_member_expression(&ty, m)? {
MemberOrExpression::Member(m) => UExpressionInner::Member(m),

View file

@ -193,7 +193,7 @@ pub enum UExpressionInner<'ast, T> {
FunctionCall(FunctionCallExpression<'ast, T, UExpression<'ast, T>>),
LeftShift(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
RightShift(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
IfElse(IfElseExpression<'ast, T, UExpression<'ast, T>>),
Conditional(ConditionalExpression<'ast, T, UExpression<'ast, T>>),
Member(MemberExpression<'ast, T, UExpression<'ast, T>>),
Select(SelectExpression<'ast, T, UExpression<'ast, T>>),
}

View file

@ -66,13 +66,13 @@ expression_list = _{(expression ~ ("," ~ expression)*)?}
expression = { unaried_term ~ (op_binary ~ unaried_term)* }
unaried_term = { op_unary? ~ powered_term }
powered_term = { term ~ (op_pow ~ exponent_expression)? }
term = { ("(" ~ expression ~ ")") | inline_struct_expression | conditional_expression | postfix_expression | primary_expression | inline_array_expression | array_initializer_expression }
term = { ("(" ~ expression ~ ")") | inline_struct_expression | if_else_expression | postfix_expression | primary_expression | inline_array_expression | array_initializer_expression }
spread = { "..." ~ expression }
range = { from_expression? ~ ".." ~ to_expression? }
from_expression = { expression }
to_expression = { expression }
conditional_expression = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ expression ~ "fi"}
if_else_expression = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ expression ~ "fi"}
postfix_expression = { identifier ~ access+ } // we force there to be at least one access, otherwise this matches single identifiers
access = { array_access | call_access | member_access }

View file

@ -13,12 +13,12 @@ pub use ast::{
CallAccess, ConstantDefinition, ConstantGenericValue, DecimalLiteralExpression, DecimalNumber,
DecimalSuffix, DefinitionStatement, ExplicitGenerics, Expression, FieldType, File,
FromExpression, FunctionDefinition, HexLiteralExpression, HexNumberExpression,
IdentifierExpression, ImportDirective, ImportSource, ImportSymbol, InlineArrayExpression,
InlineStructExpression, InlineStructMember, IterationStatement, LiteralExpression, Parameter,
PostfixExpression, Range, RangeOrExpression, ReturnStatement, Span, Spread, SpreadOrExpression,
Statement, StructDefinition, StructField, SymbolDeclaration, TernaryExpression, ToExpression,
Type, TypedIdentifier, TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator, Underscore,
Visibility,
IdentifierExpression, IfElseExpression, ImportDirective, ImportSource, ImportSymbol,
InlineArrayExpression, InlineStructExpression, InlineStructMember, IterationStatement,
LiteralExpression, Parameter, PostfixExpression, Range, RangeOrExpression, ReturnStatement,
Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField, SymbolDeclaration,
TernaryExpression, ToExpression, Type, TypedIdentifier, TypedIdentifierOrAssignee,
UnaryExpression, UnaryOperator, Underscore, Visibility,
};
mod ast {
@ -418,6 +418,7 @@ mod ast {
#[derive(Debug, PartialEq, Clone)]
pub enum Expression<'ast> {
Ternary(TernaryExpression<'ast>),
IfElse(IfElseExpression<'ast>),
Binary(BinaryExpression<'ast>),
Unary(UnaryExpression<'ast>),
Postfix(PostfixExpression<'ast>),
@ -433,7 +434,7 @@ mod ast {
pub enum Term<'ast> {
Expression(Expression<'ast>),
InlineStruct(InlineStructExpression<'ast>),
Ternary(TernaryExpression<'ast>),
Ternary(IfElseExpression<'ast>),
Postfix(PostfixExpression<'ast>),
Primary(PrimaryExpression<'ast>),
InlineArray(InlineArrayExpression<'ast>),
@ -518,7 +519,7 @@ mod ast {
fn from(t: Term<'ast>) -> Self {
match t {
Term::Expression(e) => e,
Term::Ternary(e) => Expression::Ternary(e),
Term::Ternary(e) => Expression::IfElse(e),
Term::Postfix(e) => Expression::Postfix(e),
Term::Primary(e) => e.into(),
Term::InlineArray(e) => Expression::InlineArray(e),
@ -746,27 +747,49 @@ mod ast {
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::conditional_expression))]
#[derive(Debug, PartialEq, Clone)]
pub struct TernaryExpression<'ast> {
pub first: Box<Expression<'ast>>,
pub second: Box<Expression<'ast>>,
pub third: Box<Expression<'ast>>,
pub condition: Box<Expression<'ast>>,
pub consequence: Box<Expression<'ast>>,
pub alternative: Box<Expression<'ast>>,
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::if_else_expression))]
pub struct IfElseExpression<'ast> {
pub condition: Box<Expression<'ast>>,
pub consequence: Box<Expression<'ast>>,
pub alternative: Box<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> Expression<'ast> {
pub fn if_else(
condition: Box<Expression<'ast>>,
consequence: Box<Expression<'ast>>,
alternative: Box<Expression<'ast>>,
span: Span<'ast>,
) -> Self {
Expression::IfElse(IfElseExpression {
condition,
consequence,
alternative,
span,
})
}
pub fn ternary(
first: Box<Expression<'ast>>,
second: Box<Expression<'ast>>,
third: Box<Expression<'ast>>,
condition: Box<Expression<'ast>>,
consequence: Box<Expression<'ast>>,
alternative: Box<Expression<'ast>>,
span: Span<'ast>,
) -> Self {
Expression::Ternary(TernaryExpression {
first,
second,
third,
condition,
consequence,
alternative,
span,
})
}
@ -791,6 +814,7 @@ mod ast {
Expression::Identifier(i) => &i.span,
Expression::Literal(c) => &c.span(),
Expression::Ternary(t) => &t.span,
Expression::IfElse(ie) => &ie.span,
Expression::Postfix(p) => &p.span,
Expression::InlineArray(a) => &a.span,
Expression::InlineStruct(s) => &s.span,
@ -1056,20 +1080,6 @@ mod tests {
pub fn pow(left: Expression<'ast>, right: Expression<'ast>, span: Span<'ast>) -> Self {
Self::binary(BinaryOperator::Pow, Box::new(left), Box::new(right), span)
}
pub fn if_else(
condition: Expression<'ast>,
consequence: Expression<'ast>,
alternative: Expression<'ast>,
span: Span<'ast>,
) -> Self {
Self::ternary(
Box::new(condition),
Box::new(consequence),
Box::new(alternative),
span,
)
}
}
#[test]
@ -1248,7 +1258,7 @@ mod tests {
}))],
statements: vec![Statement::Return(ReturnStatement {
expressions: vec![Expression::if_else(
Expression::Literal(LiteralExpression::DecimalLiteral(
Box::new(Expression::Literal(LiteralExpression::DecimalLiteral(
DecimalLiteralExpression {
suffix: None,
value: DecimalNumber {
@ -1256,8 +1266,8 @@ mod tests {
},
span: Span::new(&source, 62, 63).unwrap()
}
)),
Expression::Literal(LiteralExpression::DecimalLiteral(
))),
Box::new(Expression::Literal(LiteralExpression::DecimalLiteral(
DecimalLiteralExpression {
suffix: None,
value: DecimalNumber {
@ -1265,8 +1275,8 @@ mod tests {
},
span: Span::new(&source, 69, 70).unwrap()
}
)),
Expression::Literal(LiteralExpression::DecimalLiteral(
))),
Box::new(Expression::Literal(LiteralExpression::DecimalLiteral(
DecimalLiteralExpression {
suffix: None,
value: DecimalNumber {
@ -1274,7 +1284,7 @@ mod tests {
},
span: Span::new(&source, 76, 77).unwrap()
}
)),
))),
Span::new(&source, 59, 80).unwrap()
)],
span: Span::new(&source, 52, 80).unwrap(),