[TM-410] make Indigo's tutorial a buildable website

Problem: we can use the existing tutorial to make a static website
for Indigo using mkdocs.
This needs changed in the documentation's content, namely:
- we would like to statically include part of the example modules
- there needs to be an index/home page
- the appendices should be moved to be "reference" pages
- the explanations should not be flat, but include note blocks, etc.
- references to local files need to be removed, as they don't work

Solution: Make a buildable website with:
- configuration for mkdocs and its extension
- CSS for customized styling
- a python-markdown extension for example source code inclusion
parent 1145fb98
......@@ -21,3 +21,6 @@ db.json
local-chain/node-dir/
local-chain/baker.log
local-chain/node.log
# Indigo static website
code/indigo/tutorial/site/
The MIT License (MIT) (Except where stated below)
Copyright (c) 2014 - 2020 Isaac Muse
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
......@@ -9,7 +9,7 @@ management and supports common features of imperative languages.
It is built on top of `Lorentz`, which in turn is built on top of `Morley`, a
dialect that is a superset of vanilla Michelson.
If you are interested more in the relationships between these projects you can
start by taking a look at [Morley's README](../../README.md).
start by taking a look at [the repo on GitLab](https://gitlab.com/morley-framework/morley).
## Overall idea
......@@ -30,6 +30,6 @@ Michelson code (or to any of the other projects in the chain mentioned above).
## Tutorial and documentation
Indigo has a tutorial that you can find [here](tutorial/).
Indigo has a tutorial that you can find at [indigo-lang.gitlab.io](https://indigo-lang.gitlab.io/).
In addition, as for the other Morley projects, it has Haddock documentation.
In addition, as for the other Morley projects, it has [Haddock documentation](https://hackage.haskell.org/package/indigo).
......@@ -7,15 +7,11 @@ SPDX-License-Identifier: LicenseRef-MIT-TQ
# Indigo Tutorial
This is a tutorial for [Indigo eDSL](../).
It aims to be accessible to as many people as possible, but also contains more
technical information for Haskell developers that are interested in learning more.
## Tutorial index
- [00 - Getting started](src/Indigo/Tutorial/T00)
- [01 - Basics and Variables](src/Indigo/Tutorial/T01)
- [02 - Expressions and operators](src/Indigo/Tutorial/T02)
- [03 - Imperative statements](src/Indigo/Tutorial/T03)
- [04 - Functions and Procedures](src/Indigo/Tutorial/T04)
- [05 - Side Effects and Errors](src/Indigo/Tutorial/T05)
- [Appendix A: types](src/Indigo/Tutorial/AA.md)
- [Appendix B: expressions](src/Indigo/Tutorial/AB.md)
You can generate or serve the static website using
[mkdocs](https://mkdocs.readthedocs.io/en/stable/), see their documentation for
the availabe commands.
To use it you will need to install that, as well as:
- [pymdown-extensions](https://pypi.org/project/pymdown-extensions)
- [include_code](docs/markdown-ext)
......@@ -4,16 +4,6 @@ SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
-->
## Tutorial index
- [00 - Getting started](../T00)
- **01 - Basics and Variables**
- [02 - Expressions and operators](../T02)
- [03 - Imperative statements](../T03)
- [04 - Functions and Procedures](../T04)
- [05 - Side Effects and Errors](../T05)
- [Appendix A: types](../AA.md)
- [Appendix B: expressions](../AB.md)
# Basics and Variables
This chapter will explain the basics necessary to write an Indigo contract and
......@@ -21,17 +11,20 @@ the syntax for variable manipulation.
## Contract definitions
### Breaking down the example
## Breaking down the example
There is a new `Example.hs` source file for this chapter:
{!haskell 5-* src/Indigo/Tutorial/Basics/Example.hs!}
There is a new `Example.hs` in this chapter, if you look it up you'll see the
same `exampleContract` as before and a new one: `textKeeper`.
here we can see the same `exampleContract` as before and a new one: `textKeeper`.
Let's ignore `textKeeper` for now and take a deeper look at `exampleContract`.
Its very first line is:
```haskell
exampleContract :: IndigoContract Integer Integer
```
this is a type signature: it says that we are going to define `exampleContract`,
{!haskell 11 src/Indigo/Tutorial/Basics/Example.hs!}
This is a type signature: it says that we are going to define `exampleContract`,
which is (aka has the type of, aka `::`) an `IndigoContract` that takes an `Integer`
parameter and has an `Integer` storage.
Before every contract definition, we need to specify its type signature, it's
......@@ -42,23 +35,23 @@ always going to look like this:
Not that complicated, right?
Let's go to the second line:
```haskell
exampleContract param = defContract do
```
{!haskell 12 src/Indigo/Tutorial/Basics/Example.hs!}
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
then say the contract definition starts here `defContract $` and we begin a code
then say the contract definition starts here `defContract` and we begin a code
block with `do`.
This is even more standard than the first line, the only thing that may differ
with other contracts here is the contract name (obviously) and the name of the
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
storageVar =: param + a
```
{!haskell 13-14 src/Indigo/Tutorial/Basics/Example.hs!}
these lines show both methods of direct variable manipulation:
- 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
......@@ -75,7 +68,7 @@ necessary because numeric types are otherwise ambiguous; a numeric literal, like
`1`, needs to be followed by either `int`, `nat` or `mutez` to clarify that its
type is `Integer`, `Natural` or `Mutez`, respectively.
### Making a new contract
## Making a new contract
Let's try to implement `textKeeper` (without cheating and looking at it!), we
want it to be a contract that takes a string parameter (`MText` type) and has a
......@@ -91,27 +84,32 @@ This is quickly solved by using a code block, like this:
<multiple_lines_definition>
:}
```
If you've used the configuration file included in the previous chapter you will
also be able to see if you are in a code block or not by the different color
and text of the prompt.
!!! note ""
If you've used the configuration file included in the previous chapter you
will also be able to see if you are in a code block or not by the different
color and text of the prompt.
After you have implemented your `textKeeper` you can check that it looks like
the one from the `Example.hs` file in this chapter and you can use
`printAsMichelson` or `saveAsMichelson` on it just as if you had loaded it from
said file.
the one from the `Example.hs` file:
{!haskell 16-18 src/Indigo/Tutorial/Basics/Example.hs!}
and you can use `printAsMichelson` or `saveAsMichelson` on it just as if you had
loaded it from said file.
At this point you may be wondering why string's type is `MText` and numbers'
types are `Integer` or `Natural`. The reason is that Indigo uses a Haskell type
for each corresponding Michelson one.
You can find more info and a complete list of types in [Appendix A: types](../AA.md),
You can find more info and a complete list of types in [the references documentation](types.md),
that also explains how to create your own types from scratch.
On the other end you are probably curious about what are the expressions and
operators available in Indigo beside `+`.
If this is the case you are in luck, because it is exactly the topic of the
[next chapter](../T02)!
[next chapter](expressions.md)!
### Technical details: IndigoState and Var
## Technical details: IndigoState and Var
The core of Indigo is encoded in its `IndigoState` type.
......@@ -174,13 +172,14 @@ which is basically a `State` monad that returns the state of a new type everytim
Getting closer to our case, we add specific types to obtain the actual definition
of our `IndigoState` indexed monad:
```haskell
newtype IndigoState inp out a = IndigoState {runIndigoState :: MetaData inp -> GenCode inp out a}
newtype IndigoState inp out a =
IndigoState {runIndigoState :: MetaData inp -> GenCode inp out a}
```
Although it may look scary, it's basically a state monad that consumes
the references on the stack and returns new references, a value and the Lorentz
code generated during its execution.
You can get more details in the [State module](../../../../../src/Indigo/Internal/State.hs),
You can get more details in the `Indigo.Internal.State` module,
where `MetaData` is the consumed type and `GenCode` is the resulting one.
You'll see that `MetaData` also contains the number of `Var` allocated up to that
point and that `GenCode` also contains the Lorentz code to remove everything
......
/*
SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
Style sheet for the codehilite extension and its custom "source" header.
*/
.codehilite-source { background-color: #f8f8f8; margin-bottom: 0px; padding: .5em; border-style: dashed; border-width: thin; }
.codehilite-source + p { display: none; }
.codehilite-source + .codehilite>pre { margin-top: 0px; }
.codehilite-source + p + .codehilite>pre { margin-top: 0px; }
.codehilite { background: #ffffff; }
.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #888888; font-style: italic } /* Comment */
.codehilite .ch { color: #888888; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #888888; font-style: italic } /* Comment.Multiline */
.codehilite .cpf { color: #888888; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #888888; font-style: italic } /* Comment.Single */
.codehilite .go { color: #888888; font-style: italic } /* Generic.Output */
.codehilite .cp { color: #888888; font-style: italic } /* Comment.Preproc */
.codehilite .cs { color: #888888; font-style: italic } /* Comment.Special */
.codehilite .k { color: #008800; font-weight: bold } /* Keyword */
.codehilite .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008800; font-weight: bold } /* Keyword.Pseudo */
.codehilite .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #bb0066; font-weight: bold } /* Keyword.Type */
.codehilite .mi + .n { color: #E74C3C; font-weight: bold } /* */
.codehilite .m { color: #E74C3C; font-weight: bold } /* Literal.Number */
.codehilite .s { color: #E74C3C; font-weight: bold } /* Literal.String */
.codehilite .mb { color: #E74C3C; font-weight: bold } /* Literal.Number.Bin */
.codehilite .mf { color: #E74C3C; font-weight: bold } /* Literal.Number.Float */
.codehilite .mh { color: #E74C3C; font-weight: bold } /* Literal.Number.Hex */
.codehilite .mi { color: #E74C3C; font-weight: bold } /* Literal.Number.Integer */
.codehilite .mo { color: #E74C3C; font-weight: bold } /* Literal.Number.Oct */
.codehilite .sa { color: #E74C3C; font-weight: bold } /* Literal.String.Affix */
.codehilite .sb { color: #E74C3C; font-weight: bold } /* Literal.String.Backtick */
.codehilite .sc { color: #E74C3C; font-weight: bold } /* Literal.String.Char */
.codehilite .dl { color: #E74C3C; font-weight: bold } /* Literal.String.Delimiter */
.codehilite .sd { color: #E74C3C; font-weight: bold } /* Literal.String.Doc */
.codehilite .s2 { color: #E74C3C; font-weight: bold } /* Literal.String.Double */
.codehilite .se { color: #E74C3C; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #E74C3C; font-weight: bold } /* Literal.String.Heredoc */
.codehilite .si { color: #E74C3C; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #E74C3C; font-weight: bold } /* Literal.String.Other */
.codehilite .sr { color: #E74C3C; font-weight: bold } /* Literal.String.Regex */
.codehilite .s1 { color: #E74C3C; font-weight: bold } /* Literal.String.Single */
.codehilite .ss { color: #E74C3C; font-weight: bold } /* Literal.String.Symbol */
.codehilite .il { color: #E74C3C; font-weight: bold } /* Literal.Number.Integer.Long */
.codehilite .err { color: #a61717 } /* Error */
.codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #aa0000 } /* Generic.Error */
.codehilite .gh { color: #333333 } /* Generic.Heading */
.codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.codehilite .gp { color: #555555 } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #666666 } /* Generic.Subheading */
.codehilite .gt { color: #aa0000 } /* Generic.Traceback */
.codehilite .na { color: #336699 } /* Name.Attribute */
.codehilite .nb { color: #003388 } /* Name.Builtin */
.codehilite .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.codehilite .no { color: #003366; font-weight: bold } /* Name.Constant */
.codehilite .nd { color: #555555 } /* Name.Decorator */
.codehilite .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.codehilite .nl { color: #336699; font-style: italic } /* Name.Label */
.codehilite .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.codehilite .py { color: #336699; font-weight: bold } /* Name.Property */
.codehilite .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #336699 } /* Name.Variable */
.codehilite .o { color: #999999; font-weight: bold } /* Operator.Word */
.codehilite .ow { color: #999999; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .bp { color: #003388 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.codehilite .vc { color: #336699 } /* Name.Variable.Class */
.codehilite .vg { color: #dd7700 } /* Name.Variable.Global */
.codehilite .vi { color: #3333bb } /* Name.Variable.Instance */
.codehilite .vm { color: #336699 } /* Name.Variable.Magic */
/*
SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
*/
.rst-content table thead th {
color: #495057;
background-color: #e9ecef;
border-color: #dee2e6;
}
.rst-content td {
vertical-align: middle;
text-align: center;
}
.rst-content table {
width: 100%;
margin-bottom: 1rem;
}
.rst-content td code {
white-space: nowrap;
}
/*
SPDX-FileCopyrightText: 2014 - 2020 Isaac Muse
SPDX-License-Identifier: LicenseRef-MIT-Isaac-Muse
*/
.tabbed-set {
display: flex;
position: relative;
flex-wrap: wrap;
}
.tabbed-set .highlight {
background: #ddd;
}
.tabbed-set .tabbed-content {
display: none;
order: 99;
width: 100%;
}
.tabbed-set label {
width: auto;
margin: 0 0.5em;
padding: 0.25em;
font-weight: bold;
cursor: pointer;
border-bottom: .1rem solid transparent;
}
.tabbed-set input {
position: absolute;
opacity: 0;
}
.tabbed-set input:nth-child(n+1) {
color: #333333;
}
.tabbed-set input:nth-child(n+1):checked + label {
color: #385abd;
border-color: #385abd;
}
.tabbed-set input:nth-child(n+1):checked + label + .tabbed-content {
display: block;
}
This diff is collapsed.
......@@ -4,25 +4,18 @@ SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
-->
## Tutorial index
- [00 - Getting started](../T00)
- [01 - Basics and Variables](../T01)
- [02 - Expressions and operators](../T02)
- [03 - Imperative statements](../T03)
- **04 - Functions and Procedures**
- [05 - Side Effects and Errors](../T05)
- [Appendix A: types](../AA.md)
- [Appendix B: expressions](../AB.md)
# Functions and Procedures
To promote reusability, readability and separation of code, Indigo supports
functions and procedures. This chapter shows the syntax and expands on their
usage.
### Granular control
## Granular control
This chapter's source file is `Functions.hs`, that contains `functionsContract`:
{!haskell 5-* src/Indigo/Tutorial/Functions/Functions.hs!}
This chapter includes a `Functions.hs` file that contains `functionsContract`.
When converted to Michelson this program is equivalent to the `controlContract`
from the previous chapter.
......@@ -30,40 +23,34 @@ The difference is fully visible, in that the contract itself is much easier to
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
return (val == 0 int)
```
{!haskell 27-29 src/Indigo/Tutorial/Functions/Functions.hs!}
This function takes the place of the code-block we used to execute in the first
pattern-match in `controlContract`, that looked like this:
```haskell
\val -> do
return (val == 0 int)
```
{!haskell 23-24 src/Indigo/Tutorial/Statements/Control.hs!}
As you can see this is almost identical to the `checkZero` function's code.
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
checkZero val = defFunction do
```
{!haskell 20 28 src/Indigo/Tutorial/Functions/Functions.hs!}
The other difference is that by using functions we need to explicitly write a
signature, but this is not hard, we can see that the ones for `checkZero` is:
```haskell
checkZero :: Var Integer -> IndigoFunction Bool
```
Just as we did in the [Basics and Variables](../T01) chapter for contracts,
{!haskell 27 src/Indigo/Tutorial/Functions/Functions.hs!}
Just as we did in the [Basics and Variables](basics.md) chapter for contracts,
we can use a formula to make function signatures:
```
<function_name> :: [Var parameter ->] IndigoFunction <return_type>
```
Here's what you need to know:
- there can be 0 parameters as well as more than one.
- The return type can be any of the supported types.
......@@ -83,9 +70,9 @@ note that just like the other imperative constructs they have (automatically
managed) scope.
Now that we are armed with functions as well we can proceed to the final chapter:
[Side Effects and Errors](../T05).
[Side Effects and Errors](side-effects.md).
### Technical details: defFunction and defContract
## Technical details: defFunction and defContract
As for `IndigoContract`s, both `IndigoProcedure`s and `IndigoFunction`s are just
specialized versions of `IndigoM`.
......@@ -99,5 +86,4 @@ given arbitrary `IndigoM`, using the same logic mentioned in the previous chapte
for imperative statements.
You can find the definitions for all of these types and functions in the
[Compilation](../../../../../src/Indigo/Compilation.hs) and
[Frontend.Language](../../../../../src/Indigo/Frontend/Language.hs) modules.
`Idnigo.Compilation` and `Indigo.Frontend.Language` modules.
......@@ -4,16 +4,6 @@ SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
-->
## Tutorial index
- **00 - Getting started**
- [01 - Basics and Variables](../T01)
- [02 - Expressions and operators](../T02)
- [03 - Imperative statements](../T03)
- [04 - Functions and Procedures](../T04)
- [05 - Side Effects and Errors](../T05)
- [Appendix A: types](../AA.md)
- [Appendix B: expressions](../AB.md)
# Getting started
This tutorial will guide you in developing Michelson contracts using Indigo.
......@@ -26,9 +16,19 @@ can learn about them by reading [tezos' documentation](http://tezos.gitlab.io/)
and following our [Michelson tutorial](https://gitlab.com/morley-framework/michelson-tutorial).
On the software side you will need to install [stack](https://github.com/commercialhaskell/stack)
for compilation.
for compilation and grab the source code for Indigo:
```
git clone https://gitlab.com/morley-framework/morley.git
cd morley
```
### Setup recommendations and first steps
!!! tip "Tutorial resources"
All the resources for this tutorial, including this documentation and the
examples' source code, are located in the [`code/indigo/tutorial`](https://gitlab.com/morley-framework/morley/-/tree/master/code/indigo/tutorial)
subfolder.
## Setup recommendations and first steps
If you are not a Haskell developer and have no intention of becoming one, you
should still be able to follow the tutorial with its examples and write your own
......@@ -36,25 +36,35 @@ contracts as well.
We can start by opening up an interactive shell with Indigo loaded in it.
Note: before opening the shell you are advised to modify the prompt, as the
standard one contains a lot of text. To use a simple one you can simply copy the
`.ghci` file included in this chapter's folder to your home directory.
!!! tip "Cleaner REPL prompt"
Before opening the shell you are advised to modify the prompt, as the
standard one contains a lot of text. To use a simple one you can simply copy
the `.ghci` file to your home directory:
{!bash 5-* .ghci!}
Provided that you have installed `stack` you can open a REPL by issuing, from
the root directory of this repository:
the root directory of the cloned repository:
```bash
stack ghci :indigo-repl
```
Note: it will take some time to compile everything the first time around, but it
will get faster later on, I promise.
!!! note ""
It will take some time to compile everything the first time around, but it
will get faster later on, I promise.
You can now load a source file by using the `:load` command, we can start by
loading the example code provided in this chapter by using:
loading the example code provided in this chapter:
{!haskell 5-14 src/Indigo/Tutorial/GettingStarted/Example.hs!}
```bash
:load code/indigo/tutorial/src/Indigo/Tutorial/T00/Example.hs
:load code/indigo/tutorial/src/Indigo/Tutorial/GettingStarted/Example.hs
```
Note: for these examples, you may receive warnings about `missing-home-modules`,
you can safely ignore these.
!!! warning ""
For these examples, you may receive warnings about `missing-home-modules`,
you can safely ignore these.
Now you have access to the contracts exported by this module (the ones on the
list at the top of the file), that in this case is just `exampleContract`.
......@@ -84,15 +94,23 @@ With these tools at your disposal you will be able to create Indigo contracts an
compile them to Michelson, just by using the REPL.
If you are ready for it, you should head straight for the next chapter:
[Basics and Variables](../T01).
[Basics and Variables](basics.md).
### Technical details: developing using Indigo
## Technical details: developing using Indigo
If you are a Haskell developer interested in developing your own library/contract
using Indigo, you'll probably be better off following this tutorial (that will
contain more of these technical paragraphs) and checking the Haddock documentation
as well.
!!! tip "Generate Haddock documentation"
You can generate Haddock documentation for indigo from its folder
, [`code/indigo`](https://gitlab.com/morley-framework/morley/-/tree/master/code/indigo)
, by using:
:::bash
make haddock
To be able to write your own project you'll probably just need to
```haskell
import Indigo
......@@ -103,8 +121,3 @@ You may not need all of them, but some are necessary and allow the language to
be neatly usable, for example `RebindableSyntax` is what makes it possible to use
the do-notation and Haskell's standard `if ... then ... else` statements (more
details on this will come later).
You may also be interested in tests, in which case you are advised to start by
taking a look at the [Example module](../../../../../test/Test/Examples.hs)
that also shows what they are translated to (in `Lorentz`, but it's easy to
follow along because it closely resembles Michelson's instructions).
<!--
SPDX-FileCopyrightText: 2020 Tocqueville Group
SPDX-License-Identifier: LicenseRef-MIT-TQ
-->
# Indigo eDSL
Indigo eDSL is a high level language for Michelson contract development.
It is meant first and foremost to free you from the burden of manual stack
management and supports common features of imperative languages.
Even with a very small example the difference in ease of use is quite visible:
=== "Indigo"
{!haskell 11-14 src/Indigo/Tutorial/GettingStarted/Example.hs!}
=== "Michelson"
{!bash 19-38 src/Indigo/Tutorial/GettingStarted/Example.hs!}
## Overall idea
Michelson contracts are stack-based and often follow the repetitive pattern of
copying the required values on top of the stack to apply an instruction to them.
Indigo can associate variables to values in the stack and it's able to refer to
them in order to handle this pattern automatically.