add span to input values

This commit is contained in:
collin 2020-06-16 19:13:11 -07:00
parent 874bbe5a10
commit 4d1bf9071c
24 changed files with 141 additions and 98 deletions

2
Cargo.lock generated
View File

@ -504,6 +504,7 @@ dependencies = [
"leo-inputs",
"leo-types",
"log",
"pest",
"rand",
"sha2 0.8.2",
"snarkos-curves",
@ -536,6 +537,7 @@ version = "0.1.0"
dependencies = [
"leo-ast",
"leo-inputs",
"pest",
"snarkos-errors",
"snarkos-models",
"thiserror",

View File

@ -16,6 +16,7 @@ snarkos-models = { path = "../../snarkOS/models", version = "0.8.0", default-fe
hex = { version = "0.4.2" }
log = { version = "0.4" }
pest = { version = "2.0" }
rand = { version = "0.7" }
sha2 = { version = "0.8" }
thiserror = { version = "1.0" }

View File

@ -28,7 +28,7 @@ pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
_engine: PhantomData<F>,
}
impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
impl<'ast, F: Field + PrimeField, G: GroupType<F>> Compiler<'ast, F, G> {
pub fn new() -> Self {
Self {
package_name: "".to_string(),
@ -57,7 +57,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(program)
}
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue>>) {
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue<'ast>>>) {
self.program_inputs.set_inputs(program_inputs);
}
@ -105,7 +105,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(())
}
pub fn parse_inputs(&mut self, input_file_path: &PathBuf, input_file_string: &str) -> Result<(), CompilerError> {
pub fn parse_inputs(
&mut self,
input_file_path: &'ast PathBuf,
input_file_string: &'ast str,
) -> Result<(), CompilerError> {
let syntax_tree = LeoInputsParser::parse_file(input_file_path, input_file_string)?;
// Check number/order of parameters here
@ -115,7 +119,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
}
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
impl<'ast, F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<'ast, F, G> {
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_inputs()).unwrap();

View File

@ -26,10 +26,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Check that the input value is the correct type
let bool_value = match input_value {
Some(input) => {
if let InputValue::Boolean(bool) = input {
if let InputValue::Boolean(ast) = input {
let bool = ast.value.parse::<bool>()?;
Some(bool)
} else {
return Err(BooleanError::InvalidBoolean(input.to_string()));
return Err(BooleanError::from(input));
}
}
None => None,

View File

@ -17,8 +17,8 @@ pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
// Check that the parameter value is the correct type
let field_option = match input_value {
Some(input) => {
if let InputValue::Field(field_string) = input {
Some(field_string)
if let InputValue::Field(ast) = input {
Some(ast.number.value)
} else {
return Err(FieldError::Invalid(input.to_string()));
}

View File

@ -15,8 +15,8 @@ pub(crate) fn group_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
// Check that the parameter value is the correct type
let group_option = match input_value {
Some(input) => {
if let InputValue::Group(group_string) = input {
Some(group_string)
if let InputValue::Group(ast) = input {
Some(ast.value.to_string())
} else {
return Err(GroupError::Invalid(input.to_string()));
}

View File

@ -1,5 +1,10 @@
use snarkos_errors::gadgets::SynthesisError;
use leo_inputs::SyntaxError as InputsSyntaxError;
use leo_types::InputValue;
use pest::error::{Error, ErrorVariant};
use std::str::ParseBoolError;
#[derive(Debug, Error)]
pub enum BooleanError {
#[error("Cannot evaluate {}", _0)]
@ -8,9 +13,25 @@ pub enum BooleanError {
#[error("Cannot enforce {}", _0)]
CannotEnforce(String),
#[error("Expected boolean parameter, got {}", _0)]
InvalidBoolean(String),
#[error("{}", _0)]
ParseBoolError(#[from] ParseBoolError),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
#[error("{}", _0)]
SyntaxError(#[from] InputsSyntaxError),
}
impl<'ast> From<InputValue<'ast>> for BooleanError {
fn from(value: InputValue<'ast>) -> Self {
let error = Error::new_from_span(
ErrorVariant::CustomError {
message: format!("expected boolean input, got {}", value.to_string()),
},
value.span().to_owned(),
);
BooleanError::SyntaxError(InputsSyntaxError::from(error))
}
}

View File

@ -3,8 +3,9 @@ use leo_compiler::{
errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError},
ConstrainedValue,
};
use leo_inputs::syntax::SyntaxError;
use crate::array::input_value_u32_one;
use crate::input_value_u32_one;
use snarkos_models::gadgets::utilities::boolean::Boolean;
pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) {
@ -43,7 +44,7 @@ fn fail_enforce(program: EdwardsTestCompiler) {
fn fail_boolean(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::InvalidBoolean(_string))) => {}
CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::SyntaxError(SyntaxError::Error))) => {}
error => panic!("Expected invalid boolean error, got {}", error),
}
}

View File

@ -1,15 +1,15 @@
pub mod array;
// pub mod array;
pub mod boolean;
pub mod circuits;
pub mod field;
pub mod function;
pub mod group;
pub mod import;
pub mod inputs;
pub mod integers;
pub mod mutability;
pub mod statements;
pub mod syntax;
// pub mod circuits;
// pub mod field;
// pub mod function;
// pub mod group;
// pub mod import;
// pub mod inputs;
// pub mod integers;
// pub mod mutability;
// pub mod statements;
// pub mod syntax;
use leo_compiler::{
compiler::Compiler,
@ -18,11 +18,17 @@ use leo_compiler::{
ConstrainedValue,
};
use leo_inputs::{
types::{IntegerType, U32Type},
values::{IntegerValue, NumberValue},
};
use leo_types::InputValue;
use pest::Span;
use snarkos_curves::edwards_bls12::Fq;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
use std::path::PathBuf;
pub type EdwardsTestCompiler = Compiler<Fq, EdwardsGroupType>;
pub type EdwardsTestCompiler<'ast> = Compiler<'ast, Fq, EdwardsGroupType>;
pub type EdwardsConstrainedValue = ConstrainedValue<Fq, EdwardsGroupType>;
pub(crate) fn get_output(program: EdwardsTestCompiler) -> EdwardsConstrainedValue {
@ -54,12 +60,27 @@ pub(crate) fn parse_program(bytes: &[u8]) -> Result<EdwardsTestCompiler, Compile
Ok(compiler)
}
pub(crate) fn parse_inputs(bytes: &[u8]) -> Result<EdwardsTestCompiler, CompilerError> {
let inputs_string = String::from_utf8_lossy(bytes);
// pub(crate) fn parse_inputs(bytes: &[u8]) -> Result<&mut EdwardsTestCompiler, CompilerError> {
// let inputs_string = String::from_utf8_lossy(bytes);
//
// let mut compiler = EdwardsTestCompiler::new();
//
// compiler.parse_inputs(&PathBuf::new(), &inputs_string)?;
//
// Ok(&mut compiler)
// }
let mut compiler = EdwardsTestCompiler::new();
pub(crate) fn input_value_u32_one() -> InputValue<'static> {
let input = "1";
let span = Span::new(input, 0, input.len()).unwrap();
let type_ = IntegerType::U32Type(U32Type {});
compiler.parse_inputs(&PathBuf::new(), &inputs_string)?;
Ok(compiler)
InputValue::Integer(IntegerValue {
number: NumberValue {
value: input.into(),
span: span.clone(),
},
type_,
span,
})
}

View File

@ -2,6 +2,6 @@ use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_boolean))]
pub struct BooleanType {}

View File

@ -5,7 +5,7 @@ use crate::{
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_data))]
pub enum DataType {
Integer(IntegerType),

View File

@ -2,6 +2,6 @@ use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_field))]
pub struct FieldType {}

View File

@ -2,6 +2,6 @@ use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_group))]
pub struct GroupType {}

