parse main, record, registers, state, state_leaf types to compiler input

This commit is contained in:
collin 2020-07-28 16:57:03 -07:00
parent b9b459ecff
commit 9fc9e16367
41 changed files with 560 additions and 125 deletions

View File

@ -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())]

View 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>),
}

View 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::*;

View 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>,
}

View 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>,
}

View 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>,
}

View 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>,
}

View File

@ -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::*;

View File

@ -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 }

View File

@ -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(())
}

View File

@ -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

View File

@ -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)

View File

@ -1,2 +0,0 @@
pub mod assignment;
pub use assignment::*;

View File

@ -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,

View File

@ -0,0 +1,2 @@
pub mod definition;
pub use definition::*;

View File

@ -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 {

View File

@ -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(),

View File

@ -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>,

View File

@ -1,2 +1,5 @@
pub mod file;
pub use file::*;
pub mod table_or_section;
pub use table_or_section::*;

View 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>),
}

View File

@ -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 }

View File

@ -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

View File

@ -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),
}
}
}

View File

@ -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>,
}

View File

@ -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

View File

@ -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_)
}
}

View 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)
}
}

View File

@ -0,0 +1,5 @@
pub mod function_input;
pub use function_input::*;
pub mod input;
pub use input::*;

View File

@ -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::*;

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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)),
}
}
}

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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),
}
}
}

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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);