imports map, leo install

This commit is contained in:
damirka 2021-07-07 17:15:03 +03:00
parent 4c1298d179
commit bbc210d016
13 changed files with 100 additions and 28 deletions

View File

@ -28,6 +28,7 @@ use crate::{
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
use leo_asg::{Asg, AsgPass, FormattedError, Program as AsgProgram};
use leo_ast::{Input, MainInput, Program as AstProgram};
use leo_imports::ImportParser;
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
use leo_parser::parse_ast;
@ -39,6 +40,7 @@ use snarkvm_r1cs::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use sha2::{Digest, Sha256};
use std::{
collections::HashMap,
fs,
marker::PhantomData,
path::{Path, PathBuf},
@ -68,6 +70,7 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
asg: Option<AsgProgram<'a>>,
options: CompilerOptions,
proof_options: TheoremOptions,
imports_map: HashMap<String, String>,
_engine: PhantomData<F>,
_group: PhantomData<G>,
}
@ -83,6 +86,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<TheoremOptions>,
imports_map: HashMap<String, String>,
) -> Self {
Self {
program_name: package_name.clone(),
@ -94,6 +98,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context,
options: options.unwrap_or_default(),
proof_options: proof_options.unwrap_or_default(),
imports_map,
_engine: PhantomData,
_group: PhantomData,
}
@ -113,6 +118,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<TheoremOptions>,
imports_map: HashMap<String, String>,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(
package_name,
@ -121,6 +127,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context,
options,
proof_options,
imports_map,
);
compiler.parse_program()?;
@ -152,6 +159,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<TheoremOptions>,
imports_map: HashMap<String, String>,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(
package_name,
@ -160,6 +168,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
context,
options,
proof_options,
imports_map,
);
compiler.parse_input(input_string, input_path, state_string, state_path)?;
@ -263,7 +272,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
let asg = Asg::new(
self.context,
&self.program,
&mut leo_imports::ImportParser::new(self.main_file_path.clone()),
&mut ImportParser::new(self.main_file_path.clone(), self.imports_map.clone()),
)?;
if self.proof_options.type_inferenced {

View File

@ -33,7 +33,7 @@ use leo_compiler::{
use snarkvm_curves::edwards_bls12::Fq;
use snarkvm_r1cs::TestConstraintSystem;
use std::path::PathBuf;
use std::{collections::HashMap, path::PathBuf};
pub const TEST_OUTPUT_DIRECTORY: &str = "/output/";
const EMPTY_FILE: &str = "";
@ -52,7 +52,15 @@ fn new_compiler() -> EdwardsTestCompiler {
let path = PathBuf::from("/test/src/main.leo");
let output_dir = PathBuf::from(TEST_OUTPUT_DIRECTORY);
EdwardsTestCompiler::new(program_name, path, output_dir, make_test_context(), None, None)
EdwardsTestCompiler::new(
program_name,
path,
output_dir,
make_test_context(),
None,
None,
HashMap::new(),
)
}
pub(crate) fn parse_program(program_string: &str) -> Result<EdwardsTestCompiler, CompilerError> {

View File

@ -14,7 +14,10 @@
// 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 std::path::{Path, PathBuf};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};
use leo_asg::*;
use leo_synthesizer::{CircuitSynthesizer, SerializedCircuit, SummarizedCircuit};
@ -40,7 +43,15 @@ fn new_compiler(path: PathBuf) -> EdwardsTestCompiler {
let program_name = "test".to_string();
let output_dir = PathBuf::from("/output/");
EdwardsTestCompiler::new(program_name, path, output_dir, make_test_context(), None, None)
EdwardsTestCompiler::new(
program_name,
path,
output_dir,
make_test_context(),
None,
None,
HashMap::new(),
)
}
pub(crate) fn parse_program(program_string: &str) -> Result<EdwardsTestCompiler, CompilerError> {

View File

@ -18,7 +18,7 @@ use crate::errors::ImportParserError;
use leo_asg::{AsgContext, AsgConvertError, ImportResolver, Program, Span};
use indexmap::{IndexMap, IndexSet};
use std::path::PathBuf;
use std::{collections::HashMap, path::PathBuf};
/// Stores imported packages.
///
@ -29,14 +29,16 @@ pub struct ImportParser<'a> {
program_path: PathBuf,
partial_imports: IndexSet<String>,
imports: IndexMap<String, Program<'a>>,
pub imports_map: HashMap<String, String>,
}
impl<'a> ImportParser<'a> {
pub fn new(program_path: PathBuf) -> Self {
pub fn new(program_path: PathBuf, imports_map: HashMap<String, String>) -> Self {
ImportParser {
program_path,
partial_imports: Default::default(),
imports: Default::default(),
imports_map,
}
}
}
@ -55,9 +57,8 @@ impl<'a> ImportResolver<'a> for ImportParser<'a> {
if let Some(program) = self.imports.get(&full_path) {
return Ok(Some(program.clone()));
}
let mut imports = Self::default();
let path = self.program_path.clone();
let mut imports = self.clone(); // Self::default() was previously
self.partial_imports.insert(full_path.clone());
let program = imports
.parse_package(context, path, package_segments, span)

View File

@ -103,21 +103,30 @@ impl<'a> ImportParser<'a> {
.collect::<Result<Vec<_>, std::io::Error>>()
.map_err(|error| ImportParserError::directory_error(error, span, &error_path))?;
// Keeping backward compatibilty for existing packages.
// If index_map contains key, use it or try to access directly.
// TODO: Remove when migration is possible.
let package_name = self
.imports_map
.get(package_name)
.unwrap_or(&package_name.to_string())
.clone();
// Check if the imported package name is in the imports directory.
let matched_import_entry = entries
.into_iter()
.find(|entry| entry.file_name().into_string().unwrap().eq(package_name));
.find(|entry| entry.file_name().into_string().unwrap().eq(&package_name));
// Check if the package name was found in both the source and imports directory.
match (matched_source_entry, matched_import_entry) {
(Some(_), Some(_)) => Err(ImportParserError::conflicting_imports(Identifier::new_with_span(
package_name,
&package_name,
span.clone(),
))),
(Some(source_entry), None) => self.parse_package_access(context, &source_entry, &segments[1..], span),
(None, Some(import_entry)) => self.parse_package_access(context, &import_entry, &segments[1..], span),
(None, None) => Err(ImportParserError::unknown_package(Identifier::new_with_span(
package_name,
&package_name,
span.clone(),
))),
}

View File

@ -34,6 +34,8 @@ use snarkvm_r1cs::ConstraintSystem;
use structopt::StructOpt;
use tracing::span::Span;
use std::collections::HashMap;
/// Compiler Options wrapper for Build command. Also used by other commands which
/// require Build command output as their input.
#[derive(StructOpt, Clone, Debug)]
@ -126,7 +128,11 @@ impl Command for Build {
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
let path = context.dir()?;
let package_name = context.manifest()?.get_package_name();
let manifest = context
.manifest()
.map_err(|_| anyhow!("Package manifest not found, try running `leo init`"))?;
let package_name = manifest.get_package_name();
let imports_map = manifest.get_imports_map().unwrap_or(HashMap::new());
// Sanitize the package path to the root directory.
let mut package_path = path.clone();
@ -174,6 +180,7 @@ impl Command for Build {
thread_leaked_context(),
Some(self.compiler_options.clone().into()),
Some(self.compiler_options.into()),
imports_map,
)?;
// Compute the current program checksum

View File

@ -33,9 +33,6 @@ pub use deploy::Deploy;
pub mod init;
pub use init::Init;
pub mod install;
pub use install::Install;
pub mod lint;
pub use lint::Lint;

View File

@ -101,9 +101,9 @@ impl Command for Add {
// Attempt to fetch the package.
let reader = {
let fetch = Fetch {
author,
author: author.clone(),
package_name: package_name.clone(),
version: self.version,
version: self.version.clone(),
};
let bytes = context.api.run_route(fetch)?.bytes()?;
std::io::Cursor::new(bytes)
@ -114,7 +114,14 @@ impl Command for Add {
{
ImportsDirectory::create(&path)?;
path.push(IMPORTS_DIRECTORY_NAME);
path.push(package_name);
// Dumb compatibility hack.
// TODO: Remove once `leo add` functionality is discussed.
if self.version.is_some() {
path.push(format!("{}-{}@{}", author, package_name, self.version.unwrap()));
} else {
path.push(package_name);
}
create_dir_all(&path)?;
};

View File

@ -14,7 +14,10 @@
// 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::{commands::Command, context::Context};
use crate::{
commands::{package::Add, Command},
context::Context,
};
use anyhow::{anyhow, Result};
use structopt::StructOpt;
@ -43,20 +46,16 @@ impl Command for Install {
.get_package_dependencies()
.ok_or_else(|| anyhow!("Package has no dependencies"))?;
use crate::commands::package::Add;
for (_name, dep) in deps.iter() {
Add::new(
None,
Some(dep.author.clone()),
Some(dep.name.clone()),
Some(dep.package.clone()),
Some(dep.version.clone()),
)
.execute(context.clone())?;
}
dbg!(deps);
Ok(())
}
}

View File

@ -20,6 +20,9 @@ pub use add::Add;
pub mod clone;
pub use clone::Clone;
pub mod install;
pub use install::Install;
pub mod login;
pub use login::Login;

View File

@ -113,6 +113,7 @@ impl Command for Test {
thread_leaked_context(),
Some(self.compiler_options.clone().into()),
Some(self.compiler_options.clone().into()),
std::collections::HashMap::new(),
)?;
let temporary_program = program;

View File

@ -22,13 +22,12 @@ pub mod logger;
pub mod updater;
use commands::{
package::{Add, Clone, Login, Logout, Publish, Remove},
package::{Add, Clone, Install, Login, Logout, Publish, Remove},
Build,
Clean,
Command,
Deploy,
Init,
Install,
Lint,
New,
Prove,

View File

@ -38,7 +38,7 @@ pub struct Remote {
pub struct Dependency {
pub author: String,
pub version: String,
pub name: String,
pub package: String,
}
#[derive(Deserialize)]
@ -85,6 +85,23 @@ impl Manifest {
self.dependencies.clone()
}
/// Get HashMap of kind:
/// import name => import directory
/// Which then used in AST/ASG to resolve import paths.
pub fn get_imports_map(&self) -> Option<HashMap<String, String>> {
self.dependencies.clone().map(|dependencies| {
dependencies
.into_iter()
.map(|(name, dependency)| {
(
name,
format!("{}-{}@{}", dependency.author, dependency.package, dependency.version),
)
})
.collect()
})
}
pub fn get_package_license(&self) -> Option<String> {
self.project.license.clone()
}
@ -119,6 +136,10 @@ license = "MIT"
[remote]
author = "{author}" # Add your Aleo Package Manager username or team name.
[dependencies]
# Define dependencies here in format:
# name = {{ package = "package-name", author = "author", version = "version" }}
"#,
name = self.project.name,
author = author