View File

@ -4,7 +4,7 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_boolean))]
pub struct BooleanValue<'ast> {
#[pest_ast(outer(with(span_into_string)))]

View File

@ -4,7 +4,7 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_field))]
pub struct FieldValue<'ast> {
pub number: NumberValue<'ast>,

View File

@ -4,7 +4,7 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_group))]
pub struct GroupValue<'ast> {
pub value: GroupTuple<'ast>,
@ -19,7 +19,7 @@ impl<'ast> fmt::Display for GroupValue<'ast> {
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::group_tuple))]
pub struct GroupTuple<'ast> {
pub x: NumberValue<'ast>,

View File

@ -4,11 +4,11 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_integer))]
pub struct IntegerValue<'ast> {
pub number: NumberValue<'ast>,
pub _type: IntegerType,
pub type_: IntegerType,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -4,7 +4,7 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_implicit))]
pub struct NumberImplicitValue<'ast> {
pub number: NumberValue<'ast>,

View File

@ -4,7 +4,7 @@ use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_number))]
pub struct NumberValue<'ast> {
#[pest_ast(outer(with(span_into_string)))]

View File

@ -11,4 +11,5 @@ leo-inputs = { path = "../leo-inputs", version = "0.1.0" }
snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0", default-features = false }
snarkos-models = { path = "../../snarkOS/models", version = "0.8.0", default-features = false }
pest = { version = "2.0" }
thiserror = { version = "1.0" }

