mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-26 02:53:08 +03:00
commit
efbf4f54e9
123
Cargo.lock
generated
123
Cargo.lock
generated
@ -233,6 +233,17 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
@ -507,6 +518,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.8"
|
||||
@ -591,17 +611,24 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||
name = "leo"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"colored",
|
||||
"env_logger",
|
||||
"failure",
|
||||
"from-pest",
|
||||
"lazy_static",
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
"leo-compiler",
|
||||
"log",
|
||||
"rand 0.7.3",
|
||||
"rand_core 0.5.1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-curves",
|
||||
"snarkos-errors",
|
||||
"snarkos-gadgets",
|
||||
"snarkos-models",
|
||||
"structopt",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -609,11 +636,7 @@ name = "leo-benchmark"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"from-pest",
|
||||
"lazy_static",
|
||||
"leo-program",
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
"leo-compiler",
|
||||
"rand 0.7.3",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-curves",
|
||||
@ -623,11 +646,12 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-program"
|
||||
name = "leo-compiler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"from-pest",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
@ -797,6 +821,32 @@ version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
@ -1149,6 +1199,9 @@ name = "serde"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
@ -1302,6 +1355,30 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
@ -1330,6 +1407,17 @@ dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-mid"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
@ -1378,6 +1466,15 @@ dependencies = [
|
||||
"crunchy 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.11.2"
|
||||
@ -1402,6 +1499,12 @@ dependencies = [
|
||||
"rustc-hex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
|
22
Cargo.toml
22
Cargo.toml
@ -6,25 +6,33 @@ edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "leo"
|
||||
path = "program/src/lib.rs"
|
||||
path = "leo/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "leo"
|
||||
path = "benchmark/src/main.rs"
|
||||
path = "leo/main.rs"
|
||||
|
||||
[workspace]
|
||||
members = [ "benchmark", "program" ]
|
||||
members = [ "benchmark", "compiler" ]
|
||||
|
||||
[dependencies]
|
||||
leo-compiler = { path = "compiler", version = "0.1.0" }
|
||||
|
||||
snarkos-algorithms = { path = "../snarkOS/algorithms", version = "0.8.0" }
|
||||
snarkos-curves = { path = "../snarkOS/curves", version = "0.8.0" }
|
||||
snarkos-errors = { path = "../snarkOS/errors", version = "0.8.0" }
|
||||
snarkos-gadgets = { path = "../snarkOS/gadgets", version = "0.8.0" }
|
||||
snarkos-models = { path = "../snarkOS/models", version = "0.8.0" }
|
||||
|
||||
clap = { version = "2.33.0" }
|
||||
colored = { version = "1.9" }
|
||||
env_logger = { version = "0.7" }
|
||||
failure = { version = "0.1.5" }
|
||||
from-pest = { version = "0.3.1" }
|
||||
lazy_static = { version = "1.3.0" }
|
||||
pest = { version = "2.0" }
|
||||
pest-ast = { version = "0.3.3" }
|
||||
pest_derive = { version = "2.0" }
|
||||
log = { version = "0.4" }
|
||||
rand = { version = "0.7" }
|
||||
rand_core = { version = "0.5.1" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0" }
|
||||
structopt = { version = "0.3.14" }
|
||||
toml = { version = "0.5" }
|
||||
|
@ -5,7 +5,7 @@ authors = ["The Aleo Team <hello@aleo.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
leo-program = { path = "../program", version = "0.1.0" }
|
||||
leo-compiler = { path = "../compiler", version = "0.1.0" }
|
||||
|
||||
snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" }
|
||||
snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" }
|
||||
@ -14,8 +14,4 @@ snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0" }
|
||||
snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" }
|
||||
|
||||
from-pest = { version = "0.3.1" }
|
||||
lazy_static = { version = "1.3.0" }
|
||||
pest = { version = "2.0" }
|
||||
pest-ast = { version = "0.3.3" }
|
||||
pest_derive = { version = "2.0" }
|
||||
rand = { version = "0.7" }
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "leo-program"
|
||||
name = "leo-compiler"
|
||||
version = "0.1.0"
|
||||
authors = ["The Aleo Team <hello@aleo.org>"]
|
||||
edition = "2018"
|
||||
@ -13,6 +13,7 @@ snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" }
|
||||
|
||||
from-pest = { version = "0.3.1" }
|
||||
lazy_static = { version = "1.3.0" }
|
||||
log = { version = "0.4" }
|
||||
pest = { version = "2.0" }
|
||||
pest-ast = { version = "0.3.3" }
|
||||
pest_derive = { version = "2.0" }
|
51
compiler/src/compiler.rs
Normal file
51
compiler/src/compiler.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::{ast, Program, ResolvedProgram};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem},
|
||||
};
|
||||
|
||||
use from_pest::FromPest;
|
||||
use std::{
|
||||
fs,
|
||||
marker::PhantomData,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Compiler<F: Field + PrimeField> {
|
||||
main_file_path: PathBuf,
|
||||
_engine: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> Compiler<F> {
|
||||
pub fn init(main_file_path: PathBuf) -> Self {
|
||||
Self { main_file_path, _engine: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> ConstraintSynthesizer<F> for Compiler<F> {
|
||||
fn generate_constraints<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path).expect("cannot read file");
|
||||
|
||||
// Parse the file using leo.pest
|
||||
let mut file = ast::parse(&unparsed_file).expect("unsuccessful parse");
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||
log::debug!("{:#?}", syntax_tree);
|
||||
|
||||
let program = Program::<'_, F>::from(syntax_tree);
|
||||
log::info!(" compiled: {:#?}", program);
|
||||
|
||||
let program = program.name("simple".into());
|
||||
ResolvedProgram::generate_constraints(cs, program);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ extern crate pest_derive;
|
||||
|
||||
pub mod ast;
|
||||
|
||||
pub mod compiler;
|
||||
|
||||
pub mod constraints;
|
||||
pub use self::constraints::*;
|
||||
|
78
leo/cli.rs
Normal file
78
leo/cli.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use crate::cli_types::*;
|
||||
use crate::errors::CLIError;
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
|
||||
pub trait CLI {
|
||||
type Options;
|
||||
type Output;
|
||||
|
||||
const NAME: NameType;
|
||||
const ABOUT: AboutType;
|
||||
const ARGUMENTS: &'static [ArgumentType];
|
||||
const FLAGS: &'static [FlagType];
|
||||
const OPTIONS: &'static [OptionType];
|
||||
const SUBCOMMANDS: &'static [SubCommandType];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn new<'a, 'b>() -> App<'a, 'b> {
|
||||
let arguments = &Self::ARGUMENTS
|
||||
.iter()
|
||||
.map(|a| Arg::with_name(a.0)
|
||||
.help(a.1)
|
||||
.required(a.2)
|
||||
.index(a.3))
|
||||
.collect::<Vec<Arg<'static, 'static>>>();
|
||||
let flags = &Self::FLAGS
|
||||
.iter()
|
||||
.map(|a| Arg::from_usage(a).global(true))
|
||||
.collect::<Vec<Arg<'static, 'static>>>();
|
||||
let options = &Self::OPTIONS
|
||||
.iter()
|
||||
.map(|a| match a.2.len() > 0 {
|
||||
true => Arg::from_usage(a.0)
|
||||
.conflicts_with_all(a.1)
|
||||
.possible_values(a.2)
|
||||
.requires_all(a.3),
|
||||
false => Arg::from_usage(a.0).conflicts_with_all(a.1).requires_all(a.3),
|
||||
})
|
||||
.collect::<Vec<Arg<'static, 'static>>>();
|
||||
let subcommands = Self::SUBCOMMANDS
|
||||
.iter()
|
||||
.map(|s| {
|
||||
SubCommand::with_name(s.0)
|
||||
.about(s.1)
|
||||
.args(
|
||||
&s.2.iter()
|
||||
.map(|a| match a.2.len() > 0 {
|
||||
true => Arg::from_usage(a.0)
|
||||
.conflicts_with_all(a.1)
|
||||
.possible_values(a.2)
|
||||
.requires_all(a.3),
|
||||
false => Arg::from_usage(a.0).conflicts_with_all(a.1).requires_all(a.3),
|
||||
})
|
||||
.collect::<Vec<Arg<'static, 'static>>>(),
|
||||
)
|
||||
.settings(s.3)
|
||||
})
|
||||
.collect::<Vec<App<'static, 'static>>>();
|
||||
|
||||
SubCommand::with_name(Self::NAME)
|
||||
.about(Self::ABOUT)
|
||||
.settings(&[
|
||||
AppSettings::ColoredHelp,
|
||||
AppSettings::DisableHelpSubcommand,
|
||||
AppSettings::DisableVersion,
|
||||
])
|
||||
.args(arguments)
|
||||
.args(flags)
|
||||
.args(options)
|
||||
.subcommands(subcommands)
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError>;
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError>;
|
||||
}
|
24
leo/cli_types.rs
Normal file
24
leo/cli_types.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use clap::AppSettings;
|
||||
|
||||
pub type NameType = &'static str;
|
||||
|
||||
pub type AboutType = &'static str;
|
||||
|
||||
pub type DescriptionType = &'static str;
|
||||
|
||||
pub type RequiredType = bool;
|
||||
|
||||
pub type IndexType = u64;
|
||||
|
||||
pub type ArgumentType = (NameType, DescriptionType, RequiredType, IndexType);
|
||||
|
||||
pub type FlagType = &'static str;
|
||||
|
||||
pub type OptionType = (
|
||||
&'static str,
|
||||
&'static [&'static str],
|
||||
&'static [&'static str],
|
||||
&'static [&'static str],
|
||||
);
|
||||
|
||||
pub type SubCommandType = (NameType, AboutType, &'static [OptionType], &'static [AppSettings]);
|
64
leo/commands/build.rs
Normal file
64
leo/commands/build.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::directories::{OutputsDirectory, source::SOURCE_DIRECTORY_NAME};
|
||||
use crate::errors::{CLIError, BuildError};
|
||||
use crate::files::{MainFile, MAIN_FILE_NAME};
|
||||
use crate::manifest::Manifest;
|
||||
use leo_compiler::compiler::Compiler;
|
||||
|
||||
use snarkos_curves::bls12_377::Fr;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::convert::TryFrom;
|
||||
use std::env::current_dir;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BuildCommand;
|
||||
|
||||
impl CLI for BuildCommand {
|
||||
type Options = ();
|
||||
type Output = Compiler<Fr>;
|
||||
|
||||
const NAME: NameType = "build";
|
||||
const ABOUT: AboutType = "Compile the current package";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(_options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||
let path = current_dir()?;
|
||||
let _manifest = Manifest::try_from(&path)?;
|
||||
|
||||
// Sanitize the package path to the root directory
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
package_path.pop();
|
||||
}
|
||||
|
||||
// Verify the main file exists
|
||||
if !MainFile::exists_at(&package_path) {
|
||||
return Err(BuildError::MainFileDoesNotExist(package_path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Create the outputs directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
// Construct the path to the main file in the source directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(SOURCE_DIRECTORY_NAME);
|
||||
main_file_path.push(MAIN_FILE_NAME);
|
||||
|
||||
log::info!("Compiling program located in {:?}", main_file_path);
|
||||
|
||||
// Compile from the main file path
|
||||
let circuit = Compiler::<Fr>::init(main_file_path);
|
||||
|
||||
Ok(circuit)
|
||||
}
|
||||
}
|
71
leo/commands/init.rs
Normal file
71
leo/commands/init.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::directories::{InputsDirectory, SourceDirectory};
|
||||
use crate::errors::{CLIError, InitError};
|
||||
use crate::files::MainFile;
|
||||
use crate::manifest::Manifest;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::env::current_dir;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InitCommand;
|
||||
|
||||
impl CLI for InitCommand {
|
||||
type Options = Option<String>;
|
||||
type Output = ();
|
||||
|
||||
const NAME: NameType = "init";
|
||||
const ABOUT: AboutType = "Creates a new Leo package in an existing directory";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||
let name = options;
|
||||
let path = current_dir()?;
|
||||
|
||||
// Derive the package name
|
||||
let package_name = match name {
|
||||
Some(name) => name,
|
||||
None => path
|
||||
.file_stem()
|
||||
.ok_or_else(|| InitError::ProjectNameInvalid(path.as_os_str().to_owned()))?
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
// Verify the directory exists
|
||||
if !path.exists() {
|
||||
return Err(InitError::DirectoryDoesNotExist(path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Verify a manifest file does not already exist
|
||||
if Manifest::exists_at(&path) {
|
||||
return Err(InitError::PackageAlreadyExists(path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Create the manifest file
|
||||
Manifest::new(&package_name).write_to(&path)?;
|
||||
|
||||
// Create the source directory
|
||||
SourceDirectory::create(&path)?;
|
||||
|
||||
// Create the inputs directory
|
||||
InputsDirectory::create(&path)?;
|
||||
|
||||
// Verify the main file does not exist
|
||||
if !MainFile::exists_at(&path) {
|
||||
// Create the main file in the source directory
|
||||
MainFile::new(&package_name).write_to(&path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
14
leo/commands/mod.rs
Normal file
14
leo/commands/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pub mod build;
|
||||
pub use self::build::*;
|
||||
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
||||
pub mod new;
|
||||
pub use self::new::*;
|
||||
|
||||
pub mod run;
|
||||
pub use self::run::*;
|
||||
|
||||
pub mod setup;
|
||||
pub use self::setup::*;
|
77
leo/commands/new.rs
Normal file
77
leo/commands/new.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::directories::{InputsDirectory, SourceDirectory};
|
||||
use crate::errors::{CLIError, NewError};
|
||||
use crate::files::MainFile;
|
||||
use crate::manifest::Manifest;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::env::current_dir;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NewCommand;
|
||||
|
||||
impl CLI for NewCommand {
|
||||
type Options = Option<String>;
|
||||
type Output = ();
|
||||
|
||||
const NAME: NameType = "new";
|
||||
const ABOUT: AboutType = "Creates a new Leo package";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[
|
||||
// (name, description, required, index)
|
||||
("NAME", "Sets the resulting package name, defaults to the directory name", true, 1u64)
|
||||
];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
match arguments.value_of("NAME") {
|
||||
Some(name) => Ok(Some(name.to_string())),
|
||||
None => Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||
let mut path = current_dir()?;
|
||||
|
||||
// Derive the package name
|
||||
let package_name = match options {
|
||||
Some(name) => name,
|
||||
None => path
|
||||
.file_stem()
|
||||
.ok_or_else(|| NewError::ProjectNameInvalid(path.as_os_str().to_owned()))?
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
// Derive the package directory path
|
||||
path.push(&package_name);
|
||||
|
||||
// Verify the package directory path does not exist yet
|
||||
if path.exists() {
|
||||
return Err(NewError::DirectoryAlreadyExists(path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Create the package directory
|
||||
fs::create_dir_all(&path).map_err(|error| {
|
||||
NewError::CreatingRootDirectory(path.as_os_str().to_owned(), error)
|
||||
})?;
|
||||
|
||||
// Create the manifest file
|
||||
Manifest::new(&package_name).write_to(&path)?;
|
||||
|
||||
// Create the source directory
|
||||
SourceDirectory::create(&path)?;
|
||||
|
||||
// Create the inputs directory
|
||||
InputsDirectory::create(&path)?;
|
||||
|
||||
// Create the main file in the source directory
|
||||
MainFile::new(&package_name).write_to(&path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
63
leo/commands/run.rs
Normal file
63
leo/commands/run.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::commands::SetupCommand;
|
||||
use crate::errors::CLIError;
|
||||
|
||||
use snarkos_algorithms::snark::{create_random_proof, verify_proof};
|
||||
|
||||
use clap::ArgMatches;
|
||||
use rand::thread_rng;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RunCommand;
|
||||
|
||||
impl CLI for RunCommand {
|
||||
type Options = ();
|
||||
type Output = ();
|
||||
|
||||
const NAME: NameType = "run";
|
||||
const ABOUT: AboutType = "Run a program with inputs";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<(), CLIError> {
|
||||
let (circuit, parameters, prepared_verifying_key) = SetupCommand::output(options)?;
|
||||
|
||||
let rng = &mut thread_rng();
|
||||
|
||||
let mut proving = Duration::new(0, 0);
|
||||
let mut verifying = Duration::new(0, 0);
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = create_random_proof(circuit, ¶meters, rng).unwrap();
|
||||
|
||||
proving += start.elapsed();
|
||||
|
||||
// let _inputs: Vec<_> = [1u32; 1].to_vec();
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap();
|
||||
|
||||
verifying += start.elapsed();
|
||||
|
||||
println!(" ");
|
||||
println!(" Prover time : {:?} milliseconds", proving.as_millis());
|
||||
println!(
|
||||
" Verifier time : {:?} milliseconds",
|
||||
verifying.as_millis()
|
||||
);
|
||||
println!(" Verifier output : {}", is_success);
|
||||
println!(" ");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
50
leo/commands/setup.rs
Normal file
50
leo/commands/setup.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::commands::BuildCommand;
|
||||
use crate::errors::CLIError;
|
||||
use leo_compiler::compiler::Compiler;
|
||||
|
||||
use snarkos_algorithms::snark::{generate_random_parameters, prepare_verifying_key, Parameters, PreparedVerifyingKey};
|
||||
use snarkos_curves::bls12_377::{Bls12_377, Fr};
|
||||
|
||||
use clap::ArgMatches;
|
||||
use rand::thread_rng;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SetupCommand;
|
||||
|
||||
impl CLI for SetupCommand {
|
||||
type Options = ();
|
||||
type Output = (Compiler<Fr>, Parameters<Bls12_377>, PreparedVerifyingKey<Bls12_377>);
|
||||
|
||||
const NAME: NameType = "setup";
|
||||
const ABOUT: AboutType = "Run a program setup";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||
let circuit = BuildCommand::output(options)?;
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let rng = &mut thread_rng();
|
||||
let parameters = generate_random_parameters::<Bls12_377, _, _>(circuit.clone(), rng).unwrap();
|
||||
let prepared_verifying_key = prepare_verifying_key::<Bls12_377>(¶meters.vk);
|
||||
|
||||
let finish = start.elapsed();
|
||||
|
||||
println!(" ");
|
||||
println!(" Setup time : {:?} milliseconds", finish.as_millis());
|
||||
println!(" ");
|
||||
|
||||
Ok((circuit, parameters, prepared_verifying_key))
|
||||
}
|
||||
}
|
61
leo/directories/inputs.rs
Normal file
61
leo/directories/inputs.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::errors::InputsDirectoryError;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(crate) static INPUTS_DIRECTORY_NAME: &str = "inputs/";
|
||||
|
||||
static INPUTS_FILE_EXTENSION: &str = "leo.in";
|
||||
|
||||
pub struct InputsDirectory;
|
||||
|
||||
impl InputsDirectory {
|
||||
/// Creates a directory at the provided path with the default directory name.
|
||||
pub fn create(path: &PathBuf) -> Result<(), InputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(INPUTS_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(INPUTS_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).map_err(InputsDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Returns a list of files in the source directory.
|
||||
pub fn files(path: &PathBuf) -> Result<Vec<PathBuf>, InputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
path.push(PathBuf::from(INPUTS_DIRECTORY_NAME));
|
||||
let directory = fs::read_dir(&path).map_err(InputsDirectoryError::Reading)?;
|
||||
|
||||
let mut file_paths = Vec::new();
|
||||
for file_entry in directory.into_iter() {
|
||||
let file_entry = file_entry.map_err(InputsDirectoryError::GettingFileEntry)?;
|
||||
let file_path = file_entry.path();
|
||||
|
||||
// Verify that the entry is structured as a valid file
|
||||
let file_type = file_entry
|
||||
.file_type()
|
||||
.map_err(|error| InputsDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?;
|
||||
if !file_type.is_file() {
|
||||
return Err(InputsDirectoryError::InvalidFileType(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_type,
|
||||
));
|
||||
}
|
||||
|
||||
// Verify that the file has the default file extension
|
||||
let file_extension = file_path
|
||||
.extension()
|
||||
.ok_or_else(|| InputsDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?;
|
||||
if file_extension != INPUTS_FILE_EXTENSION {
|
||||
return Err(InputsDirectoryError::InvalidFileExtension(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_extension.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
file_paths.push(file_path);
|
||||
}
|
||||
|
||||
Ok(file_paths)
|
||||
}
|
||||
}
|
8
leo/directories/mod.rs
Normal file
8
leo/directories/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod inputs;
|
||||
pub use self::inputs::*;
|
||||
|
||||
pub mod outputs;
|
||||
pub use self::outputs::*;
|
||||
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
34
leo/directories/outputs.rs
Normal file
34
leo/directories/outputs.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use crate::errors::OutputsDirectoryError;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(crate) static OUTPUTS_DIRECTORY_NAME: &str = "outputs/";
|
||||
|
||||
pub struct OutputsDirectory;
|
||||
|
||||
impl OutputsDirectory {
|
||||
/// Creates a directory at the provided path with the default directory name.
|
||||
pub fn create(path: &PathBuf) -> Result<(), OutputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).map_err(OutputsDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Removes the directory at the provided path.
|
||||
pub fn remove(path: &PathBuf) -> Result<(), OutputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
if path.exists() {
|
||||
fs::remove_dir_all(&path).map_err(OutputsDirectoryError::Removing)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
61
leo/directories/source.rs
Normal file
61
leo/directories/source.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::errors::SourceDirectoryError;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(crate) static SOURCE_DIRECTORY_NAME: &str = "src/";
|
||||
|
||||
static SOURCE_FILE_EXTENSION: &str = "leo";
|
||||
|
||||
pub struct SourceDirectory;
|
||||
|
||||
impl SourceDirectory {
|
||||
/// Creates a directory at the provided path with the default directory name.
|
||||
pub fn create(path: &PathBuf) -> Result<(), SourceDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(SOURCE_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).map_err(SourceDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Returns a list of files in the source directory.
|
||||
pub fn files(path: &PathBuf) -> Result<Vec<PathBuf>, SourceDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
let directory = fs::read_dir(&path).map_err(SourceDirectoryError::Reading)?;
|
||||
|
||||
let mut file_paths = Vec::new();
|
||||
for file_entry in directory.into_iter() {
|
||||
let file_entry = file_entry.map_err(SourceDirectoryError::GettingFileEntry)?;
|
||||
let file_path = file_entry.path();
|
||||
|
||||
// Verify that the entry is structured as a valid file
|
||||
let file_type = file_entry
|
||||
.file_type()
|
||||
.map_err(|error| SourceDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?;
|
||||
if !file_type.is_file() {
|
||||
return Err(SourceDirectoryError::InvalidFileType(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_type,
|
||||
));
|
||||
}
|
||||
|
||||
// Verify that the file has the default file extension
|
||||
let file_extension = file_path
|
||||
.extension()
|
||||
.ok_or_else(|| SourceDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?;
|
||||
if file_extension != SOURCE_FILE_EXTENSION {
|
||||
return Err(SourceDirectoryError::InvalidFileExtension(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_extension.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
file_paths.push(file_path);
|
||||
}
|
||||
|
||||
Ok(file_paths)
|
||||
}
|
||||
}
|
102
leo/errors/cli.rs
Normal file
102
leo/errors/cli.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use crate::errors::*;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum CLIError {
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
BuildError(BuildError),
|
||||
|
||||
#[fail(display = "{}: {}", _0, _1)]
|
||||
Crate(&'static str, String),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
InitError(InitError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
InputsDirectoryError(InputsDirectoryError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
MainFileError(MainFileError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
NewError(NewError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
OutputsDirectoryError(OutputsDirectoryError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
RunError(RunError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
SourceDirectoryError(SourceDirectoryError),
|
||||
|
||||
}
|
||||
|
||||
impl From<BuildError> for CLIError {
|
||||
fn from(error: BuildError) -> Self {
|
||||
CLIError::BuildError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InitError> for CLIError {
|
||||
fn from(error: InitError) -> Self {
|
||||
CLIError::InitError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InputsDirectoryError> for CLIError {
|
||||
fn from(error: InputsDirectoryError) -> Self {
|
||||
CLIError::InputsDirectoryError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MainFileError> for CLIError {
|
||||
fn from(error: MainFileError) -> Self {
|
||||
CLIError::MainFileError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ManifestError> for CLIError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
CLIError::ManifestError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NewError> for CLIError {
|
||||
fn from(error: NewError) -> Self {
|
||||
CLIError::NewError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OutputsDirectoryError> for CLIError {
|
||||
fn from(error: OutputsDirectoryError) -> Self {
|
||||
CLIError::OutputsDirectoryError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RunError> for CLIError {
|
||||
fn from(error: RunError) -> Self {
|
||||
CLIError::RunError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SourceDirectoryError> for CLIError {
|
||||
fn from(error: SourceDirectoryError) -> Self {
|
||||
CLIError::SourceDirectoryError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::error::Error> for CLIError {
|
||||
fn from(error: serde_json::error::Error) -> Self {
|
||||
CLIError::Crate("serde_json", format!("{}", error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for CLIError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
CLIError::Crate("std::io", format!("{}", error))
|
||||
}
|
||||
}
|
20
leo/errors/commands/build.rs
Normal file
20
leo/errors/commands/build.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use std::ffi::OsString;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum BuildError {
|
||||
|
||||
#[fail(display = "main file {:?} does not exist", _0)]
|
||||
MainFileDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for BuildError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
BuildError::ManifestError(error)
|
||||
}
|
||||
}
|
30
leo/errors/commands/init.rs
Normal file
30
leo/errors/commands/init.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum InitError {
|
||||
|
||||
#[fail(display = "root directory {:?} creating: {}", _0, _1)]
|
||||
CreatingRootDirectory(OsString, io::Error),
|
||||
|
||||
#[fail(display = "directory {:?} does not exist", _0)]
|
||||
DirectoryDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "package at path {:?} already exists", _0)]
|
||||
PackageAlreadyExists(OsString),
|
||||
|
||||
#[fail(display = "package name is missing - {:?}", _0)]
|
||||
ProjectNameInvalid(OsString),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for InitError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
InitError::ManifestError(error)
|
||||
}
|
||||
}
|
11
leo/errors/commands/mod.rs
Normal file
11
leo/errors/commands/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
pub mod build;
|
||||
pub use self::build::*;
|
||||
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
||||
pub mod new;
|
||||
pub use self::new::*;
|
||||
|
||||
pub mod run;
|
||||
pub use self::run::*;
|
30
leo/errors/commands/new.rs
Normal file
30
leo/errors/commands/new.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum NewError {
|
||||
|
||||
#[fail(display = "root directory {:?} creating: {}", _0, _1)]
|
||||
CreatingRootDirectory(OsString, io::Error),
|
||||
|
||||
#[fail(display = "directory {:?} already exists", _0)]
|
||||
DirectoryAlreadyExists(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "package at path {:?} already exists", _0)]
|
||||
PackageAlreadyExists(OsString),
|
||||
|
||||
#[fail(display = "package name is missing - {:?}", _0)]
|
||||
ProjectNameInvalid(OsString),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for NewError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
NewError::ManifestError(error)
|
||||
}
|
||||
}
|
20
leo/errors/commands/run.rs
Normal file
20
leo/errors/commands/run.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use std::ffi::OsString;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum RunError {
|
||||
|
||||
#[fail(display = "main file {:?} does not exist", _0)]
|
||||
MainFileDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for RunError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
RunError::ManifestError(error)
|
||||
}
|
||||
}
|
27
leo/errors/directory/inputs.rs
Normal file
27
leo/errors/directory/inputs.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum InputsDirectoryError {
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "file entry getting: {}", _0)]
|
||||
GettingFileEntry(io::Error),
|
||||
|
||||
#[fail(display = "file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[fail(display = "file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[fail(display = "invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
|
||||
#[fail(display = "invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[fail(display = "reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
}
|
8
leo/errors/directory/mod.rs
Normal file
8
leo/errors/directory/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod inputs;
|
||||
pub use self::inputs::*;
|
||||
|
||||
pub mod outputs;
|
||||
pub use self::outputs::*;
|
||||
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
30
leo/errors/directory/outputs.rs
Normal file
30
leo/errors/directory/outputs.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum OutputsDirectoryError {
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "file entry getting: {}", _0)]
|
||||
GettingFileEntry(io::Error),
|
||||
|
||||
#[fail(display = "file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[fail(display = "file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[fail(display = "invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
|
||||
#[fail(display = "invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[fail(display = "reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
#[fail(display = "removing: {}", _0)]
|
||||
Removing(io::Error),
|
||||
|
||||
}
|
27
leo/errors/directory/source.rs
Normal file
27
leo/errors/directory/source.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum SourceDirectoryError {
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "file entry getting: {}", _0)]
|
||||
GettingFileEntry(io::Error),
|
||||
|
||||
#[fail(display = "file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[fail(display = "file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[fail(display = "invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
|
||||
#[fail(display = "invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[fail(display = "reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
}
|
21
leo/errors/files/main.rs
Normal file
21
leo/errors/files/main.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum MainFileError {
|
||||
|
||||
#[fail(display = "{}: {}", _0, _1)]
|
||||
Crate(&'static str, String),
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "writing: {}", _0)]
|
||||
Writing(io::Error),
|
||||
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for MainFileError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
MainFileError::Crate("std::io", format!("{}", error))
|
||||
}
|
||||
}
|
2
leo/errors/files/mod.rs
Normal file
2
leo/errors/files/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod main;
|
||||
pub use self::main::*;
|
24
leo/errors/manifest.rs
Normal file
24
leo/errors/manifest.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ManifestError {
|
||||
|
||||
#[fail(display = "`{}` creating: {}", _0, _1)]
|
||||
Creating(&'static str, io::Error),
|
||||
|
||||
#[fail(display = "`{}` metadata: {}", _0, _1)]
|
||||
Metadata(&'static str, io::Error),
|
||||
|
||||
#[fail(display = "`{}` opening: {}", _0, _1)]
|
||||
Opening(&'static str, io::Error),
|
||||
|
||||
#[fail(display = "`{}` parsing: {}", _0, _1)]
|
||||
Parsing(&'static str, toml::de::Error),
|
||||
|
||||
#[fail(display = "`{}` reading: {}", _0, _1)]
|
||||
Reading(&'static str, io::Error),
|
||||
|
||||
#[fail(display = "`{}` writing: {}", _0, _1)]
|
||||
Writing(&'static str, io::Error),
|
||||
|
||||
}
|
14
leo/errors/mod.rs
Normal file
14
leo/errors/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pub mod cli;
|
||||
pub use self::cli::*;
|
||||
|
||||
pub mod commands;
|
||||
pub use self::commands::*;
|
||||
|
||||
pub mod directory;
|
||||
pub use self::directory::*;
|
||||
|
||||
pub mod files;
|
||||
pub use self::files::*;
|
||||
|
||||
pub mod manifest;
|
||||
pub use self::manifest::*;
|
58
leo/files/main.rs
Normal file
58
leo/files/main.rs
Normal file
@ -0,0 +1,58 @@
|
||||
//! The `main.leo` file.
|
||||
|
||||
use crate::directories::source::SOURCE_DIRECTORY_NAME;
|
||||
use crate::errors::MainFileError;
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub static MAIN_FILE_NAME: &str = "main.leo";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MainFile {
|
||||
pub package_name: String,
|
||||
}
|
||||
|
||||
impl MainFile {
|
||||
pub fn new(package_name: &str) -> Self {
|
||||
Self { package_name: package_name.to_string() }
|
||||
}
|
||||
|
||||
pub fn exists_at(path: &PathBuf) -> bool {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
if !path.ends_with(SOURCE_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
}
|
||||
path.push(PathBuf::from(MAIN_FILE_NAME));
|
||||
}
|
||||
path.exists()
|
||||
}
|
||||
|
||||
pub fn write_to(self, path: &PathBuf) -> Result<(), MainFileError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
if !path.ends_with(SOURCE_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
}
|
||||
path.push(PathBuf::from(MAIN_FILE_NAME));
|
||||
}
|
||||
|
||||
let mut file = File::create(&path)?;
|
||||
Ok(file.write_all(self.template().as_bytes())?)
|
||||
}
|
||||
|
||||
fn template(&self) -> String {
|
||||
format!(
|
||||
r#"// The '{}' main function.
|
||||
function main() -> (u32) {{
|
||||
a = 1 + 1
|
||||
return a
|
||||
}}
|
||||
"#,
|
||||
self.package_name
|
||||
)
|
||||
}
|
||||
}
|
2
leo/files/mod.rs
Normal file
2
leo/files/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod main;
|
||||
pub use self::main::*;
|
12
leo/lib.rs
Normal file
12
leo/lib.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
pub mod cli;
|
||||
pub mod cli_types;
|
||||
pub mod commands;
|
||||
pub mod directories;
|
||||
pub mod errors;
|
||||
pub mod files;
|
||||
pub mod logger;
|
||||
pub mod manifest;
|
45
leo/logger.rs
Normal file
45
leo/logger.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use colored::Colorize;
|
||||
use std::io::Write;
|
||||
|
||||
const LEVEL_NAME_LENGTH: usize = 10;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn level_string(level: log::Level) -> colored::ColoredString {
|
||||
match level {
|
||||
log::Level::Error => "ERROR".bold().red(),
|
||||
log::Level::Warn => "WARN".bold().yellow(),
|
||||
log::Level::Info => "INFO".bold().blue(),
|
||||
log::Level::Debug => "DEBUG".bold().magenta(),
|
||||
log::Level::Trace => "TRACE".bold(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize logger with custom format and verbosity.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `verbosity` - Verbosity level. 0 for `Warn`, 1 for `Info`, 2 for `Debug`, more for `Trace`
|
||||
pub fn init_logger(app_name: &'static str, verbosity: usize) {
|
||||
env_logger::builder()
|
||||
.filter_level(match verbosity {
|
||||
0 => log::LevelFilter::Warn,
|
||||
1 => log::LevelFilter::Info,
|
||||
2 => log::LevelFilter::Debug,
|
||||
_ => log::LevelFilter::Trace,
|
||||
})
|
||||
.format(move |buf, record| {
|
||||
let mut padding = String::from("\n");
|
||||
for _ in 0..(app_name.len() + LEVEL_NAME_LENGTH + 4) {
|
||||
padding.push(' ');
|
||||
}
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"[{:>5} {:>5}] {}",
|
||||
level_string(record.level()),
|
||||
app_name,
|
||||
record.args().to_string().replace("\n", &padding)
|
||||
)
|
||||
})
|
||||
.init();
|
||||
}
|
45
leo/main.rs
Normal file
45
leo/main.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use leo::{cli::*, commands::*, logger};
|
||||
use leo::errors::CLIError;
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn main() -> Result<(), CLIError> {
|
||||
logger::init_logger("leo", 1);
|
||||
|
||||
let arguments = App::new("leo")
|
||||
.version("v0.1.0")
|
||||
.about("Leo compiler and package manager")
|
||||
.author("The Aleo Team <hello@aleo.org>")
|
||||
.settings(&[
|
||||
AppSettings::ColoredHelp,
|
||||
AppSettings::DisableHelpSubcommand,
|
||||
AppSettings::DisableVersion,
|
||||
AppSettings::SubcommandRequiredElseHelp,
|
||||
])
|
||||
// TODO (howardwu): Print subcommands in non-alphabetical order, instead print as ordered here.
|
||||
.subcommands(vec![
|
||||
NewCommand::new(),
|
||||
InitCommand::new(),
|
||||
BuildCommand::new(),
|
||||
SetupCommand::new(),
|
||||
RunCommand::new(),
|
||||
])
|
||||
.set_term_width(0)
|
||||
.get_matches();
|
||||
|
||||
match arguments.subcommand() {
|
||||
("new", Some(arguments)) => NewCommand::output(NewCommand::parse(arguments)?),
|
||||
("init", Some(arguments)) => InitCommand::output(InitCommand::parse(arguments)?),
|
||||
("build", Some(arguments)) => {
|
||||
BuildCommand::output(BuildCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
},
|
||||
("setup", Some(arguments)) => {
|
||||
SetupCommand::output(SetupCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
},
|
||||
("run", Some(arguments)) => RunCommand::output(RunCommand::parse(arguments)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
86
leo/manifest.rs
Normal file
86
leo/manifest.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub static FILE_NAME_DEFAULT: &str = "Leo.toml";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Package {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Manifest {
|
||||
pub package: Package,
|
||||
}
|
||||
|
||||
impl Manifest {
|
||||
pub fn new(package_name: &str) -> Self {
|
||||
Self {
|
||||
package: Package {
|
||||
name: package_name.to_owned(),
|
||||
version: "0.1.0".to_owned(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exists_at(path: &PathBuf) -> bool {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
path.push(PathBuf::from(FILE_NAME_DEFAULT));
|
||||
}
|
||||
path.exists()
|
||||
}
|
||||
|
||||
pub fn write_to(self, path: &PathBuf) -> Result<(), ManifestError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
path.push(PathBuf::from(FILE_NAME_DEFAULT));
|
||||
}
|
||||
|
||||
let mut file =
|
||||
File::create(&path).map_err(|error| ManifestError::Creating(FILE_NAME_DEFAULT, error))?;
|
||||
file.write_all(self.template().as_bytes())
|
||||
.map_err(|error| ManifestError::Writing(FILE_NAME_DEFAULT, error))
|
||||
}
|
||||
|
||||
fn template(&self) -> String {
|
||||
format!(
|
||||
r#"[package]
|
||||
name = "{}"
|
||||
version = "0.1.0"
|
||||
"#,
|
||||
self.package.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&PathBuf> for Manifest {
|
||||
type Error = ManifestError;
|
||||
|
||||
fn try_from(path: &PathBuf) -> Result<Self, Self::Error> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
path.push(PathBuf::from(FILE_NAME_DEFAULT));
|
||||
}
|
||||
|
||||
let mut file =
|
||||
File::open(path).map_err(|error| ManifestError::Opening(FILE_NAME_DEFAULT, error))?;
|
||||
let size = file
|
||||
.metadata()
|
||||
.map_err(|error| ManifestError::Metadata(FILE_NAME_DEFAULT, error))?
|
||||
.len() as usize;
|
||||
|
||||
let mut buffer = String::with_capacity(size);
|
||||
file.read_to_string(&mut buffer)
|
||||
.map_err(|error| ManifestError::Reading(FILE_NAME_DEFAULT, error))?;
|
||||
|
||||
Ok(toml::from_str(&buffer).map_err(|error| ManifestError::Parsing(FILE_NAME_DEFAULT, error))?)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user