Reintroduce IntegerType

This commit is contained in:
Pranav Gaddamadugu 2022-08-09 16:13:10 -07:00
parent 7ff7170c45
commit dcbdb1bd85
15 changed files with 320 additions and 320 deletions

View File

@ -14,7 +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::GroupLiteral;
use crate::{GroupLiteral, IntegerType};
use super::*;
@ -33,31 +33,13 @@ pub enum Literal {
/// A group literal, either product or affine.
/// For example, `42group` or `(12, 52)group`.
Group(Box<GroupLiteral>),
/// An integer literal, e.g., `42`.
Integer(IntegerType, String, #[serde(with = "leo_span::span_json")] Span),
/// A scalar literal, e.g. `1scalar`.
/// An unsigned number followed by the keyword `scalar`.
Scalar(String, #[serde(with = "leo_span::span_json")] Span),
/// A string literal, e.g., `"foobar"`.
String(String, #[serde(with = "leo_span::span_json")] Span),
/// An 8-bit signed integer literal, e.g., `42i8`.
I8(String, #[serde(with = "leo_span::span_json")] Span),
/// A 16-bit signed integer literal, e.g., `42i16`.
I16(String, #[serde(with = "leo_span::span_json")] Span),
/// A 32-bit signed integer literal, e.g., `42i32`.
I32(String, #[serde(with = "leo_span::span_json")] Span),
/// A 64-bit signed integer literal, e.g., `42i64`.
I64(String, #[serde(with = "leo_span::span_json")] Span),
/// A 128-bit signed integer literal, e.g., `42i128`.
I128(String, #[serde(with = "leo_span::span_json")] Span),
/// A 8-bit unsigned integer literal, e.g., `42u8`.
U8(String, #[serde(with = "leo_span::span_json")] Span),
/// A 16-bit unsigned integer literal, e.g., `42u16`.
U16(String, #[serde(with = "leo_span::span_json")] Span),
/// A 32-bit unsigned integer literal, e.g., `42u32`.
U32(String, #[serde(with = "leo_span::span_json")] Span),
/// A 64-bit unsigned integer literal, e.g., `42u64`.
U64(String, #[serde(with = "leo_span::span_json")] Span),
/// A 128-bit unsigned integer literal, e.g., `42u128`.
U128(String, #[serde(with = "leo_span::span_json")] Span),
}
impl fmt::Display for Literal {
@ -65,20 +47,11 @@ impl fmt::Display for Literal {
match &self {
Self::Address(address, _) => write!(f, "{}", address),
Self::Boolean(boolean, _) => write!(f, "{}", boolean),
Self::I8(integer, _) => write!(f, "{}i8", integer),
Self::I16(integer, _) => write!(f, "{}i16", integer),
Self::I32(integer, _) => write!(f, "{}i32", integer),
Self::I64(integer, _) => write!(f, "{}i64", integer),
Self::I128(integer, _) => write!(f, "{}i128", integer),
Self::Field(field, _) => write!(f, "{}field", field),
Self::Group(group) => write!(f, "{}group", group),
Self::Integer(type_, value, _) => write!(f, "{}{}", value, type_),
Self::Scalar(scalar, _) => write!(f, "{}scalar", scalar),
Self::String(string, _) => write!(f, "{}", string),
Self::U8(integer, _) => write!(f, "{}u8", integer),
Self::U16(integer, _) => write!(f, "{}u16", integer),
Self::U32(integer, _) => write!(f, "{}u32", integer),
Self::U64(integer, _) => write!(f, "{}u64", integer),
Self::U128(integer, _) => write!(f, "{}u128", integer),
}
}
}
@ -89,18 +62,9 @@ impl Node for Literal {
Self::Address(_, span)
| Self::Boolean(_, span)
| Self::Field(_, span)
| Self::I8(_, span)
| Self::I16(_, span)
| Self::I32(_, span)
| Self::I64(_, span)
| Self::I128(_, span)
| Self::Integer(_, _, span)
| Self::Scalar(_, span)
| Self::String(_, span)
| Self::U8(_, span)
| Self::U16(_, span)
| Self::U32(_, span)
| Self::U64(_, span)
| Self::U128(_, span) => *span,
| Self::String(_, span) => *span,
Self::Group(group) => match &**group {
GroupLiteral::Single(_, span) => *span,
GroupLiteral::Tuple(tuple) => tuple.span,
@ -113,18 +77,9 @@ impl Node for Literal {
Self::Address(_, span)
| Self::Boolean(_, span)
| Self::Field(_, span)
| Self::I8(_, span)
| Self::I16(_, span)
| Self::I32(_, span)
| Self::I64(_, span)
| Self::I128(_, span)
| Self::Integer(_, _, span)
| Self::Scalar(_, span)
| Self::String(_, span)
| Self::U8(_, span)
| Self::U16(_, span)
| Self::U32(_, span)
| Self::U64(_, span)
| Self::U128(_, span) => *span = new_span,
| Self::String(_, span) => *span = new_span,
Self::Group(group) => match &mut **group {
GroupLiteral::Single(_, span) => *span = new_span,
GroupLiteral::Tuple(tuple) => tuple.span = new_span,

View File

@ -14,7 +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::{Expression, GroupLiteral, Literal, Node, Type, UnaryOperation};
use crate::{Expression, GroupLiteral, IntegerType, Literal, Node, Type, UnaryOperation};
use leo_errors::{InputError, LeoError, Result};
use serde::{Deserialize, Serialize};
@ -26,16 +26,7 @@ pub enum InputValue {
Boolean(bool),
Field(String),
Group(GroupLiteral),
I8(String),
I16(String),
I32(String),
I64(String),
I128(String),
U8(String),
U16(String),
U32(String),
U64(String),
U128(String),
Integer(IntegerType, String),
}
impl TryFrom<(Type, Expression)> for InputValue {
@ -47,16 +38,13 @@ impl TryFrom<(Type, Expression)> for InputValue {
(Type::Boolean, Literal::Boolean(value, _)) => Self::Boolean(value),
(Type::Field, Literal::Field(value, _)) => Self::Field(value),
(Type::Group, Literal::Group(value)) => Self::Group(*value),
(Type::I8, Literal::I8(value, _)) => Self::I8(value),
(Type::I16, Literal::I16(value, _)) => Self::I16(value),
(Type::I32, Literal::I32(value, _)) => Self::I32(value),
(Type::I64, Literal::I64(value, _)) => Self::I64(value),
(Type::I128, Literal::I128(value, _)) => Self::I128(value),
(Type::U8, Literal::U8(value, _)) => Self::U8(value),
(Type::U16, Literal::U16(value, _)) => Self::U16(value),
(Type::U32, Literal::U32(value, _)) => Self::U32(value),
(Type::U64, Literal::U64(value, _)) => Self::U64(value),
(Type::U128, Literal::U128(value, _)) => Self::U128(value),
(Type::Integer(expected), Literal::Integer(actual, value, span)) => {
if expected == actual {
Self::Integer(expected, value)
} else {
return Err(InputError::unexpected_type(expected.to_string(), actual, span).into());
}
}
(x, y) => {
return Err(InputError::unexpected_type(x, &y, y.span()).into());
}
@ -76,16 +64,7 @@ impl fmt::Display for InputValue {
InputValue::Boolean(ref boolean) => write!(f, "{}", boolean),
InputValue::Group(ref group) => write!(f, "{}", group),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::I8(ref integer) => write!(f, "{}", integer),
InputValue::I16(ref integer) => write!(f, "{}", integer),
InputValue::I32(ref integer) => write!(f, "{}", integer),
InputValue::I64(ref integer) => write!(f, "{}", integer),
InputValue::I128(ref integer) => write!(f, "{}", integer),
InputValue::U8(ref integer) => write!(f, "{}", integer),
InputValue::U16(ref integer) => write!(f, "{}", integer),
InputValue::U32(ref integer) => write!(f, "{}", integer),
InputValue::U64(ref integer) => write!(f, "{}", integer),
InputValue::U128(ref integer) => write!(f, "{}", integer),
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
}
}
}

View File

@ -0,0 +1,78 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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_span::{sym, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
/// Explicit integer type.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum IntegerType {
U8,
U16,
U32,
U64,
U128,
I8,
I16,
I32,
I64,
I128,
}
impl IntegerType {
/// Is the integer type a signed one?
pub fn is_signed(&self) -> bool {
use IntegerType::*;
matches!(self, I8 | I16 | I32 | I64 | I128)
}
/// Returns the symbol for the integer type.
pub fn symbol(self) -> Symbol {
match self {
Self::I8 => sym::i8,
Self::I16 => sym::i16,
Self::I32 => sym::i32,
Self::I64 => sym::i64,
Self::I128 => sym::i128,
Self::U8 => sym::u8,
Self::U16 => sym::u16,
Self::U32 => sym::u32,
Self::U64 => sym::u64,
Self::U128 => sym::u128,
}
}
}
impl fmt::Display for IntegerType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
IntegerType::U8 => write!(f, "u8"),
IntegerType::U16 => write!(f, "u16"),
IntegerType::U32 => write!(f, "u32"),
IntegerType::U64 => write!(f, "u64"),
IntegerType::U128 => write!(f, "u128"),
IntegerType::I8 => write!(f, "i8"),
IntegerType::I16 => write!(f, "i16"),
IntegerType::I32 => write!(f, "i32"),
IntegerType::I64 => write!(f, "i64"),
IntegerType::I128 => write!(f, "i128"),
}
}
}

View File

@ -14,6 +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/>.
pub mod integer_type;
pub use integer_type::*;
pub mod tuple;
pub use tuple::*;

View File

@ -14,7 +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::{Identifier, Tuple};
use crate::{Identifier, IntegerType, Tuple};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -31,35 +31,16 @@ pub enum Type {
Field,
/// The `group` type.
Group,
/// The 8-bit signed integer type.
I8,
/// The 16-bit signed integer type.
I16,
/// The 32-bit signed integer type.
I32,
/// The 64-bit signed integer type.
I64,
/// The 128-bit signed integer type.
I128,
/// A reference to a built in type.
Identifier(Identifier),
/// An integer type.
Integer(IntegerType),
/// The `scalar` type.
Scalar,
/// The `string` type.
String,
/// The 8-bit unsigned integer type.
U8,
/// The 16-bit unsigned integer type.
U16,
/// The 32-bit unsigned integer type.
U32,
/// The 64-bit unsigned integer type.
U64,
/// The 128-bit unsigned integer type.
U128,
/// A static tuple of at least one type.
Tuple(Tuple),
/// Placeholder for a type that could not be resolved or was not well-formed.
/// Will eventually lead to a compile error.
Err,
@ -77,18 +58,9 @@ impl Type {
| (Type::Boolean, Type::Boolean)
| (Type::Field, Type::Field)
| (Type::Group, Type::Group)
| (Type::I8, Type::I8)
| (Type::I16, Type::I16)
| (Type::I32, Type::I32)
| (Type::I64, Type::I64)
| (Type::I128, Type::I128)
| (Type::Scalar, Type::Scalar)
| (Type::String, Type::String)
| (Type::U8, Type::U8)
| (Type::U16, Type::U16)
| (Type::U32, Type::U32)
| (Type::U64, Type::U64)
| (Type::U128, Type::U128) => true,
| (Type::String, Type::String) => true,
(Type::Integer(left), Type::Integer(right)) => left.eq(right),
(Type::Tuple(left), Type::Tuple(right)) => left
.iter()
.zip(right.iter())
@ -106,19 +78,10 @@ impl fmt::Display for Type {
Type::Boolean => write!(f, "boolean"),
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::I8 => write!(f, "i8"),
Type::I16 => write!(f, "i16"),
Type::I32 => write!(f, "i32"),
Type::I64 => write!(f, "i64"),
Type::I128 => write!(f, "i128"),
Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
Type::Integer(ref integer_type) => write!(f, "{}", integer_type),
Type::Scalar => write!(f, "scalar"),
Type::String => write!(f, "string"),
Type::U8 => write!(f, "u8"),
Type::U16 => write!(f, "u16"),
Type::U32 => write!(f, "u32"),
Type::U64 => write!(f, "u64"),
Type::U128 => write!(f, "u128"),
Type::Tuple(ref tuple) => write!(f, "{}", tuple),
Type::Err => write!(f, "error"),
}

View File

@ -14,7 +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::{GroupLiteral, Identifier, Literal, Type};
use crate::{GroupLiteral, Identifier, IntegerType, Literal, Type};
use leo_errors::{type_name, FlattenError, LeoError, Result};
use leo_span::{Span, Symbol};
@ -848,16 +848,16 @@ impl From<&Value> for Type {
Circuit(ident, _) => Type::Identifier(*ident),
Field(_, _) => Type::Field,
Group(_) => Type::Group,
I8(_, _) => Type::I8,
I16(_, _) => Type::I16,
I32(_, _) => Type::I32,
I64(_, _) => Type::I64,
I128(_, _) => Type::I128,
U8(_, _) => Type::U8,
U16(_, _) => Type::U16,
U32(_, _) => Type::U32,
U64(_, _) => Type::U64,
U128(_, _) => Type::U128,
I8(_, _) => Type::Integer(IntegerType::I8),
I16(_, _) => Type::Integer(IntegerType::I16),
I32(_, _) => Type::Integer(IntegerType::I32),
I64(_, _) => Type::Integer(IntegerType::I64),
I128(_, _) => Type::Integer(IntegerType::I128),
U8(_, _) => Type::Integer(IntegerType::U8),
U16(_, _) => Type::Integer(IntegerType::U16),
U32(_, _) => Type::Integer(IntegerType::U32),
U64(_, _) => Type::Integer(IntegerType::U64),
U128(_, _) => Type::Integer(IntegerType::U128),
Scalar(_, _) => Type::Scalar,
String(_, _) => Type::String,
}
@ -876,16 +876,18 @@ impl From<&Literal> for Value {
Literal::Group(group_literal) => Self::Group(group_literal.clone()),
Literal::Scalar(string, span) => Self::Scalar(string.clone(), *span),
Literal::String(string, span) => Self::String(string.clone(), *span),
Literal::I8(string, span) => Self::I8(string.parse::<i8>().unwrap(), *span),
Literal::I16(string, span) => Self::I16(string.parse::<i16>().unwrap(), *span),
Literal::I32(string, span) => Self::I32(string.parse::<i32>().unwrap(), *span),
Literal::I64(string, span) => Self::I64(string.parse::<i64>().unwrap(), *span),
Literal::I128(string, span) => Self::I128(string.parse::<i128>().unwrap(), *span),
Literal::U8(string, span) => Self::U8(string.parse::<u8>().unwrap(), *span),
Literal::U16(string, span) => Self::U16(string.parse::<u16>().unwrap(), *span),
Literal::U32(string, span) => Self::U32(string.parse::<u32>().unwrap(), *span),
Literal::U64(string, span) => Self::U64(string.parse::<u64>().unwrap(), *span),
Literal::U128(string, span) => Self::U128(string.parse::<u128>().unwrap(), *span),
Literal::Integer(integer_type, string, span) => match integer_type {
IntegerType::U8 => Self::U8(string.parse().unwrap(), *span),
IntegerType::U16 => Self::U16(string.parse().unwrap(), *span),
IntegerType::U32 => Self::U32(string.parse().unwrap(), *span),
IntegerType::U64 => Self::U64(string.parse().unwrap(), *span),
IntegerType::U128 => Self::U128(string.parse().unwrap(), *span),
IntegerType::I8 => Self::I8(string.parse().unwrap(), *span),
IntegerType::I16 => Self::I16(string.parse().unwrap(), *span),
IntegerType::I32 => Self::I32(string.parse().unwrap(), *span),
IntegerType::I64 => Self::I64(string.parse().unwrap(), *span),
IntegerType::I128 => Self::I128(string.parse().unwrap(), *span),
},
}
}
}
@ -900,16 +902,16 @@ impl From<Value> for Literal {
Circuit(_ident, _values) => todo!("We need to test if this is hittable"),
Field(v, span) => Literal::Field(v, span),
Group(v) => Literal::Group(v),
I8(v, span) => Literal::I8(v.to_string(), span),
I16(v, span) => Literal::I16(v.to_string(), span),
I32(v, span) => Literal::I32(v.to_string(), span),
I64(v, span) => Literal::I64(v.to_string(), span),
I128(v, span) => Literal::I128(v.to_string(), span),
U8(v, span) => Literal::U8(v.to_string(), span),
U16(v, span) => Literal::U16(v.to_string(), span),
U32(v, span) => Literal::U32(v.to_string(), span),
U64(v, span) => Literal::U64(v.to_string(), span),
U128(v, span) => Literal::U128(v.to_string(), span),
I8(v, span) => Literal::Integer(IntegerType::I8, v.to_string(), span),
I16(v, span) => Literal::Integer(IntegerType::I16, v.to_string(), span),
I32(v, span) => Literal::Integer(IntegerType::I32, v.to_string(), span),
I64(v, span) => Literal::Integer(IntegerType::I64, v.to_string(), span),
I128(v, span) => Literal::Integer(IntegerType::I128, v.to_string(), span),
U8(v, span) => Literal::Integer(IntegerType::U8, v.to_string(), span),
U16(v, span) => Literal::Integer(IntegerType::U16, v.to_string(), span),
U32(v, span) => Literal::Integer(IntegerType::U32, v.to_string(), span),
U64(v, span) => Literal::Integer(IntegerType::U64, v.to_string(), span),
U128(v, span) => Literal::Integer(IntegerType::U128, v.to_string(), span),
Scalar(v, span) => Literal::Scalar(v, span),
String(v, span) => Literal::String(v, span),
}

View File

@ -22,7 +22,7 @@ pub use pedersen::*;
mod poseidon;
pub use poseidon::*;
use leo_ast::Type;
use leo_ast::{IntegerType, Type};
use leo_span::{sym, Symbol};
/// A core instruction that maps directly to an AVM bytecode instruction.
@ -188,44 +188,44 @@ const ALL_TYPES: [Type; 16] = [
Type::Boolean,
Type::Field,
Type::Group,
Type::I8,
Type::I16,
Type::I32,
Type::I64,
Type::I128,
Type::U8,
Type::U16,
Type::U32,
Type::U64,
Type::U128,
Type::Integer(IntegerType::I8),
Type::Integer(IntegerType::I16),
Type::Integer(IntegerType::I32),
Type::Integer(IntegerType::I64),
Type::Integer(IntegerType::I128),
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
Type::Integer(IntegerType::U64),
Type::Integer(IntegerType::U128),
Type::Scalar,
Type::String,
];
const BOOL_INT_STRING_TYPES: [Type; 12] = [
Type::Boolean,
Type::I8,
Type::I16,
Type::I32,
Type::I64,
Type::I128,
Type::U8,
Type::U16,
Type::U32,
Type::U64,
Type::U128,
Type::Integer(IntegerType::I8),
Type::Integer(IntegerType::I16),
Type::Integer(IntegerType::I32),
Type::Integer(IntegerType::I64),
Type::Integer(IntegerType::I128),
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
Type::Integer(IntegerType::U64),
Type::Integer(IntegerType::U128),
Type::String,
];
const BOOL_INT64_STRING_TYPES: [Type; 10] = [
Type::Boolean,
Type::I8,
Type::I16,
Type::I32,
Type::I64,
Type::U8,
Type::U16,
Type::U32,
Type::U64,
Type::Integer(IntegerType::I8),
Type::Integer(IntegerType::I16),
Type::Integer(IntegerType::I32),
Type::Integer(IntegerType::I64),
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
Type::Integer(IntegerType::U64),
Type::String,
];

View File

@ -260,22 +260,10 @@ impl ParserContext<'_> {
// If the unary operation is a negate, and the inner expression is a signed integer literal,
// then produce a negative integer literal.
// This helps handle a special case where -128i8, treated as a unary expression, overflows, but -128i8, treated as an integer literal doesn't.
Expression::Literal(Literal::I8(string, span)) if op == UnaryOperation::Negate && inner_is_integer => {
Expression::Literal(Literal::I8(format!("-{}", string), op_span + span))
}
Expression::Literal(Literal::I16(string, span)) if op == UnaryOperation::Negate && inner_is_integer => {
Expression::Literal(Literal::I16(format!("-{}", string), op_span + span))
}
Expression::Literal(Literal::I32(string, span)) if op == UnaryOperation::Negate && inner_is_integer => {
Expression::Literal(Literal::I32(format!("-{}", string), op_span + span))
}
Expression::Literal(Literal::I64(string, span)) if op == UnaryOperation::Negate && inner_is_integer => {
Expression::Literal(Literal::I64(format!("-{}", string), op_span + span))
}
Expression::Literal(Literal::I128(string, span))
Expression::Literal(Literal::Integer(integer_type, string, span))
if op == UnaryOperation::Negate && inner_is_integer =>
{
Expression::Literal(Literal::I128(format!("-{}", string), op_span + span))
Expression::Literal(Literal::Integer(integer_type, format!("-{}", string), op_span + span))
}
// Otherwise, produce a unary expression.
_ => Expression::Unary(UnaryExpression {
@ -563,19 +551,8 @@ impl ParserContext<'_> {
// Literal followed by other type suffix, e.g., `42u8`.
Some(suffix) => {
assert_no_whitespace(&suffix.to_string())?;
match suffix {
Token::I8 => Expression::Literal(Literal::I8(value, full_span)),
Token::I16 => Expression::Literal(Literal::I16(value, full_span)),
Token::I32 => Expression::Literal(Literal::I32(value, full_span)),
Token::I64 => Expression::Literal(Literal::I64(value, full_span)),
Token::I128 => Expression::Literal(Literal::I128(value, full_span)),
Token::U8 => Expression::Literal(Literal::U8(value, full_span)),
Token::U16 => Expression::Literal(Literal::U16(value, full_span)),
Token::U32 => Expression::Literal(Literal::U32(value, full_span)),
Token::U64 => Expression::Literal(Literal::U64(value, full_span)),
Token::U128 => Expression::Literal(Literal::U128(value, full_span)),
_ => return Err(ParserError::unexpected_token("Expected integer type suffix", span).into()),
}
let int_ty = Self::token_to_int_type(suffix).expect("unknown int type token");
Expression::Literal(Literal::Integer(int_ty, value, full_span))
}
None => return Err(ParserError::implicit_values_not_allowed(value, span).into()),
}

View File

@ -16,7 +16,7 @@
use super::*;
use leo_errors::{ParserError, Result};
use leo_errors::Result;
pub(super) const TYPE_TOKENS: &[Token] = &[
Token::Address,
@ -38,29 +38,39 @@ pub(super) const TYPE_TOKENS: &[Token] = &[
];
impl ParserContext<'_> {
/// Returns a [`IntegerType`] AST node if the given token is a supported integer type, or [`None`].
pub(super) fn token_to_int_type(token: &Token) -> Option<IntegerType> {
Some(match token {
Token::I8 => IntegerType::I8,
Token::I16 => IntegerType::I16,
Token::I32 => IntegerType::I32,
Token::I64 => IntegerType::I64,
Token::I128 => IntegerType::I128,
Token::U8 => IntegerType::U8,
Token::U16 => IntegerType::U16,
Token::U32 => IntegerType::U32,
Token::U64 => IntegerType::U64,
Token::U128 => IntegerType::U128,
_ => return None,
})
}
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a primitive type.
/// Also returns the span of the parsed token.
pub fn parse_primitive_type(&mut self) -> Result<(Type, Span)> {
let span = self.expect_any(TYPE_TOKENS)?;
match &self.prev_token.token {
Token::Address => Ok((Type::Address, span)),
Token::Bool => Ok((Type::Boolean, span)),
Token::Field => Ok((Type::Field, span)),
Token::Group => Ok((Type::Group, span)),
Token::I8 => Ok((Type::I8, span)),
Token::I16 => Ok((Type::I16, span)),
Token::I32 => Ok((Type::I32, span)),
Token::I64 => Ok((Type::I64, span)),
Token::I128 => Ok((Type::I128, span)),
Token::Scalar => Ok((Type::Scalar, span)),
Token::String => Ok((Type::String, span)),
Token::U8 => Ok((Type::U8, span)),
Token::U16 => Ok((Type::U16, span)),
Token::U32 => Ok((Type::U32, span)),
Token::U64 => Ok((Type::U64, span)),
Token::U128 => Ok((Type::U128, span)),
_ => Err(ParserError::unexpected_token("Expected a primitive type.", span).into()),
}
Ok((
match &self.prev_token.token {
Token::Address => Type::Address,
Token::Bool => Type::Boolean,
Token::Field => Type::Field,
Token::Group => Type::Group,
Token::Scalar => Type::Scalar,
Token::String => Type::String,
x => Type::Integer(Self::token_to_int_type(x).expect("invalid int type")),
},
span,
))
}
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.

View File

@ -28,16 +28,7 @@ impl<'a> CodeGenerator<'a> {
| Type::Group
| Type::Scalar
| Type::String
| Type::I8
| Type::I16
| Type::I32
| Type::I64
| Type::I128
| Type::U8
| Type::U16
| Type::U32
| Type::U64
| Type::U128 => format!("{}", input),
| Type::Integer(..) => format!("{}", input),
Type::Identifier(ident) => {
if let Some((_, type_)) = self.composite_mapping.get(&ident.name) {
format!("{}.{}", ident.to_string().to_lowercase(), type_)

View File

@ -51,16 +51,20 @@ impl StatementReconstructor for Unroller<'_> {
input.stop_value.clone().into_inner(),
) {
(Some(start), Some(stop)) => match (Type::from(&start), Type::from(&stop)) {
(Type::I8, Type::I8)
| (Type::I16, Type::I16)
| (Type::I32, Type::I32)
| (Type::I64, Type::I64)
| (Type::I128, Type::I128) => self.unroll_iteration_statement::<i128>(input, start, stop),
(Type::U8, Type::U8)
| (Type::U16, Type::U16)
| (Type::U32, Type::U32)
| (Type::U64, Type::U64)
| (Type::U128, Type::U128) => self.unroll_iteration_statement::<u128>(input, start, stop),
(Type::Integer(IntegerType::I8), Type::Integer(IntegerType::I8))
| (Type::Integer(IntegerType::I16), Type::Integer(IntegerType::I16))
| (Type::Integer(IntegerType::I32), Type::Integer(IntegerType::I32))
| (Type::Integer(IntegerType::I64), Type::Integer(IntegerType::I64))
| (Type::Integer(IntegerType::I128), Type::Integer(IntegerType::I128)) => {
self.unroll_iteration_statement::<i128>(input, start, stop)
}
(Type::Integer(IntegerType::U8), Type::Integer(IntegerType::U8))
| (Type::Integer(IntegerType::U16), Type::Integer(IntegerType::U16))
| (Type::Integer(IntegerType::U32), Type::Integer(IntegerType::U32))
| (Type::Integer(IntegerType::U64), Type::Integer(IntegerType::U64))
| (Type::Integer(IntegerType::U128), Type::Integer(IntegerType::U128)) => {
self.unroll_iteration_statement::<u128>(input, start, stop)
}
_ => unreachable!("Type checking ensures that `start` and `stop` have the same type."),
},
// If both loop bounds are not constant, then the loop is not unrolled.

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{
Block, DeclarationType, DefinitionStatement, Expression, IterationStatement, Literal, Statement,
Block, DeclarationType, DefinitionStatement, Expression, IntegerType, IterationStatement, Literal, Statement,
StatementReconstructor, Type, Value,
};
use std::cell::RefCell;
@ -149,16 +149,36 @@ impl<'a> Unroller<'a> {
// Reconstruct `iteration_count` as a `Literal`.
let value = match input.type_ {
Type::I8 => Literal::I8(iteration_count.to_string(), Default::default()),
Type::I16 => Literal::I16(iteration_count.to_string(), Default::default()),
Type::I32 => Literal::I32(iteration_count.to_string(), Default::default()),
Type::I64 => Literal::I64(iteration_count.to_string(), Default::default()),
Type::I128 => Literal::I128(iteration_count.to_string(), Default::default()),
Type::U8 => Literal::U8(iteration_count.to_string(), Default::default()),
Type::U16 => Literal::U16(iteration_count.to_string(), Default::default()),
Type::U32 => Literal::U32(iteration_count.to_string(), Default::default()),
Type::U64 => Literal::U64(iteration_count.to_string(), Default::default()),
Type::U128 => Literal::U128(iteration_count.to_string(), Default::default()),
Type::Integer(IntegerType::I8) => {
Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::I16) => {
Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::I32) => {
Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::I64) => {
Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::I128) => {
Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::U8) => {
Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::U16) => {
Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::U32) => {
Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::U64) => {
Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default())
}
Type::Integer(IntegerType::U128) => {
Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default())
}
_ => unreachable!(
"The iteration variable must be an integer type. This should be enforced by type checking."
),

View File

@ -480,46 +480,48 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
Literal::Address(_, _) => self.assert_and_return_type(Type::Address, expected, input.span()),
Literal::Boolean(_, _) => self.assert_and_return_type(Type::Boolean, expected, input.span()),
Literal::Field(_, _) => self.assert_and_return_type(Type::Field, expected, input.span()),
Literal::I8(string, _) => {
parse_integer_literal::<i8>(self.handler, string, input.span(), "i8");
self.assert_and_return_type(Type::I8, expected, input.span())
}
Literal::I16(string, _) => {
parse_integer_literal::<i16>(self.handler, string, input.span(), "i16");
self.assert_and_return_type(Type::I16, expected, input.span())
}
Literal::I32(string, _) => {
parse_integer_literal::<i32>(self.handler, string, input.span(), "i32");
self.assert_and_return_type(Type::I32, expected, input.span())
}
Literal::I64(string, _) => {
parse_integer_literal::<i64>(self.handler, string, input.span(), "i64");
self.assert_and_return_type(Type::I64, expected, input.span())
}
Literal::I128(string, _) => {
parse_integer_literal::<i128>(self.handler, string, input.span(), "i128");
self.assert_and_return_type(Type::I128, expected, input.span())
}
Literal::U8(string, _) => {
parse_integer_literal::<u8>(self.handler, string, input.span(), "u8");
self.assert_and_return_type(Type::U8, expected, input.span())
}
Literal::U16(string, _) => {
parse_integer_literal::<u16>(self.handler, string, input.span(), "u16");
self.assert_and_return_type(Type::U16, expected, input.span())
}
Literal::U32(string, _) => {
parse_integer_literal::<u32>(self.handler, string, input.span(), "u32");
self.assert_and_return_type(Type::U32, expected, input.span())
}
Literal::U64(string, _) => {
parse_integer_literal::<u64>(self.handler, string, input.span(), "u64");
self.assert_and_return_type(Type::U64, expected, input.span())
}
Literal::U128(string, _) => {
parse_integer_literal::<u128>(self.handler, string, input.span(), "u128");
self.assert_and_return_type(Type::U128, expected, input.span())
}
Literal::Integer(integer_type, string, _) => match integer_type {
IntegerType::U8 => {
parse_integer_literal::<u8>(self.handler, string, input.span(), "u8");
self.assert_and_return_type(Type::Integer(IntegerType::U8), expected, input.span())
}
IntegerType::U16 => {
parse_integer_literal::<u16>(self.handler, string, input.span(), "u16");
self.assert_and_return_type(Type::Integer(IntegerType::U16), expected, input.span())
}
IntegerType::U32 => {
parse_integer_literal::<u32>(self.handler, string, input.span(), "u32");
self.assert_and_return_type(Type::Integer(IntegerType::U32), expected, input.span())
}
IntegerType::U64 => {
parse_integer_literal::<u64>(self.handler, string, input.span(), "u64");
self.assert_and_return_type(Type::Integer(IntegerType::U64), expected, input.span())
}
IntegerType::U128 => {
parse_integer_literal::<u128>(self.handler, string, input.span(), "u128");
self.assert_and_return_type(Type::Integer(IntegerType::U128), expected, input.span())
}
IntegerType::I8 => {
parse_integer_literal::<i8>(self.handler, string, input.span(), "i8");
self.assert_and_return_type(Type::Integer(IntegerType::I8), expected, input.span())
}
IntegerType::I16 => {
parse_integer_literal::<i16>(self.handler, string, input.span(), "i16");
self.assert_and_return_type(Type::Integer(IntegerType::I16), expected, input.span())
}
IntegerType::I32 => {
parse_integer_literal::<i32>(self.handler, string, input.span(), "i32");
self.assert_and_return_type(Type::Integer(IntegerType::I32), expected, input.span())
}
IntegerType::I64 => {
parse_integer_literal::<i64>(self.handler, string, input.span(), "i64");
self.assert_and_return_type(Type::Integer(IntegerType::I64), expected, input.span())
}
IntegerType::I128 => {
parse_integer_literal::<i128>(self.handler, string, input.span(), "i128");
self.assert_and_return_type(Type::Integer(IntegerType::I128), expected, input.span())
}
},
Literal::Group(_) => self.assert_and_return_type(Type::Group, expected, input.span()),
Literal::Scalar(_, _) => self.assert_and_return_type(Type::Scalar, expected, input.span()),
Literal::String(_, _) => self.assert_and_return_type(Type::String, expected, input.span()),

View File

@ -120,7 +120,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
}
};
check_has_field(sym::owner, Type::Address);
check_has_field(sym::gates, Type::U64);
check_has_field(sym::gates, Type::Integer(IntegerType::U64));
}
// Ensure there are no tuple typed members.

View File

@ -16,7 +16,7 @@
use crate::SymbolTable;
use leo_ast::{Identifier, Node, Type};
use leo_ast::{Identifier, IntegerType, Node, Type};
use leo_core::*;
use leo_errors::{emitter::Handler, TypeCheckerError};
use leo_span::{Span, Symbol};
@ -43,23 +43,39 @@ const GROUP_TYPE: Type = Type::Group;
const SCALAR_TYPE: Type = Type::Scalar;
const INT_TYPES: [Type; 10] = [
Type::I8,
Type::I16,
Type::I32,
Type::I64,
Type::I128,
Type::U8,
Type::U16,
Type::U32,
Type::U64,
Type::U128,
Type::Integer(IntegerType::I8),
Type::Integer(IntegerType::I16),
Type::Integer(IntegerType::I32),
Type::Integer(IntegerType::I64),
Type::Integer(IntegerType::I128),
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
Type::Integer(IntegerType::U64),
Type::Integer(IntegerType::U128),
];
const SIGNED_INT_TYPES: [Type; 5] = [Type::I8, Type::I16, Type::I32, Type::I64, Type::I128];
const SIGNED_INT_TYPES: [Type; 5] = [
Type::Integer(IntegerType::I8),
Type::Integer(IntegerType::I16),
Type::Integer(IntegerType::I32),
Type::Integer(IntegerType::I64),
Type::Integer(IntegerType::I128),
];
const UNSIGNED_INT_TYPES: [Type; 5] = [Type::U8, Type::U16, Type::U32, Type::U64, Type::U128];
const UNSIGNED_INT_TYPES: [Type; 5] = [
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
Type::Integer(IntegerType::U64),
Type::Integer(IntegerType::U128),
];
const MAGNITUDE_TYPES: [Type; 3] = [Type::U8, Type::U16, Type::U32];
const MAGNITUDE_TYPES: [Type; 3] = [
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
];
impl<'a> TypeChecker<'a> {
/// Returns a new type checker given a symbol table and error handler.