diff --git a/.gitignore b/.gitignore index fb756e969..d2d2464e1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ Version.ml **/.DS_Store .vscode/ /ligo.install +*.coverage +/_coverage/ +/_coverage_*/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa78f2b42..9148103df 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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: diff --git a/Makefile b/Makefile index 40204f5c8..4ad94ebdc 100644 --- a/Makefile +++ b/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 diff --git a/gitlab-pages/docs/advanced/entrypoints-contracts.md b/gitlab-pages/docs/advanced/entrypoints-contracts.md index 50b24d333..7b8e901b4 100644 --- a/gitlab-pages/docs/advanced/entrypoints-contracts.md +++ b/gitlab-pages/docs/advanced/entrypoints-contracts.md @@ -20,7 +20,7 @@ This means that every smart contract needs at least one entrypoint function, her -``` +```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 -``` +```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 -``` +```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 -``` +```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" diff --git a/gitlab-pages/docs/advanced/timestamps-addresses.md b/gitlab-pages/docs/advanced/timestamps-addresses.md index 638942458..b3f1d2a0a 100644 --- a/gitlab-pages/docs/advanced/timestamps-addresses.md +++ b/gitlab-pages/docs/advanced/timestamps-addresses.md @@ -14,7 +14,7 @@ You can obtain the current time using the built-in syntax specific expression, p -```pascaligo +```pascaligo group=a const today: timestamp = now; ``` @@ -26,7 +26,7 @@ In LIGO, timestamps can be added with `int`(s), this enables you to set e.g. tim #### In 24 hours -```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 -```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; ``` @@ -49,7 +49,7 @@ You can also compare timestamps using the same comparison operators as for numbe -```pascaligo +```pascaligo group=c const not_tommorow: bool = (now = in_24_hrs) ``` @@ -62,7 +62,7 @@ Here's how you can define an address: -```pascaligo +```pascaligo group=d const my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address); ``` diff --git a/gitlab-pages/docs/language-basics/boolean-if-else.md b/gitlab-pages/docs/language-basics/boolean-if-else.md index 751f4f1cd..d57e6fa99 100644 --- a/gitlab-pages/docs/language-basics/boolean-if-else.md +++ b/gitlab-pages/docs/language-basics/boolean-if-else.md @@ -11,18 +11,18 @@ Here's how to define a boolean: -```pascaligo +```pascaligo group=a const a: bool = True; const b: bool = False; ``` -```cameligo +```cameligo group=a let a: bool = true let b: bool = false ``` -```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 -```pascaligo +```pascaligo group=b const a: string = "Alice"; const b: string = "Alice"; // True const c: bool = (a = b); ``` -```cameligo +```cameligo group=b let a: string = "Alice" let b: string = "Alice" // true let c: bool = (a = b) ``` -```reasonligo +```reasonligo group=b let a: string = "Alice"; let b: string = "Alice"; -/* true */ +(* true *) let c: bool = (a == b); ``` @@ -64,7 +64,7 @@ let c: bool = (a == b); -```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 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 group=c let a: int = 5; let b: int = 4; let c: bool = (a == b); @@ -106,23 +106,23 @@ let h: bool = (a != b); -```pascaligo +```pascaligo group=d const a: tez = 5mutez; const b: tez = 10mutez; const c: bool = (a = b); ``` -```cameligo +```cameligo group=d let a: tez = 5mutez let b: tez = 10mutez // false let c: bool = (a = b) ``` -```reasonligo +```reasonligo group=d let a: tez = 5mutez; let b: tez = 10mutez; -/* false */ +(* false *) let c: bool = (a == b); ``` @@ -136,7 +136,7 @@ Conditional logic is an important part of every real world program. -```pascaligo +```pascaligo group=e const min_age: nat = 16n; (* @@ -162,7 +162,7 @@ function is_adult(const age: nat): bool is > ``` -```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 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) { diff --git a/gitlab-pages/docs/language-basics/functions.md b/gitlab-pages/docs/language-basics/functions.md index 59baf3b37..e5ac6eb08 100644 --- a/gitlab-pages/docs/language-basics/functions.md +++ b/gitlab-pages/docs/language-basics/functions.md @@ -13,7 +13,7 @@ Each `block` needs to include at least one `instruction`, or a *placeholder* ins -```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. -```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. -```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 group=c let increment : (int -> int) = fun (i: int) -> i + 1 ``` -```reasonligo +```reasonligo group=c let increment: (int => int) = (i: int) => i + 1; ``` diff --git a/gitlab-pages/docs/language-basics/maps-records.md b/gitlab-pages/docs/language-basics/maps-records.md index 5187f82d0..e56160d3f 100644 --- a/gitlab-pages/docs/language-basics/maps-records.md +++ b/gitlab-pages/docs/language-basics/maps-records.md @@ -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 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 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 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 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 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 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); }; ``` diff --git a/gitlab-pages/docs/language-basics/math-numbers-tez.md b/gitlab-pages/docs/language-basics/math-numbers-tez.md index 77db6bef3..1609679e8 100644 --- a/gitlab-pages/docs/language-basics/math-numbers-tez.md +++ b/gitlab-pages/docs/language-basics/math-numbers-tez.md @@ -14,7 +14,7 @@ In the following example you can find a series of arithmetic operations, includi -```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 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 -/* 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: -```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 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 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; ``` @@ -133,7 +133,7 @@ You can multiply values of the same type, such as: -```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 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 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: -```pascaligo +```pascaligo group=d const a: int = 10 / 3; const b: nat = 10n / 3n; const c: nat = 10mutez / 3mutez; ``` -```cameligo +```cameligo group=d let a: int = 10 / 3 let b: nat = 10n / 3n let c: nat = 10mutez / 3mutez ``` -```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: -```pascaligo +```pascaligo group=e const a: int = int(1n); const b: nat = abs(1); ``` -```reasonligo +```reasonligo group=e let a: int = int(1n); let b: nat = abs(1); ``` diff --git a/gitlab-pages/docs/language-basics/sets-lists-touples.md b/gitlab-pages/docs/language-basics/sets-lists-touples.md index c11fa1363..88b57518a 100644 --- a/gitlab-pages/docs/language-basics/sets-lists-touples.md +++ b/gitlab-pages/docs/language-basics/sets-lists-touples.md @@ -15,7 +15,7 @@ Sets are similar to lists. The main difference is that elements of a `set` must -```pascaligo +```pascaligo group=a type int_set is set(int); const my_set: int_set = set 1; @@ -25,14 +25,14 @@ end ``` -```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 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 = -```pascaligo +```pascaligo group=a const my_set: int_set = set end; const my_set_2: int_set = set_empty; ``` -```cameligo +```cameligo group=a let my_set: int_set = (Set.empty: int set) ``` -```reasonligo +```reasonligo group=a let my_set: int_set = (Set.empty: set(int)); ``` @@ -62,18 +62,18 @@ let my_set: int_set = (Set.empty: set(int)); -```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 group=a let contains_three: bool = Set.mem 3 my_set ``` -```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 -```pascaligo +```pascaligo group=a const set_size: nat = size(my_set); ``` -```cameligo +```cameligo group=a let set_size: nat = Set.size my_set ``` -```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 -```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 group=a let larger_set: int_set = Set.add 4 my_set let smaller_set: int_set = Set.remove 3 my_set ``` -```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 -```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 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 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 -```pascaligo +```pascaligo group=b type int_list is list(int); const my_list: int_list = list 1; @@ -167,13 +167,13 @@ end ``` -```cameligo +```cameligo group=b type int_list = int list let my_list: int_list = [1; 2; 3] ``` -```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]; -```pascaligo +```pascaligo group=b const larger_list: int_list = cons(4, my_list); const even_larger_list: int_list = 5 # larger_list; ``` -```cameligo +```cameligo group=b let larger_list: int_list = 4 :: my_list (* CameLIGO doesn't have a List.cons *) ``` -```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 *) ``` @@ -211,7 +211,7 @@ let larger_list: int_list = [4, ...my_list]; -```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 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 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: -```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 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 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. -```pascaligo +```pascaligo group=c type full_name is string * string; const full_name: full_name = ("Alice", "Johnson"); ``` -```cameligo +```cameligo group=c type full_name = string * string (* The parenthesis here are optional *) let full_name: full_name = ("Alice", "Johnson") ``` -```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: -```pascaligo +```pascaligo group=c const first_name: string = full_name.1; ``` -```cameligo +```cameligo group=c let first_name: string = full_name.1 ``` -```reasonligo +```reasonligo group=c let first_name: string = full_name[1]; ``` diff --git a/gitlab-pages/docs/language-basics/types.md b/gitlab-pages/docs/language-basics/types.md index 846424d36..a2d456473 100644 --- a/gitlab-pages/docs/language-basics/types.md +++ b/gitlab-pages/docs/language-basics/types.md @@ -59,12 +59,12 @@ let ledger: account_balances = Map.literal ```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 -/* 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}) ]); ``` diff --git a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md index 9ca0346eb..ae9a1b8e3 100644 --- a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md +++ b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md @@ -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); diff --git a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-smart-contract.md b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-smart-contract.md index 5a48d0b08..e67c79506 100644 --- a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-smart-contract.md +++ b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-smart-contract.md @@ -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 ``` diff --git a/ligo.opam b/ligo.opam index 303135cdb..7b4f8c210 100644 --- a/ligo.opam +++ b/ligo.opam @@ -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 ] diff --git a/src/bin/dune b/src/bin/dune index 4546f2a6f..f0219a5f6 100644 --- a/src/bin/dune +++ b/src/bin/dune @@ -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)) ) diff --git a/src/bin/expect_tests/dune b/src/bin/expect_tests/dune index c7856e438..65504a168 100644 --- a/src/bin/expect_tests/dune +++ b/src/bin/expect_tests/dune @@ -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))) diff --git a/src/dune b/src/dune index de5be01e6..0bfd1396c 100644 --- a/src/dune +++ b/src/dune @@ -9,6 +9,6 @@ main ) (preprocess - (pps ppx_let) + (pps ppx_let bisect_ppx --conditional) ) ) diff --git a/src/main/compile/dune b/src/main/compile/dune index e13261066..90c858e1d 100644 --- a/src/main/compile/dune +++ b/src/main/compile/dune @@ -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 )) ) diff --git a/src/main/compile/helpers.ml b/src/main/compile/helpers.ml index f9706d11c..479b4cd33 100644 --- a/src/main/compile/helpers.ml +++ b/src/main/compile/helpers.ml @@ -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 diff --git a/src/main/compile/of_source.ml b/src/main/compile/of_source.ml index 2a08a229b..0c43d7d45 100644 --- a/src/main/compile/of_source.ml +++ b/src/main/compile/of_source.ml @@ -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 diff --git a/src/main/dune b/src/main/dune index e2fe18f86..802ab2af3 100644 --- a/src/main/dune +++ b/src/main/dune @@ -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 )) ) diff --git a/src/main/run/dune b/src/main/run/dune index f39c18a69..faaedeab4 100644 --- a/src/main/run/dune +++ b/src/main/run/dune @@ -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 )) ) diff --git a/src/main/uncompile/dune b/src/main/uncompile/dune index 3db4a92f0..bf039deb8 100644 --- a/src/main/uncompile/dune +++ b/src/main/uncompile/dune @@ -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 )) ) diff --git a/src/passes/1-parser/cameligo/ParserLog.ml b/src/passes/1-parser/cameligo/ParserLog.ml index 20aab4c9d..18c29a7d7 100644 --- a/src/passes/1-parser/cameligo/ParserLog.ml +++ b/src/passes/1-parser/cameligo/ParserLog.ml @@ -1,4 +1,5 @@ [@@@warning "-42"] +[@@@coverage exclude_file] open AST open! Region diff --git a/src/passes/1-parser/cameligo/dune b/src/passes/1-parser/cameligo/dune index 730290696..5604f5065 100644 --- a/src/passes/1-parser/cameligo/dune +++ b/src/passes/1-parser/cameligo/dune @@ -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))) diff --git a/src/passes/1-parser/dune b/src/passes/1-parser/dune index 8e478b392..bbf559aa0 100644 --- a/src/passes/1-parser/dune +++ b/src/passes/1-parser/dune @@ -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)) ) diff --git a/src/passes/1-parser/pascaligo/ParserLog.ml b/src/passes/1-parser/pascaligo/ParserLog.ml index 69369e7c5..dae39a4ef 100644 --- a/src/passes/1-parser/pascaligo/ParserLog.ml +++ b/src/passes/1-parser/pascaligo/ParserLog.ml @@ -1,4 +1,5 @@ [@@@warning "-42"] +[@@@coverage exclude_file] open AST open! Region diff --git a/src/passes/1-parser/pascaligo/dune b/src/passes/1-parser/pascaligo/dune index 53c2d8385..28fee7d04 100644 --- a/src/passes/1-parser/pascaligo/dune +++ b/src/passes/1-parser/pascaligo/dune @@ -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. diff --git a/src/passes/1-parser/reasonligo/dune b/src/passes/1-parser/reasonligo/dune index 8d65f1363..fc7b1d15e 100644 --- a/src/passes/1-parser/reasonligo/dune +++ b/src/passes/1-parser/reasonligo/dune @@ -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))) diff --git a/src/passes/1-parser/shared/dune b/src/passes/1-parser/shared/dune index 61c43fb28..7777459d0 100644 --- a/src/passes/1-parser/shared/dune +++ b/src/passes/1-parser/shared/dune @@ -7,7 +7,11 @@ simple-utils uutf getopt - zarith) + zarith + ) + (preprocess + (pps bisect_ppx --conditional) + ) (modules Lexer LexerLog diff --git a/src/passes/2-simplify/dune b/src/passes/2-simplify/dune index 20ec8cb9d..66ab7d4b2 100644 --- a/src/passes/2-simplify/dune +++ b/src/passes/2-simplify/dune @@ -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 )) diff --git a/src/passes/3-self_ast_simplified/dune b/src/passes/3-self_ast_simplified/dune index 39eacaf3e..69dc6b507 100644 --- a/src/passes/3-self_ast_simplified/dune +++ b/src/passes/3-self_ast_simplified/dune @@ -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 )) ) diff --git a/src/passes/4-typer/dune b/src/passes/4-typer/dune index dc6164c4f..35c5e807d 100644 --- a/src/passes/4-typer/dune +++ b/src/passes/4-typer/dune @@ -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 )) ) diff --git a/src/passes/6-transpiler/dune b/src/passes/6-transpiler/dune index a547714f0..6c3139e5e 100644 --- a/src/passes/6-transpiler/dune +++ b/src/passes/6-transpiler/dune @@ -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 )) ) diff --git a/src/passes/7-self_mini_c/dune b/src/passes/7-self_mini_c/dune index da1927e25..fed4a09a1 100644 --- a/src/passes/7-self_mini_c/dune +++ b/src/passes/7-self_mini_c/dune @@ -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 )) ) diff --git a/src/passes/8-compiler/dune b/src/passes/8-compiler/dune index 5e4412d81..89878e2fd 100644 --- a/src/passes/8-compiler/dune +++ b/src/passes/8-compiler/dune @@ -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 )) ) diff --git a/src/passes/9-self_michelson/dune b/src/passes/9-self_michelson/dune index 047fe33a4..b7387bdc1 100644 --- a/src/passes/9-self_michelson/dune +++ b/src/passes/9-self_michelson/dune @@ -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 )) ) diff --git a/src/passes/operators/dune b/src/passes/operators/dune index f2125905a..64222a117 100644 --- a/src/passes/operators/dune +++ b/src/passes/operators/dune @@ -9,7 +9,7 @@ mini_c ) (preprocess - (pps ppx_let) + (pps ppx_let bisect_ppx --conditional) ) (flags (:standard -open Simple_utils )) ) diff --git a/src/passes/operators/operators.ml b/src/passes/operators/operators.ml index 84f37f443..424032703 100644 --- a/src/passes/operators/operators.ml +++ b/src/passes/operators/operators.ml @@ -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 diff --git a/src/stages/ast_simplified/PP.ml b/src/stages/ast_simplified/PP.ml index ac7c4bafe..71ec1d6ae 100644 --- a/src/stages/ast_simplified/PP.ml +++ b/src/stages/ast_simplified/PP.ml @@ -1,3 +1,4 @@ +[@@@coverage exclude_file] open Types open PP_helpers open Format diff --git a/src/stages/ast_simplified/dune b/src/stages/ast_simplified/dune index 8d0e1651f..f6c961536 100644 --- a/src/stages/ast_simplified/dune +++ b/src/stages/ast_simplified/dune @@ -7,7 +7,7 @@ stage_common ) (preprocess - (pps ppx_let) + (pps ppx_let bisect_ppx --conditional) ) (flags (:standard -open Simple_utils )) ) diff --git a/src/stages/ast_typed/PP.ml b/src/stages/ast_typed/PP.ml index 45a4ddfec..ef0e96a39 100644 --- a/src/stages/ast_typed/PP.ml +++ b/src/stages/ast_typed/PP.ml @@ -1,3 +1,4 @@ +[@@@coverage exclude_file] open Types open Format open PP_helpers diff --git a/src/stages/ast_typed/dune b/src/stages/ast_typed/dune index 9494873a7..7eed79e47 100644 --- a/src/stages/ast_typed/dune +++ b/src/stages/ast_typed/dune @@ -8,7 +8,7 @@ stage_common ) (preprocess - (pps ppx_let) + (pps ppx_let bisect_ppx --conditional) ) (flags (:standard -open Simple_utils)) ) diff --git a/src/stages/common/dune b/src/stages/common/dune index c607b6041..0ce33599f 100644 --- a/src/stages/common/dune +++ b/src/stages/common/dune @@ -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)) ) diff --git a/src/stages/mini_c/PP.ml b/src/stages/mini_c/PP.ml index 054d88cb9..9b3e7fa3d 100644 --- a/src/stages/mini_c/PP.ml +++ b/src/stages/mini_c/PP.ml @@ -1,3 +1,4 @@ +[@@@coverage exclude_file] open Simple_utils.PP_helpers open Types open Format diff --git a/src/stages/mini_c/dune b/src/stages/mini_c/dune index 86e375fb1..827685e5e 100644 --- a/src/stages/mini_c/dune +++ b/src/stages/mini_c/dune @@ -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 )) ) diff --git a/src/stages/typesystem/dune b/src/stages/typesystem/dune index d5e1deaf6..922140cf4 100644 --- a/src/stages/typesystem/dune +++ b/src/stages/typesystem/dune @@ -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 )) ) diff --git a/src/test/doc_test.ml b/src/test/doc_test.ml new file mode 100644 index 000000000..7290c8156 --- /dev/null +++ b/src/test/doc_test.ml @@ -0,0 +1,8 @@ +open Test_helpers + +let () = + Printexc.record_backtrace true ; + run_test @@ test_suite "LIGO" [ + Md_file_tests.main ; + ] ; + () diff --git a/src/test/dune b/src/test/dune index 24a44109f..9da57c8ef 100644 --- a/src/test/dune +++ b/src/test/dune @@ -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 diff --git a/src/test/md.mll b/src/test/md.mll new file mode 100644 index 000000000..08228de9e --- /dev/null +++ b/src/test/md.mll @@ -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") +} diff --git a/src/test/md_file_tests.ml b/src/test/md_file_tests.ml new file mode 100644 index 000000000..c2e275a3d --- /dev/null +++ b/src/test/md_file_tests.ml @@ -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)