leo_passes/const_propagation/
visitor.rs1use crate::CompilerState;
18
19use leo_ast::{
20 ArrayExpression,
21 Expression,
22 Identifier,
23 IntegerType,
24 Literal,
25 NodeBuilder,
26 NodeID,
27 RepeatExpression,
28 StructExpression,
29 StructVariableInitializer,
30 TupleExpression,
31 interpreter_value::Value,
32};
33use leo_errors::StaticAnalyzerError;
34use leo_span::{Span, Symbol};
35
36pub struct ConstPropagationVisitor<'a> {
37 pub state: &'a mut CompilerState,
38 pub program: Symbol,
40 pub changed: bool,
42 pub const_not_evaluated: Option<Span>,
44 pub array_index_not_evaluated: Option<Span>,
46 pub array_length_not_evaluated: Option<Span>,
48 pub repeat_count_not_evaluated: Option<Span>,
50}
51
52impl ConstPropagationVisitor<'_> {
53 pub fn in_scope<T>(&mut self, id: NodeID, func: impl FnOnce(&mut Self) -> T) -> T {
55 self.state.symbol_table.enter_scope(Some(id));
56 let result = func(self);
57 self.state.symbol_table.enter_parent();
58 result
59 }
60
61 pub fn emit_err(&self, err: StaticAnalyzerError) {
63 self.state.handler.emit_err(err);
64 }
65}
66
67pub fn value_to_expression(value: &Value, span: Span, node_builder: &NodeBuilder) -> Option<Expression> {
68 use Value::*;
69 let id = node_builder.next_id();
70
71 let result = match value {
72 Unit => leo_ast::UnitExpression { span, id }.into(),
73 Bool(x) => Literal::boolean(*x, span, id).into(),
74 U8(x) => Literal::integer(IntegerType::U8, format!("{x}"), span, id).into(),
75 U16(x) => Literal::integer(IntegerType::U16, format!("{x}"), span, id).into(),
76 U32(x) => Literal::integer(IntegerType::U32, format!("{x}"), span, id).into(),
77 U64(x) => Literal::integer(IntegerType::U64, format!("{x}"), span, id).into(),
78 U128(x) => Literal::integer(IntegerType::U128, format!("{x}"), span, id).into(),
79 I8(x) => Literal::integer(IntegerType::I8, format!("{x}"), span, id).into(),
80 I16(x) => Literal::integer(IntegerType::I16, format!("{x}"), span, id).into(),
81 I32(x) => Literal::integer(IntegerType::I32, format!("{x}"), span, id).into(),
82 I64(x) => Literal::integer(IntegerType::I64, format!("{x}"), span, id).into(),
83 I128(x) => Literal::integer(IntegerType::I128, format!("{x}"), span, id).into(),
84 Address(x) => Literal::address(format!("{x}"), span, id).into(),
85 Group(x) => {
86 let mut s = format!("{x}");
87 s.truncate(s.len() - 5);
89 Literal::group(s, span, id).into()
90 }
91 Field(x) => {
92 let mut s = format!("{x}");
93 s.truncate(s.len() - 5);
95 Literal::field(s, span, id).into()
96 }
97 Scalar(x) => {
98 let mut s = format!("{x}");
99 s.truncate(s.len() - 6);
101 Literal::scalar(s, span, id).into()
102 }
103 Tuple(x) => {
104 let mut elements = Vec::with_capacity(x.len());
105 for value in x.iter() {
106 elements.push(value_to_expression(value, span, node_builder)?);
107 }
108 TupleExpression { elements, span, id }.into()
109 }
110 Array(x) => {
111 let mut elements = Vec::with_capacity(x.len());
112 for value in x.iter() {
113 elements.push(value_to_expression(value, span, node_builder)?);
114 }
115 ArrayExpression { elements, span, id }.into()
116 }
117 Repeat(expr, count) => RepeatExpression {
118 expr: value_to_expression(expr, span, node_builder)?,
119 count: value_to_expression(count, span, node_builder)?,
120 span,
121 id,
122 }
123 .into(),
124 Struct(x) => StructExpression {
125 name: Identifier { name: x.name, id: node_builder.next_id(), span },
126 members: {
127 let mut members = Vec::with_capacity(x.contents.len());
128 for (name, val) in x.contents.iter() {
129 let initializer = StructVariableInitializer {
130 identifier: Identifier { name: *name, id: node_builder.next_id(), span },
131 expression: Some(value_to_expression(val, span, node_builder)?),
132 span,
133 id: node_builder.next_id(),
134 };
135 members.push(initializer)
136 }
137 members
138 },
139 span,
140 id,
141 }
142 .into(),
143 Future(..) => return None,
144 };
145
146 Some(result)
147}