Add deriving toEncoder for opaques

This commit is contained in:
Ayaz Hafiz 2022-10-18 13:52:30 -05:00
parent 83813afeaf
commit c4f9aa6fe6
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 82 additions and 7 deletions

View file

@ -639,6 +639,45 @@ fn separate_implemented_and_required_members(
} }
} }
fn synthesize_derived_to_encoder<'a>(
env: &mut Env<'a>,
at_opaque: &'a str,
region: Region,
) -> ast::Expr<'a> {
let alloc_pat = |it| env.arena.alloc(Loc::at(region, it));
let alloc_expr = |it| env.arena.alloc(Loc::at(region, it));
let payload = env.arena.alloc_str("#payload");
// \@Opaq payload
let opaque_ref = alloc_pat(ast::Pattern::OpaqueRef(at_opaque));
let opaque_apply_pattern = ast::Pattern::Apply(
opaque_ref,
&*env
.arena
.alloc([Loc::at(region, ast::Pattern::Identifier(payload))]),
);
// Encode.toEncoder payload
let call_member = alloc_expr(ast::Expr::Apply(
alloc_expr(ast::Expr::Var {
module_name: "Encode",
ident: "toEncoder",
}),
&*env.arena.alloc([&*alloc_expr(ast::Expr::Var {
module_name: "",
ident: payload,
})]),
roc_module::called_via::CalledVia::Space,
));
// \@Opaq payload -> Encode.toEncoder payload
ast::Expr::Closure(
env.arena.alloc([Loc::at(region, opaque_apply_pattern)]),
call_member,
)
}
fn synthesize_derived_hash<'a>( fn synthesize_derived_hash<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
at_opaque: &'a str, at_opaque: &'a str,
@ -756,14 +795,9 @@ fn synthesize_derived_member_impl<'a>(
let (impl_name, def_body): (String, ast::Expr<'a>) = match ability_member { let (impl_name, def_body): (String, ast::Expr<'a>) = match ability_member {
Symbol::ENCODE_TO_ENCODER => ( Symbol::ENCODE_TO_ENCODER => (
format!("#{}_toEncoder", opaque_name), format!("#{}_toEncoder", opaque_name),
todo!(), synthesize_derived_to_encoder(env, at_opaque, region),
//synthesize_derived_to_encoder(env, scope, at_opaque, region),
),
Symbol::DECODE_DECODER => (
format!("#{}_decoder", opaque_name),
todo!(),
//synthesize_derived_decoder(env, scope, at_opaque, region),
), ),
Symbol::DECODE_DECODER => (format!("#{}_decoder", opaque_name), todo!()),
Symbol::HASH_HASH => ( Symbol::HASH_HASH => (
format!("#{}_hash", opaque_name), format!("#{}_hash", opaque_name),
synthesize_derived_hash(env, at_opaque, region), synthesize_derived_hash(env, at_opaque, region),

View file

@ -8045,6 +8045,23 @@ mod solve_expr {
); );
} }
#[test]
fn derive_to_encoder_for_opaque() {
infer_queries!(
indoc!(
r#"
app "test" provides [main] to "./platform"
N := U8 has [Encoding]
main = Encode.toEncoder (@N 15)
# ^^^^^^^^^^^^^^^^
"#
),
@"N#Encode.toEncoder(3) : N -[[#N_toEncoder(3)]]-> Encoder fmt | fmt has EncoderFormatting"
);
}
#[test] #[test]
fn derive_hash_for_opaque() { fn derive_hash_for_opaque() {
infer_queries!( infer_queries!(

View file

@ -374,6 +374,30 @@ fn encode_use_stdlib_without_wrapping_custom() {
) )
} }
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn encode_derive_to_encoder_for_opaque() {
assert_evals_to!(
indoc!(
r#"
app "test"
imports [Json]
provides [main] to "./platform"
HelloWorld := { a: Str } has [Encoding]
main =
result = Str.fromUtf8 (Encode.toBytes (@HelloWorld { a: "Hello, World!" }) Json.toUtf8)
when result is
Ok s -> s
_ -> "<bad>"
"#
),
RocStr::from(r#"{"a":"Hello, World!"}"#),
RocStr
)
}
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_encoder_encode_custom_has_capture() { fn to_encoder_encode_custom_has_capture() {