mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-27 02:24:15 +03:00
Support AST changes in compile passes
This commit is contained in:
parent
224cf18544
commit
8f2a6fdb27
@ -129,6 +129,13 @@ pub trait MappingConsumer {
|
||||
fn consume_mapping(&mut self, input: Mapping) -> Self::Output;
|
||||
}
|
||||
|
||||
/// A Consumer trait for program scopes in the AST.
|
||||
pub trait ProgramScopeConsumer {
|
||||
type Output;
|
||||
|
||||
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output;
|
||||
}
|
||||
|
||||
/// A Consumer trait for the program represented by the AST.
|
||||
pub trait ProgramConsumer {
|
||||
type Output;
|
||||
|
@ -312,14 +312,28 @@ pub trait StatementReconstructor: ExpressionReconstructor {
|
||||
pub trait ProgramReconstructor: StatementReconstructor {
|
||||
fn reconstruct_program(&mut self, input: Program) -> Program {
|
||||
Program {
|
||||
name: input.name,
|
||||
network: input.network,
|
||||
expected_input: input.expected_input,
|
||||
imports: input
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|(id, import)| (id, self.reconstruct_import(import)))
|
||||
.collect(),
|
||||
program_scopes: input
|
||||
.program_scopes
|
||||
.into_iter()
|
||||
.map(|(id, scope)| (id, self.reconstruct_program_scope(scope)))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
|
||||
ProgramScope {
|
||||
name: input.name,
|
||||
network: input.network,
|
||||
structs: input
|
||||
.structs
|
||||
.into_iter()
|
||||
.map(|(i, c)| (i, self.reconstruct_struct(c)))
|
||||
.collect(),
|
||||
mappings: input
|
||||
.mappings
|
||||
.into_iter()
|
||||
@ -330,11 +344,6 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
.into_iter()
|
||||
.map(|(i, f)| (i, self.reconstruct_function(f)))
|
||||
.collect(),
|
||||
structs: input
|
||||
.structs
|
||||
.into_iter()
|
||||
.map(|(i, c)| (i, self.reconstruct_struct(c)))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,13 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
|
||||
fn visit_program(&mut self, input: &'a Program) {
|
||||
input.imports.values().for_each(|import| self.visit_import(import));
|
||||
|
||||
input
|
||||
.program_scopes
|
||||
.values()
|
||||
.for_each(|scope| self.visit_program_scope(scope));
|
||||
}
|
||||
|
||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||
input.structs.values().for_each(|function| self.visit_struct(function));
|
||||
|
||||
input.mappings.values().for_each(|mapping| self.visit_mapping(mapping));
|
||||
|
@ -19,7 +19,7 @@
|
||||
pub mod program_scope;
|
||||
pub use program_scope::*;
|
||||
|
||||
use crate::{Identifier};
|
||||
use crate::Identifier;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -39,7 +39,7 @@ impl fmt::Display for Program {
|
||||
for (id, _import) in self.imports.iter() {
|
||||
writeln!(f, "import {}.leo;", id)?;
|
||||
}
|
||||
for (_, program_scope) in self.structs.iter() {
|
||||
for (_, program_scope) in self.program_scopes.iter() {
|
||||
program_scope.fmt(f)?;
|
||||
writeln!(f,)?;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! The compiler for Leo programs.
|
||||
//!
|
||||
//! The [`Compiler`] type compiles Leo programs into R1CS circuits.
|
||||
use leo_ast::{Node, Program};
|
||||
use leo_ast::Program;
|
||||
pub use leo_ast::{Ast, InputAst};
|
||||
use leo_errors::emitter::Handler;
|
||||
use leo_errors::{CompilerError, Result};
|
||||
@ -97,15 +97,7 @@ impl<'a> Compiler<'a> {
|
||||
// Use the parser to construct the abstract syntax tree (ast).
|
||||
self.ast = leo_parser::parse_ast(self.handler, &prg_sf.src, prg_sf.start_pos)?;
|
||||
|
||||
// Check that the name associated with the program scope matches file name.
|
||||
if with_session_globals(|s| self.ast.ast.name.name.as_str(s, |s| s != &self.program_name)) {
|
||||
return Err(CompilerError::program_name_should_match_file_name(
|
||||
&self.ast.ast.name,
|
||||
&self.program_name,
|
||||
self.ast.ast.name.span(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
// TODO: Check that the program name matches the file name.
|
||||
|
||||
if self.output_options.initial_ast {
|
||||
self.write_ast_to_json("initial_ast.json")?;
|
||||
|
@ -120,7 +120,7 @@ impl ParserContext<'_> {
|
||||
let network = self.expect_identifier()?;
|
||||
|
||||
// Parse `{`.
|
||||
let _open = self.expect(&Token::OpenBrace)?;
|
||||
let _open = self.expect(&Token::LeftCurly)?;
|
||||
|
||||
// Parse the body of the program scope.
|
||||
let mut functions = IndexMap::new();
|
||||
@ -142,13 +142,13 @@ impl ParserContext<'_> {
|
||||
functions.insert(id, function);
|
||||
}
|
||||
Token::Circuit => return Err(ParserError::circuit_is_deprecated(self.token.span).into()),
|
||||
Token::CloseBrace => break,
|
||||
Token::RightCurly => break,
|
||||
_ => return Err(Self::unexpected_item(&self.token).into()),
|
||||
}
|
||||
}
|
||||
|
||||
// Parse `}`.
|
||||
let _close = self.expect(&Token::CloseBrace)?;
|
||||
let _close = self.expect(&Token::RightCurly)?;
|
||||
|
||||
Ok(ProgramScope {
|
||||
name,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{functions, CallType, Function, Identifier, Mapping, Mode, Program, Struct, Type};
|
||||
use leo_ast::{functions, CallType, Function, Identifier, Mapping, Mode, Program, ProgramScope, Struct, Type};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
@ -42,16 +42,24 @@ impl<'a> CodeGenerator<'a> {
|
||||
program_string.push('\n');
|
||||
}
|
||||
|
||||
// Retrieve the program scope.
|
||||
// Note that type checking guarantees that there is exactly one program scope.
|
||||
let program_scope: &ProgramScope = input.program_scopes.values().next().unwrap();
|
||||
|
||||
// Print the program id.
|
||||
writeln!(program_string, "program {}.{};", input.name, input.network)
|
||||
.expect("Failed to write program id to string.");
|
||||
writeln!(
|
||||
program_string,
|
||||
"program {}.{};",
|
||||
program_scope.name, program_scope.network
|
||||
)
|
||||
.expect("Failed to write program id to string.");
|
||||
|
||||
// Newline separator.
|
||||
program_string.push('\n');
|
||||
|
||||
// Visit each `Struct` or `Record` in the Leo AST and produce a Aleo interface instruction.
|
||||
program_string.push_str(
|
||||
&input
|
||||
&program_scope
|
||||
.structs
|
||||
.values()
|
||||
.map(|struct_| self.visit_struct_or_record(struct_))
|
||||
@ -63,7 +71,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
// Visit each mapping in the Leo AST and produce an Aleo mapping declaration.
|
||||
program_string.push_str(
|
||||
&input
|
||||
&program_scope
|
||||
.mappings
|
||||
.values()
|
||||
.map(|mapping| self.visit_mapping(mapping))
|
||||
@ -75,7 +83,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
let mut functions = String::new();
|
||||
|
||||
// Visit each `Function` in the Leo AST and produce Aleo instructions.
|
||||
input.functions.values().for_each(|function| {
|
||||
program_scope.functions.values().for_each(|function| {
|
||||
self.is_transition_function = matches!(function.call_type, CallType::Transition);
|
||||
|
||||
let function_string = self.visit_function(function);
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
use crate::StaticSingleAssigner;
|
||||
|
||||
use leo_ast::{Block, Finalize, Function, FunctionConsumer, Program, ProgramConsumer, StatementConsumer};
|
||||
use leo_ast::{
|
||||
Block, Finalize, Function, FunctionConsumer, Program, ProgramConsumer, ProgramScope, ProgramScopeConsumer,
|
||||
StatementConsumer,
|
||||
};
|
||||
|
||||
impl FunctionConsumer for StaticSingleAssigner {
|
||||
type Output = Function;
|
||||
@ -84,27 +87,39 @@ impl FunctionConsumer for StaticSingleAssigner {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProgramConsumer for StaticSingleAssigner {
|
||||
type Output = Program;
|
||||
impl ProgramScopeConsumer for StaticSingleAssigner {
|
||||
type Output = ProgramScope;
|
||||
|
||||
fn consume_program(&mut self, input: Program) -> Self::Output {
|
||||
Program {
|
||||
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
|
||||
ProgramScope {
|
||||
name: input.name,
|
||||
network: input.network,
|
||||
expected_input: input.expected_input,
|
||||
// TODO: Do inputs need to be processed? They are not processed in the existing compiler.
|
||||
imports: input
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|(name, import)| (name, self.consume_program(import)))
|
||||
.collect(),
|
||||
structs: input.structs,
|
||||
mappings: input.mappings,
|
||||
functions: input
|
||||
.functions
|
||||
.into_iter()
|
||||
.map(|(i, f)| (i, self.consume_function(f)))
|
||||
.collect(),
|
||||
structs: input.structs,
|
||||
mappings: input.mappings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProgramConsumer for StaticSingleAssigner {
|
||||
type Output = Program;
|
||||
|
||||
fn consume_program(&mut self, input: Program) -> Self::Output {
|
||||
Program {
|
||||
imports: input
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|(name, import)| (name, self.consume_program(import)))
|
||||
.collect(),
|
||||
program_scopes: input
|
||||
.program_scopes
|
||||
.into_iter()
|
||||
.map(|(name, scope)| (name, self.consume_program_scope(scope)))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,14 +120,6 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when the parser encountered a deprecated `test function`.
|
||||
@formatted
|
||||
test_function {
|
||||
args: (),
|
||||
msg: "\"test function...\" is deprecated. Did you mean @test annotation?",
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// When more input was expected but not found.
|
||||
@backtraced
|
||||
lexer_empty_input {
|
||||
|
Loading…
Reference in New Issue
Block a user