This commit is contained in:
Richard Feldman 2023-09-06 21:24:52 -04:00 committed by Brendan Hansknecht
parent 00c27b087b
commit 34148645ae
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
6 changed files with 1139 additions and 46 deletions

View file

@ -33,6 +33,9 @@ interface Inspect
custom,
apply,
toInspector,
# TODO don't expose these - there's some way to do this!
inspectFn,
inspectOpaque,
]
imports [
Bool.{ Bool },
@ -57,12 +60,11 @@ InspectFormatter implements
set : set, ElemWalker state set elem, (elem -> Inspector f) -> Inspector f where f implements InspectFormatter
dict : dict, KeyValWalker state dict key value, (key -> Inspector f), (value -> Inspector f) -> Inspector f where f implements InspectFormatter
# Note opaque is used for both opaque types and functions.
# The auto deriver for functions probably could put the function type.
# For regular opaque types, I think we can use the type name, though that may lead to some reflection related issues that still need to be discussed.
# As a simple baseline, it can just use the exact words `opaque` and `function` for now.
# In text, this would render as `<opaque>`, `<function>`, etc
opaque : Str -> Inspector f where f implements InspectFormatter
# In text, this would render as `<opaque>`
opaque : Inspector f where f implements InspectFormatter
# In text, this would render as `<function>`
function : Inspector f where f implements InspectFormatter
u8 : U8 -> Inspector f where f implements InspectFormatter
i8 : I8 -> Inspector f where f implements InspectFormatter
@ -94,3 +96,11 @@ inspect : val -> f where val implements Inspect, f implements InspectFormatter
inspect = \val ->
(@Inspector valFn) = toInspector val
valFn (init {})
## Should not be exposed, only used in auto-deriving
inspectFn : * -> Inspector f where f implements InspectFormatter
inspectFn = \_ -> function
## Should not be exposed, only used in auto-deriving
inspectOpaque : * -> Inspector f where f implements InspectFormatter
inspectOpaque = \_ -> opaque

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@ use roc_can::expr::Expr;
use roc_can::pattern::Pattern;
use roc_can::{def::Def, module::ExposedByModule};
use roc_collections::{MutMap, VecMap};
use roc_derive_key::{inspect, DeriveKey};
use roc_derive_key::DeriveKey;
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_region::all::Loc;
use roc_types::subs::{
@ -19,7 +19,7 @@ use util::Env;
mod decoding;
mod encoding;
mod hash;
mod inspect;
mod util;
pub(crate) const DERIVED_SYNTH: ModuleId = ModuleId::DERIVED_SYNTH;

View file

@ -55,6 +55,7 @@ impl FlatEncodable {
FlatType::Record(fields, ext) => {
let (fields_iter, ext) = fields.unsorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyRecord))
})?;
@ -71,6 +72,7 @@ impl FlatEncodable {
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
@ -89,6 +91,7 @@ impl FlatEncodable {
// `t`-prefixed payload types.
let (tags_iter, ext) = tags.unsorted_tags_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext.var(), |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTagUnion))
})?;
@ -115,10 +118,9 @@ impl FlatEncodable {
)))
}
FlatType::EmptyRecord => Ok(Key(FlatEncodableKey::Record(vec![]))),
FlatType::EmptyTuple => todo!(),
FlatType::EmptyTagUnion => Ok(Key(FlatEncodableKey::TagUnion(vec![]))),
//
FlatType::Func(..) => Err(Underivable),
FlatType::EmptyTuple => unreachable!("Somehow Encoding derivation got an expression that's an empty tuple, which shouldn't be possible!"),
},
Content::Alias(sym, _, real_var, _) => match from_builtin_symbol(sym) {
Some(lambda) => lambda,
@ -129,9 +131,7 @@ impl FlatEncodable {
Content::RangedNumber(range) => {
Self::from_var(subs, range.default_compilation_variable())
}
//
Content::RecursionVar { structure, .. } => Self::from_var(subs, structure),
//
Content::Error => Err(Underivable),
Content::FlexVar(_)
| Content::RigidVar(_)

View file

@ -4,11 +4,8 @@ use roc_module::{
};
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{
util::{
check_derivable_ext_var, debug_name_fn, debug_name_record, debug_name_tag, debug_name_tuple,
},
DeriveError,
use crate::util::{
check_derivable_ext_var, debug_name_fn, debug_name_record, debug_name_tag, debug_name_tuple,
};
#[derive(Hash)]
@ -27,8 +24,9 @@ pub enum FlatInspectableKey {
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
Function(u32 /* arity; +1 for return type */),
/// This means specifically an opaque type where the author hasn't requested that it derive Inspect (or implemented it)
Opaque,
Error,
TypeVar(String),
}
impl FlatInspectableKey {
@ -42,15 +40,15 @@ impl FlatInspectableKey {
FlatInspectableKey::TagUnion(tags) => debug_name_tag(tags),
FlatInspectableKey::Function(arity) => debug_name_fn(*arity),
FlatInspectableKey::Error => "error".to_string(),
FlatInspectableKey::TypeVar(name) => format!("typeVariable({name})"),
FlatInspectableKey::Opaque => "opaque".to_string(),
}
}
}
impl FlatInspectable {
pub(crate) fn from_var(subs: &Subs, var: Variable) -> FlatInspectable {
use DeriveError::*;
use FlatInspectable::*;
match *subs.get_content_without_compacting(var) {
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(sym, _) => match sym {
@ -58,21 +56,15 @@ impl FlatInspectable {
Symbol::SET_SET => Key(FlatInspectableKey::Set()),
Symbol::DICT_DICT => Key(FlatInspectableKey::Dict()),
Symbol::STR_STR => Immediate(Symbol::INSPECT_STR),
Symbol::NUM_NUM => {
todo!();
// TODO need to match again to see what type of Num it was, then
// use Symbol::INSPECT_WHATEVERNUMBERTYPE
}
_ => Immediate(Symbol::INSPECT_OPAQUE),
},
FlatType::Record(fields, ext) => {
let (fields_iter, ext) = fields.unsorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
todo!(); // TODO open records can still derive Inspect, but we need to decide how/if to render the ext var.
// matches!(ext, Content::Structure(FlatType::EmptyRecord))
});
matches!(ext, Content::Structure(FlatType::EmptyRecord))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for record");
let mut field_names = Vec::with_capacity(fields.len());
for (field_name, _) in fields_iter {
@ -86,11 +78,10 @@ impl FlatInspectable {
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
todo!(); // TODO open tuples can still derive Inspect, but we need to decide how/if to render the ext var.
// matches!(ext, Content::Structure(FlatType::EmptyTuple))
});
matches!(ext, Content::Structure(FlatType::EmptyTuple))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for tuple");
Key(FlatInspectableKey::Tuple(elems_iter.count() as _))
}
@ -106,11 +97,10 @@ impl FlatInspectable {
// `t`-prefixed payload types.
let (tags_iter, ext) = tags.unsorted_tags_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext.var(), |ext| {
todo!(); // TODO open tag unions can still derive Inspect, but we need to decide how/if to render the ext var.
// matches!(ext, Content::Structure(FlatType::EmptyTagUnion))
});
matches!(ext, Content::Structure(FlatType::EmptyTagUnion))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for tag union");
let mut tag_names_and_payload_sizes: Vec<_> = tags_iter
.tags
@ -134,14 +124,13 @@ impl FlatInspectable {
))
}
FlatType::EmptyRecord => Key(FlatInspectableKey::Record(Vec::new())),
FlatType::EmptyTuple => todo!(),
FlatType::EmptyTagUnion => Key(FlatInspectableKey::TagUnion(Vec::new())),
//
FlatType::Func(slice, ..) => {
let arity = subs.get_subs_slice(slice).len();
Key(FlatInspectableKey::Function(arity as u32))
}
FlatType::EmptyTuple => unreachable!("Somehow Inspect derivation got an expression that's an empty tuple, which shouldn't be possible!"),
},
Content::Alias(sym, _, real_var, _) => match Self::from_builtin_alias(sym) {
Some(lambda) => lambda,
@ -157,13 +146,9 @@ impl FlatInspectable {
Content::FlexVar(_)
| Content::RigidVar(_)
| Content::FlexAbleVar(_, _)
| Content::RigidAbleVar(_, _) => {
let var_name: String = todo!();
Key(FlatInspectableKey::TypeVar(var_name))
}
Content::LambdaSet(_) | Content::ErasedLambda => {
unreachable!();
| Content::RigidAbleVar(_, _)
| Content::LambdaSet(_) | Content::ErasedLambda => {
unreachable!("There must have been a bug in the solver, because we're trying to derive Inspect on a non-concrete type.");
}
}
}

View file

@ -1627,6 +1627,8 @@ define_builtins! {
30 INSPECT_APPLY: "apply"
31 INSPECT_TO_INSPECTOR: "toInspector"
32 INSPECT_NAT: "nat"
33 INSPECT_INSPECT_FN: "inspectFn"
34 INSPECT_INSPECT_OPAQUE: "inspectOpaque"
}
15 JSON: "TotallyNotJson" => {
0 JSON_JSON: "TotallyNotJson"