mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-25 19:22:01 +03:00
do not compare array dimensions in type inference
This commit is contained in:
parent
6f3a235c76
commit
1daf6c9831
@ -14,7 +14,6 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Type;
|
|
||||||
use leo_ast::{Error as FormattedError, Identifier, Span};
|
use leo_ast::{Error as FormattedError, Identifier, Span};
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -43,60 +42,6 @@ impl TypeError {
|
|||||||
TypeError::Error(FormattedError::new_from_span(message, span))
|
TypeError::Error(FormattedError::new_from_span(message, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Expected an array type from the given expression.
|
|
||||||
///
|
|
||||||
pub fn invalid_array(actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected array type, found type `{}`.", actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Expected a circuit type from the given expression.
|
|
||||||
///
|
|
||||||
pub fn invalid_circuit(actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected circuit type, found type `{}`.", actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Expected a function type from the given expression.
|
|
||||||
///
|
|
||||||
pub fn invalid_function(actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected function type, found type `{}`.", actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Expected an integer type from the given expression.
|
|
||||||
///
|
|
||||||
pub fn invalid_integer(actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected integer type, found type `{}`.", actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Expected a tuple type from the given expression.
|
|
||||||
///
|
|
||||||
pub fn invalid_tuple(actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected tuple type, found type `{}`.", actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// The value of the expression does not match the given explicit type.
|
|
||||||
///
|
|
||||||
pub fn mismatched_types(expected: &Type, actual: &Type, span: Span) -> Self {
|
|
||||||
let message = format!("Expected type `{}`, found type `{}`.", expected, actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The `Self` keyword was used outside of a circuit.
|
/// The `Self` keyword was used outside of a circuit.
|
||||||
///
|
///
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
use crate::{SymbolTable, TypeError, TypeVariable};
|
use crate::{SymbolTable, TypeError, TypeVariable};
|
||||||
use leo_ast::{ArrayDimensions, Identifier, IntegerType, Span, Type as UnresolvedType};
|
use leo_ast::{Identifier, IntegerType, Span, Type as UnresolvedType};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
@ -33,7 +33,7 @@ pub enum Type {
|
|||||||
IntegerType(IntegerType),
|
IntegerType(IntegerType),
|
||||||
|
|
||||||
// Data type wrappers
|
// Data type wrappers
|
||||||
Array(Box<Type>, ArrayDimensions),
|
Array(Box<Type>),
|
||||||
Tuple(Vec<Type>),
|
Tuple(Vec<Type>),
|
||||||
|
|
||||||
// User defined types
|
// User defined types
|
||||||
@ -58,10 +58,10 @@ impl Type {
|
|||||||
UnresolvedType::Group => Type::Group,
|
UnresolvedType::Group => Type::Group,
|
||||||
UnresolvedType::IntegerType(integer) => Type::IntegerType(integer),
|
UnresolvedType::IntegerType(integer) => Type::IntegerType(integer),
|
||||||
|
|
||||||
UnresolvedType::Array(type_, dimensions) => {
|
UnresolvedType::Array(type_, _) => {
|
||||||
let array_type = Type::new(table, *type_, span)?;
|
let array_type = Type::new(table, *type_, span)?;
|
||||||
|
|
||||||
Type::Array(Box::new(array_type), dimensions)
|
Type::Array(Box::new(array_type))
|
||||||
}
|
}
|
||||||
UnresolvedType::Tuple(types) => {
|
UnresolvedType::Tuple(types) => {
|
||||||
let tuple_types = types
|
let tuple_types = types
|
||||||
@ -100,9 +100,9 @@ impl Type {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Self, TypeError> {
|
) -> Result<Self, TypeError> {
|
||||||
Ok(match type_ {
|
Ok(match type_ {
|
||||||
UnresolvedType::Array(type_, dimensions) => {
|
UnresolvedType::Array(type_, _) => {
|
||||||
let array_type = Type::new_from_circuit(table, *type_, circuit_name, span)?;
|
let array_type = Type::new_from_circuit(table, *type_, circuit_name, span)?;
|
||||||
Type::Array(Box::new(array_type), dimensions)
|
Type::Array(Box::new(array_type))
|
||||||
}
|
}
|
||||||
UnresolvedType::Tuple(types) => {
|
UnresolvedType::Tuple(types) => {
|
||||||
let tuple_types = types
|
let tuple_types = types
|
||||||
@ -118,73 +118,6 @@ impl Type {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns `Ok` if the given expected type is `Some` and expected type == actual type.
|
|
||||||
///
|
|
||||||
pub fn check_type(expected_option: &Option<Self>, actual: &Type, span: Span) -> Result<(), TypeError> {
|
|
||||||
if let Some(expected) = expected_option {
|
|
||||||
if expected.ne(actual) {
|
|
||||||
return Err(TypeError::mismatched_types(expected, actual, span));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns `Ok` if self is an expected integer type `Type::IntegerType`.
|
|
||||||
///
|
|
||||||
pub fn check_type_integer(&self, span: Span) -> Result<(), TypeError> {
|
|
||||||
match self {
|
|
||||||
Type::IntegerType(_) => Ok(()),
|
|
||||||
// Throw mismatched type error
|
|
||||||
type_ => Err(TypeError::invalid_integer(type_, span)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns array element type and dimensions if self is an expected array type `Type::Array`.
|
|
||||||
///
|
|
||||||
pub fn get_type_array(&self, span: Span) -> Result<(&Type, &ArrayDimensions), TypeError> {
|
|
||||||
match self {
|
|
||||||
Type::Array(element_type, dimensions) => Ok((element_type, dimensions)),
|
|
||||||
// Throw mismatched type error
|
|
||||||
type_ => Err(TypeError::invalid_array(type_, span)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns tuple element types if self is an expected tuple type `Type::Tuple`.
|
|
||||||
///
|
|
||||||
pub fn get_type_tuple(&self, span: Span) -> Result<&Vec<Type>, TypeError> {
|
|
||||||
match self {
|
|
||||||
Type::Tuple(types) => Ok(types),
|
|
||||||
// Throw mismatched type error
|
|
||||||
type_ => Err(TypeError::invalid_tuple(type_, span)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns circuit identifier if self is an expected circuit type `Type::Circuit`.
|
|
||||||
///
|
|
||||||
pub fn get_type_circuit(&self, span: Span) -> Result<&Identifier, TypeError> {
|
|
||||||
match self {
|
|
||||||
Type::Circuit(identifier) => Ok(identifier),
|
|
||||||
// Throw mismatched type error
|
|
||||||
type_ => Err(TypeError::invalid_circuit(type_, span)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns function identifier if self is an expected function type `Type::Function`.
|
|
||||||
///
|
|
||||||
pub fn get_type_function(&self, span: Span) -> Result<&Identifier, TypeError> {
|
|
||||||
match self {
|
|
||||||
Type::Function(identifier) => Ok(identifier),
|
|
||||||
// Throw mismatched type error
|
|
||||||
type_ => Err(TypeError::invalid_function(type_, span)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a list of signed integer types.
|
/// Returns a list of signed integer types.
|
||||||
pub const fn signed_integer_types() -> [Type; 5] {
|
pub const fn signed_integer_types() -> [Type; 5] {
|
||||||
[
|
[
|
||||||
@ -254,7 +187,7 @@ impl Type {
|
|||||||
*self = type_.to_owned()
|
*self = type_.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Array(self_type, _) => {
|
Type::Array(self_type) => {
|
||||||
self_type.substitute(variable, type_);
|
self_type.substitute(variable, type_);
|
||||||
}
|
}
|
||||||
Type::Tuple(types) => types
|
Type::Tuple(types) => types
|
||||||
@ -274,7 +207,7 @@ impl fmt::Display for Type {
|
|||||||
Type::Group => write!(f, "group"),
|
Type::Group => write!(f, "group"),
|
||||||
Type::IntegerType(integer_type) => write!(f, "{}", integer_type),
|
Type::IntegerType(integer_type) => write!(f, "{}", integer_type),
|
||||||
|
|
||||||
Type::Array(type_, dimensions) => write!(f, "[{}; {}]", *type_, dimensions),
|
Type::Array(type_) => write!(f, "[{}]", *type_),
|
||||||
Type::Tuple(tuple) => {
|
Type::Tuple(tuple) => {
|
||||||
let tuple_string = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
|
let tuple_string = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
|
||||||
|
|
||||||
@ -297,7 +230,7 @@ impl PartialEq for Type {
|
|||||||
(Type::Group, Type::Group) => true,
|
(Type::Group, Type::Group) => true,
|
||||||
(Type::IntegerType(integer_type1), Type::IntegerType(integer_type2)) => integer_type1.eq(integer_type2),
|
(Type::IntegerType(integer_type1), Type::IntegerType(integer_type2)) => integer_type1.eq(integer_type2),
|
||||||
|
|
||||||
(Type::Array(array1, _), Type::Array(array2, _)) => {
|
(Type::Array(array1), Type::Array(array2)) => {
|
||||||
// Get both array element types before comparison.
|
// Get both array element types before comparison.
|
||||||
let array1_element = get_array_element_type(array1);
|
let array1_element = get_array_element_type(array1);
|
||||||
let array2_element = get_array_element_type(array2);
|
let array2_element = get_array_element_type(array2);
|
||||||
@ -324,7 +257,7 @@ impl Eq for Type {}
|
|||||||
/// If the given `type_` is any other type, return the `type_`.
|
/// If the given `type_` is any other type, return the `type_`.
|
||||||
///
|
///
|
||||||
pub fn get_array_element_type(type_: &Type) -> &Type {
|
pub fn get_array_element_type(type_: &Type) -> &Type {
|
||||||
if let Type::Array(element_type, _) = type_ {
|
if let Type::Array(element_type) = type_ {
|
||||||
get_array_element_type(element_type)
|
get_array_element_type(element_type)
|
||||||
} else {
|
} else {
|
||||||
type_
|
type_
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
use crate::TypeAssertionError;
|
use crate::TypeAssertionError;
|
||||||
use leo_ast::Span;
|
use leo_ast::Span;
|
||||||
use leo_symbol_table::{get_array_element_type, Type, TypeVariable};
|
use leo_symbol_table::{get_array_element_type, Type, TypeVariable};
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
/// A type variable -> type pair.
|
/// A type variable -> type pair.
|
||||||
pub struct TypeVariablePair(TypeVariable, Type);
|
pub struct TypeVariablePair(TypeVariable, Type);
|
||||||
@ -88,9 +87,7 @@ impl TypeVariablePairs {
|
|||||||
match (left, right) {
|
match (left, right) {
|
||||||
(Type::TypeVariable(variable), type_) => Ok(self.push(variable, type_)),
|
(Type::TypeVariable(variable), type_) => Ok(self.push(variable, type_)),
|
||||||
(type_, Type::TypeVariable(variable)) => Ok(self.push(variable, type_)),
|
(type_, Type::TypeVariable(variable)) => Ok(self.push(variable, type_)),
|
||||||
(Type::Array(left_type, _), Type::Array(right_type, _)) => {
|
(Type::Array(left_type), Type::Array(right_type)) => self.push_pairs_array(*left_type, *right_type, span),
|
||||||
self.push_pairs_array(*left_type, *right_type, span)
|
|
||||||
}
|
|
||||||
(Type::Tuple(left_types), Type::Tuple(right_types)) => {
|
(Type::Tuple(left_types), Type::Tuple(right_types)) => {
|
||||||
self.push_pairs_tuple(left_types.into_iter(), right_types.into_iter(), span)
|
self.push_pairs_tuple(left_types.into_iter(), right_types.into_iter(), span)
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,15 @@ impl FrameError {
|
|||||||
Self::new_from_span(message, span)
|
Self::new_from_span(message, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Expected a usize number for the index.
|
||||||
|
///
|
||||||
|
pub fn invalid_index(actual: String, span: &Span) -> Self {
|
||||||
|
let message = format!("Expected constant number for index, found `{}`", actual);
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Attempted to call non-static member using `::`.
|
/// Attempted to call non-static member using `::`.
|
||||||
///
|
///
|
||||||
|
@ -26,6 +26,7 @@ use leo_ast::{
|
|||||||
Function,
|
Function,
|
||||||
Identifier,
|
Identifier,
|
||||||
IntegerType,
|
IntegerType,
|
||||||
|
PositiveNumber,
|
||||||
RangeOrExpression,
|
RangeOrExpression,
|
||||||
Span,
|
Span,
|
||||||
SpreadOrExpression,
|
SpreadOrExpression,
|
||||||
@ -372,7 +373,7 @@ impl Frame {
|
|||||||
for access in &assignee.accesses {
|
for access in &assignee.accesses {
|
||||||
let access_type = match access {
|
let access_type = match access {
|
||||||
AssigneeAccess::Array(r_or_e) => self.parse_array_access(type_, r_or_e, span),
|
AssigneeAccess::Array(r_or_e) => self.parse_array_access(type_, r_or_e, span),
|
||||||
AssigneeAccess::Tuple(index) => self.parse_tuple_access(type_, *index, span),
|
AssigneeAccess::Tuple(index, _) => self.parse_tuple_access(type_, &index, span),
|
||||||
AssigneeAccess::Member(identifier) => self.parse_circuit_member_access(type_, identifier, span),
|
AssigneeAccess::Member(identifier) => self.parse_circuit_member_access(type_, identifier, span),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@ -549,13 +550,18 @@ impl Frame {
|
|||||||
|
|
||||||
// Arrays
|
// Arrays
|
||||||
Expression::ArrayInline(expressions, span) => self.parse_array(expressions, span),
|
Expression::ArrayInline(expressions, span) => self.parse_array(expressions, span),
|
||||||
|
Expression::ArrayInitializer(array_w_dimensions, _span) => {
|
||||||
|
self.parse_array_initializer(&array_w_dimensions.0)
|
||||||
|
}
|
||||||
Expression::ArrayAccess(array_w_index, span) => {
|
Expression::ArrayAccess(array_w_index, span) => {
|
||||||
self.parse_expression_array_access(&array_w_index.0, &array_w_index.1, span)
|
self.parse_expression_array_access(&array_w_index.0, &array_w_index.1, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuples
|
// Tuples
|
||||||
Expression::Tuple(expressions, span) => self.parse_tuple(expressions, span),
|
Expression::Tuple(expressions, span) => self.parse_tuple(expressions, span),
|
||||||
Expression::TupleAccess(tuple, index, span) => self.parse_expression_tuple_access(tuple, *index, span),
|
Expression::TupleAccess(tuple_w_index, span) => {
|
||||||
|
self.parse_expression_tuple_access(&tuple_w_index.0, &tuple_w_index.1, span)
|
||||||
|
}
|
||||||
|
|
||||||
// Circuits
|
// Circuits
|
||||||
Expression::Circuit(identifier, members, span) => self.parse_circuit(identifier, members, span),
|
Expression::Circuit(identifier, members, span) => self.parse_circuit(identifier, members, span),
|
||||||
@ -737,7 +743,7 @@ impl Frame {
|
|||||||
fn parse_expression_tuple_access(
|
fn parse_expression_tuple_access(
|
||||||
&mut self,
|
&mut self,
|
||||||
expression: &Expression,
|
expression: &Expression,
|
||||||
index: usize,
|
index: &PositiveNumber,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<Type, FrameError> {
|
) -> Result<Type, FrameError> {
|
||||||
// Parse the tuple expression which could be a variable with type tuple.
|
// Parse the tuple expression which could be a variable with type tuple.
|
||||||
@ -750,14 +756,20 @@ impl Frame {
|
|||||||
///
|
///
|
||||||
/// Returns the type of the accessed tuple element.
|
/// Returns the type of the accessed tuple element.
|
||||||
///
|
///
|
||||||
fn parse_tuple_access(&mut self, type_: Type, index: usize, span: &Span) -> Result<Type, FrameError> {
|
fn parse_tuple_access(&mut self, type_: Type, index: &PositiveNumber, span: &Span) -> Result<Type, FrameError> {
|
||||||
// Check the type is a tuple.
|
// Check the type is a tuple.
|
||||||
let mut elements = match type_ {
|
let mut elements = match type_ {
|
||||||
Type::Tuple(elements) => elements,
|
Type::Tuple(elements) => elements,
|
||||||
type_ => return Err(FrameError::tuple_access(&type_, span)),
|
type_ => return Err(FrameError::tuple_access(&type_, span)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let element_type = elements.swap_remove(index);
|
// Parse index `String` to `usize`.
|
||||||
|
let index_usize = match index.to_string().parse::<usize>() {
|
||||||
|
Ok(index_usize) => index_usize,
|
||||||
|
Err(_) => return Err(FrameError::invalid_index(index.to_string(), span)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let element_type = elements.swap_remove(index_usize);
|
||||||
|
|
||||||
Ok(element_type)
|
Ok(element_type)
|
||||||
}
|
}
|
||||||
@ -768,12 +780,11 @@ impl Frame {
|
|||||||
fn parse_array(&mut self, expressions: &[SpreadOrExpression], span: &Span) -> Result<Type, FrameError> {
|
fn parse_array(&mut self, expressions: &[SpreadOrExpression], span: &Span) -> Result<Type, FrameError> {
|
||||||
// Store array element type.
|
// Store array element type.
|
||||||
let mut element_type = None;
|
let mut element_type = None;
|
||||||
let mut count = 0usize;
|
|
||||||
|
|
||||||
// Parse all array elements.
|
// Parse all array elements.
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
// Get the type and count of elements in each spread or expression.
|
// Get the type and count of elements in each spread or expression.
|
||||||
let (type_, element_count) = self.parse_spread_or_expression(expression, span)?;
|
let type_ = self.parse_spread_or_expression(expression, span)?;
|
||||||
|
|
||||||
// Assert that array element types are the same.
|
// Assert that array element types are the same.
|
||||||
if let Some(prev_type) = element_type {
|
if let Some(prev_type) = element_type {
|
||||||
@ -782,9 +793,6 @@ impl Frame {
|
|||||||
|
|
||||||
// Update array element type.
|
// Update array element type.
|
||||||
element_type = Some(type_);
|
element_type = Some(type_);
|
||||||
|
|
||||||
// Update number of array elements.
|
|
||||||
count += element_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an error for empty arrays.
|
// Return an error for empty arrays.
|
||||||
@ -793,43 +801,37 @@ impl Frame {
|
|||||||
None => return Err(FrameError::empty_array(span)),
|
None => return Err(FrameError::empty_array(span)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Type::Array(Box::new(type_), vec![count]))
|
Ok(Type::Array(Box::new(type_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the type of the array initializer expression.
|
||||||
|
///
|
||||||
|
fn parse_array_initializer(&mut self, array: &Expression) -> Result<Type, FrameError> {
|
||||||
|
// Get element type.
|
||||||
|
let element_type = self.parse_expression(array)?;
|
||||||
|
|
||||||
|
// Return array type.
|
||||||
|
Ok(Type::Array(Box::new(element_type)))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the type and count of elements in a spread or expression.
|
/// Returns the type and count of elements in a spread or expression.
|
||||||
///
|
///
|
||||||
fn parse_spread_or_expression(
|
fn parse_spread_or_expression(&mut self, s_or_e: &SpreadOrExpression, span: &Span) -> Result<Type, FrameError> {
|
||||||
&mut self,
|
match s_or_e {
|
||||||
s_or_e: &SpreadOrExpression,
|
|
||||||
span: &Span,
|
|
||||||
) -> Result<(Type, usize), FrameError> {
|
|
||||||
Ok(match s_or_e {
|
|
||||||
SpreadOrExpression::Spread(expression) => {
|
SpreadOrExpression::Spread(expression) => {
|
||||||
// Parse the type of the spread array expression.
|
// Parse the type of the spread array expression.
|
||||||
let array_type = self.parse_expression(expression)?;
|
let array_type = self.parse_expression(expression)?;
|
||||||
|
|
||||||
// Check that the type is an array.
|
// Check that the type is an array.
|
||||||
let (element_type, mut dimensions) = match array_type {
|
match array_type {
|
||||||
Type::Array(element_type, dimensions) => (element_type, dimensions),
|
Type::Array(element_type) => Ok(Type::Array(element_type)),
|
||||||
type_ => return Err(FrameError::invalid_spread(type_, span)),
|
type_ => Err(FrameError::invalid_spread(type_, span)),
|
||||||
};
|
}
|
||||||
|
|
||||||
// A spread copies the elements of an array.
|
|
||||||
// If the array has elements of type array, we must return a new array type with proper dimensions.
|
|
||||||
// If the array has elements of any other type, we can return the type and count directly.
|
|
||||||
let count = dimensions.pop().unwrap();
|
|
||||||
|
|
||||||
let type_ = if dimensions.is_empty() {
|
|
||||||
*element_type
|
|
||||||
} else {
|
|
||||||
Type::Array(element_type, dimensions)
|
|
||||||
};
|
|
||||||
|
|
||||||
(type_, count)
|
|
||||||
}
|
}
|
||||||
SpreadOrExpression::Expression(expression) => (self.parse_expression(expression)?, 1),
|
SpreadOrExpression::Expression(expression) => self.parse_expression(expression),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -853,8 +855,8 @@ impl Frame {
|
|||||||
///
|
///
|
||||||
fn parse_array_access(&mut self, type_: Type, r_or_e: &RangeOrExpression, span: &Span) -> Result<Type, FrameError> {
|
fn parse_array_access(&mut self, type_: Type, r_or_e: &RangeOrExpression, span: &Span) -> Result<Type, FrameError> {
|
||||||
// Check the type is an array.
|
// Check the type is an array.
|
||||||
let (element_type, _dimensions) = match type_ {
|
let element_type = match type_ {
|
||||||
Type::Array(type_, dimensions) => (type_, dimensions),
|
Type::Array(type_) => type_,
|
||||||
type_ => return Err(FrameError::array_access(&type_, span)),
|
type_ => return Err(FrameError::array_access(&type_, span)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user