Add documentation for renamed modules

This commit is contained in:
collin 2020-10-30 16:23:18 -07:00
parent 5a46cb5bb0
commit 61f4189483
11 changed files with 127 additions and 68 deletions

View File

@ -14,6 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! The pest abstract syntax tree (ast) for a Leo program.
//!
//! This module contains the [`LeoAst`] type, a wrapper around the [`File`] type.
//! The [`LeoAst`] type is the datatype generated by the pest parser using grammar from `leo.pest`.
//! The [`LeoAst`] type is intended to be parsed into a [`LeoCoreAst`]. It should not be parsed by
//! any other pass of the compiler.
#[macro_use]
extern crate lazy_static;
#[macro_use]
@ -47,6 +54,12 @@ pub(crate) use span::*;
use from_pest::FromPest;
use std::{fs, path::Path};
/// The pest abstract syntax tree (ast) for a Leo program.
///
/// The [`LeoAst`] type represents a Leo program as a series of recursive data types.
/// These data types form a tree that begins from a [`File`] type root.
///
/// A new [`LeoAst`] can be created from a `*.leo` file at a [`Path`].
pub struct LeoAst<'ast> {
ast: files::File<'ast>,
}

View File

@ -46,6 +46,7 @@ use std::{
path::{Path, PathBuf},
};
/// Stores information to compile a Leo program.
#[derive(Clone)]
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
package_name: String,
@ -76,9 +77,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Parses program files.
/// Returns a new `Compiler` from the given main file path.
///
/// Returns a compiler struct that stores the typed program abstract syntax trees (ast).
/// Parses and stores a program from the main file path.
/// Parses and stores all imported programs.
/// Performs type inference checking on the program and imported programs.
///
pub fn parse_program_without_input(
package_name: String,
@ -93,9 +96,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Parses input, state, and program files.
/// Returns a new `Compiler` from the given main file path.
///
/// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast).
/// Parses and stores program input from from the input file path and state file path
/// Parses and stores a program from the main file path.
/// Parses and stores all imported programs.
/// Performs type inference checking on the program, imported programs, and program input.
///
pub fn parse_program_with_input(
package_name: String,
@ -116,9 +122,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Parse the input and state files.
/// Parses and stores program input from from the input file path and state file path
///
/// Stores a typed ast of all input variables to the program.
/// Calls `set_path()` on compiler errors with the given input file path or state file path
///
pub fn parse_input(
&mut self,
@ -153,7 +159,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Runs program parser and program checker consecutively.
/// Runs program parser and type inference checker consecutively.
///
pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> {
self.parse_program()?;
@ -162,23 +168,28 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Parses the Leo program file, constructs a syntax tree, and generates a program.
/// Parses and stores the main program file, constructs a syntax tree, and generates a program.
///
/// Parses and stores all programs imported by the main program file.
///
pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> {
// Load the program file.
let program_string = LeoAst::load_file(&self.main_file_path)?;
// Use the parser to construct the abstract syntax tree.
let ast = LeoAst::new(&self.main_file_path, &program_string).map_err(|mut e| {
// Use the parser to construct the pest abstract syntax tree (ast).
let pest_ast = LeoAst::new(&self.main_file_path, &program_string).map_err(|mut e| {
e.set_path(&self.main_file_path);
e
})?;
// Use the typed parser to construct the typed syntax tree.
let typed_tree = LeoCoreAst::new(&self.package_name, &ast);
// Construct the core ast from the pest ast.
let core_ast = LeoCoreAst::new(&self.package_name, &pest_ast);
self.program = typed_tree.into_repr();
// Store the main program file.
self.program = core_ast.into_repr();
// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?;
tracing::debug!("Program parsing complete\n{:#?}", self.program);
@ -215,7 +226,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Parses the Leo program string, constructs a syntax tree, and generates a program.
/// Equivalent to parse_and_check_program but uses the given program_string instead of a main
/// file path.
///
/// Used for testing only.
///
#[deprecated(note = "Please use the 'parse_program' method instead.")]
@ -230,10 +243,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
// Derive the package name.
let package_name = &self.package_name;
// Use the typed parser to construct the typed syntax tree.
let typed_tree = LeoCoreAst::new(package_name, &ast);
// Construct the core ast from the pest ast.
let core_ast = LeoCoreAst::new(package_name, &ast);
self.program = typed_tree.into_repr();
// Store the main program file.
self.program = core_ast.into_repr();
// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?;
// Create a new symbol table from the program, imported programs, and program input.
@ -248,14 +264,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
///
/// Manually sets main function input
/// Manually sets main function input.
///
/// Used for testing only.
///
pub fn set_main_input(&mut self, input: MainInput) {
self.program_input.set_main_input(input);
}
///
/// Verifies the input to the program
/// Verifies the input to the program.
///
pub fn verify_local_data_commitment(
&self,
@ -297,7 +315,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
)
}
///
/// Synthesizes the circuit for test functions with program input.
///
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
generate_test_constraints::<F, G>(
self.program,
@ -308,7 +328,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
)
}
/// Calls the internal generate_constraints method with arguments
///
/// Calls the internal generate_constraints method with arguments.
///
pub fn generate_constraints_helper<CS: ConstraintSystem<F>>(
self,
cs: &mut CS,
@ -324,7 +346,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
///
/// Synthesizes the circuit with program input.
///
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
let output_directory = self.output_directory.clone();
let package_name = self.package_name.clone();

View File

@ -14,8 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! A typed syntax tree is represented as a `Program` and consists of import, circuit, and function definitions.
//! Each defined type consists of typed statements and expressions.
//! The core abstract syntax tree (ast) for a Leo program.
//!
//! This module contains the [`LeoCoreAst`] type, a wrapper around the [`Program`] type.
//! The [`LeoCoreAst`] type is intended to be parsed and modified by different passes
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`LeoCoreAst`].
pub mod annotation;
pub use self::annotation::*;
@ -58,32 +61,38 @@ pub use self::types::*;
use leo_ast::LeoAst;
/// The core abstract syntax tree (ast) for a Leo program.
///
/// The [`LeoCoreAst`] type represents a Leo program as a series of recursive data types.
/// These data types form a tree that begins from a [`Program`] type root.
///
/// A new [`LeoCoreAst`] can be created from a [`LeoAst`] generated by the pest parser in the `ast` module.
#[derive(Debug, Eq, PartialEq)]
pub struct LeoCoreAst {
typed_ast: Program,
core_ast: Program,
}
impl LeoCoreAst {
/// Creates a new core syntax tree from a given program name and abstract syntax tree.
pub fn new<'ast>(program_name: &str, ast: &LeoAst<'ast>) -> Self {
Self {
typed_ast: Program::from(program_name, ast.as_repr()),
core_ast: Program::from(program_name, ast.as_repr()),
}
}
/// Returns a reference to the inner program syntax tree representation.
pub fn into_repr(self) -> Program {
self.typed_ast
self.core_ast
}
/// Serializes the core syntax tree into a JSON string.
pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
Ok(serde_json::to_string_pretty(&self.typed_ast)?)
Ok(serde_json::to_string_pretty(&self.core_ast)?)
}
/// Deserializes the JSON string into a core syntax tree.
pub fn from_json_string(json: &str) -> Result<Self, serde_json::Error> {
let typed_ast: Program = serde_json::from_str(json)?;
Ok(Self { typed_ast })
Ok(Self { core_ast: typed_ast })
}
}

View File

@ -23,16 +23,16 @@ fn to_leo_core_tree(filepath: &Path) -> Result<String, ParserError> {
let program_filepath = filepath.to_path_buf();
let program_string = LeoAst::load_file(&program_filepath)?;
// Parses the Leo file and constructs an abstract syntax tree.
// Parses the Leo file and constructs a pest ast.
let ast = LeoAst::new(&program_filepath, &program_string)?;
// Parse the abstract core tree and constructs a typed core tree.
let typed_ast = LeoCoreAst::new("leo_core_tree", &ast);
// Parse the pest ast and constructs a core ast.
let core_ast = LeoCoreAst::new("leo_core_tree", &ast);
// Serializes the typed core tree into JSON format.
let serialized_typed_tree = LeoCoreAst::to_json_string(&typed_ast)?;
// Serializes the core tree into JSON format.
let serialized_core_ast = LeoCoreAst::to_json_string(&core_ast)?;
Ok(serialized_typed_tree)
Ok(serialized_core_ast)
}
fn main() -> Result<(), ParserError> {

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! A typed Leo program consists of import, circuit, and function definitions.
//! A Leo program consists of import, circuit, and function definitions.
//! Each defined type consists of typed statements and expressions.
use crate::{load_annotation, Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction};

View File

@ -21,74 +21,74 @@ use leo_core_ast::Program;
use std::path::{Path, PathBuf};
fn to_typed_ast(program_filepath: &Path) -> LeoCoreAst {
fn to_core_ast(program_filepath: &Path) -> LeoCoreAst {
// Loads the Leo code as a string from the given file path.
let program_string = LeoAst::load_file(program_filepath).unwrap();
// Parses the Leo file and constructs an abstract syntax tree.
// Parses the Leo file and constructs a pest ast.
let ast = LeoAst::new(&program_filepath, &program_string).unwrap();
// Parse the abstract syntax tree and constructs a typed syntax tree.
// Parses the pest ast and constructs a core ast.
LeoCoreAst::new("leo_core_tree", &ast)
}
#[test]
#[cfg(not(feature = "ci_skip"))]
fn test_serialize() {
// Construct a typed syntax tree from the given test file.
let typed_ast = {
// Construct a core ast from the given test file.
let core_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
to_typed_ast(&program_filepath)
to_core_ast(&program_filepath)
};
// Serializes the typed syntax tree into JSON format.
let serialized_typed_ast: Program =
serde_json::from_value(serde_json::to_value(typed_ast.into_repr()).unwrap()).unwrap();
// Serializes the core ast into JSON format.
let serialized_core_ast: Program =
serde_json::from_value(serde_json::to_value(core_ast.into_repr()).unwrap()).unwrap();
// Load the expected typed syntax tree.
let expected: Program = serde_json::from_str(include_str!("expected_typed_ast.json")).unwrap();
// Load the expected core ast.
let expected: Program = serde_json::from_str(include_str!("expected_core_ast.json")).unwrap();
assert_eq!(expected, serialized_typed_ast);
assert_eq!(expected, serialized_core_ast);
}
#[test]
#[cfg(not(feature = "ci_skip"))]
fn test_deserialize() {
// Load the expected typed syntax tree.
let expected_typed_ast = {
// Load the expected core ast.
let expected_core_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
to_typed_ast(&program_filepath)
to_core_ast(&program_filepath)
};
// Construct a typed syntax tree by deserializing a typed syntax tree JSON file.
let serialized_typed_ast = include_str!("expected_typed_ast.json");
let typed_ast = LeoCoreAst::from_json_string(serialized_typed_ast).unwrap();
// Construct a core ast by deserializing a core ast JSON file.
let serialized_typed_ast = include_str!("expected_core_ast.json");
let core_ast = LeoCoreAst::from_json_string(serialized_typed_ast).unwrap();
assert_eq!(expected_typed_ast, typed_ast);
assert_eq!(expected_core_ast, core_ast);
}
#[test]
fn test_serialize_deserialize_serialize() {
// Construct a typed syntax tree from the given test file.
let typed_ast = {
// Construct a core ast from the given test file.
let core_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
to_typed_ast(&program_filepath)
to_core_ast(&program_filepath)
};
// Serializes the typed syntax tree into JSON format.
let serialized_typed_ast = typed_ast.to_json_string().unwrap();
// Serializes the core ast into JSON format.
let serialized_core_ast = core_ast.to_json_string().unwrap();
// Deserializes the typed syntax tree into a LeoTypedAst.
let typed_ast = LeoCoreAst::from_json_string(&serialized_typed_ast).unwrap();
// Deserializes the serialized core ast into a LeoCoreAst.
let core_ast = LeoCoreAst::from_json_string(&serialized_core_ast).unwrap();
// Reserializes the typed syntax tree into JSON format.
let reserialized_typed_ast = typed_ast.to_json_string().unwrap();
// Reserializes the core ast into JSON format.
let reserialized_core_ast = core_ast.to_json_string().unwrap();
assert_eq!(serialized_typed_ast, reserialized_typed_ast);
assert_eq!(serialized_core_ast, reserialized_core_ast);
}

View File

@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! The symbol table for a Leo program.
//!
//! This module contains the [`SymbolTable`] type, an abstract data type that tracks the current
//! bindings for functions and circuits in a Leo program.
#[macro_use]
extern crate thiserror;

View File

@ -27,12 +27,11 @@ pub const REGISTERS_VARIABLE_NAME: &str = "registers";
pub const STATE_VARIABLE_NAME: &str = "state";
pub const STATE_LEAF_VARIABLE_NAME: &str = "state_leaf";
/// A abstract data type that tracks the current bindings for functions and circuits.
/// The symbol table for a Leo program.
///
/// A symbol table has access to all function and circuit names in its
/// parent's symbol table.
/// A symbol table has access to all function and circuit names in its parent's symbol table.
/// A symbol table cannot access names in its child's symbol table.
/// Children cannot access names in another sibling's symbol table.
/// A child symbol table cannot access names in another sibling's symbol table.
#[derive(Clone, Default)]
pub struct SymbolTable {
/// Maps name -> parameter type.

View File

@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! A type inference check for a Leo program.
//!
//! This module contains the [`TypeInference`] type, which stores information needed to run a type
//! inference check over a program.
#[macro_use]
extern crate thiserror;

View File

@ -18,7 +18,11 @@ use crate::{Frame, Scope, TypeInferenceError};
use leo_core_ast::{Circuit, CircuitMember, Function, Program};
use leo_symbol_table::SymbolTable;
/// Stores information need to run a type inference check over a program.
/// A type inference check for a Leo program.
///
/// A [`TypeInference`] type stores a stack of frames. A new frame is created for every
/// function. Frames store type assertions that assert an expression is a type.
/// Calling the `check()` method on a [`TypeInference`] checks that all type assertions are satisfied.
pub struct TypeInference {
table: SymbolTable,
frames: Vec<Frame>,