diff --git a/Cargo.lock b/Cargo.lock
index c05879dedb..11f072e055 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1210,6 +1210,7 @@ dependencies = [
"dirs",
"indexmap",
"lazy_static",
+ "leo-ast",
"leo-compiler",
"leo-errors",
"leo-package",
diff --git a/Cargo.toml b/Cargo.toml
index 389d181fd2..81454ee5c6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,6 +27,7 @@ path = "leo/main.rs"
[workspace]
members = [
+ "compiler/ast",
"compiler/compiler",
"compiler/parser",
"docs/grammar",
@@ -35,6 +36,10 @@ members = [
"tests/test-framework",
]
+[dependencies.leo-ast]
+path = "./compiler/ast"
+version = "1.5.3"
+
[dependencies.leo-compiler]
path = "./compiler/compiler"
version = "1.5.3"
diff --git a/compiler/ast/src/input/input_ast.rs b/compiler/ast/src/input/input_ast.rs
index 4eec431645..ad8922305b 100644
--- a/compiler/ast/src/input/input_ast.rs
+++ b/compiler/ast/src/input/input_ast.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{normalize_json_value, remove_key_from_json};
+use crate::{normalize_json_value, remove_key_from_json, Circuit, Expression, Type};
use super::*;
use leo_errors::{AstError, Result};
@@ -41,15 +41,41 @@ pub struct InputAst {
impl InputAst {
/// Returns all values of the input AST for execution with `leo run`.
- pub fn program_inputs(&self, program_name: &str) -> Vec {
+ pub fn program_inputs(&self, program_name: &str, circuits: IndexMap) -> Vec {
self.sections
.iter()
.filter(|section| section.name() == program_name)
.flat_map(|section| {
- section
- .definitions
- .iter()
- .map(|definition| definition.value.to_string())
+ section.definitions.iter().map(|definition| match &definition.type_ {
+ // Handle case where the input may be record.
+ Type::Identifier(identifier) => {
+ match circuits.get(&identifier.name) {
+ // TODO: Better error handling.
+ None => panic!(
+ "Input error: A circuit or record declaration does not exist for {}.",
+ identifier.name
+ ),
+ Some(circuit) => match circuit.is_record {
+ false => definition.value.to_string(),
+ true => match &definition.value {
+ Expression::Circuit(circuit_expression) => {
+ format!(
+ "{{{}}}",
+ circuit_expression
+ .members
+ .iter()
+ .map(|x| format!("{}.private", x))
+ .collect::>()
+ .join(", ")
+ )
+ }
+ _ => panic!("Input error: Expected a circuit expression."),
+ },
+ },
+ }
+ }
+ _ => definition.value.to_string(),
+ })
})
.collect::>()
}
diff --git a/examples/token/inputs/token.in b/examples/token/inputs/token.in
index adc7fc5638..026e9c28b6 100644
--- a/examples/token/inputs/token.in
+++ b/examples/token/inputs/token.in
@@ -1,4 +1,13 @@
// The program input for token/src/main.leo
[mint]
owner: address = aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7;
-amount: u64 = 100u64;
\ No newline at end of file
+amount: u64 = 100u64;
+
+[transfer]
+token: Token = Token {
+ owner: aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7,
+ gates: 0u64,
+ amount: 100u64,
+};
+to: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
+amount: u64 = 50u64;
\ No newline at end of file
diff --git a/leo/commands/build.rs b/leo/commands/build.rs
index 3a0e83e2fb..08001db49b 100644
--- a/leo/commands/build.rs
+++ b/leo/commands/build.rs
@@ -15,25 +15,26 @@
// along with the Leo library. If not, see .
use crate::{commands::Command, context::Context};
+
+use leo_ast::Circuit;
use leo_compiler::{Compiler, InputAst, OutputOptions};
use leo_errors::{CliError, CompilerError, PackageError, Result};
use leo_package::source::{SourceDirectory, MAIN_FILENAME};
-use leo_package::{
- inputs::InputFile,
- outputs::{ChecksumFile, OutputsDirectory},
-};
+use leo_package::{inputs::InputFile, outputs::OutputsDirectory};
use leo_span::symbol::with_session_globals;
use aleo::commands::Build as AleoBuild;
use clap::StructOpt;
use colored::Colorize;
+use indexmap::IndexMap;
use std::io::Write;
use std::path::{Path, PathBuf};
use leo_errors::emitter::Handler;
use leo_package::build::BuildDirectory;
use leo_package::imports::ImportsDirectory;
+use leo_span::Symbol;
use tracing::span::Span;
/// Compiler Options wrapper for Build command. Also used by other commands which
@@ -85,7 +86,7 @@ pub struct Build {
impl Command for Build {
type Input = ();
- type Output = Option;
+ type Output = (Option, IndexMap);
fn log_span(&self) -> Span {
tracing::span!(tracing::Level::INFO, "Build")
@@ -114,9 +115,12 @@ impl Command for Build {
// Fetch paths to all .leo files in the source directory.
let source_files = SourceDirectory::files(&package_path)?;
+ // Store all circuits declarations made in the source files.
+ let mut circuits = IndexMap::new();
+
// Compile all .leo files into .aleo files.
for file_path in source_files.into_iter() {
- compile_leo_file(
+ circuits.extend(compile_leo_file(
file_path,
&package_path,
&package_name,
@@ -124,7 +128,7 @@ impl Command for Build {
&build_directory,
&handler,
self.compiler_options.clone(),
- )?;
+ )?);
}
if !ImportsDirectory::is_empty(&package_path)? {
@@ -136,7 +140,7 @@ impl Command for Build {
// Compile all .leo files into .aleo files.
for file_path in import_files.into_iter() {
- compile_leo_file(
+ circuits.extend(compile_leo_file(
file_path,
&package_path,
&package_name,
@@ -144,7 +148,7 @@ impl Command for Build {
&build_imports_directory,
&handler,
self.compiler_options.clone(),
- )?;
+ )?);
}
}
@@ -157,7 +161,10 @@ impl Command for Build {
let input_sf = with_session_globals(|s| s.source_map.load_file(&input_file_path))
.map_err(|e| CompilerError::file_read_error(&input_file_path, e))?;
- leo_parser::parse_input(&handler, &input_sf.src, input_sf.start_pos).ok()
+ // TODO: This is a hack to notify the user that something is wrong with the input file. Redesign.
+ leo_parser::parse_input(&handler, &input_sf.src, input_sf.start_pos)
+ .map_err(|_e| println!("Warning: Failed to parse input file"))
+ .ok()
} else {
None
};
@@ -172,19 +179,19 @@ impl Command for Build {
// Log the result of the build
tracing::info!("{}", result);
- Ok(input_ast)
+ Ok((input_ast, circuits))
}
}
fn compile_leo_file(
file_path: PathBuf,
- package_path: &PathBuf,
+ _package_path: &Path,
package_name: &String,
outputs: &Path,
build: &Path,
handler: &Handler,
options: BuildOptions,
-) -> Result<()> {
+) -> Result> {
// Construct the Leo file name with extension `foo.leo`.
let file_name = file_path
.file_name()
@@ -214,58 +221,59 @@ fn compile_leo_file(
Some(options.into()),
);
- // Check if we need to compile the Leo program.
- let checksum_differs = {
- // Compute the current program checksum.
- let program_checksum = program.checksum()?;
+ // TODO: Temporarily removing checksum files. Need to redesign this scheme.
+ // // Check if we need to compile the Leo program.
+ // let checksum_differs = {
+ // // Compute the current program checksum.
+ // let program_checksum = program.checksum()?;
+ //
+ // // Get the current program checksum.
+ // let checksum_file = ChecksumFile::new(program_name);
+ //
+ // // If a checksum file exists, check if it differs from the new checksum.
+ // let checksum_differs = if checksum_file.exists_at(package_path) {
+ // let previous_checksum = checksum_file.read_from(package_path)?;
+ // program_checksum != previous_checksum
+ // } else {
+ // // By default, the checksum differs if there is no checksum to compare against.
+ // true
+ // };
+ //
+ // // If checksum differs, compile the program
+ // if checksum_differs {
+ // // Write the new checksum to the output directory
+ // checksum_file.write_to(package_path, program_checksum)?;
+ //
+ // tracing::debug!("Checksum saved ({:?})", package_path);
+ // }
+ //
+ // checksum_differs
+ // };
- // Get the current program checksum.
- let checksum_file = ChecksumFile::new(program_name);
+ // if checksum_differs {
+ // Compile the Leo program into Aleo instructions.
+ let (symbol_table, instructions) = program.compile_and_generate_instructions()?;
- // If a checksum file exists, check if it differs from the new checksum.
- let checksum_differs = if checksum_file.exists_at(package_path) {
- let previous_checksum = checksum_file.read_from(package_path)?;
- program_checksum != previous_checksum
- } else {
- // By default, the checksum differs if there is no checksum to compare against.
- true
- };
+ // Create the path to the Aleo file.
+ let mut aleo_file_path = build.to_path_buf();
+ aleo_file_path.push(format!("{}.aleo", program_name));
- // If checksum differs, compile the program
- if checksum_differs {
- // Write the new checksum to the output directory
- checksum_file.write_to(package_path, program_checksum)?;
+ // Write the instructions.
+ std::fs::File::create(&aleo_file_path)
+ .map_err(CliError::failed_to_load_instructions)?
+ .write_all(instructions.as_bytes())
+ .map_err(CliError::failed_to_load_instructions)?;
- tracing::debug!("Checksum saved ({:?})", package_path);
- }
+ // Prepare the path string.
+ let path_string = format!("(in \"{}\")", aleo_file_path.display());
- checksum_differs
- };
+ // Log the build as successful.
+ tracing::info!(
+ "✅ Compiled '{}' into Aleo instructions {}",
+ file_name,
+ path_string.dimmed()
+ );
+ // }
- if checksum_differs {
- // Compile the Leo program into Aleo instructions.
- let (_, instructions) = program.compile_and_generate_instructions()?;
-
- // Create the path to the Aleo file.
- let mut aleo_file_path = build.to_path_buf();
- aleo_file_path.push(format!("{}.aleo", program_name));
-
- // Write the instructions.
- std::fs::File::create(&aleo_file_path)
- .map_err(CliError::failed_to_load_instructions)?
- .write_all(instructions.as_bytes())
- .map_err(CliError::failed_to_load_instructions)?;
-
- // Prepare the path string.
- let path_string = format!("(in \"{}\")", aleo_file_path.display());
-
- // Log the build as successful.
- tracing::info!(
- "✅ Compiled '{}' into Aleo instructions {}",
- file_name,
- path_string.dimmed()
- );
- }
-
- Ok(())
+ Ok(symbol_table.circuits)
}
diff --git a/leo/commands/run.rs b/leo/commands/run.rs
index fed6e74fa7..b4d8779bfb 100644
--- a/leo/commands/run.rs
+++ b/leo/commands/run.rs
@@ -59,14 +59,16 @@ impl Command for Run {
fn apply(self, context: Context, input: Self::Input) -> Result {
// Get the input values.
let mut inputs = match input {
- Some(input_ast) => input_ast.program_inputs(&self.name),
- None => Vec::new(),
+ (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
+ _ => Vec::new(),
};
// Compose the `aleo run` command.
let mut arguments = vec![ALEO_CLI_COMMAND.to_string(), self.name];
arguments.append(&mut inputs);
+ println!("Arguments: {:?}", arguments);
+
// Open the Leo build/ directory
let path = context.dir()?;
let build_directory = BuildDirectory::open(&path)?;