mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-28 02:33:18 +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),
|
||||
}
|
||||
|
||||
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)]
|
||||
pub enum ConstValue {
|
||||
Int(ConstInt),
|
||||
|
@ -94,9 +94,10 @@ impl Input {
|
||||
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)]
|
||||
pub fn get(&self, name: &String) -> Option<Option<InputValue>> {
|
||||
pub fn get(&self, name: &String) -> Option<(Option<InputValue>, bool)> {
|
||||
self.program_input.get(name)
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ use indexmap::IndexMap;
|
||||
#[derive(Clone, PartialEq, Eq, Default)]
|
||||
pub struct MainInput {
|
||||
input: IndexMap<String, Option<InputValue>>,
|
||||
constants: IndexMap<String, Option<InputValue>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
@ -34,16 +35,21 @@ 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;
|
||||
});
|
||||
|
||||
Self { input }
|
||||
constants.iter_mut().for_each(|(_name, value)| {
|
||||
*value = None;
|
||||
});
|
||||
|
||||
Self { input, constants }
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.input.len()
|
||||
self.input.len() + self.constants.len()
|
||||
}
|
||||
|
||||
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> {
|
||||
for definition in definitions {
|
||||
let name = definition.parameter.variable.value;
|
||||
let is_const = definition.const_.is_some();
|
||||
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(())
|
||||
}
|
||||
|
||||
/// Returns an `Option` of the main function input at `name`
|
||||
pub fn get(&self, name: &str) -> Option<Option<InputValue>> {
|
||||
self.input.get(name).cloned()
|
||||
/// 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<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`
|
||||
#[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)
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ use leo_input::types::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// Explicit integer type
|
||||
/// Explicit integer type.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum IntegerType {
|
||||
U8,
|
||||
|
@ -172,7 +172,6 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
|
||||
e
|
||||
})?;
|
||||
|
||||
self.program_input.parse_input(input_syntax_tree).map_err(|mut e| {
|
||||
e.set_path(
|
||||
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>,
|
||||
span: &Span,
|
||||
) -> Result<ConstrainedValue<'a, F, G>, IntegerError> {
|
||||
match value {
|
||||
// ConstrainedValue::Integer(i) => Ok(ConstrainedValue::Integer(i.not())),
|
||||
value => Err(IntegerError::cannot_evaluate(format!("~{}", value), span)),
|
||||
}
|
||||
Err(IntegerError::cannot_evaluate(format!("~{}", value), span))
|
||||
}
|
||||
|
@ -26,15 +26,19 @@ use crate::{
|
||||
group::input::group_from_input,
|
||||
ConstrainedValue,
|
||||
},
|
||||
FieldType,
|
||||
GroupType,
|
||||
Integer,
|
||||
};
|
||||
|
||||
use leo_asg::Type;
|
||||
use leo_ast::{InputValue, Span};
|
||||
use leo_asg::{ConstInt, Type};
|
||||
use leo_ast::{InputValue, IntegerType, Span};
|
||||
use snarkvm_fields::PrimeField;
|
||||
use snarkvm_gadgets::traits::utilities::boolean::Boolean;
|
||||
use snarkvm_r1cs::ConstraintSystem;
|
||||
|
||||
// use crate::value::{Address, ConstrainedValue, Integer};
|
||||
|
||||
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
pub fn allocate_main_function_input<CS: ConstraintSystem<F>>(
|
||||
&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 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())
|
||||
})?;
|
||||
let input_value = self.allocate_main_function_input(
|
||||
cs,
|
||||
&input_variable.type_.clone(),
|
||||
&name,
|
||||
input_option,
|
||||
&function.span.clone().unwrap_or_default(),
|
||||
)?;
|
||||
|
||||
let input_value = if is_const {
|
||||
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(
|
||||
cs,
|
||||
&input_variable.type_.clone(),
|
||||
&name,
|
||||
input_option,
|
||||
&function.span.clone().unwrap_or_default(),
|
||||
)?
|
||||
};
|
||||
|
||||
// Store a new variable for every allocated main function input
|
||||
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
|
||||
// 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 pest::Span;
|
||||
@ -22,9 +23,17 @@ use pest_ast::FromPest;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::definition))]
|
||||
pub struct Definition<'ast> {
|
||||
pub const_: Option<Const<'ast>>,
|
||||
pub parameter: Parameter<'ast>,
|
||||
pub expression: Expression<'ast>,
|
||||
pub line_end: LineEnd,
|
||||
#[pest_ast(outer())]
|
||||
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 use definition::*;
|
||||
|
||||
pub mod const_;
|
||||
pub use const_::*;
|
||||
|
@ -218,8 +218,11 @@ header = { main | record | registers | state_leaf | state | identifier }
|
||||
|
||||
/// Definitions
|
||||
|
||||
// Declared in definition/const_modifier.rs
|
||||
const_ = { "const" }
|
||||
|
||||
// Declared in definition/definition.rs
|
||||
definition = { parameter ~ "=" ~ expression ~ LINE_END }
|
||||
definition = { const_? ~ parameter ~ "=" ~ expression ~ LINE_END }
|
||||
|
||||
/// Table
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user