mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
parse main, record, registers, state, state_leaf types to compiler input
This commit is contained in:
parent
b9b459ecff
commit
9fc9e16367
@ -1,4 +1,4 @@
|
||||
use crate::{ast::Rule, common::Identifier, functions::FunctionInput, statements::Statement, types::Type};
|
||||
use crate::{ast::Rule, common::Identifier, functions::inputs::Input, statements::Statement, types::Type};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -7,7 +7,7 @@ use pest_ast::FromPest;
|
||||
#[pest_ast(rule(Rule::function_definition))]
|
||||
pub struct Function<'ast> {
|
||||
pub function_name: Identifier<'ast>,
|
||||
pub parameters: Vec<FunctionInput<'ast>>,
|
||||
pub parameters: Vec<Input<'ast>>,
|
||||
pub returns: Vec<Type<'ast>>,
|
||||
pub statements: Vec<Statement<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
|
16
ast/src/functions/inputs/input.rs
Normal file
16
ast/src/functions/inputs/input.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
functions::{FunctionInput, Record, Registers, State, StateLeaf},
|
||||
};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::input))]
|
||||
pub enum Input<'ast> {
|
||||
FunctionInput(FunctionInput<'ast>),
|
||||
Record(Record<'ast>),
|
||||
Registers(Registers<'ast>),
|
||||
State(State<'ast>),
|
||||
StateLeaf(StateLeaf<'ast>),
|
||||
}
|
17
ast/src/functions/inputs/mod.rs
Normal file
17
ast/src/functions/inputs/mod.rs
Normal file
@ -0,0 +1,17 @@
|
||||
pub mod function_input;
|
||||
pub use function_input::*;
|
||||
|
||||
pub mod input;
|
||||
pub use input::*;
|
||||
|
||||
pub mod record;
|
||||
pub use record::*;
|
||||
|
||||
pub mod registers;
|
||||
pub use registers::*;
|
||||
|
||||
pub mod state;
|
||||
pub use state::*;
|
||||
|
||||
pub mod state_leaf;
|
||||
pub use state_leaf::*;
|
11
ast/src/functions/inputs/record.rs
Normal file
11
ast/src/functions/inputs/record.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::record))]
|
||||
pub struct Record<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
11
ast/src/functions/inputs/registers.rs
Normal file
11
ast/src/functions/inputs/registers.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::registers))]
|
||||
pub struct Registers<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
11
ast/src/functions/inputs/state.rs
Normal file
11
ast/src/functions/inputs/state.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::state))]
|
||||
pub struct State<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
11
ast/src/functions/inputs/state_leaf.rs
Normal file
11
ast/src/functions/inputs/state_leaf.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::state_leaf))]
|
||||
pub struct StateLeaf<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
pub mod function;
|
||||
pub use function::*;
|
||||
|
||||
pub mod function_input;
|
||||
pub use function_input::*;
|
||||
pub mod inputs;
|
||||
pub use inputs::*;
|
||||
|
||||
pub mod test_function;
|
||||
pub use test_function::*;
|
||||
|
@ -335,11 +335,32 @@ statement_return = { "return " ~ return_}
|
||||
/// Functions
|
||||
|
||||
// Declared in functions/function.rs
|
||||
function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_model_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* }
|
||||
function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* }
|
||||
|
||||
// Declared in functions/function_input.rs
|
||||
// Declared in functions/inputs/function_input.rs
|
||||
function_input = { mutable? ~ identifier ~ ":" ~ type_ }
|
||||
input_model_list = _{ (function_input ~ ("," ~ NEWLINE* ~ function_input)*)? }
|
||||
|
||||
// Declared in functions/inputs/record.rs
|
||||
record = { "record" }
|
||||
|
||||
// Declared in functions/inputs/registers.rs
|
||||
registers = { "registers" }
|
||||
|
||||
// Declared in functions/inputs/state.rs
|
||||
state = { "state" }
|
||||
|
||||
// Declared in functions/inputs/state_leaf.rs
|
||||
state_leaf = { "state_leaf" }
|
||||
|
||||
// Declared in functions/inputs/input.rs
|
||||
input = {
|
||||
record
|
||||
| registers
|
||||
| state_leaf
|
||||
| state
|
||||
| function_input
|
||||
}
|
||||
input_list = _{ (input ~ ("," ~ NEWLINE* ~ input)*)? }
|
||||
|
||||
// Declared in functions/test_function.rs
|
||||
test_function = { "test " ~ function_definition }
|
||||
|
@ -118,8 +118,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
pub fn parse_inputs(&mut self, inputs_string: &str) -> Result<(), CompilerError> {
|
||||
let syntax_tree = LeoInputsParser::parse_file(&inputs_string)?;
|
||||
|
||||
self.program_inputs
|
||||
.parse_program_input_file(syntax_tree, self.program.expected_inputs.clone())?;
|
||||
|
||||
// Check number/order of parameters here
|
||||
self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?;
|
||||
// self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
GroupType,
|
||||
};
|
||||
|
||||
use leo_types::{Expression, Function, Span};
|
||||
use leo_types::{Expression, Function, Input, Span};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
@ -39,23 +39,28 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
// Store input values as new variables in resolved program
|
||||
for (input_model, input_expression) in function.inputs.clone().iter().zip(inputs.into_iter()) {
|
||||
// First evaluate input expression
|
||||
let mut input_value = self.enforce_input(
|
||||
cs,
|
||||
scope.clone(),
|
||||
caller_scope.clone(),
|
||||
function_name.clone(),
|
||||
vec![input_model._type.clone()],
|
||||
input_expression,
|
||||
)?;
|
||||
if let Input::FunctionInput(input_model) = input_model {
|
||||
// First evaluate input expression
|
||||
let mut input_value = self.enforce_input(
|
||||
cs,
|
||||
scope.clone(),
|
||||
caller_scope.clone(),
|
||||
function_name.clone(),
|
||||
vec![input_model.type_.clone()],
|
||||
input_expression,
|
||||
)?;
|
||||
|
||||
if input_model.mutable {
|
||||
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
||||
if input_model.mutable {
|
||||
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
||||
}
|
||||
|
||||
// Store input as variable with {function_name}_{input_name}
|
||||
let input_program_identifier = new_scope(function_name.clone(), input_model.identifier.name.clone());
|
||||
self.store(input_program_identifier, input_value);
|
||||
} else {
|
||||
println!("function input model {}", input_model);
|
||||
println!("function input option {}", input_expression)
|
||||
}
|
||||
|
||||
// Store input as variable with {function_name}_{input_name}
|
||||
let input_program_identifier = new_scope(function_name.clone(), input_model.identifier.name.clone());
|
||||
self.store(input_program_identifier, input_value);
|
||||
}
|
||||
|
||||
// Evaluate every statement in the function and save all potential results
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
GroupType,
|
||||
};
|
||||
|
||||
use leo_types::{Expression, Function, InputValue};
|
||||
use leo_types::{Expression, Function, Input, InputValue};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
@ -31,19 +31,24 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
// Iterate over main function inputs and allocate new passed-by variable values
|
||||
let mut input_variables = vec![];
|
||||
for (input_model, input_option) in function.inputs.clone().into_iter().zip(inputs.into_iter()) {
|
||||
let input_value = self.allocate_main_function_input(
|
||||
cs,
|
||||
input_model._type,
|
||||
input_model.identifier.name.clone(),
|
||||
input_option,
|
||||
function.span.clone(),
|
||||
)?;
|
||||
if let Input::FunctionInput(input_model) = input_model {
|
||||
let input_value = self.allocate_main_function_input(
|
||||
cs,
|
||||
input_model.type_,
|
||||
input_model.identifier.name.clone(),
|
||||
input_option,
|
||||
function.span.clone(),
|
||||
)?;
|
||||
|
||||
// Store a new variable for every allocated main function input
|
||||
let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone());
|
||||
self.store(input_name.clone(), input_value);
|
||||
// Store a new variable for every allocated main function input
|
||||
let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone());
|
||||
self.store(input_name.clone(), input_value);
|
||||
|
||||
input_variables.push(Expression::Identifier(input_model.identifier));
|
||||
input_variables.push(Expression::Identifier(input_model.identifier));
|
||||
} else {
|
||||
println!("main function input model {}", input_model);
|
||||
// println!("main function input option {}", input_option.to_)
|
||||
}
|
||||
}
|
||||
|
||||
self.enforce_function(cs, scope, function_name, function, input_variables)
|
||||
|
@ -1,2 +0,0 @@
|
||||
pub mod assignment;
|
||||
pub use assignment::*;
|
@ -4,8 +4,8 @@ use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::assignment))]
|
||||
pub struct Assignment<'ast> {
|
||||
#[pest_ast(rule(Rule::definition))]
|
||||
pub struct Definition<'ast> {
|
||||
pub parameter: Parameter<'ast>,
|
||||
pub expression: Expression<'ast>,
|
||||
pub line_end: LineEnd,
|
2
leo-inputs/src/definitions/mod.rs
Normal file
2
leo-inputs/src/definitions/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod definition;
|
||||
pub use definition::*;
|
@ -6,6 +6,7 @@ use crate::{
|
||||
values::{NumberImplicitValue, NumberValue, Value},
|
||||
};
|
||||
|
||||
use crate::sections::Header;
|
||||
use pest::{
|
||||
error::{Error, ErrorVariant},
|
||||
Span,
|
||||
@ -81,6 +82,27 @@ impl InputParserError {
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn input_section_header(header: Header) -> Self {
|
||||
let message = format!("the section header {} does not belong in an input `.in` file", header);
|
||||
let span = header.span();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn public_section(header: Header) -> Self {
|
||||
let message = format!("the section header {} is not a public section", header);
|
||||
let span = header.span();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn private_section(header: Header) -> Self {
|
||||
let message = format!("the section header {} is not a private section", header);
|
||||
let span = header.span();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error<Rule>> for InputParserError {
|
||||
|
@ -15,7 +15,7 @@ impl From<Error<Rule>> for SyntaxError {
|
||||
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::file => "a table or section".to_owned(),
|
||||
Rule::identifier => "a variable name".to_owned(),
|
||||
Rule::type_ => "a type".to_owned(),
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{ast::Rule, common::EOI, sections::Section, tables::Table};
|
||||
use crate::{ast::Rule, common::EOI, files::TableOrSection};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -6,8 +6,7 @@ use pest_ast::FromPest;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::file))]
|
||||
pub struct File<'ast> {
|
||||
pub tables: Vec<Table<'ast>>,
|
||||
pub sections: Vec<Section<'ast>>,
|
||||
pub entries: Vec<TableOrSection<'ast>>,
|
||||
pub eoi: EOI,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -1,2 +1,5 @@
|
||||
pub mod file;
|
||||
pub use file::*;
|
||||
|
||||
pub mod table_or_section;
|
||||
pub use table_or_section::*;
|
||||
|
10
leo-inputs/src/files/table_or_section.rs
Normal file
10
leo-inputs/src/files/table_or_section.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use crate::{ast::Rule, sections::Section, tables::Table};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::table_or_section))]
|
||||
pub enum TableOrSection<'ast> {
|
||||
Section(Section<'ast>),
|
||||
Table(Table<'ast>),
|
||||
}
|
@ -14,15 +14,15 @@ protected_name = {
|
||||
| "import"
|
||||
| "in"
|
||||
| "let"
|
||||
| "main"
|
||||
| main
|
||||
| "mut"
|
||||
| "private"
|
||||
| "public"
|
||||
| "record"
|
||||
| "registers"
|
||||
| private
|
||||
| public
|
||||
| record
|
||||
| registers
|
||||
| "return"
|
||||
| "state"
|
||||
| "state_leaf"
|
||||
| state
|
||||
| state_leaf
|
||||
| "static"
|
||||
| "test"
|
||||
| "true"
|
||||
@ -145,7 +145,7 @@ parameter = { identifier ~ ":" ~ type_ }
|
||||
/// Section
|
||||
|
||||
// Declared in sections/section.rs
|
||||
section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* }
|
||||
section = { "[" ~ header ~ "]" ~ NEWLINE+ ~ (definition ~ NEWLINE*)* }
|
||||
|
||||
// Declared in sections/main_.rs
|
||||
main = { "main" }
|
||||
@ -163,12 +163,12 @@ state = { "state" }
|
||||
state_leaf = { "state_leaf" }
|
||||
|
||||
// Declared in sections/header.rs
|
||||
header = { "[" ~ main | record | registers | state | state_leaf | identifier ~ "]" }
|
||||
header = { main | record | registers | state_leaf | state | identifier }
|
||||
|
||||
/// Assignments
|
||||
/// Definitions
|
||||
|
||||
// Declared in assignment/assignment.rs
|
||||
assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END }
|
||||
// Declared in definition/definition.rs
|
||||
definition = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END }
|
||||
|
||||
/// Table
|
||||
|
||||
@ -191,5 +191,8 @@ WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* }
|
||||
|
||||
/// Files
|
||||
|
||||
// Declared in files/table_or_section.rs
|
||||
table_or_section = { table | section }
|
||||
|
||||
// Declared in files/file.rs
|
||||
file = { SOI ~ NEWLINE* ~ table* ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI }
|
||||
file = { SOI ~ NEWLINE* ~ table_or_section* ~ NEWLINE* ~ EOI }
|
||||
|
@ -6,9 +6,9 @@ extern crate thiserror;
|
||||
pub mod errors;
|
||||
pub use errors::*;
|
||||
|
||||
pub mod assignments;
|
||||
mod ast;
|
||||
pub mod common;
|
||||
pub mod definitions;
|
||||
pub mod expressions;
|
||||
pub mod files;
|
||||
pub mod parameters;
|
||||
@ -30,7 +30,7 @@ impl LeoInputsParser {
|
||||
|
||||
/// Parses the input file and constructs a syntax tree.
|
||||
pub fn parse_file(input_file: &str) -> Result<files::File, InputParserError> {
|
||||
// Parse the file using leo.pest
|
||||
// Parse the file using leo-inputs.pest
|
||||
let mut file = ast::parse(input_file)?;
|
||||
|
||||
// Build the abstract syntax tree
|
||||
|
@ -4,7 +4,9 @@ use crate::{
|
||||
sections::{Main, Record, Registers, State, StateLeaf},
|
||||
};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::header))]
|
||||
@ -16,3 +18,29 @@ pub enum Header<'ast> {
|
||||
StateLeaf(StateLeaf<'ast>),
|
||||
Identifier(Identifier<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> Header<'ast> {
|
||||
pub fn span(self) -> Span<'ast> {
|
||||
match self {
|
||||
Header::Main(main) => main.span,
|
||||
Header::Record(record) => record.span,
|
||||
Header::Registers(registers) => registers.span,
|
||||
Header::State(state) => state.span,
|
||||
Header::StateLeaf(state_leaf) => state_leaf.span,
|
||||
Header::Identifier(identifier) => identifier.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Header<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Header::Main(_main) => write!(f, "main"),
|
||||
Header::Record(_record) => write!(f, "record"),
|
||||
Header::Registers(_registers) => write!(f, "registers"),
|
||||
Header::State(_state) => write!(f, "state"),
|
||||
Header::StateLeaf(_state_leaf) => write!(f, "state_leaf"),
|
||||
Header::Identifier(identifier) => write!(f, "{}", identifier.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{assignments::Assignment, ast::Rule, sections::Header};
|
||||
use crate::{ast::Rule, definitions::Definition, sections::Header};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -7,7 +7,7 @@ use pest_ast::FromPest;
|
||||
#[pest_ast(rule(Rule::section))]
|
||||
pub struct Section<'ast> {
|
||||
pub header: Header<'ast>,
|
||||
pub assignments: Vec<Assignment<'ast>>,
|
||||
pub definitions: Vec<Definition<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{FunctionInput, Identifier, Span, Statement, Type};
|
||||
use crate::{Identifier, Input, Span, Statement, Type};
|
||||
use leo_ast::functions::Function as AstFunction;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -7,7 +7,7 @@ use std::fmt;
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Function {
|
||||
pub function_name: Identifier,
|
||||
pub inputs: Vec<FunctionInput>,
|
||||
pub inputs: Vec<Input>,
|
||||
pub returns: Vec<Type>,
|
||||
pub statements: Vec<Statement>,
|
||||
pub span: Span,
|
||||
@ -19,7 +19,7 @@ impl<'ast> From<AstFunction<'ast>> for Function {
|
||||
let parameters = function_definition
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|parameter| FunctionInput::from(parameter))
|
||||
.map(|parameter| Input::from(parameter))
|
||||
.collect();
|
||||
let returns = function_definition
|
||||
.returns
|
||||
|
@ -8,7 +8,7 @@ use std::fmt;
|
||||
pub struct FunctionInput {
|
||||
pub identifier: Identifier,
|
||||
pub mutable: bool,
|
||||
pub _type: Type,
|
||||
pub type_: Type,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ impl<'ast> From<AstFunctionInput<'ast>> for FunctionInput {
|
||||
FunctionInput {
|
||||
identifier: Identifier::from(parameter.identifier),
|
||||
mutable: parameter.mutable.is_some(),
|
||||
_type: Type::from(parameter._type),
|
||||
type_: Type::from(parameter._type),
|
||||
span: Span::from(parameter.span),
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ impl FunctionInput {
|
||||
write!(f, "mut ")?;
|
||||
}
|
||||
write!(f, "{}: ", self.identifier)?;
|
||||
write!(f, "{}", self._type)
|
||||
write!(f, "{}", self.type_)
|
||||
}
|
||||
}
|
||||
|
50
types/src/functions/inputs/input.rs
Normal file
50
types/src/functions/inputs/input.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::FunctionInput;
|
||||
use leo_ast::functions::inputs::Input as AstInput;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Input {
|
||||
FunctionInput(FunctionInput),
|
||||
Record,
|
||||
Registers,
|
||||
State,
|
||||
StateLeaf,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstInput<'ast>> for Input {
|
||||
fn from(input: AstInput<'ast>) -> Self {
|
||||
match input {
|
||||
AstInput::FunctionInput(function_input) => Input::FunctionInput(FunctionInput::from(function_input)),
|
||||
AstInput::Record(_) => Input::Record,
|
||||
AstInput::Registers(_) => Input::Registers,
|
||||
AstInput::State(_) => Input::State,
|
||||
AstInput::StateLeaf(_) => Input::StateLeaf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Input {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Input::FunctionInput(function_input) => write!(f, "{}", function_input),
|
||||
Input::Record => write!(f, "record"),
|
||||
Input::Registers => write!(f, "registers"),
|
||||
Input::State => write!(f, "state"),
|
||||
Input::StateLeaf => write!(f, "state_leaf"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Input {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Input {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
5
types/src/functions/inputs/mod.rs
Normal file
5
types/src/functions/inputs/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod function_input;
|
||||
pub use function_input::*;
|
||||
|
||||
pub mod input;
|
||||
pub use input::*;
|
@ -1,8 +1,8 @@
|
||||
pub mod function;
|
||||
pub use function::*;
|
||||
|
||||
pub mod function_input;
|
||||
pub use function_input::*;
|
||||
pub mod inputs;
|
||||
pub use inputs::*;
|
||||
|
||||
pub mod test_function;
|
||||
pub use test_function::*;
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::{FunctionInput, InputValue, ProgramInputs, ProgramState};
|
||||
use leo_inputs::{files::File, sections::header::Header, InputParserError};
|
||||
use crate::{Input, InputValue, ProgramInputs, ProgramState};
|
||||
use leo_inputs::{
|
||||
files::{File, TableOrSection},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Inputs {
|
||||
program_inputs: Vec<Option<InputValue>>,
|
||||
inputs: ProgramInputs,
|
||||
state: ProgramState,
|
||||
}
|
||||
@ -11,59 +13,39 @@ pub struct Inputs {
|
||||
impl Inputs {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
program_inputs: vec![],
|
||||
inputs: ProgramInputs::new(),
|
||||
state: ProgramState::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inputs(&self) -> Vec<Option<InputValue>> {
|
||||
self.program_inputs.clone()
|
||||
self.inputs.main.0.clone()
|
||||
}
|
||||
|
||||
pub fn set_inputs(&mut self, inputs: Vec<Option<InputValue>>) {
|
||||
self.program_inputs = inputs;
|
||||
self.inputs.main.0 = inputs;
|
||||
}
|
||||
|
||||
pub fn set_inputs_size(&mut self, size: usize) {
|
||||
self.program_inputs = vec![None; size];
|
||||
self.inputs.main.0 = vec![None; size];
|
||||
}
|
||||
|
||||
pub fn from_inputs_file(file: File, expected_inputs: Vec<FunctionInput>) -> Result<Self, InputParserError> {
|
||||
let mut program_inputs = vec![];
|
||||
|
||||
for section in file.sections.into_iter() {
|
||||
match section.header {
|
||||
Header::Main(_main) => {
|
||||
for input in &expected_inputs {
|
||||
// find input with matching name
|
||||
let matched_input = section.assignments.clone().into_iter().find(|assignment| {
|
||||
// name match
|
||||
assignment.parameter.variable.value.eq(&input.identifier.name)
|
||||
// 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)?;
|
||||
|
||||
// push value to vector
|
||||
program_inputs.push(Some(value));
|
||||
}
|
||||
None => return Err(InputParserError::InputNotFound(input.to_string())),
|
||||
}
|
||||
}
|
||||
pub fn parse_program_input_file(
|
||||
&mut self,
|
||||
file: File,
|
||||
expected_inputs: Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
for entry in file.entries.into_iter() {
|
||||
match entry {
|
||||
TableOrSection::Section(section) => {
|
||||
self.inputs.store_definitions(section, &expected_inputs)?;
|
||||
}
|
||||
TableOrSection::Table(table) => {
|
||||
self.state.store_definitions(table, &expected_inputs)?;
|
||||
}
|
||||
_ => unimplemented!("section not impl"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
program_inputs,
|
||||
inputs: ProgramInputs::new(),
|
||||
state: ProgramState::new(),
|
||||
})
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,50 @@
|
||||
use crate::InputValue;
|
||||
use crate::{Input, InputValue};
|
||||
use leo_inputs::{definitions::Definition, InputParserError};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct MainInputs(Vec<Option<InputValue>>);
|
||||
pub struct MainInputs(pub Vec<Option<InputValue>>);
|
||||
|
||||
impl MainInputs {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// Stores main input assignments that match expected main function inputs
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
definitions: Vec<Definition>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
let mut program_inputs = vec![];
|
||||
|
||||
for definition in definitions {
|
||||
// find input with matching name
|
||||
let matched_input = expected_inputs.clone().into_iter().find(|input| {
|
||||
// only look at program inputs
|
||||
match input {
|
||||
Input::FunctionInput(function_input) => {
|
||||
// name match
|
||||
function_input.identifier.name.eq(&definition.parameter.variable.value)
|
||||
// type match
|
||||
&& function_input.type_.to_string().eq(&definition.parameter.type_.to_string())
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
match matched_input {
|
||||
Some(_) => {
|
||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||
|
||||
// push value to main inputs
|
||||
program_inputs.push(Some(value));
|
||||
}
|
||||
None => return Err(InputParserError::InputNotFound(definition.parameter.variable.value)),
|
||||
}
|
||||
}
|
||||
|
||||
self.0 = program_inputs;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::{MainInputs, Registers};
|
||||
use crate::{Input, MainInputs, Registers};
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct ProgramInputs {
|
||||
main: MainInputs,
|
||||
registers: Registers,
|
||||
pub main: MainInputs,
|
||||
pub registers: Registers,
|
||||
}
|
||||
|
||||
impl ProgramInputs {
|
||||
@ -13,4 +17,16 @@ impl ProgramInputs {
|
||||
registers: Registers::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
section: Section,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
match section.header {
|
||||
Header::Main(_main) => self.main.store_definitions(section.definitions, &expected_inputs),
|
||||
Header::Registers(_registers) => self.registers.store_definitions(section.definitions, &expected_inputs),
|
||||
header => Err(InputParserError::input_section_header(header)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::InputValue;
|
||||
use crate::{Input, InputValue};
|
||||
use leo_inputs::{definitions::Definition, InputParserError};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Registers(Vec<Option<InputValue>>);
|
||||
@ -7,4 +8,31 @@ impl Registers {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// Stores register input definitions if the main function input contains the `registers` variable.
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
definitions: Vec<Definition>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
// if the main function does not contain the `registers` variable
|
||||
// then do not parse registers
|
||||
if !expected_inputs.contains(&Input::Registers) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut register_inputs = vec![];
|
||||
|
||||
// store all registers
|
||||
for definition in definitions {
|
||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||
|
||||
// push value to register inputs
|
||||
register_inputs.push(Some(value));
|
||||
}
|
||||
|
||||
self.0 = register_inputs;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
use crate::{Record, StateLeaf};
|
||||
use crate::{Input, Record, StateLeaf};
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct PrivateState {
|
||||
@ -13,4 +17,22 @@ impl PrivateState {
|
||||
state_leaf: StateLeaf::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
sections: Vec<Section>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
for section in sections {
|
||||
match section.header {
|
||||
Header::Record(_state) => self.record.store_definitions(section.definitions, expected_inputs)?,
|
||||
Header::StateLeaf(_state_leaf) => self
|
||||
.state_leaf
|
||||
.store_definitions(section.definitions, expected_inputs)?,
|
||||
header => return Err(InputParserError::private_section(header)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::InputValue;
|
||||
use crate::{Input, InputValue};
|
||||
use leo_inputs::{definitions::Definition, InputParserError};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Record(Vec<Option<InputValue>>);
|
||||
@ -7,4 +8,31 @@ impl Record {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// Stores record input definitions if the main function input contains the `record` variable.
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
definitions: Vec<Definition>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
// if the main function does not contain the `record` variable
|
||||
// then do not parse record definitions
|
||||
if !expected_inputs.contains(&Input::Record) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut record_inputs = vec![];
|
||||
|
||||
// store all definitions
|
||||
for definition in definitions {
|
||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||
|
||||
// push value to register inputs
|
||||
record_inputs.push(Some(value));
|
||||
}
|
||||
|
||||
self.0 = record_inputs;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::InputValue;
|
||||
use crate::{Input, InputValue};
|
||||
use leo_inputs::{definitions::Definition, InputParserError};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct StateLeaf(Vec<Option<InputValue>>);
|
||||
@ -7,4 +8,31 @@ impl StateLeaf {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// Stores state_leaf input definitions if the main function input contains the `state_leaf` variable.
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
definitions: Vec<Definition>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
// if the main function does not contain the `state_leaf` variable
|
||||
// then do not parse state_leaf definitions
|
||||
if !expected_inputs.contains(&Input::StateLeaf) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut state_leaf_inputs = vec![];
|
||||
|
||||
// store all definitions
|
||||
for definition in definitions {
|
||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||
|
||||
// push value to register inputs
|
||||
state_leaf_inputs.push(Some(value));
|
||||
}
|
||||
|
||||
self.0 = state_leaf_inputs;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::{PrivateState, PublicState};
|
||||
use crate::{Input, PrivateState, PublicState};
|
||||
use leo_inputs::{
|
||||
tables::{Table, Visibility},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct ProgramState {
|
||||
public: PublicState,
|
||||
private: PrivateState,
|
||||
pub public: PublicState,
|
||||
pub private: PrivateState,
|
||||
}
|
||||
|
||||
impl ProgramState {
|
||||
@ -13,4 +17,11 @@ impl ProgramState {
|
||||
private: PrivateState::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_definitions(&mut self, table: Table, expected_inputs: &Vec<Input>) -> Result<(), InputParserError> {
|
||||
match table.visibility {
|
||||
Visibility::Private(_private) => self.private.store_definitions(table.sections, &expected_inputs),
|
||||
Visibility::Public(_public) => self.public.store_definitions(table.sections, &expected_inputs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
use crate::State;
|
||||
use crate::{Input, State};
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct PublicState {
|
||||
@ -9,4 +13,19 @@ impl PublicState {
|
||||
pub fn new() -> Self {
|
||||
Self { state: State::new() }
|
||||
}
|
||||
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
sections: Vec<Section>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
for section in sections {
|
||||
match section.header {
|
||||
Header::State(_state) => self.state.store_definitions(section.definitions, expected_inputs)?,
|
||||
header => return Err(InputParserError::public_section(header)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::InputValue;
|
||||
use crate::{Input, InputValue};
|
||||
use leo_inputs::{definitions::Definition, InputParserError};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct State(Vec<Option<InputValue>>);
|
||||
@ -7,4 +8,31 @@ impl State {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// Stores state input definitions if the main function input contains the `state` variable.
|
||||
pub fn store_definitions(
|
||||
&mut self,
|
||||
definitions: Vec<Definition>,
|
||||
expected_inputs: &Vec<Input>,
|
||||
) -> Result<(), InputParserError> {
|
||||
// if the main function does not contain the `state` variable
|
||||
// then do not parse state definitions
|
||||
if !expected_inputs.contains(&Input::State) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut state_inputs = vec![];
|
||||
|
||||
// store all registers
|
||||
for definition in definitions {
|
||||
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
|
||||
|
||||
// push value to register inputs
|
||||
state_inputs.push(Some(value));
|
||||
}
|
||||
|
||||
self.0 = state_inputs;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -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, FunctionInput, Identifier, Import, TestFunction};
|
||||
use crate::{Circuit, Function, Identifier, Import, Input, TestFunction};
|
||||
use leo_ast::files::File;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -11,13 +11,15 @@ use std::collections::HashMap;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Program {
|
||||
pub name: String,
|
||||
pub expected_inputs: Vec<FunctionInput>,
|
||||
pub expected_inputs: Vec<Input>,
|
||||
pub imports: Vec<Import>,
|
||||
pub circuits: HashMap<Identifier, Circuit>,
|
||||
pub functions: HashMap<Identifier, Function>,
|
||||
pub tests: HashMap<Identifier, TestFunction>,
|
||||
}
|
||||
|
||||
const MAIN_FUNCTION_NAME: &str = "main";
|
||||
|
||||
impl<'ast> Program {
|
||||
//! Logic to convert from an abstract syntax tree (ast) representation to a Leo program.
|
||||
pub fn from(file: File<'ast>, name: String) -> Self {
|
||||
@ -38,7 +40,7 @@ impl<'ast> Program {
|
||||
});
|
||||
file.functions.into_iter().for_each(|function_def| {
|
||||
let function = Function::from(function_def);
|
||||
if function.function_name.name.eq("main") {
|
||||
if function.function_name.name.eq(MAIN_FUNCTION_NAME) {
|
||||
expected_inputs = function.inputs.clone();
|
||||
}
|
||||
functions.insert(function.function_name.clone(), function);
|
||||
|
Loading…
Reference in New Issue
Block a user