fix integer contextual inference

This commit is contained in:
Protryon 2021-01-25 11:01:28 -08:00
parent 786afeecde
commit 7c216bd07d
5 changed files with 49 additions and 19 deletions

View File

@ -203,6 +203,10 @@ impl AsgConvertError {
)
}
pub fn unexpected_nonconst(span: &Span) -> Self {
Self::new_from_span("expected const, found non-const value".to_string(), span)
}
pub fn unresolved_reference(name: &str, span: &Span) -> Self {
Self::new_from_span(format!("failed to resolve variable reference '{}'", name), span)
}

View File

@ -133,24 +133,41 @@ impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression
));
}
}
let left = value
.left
.as_deref()
.map(|left| {
Arc::<Expression>::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32))))
})
.transpose()?;
let right = value
.right
.as_deref()
.map(|right| {
Arc::<Expression>::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32))))
})
.transpose()?;
if let Some(left) = left.as_ref() {
if left.const_value().is_none() {
return Err(AsgConvertError::unexpected_nonconst(
&left.span().cloned().unwrap_or_default(),
));
}
}
if let Some(right) = right.as_ref() {
if right.const_value().is_none() {
return Err(AsgConvertError::unexpected_nonconst(
&right.span().cloned().unwrap_or_default(),
));
}
}
Ok(ArrayRangeAccessExpression {
parent: RefCell::new(None),
span: Some(value.span.clone()),
array,
left: value
.left
.as_deref()
.map(|left| {
Arc::<Expression>::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32))))
})
.transpose()?,
right: value
.right
.as_deref()
.map(|right| {
Arc::<Expression>::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32))))
})
.transpose()?,
left,
right,
})
}
}

View File

@ -102,11 +102,9 @@ impl PartialType {
pub fn matches(&self, other: &Type) -> bool {
match (self, other) {
(PartialType::Type(t), other) => t.is_assignable_from(other),
(PartialType::Integer(self_sub_type, self_contextual_type), Type::Integer(sub_type)) => self_sub_type
.as_ref()
.or_else(|| self_contextual_type.as_ref())
.map(|x| x == sub_type)
.unwrap_or(true),
(PartialType::Integer(self_sub_type, _), Type::Integer(sub_type)) => {
self_sub_type.as_ref().map(|x| x == sub_type).unwrap_or(true)
}
(PartialType::Array(element, len), Type::Array(other_element, other_len)) => {
if let Some(element) = element {
if !element.matches(&*other_element) {

View File

@ -0,0 +1,5 @@
function main() {
let x = 0u8;
let a = [0u8; 4];
console.assert(a[x] == 0);
}

View File

@ -102,6 +102,12 @@ fn test_slice() {
load_asg(program_string).unwrap();
}
#[test]
fn test_index_u8() {
let program_string = include_str!("index_u8.leo");
load_asg(program_string).unwrap();
}
#[test]
fn test_slice_i8() {
let program_string = include_str!("slice_i8.leo");