Merge pull request #2910 from rtfeldman/i/2880

Ability codegen for Encode/Decode
This commit is contained in:
Ayaz 2022-05-08 19:10:45 -04:00 committed by GitHub
commit 3e7702df01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1235 additions and 378 deletions

View file

@ -10,6 +10,9 @@ use crate::helpers::wasm::assert_evals_to;
#[cfg(test)]
use indoc::indoc;
#[cfg(test)]
use roc_std::RocList;
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn hash_specialization() {
@ -216,3 +219,107 @@ fn ability_used_as_type_still_compiles() {
u64
)
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn encode() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ myU8Bytes ] to "./platform"
Encoder fmt := List U8, fmt -> List U8 | fmt has Format
Encoding has
toEncoder : val -> Encoder fmt | val has Encoding, fmt has Format
Format has
u8 : U8 -> Encoder fmt | fmt has Format
appendWith : List U8, Encoder fmt, fmt -> List U8 | fmt has Format
appendWith = \lst, (@Encoder doFormat), fmt -> doFormat lst fmt
toBytes : val, fmt -> List U8 | val has Encoding, fmt has Format
toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt
Linear := {}
# impl Format for Linear
u8 = \n -> @Encoder (\lst, @Linear {} -> List.append lst n)
Rgba := { r : U8, g : U8, b : U8, a : U8 }
# impl Encoding for Rgba
toEncoder = \@Rgba {r, g, b, a} ->
@Encoder \lst, fmt -> lst
|> appendWith (u8 r) fmt
|> appendWith (u8 g) fmt
|> appendWith (u8 b) fmt
|> appendWith (u8 a) fmt
myU8Bytes = toBytes (@Rgba { r: 106, g: 90, b: 205, a: 255 }) (@Linear {})
"#
),
RocList::from_slice(&[106, 90, 205, 255]),
RocList<u8>
)
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn decode() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ myU8 ] to "./platform"
DecodeError : [ TooShort, Leftover (List U8) ]
Decoder val fmt := List U8, fmt -> { result: Result val DecodeError, rest: List U8 } | fmt has DecoderFormatting
Decoding has
decoder : Decoder val fmt | val has Decoding, fmt has DecoderFormatting
DecoderFormatting has
u8 : Decoder U8 fmt | fmt has DecoderFormatting
decodeWith : List U8, Decoder val fmt, fmt -> { result: Result val DecodeError, rest: List U8 } | fmt has DecoderFormatting
decodeWith = \lst, (@Decoder doDecode), fmt -> doDecode lst fmt
fromBytes : List U8, fmt -> Result val DecodeError
| fmt has DecoderFormatting, val has Decoding
fromBytes = \lst, fmt ->
when decodeWith lst decoder fmt is
{ result, rest } ->
Result.after result \val ->
if List.isEmpty rest
then Ok val
else Err (Leftover rest)
Linear := {}
# impl DecoderFormatting for Linear
u8 = @Decoder \lst, @Linear {} ->
when List.first lst is
Ok n -> { result: Ok n, rest: List.dropFirst lst }
Err _ -> { result: Err TooShort, rest: [] }
MyU8 := U8
# impl Decoding for MyU8
decoder = @Decoder \lst, fmt ->
{ result, rest } = decodeWith lst u8 fmt
{ result: Result.map result (\n -> @MyU8 n), rest }
myU8 =
when fromBytes [ 15 ] (@Linear {}) is
Ok (@MyU8 n) -> n
_ -> 27u8
"#
),
15,
u8
);
}