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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)]
pub struct TupleAccessExpression {
pub parent: RefCell<Option<Weak<Expression>>>,
pub span: Option<Span>,
pub tuple_ref: Arc<Expression>,
pub index: usize,
}
impl Node for TupleAccessExpression {
fn span(&self) -> Option<&Span> {
self.span.as_ref()
}
}
impl ExpressionNode for TupleAccessExpression {
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.tuple_ref.set_parent(Arc::downgrade(expr));
}
fn get_type(&self) -> Option<Type> {
match self.tuple_ref.get_type()? {
Type::Tuple(subtypes) => subtypes.get(self.index).cloned(),
_ => None,
}
}
fn is_mut_ref(&self) -> bool {
self.tuple_ref.is_mut_ref()
}
fn const_value(&self) -> Option<ConstValue> {
let tuple_const = self.tuple_ref.const_value()?;
match tuple_const {
ConstValue::Tuple(sub_consts) => sub_consts.get(self.index).cloned(),
_ => None,
}
}
fn is_consty(&self) -> bool {
self.tuple_ref.is_consty()
}
}
impl FromAst<leo_ast::TupleAccessExpression> for TupleAccessExpression {
fn from_ast(
scope: &Scope,
value: &leo_ast::TupleAccessExpression,
expected_type: Option<PartialType>,
) -> Result<TupleAccessExpression, AsgConvertError> {
let index = value
.index
.value
.parse::<usize>()
.map_err(|_| AsgConvertError::parse_index_error())?;
let mut expected_tuple = vec![None; index + 1];
expected_tuple[index] = expected_type;
let tuple = Arc::<Expression>::from_ast(scope, &*value.tuple, Some(PartialType::Tuple(expected_tuple)))?;
let tuple_type = tuple.get_type();
if let Some(Type::Tuple(_items)) = tuple_type {
} else {
return Err(AsgConvertError::unexpected_type(
"a tuple",
tuple_type.map(|x| x.to_string()).as_deref(),
&value.span,
));
}
Ok(TupleAccessExpression {
parent: RefCell::new(None),
span: Some(value.span.clone()),
tuple_ref: tuple,
index,
})
}
}
impl Into<leo_ast::TupleAccessExpression> for &TupleAccessExpression {
fn into(self) -> leo_ast::TupleAccessExpression {
leo_ast::TupleAccessExpression {
tuple: Box::new(self.tuple_ref.as_ref().into()),
index: leo_ast::PositiveNumber {
value: self.index.to_string(),
},
span: self.span.clone().unwrap_or_default(),
}
}
}