From b58db80005d6bd5a975eaeaf01cb692abc1fb686 Mon Sep 17 00:00:00 2001 From: damirka Date: Mon, 15 Mar 2021 16:29:45 +0300 Subject: [PATCH] updates after @collinc97 comments --- ast/src/input/input.rs | 11 ++- ast/src/input/program_input/const_input.rs | 70 ++++++++++++++++++++ ast/src/input/program_input/main_input.rs | 35 ++-------- ast/src/input/program_input/mod.rs | 3 + ast/src/input/program_input/program_input.rs | 24 +++++-- compiler/src/function/main_function.rs | 26 +++++--- 6 files changed, 118 insertions(+), 51 deletions(-) create mode 100644 ast/src/input/program_input/const_input.rs diff --git a/ast/src/input/input.rs b/ast/src/input/input.rs index 7b48afb243..55e5ec1098 100644 --- a/ast/src/input/input.rs +++ b/ast/src/input/input.rs @@ -94,13 +94,18 @@ impl Input { Ok(()) } - /// Returns the main function input value with the given `name`, second parameter - /// is a boolean indicating whether parameter is const. + /// Returns the main function input value with the given `name`. #[allow(clippy::ptr_arg)] - pub fn get(&self, name: &String) -> Option<(Option, bool)> { + pub fn get(&self, name: &String) -> Option> { self.program_input.get(name) } + /// Returns the constant input value with the given `name`. + #[allow(clippy::ptr_arg)] + pub fn get_constant(&self, name: &String) -> Option> { + self.program_input.get_constant(name) + } + /// Returns the runtime register input values pub fn get_registers(&self) -> &Registers { self.program_input.get_registers() diff --git a/ast/src/input/program_input/const_input.rs b/ast/src/input/program_input/const_input.rs new file mode 100644 index 0000000000..b4112a4097 --- /dev/null +++ b/ast/src/input/program_input/const_input.rs @@ -0,0 +1,70 @@ +// 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::InputValue; +use leo_input::{definitions::Definition, InputParserError}; + +use indexmap::IndexMap; + +#[derive(Clone, PartialEq, Eq, Default)] +pub struct ConstInput { + input: IndexMap>, +} + +#[allow(clippy::len_without_is_empty)] +impl ConstInput { + pub fn new() -> Self { + Self::default() + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private input variables. + pub fn empty(&self) -> Self { + let mut input = self.input.clone(); + + input.iter_mut().for_each(|(_name, value)| { + *value = None; + }); + + Self { input } + } + + pub fn len(&self) -> usize { + self.input.len() + } + + pub fn insert(&mut self, key: String, value: Option) { + self.input.insert(key, value); + } + + /// Parses main input definitions and stores them in `self`. + pub fn parse(&mut self, definitions: Vec) -> Result<(), InputParserError> { + for definition in definitions { + let name = definition.parameter.variable.value; + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + self.insert(name, Some(value)); + } + + Ok(()) + } + + /// Returns an `Option` of the main function input at `name`. As a second + /// value in a tuple returns flag whether input is defined as a constant in input file. + pub fn get(&self, name: &str) -> Option> { + self.input.get(name).cloned() + } +} diff --git a/ast/src/input/program_input/main_input.rs b/ast/src/input/program_input/main_input.rs index fa0f613450..9fa4bec7ef 100644 --- a/ast/src/input/program_input/main_input.rs +++ b/ast/src/input/program_input/main_input.rs @@ -22,7 +22,6 @@ use indexmap::IndexMap; #[derive(Clone, PartialEq, Eq, Default)] pub struct MainInput { input: IndexMap>, - constants: IndexMap>, } #[allow(clippy::len_without_is_empty)] @@ -35,31 +34,22 @@ impl MainInput { /// Called during constraint synthesis to provide private input variables. pub fn empty(&self) -> Self { let mut input = self.input.clone(); - let mut constants = self.constants.clone(); input.iter_mut().for_each(|(_name, value)| { *value = None; }); - constants.iter_mut().for_each(|(_name, value)| { - *value = None; - }); - - Self { input, constants } + Self { input } } pub fn len(&self) -> usize { - self.input.len() + self.constants.len() + self.input.len() } pub fn insert(&mut self, key: String, value: Option) { self.input.insert(key, value); } - pub fn insert_constant(&mut self, key: String, value: Option) { - self.constants.insert(key, value); - } - /// Parses main input definitions and stores them in `self`. pub fn parse(&mut self, definitions: Vec) -> Result<(), InputParserError> { for definition in definitions { @@ -72,26 +62,9 @@ impl MainInput { Ok(()) } - /// Parses constants input definitions and stores them in `self`. - pub fn parse_constants(&mut self, definitions: Vec) -> Result<(), InputParserError> { - for definition in definitions { - let name = definition.parameter.variable.value; - let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; - - self.insert_constant(name, Some(value)); - } - - Ok(()) - } - /// Returns an `Option` of the main function input at `name`. As a second /// value in a tuple returns flag whether input is defined as a constant in input file. - pub fn get(&self, name: &str) -> Option<(Option, bool)> { - // As we check key presence in IndexMap unwraps below can be considered secure. - match (self.input.contains_key(name), self.constants.contains_key(name)) { - (true, _) => Some((self.input.get(name).cloned().unwrap(), false)), - (_, true) => Some((self.constants.get(name).cloned().unwrap(), true)), - (_, _) => None, - } + pub fn get(&self, name: &str) -> Option> { + self.input.get(name).cloned() } } diff --git a/ast/src/input/program_input/mod.rs b/ast/src/input/program_input/mod.rs index dfda5a073f..9245144b3b 100644 --- a/ast/src/input/program_input/mod.rs +++ b/ast/src/input/program_input/mod.rs @@ -16,6 +16,9 @@ #![allow(clippy::module_inception)] +pub mod const_input; +pub use const_input::*; + pub mod main_input; pub use main_input::*; diff --git a/ast/src/input/program_input/program_input.rs b/ast/src/input/program_input/program_input.rs index c7d86a6d7f..6938817e61 100644 --- a/ast/src/input/program_input/program_input.rs +++ b/ast/src/input/program_input/program_input.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{InputValue, MainInput, Registers}; +use crate::{ConstInput, InputValue, MainInput, Registers}; use leo_input::{ sections::{Header, Section}, InputParserError, @@ -23,6 +23,7 @@ use leo_input::{ #[derive(Clone, PartialEq, Eq, Default)] pub struct ProgramInput { pub main: MainInput, + pub constants: ConstInput, registers: Registers, } @@ -36,18 +37,24 @@ impl ProgramInput { /// Called during constraint synthesis to provide private input values. pub fn empty(&self) -> Self { let main = self.main.empty(); + let constants = self.constants.empty(); let registers = self.registers.empty(); - Self { main, registers } + Self { + main, + constants, + registers, + } } pub fn len(&self) -> usize { let mut len = 0; - // add main input variables + // Add main input variables and constants. len += self.main.len(); + len += self.constants.len(); - // add registers + // Add registers. if self.registers.is_present() { len += 1; } @@ -58,7 +65,7 @@ impl ProgramInput { /// Parse each input included in a file and store them in `self`. pub fn parse(&mut self, section: Section) -> Result<(), InputParserError> { match section.header { - Header::Constants(_constants) => self.main.parse_constants(section.definitions), + Header::Constants(_constants) => self.constants.parse(section.definitions), Header::Main(_main) => self.main.parse(section.definitions), Header::Registers(_registers) => self.registers.parse(section.definitions), header => Err(InputParserError::input_section_header(header)), @@ -67,10 +74,15 @@ impl ProgramInput { /// Returns the main function input value with the given `name` #[allow(clippy::ptr_arg)] - pub fn get(&self, name: &String) -> Option<(Option, bool)> { + pub fn get(&self, name: &String) -> Option> { self.main.get(name) } + #[allow(clippy::ptr_arg)] + pub fn get_constant(&self, name: &String) -> Option> { + self.constants.get(name) + } + /// Returns the runtime register input values pub fn get_registers(&self) -> &Registers { &self.registers diff --git a/compiler/src/function/main_function.rs b/compiler/src/function/main_function.rs index 4833f4958e..dd94ebf4ed 100644 --- a/compiler/src/function/main_function.rs +++ b/compiler/src/function/main_function.rs @@ -62,29 +62,33 @@ impl<'a, F: PrimeField, G: GroupType> ConstrainedProgram<'a, F, G> { let input_variable = input_variable.get().borrow(); let name = input_variable.name.name.clone(); - let (input_option, is_const) = input.get(&name).ok_or_else(|| { - FunctionError::input_not_found(name.clone(), &function.span.clone().unwrap_or_default()) - })?; - - let input_value = if is_const { - self.parse_constant_main_function_input( + let input_value = match (input.get(&name), input.get_constant(&name)) { + // If input option is found in [main] section. + (Some(input_option), _) => self.parse_constant_main_function_input( cs, &input_variable.type_.clone(), &name, input_option, &function.span.clone().unwrap_or_default(), - )? - } else { - self.allocate_main_function_input( + )?, + // If input option is found in [constants] section. + (_, Some(input_option)) => self.allocate_main_function_input( cs, &input_variable.type_.clone(), &name, input_option, &function.span.clone().unwrap_or_default(), - )? + )?, + // When not found - Error out. + (_, _) => { + return Err(FunctionError::input_not_found( + name.clone(), + &function.span.clone().unwrap_or_default(), + )); + } }; - // Store a new variable for every allocated main function input + // Store a new variable for every function input. self.store(input_variable.id, input_value); } arguments.push(Cell::new(&*function.scope.alloc_expression(Expression::VariableRef(