1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)]
pub struct TernaryExpression {
pub parent: RefCell<Option<Weak<Expression>>>,
pub span: Option<Span>,
pub condition: Arc<Expression>,
pub if_true: Arc<Expression>,
pub if_false: Arc<Expression>,
}
impl Node for TernaryExpression {
fn span(&self) -> Option<&Span> {
self.span.as_ref()
}
}
impl ExpressionNode for TernaryExpression {
fn set_parent(&self, parent: Weak<Expression>) {
self.parent.replace(Some(parent));
}
fn get_parent(&self) -> Option<Arc<Expression>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten()
}
fn enforce_parents(&self, expr: &Arc<Expression>) {
self.condition.set_parent(Arc::downgrade(expr));
self.if_true.set_parent(Arc::downgrade(expr));
self.if_false.set_parent(Arc::downgrade(expr));
}
fn get_type(&self) -> Option<Type> {
self.if_true.get_type()
}
fn is_mut_ref(&self) -> bool {
self.if_true.is_mut_ref() && self.if_false.is_mut_ref()
}
fn const_value(&self) -> Option<ConstValue> {
if let Some(ConstValue::Boolean(switch)) = self.condition.const_value() {
if switch {
self.if_true.const_value()
} else {
self.if_false.const_value()
}
} else {
None
}
}
fn is_consty(&self) -> bool {
self.condition.is_consty() && self.if_true.is_consty() && self.if_false.is_consty()
}
}
impl FromAst<leo_ast::TernaryExpression> for TernaryExpression {
fn from_ast(
scope: &Scope,
value: &leo_ast::TernaryExpression,
expected_type: Option<PartialType>,
) -> Result<TernaryExpression, AsgConvertError> {
Ok(TernaryExpression {
parent: RefCell::new(None),
span: Some(value.span.clone()),
condition: Arc::<Expression>::from_ast(scope, &*value.condition, Some(Type::Boolean.partial()))?,
if_true: Arc::<Expression>::from_ast(scope, &*value.if_true, expected_type.clone())?,
if_false: Arc::<Expression>::from_ast(scope, &*value.if_false, expected_type)?,
})
}
}
impl Into<leo_ast::TernaryExpression> for &TernaryExpression {
fn into(self) -> leo_ast::TernaryExpression {
leo_ast::TernaryExpression {
condition: Box::new(self.condition.as_ref().into()),
if_true: Box::new(self.if_true.as_ref().into()),
if_false: Box::new(self.if_false.as_ref().into()),
span: self.span.clone().unwrap_or_default(),
}
}
}