Skip to content

Commit

Permalink
feat: implement Assembler::add_modules_from_dir()
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbinth committed Aug 12, 2024
1 parent 2414c9b commit fe33a48
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 199 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#### Enhancements

- Added `with-debug-info` feature to `miden-stdlib` (#1445).
- Added `Assembler::add_modules_from_dir()` method (#1445).
- [BREAKING] Implemented building of multi-module kernels (#1445).

#### Changes
Expand Down
25 changes: 25 additions & 0 deletions assembly/src/assembler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,31 @@ impl Assembler {
Ok(())
}

/// Adds all modules (defined by ".masm" files) from the specified directory to the module
/// of this assembler graph.
///
/// The modules will be added under the specified namespace, but otherwise preserving the
/// structure of the directory. Any module named `mod.masm` will be added using parent
/// directory path For example, if `namespace` = "ns", modules from the ~/masm directory
/// will be added as follows:
///
/// - ~/masm/foo.masm -> "ns::foo"
/// - ~/masm/bar/mod.masm -> "ns::bar"
/// - ~/masm/bar/baz.masm -> "ns::bar::baz"
#[cfg(feature = "std")]
pub fn add_modules_from_dir(
&mut self,
namespace: crate::LibraryNamespace,
dir: &std::path::Path,
) -> Result<(), Report> {
let source_manager = self.source_manager.clone();
for module in crate::parser::read_modules_from_dir(namespace, dir, source_manager)? {
self.module_graph.add_ast_module(module)?;
}

Ok(())
}

/// Adds the compiled library to provide modules for the compilation.
pub fn add_library(&mut self, library: impl AsRef<Library>) -> Result<(), Report> {
self.module_graph
Expand Down
12 changes: 12 additions & 0 deletions assembly/src/ast/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ pub struct Module {
pub(crate) procedures: Vec<Export>,
}

/// Constants
impl Module {
/// File extension for a Assembly Module.
pub const FILE_EXTENSION: &'static str = "masm";

/// Name of the root module.
pub const ROOT: &'static str = "mod";

/// File name of the root module.
pub const ROOT_FILENAME: &'static str = "mod.masm";
}

/// Construction
impl Module {
/// Creates a new [Module] with the specified `kind` and fully-qualified path, e.g.
Expand Down
12 changes: 1 addition & 11 deletions assembly/src/library/error.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
use vm_core::errors::KernelError;

use crate::{ast::QualifiedProcedureName, diagnostics::Diagnostic, LibraryNamespace, LibraryPath};
use crate::{ast::QualifiedProcedureName, diagnostics::Diagnostic};

#[derive(Debug, thiserror::Error, Diagnostic)]
pub enum LibraryError {
#[error("kernel library must contain at least one exported procedure")]
#[diagnostic()]
EmptyKernel,
#[error("duplicate module '{0}'")]
#[diagnostic()]
DuplicateModulePath(LibraryPath),
#[error("invalid export in kernel library: {procedure_path}")]
InvalidKernelExport { procedure_path: QualifiedProcedureName },
#[error(transparent)]
Kernel(#[from] KernelError),
#[error("library '{name}' contains {count} modules, but the max is {max}")]
#[diagnostic()]
TooManyModulesInLibrary {
name: LibraryNamespace,
count: usize,
max: usize,
},
}
98 changes: 0 additions & 98 deletions assembly/src/library/masl.rs

This file was deleted.

97 changes: 7 additions & 90 deletions assembly/src/library/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ use vm_core::{
use crate::ast::{ProcedureName, QualifiedProcedureName};

mod error;
#[cfg(feature = "std")]
mod masl;
mod module;
mod namespace;
mod path;
Expand All @@ -33,13 +31,6 @@ pub use self::{
#[cfg(test)]
mod tests;

// CONSTANTS
// ================================================================================================

/// Maximum number of modules in a library.
#[cfg(feature = "std")]
const MAX_MODULES: usize = u16::MAX as usize;

// LIBRARY
// ================================================================================================

Expand Down Expand Up @@ -209,29 +200,18 @@ fn content_hash(

#[cfg(feature = "std")]
mod use_std_library {
use std::{boxed::Box, collections::btree_map::Entry, fs, io, path::Path, sync::Arc};
use std::{fs, io, path::Path};

use masl::{LibraryEntry, WalkLibrary};
use miette::{Context, Report};
use miette::Report;
use vm_core::utils::ReadAdapter;

use super::*;
use crate::{
ast::{self, ModuleKind},
diagnostics::IntoDiagnostic,
Assembler, SourceManager,
};
use crate::Assembler;

impl Library {
/// File extension for the Assembly Library.
pub const LIBRARY_EXTENSION: &'static str = "masl";

/// File extension for the Assembly Module.
pub const MODULE_EXTENSION: &'static str = "masm";

/// Name of the root module.
pub const MOD: &'static str = "mod";

/// Write the library to a target file
///
/// NOTE: It is up to the caller to use the correct file extension, but there is no
Expand Down Expand Up @@ -294,68 +274,10 @@ mod use_std_library {
assembler: Assembler,
) -> Result<Self, Report> {
let path = path.as_ref();
let modules = Self::read_modules_from_dir(namespace, path, assembler.source_manager())?;
assembler.assemble_library(modules)
}

/// Read the contents (modules) of this library from `dir`, returning any errors that occur
/// while traversing the file system.
///
/// Errors may also be returned if traversal discovers issues with the library, such as
/// invalid names, etc.
///
/// Returns an iterator over all parsed modules.
pub(super) fn read_modules_from_dir(
namespace: LibraryNamespace,
dir: &Path,
source_manager: Arc<dyn SourceManager>,
) -> Result<impl Iterator<Item = Box<ast::Module>>, Report> {
if !dir.is_dir() {
return Err(Report::msg(format!(
"the provided path '{}' is not a valid directory",
dir.display()
)));
}

// mod.masm is not allowed in the root directory
if dir.join("mod.masm").exists() {
return Err(Report::msg("mod.masm is not allowed in the root directory"));
}

let mut modules = BTreeMap::default();

let walker = WalkLibrary::new(namespace.clone(), dir)
.into_diagnostic()
.wrap_err_with(|| format!("failed to load library from '{}'", dir.display()))?;
for entry in walker {
let LibraryEntry { mut name, source_path } = entry?;
if name.last() == Self::MOD {
name.pop();
}
// Parse module at the given path
let mut parser = ast::Module::parser(ModuleKind::Library);
let ast = parser.parse_file(name.clone(), &source_path, &source_manager)?;
match modules.entry(name) {
Entry::Occupied(ref entry) => {
return Err(LibraryError::DuplicateModulePath(entry.key().clone()))
.into_diagnostic();
},
Entry::Vacant(entry) => {
entry.insert(ast);
},
}
}

if modules.len() > MAX_MODULES {
return Err(LibraryError::TooManyModulesInLibrary {
name: namespace.clone(),
count: modules.len(),
max: MAX_MODULES,
}
.into());
}

Ok(modules.into_values())
let modules =
crate::parser::read_modules_from_dir(namespace, path, assembler.source_manager())?;
assembler.assemble_library(modules)
}

pub fn deserialize_from_file(path: impl AsRef<Path>) -> Result<Self, DeserializationError> {
Expand Down Expand Up @@ -557,12 +479,7 @@ mod use_std_kernel {
if let Some(lib_dir) = lib_dir {
let lib_dir = lib_dir.as_ref();
let namespace = LibraryNamespace::new("kernel").expect("invalid namespace");
let modules =
Library::read_modules_from_dir(namespace, lib_dir, assembler.source_manager())?;

for module in modules {
assembler.add_module(module)?;
}
assembler.add_modules_from_dir(namespace, lib_dir)?;
}

assembler.assemble_kernel(sys_module_path.as_ref())
Expand Down
Loading

0 comments on commit fe33a48

Please sign in to comment.