Add derive keys for decoders

This commit is contained in:
Ayaz Hafiz 2022-08-01 16:17:04 -05:00
parent 6697e353a1
commit e2179348c6
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
6 changed files with 129 additions and 4 deletions

View file

@ -69,7 +69,7 @@ fn build_derived_body(
};
encoding::derive_to_encoder(&mut env, to_encoder_key, derived_symbol)
}
DeriveKey::Decoding => todo!(),
DeriveKey::Decoder(_decoder_key) => todo!(),
};
let def = Def {

View file

@ -0,0 +1,84 @@
use roc_module::symbol::Symbol;
use roc_types::subs::{Content, FlatType, Subs, Variable};
use crate::DeriveError;
#[derive(Hash)]
pub enum FlatDecodable {
Immediate(Symbol),
Key(FlatDecodableKey),
}
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub enum FlatDecodableKey {
List(/* takes one variable */),
}
impl FlatDecodableKey {
pub(crate) fn debug_name(&self) -> String {
match self {
FlatDecodableKey::List() => "list".to_string(),
}
}
}
impl FlatDecodable {
pub(crate) fn from_var(subs: &Subs, var: Variable) -> Result<FlatDecodable, DeriveError> {
use DeriveError::*;
use FlatDecodable::*;
match *subs.get_content_without_compacting(var) {
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(sym, _) => match sym {
Symbol::LIST_LIST => Ok(Key(FlatDecodableKey::List())),
Symbol::STR_STR => Ok(Immediate(Symbol::DECODE_STRING)),
_ => Err(Underivable),
},
FlatType::Record(_fields, _ext) => {
Err(Underivable) // yet
}
FlatType::TagUnion(_tags, _ext) | FlatType::RecursiveTagUnion(_, _tags, _ext) => {
Err(Underivable) // yet
}
FlatType::FunctionOrTagUnion(_name_index, _, _) => {
Err(Underivable) // yet
}
FlatType::EmptyRecord => {
Err(Underivable) // yet
}
FlatType::EmptyTagUnion => {
Err(Underivable) // yet
}
//
FlatType::Erroneous(_) => Err(Underivable),
FlatType::Func(..) => Err(Underivable),
},
Content::Alias(sym, _, real_var, _) => match sym {
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Ok(Immediate(Symbol::DECODE_U8)),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Ok(Immediate(Symbol::DECODE_U16)),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Ok(Immediate(Symbol::DECODE_U32)),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Ok(Immediate(Symbol::DECODE_U64)),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Ok(Immediate(Symbol::DECODE_U128)),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Ok(Immediate(Symbol::DECODE_I8)),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Ok(Immediate(Symbol::DECODE_I16)),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Ok(Immediate(Symbol::DECODE_I32)),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Ok(Immediate(Symbol::DECODE_I64)),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Ok(Immediate(Symbol::DECODE_I128)),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Ok(Immediate(Symbol::DECODE_DEC)),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Ok(Immediate(Symbol::DECODE_F32)),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Ok(Immediate(Symbol::DECODE_F64)),
// NB: I believe it is okay to unwrap opaques here because derivers are only used
// by the backend, and the backend treats opaques like structural aliases.
_ => Self::from_var(subs, real_var),
},
Content::RangedNumber(_) => Err(Underivable),
//
Content::RecursionVar { .. } => Err(Underivable),
Content::Error => Err(Underivable),
Content::FlexVar(_)
| Content::RigidVar(_)
| Content::FlexAbleVar(_, _)
| Content::RigidAbleVar(_, _) => Err(UnboundVar),
Content::LambdaSet(_) => Err(Underivable),
}
}
}

View file

@ -13,8 +13,10 @@
//! For these reasons the content keying is based on a strategy as well, which are the variants of
//! [`DeriveKey`].
pub mod decoding;
pub mod encoding;
use decoding::{FlatDecodable, FlatDecodableKey};
use encoding::{FlatEncodable, FlatEncodableKey};
use roc_module::symbol::Symbol;
@ -33,15 +35,14 @@ pub enum DeriveError {
#[repr(u8)]
pub enum DeriveKey {
ToEncoder(FlatEncodableKey),
#[allow(unused)]
Decoding,
Decoder(FlatDecodableKey),
}
impl DeriveKey {
pub fn debug_name(&self) -> String {
match self {
DeriveKey::ToEncoder(key) => format!("toEncoder_{}", key.debug_name()),
DeriveKey::Decoding => todo!(),
DeriveKey::Decoder(key) => format!("decoder_{}", key.debug_name()),
}
}
}
@ -61,6 +62,7 @@ pub enum Derived {
#[derive(Clone, Copy)]
pub enum DeriveBuiltin {
ToEncoder,
Decoder,
}
impl Derived {
@ -74,6 +76,10 @@ impl Derived {
FlatEncodable::Immediate(imm) => Ok(Derived::Immediate(imm)),
FlatEncodable::Key(repr) => Ok(Derived::Key(DeriveKey::ToEncoder(repr))),
},
DeriveBuiltin::Decoder => match decoding::FlatDecodable::from_var(subs, var)? {
FlatDecodable::Immediate(imm) => Ok(Derived::Immediate(imm)),
FlatDecodable::Key(repr) => Ok(Derived::Key(DeriveKey::Decoder(repr))),
},
}
}
}

View file

@ -0,0 +1,29 @@
#![cfg(test)]
// Even with #[allow(non_snake_case)] on individual idents, rust-analyzer issues diagnostics.
// See https://github.com/rust-lang/rust-analyzer/issues/6541.
// For the `v!` macro we use uppercase variables when constructing tag unions.
#![allow(non_snake_case)]
use crate::{util::check_immediate, v};
use roc_module::symbol::Symbol;
use roc_types::subs::{Subs, Variable};
use roc_derive_key::DeriveBuiltin::Decoder;
#[test]
fn immediates() {
check_immediate(Decoder, v!(U8), Symbol::DECODE_U8);
check_immediate(Decoder, v!(U16), Symbol::DECODE_U16);
check_immediate(Decoder, v!(U32), Symbol::DECODE_U32);
check_immediate(Decoder, v!(U64), Symbol::DECODE_U64);
check_immediate(Decoder, v!(U128), Symbol::DECODE_U128);
check_immediate(Decoder, v!(I8), Symbol::DECODE_I8);
check_immediate(Decoder, v!(I16), Symbol::DECODE_I16);
check_immediate(Decoder, v!(I32), Symbol::DECODE_I32);
check_immediate(Decoder, v!(I64), Symbol::DECODE_I64);
check_immediate(Decoder, v!(I128), Symbol::DECODE_I128);
check_immediate(Decoder, v!(DEC), Symbol::DECODE_DEC);
check_immediate(Decoder, v!(F32), Symbol::DECODE_F32);
check_immediate(Decoder, v!(F64), Symbol::DECODE_F64);
check_immediate(Decoder, v!(STR), Symbol::DECODE_STRING);
}

View file

@ -1,5 +1,6 @@
#![cfg(test)]
mod decoding;
mod encoding;
mod pretty_print;

View file

@ -45,6 +45,11 @@ fn module_source_and_path(builtin: DeriveBuiltin) -> (ModuleId, &'static str, Pa
module_source(ModuleId::ENCODE),
builtins_path.join("Encode.roc"),
),
DeriveBuiltin::Decoder => (
ModuleId::DECODE,
module_source(ModuleId::DECODE),
builtins_path.join("Decode.roc"),
),
}
}