Skip to content

Commit

Permalink
add new example
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewilliamboswell committed Apr 10, 2024
1 parent 4cc7a90 commit 32c6932
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ examples/RandomNumbers/main
examples/CommandLineArgs/main
examples/Tasks/main
examples/Tuples/main
examples/EncodeDecode/main
roc_nightly/

# macOS directory attributes
Expand Down
3 changes: 3 additions & 0 deletions ci_scripts/all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ $ROC test ./examples/BasicDict/BasicDict.roc
$ROC build ./examples/MultipleRocFiles/main.roc
expect ci_scripts/expect_scripts/MultipleRocFiles.exp

$ROC build ./examples/EncodeDecode/main.roc
expect ci_scripts/expect_scripts/EncodeDecode.exp

$ROC build --lib ./examples/GoPlatform/main.roc --output examples/GoPlatform/platform/libapp.so
go build -C examples/GoPlatform/platform -buildmode=pie -o dynhost
$ROC preprocess-host ./examples/GoPlatform/main.roc
Expand Down
16 changes: 16 additions & 0 deletions ci_scripts/expect_scripts/EncodeDecode.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/expect

# uncomment line below for debugging
# exp_internal 1

set timeout 7

spawn ./examples/EncodeDecode/main

expect "(@ItemKind Text)\r\n(@ItemKind Method)\r\n(@ItemKind Function)\r\n(@ItemKind Constructor)\r\n(@ItemKind Field)\r\n(@ItemKind Variable)\r\n(@ItemKind Class)\r\n(@ItemKind Interface)\r\n(@ItemKind Module)\r\n" {
expect eof
exit 0
}

puts stderr "\nError: output was different from expected value."
exit 1
34 changes: 34 additions & 0 deletions examples/EncodeDecode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Encoding & Decoding Abilities

An example for how to implement the builtin `Encoding` and `Decoding` abilities for an opaque type.

Implementing these abilites for an opaque type like `ItemKind`, enables it to be used seamlessly within other data structures. This is useful when you would like to provide a custom mapping, such as in this example, between an integer and a tag union.

## Implementation
```roc
file:main.roc:snippet:impl
```

## Demo
```roc
file:main.roc:snippet:demo
```

## Output

Run this from the directory that has `main.roc` in it:

```
$ roc dev
(@ItemKind Text)
(@ItemKind Method)
(@ItemKind Function)
(@ItemKind Constructor)
(@ItemKind Field)
(@ItemKind Variable)
(@ItemKind Class)
(@ItemKind Interface)
(@ItemKind Module)
```

You can also use `roc test` to run the tests.
111 changes: 111 additions & 0 deletions examples/EncodeDecode/main.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
app "example"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.8.1/x8URkvfyi9I0QhmVG98roKBUs_AZRkLFwFJVJ3942YA.tar.br",
json: "https://github.com/lukewilliamboswell/roc-json/releases/download/0.6.3/_2Dh4Eju2v_tFtZeMq8aZ9qw2outG04NbkmKpFhXS_4.tar.br",
}
imports [pf.Stdout.{ line }, json.Core.{ json }]
provides [main] to pf

### start snippet impl

ItemKind := [
Text,
Method,
Function,
Constructor,
Field,
Variable,
Class,
Interface,
Module,
]
implements [
Decoding { decoder: decodeItems },
Encoding { toEncoder: encodeItems },
Inspect,
Eq,
]

decodeItems : Decoder ItemKind fmt
decodeItems = Decode.custom \bytes, _ ->

# helper to convert our tag to a DecodeResult
ok : _, List U8 -> DecodeResult ItemKind
ok = \tag, rest -> { result: Ok (@ItemKind tag), rest }

when bytes is
['1', .. as rest] -> ok Text rest
['2', .. as rest] -> ok Method rest
['3', .. as rest] -> ok Function rest
['4', .. as rest] -> ok Constructor rest
['5', .. as rest] -> ok Field rest
['6', .. as rest] -> ok Variable rest
['7', .. as rest] -> ok Class rest
['8', .. as rest] -> ok Interface rest
['9', .. as rest] -> ok Module rest
_ -> { result: Err TooShort, rest: bytes }

encodeItems : ItemKind -> Encoder fmt
encodeItems = \@ItemKind tag ->

Encode.custom \bytes, _ ->

# helper to append our encoded byte
append : U8 -> List U8
append = \u8 -> List.append bytes u8

when tag is
Text -> append '1'
Method -> append '2'
Function -> append '3'
Constructor -> append '4'
Field -> append '5'
Variable -> append '6'
Class -> append '7'
Interface -> append '8'
Module -> append '9'

### end snippet impl

### start snippet demo

# make a list of ItemKind's
originalList : List ItemKind
originalList = [
@ItemKind Text,
@ItemKind Method,
@ItemKind Function,
@ItemKind Constructor,
@ItemKind Field,
@ItemKind Variable,
@ItemKind Class,
@ItemKind Interface,
@ItemKind Module,
]

# encode them into JSON
encodedBytes : List U8
encodedBytes = Encode.toBytes originalList json

# test we have encoded correctly
expect encodedBytes == originalBytes

# take a JSON encoded list
originalBytes : List U8
originalBytes = "[1,2,3,4,5,6,7,8,9]" |> Str.toUtf8

# decode into a list of ItemKind's
decodedList : List ItemKind
decodedList = Decode.fromBytes originalBytes json |> Result.withDefault []

# test we have decoded correctly
expect decodedList == originalList

main =
# debug print decoded items to stdio
decodedList
|> List.map Inspect.toStr
|> Str.joinWith "\n"
|> Stdout.line

### end snippet demo
1 change: 1 addition & 0 deletions examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ You can find the source code for all of these at [github.com/roc-lang/examples](
- [Multi-line Comments](/MultiLineComments/README.html)
- [Go Platform](/GoPlatform/README.html)
- [.NET Platform](/DotNetPlatform/README.html)
- [Encoding & Decoding Abilities](/EncodeDecode/README.html)

## External examples

Expand Down

0 comments on commit 32c6932

Please sign in to comment.