mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 10:41:57 +03:00
allow non-u32 in various const places
This commit is contained in:
parent
958777f633
commit
2bd3a194fb
@ -178,6 +178,10 @@ impl ConstInt {
|
||||
|
||||
const_int_map!(value_negate, x, x.checked_neg()?);
|
||||
|
||||
const_int_op!(to_usize, Option<usize>, x, (*x).try_into().ok());
|
||||
|
||||
const_int_op!(to_string, String, x, (*x).to_string());
|
||||
|
||||
const_int_bimap!(value_add, x, y, x.checked_add(*y)?);
|
||||
|
||||
const_int_bimap!(value_sub, x, y, x.checked_sub(*y)?);
|
||||
|
@ -148,6 +148,23 @@ impl AsgConvertError {
|
||||
Self::new_from_span(format!("failed to index into non-array '{}'", name), span)
|
||||
}
|
||||
|
||||
pub fn invalid_assign_index(name: &str, num: &str, span: &Span) -> Self {
|
||||
Self::new_from_span(
|
||||
format!("failed to index array with invalid integer '{}'[{}]", name, num),
|
||||
span,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn invalid_backwards_assignment(name: &str, left: usize, right: usize, span: &Span) -> Self {
|
||||
Self::new_from_span(
|
||||
format!(
|
||||
"failed to index array range for assignment with left > right '{}'[{}..{}]",
|
||||
name, left, right
|
||||
),
|
||||
span,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn index_into_non_tuple(name: &str, span: &Span) -> Self {
|
||||
Self::new_from_span(format!("failed to index into non-tuple '{}'", name), span)
|
||||
}
|
||||
|
@ -14,19 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
AsgConvertError,
|
||||
ConstInt,
|
||||
ConstValue,
|
||||
Expression,
|
||||
ExpressionNode,
|
||||
FromAst,
|
||||
Node,
|
||||
PartialType,
|
||||
Scope,
|
||||
Span,
|
||||
Type,
|
||||
};
|
||||
use leo_ast::IntegerType;
|
||||
|
||||
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
sync::{Arc, Weak},
|
||||
@ -76,13 +66,13 @@ impl ExpressionNode for ArrayAccessExpression {
|
||||
_ => return None,
|
||||
};
|
||||
let const_index = match self.index.const_value()? {
|
||||
ConstValue::Int(ConstInt::U32(x)) => x,
|
||||
ConstValue::Int(x) => x.to_usize()?,
|
||||
_ => return None,
|
||||
};
|
||||
if const_index as usize >= array.len() {
|
||||
if const_index >= array.len() {
|
||||
return None;
|
||||
}
|
||||
Some(array.remove(const_index as usize))
|
||||
Some(array.remove(const_index))
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +105,7 @@ impl FromAst<leo_ast::ArrayAccessExpression> for ArrayAccessExpression {
|
||||
index: Arc::<Expression>::from_ast(
|
||||
scope,
|
||||
&*value.index,
|
||||
Some(Type::Integer(leo_ast::IntegerType::U32).partial()),
|
||||
Some(PartialType::Integer(None, Some(IntegerType::U32))),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
@ -14,19 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
AsgConvertError,
|
||||
ConstInt,
|
||||
ConstValue,
|
||||
Expression,
|
||||
ExpressionNode,
|
||||
FromAst,
|
||||
Node,
|
||||
PartialType,
|
||||
Scope,
|
||||
Span,
|
||||
Type,
|
||||
};
|
||||
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
|
||||
use leo_ast::IntegerType;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@ -73,20 +61,20 @@ impl ExpressionNode for ArrayRangeAccessExpression {
|
||||
_ => return None,
|
||||
};
|
||||
let const_left = match self.left.as_ref().map(|x| x.const_value()) {
|
||||
Some(Some(ConstValue::Int(ConstInt::U32(x)))) => x,
|
||||
Some(Some(ConstValue::Int(x))) => x.to_usize()?,
|
||||
None => 0,
|
||||
_ => return None,
|
||||
};
|
||||
let const_right = match self.right.as_ref().map(|x| x.const_value()) {
|
||||
Some(Some(ConstValue::Int(ConstInt::U32(x)))) => x,
|
||||
None => array_len as u32,
|
||||
Some(Some(ConstValue::Int(x))) => x.to_usize()?,
|
||||
None => array_len,
|
||||
_ => return None,
|
||||
};
|
||||
if const_left > const_right || const_right as usize > array_len {
|
||||
if const_left > const_right || const_right > array_len {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Type::Array(element, (const_right - const_left) as usize))
|
||||
Some(Type::Array(element, const_right - const_left))
|
||||
}
|
||||
|
||||
fn is_mut_ref(&self) -> bool {
|
||||
@ -99,22 +87,20 @@ impl ExpressionNode for ArrayRangeAccessExpression {
|
||||
_ => return None,
|
||||
};
|
||||
let const_left = match self.left.as_ref().map(|x| x.const_value()) {
|
||||
Some(Some(ConstValue::Int(ConstInt::U32(x)))) => x,
|
||||
Some(Some(ConstValue::Int(x))) => x.to_usize()?,
|
||||
None => 0,
|
||||
_ => return None,
|
||||
};
|
||||
let const_right = match self.right.as_ref().map(|x| x.const_value()) {
|
||||
Some(Some(ConstValue::Int(ConstInt::U32(x)))) => x,
|
||||
None => array.len() as u32,
|
||||
Some(Some(ConstValue::Int(x))) => x.to_usize()?,
|
||||
None => array.len(),
|
||||
_ => return None,
|
||||
};
|
||||
if const_left > const_right || const_right as usize > array.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(ConstValue::Array(
|
||||
array.drain(const_left as usize..const_right as usize).collect(),
|
||||
))
|
||||
Some(ConstValue::Array(array.drain(const_left..const_right).collect()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,12 +140,16 @@ impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression
|
||||
left: value
|
||||
.left
|
||||
.as_deref()
|
||||
.map(|left| Arc::<Expression>::from_ast(scope, left, Some(Type::Integer(IntegerType::U32).partial())))
|
||||
.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(Type::Integer(IntegerType::U32).partial())))
|
||||
.map(|right| {
|
||||
Arc::<Expression>::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32))))
|
||||
})
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
|
||||
}
|
||||
},
|
||||
BinaryOperationClass::Numeric => match expected_type {
|
||||
Some(PartialType::Type(x @ Type::Integer(_))) => Some(x),
|
||||
Some(x @ PartialType::Integer(_, _)) => Some(x),
|
||||
Some(x) => {
|
||||
return Err(AsgConvertError::unexpected_type(
|
||||
&x.to_string(),
|
||||
@ -137,8 +137,7 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
.map(Type::partial);
|
||||
};
|
||||
|
||||
// left
|
||||
let (left, right) = match Arc::<Expression>::from_ast(scope, &*value.left, expected_type.clone()) {
|
||||
@ -172,6 +171,7 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
|
||||
};
|
||||
|
||||
let left_type = left.get_type();
|
||||
#[allow(clippy::unused_unit)]
|
||||
match class {
|
||||
BinaryOperationClass::Numeric => match left_type {
|
||||
Some(Type::Integer(_)) => (),
|
||||
|
@ -154,19 +154,21 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
|
||||
}),
|
||||
}
|
||||
}
|
||||
Implicit(value, span) => match expected_type.map(PartialType::full).flatten() {
|
||||
Implicit(value, span) => match expected_type {
|
||||
None => return Err(AsgConvertError::unresolved_type("unknown", span)),
|
||||
Some(Type::Integer(int_type)) => Constant {
|
||||
parent: RefCell::new(None),
|
||||
span: Some(span.clone()),
|
||||
value: ConstValue::Int(ConstInt::parse(&int_type, value, span)?),
|
||||
},
|
||||
Some(Type::Field) => Constant {
|
||||
Some(PartialType::Integer(Some(sub_type), _)) | Some(PartialType::Integer(None, Some(sub_type))) => {
|
||||
Constant {
|
||||
parent: RefCell::new(None),
|
||||
span: Some(span.clone()),
|
||||
value: ConstValue::Int(ConstInt::parse(&sub_type, value, span)?),
|
||||
}
|
||||
}
|
||||
Some(PartialType::Type(Type::Field)) => Constant {
|
||||
parent: RefCell::new(None),
|
||||
span: Some(span.clone()),
|
||||
value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?),
|
||||
},
|
||||
Some(Type::Address) => Constant {
|
||||
Some(PartialType::Type(Type::Address)) => Constant {
|
||||
parent: RefCell::new(None),
|
||||
span: Some(span.clone()),
|
||||
value: ConstValue::Address(value.to_string()),
|
||||
@ -174,8 +176,9 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
|
||||
Some(x) => return Err(AsgConvertError::unexpected_type(&x.to_string(), Some("unknown"), span)),
|
||||
},
|
||||
Integer(int_type, value, span) => {
|
||||
match expected_type.map(PartialType::full).flatten() {
|
||||
Some(Type::Integer(sub_type)) if &sub_type == int_type => (),
|
||||
match expected_type {
|
||||
Some(PartialType::Integer(Some(sub_type), _)) if &sub_type == int_type => (),
|
||||
Some(PartialType::Integer(None, Some(_))) => (),
|
||||
None => (),
|
||||
Some(x) => {
|
||||
return Err(AsgConvertError::unexpected_type(
|
||||
|
@ -97,7 +97,7 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
|
||||
for access in statement.assignee.accesses.iter() {
|
||||
target_accesses.push(match access {
|
||||
AstAssigneeAccess::ArrayRange(left, right) => {
|
||||
let index_type = Some(Type::Integer(IntegerType::U32).into());
|
||||
let index_type = Some(PartialType::Integer(None, Some(IntegerType::U32)));
|
||||
let left = left
|
||||
.as_ref()
|
||||
.map(
|
||||
@ -127,15 +127,26 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
|
||||
.unwrap_or_else(|| Some(ConstValue::Int(ConstInt::U32(len.map(|x| x as u32)?)))),
|
||||
) {
|
||||
let left = match left {
|
||||
ConstValue::Int(ConstInt::U32(x)) => x,
|
||||
ConstValue::Int(x) => x.to_usize().ok_or_else(|| {
|
||||
AsgConvertError::invalid_assign_index(&name, &x.to_string(), &statement.span)
|
||||
})?,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
let right = match right {
|
||||
ConstValue::Int(ConstInt::U32(x)) => x,
|
||||
ConstValue::Int(x) => x.to_usize().ok_or_else(|| {
|
||||
AsgConvertError::invalid_assign_index(&name, &x.to_string(), &statement.span)
|
||||
})?,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
if right > left {
|
||||
if right >= left {
|
||||
target_type = Some(PartialType::Array(item.clone(), Some((right - left) as usize)))
|
||||
} else {
|
||||
return Err(AsgConvertError::invalid_backwards_assignment(
|
||||
&name,
|
||||
left,
|
||||
right,
|
||||
&statement.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +163,7 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
|
||||
AssignAccess::ArrayIndex(Arc::<Expression>::from_ast(
|
||||
scope,
|
||||
index,
|
||||
Some(Type::Integer(IntegerType::U32).into()),
|
||||
Some(PartialType::Integer(None, Some(IntegerType::U32))),
|
||||
)?)
|
||||
}
|
||||
AstAssigneeAccess::Tuple(index, _) => {
|
||||
|
@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::IntegerType;
|
||||
|
||||
use crate::{
|
||||
AsgConvertError,
|
||||
Expression,
|
||||
@ -25,7 +27,6 @@ use crate::{
|
||||
Scope,
|
||||
Span,
|
||||
Statement,
|
||||
Type,
|
||||
Variable,
|
||||
};
|
||||
use std::{
|
||||
@ -54,7 +55,7 @@ impl FromAst<leo_ast::IterationStatement> for Arc<Statement> {
|
||||
statement: &leo_ast::IterationStatement,
|
||||
_expected_type: Option<PartialType>,
|
||||
) -> Result<Arc<Statement>, AsgConvertError> {
|
||||
let expected_index_type = Some(Type::Integer(leo_ast::IntegerType::U32).into());
|
||||
let expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32)));
|
||||
let start = Arc::<Expression>::from_ast(scope, &statement.start, expected_index_type.clone())?;
|
||||
let stop = Arc::<Expression>::from_ast(scope, &statement.stop, expected_index_type)?;
|
||||
let variable = Arc::new(RefCell::new(InnerVariable {
|
||||
|
@ -44,7 +44,8 @@ pub enum WeakType {
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum PartialType {
|
||||
Type(Type), // non-array or tuple
|
||||
Type(Type), // non-array or tuple
|
||||
Integer(Option<IntegerType>, Option<IntegerType>), // specific, context-specific
|
||||
Array(Option<Box<PartialType>>, Option<usize>),
|
||||
Tuple(Vec<Option<PartialType>>),
|
||||
}
|
||||
@ -81,6 +82,7 @@ impl Into<Option<Type>> for PartialType {
|
||||
fn into(self) -> Option<Type> {
|
||||
match self {
|
||||
PartialType::Type(t) => Some(t),
|
||||
PartialType::Integer(sub_type, contextual_type) => Some(Type::Integer(sub_type.or(contextual_type)?)),
|
||||
PartialType::Array(element, len) => Some(Type::Array(Box::new((*element?).full()?), len?)),
|
||||
PartialType::Tuple(sub_types) => Some(Type::Tuple(
|
||||
sub_types
|
||||
@ -100,6 +102,11 @@ 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::Array(element, len), Type::Array(other_element, other_len)) => {
|
||||
if let Some(element) = element {
|
||||
if !element.matches(&*other_element) {
|
||||
@ -133,6 +140,7 @@ impl PartialType {
|
||||
impl Into<PartialType> for Type {
|
||||
fn into(self) -> PartialType {
|
||||
match self {
|
||||
Type::Integer(sub_type) => PartialType::Integer(Some(sub_type), None),
|
||||
Type::Array(element, len) => PartialType::Array(Some(Box::new((*element).into())), Some(len)),
|
||||
Type::Tuple(sub_types) => PartialType::Tuple(sub_types.into_iter().map(Into::into).map(Some).collect()),
|
||||
x => PartialType::Type(x),
|
||||
@ -182,6 +190,9 @@ impl fmt::Display for PartialType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PartialType::Type(t) => t.fmt(f),
|
||||
PartialType::Integer(Some(sub_type), _) => write!(f, "{}", sub_type),
|
||||
PartialType::Integer(_, Some(sub_type)) => write!(f, "<{}>", sub_type),
|
||||
PartialType::Integer(_, _) => write!(f, "integer"),
|
||||
PartialType::Array(sub_type, len) => {
|
||||
if let Some(sub_type) = sub_type {
|
||||
write!(f, "{}", *sub_type)?;
|
||||
|
@ -102,6 +102,12 @@ fn test_slice() {
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_i8() {
|
||||
let program_string = include_str!("slice_i8.leo");
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_lower() {
|
||||
let program_string = include_str!("slice_lower.leo");
|
||||
|
6
asg/tests/pass/array/slice_i8.leo
Normal file
6
asg/tests/pass/array/slice_i8.leo
Normal file
@ -0,0 +1,6 @@
|
||||
// `{from}..{to}` copies the elements of one array into another exclusively
|
||||
function main(a: [u8; 3]) {
|
||||
let b = [1u8; 4];
|
||||
|
||||
console.assert(a == b[0u8..3i8]);
|
||||
}
|
@ -22,7 +22,7 @@ fn test_basic() {
|
||||
let asg = load_asg(program_string).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", reformed_ast);
|
||||
panic!();
|
||||
// panic!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -47,7 +47,7 @@ fn test_function_rename() {
|
||||
let asg = load_asg(program_string).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", reformed_ast);
|
||||
panic!();
|
||||
// panic!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -84,5 +84,5 @@ fn test_imports() {
|
||||
let asg = crate::load_asg_imports(program_string, &mut imports).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", serde_json::to_string(&reformed_ast).unwrap());
|
||||
panic!();
|
||||
// panic!();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user