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
121
122
123
124
use leo_ast::IntegerType;
use crate::{
AsgConvertError,
Expression,
ExpressionNode,
FromAst,
InnerVariable,
Node,
PartialType,
Scope,
Span,
Statement,
Variable,
};
use std::cell::{Cell, RefCell};
#[derive(Clone)]
pub struct IterationStatement<'a> {
pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>,
pub variable: &'a Variable<'a>,
pub start: Cell<&'a Expression<'a>>,
pub stop: Cell<&'a Expression<'a>>,
pub body: Cell<&'a Statement<'a>>,
}
impl<'a> Node for IterationStatement<'a> {
fn span(&self) -> Option<&Span> {
self.span.as_ref()
}
}
impl<'a> FromAst<'a, leo_ast::IterationStatement> for &'a Statement<'a> {
fn from_ast(
scope: &'a Scope<'a>,
statement: &leo_ast::IterationStatement,
_expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> {
let expected_index_type = Some(PartialType::Integer(Some(IntegerType::U32), None));
let start = <&Expression<'a>>::from_ast(scope, &statement.start, expected_index_type.clone())?;
let stop = <&Expression<'a>>::from_ast(scope, &statement.stop, expected_index_type)?;
if !start.is_consty() {
return Err(AsgConvertError::unexpected_nonconst(
&start.span().cloned().unwrap_or_default(),
));
}
if !stop.is_consty() {
return Err(AsgConvertError::unexpected_nonconst(
&stop.span().cloned().unwrap_or_default(),
));
}
let variable = scope.context.alloc_variable(RefCell::new(InnerVariable {
id: scope.context.get_id(),
name: statement.variable.clone(),
type_: start
.get_type()
.ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))?,
mutable: false,
const_: true,
declaration: crate::VariableDeclaration::IterationDefinition,
references: vec![],
assignments: vec![],
}));
scope
.variables
.borrow_mut()
.insert(statement.variable.name.to_string(), variable);
let statement = scope.context.alloc_statement(Statement::Iteration(IterationStatement {
parent: Cell::new(None),
span: Some(statement.span.clone()),
variable,
stop: Cell::new(stop),
start: Cell::new(start),
body: Cell::new(
scope
.context
.alloc_statement(Statement::Block(crate::BlockStatement::from_ast(
scope,
&statement.block,
None,
)?)),
),
}));
variable.borrow_mut().assignments.push(statement);
Ok(statement)
}
}
impl<'a> Into<leo_ast::IterationStatement> for &IterationStatement<'a> {
fn into(self) -> leo_ast::IterationStatement {
leo_ast::IterationStatement {
variable: self.variable.borrow().name.clone(),
start: self.start.get().into(),
stop: self.stop.get().into(),
block: match self.body.get() {
Statement::Block(block) => block.into(),
_ => unimplemented!(),
},
span: self.span.clone().unwrap_or_default(),
}
}
}