Merge branch 'docs/loop-doc' of ssh://gitlab.com/ligolang/ligo into docs/loop-doc
This commit is contained in:
commit
2f25c4b683
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@ Version.ml
|
|||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
.vscode/
|
.vscode/
|
||||||
/ligo.install
|
/ligo.install
|
||||||
|
*.coverage
|
||||||
|
/_coverage/
|
||||||
|
/_coverage_*/
|
||||||
|
@ -85,6 +85,10 @@ local-dune-job:
|
|||||||
- scripts/install_vendors_deps.sh
|
- scripts/install_vendors_deps.sh
|
||||||
- scripts/build_ligo_local.sh
|
- scripts/build_ligo_local.sh
|
||||||
- dune runtest
|
- dune runtest
|
||||||
|
- make coverage
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _coverage_all
|
||||||
|
|
||||||
# Run a docker build without publishing to the registry
|
# Run a docker build without publishing to the registry
|
||||||
build-current-docker-image:
|
build-current-docker-image:
|
||||||
|
24
Makefile
24
Makefile
@ -30,3 +30,27 @@ test: build
|
|||||||
export PATH="/usr/local/bin$${PATH:+:}$${PATH:-}"
|
export PATH="/usr/local/bin$${PATH:+:}$${PATH:-}"
|
||||||
eval $$(opam config env)
|
eval $$(opam config env)
|
||||||
scripts/test_ligo.sh
|
scripts/test_ligo.sh
|
||||||
|
|
||||||
|
clean:
|
||||||
|
dune clean
|
||||||
|
rm -fr _coverage_all _coverage_cli _coverage_ligo
|
||||||
|
|
||||||
|
coverage: clean
|
||||||
|
BISECT_ENABLE=yes dune runtest --force
|
||||||
|
bisect-ppx-report html -o ./_coverage_all --title="LIGO overall test coverage"
|
||||||
|
bisect-ppx-report summary --per-file
|
||||||
|
|
||||||
|
coverage-ligo: clean
|
||||||
|
BISECT_ENABLE=yes dune runtest src/test --force
|
||||||
|
bisect-ppx-report html -o ./_coverage_ligo --title="LIGO test coverage"
|
||||||
|
bisect-ppx-report summary --per-file
|
||||||
|
|
||||||
|
coverage-doc: clean
|
||||||
|
BISECT_ENABLE=yes dune build @doc-test --force
|
||||||
|
bisect-ppx-report html -o ./_coverage_doc --title="LIGO doc coverage"
|
||||||
|
bisect-ppx-report summary --per-file
|
||||||
|
|
||||||
|
coverage-cli: clean
|
||||||
|
BISECT_ENABLE=yes dune runtest src/bin/expect_tests
|
||||||
|
bisect-ppx-report html -o ./_coverage_cli --title="CLI test coverage"
|
||||||
|
bisect-ppx-report summary --per-file
|
||||||
|
@ -20,7 +20,7 @@ This means that every smart contract needs at least one entrypoint function, her
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```
|
```pascaligo group=a
|
||||||
type parameter is unit;
|
type parameter is unit;
|
||||||
type store is unit;
|
type store is unit;
|
||||||
function main(const parameter: parameter; const store: store): (list(operation) * store) is
|
function main(const parameter: parameter; const store: store): (list(operation) * store) is
|
||||||
@ -46,7 +46,7 @@ This example shows how `amount` and `failwith` can be used to decline a transact
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```
|
```pascaligo group=b
|
||||||
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
||||||
block {
|
block {
|
||||||
if amount > 0mutez then failwith("This contract does not accept tez") else skip
|
if amount > 0mutez then failwith("This contract does not accept tez") else skip
|
||||||
@ -60,7 +60,7 @@ This example shows how `sender` or `source` can be used to deny access to an ent
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```
|
```pascaligo group=c
|
||||||
const owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
const owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
||||||
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
||||||
block {
|
block {
|
||||||
@ -79,7 +79,7 @@ In our case, we have a `counter.ligo` contract that accepts a parameter of type
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```
|
```pascaligo group=dup
|
||||||
// counter.types.ligo
|
// counter.types.ligo
|
||||||
type action is
|
type action is
|
||||||
| Increment of int
|
| Increment of int
|
||||||
@ -87,7 +87,7 @@ type action is
|
|||||||
| Reset of unit
|
| Reset of unit
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```pascaligo group=d
|
||||||
// counter.ligo
|
// counter.ligo
|
||||||
type action is
|
type action is
|
||||||
| Increment of int
|
| Increment of int
|
||||||
@ -95,7 +95,7 @@ type action is
|
|||||||
| Reset of unit
|
| Reset of unit
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```pascaligo gorup=d
|
||||||
// proxy.ligo
|
// proxy.ligo
|
||||||
#include "counter.types.ligo"
|
#include "counter.types.ligo"
|
||||||
|
|
||||||
|
71
gitlab-pages/docs/advanced/include.md
Normal file
71
gitlab-pages/docs/advanced/include.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
id: include
|
||||||
|
title: Including Other Contracts
|
||||||
|
---
|
||||||
|
|
||||||
|
Lets say we have a contract that's getting a bit too big. If it has a modular
|
||||||
|
structure, you might find it useful to use the `#include` statement to split the
|
||||||
|
contract up over multiple files.
|
||||||
|
|
||||||
|
|
||||||
|
You take the code that you want to include and put it in a separate file, for
|
||||||
|
example `included.ligo`:
|
||||||
|
|
||||||
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
|
|
||||||
|
<!--PascaLIGO-->
|
||||||
|
```pascaligo
|
||||||
|
|
||||||
|
// Demonstrate PascaLIGO inclusion statements, see includer.ligo
|
||||||
|
|
||||||
|
const foo : int = 144
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--CameLIGO-->
|
||||||
|
```cameligo
|
||||||
|
|
||||||
|
// Demonstrate CameLIGO inclusion statements, see includer.mligo
|
||||||
|
|
||||||
|
let foo : int = 144
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--ReasonLIGO-->
|
||||||
|
```reasonligo
|
||||||
|
|
||||||
|
// Demonstrate ReasonLIGO inclusion statements, see includer.religo
|
||||||
|
|
||||||
|
let foo : int = 144;
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
|
|
||||||
|
|
||||||
|
And then you can include this code using the `#include` statement like so:
|
||||||
|
|
||||||
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
|
|
||||||
|
<!--PascaLIGO-->
|
||||||
|
```pascaligo
|
||||||
|
|
||||||
|
#include "included.ligo"
|
||||||
|
|
||||||
|
const bar : int = foo
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--CameLIGO-->
|
||||||
|
```cameligo
|
||||||
|
|
||||||
|
#include "included.mligo"
|
||||||
|
|
||||||
|
let bar : int = foo
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--ReasonLIGO-->
|
||||||
|
```reasonligo
|
||||||
|
|
||||||
|
#include "included.religo"
|
||||||
|
|
||||||
|
let bar : int = foo;
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
@ -14,7 +14,7 @@ You can obtain the current time using the built-in syntax specific expression, p
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const today: timestamp = now;
|
const today: timestamp = now;
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -26,7 +26,7 @@ In LIGO, timestamps can be added with `int`(s), this enables you to set e.g. tim
|
|||||||
#### In 24 hours
|
#### In 24 hours
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
const today: timestamp = now;
|
const today: timestamp = now;
|
||||||
const one_day: int = 86400;
|
const one_day: int = 86400;
|
||||||
const in_24_hrs: timestamp = today + one_day;
|
const in_24_hrs: timestamp = today + one_day;
|
||||||
@ -36,10 +36,10 @@ const in_24_hrs: timestamp = today + one_day;
|
|||||||
#### 24 hours ago
|
#### 24 hours ago
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const today: timestamp = now;
|
const today: timestamp = now;
|
||||||
const one_day: int = 86400;
|
const one_day: int = 86400;
|
||||||
const 24_hrs_ago: timestamp = today - one_day;
|
const in_24_hrs: timestamp = today - one_day;
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ You can also compare timestamps using the same comparison operators as for numbe
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const not_tommorow: bool = (now = in_24_hrs)
|
const not_tommorow: bool = (now = in_24_hrs)
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -62,7 +62,7 @@ Here's how you can define an address:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=d
|
||||||
const my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
const my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
|
@ -11,18 +11,18 @@ Here's how to define a boolean:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const a: bool = True;
|
const a: bool = True;
|
||||||
const b: bool = False;
|
const b: bool = False;
|
||||||
```
|
```
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let a: bool = true
|
let a: bool = true
|
||||||
let b: bool = false
|
let b: bool = false
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let a: bool = true;
|
let a: bool = true;
|
||||||
let b: bool = false;
|
let b: bool = false;
|
||||||
```
|
```
|
||||||
@ -37,24 +37,24 @@ In LIGO, only values of the same type can be compared. We call these "comparable
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
const a: string = "Alice";
|
const a: string = "Alice";
|
||||||
const b: string = "Alice";
|
const b: string = "Alice";
|
||||||
// True
|
// True
|
||||||
const c: bool = (a = b);
|
const c: bool = (a = b);
|
||||||
```
|
```
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let a: string = "Alice"
|
let a: string = "Alice"
|
||||||
let b: string = "Alice"
|
let b: string = "Alice"
|
||||||
// true
|
// true
|
||||||
let c: bool = (a = b)
|
let c: bool = (a = b)
|
||||||
```
|
```
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let a: string = "Alice";
|
let a: string = "Alice";
|
||||||
let b: string = "Alice";
|
let b: string = "Alice";
|
||||||
/* true */
|
(* true *)
|
||||||
let c: bool = (a == b);
|
let c: bool = (a == b);
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -64,7 +64,7 @@ let c: bool = (a == b);
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const a: int = 5;
|
const a: int = 5;
|
||||||
const b: int = 4;
|
const b: int = 4;
|
||||||
const c: bool = (a = b);
|
const c: bool = (a = b);
|
||||||
@ -75,7 +75,7 @@ const g: bool = (a >= b);
|
|||||||
const h: bool = (a =/= b);
|
const h: bool = (a =/= b);
|
||||||
```
|
```
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=c
|
||||||
let a: int = 5
|
let a: int = 5
|
||||||
let b: int = 4
|
let b: int = 4
|
||||||
let c: bool = (a = b)
|
let c: bool = (a = b)
|
||||||
@ -83,11 +83,11 @@ let d: bool = (a > b)
|
|||||||
let e: bool = (a < b)
|
let e: bool = (a < b)
|
||||||
let f: bool = (a <= b)
|
let f: bool = (a <= b)
|
||||||
let g: bool = (a >= b)
|
let g: bool = (a >= b)
|
||||||
let h: bool = (a =/= b)
|
let h: bool = (a <> b)
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=c
|
||||||
let a: int = 5;
|
let a: int = 5;
|
||||||
let b: int = 4;
|
let b: int = 4;
|
||||||
let c: bool = (a == b);
|
let c: bool = (a == b);
|
||||||
@ -106,23 +106,23 @@ let h: bool = (a != b);
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=d
|
||||||
const a: tez = 5mutez;
|
const a: tez = 5mutez;
|
||||||
const b: tez = 10mutez;
|
const b: tez = 10mutez;
|
||||||
const c: bool = (a = b);
|
const c: bool = (a = b);
|
||||||
```
|
```
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=d
|
||||||
let a: tez = 5mutez
|
let a: tez = 5mutez
|
||||||
let b: tez = 10mutez
|
let b: tez = 10mutez
|
||||||
// false
|
// false
|
||||||
let c: bool = (a = b)
|
let c: bool = (a = b)
|
||||||
```
|
```
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=d
|
||||||
let a: tez = 5mutez;
|
let a: tez = 5mutez;
|
||||||
let b: tez = 10mutez;
|
let b: tez = 10mutez;
|
||||||
/* false */
|
(* false *)
|
||||||
let c: bool = (a == b);
|
let c: bool = (a == b);
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -136,7 +136,7 @@ Conditional logic is an important part of every real world program.
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=e
|
||||||
const min_age: nat = 16n;
|
const min_age: nat = 16n;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
@ -162,7 +162,7 @@ function is_adult(const age: nat): bool is
|
|||||||
> ```
|
> ```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=e
|
||||||
let min_age: nat = 16n
|
let min_age: nat = 16n
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@ -177,17 +177,17 @@ let is_adult (age: nat) : bool =
|
|||||||
if (age > min_age) then true else false
|
if (age > min_age) then true else false
|
||||||
```
|
```
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=e
|
||||||
let min_age: nat = 16n;
|
let min_age: nat = 16n;
|
||||||
|
|
||||||
/**
|
(**
|
||||||
|
|
||||||
This function is really obnoxious, but it showcases
|
This function is really obnoxious, but it showcases
|
||||||
how the if statement and it's syntax can be used.
|
how the if statement and it's syntax can be used.
|
||||||
|
|
||||||
Normally, you'd use `with (age > min_age)` instead.
|
Normally, you'd use `with (age > min_age)` instead.
|
||||||
|
|
||||||
*/
|
*)
|
||||||
|
|
||||||
let is_adult = (age: nat): bool =>
|
let is_adult = (age: nat): bool =>
|
||||||
if (age > min_age) {
|
if (age > min_age) {
|
||||||
|
@ -13,7 +13,7 @@ Each `block` needs to include at least one `instruction`, or a *placeholder* ins
|
|||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
// shorthand syntax
|
// shorthand syntax
|
||||||
block { skip }
|
block { skip }
|
||||||
// verbose syntax
|
// verbose syntax
|
||||||
@ -34,7 +34,7 @@ Functions in PascaLIGO are defined using the `function` keyword followed by thei
|
|||||||
Here's how you define a basic function that accepts two `ints` and returns a single `int`:
|
Here's how you define a basic function that accepts two `ints` and returns a single `int`:
|
||||||
|
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
function add(const a: int; const b: int): int is
|
function add(const a: int; const b: int): int is
|
||||||
begin
|
begin
|
||||||
const result: int = a + b;
|
const result: int = a + b;
|
||||||
@ -51,7 +51,7 @@ The function body consists of two parts:
|
|||||||
Functions that can contain all of their logic into a single instruction/expression, can be defined without the surrounding `block`.
|
Functions that can contain all of their logic into a single instruction/expression, can be defined without the surrounding `block`.
|
||||||
Instead, you can inline the necessary logic directly, like this:
|
Instead, you can inline the necessary logic directly, like this:
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
function add(const a: int; const b: int): int is a + b
|
function add(const a: int; const b: int): int is a + b
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ along with a return type.
|
|||||||
|
|
||||||
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
||||||
|
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let add (a: int) (b: int) : int = a + b
|
let add (a: int) (b: int) : int = a + b
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ along with a return type.
|
|||||||
|
|
||||||
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
||||||
|
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let add = (a: int, b: int) : int => a + b;
|
let add = (a: int, b: int) : int => a + b;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ value.
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
||||||
// a = 2
|
// a = 2
|
||||||
const a: int = increment(1);
|
const a: int = increment(1);
|
||||||
@ -104,19 +104,19 @@ Functions without a name, also known as anonymous functions are useful in cases
|
|||||||
Here's how to define an anonymous function assigned to a variable `increment`, with it's appropriate function type signature.
|
Here's how to define an anonymous function assigned to a variable `increment`, with it's appropriate function type signature.
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
||||||
// a = 2
|
// a = 2
|
||||||
const a: int = increment(1);
|
const a: int = increment(1);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=c
|
||||||
let increment : (int -> int) = fun (i: int) -> i + 1
|
let increment : (int -> int) = fun (i: int) -> i + 1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=c
|
||||||
let increment: (int => int) = (i: int) => i + 1;
|
let increment: (int => int) = (i: int) => i + 1;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -36,14 +36,36 @@ that does the fold returns either boolean true or boolean false to indicate
|
|||||||
whether the fold should continue or not. The initial value must match the input
|
whether the fold should continue or not. The initial value must match the input
|
||||||
parameter of the auxillary function, and the auxillary should return type `(bool * input)`.
|
parameter of the auxillary function, and the auxillary should return type `(bool * input)`.
|
||||||
|
|
||||||
|
`continue` and `stop` are provided as syntactic sugar for the return values.
|
||||||
|
|
||||||
```cameligo
|
```cameligo
|
||||||
let aux (i: int) : bool * int =
|
let aux (i: int) : bool * int =
|
||||||
if i < 100 then continue (i + 1) else stop i
|
if i < 100 then continue (i + 1) else stop i
|
||||||
|
|
||||||
let counter_simple (n: int) : int =
|
let counter_simple (n: int) : int =
|
||||||
Loop.fold_while aux_simple n
|
Loop.fold_while aux n
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!--ReasonLIGO-->
|
||||||
|
|
||||||
|
`Loop.fold_while` is a fold operation that takes an initial value of a certain type
|
||||||
|
and then iterates on it until a condition is reached. The auxillary function
|
||||||
|
that does the fold returns either boolean true or boolean false to indicate
|
||||||
|
whether the fold should continue or not. The initial value must match the input
|
||||||
|
parameter of the auxillary function, and the auxillary should return type `(bool, input)`.
|
||||||
|
|
||||||
|
`continue` and `stop` are provided as syntactic sugar for the return values.
|
||||||
|
|
||||||
|
```reasonligo
|
||||||
|
let aux = (i: int): (bool, int) =>
|
||||||
|
if (i < 100) {
|
||||||
|
continue(i + 1);
|
||||||
|
} else {
|
||||||
|
stop(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
let counter_simple = (n: int): int => Loop.fold_while(aux, n);```
|
||||||
|
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
|
|
||||||
## For Loop
|
## For Loop
|
||||||
|
@ -135,21 +135,21 @@ otherwise.
|
|||||||
function iter_op (const m : ledger) : unit is
|
function iter_op (const m : ledger) : unit is
|
||||||
block {
|
block {
|
||||||
function aggregate (const i : address ; const j : tez) : unit is block
|
function aggregate (const i : address ; const j : tez) : unit is block
|
||||||
{ if (j > 100) then skip else failwith("fail") } with unit ;
|
{ if (j > 100mutez) then skip else failwith("fail") } with unit ;
|
||||||
} with map_iter(aggregate, m) ;
|
} with map_iter(aggregate, m) ;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo
|
||||||
let iter_op (m : ledger) : unit =
|
let iter_op (m : ledger) : unit =
|
||||||
let assert_eq = fun (i: address) (j: tez) -> assert (j > 100)
|
let assert_eq = fun (i: address) (j: tez) -> assert (j > 100tz)
|
||||||
in Map.iter assert_eq m
|
in Map.iter assert_eq m
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo
|
||||||
let iter_op = (m: ledger): unit => {
|
let iter_op = (m: ledger): unit => {
|
||||||
let assert_eq = (i: address, j: tez) => assert(j > 100);
|
let assert_eq = (i: address, j: tez) => assert(j > 100mutez);
|
||||||
Map.iter(assert_eq, m);
|
Map.iter(assert_eq, m);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -162,21 +162,21 @@ let iter_op = (m: ledger): unit => {
|
|||||||
```pascaligo
|
```pascaligo
|
||||||
function map_op (const m : ledger) : ledger is
|
function map_op (const m : ledger) : ledger is
|
||||||
block {
|
block {
|
||||||
function increment (const i : address ; const j : tez) : tez is block { skip } with j + 1 ;
|
function increment (const i : address ; const j : tez) : tez is block { skip } with j + 1mutez ;
|
||||||
} with map_map(increment, m) ;
|
} with map_map(increment, m) ;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo
|
||||||
let map_op (m : ledger) : ledger =
|
let map_op (m : ledger) : ledger =
|
||||||
let increment = fun (_: address) (j: tez) -> j+1
|
let increment = fun (_: address) (j: tez) -> j + 1tz
|
||||||
in Map.map increment m
|
in Map.map increment m
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo
|
||||||
let map_op = (m: ledger): ledger => {
|
let map_op = (m: ledger): ledger => {
|
||||||
let increment = (ignore: address, j: tez) => j + 1;
|
let increment = (ignore: address, j: tez) => j + 1tz;
|
||||||
Map.map(increment, m);
|
Map.map(increment, m);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -196,22 +196,22 @@ It eventually returns the result of combining all the elements.
|
|||||||
```pascaligo
|
```pascaligo
|
||||||
function fold_op (const m : ledger) : tez is
|
function fold_op (const m : ledger) : tez is
|
||||||
block {
|
block {
|
||||||
function aggregate (const i : address ; const j : (tez * tez)) : tez is block { skip } with j.0 + j.1 ;
|
function aggregate (const j : tez ; const cur : (address * tez)) : tez is j + cur.1 ;
|
||||||
} with map_fold(aggregate, m , 10)
|
} with map_fold(aggregate, m , 10mutez)
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo
|
||||||
let fold_op (m : ledger) : ledger =
|
let fold_op (m : ledger) : ledger =
|
||||||
let aggregate = fun (ignore: address) (j: tez * tez) -> j.0 + j.1
|
let aggregate = fun (j: tez) (cur: address * tez) -> j + cur.1 in
|
||||||
in Map.fold aggregate m 10
|
Map.fold aggregate m 10tz
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo
|
||||||
let fold_op = (m: ledger): ledger => {
|
let fold_op = (m: ledger): ledger => {
|
||||||
let aggregate = (ignore: address, j: (tez, tez)) => j[0] + j[1];
|
let aggregate = (j: tez, cur: (address, tez)) => j + cur[1];
|
||||||
Map.fold(aggregate, m, 10);
|
Map.fold(aggregate, m, 10tz);
|
||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -14,7 +14,7 @@ In the following example you can find a series of arithmetic operations, includi
|
|||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
// int + int produces int
|
// int + int produces int
|
||||||
const a: int = 5 + 10;
|
const a: int = 5 + 10;
|
||||||
// nat + int produces int
|
// nat + int produces int
|
||||||
@ -38,7 +38,7 @@ const g: int = 1_000_000;
|
|||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
|
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
// int + int produces int
|
// int + int produces int
|
||||||
let a: int = 5 + 10
|
let a: int = 5 + 10
|
||||||
// nat + int produces int
|
// nat + int produces int
|
||||||
@ -62,19 +62,19 @@ let g: int = 1_000_000
|
|||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
|
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
/* int + int produces int */
|
(* int + int produces int *)
|
||||||
let a: int = 5 + 10;
|
let a: int = 5 + 10;
|
||||||
/* nat + int produces int */
|
(* nat + int produces int *)
|
||||||
let b: int = 5n + 10;
|
let b: int = 5n + 10;
|
||||||
/* tez + tez produces tez */
|
(* tez + tez produces tez *)
|
||||||
let c: tez = 5mutez + 10mutez;
|
let c: tez = 5mutez + 10mutez;
|
||||||
/* you can't add tez + int or tez + nat, this won't compile */
|
(* you can't add tez + int or tez + nat, this won't compile:
|
||||||
/* let d: tez = 5mutez + 10n; */
|
let d: tez = 5mutez + 10n; *)
|
||||||
/* two nats produce a nat */
|
(* two nats produce a nat *)
|
||||||
let e: nat = 5n + 10n;
|
let e: nat = 5n + 10n;
|
||||||
/* nat + int produces an int, this won't compile */
|
(* nat + int produces an int, this won't compile:
|
||||||
/* let f: nat = 5n + 10; */
|
let f: nat = 5n + 10; *)
|
||||||
let g: int = 1_000_000;
|
let g: int = 1_000_000;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -94,33 +94,33 @@ The simpliest substraction looks like this:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
const a: int = 5 - 10;
|
const a: int = 5 - 10;
|
||||||
// substraction of two nats, yields an int
|
// substraction of two nats, yields an int
|
||||||
const b: int = 5n - 2n;
|
const b: int = 5n - 2n;
|
||||||
// won't compile, result is an int, not a nat
|
// won't compile, result is an int, not a nat
|
||||||
// const c: nat = 5n - 2n;
|
// const c: nat = 5n - 2n;
|
||||||
const d: tez = 5mutez - 1mt;
|
const d: tez = 5mutez - 1mutez;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let a: int = 5 - 10
|
let a: int = 5 - 10
|
||||||
// substraction of two nats, yields an int
|
// substraction of two nats, yields an int
|
||||||
let b: int = 5n - 2n
|
let b: int = 5n - 2n
|
||||||
// won't compile, result is an int, not a nat
|
// won't compile, result is an int, not a nat
|
||||||
// const c: nat = 5n - 2n
|
// const c: nat = 5n - 2n
|
||||||
let d: tez = 5mutez - 1mt
|
let d: tez = 5mutez - 1mutez
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let a: int = 5 - 10;
|
let a: int = 5 - 10;
|
||||||
/* substraction of two nats, yields an int */
|
(* substraction of two nats, yields an int *)
|
||||||
let b: int = 5n - 2n;
|
let b: int = 5n - 2n;
|
||||||
/* won't compile, result is an int, not a nat */
|
(* won't compile, result is an int, not a nat *)
|
||||||
/* let c: nat = 5n - 2n; */
|
(* let c: nat = 5n - 2n; *)
|
||||||
let d: tez = 5mutez - 1mt;
|
let d: tez = 5mutez - 1mutez;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -133,7 +133,7 @@ You can multiply values of the same type, such as:
|
|||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const a: int = 5 * 5;
|
const a: int = 5 * 5;
|
||||||
const b: nat = 5n * 5n;
|
const b: nat = 5n * 5n;
|
||||||
// you can also multiply `nat` and `tez`
|
// you can also multiply `nat` and `tez`
|
||||||
@ -141,7 +141,7 @@ const c: tez = 5n * 5mutez;
|
|||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=c
|
||||||
let a: int = 5 * 5
|
let a: int = 5 * 5
|
||||||
let b: nat = 5n * 5n
|
let b: nat = 5n * 5n
|
||||||
// you can also multiply `nat` and `tez`
|
// you can also multiply `nat` and `tez`
|
||||||
@ -149,10 +149,10 @@ let c: tez = 5n * 5mutez
|
|||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=c
|
||||||
let a: int = 5 * 5;
|
let a: int = 5 * 5;
|
||||||
let b: nat = 5n * 5n;
|
let b: nat = 5n * 5n;
|
||||||
/* you can also multiply `nat` and `tez` */
|
(* you can also multiply `nat` and `tez` *)
|
||||||
let c: tez = 5n * 5mutez;
|
let c: tez = 5n * 5mutez;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -167,21 +167,21 @@ In LIGO you can divide `int`, `nat`, and `tez`. Here's how:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=d
|
||||||
const a: int = 10 / 3;
|
const a: int = 10 / 3;
|
||||||
const b: nat = 10n / 3n;
|
const b: nat = 10n / 3n;
|
||||||
const c: nat = 10mutez / 3mutez;
|
const c: nat = 10mutez / 3mutez;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=d
|
||||||
let a: int = 10 / 3
|
let a: int = 10 / 3
|
||||||
let b: nat = 10n / 3n
|
let b: nat = 10n / 3n
|
||||||
let c: nat = 10mutez / 3mutez
|
let c: nat = 10mutez / 3mutez
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=d
|
||||||
let a: int = 10 / 3;
|
let a: int = 10 / 3;
|
||||||
let b: nat = 10n / 3n;
|
let b: nat = 10n / 3n;
|
||||||
let c: nat = 10mutez / 3mutez;
|
let c: nat = 10mutez / 3mutez;
|
||||||
@ -195,13 +195,13 @@ You can *cast* an `int` to a `nat` and vice versa, here's how:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=e
|
||||||
const a: int = int(1n);
|
const a: int = int(1n);
|
||||||
const b: nat = abs(1);
|
const b: nat = abs(1);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=e
|
||||||
let a: int = int(1n);
|
let a: int = int(1n);
|
||||||
let b: nat = abs(1);
|
let b: nat = abs(1);
|
||||||
```
|
```
|
||||||
|
@ -15,7 +15,7 @@ Sets are similar to lists. The main difference is that elements of a `set` must
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
type int_set is set(int);
|
type int_set is set(int);
|
||||||
const my_set: int_set = set
|
const my_set: int_set = set
|
||||||
1;
|
1;
|
||||||
@ -25,14 +25,14 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
type int_set = int set
|
type int_set = int set
|
||||||
let my_set: int_set =
|
let my_set: int_set =
|
||||||
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
|
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
type int_set = set(int);
|
type int_set = set(int);
|
||||||
let my_set: int_set =
|
let my_set: int_set =
|
||||||
Set.add(3, Set.add(2, Set.add(1, Set.empty: set(int))));
|
Set.add(3, Set.add(2, Set.add(1, Set.empty: set(int))));
|
||||||
@ -44,16 +44,16 @@ let my_set: int_set =
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const my_set: int_set = set end;
|
const my_set: int_set = set end;
|
||||||
const my_set_2: int_set = set_empty;
|
const my_set_2: int_set = set_empty;
|
||||||
```
|
```
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let my_set: int_set = (Set.empty: int set)
|
let my_set: int_set = (Set.empty: int set)
|
||||||
```
|
```
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let my_set: int_set = (Set.empty: set(int));
|
let my_set: int_set = (Set.empty: set(int));
|
||||||
```
|
```
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -62,18 +62,18 @@ let my_set: int_set = (Set.empty: set(int));
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const contains_three: bool = my_set contains 3;
|
const contains_three: bool = my_set contains 3;
|
||||||
// or alternatively
|
// or alternatively
|
||||||
const contains_three_fn: bool = set_mem(3, my_set);
|
const contains_three_fn: bool = set_mem(3, my_set);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let contains_three: bool = Set.mem 3 my_set
|
let contains_three: bool = Set.mem 3 my_set
|
||||||
```
|
```
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let contains_three: bool = Set.mem(3, my_set);
|
let contains_three: bool = Set.mem(3, my_set);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -83,17 +83,17 @@ let contains_three: bool = Set.mem(3, my_set);
|
|||||||
### Obtaining the size of a set
|
### Obtaining the size of a set
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const set_size: nat = size(my_set);
|
const set_size: nat = size(my_set);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let set_size: nat = Set.size my_set
|
let set_size: nat = Set.size my_set
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let set_size: nat = Set.size(my_set);
|
let set_size: nat = Set.size(my_set);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -103,21 +103,21 @@ let set_size: nat = Set.size(my_set);
|
|||||||
### Modifying a set
|
### Modifying a set
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
const larger_set: int_set = set_add(4, my_set);
|
const larger_set: int_set = set_add(4, my_set);
|
||||||
const smaller_set: int_set = set_remove(3, my_set);
|
const smaller_set: int_set = set_remove(3, my_set);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
|
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let larger_set: int_set = Set.add 4 my_set
|
let larger_set: int_set = Set.add 4 my_set
|
||||||
let smaller_set: int_set = Set.remove 3 my_set
|
let smaller_set: int_set = Set.remove 3 my_set
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
|
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let larger_set: int_set = Set.add(4, my_set);
|
let larger_set: int_set = Set.add(4, my_set);
|
||||||
let smaller_set: int_set = Set.remove(3, my_set);
|
let smaller_set: int_set = Set.remove(3, my_set);
|
||||||
```
|
```
|
||||||
@ -128,20 +128,20 @@ let smaller_set: int_set = Set.remove(3, my_set);
|
|||||||
### Folding a set
|
### Folding a set
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
function sum(const result: int; const i: int): int is result + i;
|
function sum(const result: int; const i: int): int is result + i;
|
||||||
// Outputs 6
|
// Outputs 6
|
||||||
const sum_of_a_set: int = set_fold(sum, my_set, 0);
|
const sum_of_a_set: int = set_fold(sum, my_set, 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=a
|
||||||
let sum (result: int) (i: int) : int = result + i
|
let sum (result: int) (i: int) : int = result + i
|
||||||
let sum_of_a_set: int = Set.fold sum my_set 0
|
let sum_of_a_set: int = Set.fold sum my_set 0
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=a
|
||||||
let sum = (result: int, i: int): int => result + i;
|
let sum = (result: int, i: int): int => result + i;
|
||||||
let sum_of_a_set: int = Set.fold(sum, my_set, 0);
|
let sum_of_a_set: int = Set.fold(sum, my_set, 0);
|
||||||
```
|
```
|
||||||
@ -157,7 +157,7 @@ Lists are similar to sets, but their elements don't need to be unique and they d
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
type int_list is list(int);
|
type int_list is list(int);
|
||||||
const my_list: int_list = list
|
const my_list: int_list = list
|
||||||
1;
|
1;
|
||||||
@ -167,13 +167,13 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
type int_list = int list
|
type int_list = int list
|
||||||
let my_list: int_list = [1; 2; 3]
|
let my_list: int_list = [1; 2; 3]
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
type int_list = list(int);
|
type int_list = list(int);
|
||||||
let my_list: int_list = [1, 2, 3];
|
let my_list: int_list = [1, 2, 3];
|
||||||
```
|
```
|
||||||
@ -185,21 +185,21 @@ let my_list: int_list = [1, 2, 3];
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
const larger_list: int_list = cons(4, my_list);
|
const larger_list: int_list = cons(4, my_list);
|
||||||
const even_larger_list: int_list = 5 # larger_list;
|
const even_larger_list: int_list = 5 # larger_list;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let larger_list: int_list = 4 :: my_list
|
let larger_list: int_list = 4 :: my_list
|
||||||
(* CameLIGO doesn't have a List.cons *)
|
(* CameLIGO doesn't have a List.cons *)
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let larger_list: int_list = [4, ...my_list];
|
let larger_list: int_list = [4, ...my_list];
|
||||||
/* ReasonLIGO doesn't have a List.cons */
|
(* ReasonLIGO doesn't have a List.cons *)
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||||
@ -211,7 +211,7 @@ let larger_list: int_list = [4, ...my_list];
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
function increment(const i: int): int is block { skip } with i + 1;
|
function increment(const i: int): int is block { skip } with i + 1;
|
||||||
// Creates a new list with elements incremented by 1
|
// Creates a new list with elements incremented by 1
|
||||||
const incremented_list: int_list = list_map(increment, even_larger_list);
|
const incremented_list: int_list = list_map(increment, even_larger_list);
|
||||||
@ -219,7 +219,7 @@ const incremented_list: int_list = list_map(increment, even_larger_list);
|
|||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
|
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let increment (i: int) : int = i + 1
|
let increment (i: int) : int = i + 1
|
||||||
(* Creates a new list with elements incremented by 1 *)
|
(* Creates a new list with elements incremented by 1 *)
|
||||||
let incremented_list: int_list = List.map increment larger_list
|
let incremented_list: int_list = List.map increment larger_list
|
||||||
@ -228,9 +228,9 @@ let incremented_list: int_list = List.map increment larger_list
|
|||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
|
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let increment = (i: int): int => i + 1;
|
let increment = (i: int): int => i + 1;
|
||||||
/* Creates a new list with elements incremented by 1 */
|
(* Creates a new list with elements incremented by 1 *)
|
||||||
let incremented_list: int_list = List.map(increment, larger_list);
|
let incremented_list: int_list = List.map(increment, larger_list);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ let incremented_list: int_list = List.map(increment, larger_list);
|
|||||||
### Folding of a list:
|
### Folding of a list:
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
function sum(const result: int; const i: int): int is block { skip } with result + i;
|
function sum(const result: int; const i: int): int is block { skip } with result + i;
|
||||||
// Outputs 6
|
// Outputs 6
|
||||||
const sum_of_a_list: int = list_fold(sum, my_list, 0);
|
const sum_of_a_list: int = list_fold(sum, my_list, 0);
|
||||||
@ -248,7 +248,7 @@ const sum_of_a_list: int = list_fold(sum, my_list, 0);
|
|||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
|
|
||||||
```cameligo
|
```cameligo group=b
|
||||||
let sum (result: int) (i: int) : int = result + i
|
let sum (result: int) (i: int) : int = result + i
|
||||||
// Outputs 6
|
// Outputs 6
|
||||||
let sum_of_a_list: int = List.fold sum my_list 0
|
let sum_of_a_list: int = List.fold sum my_list 0
|
||||||
@ -256,9 +256,9 @@ let sum_of_a_list: int = List.fold sum my_list 0
|
|||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
|
|
||||||
```reasonligo
|
```reasonligo group=b
|
||||||
let sum = (result: int, i: int): int => result + i;
|
let sum = (result: int, i: int): int => result + i;
|
||||||
/* Outputs 6 */
|
(* Outputs 6 *)
|
||||||
let sum_of_a_list: int = List.fold(sum, my_list, 0);
|
let sum_of_a_list: int = List.fold(sum, my_list, 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -287,22 +287,22 @@ sake of illustration.
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
type full_name is string * string;
|
type full_name is string * string;
|
||||||
const full_name: full_name = ("Alice", "Johnson");
|
const full_name: full_name = ("Alice", "Johnson");
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=c
|
||||||
type full_name = string * string
|
type full_name = string * string
|
||||||
(* The parenthesis here are optional *)
|
(* The parenthesis here are optional *)
|
||||||
let full_name: full_name = ("Alice", "Johnson")
|
let full_name: full_name = ("Alice", "Johnson")
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=c
|
||||||
type full_name = (string, string);
|
type full_name = (string, string);
|
||||||
/* The parenthesis here are optional */
|
(* The parenthesis here are optional *)
|
||||||
let full_name: full_name = ("Alice", "Johnson");
|
let full_name: full_name = ("Alice", "Johnson");
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -320,17 +320,17 @@ Tuple elements are one-indexed and accessed like so:
|
|||||||
|
|
||||||
<!--DOCUSAURUS_CODE_TABS-->
|
<!--DOCUSAURUS_CODE_TABS-->
|
||||||
<!--Pascaligo-->
|
<!--Pascaligo-->
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
const first_name: string = full_name.1;
|
const first_name: string = full_name.1;
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--CameLIGO-->
|
<!--CameLIGO-->
|
||||||
```cameligo
|
```cameligo group=c
|
||||||
let first_name: string = full_name.1
|
let first_name: string = full_name.1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo group=c
|
||||||
let first_name: string = full_name[1];
|
let first_name: string = full_name[1];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -59,12 +59,12 @@ let ledger: account_balances = Map.literal
|
|||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo
|
||||||
/* account_balances is a simple type, a map of address <-> tez */
|
(* account_balances is a simple type, a map of address <-> tez *)
|
||||||
type account_balances = map(address, tez);
|
type account_balances = map(address, tez);
|
||||||
|
|
||||||
let ledger: account_balances =
|
let ledger: account_balances =
|
||||||
Map.literal([
|
Map.literal([
|
||||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, 10mutez),
|
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, 10mutez)
|
||||||
]);
|
]);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -124,25 +124,23 @@ let ledger: account_balances = Map.literal
|
|||||||
|
|
||||||
<!--ReasonLIGO-->
|
<!--ReasonLIGO-->
|
||||||
```reasonligo
|
```reasonligo
|
||||||
/* alias two types */
|
(* alias two types *)
|
||||||
type account = address;
|
type account = address;
|
||||||
type number_of_transactions = nat;
|
type number_of_transactions = nat;
|
||||||
/* account_data consists of a record with two fields (balance, number_of_transactions) */
|
(* account_data consists of a record with two fields (balance, number_of_transactions) *)
|
||||||
type account_data = {
|
type account_data = {
|
||||||
balance: tez,
|
balance: tez,
|
||||||
number_of_transactions,
|
number_of_transactions,
|
||||||
};
|
};
|
||||||
/* our ledger / account_balances is a map of account <-> account_data */
|
(* our ledger / account_balances is a map of account <-> account_data *)
|
||||||
type account_balances = map(account, account_data);
|
type account_balances = map(account, account_data);
|
||||||
|
|
||||||
/* pseudo-JSON representation of our map */
|
(* pseudo-JSON representation of our map
|
||||||
/* {"tz1...": {balance: 10mutez, number_of_transactions: 5n}} */
|
{"tz1...": {balance: 10mutez, number_of_transactions: 5n}} *)
|
||||||
let ledger: account_balances =
|
let ledger: account_balances =
|
||||||
Map.literal([
|
Map.literal([
|
||||||
(
|
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address,
|
||||||
"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address,
|
{balance: 10mutez, number_of_transactions: 5n})
|
||||||
{balance: 10mutez, number_of_transactions: 5n},
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -17,7 +17,7 @@ In the [previous tutorial](tutorials/get-started/tezos-taco-shop-smart-contract.
|
|||||||
## Analyzing the current contract
|
## Analyzing the current contract
|
||||||
|
|
||||||
### **`taco-shop.ligo`**
|
### **`taco-shop.ligo`**
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -34,7 +34,7 @@ function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_sho
|
|||||||
|
|
||||||
if amount =/= current_purchase_price then
|
if amount =/= current_purchase_price then
|
||||||
// we won't sell tacos if the amount isn't correct
|
// we won't sell tacos if the amount isn't correct
|
||||||
fail("Sorry, the taco you're trying to purchase has a different price");
|
failwith("Sorry, the taco you're trying to purchase has a different price");
|
||||||
else
|
else
|
||||||
// Decrease the stock by 1n, because we've just sold one
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
@ -47,7 +47,7 @@ function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_sho
|
|||||||
### Purchase price formula
|
### Purchase price formula
|
||||||
Pedro's Taco Shop contract currently enables customers to buy tacos, at a computed price based on a simple formula.
|
Pedro's Taco Shop contract currently enables customers to buy tacos, at a computed price based on a simple formula.
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock;
|
const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -67,8 +67,8 @@ This means that after all the *purchase conditions* of our contract are met - e.
|
|||||||
### Defining the recipient
|
### Defining the recipient
|
||||||
In order to send tokens, we will need a receiver address - which in our case will be Pedro's personal account. Additionally we'll wrap the given address as a *`contract(unit)`* - which represents either a contract with no parameters, or an implicit account.
|
In order to send tokens, we will need a receiver address - which in our case will be Pedro's personal account. Additionally we'll wrap the given address as a *`contract(unit)`* - which represents either a contract with no parameters, or an implicit account.
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=ex1
|
||||||
const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
|
const ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
|
||||||
const receiver : contract(unit) = get_contract(ownerAddress);
|
const receiver : contract(unit) = get_contract(ownerAddress);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ const receiver : contract(unit) = get_contract(ownerAddress);
|
|||||||
Now we can transfer the `amount` received by `buy_taco` to Pedro's `ownerAddress`. We will do so by forging a `transaction(unit, amount, receiver)` within a list of operations returned at the end of our contract.
|
Now we can transfer the `amount` received by `buy_taco` to Pedro's `ownerAddress`. We will do so by forging a `transaction(unit, amount, receiver)` within a list of operations returned at the end of our contract.
|
||||||
|
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=ex1
|
||||||
const payoutOperation : operation = transaction(unit, amount, receiver) ;
|
const payoutOperation : operation = transaction(unit, amount, receiver) ;
|
||||||
const operations : list(operation) = list
|
const operations : list(operation) = list
|
||||||
payoutOperation
|
payoutOperation
|
||||||
@ -90,14 +90,14 @@ end;
|
|||||||
## Finalizing the contract
|
## Finalizing the contract
|
||||||
|
|
||||||
### **`taco-shop.ligo`**
|
### **`taco-shop.ligo`**
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
end
|
end
|
||||||
type taco_shop_storage is map(nat, taco_supply);
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
|
const ownerAddress: address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
|
||||||
|
|
||||||
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
begin
|
begin
|
||||||
@ -108,7 +108,7 @@ function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_sho
|
|||||||
|
|
||||||
if amount =/= current_purchase_price then
|
if amount =/= current_purchase_price then
|
||||||
// we won't sell tacos if the amount isn't correct
|
// we won't sell tacos if the amount isn't correct
|
||||||
fail("Sorry, the taco you're trying to purchase has a different price");
|
failwith("Sorry, the taco you're trying to purchase has a different price");
|
||||||
else
|
else
|
||||||
// Decrease the stock by 1n, because we've just sold one
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
@ -130,7 +130,7 @@ function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_sho
|
|||||||
|
|
||||||
To confirm that our contract is valid, we can dry run it. As a result we see a *new operation* in the list of returned operations to be executed subsequently.
|
To confirm that our contract is valid, we can dry run it. As a result we see a *new operation* in the list of returned operations to be executed subsequently.
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
ligo dry-run taco-shop.ligo --syntax pascaligo --amount 1 buy_taco 1n "map
|
ligo dry-run taco-shop.ligo --syntax pascaligo --amount 1 buy_taco 1n "map
|
||||||
1n -> record
|
1n -> record
|
||||||
current_stock = 50n;
|
current_stock = 50n;
|
||||||
@ -158,12 +158,12 @@ end"
|
|||||||
|
|
||||||
Because Pedro is a member of the (STA) Specialty Taco Association, he has decided to donate **10%** of the earnings to the STA. We'll just add a `donationAddress` to the contract, and compute a 10% donation sum from each taco purchase.
|
Because Pedro is a member of the (STA) Specialty Taco Association, he has decided to donate **10%** of the earnings to the STA. We'll just add a `donationAddress` to the contract, and compute a 10% donation sum from each taco purchase.
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=bonus
|
||||||
const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
|
const ownerAddress: address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
|
||||||
const donationAddress: address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
|
const donationAddress: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
|
||||||
```
|
```
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=bonus
|
||||||
const receiver : contract(unit) = get_contract(ownerAddress);
|
const receiver : contract(unit) = get_contract(ownerAddress);
|
||||||
const donationReceiver : contract(unit) = get_contract(donationAddress);
|
const donationReceiver : contract(unit) = get_contract(donationAddress);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ Each taco kind, has its own `max_price` that it sells for, and a finite supply f
|
|||||||
|
|
||||||
Current purchase price is calculated with the following equation:
|
Current purchase price is calculated with the following equation:
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
current_purchase_price = max_price / available_stock
|
current_purchase_price = max_price / available_stock
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ The best way to install the dockerized LIGO is as a **global executable** throug
|
|||||||
To begin implementing our smart contract, we need an entry point. We'll call it `main` and it'll specify our contract's storage (`int`) and input parameter (`int`). Of course this is not the final storage/parameter of our contract, but it's something to get us started and test our LIGO installation as well.
|
To begin implementing our smart contract, we need an entry point. We'll call it `main` and it'll specify our contract's storage (`int`) and input parameter (`int`). Of course this is not the final storage/parameter of our contract, but it's something to get us started and test our LIGO installation as well.
|
||||||
|
|
||||||
### `taco-shop.ligo`
|
### `taco-shop.ligo`
|
||||||
```pascaligo
|
```pascaligo group=a
|
||||||
function main (const parameter: int; const contractStorage: int) : (list(operation) * int) is
|
function main (const parameter: int; const contractStorage: int) : (list(operation) * int) is
|
||||||
block {skip} with ((nil : list(operation)), contractStorage + parameter)
|
block {skip} with ((nil : list(operation)), contractStorage + parameter)
|
||||||
```
|
```
|
||||||
@ -129,7 +129,7 @@ ligo dry-run taco-shop.ligo --syntax pascaligo main 4 3
|
|||||||
We know that Pedro's Taco Shop serves two kinds of tacos, so we'll need to manage stock individually, per kind. Let's define a type, that will keep the `stock` & `max_price` per kind - in a record with two fields. Additionally, we'll want to combine our `taco_supply` type into a map, consisting of the entire offer of Pedro's shop.
|
We know that Pedro's Taco Shop serves two kinds of tacos, so we'll need to manage stock individually, per kind. Let's define a type, that will keep the `stock` & `max_price` per kind - in a record with two fields. Additionally, we'll want to combine our `taco_supply` type into a map, consisting of the entire offer of Pedro's shop.
|
||||||
|
|
||||||
**Taco shop's storage**
|
**Taco shop's storage**
|
||||||
```pascaligo
|
```pascaligo group=b
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -141,7 +141,7 @@ type taco_shop_storage is map(nat, taco_supply);
|
|||||||
Next step is to update the `main` entry point to include `taco_shop_storage` as its storage - while doing that let's set the `parameter` to `unit` as well to clear things up.
|
Next step is to update the `main` entry point to include `taco_shop_storage` as its storage - while doing that let's set the `parameter` to `unit` as well to clear things up.
|
||||||
|
|
||||||
**`taco-shop.ligo`**
|
**`taco-shop.ligo`**
|
||||||
```pascaligo
|
```pascaligo group=b+
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -208,7 +208,7 @@ Let's start by customizing our contract a bit, we will:
|
|||||||
- change `taco_shop_storage` to a `var` instead of a `const`, because we'll want to modify it
|
- change `taco_shop_storage` to a `var` instead of a `const`, because we'll want to modify it
|
||||||
|
|
||||||
**`taco-shop.ligo`**
|
**`taco-shop.ligo`**
|
||||||
```pascaligo
|
```pascaligo group=c
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -231,7 +231,7 @@ In order to decrease the stock in our contract's storage for a specific taco kin
|
|||||||
|
|
||||||
**`taco-shop.ligo`**
|
**`taco-shop.ligo`**
|
||||||
|
|
||||||
```pascaligo
|
```pascaligo group=d
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -266,7 +266,7 @@ To make sure we get paid, we will:
|
|||||||
- if yes, stock for the given `taco_kind` will be decreased and the payment accepted
|
- if yes, stock for the given `taco_kind` will be decreased and the payment accepted
|
||||||
|
|
||||||
**`taco-shop.ligo`**
|
**`taco-shop.ligo`**
|
||||||
```pascaligo
|
```pascaligo group=e
|
||||||
type taco_supply is record
|
type taco_supply is record
|
||||||
current_stock : nat;
|
current_stock : nat;
|
||||||
max_price : tez;
|
max_price : tez;
|
||||||
@ -282,7 +282,7 @@ function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_sho
|
|||||||
|
|
||||||
if amount =/= current_purchase_price then
|
if amount =/= current_purchase_price then
|
||||||
// we won't sell tacos if the amount isn't correct
|
// we won't sell tacos if the amount isn't correct
|
||||||
fail("Sorry, the taco you're trying to purchase has a different price");
|
failwith("Sorry, the taco you're trying to purchase has a different price");
|
||||||
else
|
else
|
||||||
// Decrease the stock by 1n, because we've just sold one
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
@ -324,14 +324,14 @@ end"
|
|||||||
|
|
||||||
## 💰 Bonus: *Accepting tips above the taco purchase price*
|
## 💰 Bonus: *Accepting tips above the taco purchase price*
|
||||||
|
|
||||||
If you'd like to accept tips in your contract as well, simply change the following line, depending on which behavior do you prefer.
|
If you'd like to accept tips in your contract as well, simply change the following line, depending on your preference.
|
||||||
|
|
||||||
**Without tips**
|
**Without tips**
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
if amount =/= current_purchase_price then
|
if amount =/= current_purchase_price then
|
||||||
```
|
```
|
||||||
|
|
||||||
**With tips**
|
**With tips**
|
||||||
```pascaligo
|
```pascaligo skip
|
||||||
if amount >= current_purchase_price then
|
if amount >= current_purchase_price then
|
||||||
```
|
```
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"Advanced": [
|
"Advanced": [
|
||||||
"advanced/timestamps-addresses",
|
"advanced/timestamps-addresses",
|
||||||
"advanced/entrypoints-contracts",
|
"advanced/entrypoints-contracts",
|
||||||
|
"advanced/include",
|
||||||
"advanced/first-contract"
|
"advanced/first-contract"
|
||||||
],
|
],
|
||||||
"API": [
|
"API": [
|
||||||
|
@ -11,6 +11,7 @@ depends: [
|
|||||||
"ocamlfind" { build }
|
"ocamlfind" { build }
|
||||||
"dune" { build & = "1.11.4" }
|
"dune" { build & = "1.11.4" }
|
||||||
"menhir" { = "20190626" }
|
"menhir" { = "20190626" }
|
||||||
|
"bisect_ppx" {dev & >= "2.0.0"}
|
||||||
"ppx_let"
|
"ppx_let"
|
||||||
"ppx_deriving"
|
"ppx_deriving"
|
||||||
"ppx_expect"
|
"ppx_expect"
|
||||||
@ -20,7 +21,10 @@ depends: [
|
|||||||
"alcotest" { with-test }
|
"alcotest" { with-test }
|
||||||
"getopt"
|
"getopt"
|
||||||
# work around upstream in-place update
|
# work around upstream in-place update
|
||||||
"ocaml-migrate-parsetree" { = "1.3.1" }
|
"ocaml-migrate-parsetree" { = "1.4.0" }
|
||||||
|
]
|
||||||
|
pin-depends: [
|
||||||
|
["bisect_ppx.git" "git+https://github.com/aantron/bisect_ppx.git#02dfb10188033a26d07d23480c2bc44a3a670357"]
|
||||||
]
|
]
|
||||||
build: [
|
build: [
|
||||||
[ "dune" "build" "-p" name "-j" jobs ]
|
[ "dune" "build" "-p" name "-j" jobs ]
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
)
|
)
|
||||||
(modules cli cli_helpers version)
|
(modules cli cli_helpers version)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils))
|
(flags (:standard -open Simple_utils))
|
||||||
)
|
)
|
||||||
@ -31,7 +31,7 @@
|
|||||||
(modules runligo)
|
(modules runligo)
|
||||||
(package ligo)
|
(package ligo)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils))
|
(flags (:standard -open Simple_utils))
|
||||||
)
|
)
|
||||||
|
@ -927,4 +927,12 @@ let%expect_test _ =
|
|||||||
|
|
||||||
let%expect_test _ =
|
let%expect_test _ =
|
||||||
run_ligo_bad [ "compile-contract" ; contract "bad_type_operator.ligo" ; "main" ] ;
|
run_ligo_bad [ "compile-contract" ; contract "bad_type_operator.ligo" ; "main" ] ;
|
||||||
[%expect {| ligo: bad type operator (TO_Map (unit,unit)): |}] ;
|
[%expect {| ligo: bad type operator (TO_Map (unit,unit)): |}]
|
||||||
|
|
||||||
|
let%expect_test _ =
|
||||||
|
run_ligo_bad [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ;
|
||||||
|
[%expect {| ligo: Execution failed: {"value":"some_string","type":"string"} |}]
|
||||||
|
|
||||||
|
let%expect_test _ =
|
||||||
|
run_ligo_bad [ "compile-contract" ; contract "bad_address_format.religo" ; "main" ] ;
|
||||||
|
[%expect {| ligo: in file "bad_address_format.religo", line 2, characters 25-47. Badly formatted address "KT1badaddr": {"location":"in file \"bad_address_format.religo\", line 2, characters 25-47"} |}]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(library
|
(library
|
||||||
(name cli_expect_tests)
|
(name cli_expect_tests)
|
||||||
(libraries simple-utils cli)
|
(libraries simple-utils cli)
|
||||||
(inline_tests)
|
(inline_tests (deps (source_tree ../../test/contracts)))
|
||||||
(preprocess (pps ppx_let ppx_expect))
|
(preprocess (pps ppx_let ppx_expect))
|
||||||
(flags (:standard -open Simple_utils)))
|
(flags (:standard -open Simple_utils)))
|
||||||
|
2
src/dune
2
src/dune
@ -9,6 +9,6 @@
|
|||||||
main
|
main
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
self_michelson
|
self_michelson
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -68,15 +68,6 @@ let parsify_reasonligo = fun source ->
|
|||||||
Simplify.Cameligo.simpl_program raw in
|
Simplify.Cameligo.simpl_program raw in
|
||||||
ok simplified
|
ok simplified
|
||||||
|
|
||||||
let parsify_string_reasonligo = fun source ->
|
|
||||||
let%bind raw =
|
|
||||||
trace (simple_error "parsing") @@
|
|
||||||
Parser.Reasonligo.parse_string source in
|
|
||||||
let%bind simplified =
|
|
||||||
trace (simple_error "simplifying") @@
|
|
||||||
Simplify.Cameligo.simpl_program raw in
|
|
||||||
ok simplified
|
|
||||||
|
|
||||||
let parsify_expression_reasonligo = fun source ->
|
let parsify_expression_reasonligo = fun source ->
|
||||||
let%bind raw =
|
let%bind raw =
|
||||||
trace (simple_error "parsing expression") @@
|
trace (simple_error "parsing expression") @@
|
||||||
@ -105,3 +96,40 @@ let parsify_expression = fun syntax source ->
|
|||||||
let%bind parsified = parsify source in
|
let%bind parsified = parsify source in
|
||||||
let%bind applied = Self_ast_simplified.all_expression parsified in
|
let%bind applied = Self_ast_simplified.all_expression parsified in
|
||||||
ok applied
|
ok applied
|
||||||
|
|
||||||
|
let parsify_string_reasonligo = fun source ->
|
||||||
|
let%bind raw =
|
||||||
|
trace (simple_error "parsing") @@
|
||||||
|
Parser.Reasonligo.parse_string source in
|
||||||
|
let%bind simplified =
|
||||||
|
trace (simple_error "simplifying") @@
|
||||||
|
Simplify.Cameligo.simpl_program raw in
|
||||||
|
ok simplified
|
||||||
|
|
||||||
|
let parsify_string_pascaligo = fun source ->
|
||||||
|
let%bind raw =
|
||||||
|
trace (simple_error "parsing") @@
|
||||||
|
Parser.Pascaligo.parse_string source in
|
||||||
|
let%bind simplified =
|
||||||
|
trace (simple_error "simplifying") @@
|
||||||
|
Simplify.Pascaligo.simpl_program raw in
|
||||||
|
ok simplified
|
||||||
|
|
||||||
|
let parsify_string_cameligo = fun source ->
|
||||||
|
let%bind raw =
|
||||||
|
trace (simple_error "parsing") @@
|
||||||
|
Parser.Cameligo.parse_string source in
|
||||||
|
let%bind simplified =
|
||||||
|
trace (simple_error "simplifying") @@
|
||||||
|
Simplify.Cameligo.simpl_program raw in
|
||||||
|
ok simplified
|
||||||
|
|
||||||
|
let parsify_string = fun (syntax : v_syntax) source_filename ->
|
||||||
|
let%bind parsify = match syntax with
|
||||||
|
| Pascaligo -> ok parsify_string_pascaligo
|
||||||
|
| Cameligo -> ok parsify_string_cameligo
|
||||||
|
| ReasonLIGO -> ok parsify_string_reasonligo
|
||||||
|
in
|
||||||
|
let%bind parsified = parsify source_filename in
|
||||||
|
let%bind applied = Self_ast_simplified.all_program parsified in
|
||||||
|
ok applied
|
||||||
|
@ -6,6 +6,10 @@ let compile (source_filename:string) syntax : Ast_simplified.program result =
|
|||||||
let%bind simplified = parsify syntax source_filename in
|
let%bind simplified = parsify syntax source_filename in
|
||||||
ok simplified
|
ok simplified
|
||||||
|
|
||||||
|
let compile_string (source:string) syntax : Ast_simplified.program result =
|
||||||
|
let%bind simplified = parsify_string syntax source in
|
||||||
|
ok simplified
|
||||||
|
|
||||||
let compile_expression : v_syntax -> string -> Ast_simplified.expression result =
|
let compile_expression : v_syntax -> string -> Ast_simplified.expression result =
|
||||||
fun syntax exp ->
|
fun syntax exp ->
|
||||||
parsify_expression syntax exp
|
parsify_expression syntax exp
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
uncompile
|
uncompile
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
compile
|
compile
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,21 @@ open Trace
|
|||||||
open Memory_proto_alpha.Protocol.Script_ir_translator
|
open Memory_proto_alpha.Protocol.Script_ir_translator
|
||||||
open Memory_proto_alpha.X
|
open Memory_proto_alpha.X
|
||||||
|
|
||||||
|
module Errors = struct
|
||||||
|
let unknown_failwith_type () =
|
||||||
|
let title () = "Execution failed with an unknown failwith type" in
|
||||||
|
let message () = "only bytes, string or int are printable" in
|
||||||
|
error title message
|
||||||
|
|
||||||
|
let failwith data_str type_str () =
|
||||||
|
let title () = "Execution failed" in
|
||||||
|
let message () = "" in
|
||||||
|
let data = [
|
||||||
|
("value" , fun () -> Format.asprintf "%s" data_str);
|
||||||
|
("type" , fun () -> Format.asprintf "%s" type_str);
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
end
|
||||||
type options = Memory_proto_alpha.options
|
type options = Memory_proto_alpha.options
|
||||||
|
|
||||||
type run_res =
|
type run_res =
|
||||||
@ -121,7 +136,12 @@ let run ?options (exp:Michelson.t) (exp_type:ex_ty) : ex_typed_value result =
|
|||||||
let%bind expr = run_expression ?options exp exp_type in
|
let%bind expr = run_expression ?options exp exp_type in
|
||||||
match expr with
|
match expr with
|
||||||
| Success res -> ok res
|
| Success res -> ok res
|
||||||
| _ -> simple_fail "Execution terminated with failwith"
|
| Fail res -> ( match Tezos_micheline.Micheline.root @@ Memory_proto_alpha.strings_of_prims res with
|
||||||
|
| Int (_ , i) -> fail @@ Errors.failwith (Z.to_string i) "int" ()
|
||||||
|
| String (_ , s) -> fail @@ Errors.failwith s "string" ()
|
||||||
|
| Bytes (_, s) -> fail @@ Errors.failwith (Bytes.to_string s) "bytes" ()
|
||||||
|
| _ -> fail @@ Errors.unknown_failwith_type () )
|
||||||
|
|
||||||
|
|
||||||
let run_failwith ?options (exp:Michelson.t) (exp_type:ex_ty) : run_failwith_res result =
|
let run_failwith ?options (exp:Michelson.t) (exp_type:ex_ty) : run_failwith_res result =
|
||||||
let%bind expr = run_expression ?options exp exp_type in
|
let%bind expr = run_expression ?options exp exp_type in
|
||||||
@ -129,7 +149,7 @@ let run_failwith ?options (exp:Michelson.t) (exp_type:ex_ty) : run_failwith_res
|
|||||||
| Fail res -> ( match Tezos_micheline.Micheline.root @@ Memory_proto_alpha.strings_of_prims res with
|
| Fail res -> ( match Tezos_micheline.Micheline.root @@ Memory_proto_alpha.strings_of_prims res with
|
||||||
| Int (_ , i) -> ok (Failwith_int (Z.to_int i))
|
| Int (_ , i) -> ok (Failwith_int (Z.to_int i))
|
||||||
| String (_ , s) -> ok (Failwith_string s)
|
| String (_ , s) -> ok (Failwith_string s)
|
||||||
| Bytes (_,b) -> ok (Failwith_bytes b)
|
| Bytes (_, b) -> ok (Failwith_bytes b)
|
||||||
| _ -> simple_fail "Unknown failwith type" )
|
| _ -> simple_fail "Unknown failwith type" )
|
||||||
| _ -> simple_fail "An error of execution was expected"
|
| _ -> simple_fail "An error of execution was expected"
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
transpiler
|
transpiler
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[@@@warning "-42"]
|
[@@@warning "-42"]
|
||||||
|
[@@@coverage exclude_file]
|
||||||
|
|
||||||
open AST
|
open AST
|
||||||
open! Region
|
open! Region
|
||||||
|
@ -15,8 +15,11 @@
|
|||||||
str
|
str
|
||||||
simple-utils
|
simple-utils
|
||||||
tezos-utils
|
tezos-utils
|
||||||
getopt)
|
getopt )
|
||||||
(flags (:standard -open Simple_utils -open Parser_shared )))
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional) )
|
||||||
|
(flags (:standard -open Simple_utils -open Parser_shared ))
|
||||||
|
)
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name LexerMain)
|
(name LexerMain)
|
||||||
@ -24,6 +27,8 @@
|
|||||||
parser_cameligo)
|
parser_cameligo)
|
||||||
(modules
|
(modules
|
||||||
LexerMain)
|
LexerMain)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
(flags (:standard -open Parser_shared -open Parser_cameligo)))
|
(flags (:standard -open Parser_shared -open Parser_cameligo)))
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
@ -33,4 +38,6 @@
|
|||||||
(modules
|
(modules
|
||||||
ParserAPI
|
ParserAPI
|
||||||
ParserMain)
|
ParserMain)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
|
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
parser_reasonligo
|
parser_reasonligo
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Parser_shared))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Parser_shared))
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[@@@warning "-42"]
|
[@@@warning "-42"]
|
||||||
|
[@@@coverage exclude_file]
|
||||||
|
|
||||||
open AST
|
open AST
|
||||||
open! Region
|
open! Region
|
||||||
|
@ -10,12 +10,16 @@
|
|||||||
(public_name ligo.parser.pascaligo)
|
(public_name ligo.parser.pascaligo)
|
||||||
(modules AST pascaligo Parser ParserLog LexToken)
|
(modules AST pascaligo Parser ParserLog LexToken)
|
||||||
(libraries
|
(libraries
|
||||||
menhirLib
|
menhirLib
|
||||||
parser_shared
|
parser_shared
|
||||||
hex
|
hex
|
||||||
simple-utils
|
simple-utils
|
||||||
tezos-utils)
|
tezos-utils
|
||||||
(flags (:standard -open Parser_shared -open Simple_utils)))
|
)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
|
(flags (:standard -open Parser_shared -open Simple_utils))
|
||||||
|
)
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name LexerMain)
|
(name LexerMain)
|
||||||
@ -25,18 +29,25 @@
|
|||||||
tezos-utils
|
tezos-utils
|
||||||
parser_pascaligo)
|
parser_pascaligo)
|
||||||
(modules
|
(modules
|
||||||
LexerMain)
|
LexerMain)
|
||||||
(flags (:standard -open Parser_shared -open Parser_pascaligo)))
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
|
(flags (:standard -open Parser_shared -open Parser_pascaligo))
|
||||||
|
)
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name ParserMain)
|
(name ParserMain)
|
||||||
(libraries
|
(libraries
|
||||||
parser_pascaligo)
|
parser_pascaligo)
|
||||||
(modules ParserMain)
|
(modules ParserMain)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo)))
|
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo)))
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name Unlexer)
|
(name Unlexer)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional))
|
||||||
(modules Unlexer))
|
(modules Unlexer))
|
||||||
|
|
||||||
;; Les deux directives (rule) qui suivent sont pour le dev local.
|
;; Les deux directives (rule) qui suivent sont pour le dev local.
|
||||||
|
@ -16,8 +16,13 @@
|
|||||||
str
|
str
|
||||||
simple-utils
|
simple-utils
|
||||||
tezos-utils
|
tezos-utils
|
||||||
getopt)
|
getopt
|
||||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
|
)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional)
|
||||||
|
)
|
||||||
|
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo ))
|
||||||
|
)
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name LexerMain)
|
(name LexerMain)
|
||||||
@ -25,7 +30,11 @@
|
|||||||
parser_reasonligo)
|
parser_reasonligo)
|
||||||
(modules
|
(modules
|
||||||
LexerMain)
|
LexerMain)
|
||||||
(flags (:standard -open Parser_shared -open Parser_reasonligo)))
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional)
|
||||||
|
)
|
||||||
|
(flags (:standard -open Parser_shared -open Parser_reasonligo))
|
||||||
|
)
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name ParserMain)
|
(name ParserMain)
|
||||||
@ -35,4 +44,7 @@
|
|||||||
(modules
|
(modules
|
||||||
ParserAPI
|
ParserAPI
|
||||||
ParserMain)
|
ParserMain)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional)
|
||||||
|
)
|
||||||
(flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo)))
|
(flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo)))
|
||||||
|
@ -7,7 +7,11 @@
|
|||||||
simple-utils
|
simple-utils
|
||||||
uutf
|
uutf
|
||||||
getopt
|
getopt
|
||||||
zarith)
|
zarith
|
||||||
|
)
|
||||||
|
(preprocess
|
||||||
|
(pps bisect_ppx --conditional)
|
||||||
|
)
|
||||||
(modules
|
(modules
|
||||||
Lexer
|
Lexer
|
||||||
LexerLog
|
LexerLog
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
(preprocess
|
(preprocess
|
||||||
(pps
|
(pps
|
||||||
ppx_let
|
ppx_let
|
||||||
|
bisect_ppx --conditional
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
(libraries
|
(libraries
|
||||||
simple-utils
|
simple-utils
|
||||||
ast_simplified
|
ast_simplified
|
||||||
|
proto-alpha-utils
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,28 @@
|
|||||||
open Ast_simplified
|
open Ast_simplified
|
||||||
open Trace
|
open Trace
|
||||||
|
open Proto_alpha_utils
|
||||||
|
|
||||||
|
module Errors = struct
|
||||||
|
let bad_literal_address s_addr loc () =
|
||||||
|
let title = (thunk ("Badly formatted address \""^s_addr^"\"")) in
|
||||||
|
let message () = "" in
|
||||||
|
let data = [
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
|
] in
|
||||||
|
error ~data title message ()
|
||||||
|
end
|
||||||
|
open Errors
|
||||||
|
|
||||||
let peephole_expression : expression -> expression result = fun e ->
|
let peephole_expression : expression -> expression result = fun e ->
|
||||||
let return expression = ok { e with expression } in
|
let return expression = ok { e with expression } in
|
||||||
match e.expression with
|
match e.expression with
|
||||||
|
| E_literal (Literal_address s) as l -> (
|
||||||
|
let open Memory_proto_alpha in
|
||||||
|
let%bind (_contract:Protocol.Alpha_context.Contract.t) =
|
||||||
|
Trace.trace_alpha_tzresult (bad_literal_address s e.location) @@
|
||||||
|
Protocol.Alpha_context.Contract.of_b58check s in
|
||||||
|
return l
|
||||||
|
)
|
||||||
| E_constant (C_BIG_MAP_LITERAL , lst) -> (
|
| E_constant (C_BIG_MAP_LITERAL , lst) -> (
|
||||||
let%bind elt =
|
let%bind elt =
|
||||||
trace_option (simple_error "big_map literal expects a single parameter") @@
|
trace_option (simple_error "big_map literal expects a single parameter") @@
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
operators
|
operators
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
operators
|
operators
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
)
|
)
|
||||||
(inline_tests)
|
(inline_tests)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let ppx_expect)
|
(pps ppx_let ppx_expect bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
operators
|
operators
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
tezos-utils
|
tezos-utils
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
mini_c
|
mini_c
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils ))
|
(flags (:standard -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -92,6 +92,7 @@ module Simplify = struct
|
|||||||
| "bytes_concat" -> ok C_CONCAT
|
| "bytes_concat" -> ok C_CONCAT
|
||||||
| "bytes_slice" -> ok C_SLICE
|
| "bytes_slice" -> ok C_SLICE
|
||||||
| "bytes_pack" -> ok C_BYTES_PACK
|
| "bytes_pack" -> ok C_BYTES_PACK
|
||||||
|
| "bytes_unpack" -> ok C_BYTES_UNPACK
|
||||||
| "set_empty" -> ok C_SET_EMPTY
|
| "set_empty" -> ok C_SET_EMPTY
|
||||||
| "set_mem" -> ok C_SET_MEM
|
| "set_mem" -> ok C_SET_MEM
|
||||||
| "set_add" -> ok C_SET_ADD
|
| "set_add" -> ok C_SET_ADD
|
||||||
@ -243,6 +244,7 @@ module Simplify = struct
|
|||||||
| "AND" -> ok C_AND
|
| "AND" -> ok C_AND
|
||||||
| "OR" -> ok C_OR
|
| "OR" -> ok C_OR
|
||||||
| "GT" -> ok C_GT
|
| "GT" -> ok C_GT
|
||||||
|
| "GE" -> ok C_GE
|
||||||
| "LT" -> ok C_LT
|
| "LT" -> ok C_LT
|
||||||
| "LE" -> ok C_LE
|
| "LE" -> ok C_LE
|
||||||
| "CONS" -> ok C_CONS
|
| "CONS" -> ok C_CONS
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
[@@@coverage exclude_file]
|
||||||
open Types
|
open Types
|
||||||
open PP_helpers
|
open PP_helpers
|
||||||
open Format
|
open Format
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
stage_common
|
stage_common
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils ))
|
(flags (:standard -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
[@@@coverage exclude_file]
|
||||||
open Types
|
open Types
|
||||||
open Format
|
open Format
|
||||||
open PP_helpers
|
open PP_helpers
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
stage_common
|
stage_common
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils))
|
(flags (:standard -open Simple_utils))
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
)
|
)
|
||||||
(inline_tests)
|
(inline_tests)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let ppx_expect)
|
(pps ppx_let ppx_expect bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -open Simple_utils))
|
(flags (:standard -open Simple_utils))
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
[@@@coverage exclude_file]
|
||||||
open Simple_utils.PP_helpers
|
open Simple_utils.PP_helpers
|
||||||
open Types
|
open Types
|
||||||
open Format
|
open Format
|
||||||
|
@ -7,6 +7,6 @@
|
|||||||
stage_common
|
stage_common
|
||||||
)
|
)
|
||||||
(inline_tests)
|
(inline_tests)
|
||||||
(preprocess (pps ppx_expect ppx_let))
|
(preprocess (pps ppx_expect ppx_let bisect_ppx --conditional))
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
mini_c
|
mini_c
|
||||||
)
|
)
|
||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let bisect_ppx --conditional)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
3
src/test/contracts/bad_address_format.religo
Normal file
3
src/test/contracts/bad_address_format.religo
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
let main = (parameter: int, storage: address) => {
|
||||||
|
([]:list(operation), "KT1badaddr" : address);
|
||||||
|
};
|
11
src/test/contracts/bytes_unpack.ligo
Normal file
11
src/test/contracts/bytes_unpack.ligo
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
function id_string (const p : string) : option(string) is block {
|
||||||
|
const packed : bytes = bytes_pack(p) ;
|
||||||
|
} with (bytes_unpack(packed): option(string))
|
||||||
|
|
||||||
|
function id_int (const p : int) : option(int) is block {
|
||||||
|
const packed : bytes = bytes_pack(p) ;
|
||||||
|
} with (bytes_unpack(packed): option(int))
|
||||||
|
|
||||||
|
function id_address (const p : address) : option(address) is block {
|
||||||
|
const packed : bytes = bytes_pack(p) ;
|
||||||
|
} with (bytes_unpack(packed): option(address))
|
@ -31,3 +31,7 @@ function foobar (const i : int) : int is
|
|||||||
| Zero (n) -> i
|
| Zero (n) -> i
|
||||||
| Pos (n) -> (failwith ("waaaa") : int)
|
| Pos (n) -> (failwith ("waaaa") : int)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function failer(const p : int) : int is block {
|
||||||
|
if p = 1 then failwith("some_string") else skip ;
|
||||||
|
} with p
|
||||||
|
3
src/test/contracts/included.mligo
Normal file
3
src/test/contracts/included.mligo
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Demonstrate CameLIGO inclusion statements, see includer.mligo
|
||||||
|
|
||||||
|
let foo : int = 144
|
3
src/test/contracts/included.religo
Normal file
3
src/test/contracts/included.religo
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Demonstrate ReasonLIGO inclusion statements, see includer.religo
|
||||||
|
|
||||||
|
let foo : int = 144;
|
5
src/test/contracts/includer.mligo
Normal file
5
src/test/contracts/includer.mligo
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Demonstrate CameLIGO inclusion statements, see included.mligo
|
||||||
|
|
||||||
|
#include "included.mligo"
|
||||||
|
|
||||||
|
let bar : int = foo
|
5
src/test/contracts/includer.religo
Normal file
5
src/test/contracts/includer.religo
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Demonstrate ReasonLIGO inclusion statements, see included.religo
|
||||||
|
|
||||||
|
#include "included.religo"
|
||||||
|
|
||||||
|
let bar : int = foo;
|
8
src/test/doc_test.ml
Normal file
8
src/test/doc_test.ml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
open Test_helpers
|
||||||
|
|
||||||
|
let () =
|
||||||
|
Printexc.record_backtrace true ;
|
||||||
|
run_test @@ test_suite "LIGO" [
|
||||||
|
Md_file_tests.main ;
|
||||||
|
] ;
|
||||||
|
()
|
@ -1,5 +1,7 @@
|
|||||||
|
(ocamllex md)
|
||||||
|
|
||||||
(executables
|
(executables
|
||||||
(names test manual_test)
|
(names test manual_test doc_test)
|
||||||
(libraries
|
(libraries
|
||||||
simple-utils
|
simple-utils
|
||||||
ligo
|
ligo
|
||||||
@ -12,6 +14,12 @@
|
|||||||
(flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils ))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(alias
|
||||||
|
(name doc-test)
|
||||||
|
(action (run ./doc_test.exe))
|
||||||
|
(deps (source_tree ../../gitlab-pages/docs))
|
||||||
|
)
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
(name ligo-test)
|
(name ligo-test)
|
||||||
(action (run ./test.exe))
|
(action (run ./test.exe))
|
||||||
@ -21,7 +29,7 @@
|
|||||||
|
|
||||||
(alias
|
(alias
|
||||||
(name runtest)
|
(name runtest)
|
||||||
(deps (alias ligo-test))
|
(deps (alias ligo-test) (alias doc-test))
|
||||||
)
|
)
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
|
@ -604,6 +604,14 @@ let include_ () : unit result =
|
|||||||
let%bind program = type_file "./contracts/includer.ligo" in
|
let%bind program = type_file "./contracts/includer.ligo" in
|
||||||
expect_eq_evaluate program "bar" (e_int 144)
|
expect_eq_evaluate program "bar" (e_int 144)
|
||||||
|
|
||||||
|
let include_mligo () : unit result =
|
||||||
|
let%bind program = mtype_file "./contracts/includer.mligo" in
|
||||||
|
expect_eq_evaluate program "bar" (e_int 144)
|
||||||
|
|
||||||
|
let include_religo () : unit result =
|
||||||
|
let%bind program = retype_file "./contracts/includer.religo" in
|
||||||
|
expect_eq_evaluate program "bar" (e_int 144)
|
||||||
|
|
||||||
let record_ez_int names n =
|
let record_ez_int names n =
|
||||||
ez_e_record @@ List.map (fun x -> x, e_int n) names
|
ez_e_record @@ List.map (fun x -> x, e_int n) names
|
||||||
|
|
||||||
@ -1812,7 +1820,18 @@ let let_in_multi_bind () : unit result =
|
|||||||
(e_string "mynameisbob")
|
(e_string "mynameisbob")
|
||||||
in ok ()
|
in ok ()
|
||||||
|
|
||||||
|
let bytes_unpack () : unit result =
|
||||||
|
let%bind program = type_file "./contracts/bytes_unpack.ligo" in
|
||||||
|
let%bind () = expect_eq program "id_string" (e_string "teststring") (e_some (e_string "teststring")) in
|
||||||
|
let%bind () = expect_eq program "id_int" (e_int 42) (e_some (e_int 42)) in
|
||||||
|
let open Proto_alpha_utils.Memory_proto_alpha in
|
||||||
|
let addr = Protocol.Alpha_context.Contract.to_b58check @@
|
||||||
|
(List.nth dummy_environment.identities 0).implicit_contract in
|
||||||
|
let%bind () = expect_eq program "id_address" (e_address addr) (e_some (e_address addr)) in
|
||||||
|
ok ()
|
||||||
|
|
||||||
let main = test_suite "Integration (End to End)" [
|
let main = test_suite "Integration (End to End)" [
|
||||||
|
test "bytes unpack" bytes_unpack ;
|
||||||
test "key hash" key_hash ;
|
test "key hash" key_hash ;
|
||||||
test "chain id" chain_id ;
|
test "chain id" chain_id ;
|
||||||
test "type alias" type_alias ;
|
test "type alias" type_alias ;
|
||||||
@ -1888,6 +1907,8 @@ let main = test_suite "Integration (End to End)" [
|
|||||||
test "quote declaration" quote_declaration ;
|
test "quote declaration" quote_declaration ;
|
||||||
test "quote declarations" quote_declarations ;
|
test "quote declarations" quote_declarations ;
|
||||||
test "#include directives" include_ ;
|
test "#include directives" include_ ;
|
||||||
|
test "#include directives (mligo)" include_mligo ;
|
||||||
|
test "#include directives (religo)" include_religo ;
|
||||||
test "counter contract" counter_contract ;
|
test "counter contract" counter_contract ;
|
||||||
test "super counter contract" super_counter_contract ;
|
test "super counter contract" super_counter_contract ;
|
||||||
test "super counter contract" super_counter_contract_mligo ;
|
test "super counter contract" super_counter_contract_mligo ;
|
||||||
|
62
src/test/md.mll
Normal file
62
src/test/md.mll
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
(* initial version taken from https://github.com/realworldocaml/mdx *)
|
||||||
|
type arg =
|
||||||
|
| Field of string
|
||||||
|
| NameValue of string * string
|
||||||
|
|
||||||
|
type block = {
|
||||||
|
line : int;
|
||||||
|
file : string;
|
||||||
|
arguments: arg list;
|
||||||
|
header : string option;
|
||||||
|
contents: string list;
|
||||||
|
}
|
||||||
|
|
||||||
|
exception Err of string
|
||||||
|
|
||||||
|
let line_ref = ref 1
|
||||||
|
|
||||||
|
let newline lexbuf =
|
||||||
|
Lexing.new_line lexbuf;
|
||||||
|
incr line_ref
|
||||||
|
}
|
||||||
|
|
||||||
|
let eol = '\n' | eof
|
||||||
|
let ws = ' ' | '\t'
|
||||||
|
|
||||||
|
rule text = parse
|
||||||
|
| eof { [] }
|
||||||
|
| "```" ([^' ' '\n']* as h) ws* ([^'\n']* as l) eol
|
||||||
|
{
|
||||||
|
let header = if h = "" then None else Some h in
|
||||||
|
let contents = block lexbuf in
|
||||||
|
let arguments = String.split_on_char ' ' l in
|
||||||
|
let arguments = List.map (fun a ->
|
||||||
|
if (String.contains a '=') then
|
||||||
|
( let a = String.split_on_char '=' a in
|
||||||
|
NameValue (List.nth a 0, List.nth a 1))
|
||||||
|
else
|
||||||
|
Field a
|
||||||
|
) arguments in
|
||||||
|
let file = lexbuf.Lexing.lex_start_p.Lexing.pos_fname in
|
||||||
|
newline lexbuf;
|
||||||
|
let line = !line_ref in
|
||||||
|
List.iter (fun _ -> newline lexbuf) contents;
|
||||||
|
newline lexbuf;
|
||||||
|
{ file; line; header; arguments; contents; }
|
||||||
|
:: text lexbuf }
|
||||||
|
| [^'\n']* eol
|
||||||
|
{ newline lexbuf;
|
||||||
|
text lexbuf }
|
||||||
|
|
||||||
|
and block = parse
|
||||||
|
| eof | "```" ws* eol { [] }
|
||||||
|
| ([^'\n'] * as str) eol { str :: block lexbuf }
|
||||||
|
|
||||||
|
{
|
||||||
|
let token lexbuf =
|
||||||
|
try
|
||||||
|
text lexbuf
|
||||||
|
with Failure _ ->
|
||||||
|
raise (Err "incomplete code block")
|
||||||
|
}
|
121
src/test/md_file_tests.ml
Normal file
121
src/test/md_file_tests.ml
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
open Trace
|
||||||
|
open Test_helpers
|
||||||
|
|
||||||
|
module SnippetsGroup = Map.Make(struct type t = (string * string) let compare a b = compare a b end)
|
||||||
|
|
||||||
|
let failed_to_compile_md_file md_file (s,group,prg) =
|
||||||
|
let title () = "Failed to compile ```"^s^" block (group '"^group^"') in file '"^md_file^"'" in
|
||||||
|
let content () = "\n"^prg in
|
||||||
|
error title content
|
||||||
|
|
||||||
|
(**
|
||||||
|
binds the snippets by (syntax, group_name)
|
||||||
|
e.g. :(pascaligo, a) -> "let .. in let .. in"
|
||||||
|
(cameligo, a) -> "let .. in let .. in"
|
||||||
|
syntax and group_name being retrieved from the .md file header & arguments
|
||||||
|
e.g. : ```syntax group=group_name ...some code ... ```
|
||||||
|
**)
|
||||||
|
let get_groups md_file =
|
||||||
|
let channel = open_in md_file in
|
||||||
|
let lexbuf = Lexing.from_channel channel in
|
||||||
|
let code_blocks = Md.token lexbuf in
|
||||||
|
List.fold_left
|
||||||
|
(fun (grp_map: _ SnippetsGroup.t) (el:Md.block) ->
|
||||||
|
match el.header with
|
||||||
|
| Some s when (String.equal s "pascaligo") || (String.equal s "cameligo") || (String.equal s "reasonligo") -> (
|
||||||
|
match el.arguments with
|
||||||
|
| [Md.Field ""] -> SnippetsGroup.update (s,"ungrouped")
|
||||||
|
(fun arg_content ->
|
||||||
|
match arg_content with
|
||||||
|
| Some ct -> Some (String.concat "\n" (ct::el.contents))
|
||||||
|
| None -> Some (String.concat "\n" el.contents)
|
||||||
|
)
|
||||||
|
grp_map
|
||||||
|
| [Md.Field "skip"] -> grp_map
|
||||||
|
| _ ->
|
||||||
|
List.fold_left
|
||||||
|
(fun grp_map arg -> match arg with
|
||||||
|
| Md.NameValue ("group", name) ->
|
||||||
|
SnippetsGroup.update (s,name)
|
||||||
|
(fun arg_content ->
|
||||||
|
match arg_content with
|
||||||
|
| Some ct -> Some (String.concat "\n" (ct::el.contents))
|
||||||
|
| None -> Some (String.concat "\n" el.contents)
|
||||||
|
)
|
||||||
|
grp_map
|
||||||
|
| _ -> grp_map
|
||||||
|
)
|
||||||
|
grp_map el.arguments )
|
||||||
|
| None | Some _ -> grp_map
|
||||||
|
)
|
||||||
|
SnippetsGroup.empty code_blocks
|
||||||
|
|
||||||
|
(**
|
||||||
|
evaluate each expression in each programs from the snippets group map
|
||||||
|
**)
|
||||||
|
let compile_groups _filename grp_list =
|
||||||
|
let%bind (_michelsons : Compiler.compiled_expression list list) = bind_map_list
|
||||||
|
(fun ((s,grp),contents) ->
|
||||||
|
trace (failed_to_compile_md_file _filename (s,grp,contents)) @@
|
||||||
|
let%bind v_syntax = Compile.Helpers.syntax_to_variant (Syntax_name s) None in
|
||||||
|
let%bind simplified = Compile.Of_source.compile_string contents v_syntax in
|
||||||
|
let%bind typed,_ = Compile.Of_simplified.compile simplified in
|
||||||
|
let%bind mini_c = Compile.Of_typed.compile typed in
|
||||||
|
bind_map_list
|
||||||
|
(fun ((_,exp),_) -> Compile.Of_mini_c.aggregate_and_compile_expression mini_c exp)
|
||||||
|
mini_c
|
||||||
|
)
|
||||||
|
grp_list in
|
||||||
|
ok ()
|
||||||
|
|
||||||
|
let compile filename () =
|
||||||
|
let groups = SnippetsGroup.bindings @@ get_groups filename in
|
||||||
|
let%bind () = compile_groups filename groups in
|
||||||
|
ok ()
|
||||||
|
|
||||||
|
(*
|
||||||
|
find ./gitlab-pages/ -iname "*.md"
|
||||||
|
*)
|
||||||
|
let md_files = [
|
||||||
|
"/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-smart-contract.md";
|
||||||
|
"/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md";
|
||||||
|
"/gitlab-pages/docs/intro/installation.md";
|
||||||
|
"/gitlab-pages/docs/intro/editor-support.md";
|
||||||
|
"/gitlab-pages/docs/intro/what-and-why.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/math-numbers-tez.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/functions.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/boolean-if-else.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/types.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/strings.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/maps-records.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/variables-and-constants.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/sets-lists-touples.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/operators.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md";
|
||||||
|
"/gitlab-pages/docs/language-basics/loops.md";
|
||||||
|
"/gitlab-pages/docs/contributors/big-picture/back-end.md";
|
||||||
|
"/gitlab-pages/docs/contributors/big-picture/vendors.md";
|
||||||
|
"/gitlab-pages/docs/contributors/big-picture/front-end.md";
|
||||||
|
"/gitlab-pages/docs/contributors/big-picture/overview.md";
|
||||||
|
"/gitlab-pages/docs/contributors/big-picture/middle-end.md";
|
||||||
|
"/gitlab-pages/docs/contributors/documentation-and-releases.md";
|
||||||
|
"/gitlab-pages/docs/contributors/getting-started.md";
|
||||||
|
"/gitlab-pages/docs/contributors/philosophy.md";
|
||||||
|
"/gitlab-pages/docs/contributors/ligo_test_guide.md";
|
||||||
|
"/gitlab-pages/docs/contributors/road-map/short-term.md";
|
||||||
|
"/gitlab-pages/docs/contributors/road-map/long-term.md";
|
||||||
|
"/gitlab-pages/docs/contributors/origin.md";
|
||||||
|
"/gitlab-pages/docs/advanced/first-contract.md";
|
||||||
|
"/gitlab-pages/docs/advanced/entrypoints-contracts.md";
|
||||||
|
"/gitlab-pages/docs/advanced/timestamps-addresses.md";
|
||||||
|
"/gitlab-pages/docs/api/cli-commands.md";
|
||||||
|
"/gitlab-pages/docs/api/cheat-sheet.md";
|
||||||
|
]
|
||||||
|
|
||||||
|
let md_root = "../../gitlab-pages/docs/language-basics/"
|
||||||
|
let main = test_suite "Markdown files"
|
||||||
|
(List.map (fun md_file ->
|
||||||
|
let test_name = "File : \"."^md_file^"\"" in
|
||||||
|
let md_path = "../.."^md_file in
|
||||||
|
test test_name (compile md_path))
|
||||||
|
md_files)
|
Loading…
Reference in New Issue
Block a user