From 6919f62d4489776ce74ef8676256b53ef17d0aab Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 6 May 2020 12:29:33 -0700 Subject: [PATCH 01/15] impl leo-inputs --- Cargo.lock | 17 ++ Cargo.toml | 3 +- leo-inputs/Cargo.toml | 19 ++ leo-inputs/input.leo | 4 + leo-inputs/src/inputs_ast.rs | 263 +++++++++++++++++++ leo-inputs/src/inputs_display.rs | 204 ++++++++++++++ {compiler => leo-inputs}/src/leo-inputs.pest | 37 +-- leo-inputs/src/lib.rs | 10 + leo-inputs/src/main.rs | 17 ++ 9 files changed, 555 insertions(+), 19 deletions(-) create mode 100644 leo-inputs/Cargo.toml create mode 100644 leo-inputs/input.leo create mode 100644 leo-inputs/src/inputs_ast.rs create mode 100644 leo-inputs/src/inputs_display.rs rename {compiler => leo-inputs}/src/leo-inputs.pest (63%) create mode 100644 leo-inputs/src/lib.rs create mode 100644 leo-inputs/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index b17433959e..4f08022375 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,6 +481,7 @@ dependencies = [ "failure", "from-pest", "leo-compiler", + "leo-inputs", "log", "rand", "rand_core", @@ -531,6 +532,22 @@ dependencies = [ "snarkos-models", ] +[[package]] +name = "leo-inputs" +version = "0.1.0" +dependencies = [ + "from-pest", + "leo-compiler", + "pest", + "pest-ast", + "pest_derive", + "snarkos-algorithms", + "snarkos-curves", + "snarkos-errors", + "snarkos-gadgets", + "snarkos-models", +] + [[package]] name = "libc" version = "0.2.67" diff --git a/Cargo.toml b/Cargo.toml index 687cde3ae9..dc26a5de55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,10 +13,11 @@ name = "leo" path = "leo/main.rs" [workspace] -members = [ "benchmark", "compiler" ] +members = [ "benchmark", "compiler", "leo-inputs" ] [dependencies] leo-compiler = { path = "compiler", version = "0.1.0" } +leo-inputs = { path = "leo-inputs", version = "0.1.0"} snarkos-algorithms = { path = "../snarkOS/algorithms", version = "0.8.0" } snarkos-curves = { path = "../snarkOS/curves", version = "0.8.0" } diff --git a/leo-inputs/Cargo.toml b/leo-inputs/Cargo.toml new file mode 100644 index 0000000000..8886a317f9 --- /dev/null +++ b/leo-inputs/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "leo-inputs" +version = "0.1.0" +authors = ["The Aleo Team "] +edition = "2018" + +[dependencies] +leo-compiler = { path = "../compiler", version = "0.1.0" } + +snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" } +snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" } +snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" } +snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0" } +snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" } + +from-pest = { version = "0.3.1" } +pest = { version = "2.0" } +pest-ast = { version = "0.3.3" } +pest_derive = { version = "2.0" } \ No newline at end of file diff --git a/leo-inputs/input.leo b/leo-inputs/input.leo new file mode 100644 index 0000000000..af741c284d --- /dev/null +++ b/leo-inputs/input.leo @@ -0,0 +1,4 @@ +[main] +a: private u32 = 5 +b: public fe = 1fe +c: private bool = true \ No newline at end of file diff --git a/leo-inputs/src/inputs_ast.rs b/leo-inputs/src/inputs_ast.rs new file mode 100644 index 0000000000..21e4690cb4 --- /dev/null +++ b/leo-inputs/src/inputs_ast.rs @@ -0,0 +1,263 @@ +//! Abstract syntax tree (ast) representation from leo-inputs.pest. + +use pest::{error::Error, iterators::Pairs, Parser, Span}; +use pest_ast::FromPest; + +#[derive(Parser)] +#[grammar = "leo-inputs.pest"] +pub struct LanguageParser; + +pub fn parse(input: &str) -> Result, Error> { + LanguageParser::parse(Rule::file, input) +} + +fn span_into_string(span: Span) -> String { + span.as_str().to_string() +} + +// Visibility + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_public))] +pub struct Public {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_private))] +pub struct Private {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility))] +pub enum Visibility { + Public(Public), + Private(Private), +} + +// Types + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u32))] +pub struct U32Type<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_field))] +pub struct FieldType<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_bool))] +pub struct BooleanType<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_basic))] +pub enum BasicType<'ast> { + U32(U32Type<'ast>), + Field(FieldType<'ast>), + Boolean(BooleanType<'ast>), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_struct))] +pub struct StructType<'ast> { + pub variable: Variable<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_array))] +pub struct ArrayType<'ast> { + pub _type: BasicType<'ast>, + pub count: Value<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::_type))] +pub enum Type<'ast> { + Basic(BasicType<'ast>), + Array(ArrayType<'ast>), + Struct(StructType<'ast>), +} + +// Values + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_number))] +pub struct Number<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_u32))] +pub struct U32<'ast> { + pub number: Number<'ast>, + pub _type: Option>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_field))] +pub struct Field<'ast> { + pub number: Number<'ast>, + pub _type: FieldType<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_boolean))] +pub struct Boolean<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value))] +pub enum Value<'ast> { + Field(Field<'ast>), + Boolean(Boolean<'ast>), + U32(U32<'ast>), +} + +// Variables + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::variable))] +pub struct Variable<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// Arrays + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_inline))] +pub struct ArrayInlineExpression<'ast> { + pub expressions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_initializer))] +pub struct ArrayInitializerExpression<'ast> { + pub expression: Box>, + pub count: Value<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// Structs + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::inline_struct_member))] +pub struct InlineStructMember<'ast> { + pub variable: Variable<'ast>, + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_inline_struct))] +pub struct StructInlineExpression<'ast> { + pub variable: Variable<'ast>, + pub members: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// Expressions + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression))] +pub enum Expression<'ast> { + StructInline(StructInlineExpression<'ast>), + ArrayInline(ArrayInlineExpression<'ast>), + ArrayInitializer(ArrayInitializerExpression<'ast>), + Value(Value<'ast>), + Variable(Variable<'ast>), +} + +// Functions + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::parameter))] +pub struct Parameter<'ast> { + pub variable: Variable<'ast>, + pub visibility: Option, + pub _type: Type<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::function_name))] +pub struct FunctionName<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// Sections + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::header))] +pub struct Header<'ast> { + pub function_name: FunctionName<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::assignment))] +pub struct Assignment<'ast> { + pub parameter: Parameter<'ast>, + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::section))] +pub struct Section<'ast> { + pub header: Header<'ast>, + pub assignments: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// Utilities + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::EOI))] +pub struct EOI; + +// File + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::file))] +pub struct File<'ast> { + pub sections: Vec>, + pub eoi: EOI, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/inputs_display.rs b/leo-inputs/src/inputs_display.rs new file mode 100644 index 0000000000..25a12d1474 --- /dev/null +++ b/leo-inputs/src/inputs_display.rs @@ -0,0 +1,204 @@ +//! Display implementations for a Leo inputs file + +use crate::inputs_ast::{ + ArrayInitializerExpression, ArrayInlineExpression, ArrayType, Assignment, BasicType, Boolean, + BooleanType, Expression, Field, FieldType, File, Number, Parameter, Private, Section, + StructInlineExpression, StructType, Type, U32Type, Value, Variable, Visibility, U32, +}; + +use std::fmt; + +// Visibility + +impl fmt::Display for Visibility { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Visibility::Private(_private) => write!(f, "private"), + Visibility::Public(_public) => write!(f, "public"), + } + } +} + +// Types + +impl<'ast> fmt::Display for BooleanType<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "bool") + } +} + +impl<'ast> fmt::Display for FieldType<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "fe") + } +} + +impl<'ast> fmt::Display for U32Type<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "u32") + } +} + +impl<'ast> fmt::Display for BasicType<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + BasicType::Boolean(bool) => write!(f, "{}", bool), + BasicType::Field(field) => write!(f, "{}", field), + BasicType::U32(u32) => write!(f, "{}", u32), + } + } +} + +impl<'ast> fmt::Display for ArrayType<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}; {}]", self._type, self.count) + } +} + +impl<'ast> fmt::Display for StructType<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.variable) + } +} + +impl<'ast> fmt::Display for Type<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Basic(ref _type) => write!(f, "{}", _type), + Type::Array(ref _type) => write!(f, "{}", _type), + Type::Struct(ref _type) => write!(f, "{}", _type), + } + } +} + +// Values + +impl<'ast> fmt::Display for Number<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +impl<'ast> fmt::Display for U32<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} + +impl<'ast> fmt::Display for Field<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} + +impl<'ast> fmt::Display for Boolean<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +impl<'ast> fmt::Display for Value<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Value::U32(ref value) => write!(f, "{}", value), + Value::Field(ref value) => write!(f, "{}", value), + Value::Boolean(ref value) => write!(f, "{}", value), + } + } +} +// Variables + +impl<'ast> fmt::Display for Variable<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +// Expressions + +impl<'ast> fmt::Display for StructInlineExpression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} {{", self.variable)?; + for (i, member) in self.members.iter().enumerate() { + write!(f, "{}: {}", member.variable, member.expression)?; + if i < self.members.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "}}") + } +} + +impl<'ast> fmt::Display for ArrayInlineExpression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[")?; + for (i, expression) in self.expressions.iter().enumerate() { + write!(f, "{}", expression)?; + if i < self.expressions.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "]") + } +} + +impl<'ast> fmt::Display for ArrayInitializerExpression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{} ; {}]", self.expression, self.count) + } +} + +impl<'ast> fmt::Display for Expression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Expression::StructInline(_struct) => write!(f, "{}", _struct), + Expression::ArrayInline(array) => write!(f, "{}", array), + Expression::ArrayInitializer(array) => write!(f, "{}", array), + Expression::Value(value) => write!(f, "{}", value), + Expression::Variable(variable) => write!(f, "{}", variable), + } + } +} + +// Sections + +impl<'ast> fmt::Display for Parameter<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}: {} {}", + self.variable, + self.visibility + .as_ref() + .unwrap_or(&Visibility::Private(Private {})), // private by default + self._type + ) + } +} + +impl<'ast> fmt::Display for Assignment<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} = {}", self.parameter, self.expression) + } +} + +impl<'ast> fmt::Display for Section<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}]\n", self.header.function_name.value)?; + for assignment in self.assignments.iter() { + write!(f, "\t{}\n", assignment)?; + } + write!(f, "") + } +} + +// File + +impl<'ast> fmt::Display for File<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for value in self.sections.iter() { + write!(f, "{}", value)?; + } + write!(f, "") + } +} diff --git a/compiler/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest similarity index 63% rename from compiler/src/leo-inputs.pest rename to leo-inputs/src/leo-inputs.pest index 0ba380ac4f..a31780fb36 100644 --- a/compiler/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -6,19 +6,19 @@ visibility = { visibility_public | visibility_private } /// Types -ty_u32 = {"u32"} -ty_field = {"fe"} -ty_bool = {"bool"} -ty_basic = { ty_u32 | ty_field | ty_bool } -ty_struct = { variable } -ty_array = {ty_basic ~ ("[" ~ value ~ "]")+ } -ty = { ty_array | ty_basic | ty_struct } +type_u32 = {"u32"} +type_field = {"fe"} +type_bool = {"bool"} +type_basic = { type_u32 | type_field | type_bool } +type_struct = { variable } +type_array = {type_basic ~ ("[" ~ value ~ "]")+ } +_type = { type_array | type_basic | type_struct } /// Values value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } -value_u32 = { value_number ~ ty_u32? } -value_field = { value_number ~ ty_field } +value_u32 = { value_number ~ type_u32? } +value_field = { value_number ~ type_field } value_boolean = { "true" | "false" } value = { value_field | value_boolean | value_u32 } @@ -29,38 +29,39 @@ variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHAN /// Arrays -inline_array_inner = _{(expression_term ~ ("," ~ NEWLINE* ~ expression_term)*)?} +inline_array_inner = _{(expression ~ ("," ~ NEWLINE* ~ expression)*)?} expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} -expression_array_initializer = { "[" ~ expression_term ~ ";" ~ value ~ "]" } +expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } /// Structs -inline_struct_member = { variable ~ ":" ~ expression_term } +inline_struct_member = { variable ~ ":" ~ expression } inline_struct_member_list = _{(inline_struct_member ~ ("," ~ NEWLINE* ~ inline_struct_member)*)? ~ ","? } expression_inline_struct = { variable ~ "{" ~ NEWLINE* ~ inline_struct_member_list ~ NEWLINE* ~ "}" } /// Expressions -expression_primitive = { value | variable } -expression_term = { +expression = { expression_inline_struct - | expression_primitive | expression_array_inline | expression_array_initializer + | value + | variable } /// Functions -parameter = { variable ~ ":" ~ visibility? ~ ty } +parameter = { variable ~ ":" ~ visibility? ~ _type } function_name = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } /// Section header = { "[" ~ function_name ~ "]" } -assignment = { parameter ~ "=" ~ expression_term } +assignment = { parameter ~ "=" ~ expression } +// assignment = { parameter ~ "=" } -section = { header ~ NEWLINE+ ~ assignment* ~ NEWLINE* } +section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } /// Utilities diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs new file mode 100644 index 0000000000..48c17d24d3 --- /dev/null +++ b/leo-inputs/src/lib.rs @@ -0,0 +1,10 @@ +extern crate from_pest; +extern crate pest; +extern crate pest_ast; + +#[macro_use] +extern crate pest_derive; + +pub mod inputs_ast; + +pub(crate) mod inputs_display; diff --git a/leo-inputs/src/main.rs b/leo-inputs/src/main.rs new file mode 100644 index 0000000000..c697e9de61 --- /dev/null +++ b/leo-inputs/src/main.rs @@ -0,0 +1,17 @@ +use leo_inputs::{self, inputs_ast}; + +use from_pest::FromPest; +use std::fs; + +fn main() { + // Read in file as string + let unparsed_file = fs::read_to_string("input.leo").expect("cannot read file"); + + // Parse the file using leo.pest + let mut file = inputs_ast::parse(&unparsed_file).expect("unsuccessful parse"); + + // Build the abstract syntax tree + let syntax_tree = inputs_ast::File::from_pest(&mut file).expect("infallible"); + + println!("tree: {}", syntax_tree); +} From 08e6eb145c86dfb6ba47b1e77ba112319072a108 Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 8 Jun 2020 12:00:27 -0700 Subject: [PATCH 02/15] update leo-inputs ast --- leo-inputs/input.leo | 6 +- leo-inputs/src/inputs_ast.rs | 233 +++++++++++++++++++------------ leo-inputs/src/inputs_display.rs | 204 --------------------------- leo-inputs/src/leo-inputs.pest | 102 ++++++++------ leo-inputs/src/lib.rs | 2 - leo-inputs/src/main.rs | 2 +- 6 files changed, 209 insertions(+), 340 deletions(-) delete mode 100644 leo-inputs/src/inputs_display.rs diff --git a/leo-inputs/input.leo b/leo-inputs/input.leo index af741c284d..fce77b60c5 100644 --- a/leo-inputs/input.leo +++ b/leo-inputs/input.leo @@ -1,4 +1,4 @@ [main] -a: private u32 = 5 -b: public fe = 1fe -c: private bool = true \ No newline at end of file +a: private u32 = 5; +b: public field = 1field; +c: private bool = true; \ No newline at end of file diff --git a/leo-inputs/src/inputs_ast.rs b/leo-inputs/src/inputs_ast.rs index 21e4690cb4..9738652480 100644 --- a/leo-inputs/src/inputs_ast.rs +++ b/leo-inputs/src/inputs_ast.rs @@ -34,39 +34,31 @@ pub enum Visibility { // Types -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u32))] -pub struct U32Type<'ast> { - #[pest_ast(outer())] - pub span: Span<'ast>, -} - #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::type_field))] -pub struct FieldType<'ast> { - #[pest_ast(outer())] - pub span: Span<'ast>, +pub struct FieldType {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_group))] +pub struct GroupType {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_boolean))] +pub struct BooleanType {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_data))] +pub enum DataType { + Integer(IntegerType), + Field(FieldType), + Group(GroupType), + Boolean(BooleanType), } #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_bool))] -pub struct BooleanType<'ast> { - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_basic))] -pub enum BasicType<'ast> { - U32(U32Type<'ast>), - Field(FieldType<'ast>), - Boolean(BooleanType<'ast>), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_struct))] -pub struct StructType<'ast> { - pub variable: Variable<'ast>, +#[pest_ast(rule(Rule::type_circuit))] +pub struct CircuitType<'ast> { + pub variable: Identifier<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } @@ -74,8 +66,8 @@ pub struct StructType<'ast> { #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::type_array))] pub struct ArrayType<'ast> { - pub _type: BasicType<'ast>, - pub count: Value<'ast>, + pub _type: DataType, + pub dimensions: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, } @@ -83,62 +75,125 @@ pub struct ArrayType<'ast> { #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::_type))] pub enum Type<'ast> { - Basic(BasicType<'ast>), + Data(DataType), Array(ArrayType<'ast>), - Struct(StructType<'ast>), + Circuit(CircuitType<'ast>), } // Values #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::value_number))] -pub struct Number<'ast> { +pub struct NumberValue<'ast> { #[pest_ast(outer(with(span_into_string)))] pub value: String, #[pest_ast(outer())] pub span: Span<'ast>, } -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_u32))] -pub struct U32<'ast> { - pub number: Number<'ast>, - pub _type: Option>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::value_field))] -pub struct Field<'ast> { - pub number: Number<'ast>, - pub _type: FieldType<'ast>, +pub struct FieldValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: FieldType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_group))] +pub struct GroupValue<'ast> { + pub value: GroupRepresentation<'ast>, + pub _type: GroupType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_single_or_tuple))] +pub enum GroupRepresentation<'ast> { + Single(NumberValue<'ast>), + Tuple(GroupTuple<'ast>), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_tuple))] +pub struct GroupTuple<'ast> { + pub x: NumberValue<'ast>, + pub y: NumberValue<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::value_boolean))] -pub struct Boolean<'ast> { +pub struct BooleanValue<'ast> { #[pest_ast(outer(with(span_into_string)))] pub value: String, #[pest_ast(outer())] pub span: Span<'ast>, } +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_integer))] +pub enum IntegerType { + U8Type(U8Type), + U16Type(U16Type), + U32Type(U32Type), + U64Type(U64Type), + U128Type(U128Type), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u8))] +pub struct U8Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u16))] +pub struct U16Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u32))] +pub struct U32Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u64))] +pub struct U64Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u128))] +pub struct U128Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_integer))] +pub struct IntegerValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: IntegerType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_implicit))] +pub struct NumberImplicitValue<'ast> { + pub number: NumberValue<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::value))] pub enum Value<'ast> { - Field(Field<'ast>), - Boolean(Boolean<'ast>), - U32(U32<'ast>), + Integer(IntegerValue<'ast>), + Field(FieldValue<'ast>), + Group(GroupValue<'ast>), + Boolean(BooleanValue<'ast>), + Implicit(NumberImplicitValue<'ast>), } - -// Variables +// Identifier #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::variable))] -pub struct Variable<'ast> { +#[pest_ast(rule(Rule::identifier))] +pub struct Identifier<'ast> { #[pest_ast(outer(with(span_into_string)))] pub value: String, #[pest_ast(outer())] @@ -164,22 +219,22 @@ pub struct ArrayInitializerExpression<'ast> { pub span: Span<'ast>, } -// Structs +// Circuits #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::inline_struct_member))] -pub struct InlineStructMember<'ast> { - pub variable: Variable<'ast>, +#[pest_ast(rule(Rule::circuit_field))] +pub struct CircuitField<'ast> { + pub variable: Identifier<'ast>, pub expression: Expression<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_inline_struct))] -pub struct StructInlineExpression<'ast> { - pub variable: Variable<'ast>, - pub members: Vec>, +#[pest_ast(rule(Rule::expression_circuit_inline))] +pub struct CircuitInlineExpression<'ast> { + pub variable: Identifier<'ast>, + pub members: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, } @@ -189,53 +244,27 @@ pub struct StructInlineExpression<'ast> { #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression))] pub enum Expression<'ast> { - StructInline(StructInlineExpression<'ast>), + CircuitInline(CircuitInlineExpression<'ast>), ArrayInline(ArrayInlineExpression<'ast>), ArrayInitializer(ArrayInitializerExpression<'ast>), Value(Value<'ast>), - Variable(Variable<'ast>), + Variable(Identifier<'ast>), } -// Functions +// Parameters #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::parameter))] pub struct Parameter<'ast> { - pub variable: Variable<'ast>, + pub variable: Identifier<'ast>, pub visibility: Option, pub _type: Type<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::function_name))] -pub struct FunctionName<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - // Sections -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::header))] -pub struct Header<'ast> { - pub function_name: FunctionName<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::assignment))] -pub struct Assignment<'ast> { - pub parameter: Parameter<'ast>, - pub expression: Expression<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::section))] pub struct Section<'ast> { @@ -245,12 +274,34 @@ pub struct Section<'ast> { pub span: Span<'ast>, } +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::header))] +pub struct Header<'ast> { + pub name: Identifier<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::assignment))] +pub struct Assignment<'ast> { + pub parameter: Parameter<'ast>, + pub expression: Expression<'ast>, + pub line_end: LineEnd, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + // Utilities #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::EOI))] pub struct EOI; +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::LINE_END))] +pub struct LineEnd; + // File #[derive(Clone, Debug, FromPest, PartialEq)] diff --git a/leo-inputs/src/inputs_display.rs b/leo-inputs/src/inputs_display.rs deleted file mode 100644 index 25a12d1474..0000000000 --- a/leo-inputs/src/inputs_display.rs +++ /dev/null @@ -1,204 +0,0 @@ -//! Display implementations for a Leo inputs file - -use crate::inputs_ast::{ - ArrayInitializerExpression, ArrayInlineExpression, ArrayType, Assignment, BasicType, Boolean, - BooleanType, Expression, Field, FieldType, File, Number, Parameter, Private, Section, - StructInlineExpression, StructType, Type, U32Type, Value, Variable, Visibility, U32, -}; - -use std::fmt; - -// Visibility - -impl fmt::Display for Visibility { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Visibility::Private(_private) => write!(f, "private"), - Visibility::Public(_public) => write!(f, "public"), - } - } -} - -// Types - -impl<'ast> fmt::Display for BooleanType<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "bool") - } -} - -impl<'ast> fmt::Display for FieldType<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "fe") - } -} - -impl<'ast> fmt::Display for U32Type<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "u32") - } -} - -impl<'ast> fmt::Display for BasicType<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - BasicType::Boolean(bool) => write!(f, "{}", bool), - BasicType::Field(field) => write!(f, "{}", field), - BasicType::U32(u32) => write!(f, "{}", u32), - } - } -} - -impl<'ast> fmt::Display for ArrayType<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{}; {}]", self._type, self.count) - } -} - -impl<'ast> fmt::Display for StructType<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.variable) - } -} - -impl<'ast> fmt::Display for Type<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Type::Basic(ref _type) => write!(f, "{}", _type), - Type::Array(ref _type) => write!(f, "{}", _type), - Type::Struct(ref _type) => write!(f, "{}", _type), - } - } -} - -// Values - -impl<'ast> fmt::Display for Number<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -impl<'ast> fmt::Display for U32<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.number) - } -} - -impl<'ast> fmt::Display for Field<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.number) - } -} - -impl<'ast> fmt::Display for Boolean<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -impl<'ast> fmt::Display for Value<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Value::U32(ref value) => write!(f, "{}", value), - Value::Field(ref value) => write!(f, "{}", value), - Value::Boolean(ref value) => write!(f, "{}", value), - } - } -} -// Variables - -impl<'ast> fmt::Display for Variable<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -// Expressions - -impl<'ast> fmt::Display for StructInlineExpression<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} {{", self.variable)?; - for (i, member) in self.members.iter().enumerate() { - write!(f, "{}: {}", member.variable, member.expression)?; - if i < self.members.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, "}}") - } -} - -impl<'ast> fmt::Display for ArrayInlineExpression<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[")?; - for (i, expression) in self.expressions.iter().enumerate() { - write!(f, "{}", expression)?; - if i < self.expressions.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, "]") - } -} - -impl<'ast> fmt::Display for ArrayInitializerExpression<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{} ; {}]", self.expression, self.count) - } -} - -impl<'ast> fmt::Display for Expression<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Expression::StructInline(_struct) => write!(f, "{}", _struct), - Expression::ArrayInline(array) => write!(f, "{}", array), - Expression::ArrayInitializer(array) => write!(f, "{}", array), - Expression::Value(value) => write!(f, "{}", value), - Expression::Variable(variable) => write!(f, "{}", variable), - } - } -} - -// Sections - -impl<'ast> fmt::Display for Parameter<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}: {} {}", - self.variable, - self.visibility - .as_ref() - .unwrap_or(&Visibility::Private(Private {})), // private by default - self._type - ) - } -} - -impl<'ast> fmt::Display for Assignment<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} = {}", self.parameter, self.expression) - } -} - -impl<'ast> fmt::Display for Section<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{}]\n", self.header.function_name.value)?; - for assignment in self.assignments.iter() { - write!(f, "\t{}\n", assignment)?; - } - write!(f, "") - } -} - -// File - -impl<'ast> fmt::Display for File<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for value in self.sections.iter() { - write!(f, "{}", value)?; - } - write!(f, "") - } -} diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index a31780fb36..90f76c96e8 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -1,73 +1,97 @@ -/// Visibility +/// Common +file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } + +identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } +protected_name = { visibility | "let" | "for"| "if" | "else" | "as" | "return" } + + +LINE_END = { ";" ~ NEWLINE* } + +visibility = { visibility_public | visibility_private } visibility_public = { "public" } visibility_private = { "private" } -visibility = { visibility_public | visibility_private } /// Types -type_u32 = {"u32"} -type_field = {"fe"} -type_bool = {"bool"} -type_basic = { type_u32 | type_field | type_bool } -type_struct = { variable } -type_array = {type_basic ~ ("[" ~ value ~ "]")+ } -_type = { type_array | type_basic | type_struct } +_type = { type_array | type_data | type_circuit } +type_integer = { + type_u8 + | type_u16 + | type_u32 + | type_u64 + | type_u128 +} +type_u8 = { "u8" } +type_u16 = { "u16" } +type_u32 = { "u32" } +type_u64 = { "u64" } +type_u128 = { "u128" } + +type_field = { "field" } + +type_group = { "group" } + +type_boolean = { "bool" } + +type_data = { type_field | type_group | type_boolean | type_integer } + +type_circuit = { identifier } + +type_array = { type_data ~ ("[" ~ value ~ "]")+ } /// Values +value = { value_field | value_group | value_boolean | value_integer | value_implicit } + value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } -value_u32 = { value_number ~ type_u32? } -value_field = { value_number ~ type_field } + +value_implicit = { value_number } + +value_integer = { value_number ~ type_integer } + value_boolean = { "true" | "false" } -value = { value_field | value_boolean | value_u32 } -/// Variables +value_field = { value_number ~ type_field } -protected_name = { visibility | "return" } -variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } - -/// Arrays - -inline_array_inner = _{(expression ~ ("," ~ NEWLINE* ~ expression)*)?} -expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} -expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } - -/// Structs - -inline_struct_member = { variable ~ ":" ~ expression } -inline_struct_member_list = _{(inline_struct_member ~ ("," ~ NEWLINE* ~ inline_struct_member)*)? ~ ","? } -expression_inline_struct = { variable ~ "{" ~ NEWLINE* ~ inline_struct_member_list ~ NEWLINE* ~ "}" } +value_group = { group_single_or_tuple ~ type_group } +group_tuple = { "(" ~ NEWLINE* ~ value_number ~ "," ~ NEWLINE* ~ value_number ~ NEWLINE* ~")" } +group_single_or_tuple = { value_number | group_tuple } /// Expressions +expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } + +expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} +inline_array_inner = _{ (expression ~ ("," ~ NEWLINE* ~ expression)*)? } + +expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" } +circuit_field = { identifier ~ ":" ~ expression } +circuit_field_list = _{ (circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? } + expression = { - expression_inline_struct + expression_circuit_inline | expression_array_inline | expression_array_initializer | value - | variable + | identifier } -/// Functions +/// Parameters -parameter = { variable ~ ":" ~ visibility? ~ _type } - -function_name = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } +parameter = { identifier ~ ":" ~ visibility? ~ _type } /// Section -header = { "[" ~ function_name ~ "]" } -assignment = { parameter ~ "=" ~ expression } -// assignment = { parameter ~ "=" } - section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } +header = { "[" ~ identifier ~ "]" } + +assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } + /// Utilities COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } -/// Program File -file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 48c17d24d3..0f23c65930 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -6,5 +6,3 @@ extern crate pest_ast; extern crate pest_derive; pub mod inputs_ast; - -pub(crate) mod inputs_display; diff --git a/leo-inputs/src/main.rs b/leo-inputs/src/main.rs index c697e9de61..7efee39083 100644 --- a/leo-inputs/src/main.rs +++ b/leo-inputs/src/main.rs @@ -13,5 +13,5 @@ fn main() { // Build the abstract syntax tree let syntax_tree = inputs_ast::File::from_pest(&mut file).expect("infallible"); - println!("tree: {}", syntax_tree); + println!("tree: {:?}", syntax_tree); } From 8846f62c8f5dd9e34458866b1bb1250f6511d1ea Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 8 Jun 2020 12:24:15 -0700 Subject: [PATCH 03/15] add parser --- Cargo.lock | 1 + leo-inputs/Cargo.toml | 3 +- leo-inputs/src/{inputs_ast.rs => ast.rs} | 0 leo-inputs/src/errors/mod.rs | 5 +++ leo-inputs/src/errors/parser.rs | 22 +++++++++++++ leo-inputs/src/errors/syntax.rs | 29 ++++++++++++++++ leo-inputs/src/lib.rs | 42 +++++++++++++++++++++--- leo-inputs/src/main.rs | 18 ++++------ 8 files changed, 103 insertions(+), 17 deletions(-) rename leo-inputs/src/{inputs_ast.rs => ast.rs} (100%) create mode 100644 leo-inputs/src/errors/mod.rs create mode 100644 leo-inputs/src/errors/parser.rs create mode 100644 leo-inputs/src/errors/syntax.rs diff --git a/Cargo.lock b/Cargo.lock index 4216a0d78a..d2b75f30bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,6 +534,7 @@ dependencies = [ "snarkos-errors", "snarkos-gadgets", "snarkos-models", + "thiserror", ] [[package]] diff --git a/leo-inputs/Cargo.toml b/leo-inputs/Cargo.toml index 8886a317f9..33d89ce2b5 100644 --- a/leo-inputs/Cargo.toml +++ b/leo-inputs/Cargo.toml @@ -16,4 +16,5 @@ snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" } from-pest = { version = "0.3.1" } pest = { version = "2.0" } pest-ast = { version = "0.3.3" } -pest_derive = { version = "2.0" } \ No newline at end of file +pest_derive = { version = "2.0" } +thiserror = { version = "1.0" } diff --git a/leo-inputs/src/inputs_ast.rs b/leo-inputs/src/ast.rs similarity index 100% rename from leo-inputs/src/inputs_ast.rs rename to leo-inputs/src/ast.rs diff --git a/leo-inputs/src/errors/mod.rs b/leo-inputs/src/errors/mod.rs new file mode 100644 index 0000000000..9d9164fa35 --- /dev/null +++ b/leo-inputs/src/errors/mod.rs @@ -0,0 +1,5 @@ +pub mod parser; +pub use parser::*; + +pub mod syntax; +pub use syntax::*; diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs new file mode 100644 index 0000000000..3bce388a25 --- /dev/null +++ b/leo-inputs/src/errors/parser.rs @@ -0,0 +1,22 @@ +use crate::{ast::Rule, errors::SyntaxError}; + +use pest::error::Error; +use std::path::PathBuf; + +#[derive(Debug, Error)] +pub enum ParserError { + #[error("Cannot read from the provided file path - {:?}", _0)] + FileReadError(PathBuf), + + #[error("{}", _0)] + SyntaxError(#[from] SyntaxError), + + #[error("Unable to construct abstract syntax tree")] + SyntaxTreeError, +} + +impl From> for ParserError { + fn from(error: Error) -> Self { + ParserError::SyntaxError(SyntaxError::from(error)) + } +} diff --git a/leo-inputs/src/errors/syntax.rs b/leo-inputs/src/errors/syntax.rs new file mode 100644 index 0000000000..358a23af85 --- /dev/null +++ b/leo-inputs/src/errors/syntax.rs @@ -0,0 +1,29 @@ +use crate::ast::Rule; + +use pest::error::Error; + +#[derive(Debug, Error)] +pub enum SyntaxError { + #[error("aborting due to syntax error")] + Error, +} + +impl From> for SyntaxError { + fn from(mut error: Error) -> Self { + error = error.renamed_rules(|rule| match *rule { + Rule::LINE_END => "`;`".to_owned(), + 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::identifier => "a variable name".to_owned(), + Rule::_type => "a type".to_owned(), + + rule => format!("{:?}", rule), + }); + + println!("{}\n", error); + + SyntaxError::Error + } +} diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 0f23c65930..156b7890e1 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -1,8 +1,40 @@ -extern crate from_pest; -extern crate pest; -extern crate pest_ast; - #[macro_use] extern crate pest_derive; +#[macro_use] +extern crate thiserror; -pub mod inputs_ast; +pub mod errors; +pub use errors::*; + +//extern crate from_pest; +mod ast; + +use from_pest::FromPest; +use std::{fs, path::PathBuf}; + +pub struct LeoInputsParser; + +impl LeoInputsParser { + /// Reads in the given file path into a string. + pub fn load_file(file_path: &PathBuf) -> Result { + Ok(fs::read_to_string(file_path) + .map_err(|_| ParserError::FileReadError(file_path.clone()))?) + } + + /// Parses the input file and constructs a syntax tree. + pub fn parse_file<'a>( + file_path: &'a PathBuf, + input_file: &'a str, + ) -> Result, ParserError> { + // Parse the file using leo.pest + let mut file = ast::parse(input_file) + .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; + + // Build the abstract syntax tree + let syntax_tree = + ast::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; + // println!("{:?}", syntax_tree); + + Ok(syntax_tree) + } +} diff --git a/leo-inputs/src/main.rs b/leo-inputs/src/main.rs index 7efee39083..50dc3b1944 100644 --- a/leo-inputs/src/main.rs +++ b/leo-inputs/src/main.rs @@ -1,17 +1,13 @@ -use leo_inputs::{self, inputs_ast}; +use leo_inputs::{self, LeoInputsParser}; -use from_pest::FromPest; -use std::fs; +use std::env::current_dir; fn main() { - // Read in file as string - let unparsed_file = fs::read_to_string("input.leo").expect("cannot read file"); + let mut path = current_dir().unwrap(); + path.push("input.leo"); - // Parse the file using leo.pest - let mut file = inputs_ast::parse(&unparsed_file).expect("unsuccessful parse"); + let input_file = &LeoInputsParser::load_file(&path).expect("cannot read file"); + let syntax_tree = LeoInputsParser::parse_file(&path, input_file).unwrap(); - // Build the abstract syntax tree - let syntax_tree = inputs_ast::File::from_pest(&mut file).expect("infallible"); - - println!("tree: {:?}", syntax_tree); + println!("tree: {:#?}", syntax_tree); } From b6836b37d4b1a914d86e224527e526667506950b Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 8 Jun 2020 14:07:06 -0700 Subject: [PATCH 04/15] add leo-inputs ast --- leo-inputs/src/assignments/assignment.rs | 14 + leo-inputs/src/assignments/mod.rs | 2 + leo-inputs/src/ast.rs | 302 +----------------- leo-inputs/src/circuits/circuit_field.rs | 13 + leo-inputs/src/circuits/mod.rs | 4 + leo-inputs/src/common/eoi.rs | 7 + leo-inputs/src/common/identifier.rs | 20 ++ leo-inputs/src/common/line_end.rs | 7 + leo-inputs/src/common/mod.rs | 11 + leo-inputs/src/common/visibility.rs | 18 ++ leo-inputs/src/errors/syntax.rs | 2 +- .../array_initializer_expression.rs | 13 + .../expressions/array_inline_expression.rs | 12 + .../expressions/circuit_inline_expression.rs | 13 + leo-inputs/src/expressions/expression.rs | 40 +++ leo-inputs/src/expressions/mod.rs | 11 + leo-inputs/src/files/file.rs | 13 + leo-inputs/src/files/mod.rs | 2 + leo-inputs/src/leo-inputs.pest | 39 ++- leo-inputs/src/lib.rs | 13 +- leo-inputs/src/parameters/mod.rs | 2 + leo-inputs/src/parameters/parameter.rs | 14 + leo-inputs/src/sections/header.rs | 12 + leo-inputs/src/sections/mod.rs | 5 + leo-inputs/src/sections/section.rs | 13 + leo-inputs/src/types/array_type.rs | 13 + leo-inputs/src/types/boolean_type.rs | 7 + leo-inputs/src/types/circuit_type.rs | 12 + leo-inputs/src/types/data_type.rs | 12 + leo-inputs/src/types/field_type.rs | 7 + leo-inputs/src/types/group_type.rs | 7 + leo-inputs/src/types/integer_type.rs | 33 ++ leo-inputs/src/types/mod.rs | 23 ++ leo-inputs/src/types/type_.rs | 22 ++ leo-inputs/src/values/boolean_value.rs | 20 ++ leo-inputs/src/values/field_value.rs | 20 ++ leo-inputs/src/values/group_value.rs | 51 +++ leo-inputs/src/values/integer_value.rs | 20 ++ leo-inputs/src/values/mod.rs | 20 ++ .../src/values/number_implicit_value.rs | 19 ++ leo-inputs/src/values/number_value.rs | 20 ++ leo-inputs/src/values/value.rs | 39 +++ 42 files changed, 638 insertions(+), 309 deletions(-) create mode 100644 leo-inputs/src/assignments/assignment.rs create mode 100644 leo-inputs/src/assignments/mod.rs create mode 100644 leo-inputs/src/circuits/circuit_field.rs create mode 100644 leo-inputs/src/circuits/mod.rs create mode 100644 leo-inputs/src/common/eoi.rs create mode 100644 leo-inputs/src/common/identifier.rs create mode 100644 leo-inputs/src/common/line_end.rs create mode 100644 leo-inputs/src/common/mod.rs create mode 100644 leo-inputs/src/common/visibility.rs create mode 100644 leo-inputs/src/expressions/array_initializer_expression.rs create mode 100644 leo-inputs/src/expressions/array_inline_expression.rs create mode 100644 leo-inputs/src/expressions/circuit_inline_expression.rs create mode 100644 leo-inputs/src/expressions/expression.rs create mode 100644 leo-inputs/src/expressions/mod.rs create mode 100644 leo-inputs/src/files/file.rs create mode 100644 leo-inputs/src/files/mod.rs create mode 100644 leo-inputs/src/parameters/mod.rs create mode 100644 leo-inputs/src/parameters/parameter.rs create mode 100644 leo-inputs/src/sections/header.rs create mode 100644 leo-inputs/src/sections/mod.rs create mode 100644 leo-inputs/src/sections/section.rs create mode 100644 leo-inputs/src/types/array_type.rs create mode 100644 leo-inputs/src/types/boolean_type.rs create mode 100644 leo-inputs/src/types/circuit_type.rs create mode 100644 leo-inputs/src/types/data_type.rs create mode 100644 leo-inputs/src/types/field_type.rs create mode 100644 leo-inputs/src/types/group_type.rs create mode 100644 leo-inputs/src/types/integer_type.rs create mode 100644 leo-inputs/src/types/mod.rs create mode 100644 leo-inputs/src/types/type_.rs create mode 100644 leo-inputs/src/values/boolean_value.rs create mode 100644 leo-inputs/src/values/field_value.rs create mode 100644 leo-inputs/src/values/group_value.rs create mode 100644 leo-inputs/src/values/integer_value.rs create mode 100644 leo-inputs/src/values/mod.rs create mode 100644 leo-inputs/src/values/number_implicit_value.rs create mode 100644 leo-inputs/src/values/number_value.rs create mode 100644 leo-inputs/src/values/value.rs diff --git a/leo-inputs/src/assignments/assignment.rs b/leo-inputs/src/assignments/assignment.rs new file mode 100644 index 0000000000..0945a146a1 --- /dev/null +++ b/leo-inputs/src/assignments/assignment.rs @@ -0,0 +1,14 @@ +use crate::{ast::Rule, common::LineEnd, expressions::Expression, parameters::Parameter}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::assignment))] +pub struct Assignment<'ast> { + pub parameter: Parameter<'ast>, + pub expression: Expression<'ast>, + pub line_end: LineEnd, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/assignments/mod.rs b/leo-inputs/src/assignments/mod.rs new file mode 100644 index 0000000000..e02881fe86 --- /dev/null +++ b/leo-inputs/src/assignments/mod.rs @@ -0,0 +1,2 @@ +pub mod assignment; +pub use assignment::*; diff --git a/leo-inputs/src/ast.rs b/leo-inputs/src/ast.rs index 9738652480..9d82bbb91d 100644 --- a/leo-inputs/src/ast.rs +++ b/leo-inputs/src/ast.rs @@ -1,7 +1,5 @@ //! Abstract syntax tree (ast) representation from leo-inputs.pest. - use pest::{error::Error, iterators::Pairs, Parser, Span}; -use pest_ast::FromPest; #[derive(Parser)] #[grammar = "leo-inputs.pest"] @@ -11,304 +9,6 @@ pub fn parse(input: &str) -> Result, Error> { LanguageParser::parse(Rule::file, input) } -fn span_into_string(span: Span) -> String { +pub fn span_into_string(span: Span) -> String { span.as_str().to_string() } - -// Visibility - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility_public))] -pub struct Public {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility_private))] -pub struct Private {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility))] -pub enum Visibility { - Public(Public), - Private(Private), -} - -// Types - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_field))] -pub struct FieldType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_group))] -pub struct GroupType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_boolean))] -pub struct BooleanType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_data))] -pub enum DataType { - Integer(IntegerType), - Field(FieldType), - Group(GroupType), - Boolean(BooleanType), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_circuit))] -pub struct CircuitType<'ast> { - pub variable: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_array))] -pub struct ArrayType<'ast> { - pub _type: DataType, - pub dimensions: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::_type))] -pub enum Type<'ast> { - Data(DataType), - Array(ArrayType<'ast>), - Circuit(CircuitType<'ast>), -} - -// Values - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_number))] -pub struct NumberValue<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_field))] -pub struct FieldValue<'ast> { - pub number: NumberValue<'ast>, - pub _type: FieldType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_group))] -pub struct GroupValue<'ast> { - pub value: GroupRepresentation<'ast>, - pub _type: GroupType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::group_single_or_tuple))] -pub enum GroupRepresentation<'ast> { - Single(NumberValue<'ast>), - Tuple(GroupTuple<'ast>), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::group_tuple))] -pub struct GroupTuple<'ast> { - pub x: NumberValue<'ast>, - pub y: NumberValue<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_boolean))] -pub struct BooleanValue<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_integer))] -pub enum IntegerType { - U8Type(U8Type), - U16Type(U16Type), - U32Type(U32Type), - U64Type(U64Type), - U128Type(U128Type), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u8))] -pub struct U8Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u16))] -pub struct U16Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u32))] -pub struct U32Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u64))] -pub struct U64Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u128))] -pub struct U128Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_integer))] -pub struct IntegerValue<'ast> { - pub number: NumberValue<'ast>, - pub _type: IntegerType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_implicit))] -pub struct NumberImplicitValue<'ast> { - pub number: NumberValue<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value))] -pub enum Value<'ast> { - Integer(IntegerValue<'ast>), - Field(FieldValue<'ast>), - Group(GroupValue<'ast>), - Boolean(BooleanValue<'ast>), - Implicit(NumberImplicitValue<'ast>), -} -// Identifier - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::identifier))] -pub struct Identifier<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Arrays - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_array_inline))] -pub struct ArrayInlineExpression<'ast> { - pub expressions: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_array_initializer))] -pub struct ArrayInitializerExpression<'ast> { - pub expression: Box>, - pub count: Value<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Circuits - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::circuit_field))] -pub struct CircuitField<'ast> { - pub variable: Identifier<'ast>, - pub expression: Expression<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_circuit_inline))] -pub struct CircuitInlineExpression<'ast> { - pub variable: Identifier<'ast>, - pub members: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Expressions - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression))] -pub enum Expression<'ast> { - CircuitInline(CircuitInlineExpression<'ast>), - ArrayInline(ArrayInlineExpression<'ast>), - ArrayInitializer(ArrayInitializerExpression<'ast>), - Value(Value<'ast>), - Variable(Identifier<'ast>), -} - -// Parameters - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::parameter))] -pub struct Parameter<'ast> { - pub variable: Identifier<'ast>, - pub visibility: Option, - pub _type: Type<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Sections - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::section))] -pub struct Section<'ast> { - pub header: Header<'ast>, - pub assignments: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::header))] -pub struct Header<'ast> { - pub name: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::assignment))] -pub struct Assignment<'ast> { - pub parameter: Parameter<'ast>, - pub expression: Expression<'ast>, - pub line_end: LineEnd, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Utilities - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::EOI))] -pub struct EOI; - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::LINE_END))] -pub struct LineEnd; - -// File - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::file))] -pub struct File<'ast> { - pub sections: Vec>, - pub eoi: EOI, - #[pest_ast(outer())] - pub span: Span<'ast>, -} diff --git a/leo-inputs/src/circuits/circuit_field.rs b/leo-inputs/src/circuits/circuit_field.rs new file mode 100644 index 0000000000..0c48dec655 --- /dev/null +++ b/leo-inputs/src/circuits/circuit_field.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, common::Identifier, expressions::Expression}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::circuit_field))] +pub struct CircuitField<'ast> { + pub identifier: Identifier<'ast>, + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/circuits/mod.rs b/leo-inputs/src/circuits/mod.rs new file mode 100644 index 0000000000..5b7ea46f55 --- /dev/null +++ b/leo-inputs/src/circuits/mod.rs @@ -0,0 +1,4 @@ + +pub mod circuit_field; +pub use circuit_field::*; + diff --git a/leo-inputs/src/common/eoi.rs b/leo-inputs/src/common/eoi.rs new file mode 100644 index 0000000000..1293320f1a --- /dev/null +++ b/leo-inputs/src/common/eoi.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::EOI))] +pub struct EOI; diff --git a/leo-inputs/src/common/identifier.rs b/leo-inputs/src/common/identifier.rs new file mode 100644 index 0000000000..35c74e30be --- /dev/null +++ b/leo-inputs/src/common/identifier.rs @@ -0,0 +1,20 @@ +use crate::ast::{span_into_string, Rule}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::identifier))] +pub struct Identifier<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Identifier<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} diff --git a/leo-inputs/src/common/line_end.rs b/leo-inputs/src/common/line_end.rs new file mode 100644 index 0000000000..ee34060bd6 --- /dev/null +++ b/leo-inputs/src/common/line_end.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::LINE_END))] +pub struct LineEnd; diff --git a/leo-inputs/src/common/mod.rs b/leo-inputs/src/common/mod.rs new file mode 100644 index 0000000000..b0b7155373 --- /dev/null +++ b/leo-inputs/src/common/mod.rs @@ -0,0 +1,11 @@ +pub mod eoi; +pub use eoi::*; + +pub mod identifier; +pub use identifier::*; + +pub mod line_end; +pub use line_end::*; + +pub mod visibility; +pub use visibility::*; diff --git a/leo-inputs/src/common/visibility.rs b/leo-inputs/src/common/visibility.rs new file mode 100644 index 0000000000..cd63bb1119 --- /dev/null +++ b/leo-inputs/src/common/visibility.rs @@ -0,0 +1,18 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility))] +pub enum Visibility { + Public(Public), + Private(Private), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_public))] +pub struct Public {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_private))] +pub struct Private {} diff --git a/leo-inputs/src/errors/syntax.rs b/leo-inputs/src/errors/syntax.rs index 358a23af85..a436ec15b1 100644 --- a/leo-inputs/src/errors/syntax.rs +++ b/leo-inputs/src/errors/syntax.rs @@ -17,7 +17,7 @@ impl From> for SyntaxError { Rule::type_group => "`group`".to_owned(), Rule::file => "an import, circuit, or function".to_owned(), Rule::identifier => "a variable name".to_owned(), - Rule::_type => "a type".to_owned(), + Rule::type_ => "a type".to_owned(), rule => format!("{:?}", rule), }); diff --git a/leo-inputs/src/expressions/array_initializer_expression.rs b/leo-inputs/src/expressions/array_initializer_expression.rs new file mode 100644 index 0000000000..37ebc032d5 --- /dev/null +++ b/leo-inputs/src/expressions/array_initializer_expression.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, expressions::Expression, values::Value}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_initializer))] +pub struct ArrayInitializerExpression<'ast> { + pub expression: Box>, + pub count: Value<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/array_inline_expression.rs b/leo-inputs/src/expressions/array_inline_expression.rs new file mode 100644 index 0000000000..bb25e12721 --- /dev/null +++ b/leo-inputs/src/expressions/array_inline_expression.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, expressions::Expression}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_inline))] +pub struct ArrayInlineExpression<'ast> { + pub expressions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/circuit_inline_expression.rs b/leo-inputs/src/expressions/circuit_inline_expression.rs new file mode 100644 index 0000000000..52d8b99983 --- /dev/null +++ b/leo-inputs/src/expressions/circuit_inline_expression.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, circuits::CircuitField, common::Identifier,}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_circuit_inline))] +pub struct CircuitInlineExpression<'ast> { + pub identifier: Identifier<'ast>, + pub members: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/expression.rs b/leo-inputs/src/expressions/expression.rs new file mode 100644 index 0000000000..af8f20a4ea --- /dev/null +++ b/leo-inputs/src/expressions/expression.rs @@ -0,0 +1,40 @@ +use crate::{ast::Rule, common::Identifier, expressions::*, values::Value,}; + +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression))] +pub enum Expression<'ast> { + CircuitInline(CircuitInlineExpression<'ast>), + ArrayInline(ArrayInlineExpression<'ast>), + ArrayInitializer(ArrayInitializerExpression<'ast>), + Value(Value<'ast>), + Variable(Identifier<'ast>), +} + +impl<'ast> fmt::Display for Expression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Expression::Value(ref expression) => write!(f, "{}", expression), + Expression::Variable(ref expression) => write!(f, "{}", expression), + Expression::ArrayInline(ref expression) => { + for (i, spread_or_expression) in expression.expressions.iter().enumerate() { + write!(f, "{}", spread_or_expression)?; + if i < expression.expressions.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "") + } + Expression::ArrayInitializer(ref expression) => { + write!(f, "[{} ; {}]", expression.expression, expression.count) + } + Expression::CircuitInline(ref expression) => write!( + f, + "inline circuit display not impl {}", + expression.identifier + ), + } + } +} diff --git a/leo-inputs/src/expressions/mod.rs b/leo-inputs/src/expressions/mod.rs new file mode 100644 index 0000000000..f79e25ae50 --- /dev/null +++ b/leo-inputs/src/expressions/mod.rs @@ -0,0 +1,11 @@ +pub mod array_initializer_expression; +pub use array_initializer_expression::*; + +pub mod array_inline_expression; +pub use array_inline_expression::*; + +pub mod circuit_inline_expression; +pub use circuit_inline_expression::*; + +pub mod expression; +pub use expression::*; \ No newline at end of file diff --git a/leo-inputs/src/files/file.rs b/leo-inputs/src/files/file.rs new file mode 100644 index 0000000000..48f720d841 --- /dev/null +++ b/leo-inputs/src/files/file.rs @@ -0,0 +1,13 @@ +use crate::{ast::{Rule}, common::EOI, sections::Section }; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::file))] +pub struct File<'ast> { + pub sections: 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 new file mode 100644 index 0000000000..de03a628a4 --- /dev/null +++ b/leo-inputs/src/files/mod.rs @@ -0,0 +1,2 @@ +pub mod file; +pub use file::*; diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 90f76c96e8..73ef11cbe5 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -1,20 +1,23 @@ /// Common -file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } - +// Declared in common/identifier.rs identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } protected_name = { visibility | "let" | "for"| "if" | "else" | "as" | "return" } - +// Declared in common/line_end.rs LINE_END = { ";" ~ NEWLINE* } +// Declared in common/visibility.rs visibility = { visibility_public | visibility_private } visibility_public = { "public" } visibility_private = { "private" } /// Types -_type = { type_array | type_data | type_circuit } +// Declared in types/type_.rs +type_ = { type_array | type_data | type_circuit } + +// Declared in types/integer_type.rs type_integer = { type_u8 | type_u16 @@ -28,47 +31,64 @@ type_u32 = { "u32" } type_u64 = { "u64" } type_u128 = { "u128" } +// Declared in types/field_type.rs type_field = { "field" } +// Declared in types/group_type.rs type_group = { "group" } +// Declared in types/boolean_type.rs type_boolean = { "bool" } +// Declared in types/data_type.rs type_data = { type_field | type_group | type_boolean | type_integer } +// Declared in types/circuit_type.rs type_circuit = { identifier } +// Declared in types/array_type.rs type_array = { type_data ~ ("[" ~ value ~ "]")+ } /// Values +// Declared in values/value.rs value = { value_field | value_group | value_boolean | value_integer | value_implicit } +// Declared in values/number_value.rs value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } +// Declared in values/number_implicit_value.rs value_implicit = { value_number } +// Declared in values/integer_value.rs value_integer = { value_number ~ type_integer } +// Declared in values/boolean_value.rs value_boolean = { "true" | "false" } +// Declared in values/field_value.rs value_field = { value_number ~ type_field } +// Declared in values/group_value.rs value_group = { group_single_or_tuple ~ type_group } group_tuple = { "(" ~ NEWLINE* ~ value_number ~ "," ~ NEWLINE* ~ value_number ~ NEWLINE* ~")" } group_single_or_tuple = { value_number | group_tuple } /// Expressions +// Declared in expressions/array_initializer_expression.rs expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } +// Declared in expressions/array_inline_expression.rs expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} inline_array_inner = _{ (expression ~ ("," ~ NEWLINE* ~ expression)*)? } +// Declared in expressions/circuit_inline_expression.rs expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" } circuit_field = { identifier ~ ":" ~ expression } circuit_field_list = _{ (circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? } +// Declared in expressions/expression.rs expression = { expression_circuit_inline | expression_array_inline @@ -79,14 +99,20 @@ expression = { /// Parameters -parameter = { identifier ~ ":" ~ visibility? ~ _type } +// Declared in parameters/parameters.rs +parameter = { identifier ~ ":" ~ visibility? ~ type_ } /// Section +// Declared in sections/section.rs section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } +// Declared in sections/header.rs header = { "[" ~ identifier ~ "]" } +/// Assignments + +// Declared in assignment/assignment.rs assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } /// Utilities @@ -94,4 +120,7 @@ assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } +/// Files +// Declared in files/file.rs +file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 156b7890e1..1c8a339458 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -8,6 +8,15 @@ pub use errors::*; //extern crate from_pest; mod ast; +pub mod assignments; +pub mod circuits; +pub mod common; +pub mod expressions; +pub mod files; +pub mod parameters; +pub mod sections; +pub mod types; +pub mod values; use from_pest::FromPest; use std::{fs, path::PathBuf}; @@ -25,14 +34,14 @@ impl LeoInputsParser { pub fn parse_file<'a>( file_path: &'a PathBuf, input_file: &'a str, - ) -> Result, ParserError> { + ) -> Result, ParserError> { // Parse the file using leo.pest let mut file = ast::parse(input_file) .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; // Build the abstract syntax tree let syntax_tree = - ast::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; + files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; // println!("{:?}", syntax_tree); Ok(syntax_tree) diff --git a/leo-inputs/src/parameters/mod.rs b/leo-inputs/src/parameters/mod.rs new file mode 100644 index 0000000000..861bb16a1a --- /dev/null +++ b/leo-inputs/src/parameters/mod.rs @@ -0,0 +1,2 @@ +pub mod parameter; +pub use parameter::*; \ No newline at end of file diff --git a/leo-inputs/src/parameters/parameter.rs b/leo-inputs/src/parameters/parameter.rs new file mode 100644 index 0000000000..ee4469eac0 --- /dev/null +++ b/leo-inputs/src/parameters/parameter.rs @@ -0,0 +1,14 @@ +use crate::{ast::Rule, common::{Identifier, Visibility}, types::Type}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::parameter))] +pub struct Parameter<'ast> { + pub variable: Identifier<'ast>, + pub visibility: Option, + pub _type: Type<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/sections/header.rs b/leo-inputs/src/sections/header.rs new file mode 100644 index 0000000000..3805431def --- /dev/null +++ b/leo-inputs/src/sections/header.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, common::Identifier}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::header))] +pub struct Header<'ast> { + pub name: Identifier<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/sections/mod.rs b/leo-inputs/src/sections/mod.rs new file mode 100644 index 0000000000..2ed80e53e5 --- /dev/null +++ b/leo-inputs/src/sections/mod.rs @@ -0,0 +1,5 @@ +pub mod header; +pub use header::*; + +pub mod section; +pub use section::*; \ No newline at end of file diff --git a/leo-inputs/src/sections/section.rs b/leo-inputs/src/sections/section.rs new file mode 100644 index 0000000000..c12ad67db6 --- /dev/null +++ b/leo-inputs/src/sections/section.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, sections::Header, assignments::Assignment}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::section))] +pub struct Section<'ast> { + pub header: Header<'ast>, + pub assignments: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/types/array_type.rs b/leo-inputs/src/types/array_type.rs new file mode 100644 index 0000000000..01650cdfb3 --- /dev/null +++ b/leo-inputs/src/types/array_type.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, types::DataType, values::Value}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_array))] +pub struct ArrayType<'ast> { + pub _type: DataType, + pub dimensions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/types/boolean_type.rs b/leo-inputs/src/types/boolean_type.rs new file mode 100644 index 0000000000..9abd021ffa --- /dev/null +++ b/leo-inputs/src/types/boolean_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_boolean))] +pub struct BooleanType {} diff --git a/leo-inputs/src/types/circuit_type.rs b/leo-inputs/src/types/circuit_type.rs new file mode 100644 index 0000000000..8b87935568 --- /dev/null +++ b/leo-inputs/src/types/circuit_type.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, common::Identifier}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_circuit))] +pub struct CircuitType<'ast> { + pub identifier: Identifier<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/types/data_type.rs b/leo-inputs/src/types/data_type.rs new file mode 100644 index 0000000000..8cf3a0f75c --- /dev/null +++ b/leo-inputs/src/types/data_type.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, types::{IntegerType, FieldType, GroupType, BooleanType}}; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_data))] +pub enum DataType { + Integer(IntegerType), + Field(FieldType), + Group(GroupType), + Boolean(BooleanType), +} \ No newline at end of file diff --git a/leo-inputs/src/types/field_type.rs b/leo-inputs/src/types/field_type.rs new file mode 100644 index 0000000000..64d12a67ab --- /dev/null +++ b/leo-inputs/src/types/field_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_field))] +pub struct FieldType {} \ No newline at end of file diff --git a/leo-inputs/src/types/group_type.rs b/leo-inputs/src/types/group_type.rs new file mode 100644 index 0000000000..c099ab778a --- /dev/null +++ b/leo-inputs/src/types/group_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_group))] +pub struct GroupType {} diff --git a/leo-inputs/src/types/integer_type.rs b/leo-inputs/src/types/integer_type.rs new file mode 100644 index 0000000000..6d74555f09 --- /dev/null +++ b/leo-inputs/src/types/integer_type.rs @@ -0,0 +1,33 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_integer))] +pub enum IntegerType { + U8Type(U8Type), + U16Type(U16Type), + U32Type(U32Type), + U64Type(U64Type), + U128Type(U128Type), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u8))] +pub struct U8Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u16))] +pub struct U16Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u32))] +pub struct U32Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u64))] +pub struct U64Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u128))] +pub struct U128Type {} diff --git a/leo-inputs/src/types/mod.rs b/leo-inputs/src/types/mod.rs new file mode 100644 index 0000000000..cd0d08ac60 --- /dev/null +++ b/leo-inputs/src/types/mod.rs @@ -0,0 +1,23 @@ +pub mod array_type; +pub use array_type::*; + +pub mod boolean_type; +pub use boolean_type::*; + +pub mod circuit_type; +pub use circuit_type::*; + +pub mod data_type; +pub use data_type::*; + +pub mod field_type; +pub use field_type::*; + +pub mod group_type; +pub use group_type::*; + +pub mod integer_type; +pub use integer_type::*; + +pub mod type_; +pub use type_::*; diff --git a/leo-inputs/src/types/type_.rs b/leo-inputs/src/types/type_.rs new file mode 100644 index 0000000000..ddf650563d --- /dev/null +++ b/leo-inputs/src/types/type_.rs @@ -0,0 +1,22 @@ +use crate::{ast::Rule, types::*}; + +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_))] +pub enum Type<'ast> { + Basic(DataType), + Array(ArrayType<'ast>), + Circuit(CircuitType<'ast>), +} + +impl<'ast> fmt::Display for Type<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Basic(ref _type) => write!(f, "basic"), + Type::Array(ref _type) => write!(f, "array"), + Type::Circuit(ref _type) => write!(f, "struct"), + } + } +} diff --git a/leo-inputs/src/values/boolean_value.rs b/leo-inputs/src/values/boolean_value.rs new file mode 100644 index 0000000000..43f1c71060 --- /dev/null +++ b/leo-inputs/src/values/boolean_value.rs @@ -0,0 +1,20 @@ +use crate::ast::{Rule, span_into_string}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_boolean))] +pub struct BooleanValue<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for BooleanValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} diff --git a/leo-inputs/src/values/field_value.rs b/leo-inputs/src/values/field_value.rs new file mode 100644 index 0000000000..716aa44a3b --- /dev/null +++ b/leo-inputs/src/values/field_value.rs @@ -0,0 +1,20 @@ +use crate::{ast::Rule, types::FieldType, values::NumberValue,}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_field))] +pub struct FieldValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: FieldType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for FieldValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/group_value.rs b/leo-inputs/src/values/group_value.rs new file mode 100644 index 0000000000..78250cd6dc --- /dev/null +++ b/leo-inputs/src/values/group_value.rs @@ -0,0 +1,51 @@ +use crate::{ast::Rule, types::GroupType, values::NumberValue,}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_group))] +pub struct GroupValue<'ast> { + pub value: GroupRepresentation<'ast>, + pub _type: GroupType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for GroupValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_single_or_tuple))] +pub enum GroupRepresentation<'ast> { + Single(NumberValue<'ast>), + Tuple(GroupTuple<'ast>), +} + +impl<'ast> fmt::Display for GroupRepresentation<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GroupRepresentation::Single(number) => write!(f, "{}", number), + GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple), + } + } +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_tuple))] +pub struct GroupTuple<'ast> { + pub x: NumberValue<'ast>, + pub y: NumberValue<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for GroupTuple<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} diff --git a/leo-inputs/src/values/integer_value.rs b/leo-inputs/src/values/integer_value.rs new file mode 100644 index 0000000000..141cb9aab6 --- /dev/null +++ b/leo-inputs/src/values/integer_value.rs @@ -0,0 +1,20 @@ +use crate::{ast::Rule, types::IntegerType, values::NumberValue}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_integer))] +pub struct IntegerValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: IntegerType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for IntegerValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/mod.rs b/leo-inputs/src/values/mod.rs new file mode 100644 index 0000000000..87090f0ffa --- /dev/null +++ b/leo-inputs/src/values/mod.rs @@ -0,0 +1,20 @@ +pub mod boolean_value; +pub use boolean_value::*; + +pub mod field_value; +pub use field_value::*; + +pub mod group_value; +pub use group_value::*; + +pub mod integer_value; +pub use integer_value::*; + +pub mod number_implicit_value; +pub use number_implicit_value::*; + +pub mod number_value; +pub use number_value::*; + +pub mod value; +pub use value::*; diff --git a/leo-inputs/src/values/number_implicit_value.rs b/leo-inputs/src/values/number_implicit_value.rs new file mode 100644 index 0000000000..0aae2cc51e --- /dev/null +++ b/leo-inputs/src/values/number_implicit_value.rs @@ -0,0 +1,19 @@ +use crate::{ast::Rule, values::NumberValue}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_implicit))] +pub struct NumberImplicitValue<'ast> { + pub number: NumberValue<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for NumberImplicitValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/number_value.rs b/leo-inputs/src/values/number_value.rs new file mode 100644 index 0000000000..0401d56d7b --- /dev/null +++ b/leo-inputs/src/values/number_value.rs @@ -0,0 +1,20 @@ +use crate::ast::{Rule, span_into_string}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_number))] +pub struct NumberValue<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for NumberValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} \ No newline at end of file diff --git a/leo-inputs/src/values/value.rs b/leo-inputs/src/values/value.rs new file mode 100644 index 0000000000..c1b869241c --- /dev/null +++ b/leo-inputs/src/values/value.rs @@ -0,0 +1,39 @@ +use crate::{ast::Rule, values::{BooleanValue, IntegerValue, FieldValue, GroupValue, NumberImplicitValue}}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value))] +pub enum Value<'ast> { + Integer(IntegerValue<'ast>), + Field(FieldValue<'ast>), + Group(GroupValue<'ast>), + Boolean(BooleanValue<'ast>), + Implicit(NumberImplicitValue<'ast>), +} + +impl<'ast> Value<'ast> { + pub fn span(&self) -> &Span<'ast> { + match self { + Value::Integer(value) => &value.span, + Value::Field(value) => &value.span, + Value::Group(value) => &value.span, + Value::Boolean(value) => &value.span, + Value::Implicit(value) => &value.span, + } + } +} + +impl<'ast> fmt::Display for Value<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Value::Integer(ref value) => write!(f, "{}", value), + Value::Field(ref value) => write!(f, "{}", value), + Value::Group(ref value) => write!(f, "{}", value), + Value::Boolean(ref value) => write!(f, "{}", value), + Value::Implicit(ref value) => write!(f, "{}", value), + } + } +} From 643cd3026e70ddf4bd6b6635f034fc7d9dc83f58 Mon Sep 17 00:00:00 2001 From: collin Date: Tue, 9 Jun 2020 16:36:15 -0700 Subject: [PATCH 05/15] initial private boolean input support --- Cargo.lock | 3 +- Cargo.toml | 2 +- compiler/Cargo.toml | 1 + compiler/src/compiler.rs | 34 ++++++--- compiler/src/errors/compiler.rs | 4 ++ leo-inputs/Cargo.toml | 2 - leo-inputs/src/circuits/mod.rs | 2 - leo-inputs/src/errors/parser.rs | 11 +-- .../expressions/circuit_inline_expression.rs | 2 +- leo-inputs/src/expressions/expression.rs | 10 ++- leo-inputs/src/expressions/mod.rs | 2 +- leo-inputs/src/files/file.rs | 2 +- leo-inputs/src/lib.rs | 17 ++--- leo-inputs/src/parameters/mod.rs | 2 +- leo-inputs/src/parameters/parameter.rs | 10 ++- leo-inputs/src/sections/header.rs | 2 +- leo-inputs/src/sections/mod.rs | 2 +- leo-inputs/src/sections/section.rs | 4 +- leo-inputs/src/types/circuit_type.rs | 2 +- leo-inputs/src/types/data_type.rs | 7 +- leo-inputs/src/types/field_type.rs | 2 +- leo-inputs/src/values/boolean_value.rs | 2 +- leo-inputs/src/values/field_value.rs | 2 +- leo-inputs/src/values/group_value.rs | 2 +- leo-inputs/src/values/number_value.rs | 4 +- leo-inputs/src/values/value.rs | 5 +- leo/commands/prove.rs | 9 ++- leo/commands/run.rs | 1 + tmp/.gitignore | 2 + tmp/Leo.toml | 3 + tmp/inputs/inputs.leo | 2 + tmp/src/main.leo | 4 ++ types/Cargo.toml | 1 + types/src/input_value.rs | 31 --------- types/src/inputs/input_value.rs | 69 +++++++++++++++++++ types/src/inputs/inputs.rs | 52 ++++++++++++++ types/src/inputs/mod.rs | 5 ++ types/src/lib.rs | 4 +- 38 files changed, 231 insertions(+), 90 deletions(-) create mode 100644 tmp/.gitignore create mode 100644 tmp/Leo.toml create mode 100644 tmp/inputs/inputs.leo create mode 100644 tmp/src/main.leo delete mode 100644 types/src/input_value.rs create mode 100644 types/src/inputs/input_value.rs create mode 100644 types/src/inputs/inputs.rs create mode 100644 types/src/inputs/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 6f13b2333a..fc008fd0df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -551,6 +551,7 @@ version = "0.1.0" dependencies = [ "hex", "leo-ast", + "leo-inputs", "leo-types", "log", "rand", @@ -568,7 +569,6 @@ name = "leo-inputs" version = "0.1.0" dependencies = [ "from-pest", - "leo-compiler", "pest", "pest-ast", "pest_derive", @@ -585,6 +585,7 @@ name = "leo-types" version = "0.1.0" dependencies = [ "leo-ast", + "leo-inputs", "snarkos-errors", "snarkos-models", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 2e753b9d68..3982a1f22c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ name = "leo" path = "leo/main.rs" [workspace] -members = [ "ast", "compiler", "types" ] +members = [ "ast", "compiler", "leo-inputs", "types" ] [dependencies] leo-compiler = { path = "compiler", version = "0.1.0" } diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 6c5f145b0d..4a7c2e1ce3 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] leo-ast = { path = "../ast", version = "0.1.0" } leo-types = { path = "../types", version = "0.1.0" } +leo-inputs = { path = "../leo-inputs", version = "0.1.0" } snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" } snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" } diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index cf14be756a..1be9a384b9 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -6,7 +6,8 @@ use crate::{ GroupType, }; use leo_ast::LeoParser; -use leo_types::{InputValue, Program}; +use leo_inputs::LeoInputsParser; +use leo_types::{InputValue, Inputs, Program}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ @@ -22,7 +23,7 @@ pub struct Compiler> { package_name: String, main_file_path: PathBuf, program: Program, - program_inputs: Vec>, + program_inputs: Inputs, output: Option>, _engine: PhantomData, } @@ -33,7 +34,7 @@ impl> Compiler { package_name: "".to_string(), main_file_path: PathBuf::new(), program: Program::new(), - program_inputs: vec![], + program_inputs: Inputs::new(), output: None, _engine: PhantomData, } @@ -44,7 +45,7 @@ impl> Compiler { package_name, main_file_path, program: Program::new(), - program_inputs: vec![], + program_inputs: Inputs::new(), output: None, _engine: PhantomData, }; @@ -57,7 +58,7 @@ impl> Compiler { } pub fn set_inputs(&mut self, program_inputs: Vec>) { - self.program_inputs = program_inputs; + self.program_inputs.set_private_inputs(program_inputs); } pub fn checksum(&self) -> Result { @@ -77,7 +78,7 @@ impl> Compiler { self, cs: &mut CS, ) -> Result, CompilerError> { - generate_constraints(cs, self.program, self.program_inputs) + generate_constraints(cs, self.program, self.program_inputs.get_private_inputs()) } pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem) -> Result<(), CompilerError> { @@ -98,17 +99,34 @@ impl> Compiler { let package_name = self.package_name.clone(); self.program = Program::from(syntax_tree, package_name); - self.program_inputs = vec![None; self.program.num_parameters]; + self.program_inputs.set_private_inputs_size(self.program.num_parameters); log::debug!("Program parsing complete\n{:#?}", self.program); Ok(()) } + + pub fn parse_inputs(&mut self, file_path: &PathBuf) -> Result<(), CompilerError> { + let mut path = file_path.clone(); + path.push("inputs"); + path.push("inputs.leo"); + + let input_file = &LeoInputsParser::load_file(&path)?; + let syntax_tree = LeoInputsParser::parse_file(&path, input_file)?; + // println!("{:?}", syntax_tree); + + // Check number of private parameters here + + self.program_inputs = Inputs::from_inputs_file(syntax_tree)?; + + Ok(()) + } } impl> ConstraintSynthesizer for Compiler { fn generate_constraints>(self, cs: &mut CS) -> Result<(), SynthesisError> { - let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs).unwrap(); + let _result = + generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_private_inputs()).unwrap(); // Write results to file or something diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index 593015cfb3..d6ee381509 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -1,5 +1,6 @@ use crate::errors::{FunctionError, ImportError}; use leo_ast::{ParserError, SyntaxError}; +use leo_inputs::InputParserError; use leo_types::IntegerError; use std::{io, path::PathBuf}; @@ -15,6 +16,9 @@ pub enum CompilerError { #[error("{}", _0)] ImportError(#[from] ImportError), + #[error("{}", _0)] + InputParserError(#[from] InputParserError), + #[error("{}", _0)] IntegerError(#[from] IntegerError), diff --git a/leo-inputs/Cargo.toml b/leo-inputs/Cargo.toml index 33d89ce2b5..05285399f8 100644 --- a/leo-inputs/Cargo.toml +++ b/leo-inputs/Cargo.toml @@ -5,8 +5,6 @@ authors = ["The Aleo Team "] edition = "2018" [dependencies] -leo-compiler = { path = "../compiler", version = "0.1.0" } - snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" } snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" } snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" } diff --git a/leo-inputs/src/circuits/mod.rs b/leo-inputs/src/circuits/mod.rs index 5b7ea46f55..e9385224e0 100644 --- a/leo-inputs/src/circuits/mod.rs +++ b/leo-inputs/src/circuits/mod.rs @@ -1,4 +1,2 @@ - pub mod circuit_field; pub use circuit_field::*; - diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index 3bce388a25..acab1552c2 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -1,13 +1,16 @@ use crate::{ast::Rule, errors::SyntaxError}; use pest::error::Error; -use std::path::PathBuf; +use std::{path::PathBuf, str::ParseBoolError}; #[derive(Debug, Error)] -pub enum ParserError { +pub enum InputParserError { #[error("Cannot read from the provided file path - {:?}", _0)] FileReadError(PathBuf), + #[error("{}", _0)] + ParseBoolError(#[from] ParseBoolError), + #[error("{}", _0)] SyntaxError(#[from] SyntaxError), @@ -15,8 +18,8 @@ pub enum ParserError { SyntaxTreeError, } -impl From> for ParserError { +impl From> for InputParserError { fn from(error: Error) -> Self { - ParserError::SyntaxError(SyntaxError::from(error)) + InputParserError::SyntaxError(SyntaxError::from(error)) } } diff --git a/leo-inputs/src/expressions/circuit_inline_expression.rs b/leo-inputs/src/expressions/circuit_inline_expression.rs index 52d8b99983..e276373f18 100644 --- a/leo-inputs/src/expressions/circuit_inline_expression.rs +++ b/leo-inputs/src/expressions/circuit_inline_expression.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, circuits::CircuitField, common::Identifier,}; +use crate::{ast::Rule, circuits::CircuitField, common::Identifier}; use pest::Span; use pest_ast::FromPest; diff --git a/leo-inputs/src/expressions/expression.rs b/leo-inputs/src/expressions/expression.rs index af8f20a4ea..662cdf3d10 100644 --- a/leo-inputs/src/expressions/expression.rs +++ b/leo-inputs/src/expressions/expression.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::Identifier, expressions::*, values::Value,}; +use crate::{ast::Rule, common::Identifier, expressions::*, values::Value}; use pest_ast::FromPest; use std::fmt; @@ -30,11 +30,9 @@ impl<'ast> fmt::Display for Expression<'ast> { Expression::ArrayInitializer(ref expression) => { write!(f, "[{} ; {}]", expression.expression, expression.count) } - Expression::CircuitInline(ref expression) => write!( - f, - "inline circuit display not impl {}", - expression.identifier - ), + Expression::CircuitInline(ref expression) => { + write!(f, "inline circuit display not impl {}", expression.identifier) + } } } } diff --git a/leo-inputs/src/expressions/mod.rs b/leo-inputs/src/expressions/mod.rs index f79e25ae50..f7dff738a9 100644 --- a/leo-inputs/src/expressions/mod.rs +++ b/leo-inputs/src/expressions/mod.rs @@ -8,4 +8,4 @@ pub mod circuit_inline_expression; pub use circuit_inline_expression::*; pub mod expression; -pub use expression::*; \ No newline at end of file +pub use expression::*; diff --git a/leo-inputs/src/files/file.rs b/leo-inputs/src/files/file.rs index 48f720d841..1c6a1ddeb9 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 }; +use crate::{ast::Rule, common::EOI, sections::Section}; use pest::Span; use pest_ast::FromPest; diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 1c8a339458..84ce64b65b 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -7,8 +7,8 @@ pub mod errors; pub use errors::*; //extern crate from_pest; -mod ast; pub mod assignments; +mod ast; pub mod circuits; pub mod common; pub mod expressions; @@ -25,23 +25,18 @@ pub struct LeoInputsParser; impl LeoInputsParser { /// Reads in the given file path into a string. - pub fn load_file(file_path: &PathBuf) -> Result { - Ok(fs::read_to_string(file_path) - .map_err(|_| ParserError::FileReadError(file_path.clone()))?) + pub fn load_file(file_path: &PathBuf) -> Result { + Ok(fs::read_to_string(file_path).map_err(|_| InputParserError::FileReadError(file_path.clone()))?) } /// Parses the input file and constructs a syntax tree. - pub fn parse_file<'a>( - file_path: &'a PathBuf, - input_file: &'a str, - ) -> Result, ParserError> { + pub fn parse_file<'a>(file_path: &'a PathBuf, input_file: &'a str) -> Result, InputParserError> { // Parse the file using leo.pest let mut file = ast::parse(input_file) - .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; + .map_err(|error| InputParserError::from(error.with_path(file_path.to_str().unwrap())))?; // Build the abstract syntax tree - let syntax_tree = - files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; + let syntax_tree = files::File::from_pest(&mut file).map_err(|_| InputParserError::SyntaxTreeError)?; // println!("{:?}", syntax_tree); Ok(syntax_tree) diff --git a/leo-inputs/src/parameters/mod.rs b/leo-inputs/src/parameters/mod.rs index 861bb16a1a..cf55dbc6dd 100644 --- a/leo-inputs/src/parameters/mod.rs +++ b/leo-inputs/src/parameters/mod.rs @@ -1,2 +1,2 @@ pub mod parameter; -pub use parameter::*; \ No newline at end of file +pub use parameter::*; diff --git a/leo-inputs/src/parameters/parameter.rs b/leo-inputs/src/parameters/parameter.rs index ee4469eac0..a58e8cc339 100644 --- a/leo-inputs/src/parameters/parameter.rs +++ b/leo-inputs/src/parameters/parameter.rs @@ -1,4 +1,8 @@ -use crate::{ast::Rule, common::{Identifier, Visibility}, types::Type}; +use crate::{ + ast::Rule, + common::{Identifier, Visibility}, + types::Type, +}; use pest::Span; use pest_ast::FromPest; @@ -8,7 +12,7 @@ use pest_ast::FromPest; pub struct Parameter<'ast> { pub variable: Identifier<'ast>, pub visibility: Option, - pub _type: Type<'ast>, + pub type_: Type<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, -} \ No newline at end of file +} diff --git a/leo-inputs/src/sections/header.rs b/leo-inputs/src/sections/header.rs index 3805431def..5ecb08eb14 100644 --- a/leo-inputs/src/sections/header.rs +++ b/leo-inputs/src/sections/header.rs @@ -9,4 +9,4 @@ pub struct Header<'ast> { pub name: Identifier<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, -} \ No newline at end of file +} diff --git a/leo-inputs/src/sections/mod.rs b/leo-inputs/src/sections/mod.rs index 2ed80e53e5..ad84b1fade 100644 --- a/leo-inputs/src/sections/mod.rs +++ b/leo-inputs/src/sections/mod.rs @@ -2,4 +2,4 @@ pub mod header; pub use header::*; pub mod section; -pub use section::*; \ No newline at end of file +pub use section::*; diff --git a/leo-inputs/src/sections/section.rs b/leo-inputs/src/sections/section.rs index c12ad67db6..02186b2c61 100644 --- a/leo-inputs/src/sections/section.rs +++ b/leo-inputs/src/sections/section.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, sections::Header, assignments::Assignment}; +use crate::{assignments::Assignment, ast::Rule, sections::Header}; use pest::Span; use pest_ast::FromPest; @@ -10,4 +10,4 @@ pub struct Section<'ast> { pub assignments: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, -} \ No newline at end of file +} diff --git a/leo-inputs/src/types/circuit_type.rs b/leo-inputs/src/types/circuit_type.rs index 8b87935568..fa8acf3e78 100644 --- a/leo-inputs/src/types/circuit_type.rs +++ b/leo-inputs/src/types/circuit_type.rs @@ -9,4 +9,4 @@ pub struct CircuitType<'ast> { pub identifier: Identifier<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, -} \ No newline at end of file +} diff --git a/leo-inputs/src/types/data_type.rs b/leo-inputs/src/types/data_type.rs index 8cf3a0f75c..84ab20c0ee 100644 --- a/leo-inputs/src/types/data_type.rs +++ b/leo-inputs/src/types/data_type.rs @@ -1,4 +1,7 @@ -use crate::{ast::Rule, types::{IntegerType, FieldType, GroupType, BooleanType}}; +use crate::{ + ast::Rule, + types::{BooleanType, FieldType, GroupType, IntegerType}, +}; use pest_ast::FromPest; @@ -9,4 +12,4 @@ pub enum DataType { Field(FieldType), Group(GroupType), Boolean(BooleanType), -} \ No newline at end of file +} diff --git a/leo-inputs/src/types/field_type.rs b/leo-inputs/src/types/field_type.rs index 64d12a67ab..d3751a2432 100644 --- a/leo-inputs/src/types/field_type.rs +++ b/leo-inputs/src/types/field_type.rs @@ -4,4 +4,4 @@ use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::type_field))] -pub struct FieldType {} \ No newline at end of file +pub struct FieldType {} diff --git a/leo-inputs/src/values/boolean_value.rs b/leo-inputs/src/values/boolean_value.rs index 43f1c71060..c16b9be740 100644 --- a/leo-inputs/src/values/boolean_value.rs +++ b/leo-inputs/src/values/boolean_value.rs @@ -1,4 +1,4 @@ -use crate::ast::{Rule, span_into_string}; +use crate::ast::{span_into_string, Rule}; use pest::Span; use pest_ast::FromPest; diff --git a/leo-inputs/src/values/field_value.rs b/leo-inputs/src/values/field_value.rs index 716aa44a3b..3c21e56cc8 100644 --- a/leo-inputs/src/values/field_value.rs +++ b/leo-inputs/src/values/field_value.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, types::FieldType, values::NumberValue,}; +use crate::{ast::Rule, types::FieldType, values::NumberValue}; use pest::Span; use pest_ast::FromPest; diff --git a/leo-inputs/src/values/group_value.rs b/leo-inputs/src/values/group_value.rs index 78250cd6dc..365954e5ed 100644 --- a/leo-inputs/src/values/group_value.rs +++ b/leo-inputs/src/values/group_value.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, types::GroupType, values::NumberValue,}; +use crate::{ast::Rule, types::GroupType, values::NumberValue}; use pest::Span; use pest_ast::FromPest; diff --git a/leo-inputs/src/values/number_value.rs b/leo-inputs/src/values/number_value.rs index 0401d56d7b..1054911286 100644 --- a/leo-inputs/src/values/number_value.rs +++ b/leo-inputs/src/values/number_value.rs @@ -1,4 +1,4 @@ -use crate::ast::{Rule, span_into_string}; +use crate::ast::{span_into_string, Rule}; use pest::Span; use pest_ast::FromPest; @@ -17,4 +17,4 @@ impl<'ast> fmt::Display for NumberValue<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.value) } -} \ No newline at end of file +} diff --git a/leo-inputs/src/values/value.rs b/leo-inputs/src/values/value.rs index c1b869241c..6c3601fb26 100644 --- a/leo-inputs/src/values/value.rs +++ b/leo-inputs/src/values/value.rs @@ -1,4 +1,7 @@ -use crate::{ast::Rule, values::{BooleanValue, IntegerValue, FieldValue, GroupValue, NumberImplicitValue}}; +use crate::{ + ast::Rule, + values::{BooleanValue, FieldValue, GroupValue, IntegerValue, NumberImplicitValue}, +}; use pest::Span; use pest_ast::FromPest; diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 64e3423db3..5c8243b8a1 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -34,12 +34,19 @@ impl CLI for ProveCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result { - let (program, parameters, _) = SetupCommand::output(options)?; + let (mut program, parameters, _) = SetupCommand::output(options)?; // Get the package name let path = current_dir()?; let package_name = Manifest::try_from(&path)?.get_package_name(); + // Fetch private inputs here + program.parse_inputs(&path)?; + // let _res = LeoInputsParser::get_private(&path).unwrap(); + // let inputs_path = path.clone().push("/inputs") + // LeoInputsParser::load_file() + // program.set_inputs(); + // Start the timer let start = Instant::now(); diff --git a/leo/commands/run.rs b/leo/commands/run.rs index a7004ee18c..522cfcea95 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -36,6 +36,7 @@ impl CLI for RunCommand { let mut verifying = Duration::new(0, 0); + // fetch public inputs here // let _inputs: Vec<_> = [1u32; 1].to_vec(); let start = Instant::now(); diff --git a/tmp/.gitignore b/tmp/.gitignore new file mode 100644 index 0000000000..ee3b8ff567 --- /dev/null +++ b/tmp/.gitignore @@ -0,0 +1,2 @@ +/output +/.leo diff --git a/tmp/Leo.toml b/tmp/Leo.toml new file mode 100644 index 0000000000..36afb9b7ec --- /dev/null +++ b/tmp/Leo.toml @@ -0,0 +1,3 @@ +[package] +name = "tmp" +version = "0.1.0" diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo new file mode 100644 index 0000000000..8a4b4e64eb --- /dev/null +++ b/tmp/inputs/inputs.leo @@ -0,0 +1,2 @@ +[main] +x: private bool = true; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo new file mode 100644 index 0000000000..2b0615170f --- /dev/null +++ b/tmp/src/main.leo @@ -0,0 +1,4 @@ +// The 'tmp' main function. +function main(x: private bool) -> bool { + return x +} diff --git a/types/Cargo.toml b/types/Cargo.toml index 4bab67b62d..ed673f1d3d 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] leo-ast = { path = "../ast", version = "0.1.0" } +leo-inputs = { path = "../leo-inputs", version = "0.1.0" } snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" } snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" } diff --git a/types/src/input_value.rs b/types/src/input_value.rs deleted file mode 100644 index 3e7cf72732..0000000000 --- a/types/src/input_value.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::fmt; - -#[derive(Clone, PartialEq, Eq)] -pub enum InputValue { - Integer(u128), - Field(String), - Group(String), - Boolean(bool), - Array(Vec), -} - -impl fmt::Display for InputValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - InputValue::Integer(ref integer) => write!(f, "{}", integer), - InputValue::Field(ref field) => write!(f, "{}", field), - InputValue::Group(ref group) => write!(f, "{}", group), - InputValue::Boolean(ref bool) => write!(f, "{}", bool), - InputValue::Array(ref array) => { - write!(f, "[")?; - for (i, e) in array.iter().enumerate() { - write!(f, "{}", e)?; - if i < array.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, "]") - } - } - } -} diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs new file mode 100644 index 0000000000..dc478e20b1 --- /dev/null +++ b/types/src/inputs/input_value.rs @@ -0,0 +1,69 @@ +use leo_inputs::{ + errors::InputParserError, + expressions::Expression, + types::{DataType, Type}, + values::{BooleanValue, Value}, +}; +use std::fmt; + +#[derive(Clone, PartialEq, Eq)] +pub enum InputValue { + Integer(u128), + Field(String), + Group(String), + Boolean(bool), + Array(Vec), +} + +impl<'ast> InputValue { + fn from_boolean(boolean: BooleanValue<'ast>) -> Result { + let boolean = boolean.value.parse::()?; + Ok(InputValue::Boolean(boolean)) + } + + fn from_value(data_type: DataType, value: Value<'ast>) -> Result { + match (data_type, value) { + (DataType::Boolean(_), Value::Boolean(value)) => InputValue::from_boolean(value), + (DataType::Integer(_), Value::Integer(_)) => unimplemented!(), + (DataType::Group(_), Value::Group(_)) => unimplemented!(), + (DataType::Field(_), Value::Field(_)) => unimplemented!(), + (data_type, Value::Implicit(_)) => unimplemented!(), //do something with data type + (_, _) => unimplemented!("incompatible types"), + } + } + + pub(crate) fn from_expression(type_: Type<'ast>, expression: Expression<'ast>) -> Result { + // evaluate expression + match (type_, expression) { + (Type::Basic(_), Expression::Variable(ref variable)) => unimplemented!("variable inputs not supported"), + (Type::Basic(data_type), Expression::Value(value)) => InputValue::from_value(data_type, value), + (Type::Array(array_type), Expression::ArrayInline(_)) => unimplemented!(), + (Type::Array(array_type), Expression::ArrayInitializer(_)) => unimplemented!(), + (Type::Circuit(circuit_type), Expression::CircuitInline(_)) => unimplemented!(), + (_, _) => unimplemented!("incompatible types"), + } + + // check type + } +} + +impl fmt::Display for InputValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + InputValue::Integer(ref integer) => write!(f, "{}", integer), + InputValue::Field(ref field) => write!(f, "{}", field), + InputValue::Group(ref group) => write!(f, "{}", group), + InputValue::Boolean(ref bool) => write!(f, "{}", bool), + InputValue::Array(ref array) => { + write!(f, "[")?; + for (i, e) in array.iter().enumerate() { + write!(f, "{}", e)?; + if i < array.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "]") + } + } + } +} diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs new file mode 100644 index 0000000000..7c44b379d5 --- /dev/null +++ b/types/src/inputs/inputs.rs @@ -0,0 +1,52 @@ +use crate::InputValue; +use leo_inputs::{ + common::visibility::{Private, Visibility}, + files::File, + InputParserError, +}; + +#[derive(Clone)] +pub struct Inputs { + private: Vec>, + //public: Vec<_> +} + +impl Inputs { + pub fn new() -> Self { + Self { private: vec![] } + } + + pub fn get_private_inputs(&self) -> Vec> { + return self.private.clone(); + } + + pub fn set_private_inputs(&mut self, inputs: Vec>) { + self.private = inputs; + } + + pub fn set_private_inputs_size(&mut self, size: usize) { + self.private = vec![None; size]; + } + + pub fn from_inputs_file(file: File) -> Result { + let mut private = vec![]; + + for section in file.sections.into_iter() { + for assignment in section.assignments.into_iter() { + if let Some(Visibility::Public(_)) = assignment.parameter.visibility { + // Collect public parameters here + } else { + // parameter is private by default + + // evaluate expression + let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; + + // push value to vector + private.push(Some(value)); + } + } + } + + Ok(Self { private }) + } +} diff --git a/types/src/inputs/mod.rs b/types/src/inputs/mod.rs new file mode 100644 index 0000000000..5f93ed25d3 --- /dev/null +++ b/types/src/inputs/mod.rs @@ -0,0 +1,5 @@ +pub mod inputs; +pub use inputs::*; + +pub mod input_value; +pub use input_value::*; diff --git a/types/src/lib.rs b/types/src/lib.rs index 431c25c8d2..d398829f59 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -19,8 +19,8 @@ pub use functions::*; pub mod imports; pub use imports::*; -pub mod input_value; -pub use input_value::*; +pub mod inputs; +pub use inputs::*; pub mod integer; pub use integer::*; From c6d322128985d06b569de7cbc3aa242b863c0c5b Mon Sep 17 00:00:00 2001 From: collin Date: Tue, 9 Jun 2020 19:29:26 -0700 Subject: [PATCH 06/15] private input primitives and array support --- leo-inputs/src/errors/parser.rs | 14 +- .../array_initializer_expression.rs | 4 +- leo-inputs/src/leo-inputs.pest | 4 +- leo-inputs/src/types/array_type.rs | 10 +- leo-inputs/src/types/data_type.rs | 11 ++ tmp/inputs/inputs.leo | 2 +- tmp/src/main.leo | 4 +- types/src/inputs/input_value.rs | 133 +++++++++++++++--- types/src/inputs/inputs.rs | 6 +- 9 files changed, 157 insertions(+), 31 deletions(-) diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index acab1552c2..4b05621692 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -1,21 +1,33 @@ use crate::{ast::Rule, errors::SyntaxError}; use pest::error::Error; -use std::{path::PathBuf, str::ParseBoolError}; +use std::{num::ParseIntError, path::PathBuf, str::ParseBoolError}; #[derive(Debug, Error)] pub enum InputParserError { + #[error("expected array length {}, got {}", _0, _1)] + InvalidArrayLength(usize, usize), + + #[error("expected type {}, got {}", _0, _1)] + IncompatibleTypes(String, String), + #[error("Cannot read from the provided file path - {:?}", _0)] FileReadError(PathBuf), #[error("{}", _0)] ParseBoolError(#[from] ParseBoolError), + #[error("{}", _0)] + ParseIntError(#[from] ParseIntError), + #[error("{}", _0)] SyntaxError(#[from] SyntaxError), #[error("Unable to construct abstract syntax tree")] SyntaxTreeError, + + #[error("found an empty array dimension in type")] + UndefinedArrayDimension, } impl From> for InputParserError { diff --git a/leo-inputs/src/expressions/array_initializer_expression.rs b/leo-inputs/src/expressions/array_initializer_expression.rs index 37ebc032d5..ba9d86f3a0 100644 --- a/leo-inputs/src/expressions/array_initializer_expression.rs +++ b/leo-inputs/src/expressions/array_initializer_expression.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, expressions::Expression, values::Value}; +use crate::{ast::Rule, expressions::Expression, values::NumberValue}; use pest::Span; use pest_ast::FromPest; @@ -7,7 +7,7 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::expression_array_initializer))] pub struct ArrayInitializerExpression<'ast> { pub expression: Box>, - pub count: Value<'ast>, + pub count: NumberValue<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 73ef11cbe5..4e26c4b1c6 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -47,7 +47,7 @@ type_data = { type_field | type_group | type_boolean | type_integer } type_circuit = { identifier } // Declared in types/array_type.rs -type_array = { type_data ~ ("[" ~ value ~ "]")+ } +type_array = { type_data ~ ("[" ~ value_number ~ "]")+ } /// Values @@ -77,7 +77,7 @@ group_single_or_tuple = { value_number | group_tuple } /// Expressions // Declared in expressions/array_initializer_expression.rs -expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } +expression_array_initializer = { "[" ~ expression ~ ";" ~ value_number ~ "]" } // Declared in expressions/array_inline_expression.rs expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} diff --git a/leo-inputs/src/types/array_type.rs b/leo-inputs/src/types/array_type.rs index 01650cdfb3..b73cb53fea 100644 --- a/leo-inputs/src/types/array_type.rs +++ b/leo-inputs/src/types/array_type.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, types::DataType, values::Value}; +use crate::{ast::Rule, types::DataType, values::NumberValue}; use pest::Span; use pest_ast::FromPest; @@ -7,7 +7,13 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::type_array))] pub struct ArrayType<'ast> { pub _type: DataType, - pub dimensions: Vec>, + pub dimensions: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, } + +impl<'ast> ArrayType<'ast> { + pub fn next_dimension(&mut self) -> Option> { + self.dimensions.pop() + } +} diff --git a/leo-inputs/src/types/data_type.rs b/leo-inputs/src/types/data_type.rs index 84ab20c0ee..49ad917eac 100644 --- a/leo-inputs/src/types/data_type.rs +++ b/leo-inputs/src/types/data_type.rs @@ -13,3 +13,14 @@ pub enum DataType { Group(GroupType), Boolean(BooleanType), } + +impl std::fmt::Display for DataType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + DataType::Integer(_) => write!(f, "integer"), + DataType::Field(_) => write!(f, "field"), + DataType::Group(_) => write!(f, "group"), + DataType::Boolean(_) => write!(f, "bool"), + } + } +} diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo index 8a4b4e64eb..9e8858bdde 100644 --- a/tmp/inputs/inputs.leo +++ b/tmp/inputs/inputs.leo @@ -1,2 +1,2 @@ [main] -x: private bool = true; \ No newline at end of file +a: private bool[2] = [true; 2]; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo index 2b0615170f..60ac840043 100644 --- a/tmp/src/main.leo +++ b/tmp/src/main.leo @@ -1,4 +1,4 @@ // The 'tmp' main function. -function main(x: private bool) -> bool { - return x +function main(a: bool[2]) -> bool { + return a[0] } diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs index dc478e20b1..f3cb251a39 100644 --- a/types/src/inputs/input_value.rs +++ b/types/src/inputs/input_value.rs @@ -1,8 +1,8 @@ use leo_inputs::{ errors::InputParserError, - expressions::Expression, - types::{DataType, Type}, - values::{BooleanValue, Value}, + expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression}, + types::{ArrayType, DataType, Type}, + values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value}, }; use std::fmt; @@ -21,29 +21,130 @@ impl<'ast> InputValue { Ok(InputValue::Boolean(boolean)) } + fn from_number(number: NumberValue<'ast>) -> Result { + let integer = number.value.parse::()?; + Ok(InputValue::Integer(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 { + match data_type { + DataType::Boolean(_) => Err(InputParserError::IncompatibleTypes( + "bool".to_string(), + "implicit number".to_string(), + )), + DataType::Integer(_) => InputValue::from_number(implicit.number), + DataType::Group(_) => Ok(InputValue::Group(implicit.number.value)), + DataType::Field(_) => Ok(InputValue::Field(implicit.number.value)), + } + } + fn from_value(data_type: DataType, value: Value<'ast>) -> Result { match (data_type, value) { - (DataType::Boolean(_), Value::Boolean(value)) => InputValue::from_boolean(value), - (DataType::Integer(_), Value::Integer(_)) => unimplemented!(), - (DataType::Group(_), Value::Group(_)) => unimplemented!(), - (DataType::Field(_), Value::Field(_)) => unimplemented!(), - (data_type, Value::Implicit(_)) => unimplemented!(), //do something with data type - (_, _) => unimplemented!("incompatible types"), + (DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean), + (DataType::Integer(_), Value::Integer(integer)) => InputValue::from_number(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), + (data_type, value) => Err(InputParserError::IncompatibleTypes( + data_type.to_string(), + value.to_string(), + )), } } pub(crate) fn from_expression(type_: Type<'ast>, expression: Expression<'ast>) -> Result { - // evaluate expression match (type_, expression) { - (Type::Basic(_), Expression::Variable(ref variable)) => unimplemented!("variable inputs not supported"), (Type::Basic(data_type), Expression::Value(value)) => InputValue::from_value(data_type, value), - (Type::Array(array_type), Expression::ArrayInline(_)) => unimplemented!(), - (Type::Array(array_type), Expression::ArrayInitializer(_)) => unimplemented!(), - (Type::Circuit(circuit_type), Expression::CircuitInline(_)) => unimplemented!(), - (_, _) => unimplemented!("incompatible types"), + (Type::Array(array_type), Expression::ArrayInline(inline)) => { + InputValue::from_array_inline(array_type, inline) + } + (Type::Array(array_type), Expression::ArrayInitializer(initializer)) => { + InputValue::from_array_initializer(array_type, initializer) + } + (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not implemented"), + (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable inputs not supported"), + (type_, value) => Err(InputParserError::IncompatibleTypes( + type_.to_string(), + value.to_string(), + )), + } + } + + pub(crate) fn from_array_inline( + mut array_type: ArrayType, + inline: ArrayInlineExpression, + ) -> Result { + match array_type.next_dimension() { + Some(number) => { + let outer_dimension = number.value.parse::()?; + + if outer_dimension != inline.expressions.len() { + return Err(InputParserError::InvalidArrayLength( + outer_dimension, + inline.expressions.len(), + )); + } + } + None => return Err(InputParserError::UndefinedArrayDimension), } - // check type + let inner_array_type = if array_type.dimensions.len() == 0 { + // this is a single array + Type::Basic(array_type._type) + } else { + Type::Array(array_type) + }; + + let mut values = vec![]; + for expression in inline.expressions.into_iter() { + let value = InputValue::from_expression(inner_array_type.clone(), expression)?; + + values.push(value) + } + + Ok(InputValue::Array(values)) + } + + pub(crate) fn from_array_initializer( + mut array_type: ArrayType, + initializer: ArrayInitializerExpression, + ) -> Result { + let initializer_count = initializer.count.value.parse::()?; + + match array_type.next_dimension() { + Some(number) => { + let outer_dimension = number.value.parse::()?; + + if outer_dimension != initializer_count { + return Err(InputParserError::InvalidArrayLength(outer_dimension, initializer_count)); + } + } + None => return Err(InputParserError::UndefinedArrayDimension), + } + + let inner_array_type = if array_type.dimensions.len() == 0 { + // this is a single array + Type::Basic(array_type._type) + } else { + Type::Array(array_type) + }; + + let mut values = vec![]; + for _ in 0..initializer_count { + let value = InputValue::from_expression(inner_array_type.clone(), *initializer.expression.clone())?; + + values.push(value) + } + + Ok(InputValue::Array(values)) } } diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index 7c44b379d5..874b188f19 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,9 +1,5 @@ use crate::InputValue; -use leo_inputs::{ - common::visibility::{Private, Visibility}, - files::File, - InputParserError, -}; +use leo_inputs::{common::visibility::Visibility, files::File, InputParserError}; #[derive(Clone)] pub struct Inputs { From 67b8a48fcfbadf4d2c10d2bc1976d5a50d7abad0 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 16:14:55 -0700 Subject: [PATCH 07/15] public input booleans and integers --- .gitignore | 1 + compiler/src/compiler.rs | 15 +++++--- compiler/tests/array/mod.rs | 9 ++++- compiler/tests/boolean/mod.rs | 3 +- compiler/tests/mutability/mod.rs | 5 ++- leo-inputs/src/types/integer_type.rs | 12 +++--- leo/commands/prove.rs | 12 +++--- leo/commands/run.rs | 9 +++-- tmp/inputs/inputs.leo | 2 +- tmp/src/main.leo | 4 +- types/src/inputs/input_fields.rs | 34 +++++++++++++++++ types/src/inputs/input_value.rs | 36 ++++++++++++------ types/src/inputs/inputs.rs | 56 +++++++++++++++++++--------- types/src/inputs/mod.rs | 3 ++ types/src/integer.rs | 2 +- 15 files changed, 142 insertions(+), 61 deletions(-) create mode 100644 types/src/inputs/input_fields.rs diff --git a/.gitignore b/.gitignore index e995008d72..a2f8c9699b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +/tmp/ **.idea/ outputs/ *.DS_Store diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 1be9a384b9..55da44d852 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -16,6 +16,7 @@ use snarkos_models::{ }; use sha2::{Digest, Sha256}; +use snarkos_models::curves::PairingEngine; use std::{fs, marker::PhantomData, path::PathBuf}; #[derive(Clone)] @@ -58,7 +59,11 @@ impl> Compiler { } pub fn set_inputs(&mut self, program_inputs: Vec>) { - self.program_inputs.set_private_inputs(program_inputs); + self.program_inputs.set_inputs(program_inputs); + } + + pub fn get_public_inputs(&self) -> Result, CompilerError> { + Ok(self.program_inputs.get_public_inputs::()?) } pub fn checksum(&self) -> Result { @@ -78,7 +83,7 @@ impl> Compiler { self, cs: &mut CS, ) -> Result, CompilerError> { - generate_constraints(cs, self.program, self.program_inputs.get_private_inputs()) + generate_constraints(cs, self.program, self.program_inputs.get_inputs()) } pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem) -> Result<(), CompilerError> { @@ -99,7 +104,7 @@ impl> Compiler { let package_name = self.package_name.clone(); self.program = Program::from(syntax_tree, package_name); - self.program_inputs.set_private_inputs_size(self.program.num_parameters); + self.program_inputs.set_inputs_size(self.program.num_parameters); log::debug!("Program parsing complete\n{:#?}", self.program); @@ -116,7 +121,6 @@ impl> Compiler { // println!("{:?}", syntax_tree); // Check number of private parameters here - self.program_inputs = Inputs::from_inputs_file(syntax_tree)?; Ok(()) @@ -125,8 +129,7 @@ impl> Compiler { impl> ConstraintSynthesizer for Compiler { fn generate_constraints>(self, cs: &mut CS) -> Result<(), SynthesisError> { - let _result = - generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_private_inputs()).unwrap(); + let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_inputs()).unwrap(); // Write results to file or something diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index f38d620719..2df023642b 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::{InputValue, Integer, IntegerError}; +use leo_inputs::types::{IntegerType, U32Type}; use snarkos_models::gadgets::utilities::uint::UInt32; // [1, 1, 1] @@ -52,6 +53,10 @@ fn fail_synthesis(program: EdwardsTestCompiler) { } } +pub(crate) fn input_value_u32_one() -> InputValue { + InputValue::Integer(IntegerType::U32Type(U32Type {}), 1) +} + // Expressions #[test] @@ -101,7 +106,7 @@ fn test_input_array() { let bytes = include_bytes!("input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Array(vec![InputValue::Integer(1u128); 3]))]); + program.set_inputs(vec![Some(InputValue::Array(vec![input_value_u32_one(); 3]))]); output_ones(program) } @@ -111,7 +116,7 @@ fn test_input_array_fail() { let bytes = include_bytes!("input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1u128))]); + program.set_inputs(vec![Some(input_value_u32_one())]); fail_array(program); } diff --git a/compiler/tests/boolean/mod.rs b/compiler/tests/boolean/mod.rs index 5ad4313719..dd4065da9c 100644 --- a/compiler/tests/boolean/mod.rs +++ b/compiler/tests/boolean/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::InputValue; +use crate::array::input_value_u32_one; use snarkos_models::gadgets::utilities::boolean::Boolean; pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) { @@ -76,7 +77,7 @@ fn test_input_bool_field() { let bytes = include_bytes!("input_bool.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1u128))]); + program.set_inputs(vec![Some(input_value_u32_one())]); fail_boolean(program); } diff --git a/compiler/tests/mutability/mod.rs b/compiler/tests/mutability/mod.rs index 5a6defbfd8..e5daaefa63 100644 --- a/compiler/tests/mutability/mod.rs +++ b/compiler/tests/mutability/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::{InputValue, Integer}; +use crate::array::input_value_u32_one; use snarkos_curves::edwards_bls12::Fq; use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::uint::UInt32}; @@ -84,7 +85,7 @@ fn test_function_input() { let bytes = include_bytes!("function_input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1))]); + program.set_inputs(vec![Some(input_value_u32_one())]); mut_fail(program); } @@ -93,6 +94,6 @@ fn test_function_input_mut() { let bytes = include_bytes!("function_input_mut.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1))]); + program.set_inputs(vec![Some(input_value_u32_one())]); mut_success(program); } diff --git a/leo-inputs/src/types/integer_type.rs b/leo-inputs/src/types/integer_type.rs index 6d74555f09..504a1c3706 100644 --- a/leo-inputs/src/types/integer_type.rs +++ b/leo-inputs/src/types/integer_type.rs @@ -2,7 +2,7 @@ use crate::ast::Rule; use pest_ast::FromPest; -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_integer))] pub enum IntegerType { U8Type(U8Type), @@ -12,22 +12,22 @@ pub enum IntegerType { U128Type(U128Type), } -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u8))] pub struct U8Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u16))] pub struct U16Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u32))] pub struct U32Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u64))] pub struct U64Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u128))] pub struct U128Type {} diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 5c8243b8a1..dc9740b0b5 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -10,7 +10,9 @@ use snarkos_algorithms::snark::{create_random_proof, Proof}; use snarkos_curves::bls12_377::Bls12_377; use clap::ArgMatches; +use leo_compiler::{compiler::Compiler, edwards_bls12::EdwardsGroupType}; use rand::thread_rng; +use snarkos_curves::edwards_bls12::Fq; use std::{convert::TryFrom, env::current_dir, time::Instant}; #[derive(Debug)] @@ -18,7 +20,7 @@ pub struct ProveCommand; impl CLI for ProveCommand { type Options = (); - type Output = Proof; + type Output = (Compiler, Proof); const ABOUT: AboutType = "Run the program and produce a proof"; const ARGUMENTS: &'static [ArgumentType] = &[]; @@ -42,16 +44,12 @@ impl CLI for ProveCommand { // Fetch private inputs here program.parse_inputs(&path)?; - // let _res = LeoInputsParser::get_private(&path).unwrap(); - // let inputs_path = path.clone().push("/inputs") - // LeoInputsParser::load_file() - // program.set_inputs(); // Start the timer let start = Instant::now(); let rng = &mut thread_rng(); - let program_proof = create_random_proof(program, ¶meters, rng).unwrap(); + let program_proof = create_random_proof(program.clone(), ¶meters, rng).unwrap(); log::info!("Prover completed in {:?} milliseconds", start.elapsed().as_millis()); @@ -62,6 +60,6 @@ impl CLI for ProveCommand { log::info!("Completed program proving"); - Ok(program_proof) + Ok((program, program_proof)) } } diff --git a/leo/commands/run.rs b/leo/commands/run.rs index 522cfcea95..20f4dd290c 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -6,6 +6,7 @@ use crate::{ }; use snarkos_algorithms::snark::verify_proof; +use snarkos_curves::bls12_377::Bls12_377; use clap::ArgMatches; use std::time::{Duration, Instant}; @@ -32,16 +33,16 @@ impl CLI for RunCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result<(), CLIError> { let (_program, _parameters, prepared_verifying_key) = SetupCommand::output(options)?; - let proof = ProveCommand::output(options)?; + let (program, proof) = ProveCommand::output(options)?; let mut verifying = Duration::new(0, 0); - // fetch public inputs here - // let _inputs: Vec<_> = [1u32; 1].to_vec(); + // fetch public inputs + let inputs: Vec<_> = program.get_public_inputs::().unwrap(); let start = Instant::now(); - let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap(); + let is_success = verify_proof(&prepared_verifying_key, &proof, &inputs).unwrap(); verifying += start.elapsed(); diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo index 9e8858bdde..d822cd1b41 100644 --- a/tmp/inputs/inputs.leo +++ b/tmp/inputs/inputs.leo @@ -1,2 +1,2 @@ [main] -a: private bool[2] = [true; 2]; \ No newline at end of file +a: public u128 = 120; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo index 60ac840043..13ed40de78 100644 --- a/tmp/src/main.leo +++ b/tmp/src/main.leo @@ -1,4 +1,4 @@ // The 'tmp' main function. -function main(a: bool[2]) -> bool { - return a[0] +function main(a: public u128) -> u128 { + return a } diff --git a/types/src/inputs/input_fields.rs b/types/src/inputs/input_fields.rs new file mode 100644 index 0000000000..fecb030498 --- /dev/null +++ b/types/src/inputs/input_fields.rs @@ -0,0 +1,34 @@ +use leo_inputs::{types::IntegerType, InputParserError}; +use snarkos_models::curves::{Field, PairingEngine}; + +pub struct InputFields(pub Vec); + +impl InputFields { + pub(crate) fn from_boolean(boolean: &bool) -> Self { + if *boolean { + Self(vec![E::Fr::one()]) + } else { + Self(vec![E::Fr::zero()]) + } + } + + pub(crate) fn from_integer(type_: &IntegerType, integer: &u128) -> Result { + let bits: usize = match type_ { + IntegerType::U8Type(_) => 8, + IntegerType::U16Type(_) => 16, + IntegerType::U32Type(_) => 32, + IntegerType::U64Type(_) => 64, + IntegerType::U128Type(_) => 128, + }; + let mut fields = vec![]; + + for i in 0..bits { + let boolean = (integer.to_le() >> i) & 1 == 1; + let mut boolean_fields = InputFields::::from_boolean(&boolean); + + fields.append(&mut boolean_fields.0); + } + + Ok(Self(fields)) + } +} diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs index f3cb251a39..6403f8b2f3 100644 --- a/types/src/inputs/input_value.rs +++ b/types/src/inputs/input_value.rs @@ -1,14 +1,16 @@ +use crate::InputFields; use leo_inputs::{ errors::InputParserError, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression}, - types::{ArrayType, DataType, Type}, + types::{ArrayType, DataType, IntegerType, Type}, values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value}, }; +use snarkos_models::curves::PairingEngine; use std::fmt; #[derive(Clone, PartialEq, Eq)] pub enum InputValue { - Integer(u128), + Integer(IntegerType, u128), Field(String), Group(String), Boolean(bool), @@ -21,9 +23,9 @@ impl<'ast> InputValue { Ok(InputValue::Boolean(boolean)) } - fn from_number(number: NumberValue<'ast>) -> Result { + fn from_number(integer_type: IntegerType, number: NumberValue<'ast>) -> Result { let integer = number.value.parse::()?; - Ok(InputValue::Integer(integer)) + Ok(InputValue::Integer(integer_type, integer)) } fn from_group(group: GroupValue<'ast>) -> Self { @@ -40,7 +42,7 @@ impl<'ast> InputValue { "bool".to_string(), "implicit number".to_string(), )), - DataType::Integer(_) => InputValue::from_number(implicit.number), + 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)), } @@ -49,7 +51,9 @@ impl<'ast> InputValue { fn from_value(data_type: DataType, value: Value<'ast>) -> Result { match (data_type, value) { (DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean), - (DataType::Integer(_), Value::Integer(integer)) => InputValue::from_number(integer.number), + (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), @@ -69,8 +73,8 @@ impl<'ast> InputValue { (Type::Array(array_type), Expression::ArrayInitializer(initializer)) => { InputValue::from_array_initializer(array_type, initializer) } - (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not implemented"), - (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable inputs not supported"), + (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not supported"), + (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable input values not supported"), (type_, value) => Err(InputParserError::IncompatibleTypes( type_.to_string(), value.to_string(), @@ -146,15 +150,25 @@ impl<'ast> InputValue { Ok(InputValue::Array(values)) } + + pub(crate) fn to_input_fields(&self) -> Result, InputParserError> { + match self { + InputValue::Boolean(boolean) => Ok(InputFields::from_boolean(boolean)), + InputValue::Integer(type_, number) => InputFields::from_integer(type_, number), + InputValue::Group(_) => unimplemented!(), + InputValue::Field(_) => unimplemented!(), + InputValue::Array(_) => unimplemented!(), + } + } } impl fmt::Display for InputValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - InputValue::Integer(ref integer) => write!(f, "{}", integer), - InputValue::Field(ref field) => write!(f, "{}", field), + InputValue::Boolean(ref boolean) => write!(f, "{}", boolean), + InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_), InputValue::Group(ref group) => write!(f, "{}", group), - InputValue::Boolean(ref bool) => write!(f, "{}", bool), + InputValue::Field(ref field) => write!(f, "{}", field), InputValue::Array(ref array) => { write!(f, "[")?; for (i, e) in array.iter().enumerate() { diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index 874b188f19..eb3d334f5f 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,48 +1,68 @@ use crate::InputValue; use leo_inputs::{common::visibility::Visibility, files::File, InputParserError}; +use snarkos_models::curves::PairingEngine; #[derive(Clone)] pub struct Inputs { - private: Vec>, - //public: Vec<_> + program_inputs: Vec>, + public: Vec, } impl Inputs { pub fn new() -> Self { - Self { private: vec![] } + Self { + program_inputs: vec![], + public: vec![], + } } - pub fn get_private_inputs(&self) -> Vec> { - return self.private.clone(); + pub fn get_inputs(&self) -> Vec> { + self.program_inputs.clone() } - pub fn set_private_inputs(&mut self, inputs: Vec>) { - self.private = inputs; + pub fn set_inputs(&mut self, inputs: Vec>) { + self.program_inputs = inputs; } - pub fn set_private_inputs_size(&mut self, size: usize) { - self.private = vec![None; size]; + pub fn set_inputs_size(&mut self, size: usize) { + self.program_inputs = vec![None; size]; } pub fn from_inputs_file(file: File) -> Result { let mut private = vec![]; + let mut public = vec![]; for section in file.sections.into_iter() { for assignment in section.assignments.into_iter() { + let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; if let Some(Visibility::Public(_)) = assignment.parameter.visibility { - // Collect public parameters here - } else { - // parameter is private by default + // Collect public inputs here - // evaluate expression - let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; - - // push value to vector - private.push(Some(value)); + public.push(value.clone()); } + + // push value to vector + private.push(Some(value)); } } - Ok(Self { private }) + Ok(Self { + program_inputs: private, + public, + }) + } + + pub fn get_public_inputs(&self) -> Result, InputParserError> { + let mut input_vec = vec![]; + + for input in self.public.iter() { + // get fields + let mut input_fields = input.to_input_fields::()?; + + // push fields to input_vec + input_vec.append(&mut input_fields.0) + } + + Ok(input_vec) } } diff --git a/types/src/inputs/mod.rs b/types/src/inputs/mod.rs index 5f93ed25d3..085568ef93 100644 --- a/types/src/inputs/mod.rs +++ b/types/src/inputs/mod.rs @@ -1,5 +1,8 @@ pub mod inputs; pub use inputs::*; +pub mod input_fields; +pub use input_fields::*; + pub mod input_value; pub use input_value::*; diff --git a/types/src/integer.rs b/types/src/integer.rs index a6d056f740..eff0b91dfe 100644 --- a/types/src/integer.rs +++ b/types/src/integer.rs @@ -87,7 +87,7 @@ impl Integer { // Check that the input value is the correct type let integer_option = match integer_value { Some(input) => { - if let InputValue::Integer(integer) = input { + if let InputValue::Integer(_type_, integer) = input { Some(integer) } else { return Err(IntegerError::InvalidInteger(input.to_string())); From 6c7355a89cdd7369142ef6fd7a917fdea8a6e8ac Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 17:21:47 -0700 Subject: [PATCH 08/15] public input fields, arrays, group tuples --- leo-inputs/src/circuits/circuit_field.rs | 13 ------ leo-inputs/src/circuits/mod.rs | 2 - leo-inputs/src/errors/parser.rs | 3 ++ .../expressions/circuit_inline_expression.rs | 13 ------ leo-inputs/src/expressions/expression.rs | 8 +--- leo-inputs/src/expressions/mod.rs | 3 -- leo-inputs/src/leo-inputs.pest | 14 +----- leo-inputs/src/lib.rs | 1 - leo-inputs/src/types/circuit_type.rs | 12 ----- leo-inputs/src/types/mod.rs | 3 -- leo-inputs/src/types/type_.rs | 2 - leo/commands/prove.rs | 2 +- tmp/inputs/inputs.leo | 2 +- tmp/src/main.leo | 2 +- types/src/inputs/input_fields.rs | 45 ++++++++++++++++++- types/src/inputs/input_value.rs | 10 ++--- types/src/inputs/inputs.rs | 1 - 17 files changed, 57 insertions(+), 79 deletions(-) delete mode 100644 leo-inputs/src/circuits/circuit_field.rs delete mode 100644 leo-inputs/src/circuits/mod.rs delete mode 100644 leo-inputs/src/expressions/circuit_inline_expression.rs delete mode 100644 leo-inputs/src/types/circuit_type.rs diff --git a/leo-inputs/src/circuits/circuit_field.rs b/leo-inputs/src/circuits/circuit_field.rs deleted file mode 100644 index 0c48dec655..0000000000 --- a/leo-inputs/src/circuits/circuit_field.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::{ast::Rule, common::Identifier, expressions::Expression}; - -use pest::Span; -use pest_ast::FromPest; - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::circuit_field))] -pub struct CircuitField<'ast> { - pub identifier: Identifier<'ast>, - pub expression: Expression<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} diff --git a/leo-inputs/src/circuits/mod.rs b/leo-inputs/src/circuits/mod.rs deleted file mode 100644 index e9385224e0..0000000000 --- a/leo-inputs/src/circuits/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod circuit_field; -pub use circuit_field::*; diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index 4b05621692..a821fc4f63 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -20,6 +20,9 @@ pub enum InputParserError { #[error("{}", _0)] ParseIntError(#[from] ParseIntError), + #[error("cannot parse {} as field", _0)] + ParseFieldError(String), + #[error("{}", _0)] SyntaxError(#[from] SyntaxError), diff --git a/leo-inputs/src/expressions/circuit_inline_expression.rs b/leo-inputs/src/expressions/circuit_inline_expression.rs deleted file mode 100644 index e276373f18..0000000000 --- a/leo-inputs/src/expressions/circuit_inline_expression.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::{ast::Rule, circuits::CircuitField, common::Identifier}; - -use pest::Span; -use pest_ast::FromPest; - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_circuit_inline))] -pub struct CircuitInlineExpression<'ast> { - pub identifier: Identifier<'ast>, - pub members: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} diff --git a/leo-inputs/src/expressions/expression.rs b/leo-inputs/src/expressions/expression.rs index 662cdf3d10..29de72bf91 100644 --- a/leo-inputs/src/expressions/expression.rs +++ b/leo-inputs/src/expressions/expression.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::Identifier, expressions::*, values::Value}; +use crate::{ast::Rule, expressions::*, values::Value}; use pest_ast::FromPest; use std::fmt; @@ -6,18 +6,15 @@ use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::expression))] pub enum Expression<'ast> { - CircuitInline(CircuitInlineExpression<'ast>), ArrayInline(ArrayInlineExpression<'ast>), ArrayInitializer(ArrayInitializerExpression<'ast>), Value(Value<'ast>), - Variable(Identifier<'ast>), } impl<'ast> fmt::Display for Expression<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Expression::Value(ref expression) => write!(f, "{}", expression), - Expression::Variable(ref expression) => write!(f, "{}", expression), Expression::ArrayInline(ref expression) => { for (i, spread_or_expression) in expression.expressions.iter().enumerate() { write!(f, "{}", spread_or_expression)?; @@ -30,9 +27,6 @@ impl<'ast> fmt::Display for Expression<'ast> { Expression::ArrayInitializer(ref expression) => { write!(f, "[{} ; {}]", expression.expression, expression.count) } - Expression::CircuitInline(ref expression) => { - write!(f, "inline circuit display not impl {}", expression.identifier) - } } } } diff --git a/leo-inputs/src/expressions/mod.rs b/leo-inputs/src/expressions/mod.rs index f7dff738a9..621a7da70d 100644 --- a/leo-inputs/src/expressions/mod.rs +++ b/leo-inputs/src/expressions/mod.rs @@ -4,8 +4,5 @@ pub use array_initializer_expression::*; pub mod array_inline_expression; pub use array_inline_expression::*; -pub mod circuit_inline_expression; -pub use circuit_inline_expression::*; - pub mod expression; pub use expression::*; diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 4e26c4b1c6..c352109d16 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -15,7 +15,7 @@ visibility_private = { "private" } /// Types // Declared in types/type_.rs -type_ = { type_array | type_data | type_circuit } +type_ = { type_array | type_data } // Declared in types/integer_type.rs type_integer = { @@ -43,9 +43,6 @@ type_boolean = { "bool" } // Declared in types/data_type.rs type_data = { type_field | type_group | type_boolean | type_integer } -// Declared in types/circuit_type.rs -type_circuit = { identifier } - // Declared in types/array_type.rs type_array = { type_data ~ ("[" ~ value_number ~ "]")+ } @@ -83,18 +80,11 @@ expression_array_initializer = { "[" ~ expression ~ ";" ~ value_number ~ "]" } expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} inline_array_inner = _{ (expression ~ ("," ~ NEWLINE* ~ expression)*)? } -// Declared in expressions/circuit_inline_expression.rs -expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" } -circuit_field = { identifier ~ ":" ~ expression } -circuit_field_list = _{ (circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? } - // Declared in expressions/expression.rs expression = { - expression_circuit_inline - | expression_array_inline + expression_array_inline | expression_array_initializer | value - | identifier } /// Parameters diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 84ce64b65b..0680d48f62 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -9,7 +9,6 @@ pub use errors::*; //extern crate from_pest; pub mod assignments; mod ast; -pub mod circuits; pub mod common; pub mod expressions; pub mod files; diff --git a/leo-inputs/src/types/circuit_type.rs b/leo-inputs/src/types/circuit_type.rs deleted file mode 100644 index fa8acf3e78..0000000000 --- a/leo-inputs/src/types/circuit_type.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::{ast::Rule, common::Identifier}; - -use pest::Span; -use pest_ast::FromPest; - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_circuit))] -pub struct CircuitType<'ast> { - pub identifier: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} diff --git a/leo-inputs/src/types/mod.rs b/leo-inputs/src/types/mod.rs index cd0d08ac60..9db6353b8d 100644 --- a/leo-inputs/src/types/mod.rs +++ b/leo-inputs/src/types/mod.rs @@ -4,9 +4,6 @@ pub use array_type::*; pub mod boolean_type; pub use boolean_type::*; -pub mod circuit_type; -pub use circuit_type::*; - pub mod data_type; pub use data_type::*; diff --git a/leo-inputs/src/types/type_.rs b/leo-inputs/src/types/type_.rs index ddf650563d..f6ea8e8933 100644 --- a/leo-inputs/src/types/type_.rs +++ b/leo-inputs/src/types/type_.rs @@ -8,7 +8,6 @@ use std::fmt; pub enum Type<'ast> { Basic(DataType), Array(ArrayType<'ast>), - Circuit(CircuitType<'ast>), } impl<'ast> fmt::Display for Type<'ast> { @@ -16,7 +15,6 @@ impl<'ast> fmt::Display for Type<'ast> { match *self { Type::Basic(ref _type) => write!(f, "basic"), Type::Array(ref _type) => write!(f, "array"), - Type::Circuit(ref _type) => write!(f, "struct"), } } } diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index dc9740b0b5..75b6331ebb 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -49,7 +49,7 @@ impl CLI for ProveCommand { let start = Instant::now(); let rng = &mut thread_rng(); - let program_proof = create_random_proof(program.clone(), ¶meters, rng).unwrap(); + let program_proof = create_random_proof(program.clone(), ¶meters, rng)?; log::info!("Prover completed in {:?} milliseconds", start.elapsed().as_millis()); diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo index d822cd1b41..181eaed6c1 100644 --- a/tmp/inputs/inputs.leo +++ b/tmp/inputs/inputs.leo @@ -1,2 +1,2 @@ [main] -a: public u128 = 120; \ No newline at end of file +a: public group = (0, 1)group; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo index 13ed40de78..8eb117e06f 100644 --- a/tmp/src/main.leo +++ b/tmp/src/main.leo @@ -1,4 +1,4 @@ // The 'tmp' main function. -function main(a: public u128) -> u128 { +function main(a: public group) -> group { return a } diff --git a/types/src/inputs/input_fields.rs b/types/src/inputs/input_fields.rs index fecb030498..b253dd2ce7 100644 --- a/types/src/inputs/input_fields.rs +++ b/types/src/inputs/input_fields.rs @@ -1,5 +1,7 @@ +use crate::InputValue; use leo_inputs::{types::IntegerType, InputParserError}; use snarkos_models::curves::{Field, PairingEngine}; +use std::str::FromStr; pub struct InputFields(pub Vec); @@ -12,7 +14,7 @@ impl InputFields { } } - pub(crate) fn from_integer(type_: &IntegerType, integer: &u128) -> Result { + pub(crate) fn from_integer(type_: &IntegerType, integer: &u128) -> Self { let bits: usize = match type_ { IntegerType::U8Type(_) => 8, IntegerType::U16Type(_) => 16, @@ -29,6 +31,47 @@ impl InputFields { fields.append(&mut boolean_fields.0); } + Self(fields) + } + + pub(crate) fn from_field(field: &str) -> Result { + let field = E::Fr::from_str(field).map_err(|_| InputParserError::ParseFieldError(field.to_string()))?; + + Ok(Self(vec![field])) + } + + pub(crate) fn from_group(group: &str) -> Result { + let s = group.trim(); + // if s.is_empty() { + // return Err(()); + // } + // if s.len() < 3 { + // return Err(()); + // } + // if !(s.starts_with('(') && s.ends_with(')')) { + // return Err(()); + // } + let mut fields = vec![]; + for substr in s.split(|c| c == '(' || c == ')' || c == ',' || c == ' ') { + if !substr.is_empty() { + let mut input_fields = InputFields::::from_field(&substr)?; + + fields.append(&mut input_fields.0); + } + } + + Ok(Self(fields)) + } + + pub(crate) fn from_array(array: &Vec) -> Result { + let mut fields = vec![]; + + for input in array.iter() { + let mut input_fields = input.to_input_fields::()?; + + fields.append(&mut input_fields.0); + } + Ok(Self(fields)) } } diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs index 6403f8b2f3..776a17e75c 100644 --- a/types/src/inputs/input_value.rs +++ b/types/src/inputs/input_value.rs @@ -73,8 +73,6 @@ impl<'ast> InputValue { (Type::Array(array_type), Expression::ArrayInitializer(initializer)) => { InputValue::from_array_initializer(array_type, initializer) } - (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not supported"), - (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable input values not supported"), (type_, value) => Err(InputParserError::IncompatibleTypes( type_.to_string(), value.to_string(), @@ -154,10 +152,10 @@ impl<'ast> InputValue { pub(crate) fn to_input_fields(&self) -> Result, InputParserError> { match self { InputValue::Boolean(boolean) => Ok(InputFields::from_boolean(boolean)), - InputValue::Integer(type_, number) => InputFields::from_integer(type_, number), - InputValue::Group(_) => unimplemented!(), - InputValue::Field(_) => unimplemented!(), - InputValue::Array(_) => unimplemented!(), + InputValue::Integer(type_, number) => Ok(InputFields::from_integer(type_, number)), + InputValue::Group(group) => InputFields::from_group(group), + InputValue::Field(field) => InputFields::from_field(field), + InputValue::Array(array) => InputFields::from_array(array), } } } diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index eb3d334f5f..028bea0d68 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -37,7 +37,6 @@ impl Inputs { let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; if let Some(Visibility::Public(_)) = assignment.parameter.visibility { // Collect public inputs here - public.push(value.clone()); } From 52f0d012c81eb15ccf46136b5c85390eba776573 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 17:53:38 -0700 Subject: [PATCH 09/15] fix tests --- compiler/tests/boolean/mod.rs | 1 - compiler/tests/integers/macros.rs | 80 ++++++++++++++--------------- compiler/tests/integers/u128/mod.rs | 3 +- compiler/tests/integers/u16/mod.rs | 3 +- compiler/tests/integers/u32/mod.rs | 3 +- compiler/tests/integers/u64/mod.rs | 3 +- compiler/tests/integers/u8/mod.rs | 3 +- compiler/tests/mutability/mod.rs | 2 +- 8 files changed, 51 insertions(+), 47 deletions(-) diff --git a/compiler/tests/boolean/mod.rs b/compiler/tests/boolean/mod.rs index dd4065da9c..01b428e755 100644 --- a/compiler/tests/boolean/mod.rs +++ b/compiler/tests/boolean/mod.rs @@ -3,7 +3,6 @@ use leo_compiler::{ errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError}, ConstrainedValue, }; -use leo_types::InputValue; use crate::array::input_value_u32_one; use snarkos_models::gadgets::utilities::boolean::Boolean; diff --git a/compiler/tests/integers/macros.rs b/compiler/tests/integers/macros.rs index 96f414d3ec..f322113f39 100644 --- a/compiler/tests/integers/macros.rs +++ b/compiler/tests/integers/macros.rs @@ -1,5 +1,5 @@ macro_rules! test_uint { - ($name: ident, $_type: ty, $gadget: ty) => { + ($name: ident, $_type: ty, $integer_type: expr, $gadget: ty) => { pub struct $name {} impl $name { @@ -31,7 +31,7 @@ macro_rules! test_uint { let bytes = include_bytes!("input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(num as u128))]); + program.set_inputs(vec![Some(InputValue::Integer($integer_type, num as u128))]); output_expected_allocated(program, expected); @@ -61,8 +61,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program, sum_allocated); @@ -83,8 +83,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program, difference_allocated); @@ -105,8 +105,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program, product_allocated); @@ -127,8 +127,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program, quotient_allocated); @@ -150,8 +150,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program, result_allocated); @@ -167,8 +167,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); output_true(program); @@ -181,8 +181,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_boolean(program, result); @@ -198,8 +198,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); output_true(program); @@ -212,8 +212,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_boolean(program, result); @@ -229,8 +229,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); output_false(program); @@ -243,8 +243,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_boolean(program, result); @@ -260,8 +260,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); output_true(program); @@ -274,8 +274,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_boolean(program, result); @@ -291,8 +291,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); output_false(program); @@ -305,8 +305,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_boolean(program, result); @@ -322,8 +322,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), ]); let _ = get_output(program); @@ -338,8 +338,8 @@ macro_rules! test_uint { let mut program = parse_program(bytes).unwrap(); program.set_inputs(vec![ - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); let mut cs = TestConstraintSystem::::new(); @@ -363,8 +363,8 @@ macro_rules! test_uint { // true -> field 1 program_1.set_inputs(vec![ Some(InputValue::Boolean(true)), - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program_1, g1); @@ -372,8 +372,8 @@ macro_rules! test_uint { // false -> field 2 program_2.set_inputs(vec![ Some(InputValue::Boolean(false)), - Some(InputValue::Integer(r1 as u128)), - Some(InputValue::Integer(r2 as u128)), + Some(InputValue::Integer($integer_type, r1 as u128)), + Some(InputValue::Integer($integer_type, r2 as u128)), ]); output_expected_allocated(program_2, g2); diff --git a/compiler/tests/integers/u128/mod.rs b/compiler/tests/integers/u128/mod.rs index b2d41c0bd6..ad5cc58bd9 100644 --- a/compiler/tests/integers/u128/mod.rs +++ b/compiler/tests/integers/u128/mod.rs @@ -7,6 +7,7 @@ use crate::{ EdwardsTestCompiler, }; use leo_compiler::ConstrainedValue; +use leo_inputs::types::{IntegerType, U128Type}; use leo_types::{InputValue, Integer}; use snarkos_curves::edwards_bls12::Fq; @@ -30,7 +31,7 @@ fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt128) { #[test] #[ignore] // temporarily ignore memory expensive tests for travis fn test_u128() { - test_uint!(TestU128, u128, UInt128); + test_uint!(TestU128, u128, IntegerType::U128Type(U128Type {}), UInt128); TestU128::test_min(std::u128::MIN); TestU128::test_max(std::u128::MAX); diff --git a/compiler/tests/integers/u16/mod.rs b/compiler/tests/integers/u16/mod.rs index 9a5510d741..e6aa8b1060 100644 --- a/compiler/tests/integers/u16/mod.rs +++ b/compiler/tests/integers/u16/mod.rs @@ -7,6 +7,7 @@ use crate::{ EdwardsTestCompiler, }; use leo_compiler::ConstrainedValue; +use leo_inputs::types::{IntegerType, U16Type}; use leo_types::{InputValue, Integer}; use snarkos_curves::edwards_bls12::Fq; @@ -29,7 +30,7 @@ fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt16) { #[test] fn test_u16() { - test_uint!(Testu16, u16, UInt16); + test_uint!(Testu16, u16, IntegerType::U16Type(U16Type {}), UInt16); Testu16::test_min(std::u16::MIN); Testu16::test_max(std::u16::MAX); diff --git a/compiler/tests/integers/u32/mod.rs b/compiler/tests/integers/u32/mod.rs index 5f9d39f24c..d9b02855c7 100644 --- a/compiler/tests/integers/u32/mod.rs +++ b/compiler/tests/integers/u32/mod.rs @@ -7,6 +7,7 @@ use crate::{ EdwardsTestCompiler, }; use leo_compiler::ConstrainedValue; +use leo_inputs::types::{IntegerType, U32Type}; use leo_types::{InputValue, Integer}; use snarkos_curves::edwards_bls12::Fq; @@ -47,7 +48,7 @@ pub(crate) fn output_one(program: EdwardsTestCompiler) { #[test] fn test_u32() { - test_uint!(TestU32, u32, UInt32); + test_uint!(TestU32, u32, IntegerType::U32Type(U32Type {}), UInt32); TestU32::test_min(std::u32::MIN); TestU32::test_max(std::u32::MAX); diff --git a/compiler/tests/integers/u64/mod.rs b/compiler/tests/integers/u64/mod.rs index d31fb904a6..87d73ddcfe 100644 --- a/compiler/tests/integers/u64/mod.rs +++ b/compiler/tests/integers/u64/mod.rs @@ -7,6 +7,7 @@ use crate::{ EdwardsTestCompiler, }; use leo_compiler::ConstrainedValue; +use leo_inputs::types::{IntegerType, U64Type}; use leo_types::{InputValue, Integer}; use snarkos_curves::edwards_bls12::Fq; @@ -30,7 +31,7 @@ fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt64) { #[test] #[ignore] //temporarily ignore memory expensive tests for travis fn test_u64() { - test_uint!(Testu64, u64, UInt64); + test_uint!(Testu64, u64, IntegerType::U64Type(U64Type {}), UInt64); Testu64::test_min(std::u64::MIN); Testu64::test_max(std::u64::MAX); diff --git a/compiler/tests/integers/u8/mod.rs b/compiler/tests/integers/u8/mod.rs index 0fa87e8925..40796075f8 100644 --- a/compiler/tests/integers/u8/mod.rs +++ b/compiler/tests/integers/u8/mod.rs @@ -7,6 +7,7 @@ use crate::{ EdwardsTestCompiler, }; use leo_compiler::ConstrainedValue; +use leo_inputs::types::{IntegerType, U8Type}; use leo_types::{InputValue, Integer}; use snarkos_curves::edwards_bls12::Fq; @@ -29,7 +30,7 @@ fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt8) { #[test] fn test_u8() { - test_uint!(Testu8, u8, UInt8); + test_uint!(Testu8, u8, IntegerType::U8Type(U8Type {}), UInt8); Testu8::test_min(std::u8::MIN); Testu8::test_max(std::u8::MAX); diff --git a/compiler/tests/mutability/mod.rs b/compiler/tests/mutability/mod.rs index e5daaefa63..e04ca08cae 100644 --- a/compiler/tests/mutability/mod.rs +++ b/compiler/tests/mutability/mod.rs @@ -3,7 +3,7 @@ use leo_compiler::{ errors::{CompilerError, FunctionError, StatementError}, ConstrainedValue, }; -use leo_types::{InputValue, Integer}; +use leo_types::Integer; use crate::array::input_value_u32_one; use snarkos_curves::edwards_bls12::Fq; From 9d15a0b038bb91497f35dafb23558322fc62066e Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 18:30:38 -0700 Subject: [PATCH 10/15] only allow (x,y) affine groups --- leo-inputs/src/leo-inputs.pest | 3 +-- leo-inputs/src/values/group_value.rs | 18 +----------------- types/src/inputs/input_fields.rs | 10 +--------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index c352109d16..9be3f7eb80 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -67,9 +67,8 @@ value_boolean = { "true" | "false" } value_field = { value_number ~ type_field } // Declared in values/group_value.rs -value_group = { group_single_or_tuple ~ type_group } +value_group = { group_tuple ~ type_group } group_tuple = { "(" ~ NEWLINE* ~ value_number ~ "," ~ NEWLINE* ~ value_number ~ NEWLINE* ~")" } -group_single_or_tuple = { value_number | group_tuple } /// Expressions diff --git a/leo-inputs/src/values/group_value.rs b/leo-inputs/src/values/group_value.rs index 365954e5ed..865276658b 100644 --- a/leo-inputs/src/values/group_value.rs +++ b/leo-inputs/src/values/group_value.rs @@ -7,7 +7,7 @@ use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::value_group))] pub struct GroupValue<'ast> { - pub value: GroupRepresentation<'ast>, + pub value: GroupTuple<'ast>, pub _type: GroupType, #[pest_ast(outer())] pub span: Span<'ast>, @@ -19,22 +19,6 @@ impl<'ast> fmt::Display for GroupValue<'ast> { } } -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::group_single_or_tuple))] -pub enum GroupRepresentation<'ast> { - Single(NumberValue<'ast>), - Tuple(GroupTuple<'ast>), -} - -impl<'ast> fmt::Display for GroupRepresentation<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - GroupRepresentation::Single(number) => write!(f, "{}", number), - GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple), - } - } -} - #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::group_tuple))] pub struct GroupTuple<'ast> { diff --git a/types/src/inputs/input_fields.rs b/types/src/inputs/input_fields.rs index b253dd2ce7..fb7806e243 100644 --- a/types/src/inputs/input_fields.rs +++ b/types/src/inputs/input_fields.rs @@ -42,16 +42,8 @@ impl InputFields { pub(crate) fn from_group(group: &str) -> Result { let s = group.trim(); - // if s.is_empty() { - // return Err(()); - // } - // if s.len() < 3 { - // return Err(()); - // } - // if !(s.starts_with('(') && s.ends_with(')')) { - // return Err(()); - // } let mut fields = vec![]; + for substr in s.split(|c| c == '(' || c == ')' || c == ',' || c == ' ') { if !substr.is_empty() { let mut input_fields = InputFields::::from_field(&substr)?; From 142520c76f288a3a5b24e9821c3b41d2d67fad03 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 18:50:03 -0700 Subject: [PATCH 11/15] update leo init example --- leo/commands/init.rs | 7 ++++++ leo/files/inputs.rs | 56 +++++++++++++++++++++++++++++++++++++++++++ leo/files/main.rs | 6 ++--- leo/files/mod.rs | 3 +++ tmp/.gitignore | 2 -- tmp/Leo.toml | 3 --- tmp/inputs/inputs.leo | 2 -- tmp/src/main.leo | 4 ---- 8 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 leo/files/inputs.rs delete mode 100644 tmp/.gitignore delete mode 100644 tmp/Leo.toml delete mode 100644 tmp/inputs/inputs.leo delete mode 100644 tmp/src/main.leo diff --git a/leo/commands/init.rs b/leo/commands/init.rs index d1b79fc19f..2846940f59 100644 --- a/leo/commands/init.rs +++ b/leo/commands/init.rs @@ -6,6 +6,7 @@ use crate::{ files::{Gitignore, MainFile, Manifest}, }; +use crate::files::InputsFile; use clap::ArgMatches; use std::env::current_dir; @@ -65,6 +66,12 @@ impl CLI for InitCommand { // Create the inputs directory InputsDirectory::create(&path)?; + // Verify the inputs file does not exist + if !InputsFile::exists_at(&path) { + // Create the main file in the source directory + InputsFile::new(&package_name).write_to(&path)?; + } + // Verify the main file does not exist if !MainFile::exists_at(&path) { // Create the main file in the source directory diff --git a/leo/files/inputs.rs b/leo/files/inputs.rs new file mode 100644 index 0000000000..138f671a82 --- /dev/null +++ b/leo/files/inputs.rs @@ -0,0 +1,56 @@ +//! The `inputs.leo` file. + +use crate::{directories::inputs::INPUTS_DIRECTORY_NAME, errors::MainFileError}; + +use serde::Deserialize; +use std::{fs::File, io::Write, path::PathBuf}; + +pub static INPUTS_FILE_NAME: &str = "inputs.leo"; + +#[derive(Deserialize)] +pub struct InputsFile { + pub package_name: String, +} + +impl InputsFile { + pub fn new(package_name: &str) -> Self { + Self { + package_name: package_name.to_string(), + } + } + + pub fn exists_at(path: &PathBuf) -> bool { + let mut path = path.to_owned(); + if path.is_dir() { + if !path.ends_with(INPUTS_DIRECTORY_NAME) { + path.push(PathBuf::from(INPUTS_DIRECTORY_NAME)); + } + path.push(PathBuf::from(INPUTS_FILE_NAME)); + } + path.exists() + } + + pub fn write_to(self, path: &PathBuf) -> Result<(), MainFileError> { + let mut path = path.to_owned(); + if path.is_dir() { + if !path.ends_with(INPUTS_DIRECTORY_NAME) { + path.push(PathBuf::from(INPUTS_DIRECTORY_NAME)); + } + path.push(PathBuf::from(INPUTS_FILE_NAME)); + } + + let mut file = File::create(&path)?; + Ok(file.write_all(self.template().as_bytes())?) + } + + fn template(&self) -> String { + format!( + r#"// The inputs for {}/src/main.leo +[main] +a: private u32 = 1; +b: public u32 = 2; +"#, + self.package_name + ) + } +} diff --git a/leo/files/main.rs b/leo/files/main.rs index 9411fff570..955999d047 100644 --- a/leo/files/main.rs +++ b/leo/files/main.rs @@ -46,9 +46,9 @@ impl MainFile { fn template(&self) -> String { format!( r#"// The '{}' main function. -function main() -> u32 {{ - let a: u32 = 1 + 1; - return a +function main(a: private u32, b: public u32) -> u32 {{ + let c: u32 = a + b; + return c }} "#, self.package_name diff --git a/leo/files/mod.rs b/leo/files/mod.rs index 556bb337ef..6ef50f807b 100644 --- a/leo/files/mod.rs +++ b/leo/files/mod.rs @@ -1,6 +1,9 @@ pub mod checksum; pub use self::checksum::*; +pub mod inputs; +pub use self::inputs::*; + pub mod gitignore; pub use self::gitignore::*; diff --git a/tmp/.gitignore b/tmp/.gitignore deleted file mode 100644 index ee3b8ff567..0000000000 --- a/tmp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/output -/.leo diff --git a/tmp/Leo.toml b/tmp/Leo.toml deleted file mode 100644 index 36afb9b7ec..0000000000 --- a/tmp/Leo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[package] -name = "tmp" -version = "0.1.0" diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo deleted file mode 100644 index 181eaed6c1..0000000000 --- a/tmp/inputs/inputs.leo +++ /dev/null @@ -1,2 +0,0 @@ -[main] -a: public group = (0, 1)group; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo deleted file mode 100644 index 8eb117e06f..0000000000 --- a/tmp/src/main.leo +++ /dev/null @@ -1,4 +0,0 @@ -// The 'tmp' main function. -function main(a: public group) -> group { - return a -} From 59766d0740894acfee176a8cacfa04b16ea6ccc1 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 18:56:17 -0700 Subject: [PATCH 12/15] remove additional setup call in cli --- leo/commands/prove.rs | 12 ++++++++---- leo/commands/run.rs | 10 ++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 75b6331ebb..07c49ffaf1 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -6,7 +6,7 @@ use crate::{ files::{Manifest, ProofFile}, }; -use snarkos_algorithms::snark::{create_random_proof, Proof}; +use snarkos_algorithms::snark::{create_random_proof, PreparedVerifyingKey, Proof}; use snarkos_curves::bls12_377::Bls12_377; use clap::ArgMatches; @@ -20,7 +20,11 @@ pub struct ProveCommand; impl CLI for ProveCommand { type Options = (); - type Output = (Compiler, Proof); + type Output = ( + Compiler, + Proof, + PreparedVerifyingKey, + ); const ABOUT: AboutType = "Run the program and produce a proof"; const ARGUMENTS: &'static [ArgumentType] = &[]; @@ -36,7 +40,7 @@ impl CLI for ProveCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result { - let (mut program, parameters, _) = SetupCommand::output(options)?; + let (mut program, parameters, prepared_verifying_key) = SetupCommand::output(options)?; // Get the package name let path = current_dir()?; @@ -60,6 +64,6 @@ impl CLI for ProveCommand { log::info!("Completed program proving"); - Ok((program, program_proof)) + Ok((program, program_proof, prepared_verifying_key)) } } diff --git a/leo/commands/run.rs b/leo/commands/run.rs index 20f4dd290c..c0f42b2191 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -1,9 +1,4 @@ -use crate::{ - cli::*, - cli_types::*, - commands::{ProveCommand, SetupCommand}, - errors::CLIError, -}; +use crate::{cli::*, cli_types::*, commands::ProveCommand, errors::CLIError}; use snarkos_algorithms::snark::verify_proof; use snarkos_curves::bls12_377::Bls12_377; @@ -32,8 +27,7 @@ impl CLI for RunCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result<(), CLIError> { - let (_program, _parameters, prepared_verifying_key) = SetupCommand::output(options)?; - let (program, proof) = ProveCommand::output(options)?; + let (program, proof, prepared_verifying_key) = ProveCommand::output(options)?; let mut verifying = Duration::new(0, 0); From 824a6059fb0155cc95232ba4ca9a369355e38551 Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 11 Jun 2020 11:43:05 -0700 Subject: [PATCH 13/15] split up input loading and parsing in compiler --- compiler/src/compiler.rs | 15 ++++----------- compiler/tests/mod.rs | 11 +++++++++++ compiler/tests/syntax/inputs_semicolon.leo | 2 ++ compiler/tests/syntax/mod.rs | 14 +++++++++++++- leo/commands/prove.rs | 10 +++++++++- leo/errors/cli.rs | 6 ++++++ types/src/inputs/input_fields.rs | 1 + types/src/inputs/input_value.rs | 1 + types/src/inputs/inputs.rs | 1 + 9 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 compiler/tests/syntax/inputs_semicolon.leo diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 55da44d852..b177bf67af 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -92,8 +92,7 @@ impl> Compiler { fn load_program(&mut self) -> Result { // Load the program syntax tree from the file path - let file_path = &self.main_file_path; - Ok(LeoParser::load_file(file_path)?) + Ok(LeoParser::load_file(&self.main_file_path)?) } pub fn parse_program(&mut self, program_string: &str) -> Result<(), CompilerError> { @@ -111,16 +110,10 @@ impl> Compiler { Ok(()) } - pub fn parse_inputs(&mut self, file_path: &PathBuf) -> Result<(), CompilerError> { - let mut path = file_path.clone(); - path.push("inputs"); - path.push("inputs.leo"); + pub fn parse_inputs(&mut self, input_file_path: &PathBuf, input_file_string: &str) -> Result<(), CompilerError> { + let syntax_tree = LeoInputsParser::parse_file(input_file_path, input_file_string)?; - let input_file = &LeoInputsParser::load_file(&path)?; - let syntax_tree = LeoInputsParser::parse_file(&path, input_file)?; - // println!("{:?}", syntax_tree); - - // Check number of private parameters here + // Check number/order of private parameters here self.program_inputs = Inputs::from_inputs_file(syntax_tree)?; Ok(()) diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index 9898b6c53d..283afeb561 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -19,6 +19,7 @@ use leo_compiler::{ use snarkos_curves::edwards_bls12::Fq; use snarkos_models::gadgets::r1cs::TestConstraintSystem; +use std::path::PathBuf; pub type EdwardsTestCompiler = Compiler; pub type EdwardsConstrainedValue = ConstrainedValue; @@ -51,3 +52,13 @@ pub(crate) fn parse_program(bytes: &[u8]) -> Result Result { + let program_string = String::from_utf8_lossy(bytes); + + let mut compiler = EdwardsTestCompiler::new(); + + compiler.parse_inputs(&PathBuf::new(), &program_string)?; + + Ok(compiler) +} diff --git a/compiler/tests/syntax/inputs_semicolon.leo b/compiler/tests/syntax/inputs_semicolon.leo new file mode 100644 index 0000000000..9054049169 --- /dev/null +++ b/compiler/tests/syntax/inputs_semicolon.leo @@ -0,0 +1,2 @@ +[main] +a: private u32 = 5 \ No newline at end of file diff --git a/compiler/tests/syntax/mod.rs b/compiler/tests/syntax/mod.rs index 4cf5ec5f0b..7d5630760c 100644 --- a/compiler/tests/syntax/mod.rs +++ b/compiler/tests/syntax/mod.rs @@ -1,6 +1,7 @@ -use crate::parse_program; +use crate::{parse_inputs, parse_program}; use leo_ast::ParserError; use leo_compiler::errors::CompilerError; +use leo_inputs::InputParserError; #[test] fn test_semicolon() { @@ -12,3 +13,14 @@ fn test_semicolon() { _ => panic!("test_semicolon failed the wrong expected error, should be a ParserError"), } } + +#[test] +fn inputs_syntax_error() { + let bytes = include_bytes!("inputs_semicolon.leo"); + let error = parse_inputs(bytes).err().unwrap(); + + match error { + CompilerError::InputParserError(InputParserError::SyntaxError(_)) => {} + _ => panic!("inputs syntax error should be a ParserError"), + } +} diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 07c49ffaf1..1bc244ad1b 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -9,8 +9,10 @@ use crate::{ use snarkos_algorithms::snark::{create_random_proof, PreparedVerifyingKey, Proof}; use snarkos_curves::bls12_377::Bls12_377; +use crate::{directories::INPUTS_DIRECTORY_NAME, files::INPUTS_FILE_NAME}; use clap::ArgMatches; use leo_compiler::{compiler::Compiler, edwards_bls12::EdwardsGroupType}; +use leo_inputs::LeoInputsParser; use rand::thread_rng; use snarkos_curves::edwards_bls12::Fq; use std::{convert::TryFrom, env::current_dir, time::Instant}; @@ -46,8 +48,14 @@ impl CLI for ProveCommand { let path = current_dir()?; let package_name = Manifest::try_from(&path)?.get_package_name(); + // Construct the path to the inputs file in the inputs directory + let mut inputs_file_path = path.clone(); + inputs_file_path.push(INPUTS_DIRECTORY_NAME); + inputs_file_path.push(INPUTS_FILE_NAME); + // Fetch private inputs here - program.parse_inputs(&path)?; + let inputs_file_string = LeoInputsParser::load_file(&inputs_file_path)?; + program.parse_inputs(&inputs_file_path, &inputs_file_string)?; // Start the timer let start = Instant::now(); diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index 007d2cffaf..53599b83cc 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -57,6 +57,12 @@ impl From for CLIError { } } +impl From for CLIError { + fn from(error: leo_inputs::errors::InputParserError) -> Self { + CLIError::Crate("leo_inputs", format!("{}", error)) + } +} + impl From for CLIError { fn from(error: snarkos_errors::gadgets::SynthesisError) -> Self { CLIError::Crate("snarkos_errors", format!("{}", error)) diff --git a/types/src/inputs/input_fields.rs b/types/src/inputs/input_fields.rs index fb7806e243..30f3324b55 100644 --- a/types/src/inputs/input_fields.rs +++ b/types/src/inputs/input_fields.rs @@ -1,5 +1,6 @@ use crate::InputValue; use leo_inputs::{types::IntegerType, InputParserError}; + use snarkos_models::curves::{Field, PairingEngine}; use std::str::FromStr; diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs index 776a17e75c..dbc16ed44f 100644 --- a/types/src/inputs/input_value.rs +++ b/types/src/inputs/input_value.rs @@ -5,6 +5,7 @@ use leo_inputs::{ types::{ArrayType, DataType, IntegerType, Type}, values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value}, }; + use snarkos_models::curves::PairingEngine; use std::fmt; diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index 028bea0d68..dc08c30e98 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,5 +1,6 @@ use crate::InputValue; use leo_inputs::{common::visibility::Visibility, files::File, InputParserError}; + use snarkos_models::curves::PairingEngine; #[derive(Clone)] From b44e336cb6bb16d81c26f3dd58a332edabf4b523 Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 11 Jun 2020 13:06:36 -0700 Subject: [PATCH 14/15] update readme --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++++ leo/commands/prove.rs | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e5dca0a8b..9728a064e7 100644 --- a/README.md +++ b/README.md @@ -381,6 +381,49 @@ test function expect_fail() { } ``` +# Leo Inputs + +Public and private inputs for a Leo program are specified in the `inputs/` directory. The syntax for an input file is a limited subset of the Leo program syntax. The default inputs file is `inputs/inputs.leo`. + +## Sections +A Leo input file is made up of sections. Sections are defined by a section header in brackets followed by one or more input definitions. + +Section headers specify the target file which must have a main function with matching input names and types defined in the same order. + +`inputs/inputs.leo` + +```rust +[main] // <- section header +a: private u32 = 1; // <- private input +b: public u32 = 2; // <- public input +``` + +`src/main.leo` + +```rust +function main(a: private u32, b: public u32) -> u32 { + let c: u32 = a + b; + return c +} +``` + +## Input Definitions + +### Supported types +```rust +[main] +a: bool = true; // <- booleans +b: u8 = 2; // <- integers +c: field = 0; // <- fields +d: group = (0, 1)group // <- group tuples +``` + +### Arrays +```rust +[main] +a: private u8[4] = [0u8; 4]; // <- single +b: private u8[2][3] = [[0u8; 2]; 3]; // <- multi-dimensional +``` # Leo CLI @@ -395,6 +438,7 @@ leo new {$NAME} This will create a new directory with a given package name. The new package will have a directory structure as follows: ``` - inputs # Your program inputs + - inputs.leo # Your program inputs for main.leo - outputs # Your program outputs - src - lib.leo # Your program library @@ -455,6 +499,8 @@ leo prove ``` Leo starts by checking the `target` directory for an existing `.leo.pk` file. If it doesn't exist, it will proceed to run `leo setup` and then continue. +Next any input files in the `inputs` directory are parsed and all input values are passed to the program. + Once again, Leo uses cryptographic randomness from your machine to produce the proof. The proof is stored in the `target` directory as `.leo.proof`: ``` diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 1bc244ad1b..787d681884 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -53,7 +53,7 @@ impl CLI for ProveCommand { inputs_file_path.push(INPUTS_DIRECTORY_NAME); inputs_file_path.push(INPUTS_FILE_NAME); - // Fetch private inputs here + // Fetch program inputs here let inputs_file_string = LeoInputsParser::load_file(&inputs_file_path)?; program.parse_inputs(&inputs_file_path, &inputs_file_string)?; From 3f668422fda3add0cdc6d9ad52aa8f58c20b64dc Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 11 Jun 2020 14:40:27 -0700 Subject: [PATCH 15/15] enforce name, type, visibility of inputs. add tests --- README.md | 2 +- compiler/src/compiler.rs | 4 +- compiler/tests/inputs/inputs.leo | 2 + compiler/tests/inputs/inputs_fail_name.leo | 2 + compiler/tests/inputs/inputs_fail_type.leo | 2 + .../tests/inputs/inputs_fail_visibility.leo | 2 + compiler/tests/inputs/inputs_multiple.leo | 3 + compiler/tests/inputs/main.leo | 3 + compiler/tests/inputs/main_multiple.leo | 3 + compiler/tests/inputs/mod.rs | 72 +++++++++++++++++++ compiler/tests/mod.rs | 5 +- leo-inputs/src/errors/parser.rs | 3 + leo-inputs/src/types/array_type.rs | 10 +++ leo-inputs/src/types/data_type.rs | 2 +- leo-inputs/src/types/integer_type.rs | 12 ++++ leo-inputs/src/types/type_.rs | 4 +- types/src/functions/function_input.rs | 16 ++++- types/src/inputs/inputs.rs | 44 +++++++++--- types/src/program.rs | 12 ++-- 19 files changed, 177 insertions(+), 26 deletions(-) create mode 100644 compiler/tests/inputs/inputs.leo create mode 100644 compiler/tests/inputs/inputs_fail_name.leo create mode 100644 compiler/tests/inputs/inputs_fail_type.leo create mode 100644 compiler/tests/inputs/inputs_fail_visibility.leo create mode 100644 compiler/tests/inputs/inputs_multiple.leo create mode 100644 compiler/tests/inputs/main.leo create mode 100644 compiler/tests/inputs/main_multiple.leo create mode 100644 compiler/tests/inputs/mod.rs diff --git a/README.md b/README.md index 9728a064e7..50806f0b87 100644 --- a/README.md +++ b/README.md @@ -388,7 +388,7 @@ Public and private inputs for a Leo program are specified in the `inputs/` direc ## Sections A Leo input file is made up of sections. Sections are defined by a section header in brackets followed by one or more input definitions. -Section headers specify the target file which must have a main function with matching input names and types defined in the same order. +Section headers specify the target file which must have a main function with matching input names and types. `inputs/inputs.leo` diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index b177bf67af..fa3a77ff5f 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -103,7 +103,7 @@ impl> Compiler { let package_name = self.package_name.clone(); self.program = Program::from(syntax_tree, package_name); - self.program_inputs.set_inputs_size(self.program.num_parameters); + self.program_inputs.set_inputs_size(self.program.expected_inputs.len()); log::debug!("Program parsing complete\n{:#?}", self.program); @@ -114,7 +114,7 @@ impl> Compiler { let syntax_tree = LeoInputsParser::parse_file(input_file_path, input_file_string)?; // Check number/order of private parameters here - self.program_inputs = Inputs::from_inputs_file(syntax_tree)?; + self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?; Ok(()) } diff --git a/compiler/tests/inputs/inputs.leo b/compiler/tests/inputs/inputs.leo new file mode 100644 index 0000000000..e47a66d09f --- /dev/null +++ b/compiler/tests/inputs/inputs.leo @@ -0,0 +1,2 @@ +[main] +b: private bool = true; \ No newline at end of file diff --git a/compiler/tests/inputs/inputs_fail_name.leo b/compiler/tests/inputs/inputs_fail_name.leo new file mode 100644 index 0000000000..42beb0b509 --- /dev/null +++ b/compiler/tests/inputs/inputs_fail_name.leo @@ -0,0 +1,2 @@ +[main] +bad_name: private bool = true; \ No newline at end of file diff --git a/compiler/tests/inputs/inputs_fail_type.leo b/compiler/tests/inputs/inputs_fail_type.leo new file mode 100644 index 0000000000..1c5db3bfb1 --- /dev/null +++ b/compiler/tests/inputs/inputs_fail_type.leo @@ -0,0 +1,2 @@ +[main] +b: private u8 = 1; \ No newline at end of file diff --git a/compiler/tests/inputs/inputs_fail_visibility.leo b/compiler/tests/inputs/inputs_fail_visibility.leo new file mode 100644 index 0000000000..81f53cf9ed --- /dev/null +++ b/compiler/tests/inputs/inputs_fail_visibility.leo @@ -0,0 +1,2 @@ +[main] +b: public bool = true; \ No newline at end of file diff --git a/compiler/tests/inputs/inputs_multiple.leo b/compiler/tests/inputs/inputs_multiple.leo new file mode 100644 index 0000000000..32ee99b6cf --- /dev/null +++ b/compiler/tests/inputs/inputs_multiple.leo @@ -0,0 +1,3 @@ +[main] +b: private bool = true; +a: public bool = false; \ No newline at end of file diff --git a/compiler/tests/inputs/main.leo b/compiler/tests/inputs/main.leo new file mode 100644 index 0000000000..54eb4940dc --- /dev/null +++ b/compiler/tests/inputs/main.leo @@ -0,0 +1,3 @@ +function main(b: private bool) -> bool { + return b +} \ No newline at end of file diff --git a/compiler/tests/inputs/main_multiple.leo b/compiler/tests/inputs/main_multiple.leo new file mode 100644 index 0000000000..24f2cbe84d --- /dev/null +++ b/compiler/tests/inputs/main_multiple.leo @@ -0,0 +1,3 @@ +function main(a: public bool, b: private bool) -> bool { + return a || b +} \ No newline at end of file diff --git a/compiler/tests/inputs/mod.rs b/compiler/tests/inputs/mod.rs new file mode 100644 index 0000000000..424acd6378 --- /dev/null +++ b/compiler/tests/inputs/mod.rs @@ -0,0 +1,72 @@ +use crate::{boolean::output_true, parse_program}; +use leo_compiler::errors::CompilerError; +use leo_inputs::InputParserError; + +use std::path::PathBuf; + +fn fail_input_parser(error: CompilerError) { + match error { + CompilerError::InputParserError(InputParserError::InputNotFound(_)) => {} + err => panic!("expected input parser error, got {}", err), + } +} + +#[test] +fn test_inputs_pass() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs.leo"); + let input_string = String::from_utf8_lossy(input_bytes); + + let mut program = parse_program(program_bytes).unwrap(); + program.parse_inputs(&PathBuf::new(), &input_string).unwrap(); + + output_true(program); +} + +#[test] +fn test_inputs_fail_name() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs_fail_name.leo"); + let input_string = String::from_utf8_lossy(input_bytes); + + let mut program = parse_program(program_bytes).unwrap(); + let error = program.parse_inputs(&PathBuf::new(), &input_string).unwrap_err(); + + fail_input_parser(error); +} + +#[test] +fn test_inputs_fail_type() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs_fail_type.leo"); + let input_string = String::from_utf8_lossy(input_bytes); + + let mut program = parse_program(program_bytes).unwrap(); + let error = program.parse_inputs(&PathBuf::new(), &input_string).unwrap_err(); + + fail_input_parser(error); +} + +#[test] +fn test_inputs_fail_visibility() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs_fail_visibility.leo"); + let input_string = String::from_utf8_lossy(input_bytes); + + let mut program = parse_program(program_bytes).unwrap(); + let error = program.parse_inputs(&PathBuf::new(), &input_string).unwrap_err(); + + fail_input_parser(error); +} + +#[test] +fn test_inputs_multiple() { + let program_bytes = include_bytes!("main_multiple.leo"); + let input_bytes = include_bytes!("inputs_multiple.leo"); + let input_string = String::from_utf8_lossy(input_bytes); + + let mut program = parse_program(program_bytes).unwrap(); + program.parse_inputs(&PathBuf::new(), &input_string).unwrap(); + + output_true(program); +} diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index 283afeb561..1822a963f8 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -5,6 +5,7 @@ pub mod field; pub mod function; pub mod group; pub mod import; +pub mod inputs; pub mod integers; pub mod mutability; pub mod statements; @@ -54,11 +55,11 @@ pub(crate) fn parse_program(bytes: &[u8]) -> Result Result { - let program_string = String::from_utf8_lossy(bytes); + let inputs_string = String::from_utf8_lossy(bytes); let mut compiler = EdwardsTestCompiler::new(); - compiler.parse_inputs(&PathBuf::new(), &program_string)?; + compiler.parse_inputs(&PathBuf::new(), &inputs_string)?; Ok(compiler) } diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index a821fc4f63..4409b9828d 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -11,6 +11,9 @@ pub enum InputParserError { #[error("expected type {}, got {}", _0, _1)] IncompatibleTypes(String, String), + #[error("Program input value {} not found", _0)] + InputNotFound(String), + #[error("Cannot read from the provided file path - {:?}", _0)] FileReadError(PathBuf), diff --git a/leo-inputs/src/types/array_type.rs b/leo-inputs/src/types/array_type.rs index b73cb53fea..fd1ca18dbe 100644 --- a/leo-inputs/src/types/array_type.rs +++ b/leo-inputs/src/types/array_type.rs @@ -17,3 +17,13 @@ impl<'ast> ArrayType<'ast> { self.dimensions.pop() } } + +impl<'ast> std::fmt::Display for ArrayType<'ast> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self._type)?; + for row in &self.dimensions { + write!(f, "[{}]", row)?; + } + write!(f, "") + } +} diff --git a/leo-inputs/src/types/data_type.rs b/leo-inputs/src/types/data_type.rs index 49ad917eac..d675c59e6e 100644 --- a/leo-inputs/src/types/data_type.rs +++ b/leo-inputs/src/types/data_type.rs @@ -17,7 +17,7 @@ pub enum DataType { impl std::fmt::Display for DataType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - DataType::Integer(_) => write!(f, "integer"), + DataType::Integer(ref integer) => write!(f, "{}", integer), DataType::Field(_) => write!(f, "field"), DataType::Group(_) => write!(f, "group"), DataType::Boolean(_) => write!(f, "bool"), diff --git a/leo-inputs/src/types/integer_type.rs b/leo-inputs/src/types/integer_type.rs index 504a1c3706..ed2b520d1c 100644 --- a/leo-inputs/src/types/integer_type.rs +++ b/leo-inputs/src/types/integer_type.rs @@ -31,3 +31,15 @@ pub struct U64Type {} #[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u128))] pub struct U128Type {} + +impl std::fmt::Display for IntegerType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + IntegerType::U8Type(_) => write!(f, "u8"), + IntegerType::U16Type(_) => write!(f, "u16"), + IntegerType::U32Type(_) => write!(f, "u32"), + IntegerType::U64Type(_) => write!(f, "u64"), + IntegerType::U128Type(_) => write!(f, "u128"), + } + } +} diff --git a/leo-inputs/src/types/type_.rs b/leo-inputs/src/types/type_.rs index f6ea8e8933..a7a823ecab 100644 --- a/leo-inputs/src/types/type_.rs +++ b/leo-inputs/src/types/type_.rs @@ -13,8 +13,8 @@ pub enum Type<'ast> { impl<'ast> fmt::Display for Type<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Type::Basic(ref _type) => write!(f, "basic"), - Type::Array(ref _type) => write!(f, "array"), + Type::Basic(ref basic) => write!(f, "{}", basic), + Type::Array(ref array) => write!(f, "{}", array), } } } diff --git a/types/src/functions/function_input.rs b/types/src/functions/function_input.rs index 636b622d7a..48fbbbed35 100644 --- a/types/src/functions/function_input.rs +++ b/types/src/functions/function_input.rs @@ -28,8 +28,8 @@ impl<'ast> From> for FunctionInput { } } -impl fmt::Display for FunctionInput { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl FunctionInput { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { // mut var: private bool if self.mutable { write!(f, "mut ")?; @@ -43,3 +43,15 @@ impl fmt::Display for FunctionInput { write!(f, "{}", self._type) } } + +impl fmt::Display for FunctionInput { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for FunctionInput { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index dc08c30e98..d5b2b8b701 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,6 +1,7 @@ -use crate::InputValue; +use crate::{FunctionInput, InputValue}; use leo_inputs::{common::visibility::Visibility, files::File, InputParserError}; +use leo_inputs::common::Private; use snarkos_models::curves::PairingEngine; #[derive(Clone)] @@ -29,20 +30,43 @@ impl Inputs { self.program_inputs = vec![None; size]; } - pub fn from_inputs_file(file: File) -> Result { + pub fn from_inputs_file(file: File, expected_inputs: Vec) -> Result { let mut private = vec![]; let mut public = vec![]; for section in file.sections.into_iter() { - for assignment in section.assignments.into_iter() { - let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; - if let Some(Visibility::Public(_)) = assignment.parameter.visibility { - // Collect public inputs here - public.push(value.clone()); - } + if section.header.name.value.eq("main") { + for input in &expected_inputs { + // find input with matching name + let matched_input = section.assignments.clone().into_iter().find(|assignment| { + let visibility = assignment + .parameter + .visibility + .as_ref() + .map_or(true, |visibility| visibility.eq(&Visibility::Private(Private {}))); - // push value to vector - private.push(Some(value)); + // name match + assignment.parameter.variable.value.eq(&input.identifier.name) + // visibility match + && visibility.eq(&input.private) + // 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)?; + if let Some(Visibility::Public(_)) = assignment.parameter.visibility { + // Collect public inputs here + public.push(value.clone()); + } + + // push value to vector + private.push(Some(value)); + } + None => return Err(InputParserError::InputNotFound(input.to_string())), + } + } } } diff --git a/types/src/program.rs b/types/src/program.rs index c14adb9533..3bbad00d18 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, Identifier, Import, TestFunction}; +use crate::{Circuit, Function, FunctionInput, Identifier, Import, TestFunction}; use leo_ast::files::File; use std::collections::HashMap; @@ -10,7 +10,7 @@ use std::collections::HashMap; #[derive(Debug, Clone)] pub struct Program { pub name: Identifier, - pub num_parameters: usize, + pub expected_inputs: Vec, pub imports: Vec, pub circuits: HashMap, pub functions: HashMap, @@ -30,7 +30,7 @@ impl<'ast> Program { let mut circuits = HashMap::new(); let mut functions = HashMap::new(); let mut tests = HashMap::new(); - let mut num_parameters = 0usize; + let mut expected_inputs = vec![]; file.circuits.into_iter().for_each(|circuit| { circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit)); @@ -49,12 +49,12 @@ impl<'ast> Program { }); if let Some(main_function) = functions.get(&Identifier::new("main".into())) { - num_parameters = main_function.inputs.len(); + expected_inputs = main_function.inputs.clone(); } Self { name: Identifier::new(name), - num_parameters, + expected_inputs, imports, circuits, functions, @@ -67,7 +67,7 @@ impl Program { pub fn new() -> Self { Self { name: Identifier::new("".into()), - num_parameters: 0, + expected_inputs: vec![], imports: vec![], circuits: HashMap::new(), functions: HashMap::new(),