Merge branch 'feature/coverage-tool' into 'dev'
Use bisect for code coverage See merge request ligolang/ligo!245
This commit is contained in:
commit
f946a14ca0
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@ Version.ml
|
||||
**/.DS_Store
|
||||
.vscode/
|
||||
/ligo.install
|
||||
*.coverage
|
||||
/_coverage/
|
||||
/_coverage_*/
|
||||
|
@ -85,6 +85,10 @@ local-dune-job:
|
||||
- scripts/install_vendors_deps.sh
|
||||
- scripts/build_ligo_local.sh
|
||||
- dune runtest
|
||||
- make coverage
|
||||
artifacts:
|
||||
paths:
|
||||
- _coverage_all
|
||||
|
||||
# Run a docker build without publishing to the registry
|
||||
build-current-docker-image:
|
||||
|
24
Makefile
24
Makefile
@ -30,3 +30,27 @@ test: build
|
||||
export PATH="/usr/local/bin$${PATH:+:}$${PATH:-}"
|
||||
eval $$(opam config env)
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```
|
||||
```pascaligo group=a
|
||||
type parameter is unit;
|
||||
type store is unit;
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```
|
||||
```pascaligo group=b
|
||||
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
||||
block {
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```
|
||||
```pascaligo group=c
|
||||
const owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
||||
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
|
||||
block {
|
||||
@ -79,7 +79,7 @@ In our case, we have a `counter.ligo` contract that accepts a parameter of type
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```
|
||||
```pascaligo group=dup
|
||||
// counter.types.ligo
|
||||
type action is
|
||||
| Increment of int
|
||||
@ -87,7 +87,7 @@ type action is
|
||||
| Reset of unit
|
||||
```
|
||||
|
||||
```
|
||||
```pascaligo group=d
|
||||
// counter.ligo
|
||||
type action is
|
||||
| Increment of int
|
||||
@ -95,7 +95,7 @@ type action is
|
||||
| Reset of unit
|
||||
```
|
||||
|
||||
```
|
||||
```pascaligo gorup=d
|
||||
// proxy.ligo
|
||||
#include "counter.types.ligo"
|
||||
|
||||
|
@ -14,7 +14,7 @@ You can obtain the current time using the built-in syntax specific expression, p
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const today: timestamp = now;
|
||||
```
|
||||
<!--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
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
const today: timestamp = now;
|
||||
const one_day: int = 86400;
|
||||
const in_24_hrs: timestamp = today + one_day;
|
||||
@ -36,10 +36,10 @@ const in_24_hrs: timestamp = today + one_day;
|
||||
#### 24 hours ago
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const today: timestamp = now;
|
||||
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-->
|
||||
|
||||
@ -49,7 +49,7 @@ You can also compare timestamps using the same comparison operators as for numbe
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const not_tommorow: bool = (now = in_24_hrs)
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -62,7 +62,7 @@ Here's how you can define an address:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=d
|
||||
const my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
@ -11,18 +11,18 @@ Here's how to define a boolean:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const a: bool = True;
|
||||
const b: bool = False;
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let a: bool = true
|
||||
let b: bool = false
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
let a: bool = true;
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
const a: string = "Alice";
|
||||
const b: string = "Alice";
|
||||
// True
|
||||
const c: bool = (a = b);
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=b
|
||||
let a: string = "Alice"
|
||||
let b: string = "Alice"
|
||||
// true
|
||||
let c: bool = (a = b)
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=b
|
||||
let a: string = "Alice";
|
||||
let b: string = "Alice";
|
||||
/* true */
|
||||
(* true *)
|
||||
let c: bool = (a == b);
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -64,7 +64,7 @@ let c: bool = (a == b);
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const a: int = 5;
|
||||
const b: int = 4;
|
||||
const c: bool = (a = b);
|
||||
@ -75,7 +75,7 @@ const g: bool = (a >= b);
|
||||
const h: bool = (a =/= b);
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=c
|
||||
let a: int = 5
|
||||
let b: int = 4
|
||||
let c: bool = (a = b)
|
||||
@ -83,11 +83,11 @@ let d: bool = (a > b)
|
||||
let e: bool = (a < b)
|
||||
let f: bool = (a <= b)
|
||||
let g: bool = (a >= b)
|
||||
let h: bool = (a =/= b)
|
||||
let h: bool = (a <> b)
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=c
|
||||
let a: int = 5;
|
||||
let b: int = 4;
|
||||
let c: bool = (a == b);
|
||||
@ -106,23 +106,23 @@ let h: bool = (a != b);
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=d
|
||||
const a: tez = 5mutez;
|
||||
const b: tez = 10mutez;
|
||||
const c: bool = (a = b);
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=d
|
||||
let a: tez = 5mutez
|
||||
let b: tez = 10mutez
|
||||
// false
|
||||
let c: bool = (a = b)
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=d
|
||||
let a: tez = 5mutez;
|
||||
let b: tez = 10mutez;
|
||||
/* false */
|
||||
(* false *)
|
||||
let c: bool = (a == b);
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -136,7 +136,7 @@ Conditional logic is an important part of every real world program.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=e
|
||||
const min_age: nat = 16n;
|
||||
|
||||
(*
|
||||
@ -162,7 +162,7 @@ function is_adult(const age: nat): bool is
|
||||
> ```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=e
|
||||
let min_age: nat = 16n
|
||||
|
||||
(**
|
||||
@ -177,17 +177,17 @@ let is_adult (age: nat) : bool =
|
||||
if (age > min_age) then true else false
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=e
|
||||
let min_age: nat = 16n;
|
||||
|
||||
/**
|
||||
(**
|
||||
|
||||
This function is really obnoxious, but it showcases
|
||||
how the if statement and it's syntax can be used.
|
||||
|
||||
Normally, you'd use `with (age > min_age)` instead.
|
||||
|
||||
*/
|
||||
*)
|
||||
|
||||
let is_adult = (age: nat): bool =>
|
||||
if (age > min_age) {
|
||||
|
@ -13,7 +13,7 @@ Each `block` needs to include at least one `instruction`, or a *placeholder* ins
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
|
||||
```pascaligo
|
||||
```pascaligo skip
|
||||
// shorthand syntax
|
||||
block { skip }
|
||||
// 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`:
|
||||
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
function add(const a: int; const b: int): int is
|
||||
begin
|
||||
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`.
|
||||
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
|
||||
```
|
||||
|
||||
@ -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:
|
||||
|
||||
```cameligo
|
||||
```cameligo group=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:
|
||||
|
||||
```reasonligo
|
||||
```reasonligo group=b
|
||||
let add = (a: int, b: int) : int => a + b;
|
||||
```
|
||||
|
||||
@ -90,7 +90,7 @@ value.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
||||
// a = 2
|
||||
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.
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
||||
// a = 2
|
||||
const a: int = increment(1);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=c
|
||||
let increment : (int -> int) = fun (i: int) -> i + 1
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=c
|
||||
let increment: (int => int) = (i: int) => i + 1;
|
||||
```
|
||||
|
||||
|
@ -135,21 +135,21 @@ otherwise.
|
||||
function iter_op (const m : ledger) : 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) ;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
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
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
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);
|
||||
};
|
||||
```
|
||||
@ -162,21 +162,21 @@ let iter_op = (m: ledger): unit => {
|
||||
```pascaligo
|
||||
function map_op (const m : ledger) : ledger is
|
||||
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) ;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
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
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
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);
|
||||
};
|
||||
```
|
||||
@ -196,22 +196,22 @@ It eventually returns the result of combining all the elements.
|
||||
```pascaligo
|
||||
function fold_op (const m : ledger) : tez is
|
||||
block {
|
||||
function aggregate (const i : address ; const j : (tez * tez)) : tez is block { skip } with j.0 + j.1 ;
|
||||
} with map_fold(aggregate, m , 10)
|
||||
function aggregate (const j : tez ; const cur : (address * tez)) : tez is j + cur.1 ;
|
||||
} with map_fold(aggregate, m , 10mutez)
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let fold_op (m : ledger) : ledger =
|
||||
let aggregate = fun (ignore: address) (j: tez * tez) -> j.0 + j.1
|
||||
in Map.fold aggregate m 10
|
||||
let aggregate = fun (j: tez) (cur: address * tez) -> j + cur.1 in
|
||||
Map.fold aggregate m 10tz
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let fold_op = (m: ledger): ledger => {
|
||||
let aggregate = (ignore: address, j: (tez, tez)) => j[0] + j[1];
|
||||
Map.fold(aggregate, m, 10);
|
||||
let aggregate = (j: tez, cur: (address, tez)) => j + cur[1];
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
// int + int produces int
|
||||
const a: int = 5 + 10;
|
||||
// nat + int produces int
|
||||
@ -38,7 +38,7 @@ const g: int = 1_000_000;
|
||||
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
// int + int produces int
|
||||
let a: int = 5 + 10
|
||||
// nat + int produces int
|
||||
@ -62,19 +62,19 @@ let g: int = 1_000_000
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
```reasonligo
|
||||
/* int + int produces int */
|
||||
```reasonligo group=a
|
||||
(* int + int produces int *)
|
||||
let a: int = 5 + 10;
|
||||
/* nat + int produces int */
|
||||
(* nat + int produces int *)
|
||||
let b: int = 5n + 10;
|
||||
/* tez + tez produces tez */
|
||||
(* tez + tez produces tez *)
|
||||
let c: tez = 5mutez + 10mutez;
|
||||
/* you can't add tez + int or tez + nat, this won't compile */
|
||||
/* let d: tez = 5mutez + 10n; */
|
||||
/* two nats produce a nat */
|
||||
(* you can't add tez + int or tez + nat, this won't compile:
|
||||
let d: tez = 5mutez + 10n; *)
|
||||
(* two nats produce a nat *)
|
||||
let e: nat = 5n + 10n;
|
||||
/* nat + int produces an int, this won't compile */
|
||||
/* let f: nat = 5n + 10; */
|
||||
(* nat + int produces an int, this won't compile:
|
||||
let f: nat = 5n + 10; *)
|
||||
let g: int = 1_000_000;
|
||||
```
|
||||
|
||||
@ -94,33 +94,33 @@ The simpliest substraction looks like this:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
const a: int = 5 - 10;
|
||||
// substraction of two nats, yields an int
|
||||
const b: int = 5n - 2n;
|
||||
// won't compile, result is an int, not a nat
|
||||
// const c: nat = 5n - 2n;
|
||||
const d: tez = 5mutez - 1mt;
|
||||
const d: tez = 5mutez - 1mutez;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=b
|
||||
let a: int = 5 - 10
|
||||
// substraction of two nats, yields an int
|
||||
let b: int = 5n - 2n
|
||||
// won't compile, result is an int, not a nat
|
||||
// const c: nat = 5n - 2n
|
||||
let d: tez = 5mutez - 1mt
|
||||
let d: tez = 5mutez - 1mutez
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=b
|
||||
let a: int = 5 - 10;
|
||||
/* substraction of two nats, yields an int */
|
||||
(* substraction of two nats, yields an int *)
|
||||
let b: int = 5n - 2n;
|
||||
/* won't compile, result is an int, not a nat */
|
||||
/* let c: nat = 5n - 2n; */
|
||||
let d: tez = 5mutez - 1mt;
|
||||
(* won't compile, result is an int, not a nat *)
|
||||
(* let c: nat = 5n - 2n; *)
|
||||
let d: tez = 5mutez - 1mutez;
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -133,7 +133,7 @@ You can multiply values of the same type, such as:
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const a: int = 5 * 5;
|
||||
const b: nat = 5n * 5n;
|
||||
// you can also multiply `nat` and `tez`
|
||||
@ -141,7 +141,7 @@ const c: tez = 5n * 5mutez;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=c
|
||||
let a: int = 5 * 5
|
||||
let b: nat = 5n * 5n
|
||||
// you can also multiply `nat` and `tez`
|
||||
@ -149,10 +149,10 @@ let c: tez = 5n * 5mutez
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=c
|
||||
let a: int = 5 * 5;
|
||||
let b: nat = 5n * 5n;
|
||||
/* you can also multiply `nat` and `tez` */
|
||||
(* you can also multiply `nat` and `tez` *)
|
||||
let c: tez = 5n * 5mutez;
|
||||
```
|
||||
|
||||
@ -167,21 +167,21 @@ In LIGO you can divide `int`, `nat`, and `tez`. Here's how:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=d
|
||||
const a: int = 10 / 3;
|
||||
const b: nat = 10n / 3n;
|
||||
const c: nat = 10mutez / 3mutez;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=d
|
||||
let a: int = 10 / 3
|
||||
let b: nat = 10n / 3n
|
||||
let c: nat = 10mutez / 3mutez
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=d
|
||||
let a: int = 10 / 3;
|
||||
let b: nat = 10n / 3n;
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=e
|
||||
const a: int = int(1n);
|
||||
const b: nat = abs(1);
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=e
|
||||
let a: int = int(1n);
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
type int_set is set(int);
|
||||
const my_set: int_set = set
|
||||
1;
|
||||
@ -25,14 +25,14 @@ end
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
type int_set = int set
|
||||
let my_set: int_set =
|
||||
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
type int_set = set(int);
|
||||
let my_set: int_set =
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const my_set: int_set = set end;
|
||||
const my_set_2: int_set = set_empty;
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let my_set: int_set = (Set.empty: int set)
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
let my_set: int_set = (Set.empty: set(int));
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -62,18 +62,18 @@ let my_set: int_set = (Set.empty: set(int));
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const contains_three: bool = my_set contains 3;
|
||||
// or alternatively
|
||||
const contains_three_fn: bool = set_mem(3, my_set);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let contains_three: bool = Set.mem 3 my_set
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
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
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const set_size: nat = size(my_set);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let set_size: nat = Set.size my_set
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
let set_size: nat = Set.size(my_set);
|
||||
```
|
||||
|
||||
@ -103,21 +103,21 @@ let set_size: nat = Set.size(my_set);
|
||||
### Modifying a set
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
const larger_set: int_set = set_add(4, my_set);
|
||||
const smaller_set: int_set = set_remove(3, my_set);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let larger_set: int_set = Set.add 4 my_set
|
||||
let smaller_set: int_set = Set.remove 3 my_set
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
let larger_set: int_set = Set.add(4, 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
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
function sum(const result: int; const i: int): int is result + i;
|
||||
// Outputs 6
|
||||
const sum_of_a_set: int = set_fold(sum, my_set, 0);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=a
|
||||
let sum (result: int) (i: int) : int = result + i
|
||||
let sum_of_a_set: int = Set.fold sum my_set 0
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=a
|
||||
let sum = (result: int, i: int): int => result + i;
|
||||
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-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
type int_list is list(int);
|
||||
const my_list: int_list = list
|
||||
1;
|
||||
@ -167,13 +167,13 @@ end
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=b
|
||||
type int_list = int list
|
||||
let my_list: int_list = [1; 2; 3]
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=b
|
||||
type int_list = list(int);
|
||||
let my_list: int_list = [1, 2, 3];
|
||||
```
|
||||
@ -185,21 +185,21 @@ let my_list: int_list = [1, 2, 3];
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
const larger_list: int_list = cons(4, my_list);
|
||||
const even_larger_list: int_list = 5 # larger_list;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=b
|
||||
let larger_list: int_list = 4 :: my_list
|
||||
(* CameLIGO doesn't have a List.cons *)
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=b
|
||||
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-->
|
||||
@ -211,7 +211,7 @@ let larger_list: int_list = [4, ...my_list];
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
function increment(const i: int): int is block { skip } with i + 1;
|
||||
// Creates a new list with elements incremented by 1
|
||||
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 group=b
|
||||
let increment (i: int) : int = i + 1
|
||||
(* Creates a new list with elements incremented by 1 *)
|
||||
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 group=b
|
||||
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);
|
||||
```
|
||||
|
||||
@ -240,7 +240,7 @@ let incremented_list: int_list = List.map(increment, larger_list);
|
||||
### Folding of a list:
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
function sum(const result: int; const i: int): int is block { skip } with result + i;
|
||||
// Outputs 6
|
||||
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 group=b
|
||||
let sum (result: int) (i: int) : int = result + i
|
||||
// Outputs 6
|
||||
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 group=b
|
||||
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);
|
||||
```
|
||||
|
||||
@ -287,22 +287,22 @@ sake of illustration.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
type full_name is string * string;
|
||||
const full_name: full_name = ("Alice", "Johnson");
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=c
|
||||
type full_name = string * string
|
||||
(* The parenthesis here are optional *)
|
||||
let full_name: full_name = ("Alice", "Johnson")
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=c
|
||||
type full_name = (string, string);
|
||||
/* The parenthesis here are optional */
|
||||
(* The parenthesis here are optional *)
|
||||
let full_name: full_name = ("Alice", "Johnson");
|
||||
```
|
||||
|
||||
@ -320,17 +320,17 @@ Tuple elements are one-indexed and accessed like so:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
const first_name: string = full_name.1;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
```cameligo group=c
|
||||
let first_name: string = full_name.1
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
```reasonligo group=c
|
||||
let first_name: string = full_name[1];
|
||||
```
|
||||
|
||||
|
@ -59,12 +59,12 @@ let ledger: account_balances = Map.literal
|
||||
|
||||
<!--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);
|
||||
|
||||
let ledger: account_balances =
|
||||
Map.literal([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, 10mutez),
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, 10mutez)
|
||||
]);
|
||||
```
|
||||
|
||||
@ -124,25 +124,23 @@ let ledger: account_balances = Map.literal
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
/* alias two types */
|
||||
(* alias two types *)
|
||||
type account = address;
|
||||
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 = {
|
||||
balance: tez,
|
||||
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);
|
||||
|
||||
/* pseudo-JSON representation of our map */
|
||||
/* {"tz1...": {balance: 10mutez, number_of_transactions: 5n}} */
|
||||
(* pseudo-JSON representation of our map
|
||||
{"tz1...": {balance: 10mutez, number_of_transactions: 5n}} *)
|
||||
let ledger: account_balances =
|
||||
Map.literal([
|
||||
(
|
||||
"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address,
|
||||
{balance: 10mutez, number_of_transactions: 5n},
|
||||
),
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address,
|
||||
{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
|
||||
|
||||
### **`taco-shop.ligo`**
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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
|
||||
// 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
|
||||
// Decrease the stock by 1n, because we've just sold one
|
||||
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
|
||||
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;
|
||||
```
|
||||
|
||||
@ -67,8 +67,8 @@ This means that after all the *purchase conditions* of our contract are met - e.
|
||||
### 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.
|
||||
|
||||
```pascaligo
|
||||
const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
|
||||
```pascaligo group=ex1
|
||||
const ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
|
||||
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.
|
||||
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=ex1
|
||||
const payoutOperation : operation = transaction(unit, amount, receiver) ;
|
||||
const operations : list(operation) = list
|
||||
payoutOperation
|
||||
@ -90,14 +90,14 @@ end;
|
||||
## Finalizing the contract
|
||||
|
||||
### **`taco-shop.ligo`**
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
max_price : tez;
|
||||
end
|
||||
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
|
||||
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
|
||||
// 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
|
||||
// Decrease the stock by 1n, because we've just sold one
|
||||
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.
|
||||
|
||||
```pascaligo
|
||||
```pascaligo skip
|
||||
ligo dry-run taco-shop.ligo --syntax pascaligo --amount 1 buy_taco 1n "map
|
||||
1n -> record
|
||||
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.
|
||||
|
||||
```pascaligo
|
||||
const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
|
||||
const donationAddress: address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
|
||||
```pascaligo group=bonus
|
||||
const ownerAddress: address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
|
||||
const donationAddress: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
|
||||
```
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=bonus
|
||||
const receiver : contract(unit) = get_contract(ownerAddress);
|
||||
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:
|
||||
|
||||
```pascaligo
|
||||
```pascaligo skip
|
||||
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.
|
||||
|
||||
### `taco-shop.ligo`
|
||||
```pascaligo
|
||||
```pascaligo group=a
|
||||
function main (const parameter: int; const contractStorage: int) : (list(operation) * int) is
|
||||
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.
|
||||
|
||||
**Taco shop's storage**
|
||||
```pascaligo
|
||||
```pascaligo group=b
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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.
|
||||
|
||||
**`taco-shop.ligo`**
|
||||
```pascaligo
|
||||
```pascaligo group=b+
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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
|
||||
|
||||
**`taco-shop.ligo`**
|
||||
```pascaligo
|
||||
```pascaligo group=c
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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`**
|
||||
|
||||
```pascaligo
|
||||
```pascaligo group=d
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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
|
||||
|
||||
**`taco-shop.ligo`**
|
||||
```pascaligo
|
||||
```pascaligo group=e
|
||||
type taco_supply is record
|
||||
current_stock : nat;
|
||||
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
|
||||
// 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
|
||||
// Decrease the stock by 1n, because we've just sold one
|
||||
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||
@ -324,14 +324,14 @@ end"
|
||||
|
||||
## 💰 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**
|
||||
```pascaligo
|
||||
```pascaligo skip
|
||||
if amount =/= current_purchase_price then
|
||||
```
|
||||
|
||||
**With tips**
|
||||
```pascaligo
|
||||
```pascaligo skip
|
||||
if amount >= current_purchase_price then
|
||||
```
|
||||
|
@ -11,6 +11,7 @@ depends: [
|
||||
"ocamlfind" { build }
|
||||
"dune" { build & = "1.11.4" }
|
||||
"menhir" { = "20190626" }
|
||||
"bisect_ppx" {dev & >= "2.0.0"}
|
||||
"ppx_let"
|
||||
"ppx_deriving"
|
||||
"ppx_expect"
|
||||
@ -20,7 +21,10 @@ depends: [
|
||||
"alcotest" { with-test }
|
||||
"getopt"
|
||||
# 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: [
|
||||
[ "dune" "build" "-p" name "-j" jobs ]
|
||||
|
@ -7,7 +7,7 @@
|
||||
)
|
||||
(modules cli cli_helpers version)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils))
|
||||
)
|
||||
@ -31,7 +31,7 @@
|
||||
(modules runligo)
|
||||
(package ligo)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils))
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
(library
|
||||
(name cli_expect_tests)
|
||||
(libraries simple-utils cli)
|
||||
(inline_tests)
|
||||
(inline_tests (deps (source_tree ../../test/contracts)))
|
||||
(preprocess (pps ppx_let ppx_expect))
|
||||
(flags (:standard -open Simple_utils)))
|
||||
|
2
src/dune
2
src/dune
@ -9,6 +9,6 @@
|
||||
main
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
)
|
||||
|
@ -18,7 +18,7 @@
|
||||
self_michelson
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -68,15 +68,6 @@ let parsify_reasonligo = fun source ->
|
||||
Simplify.Cameligo.simpl_program raw in
|
||||
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%bind raw =
|
||||
trace (simple_error "parsing expression") @@
|
||||
@ -105,3 +96,40 @@ let parsify_expression = fun syntax source ->
|
||||
let%bind parsified = parsify source in
|
||||
let%bind applied = Self_ast_simplified.all_expression parsified in
|
||||
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
|
||||
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 =
|
||||
fun syntax exp ->
|
||||
parsify_expression syntax exp
|
||||
|
@ -7,7 +7,7 @@
|
||||
uncompile
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -17,7 +17,7 @@
|
||||
compile
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -11,7 +11,7 @@
|
||||
transpiler
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
[@@@warning "-42"]
|
||||
[@@@coverage exclude_file]
|
||||
|
||||
open AST
|
||||
open! Region
|
||||
|
@ -15,8 +15,11 @@
|
||||
str
|
||||
simple-utils
|
||||
tezos-utils
|
||||
getopt)
|
||||
(flags (:standard -open Simple_utils -open Parser_shared )))
|
||||
getopt )
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional) )
|
||||
(flags (:standard -open Simple_utils -open Parser_shared ))
|
||||
)
|
||||
|
||||
(executable
|
||||
(name LexerMain)
|
||||
@ -24,6 +27,8 @@
|
||||
parser_cameligo)
|
||||
(modules
|
||||
LexerMain)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(flags (:standard -open Parser_shared -open Parser_cameligo)))
|
||||
|
||||
(executable
|
||||
@ -33,4 +38,6 @@
|
||||
(modules
|
||||
ParserAPI
|
||||
ParserMain)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
|
||||
|
@ -10,7 +10,7 @@
|
||||
parser_reasonligo
|
||||
)
|
||||
(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))
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
[@@@warning "-42"]
|
||||
[@@@coverage exclude_file]
|
||||
|
||||
open AST
|
||||
open! Region
|
||||
|
@ -10,12 +10,16 @@
|
||||
(public_name ligo.parser.pascaligo)
|
||||
(modules AST pascaligo Parser ParserLog LexToken)
|
||||
(libraries
|
||||
menhirLib
|
||||
parser_shared
|
||||
hex
|
||||
simple-utils
|
||||
tezos-utils)
|
||||
(flags (:standard -open Parser_shared -open Simple_utils)))
|
||||
menhirLib
|
||||
parser_shared
|
||||
hex
|
||||
simple-utils
|
||||
tezos-utils
|
||||
)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(flags (:standard -open Parser_shared -open Simple_utils))
|
||||
)
|
||||
|
||||
(executable
|
||||
(name LexerMain)
|
||||
@ -25,18 +29,25 @@
|
||||
tezos-utils
|
||||
parser_pascaligo)
|
||||
(modules
|
||||
LexerMain)
|
||||
(flags (:standard -open Parser_shared -open Parser_pascaligo)))
|
||||
LexerMain)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(flags (:standard -open Parser_shared -open Parser_pascaligo))
|
||||
)
|
||||
|
||||
(executable
|
||||
(name ParserMain)
|
||||
(libraries
|
||||
parser_pascaligo)
|
||||
(modules ParserMain)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo)))
|
||||
|
||||
(executable
|
||||
(name Unlexer)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional))
|
||||
(modules Unlexer))
|
||||
|
||||
;; Les deux directives (rule) qui suivent sont pour le dev local.
|
||||
|
@ -16,16 +16,25 @@
|
||||
str
|
||||
simple-utils
|
||||
tezos-utils
|
||||
getopt)
|
||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
|
||||
getopt
|
||||
)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo ))
|
||||
)
|
||||
|
||||
(executable
|
||||
(name LexerMain)
|
||||
(libraries
|
||||
parser_reasonligo)
|
||||
(modules
|
||||
(modules
|
||||
LexerMain)
|
||||
(flags (:standard -open Parser_shared -open Parser_reasonligo)))
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Parser_shared -open Parser_reasonligo))
|
||||
)
|
||||
|
||||
(executable
|
||||
(name ParserMain)
|
||||
@ -35,4 +44,7 @@
|
||||
(modules
|
||||
ParserAPI
|
||||
ParserMain)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo)))
|
||||
|
@ -7,7 +7,11 @@
|
||||
simple-utils
|
||||
uutf
|
||||
getopt
|
||||
zarith)
|
||||
zarith
|
||||
)
|
||||
(preprocess
|
||||
(pps bisect_ppx --conditional)
|
||||
)
|
||||
(modules
|
||||
Lexer
|
||||
LexerLog
|
||||
|
@ -12,6 +12,7 @@
|
||||
(preprocess
|
||||
(pps
|
||||
ppx_let
|
||||
bisect_ppx --conditional
|
||||
)
|
||||
)
|
||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||
|
@ -6,7 +6,7 @@
|
||||
ast_simplified
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -11,7 +11,7 @@
|
||||
operators
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -10,7 +10,7 @@
|
||||
operators
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -6,7 +6,7 @@
|
||||
)
|
||||
(inline_tests)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -9,7 +9,7 @@
|
||||
operators
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -6,7 +6,7 @@
|
||||
tezos-utils
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -9,7 +9,7 @@
|
||||
mini_c
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils ))
|
||||
)
|
||||
|
@ -243,6 +243,7 @@ module Simplify = struct
|
||||
| "AND" -> ok C_AND
|
||||
| "OR" -> ok C_OR
|
||||
| "GT" -> ok C_GT
|
||||
| "GE" -> ok C_GE
|
||||
| "LT" -> ok C_LT
|
||||
| "LE" -> ok C_LE
|
||||
| "CONS" -> ok C_CONS
|
||||
|
@ -1,3 +1,4 @@
|
||||
[@@@coverage exclude_file]
|
||||
open Types
|
||||
open PP_helpers
|
||||
open Format
|
||||
|
@ -7,7 +7,7 @@
|
||||
stage_common
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils ))
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
[@@@coverage exclude_file]
|
||||
open Types
|
||||
open Format
|
||||
open PP_helpers
|
||||
|
@ -8,7 +8,7 @@
|
||||
stage_common
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let)
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils))
|
||||
)
|
||||
|
@ -7,7 +7,7 @@
|
||||
)
|
||||
(inline_tests)
|
||||
(preprocess
|
||||
(pps ppx_let ppx_expect)
|
||||
(pps ppx_let ppx_expect bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -open Simple_utils))
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
[@@@coverage exclude_file]
|
||||
open Simple_utils.PP_helpers
|
||||
open Types
|
||||
open Format
|
||||
|
@ -7,6 +7,6 @@
|
||||
stage_common
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
@ -8,7 +8,7 @@
|
||||
mini_c
|
||||
)
|
||||
(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 ))
|
||||
)
|
||||
|
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
|
||||
(names test manual_test)
|
||||
(names test manual_test doc_test)
|
||||
(libraries
|
||||
simple-utils
|
||||
ligo
|
||||
@ -12,6 +14,12 @@
|
||||
(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
|
||||
(name ligo-test)
|
||||
(action (run ./test.exe))
|
||||
@ -21,7 +29,7 @@
|
||||
|
||||
(alias
|
||||
(name runtest)
|
||||
(deps (alias ligo-test))
|
||||
(deps (alias ligo-test) (alias doc-test))
|
||||
)
|
||||
|
||||
(alias
|
||||
|
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")
|
||||
}
|
120
src/test/md_file_tests.ml
Normal file
120
src/test/md_file_tests.ml
Normal file
@ -0,0 +1,120 @@
|
||||
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/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