Merge pull request #3531 from rtfeldman/decode

Very basic Decode.roc in the standard library
This commit is contained in:
Ayaz 2022-08-02 14:26:28 -05:00 committed by GitHub
commit fa14146054
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 588 additions and 90 deletions

View file

@ -6,7 +6,7 @@ use roc_module::symbol::Symbol;
use roc_region::all::{Loc, Region};
use roc_solve_problem::{TypeError, UnderivableReason, Unfulfilled};
use roc_types::subs::{instantiate_rigids, Content, FlatType, GetSubsSlice, Rank, Subs, Variable};
use roc_types::types::{AliasKind, Category, PatternCategory};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory};
use roc_unify::unify::{Env, MustImplementConstraints};
use roc_unify::unify::{MustImplementAbility, Obligated};
@ -547,7 +547,7 @@ pub fn type_implementing_specialization(
}
/// Result of trying to resolve an ability specialization.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub enum Resolved {
/// A user-defined specialization should be used.
Specialization(Symbol),
@ -555,23 +555,61 @@ pub enum Resolved {
NeedsGenerated,
}
pub fn resolve_ability_specialization(
/// An [`AbilityResolver`] is a shell of an abilities store that answers questions needed for
/// [resolving ability specializations][`resolve_ability_specialization`].
///
/// The trait is provided so you can implement your own resolver at other points in the compilation
/// process, for example during monomorphization we have module-re-entrant ability stores that are
/// not available during solving.
pub trait AbilityResolver {
/// Gets the parent ability and type of an ability member.
///
/// If needed, the type of the ability member will be imported into a local `subs` buffer; as
/// such, subs must be provided.
fn member_parent_and_signature_var(
&self,
ability_member: Symbol,
home_subs: &mut Subs,
) -> Option<(Symbol, Variable)>;
/// Finds the declared implementation of an [`ImplKey`][roc_can::abilities::ImplKey].
fn get_implementation(&self, impl_key: roc_can::abilities::ImplKey) -> Option<MemberImpl>;
}
/// Trivial implementation of a resolver for a module-local abilities store, that defers all
/// queries to the module store.
impl AbilityResolver for AbilitiesStore {
#[inline(always)]
fn member_parent_and_signature_var(
&self,
ability_member: Symbol,
_home_subs: &mut Subs, // only have access to one abilities store, do nothing with subs
) -> Option<(Symbol, Variable)> {
self.member_def(ability_member)
.map(|def| (def.parent_ability, def.signature_var()))
}
#[inline(always)]
fn get_implementation(&self, impl_key: roc_can::abilities::ImplKey) -> Option<MemberImpl> {
self.get_implementation(impl_key).copied()
}
}
pub fn resolve_ability_specialization<R: AbilityResolver>(
subs: &mut Subs,
abilities_store: &AbilitiesStore,
resolver: &R,
ability_member: Symbol,
specialization_var: Variable,
) -> Option<Resolved> {
use roc_unify::unify::{unify, Mode};
let member_def = abilities_store
.member_def(ability_member)
let (parent_ability, signature_var) = resolver
.member_parent_and_signature_var(ability_member, subs)
.expect("Not an ability member symbol");
// Figure out the ability we're resolving in a temporary subs snapshot.
let snapshot = subs.snapshot();
let signature_var = member_def.signature_var();
instantiate_rigids(subs, signature_var);
let (_vars, must_implement_ability, _lambda_sets_to_specialize, _meta) = unify(
&mut Env::new(subs),
@ -585,8 +623,7 @@ pub fn resolve_ability_specialization(
subs.rollback_to(snapshot);
let obligated =
type_implementing_specialization(&must_implement_ability, member_def.parent_ability)?;
let obligated = type_implementing_specialization(&must_implement_ability, parent_ability)?;
let resolved = match obligated {
Obligated::Opaque(symbol) => {
@ -595,9 +632,9 @@ pub fn resolve_ability_specialization(
ability_member,
};
match abilities_store.get_implementation(impl_key)? {
match resolver.get_implementation(impl_key)? {
roc_types::types::MemberImpl::Impl(spec_symbol) => {
Resolved::Specialization(*spec_symbol)
Resolved::Specialization(spec_symbol)
}
roc_types::types::MemberImpl::Derived => Resolved::NeedsGenerated,
// TODO this is not correct. We can replace `Resolved` with `MemberImpl` entirely,