mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-01 02:08:31 +03:00
staging commit with const input syntax and constants processing
This commit is contained in:
parent
c47ab84b1b
commit
47e4d23ab1
@ -91,6 +91,16 @@ pub enum GroupValue {
|
|||||||
Tuple(GroupCoordinate, GroupCoordinate),
|
Tuple(GroupCoordinate, GroupCoordinate),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<leo_ast::GroupValue> for GroupValue {
|
||||||
|
fn from(other: leo_ast::GroupValue) -> Self {
|
||||||
|
use leo_ast::GroupValue::*;
|
||||||
|
match other {
|
||||||
|
Single(value, _) => GroupValue::Single(value),
|
||||||
|
Tuple(value) => GroupValue::Tuple(GroupCoordinate::from(&value.x), GroupCoordinate::from(&value.y)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ConstValue {
|
pub enum ConstValue {
|
||||||
Int(ConstInt),
|
Int(ConstInt),
|
||||||
|
@ -94,9 +94,10 @@ impl Input {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the main function input value with the given `name`
|
/// Returns the main function input value with the given `name`, second parameter
|
||||||
|
/// is a boolean indicating whether parameter is const.
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
pub fn get(&self, name: &String) -> Option<Option<InputValue>> {
|
pub fn get(&self, name: &String) -> Option<(Option<InputValue>, bool)> {
|
||||||
self.program_input.get(name)
|
self.program_input.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use indexmap::IndexMap;
|
|||||||
#[derive(Clone, PartialEq, Eq, Default)]
|
#[derive(Clone, PartialEq, Eq, Default)]
|
||||||
pub struct MainInput {
|
pub struct MainInput {
|
||||||
input: IndexMap<String, Option<InputValue>>,
|
input: IndexMap<String, Option<InputValue>>,
|
||||||
|
constants: IndexMap<String, Option<InputValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
@ -34,16 +35,21 @@ impl MainInput {
|
|||||||
/// Called during constraint synthesis to provide private input variables.
|
/// Called during constraint synthesis to provide private input variables.
|
||||||
pub fn empty(&self) -> Self {
|
pub fn empty(&self) -> Self {
|
||||||
let mut input = self.input.clone();
|
let mut input = self.input.clone();
|
||||||
|
let mut constants = self.constants.clone();
|
||||||
|
|
||||||
input.iter_mut().for_each(|(_name, value)| {
|
input.iter_mut().for_each(|(_name, value)| {
|
||||||
*value = None;
|
*value = None;
|
||||||
});
|
});
|
||||||
|
|
||||||
Self { input }
|
constants.iter_mut().for_each(|(_name, value)| {
|
||||||
|
*value = None;
|
||||||
|
});
|
||||||
|
|
||||||
|
Self { input, constants }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.input.len()
|
self.input.len() + self.constants.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, key: String, value: Option<InputValue>) {
|
pub fn insert(&mut self, key: String, value: Option<InputValue>) {
|
||||||
@ -54,16 +60,27 @@ impl MainInput {
|
|||||||
pub fn parse(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
|
pub fn parse(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
|
||||||
for definition in definitions {
|
for definition in definitions {
|
||||||
let name = definition.parameter.variable.value;
|
let name = definition.parameter.variable.value;
|
||||||
|
let is_const = definition.const_.is_some();
|
||||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||||
|
|
||||||
self.insert(name, Some(value));
|
if is_const {
|
||||||
|
self.constants.insert(name, Some(value));
|
||||||
|
} else {
|
||||||
|
self.input.insert(name, Some(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an `Option` of the main function input at `name`
|
/// Returns an `Option` of the main function input at `name`. As a second
|
||||||
pub fn get(&self, name: &str) -> Option<Option<InputValue>> {
|
/// value in a tuple returns flag whether input is defined as a constant in input file.
|
||||||
self.input.get(name).cloned()
|
pub fn get(&self, name: &str) -> Option<(Option<InputValue>, 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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ impl ProgramInput {
|
|||||||
|
|
||||||
/// Returns the main function input value with the given `name`
|
/// Returns the main function input value with the given `name`
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
pub fn get(&self, name: &String) -> Option<Option<InputValue>> {
|
pub fn get(&self, name: &String) -> Option<(Option<InputValue>, bool)> {
|
||||||
self.main.get(name)
|
self.main.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use leo_input::types::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// Explicit integer type
|
/// Explicit integer type.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum IntegerType {
|
pub enum IntegerType {
|
||||||
U8,
|
U8,
|
||||||
|
@ -172,7 +172,6 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
|
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.program_input.parse_input(input_syntax_tree).map_err(|mut e| {
|
self.program_input.parse_input(input_syntax_tree).map_err(|mut e| {
|
||||||
e.set_path(
|
e.set_path(
|
||||||
input_path.to_str().unwrap_or_default(),
|
input_path.to_str().unwrap_or_default(),
|
||||||
|
@ -25,8 +25,5 @@ pub fn evaluate_bit_not<'a, F: PrimeField, G: GroupType<F>>(
|
|||||||
value: ConstrainedValue<'a, F, G>,
|
value: ConstrainedValue<'a, F, G>,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<'a, F, G>, IntegerError> {
|
) -> Result<ConstrainedValue<'a, F, G>, IntegerError> {
|
||||||
match value {
|
Err(IntegerError::cannot_evaluate(format!("~{}", value), span))
|
||||||
// ConstrainedValue::Integer(i) => Ok(ConstrainedValue::Integer(i.not())),
|
|
||||||
value => Err(IntegerError::cannot_evaluate(format!("~{}", value), span)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,19 @@ use crate::{
|
|||||||
group::input::group_from_input,
|
group::input::group_from_input,
|
||||||
ConstrainedValue,
|
ConstrainedValue,
|
||||||
},
|
},
|
||||||
|
FieldType,
|
||||||
GroupType,
|
GroupType,
|
||||||
Integer,
|
Integer,
|
||||||
};
|
};
|
||||||
|
|
||||||
use leo_asg::Type;
|
use leo_asg::{ConstInt, Type};
|
||||||
use leo_ast::{InputValue, Span};
|
use leo_ast::{InputValue, IntegerType, Span};
|
||||||
use snarkvm_fields::PrimeField;
|
use snarkvm_fields::PrimeField;
|
||||||
|
use snarkvm_gadgets::traits::utilities::boolean::Boolean;
|
||||||
use snarkvm_r1cs::ConstraintSystem;
|
use snarkvm_r1cs::ConstraintSystem;
|
||||||
|
|
||||||
|
// use crate::value::{Address, ConstrainedValue, Integer};
|
||||||
|
|
||||||
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||||
pub fn allocate_main_function_input<CS: ConstraintSystem<F>>(
|
pub fn allocate_main_function_input<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -62,3 +66,48 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Process constant inputs and return ConstrainedValue with constant value in it.
|
||||||
|
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||||
|
pub fn parse_constant_main_function_input<CS: ConstraintSystem<F>>(
|
||||||
|
&mut self,
|
||||||
|
// TODO: remove unnecessary arguments
|
||||||
|
_cs: &mut CS,
|
||||||
|
_type_: &Type,
|
||||||
|
name: &str,
|
||||||
|
input_option: Option<InputValue>,
|
||||||
|
span: &Span,
|
||||||
|
) -> Result<ConstrainedValue<'a, F, G>, FunctionError> {
|
||||||
|
let value = input_option.unwrap();
|
||||||
|
|
||||||
|
Ok(match value {
|
||||||
|
InputValue::Address(value) => ConstrainedValue::Address(Address::constant(value, span)?),
|
||||||
|
InputValue::Boolean(value) => ConstrainedValue::Boolean(Boolean::constant(value)),
|
||||||
|
InputValue::Field(value) => ConstrainedValue::Field(FieldType::constant(value, span)?),
|
||||||
|
InputValue::Group(value) => ConstrainedValue::Group(G::constant(&value.into(), span)?),
|
||||||
|
InputValue::Integer(integer_type, value) => {
|
||||||
|
let integer = IntegerType::from(integer_type);
|
||||||
|
let const_int = match integer {
|
||||||
|
IntegerType::U8 => ConstInt::U8(value.parse::<u8>().unwrap()),
|
||||||
|
IntegerType::U16 => ConstInt::U16(value.parse::<u16>().unwrap()),
|
||||||
|
IntegerType::U32 => ConstInt::U32(value.parse::<u32>().unwrap()),
|
||||||
|
IntegerType::U64 => ConstInt::U64(value.parse::<u64>().unwrap()),
|
||||||
|
IntegerType::U128 => ConstInt::U128(value.parse::<u128>().unwrap()),
|
||||||
|
|
||||||
|
IntegerType::I8 => ConstInt::I8(value.parse::<i8>().unwrap()),
|
||||||
|
IntegerType::I16 => ConstInt::I16(value.parse::<i16>().unwrap()),
|
||||||
|
IntegerType::I32 => ConstInt::I32(value.parse::<i32>().unwrap()),
|
||||||
|
IntegerType::I64 => ConstInt::I64(value.parse::<i64>().unwrap()),
|
||||||
|
IntegerType::I128 => ConstInt::I128(value.parse::<i128>().unwrap()),
|
||||||
|
};
|
||||||
|
|
||||||
|
ConstrainedValue::Integer(Integer::new(&const_int))
|
||||||
|
}
|
||||||
|
// TODO: array and tuple values.
|
||||||
|
// InputValue::Array(Vec<InputValue>) => ,
|
||||||
|
// InputValue::Tuple(Vec<InputValue>),
|
||||||
|
// TODO: rework this error to something better fitting into context.
|
||||||
|
_ => return Err(FunctionError::input_not_found(name.to_string(), span)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -61,16 +61,28 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
{
|
{
|
||||||
let input_variable = input_variable.get().borrow();
|
let input_variable = input_variable.get().borrow();
|
||||||
let name = input_variable.name.name.clone();
|
let name = input_variable.name.name.clone();
|
||||||
let input_option = input.get(&name).ok_or_else(|| {
|
|
||||||
|
let (input_option, is_const) = input.get(&name).ok_or_else(|| {
|
||||||
FunctionError::input_not_found(name.clone(), &function.span.clone().unwrap_or_default())
|
FunctionError::input_not_found(name.clone(), &function.span.clone().unwrap_or_default())
|
||||||
})?;
|
})?;
|
||||||
let input_value = self.allocate_main_function_input(
|
|
||||||
cs,
|
let input_value = if is_const {
|
||||||
&input_variable.type_.clone(),
|
self.parse_constant_main_function_input(
|
||||||
&name,
|
cs,
|
||||||
input_option,
|
&input_variable.type_.clone(),
|
||||||
&function.span.clone().unwrap_or_default(),
|
&name,
|
||||||
)?;
|
input_option,
|
||||||
|
&function.span.clone().unwrap_or_default(),
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
self.allocate_main_function_input(
|
||||||
|
cs,
|
||||||
|
&input_variable.type_.clone(),
|
||||||
|
&name,
|
||||||
|
input_option,
|
||||||
|
&function.span.clone().unwrap_or_default(),
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
// Store a new variable for every allocated main function input
|
// Store a new variable for every allocated main function input
|
||||||
self.store(input_variable.id, input_value);
|
self.store(input_variable.id, input_value);
|
||||||
|
27
input/src/definitions/const_.rs
Normal file
27
input/src/definitions/const_.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::ast::Rule;
|
||||||
|
|
||||||
|
use pest::Span;
|
||||||
|
use pest_ast::FromPest;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||||
|
#[pest_ast(rule(Rule::const_))]
|
||||||
|
pub struct Const<'ast> {
|
||||||
|
#[pest_ast(outer())]
|
||||||
|
pub span: Span<'ast>,
|
||||||
|
}
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::Const;
|
||||||
use crate::{ast::Rule, common::LineEnd, expressions::Expression, parameters::Parameter};
|
use crate::{ast::Rule, common::LineEnd, expressions::Expression, parameters::Parameter};
|
||||||
|
|
||||||
use pest::Span;
|
use pest::Span;
|
||||||
@ -22,9 +23,17 @@ use pest_ast::FromPest;
|
|||||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||||
#[pest_ast(rule(Rule::definition))]
|
#[pest_ast(rule(Rule::definition))]
|
||||||
pub struct Definition<'ast> {
|
pub struct Definition<'ast> {
|
||||||
|
pub const_: Option<Const<'ast>>,
|
||||||
pub parameter: Parameter<'ast>,
|
pub parameter: Parameter<'ast>,
|
||||||
pub expression: Expression<'ast>,
|
pub expression: Expression<'ast>,
|
||||||
pub line_end: LineEnd,
|
pub line_end: LineEnd,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
pub span: Span<'ast>,
|
pub span: Span<'ast>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ast> Definition<'ast> {
|
||||||
|
/// Check whether `const` keyword is placed before definition.
|
||||||
|
pub fn is_const(&self) -> bool {
|
||||||
|
self.const_.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,3 +16,6 @@
|
|||||||
|
|
||||||
pub mod definition;
|
pub mod definition;
|
||||||
pub use definition::*;
|
pub use definition::*;
|
||||||
|
|
||||||
|
pub mod const_;
|
||||||
|
pub use const_::*;
|
||||||
|
@ -218,8 +218,11 @@ header = { main | record | registers | state_leaf | state | identifier }
|
|||||||
|
|
||||||
/// Definitions
|
/// Definitions
|
||||||
|
|
||||||
|
// Declared in definition/const_modifier.rs
|
||||||
|
const_ = { "const" }
|
||||||
|
|
||||||
// Declared in definition/definition.rs
|
// Declared in definition/definition.rs
|
||||||
definition = { parameter ~ "=" ~ expression ~ LINE_END }
|
definition = { const_? ~ parameter ~ "=" ~ expression ~ LINE_END }
|
||||||
|
|
||||||
/// Table
|
/// Table
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user