Skip to content

Commit b41f985

Browse files
committed
Update doc structure, use BuiltinUnit for cleaner UPLC code
1 parent 9ec5b1a commit b41f985

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

doc/docusaurus/docs/delve-deeper/casing-constants.md

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,32 @@ This use of `case` in UPLC was introduced with protocol version 11 and requires
1313
:::
1414

1515
In UPLC, it is possible to branch on expressions of certain built-in types, like
16-
`Integer` and `Bool`. This can be done with `case` syntax, which is also used
17-
for [sums-of-products](./encoding#sums-of-products). Using `case` on built-in
18-
values may improve script performance and size.
19-
The built-in types that `case` currently supports are:
16+
`Integer` and `Bool` using `case` syntax, which is also used
17+
for [sums-of-products](./encoding#sums-of-products). This may improve script performance
18+
and size, compared to older alternatives that use built-in functions.
19+
20+
This page describes the built-in types that are supported in UPLC and how Plinth
21+
developers can benefit from the improved performance.
22+
23+
## Usage from Plinth
24+
25+
:::info
26+
27+
The Plinth compiler option will change from `datatypes=BuiltinCasing` to
28+
`datatypes=SumsOfProducts` in the future.
29+
30+
:::
31+
32+
33+
Plinth developers can benefit from the performance of `case` by enabling the
34+
compiler [option](./plinth-compiler-options) `datatypes=BuiltinCasing`, and
35+
using standard library functions such as `caseList`, `fstPair`.
36+
Note that Plinth's `case ... of ...` syntax is not generally compiled to UPLC,
37+
as it can be more expressive.
38+
39+
## Supported types
40+
41+
The UPLC built-in types that `case` can be used on are:
2042

2143
- `bool`
2244
- `unit`
@@ -26,42 +48,32 @@ The built-in types that `case` currently supports are:
2648

2749
In the future, support for `data` is also planned.
2850

29-
For each type, the allowed branches and their order differs. See [Supported
30-
Types](#supported-types) for more detail.
31-
32-
## Compiling to `case` in Plinth
33-
34-
When compiling Plinth code with the [option](./plinth-compiler-options)
35-
`datatypes=BuiltinCasing` (which in the future be achieved with
36-
`datatypes=SumsOfProducts`), many standard library functions will be compiled
37-
into this use of `case`, such as `fstPair`, `ifThenElse` and `caseList`. Note
38-
that Plinth's `case ... of ...` syntax is not generally compiled to UPLC, as
39-
it can be more expressive.
40-
41-
## Supported types
42-
4351
### Bool
4452

45-
Consider the following Plinth code that implements a basic assertion:
53+
The following Plinth code implements a basic assertion:
4654

4755
```haskell
48-
assert :: Bool -> ()
56+
assert :: Bool -> BuiltinUnit
4957
assert False = error ()
50-
assert True = ()
58+
assert True = unitval
5159
```
5260

5361
With `datatypes=BuiltinCasing`, it is compiled to the new casing on builtins:
5462

5563
```uplc
56-
\b -> case b error (constr 0 [])
64+
\b -> case b [error, ()]
5765
```
5866

67+
In UPLC, booleans can be used in `case` with either one or two branches, where
68+
the first is always the `False` branch. When only a single branch is provided,
69+
script execution will fail when the boolean evaluates to True.
70+
5971
:::info
6072

6173
Compare this to the UPLC that would have been generated otherwise:
6274

6375
```uplc
64-
\b -> force (force ifThenElse b (delay (constr 0 [])) (delay error))
76+
\b -> force (force ifThenElse b (delay ()) (delay error))
6577
```
6678

6779
This uses the UPLC builtin function `ifThenElse`, which requires delaying the branch
@@ -70,11 +82,11 @@ delaying impacts the size and execution cost.
7082
:::
7183

7284

73-
### Unit
85+
### BuiltinUnit
7486

7587
The built-in unit type can be used in a trivial way with `case` in UPLC, which
7688
takes exactly one branch. With `datatypes=BuiltinCasing`, Plinth will compile
77-
the `chooseUnit` built-in into `case`. Consider the following trivial Plinth code:
89+
`chooseUnit` from `PlutusTx.Builtins.Internal` into `case`. For example:
7890

7991
```haskell
8092
forceUnit :: BuiltinUnit -> Integer
@@ -91,10 +103,9 @@ UPLC's case on built-in unit requires exactly one branch. If the expression
91103
being cased on evaluates to the unit value, evaluation will continue with the
92104
expression in that branch.
93105

94-
### Pair
106+
### BuiltinPair
95107

96-
To destruct a built-in pair, use `casePair`. It compiles into the `case`
97-
construct. For example:
108+
To destruct a built-in pair, use `casePair` from `PlutusTx.Builtins`. For example:
98109

99110
```haskell
100111
addPair :: BuiltinPair Integer Integer -> Integer
@@ -152,11 +163,11 @@ fail. Note that there is no way to provide a "catch-all" case for integers.
152163
When not using `datatypes=BuiltinCasing`, Plinth's `caseInteger` is compiled
153164
into a much less efficient implementation that turns the second argument in a
154165
list (of which the representation depends on the chosen `datatypes=` flag), and
155-
does a recursive lookup in that list.
166+
does a recursive lookup in that list. The above Plinth code is compiled to:
156167

157168

158169
```uplc
159-
((\traceError ->
170+
(\traceError ->
160171
(\go i ->
161172
force
162173
(force ifThenElse
@@ -181,12 +192,12 @@ does a recursive lookup in that list.
181192
(delay x)
182193
(delay
183194
((\x -> s s x) (subtractInteger ds 1) xs)))) ])))
184-
(\str -> (\x -> error) (force trace str (constr 0 []))))
195+
(\str -> (\x -> error) (force trace str (constr 0 [])))
185196
```
186197
:::
187198

188199

189-
### List
200+
### BuiltinList
190201

191202
A `case` on built-in lists may be given one or two branches (similar to
192203
booleans), where the first one deals with the cons case, and the second one with
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(program 1.1.0 (\ds -> case ds [error, (constr 0 [])]))
1+
(program 1.1.0 (\ds -> case ds [error, ()]))

plutus-tx-plugin/test/BuiltinCasing/Spec.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import Test.Tasty.Extras
1212

1313
import PlutusTx (compile)
1414
import PlutusTx.Builtins (caseInteger, caseList, casePair)
15-
import PlutusTx.Builtins.Internal (chooseUnit)
15+
import PlutusTx.Builtins.Internal (chooseUnit, unitval)
1616
import PlutusTx.Prelude
1717
import PlutusTx.Test
1818

19-
assert :: Bool -> ()
19+
assert :: Bool -> BuiltinUnit
2020
assert False = error ()
21-
assert True = ()
21+
assert True = unitval
2222

2323
forceUnit :: BuiltinUnit -> Integer
2424
forceUnit e = chooseUnit e 5

0 commit comments

Comments
 (0)