# Expressions and operators¶

This chapter will introduce the concepts of expressions and operators in Indigo.

For a full list of the available operators and constructs, please refer to the relative reference page

## Expression resolution¶

Indigo supports deep expressions resolution, meaning that you can build expressions starting from other expressions/operators. Behind the scenes it translates them to a series of Michelson instructions that operate on the stack to bring you the same result.

This chapter contains a `Math.hs` module, let's take a look at it and proceed with the explanation:

``````module Indigo.Tutorial.Expressions.Math
( mathContract
) where

import Indigo

mathContract :: IndigoContract Integer Integer
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)

storage :: HasStorage Integer => Var Integer
storage = storageVar
``````

Remember: you can always bring it into the REPL by using `:load` and then print the `mathContract` inside using `printAsMichelson` or `saveAsMichelson`.

We can see in the first line of the code that it creates a variable starting from the simplest expression, a constant: `0 int`.

``````  zero <- new\$ 0 int
``````

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:

``````  _z <- new\$ zero
``````

Unused variable syntax

The second variable is also an example of an unused one, you can see how its name starts with an underscore: `_z`.

This denotes a variable that is not used later on in the code and it helps in keeping track of them, because if it didn't start with one you'd receive a warning.

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 int` to make a `new\$` variable:

``````  five <- new\$ zero + 6 int
``````

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 computing the difference first (`five - 1 int`) and then using `=:`:

``````  five -= 1 int
``````

When possible, you should always try to use compound operators, because they are more efficient as they avoid unnecessary duplication on the stack.

In the next and final line, we can see all of this together, we update the `storage` by adding to it (`+=`), we use a prefix operator (`abs`), variables (`params` and `five`) and constants (`10 int`):

``````  storage += abs (param * five - 10 int)
``````

## The `storage` definition¶

You probably noticed that we used `storage` here instead of `storageVar`, and that there is a weird `storage` definition below our contract:

``````storage :: HasStorage Integer => Var Integer
storage = storageVar
``````

We need this for the same reason we have to use `::` and `@` sometimes in our code, which is to remove ambiguity for the compiler. Its definition is always the same, following the formula:

``````storage :: HasStorage <storage_type> => Var <storage_type>
storage = storageVar
``````

where `storage_type` is the only thing to fill and has to match the one from the contract we are using this `storage` in.

Although we now know how to compose operators, expressions, variables, etc. we still only have linear code execution, hence the next chapter: Imperative statements

## Technical details: expressions evaluation and variables¶

With the strongly typed foundations described in the previous chapter we want to define expression manipulation and operations.

For this we need an assignment operator that can create a new variable from some expression and to define an `Expr` datatype for expressions construction.

The latter is contained in the `Indigo.Internal.Expr.Types` module. Here we take a look at a simplified version of it to explain it better; let's suppose we defined it like this:

``````data Expr a where
C   :: a -> Expr a
V   :: Var a -> Expr a
Add :: Expr Int -> Expr Int -> Expr Int
``````

The first constructor creates an expression from a constant, the second from a variable and the last one is for the addition operation of two expressions of `Int`s.

We can now define a function that will compile `Expr` to `IndigoM` code, that computes the value of the given expression and leaves it on top of the stack:

``````compileExpr :: Expr a -> IndigoState inp (a : inp) ()
``````

We can see that the resulting type will have a value of type `a` on the top of the stack as a result of the computation.

Let's define it step by step, explaining the definition for each constructor:

``````compileExpr (C a) = do
md <- iget
iput \$ GenCode () (pushNoRefMd md) (L.push a) L.drop
``````

As a reminder: here we use the `do` syntax that thanks to `RebindableSyntax` resolves to `IndigoState`. In the first line we get the current state, of type `MetaData`, while in the second line we construct a `GenCode` datatype, which is the resulting type.

`GenCode` consists (in this order) of a return value, the updated `MetaData`, the generated Lorentz code and the "cleaning" Lorentz code.

As you can see:

• we have no return value just yet
• the metadata is updated by `pushNoRefMd`, which adds a `NoRef` of type `StkEl a` on the top of the stack to satisfy the output stack type: `a : inp`
• the Lorentz code is just a `PUSH`, that puts the value on the stack
• the "cleaning" code is just a `DROP`, this will come in handy if we ever need to remove what we just added (e.g. while exiting a scope or context)

The next step is the constructor for variables:

``````compileExpr (V a) = do
iput \$ GenCode () (pushNoRefMd md) (varActionGet a s) L.drop
``````

This may seem similar to the previous one, but that is because the complexity is hidden by the only difference: `varActionGet`.

As stated previously, the main idea here is that we assign an index to each variable and link them to an element of the stack that it refers to. This is where things come together. To compute an expression that is just a variable we have to generate the Lorentz code to `duup` the element corresponding to this variable. This logic is implemented in the `Indigo.Internal.Lookup` module, that exports the function to copy the value associated to a `Var` to the top of the stack: `varActionGet`.

This function iterates over `StackVars` to find the depth of the `Var`, then check all the required constraints to use the `duupX` Lorentz macro.

You can notice that the same module contains not only the getter of a variable, but also the `varActionSet` setter (to assign to the variable the value on the top of the stack) and the `varActionUpdate` updater (to update the variable using a binary instruction, the value at the top of the stack and the current value of the variable itself)

The last step for `compileExpr` is the `Add` constructor:

``````compileExpr (Add e1 e2) = IndigoState \$ \md ->
let GenCode _ md2 cd2 _cl2  = runIndigoState (compileExpr e2) md in
let GenCode _ _md1 cd1 _cl1 = runIndigoState (compileExpr e1) md2 in
GenCode () (pushNoRefMd md) (cd2 # cd1 # L.add) L.drop
``````

This constructor needs to run the `compileExpr` for the operands of `Add`, it then has to bring it all together in the resulting `GenCode`. In particular, it has to use subsequent metadatas for the operation, but ignore them in the end (because what we put on the stack will be consumed and a new element inserted), compose the generated Lorentz code and ignore the return value as well as the cleaning code (because this too needs to be mindful of the same changes to the stack as metadata).

Now we can finally write the assignment operator, to create a variable referring to the top of the stack after a computed expression takes place. This can be done with a function having the type

``````makeTopVar :: KnownValue x => IndigoState (x : inp) (x : inp) (Var x)
``````

You can find its implementation in the `Indigo.Internal.State` module.

In the `Indigo.Internal.Expr.Types` module you can also find more useful constructors of `Expr` and their compilation. Note the differences in the `Add` constructor, that needs to contain type constraints.

This module also contains types and typeclasses to allow for better handling (see `IsExpr` for the ability to derive expressions from types), functions and operators to generate `Expr` constructors are instead in `Indigo.Internal.Expr.Operators`.

## Technical details: a note about HasStorage¶

`HasStorage` is one of the specific parts of `IndigoContract` that separates it from any generic `IndigoM`.

It is such because every contract has a storage, and we can make it available during compilation.

You can find out more starting by looking at `compileIndigoContract` in the `Indigo.Compilation` module, which is the function that compiles an Indigo contract to Lorentz (code that in turn can be compiled to Morley and Michelson).