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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use super::{problems, util, ResolvedVCExpression, ResolvedVPExpression, ScopeResolver};
use crate::high_level::problem::{CompileProblem, FilePosition};
use crate::resolved::structure as o;
use crate::vague::structure as i;
use std::borrow::Borrow;
impl<'a> ScopeResolver<'a> {
fn resolve_vc_variable(
&mut self,
var_id: i::VariableId,
position: &FilePosition,
) -> Result<ResolvedVCExpression, CompileProblem> {
let (_, var_type) = self
.get_var_info(var_id)
.expect("Variable used before declaration, vague step should have caught this.");
Ok(ResolvedVCExpression::Specific {
var: var_id,
indexes: Vec::new(),
typ: var_type.clone(),
pos: position.clone(),
})
}
fn resolve_vc_index(
&mut self,
base: &i::VCExpression,
indexes: &Vec<(i::VPExpression, bool)>,
position: &FilePosition,
) -> Result<ResolvedVCExpression, CompileProblem> {
let rbase = self.resolve_vc_expression(base)?;
let mut known_indexes = Vec::new();
let mut all_indexes = Vec::new();
let mut etype = rbase.borrow_data_type();
for (index, optional) in indexes {
let arr_len = if let i::DataType::Array(len, eetype) = etype {
etype = eetype;
*len
} else if *optional {
continue;
} else {
return Err(problems::too_many_indexes(
position.clone(),
indexes.len(),
all_indexes.len(),
base.clone_position(),
rbase.borrow_data_type(),
));
};
let rindex = self.resolve_vp_expression(index)?;
if rindex.borrow_data_type() != &i::DataType::Int {
return Err(problems::array_index_not_int(
rindex.clone_position(),
rindex.borrow_data_type(),
position.clone(),
));
}
if let ResolvedVPExpression::Interpreted(data, pos, ..) = &rindex {
let val = data.require_int(); // We already checked that it should be an int.
if val < 0 {
return Err(problems::array_index_less_than_zero(
pos.clone(),
val,
position.clone(),
));
}
let val = val as usize;
if val >= arr_len {
return Err(problems::array_index_too_big(
pos.clone(),
val,
arr_len,
position.clone(),
));
}
// If they are unequal, that means at some point we didn't know what one of the
// earlier indexes was, so we should not add on any more known indexes because it's
// not really useful in this phase. LLVM will still be able to do optimizations on
// the literal values that will take their place.
if known_indexes.len() == all_indexes.len() {
known_indexes.push(val);
}
}
all_indexes.push(rindex.as_vp_expression()?);
}
let etype = etype.clone();
Ok(match rbase {
ResolvedVCExpression::Modified {
mut vce,
base,
indexes,
..
} => {
// We can't add on our known indices. If all the previous indices were known, we
// would have gotten a Specific result. Instead, since it is Modified, we cannot
// add on our indexes to the end because the previous set of indexes is not
// complete.
vce.indexes.append(&mut all_indexes);
ResolvedVCExpression::Modified {
vce,
typ: etype,
base,
indexes,
}
}
ResolvedVCExpression::Specific {
var,
mut indexes,
pos,
typ,
} => {
let unknown_indexes = &all_indexes[known_indexes.len()..];
indexes.append(&mut known_indexes);
if unknown_indexes.len() == 0 {
ResolvedVCExpression::Specific {
var,
indexes,
pos,
typ: etype,
}
} else {
let mut all_indexes = Vec::new();
for literal_index in &indexes {
all_indexes.push(o::VPExpression::Literal(
o::KnownData::Int(*literal_index as i64),
FilePosition::placeholder(),
));
}
for index in unknown_indexes {
all_indexes.push(index.clone());
}
let resolved_var = if let Some((Some(id), _)) = self.get_var_info(var) {
*id
} else {
return Err(problems::rt_indexes_on_ct_variable(position.clone(), &typ));
};
ResolvedVCExpression::Modified {
vce: o::VCExpression::index(resolved_var, all_indexes, position.clone()),
typ: etype,
base: var,
indexes,
}
}
}
})
}
pub(super) fn resolve_vc_expression(
&mut self,
input: &i::VCExpression,
) -> Result<ResolvedVCExpression, CompileProblem> {
match input {
i::VCExpression::Variable(id, position) => self.resolve_vc_variable(*id, position),
i::VCExpression::Index {
base,
indexes,
position,
} => self.resolve_vc_index(base, indexes, position),
}
}
}