Deployed a04dd6c to master with MkDocs 1.2.3 and mike 1.0.1

This commit is contained in:
GitHub Action 2021-12-03 16:26:49 +00:00
parent 6bdb7ca540
commit efad43d8f5
7 changed files with 312 additions and 312 deletions

View File

@ -403,59 +403,59 @@ interface. As yet the interface is very basic.</p>
function new_answer(q : string, a : int) : answers() = { [q] = a }
</code></pre></div>
<p>generates the following JSON structure representing the contract interface:</p>
<div class="highlight"><pre><span></span><code><span class="p">{</span>
<span class="nt">&quot;contract&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;functions&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;arguments&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;init&quot;</span><span class="p">,</span>
<span class="nt">&quot;returns&quot;</span><span class="p">:</span> <span class="s2">&quot;Answers.state&quot;</span><span class="p">,</span>
<span class="nt">&quot;stateful&quot;</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="nt">&quot;arguments&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;q&quot;</span><span class="p">,</span>
<span class="nt">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;string&quot;</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;a&quot;</span><span class="p">,</span>
<span class="nt">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;int&quot;</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;new_answer&quot;</span><span class="p">,</span>
<span class="nt">&quot;returns&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;map&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="s2">&quot;int&quot;</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="nt">&quot;stateful&quot;</span><span class="p">:</span> <span class="kc">false</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Answers&quot;</span><span class="p">,</span>
<span class="nt">&quot;state&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;record&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;a&quot;</span><span class="p">,</span>
<span class="nt">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;Answers.answers&quot;</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="nt">&quot;type_defs&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;answers&quot;</span><span class="p">,</span>
<span class="nt">&quot;typedef&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;map&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="s2">&quot;int&quot;</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="nt">&quot;vars&quot;</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<div class="highlight"><pre><span></span><code><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;contract&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;functions&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;arguments&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;init&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;returns&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Answers.state&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;stateful&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;arguments&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;q&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;string&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;int&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;new_answer&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;returns&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;string&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;int&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;stateful&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Answers&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;state&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;record&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Answers.answers&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;type_defs&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;answers&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;typedef&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;string&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;int&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;vars&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>When that encoding is decoded the following include definition is generated:</p>
<div class="highlight"><pre><span></span><code>contract Answers =

View File

@ -2,47 +2,47 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2021-11-24</lastmod>
<lastmod>2021-12-03</lastmod>
<changefreq>daily</changefreq>
</url>
</urlset>

Binary file not shown.

View File

@ -406,68 +406,68 @@
<h1 id="contract-examples">Contract examples</h1>
<h2 id="crowdfunding">Crowdfunding</h2>
<div class="highlight"><pre><span></span><code>/*
* A simple crowd-funding example
*/
contract FundMe =
<div class="highlight"><pre><span></span><code><span class="cm">/*</span>
<span class="cm"> * A simple crowd-funding example</span>
<span class="cm"> */</span><span class="w"></span>
<span class="k">contract</span><span class="w"> </span><span class="nf">FundMe</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
record spend_args = { recipient : address,
amount : int }
<span class="w"> </span><span class="k">record</span><span class="w"> </span><span class="n">spend_args</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">recipient</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
record state = { contributions : map(address, int),
total : int,
beneficiary : address,
deadline : int,
goal : int }
<span class="w"> </span><span class="k">record</span><span class="w"> </span><span class="nb">state</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">contributions</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">beneficiary</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">deadline</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">goal</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
stateful function spend(args : spend_args) =
Chain.spend(args.recipient, args.amount)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">spend</span><span class="p">(</span><span class="n">args</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">spend_args</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">spend</span><span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">recipient</span><span class="p">,</span><span class="w"> </span><span class="n">args</span><span class="p">.</span><span class="n">amount</span><span class="p">)</span><span class="w"></span>
entrypoint init(beneficiary, deadline, goal) : state =
{ contributions = {},
beneficiary = beneficiary,
deadline = deadline,
total = 0,
goal = goal }
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">beneficiary</span><span class="p">,</span><span class="w"> </span><span class="n">deadline</span><span class="p">,</span><span class="w"> </span><span class="n">goal</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nb">state</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">contributions</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">{},</span><span class="w"></span>
<span class="w"> </span><span class="n">beneficiary</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">beneficiary</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">deadline</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">deadline</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">goal</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">goal</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
function is_contributor(addr) =
Map.member(addr, state.contributions)
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">is_contributor</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Map</span><span class="p">.</span><span class="n">member</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">contributions</span><span class="p">)</span><span class="w"></span>
stateful entrypoint contribute() =
if(Chain.block_height &gt;= state.deadline)
spend({ recipient = Call.caller, amount = Call.value }) // Refund money
false
else
let amount =
switch(Map.lookup(Call.caller, state.contributions))
None =&gt; Call.value
Some(n) =&gt; n + Call.value
put(state{ contributions[Call.caller] = amount,
total @ tot = tot + Call.value })
true
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">contribute</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nc">Chain</span><span class="p">.</span><span class="n">block_height</span><span class="w"> </span><span class="ow">&gt;=</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">deadline</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">spend</span><span class="p">({</span><span class="w"> </span><span class="n">recipient</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="p">,</span><span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="c1">// Refund money</span>
<span class="w"> </span><span class="kc">false</span><span class="w"></span>
<span class="w"> </span><span class="k">else</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="nc">Map</span><span class="p">.</span><span class="n">lookup</span><span class="p">(</span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="p">,</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">contributions</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="w"></span>
<span class="w"> </span><span class="nb">put</span><span class="p">(</span><span class="nb">state</span><span class="p">{</span><span class="w"> </span><span class="n">contributions</span><span class="p">[</span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">amount</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="ow">@</span><span class="w"> </span><span class="n">tot</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">tot</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="kc">true</span><span class="w"></span>
stateful entrypoint withdraw() =
if(Chain.block_height &lt; state.deadline)
abort(&quot;Cannot withdraw before deadline&quot;)
if(Call.caller == state.beneficiary)
withdraw_beneficiary()
elif(is_contributor(Call.caller))
withdraw_contributor()
else
abort(&quot;Not a contributor or beneficiary&quot;)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">withdraw</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nc">Chain</span><span class="p">.</span><span class="n">block_height</span><span class="w"> </span><span class="ow">&lt;</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">deadline</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nb">abort</span><span class="p">(</span><span class="s2">&quot;Cannot withdraw before deadline&quot;</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="w"> </span><span class="ow">==</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">beneficiary</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">withdraw_beneficiary</span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">elif</span><span class="p">(</span><span class="n">is_contributor</span><span class="p">(</span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="n">withdraw_contributor</span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">else</span><span class="w"></span>
<span class="w"> </span><span class="nb">abort</span><span class="p">(</span><span class="s2">&quot;Not a contributor or beneficiary&quot;</span><span class="p">)</span><span class="w"></span>
stateful function withdraw_beneficiary() =
require(state.total &gt;= state.goal, &quot;Project was not funded&quot;)
spend({recipient = state.beneficiary,
amount = Contract.balance })
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">withdraw_beneficiary</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nb">require</span><span class="p">(</span><span class="nb">state</span><span class="p">.</span><span class="n">total</span><span class="w"> </span><span class="ow">&gt;=</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">goal</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Project was not funded&quot;</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">spend</span><span class="p">({</span><span class="n">recipient</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">beneficiary</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Contract</span><span class="p">.</span><span class="n">balance</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
stateful function withdraw_contributor() =
if(state.total &gt;= state.goal)
abort(&quot;Project was funded&quot;)
let to = Call.caller
spend({recipient = to,
amount = state.contributions[to]})
put(state{ contributions @ c = Map.delete(to, c) })
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">withdraw_contributor</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nb">state</span><span class="p">.</span><span class="n">total</span><span class="w"> </span><span class="ow">&gt;=</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">goal</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nb">abort</span><span class="p">(</span><span class="s2">&quot;Project was funded&quot;</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">caller</span><span class="w"></span>
<span class="w"> </span><span class="n">spend</span><span class="p">({</span><span class="n">recipient</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">to</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">state</span><span class="p">.</span><span class="n">contributions</span><span class="p">[</span><span class="n">to</span><span class="p">]})</span><span class="w"></span>
<span class="w"> </span><span class="nb">put</span><span class="p">(</span><span class="nb">state</span><span class="p">{</span><span class="w"> </span><span class="n">contributions</span><span class="w"> </span><span class="ow">@</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Map</span><span class="p">.</span><span class="n">delete</span><span class="p">(</span><span class="n">to</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">)</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
</code></pre></div>
<h2 id="repositories">Repositories</h2>
<p>This is a list with repositories that include smart contracts written in Sophia:</p>

View File

@ -1027,23 +1027,23 @@ and the <a href="../sophia_stdlib/#call">Call</a> namespaces in the documentatio
<p>To call a function in another contract you need the address to an instance of
the contract. The type of the address must be a contract type, which consists
of a number of type definitions and entrypoint declarations. For instance,</p>
<div class="highlight"><pre><span></span><code>// A contract type
contract interface VotingType =
entrypoint vote : string =&gt; unit
<div class="highlight"><pre><span></span><code><span class="c1">// A contract type</span>
<span class="k">contract</span><span class="w"> </span><span class="k">interface</span><span class="w"> </span><span class="nf">VotingType</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">vote</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">unit</span><span class="w"></span>
</code></pre></div>
<p>Now given contract address of type <code>VotingType</code> you can call the <code>vote</code>
entrypoint of that contract:</p>
<div class="highlight"><pre><span></span><code>contract VoteTwice =
entrypoint voteTwice(v : VotingType, alt : string) =
v.vote(alt)
v.vote(alt)
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="nf">VoteTwice</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">voteTwice</span><span class="p">(</span><span class="n">v</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">VotingType</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">vote</span><span class="p">(</span><span class="n">alt</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">vote</span><span class="p">(</span><span class="n">alt</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>Contract calls take two optional named arguments <code>gas : int</code> and <code>value : int</code>
that lets you set a gas limit and provide tokens to a contract call. If omitted
the defaults are no gas limit and no tokens. Suppose there is a fee for voting:</p>
<div class="highlight"><pre><span></span><code> entrypoint voteTwice(v : VotingType, fee : int, alt : string) =
v.vote(value = fee, alt)
v.vote(value = fee, alt)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">voteTwice</span><span class="p">(</span><span class="n">v</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">VotingType</span><span class="p">,</span><span class="w"> </span><span class="n">fee</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">vote</span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fee</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">vote</span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fee</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>Named arguments can be given in any order.</p>
<p>Note that reentrant calls are not permitted. In other words, when calling
@ -1057,8 +1057,8 @@ fails.</p>
<p>To recover the underlying <code>address</code> of a contract instance there is a field
<code>address : address</code>. For instance, to send tokens to the voting contract (given that it is payable)
without calling it you can write</p>
<div class="highlight"><pre><span></span><code> entrypoint pay(v : VotingType, amount : int) =
Chain.spend(v.address, amount)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">pay</span><span class="p">(</span><span class="n">v</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">VotingType</span><span class="p">,</span><span class="w"> </span><span class="n">amount</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">spend</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">amount</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<h3 id="protected-contract-calls">Protected contract calls</h3>
<p>If a contract call fails for any reason (for instance, the remote contract
@ -1069,14 +1069,14 @@ contract calls takes a named argument <code>protected : bool</code> (default <co
changes the type of the contract call, wrapping the result in an <code>option</code> type.
If the call fails the result is <code>None</code>, otherwise it's <code>Some(r)</code> where <code>r</code> is
the return value of the call.</p>
<div class="highlight"><pre><span></span><code>contract interface VotingType =
entrypoint : vote : string =&gt; unit
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="k">interface</span><span class="w"> </span><span class="nf">VotingType</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">vote</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">unit</span><span class="w"></span>
contract Voter =
entrypoint tryVote(v : VotingType, alt : string) =
switch(v.vote(alt, protected = true) : option(unit))
None =&gt; &quot;Voting failed&quot;
Some(_) =&gt; &quot;Voting successful&quot;
<span class="k">contract</span><span class="w"> </span><span class="nf">Voter</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">tryVote</span><span class="p">(</span><span class="n">v</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">VotingType</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">vote</span><span class="p">(</span><span class="n">alt</span><span class="p">,</span><span class="w"> </span><span class="n">protected</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kc">true</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="kt">unit</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="s2">&quot;Voting failed&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="s2">&quot;Voting successful&quot;</span><span class="w"></span>
</code></pre></div>
<p>Any gas that was consumed by the contract call before the failure stays
consumed, which means that in order to protect against the remote contract
@ -1096,15 +1096,15 @@ arguments please refer to their documentation for the details.</p>
<p>While <code>Chain.clone</code> requires only a <code>contract interface</code> and a living instance
of a given contract on the chain, <code>Chain.create</code> needs a full definition of a
to-create contract defined by the standard <code>contract</code> syntax, for example</p>
<div class="highlight"><pre><span></span><code>contract IntHolder =
type state = int
entrypoint init(x) = x
entrypoint get() = state
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="nf">IntHolder</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nb">state</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">get</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">state</span><span class="w"></span>
main contract IntHolderFactory =
stateful entrypoint new(x : int) : IntHolder =
let ih = Chain.create(x) : IntHolder
ih
<span class="k">main</span><span class="w"> </span><span class="k">contract</span><span class="w"> </span><span class="nf">IntHolderFactory</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">new</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">IntHolder</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">ih</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nf">IntHolder</span><span class="w"></span>
<span class="w"> </span><span class="n">ih</span><span class="w"></span>
</code></pre></div>
<p>In case of a presence of child contracts (<code>IntHolder</code> in this case), the main
contract must be pointed out with the <code>main</code> keyword as shown in the example.</p>
@ -1133,8 +1133,8 @@ provides special syntax for map/record updates.</p>
<p>Top-level functions and entrypoints must be annotated with the
<code>stateful</code> keyword to be allowed to affect the state of the running contract.
For instance,</p>
<div class="highlight"><pre><span></span><code> stateful entrypoint set_state(s : state) =
put(s)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">set_state</span><span class="p">(</span><span class="n">s</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nb">state</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nb">put</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>Without the <code>stateful</code> annotation the compiler does not allow the call to
<code>put</code>. A <code>stateful</code> annotation is required to</p>
@ -1165,9 +1165,9 @@ For instance,</p>
<p>A concrete contract is by default <em>not</em> payable. Any attempt at spending to such
a contract (either a <code>Chain.spend</code> or a normal spend transaction) will fail. If a
contract shall be able to receive funds in this way it has to be declared <code>payable</code>:</p>
<div class="highlight"><pre><span></span><code>// A payable contract
payable contract ExampleContract =
stateful entrypoint do_stuff() = ...
<div class="highlight"><pre><span></span><code><span class="c1">// A payable contract</span>
<span class="k">payable</span><span class="w"> </span><span class="k">contract</span><span class="w"> </span><span class="nf">ExampleContract</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">do_stuff</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span>
</code></pre></div>
<p>If in doubt, it is possible to check if an address is payable using
<code>Address.is_payable(addr)</code>.</p>
@ -1176,11 +1176,11 @@ payable contract ExampleContract =
(either a <a href="#calling-other-contracts">Remote call</a> or a contract call transaction)
that has a non-zero <code>value</code> will fail. Contract entrypoints that should be called
with a non-zero value should be declared <code>payable</code>.</p>
<div class="highlight"><pre><span></span><code>payable stateful entrypoint buy(to : address) =
if(Call.value &gt; 42)
transfer_item(to)
else
abort(&quot;Value too low&quot;)
<div class="highlight"><pre><span></span><code><span class="k">payable</span><span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">buy</span><span class="p">(</span><span class="n">to</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">42</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">transfer_item</span><span class="p">(</span><span class="n">to</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">else</span><span class="w"></span>
<span class="w"> </span><span class="nb">abort</span><span class="p">(</span><span class="s2">&quot;Value too low&quot;</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>Note: In the æternity VM (AEVM) contracts and entrypoints were by default
payable until the Lima release.</p>
@ -1190,13 +1190,13 @@ can appear at the top-level and can contain type and function definitions, but
not entrypoints. Outside the namespace you can refer to the (non-private) names
by qualifying them with the namespace (<code>Namespace.name</code>).
For example,</p>
<div class="highlight"><pre><span></span><code>namespace Library =
type number = int
function inc(x : number) : number = x + 1
<div class="highlight"><pre><span></span><code><span class="k">namespace</span><span class="w"> </span><span class="nf">Library</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">inc</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">number</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="mi">1</span><span class="w"></span>
contract MyContract =
entrypoint plus2(x) : Library.number =
Library.inc(Library.inc(x))
<span class="k">contract</span><span class="w"> </span><span class="nf">MyContract</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">plus2</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">Library</span><span class="p">.</span><span class="n">number</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Library</span><span class="p">.</span><span class="n">inc</span><span class="p">(</span><span class="nc">Library</span><span class="p">.</span><span class="n">inc</span><span class="p">(</span><span class="n">x</span><span class="p">))</span><span class="w"></span>
</code></pre></div>
<p>Functions in namespaces have access to the same environment (including the
<code>Chain</code>, <code>Call</code>, and <code>Contract</code>, builtin namespaces) as function in a contract,
@ -1256,13 +1256,13 @@ contract level, namespace level, or in the function level.</p>
statement. These must appear at the top-level (outside the main contract). The
included file can contain one or more namespaces and abstract contracts. For
example, if the file <code>library.aes</code> contains</p>
<div class="highlight"><pre><span></span><code>namespace Library =
function inc(x) = x + 1
<div class="highlight"><pre><span></span><code><span class="k">namespace</span><span class="w"> </span><span class="nf">Library</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">inc</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="mi">1</span><span class="w"></span>
</code></pre></div>
<p>you can use it from another file using an <code>include</code>:</p>
<div class="highlight"><pre><span></span><code>include &quot;library.aes&quot;
contract MyContract =
entrypoint plus2(x) = Library.inc(Library.inc(x))
<div class="highlight"><pre><span></span><code><span class="k">include</span><span class="w"> </span><span class="s2">&quot;library.aes&quot;</span><span class="w"></span>
<span class="k">contract</span><span class="w"> </span><span class="nf">MyContract</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">plus2</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Library</span><span class="p">.</span><span class="n">inc</span><span class="p">(</span><span class="nc">Library</span><span class="p">.</span><span class="n">inc</span><span class="p">(</span><span class="n">x</span><span class="p">))</span><span class="w"></span>
</code></pre></div>
<p>This behaves as if the contents of <code>library.aes</code> was textually inserted into
the file, except that error messages will refer to the original source
@ -1275,13 +1275,13 @@ namespaces like <code>Chain</code>, <code>Contract</code>, <code>Map</code>
are included by default and are supported internally by the compiler.
Others like <code>List</code>, <code>Frac</code>, <code>Option</code> need to be manually included using the
<code>include</code> directive. For example
<div class="highlight"><pre><span></span><code>include &quot;List.aes&quot;
include &quot;Pair.aes&quot;
-- Map is already there!
<div class="highlight"><pre><span></span><code><span class="k">include</span><span class="w"> </span><span class="s2">&quot;List.aes&quot;</span><span class="w"></span>
<span class="k">include</span><span class="w"> </span><span class="s2">&quot;Pair.aes&quot;</span><span class="w"></span>
<span class="ow">--</span><span class="w"> </span><span class="nf">Map</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">already</span><span class="w"> </span><span class="n">there</span><span class="ow">!</span><span class="w"></span>
namespace C =
entrypoint keys(m : map(&#39;a, &#39;b)) : list(&#39;a) =
List.map(Pair.fst, (Map.to_list(m)))
<span class="k">namespace</span><span class="w"> </span><span class="nf">C</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">keys</span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">List</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="nc">Pair</span><span class="p">.</span><span class="n">fst</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nc">Map</span><span class="p">.</span><span class="n">to_list</span><span class="p">(</span><span class="n">m</span><span class="p">)))</span><span class="w"></span>
</code></pre></div></p>
<h2 id="types">Types</h2>
<p>Sophia has the following types:</p>
@ -1508,8 +1508,8 @@ corresponding integer, so setting very high bits can be expensive).</p>
<h2 id="type-aliases">Type aliases</h2>
<p>Type aliases can be introduced with the <code>type</code> keyword and can be
parameterized. For instance</p>
<div class="highlight"><pre><span></span><code>type number = int
type string_map(&#39;a) = map(string, &#39;a)
<div class="highlight"><pre><span></span><code><span class="k">type</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="k">type</span><span class="w"> </span><span class="n">string_map</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>A type alias and its definition can be used interchangeably. Sophia does not support
higher-kinded types, meaning that following type alias is invalid: <code>type wrap('f, 'a) = 'f('a)</code></p>
@ -1517,47 +1517,47 @@ higher-kinded types, meaning that following type alias is invalid: <code>type wr
<p>Sophia supports algebraic data types (variant types) and pattern matching. Data
types are declared by giving a list of constructors with
their respective arguments. For instance,</p>
<div class="highlight"><pre><span></span><code>datatype one_or_both(&#39;a, &#39;b) = Left(&#39;a) | Right(&#39;b) | Both(&#39;a, &#39;b)
<div class="highlight"><pre><span></span><code><span class="k">datatype</span><span class="w"> </span><span class="n">one_or_both</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Left</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="nf">Right</span><span class="p">(</span><span class="nv">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="nf">Both</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>Elements of data types can be pattern matched against, using the <code>switch</code> construct:</p>
<div class="highlight"><pre><span></span><code>function get_left(x : one_or_both(&#39;a, &#39;b)) : option(&#39;a) =
switch(x)
Left(x) =&gt; Some(x)
Right(_) =&gt; None
Both(x, _) =&gt; Some(x)
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"> </span><span class="n">get_left</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">one_or_both</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nf">Left</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nf">Right</span><span class="p">(</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">None</span><span class="w"></span>
<span class="w"> </span><span class="nf">Both</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>or directly in the left-hand side:
<div class="highlight"><pre><span></span><code>function
get_left : one_or_both(&#39;a, &#39;b) =&gt; option(&#39;a)
get_left(Left(x)) = Some(x)
get_left(Right(_)) = None
get_left(Both(x, _)) = Some(x)
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">one_or_both</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left</span><span class="p">(</span><span class="nf">Left</span><span class="p">(</span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left</span><span class="p">(</span><span class="nf">Right</span><span class="p">(</span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">None</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left</span><span class="p">(</span><span class="nf">Both</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
</code></pre></div></p>
<p><em>NOTE: Data types cannot currently be recursive.</em></p>
<p>Sophia also supports the assignment of patterns to variables:
<div class="highlight"><pre><span></span><code>function f(x) = switch(x)
h1::(t = h2::_) =&gt; (h1 + h2)::t // same as `h1::h2::k =&gt; (h1 + h2)::h2::k`
_ =&gt; x
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">h1</span><span class="ow">::</span><span class="p">(</span><span class="n">t</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">h2</span><span class="ow">::</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">h1</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="n">h2</span><span class="p">)</span><span class="ow">::</span><span class="n">t</span><span class="w"> </span><span class="c1">// same as `h1::h2::k =&gt; (h1 + h2)::h2::k`</span>
<span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>
function g(p : int * option(int)) : int =
let (a, (o = Some(b))) = p // o is equal to Pair.snd(p)
b
<span class="k">function</span><span class="w"> </span><span class="n">g</span><span class="p">(</span><span class="n">p</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="ow">*</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="kt">int</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">b</span><span class="p">)))</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="c1">// o is equal to Pair.snd(p)</span>
<span class="w"> </span><span class="n">b</span><span class="w"></span>
</code></pre></div></p>
<p>Guards are boolean expressions that can be used on patterns in both switch
statements and functions definitions. If a guard expression evaluates to
<code>true</code>, then the corresponding body will be used. Otherwise, the next pattern
will be checked:</p>
<div class="highlight"><pre><span></span><code>function get_left_if_positive(x : one_or_both(int, &#39;b)) : option(int) =
switch(x)
Left(x) | x &gt; 0 =&gt; Some(x)
Both(x, _) | x &gt; 0 =&gt; Some(x)
_ =&gt; None
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"> </span><span class="n">get_left_if_positive</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">one_or_both</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nf">Left</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nf">Both</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="nf">None</span><span class="w"></span>
</code></pre></div>
<div class="highlight"><pre><span></span><code>function
get_left_if_positive : one_or_both(int, &#39;b) =&gt; option(int)
get_left_if_positive(Left(x)) | x &gt; 0 = Some(x)
get_left_if_positive(Both(x, _)) | x &gt; 0 = Some(x)
get_left_if_positive(_) = None
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left_if_positive</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">one_or_both</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="nv">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left_if_positive</span><span class="p">(</span><span class="nf">Left</span><span class="p">(</span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left_if_positive</span><span class="p">(</span><span class="nf">Both</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="n">get_left_if_positive</span><span class="p">(</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">None</span><span class="w"></span>
</code></pre></div>
<p>Guards cannot be stateful even when used inside a stateful function.</p>
<h2 id="lists">Lists</h2>
@ -1566,9 +1566,9 @@ linked list. A list is constructed with the syntax <code>[1, 2, 3]</code>. The
elements of a list can be any of datatype but they must have the same
type. The type of lists with elements of type <code>'e</code> is written
<code>list('e)</code>. For example we can have the following lists:</p>
<div class="highlight"><pre><span></span><code>[1, 33, 2, 666] : list(int)
[(1, &quot;aaa&quot;), (10, &quot;jjj&quot;), (666, &quot;the beast&quot;)] : list(int * string)
[{[1] = &quot;aaa&quot;, [10] = &quot;jjj&quot;}, {[5] = &quot;eee&quot;, [666] = &quot;the beast&quot;}] : list(map(int, string))
<div class="highlight"><pre><span></span><code><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">33</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">666</span><span class="p">]</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"></span>
<span class="p">[(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;aaa&quot;</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;jjj&quot;</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">666</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;the beast&quot;</span><span class="p">)]</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="ow">*</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"></span>
<span class="p">[{[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s2">&quot;aaa&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="mi">10</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s2">&quot;jjj&quot;</span><span class="p">},</span><span class="w"> </span><span class="p">{[</span><span class="mi">5</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s2">&quot;eee&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="mi">666</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s2">&quot;the beast&quot;</span><span class="p">}]</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="kt">map</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="p">))</span><span class="w"></span>
</code></pre></div>
<p>New elements can be prepended to the front of a list with the <code>::</code>
operator. So <code>42 :: [1, 2, 3]</code> returns the list <code>[42, 1, 2, 3]</code>. The
@ -1577,20 +1577,20 @@ and returns the resulting list. So concatenating two lists
<code>[1, 22, 33] ++ [10, 18, 55]</code> returns the list <code>[1, 22, 33, 10, 18, 55]</code>.</p>
<p>Sophia supports list comprehensions known from languages like Python, Haskell or Erlang.
Example syntax:
<div class="highlight"><pre><span></span><code>[x + y | x &lt;- [1,2,3,4,5], let k = x*x, if (k &gt; 5), y &lt;- [k, k+1, k+2]]
// yields [12,13,14,20,21,22,30,31,32]
<div class="highlight"><pre><span></span><code><span class="p">[</span><span class="n">x</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">&lt;-</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="ow">*</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">5</span><span class="p">),</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">&lt;-</span><span class="w"> </span><span class="p">[</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="ow">+</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="ow">+</span><span class="mi">2</span><span class="p">]]</span><span class="w"></span>
<span class="c1">// yields [12,13,14,20,21,22,30,31,32]</span>
</code></pre></div></p>
<p>Lists can be constructed using the range syntax using special <code>..</code> operator:
<div class="highlight"><pre><span></span><code>[1..4] == [1,2,3,4]
<div class="highlight"><pre><span></span><code><span class="p">[</span><span class="mi">1</span><span class="p">..</span><span class="mi">4</span><span class="p">]</span><span class="w"> </span><span class="ow">==</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span><span class="w"></span>
</code></pre></div>
The ranges are always ascending and have step equal to 1.</p>
<p>Please refer to the <a href="../sophia_stdlib/#list">standard library</a> for the predefined functionalities.</p>
<h2 id="maps-and-records">Maps and records</h2>
<p>A Sophia record type is given by a fixed set of fields with associated,
possibly different, types. For instance
<div class="highlight"><pre><span></span><code> record account = { name : string,
balance : int,
history : list(transaction) }
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">record</span><span class="w"> </span><span class="n">account</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">balance</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">history</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="n">transaction</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div></p>
<p>Maps, on the other hand, can contain an arbitrary number of key-value bindings,
but of a fixed type. The type of maps with keys of type <code>'k</code> and values of type
@ -1600,18 +1600,18 @@ contain a map or a function type.</p>
<h3 id="constructing-maps-and-records">Constructing maps and records</h3>
<p>A value of record type is constructed by giving a value for each of the fields.
For the example above,
<div class="highlight"><pre><span></span><code> function new_account(name) =
{name = name, balance = 0, history = []}
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">new_account</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">balance</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">history</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">[]}</span><span class="w"></span>
</code></pre></div>
Maps are constructed similarly, with keys enclosed in square brackets
<div class="highlight"><pre><span></span><code> function example_map() : map(string, int) =
{[&quot;key1&quot;] = 1, [&quot;key2&quot;] = 2}
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">example_map</span><span class="p">()</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="p">{[</span><span class="s2">&quot;key1&quot;</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;key2&quot;</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">2</span><span class="p">}</span><span class="w"></span>
</code></pre></div>
The empty map is written <code>{}</code>.</p>
<h3 id="accessing-values">Accessing values</h3>
<p>Record fields access is written <code>r.f</code> and map lookup <code>m[k]</code>. For instance,
<div class="highlight"><pre><span></span><code> function get_balance(a : address, accounts : map(address, account)) =
accounts[a].balance
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">get_balance</span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">accounts</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">account</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="n">accounts</span><span class="p">[</span><span class="n">a</span><span class="p">].</span><span class="n">balance</span><span class="w"></span>
</code></pre></div>
Looking up a non-existing key in a map results in contract execution failing. A
default value to return for non-existing keys can be provided using the syntax
@ -1630,13 +1630,13 @@ in the map or execution fails, but a default value can be provided:
<code>m{ [k = default] @ x = v }</code>. In this case <code>x</code> is bound to <code>default</code> if
<code>k</code> is not in the map.</p>
<p>Updates can be nested:
<div class="highlight"><pre><span></span><code>function clear_history(a : address, accounts : map(address, account)) : map(address, account) =
accounts{ [a].history = [] }
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"> </span><span class="n">clear_history</span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">accounts</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">account</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">map</span><span class="p">(</span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">account</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="n">accounts</span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">].</span><span class="n">history</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
This is equivalent to <code>accounts{ [a] @ acc = acc{ history = [] } }</code> and thus
requires <code>a</code> to be present in the accounts map. To have <code>clear_history</code> create
an account if <code>a</code> is not in the map you can write (given a function <code>empty_account</code>):
<div class="highlight"><pre><span></span><code> accounts{ [a = empty_account()].history = [] }
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">accounts</span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">empty_account</span><span class="p">()].</span><span class="n">history</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div></p>
<h3 id="map-implementation">Map implementation</h3>
<p>Internally in the VM maps are implemented as hash maps and support fast lookup
@ -1676,53 +1676,53 @@ through the Oracle interface.</p>
For a functionality documentation refer to the <a href="../sophia_stdlib/#oracle">standard library</a>.</p>
<h3 id="example">Example</h3>
<p>Example for an oracle answering questions of type <code>string</code> with answers of type <code>int</code>:
<div class="highlight"><pre><span></span><code>contract Oracles =
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="nf">Oracles</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
stateful entrypoint registerOracle(acct : address,
sign : signature, // Signed network id + oracle address + contract address
qfee : int,
ttl : Chain.ttl) : oracle(string, int) =
Oracle.register(acct, signature = sign, qfee, ttl)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">registerOracle</span><span class="p">(</span><span class="n">acct</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">sign</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">,</span><span class="w"> </span><span class="c1">// Signed network id + oracle address + contract address</span>
<span class="w"> </span><span class="n">qfee</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">ttl</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">ttl</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">register</span><span class="p">(</span><span class="n">acct</span><span class="p">,</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sign</span><span class="p">,</span><span class="w"> </span><span class="n">qfee</span><span class="p">,</span><span class="w"> </span><span class="n">ttl</span><span class="p">)</span><span class="w"></span>
entrypoint queryFee(o : oracle(string, int)) : int =
Oracle.query_fee(o)
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">queryFee</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">query_fee</span><span class="p">(</span><span class="n">o</span><span class="p">)</span><span class="w"></span>
payable stateful entrypoint createQuery(o : oracle_query(string, int),
q : string,
qfee : int,
qttl : Chain.ttl,
rttl : int) : oracle_query(string, int) =
require(qfee =&lt; Call.value, &quot;insufficient value for qfee&quot;)
Oracle.query(o, q, qfee, qttl, RelativeTTL(rttl))
<span class="w"> </span><span class="k">payable</span><span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">createQuery</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">qfee</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">qttl</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">ttl</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">rttl</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nb">require</span><span class="p">(</span><span class="n">qfee</span><span class="w"> </span><span class="ow">=&lt;</span><span class="w"> </span><span class="nc">Call</span><span class="p">.</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;insufficient value for qfee&quot;</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">query</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">q</span><span class="p">,</span><span class="w"> </span><span class="n">qfee</span><span class="p">,</span><span class="w"> </span><span class="n">qttl</span><span class="p">,</span><span class="w"> </span><span class="nf">RelativeTTL</span><span class="p">(</span><span class="n">rttl</span><span class="p">))</span><span class="w"></span>
stateful entrypoint extendOracle(o : oracle(string, int),
ttl : Chain.ttl) : unit =
Oracle.extend(o, ttl)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">extendOracle</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">ttl</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">ttl</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">unit</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">extend</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">ttl</span><span class="p">)</span><span class="w"></span>
stateful entrypoint signExtendOracle(o : oracle(string, int),
sign : signature, // Signed network id + oracle address + contract address
ttl : Chain.ttl) : unit =
Oracle.extend(o, signature = sign, ttl)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">signExtendOracle</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">sign</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">,</span><span class="w"> </span><span class="c1">// Signed network id + oracle address + contract address</span>
<span class="w"> </span><span class="n">ttl</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">ttl</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">unit</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">extend</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sign</span><span class="p">,</span><span class="w"> </span><span class="n">ttl</span><span class="p">)</span><span class="w"></span>
stateful entrypoint respond(o : oracle(string, int),
q : oracle_query(string, int),
sign : signature, // Signed network id + oracle query id + contract address
r : int) =
Oracle.respond(o, q, signature = sign, r)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">respond</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">sign</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">,</span><span class="w"> </span><span class="c1">// Signed network id + oracle query id + contract address</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">q</span><span class="p">,</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sign</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"></span>
entrypoint getQuestion(o : oracle(string, int),
q : oracle_query(string, int)) : string =
Oracle.get_question(o, q)
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">getQuestion</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">get_question</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">q</span><span class="p">)</span><span class="w"></span>
entrypoint hasAnswer(o : oracle(string, int),
q : oracle_query(string, int)) =
switch(Oracle.get_answer(o, q))
None =&gt; false
Some(_) =&gt; true
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">hasAnswer</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="nc">Oracle</span><span class="p">.</span><span class="n">get_answer</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">q</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kc">false</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kc">true</span><span class="w"></span>
entrypoint getAnswer(o : oracle(string, int),
q : oracle_query(string, int)) : option(int) =
Oracle.get_answer(o, q)
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">getAnswer</span><span class="p">(</span><span class="n">o</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">oracle_query</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">))</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">option</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Oracle</span><span class="p">.</span><span class="n">get_answer</span><span class="p">(</span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="n">q</span><span class="p">)</span><span class="w"></span>
</code></pre></div></p>
<h3 id="sanity-checks">Sanity checks</h3>
<p>When an Oracle literal is passed to a contract, no deep checks are performed.
@ -1739,29 +1739,29 @@ an account with address <code>addr</code>. In order to allow a contract <code>ct
<a href="#delegation-signature">signature</a> <code>sig</code> of <code>addr | name.hash | ct.address</code>.</p>
<p>Armed with this information we can for example write a function that extends
the name if it expires within 1000 blocks:
<div class="highlight"><pre><span></span><code> stateful entrypoint extend_if_necessary(addr : address, name : string, sig : signature) =
switch(AENS.lookup(name))
None =&gt; ()
Some(AENS.Name(_, FixedTTL(expiry), _)) =&gt;
if(Chain.block_height + 1000 &gt; expiry)
AENS.update(addr, name, Some(RelativeTTL(50000)), None, None, signature = sig)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">extend_if_necessary</span><span class="p">(</span><span class="n">addr</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="n">sig</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">name</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="nf">FixedTTL</span><span class="p">(</span><span class="n">expiry</span><span class="p">),</span><span class="w"> </span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="nc">Chain</span><span class="p">.</span><span class="n">block_height</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="mi">1000</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="n">expiry</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nc">AENS</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="nf">RelativeTTL</span><span class="p">(</span><span class="mi">50000</span><span class="p">)),</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sig</span><span class="p">)</span><span class="w"></span>
</code></pre></div></p>
<p>And we can write functions that adds and removes keys from the pointers of the
name:
<div class="highlight"><pre><span></span><code> stateful entrypoint add_key(addr : address, name : string, key : string,
pt : AENS.pointee, sig : signature) =
switch(AENS.lookup(name))
None =&gt; ()
Some(AENS.Name(_, _, ptrs)) =&gt;
AENS.update(addr, name, None, None, Some(ptrs{[key] = pt}), signature = sig)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">add_key</span><span class="p">(</span><span class="n">addr</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">pt</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nc">AENS</span><span class="p">.</span><span class="n">pointee</span><span class="p">,</span><span class="w"> </span><span class="n">sig</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">name</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">ptrs</span><span class="p">))</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"></span>
<span class="w"> </span><span class="nc">AENS</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">ptrs</span><span class="p">{[</span><span class="n">key</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pt</span><span class="p">}),</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sig</span><span class="p">)</span><span class="w"></span>
stateful entrypoint delete_key(addr : address, name : string,
key : string, sig : signature) =
switch(AENS.lookup(name))
None =&gt; ()
Some(AENS.Name(_, _, ptrs)) =&gt;
let ptrs = Map.delete(key, ptrs)
AENS.update(addr, name, None, None, Some(ptrs), signature = sig)
<span class="w"> </span><span class="k">stateful</span><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">delete_key</span><span class="p">(</span><span class="n">addr</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">address</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="n">sig</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">name</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="nc">AENS</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">ptrs</span><span class="p">))</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">ptrs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nc">Map</span><span class="p">.</span><span class="n">delete</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">ptrs</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="nc">AENS</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="nf">None</span><span class="p">,</span><span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">ptrs</span><span class="p">),</span><span class="w"> </span><span class="kt">signature</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sig</span><span class="p">)</span><span class="w"></span>
</code></pre></div></p>
<p><em>Note:</em> From the Iris hardfork more strict rules apply for AENS pointers, when
a Sophia contract lookup or update (bad) legacy pointers, the bad keys are
@ -1773,11 +1773,11 @@ Solidity</a>.
Events are further discussed in the <a href="https://github.com/aeternity/protocol/blob/master/contracts/events.md">protocol</a>.</p>
<p>To use events a contract must declare a datatype <code>event</code>, and events are then
logged using the <code>Chain.event</code> function:</p>
<div class="highlight"><pre><span></span><code> datatype event
= Event1(int, int, string)
| Event2(string, address)
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">datatype</span><span class="w"> </span><span class="kt">event</span><span class="w"></span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Event1</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="nf">Event2</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">address</span><span class="p">)</span><span class="w"></span>
Chain.event(e : event) : unit
<span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">event</span><span class="p">(</span><span class="n">e</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">event</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">unit</span><span class="w"></span>
</code></pre></div>
<p>The event can have 0-3 <em>indexed</em> fields, and an optional <em>payload</em> field. A
field is indexed if it fits in a 32-byte word, i.e.
@ -1794,18 +1794,18 @@ The fields can appear in any order.</p>
<p><em>NOTE:</em> Indexing is not part of the core æternity node.</p>
<p>Events are emitted by using the <code>Chain.event</code> function. The following function
will emit one Event of each kind in the example.</p>
<div class="highlight"><pre><span></span><code> entrypoint emit_events() : () =
Chain.event(Event1(42, 34, &quot;foo&quot;))
Chain.event(Event2(&quot;This is not indexed&quot;, Contract.address))
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">emit_events</span><span class="p">()</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">event</span><span class="p">(</span><span class="nf">Event1</span><span class="p">(</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">34</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;foo&quot;</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nc">Chain</span><span class="p">.</span><span class="n">event</span><span class="p">(</span><span class="nf">Event2</span><span class="p">(</span><span class="s2">&quot;This is not indexed&quot;</span><span class="p">,</span><span class="w"> </span><span class="nc">Contract</span><span class="p">.</span><span class="n">address</span><span class="p">))</span><span class="w"></span>
</code></pre></div>
<h3 id="argument-order">Argument order</h3>
<p>It is only possible to have one (1) <code>string</code> parameter in the event, but it can
be placed in any position (and its value will end up in the <code>data</code> field), i.e.
<div class="highlight"><pre><span></span><code>AnotherEvent(string, indexed address)
<div class="highlight"><pre><span></span><code><span class="nf">AnotherEvent</span><span class="p">(</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="k">indexed</span><span class="w"> </span><span class="kt">address</span><span class="p">)</span><span class="w"></span>
...
<span class="p">...</span><span class="w"></span>
Chain.event(AnotherEvent(&quot;This is not indexed&quot;, Contract.address))
<span class="nc">Chain</span><span class="p">.</span><span class="n">event</span><span class="p">(</span><span class="nf">AnotherEvent</span><span class="p">(</span><span class="s2">&quot;This is not indexed&quot;</span><span class="p">,</span><span class="w"> </span><span class="nc">Contract</span><span class="p">.</span><span class="n">address</span><span class="p">))</span><span class="w"></span>
</code></pre></div>
would yield exactly the same result in the example above!</p>
<h2 id="compiler-pragmas">Compiler pragmas</h2>
@ -1813,8 +1813,8 @@ would yield exactly the same result in the example above!</p>
Sophia compiler, you can give one or more <code>@compiler</code> pragmas at the
top-level (typically at the beginning) of a file. For instance, to enforce that
a contract is compiled with version 4.3 of the compiler you write</p>
<div class="highlight"><pre><span></span><code>@compiler &gt;= 4.3
@compiler &lt; 4.4
<div class="highlight"><pre><span></span><code><span class="ow">@</span><span class="n">compiler</span><span class="w"> </span><span class="ow">&gt;=</span><span class="w"> </span><span class="mi">4</span><span class="p">.</span><span class="mi">3</span><span class="w"></span>
<span class="ow">@</span><span class="n">compiler</span><span class="w"> </span><span class="ow">&lt;</span><span class="w"> </span><span class="mi">4</span><span class="p">.</span><span class="mi">4</span><span class="w"></span>
</code></pre></div>
<p>Valid operators in compiler pragmas are <code>&lt;</code>, <code>=&lt;</code>, <code>==</code>, <code>&gt;=</code>, and <code>&gt;</code>. Version
numbers are given as a sequence of non-negative integers separated by dots.
@ -1822,15 +1822,15 @@ Trailing zeros are ignored, so <code>4.0.0 == 4</code>. If a constraint is viola
error is reported and compilation fails.</p>
<h2 id="exceptions">Exceptions</h2>
<p>Contracts can fail with an (uncatchable) exception using the built-in function</p>
<div class="highlight"><pre><span></span><code>abort(reason : string) : &#39;a
<div class="highlight"><pre><span></span><code><span class="nb">abort</span><span class="p">(</span><span class="n">reason</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nv">&#39;a</span><span class="w"></span>
</code></pre></div>
<p>Calling abort causes the top-level call transaction to return an error result
containing the <code>reason</code> string. Only the gas used up to and including the abort
call is charged. This is different from termination due to a crash which
consumes all available gas.</p>
<p>For convenience the following function is also built-in:</p>
<div class="highlight"><pre><span></span><code>function require(b : bool, err : string) =
if(!b) abort(err)
<div class="highlight"><pre><span></span><code><span class="k">function</span><span class="w"> </span><span class="nb">require</span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">bool</span><span class="p">,</span><span class="w"> </span><span class="n">err</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="ow">!</span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="nb">abort</span><span class="p">(</span><span class="n">err</span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<h2 id="delegation-signature">Delegation signature</h2>
<p>Some chain operations (<code>Oracle.&lt;operation&gt;</code> and <code>AENS.&lt;operation&gt;</code>) have an

View File

@ -642,12 +642,12 @@ indented more than the currently enclosing layout block. Blocks with a single
element can be written on the same line as the previous token.</p>
<p>Each element of the block must share the same indentation and no part of an
element may be indented less than the indentation of the block. For instance</p>
<div class="highlight"><pre><span></span><code>contract Layout =
function foo() = 0 // no layout
function bar() = // layout block starts on next line
let x = foo() // indented more than 2 spaces
x
+ 1 // the &#39;+&#39; is indented more than the &#39;x&#39;
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="nf">Layout</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">foo</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="c1">// no layout</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">bar</span><span class="p">()</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="c1">// layout block starts on next line</span>
<span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">foo</span><span class="p">()</span><span class="w"> </span><span class="c1">// indented more than 2 spaces</span>
<span class="w"> </span><span class="n">x</span><span class="w"></span>
<span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="c1">// the &#39;+&#39; is indented more than the &#39;x&#39;</span>
</code></pre></div>
<h2 id="notation">Notation</h2>
<p>In describing the syntax below, we use the following conventions:</p>
@ -692,9 +692,9 @@ element may be indented less than the indentation of the block. For instance</p>
</code></pre></div>
<p>Contract declarations must appear at the top-level.</p>
<p>For example,
<div class="highlight"><pre><span></span><code>contract Test =
type t = int
entrypoint add (x : t, y : t) = x + y
<div class="highlight"><pre><span></span><code><span class="k">contract</span><span class="w"> </span><span class="nf">Test</span><span class="w"> </span><span class="ow">=</span><span class="w"></span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="w"> </span><span class="k">entrypoint</span><span class="w"> </span><span class="n">add</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">t</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="n">y</span><span class="w"></span>
</code></pre></div></p>
<p>There are three forms of type declarations: type aliases (declared with the
<code>type</code> keyword), record type definitions (<code>record</code>) and data type definitions
@ -707,9 +707,9 @@ element may be indented less than the indentation of the block. For instance</p>
<span class="n">ConDecl</span><span class="w"> </span><span class="o">::=</span><span class="w"> </span><span class="n">Con</span><span class="w"> </span><span class="p">[</span><span class="sc">&#39;(&#39;</span><span class="w"> </span><span class="n">Sep1</span><span class="p">(</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="sc">&#39;,&#39;</span><span class="p">)</span><span class="w"> </span><span class="sc">&#39;)&#39;</span><span class="p">]</span><span class="w"></span>
</code></pre></div>
<p>For example,
<div class="highlight"><pre><span></span><code>record point(&#39;a) = {x : &#39;a, y : &#39;a}
datatype shape(&#39;a) = Circle(point(&#39;a), &#39;a) | Rect(point(&#39;a), point(&#39;a))
type int_shape = shape(int)
<div class="highlight"><pre><span></span><code><span class="k">record</span><span class="w"> </span><span class="n">point</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nv">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="nv">&#39;a</span><span class="p">}</span><span class="w"></span>
<span class="k">datatype</span><span class="w"> </span><span class="n">shape</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">Circle</span><span class="p">(</span><span class="n">point</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">),</span><span class="w"> </span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="nf">Rect</span><span class="p">(</span><span class="n">point</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">),</span><span class="w"> </span><span class="n">point</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">))</span><span class="w"></span>
<span class="k">type</span><span class="w"> </span><span class="n">int_shape</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">shape</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"></span>
</code></pre></div></p>
<h2 id="types">Types</h2>
<div class="highlight"><pre><span></span><code><span class="n">Type</span><span class="w"> </span><span class="o">::=</span><span class="w"> </span><span class="n">Domain</span><span class="w"> </span><span class="err">&#39;</span><span class="o">=&gt;</span><span class="err">&#39;</span><span class="w"> </span><span class="n">Type</span><span class="w"> </span><span class="c1">// Function type</span>
@ -723,7 +723,7 @@ type int_shape = shape(int)
</code></pre></div>
<p>The function type arrow associates to the right.</p>
<p>Example,
<div class="highlight"><pre><span></span><code>&#39;a =&gt; list(&#39;a) =&gt; (int * list(&#39;a))
<div class="highlight"><pre><span></span><code><span class="nv">&#39;a</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="ow">*</span><span class="w"> </span><span class="kt">list</span><span class="p">(</span><span class="nv">&#39;a</span><span class="p">))</span><span class="w"></span>
</code></pre></div></p>
<h2 id="statements">Statements</h2>
<p>Function bodies are blocks of <em>statements</em>, where a statement is one of the following</p>
@ -741,16 +741,16 @@ type int_shape = shape(int)
<span class="n">Pattern</span><span class="w"> </span><span class="o">::=</span><span class="w"> </span><span class="n">Expr</span><span class="w"></span>
</code></pre></div>
<p><code>if</code> statements can be followed by zero or more <code>elif</code> statements and an optional final <code>else</code> statement. For example,</p>
<div class="highlight"><pre><span></span><code>let x : int = 4
switch(f(x))
None =&gt; 0
Some(y) =&gt;
if(y &gt; 10)
&quot;too big&quot;
elif(y &lt; 3)
&quot;too small&quot;
else
&quot;just right&quot;
<div class="highlight"><pre><span></span><code><span class="k">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">4</span><span class="w"></span>
<span class="k">switch</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="nf">None</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"></span>
<span class="w"> </span><span class="nf">Some</span><span class="p">(</span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="ow">&gt;</span><span class="w"> </span><span class="mi">10</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;too big&quot;</span><span class="w"></span>
<span class="w"> </span><span class="k">elif</span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="ow">&lt;</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;too small&quot;</span><span class="w"></span>
<span class="w"> </span><span class="k">else</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;just right&quot;</span><span class="w"></span>
</code></pre></div>
<h2 id="expressions">Expressions</h2>
<div class="highlight"><pre><span></span><code><span class="n">Expr</span><span class="w"> </span><span class="o">::=</span><span class="w"> </span><span class="sc">&#39;(&#39;</span><span class="w"> </span><span class="n">LamArgs</span><span class="w"> </span><span class="sc">&#39;)&#39;</span><span class="w"> </span><span class="err">&#39;</span><span class="o">=&gt;</span><span class="err">&#39;</span><span class="w"> </span><span class="n">Block</span><span class="p">(</span><span class="n">Stmt</span><span class="p">)</span><span class="w"> </span><span class="c1">// Anonymous function (x) =&gt; x + 1</span>