Thread down environment module from cli down to the type-checker

We simply provide a flag with a free-form output which acts as
  the module to lookup in the 'env' folder. The strategy is to replace
  the environment module name on-the-fly when a user tries to import
  'env'.

  If the environment isn't found, an 'UnknownModule' error is raised
  (which I will slightly adjust in a following commits to something more
  related to environment)

  There are few important consequences to this design which may not seem
  immediately obvious:

  1. We parse and type-check every env modules, even if they aren't
     used. This ensures that code doesn't break with a compilation error
     simply because people forgot to type-check a given env.

     Note that compilation could still fail because the env module
     itself could provide an invalid API. So it only prevents each
     modules to be independently wrong when taken in isolation.

  2. Technically, this also means that one can import env modules in
     other env modules by their names. I don't know if it's a good or
     bad idea at this point but it doesn't really do any wrong;
     dependencies and cycles are handlded all-the-same.
This commit is contained in:
KtorZ
2024-08-04 10:27:32 +02:00
parent c9d0da0c22
commit fbe2f82582
16 changed files with 73 additions and 63 deletions

View File

@@ -32,7 +32,7 @@ use crate::{
};
use aiken_lang::{
ast::{
DataTypeKey, Definition, FunctionAccessKey, ModuleKind, Tracing, TypedDataType,
self, DataTypeKey, Definition, FunctionAccessKey, ModuleKind, Tracing, TypedDataType,
TypedFunction,
},
builtins,
@@ -65,8 +65,6 @@ use uplc::{
PlutusData,
};
const DEFAULT_ENV_MODULE: &str = "default";
#[derive(Debug)]
pub struct Source {
pub path: PathBuf,
@@ -186,10 +184,16 @@ where
self.defined_modules = checkpoint.defined_modules;
}
pub fn build(&mut self, uplc: bool, tracing: Tracing) -> Result<(), Vec<Error>> {
pub fn build(
&mut self,
uplc: bool,
tracing: Tracing,
env: Option<String>,
) -> Result<(), Vec<Error>> {
let options = Options {
code_gen_mode: CodeGenMode::Build(uplc),
tracing,
env,
};
self.compile(options)
@@ -211,7 +215,7 @@ where
let mut modules = self.parse_sources(self.config.name.clone())?;
self.type_check(&mut modules, Tracing::silent(), false)?;
self.type_check(&mut modules, Tracing::silent(), None, false)?;
let destination = destination.unwrap_or_else(|| self.root.join("docs"));
@@ -252,9 +256,11 @@ where
seed: u32,
property_max_success: usize,
tracing: Tracing,
env: Option<String>,
) -> Result<(), Vec<Error>> {
let options = Options {
tracing,
env,
code_gen_mode: if skip_tests {
CodeGenMode::NoOp
} else {
@@ -307,7 +313,7 @@ where
let mut modules = self.parse_sources(self.config.name.clone())?;
self.type_check(&mut modules, options.tracing, true)?;
self.type_check(&mut modules, options.tracing, options.env.as_deref(), true)?;
match options.code_gen_mode {
CodeGenMode::Build(uplc_dump) => {
@@ -725,6 +731,7 @@ where
&mut self,
modules: &mut ParsedModules,
tracing: Tracing,
env: Option<&str>,
validate_module_name: bool,
) -> Result<(), Vec<Error>> {
let our_modules: BTreeSet<String> = modules.keys().cloned().collect();
@@ -737,6 +744,7 @@ where
&self.id_gen,
&self.config.name.to_string(),
tracing,
env,
validate_module_name,
&mut self.module_sources,
&mut self.module_types,
@@ -905,7 +913,7 @@ where
}
if keep {
if self.module_name(dir, &path).as_str() == DEFAULT_ENV_MODULE {
if self.module_name(dir, &path).as_str() == ast::DEFAULT_ENV_MODULE {
has_default = Some(true);
}
self.add_module(path, dir, kind)

View File

@@ -51,6 +51,7 @@ impl ParsedModule {
id_gen: &IdGenerator,
package: &str,
tracing: Tracing,
env: Option<&str>,
validate_module_name: bool,
module_sources: &mut HashMap<String, (String, LineNumbers)>,
module_types: &mut HashMap<String, TypeInfo>,
@@ -68,6 +69,7 @@ impl ParsedModule {
module_types,
tracing,
&mut warnings,
env,
)
.map_err(|error| Error::Type {
path: self.path.clone(),

View File

@@ -3,6 +3,7 @@ use aiken_lang::ast::Tracing;
pub struct Options {
pub code_gen_mode: CodeGenMode,
pub tracing: Tracing,
pub env: Option<String>,
}
impl Default for Options {
@@ -10,6 +11,7 @@ impl Default for Options {
Self {
code_gen_mode: CodeGenMode::NoOp,
tracing: Tracing::silent(),
env: None,
}
}
}

View File

@@ -1314,6 +1314,7 @@ mod test {
&module_types,
Tracing::All(TraceLevel::Verbose),
&mut warnings,
None,
)
.expect("Failed to type-check module.");

View File

@@ -99,6 +99,7 @@ impl TestProject {
&self.module_types,
Tracing::All(TraceLevel::Verbose),
&mut warnings,
None,
)
.expect("Failed to type-check module");