mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-19 01:37:34 +03:00
import codegen working
This commit is contained in:
parent
776ad7c88e
commit
7f14e02055
@ -1,38 +0,0 @@
|
||||
// Copyright (C) 2019-2022 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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/>.
|
||||
|
||||
use crate::{Identifier, Node};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// An import statement `import foo.leo;`.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub struct ImportStatement {
|
||||
/// The import name `foo` without `.leo` extension.
|
||||
pub identifier: Identifier,
|
||||
/// The span including the semicolon.
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Display for ImportStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "import {}.leo;", self.identifier)
|
||||
}
|
||||
}
|
||||
|
||||
crate::simple_node_impl!(ImportStatement);
|
@ -39,9 +39,6 @@ pub use self::functions::*;
|
||||
pub mod groups;
|
||||
pub use self::groups::*;
|
||||
|
||||
pub mod imports;
|
||||
pub use self::imports::*;
|
||||
|
||||
pub mod input;
|
||||
pub use self::input::*;
|
||||
|
||||
|
@ -291,7 +291,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
input
|
||||
}
|
||||
|
||||
fn reconstruct_import(&mut self, input: ImportStatement) -> ImportStatement {
|
||||
fn reconstruct_import(&mut self, input: Program) -> Program {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
@ -192,5 +192,7 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
|
||||
|
||||
fn visit_circuit(&mut self, _input: &'a Circuit) {}
|
||||
|
||||
fn visit_import(&mut self, _input: &'a ImportStatement) {}
|
||||
fn visit_import(&mut self, input: &'a Program) {
|
||||
self.visit_program(input)
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! A Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of ast statements and expressions.
|
||||
|
||||
use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement};
|
||||
use crate::{Circuit, Function, FunctionInput, Identifier};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -34,7 +34,7 @@ pub struct Program {
|
||||
/// Empty after parsing.
|
||||
pub expected_input: Vec<FunctionInput>,
|
||||
/// A map from import names to import definitions.
|
||||
pub imports: IndexMap<Identifier, ImportStatement>,
|
||||
pub imports: IndexMap<Identifier, Program>,
|
||||
/// A map from function names to function definitions.
|
||||
pub functions: IndexMap<Identifier, Function>,
|
||||
/// A map from circuit names to circuit definitions.
|
||||
@ -43,9 +43,8 @@ pub struct Program {
|
||||
|
||||
impl fmt::Display for Program {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for (_, import) in self.imports.iter() {
|
||||
import.fmt(f)?;
|
||||
writeln!(f,)?;
|
||||
for (id, _import) in self.imports.iter() {
|
||||
writeln!(f, "import {}.leo;", id)?;
|
||||
}
|
||||
for (_, function) in self.functions.iter() {
|
||||
function.fmt(f)?;
|
||||
|
@ -15,9 +15,13 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use leo_errors::{ParserError, ParserWarning, Result};
|
||||
use crate::parse_ast;
|
||||
use leo_errors::{CompilerError, ParserError, ParserWarning, Result};
|
||||
use leo_span::source_map::FileName;
|
||||
use leo_span::sym;
|
||||
use leo_span::symbol::with_session_globals;
|
||||
|
||||
use std::fs;
|
||||
|
||||
impl ParserContext<'_> {
|
||||
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
|
||||
@ -71,25 +75,50 @@ impl ParserContext<'_> {
|
||||
}
|
||||
|
||||
/// Parses an import statement `import foo.leo;`.
|
||||
pub(super) fn parse_import(&mut self) -> Result<(Identifier, ImportStatement)> {
|
||||
let start = self.expect(&Token::Import)?;
|
||||
pub(super) fn parse_import(&mut self) -> Result<(Identifier, Program)> {
|
||||
// Parse `import`.
|
||||
let _start = self.expect(&Token::Import)?;
|
||||
|
||||
// Parse `foo`.
|
||||
let import_name = self.expect_identifier()?;
|
||||
|
||||
// Parse `.leo`.
|
||||
self.expect(&Token::Dot)?;
|
||||
let leo_file_extension = self.expect_identifier()?;
|
||||
|
||||
// Throw error for non-leo files.
|
||||
if leo_file_extension.name.ne(&sym::leo) {
|
||||
return Err(ParserError::leo_imports_only(leo_file_extension, self.token.span).into());
|
||||
}
|
||||
let end = self.expect(&Token::Semicolon)?;
|
||||
let _end = self.expect(&Token::Semicolon)?;
|
||||
|
||||
Ok((
|
||||
import_name,
|
||||
ImportStatement {
|
||||
identifier: import_name,
|
||||
span: start + end,
|
||||
},
|
||||
))
|
||||
// Tokenize and parse import file.
|
||||
// Todo: move this to a different module.
|
||||
let mut import_file_path =
|
||||
std::env::current_dir().map_err(|err| CompilerError::cannot_open_cwd(err, self.token.span))?;
|
||||
import_file_path.push("imports");
|
||||
import_file_path.push(format!("{}.leo", import_name.name));
|
||||
|
||||
// Throw an error if the import file doesn't exist.
|
||||
if !import_file_path.exists() {
|
||||
return Err(CompilerError::import_not_found(import_file_path.display(), self.token.span).into());
|
||||
}
|
||||
|
||||
// Read the import file into string.
|
||||
// Todo: protect against cyclic imports.
|
||||
let program_string =
|
||||
fs::read_to_string(&import_file_path).map_err(|e| CompilerError::file_read_error(&import_file_path, e))?;
|
||||
|
||||
// Create import file name.
|
||||
let name: FileName = FileName::Real(import_file_path);
|
||||
|
||||
// Register the source (`program_string`) in the source map.
|
||||
let prg_sf = with_session_globals(|s| s.source_map.new_source(&program_string, name));
|
||||
|
||||
// Use the parser to construct the imported abstract syntax tree (ast).
|
||||
let program_ast = parse_ast(self.handler, &prg_sf.src, prg_sf.start_pos)?;
|
||||
|
||||
Ok((import_name, program_ast.into_repr()))
|
||||
}
|
||||
|
||||
/// Returns a [`Vec<CircuitMember>`] AST node if the next tokens represent a circuit member variable
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{Circuit, CircuitMember, Function, ImportStatement, Program};
|
||||
use leo_ast::{Circuit, CircuitMember, Function, Identifier, Program};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
@ -32,8 +32,8 @@ impl<'a> CodeGenerator<'a> {
|
||||
program_string.push_str(
|
||||
&input
|
||||
.imports
|
||||
.values()
|
||||
.map(|import| self.visit_import(import))
|
||||
.iter()
|
||||
.map(|(identifier, imported_program)| self.visit_import(identifier, imported_program))
|
||||
.join("\n"),
|
||||
);
|
||||
|
||||
@ -72,8 +72,13 @@ impl<'a> CodeGenerator<'a> {
|
||||
program_string
|
||||
}
|
||||
|
||||
fn visit_import(&mut self, import: &'a ImportStatement) -> String {
|
||||
format!("import {}.aleo;", import.identifier)
|
||||
fn visit_import(&mut self, import_name: &'a Identifier, import_program: &'a Program) -> String {
|
||||
// Load symbols into composite mapping.
|
||||
let _import_program_string = self.visit_program(import_program);
|
||||
// todo: We do not need the import program string because we generate instructions for imports separately during leo build.
|
||||
|
||||
// Generate string for import statement.
|
||||
format!("import {}.aleo;", import_name)
|
||||
}
|
||||
|
||||
fn visit_circuit_or_record(&mut self, circuit: &'a Circuit) -> String {
|
||||
|
@ -57,4 +57,8 @@ impl<'a> ProgramVisitor<'a> for CreateSymbolTable<'a> {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import(&mut self, input: &'a Program) {
|
||||
self.visit_program(input)
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +309,21 @@ create_messages!(
|
||||
@formatted
|
||||
illegal_static_member_assignment {
|
||||
args: (member: impl Display),
|
||||
msg: format!("Tried to assign to static member `{}`", member),
|
||||
msg: format!("Tried to assign to static member `{member}`"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
import_not_found {
|
||||
args: (file_path: impl Display),
|
||||
msg: format!("Attempted to import a file that does not exist `{file_path}`."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
cannot_open_cwd {
|
||||
args: (err: impl ErrorArg),
|
||||
msg: format!("Failed to open current working directory. Error: {err}"),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -2,5 +2,7 @@ import other.leo;
|
||||
|
||||
// The 'helloworld' main function.
|
||||
function main(public a: u32, b: u32) -> u32 {
|
||||
let o: Other = Other { a: 1u64 };
|
||||
|
||||
return a + b;
|
||||
}
|
Loading…
Reference in New Issue
Block a user