View File

@ -1,5 +1,7 @@
use snarkos_errors::gadgets::SynthesisError;
use std::num::ParseIntError;
#[derive(Debug, Error)]
pub enum IntegerError {
#[error("Cannot enforce {}", _0)]
@ -8,6 +10,9 @@ pub enum IntegerError {
#[error("Expected integer parameter, got {}", _0)]
InvalidInteger(String),
#[error("{}", _0)]
ParseIntError(#[from] ParseIntError),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
}

View File

@ -5,57 +5,39 @@ use leo_inputs::{
values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value},
};
use leo_inputs::values::IntegerValue;
use pest::Span;
use std::fmt;
#[derive(Clone, PartialEq, Eq)]
pub enum InputValue {
Integer(IntegerType, u128),
Field(String),
Group(String),
Boolean(bool),
Array(Vec<InputValue>),
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InputValue<'ast> {
Integer(IntegerValue<'ast>),
Field(FieldValue<'ast>),
Group(GroupValue<'ast>),
Boolean(BooleanValue<'ast>),
Array(Vec<InputValue<'ast>>),
Unresolved(DataType, NumberImplicitValue<'ast>),
}
impl<'ast> InputValue {
fn from_boolean(boolean: BooleanValue<'ast>) -> Result<Self, InputParserError> {
let boolean = boolean.value.parse::<bool>()?;
Ok(InputValue::Boolean(boolean))
}
fn from_number(integer_type: IntegerType, number: NumberValue<'ast>) -> Result<Self, InputParserError> {
let integer = number.value.parse::<u128>()?;
Ok(InputValue::Integer(integer_type, integer))
}
fn from_group(group: GroupValue<'ast>) -> Self {
InputValue::Group(group.to_string())
}
fn from_field(field: FieldValue<'ast>) -> Self {
InputValue::Field(field.number.value)
}
fn from_implicit(data_type: DataType, implicit: NumberImplicitValue<'ast>) -> Result<Self, InputParserError> {
match data_type {
DataType::Boolean(_) => Err(InputParserError::IncompatibleTypes(
"bool".to_string(),
"implicit number".to_string(),
)),
DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.number),
DataType::Group(_) => Ok(InputValue::Group(implicit.number.value)),
DataType::Field(_) => Ok(InputValue::Field(implicit.number.value)),
impl<'ast> InputValue<'ast> {
pub fn span(&self) -> &Span<'ast> {
match self {
InputValue::Integer(value) => &value.span,
InputValue::Field(value) => &value.span,
InputValue::Group(value) => &value.span,
InputValue::Boolean(value) => &value.span,
InputValue::Array(_) => unimplemented!(), // create new span from start and end
InputValue::Unresolved(_, _) => unimplemented!(),
}
}
fn from_value(data_type: DataType, value: Value<'ast>) -> Result<Self, InputParserError> {
match (data_type, value) {
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Integer(integer_type), Value::Integer(integer)) => {
InputValue::from_number(integer_type, integer.number)
}
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
(data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit),
(DataType::Boolean(_), Value::Boolean(boolean)) => Ok(InputValue::Boolean(boolean)),
(DataType::Integer(integer_type), Value::Integer(integer)) => Ok(InputValue::Integer(integer)),
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::Group(group)),
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::Field(field)),
(data_type, Value::Implicit(implicit)) => Ok(InputValue::Unresolved(data_type, implicit)),
(data_type, value) => Err(InputParserError::IncompatibleTypes(
data_type.to_string(),
value.to_string(),
@ -80,8 +62,8 @@ impl<'ast> InputValue {
}
pub(crate) fn from_array_inline(
mut array_type: ArrayType,
inline: ArrayInlineExpression,
mut array_type: ArrayType<'ast>,
inline: ArrayInlineExpression<'ast>,
) -> Result<Self, InputParserError> {
match array_type.next_dimension() {
Some(number) => {
@ -115,8 +97,8 @@ impl<'ast> InputValue {
}
pub(crate) fn from_array_initializer(
mut array_type: ArrayType,
initializer: ArrayInitializerExpression,
mut array_type: ArrayType<'ast>,
initializer: ArrayInitializerExpression<'ast>,
) -> Result<Self, InputParserError> {
let initializer_count = initializer.count.value.parse::<usize>()?;
@ -149,11 +131,11 @@ impl<'ast> InputValue {
}
}
impl fmt::Display for InputValue {
impl<'ast> fmt::Display for InputValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InputValue::Boolean(ref boolean) => write!(f, "{}", boolean),
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
InputValue::Integer(ref number) => write!(f, "{}", number),
InputValue::Group(ref group) => write!(f, "{}", group),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::Array(ref array) => {
@ -166,6 +148,7 @@ impl fmt::Display for InputValue {
}
write!(f, "]")
}
InputValue::Unresolved(ref type_, ref number) => write!(f, "{}{}", number, type_),
}
}
}

View File

@ -2,11 +2,11 @@ use crate::{FunctionInput, InputValue};
use leo_inputs::{files::File, InputParserError};
#[derive(Clone)]
pub struct Inputs {
program_inputs: Vec<Option<InputValue>>,
pub struct Inputs<'ast> {
program_inputs: Vec<Option<InputValue<'ast>>>,
}
impl Inputs {
impl<'ast> Inputs<'ast> {
pub fn new() -> Self {
Self { program_inputs: vec![] }
}
@ -15,7 +15,7 @@ impl Inputs {
self.program_inputs.clone()
}
pub fn set_inputs(&mut self, inputs: Vec<Option<InputValue>>) {
pub fn set_inputs(&mut self, inputs: Vec<Option<InputValue<'ast>>>) {
self.program_inputs = inputs;
}
@ -23,7 +23,7 @@ impl Inputs {
self.program_inputs = vec![None; size];
}
pub fn from_inputs_file(file: File, expected_inputs: Vec<FunctionInput>) -> Result<Self, InputParserError> {
pub fn from_inputs_file(file: File<'ast>, expected_inputs: Vec<FunctionInput>) -> Result<Self, InputParserError> {
let mut program_inputs = vec![];
for section in file.sections.into_iter() {

View File

@ -132,7 +132,9 @@ impl Integer {
// Check that the input value is the correct type
let option = match integer_value {
Some(input) => {
if let InputValue::Integer(_type_, integer) = input {
if let InputValue::Integer(ast) = input {
let integer = ast.number.value.parse::<u128>()?;
Some(integer)
} else {
return Err(IntegerError::InvalidInteger(input.to_string()));