mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
Produce a valid record as input
This commit is contained in:
parent
0570a421f0
commit
a6feb314a7
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1210,6 +1210,7 @@ dependencies = [
|
|||||||
"dirs",
|
"dirs",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"leo-ast",
|
||||||
"leo-compiler",
|
"leo-compiler",
|
||||||
"leo-errors",
|
"leo-errors",
|
||||||
"leo-package",
|
"leo-package",
|
||||||
|
@ -27,6 +27,7 @@ path = "leo/main.rs"
|
|||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"compiler/ast",
|
||||||
"compiler/compiler",
|
"compiler/compiler",
|
||||||
"compiler/parser",
|
"compiler/parser",
|
||||||
"docs/grammar",
|
"docs/grammar",
|
||||||
@ -35,6 +36,10 @@ members = [
|
|||||||
"tests/test-framework",
|
"tests/test-framework",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[dependencies.leo-ast]
|
||||||
|
path = "./compiler/ast"
|
||||||
|
version = "1.5.3"
|
||||||
|
|
||||||
[dependencies.leo-compiler]
|
[dependencies.leo-compiler]
|
||||||
path = "./compiler/compiler"
|
path = "./compiler/compiler"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{normalize_json_value, remove_key_from_json};
|
use crate::{normalize_json_value, remove_key_from_json, Circuit, Expression, Type};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use leo_errors::{AstError, Result};
|
use leo_errors::{AstError, Result};
|
||||||
@ -41,15 +41,41 @@ pub struct InputAst {
|
|||||||
|
|
||||||
impl InputAst {
|
impl InputAst {
|
||||||
/// Returns all values of the input AST for execution with `leo run`.
|
/// Returns all values of the input AST for execution with `leo run`.
|
||||||
pub fn program_inputs(&self, program_name: &str) -> Vec<String> {
|
pub fn program_inputs(&self, program_name: &str, circuits: IndexMap<Symbol, Circuit>) -> Vec<String> {
|
||||||
self.sections
|
self.sections
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|section| section.name() == program_name)
|
.filter(|section| section.name() == program_name)
|
||||||
.flat_map(|section| {
|
.flat_map(|section| {
|
||||||
section
|
section.definitions.iter().map(|definition| match &definition.type_ {
|
||||||
.definitions
|
// Handle case where the input may be record.
|
||||||
.iter()
|
Type::Identifier(identifier) => {
|
||||||
.map(|definition| definition.value.to_string())
|
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::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => panic!("Input error: Expected a circuit expression."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => definition.value.to_string(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
// The program input for token/src/main.leo
|
// The program input for token/src/main.leo
|
||||||
[mint]
|
[mint]
|
||||||
owner: address = aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7;
|
owner: address = aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7;
|
||||||
amount: u64 = 100u64;
|
amount: u64 = 100u64;
|
||||||
|
|
||||||
|
[transfer]
|
||||||
|
token: Token = Token {
|
||||||
|
owner: aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7,
|
||||||
|
gates: 0u64,
|
||||||
|
amount: 100u64,
|
||||||
|
};
|
||||||
|
to: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
|
||||||
|
amount: u64 = 50u64;
|
@ -15,25 +15,26 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{commands::Command, context::Context};
|
use crate::{commands::Command, context::Context};
|
||||||
|
|
||||||
|
use leo_ast::Circuit;
|
||||||
use leo_compiler::{Compiler, InputAst, OutputOptions};
|
use leo_compiler::{Compiler, InputAst, OutputOptions};
|
||||||
use leo_errors::{CliError, CompilerError, PackageError, Result};
|
use leo_errors::{CliError, CompilerError, PackageError, Result};
|
||||||
use leo_package::source::{SourceDirectory, MAIN_FILENAME};
|
use leo_package::source::{SourceDirectory, MAIN_FILENAME};
|
||||||
use leo_package::{
|
use leo_package::{inputs::InputFile, outputs::OutputsDirectory};
|
||||||
inputs::InputFile,
|
|
||||||
outputs::{ChecksumFile, OutputsDirectory},
|
|
||||||
};
|
|
||||||
use leo_span::symbol::with_session_globals;
|
use leo_span::symbol::with_session_globals;
|
||||||
|
|
||||||
use aleo::commands::Build as AleoBuild;
|
use aleo::commands::Build as AleoBuild;
|
||||||
|
|
||||||
use clap::StructOpt;
|
use clap::StructOpt;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use indexmap::IndexMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use leo_errors::emitter::Handler;
|
use leo_errors::emitter::Handler;
|
||||||
use leo_package::build::BuildDirectory;
|
use leo_package::build::BuildDirectory;
|
||||||
use leo_package::imports::ImportsDirectory;
|
use leo_package::imports::ImportsDirectory;
|
||||||
|
use leo_span::Symbol;
|
||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Compiler Options wrapper for Build command. Also used by other commands which
|
/// Compiler Options wrapper for Build command. Also used by other commands which
|
||||||
@ -85,7 +86,7 @@ pub struct Build {
|
|||||||
|
|
||||||
impl Command for Build {
|
impl Command for Build {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = Option<InputAst>;
|
type Output = (Option<InputAst>, IndexMap<Symbol, Circuit>);
|
||||||
|
|
||||||
fn log_span(&self) -> Span {
|
fn log_span(&self) -> Span {
|
||||||
tracing::span!(tracing::Level::INFO, "Build")
|
tracing::span!(tracing::Level::INFO, "Build")
|
||||||
@ -114,9 +115,12 @@ impl Command for Build {
|
|||||||
// Fetch paths to all .leo files in the source directory.
|
// Fetch paths to all .leo files in the source directory.
|
||||||
let source_files = SourceDirectory::files(&package_path)?;
|
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.
|
// Compile all .leo files into .aleo files.
|
||||||
for file_path in source_files.into_iter() {
|
for file_path in source_files.into_iter() {
|
||||||
compile_leo_file(
|
circuits.extend(compile_leo_file(
|
||||||
file_path,
|
file_path,
|
||||||
&package_path,
|
&package_path,
|
||||||
&package_name,
|
&package_name,
|
||||||
@ -124,7 +128,7 @@ impl Command for Build {
|
|||||||
&build_directory,
|
&build_directory,
|
||||||
&handler,
|
&handler,
|
||||||
self.compiler_options.clone(),
|
self.compiler_options.clone(),
|
||||||
)?;
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ImportsDirectory::is_empty(&package_path)? {
|
if !ImportsDirectory::is_empty(&package_path)? {
|
||||||
@ -136,7 +140,7 @@ impl Command for Build {
|
|||||||
|
|
||||||
// Compile all .leo files into .aleo files.
|
// Compile all .leo files into .aleo files.
|
||||||
for file_path in import_files.into_iter() {
|
for file_path in import_files.into_iter() {
|
||||||
compile_leo_file(
|
circuits.extend(compile_leo_file(
|
||||||
file_path,
|
file_path,
|
||||||
&package_path,
|
&package_path,
|
||||||
&package_name,
|
&package_name,
|
||||||
@ -144,7 +148,7 @@ impl Command for Build {
|
|||||||
&build_imports_directory,
|
&build_imports_directory,
|
||||||
&handler,
|
&handler,
|
||||||
self.compiler_options.clone(),
|
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))
|
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))?;
|
.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 {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -172,19 +179,19 @@ impl Command for Build {
|
|||||||
// Log the result of the build
|
// Log the result of the build
|
||||||
tracing::info!("{}", result);
|
tracing::info!("{}", result);
|
||||||
|
|
||||||
Ok(input_ast)
|
Ok((input_ast, circuits))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_leo_file(
|
fn compile_leo_file(
|
||||||
file_path: PathBuf,
|
file_path: PathBuf,
|
||||||
package_path: &PathBuf,
|
_package_path: &Path,
|
||||||
package_name: &String,
|
package_name: &String,
|
||||||
outputs: &Path,
|
outputs: &Path,
|
||||||
build: &Path,
|
build: &Path,
|
||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
options: BuildOptions,
|
options: BuildOptions,
|
||||||
) -> Result<()> {
|
) -> Result<IndexMap<Symbol, Circuit>> {
|
||||||
// Construct the Leo file name with extension `foo.leo`.
|
// Construct the Leo file name with extension `foo.leo`.
|
||||||
let file_name = file_path
|
let file_name = file_path
|
||||||
.file_name()
|
.file_name()
|
||||||
@ -214,58 +221,59 @@ fn compile_leo_file(
|
|||||||
Some(options.into()),
|
Some(options.into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if we need to compile the Leo program.
|
// TODO: Temporarily removing checksum files. Need to redesign this scheme.
|
||||||
let checksum_differs = {
|
// // Check if we need to compile the Leo program.
|
||||||
// Compute the current program checksum.
|
// let checksum_differs = {
|
||||||
let program_checksum = program.checksum()?;
|
// // 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.
|
// if checksum_differs {
|
||||||
let checksum_file = ChecksumFile::new(program_name);
|
// 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.
|
// Create the path to the Aleo file.
|
||||||
let checksum_differs = if checksum_file.exists_at(package_path) {
|
let mut aleo_file_path = build.to_path_buf();
|
||||||
let previous_checksum = checksum_file.read_from(package_path)?;
|
aleo_file_path.push(format!("{}.aleo", program_name));
|
||||||
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
|
// Write the instructions.
|
||||||
if checksum_differs {
|
std::fs::File::create(&aleo_file_path)
|
||||||
// Write the new checksum to the output directory
|
.map_err(CliError::failed_to_load_instructions)?
|
||||||
checksum_file.write_to(package_path, program_checksum)?;
|
.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 {
|
Ok(symbol_table.circuits)
|
||||||
// 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(())
|
|
||||||
}
|
}
|
||||||
|
@ -59,14 +59,16 @@ impl Command for Run {
|
|||||||
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
// Get the input values.
|
// Get the input values.
|
||||||
let mut inputs = match input {
|
let mut inputs = match input {
|
||||||
Some(input_ast) => input_ast.program_inputs(&self.name),
|
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
|
||||||
None => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compose the `aleo run` command.
|
// Compose the `aleo run` command.
|
||||||
let mut arguments = vec![ALEO_CLI_COMMAND.to_string(), self.name];
|
let mut arguments = vec![ALEO_CLI_COMMAND.to_string(), self.name];
|
||||||
arguments.append(&mut inputs);
|
arguments.append(&mut inputs);
|
||||||
|
|
||||||
|
println!("Arguments: {:?}", arguments);
|
||||||
|
|
||||||
// Open the Leo build/ directory
|
// Open the Leo build/ directory
|
||||||
let path = context.dir()?;
|
let path = context.dir()?;
|
||||||
let build_directory = BuildDirectory::open(&path)?;
|
let build_directory = BuildDirectory::open(&path)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user