mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-25 02:22:44 +03:00
Merge pull request #53 from AleoHQ/feature/leo-inputs
Feature/leo inputs
This commit is contained in:
commit
5661cbe927
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
/target
|
||||
/tmp/
|
||||
**.idea/
|
||||
outputs/
|
||||
*.DS_Store
|
||||
|
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -515,6 +515,7 @@ dependencies = [
|
||||
"env_logger",
|
||||
"from-pest",
|
||||
"leo-compiler",
|
||||
"leo-inputs",
|
||||
"log",
|
||||
"rand",
|
||||
"rand_core",
|
||||
@ -550,6 +551,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"leo-ast",
|
||||
"leo-inputs",
|
||||
"leo-types",
|
||||
"log",
|
||||
"rand",
|
||||
@ -562,11 +564,28 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-inputs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"from-pest",
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-curves",
|
||||
"snarkos-errors",
|
||||
"snarkos-gadgets",
|
||||
"snarkos-models",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"leo-ast",
|
||||
"leo-inputs",
|
||||
"snarkos-errors",
|
||||
"snarkos-models",
|
||||
"thiserror",
|
||||
|
@ -13,10 +13,11 @@ 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" }
|
||||
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" }
|
||||
|
46
README.md
46
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.
|
||||
|
||||
`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`:
|
||||
|
||||
```
|
||||
|
@ -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" }
|
||||
|
@ -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::{
|
||||
@ -15,6 +16,7 @@ use snarkos_models::{
|
||||
};
|
||||
|
||||
use sha2::{Digest, Sha256};
|
||||
use snarkos_models::curves::PairingEngine;
|
||||
use std::{fs, marker::PhantomData, path::PathBuf};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -22,7 +24,7 @@ pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
|
||||
package_name: String,
|
||||
main_file_path: PathBuf,
|
||||
program: Program,
|
||||
program_inputs: Vec<Option<InputValue>>,
|
||||
program_inputs: Inputs,
|
||||
output: Option<ConstrainedValue<F, G>>,
|
||||
_engine: PhantomData<F>,
|
||||
}
|
||||
@ -33,7 +35,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
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 +46,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
package_name,
|
||||
main_file_path,
|
||||
program: Program::new(),
|
||||
program_inputs: vec![],
|
||||
program_inputs: Inputs::new(),
|
||||
output: None,
|
||||
_engine: PhantomData,
|
||||
};
|
||||
@ -57,7 +59,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
}
|
||||
|
||||
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue>>) {
|
||||
self.program_inputs = program_inputs;
|
||||
self.program_inputs.set_inputs(program_inputs);
|
||||
}
|
||||
|
||||
pub fn get_public_inputs<E: PairingEngine>(&self) -> Result<Vec<E::Fr>, CompilerError> {
|
||||
Ok(self.program_inputs.get_public_inputs::<E>()?)
|
||||
}
|
||||
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
@ -77,7 +83,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
||||
generate_constraints(cs, self.program, self.program_inputs)
|
||||
generate_constraints(cs, self.program, self.program_inputs.get_inputs())
|
||||
}
|
||||
|
||||
pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem<F>) -> Result<(), CompilerError> {
|
||||
@ -86,8 +92,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
|
||||
fn load_program(&mut self) -> Result<String, CompilerError> {
|
||||
// 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> {
|
||||
@ -98,17 +103,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
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_inputs_size(self.program.expected_inputs.len());
|
||||
|
||||
log::debug!("Program parsing complete\n{:#?}", self.program);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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)?;
|
||||
|
||||
// Check number/order of private parameters here
|
||||
self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
|
||||
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
|
||||
let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs).unwrap();
|
||||
let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_inputs()).unwrap();
|
||||
|
||||
// Write results to file or something
|
||||
|
||||
|
@ -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),
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
/// Visibility
|
||||
|
||||
visibility_public = { "public" }
|
||||
visibility_private = { "private" }
|
||||
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 }
|
||||
|
||||
/// Values
|
||||
|
||||
value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* }
|
||||
value_u32 = { value_number ~ ty_u32? }
|
||||
value_field = { value_number ~ ty_field }
|
||||
value_boolean = { "true" | "false" }
|
||||
value = { value_field | value_boolean | value_u32 }
|
||||
|
||||
/// Variables
|
||||
|
||||
protected_name = { visibility | "return" }
|
||||
variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
|
||||
|
||||
/// Arrays
|
||||
|
||||
inline_array_inner = _{(expression_term ~ ("," ~ NEWLINE* ~ expression_term)*)?}
|
||||
expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"}
|
||||
expression_array_initializer = { "[" ~ expression_term ~ ";" ~ value ~ "]" }
|
||||
|
||||
/// Structs
|
||||
|
||||
inline_struct_member = { variable ~ ":" ~ expression_term }
|
||||
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_inline_struct
|
||||
| expression_primitive
|
||||
| expression_array_inline
|
||||
| expression_array_initializer
|
||||
}
|
||||
|
||||
/// Functions
|
||||
|
||||
parameter = { variable ~ ":" ~ visibility? ~ ty }
|
||||
|
||||
function_name = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
|
||||
|
||||
/// Section
|
||||
|
||||
header = { "[" ~ function_name ~ "]" }
|
||||
assignment = { parameter ~ "=" ~ expression_term }
|
||||
|
||||
section = { header ~ NEWLINE+ ~ assignment* ~ NEWLINE* }
|
||||
|
||||
/// Utilities
|
||||
|
||||
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
|
||||
WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* }
|
||||
|
||||
/// Program File
|
||||
|
||||
file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI }
|
@ -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);
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ 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;
|
||||
|
||||
pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) {
|
||||
@ -76,7 +76,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);
|
||||
}
|
||||
|
2
compiler/tests/inputs/inputs.leo
Normal file
2
compiler/tests/inputs/inputs.leo
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
b: private bool = true;
|
2
compiler/tests/inputs/inputs_fail_name.leo
Normal file
2
compiler/tests/inputs/inputs_fail_name.leo
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
bad_name: private bool = true;
|
2
compiler/tests/inputs/inputs_fail_type.leo
Normal file
2
compiler/tests/inputs/inputs_fail_type.leo
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
b: private u8 = 1;
|
2
compiler/tests/inputs/inputs_fail_visibility.leo
Normal file
2
compiler/tests/inputs/inputs_fail_visibility.leo
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
b: public bool = true;
|
3
compiler/tests/inputs/inputs_multiple.leo
Normal file
3
compiler/tests/inputs/inputs_multiple.leo
Normal file
@ -0,0 +1,3 @@
|
||||
[main]
|
||||
b: private bool = true;
|
||||
a: public bool = false;
|
3
compiler/tests/inputs/main.leo
Normal file
3
compiler/tests/inputs/main.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(b: private bool) -> bool {
|
||||
return b
|
||||
}
|
3
compiler/tests/inputs/main_multiple.leo
Normal file
3
compiler/tests/inputs/main_multiple.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: public bool, b: private bool) -> bool {
|
||||
return a || b
|
||||
}
|
72
compiler/tests/inputs/mod.rs
Normal file
72
compiler/tests/inputs/mod.rs
Normal file
@ -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);
|
||||
}
|
@ -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::<Fq>::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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
@ -19,6 +20,7 @@ use leo_compiler::{
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub type EdwardsTestCompiler = Compiler<Fq, EdwardsGroupType>;
|
||||
pub type EdwardsConstrainedValue = ConstrainedValue<Fq, EdwardsGroupType>;
|
||||
@ -51,3 +53,13 @@ pub(crate) fn parse_program(bytes: &[u8]) -> Result<EdwardsTestCompiler, Compile
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_inputs(bytes: &[u8]) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let inputs_string = String::from_utf8_lossy(bytes);
|
||||
|
||||
let mut compiler = EdwardsTestCompiler::new();
|
||||
|
||||
compiler.parse_inputs(&PathBuf::new(), &inputs_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
@ -3,8 +3,9 @@ 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;
|
||||
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);
|
||||
}
|
||||
|
2
compiler/tests/syntax/inputs_semicolon.leo
Normal file
2
compiler/tests/syntax/inputs_semicolon.leo
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
a: private u32 = 5
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
18
leo-inputs/Cargo.toml
Normal file
18
leo-inputs/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "leo-inputs"
|
||||
version = "0.1.0"
|
||||
authors = ["The Aleo Team <hello@aleo.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
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" }
|
||||
thiserror = { version = "1.0" }
|
4
leo-inputs/input.leo
Normal file
4
leo-inputs/input.leo
Normal file
@ -0,0 +1,4 @@
|
||||
[main]
|
||||
a: private u32 = 5;
|
||||
b: public field = 1field;
|
||||
c: private bool = true;
|
14
leo-inputs/src/assignments/assignment.rs
Normal file
14
leo-inputs/src/assignments/assignment.rs
Normal file
@ -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>,
|
||||
}
|
2
leo-inputs/src/assignments/mod.rs
Normal file
2
leo-inputs/src/assignments/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod assignment;
|
||||
pub use assignment::*;
|
14
leo-inputs/src/ast.rs
Normal file
14
leo-inputs/src/ast.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//! Abstract syntax tree (ast) representation from leo-inputs.pest.
|
||||
use pest::{error::Error, iterators::Pairs, Parser, Span};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "leo-inputs.pest"]
|
||||
pub struct LanguageParser;
|
||||
|
||||
pub fn parse(input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
|
||||
LanguageParser::parse(Rule::file, input)
|
||||
}
|
||||
|
||||
pub fn span_into_string(span: Span) -> String {
|
||||
span.as_str().to_string()
|
||||
}
|
7
leo-inputs/src/common/eoi.rs
Normal file
7
leo-inputs/src/common/eoi.rs
Normal file
@ -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;
|
20
leo-inputs/src/common/identifier.rs
Normal file
20
leo-inputs/src/common/identifier.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
7
leo-inputs/src/common/line_end.rs
Normal file
7
leo-inputs/src/common/line_end.rs
Normal file
@ -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;
|
11
leo-inputs/src/common/mod.rs
Normal file
11
leo-inputs/src/common/mod.rs
Normal file
@ -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::*;
|
18
leo-inputs/src/common/visibility.rs
Normal file
18
leo-inputs/src/common/visibility.rs
Normal file
@ -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 {}
|
5
leo-inputs/src/errors/mod.rs
Normal file
5
leo-inputs/src/errors/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod parser;
|
||||
pub use parser::*;
|
||||
|
||||
pub mod syntax;
|
||||
pub use syntax::*;
|
43
leo-inputs/src/errors/parser.rs
Normal file
43
leo-inputs/src/errors/parser.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use crate::{ast::Rule, errors::SyntaxError};
|
||||
|
||||
use pest::error::Error;
|
||||
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("Program input value {} not found", _0)]
|
||||
InputNotFound(String),
|
||||
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseBoolError(#[from] ParseBoolError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
|
||||
#[error("cannot parse {} as field", _0)]
|
||||
ParseFieldError(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
SyntaxError(#[from] SyntaxError),
|
||||
|
||||
#[error("Unable to construct abstract syntax tree")]
|
||||
SyntaxTreeError,
|
||||
|
||||
#[error("found an empty array dimension in type")]
|
||||
UndefinedArrayDimension,
|
||||
}
|
||||
|
||||
impl From<Error<Rule>> for InputParserError {
|
||||
fn from(error: Error<Rule>) -> Self {
|
||||
InputParserError::SyntaxError(SyntaxError::from(error))
|
||||
}
|
||||
}
|
29
leo-inputs/src/errors/syntax.rs
Normal file
29
leo-inputs/src/errors/syntax.rs
Normal file
@ -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<Error<Rule>> for SyntaxError {
|
||||
fn from(mut error: Error<Rule>) -> 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
|
||||
}
|
||||
}
|
13
leo-inputs/src/expressions/array_initializer_expression.rs
Normal file
13
leo-inputs/src/expressions/array_initializer_expression.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::{ast::Rule, expressions::Expression, values::NumberValue};
|
||||
|
||||
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<Expression<'ast>>,
|
||||
pub count: NumberValue<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
12
leo-inputs/src/expressions/array_inline_expression.rs
Normal file
12
leo-inputs/src/expressions/array_inline_expression.rs
Normal file
@ -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<Expression<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
32
leo-inputs/src/expressions/expression.rs
Normal file
32
leo-inputs/src/expressions/expression.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::{ast::Rule, expressions::*, values::Value};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::expression))]
|
||||
pub enum Expression<'ast> {
|
||||
ArrayInline(ArrayInlineExpression<'ast>),
|
||||
ArrayInitializer(ArrayInitializerExpression<'ast>),
|
||||
Value(Value<'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::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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
leo-inputs/src/expressions/mod.rs
Normal file
8
leo-inputs/src/expressions/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod array_initializer_expression;
|
||||
pub use array_initializer_expression::*;
|
||||
|
||||
pub mod array_inline_expression;
|
||||
pub use array_inline_expression::*;
|
||||
|
||||
pub mod expression;
|
||||
pub use expression::*;
|
13
leo-inputs/src/files/file.rs
Normal file
13
leo-inputs/src/files/file.rs
Normal file
@ -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<Section<'ast>>,
|
||||
pub eoi: EOI,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
2
leo-inputs/src/files/mod.rs
Normal file
2
leo-inputs/src/files/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod file;
|
||||
pub use file::*;
|
115
leo-inputs/src/leo-inputs.pest
Normal file
115
leo-inputs/src/leo-inputs.pest
Normal file
@ -0,0 +1,115 @@
|
||||
/// Common
|
||||
|
||||
// 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
|
||||
|
||||
// Declared in types/type_.rs
|
||||
type_ = { type_array | type_data }
|
||||
|
||||
// Declared in types/integer_type.rs
|
||||
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" }
|
||||
|
||||
// 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/array_type.rs
|
||||
type_array = { type_data ~ ("[" ~ value_number ~ "]")+ }
|
||||
|
||||
/// 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_tuple ~ type_group }
|
||||
group_tuple = { "(" ~ NEWLINE* ~ value_number ~ "," ~ NEWLINE* ~ value_number ~ NEWLINE* ~")" }
|
||||
|
||||
/// Expressions
|
||||
|
||||
// Declared in expressions/array_initializer_expression.rs
|
||||
expression_array_initializer = { "[" ~ expression ~ ";" ~ value_number ~ "]" }
|
||||
|
||||
// Declared in expressions/array_inline_expression.rs
|
||||
expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"}
|
||||
inline_array_inner = _{ (expression ~ ("," ~ NEWLINE* ~ expression)*)? }
|
||||
|
||||
// Declared in expressions/expression.rs
|
||||
expression = {
|
||||
expression_array_inline
|
||||
| expression_array_initializer
|
||||
| value
|
||||
}
|
||||
|
||||
/// Parameters
|
||||
|
||||
// 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
|
||||
|
||||
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
|
||||
WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* }
|
||||
|
||||
/// Files
|
||||
|
||||
// Declared in files/file.rs
|
||||
file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI }
|
43
leo-inputs/src/lib.rs
Normal file
43
leo-inputs/src/lib.rs
Normal file
@ -0,0 +1,43 @@
|
||||
#[macro_use]
|
||||
extern crate pest_derive;
|
||||
#[macro_use]
|
||||
extern crate thiserror;
|
||||
|
||||
pub mod errors;
|
||||
pub use errors::*;
|
||||
|
||||
//extern crate from_pest;
|
||||
pub mod assignments;
|
||||
mod ast;
|
||||
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};
|
||||
|
||||
pub struct LeoInputsParser;
|
||||
|
||||
impl LeoInputsParser {
|
||||
/// Reads in the given file path into a string.
|
||||
pub fn load_file(file_path: &PathBuf) -> Result<String, InputParserError> {
|
||||
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<files::File<'a>, InputParserError> {
|
||||
// Parse the file using leo.pest
|
||||
let mut file = ast::parse(input_file)
|
||||
.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(|_| InputParserError::SyntaxTreeError)?;
|
||||
// println!("{:?}", syntax_tree);
|
||||
|
||||
Ok(syntax_tree)
|
||||
}
|
||||
}
|
13
leo-inputs/src/main.rs
Normal file
13
leo-inputs/src/main.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use leo_inputs::{self, LeoInputsParser};
|
||||
|
||||
use std::env::current_dir;
|
||||
|
||||
fn main() {
|
||||
let mut path = current_dir().unwrap();
|
||||
path.push("input.leo");
|
||||
|
||||
let input_file = &LeoInputsParser::load_file(&path).expect("cannot read file");
|
||||
let syntax_tree = LeoInputsParser::parse_file(&path, input_file).unwrap();
|
||||
|
||||
println!("tree: {:#?}", syntax_tree);
|
||||
}
|
2
leo-inputs/src/parameters/mod.rs
Normal file
2
leo-inputs/src/parameters/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod parameter;
|
||||
pub use parameter::*;
|
18
leo-inputs/src/parameters/parameter.rs
Normal file
18
leo-inputs/src/parameters/parameter.rs
Normal file
@ -0,0 +1,18 @@
|
||||
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<Visibility>,
|
||||
pub type_: Type<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
12
leo-inputs/src/sections/header.rs
Normal file
12
leo-inputs/src/sections/header.rs
Normal file
@ -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>,
|
||||
}
|
5
leo-inputs/src/sections/mod.rs
Normal file
5
leo-inputs/src/sections/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod header;
|
||||
pub use header::*;
|
||||
|
||||
pub mod section;
|
||||
pub use section::*;
|
13
leo-inputs/src/sections/section.rs
Normal file
13
leo-inputs/src/sections/section.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::{assignments::Assignment, ast::Rule, sections::Header};
|
||||
|
||||
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<Assignment<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
29
leo-inputs/src/types/array_type.rs
Normal file
29
leo-inputs/src/types/array_type.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::{ast::Rule, types::DataType, values::NumberValue};
|
||||
|
||||
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<NumberValue<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
impl<'ast> ArrayType<'ast> {
|
||||
pub fn next_dimension(&mut self) -> Option<NumberValue<'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, "")
|
||||
}
|
||||
}
|
7
leo-inputs/src/types/boolean_type.rs
Normal file
7
leo-inputs/src/types/boolean_type.rs
Normal file
@ -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 {}
|
26
leo-inputs/src/types/data_type.rs
Normal file
26
leo-inputs/src/types/data_type.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
types::{BooleanType, FieldType, GroupType, IntegerType},
|
||||
};
|
||||
|
||||
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),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DataType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
DataType::Integer(ref integer) => write!(f, "{}", integer),
|
||||
DataType::Field(_) => write!(f, "field"),
|
||||
DataType::Group(_) => write!(f, "group"),
|
||||
DataType::Boolean(_) => write!(f, "bool"),
|
||||
}
|
||||
}
|
||||
}
|
7
leo-inputs/src/types/field_type.rs
Normal file
7
leo-inputs/src/types/field_type.rs
Normal file
@ -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 {}
|
7
leo-inputs/src/types/group_type.rs
Normal file
7
leo-inputs/src/types/group_type.rs
Normal file
@ -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 {}
|
45
leo-inputs/src/types/integer_type.rs
Normal file
45
leo-inputs/src/types/integer_type.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_integer))]
|
||||
pub enum IntegerType {
|
||||
U8Type(U8Type),
|
||||
U16Type(U16Type),
|
||||
U32Type(U32Type),
|
||||
U64Type(U64Type),
|
||||
U128Type(U128Type),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_u8))]
|
||||
pub struct U8Type {}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_u16))]
|
||||
pub struct U16Type {}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_u32))]
|
||||
pub struct U32Type {}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_u64))]
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
20
leo-inputs/src/types/mod.rs
Normal file
20
leo-inputs/src/types/mod.rs
Normal file
@ -0,0 +1,20 @@
|
||||
pub mod array_type;
|
||||
pub use array_type::*;
|
||||
|
||||
pub mod boolean_type;
|
||||
pub use boolean_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_::*;
|
20
leo-inputs/src/types/type_.rs
Normal file
20
leo-inputs/src/types/type_.rs
Normal file
@ -0,0 +1,20 @@
|
||||
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>),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Type<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Type::Basic(ref basic) => write!(f, "{}", basic),
|
||||
Type::Array(ref array) => write!(f, "{}", array),
|
||||
}
|
||||
}
|
||||
}
|
20
leo-inputs/src/values/boolean_value.rs
Normal file
20
leo-inputs/src/values/boolean_value.rs
Normal file
@ -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::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)
|
||||
}
|
||||
}
|
20
leo-inputs/src/values/field_value.rs
Normal file
20
leo-inputs/src/values/field_value.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
35
leo-inputs/src/values/group_value.rs
Normal file
35
leo-inputs/src/values/group_value.rs
Normal file
@ -0,0 +1,35 @@
|
||||
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: GroupTuple<'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_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)
|
||||
}
|
||||
}
|
20
leo-inputs/src/values/integer_value.rs
Normal file
20
leo-inputs/src/values/integer_value.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
20
leo-inputs/src/values/mod.rs
Normal file
20
leo-inputs/src/values/mod.rs
Normal file
@ -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::*;
|
19
leo-inputs/src/values/number_implicit_value.rs
Normal file
19
leo-inputs/src/values/number_implicit_value.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
20
leo-inputs/src/values/number_value.rs
Normal file
20
leo-inputs/src/values/number_value.rs
Normal file
@ -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::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)
|
||||
}
|
||||
}
|
42
leo-inputs/src/values/value.rs
Normal file
42
leo-inputs/src/values/value.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
values::{BooleanValue, FieldValue, GroupValue, IntegerValue, 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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -6,11 +6,15 @@ 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 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};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -18,7 +22,11 @@ pub struct ProveCommand;
|
||||
|
||||
impl CLI for ProveCommand {
|
||||
type Options = ();
|
||||
type Output = Proof<Bls12_377>;
|
||||
type Output = (
|
||||
Compiler<Fq, EdwardsGroupType>,
|
||||
Proof<Bls12_377>,
|
||||
PreparedVerifyingKey<Bls12_377>,
|
||||
);
|
||||
|
||||
const ABOUT: AboutType = "Run the program and produce a proof";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
@ -34,17 +42,26 @@ impl CLI for ProveCommand {
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||
let (program, parameters, _) = SetupCommand::output(options)?;
|
||||
let (mut program, parameters, prepared_verifying_key) = SetupCommand::output(options)?;
|
||||
|
||||
// Get the package name
|
||||
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 program inputs here
|
||||
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();
|
||||
|
||||
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)?;
|
||||
|
||||
log::info!("Prover completed in {:?} milliseconds", start.elapsed().as_millis());
|
||||
|
||||
@ -55,6 +72,6 @@ impl CLI for ProveCommand {
|
||||
|
||||
log::info!("Completed program proving");
|
||||
|
||||
Ok(program_proof)
|
||||
Ok((program, program_proof, prepared_verifying_key))
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
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;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::time::{Duration, Instant};
|
||||
@ -31,16 +27,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, prepared_verifying_key) = ProveCommand::output(options)?;
|
||||
|
||||
let mut verifying = Duration::new(0, 0);
|
||||
|
||||
// let _inputs: Vec<_> = [1u32; 1].to_vec();
|
||||
// fetch public inputs
|
||||
let inputs: Vec<_> = program.get_public_inputs::<Bls12_377>().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();
|
||||
|
||||
|
@ -57,6 +57,12 @@ impl From<leo_compiler::errors::CompilerError> for CLIError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<leo_inputs::errors::InputParserError> for CLIError {
|
||||
fn from(error: leo_inputs::errors::InputParserError) -> Self {
|
||||
CLIError::Crate("leo_inputs", format!("{}", error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<snarkos_errors::gadgets::SynthesisError> for CLIError {
|
||||
fn from(error: snarkos_errors::gadgets::SynthesisError) -> Self {
|
||||
CLIError::Crate("snarkos_errors", format!("{}", error))
|
||||
|
56
leo/files/inputs.rs
Normal file
56
leo/files/inputs.rs
Normal file
@ -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
|
||||
)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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" }
|
||||
|
@ -28,8 +28,8 @@ impl<'ast> From<AstFunctionInput<'ast>> 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)
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum InputValue {
|
||||
Integer(u128),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Boolean(bool),
|
||||
Array(Vec<InputValue>),
|
||||
}
|
||||
|
||||
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, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
70
types/src/inputs/input_fields.rs
Normal file
70
types/src/inputs/input_fields.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use crate::InputValue;
|
||||
use leo_inputs::{types::IntegerType, InputParserError};
|
||||
|
||||
use snarkos_models::curves::{Field, PairingEngine};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub struct InputFields<E: PairingEngine>(pub Vec<E::Fr>);
|
||||
|
||||
impl<E: PairingEngine> InputFields<E> {
|
||||
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) -> Self {
|
||||
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::<E>::from_boolean(&boolean);
|
||||
|
||||
fields.append(&mut boolean_fields.0);
|
||||
}
|
||||
|
||||
Self(fields)
|
||||
}
|
||||
|
||||
pub(crate) fn from_field(field: &str) -> Result<Self, InputParserError> {
|
||||
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<Self, InputParserError> {
|
||||
let s = group.trim();
|
||||
let mut fields = vec![];
|
||||
|
||||
for substr in s.split(|c| c == '(' || c == ')' || c == ',' || c == ' ') {
|
||||
if !substr.is_empty() {
|
||||
let mut input_fields = InputFields::<E>::from_field(&substr)?;
|
||||
|
||||
fields.append(&mut input_fields.0);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self(fields))
|
||||
}
|
||||
|
||||
pub(crate) fn from_array(array: &Vec<InputValue>) -> Result<Self, InputParserError> {
|
||||
let mut fields = vec![];
|
||||
|
||||
for input in array.iter() {
|
||||
let mut input_fields = input.to_input_fields::<E>()?;
|
||||
|
||||
fields.append(&mut input_fields.0);
|
||||
}
|
||||
|
||||
Ok(Self(fields))
|
||||
}
|
||||
}
|
183
types/src/inputs/input_value.rs
Normal file
183
types/src/inputs/input_value.rs
Normal file
@ -0,0 +1,183 @@
|
||||
use crate::InputFields;
|
||||
use leo_inputs::{
|
||||
errors::InputParserError,
|
||||
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression},
|
||||
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(IntegerType, u128),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Boolean(bool),
|
||||
Array(Vec<InputValue>),
|
||||
}
|
||||
|
||||
impl<'ast> InputValue {
|
||||
fn from_boolean(boolean: BooleanValue<'ast>) -> Result<Self, InputParserError> {
|
||||
let boolean = boolean.value.parse::<bool>()?;
|
||||
Ok(InputValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
fn from_number(integer_type: IntegerType, number: NumberValue<'ast>) -> Result<Self, InputParserError> {
|
||||
let integer = number.value.parse::<u128>()?;
|
||||
Ok(InputValue::Integer(integer_type, integer))
|
||||
}
|
||||
|
||||
fn from_group(group: GroupValue<'ast>) -> Self {
|
||||
InputValue::Group(group.to_string())
|
||||
}
|
||||
|
||||
fn from_field(field: FieldValue<'ast>) -> Self {
|
||||
InputValue::Field(field.number.value)
|
||||
}
|
||||
|
||||
fn from_implicit(data_type: DataType, implicit: NumberImplicitValue<'ast>) -> Result<Self, InputParserError> {
|
||||
match data_type {
|
||||
DataType::Boolean(_) => Err(InputParserError::IncompatibleTypes(
|
||||
"bool".to_string(),
|
||||
"implicit number".to_string(),
|
||||
)),
|
||||
DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.number),
|
||||
DataType::Group(_) => Ok(InputValue::Group(implicit.number.value)),
|
||||
DataType::Field(_) => Ok(InputValue::Field(implicit.number.value)),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_value(data_type: DataType, value: Value<'ast>) -> Result<Self, InputParserError> {
|
||||
match (data_type, value) {
|
||||
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
|
||||
(DataType::Integer(integer_type), Value::Integer(integer)) => {
|
||||
InputValue::from_number(integer_type, integer.number)
|
||||
}
|
||||
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
|
||||
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
|
||||
(data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit),
|
||||
(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<Self, InputParserError> {
|
||||
match (type_, expression) {
|
||||
(Type::Basic(data_type), Expression::Value(value)) => InputValue::from_value(data_type, value),
|
||||
(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_, value) => Err(InputParserError::IncompatibleTypes(
|
||||
type_.to_string(),
|
||||
value.to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_array_inline(
|
||||
mut array_type: ArrayType,
|
||||
inline: ArrayInlineExpression,
|
||||
) -> Result<Self, InputParserError> {
|
||||
match array_type.next_dimension() {
|
||||
Some(number) => {
|
||||
let outer_dimension = number.value.parse::<usize>()?;
|
||||
|
||||
if outer_dimension != inline.expressions.len() {
|
||||
return Err(InputParserError::InvalidArrayLength(
|
||||
outer_dimension,
|
||||
inline.expressions.len(),
|
||||
));
|
||||
}
|
||||
}
|
||||
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 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<Self, InputParserError> {
|
||||
let initializer_count = initializer.count.value.parse::<usize>()?;
|
||||
|
||||
match array_type.next_dimension() {
|
||||
Some(number) => {
|
||||
let outer_dimension = number.value.parse::<usize>()?;
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
pub(crate) fn to_input_fields<E: PairingEngine>(&self) -> Result<InputFields<E>, InputParserError> {
|
||||
match self {
|
||||
InputValue::Boolean(boolean) => Ok(InputFields::from_boolean(boolean)),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InputValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
InputValue::Boolean(ref boolean) => write!(f, "{}", boolean),
|
||||
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
|
||||
InputValue::Group(ref group) => write!(f, "{}", group),
|
||||
InputValue::Field(ref field) => write!(f, "{}", field),
|
||||
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, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
92
types/src/inputs/inputs.rs
Normal file
92
types/src/inputs/inputs.rs
Normal file
@ -0,0 +1,92 @@
|
||||
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)]
|
||||
pub struct Inputs {
|
||||
program_inputs: Vec<Option<InputValue>>,
|
||||
public: Vec<InputValue>,
|
||||
}
|
||||
|
||||
impl Inputs {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
program_inputs: vec![],
|
||||
public: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inputs(&self) -> Vec<Option<InputValue>> {
|
||||
self.program_inputs.clone()
|
||||
}
|
||||
|
||||
pub fn set_inputs(&mut self, inputs: Vec<Option<InputValue>>) {
|
||||
self.program_inputs = inputs;
|
||||
}
|
||||
|
||||
pub fn set_inputs_size(&mut self, size: usize) {
|
||||
self.program_inputs = vec![None; size];
|
||||
}
|
||||
|
||||
pub fn from_inputs_file(file: File, expected_inputs: Vec<FunctionInput>) -> Result<Self, InputParserError> {
|
||||
let mut private = vec![];
|
||||
let mut public = vec![];
|
||||
|
||||
for section in file.sections.into_iter() {
|
||||
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 {})));
|
||||
|
||||
// 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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
program_inputs: private,
|
||||
public,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_public_inputs<E: PairingEngine>(&self) -> Result<Vec<E::Fr>, InputParserError> {
|
||||
let mut input_vec = vec![];
|
||||
|
||||
for input in self.public.iter() {
|
||||
// get fields
|
||||
let mut input_fields = input.to_input_fields::<E>()?;
|
||||
|
||||
// push fields to input_vec
|
||||
input_vec.append(&mut input_fields.0)
|
||||
}
|
||||
|
||||
Ok(input_vec)
|
||||
}
|
||||
}
|
8
types/src/inputs/mod.rs
Normal file
8
types/src/inputs/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod inputs;
|
||||
pub use inputs::*;
|
||||
|
||||
pub mod input_fields;
|
||||
pub use input_fields::*;
|
||||
|
||||
pub mod input_value;
|
||||
pub use input_value::*;
|
@ -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()));
|
||||
|
@ -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::*;
|
||||
|
@ -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<FunctionInput>,
|
||||
pub imports: Vec<Import>,
|
||||
pub circuits: HashMap<Identifier, Circuit>,
|
||||
pub functions: HashMap<Identifier, Function>,
|
||||
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user