From 9fc9e16367e6d945d6e4fefa2a4a80dc29a81586 Mon Sep 17 00:00:00 2001 From: collin Date: Tue, 28 Jul 2020 16:57:03 -0700 Subject: [PATCH] parse main, record, registers, state, state_leaf types to compiler input --- ast/src/functions/function.rs | 4 +- .../functions/{ => inputs}/function_input.rs | 0 ast/src/functions/inputs/input.rs | 16 +++++ ast/src/functions/inputs/mod.rs | 17 ++++++ ast/src/functions/inputs/record.rs | 11 ++++ ast/src/functions/inputs/registers.rs | 11 ++++ ast/src/functions/inputs/state.rs | 11 ++++ ast/src/functions/inputs/state_leaf.rs | 11 ++++ ast/src/functions/mod.rs | 4 +- ast/src/leo.pest | 27 ++++++++- compiler/src/compiler.rs | 5 +- compiler/src/function/function.rs | 37 +++++++----- compiler/src/function/main_function.rs | 29 +++++---- leo-inputs/src/assignments/mod.rs | 2 - .../definition.rs} | 4 +- leo-inputs/src/definitions/mod.rs | 2 + leo-inputs/src/errors/parser.rs | 22 +++++++ leo-inputs/src/errors/syntax.rs | 2 +- leo-inputs/src/files/file.rs | 5 +- leo-inputs/src/files/mod.rs | 3 + leo-inputs/src/files/table_or_section.rs | 10 ++++ leo-inputs/src/leo-inputs.pest | 29 +++++---- leo-inputs/src/lib.rs | 4 +- leo-inputs/src/sections/header.rs | 28 +++++++++ leo-inputs/src/sections/section.rs | 4 +- types/src/functions/function.rs | 6 +- .../functions/{ => inputs}/function_input.rs | 6 +- types/src/functions/inputs/input.rs | 50 ++++++++++++++++ types/src/functions/inputs/mod.rs | 5 ++ types/src/functions/mod.rs | 4 +- types/src/inputs/inputs.rs | 60 +++++++------------ .../src/inputs/program_inputs/main_inputs.rs | 44 +++++++++++++- .../inputs/program_inputs/program_inputs.rs | 22 ++++++- types/src/inputs/program_inputs/registers.rs | 30 +++++++++- .../private_state/private_state.rs | 24 +++++++- .../program_state/private_state/record.rs | 30 +++++++++- .../program_state/private_state/state_leaf.rs | 30 +++++++++- .../src/inputs/program_state/program_state.rs | 17 +++++- .../public_state/public_state.rs | 21 ++++++- .../program_state/public_state/state.rs | 30 +++++++++- types/src/program.rs | 8 ++- 41 files changed, 560 insertions(+), 125 deletions(-) rename ast/src/functions/{ => inputs}/function_input.rs (100%) create mode 100644 ast/src/functions/inputs/input.rs create mode 100644 ast/src/functions/inputs/mod.rs create mode 100644 ast/src/functions/inputs/record.rs create mode 100644 ast/src/functions/inputs/registers.rs create mode 100644 ast/src/functions/inputs/state.rs create mode 100644 ast/src/functions/inputs/state_leaf.rs delete mode 100644 leo-inputs/src/assignments/mod.rs rename leo-inputs/src/{assignments/assignment.rs => definitions/definition.rs} (83%) create mode 100644 leo-inputs/src/definitions/mod.rs create mode 100644 leo-inputs/src/files/table_or_section.rs rename types/src/functions/{ => inputs}/function_input.rs (91%) create mode 100644 types/src/functions/inputs/input.rs create mode 100644 types/src/functions/inputs/mod.rs diff --git a/ast/src/functions/function.rs b/ast/src/functions/function.rs index 46fb34abbb..a8a852590c 100644 --- a/ast/src/functions/function.rs +++ b/ast/src/functions/function.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::Identifier, functions::FunctionInput, statements::Statement, types::Type}; +use crate::{ast::Rule, common::Identifier, functions::inputs::Input, statements::Statement, types::Type}; use pest::Span; use pest_ast::FromPest; @@ -7,7 +7,7 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::function_definition))] pub struct Function<'ast> { pub function_name: Identifier<'ast>, - pub parameters: Vec>, + pub parameters: Vec>, pub returns: Vec>, pub statements: Vec>, #[pest_ast(outer())] diff --git a/ast/src/functions/function_input.rs b/ast/src/functions/inputs/function_input.rs similarity index 100% rename from ast/src/functions/function_input.rs rename to ast/src/functions/inputs/function_input.rs diff --git a/ast/src/functions/inputs/input.rs b/ast/src/functions/inputs/input.rs new file mode 100644 index 0000000000..7ac23d928e --- /dev/null +++ b/ast/src/functions/inputs/input.rs @@ -0,0 +1,16 @@ +use crate::{ + ast::Rule, + functions::{FunctionInput, Record, Registers, State, StateLeaf}, +}; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::input))] +pub enum Input<'ast> { + FunctionInput(FunctionInput<'ast>), + Record(Record<'ast>), + Registers(Registers<'ast>), + State(State<'ast>), + StateLeaf(StateLeaf<'ast>), +} diff --git a/ast/src/functions/inputs/mod.rs b/ast/src/functions/inputs/mod.rs new file mode 100644 index 0000000000..ec188dab11 --- /dev/null +++ b/ast/src/functions/inputs/mod.rs @@ -0,0 +1,17 @@ +pub mod function_input; +pub use function_input::*; + +pub mod input; +pub use input::*; + +pub mod record; +pub use record::*; + +pub mod registers; +pub use registers::*; + +pub mod state; +pub use state::*; + +pub mod state_leaf; +pub use state_leaf::*; diff --git a/ast/src/functions/inputs/record.rs b/ast/src/functions/inputs/record.rs new file mode 100644 index 0000000000..2f67290130 --- /dev/null +++ b/ast/src/functions/inputs/record.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::record))] +pub struct Record<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/registers.rs b/ast/src/functions/inputs/registers.rs new file mode 100644 index 0000000000..8e11fde122 --- /dev/null +++ b/ast/src/functions/inputs/registers.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::registers))] +pub struct Registers<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/state.rs b/ast/src/functions/inputs/state.rs new file mode 100644 index 0000000000..8063e4f8a9 --- /dev/null +++ b/ast/src/functions/inputs/state.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::state))] +pub struct State<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/state_leaf.rs b/ast/src/functions/inputs/state_leaf.rs new file mode 100644 index 0000000000..932203f24c --- /dev/null +++ b/ast/src/functions/inputs/state_leaf.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::state_leaf))] +pub struct StateLeaf<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/mod.rs b/ast/src/functions/mod.rs index fadb2897b1..7ae6a0a9fe 100644 --- a/ast/src/functions/mod.rs +++ b/ast/src/functions/mod.rs @@ -1,8 +1,8 @@ pub mod function; pub use function::*; -pub mod function_input; -pub use function_input::*; +pub mod inputs; +pub use inputs::*; pub mod test_function; pub use test_function::*; diff --git a/ast/src/leo.pest b/ast/src/leo.pest index e292ba698f..2177a06df4 100644 --- a/ast/src/leo.pest +++ b/ast/src/leo.pest @@ -335,11 +335,32 @@ statement_return = { "return " ~ return_} /// Functions // Declared in functions/function.rs -function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_model_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* } +function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* } -// Declared in functions/function_input.rs +// Declared in functions/inputs/function_input.rs function_input = { mutable? ~ identifier ~ ":" ~ type_ } -input_model_list = _{ (function_input ~ ("," ~ NEWLINE* ~ function_input)*)? } + +// Declared in functions/inputs/record.rs +record = { "record" } + +// Declared in functions/inputs/registers.rs +registers = { "registers" } + +// Declared in functions/inputs/state.rs +state = { "state" } + +// Declared in functions/inputs/state_leaf.rs +state_leaf = { "state_leaf" } + +// Declared in functions/inputs/input.rs +input = { + record + | registers + | state_leaf + | state + | function_input +} +input_list = _{ (input ~ ("," ~ NEWLINE* ~ input)*)? } // Declared in functions/test_function.rs test_function = { "test " ~ function_definition } diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 5f4718875c..3180b50c1b 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -118,8 +118,11 @@ impl> Compiler { pub fn parse_inputs(&mut self, inputs_string: &str) -> Result<(), CompilerError> { let syntax_tree = LeoInputsParser::parse_file(&inputs_string)?; + self.program_inputs + .parse_program_input_file(syntax_tree, self.program.expected_inputs.clone())?; + // Check number/order of parameters here - self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?; + // self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?; Ok(()) } diff --git a/compiler/src/function/function.rs b/compiler/src/function/function.rs index 95876b0016..5c524dd408 100644 --- a/compiler/src/function/function.rs +++ b/compiler/src/function/function.rs @@ -7,7 +7,7 @@ use crate::{ GroupType, }; -use leo_types::{Expression, Function, Span}; +use leo_types::{Expression, Function, Input, Span}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -39,23 +39,28 @@ impl> ConstrainedProgram { // Store input values as new variables in resolved program for (input_model, input_expression) in function.inputs.clone().iter().zip(inputs.into_iter()) { - // First evaluate input expression - let mut input_value = self.enforce_input( - cs, - scope.clone(), - caller_scope.clone(), - function_name.clone(), - vec![input_model._type.clone()], - input_expression, - )?; + if let Input::FunctionInput(input_model) = input_model { + // First evaluate input expression + let mut input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![input_model.type_.clone()], + input_expression, + )?; - if input_model.mutable { - input_value = ConstrainedValue::Mutable(Box::new(input_value)) + if input_model.mutable { + input_value = ConstrainedValue::Mutable(Box::new(input_value)) + } + + // Store input as variable with {function_name}_{input_name} + let input_program_identifier = new_scope(function_name.clone(), input_model.identifier.name.clone()); + self.store(input_program_identifier, input_value); + } else { + println!("function input model {}", input_model); + println!("function input option {}", input_expression) } - - // Store input as variable with {function_name}_{input_name} - let input_program_identifier = new_scope(function_name.clone(), input_model.identifier.name.clone()); - self.store(input_program_identifier, input_value); } // Evaluate every statement in the function and save all potential results diff --git a/compiler/src/function/main_function.rs b/compiler/src/function/main_function.rs index cb044fc238..9e6d32af9d 100644 --- a/compiler/src/function/main_function.rs +++ b/compiler/src/function/main_function.rs @@ -8,7 +8,7 @@ use crate::{ GroupType, }; -use leo_types::{Expression, Function, InputValue}; +use leo_types::{Expression, Function, Input, InputValue}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -31,19 +31,24 @@ impl> ConstrainedProgram { // Iterate over main function inputs and allocate new passed-by variable values let mut input_variables = vec![]; for (input_model, input_option) in function.inputs.clone().into_iter().zip(inputs.into_iter()) { - let input_value = self.allocate_main_function_input( - cs, - input_model._type, - input_model.identifier.name.clone(), - input_option, - function.span.clone(), - )?; + if let Input::FunctionInput(input_model) = input_model { + let input_value = self.allocate_main_function_input( + cs, + input_model.type_, + input_model.identifier.name.clone(), + input_option, + function.span.clone(), + )?; - // Store a new variable for every allocated main function input - let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone()); - self.store(input_name.clone(), input_value); + // Store a new variable for every allocated main function input + let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone()); + self.store(input_name.clone(), input_value); - input_variables.push(Expression::Identifier(input_model.identifier)); + input_variables.push(Expression::Identifier(input_model.identifier)); + } else { + println!("main function input model {}", input_model); + // println!("main function input option {}", input_option.to_) + } } self.enforce_function(cs, scope, function_name, function, input_variables) diff --git a/leo-inputs/src/assignments/mod.rs b/leo-inputs/src/assignments/mod.rs deleted file mode 100644 index e02881fe86..0000000000 --- a/leo-inputs/src/assignments/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod assignment; -pub use assignment::*; diff --git a/leo-inputs/src/assignments/assignment.rs b/leo-inputs/src/definitions/definition.rs similarity index 83% rename from leo-inputs/src/assignments/assignment.rs rename to leo-inputs/src/definitions/definition.rs index 0945a146a1..7f33591ba9 100644 --- a/leo-inputs/src/assignments/assignment.rs +++ b/leo-inputs/src/definitions/definition.rs @@ -4,8 +4,8 @@ use pest::Span; use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::assignment))] -pub struct Assignment<'ast> { +#[pest_ast(rule(Rule::definition))] +pub struct Definition<'ast> { pub parameter: Parameter<'ast>, pub expression: Expression<'ast>, pub line_end: LineEnd, diff --git a/leo-inputs/src/definitions/mod.rs b/leo-inputs/src/definitions/mod.rs new file mode 100644 index 0000000000..c4cce58786 --- /dev/null +++ b/leo-inputs/src/definitions/mod.rs @@ -0,0 +1,2 @@ +pub mod definition; +pub use definition::*; diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index 5753af6bbd..b0345e3963 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -6,6 +6,7 @@ use crate::{ values::{NumberImplicitValue, NumberValue, Value}, }; +use crate::sections::Header; use pest::{ error::{Error, ErrorVariant}, Span, @@ -81,6 +82,27 @@ impl InputParserError { Self::new_from_span(message, span) } + + pub fn input_section_header(header: Header) -> Self { + let message = format!("the section header {} does not belong in an input `.in` file", header); + let span = header.span(); + + Self::new_from_span(message, span) + } + + pub fn public_section(header: Header) -> Self { + let message = format!("the section header {} is not a public section", header); + let span = header.span(); + + Self::new_from_span(message, span) + } + + pub fn private_section(header: Header) -> Self { + let message = format!("the section header {} is not a private section", header); + let span = header.span(); + + Self::new_from_span(message, span) + } } impl From> for InputParserError { diff --git a/leo-inputs/src/errors/syntax.rs b/leo-inputs/src/errors/syntax.rs index a436ec15b1..8e73accb69 100644 --- a/leo-inputs/src/errors/syntax.rs +++ b/leo-inputs/src/errors/syntax.rs @@ -15,7 +15,7 @@ impl From> for SyntaxError { Rule::type_integer => "`u32`".to_owned(), Rule::type_field => "`field`".to_owned(), Rule::type_group => "`group`".to_owned(), - Rule::file => "an import, circuit, or function".to_owned(), + Rule::file => "a table or section".to_owned(), Rule::identifier => "a variable name".to_owned(), Rule::type_ => "a type".to_owned(), diff --git a/leo-inputs/src/files/file.rs b/leo-inputs/src/files/file.rs index 292c533ccd..8d2fdfa3bc 100644 --- a/leo-inputs/src/files/file.rs +++ b/leo-inputs/src/files/file.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::EOI, sections::Section, tables::Table}; +use crate::{ast::Rule, common::EOI, files::TableOrSection}; use pest::Span; use pest_ast::FromPest; @@ -6,8 +6,7 @@ use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::file))] pub struct File<'ast> { - pub tables: Vec>, - pub sections: Vec>, + pub entries: Vec>, pub eoi: EOI, #[pest_ast(outer())] pub span: Span<'ast>, diff --git a/leo-inputs/src/files/mod.rs b/leo-inputs/src/files/mod.rs index de03a628a4..1638d8b176 100644 --- a/leo-inputs/src/files/mod.rs +++ b/leo-inputs/src/files/mod.rs @@ -1,2 +1,5 @@ pub mod file; pub use file::*; + +pub mod table_or_section; +pub use table_or_section::*; diff --git a/leo-inputs/src/files/table_or_section.rs b/leo-inputs/src/files/table_or_section.rs new file mode 100644 index 0000000000..071fa3e790 --- /dev/null +++ b/leo-inputs/src/files/table_or_section.rs @@ -0,0 +1,10 @@ +use crate::{ast::Rule, sections::Section, tables::Table}; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::table_or_section))] +pub enum TableOrSection<'ast> { + Section(Section<'ast>), + Table(Table<'ast>), +} diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 2f153b513a..d9fdc3c801 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -14,15 +14,15 @@ protected_name = { | "import" | "in" | "let" - | "main" + | main | "mut" - | "private" - | "public" - | "record" - | "registers" + | private + | public + | record + | registers | "return" - | "state" - | "state_leaf" + | state + | state_leaf | "static" | "test" | "true" @@ -145,7 +145,7 @@ parameter = { identifier ~ ":" ~ type_ } /// Section // Declared in sections/section.rs -section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } +section = { "[" ~ header ~ "]" ~ NEWLINE+ ~ (definition ~ NEWLINE*)* } // Declared in sections/main_.rs main = { "main" } @@ -163,12 +163,12 @@ state = { "state" } state_leaf = { "state_leaf" } // Declared in sections/header.rs -header = { "[" ~ main | record | registers | state | state_leaf | identifier ~ "]" } +header = { main | record | registers | state_leaf | state | identifier } -/// Assignments +/// Definitions -// Declared in assignment/assignment.rs -assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } +// Declared in definition/definition.rs +definition = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } /// Table @@ -191,5 +191,8 @@ WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } /// Files +// Declared in files/table_or_section.rs +table_or_section = { table | section } + // Declared in files/file.rs -file = { SOI ~ NEWLINE* ~ table* ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } +file = { SOI ~ NEWLINE* ~ table_or_section* ~ NEWLINE* ~ EOI } diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 527d019f21..6c25dba251 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -6,9 +6,9 @@ extern crate thiserror; pub mod errors; pub use errors::*; -pub mod assignments; mod ast; pub mod common; +pub mod definitions; pub mod expressions; pub mod files; pub mod parameters; @@ -30,7 +30,7 @@ impl LeoInputsParser { /// Parses the input file and constructs a syntax tree. pub fn parse_file(input_file: &str) -> Result { - // Parse the file using leo.pest + // Parse the file using leo-inputs.pest let mut file = ast::parse(input_file)?; // Build the abstract syntax tree diff --git a/leo-inputs/src/sections/header.rs b/leo-inputs/src/sections/header.rs index 19ecd53d82..d5aa339251 100644 --- a/leo-inputs/src/sections/header.rs +++ b/leo-inputs/src/sections/header.rs @@ -4,7 +4,9 @@ use crate::{ sections::{Main, Record, Registers, State, StateLeaf}, }; +use pest::Span; use pest_ast::FromPest; +use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::header))] @@ -16,3 +18,29 @@ pub enum Header<'ast> { StateLeaf(StateLeaf<'ast>), Identifier(Identifier<'ast>), } + +impl<'ast> Header<'ast> { + pub fn span(self) -> Span<'ast> { + match self { + Header::Main(main) => main.span, + Header::Record(record) => record.span, + Header::Registers(registers) => registers.span, + Header::State(state) => state.span, + Header::StateLeaf(state_leaf) => state_leaf.span, + Header::Identifier(identifier) => identifier.span, + } + } +} + +impl<'ast> fmt::Display for Header<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Header::Main(_main) => write!(f, "main"), + Header::Record(_record) => write!(f, "record"), + Header::Registers(_registers) => write!(f, "registers"), + Header::State(_state) => write!(f, "state"), + Header::StateLeaf(_state_leaf) => write!(f, "state_leaf"), + Header::Identifier(identifier) => write!(f, "{}", identifier.value), + } + } +} diff --git a/leo-inputs/src/sections/section.rs b/leo-inputs/src/sections/section.rs index 02186b2c61..0e43dd9778 100644 --- a/leo-inputs/src/sections/section.rs +++ b/leo-inputs/src/sections/section.rs @@ -1,4 +1,4 @@ -use crate::{assignments::Assignment, ast::Rule, sections::Header}; +use crate::{ast::Rule, definitions::Definition, sections::Header}; use pest::Span; use pest_ast::FromPest; @@ -7,7 +7,7 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::section))] pub struct Section<'ast> { pub header: Header<'ast>, - pub assignments: Vec>, + pub definitions: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, } diff --git a/types/src/functions/function.rs b/types/src/functions/function.rs index 8808234d61..2bc6e7cc50 100644 --- a/types/src/functions/function.rs +++ b/types/src/functions/function.rs @@ -1,4 +1,4 @@ -use crate::{FunctionInput, Identifier, Span, Statement, Type}; +use crate::{Identifier, Input, Span, Statement, Type}; use leo_ast::functions::Function as AstFunction; use serde::{Deserialize, Serialize}; @@ -7,7 +7,7 @@ use std::fmt; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Function { pub function_name: Identifier, - pub inputs: Vec, + pub inputs: Vec, pub returns: Vec, pub statements: Vec, pub span: Span, @@ -19,7 +19,7 @@ impl<'ast> From> for Function { let parameters = function_definition .parameters .into_iter() - .map(|parameter| FunctionInput::from(parameter)) + .map(|parameter| Input::from(parameter)) .collect(); let returns = function_definition .returns diff --git a/types/src/functions/function_input.rs b/types/src/functions/inputs/function_input.rs similarity index 91% rename from types/src/functions/function_input.rs rename to types/src/functions/inputs/function_input.rs index 98c88071dc..e2f49cad21 100644 --- a/types/src/functions/function_input.rs +++ b/types/src/functions/inputs/function_input.rs @@ -8,7 +8,7 @@ use std::fmt; pub struct FunctionInput { pub identifier: Identifier, pub mutable: bool, - pub _type: Type, + pub type_: Type, pub span: Span, } @@ -17,7 +17,7 @@ impl<'ast> From> for FunctionInput { FunctionInput { identifier: Identifier::from(parameter.identifier), mutable: parameter.mutable.is_some(), - _type: Type::from(parameter._type), + type_: Type::from(parameter._type), span: Span::from(parameter.span), } } @@ -30,7 +30,7 @@ impl FunctionInput { write!(f, "mut ")?; } write!(f, "{}: ", self.identifier)?; - write!(f, "{}", self._type) + write!(f, "{}", self.type_) } } diff --git a/types/src/functions/inputs/input.rs b/types/src/functions/inputs/input.rs new file mode 100644 index 0000000000..7f46b1fcc4 --- /dev/null +++ b/types/src/functions/inputs/input.rs @@ -0,0 +1,50 @@ +use crate::FunctionInput; +use leo_ast::functions::inputs::Input as AstInput; + +use serde::{Deserialize, Serialize}; +use std::fmt; + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum Input { + FunctionInput(FunctionInput), + Record, + Registers, + State, + StateLeaf, +} + +impl<'ast> From> for Input { + fn from(input: AstInput<'ast>) -> Self { + match input { + AstInput::FunctionInput(function_input) => Input::FunctionInput(FunctionInput::from(function_input)), + AstInput::Record(_) => Input::Record, + AstInput::Registers(_) => Input::Registers, + AstInput::State(_) => Input::State, + AstInput::StateLeaf(_) => Input::StateLeaf, + } + } +} + +impl Input { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Input::FunctionInput(function_input) => write!(f, "{}", function_input), + Input::Record => write!(f, "record"), + Input::Registers => write!(f, "registers"), + Input::State => write!(f, "state"), + Input::StateLeaf => write!(f, "state_leaf"), + } + } +} + +impl fmt::Display for Input { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for Input { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} diff --git a/types/src/functions/inputs/mod.rs b/types/src/functions/inputs/mod.rs new file mode 100644 index 0000000000..a545b7282e --- /dev/null +++ b/types/src/functions/inputs/mod.rs @@ -0,0 +1,5 @@ +pub mod function_input; +pub use function_input::*; + +pub mod input; +pub use input::*; diff --git a/types/src/functions/mod.rs b/types/src/functions/mod.rs index fadb2897b1..7ae6a0a9fe 100644 --- a/types/src/functions/mod.rs +++ b/types/src/functions/mod.rs @@ -1,8 +1,8 @@ pub mod function; pub use function::*; -pub mod function_input; -pub use function_input::*; +pub mod inputs; +pub use inputs::*; pub mod test_function; pub use test_function::*; diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index e242c272e2..485a44aa10 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,9 +1,11 @@ -use crate::{FunctionInput, InputValue, ProgramInputs, ProgramState}; -use leo_inputs::{files::File, sections::header::Header, InputParserError}; +use crate::{Input, InputValue, ProgramInputs, ProgramState}; +use leo_inputs::{ + files::{File, TableOrSection}, + InputParserError, +}; #[derive(Clone)] pub struct Inputs { - program_inputs: Vec>, inputs: ProgramInputs, state: ProgramState, } @@ -11,59 +13,39 @@ pub struct Inputs { impl Inputs { pub fn new() -> Self { Self { - program_inputs: vec![], inputs: ProgramInputs::new(), state: ProgramState::new(), } } pub fn get_inputs(&self) -> Vec> { - self.program_inputs.clone() + self.inputs.main.0.clone() } pub fn set_inputs(&mut self, inputs: Vec>) { - self.program_inputs = inputs; + self.inputs.main.0 = inputs; } pub fn set_inputs_size(&mut self, size: usize) { - self.program_inputs = vec![None; size]; + self.inputs.main.0 = vec![None; size]; } - pub fn from_inputs_file(file: File, expected_inputs: Vec) -> Result { - let mut program_inputs = vec![]; - - for section in file.sections.into_iter() { - match section.header { - Header::Main(_main) => { - for input in &expected_inputs { - // find input with matching name - let matched_input = section.assignments.clone().into_iter().find(|assignment| { - // name match - assignment.parameter.variable.value.eq(&input.identifier.name) - // type match - && assignment.parameter.type_.to_string().eq(&input._type.to_string()) - }); - - match matched_input { - Some(assignment) => { - let value = - InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; - - // push value to vector - program_inputs.push(Some(value)); - } - None => return Err(InputParserError::InputNotFound(input.to_string())), - } - } + pub fn parse_program_input_file( + &mut self, + file: File, + expected_inputs: Vec, + ) -> Result<(), InputParserError> { + for entry in file.entries.into_iter() { + match entry { + TableOrSection::Section(section) => { + self.inputs.store_definitions(section, &expected_inputs)?; + } + TableOrSection::Table(table) => { + self.state.store_definitions(table, &expected_inputs)?; } - _ => unimplemented!("section not impl"), } } - Ok(Self { - program_inputs, - inputs: ProgramInputs::new(), - state: ProgramState::new(), - }) + Ok(()) } } diff --git a/types/src/inputs/program_inputs/main_inputs.rs b/types/src/inputs/program_inputs/main_inputs.rs index 708ef2e05a..7f7c607057 100644 --- a/types/src/inputs/program_inputs/main_inputs.rs +++ b/types/src/inputs/program_inputs/main_inputs.rs @@ -1,10 +1,50 @@ -use crate::InputValue; +use crate::{Input, InputValue}; +use leo_inputs::{definitions::Definition, InputParserError}; #[derive(Clone, PartialEq, Eq)] -pub struct MainInputs(Vec>); +pub struct MainInputs(pub Vec>); impl MainInputs { pub fn new() -> Self { Self(vec![]) } + + /// Stores main input assignments that match expected main function inputs + pub fn store_definitions( + &mut self, + definitions: Vec, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + let mut program_inputs = vec![]; + + for definition in definitions { + // find input with matching name + let matched_input = expected_inputs.clone().into_iter().find(|input| { + // only look at program inputs + match input { + Input::FunctionInput(function_input) => { + // name match + function_input.identifier.name.eq(&definition.parameter.variable.value) + // type match + && function_input.type_.to_string().eq(&definition.parameter.type_.to_string()) + } + _ => false, + } + }); + + match matched_input { + Some(_) => { + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + // push value to main inputs + program_inputs.push(Some(value)); + } + None => return Err(InputParserError::InputNotFound(definition.parameter.variable.value)), + } + } + + self.0 = program_inputs; + + Ok(()) + } } diff --git a/types/src/inputs/program_inputs/program_inputs.rs b/types/src/inputs/program_inputs/program_inputs.rs index ce3504b823..c4b418a9c8 100644 --- a/types/src/inputs/program_inputs/program_inputs.rs +++ b/types/src/inputs/program_inputs/program_inputs.rs @@ -1,9 +1,13 @@ -use crate::{MainInputs, Registers}; +use crate::{Input, MainInputs, Registers}; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; #[derive(Clone, PartialEq, Eq)] pub struct ProgramInputs { - main: MainInputs, - registers: Registers, + pub main: MainInputs, + pub registers: Registers, } impl ProgramInputs { @@ -13,4 +17,16 @@ impl ProgramInputs { registers: Registers::new(), } } + + pub fn store_definitions( + &mut self, + section: Section, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + match section.header { + Header::Main(_main) => self.main.store_definitions(section.definitions, &expected_inputs), + Header::Registers(_registers) => self.registers.store_definitions(section.definitions, &expected_inputs), + header => Err(InputParserError::input_section_header(header)), + } + } } diff --git a/types/src/inputs/program_inputs/registers.rs b/types/src/inputs/program_inputs/registers.rs index 006ecc2637..46876af4f2 100644 --- a/types/src/inputs/program_inputs/registers.rs +++ b/types/src/inputs/program_inputs/registers.rs @@ -1,4 +1,5 @@ -use crate::InputValue; +use crate::{Input, InputValue}; +use leo_inputs::{definitions::Definition, InputParserError}; #[derive(Clone, PartialEq, Eq)] pub struct Registers(Vec>); @@ -7,4 +8,31 @@ impl Registers { pub fn new() -> Self { Self(vec![]) } + + /// Stores register input definitions if the main function input contains the `registers` variable. + pub fn store_definitions( + &mut self, + definitions: Vec, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + // if the main function does not contain the `registers` variable + // then do not parse registers + if !expected_inputs.contains(&Input::Registers) { + return Ok(()); + } + + let mut register_inputs = vec![]; + + // store all registers + for definition in definitions { + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + // push value to register inputs + register_inputs.push(Some(value)); + } + + self.0 = register_inputs; + + Ok(()) + } } diff --git a/types/src/inputs/program_state/private_state/private_state.rs b/types/src/inputs/program_state/private_state/private_state.rs index 53e12f768f..0189a5d706 100644 --- a/types/src/inputs/program_state/private_state/private_state.rs +++ b/types/src/inputs/program_state/private_state/private_state.rs @@ -1,4 +1,8 @@ -use crate::{Record, StateLeaf}; +use crate::{Input, Record, StateLeaf}; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; #[derive(Clone, PartialEq, Eq)] pub struct PrivateState { @@ -13,4 +17,22 @@ impl PrivateState { state_leaf: StateLeaf::new(), } } + + pub fn store_definitions( + &mut self, + sections: Vec
, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + for section in sections { + match section.header { + Header::Record(_state) => self.record.store_definitions(section.definitions, expected_inputs)?, + Header::StateLeaf(_state_leaf) => self + .state_leaf + .store_definitions(section.definitions, expected_inputs)?, + header => return Err(InputParserError::private_section(header)), + } + } + + Ok(()) + } } diff --git a/types/src/inputs/program_state/private_state/record.rs b/types/src/inputs/program_state/private_state/record.rs index 4f9454ce4e..80d6865126 100644 --- a/types/src/inputs/program_state/private_state/record.rs +++ b/types/src/inputs/program_state/private_state/record.rs @@ -1,4 +1,5 @@ -use crate::InputValue; +use crate::{Input, InputValue}; +use leo_inputs::{definitions::Definition, InputParserError}; #[derive(Clone, PartialEq, Eq)] pub struct Record(Vec>); @@ -7,4 +8,31 @@ impl Record { pub fn new() -> Self { Self(vec![]) } + + /// Stores record input definitions if the main function input contains the `record` variable. + pub fn store_definitions( + &mut self, + definitions: Vec, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + // if the main function does not contain the `record` variable + // then do not parse record definitions + if !expected_inputs.contains(&Input::Record) { + return Ok(()); + } + + let mut record_inputs = vec![]; + + // store all definitions + for definition in definitions { + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + // push value to register inputs + record_inputs.push(Some(value)); + } + + self.0 = record_inputs; + + Ok(()) + } } diff --git a/types/src/inputs/program_state/private_state/state_leaf.rs b/types/src/inputs/program_state/private_state/state_leaf.rs index 15884af751..47317425a2 100644 --- a/types/src/inputs/program_state/private_state/state_leaf.rs +++ b/types/src/inputs/program_state/private_state/state_leaf.rs @@ -1,4 +1,5 @@ -use crate::InputValue; +use crate::{Input, InputValue}; +use leo_inputs::{definitions::Definition, InputParserError}; #[derive(Clone, PartialEq, Eq)] pub struct StateLeaf(Vec>); @@ -7,4 +8,31 @@ impl StateLeaf { pub fn new() -> Self { Self(vec![]) } + + /// Stores state_leaf input definitions if the main function input contains the `state_leaf` variable. + pub fn store_definitions( + &mut self, + definitions: Vec, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + // if the main function does not contain the `state_leaf` variable + // then do not parse state_leaf definitions + if !expected_inputs.contains(&Input::StateLeaf) { + return Ok(()); + } + + let mut state_leaf_inputs = vec![]; + + // store all definitions + for definition in definitions { + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + // push value to register inputs + state_leaf_inputs.push(Some(value)); + } + + self.0 = state_leaf_inputs; + + Ok(()) + } } diff --git a/types/src/inputs/program_state/program_state.rs b/types/src/inputs/program_state/program_state.rs index c5a5cae3b9..0fb7b18f49 100644 --- a/types/src/inputs/program_state/program_state.rs +++ b/types/src/inputs/program_state/program_state.rs @@ -1,9 +1,13 @@ -use crate::{PrivateState, PublicState}; +use crate::{Input, PrivateState, PublicState}; +use leo_inputs::{ + tables::{Table, Visibility}, + InputParserError, +}; #[derive(Clone, PartialEq, Eq)] pub struct ProgramState { - public: PublicState, - private: PrivateState, + pub public: PublicState, + pub private: PrivateState, } impl ProgramState { @@ -13,4 +17,11 @@ impl ProgramState { private: PrivateState::new(), } } + + pub fn store_definitions(&mut self, table: Table, expected_inputs: &Vec) -> Result<(), InputParserError> { + match table.visibility { + Visibility::Private(_private) => self.private.store_definitions(table.sections, &expected_inputs), + Visibility::Public(_public) => self.public.store_definitions(table.sections, &expected_inputs), + } + } } diff --git a/types/src/inputs/program_state/public_state/public_state.rs b/types/src/inputs/program_state/public_state/public_state.rs index 29d23eba93..21999c14b8 100644 --- a/types/src/inputs/program_state/public_state/public_state.rs +++ b/types/src/inputs/program_state/public_state/public_state.rs @@ -1,4 +1,8 @@ -use crate::State; +use crate::{Input, State}; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; #[derive(Clone, PartialEq, Eq)] pub struct PublicState { @@ -9,4 +13,19 @@ impl PublicState { pub fn new() -> Self { Self { state: State::new() } } + + pub fn store_definitions( + &mut self, + sections: Vec
, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + for section in sections { + match section.header { + Header::State(_state) => self.state.store_definitions(section.definitions, expected_inputs)?, + header => return Err(InputParserError::public_section(header)), + } + } + + Ok(()) + } } diff --git a/types/src/inputs/program_state/public_state/state.rs b/types/src/inputs/program_state/public_state/state.rs index 818c456652..0ec728692c 100644 --- a/types/src/inputs/program_state/public_state/state.rs +++ b/types/src/inputs/program_state/public_state/state.rs @@ -1,4 +1,5 @@ -use crate::InputValue; +use crate::{Input, InputValue}; +use leo_inputs::{definitions::Definition, InputParserError}; #[derive(Clone, PartialEq, Eq)] pub struct State(Vec>); @@ -7,4 +8,31 @@ impl State { pub fn new() -> Self { Self(vec![]) } + + /// Stores state input definitions if the main function input contains the `state` variable. + pub fn store_definitions( + &mut self, + definitions: Vec, + expected_inputs: &Vec, + ) -> Result<(), InputParserError> { + // if the main function does not contain the `state` variable + // then do not parse state definitions + if !expected_inputs.contains(&Input::State) { + return Ok(()); + } + + let mut state_inputs = vec![]; + + // store all registers + for definition in definitions { + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + // push value to register inputs + state_inputs.push(Some(value)); + } + + self.0 = state_inputs; + + Ok(()) + } } diff --git a/types/src/program.rs b/types/src/program.rs index 931766122d..3f58ac0443 100644 --- a/types/src/program.rs +++ b/types/src/program.rs @@ -1,7 +1,7 @@ //! A typed Leo program consists of import, circuit, and function definitions. //! Each defined type consists of typed statements and expressions. -use crate::{Circuit, Function, FunctionInput, Identifier, Import, TestFunction}; +use crate::{Circuit, Function, Identifier, Import, Input, TestFunction}; use leo_ast::files::File; use serde::{Deserialize, Serialize}; @@ -11,13 +11,15 @@ use std::collections::HashMap; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Program { pub name: String, - pub expected_inputs: Vec, + pub expected_inputs: Vec, pub imports: Vec, pub circuits: HashMap, pub functions: HashMap, pub tests: HashMap, } +const MAIN_FUNCTION_NAME: &str = "main"; + impl<'ast> Program { //! Logic to convert from an abstract syntax tree (ast) representation to a Leo program. pub fn from(file: File<'ast>, name: String) -> Self { @@ -38,7 +40,7 @@ impl<'ast> Program { }); file.functions.into_iter().for_each(|function_def| { let function = Function::from(function_def); - if function.function_name.name.eq("main") { + if function.function_name.name.eq(MAIN_FUNCTION_NAME) { expected_inputs = function.inputs.clone(); } functions.insert(function.function_name.clone(), function);