From 1903858e7a47bd8ec39f8ff62b56eb9e9fd28980 Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 13 Apr 2020 17:21:09 -0700 Subject: [PATCH] program structs --- simple.program | 7 ++-- src/aleo_program/types.rs | 55 +++++++++++++++++-------- src/aleo_program/types_display.rs | 31 +++++++++++++- src/aleo_program/types_from.rs | 68 ++++++++++++++++++++++++++++++- src/ast.rs | 66 +++++++++++++++--------------- src/language.pest | 7 +--- 6 files changed, 172 insertions(+), 62 deletions(-) diff --git a/simple.program b/simple.program index 23fba51ab2..ff20c799e5 100644 --- a/simple.program +++ b/simple.program @@ -1,4 +1,5 @@ -for field i in 0..4 do - a = 1 + 1 -endfor +struct Foo { + field a + bool b +} return 1 \ No newline at end of file diff --git a/src/aleo_program/types.rs b/src/aleo_program/types.rs index 9b72dd7d8e..decd976411 100644 --- a/src/aleo_program/types.rs +++ b/src/aleo_program/types.rs @@ -89,10 +89,31 @@ pub enum Statement { Return(Vec), } +#[derive(Clone, Debug)] +pub enum Type { + FieldElement, + Boolean, + Array(Box, usize), + Struct(Variable), +} + +#[derive(Clone)] +pub struct StructField { + pub variable: Variable, + pub ty: Type, +} + +#[derive(Clone)] +pub struct Struct { + pub variable: Variable, + pub fields: Vec, +} + /// A simple program with statement expressions, program arguments and program returns. #[derive(Debug, Clone)] pub struct Program { pub id: String, + pub structs: Vec, pub statements: Vec, pub arguments: Vec, pub returns: Vec, @@ -150,21 +171,21 @@ mod tests { // // println!("{:#?}", program); // } - #[test] - fn test_basic_prog() { - // return 1 == 1 - let prog = Program { - id: "main".into(), - statements: vec![Statement::Return(vec![Expression::Boolean( - BooleanExpression::FieldEq( - Box::new(FieldExpression::Number(1)), - Box::new(FieldExpression::Number(1)), - ), - )])], - arguments: vec![], - returns: vec![], - }; - - println!("{:#?}", prog); - } + // #[test] + // fn test_basic_prog() { + // // return 1 == 1 + // let prog = Program { + // id: "main".into(), + // statements: vec![Statement::Return(vec![Expression::Boolean( + // BooleanExpression::FieldEq( + // Box::new(FieldExpression::Number(1)), + // Box::new(FieldExpression::Number(1)), + // ), + // )])], + // arguments: vec![], + // returns: vec![], + // }; + // + // println!("{:#?}", prog); + // } } diff --git a/src/aleo_program/types_display.rs b/src/aleo_program/types_display.rs index 7aedc4127c..e273325f18 100644 --- a/src/aleo_program/types_display.rs +++ b/src/aleo_program/types_display.rs @@ -4,7 +4,9 @@ //! @author Collin Chin //! @date 2020 -use crate::aleo_program::{BooleanExpression, Expression, FieldExpression, Statement, Variable}; +use crate::aleo_program::{ + BooleanExpression, Expression, FieldExpression, Statement, Struct, StructField, Type, Variable, +}; use std::fmt; @@ -91,3 +93,30 @@ impl fmt::Debug for Statement { } } } + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Boolean => write!(f, "bool"), + Type::FieldElement => write!(f, "field"), + Type::Struct(ref variable) => write!(f, "{}", variable), + Type::Array(ref array, ref count) => write!(f, "[{}; {}]", array, count), + } + } +} + +impl fmt::Display for StructField { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} : {}", self.ty, self.variable) + } +} + +impl fmt::Debug for Struct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "struct {} {{ \n", self.variable)?; + for field in self.fields.iter() { + write!(f, " {}\n", field)?; + } + write!(f, "}}") + } +} diff --git a/src/aleo_program/types_from.rs b/src/aleo_program/types_from.rs index 28bb0e960f..d4029a9e0a 100644 --- a/src/aleo_program/types_from.rs +++ b/src/aleo_program/types_from.rs @@ -338,12 +338,75 @@ impl<'ast> From> for types::Statement { } } +impl<'ast> From> for types::Type { + fn from(basic_type: ast::BasicType<'ast>) -> Self { + match basic_type { + ast::BasicType::Field(ty) => types::Type::FieldElement, + ast::BasicType::Boolean(ty) => types::Type::Boolean, + } + } +} + +impl<'ast> From> for types::Type { + fn from(array_type: ast::ArrayType<'ast>) -> Self { + let element_type = Box::new(types::Type::from(array_type.ty)); + let count = match array_type.count { + ast::Value::Field(f) => f.value.parse::().expect("Unable to read array size"), + _ => unimplemented!("Array size should be an integer"), + }; + types::Type::Array(element_type, count) + } +} + +impl<'ast> From> for types::Type { + fn from(struct_type: ast::StructType<'ast>) -> Self { + types::Type::Struct(types::Variable::from(struct_type.variable)) + } +} + +impl<'ast> From> for types::Type { + fn from(ty: ast::Type<'ast>) -> Self { + match ty { + ast::Type::Basic(ty) => types::Type::from(ty), + ast::Type::Array(ty) => types::Type::from(ty), + ast::Type::Struct(ty) => types::Type::from(ty), + } + } +} + +impl<'ast> From> for types::StructField { + fn from(struct_field: ast::StructField<'ast>) -> Self { + types::StructField { + variable: types::Variable::from(struct_field.variable), + ty: types::Type::from(struct_field.ty), + } + } +} + +impl<'ast> From> for types::Struct { + fn from(struct_definition: ast::Struct<'ast>) -> Self { + let variable = types::Variable::from(struct_definition.variable); + let fields = struct_definition + .fields + .into_iter() + .map(|struct_field| types::StructField::from(struct_field)) + .collect(); + + types::Struct { variable, fields } + } +} + impl<'ast> From> for types::Program { fn from(file: ast::File<'ast>) -> Self { // 1. compile ast -> aleo program representation - file.structs + let structs = file + .structs .into_iter() - .for_each(|struct_def| println!("{:#?}", struct_def)); + .map(|struct_def| { + println!("{:#?}", struct_def); + types::Struct::from(struct_def) + }) + .collect(); file.functions .into_iter() .for_each(|function_def| println!("{:#?}", function_def)); @@ -355,6 +418,7 @@ impl<'ast> From> for types::Program { types::Program { id: "main".into(), + structs, statements, arguments: vec![], returns: vec![], diff --git a/src/ast.rs b/src/ast.rs index 357fb90c86..731cb6944a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -170,21 +170,21 @@ fn binary_expression<'ast>( // Types -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_bool))] pub struct BooleanType<'ast> { #[pest_ast(outer())] pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_field))] pub struct FieldType<'ast> { #[pest_ast(outer())] pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_struct))] pub struct StructType<'ast> { pub variable: Variable<'ast>, @@ -192,30 +192,30 @@ pub struct StructType<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_basic))] pub enum BasicType<'ast> { Field(FieldType<'ast>), Boolean(BooleanType<'ast>), } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_basic_or_struct))] pub enum BasicOrStructType<'ast> { Struct(StructType<'ast>), Basic(BasicType<'ast>), } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty_array))] pub struct ArrayType<'ast> { pub ty: BasicType<'ast>, - pub dimensions: Vec>, + pub count: Value<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::ty))] pub enum Type<'ast> { Basic(BasicType<'ast>), @@ -275,7 +275,7 @@ pub struct Decrement<'ast> { // Binary Operations -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] pub enum BinaryOperator { Or, And, @@ -368,15 +368,15 @@ impl<'ast> fmt::Display for Variable<'ast> { // Access -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::from_expression))] pub struct FromExpression<'ast>(pub Expression<'ast>); -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::to_expression))] pub struct ToExpression<'ast>(pub Expression<'ast>); -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::range))] pub struct Range<'ast> { pub from: Option>, @@ -385,14 +385,14 @@ pub struct Range<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::range_or_expression))] pub enum RangeOrExpression<'ast> { Range(Range<'ast>), Expression(Expression<'ast>), } -// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[derive(Clone, Debug, FromPest, PartialEq)] // #[pest_ast(rule(Rule::call_access))] // pub struct CallAccess<'ast> { // pub expressions: Vec>, @@ -400,7 +400,7 @@ pub enum RangeOrExpression<'ast> { // pub span: Span<'ast>, // } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::access_array))] pub struct ArrayAccess<'ast> { pub expression: RangeOrExpression<'ast>, @@ -408,7 +408,7 @@ pub struct ArrayAccess<'ast> { pub span: Span<'ast>, } -// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[derive(Clone, Debug, FromPest, PartialEq)] // #[pest_ast(rule(Rule::member_access))] // pub struct MemberAccess<'ast> { // pub id: IdentifierExpression<'ast>, @@ -416,7 +416,7 @@ pub struct ArrayAccess<'ast> { // pub span: Span<'ast>, // } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::access))] pub enum Access<'ast> { // Call(CallAccess<'ast>), @@ -424,7 +424,7 @@ pub enum Access<'ast> { // Member(MemberAccess<'ast>), } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression_postfix))] pub struct PostfixExpression<'ast> { pub variable: Variable<'ast>, @@ -433,7 +433,7 @@ pub struct PostfixExpression<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::spread))] pub struct Spread<'ast> { pub expression: Expression<'ast>, @@ -447,7 +447,7 @@ impl<'ast> fmt::Display for Spread<'ast> { } } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::spread_or_expression))] pub enum SpreadOrExpression<'ast> { Spread(Spread<'ast>), @@ -465,7 +465,7 @@ impl<'ast> fmt::Display for SpreadOrExpression<'ast> { // Arrays -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression_array_inline))] pub struct ArrayInlineExpression<'ast> { pub expressions: Vec>, @@ -473,18 +473,18 @@ pub struct ArrayInlineExpression<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression_array_initializer))] pub struct ArrayInitializerExpression<'ast> { pub expression: Box>, - pub value: Value<'ast>, + pub count: Value<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } // Structs -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::struct_field))] pub struct StructField<'ast> { pub ty: Type<'ast>, @@ -493,7 +493,7 @@ pub struct StructField<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::struct_definition))] pub struct Struct<'ast> { pub variable: Variable<'ast>, @@ -502,7 +502,7 @@ pub struct Struct<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::inline_struct_member))] pub struct InlineStructMember<'ast> { pub variable: Variable<'ast>, @@ -511,7 +511,7 @@ pub struct InlineStructMember<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression_inline_struct))] pub struct StructInlineExpression<'ast> { pub variable: Variable<'ast>, @@ -654,7 +654,7 @@ impl<'ast> fmt::Display for Expression<'ast> { write!(f, "") } Expression::ArrayInitializer(ref expression) => { - write!(f, "{} = {}", expression.value, expression.expression) + write!(f, "[{} ; {}]", expression.expression, expression.count) } Expression::StructInline(ref expression) => { write!(f, "inline struct display not impl {}", expression.variable) @@ -686,7 +686,7 @@ impl<'ast> FromPest<'ast> for Expression<'ast> { // Statements -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_assign))] pub struct AssignStatement<'ast> { pub variable: Variable<'ast>, @@ -717,7 +717,7 @@ pub struct IterationStatement<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_return))] pub struct ReturnStatement<'ast> { pub expressions: Vec>, @@ -781,7 +781,7 @@ impl<'ast> fmt::Display for Statement<'ast> { // Functions -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::parameter))] pub struct Parameter<'ast> { pub visibility: Option, @@ -791,7 +791,7 @@ pub struct Parameter<'ast> { pub span: Span<'ast>, } -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::function_definition))] pub struct Function<'ast> { pub variable: Variable<'ast>, @@ -817,6 +817,6 @@ pub struct File<'ast> { // Utilities -#[derive(Debug, FromPest, PartialEq, Clone)] +#[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::EOI))] pub struct EOI; diff --git a/src/language.pest b/src/language.pest index 4537ac39e2..fd4e3308d6 100644 --- a/src/language.pest +++ b/src/language.pest @@ -56,7 +56,6 @@ ty_struct = { variable } ty_basic_or_struct = {ty_basic | ty_struct } ty_array = {ty_basic ~ ("[" ~ expression ~ "]")+ } ty = {ty_array | ty_basic | ty_struct} -// ty = {ty_array} type_list = _{(ty ~ ("," ~ ty)*)?} /// Values @@ -87,7 +86,7 @@ access_array = { "[" ~ range_or_expression ~ "]" } access_call = { "(" ~ expression_tuple ~ ")" } access_member = { "." ~ variable } access = { access_array | access_call | access_member } -expression_postfix = { variable ~ access+ } +expression_postfix = { variable ~ access+ } // add ++ and -- operators spread = { "..." ~ expression } spread_or_expression = { spread | expression } @@ -98,7 +97,6 @@ inline_array_inner = _{(spread_or_expression ~ ("," ~ NEWLINE* ~ spread_or_expre expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } - /// Structs struct_field = { ty ~ variable } @@ -109,7 +107,6 @@ inline_struct_member = { variable ~ ":" ~ expression } inline_struct_member_list = _{(inline_struct_member ~ ("," ~ NEWLINE* ~ inline_struct_member)*)? ~ ","? } expression_inline_struct = { variable ~ "{" ~ NEWLINE* ~ inline_struct_member_list ~ NEWLINE* ~ "}" } - /// Conditionals expression_conditional = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ expression ~ "fi"} @@ -135,7 +132,6 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? } /// Statements -// statement_expression = { expression } statement_assign = { variable ~ "=" ~ expression } statement_definition = { ty ~ variable ~ "=" ~ expression } statement_return = { "return" ~ expression_tuple } @@ -146,7 +142,6 @@ statement = { | (statement_iteration | statement_assign | statement_definition -// | statement_expression ) ~ NEWLINE ) ~ NEWLINE* }