[#138] Reduce the usage `$` in Indigo

Problem: Indigo code often contains the `$` Haskell operator,
however since the language is meant to be used by people not
familiar with Haskell it would be great to not make it a necessity.

Solution: Reduce usage of `$` in 2 places:

1. right before `do` is used for a block code
- Solved by using `BlockArguments`

2. right after `new`
- Solved by treating `new$` as one keyword
parent 7e35220f
Pipeline #148566660 passed with stages
in 5 minutes and 59 seconds
......@@ -229,7 +229,7 @@ updateStorageField
-> IndigoM ()
updateStorageField field upd = scope $ do
let storage = storageVar @store
fieldVar <- new (storage %! field)
fieldVar <- new$ storage %! field
expr <- upd fieldVar
setField (storageVar @store) field expr
......@@ -242,7 +242,7 @@ getStorageField
, HasField store fname ftype
)
=> Label fname -> IndigoM (Var ftype)
getStorageField field = new (storageVar @store %! field)
getStorageField field = new$ storageVar @store %! field
----------------------------------------------------------------------------
-- Conditional
......
......@@ -132,7 +132,7 @@ subGt0 minuend subtrahend onNegative = do
when (diff <. zero) onNegative
resVar <- new Nothing
resVar <- new$ Nothing
if diff ==. zero then setVar resVar $ C Nothing else setVar resVar $ isNat diff
......
......@@ -89,17 +89,17 @@ assertCheck param st
contractVarLorentz :: ContractCode Integer Integer
contractVarLorentz = compileIndigoContract $ \_param ->
when (5 int <. 10 int) $ do
_a <- new $ 10 int
when (5 int <. 10 int) do
_a <- new$ 10 int
return ()
ifTest :: L.Contract Integer Integer
ifTest = noOptimizationContract $ compileIndigoContract $ \param -> do
a <- new $ 7 int +. param
when (param <. a) $ do
_c <- new (storageVar @Integer)
a <- new$ 7 int +. param
when (param <. a) do
_c <- new$ storageVar @Integer
return ()
_c <- new $ param <. storageVar @Integer
_c <- new$ param <. storageVar @Integer
return ()
contractIfLorentz :: ContractCode Integer Integer
......@@ -107,18 +107,18 @@ contractIfLorentz = L.cCode ifTest
contractIfValueLorentz :: ContractCode Integer Integer
contractIfValueLorentz = compileIndigoContract $ \param -> do
a <- new $ 7 int +. param
when (param <. a) $ do
_c <- new (storageVar @Integer)
a <- new$ 7 int +. param
when (param <. a) do
_c <- new$ storageVar @Integer
return ()
_c <- new $ param <. storageVar @Integer
_c <- new$ param <. storageVar @Integer
return ()
contractWhileLorentz :: ContractCode Integer Integer
contractWhileLorentz = compileIndigoContract $ \param -> do
i <- new $ 0 int
s <- new $ 0 int
while (i <. storageVar @Integer) $ do
i <- new$ 0 int
s <- new$ 0 int
while (i <. storageVar @Integer) do
when (i %. param ==. 0 nat) $
s += i
i += 1 int
......@@ -126,13 +126,13 @@ contractWhileLorentz = compileIndigoContract $ \param -> do
contractForEachLorentz :: ContractCode [Integer] Integer
contractForEachLorentz = compileIndigoContract $ \param -> do
s <- new $ 0 int
s <- new$ 0 int
forEach param $ \it -> do
s =: s +. it
storageVar =: s
contractCaseLorentz :: ContractCode DummyOp Integer
contractCaseLorentz = compileIndigoContract $ \param -> scope $ do
contractCaseLorentz = compileIndigoContract $ \param -> scope do
-- This example demostrates following:
-- 1. types of the stack case branched may be diverged,
-- they are automatically moved to the same stack
......@@ -169,7 +169,7 @@ doSub :: Var Integer -> Var (Integer, Integer) -> IndigoM (Var Bool)
doSub storage p = do
-- Create a variable to demostrate that branches of case
-- are cleaned automatically
testVar <- new True
testVar <- new$ True
storage =: Fst p -. Snd p
return testVar
......@@ -182,29 +182,29 @@ contractDocLorentz :: ContractCode Integer Integer
contractDocLorentz = compileIndigoContract $ \param -> do
doc (DDescription "x")
contractName "aaa" (doc $ DDescription "a")
i <- new $ 10 int
i <- new$ 10 int
docGroup (SomeDocItem . DName "bbb") (doc $ DDescription "b")
storageVar =: param +. i
contractOpsLorentz :: ContractCode (Maybe KeyHash) Address
contractOpsLorentz = compileIndigoContract $ \param -> do
setDelegate param
m <- new $ 0 mutez
is <- new $ 0 int
m <- new$ 0 mutez
is <- new$ 0 int
addr <- createLorentzContract ifTest param m is
storageVar =: addr
contractAssertLorentz :: ContractCode Integer Integer
contractAssertLorentz = compileIndigoContract $ \param -> do
s <- new (param +. storageVar @Integer)
z <- new $ 0 int
s <- new$ param +. storageVar @Integer
z <- new$ 0 int
assert negativeResM (s >. z)
storageVar =: s
contractCommentLorentz :: ContractCode Integer Integer
contractCommentLorentz = compileIndigoContract $ \param -> do
s <- commentAroundStmt "param plus storage" $ new (param +. storageVar @Integer)
_z <- new $ 0 int
s <- commentAroundStmt "param plus storage" $ new$ param +. storageVar @Integer
_z <- new$ 0 int
justComment "just comment"
storageVar =: s
......@@ -226,7 +226,7 @@ expectedDocContract =
L.doc (DDescription "x") #
-- contractName "aaa" (doc $ DDescription "a")
L.contractName "aaa" (L.doc $ DDescription "a") #
-- i <- new $ 10 int
-- i <- new$ 10 int
L.push (10 int) #
-- docGroup (SomeDocItem . DName "bbb") (doc $ DDescription "b")
L.docGroup (SomeDocItem . DName "bbb") (L.doc $ DDescription "b") #
......
......@@ -263,7 +263,7 @@ exprUnpack= compileIndigo @2 $ \st param -> st =: unpack param
exprSet :: '[(Set Integer), Integer] :-> '[(Set Integer), Integer]
exprSet = compileIndigo @2 $ \st param -> do
z <- new (0 :: Integer)
z <- new$ (0 :: Integer)
if_ (param #? z &&. mem z param) -- Same, but also checks `mem` expression
(param =: param #- z)
(param =: param #~ (1 :: Integer))
......@@ -313,8 +313,8 @@ exprUStore
:: '[Integer, MyUstore]
:-> '[Integer, MyUstore]
exprUStore = compileIndigo @2 $ \st param -> do
st1 <- new $ st %~ (#ints, param, ())
st2 <- new $ st1 %~~ (#ints, notNewKeyM, 0 :: Integer, ())
st1 <- new$ st %~ (#ints, param, ())
st2 <- new$ st1 %~~ (#ints, notNewKeyM, 0 :: Integer, ())
ifSome (st2 %@ (#ints, -1 :: Integer))
(\_v -> st =: st)
(st =: st2)
......@@ -332,7 +332,7 @@ exprCrypto
:: '[ByteString, ByteString]
:-> '[ByteString, ByteString]
exprCrypto = compileIndigo @2 $ \st param -> do
_sha256var <- new $ sha256 param
_sha256var <- new$ sha256 param
st =: blake2b param
param =: sha512 param
......
......@@ -48,7 +48,7 @@ sumLambdaCheck param _st = Right $ sum param
-- In this case code has to be just inlined.
sumLambdaCalledOnce :: ContractCode [Integer] Integer
sumLambdaCalledOnce = compileIndigoContract $ \lst -> do
s <- new @Integer 0
s <- new$ (0 :: Integer)
forEach lst $
setVar s <=< sumLambda . pair s
storageVar =: s
......@@ -57,7 +57,7 @@ sumLambdaCalledOnce = compileIndigoContract $ \lst -> do
-- In this case lambda has to be pushed on the stack and then called using @[email protected]
sumLambdaCalledTwice :: ContractCode [Integer] Integer
sumLambdaCalledTwice = compileIndigoContract $ \lst -> do
s <- new @Integer 0 >>= sumLambda . pair (0 :: Integer)
s <- (new$ (0 :: Integer)) >>= sumLambda . pair (0 :: Integer)
forEach lst $
setVar s <=< sumLambda . pair s
storageVar =: s
......@@ -73,11 +73,11 @@ lambdasSideEffectsCheck param st = Right ([crConOp 1, crConOp 0], st + 2)
dummyContract
:: L.Contract Integer Integer
dummyContract = noOptimizationContract $ compileIndigoContract $ \param -> do
a <- new $ (7 :: Integer) +. param
when (param <. a) $ do
_c <- new (storageVar @Integer)
a <- new$ (7 :: Integer) +. param
when (param <. a) do
_c <- new$ storageVar @Integer
return ()
_c <- new $ param <. storageVar @Integer
_c <- new$ param <. storageVar @Integer
return ()
lambdaCreateContract ::
......@@ -85,7 +85,7 @@ lambdaCreateContract ::
, HasSideEffects, HasStorage Integer
) => ex -> IndigoM ()
lambdaCreateContract = defNamedEffLambda1 @Integer "create storage" $ \paramSt -> do
m <- new (toMutez 0)
m <- new$ toMutez 0
_addr <- createLorentzContract dummyContract (fst paramSt) m (snd paramSt)
storageVar @Integer += (1 :: Integer)
......@@ -147,7 +147,7 @@ lambdaInLambda2 = compileIndigoContract $ \matrix -> do
-- * a pure lambda uses @[email protected] or @[email protected]
lambdaOuterVarClosure :: ContractCode Integer Integer
lambdaOuterVarClosure = compileIndigoContract $ \param -> do
plusTwo <- new (param +. (2 :: Integer))
plusTwo <- new$ param +. (2 :: Integer)
let lam :: pr :~> Integer => pr -> IndigoM (Var Integer)
lam = defNamedPureLambda1 "lambda" $ \innerPar -> pure (plusTwo +. innerPar)
_v1 <- lam (3 :: Integer)
......
......@@ -187,11 +187,11 @@ prefixing the name with a `#`.
For example, this is some Indigo code interacting with `TransferParams`s:
```haskell
-- just a variable of type 'Address'
a <- new sender
a <- new$ sender
-- creation of a variable of type TransferParams
tp <- new $ construct (a !~ #source, a !~ #receiver, 10 !~ #amount)
tp <- new$ construct (a !~ #source, a !~ #receiver, 10 !~ #amount)
-- extracting the "amount" from a TransferParams
amount <- new $ tp !. #amount
amount <- new$ tp !. #amount
-- updating the "amount" in a TransferParams
tp =: tp ~. (#amount, 20)
```
......
......@@ -62,10 +62,10 @@ For example:
```haskell
1 int += 2 int -- is invalid, this will not compile
a <- new (1 int)
a <- new$ 1 int
a += 2 int -- "a" will have value of "3" after this expression
b <- new (a += 1 int) -- is also invalid, because "(a += b)" is not an expression
b <- new$ a += 1 int -- is also invalid, because "(a += b)" is not an expression
```
*Type variables* are used in the types of these tables as well, you can recognize
......@@ -396,7 +396,7 @@ For example, let's say we have a contract that takes a `View Integer Bool`
view_ greaterThan0 param
greaterThan0 :: Var Integer -> IndigoFunction Bool
greaterThan0 val = defFunction $ do
greaterThan0 val = defFunction do
return (val >. 0 int)
```
As you can see we only need the function to take an `Integer` as parameter and
......@@ -436,7 +436,7 @@ resVal <- if 1 int ==. 2 int
then do
return False
else do
a <- new (1 int ==. 1 int)
a <- new$ 1 int ==. 1 int
return a
-- we can now use the `resVal` `Bool` variable
```
......@@ -447,7 +447,7 @@ called `when` that only takes the `Bool` condition and a single branch, that wil
be executed only if the condition is `True`.
The first statement above could so be rewritten as:
```haskell
when (1 int <= 2 int) $ do
when (1 int <= 2 int) do
storage =: 1 int
```
......@@ -456,7 +456,7 @@ only when a `Bool` condition is `False`.
Indigo has a convenience statement for this too, called `unless`.
The previous example for instance could also be written as:
```haskell
unless (1 int > 2 int) $ do
unless (1 int > 2 int) do
storage =: 1 int
```
......@@ -487,8 +487,8 @@ We also two have statements similar to `when` for convenience:
`while` is the statement that will execute a piece of code as long as a `Bool`
condition holds. For example, this loop would execute twice:
```haskell
i <- new (0 int)
while (i int < 2 int) $ do
i <- new$ 0 int
while (i int < 2 int) do
-- more code can be here
i += 1 int
-- the code following will get executed after the loop
......@@ -500,7 +500,7 @@ of a container (a list, set or map).
For example, given a `numList` variable of type `[Integer]` this will compute
the sum of all its elements:
```haskell
sum <- new (0 int)
sum <- new$ 0 int
forEach numList $ \number -> do
sum += number
```
......
......@@ -9,6 +9,6 @@ module Indigo.Tutorial.T00.Example
import Indigo
exampleContract :: IndigoContract Integer Integer
exampleContract param = defContract $ do
a <- new (1 int)
exampleContract param = defContract do
a <- new$ 1 int
storageVar =: param +. a
......@@ -10,10 +10,10 @@ module Indigo.Tutorial.T01.Example
import Indigo
exampleContract :: IndigoContract Integer Integer
exampleContract param = defContract $ do
a <- new (1 int)
exampleContract param = defContract do
a <- new$ 1 int
storageVar =: param +. a
textKeeper :: IndigoContract MText MText
textKeeper param = defContract $ do
textKeeper param = defContract do
storageVar =: param
......@@ -43,7 +43,7 @@ Not that complicated, right?
Let's go to the second line:
```haskell
exampleContract param = defContract $ do
exampleContract param = defContract do
```
this is the start of our contract definition, we define `exampleContract` and
say that it takes a parameter variable (in this case we call it `param`), we
......@@ -56,11 +56,11 @@ parameter variable (in case we want to use something other than `param`).
The indented lines that follow are the actual contract code.
In this case:
```haskell
a <- new (1 int)
a <- new$ 1 int
storageVar =: param +. a
```
these lines show both methods of direct variable manipulation:
- we can create a new variable by using `new`, on its right we put the
- we can create a new variable by using `new$`, on its right we put the
expression we want to assign to the new variable (`1 int`) and on the left of the
arrow `<-` the name we'll be referring to with (`a`)
- we can set an existing variable to a new value by using `=:`, on its
......@@ -192,3 +192,14 @@ This module however does not contain `new` and `=:`, introduced above,
nor the code to lookup variables on the stack.
These are located in specific modules and will be explained in the following
chapters.
In Indigo we also use the `BlockArguments` extension to remove the `$` before
the `do` notation as well, which results in being able to use this syntax:
```haskell
exampleContract param = defContract do
```
instead of:
```haskell
exampleContract param = defContract $ do
```
......@@ -9,10 +9,10 @@ module Indigo.Tutorial.T02.Math
import Indigo
mathContract :: IndigoContract Integer Integer
mathContract param = defContract $ do
zero <- new (0 int)
_z <- new zero
five <- new (zero +. 6 int)
mathContract param = defContract do
zero <- new$ 0 int
_z <- new$ zero
five <- new$ zero +. 6 int
five -= 1 int
storage += abs ((param *. five) -. 10 int)
......
......@@ -35,7 +35,7 @@ with the explanation. Remember: you can always bring it into the REPL by using
We can see in the first line of the code that it creates a variable starting from
the simplest expression, a constant: `0`.
Here this constant is used to create a new variable `zero` with `new`, all
Here this constant is used to create a new variable `zero` with `new$`, all
variables are expressions too, so we can see in the next line how it creates
another variable from it.
......@@ -48,7 +48,7 @@ You can see that indeed this is here just for demonstration purposes and it is
not used anywhere else, in a real contract it would be better to just remove it.
If we proceed to the third line we have the allocation of `five`, this is nothing
new: it sums (`+.`) the variable `zero` and the constant `6` to make a `new`.
new: it sums (`+.`) the variable `zero` and the constant `6` to make a `new$`.
However `6` is not quite a good definition for `five`, so in the next line we can
see that we use a compound operator `-=` to update the value of `five` instead of
......
......@@ -18,16 +18,16 @@ instance ParameterHasEntryPoints IncrementIf where
type ParameterEntryPointsDerivation IncrementIf = EpdPlain
controlContract :: IndigoContract IncrementIf Natural
controlContract param = defContract $ do
base <- new (10 nat)
controlContract param = defContract do
base <- new$ 10 nat
result <- case_ param $
( #cIsZero //-> \val -> do
return (val ==. 0 int)
, #cHasDigitOne //-> \val -> do
checkRes <- new False
while (val >. base &&. checkRes ==. False) $ do
checkRes <- new$ False
while (val >. base &&. checkRes ==. False) do
val =: val /. base
remainder <- new (val %. base)
remainder <- new$ val %. base
checkRes =: remainder ==. 1 nat
return checkRes
)
......
......@@ -72,10 +72,10 @@ Let's look instead at the isolated code for the second branch, the one for
`#cHasDigitOne`:
```haskell
\val -> do
checkRes <- new False
while (val >. base &&. checkRes ==. False) $ do
checkRes <- new$ False
while (val >. base &&. checkRes ==. False) do
val =: val /. base
remainder <- new (val %. base)
remainder <- new$ val %. base
checkRes =: remainder ==. 1 nat
return checkRes
```
......
......@@ -18,7 +18,7 @@ instance ParameterHasEntryPoints IncrementIf where
type ParameterEntryPointsDerivation IncrementIf = EpdPlain
functionsContract :: IndigoContract IncrementIf Natural
functionsContract param = defContract $ do
functionsContract param = defContract do
result <- case_ param $
( #cIsZero //-> checkZero
, #cHasDigitOne //-> checkHasDigitOne
......@@ -26,25 +26,25 @@ functionsContract param = defContract $ do
updateStorage result
checkZero :: Var Integer -> IndigoFunction Bool
checkZero val = defFunction $ do
checkZero val = defFunction do
return (val ==. 0 int)
checkHasDigitOne :: Var Natural -> IndigoFunction Bool
checkHasDigitOne val = defFunction $ do
base <- new (10 nat)
checkRes <- new False
while (val >. base &&. checkRes ==. False) $ do
checkHasDigitOne val = defFunction do
base <- new$ 10 nat
checkRes <- new$ False
while (val >. base &&. checkRes ==. False) do
val =: val /. base
remainder <- new (val %. base)
remainder <- new$ val %. base
checkRes =: remainder ==. 1 nat
return checkRes
updateStorage :: HasStorage Natural => Var Bool -> IndigoProcedure
updateStorage result = defFunction $ do
updateStorage result = defFunction do
if result then storage =: 0 nat else incrementStorage
incrementStorage :: HasStorage Natural => IndigoProcedure
incrementStorage = defFunction $ do
incrementStorage = defFunction do
storage += 1 nat
storage :: HasStorage Natural => Var Natural
......
......@@ -32,7 +32,7 @@ read because it has been broken down into simple functions.
Let's look at their definition, starting from the first one:
```haskell
checkZero :: Var Integer -> IndigoFunction Bool
checkZero val = defFunction $ do
checkZero val = defFunction do
return (val ==. 0 int)
```
......@@ -48,9 +48,9 @@ The main difference is that we put `val` before an `=` and used `defFunction`,
this should be easy to figure out, because `defFunction` is to functions what
`defContract` is to ... contracts, as you can see from the first lines here:
```haskell
functionsContract param = defContract $ do
functionsContract param = defContract do
checkZero val = defFunction $ do
checkZero val = defFunction do
```
The other difference is that by using functions we need to explicitly write a
......
......@@ -18,7 +18,7 @@ instance ParameterHasEntryPoints IncrementIf where
type ParameterEntryPointsDerivation IncrementIf = EpdPlain
errorsContract :: IndigoContract IncrementIf Natural
errorsContract param = defContract $ do
errorsContract param = defContract do
case_ param $
( #cIsZero //-> checkZero
, #cHasDigitOne //-> checkHasDigitOne
......@@ -26,15 +26,15 @@ errorsContract param = defContract $ do
incrementStorage
checkZero :: Var Integer -> IndigoProcedure
checkZero val = defFunction $ do
checkZero val = defFunction do
assert [mt|unacceptable zero value|] (val ==. 0 int)
checkHasDigitOne :: Var Natural -> IndigoProcedure
checkHasDigitOne val = defFunction $ do
base <- new (10 nat)
while (val >. base) $ do
checkHasDigitOne val = defFunction do
base <- new$ 10 nat
while (val >. base) do
val =: val /. base
remainder <- new (val %. base)
remainder <- new$ val %. base
checkSingleDigitOne remainder
checkSingleDigitOne val
......@@ -43,7 +43,7 @@ checkSingleDigitOne digit = do
assert [mt|unacceptable non-one digit|] (digit ==. 1 nat)
incrementStorage :: HasStorage Natural => IndigoProcedure
incrementStorage = defFunction $ do
incrementStorage = defFunction do
storage += 1 nat
storage :: HasStorage Natural => Var Natural
......
......@@ -10,21 +10,21 @@ module Indigo.Tutorial.T05.SideEffects
import Indigo
sideEffectsContract :: IndigoContract (Maybe MText) Address
sideEffectsContract param = defContract $ do
deleg <- new none
mtz <- new (0 mutez)
notInit <- new [mt|not initialized|]
sideEffectsContract param = defContract do
deleg <- new$ none
mtz <- new$ 0 mutez
notInit <- new$ [mt|not initialized|]
addr <- createContract textKeeper deleg mtz notInit
ifSome param (initializeContract addr) (return ())
storage =: addr
textKeeper :: IndigoContract MText MText
textKeeper param = defContract $ do
textKeeper param = defContract do
storageVar =: param
initializeContract :: HasSideEffects => Var Address -> Var MText -> IndigoProcedure
initializeContract addr msg = defFunction $ do
mtz <- new (0 mutez)
initializeContract addr msg = defFunction do
mtz <- new$ 0 mutez
ifSome (contract addr)
(\cRef -> transferTokens msg mtz cRef)
failForRef
......
......@@ -69,11 +69,11 @@ transfer parameter = do
ensureNotPaused @s