diff --git a/asg/src/const_value.rs b/asg/src/const_value.rs index 6f453839e1..fd0d48414a 100644 --- a/asg/src/const_value.rs +++ b/asg/src/const_value.rs @@ -109,6 +109,7 @@ pub enum ConstValue { Field(BigInt), Address(StrTendril), Boolean(bool), + Char(char), // compounds Tuple(Vec), @@ -302,6 +303,7 @@ impl ConstValue { ConstValue::Field(_) => Type::Field, ConstValue::Address(_) => Type::Address, ConstValue::Boolean(_) => Type::Boolean, + ConstValue::Char(_) => Type::Char, ConstValue::Tuple(sub_consts) => { Type::Tuple(sub_consts.iter().map(|x| x.get_type()).collect::>>()?) } diff --git a/asg/src/error/mod.rs b/asg/src/error/mod.rs index 7e2170b2d3..8b3eccc9d1 100644 --- a/asg/src/error/mod.rs +++ b/asg/src/error/mod.rs @@ -247,6 +247,10 @@ impl AsgConvertError { Self::new_from_span(format!("failed to parse boolean value '{}'", value), span) } + pub fn invalid_char(value: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to parse char value '{}'", value), span) + } + pub fn invalid_int(value: &str, span: &Span) -> Self { Self::new_from_span(format!("failed to parse int value '{}'", value), span) } diff --git a/asg/src/expression/constant.rs b/asg/src/expression/constant.rs index 2f30d672dc..52f6cea11f 100644 --- a/asg/src/expression/constant.rs +++ b/asg/src/expression/constant.rs @@ -118,6 +118,23 @@ impl<'a> FromAst<'a, leo_ast::ValueExpression> for Constant<'a> { ), } } + Char(value, span) => { + match expected_type.map(PartialType::full).flatten() { + Some(Type::Char) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Char.to_string()), + span, + )); + } + } + Constant { + parent: Cell::new(None), + span: Some(span.clone()), + value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_char(&value, span))?), + } + } Field(value, span) => { match expected_type.map(PartialType::full).flatten() { Some(Type::Field) | None => (), @@ -215,6 +232,9 @@ impl<'a> Into for &Constant<'a> { ConstValue::Boolean(value) => { leo_ast::ValueExpression::Boolean(value.to_string().into(), self.span.clone().unwrap_or_default()) } + ConstValue::Char(value) => { + leo_ast::ValueExpression::Char(value.to_string().into(), self.span.clone().unwrap_or_default()) + } ConstValue::Field(value) => { leo_ast::ValueExpression::Field(value.to_string().into(), self.span.clone().unwrap_or_default()) } diff --git a/asg/src/scope.rs b/asg/src/scope.rs index 1c4bcb98ca..0582aa13c0 100644 --- a/asg/src/scope.rs +++ b/asg/src/scope.rs @@ -178,6 +178,7 @@ impl<'a> Scope<'a> { Ok(match type_ { Address => Type::Address, Boolean => Type::Boolean, + Char => Type::Char, Field => Type::Field, Group => Type::Group, IntegerType(int_type) => Type::Integer(int_type.clone()), diff --git a/asg/src/type_.rs b/asg/src/type_.rs index b578f0d9b8..268eb65730 100644 --- a/asg/src/type_.rs +++ b/asg/src/type_.rs @@ -25,6 +25,7 @@ pub enum Type<'a> { // Data types Address, Boolean, + Char, Field, Group, Integer(IntegerType), @@ -134,6 +135,7 @@ impl<'a> fmt::Display for Type<'a> { match self { Type::Address => write!(f, "address"), Type::Boolean => write!(f, "bool"), + Type::Char => write!(f, "char"), Type::Field => write!(f, "field"), Type::Group => write!(f, "group"), Type::Integer(sub_type) => sub_type.fmt(f), @@ -199,6 +201,7 @@ impl<'a> Into for &Type<'a> { match self { Address => leo_ast::Type::Address, Boolean => leo_ast::Type::Boolean, + Char => leo_ast::Type::Char, Field => leo_ast::Type::Field, Group => leo_ast::Type::Group, Integer(int_type) => leo_ast::Type::IntegerType(int_type.clone()), diff --git a/ast/src/expression/value.rs b/ast/src/expression/value.rs index 9b3ceda943..14bd2ca687 100644 --- a/ast/src/expression/value.rs +++ b/ast/src/expression/value.rs @@ -24,6 +24,7 @@ pub enum ValueExpression { // todo: deserialize values here Address(#[serde(with = "crate::common::tendril_json")] StrTendril, Span), Boolean(#[serde(with = "crate::common::tendril_json")] StrTendril, Span), + Char(#[serde(with = "crate::common::tendril_json")] StrTendril, Span), Field(#[serde(with = "crate::common::tendril_json")] StrTendril, Span), Group(Box), Implicit(#[serde(with = "crate::common::tendril_json")] StrTendril, Span), @@ -40,6 +41,7 @@ impl fmt::Display for ValueExpression { match &self { Address(address, _) => write!(f, "{}", address), Boolean(boolean, _) => write!(f, "{}", boolean), + Char(character, _) => write!(f, "{}", character), Field(field, _) => write!(f, "{}", field), Implicit(implicit, _) => write!(f, "{}", implicit), Integer(value, type_, _) => write!(f, "{}{}", value, type_), @@ -52,7 +54,12 @@ impl Node for ValueExpression { fn span(&self) -> &Span { use ValueExpression::*; match &self { - Address(_, span) | Boolean(_, span) | Field(_, span) | Implicit(_, span) | Integer(_, _, span) => span, + Address(_, span) + | Boolean(_, span) + | Char(_, span) + | Field(_, span) + | Implicit(_, span) + | Integer(_, _, span) => span, Group(group) => match &**group { GroupValue::Single(_, span) | GroupValue::Tuple(GroupTuple { span, .. }) => span, }, @@ -62,9 +69,12 @@ impl Node for ValueExpression { fn set_span(&mut self, new_span: Span) { use ValueExpression::*; match self { - Address(_, span) | Boolean(_, span) | Field(_, span) | Implicit(_, span) | Integer(_, _, span) => { - *span = new_span - } + Address(_, span) + | Boolean(_, span) + | Char(_, span) + | Field(_, span) + | Implicit(_, span) + | Integer(_, _, span) => *span = new_span, Group(group) => match &mut **group { GroupValue::Single(_, span) | GroupValue::Tuple(GroupTuple { span, .. }) => *span = new_span, }, diff --git a/ast/src/input/input_value.rs b/ast/src/input/input_value.rs index daa4194dc9..12b6407f7d 100644 --- a/ast/src/input/input_value.rs +++ b/ast/src/input/input_value.rs @@ -69,6 +69,7 @@ impl InputValue { match data_type { DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)), DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)), + DataType::Char(_) => Err(InputParserError::implicit_type(data_type, implicit)), DataType::Integer(integer_type) => Ok(InputValue::from_number(integer_type, implicit.to_string())), DataType::Group(_) => Err(InputParserError::implicit_group(implicit)), DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())), diff --git a/ast/src/types/type_.rs b/ast/src/types/type_.rs index f919ce8df2..fb4ad87522 100644 --- a/ast/src/types/type_.rs +++ b/ast/src/types/type_.rs @@ -31,6 +31,7 @@ pub enum Type { // Data types Address, Boolean, + Char, Field, Group, IntegerType(IntegerType), @@ -66,6 +67,7 @@ impl Type { match (self, other) { (Type::Address, Type::Address) => true, (Type::Boolean, Type::Boolean) => true, + (Type::Char, Type::Char) => true, (Type::Field, Type::Field) => true, (Type::Group, Type::Group) => true, (Type::IntegerType(left), Type::IntegerType(right)) => left.eq(&right), @@ -108,6 +110,7 @@ impl From for Type { match data_type { InputDataType::Address(_type) => Type::Address, InputDataType::Boolean(_type) => Type::Boolean, + InputDataType::Char(_type) => Type::Char, InputDataType::Field(_type) => Type::Field, InputDataType::Group(_type) => Type::Group, InputDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)), @@ -147,6 +150,7 @@ impl fmt::Display for Type { match *self { Type::Address => write!(f, "address"), Type::Boolean => write!(f, "bool"), + Type::Char => write!(f, "char"), Type::Field => write!(f, "field"), Type::Group => write!(f, "group"), Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type), diff --git a/compiler/src/expression/expression.rs b/compiler/src/expression/expression.rs index 14e31b4883..b415df644d 100644 --- a/compiler/src/expression/expression.rs +++ b/compiler/src/expression/expression.rs @@ -43,6 +43,9 @@ impl<'a, F: PrimeField, G: GroupType> ConstrainedProgram<'a, F, G> { Ok(match value { ConstValue::Address(value) => ConstrainedValue::Address(Address::constant(value.to_string(), span)?), ConstValue::Boolean(value) => ConstrainedValue::Boolean(Boolean::Constant(*value)), + ConstValue::Char(value) => { + ConstrainedValue::Field(FieldType::constant(format!("{}", *value as u32), span)?) + } ConstValue::Field(value) => ConstrainedValue::Field(FieldType::constant(value.to_string(), span)?), ConstValue::Group(value) => ConstrainedValue::Group(G::constant(value, span)?), ConstValue::Int(value) => ConstrainedValue::Integer(Integer::new(value)), diff --git a/input/src/leo-input.pest b/input/src/leo-input.pest index 064dc40584..6e14499d15 100644 --- a/input/src/leo-input.pest +++ b/input/src/leo-input.pest @@ -73,6 +73,9 @@ type_integer_signed = { | type_i128 } +// Declared in types/char_type.rs +type_char = { "char" } + // Declared in types/field_type.rs type_field = { "field" } diff --git a/input/src/types/char_type.rs b/input/src/types/char_type.rs new file mode 100644 index 0000000000..56e20a68e0 --- /dev/null +++ b/input/src/types/char_type.rs @@ -0,0 +1,23 @@ +// Copyright (C) 2019-2021 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 . + +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] +#[pest_ast(rule(Rule::type_char))] +pub struct CharType {} diff --git a/input/src/types/data_type.rs b/input/src/types/data_type.rs index ecb82e3bda..a0977be017 100644 --- a/input/src/types/data_type.rs +++ b/input/src/types/data_type.rs @@ -16,7 +16,7 @@ use crate::{ ast::Rule, - types::{BooleanType, FieldType, GroupType, IntegerType}, + types::{BooleanType, CharType, FieldType, GroupType, IntegerType}, }; use crate::types::AddressType; @@ -27,6 +27,7 @@ use pest_ast::FromPest; pub enum DataType { Address(AddressType), Boolean(BooleanType), + Char(CharType), Field(FieldType), Group(GroupType), Integer(IntegerType), @@ -37,6 +38,7 @@ impl std::fmt::Display for DataType { match self { DataType::Address(_) => write!(f, "address"), DataType::Boolean(_) => write!(f, "bool"), + DataType::Char(_) => write!(f, "char"), DataType::Field(_) => write!(f, "field"), DataType::Group(_) => write!(f, "group"), DataType::Integer(ref integer) => write!(f, "{}", integer), diff --git a/input/src/types/mod.rs b/input/src/types/mod.rs index 54e309a43b..3f8bb810f8 100644 --- a/input/src/types/mod.rs +++ b/input/src/types/mod.rs @@ -26,6 +26,9 @@ pub use array_type::*; pub mod boolean_type; pub use boolean_type::*; +pub mod char_type; +pub use char_type::*; + pub mod data_type; pub use data_type::*;