mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
wip
This commit is contained in:
parent
00c27b087b
commit
34148645ae
6 changed files with 1139 additions and 46 deletions
|
@ -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
|
||||
|
|
1096
crates/compiler/derive/src/inspect.rs
Normal file
1096
crates/compiler/derive/src/inspect.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
|
@ -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(_)
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue