Merge attempt

This commit is contained in:
Sam Mohr 2024-08-19 23:34:05 -07:00
parent 7c15c16ae0
commit 12df3a04de
No known key found for this signature in database
GPG key ID: EA41D161A3C1BC99
236 changed files with 9053 additions and 6428 deletions

View file

@ -10,6 +10,7 @@ use crate::annotation::IntroducedVariables;
use crate::annotation::OwnedNamedOrAble;
use crate::derive;
use crate::env::Env;
use crate::expr::canonicalize_record;
use crate::expr::get_lookup_symbols;
use crate::expr::AnnotatedMark;
use crate::expr::ClosureData;
@ -18,6 +19,7 @@ use crate::expr::Expr::{self, *};
use crate::expr::StructAccessorData;
use crate::expr::{canonicalize_expr, Output, Recursive};
use crate::pattern::{canonicalize_def_header_pattern, BindingsFromPattern, Pattern};
use crate::procedure::QualifiedReference;
use crate::procedure::References;
use crate::scope::create_alias;
use crate::scope::{PendingAbilitiesInScope, Scope};
@ -160,6 +162,13 @@ enum PendingValueDef<'a> {
&'a Loc<ast::TypeAnnotation<'a>>,
&'a Loc<ast::Expr<'a>>,
),
/// Module params from an import
ImportParams {
symbol: Symbol,
loc_pattern: Loc<Pattern>,
module_id: ModuleId,
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
},
/// Ingested file
IngestedFile(
Loc<Pattern>,
@ -174,6 +183,12 @@ impl PendingValueDef<'_> {
PendingValueDef::AnnotationOnly(loc_pattern, _) => loc_pattern,
PendingValueDef::Body(loc_pattern, _) => loc_pattern,
PendingValueDef::TypedBody(_, loc_pattern, _, _) => loc_pattern,
PendingValueDef::ImportParams {
loc_pattern,
symbol: _,
module_id: _,
opt_provided: _,
} => loc_pattern,
PendingValueDef::IngestedFile(loc_pattern, _, _) => loc_pattern,
}
}
@ -485,6 +500,16 @@ fn canonicalize_alias<'a>(
}
}
#[macro_export]
macro_rules! params_in_abilities_unimplemented {
($lookup:expr) => {
match $lookup.module_params {
None => $lookup.symbol,
Some(_) => unimplemented!("params in abilities"),
}
};
}
/// Canonicalizes a claimed ability implementation like `{ eq }` or `{ eq: myEq }`.
/// Returns a mapping of the ability member to the implementation symbol.
/// If there was an error, a problem will be recorded and nothing is returned.
@ -503,7 +528,7 @@ fn canonicalize_claimed_ability_impl<'a>(
let member_symbol =
match env.qualified_lookup_with_module_id(scope, ability_home, label_str, region) {
Ok(symbol) => symbol,
Ok(lookup) => params_in_abilities_unimplemented!(lookup),
Err(_) => {
env.problem(Problem::NotAnAbilityMember {
ability,
@ -546,8 +571,13 @@ fn canonicalize_claimed_ability_impl<'a>(
// To handle both cases, try checking for a shadow first, then check for a direct
// reference. We want to check for a direct reference second so that if there is a
// shadow, we won't accidentally grab the imported symbol.
let opt_impl_symbol = (scope.lookup_ability_member_shadow(member_symbol))
.or_else(|| scope.lookup_str(label_str, region).ok());
let opt_impl_symbol =
(scope.lookup_ability_member_shadow(member_symbol)).or_else(|| {
scope
.lookup_str(label_str, region)
.map(|s| params_in_abilities_unimplemented!(s))
.ok()
});
match opt_impl_symbol {
// It's possible that even if we find a symbol it is still only the member
@ -599,7 +629,7 @@ fn canonicalize_claimed_ability_impl<'a>(
label.value,
label.region,
) {
Ok(symbol) => symbol,
Ok(lookup) => params_in_abilities_unimplemented!(lookup),
Err(_) => {
env.problem(Problem::NotAnAbilityMember {
ability,
@ -611,7 +641,7 @@ fn canonicalize_claimed_ability_impl<'a>(
};
let impl_symbol = match scope.lookup(&impl_ident.into(), impl_region) {
Ok(symbol) => symbol,
Ok(symbol) => params_in_abilities_unimplemented!(symbol),
Err(err) => {
env.problem(Problem::RuntimeError(err));
return Err(());
@ -1109,8 +1139,24 @@ fn canonicalize_value_defs<'a>(
PendingValue::ExpectFx(pending_expect) => {
pending_expect_fx.push(pending_expect);
}
PendingValue::ModuleImport(introduced_import) => {
imports_introduced.push(introduced_import);
PendingValue::ModuleImport(PendingModuleImport {
module_id,
region,
exposed_symbols,
params,
}) => {
imports_introduced.push(IntroducedImport {
module_id,
region,
exposed_symbols,
});
pending_value_defs.push(PendingValueDef::ImportParams {
symbol: params.symbol,
loc_pattern: params.loc_pattern,
opt_provided: params.opt_provided,
module_id,
});
}
PendingValue::InvalidIngestedFile => { /* skip */ }
PendingValue::ImportNameConflict => { /* skip */ }
@ -1558,7 +1604,7 @@ impl DefOrdering {
fn insert_symbol_references(&mut self, def_id: u32, def_references: &DefReferences) {
match def_references {
DefReferences::Value(references) => {
let it = references.value_lookups().chain(references.calls());
let it = references.value_lookups();
for referenced in it {
if let Some(ref_id) = self.get_id(*referenced) {
@ -2352,6 +2398,50 @@ fn canonicalize_pending_value_def<'a>(
None,
)
}
ImportParams {
symbol,
loc_pattern,
module_id,
opt_provided,
} => {
// Insert a reference to the record so that we don't report it as unused
// If the whole module is unused, we'll report that separately
output
.references
.insert_value_lookup(symbol, QualifiedReference::Unqualified);
let (opt_var_record, references) = match opt_provided {
Some(params) => {
let (record, can_output) =
canonicalize_record(env, var_store, scope, loc_pattern.region, params);
let references = can_output.references.clone();
output.union(can_output);
(Some((var_store.fresh(), Box::new(record))), references)
}
None => (None, References::new()),
};
let loc_expr = Loc::at(
loc_pattern.region,
Expr::ImportParams(module_id, loc_pattern.region, opt_var_record),
);
let def = single_can_def(
loc_pattern,
loc_expr,
var_store.fresh(),
None,
SendMap::default(),
);
DefOutput {
output,
references: DefReferences::Value(references),
def,
}
}
IngestedFile(loc_pattern, opt_loc_ann, path_literal) => {
let relative_path =
if let ast::StrLiteral::PlainLine(ingested_path) = path_literal.value {
@ -2892,7 +2982,7 @@ enum PendingValue<'a> {
Dbg(PendingExpectOrDbg<'a>),
Expect(PendingExpectOrDbg<'a>),
ExpectFx(PendingExpectOrDbg<'a>),
ModuleImport(IntroducedImport),
ModuleImport(PendingModuleImport<'a>),
SignatureDefMismatch,
InvalidIngestedFile,
ImportNameConflict,
@ -2903,6 +2993,19 @@ struct PendingExpectOrDbg<'a> {
preceding_comment: Region,
}
struct PendingModuleImport<'a> {
module_id: ModuleId,
region: Region,
exposed_symbols: Vec<(Symbol, Region)>,
params: PendingModuleImportParams<'a>,
}
struct PendingModuleImportParams<'a> {
symbol: Symbol,
loc_pattern: Loc<Pattern>,
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
}
pub struct IntroducedImport {
module_id: ModuleId,
region: Region,
@ -3042,10 +3145,27 @@ fn to_pending_value_def<'a>(
None => module_name.clone(),
};
// Generate a symbol for the module params def
// We do this even if params weren't provided so that solve can report if they are missing
let params_sym = scope.gen_unique_symbol();
let params_region = module_import.params.map(|p| p.params.region).unwrap_or(region);
let params =
PendingModuleImportParams {
symbol: params_sym,
loc_pattern: Loc::at(params_region, Pattern::Identifier(params_sym)),
opt_provided: module_import.params.map(|p| p.params.value),
};
let provided_params_sym = if module_import.params.is_some() {
// Only add params to scope if they are provided
Some(params_sym)
} else {
None
};
if let Err(existing_import) =
scope
.modules
.insert(name_with_alias.clone(), module_id, region)
.insert(name_with_alias.clone(), module_id, provided_params_sym, region)
{
env.problems.push(Problem::ImportNameConflict {
name: name_with_alias,
@ -3056,7 +3176,7 @@ fn to_pending_value_def<'a>(
});
return PendingValue::ImportNameConflict;
}
};
let exposed_names = module_import
.exposed
@ -3108,13 +3228,13 @@ fn to_pending_value_def<'a>(
}))
}
}
}
PendingValue::ModuleImport(IntroducedImport {
PendingValue::ModuleImport(PendingModuleImport {
module_id,
region,
exposed_symbols,
params,
})
}
IngestedFileImport(ingested_file) => {