From dcfc8d6391fcf9420c751af4479a9480b765d63a Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Sun, 29 Dec 2019 01:24:22 +0000 Subject: [PATCH 01/43] Horrible hack to rewrite CST for tuple param destruct, Fails because Let In doesn't support multi-bind --- src/passes/2-simplify/cameligo.ml | 112 +++++++++++++----- src/test/contracts/tuple_param_destruct.mligo | 1 + src/test/integration_tests.ml | 6 + 3 files changed, 92 insertions(+), 27 deletions(-) create mode 100644 src/test/contracts/tuple_param_destruct.mligo diff --git a/src/passes/2-simplify/cameligo.ml b/src/passes/2-simplify/cameligo.ml index 9b047239d..762215450 100644 --- a/src/passes/2-simplify/cameligo.ml +++ b/src/passes/2-simplify/cameligo.ml @@ -10,7 +10,6 @@ module Option = Simple_utils.Option open Combinators -type 'a nseq = 'a * 'a list let nseq_to_list (hd, tl) = hd :: tl let npseq_to_list (hd, tl) = hd :: (List.map snd tl) let npseq_to_nelist (hd, tl) = hd, (List.map snd tl) @@ -23,12 +22,13 @@ module Errors = struct let wrong_pattern expected_name actual = let title () = "wrong pattern" in let message () = - match actual with - | Raw.PTuple _ -> "tuple" - | Raw.PRecord _ -> "record" - | Raw.PList _ -> "list" - | Raw.PBytes _ -> "bytes" - | _ -> "other" + match actual with + | Raw.PVar v -> v.value + | Raw.PTuple _ -> "tuple" + | Raw.PRecord _ -> "record" + | Raw.PList _ -> "list" + | Raw.PBytes _ -> "bytes" + | _ -> "other" in let data = [ ("expected", fun () -> expected_name); @@ -36,15 +36,14 @@ module Errors = struct ] in error ~data title message - let multiple_patterns construct (patterns: Raw.pattern list) = - let title () = "multiple patterns" in - let message () = - Format.asprintf "multiple patterns in \"%s\" are not supported yet" construct in + let unsuppported_let_in_function (patterns : Raw.pattern list) = + let title () = "unsupported 'let ... in' function" in + let message () = "defining functions via 'let ... in' is not supported yet" in let patterns_loc = List.fold_left (fun a p -> Region.cover a (Raw.pattern_to_region p)) Region.ghost patterns in let data = [ - ("patterns_loc", fun () -> Format.asprintf "%a" Location.pp_lift @@ patterns_loc) + ("loc", fun () -> Format.asprintf "%a" Location.pp_lift @@ patterns_loc) ] in error ~data title message @@ -154,7 +153,7 @@ let rec pattern_to_var : Raw.pattern -> _ = fun p -> | Raw.PPar p -> pattern_to_var p.value.inside | Raw.PVar v -> ok v | Raw.PWild r -> ok @@ ({ region = r ; value = "_" } : Raw.variable) - | _ -> fail @@ wrong_pattern "var" p + | _ -> fail @@ wrong_pattern "single var" p let rec pattern_to_typed_var : Raw.pattern -> _ = fun p -> match p with @@ -166,24 +165,19 @@ let rec pattern_to_typed_var : Raw.pattern -> _ = fun p -> ) | Raw.PVar v -> ok (v , None) | Raw.PWild r -> ok (({ region = r ; value = "_" } : Raw.variable) , None) - | _ -> fail @@ wrong_pattern "typed variable" p + | _ -> fail @@ wrong_pattern "single typed variable" p let rec expr_to_typed_expr : Raw.expr -> _ = function EPar e -> expr_to_typed_expr e.value.inside | EAnnot {value={inside=e,_,t; _}; _} -> ok (e, Some t) | e -> ok (e , None) -let rec patterns_to_typed_vars : Raw.pattern nseq -> _ = fun ps -> - match ps with - | pattern, [] -> - begin - match pattern with - | Raw.PPar pp -> patterns_to_typed_vars (pp.value.inside, []) - | Raw.PTuple pt -> bind_map_list pattern_to_typed_var (npseq_to_list pt.value) - | Raw.PVar _ -> bind_list [pattern_to_typed_var pattern] - | other -> (fail @@ wrong_pattern "parenthetical, tuple, or variable" other) - end - | _ -> fail @@ multiple_patterns "let" (nseq_to_list ps) +let rec tuple_pattern_to_typed_vars : Raw.pattern -> _ = fun pattern -> + match pattern with + | Raw.PPar pp -> tuple_pattern_to_typed_vars pp.value.inside + | Raw.PTuple pt -> bind_map_list pattern_to_typed_var (npseq_to_list pt.value) + | Raw.PVar _ -> bind_list [pattern_to_typed_var pattern] + | other -> (fail @@ wrong_pattern "parenthetical, tuple, or variable" other) let rec simpl_type_expression : Raw.type_expr -> type_expression result = fun te -> trace (simple_info "simplifying this type expression...") @@ @@ -274,7 +268,10 @@ let rec simpl_expression : Raw.ELetIn e -> let Raw.{binding; body; _} = e.value in let Raw.{binders; lhs_type; let_rhs; _} = binding in - let%bind variables = patterns_to_typed_vars binders in + begin match binders with + (* let p = rhs in body *) + | (p, []) -> + let%bind variables = tuple_pattern_to_typed_vars p in let%bind ty_opt = bind_map_option (fun (_,te) -> simpl_type_expression te) lhs_type in let%bind rhs = simpl_expression let_rhs in @@ -319,6 +316,11 @@ let rec simpl_expression : then ok (chain_let_in prep_vars body) (* Bind the right hand side so we only evaluate it once *) else ok (e_let_in (rhs_b, ty_opt) rhs' (chain_let_in prep_vars body)) + + (* let f p1 ps... = rhs in body *) + | (f, p1 :: ps) -> + fail @@ unsuppported_let_in_function (f :: p1 :: ps) + end | Raw.EAnnot a -> let Raw.{inside=expr, _, type_expr; _}, loc = r_split a in let%bind expr' = simpl_expression expr in @@ -484,6 +486,28 @@ and simpl_fun lamb' : expr result = let (lamb , loc) = r_split lamb' in let%bind args' = let args = nseq_to_list lamb.binders in + let args = (* Handle case where we have tuple destructure in params *) + match lamb.binders with + (* TODO: currently works only if there is one param *) + | (Raw.PPar pp, []) -> + let pt = pp.value.inside in + (match pt with + | Raw.PTyped pt -> + begin + match pt.value.pattern with + | Raw.PVar _ -> args + | Raw.PTuple _ -> + [Raw.PTyped + {region=Region.ghost; + value= + { pt.value with pattern= + Raw.PVar {region=Region.ghost; + value="#P"}}}] + | _ -> args + end + | _ -> args) + | _ -> args + in let%bind p_args = bind_map_list pattern_to_typed_var args in let aux ((var : Raw.variable) , ty_opt) = match var.value , ty_opt with @@ -502,7 +526,41 @@ and simpl_fun lamb' : expr result = | [ single ] -> ( let (binder , input_type) = (Var.of_name (fst single).value , snd single) in - let%bind (body , body_type) = expr_to_typed_expr lamb.body in + let%bind body = + let original_args = nseq_to_list lamb.binders in + let destruct = List.hd original_args in + match destruct with (* Handle tuple parameter destructuring *) + | Raw.PPar pp -> + (match pp.value.inside with + | Raw.PTyped pt -> + let vars = pt.value in + (match vars.pattern with + | PTuple vars -> + let let_in_binding: Raw.let_binding = + {binders = (PTuple vars, []) ; + lhs_type=None; + eq=Region.ghost; + let_rhs=(Raw.EVar {region=Region.ghost; value="#P"}); + } + in + let let_in: Raw.let_in = + {kwd_let= Region.ghost; + binding= let_in_binding; + kwd_in= Region.ghost; + body= lamb.body; + } + in + ok (Raw.ELetIn + { + region=Region.ghost; + value=let_in + }) + | Raw.PVar _ -> ok lamb.body + | _ -> ok lamb.body) + | _ -> ok lamb.body) + | _ -> ok lamb.body + in + let%bind (body , body_type) = expr_to_typed_expr body in let%bind output_type = bind_map_option simpl_type_expression body_type in let%bind result = simpl_expression body in diff --git a/src/test/contracts/tuple_param_destruct.mligo b/src/test/contracts/tuple_param_destruct.mligo new file mode 100644 index 000000000..6dfe30fe4 --- /dev/null +++ b/src/test/contracts/tuple_param_destruct.mligo @@ -0,0 +1 @@ +let sum (result, i : int * int) : int = result + i diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index f6b58f237..d5b1c940c 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -1795,6 +1795,11 @@ let type_tuple_destruct () : unit result = let%bind () = expect_eq program "type_tuple_d_2" (e_unit ()) (e_string "helloworld") in ok () +let tuple_param_destruct () : unit result = + let%bind program = mtype_file "./contracts/tuple_param_destruct.mligo" in + let%bind () = expect_eq program "sum" (e_tuple [e_int 10; e_int 10]) (e_int 20) + in ok () + let let_in_multi_bind () : unit result = let%bind program = mtype_file "./contracts/let_in_multi_bind.mligo" in let%bind () = expect_eq program "sum" (e_tuple [e_int 10; e_int 10]) (e_int 20) in @@ -1946,4 +1951,5 @@ let main = test_suite "Integration (End to End)" [ test "entrypoints (ligo)" entrypoints_ligo ; test "type tuple destruct (mligo)" type_tuple_destruct ; test "let in multi-bind (mligo)" let_in_multi_bind ; + test "tuple param destruct (mligo)" tuple_param_destruct ; ] From c8339ed2efdf4ab9a39f641e298c584451a9be4a Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 12:23:11 +0100 Subject: [PATCH 02/43] first try --- .gitignore | 1 + ligo.opam | 6 +++++- src/bin/dune | 2 +- src/bin/expect_tests/dune | 2 +- src/dune | 2 +- src/main/compile/dune | 2 +- src/main/dune | 2 +- src/main/run/dune | 2 +- src/main/uncompile/dune | 2 +- src/passes/1-parser/cameligo/dune | 7 +++++-- src/passes/1-parser/dune | 2 +- src/passes/1-parser/pascaligo/dune | 17 +++++++++++------ src/passes/1-parser/reasonligo/dune | 9 +++++++-- src/passes/1-parser/shared/dune | 6 +++++- src/passes/2-simplify/dune | 1 + src/passes/3-self_ast_simplified/dune | 2 +- src/passes/4-typer/dune | 2 +- src/passes/6-transpiler/dune | 2 +- src/passes/7-self_mini_c/dune | 2 +- src/passes/8-compiler/dune | 2 +- src/passes/9-self_michelson/dune | 2 +- src/passes/operators/dune | 2 +- src/stages/ast_simplified/dune | 2 +- src/stages/ast_typed/dune | 2 +- src/stages/common/dune | 2 +- src/stages/mini_c/dune | 2 +- src/stages/typesystem/dune | 2 +- src/test/dune | 2 +- 28 files changed, 56 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index fb756e969..6b016bfb5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ Version.ml **/.DS_Store .vscode/ /ligo.install +/_coverage/ diff --git a/ligo.opam b/ligo.opam index 303135cdb..896b93eee 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"] ] build: [ [ "dune" "build" "-p" name "-j" jobs ] diff --git a/src/bin/dune b/src/bin/dune index 4546f2a6f..60874931e 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)) ) diff --git a/src/bin/expect_tests/dune b/src/bin/expect_tests/dune index c7856e438..9c3d03b03 100644 --- a/src/bin/expect_tests/dune +++ b/src/bin/expect_tests/dune @@ -2,5 +2,5 @@ (name cli_expect_tests) (libraries simple-utils cli) (inline_tests) - (preprocess (pps ppx_let ppx_expect)) + (preprocess (pps ppx_let ppx_expect bisect_ppx --conditional)) (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/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/dune b/src/passes/1-parser/cameligo/dune index 730290696..f68e85661 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) 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/dune b/src/passes/1-parser/pascaligo/dune index 53c2d8385..a5bcdc6b7 100644 --- a/src/passes/1-parser/pascaligo/dune +++ b/src/passes/1-parser/pascaligo/dune @@ -10,12 +10,17 @@ (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) diff --git a/src/passes/1-parser/reasonligo/dune b/src/passes/1-parser/reasonligo/dune index 8d65f1363..e98678262 100644 --- a/src/passes/1-parser/reasonligo/dune +++ b/src/passes/1-parser/reasonligo/dune @@ -16,8 +16,13 @@ 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) 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/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/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/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/dune b/src/test/dune index 24a44109f..a65a038c0 100644 --- a/src/test/dune +++ b/src/test/dune @@ -7,7 +7,7 @@ tezos-crypto ) (preprocess - (pps ppx_let) + (pps ppx_let bisect_ppx --conditional) ) (flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils )) ) From 46ac00e94dbe2309acaa23b1e2fe81571a6fd40b Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 13:10:05 +0100 Subject: [PATCH 03/43] makefile target --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 40204f5c8..e472e32c2 100644 --- a/Makefile +++ b/Makefile @@ -30,3 +30,8 @@ test: build export PATH="/usr/local/bin$${PATH:+:}$${PATH:-}" eval $$(opam config env) scripts/test_ligo.sh + +coverage: build-deps + BISECT_ENABLE=yes dune runtest --force + bisect-ppx-report html + bisect-ppx-report summary From e8d1e359f4b1944b09dfeb44375ae0fb79f7233d Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 13:44:47 +0100 Subject: [PATCH 04/43] exclude PPs from coverage --- src/stages/ast_simplified/PP.ml | 1 + src/stages/ast_typed/PP.ml | 1 + src/stages/mini_c/PP.ml | 1 + 3 files changed, 3 insertions(+) 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_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/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 From 6f804a4432bb839d6862d91202dbf797c0a2ddb9 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 13:50:16 +0100 Subject: [PATCH 05/43] exclude parser debug tooling --- src/passes/1-parser/cameligo/ParserLog.ml | 1 + src/passes/1-parser/pascaligo/ParserLog.ml | 1 + 2 files changed, 2 insertions(+) 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/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 From 787d4689a0600c3905b333f062c00d53c022a51c Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 18:59:45 +0100 Subject: [PATCH 06/43] dune clean in the coverage target makes it more stable --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e472e32c2..896116f52 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,8 @@ test: build eval $$(opam config env) scripts/test_ligo.sh -coverage: build-deps +coverage: + dune clean BISECT_ENABLE=yes dune runtest --force bisect-ppx-report html bisect-ppx-report summary From 61d095ea28dcf4b143044d9254e70581dbcb572d Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 11 Dec 2019 19:07:52 +0100 Subject: [PATCH 07/43] also preprocess the executable --- src/bin/dune | 2 +- src/passes/1-parser/cameligo/dune | 4 ++++ src/passes/1-parser/pascaligo/dune | 14 ++++++++++---- src/passes/1-parser/reasonligo/dune | 11 +++++++++-- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/bin/dune b/src/bin/dune index 60874931e..f0219a5f6 100644 --- a/src/bin/dune +++ b/src/bin/dune @@ -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/passes/1-parser/cameligo/dune b/src/passes/1-parser/cameligo/dune index f68e85661..5604f5065 100644 --- a/src/passes/1-parser/cameligo/dune +++ b/src/passes/1-parser/cameligo/dune @@ -27,6 +27,8 @@ parser_cameligo) (modules LexerMain) + (preprocess + (pps bisect_ppx --conditional)) (flags (:standard -open Parser_shared -open Parser_cameligo))) (executable @@ -36,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/pascaligo/dune b/src/passes/1-parser/pascaligo/dune index a5bcdc6b7..28fee7d04 100644 --- a/src/passes/1-parser/pascaligo/dune +++ b/src/passes/1-parser/pascaligo/dune @@ -17,8 +17,7 @@ tezos-utils ) (preprocess - (pps bisect_ppx --conditional) - ) + (pps bisect_ppx --conditional)) (flags (:standard -open Parser_shared -open Simple_utils)) ) @@ -30,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 e98678262..fc7b1d15e 100644 --- a/src/passes/1-parser/reasonligo/dune +++ b/src/passes/1-parser/reasonligo/dune @@ -28,9 +28,13 @@ (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) @@ -40,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))) From 783cd355e494e7de7bf8198f19ef6039539c22f1 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 12 Dec 2019 15:07:42 +0100 Subject: [PATCH 08/43] no pinned deps --- ligo.opam | 3 --- 1 file changed, 3 deletions(-) diff --git a/ligo.opam b/ligo.opam index 896b93eee..351c8fed7 100644 --- a/ligo.opam +++ b/ligo.opam @@ -23,9 +23,6 @@ depends: [ # work around upstream in-place update "ocaml-migrate-parsetree" { = "1.4.0" } ] -pin-depends: [ - ["bisect_ppx.git" "git+https://github.com/aantron/bisect_ppx.git"] -] build: [ [ "dune" "build" "-p" name "-j" jobs ] ] From 6c7440ea79a0958fc6965446c45a7af3c68b58fc Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 12 Dec 2019 16:55:40 +0100 Subject: [PATCH 09/43] inline magic --- src/bin/expect_tests/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/expect_tests/dune b/src/bin/expect_tests/dune index 9c3d03b03..97422faad 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 bisect_ppx --conditional)) (flags (:standard -open Simple_utils))) From acee34985ba2165f56eaa2d4afa67e62cbd0e81a Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 12 Dec 2019 17:32:37 +0100 Subject: [PATCH 10/43] remove ppx in tests --- src/test/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/dune b/src/test/dune index a65a038c0..24a44109f 100644 --- a/src/test/dune +++ b/src/test/dune @@ -7,7 +7,7 @@ tezos-crypto ) (preprocess - (pps ppx_let bisect_ppx --conditional) + (pps ppx_let) ) (flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils )) ) From 15e819cde18db994931770739aad64f56a33becc Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 13 Dec 2019 11:18:07 +0100 Subject: [PATCH 11/43] more targets --- .gitignore | 3 +++ Makefile | 20 +++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6b016bfb5..20157262c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ Version.ml .vscode/ /ligo.install /_coverage/ +/_coverage_all/ +/_coverage_ligo/ +/_coverage_cli/ diff --git a/Makefile b/Makefile index 896116f52..49402e6d1 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,22 @@ test: build eval $$(opam config env) scripts/test_ligo.sh -coverage: +clean: dune clean + +coverage: clean BISECT_ENABLE=yes dune runtest --force - bisect-ppx-report html - bisect-ppx-report summary + 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-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 + # PRE="CLI coverage: " + # bisect-ppx-report summary --per-file | grep 'src/bin/cli.ml\|src/bin/cli_helpers.ml' | awk -v ORS=" " '{print $1}' | awk -v PRE=${PRE} -v POST="%" '{print PRE ($1 + $2 / NF) POST}' \ No newline at end of file From c873350b154da0ac94455e8a8a27e6edd0173c7b Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 13 Dec 2019 12:25:54 +0100 Subject: [PATCH 12/43] no ppx in expect_tests lib --- Makefile | 1 + src/bin/expect_tests/dune | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 49402e6d1..7932e1d84 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ test: build clean: dune clean + rm -fr _coverage_all _coverage_cli _coverage_ligo coverage: clean BISECT_ENABLE=yes dune runtest --force diff --git a/src/bin/expect_tests/dune b/src/bin/expect_tests/dune index 97422faad..65504a168 100644 --- a/src/bin/expect_tests/dune +++ b/src/bin/expect_tests/dune @@ -2,5 +2,5 @@ (name cli_expect_tests) (libraries simple-utils cli) (inline_tests (deps (source_tree ../../test/contracts))) - (preprocess (pps ppx_let ppx_expect bisect_ppx --conditional)) + (preprocess (pps ppx_let ppx_expect)) (flags (:standard -open Simple_utils))) From 23cc7e82d66e101e9cea77a3240a90b04d0752fd Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 13 Dec 2019 12:50:20 +0100 Subject: [PATCH 13/43] Revert "no pinned deps" This reverts commit 9c3d8d7df22d7e5befc8e80ab890a90cbf0862b6. --- ligo.opam | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ligo.opam b/ligo.opam index 351c8fed7..896b93eee 100644 --- a/ligo.opam +++ b/ligo.opam @@ -23,6 +23,9 @@ depends: [ # work around upstream in-place update "ocaml-migrate-parsetree" { = "1.4.0" } ] +pin-depends: [ + ["bisect_ppx.git" "git+https://github.com/aantron/bisect_ppx.git"] +] build: [ [ "dune" "build" "-p" name "-j" jobs ] ] From 2bff4eef6a325aa336e2c5a93d59f338c09ae501 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 23 Dec 2019 14:39:41 +0100 Subject: [PATCH 14/43] Commit hash for bisect_ppx pinned dep --- ligo.opam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ligo.opam b/ligo.opam index 896b93eee..7b4f8c210 100644 --- a/ligo.opam +++ b/ligo.opam @@ -24,7 +24,7 @@ depends: [ "ocaml-migrate-parsetree" { = "1.4.0" } ] pin-depends: [ - ["bisect_ppx.git" "git+https://github.com/aantron/bisect_ppx.git"] + ["bisect_ppx.git" "git+https://github.com/aantron/bisect_ppx.git#02dfb10188033a26d07d23480c2bc44a3a670357"] ] build: [ [ "dune" "build" "-p" name "-j" jobs ] From 08471ba246836b83f57be98d71fa9005afae3107 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 23 Dec 2019 15:18:32 +0100 Subject: [PATCH 15/43] basic architecture for the doc tests --- .gitignore | 5 +- Makefile | 9 ++- .../language-basics/sets-lists-touples.md | 80 +++++++++---------- src/main/compile/helpers.ml | 46 ++++++++--- src/main/compile/of_source.ml | 4 + src/test/doc_test.ml | 8 ++ src/test/dune | 10 ++- src/test/md.mll | 62 ++++++++++++++ src/test/md_file_tests.ml | 74 +++++++++++++++++ 9 files changed, 242 insertions(+), 56 deletions(-) create mode 100644 src/test/doc_test.ml create mode 100644 src/test/md.mll create mode 100644 src/test/md_file_tests.ml diff --git a/.gitignore b/.gitignore index 20157262c..d2d2464e1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ Version.ml **/.DS_Store .vscode/ /ligo.install +*.coverage /_coverage/ -/_coverage_all/ -/_coverage_ligo/ -/_coverage_cli/ +/_coverage_*/ diff --git a/Makefile b/Makefile index 7932e1d84..f69d64ba3 100644 --- a/Makefile +++ b/Makefile @@ -45,9 +45,12 @@ coverage-ligo: clean 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 - # PRE="CLI coverage: " - # bisect-ppx-report summary --per-file | grep 'src/bin/cli.ml\|src/bin/cli_helpers.ml' | awk -v ORS=" " '{print $1}' | awk -v PRE=${PRE} -v POST="%" '{print PRE ($1 + $2 / NF) POST}' \ No newline at end of file + bisect-ppx-report summary --per-file \ No newline at end of file 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/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/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..9c018595d 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/language-basics)) +) + (alias (name ligo-test) (action (run ./test.exe)) 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..347acbbcf --- /dev/null +++ b/src/test/md_file_tests.ml @@ -0,0 +1,74 @@ +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^" group '"^group^"' in file '"^md_file^"'" in + let content () = "unable to compile the program down to michelson" in + let data = [ + ("source" , fun () -> Format.asprintf "%s" prg) ; + ] in + error ~data 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 -> + 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 -> grp_map + ) + SnippetsGroup.empty code_blocks + +(** + evaluate each expression in each programs from the snippets group map +**) +let compile_groups _filename (grp_map: _ SnippetsGroup.t) = + let grp_list = SnippetsGroup.bindings grp_map in + let%bind _michelsons = bind_map_list + (fun ((s,_grp),contents) -> + (*TODO: hierarchical error ?*) + trace_strong (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 = get_groups filename in + let%bind () = compile_groups filename groups in + ok () + +let md_root = "../../gitlab-pages/docs/language-basics/" +let main = test_suite "Markdown files" [ + test "sets_lists_touples" (compile (md_root^"sets-lists-touples.md")) ; + ] From 883d17a9c1d0825d3656bf62588ffd35a991d214 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Tue, 24 Dec 2019 16:09:48 +0100 Subject: [PATCH 16/43] fix "map-records.md" --- .../docs/language-basics/maps-records.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) 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); }; ``` From afa61e58257fece22262392f87d2fdafbdb5ca58 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Tue, 24 Dec 2019 16:10:31 +0100 Subject: [PATCH 17/43] Now have an default group "ungrouped" for all the code blocks without any "group=..." --- Makefile | 2 +- src/test/md_file_tests.ml | 100 ++++++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index f69d64ba3..4ad94ebdc 100644 --- a/Makefile +++ b/Makefile @@ -53,4 +53,4 @@ coverage-doc: clean 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 \ No newline at end of file + bisect-ppx-report summary --per-file diff --git a/src/test/md_file_tests.ml b/src/test/md_file_tests.ml index 347acbbcf..02336dcfe 100644 --- a/src/test/md_file_tests.ml +++ b/src/test/md_file_tests.ml @@ -4,7 +4,7 @@ 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^" group '"^group^"' in file '"^md_file^"'" in + let title () = "Failed to compile ```"^s^" block (group '"^group^"') in file '"^md_file^"'" in let content () = "unable to compile the program down to michelson" in let data = [ ("source" , fun () -> Format.asprintf "%s" prg) ; @@ -25,7 +25,16 @@ let get_groups md_file = List.fold_left (fun (grp_map: _ SnippetsGroup.t) (el:Md.block) -> match el.header with - | Some s -> + | 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 + | _ -> List.fold_left (fun grp_map arg -> match arg with | Md.NameValue ("group", name) -> @@ -38,37 +47,96 @@ let get_groups md_file = grp_map | _ -> grp_map ) - grp_map el.arguments - | None -> 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_map: _ SnippetsGroup.t) = - let grp_list = SnippetsGroup.bindings grp_map in - let%bind _michelsons = bind_map_list +let compile_groups _filename grp_list = + let%bind (_michelsons : Compiler.compiled_expression list list) = bind_map_list (fun ((s,_grp),contents) -> - (*TODO: hierarchical error ?*) - trace_strong (failed_to_compile_md_file _filename (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) + (fun ((_,exp),_) -> Compile.Of_mini_c.aggregate_and_compile_expression mini_c exp) mini_c - ) + ) grp_list in ok () -let compile filename () = - let groups = get_groups filename in +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/functions.md"; + "/gitlab-pages/docs/language-basics/math-numbers-tez.md"; + *) + (* antislash problem: + "/gitlab-pages/docs/language-basics/strings.md"; + "/gitlab-pages/docs/language-basics/boolean-if-else.md"; + "/gitlab-pages/docs/language-basics/types.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"; + "/gitlab-pages/website/blog/2019-07-11-ligo-update.md"; + "/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/back-end.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/vendors.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/front-end.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/overview.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/middle-end.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/road-map/short-term.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/road-map/long-term.md"; + "/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md"; + "/gitlab-pages/website/versioned_docs/version-next/api-cli-commands.md"; + "/gitlab-pages/website/README.md"; + "/gitlab-pages/README.md"; + *) +] + let md_root = "../../gitlab-pages/docs/language-basics/" -let main = test_suite "Markdown files" [ - test "sets_lists_touples" (compile (md_root^"sets-lists-touples.md")) ; - ] +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) From 3d925ae43e88f000ada43e6508fb1d381d7d2a40 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 25 Dec 2019 22:53:40 +0100 Subject: [PATCH 18/43] fix "types.md" --- gitlab-pages/docs/language-basics/types.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) 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}) ]); ``` From bddad3f2340c383af0ca1189f963ddd4c1172d0b Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 25 Dec 2019 23:38:07 +0100 Subject: [PATCH 19/43] add missing GE operator (>=) to cameligo --- src/passes/operators/operators.ml | 1 + 1 file changed, 1 insertion(+) 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 From 9a5800dc3e98462512778bd909b8f5aadd9a3ff5 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 25 Dec 2019 23:38:37 +0100 Subject: [PATCH 20/43] fix "boolean-if-else.md" --- .../docs/language-basics/boolean-if-else.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) 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) { From 8f4bdcad6aa0e54d9248d16813280ada0af482e6 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 12:51:42 +0100 Subject: [PATCH 21/43] fix "functions.md" --- gitlab-pages/docs/language-basics/functions.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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; ``` From d31eec13274d150d2881a5bbeaa55235e7ab47f6 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 13:29:22 +0100 Subject: [PATCH 22/43] fix "math-numbers-tez.md" --- .../docs/language-basics/math-numbers-tez.md | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) 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); ``` From d859a5ce5c52799945498fa7e66d68cb2fc6f73e Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 13:40:45 +0100 Subject: [PATCH 23/43] fix "tezos-taco-shop-payout.md" --- .../get-started/tezos-taco-shop-payout.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) 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); From aa35043414cca8ad0d95b80d0746de5388467b03 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 13:48:07 +0100 Subject: [PATCH 24/43] fix "tezos-taco-shop-smart-contract.md" --- .../tezos-taco-shop-smart-contract.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 ``` From 4556568c7285ab120fb01c40fc3b89eebc67f9b7 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 14:21:05 +0100 Subject: [PATCH 25/43] fix "entrypoints-contracts.md" --- gitlab-pages/docs/advanced/entrypoints-contracts.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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" From eac5e9b82e7333ac8383e53f42fa28e8f7a3795a Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 14:21:17 +0100 Subject: [PATCH 26/43] fix "timestamps-addresses.md" --- gitlab-pages/docs/advanced/timestamps-addresses.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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); ``` From c171ce7ad95ac6d30340c750ab33f3a2d70bd8a4 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 14:22:13 +0100 Subject: [PATCH 27/43] fully tested md_files --- src/test/dune | 2 +- src/test/md_file_tests.ml | 36 +++++++----------------------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/test/dune b/src/test/dune index 9c018595d..9582317c9 100644 --- a/src/test/dune +++ b/src/test/dune @@ -17,7 +17,7 @@ (alias (name doc-test) (action (run ./doc_test.exe)) - (deps (source_tree ../../gitlab-pages/docs/language-basics)) + (deps (source_tree ../../gitlab-pages/docs)) ) (alias diff --git a/src/test/md_file_tests.ml b/src/test/md_file_tests.ml index 02336dcfe..c2e275a3d 100644 --- a/src/test/md_file_tests.ml +++ b/src/test/md_file_tests.ml @@ -5,11 +5,8 @@ module SnippetsGroup = Map.Make(struct type t = (string * string) let compare a 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 () = "unable to compile the program down to michelson" in - let data = [ - ("source" , fun () -> Format.asprintf "%s" prg) ; - ] in - error ~data title content + let content () = "\n"^prg in + error title content (** binds the snippets by (syntax, group_name) @@ -34,6 +31,7 @@ let get_groups md_file = | None -> Some (String.concat "\n" el.contents) ) grp_map + | [Md.Field "skip"] -> grp_map | _ -> List.fold_left (fun grp_map arg -> match arg with @@ -57,8 +55,8 @@ let get_groups md_file = **) 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)) @@ + (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 @@ -79,24 +77,19 @@ let compile filename () = 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/functions.md"; "/gitlab-pages/docs/language-basics/math-numbers-tez.md"; - *) - (* antislash problem: - "/gitlab-pages/docs/language-basics/strings.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"; @@ -116,21 +109,6 @@ let md_files = [ "/gitlab-pages/docs/advanced/timestamps-addresses.md"; "/gitlab-pages/docs/api/cli-commands.md"; "/gitlab-pages/docs/api/cheat-sheet.md"; - "/gitlab-pages/website/blog/2019-07-11-ligo-update.md"; - "/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/back-end.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/vendors.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/front-end.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/overview.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/big-picture/middle-end.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/road-map/short-term.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/road-map/long-term.md"; - "/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md"; - "/gitlab-pages/website/versioned_docs/version-next/api-cli-commands.md"; - "/gitlab-pages/website/README.md"; - "/gitlab-pages/README.md"; - *) ] let md_root = "../../gitlab-pages/docs/language-basics/" From d0ea94b4723f520fb99520ec7864ec1ff001a550 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 14:26:57 +0100 Subject: [PATCH 28/43] 'dune runtest' also execute 'md files tests' --- src/test/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/dune b/src/test/dune index 9582317c9..9da57c8ef 100644 --- a/src/test/dune +++ b/src/test/dune @@ -29,7 +29,7 @@ (alias (name runtest) - (deps (alias ligo-test)) + (deps (alias ligo-test) (alias doc-test)) ) (alias From f16f16e4b34fbaadfcfefcf27cfc8147d18b3ac8 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 26 Dec 2019 18:12:07 +0100 Subject: [PATCH 29/43] coverage resutlts as a CI artifact --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) 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: From 0e7b79026d14f066c9d90a6f385e95f14d584a82 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 1 Jan 2020 12:30:55 -0800 Subject: [PATCH 30/43] Add docs page for loops --- gitlab-pages/docs/language-basics/loops.md | 87 ++++++++++++++++++++++ gitlab-pages/website/sidebars.json | 1 + 2 files changed, 88 insertions(+) create mode 100644 gitlab-pages/docs/language-basics/loops.md diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md new file mode 100644 index 000000000..6ac382fe5 --- /dev/null +++ b/gitlab-pages/docs/language-basics/loops.md @@ -0,0 +1,87 @@ +--- +id: loops +title: Loops +--- + + + +## While Loop + + + + + +The PascaLIGO while loop should look familiar to users of imperative languages. +While loops are of the form `while `, and evaluate +their associated block until the condition evaluates to false. + +> ⚠️ The current PascaLIGO while loop has semantics that have diverged from other LIGO syntaxes. The goal of LIGO is that the various syntaxes express the same semantics, so this will be corrected in future versions. For details on how loops will likely work after refactoring, see the CameLIGO tab of this example. + +```pascaligo +function while_sum (var n : nat) : nat is block { + var i : nat := 0n ; + var r : nat := 0n ; + while i < n block { + i := i + 1n; + r := r + i; + } +} with r +``` + + + +`Loop.fold_while` is a fold operation that takes an initial value of a certain type +and then iterates on it until a condition is reached. The auxillary function +that does the fold returns either boolean true or boolean false to indicate +whether the fold should continue or not. The initial value must match the input +parameter of the auxillary function, and the auxillary should return type `(bool * input)`. + +```cameligo +let aux (i: int) : bool * int = + if i < 100 then continue (i + 1) else stop i + +let counter_simple (n: int) : int = + Loop.fold_while aux_simple n +``` + + + +## For Loop + + + + +To iterate over a range of integers you use a loop of the form `for to `. + +```pascaligo +function for_sum (var n : nat) : int is block { + var acc : int := 0 ; + for i := 1 to int(n) + begin + acc := acc + i; + end +} with acc +``` + + + + + + +PascaLIGO for loops can also iterate through the contents of a collection. This is +done with a loop of the form `for in `. + +```pascaligo +function for_collection_list (var nee : unit) : (int * string) is block { + var acc : int := 0; + var st : string := "to"; + var mylist : list(int) := list 1; 1; 1 end; + for x in list mylist + begin + acc := acc + x; + st := st ^ "to"; + end +} with (acc, st) +``` + + diff --git a/gitlab-pages/website/sidebars.json b/gitlab-pages/website/sidebars.json index 13ce03e4e..4c5017e56 100644 --- a/gitlab-pages/website/sidebars.json +++ b/gitlab-pages/website/sidebars.json @@ -8,6 +8,7 @@ "language-basics/strings", "language-basics/functions", "language-basics/boolean-if-else", + "language-basics/loops", "language-basics/unit-option-pattern-matching", "language-basics/maps-records", "language-basics/sets-lists-touples" From 98ac18ccefc35b9f7ee7a1539dd91915a60dc6d3 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Tue, 31 Dec 2019 15:27:06 +0100 Subject: [PATCH 31/43] propagate failwith strings (also support for others) in the error --- src/bin/expect_tests/contract_tests.ml | 6 +++++- src/main/run/of_michelson.ml | 24 ++++++++++++++++++++++-- src/test/contracts/failwith.ligo | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml index 53db85afc..4d2d6b5a9 100644 --- a/src/bin/expect_tests/contract_tests.ml +++ b/src/bin/expect_tests/contract_tests.ml @@ -927,4 +927,8 @@ let%expect_test _ = let%expect_test _ = run_ligo_bad [ "compile-contract" ; contract "bad_type_operator.ligo" ; "main" ] ; - [%expect {| ligo: bad type operator (TO_Map (unit,unit)): |}] ; \ No newline at end of file + [%expect {| ligo: bad type operator (TO_Map (unit,unit)): |}] + +let%expect_test _ = + run_ligo_bad [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ; + [%expect {| ligo: Execution failed: {"value":"some_string","type":"string"} |}] \ No newline at end of file diff --git a/src/main/run/of_michelson.ml b/src/main/run/of_michelson.ml index ef26bc11a..1a3b58114 100644 --- a/src/main/run/of_michelson.ml +++ b/src/main/run/of_michelson.ml @@ -3,6 +3,21 @@ open Trace open Memory_proto_alpha.Protocol.Script_ir_translator open Memory_proto_alpha.X +module Errors = struct + let unknown_failwith_type () = + let title () = "Execution failed with an unknown failwith type" in + let message () = "only bytes, string or int are printable" in + error title message + + let failwith data_str type_str () = + let title () = "Execution failed" in + let message () = "" in + let data = [ + ("value" , fun () -> Format.asprintf "%s" data_str); + ("type" , fun () -> Format.asprintf "%s" type_str); + ] in + error ~data title message +end type options = Memory_proto_alpha.options type run_res = @@ -121,7 +136,12 @@ let run ?options (exp:Michelson.t) (exp_type:ex_ty) : ex_typed_value result = let%bind expr = run_expression ?options exp exp_type in match expr with | Success res -> ok res - | _ -> simple_fail "Execution terminated with failwith" + | Fail res -> ( match Tezos_micheline.Micheline.root @@ Memory_proto_alpha.strings_of_prims res with + | Int (_ , i) -> fail @@ Errors.failwith (Z.to_string i) "int" () + | String (_ , s) -> fail @@ Errors.failwith s "string" () + | Bytes (_, s) -> fail @@ Errors.failwith (Bytes.to_string s) "bytes" () + | _ -> fail @@ Errors.unknown_failwith_type () ) + let run_failwith ?options (exp:Michelson.t) (exp_type:ex_ty) : run_failwith_res result = let%bind expr = run_expression ?options exp exp_type in @@ -129,7 +149,7 @@ let run_failwith ?options (exp:Michelson.t) (exp_type:ex_ty) : run_failwith_res | Fail res -> ( match Tezos_micheline.Micheline.root @@ Memory_proto_alpha.strings_of_prims res with | Int (_ , i) -> ok (Failwith_int (Z.to_int i)) | String (_ , s) -> ok (Failwith_string s) - | Bytes (_,b) -> ok (Failwith_bytes b) + | Bytes (_, b) -> ok (Failwith_bytes b) | _ -> simple_fail "Unknown failwith type" ) | _ -> simple_fail "An error of execution was expected" diff --git a/src/test/contracts/failwith.ligo b/src/test/contracts/failwith.ligo index 16c93f026..29b757c3e 100644 --- a/src/test/contracts/failwith.ligo +++ b/src/test/contracts/failwith.ligo @@ -31,3 +31,7 @@ function foobar (const i : int) : int is | Zero (n) -> i | Pos (n) -> (failwith ("waaaa") : int) end + +function failer(const p : int) : int is block { + if p = 1 then failwith("some_string") else skip ; +} with p From 42cbabac6995ca7b74f54d8626c116dfb51b6727 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 15:01:55 +0100 Subject: [PATCH 32/43] check ast_simplified address literals to be well formatted --- src/passes/3-self_ast_simplified/dune | 1 + src/passes/3-self_ast_simplified/literals.ml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/passes/3-self_ast_simplified/dune b/src/passes/3-self_ast_simplified/dune index 69dc6b507..aef575249 100644 --- a/src/passes/3-self_ast_simplified/dune +++ b/src/passes/3-self_ast_simplified/dune @@ -4,6 +4,7 @@ (libraries simple-utils ast_simplified + proto-alpha-utils ) (preprocess (pps ppx_let bisect_ppx --conditional) diff --git a/src/passes/3-self_ast_simplified/literals.ml b/src/passes/3-self_ast_simplified/literals.ml index 38116590b..7950aeae2 100644 --- a/src/passes/3-self_ast_simplified/literals.ml +++ b/src/passes/3-self_ast_simplified/literals.ml @@ -1,9 +1,17 @@ open Ast_simplified open Trace +open Proto_alpha_utils let peephole_expression : expression -> expression result = fun e -> let return expression = ok { e with expression } in match e.expression with + | E_literal (Literal_address s) as e -> ( + let open Memory_proto_alpha in + let%bind (_contract:Protocol.Alpha_context.Contract.t) = + Trace.trace_alpha_tzresult (simple_error ("address \""^s^"\" is not a valid address")) @@ + Protocol.Alpha_context.Contract.of_b58check s in + return e + ) | E_constant (C_BIG_MAP_LITERAL , lst) -> ( let%bind elt = trace_option (simple_error "big_map literal expects a single parameter") @@ From 8584bacf83eb35e9eb4ec0bd2d7cbc4644852be2 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 15:02:02 +0100 Subject: [PATCH 33/43] test & dune promote --- src/bin/expect_tests/contract_tests.ml | 6 +++++- src/test/contracts/bad_address_format.religo | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 src/test/contracts/bad_address_format.religo diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml index 4d2d6b5a9..0ce94f98d 100644 --- a/src/bin/expect_tests/contract_tests.ml +++ b/src/bin/expect_tests/contract_tests.ml @@ -931,4 +931,8 @@ let%expect_test _ = let%expect_test _ = run_ligo_bad [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ; - [%expect {| ligo: Execution failed: {"value":"some_string","type":"string"} |}] \ No newline at end of file + [%expect {| ligo: Execution failed: {"value":"some_string","type":"string"} |}] + +let%expect_test _ = + run_ligo_bad [ "compile-contract" ; contract "bad_address_format.religo" ; "main" ] ; + [%expect {| ligo: in file "bad_address_format.religo", line 2, characters 25-47. Badly formatted address "KT1badaddr": {"location":"in file \"bad_address_format.religo\", line 2, characters 25-47"} |}] diff --git a/src/test/contracts/bad_address_format.religo b/src/test/contracts/bad_address_format.religo new file mode 100644 index 000000000..c8668bc45 --- /dev/null +++ b/src/test/contracts/bad_address_format.religo @@ -0,0 +1,3 @@ +let main = (parameter: int, storage: address) => { + ([]:list(operation), "KT1badaddr" : address); +}; From 46027de719930b227b90332f373a119f334cdf45 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 15:11:02 +0100 Subject: [PATCH 34/43] Proper error with location --- src/passes/3-self_ast_simplified/literals.ml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/passes/3-self_ast_simplified/literals.ml b/src/passes/3-self_ast_simplified/literals.ml index 7950aeae2..dfe3cac4a 100644 --- a/src/passes/3-self_ast_simplified/literals.ml +++ b/src/passes/3-self_ast_simplified/literals.ml @@ -2,15 +2,26 @@ open Ast_simplified open Trace open Proto_alpha_utils +module Errors = struct + let bad_literal_address s_addr loc () = + let title = (thunk ("Badly formatted address \""^s_addr^"\"")) in + let message () = "" in + let data = [ + ("location" , fun () -> Format.asprintf "%a" Location.pp loc) + ] in + error ~data title message () +end +open Errors + let peephole_expression : expression -> expression result = fun e -> let return expression = ok { e with expression } in match e.expression with - | E_literal (Literal_address s) as e -> ( + | E_literal (Literal_address s) as l -> ( let open Memory_proto_alpha in let%bind (_contract:Protocol.Alpha_context.Contract.t) = - Trace.trace_alpha_tzresult (simple_error ("address \""^s^"\" is not a valid address")) @@ + Trace.trace_alpha_tzresult (bad_literal_address s e.location) @@ Protocol.Alpha_context.Contract.of_b58check s in - return e + return l ) | E_constant (C_BIG_MAP_LITERAL , lst) -> ( let%bind elt = From 2d7c3eb2162cc8f8053f08c26b2a38bc45fdcc06 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 16:19:21 +0100 Subject: [PATCH 35/43] support bytes_unpack operator in pascaligo + tests --- src/passes/operators/operators.ml | 1 + src/test/contracts/bytes_unpack.ligo | 11 +++++++++++ src/test/integration_tests.ml | 11 +++++++++++ 3 files changed, 23 insertions(+) create mode 100644 src/test/contracts/bytes_unpack.ligo diff --git a/src/passes/operators/operators.ml b/src/passes/operators/operators.ml index 424032703..485701813 100644 --- a/src/passes/operators/operators.ml +++ b/src/passes/operators/operators.ml @@ -92,6 +92,7 @@ module Simplify = struct | "bytes_concat" -> ok C_CONCAT | "bytes_slice" -> ok C_SLICE | "bytes_pack" -> ok C_BYTES_PACK + | "bytes_unpack" -> ok C_BYTES_UNPACK | "set_empty" -> ok C_SET_EMPTY | "set_mem" -> ok C_SET_MEM | "set_add" -> ok C_SET_ADD diff --git a/src/test/contracts/bytes_unpack.ligo b/src/test/contracts/bytes_unpack.ligo new file mode 100644 index 000000000..c6b087635 --- /dev/null +++ b/src/test/contracts/bytes_unpack.ligo @@ -0,0 +1,11 @@ +function id_string (const p : string) : option(string) is block { + const packed : bytes = bytes_pack(p) ; +} with (bytes_unpack(packed): option(string)) + +function id_int (const p : int) : option(int) is block { + const packed : bytes = bytes_pack(p) ; +} with (bytes_unpack(packed): option(int)) + +function id_address (const p : address) : option(address) is block { + const packed : bytes = bytes_pack(p) ; +} with (bytes_unpack(packed): option(address)) \ No newline at end of file diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index d5b1c940c..b633f3faa 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -1812,7 +1812,18 @@ let let_in_multi_bind () : unit result = (e_string "mynameisbob") in ok () +let bytes_unpack () : unit result = + let%bind program = type_file "./contracts/bytes_unpack.ligo" in + let%bind () = expect_eq program "id_string" (e_string "teststring") (e_some (e_string "teststring")) in + let%bind () = expect_eq program "id_int" (e_int 42) (e_some (e_int 42)) in + let open Proto_alpha_utils.Memory_proto_alpha in + let addr = Protocol.Alpha_context.Contract.to_b58check @@ + (List.nth dummy_environment.identities 0).implicit_contract in + let%bind () = expect_eq program "id_address" (e_address addr) (e_some (e_address addr)) in + ok () + let main = test_suite "Integration (End to End)" [ + test "bytes unpack" bytes_unpack ; test "key hash" key_hash ; test "chain id" chain_id ; test "type alias" type_alias ; From 7c4f59035fbb207fe0b6347a9c8a9f14b11449eb Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 1 Jan 2020 21:30:50 -0800 Subject: [PATCH 36/43] Add inclusion directive docs and inclusion tests for CameLIGO and ReasonLIGO --- gitlab-pages/docs/advanced/include.md | 71 +++++++++++++++++++++++++++ gitlab-pages/website/sidebars.json | 1 + src/test/contracts/included.mligo | 3 ++ src/test/contracts/included.religo | 3 ++ src/test/contracts/includer.mligo | 5 ++ src/test/contracts/includer.religo | 5 ++ src/test/integration_tests.ml | 10 ++++ 7 files changed, 98 insertions(+) create mode 100644 gitlab-pages/docs/advanced/include.md create mode 100644 src/test/contracts/included.mligo create mode 100644 src/test/contracts/included.religo create mode 100644 src/test/contracts/includer.mligo create mode 100644 src/test/contracts/includer.religo diff --git a/gitlab-pages/docs/advanced/include.md b/gitlab-pages/docs/advanced/include.md new file mode 100644 index 000000000..956d4a80e --- /dev/null +++ b/gitlab-pages/docs/advanced/include.md @@ -0,0 +1,71 @@ +--- +id: include +title: Including Other Contracts +--- + +Lets say we have a contract that's getting a bit too big. If it has a modular +structure, you might find it useful to use the `#include` statement to split the +contract up over multiple files. + + +You take the code that you want to include and put it in a separate file, for +example `included.ligo`: + + + + +```pascaligo + +// Demonstrate PascaLIGO inclusion statements, see includer.ligo + +const foo : int = 144 +``` + + +```cameligo + +// Demonstrate CameLIGO inclusion statements, see includer.mligo + +let foo : int = 144 +``` + + +```reasonligo + +// Demonstrate ReasonLIGO inclusion statements, see includer.religo + +let foo : int = 144; +``` + + + + +And then you can include this code using the `#include` statement like so: + + + + +```pascaligo + +#include "included.ligo" + +const bar : int = foo +``` + + +```cameligo + +#include "included.mligo" + +let bar : int = foo +``` + + +```reasonligo + +#include "included.religo" + +let bar : int = foo; +``` + + diff --git a/gitlab-pages/website/sidebars.json b/gitlab-pages/website/sidebars.json index 13ce03e4e..f684e1fb4 100644 --- a/gitlab-pages/website/sidebars.json +++ b/gitlab-pages/website/sidebars.json @@ -15,6 +15,7 @@ "Advanced": [ "advanced/timestamps-addresses", "advanced/entrypoints-contracts", + "advanced/include", "advanced/first-contract" ], "API": [ diff --git a/src/test/contracts/included.mligo b/src/test/contracts/included.mligo new file mode 100644 index 000000000..2d5850f1b --- /dev/null +++ b/src/test/contracts/included.mligo @@ -0,0 +1,3 @@ +// Demonstrate CameLIGO inclusion statements, see includer.mligo + +let foo : int = 144 diff --git a/src/test/contracts/included.religo b/src/test/contracts/included.religo new file mode 100644 index 000000000..1478f2650 --- /dev/null +++ b/src/test/contracts/included.religo @@ -0,0 +1,3 @@ +// Demonstrate ReasonLIGO inclusion statements, see includer.religo + +let foo : int = 144; diff --git a/src/test/contracts/includer.mligo b/src/test/contracts/includer.mligo new file mode 100644 index 000000000..611939afc --- /dev/null +++ b/src/test/contracts/includer.mligo @@ -0,0 +1,5 @@ +// Demonstrate CameLIGO inclusion statements, see included.mligo + +#include "included.mligo" + +let bar : int = foo diff --git a/src/test/contracts/includer.religo b/src/test/contracts/includer.religo new file mode 100644 index 000000000..8a04951e9 --- /dev/null +++ b/src/test/contracts/includer.religo @@ -0,0 +1,5 @@ +// Demonstrate ReasonLIGO inclusion statements, see included.religo + +#include "included.religo" + +let bar : int = foo; diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index b633f3faa..c4610dc89 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -604,6 +604,14 @@ let include_ () : unit result = let%bind program = type_file "./contracts/includer.ligo" in expect_eq_evaluate program "bar" (e_int 144) +let include_mligo () : unit result = + let%bind program = mtype_file "./contracts/includer.mligo" in + expect_eq_evaluate program "bar" (e_int 144) + +let include_religo () : unit result = + let%bind program = retype_file "./contracts/includer.religo" in + expect_eq_evaluate program "bar" (e_int 144) + let record_ez_int names n = ez_e_record @@ List.map (fun x -> x, e_int n) names @@ -1899,6 +1907,8 @@ let main = test_suite "Integration (End to End)" [ test "quote declaration" quote_declaration ; test "quote declarations" quote_declarations ; test "#include directives" include_ ; + test "#include directives (mligo)" include_mligo ; + test "#include directives (religo)" include_religo ; test "counter contract" counter_contract ; test "super counter contract" super_counter_contract ; test "super counter contract" super_counter_contract_mligo ; From 6b469ac869d20db0fa7d9237d44f827b1d66cdef Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 1 Jan 2020 12:30:55 -0800 Subject: [PATCH 37/43] Add docs page for loops --- gitlab-pages/docs/language-basics/loops.md | 87 ++++++++++++++++++++++ gitlab-pages/website/sidebars.json | 1 + 2 files changed, 88 insertions(+) create mode 100644 gitlab-pages/docs/language-basics/loops.md diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md new file mode 100644 index 000000000..6ac382fe5 --- /dev/null +++ b/gitlab-pages/docs/language-basics/loops.md @@ -0,0 +1,87 @@ +--- +id: loops +title: Loops +--- + + + +## While Loop + + + + + +The PascaLIGO while loop should look familiar to users of imperative languages. +While loops are of the form `while `, and evaluate +their associated block until the condition evaluates to false. + +> ⚠️ The current PascaLIGO while loop has semantics that have diverged from other LIGO syntaxes. The goal of LIGO is that the various syntaxes express the same semantics, so this will be corrected in future versions. For details on how loops will likely work after refactoring, see the CameLIGO tab of this example. + +```pascaligo +function while_sum (var n : nat) : nat is block { + var i : nat := 0n ; + var r : nat := 0n ; + while i < n block { + i := i + 1n; + r := r + i; + } +} with r +``` + + + +`Loop.fold_while` is a fold operation that takes an initial value of a certain type +and then iterates on it until a condition is reached. The auxillary function +that does the fold returns either boolean true or boolean false to indicate +whether the fold should continue or not. The initial value must match the input +parameter of the auxillary function, and the auxillary should return type `(bool * input)`. + +```cameligo +let aux (i: int) : bool * int = + if i < 100 then continue (i + 1) else stop i + +let counter_simple (n: int) : int = + Loop.fold_while aux_simple n +``` + + + +## For Loop + + + + +To iterate over a range of integers you use a loop of the form `for to `. + +```pascaligo +function for_sum (var n : nat) : int is block { + var acc : int := 0 ; + for i := 1 to int(n) + begin + acc := acc + i; + end +} with acc +``` + + + + + + +PascaLIGO for loops can also iterate through the contents of a collection. This is +done with a loop of the form `for in `. + +```pascaligo +function for_collection_list (var nee : unit) : (int * string) is block { + var acc : int := 0; + var st : string := "to"; + var mylist : list(int) := list 1; 1; 1 end; + for x in list mylist + begin + acc := acc + x; + st := st ^ "to"; + end +} with (acc, st) +``` + + diff --git a/gitlab-pages/website/sidebars.json b/gitlab-pages/website/sidebars.json index f684e1fb4..00fe28d25 100644 --- a/gitlab-pages/website/sidebars.json +++ b/gitlab-pages/website/sidebars.json @@ -8,6 +8,7 @@ "language-basics/strings", "language-basics/functions", "language-basics/boolean-if-else", + "language-basics/loops", "language-basics/unit-option-pattern-matching", "language-basics/maps-records", "language-basics/sets-lists-touples" From e25c5bac3542393e22ded87be345073ecc1fafd1 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 20:38:45 +0100 Subject: [PATCH 38/43] adding loops.md to the list of tested file and fixed "loops.md" --- gitlab-pages/docs/language-basics/loops.md | 2 +- src/test/md_file_tests.ml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md index 6ac382fe5..eee32142e 100644 --- a/gitlab-pages/docs/language-basics/loops.md +++ b/gitlab-pages/docs/language-basics/loops.md @@ -41,7 +41,7 @@ let aux (i: int) : bool * int = if i < 100 then continue (i + 1) else stop i let counter_simple (n: int) : int = - Loop.fold_while aux_simple n + Loop.fold_while aux n ``` diff --git a/src/test/md_file_tests.ml b/src/test/md_file_tests.ml index c2e275a3d..eb89fa4a5 100644 --- a/src/test/md_file_tests.ml +++ b/src/test/md_file_tests.ml @@ -92,6 +92,7 @@ let md_files = [ "/gitlab-pages/docs/language-basics/sets-lists-touples.md"; "/gitlab-pages/docs/language-basics/operators.md"; "/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md"; + "/gitlab-pages/docs/language-basics/loops.md"; "/gitlab-pages/docs/contributors/big-picture/back-end.md"; "/gitlab-pages/docs/contributors/big-picture/vendors.md"; "/gitlab-pages/docs/contributors/big-picture/front-end.md"; From fcd33026bb5ccf6a7d9b1a73845cbc2bc44d3fbd Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Thu, 2 Jan 2020 12:26:02 -0800 Subject: [PATCH 39/43] Fix loops page with ReasonLIGO --- gitlab-pages/docs/language-basics/loops.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md index 964bf35ba..9fd26d024 100644 --- a/gitlab-pages/docs/language-basics/loops.md +++ b/gitlab-pages/docs/language-basics/loops.md @@ -64,7 +64,8 @@ let aux = (i: int): (bool, int) => stop(i); }; -let counter_simple = (n: int): int => Loop.fold_while(aux, n);``` +let counter_simple = (n: int): int => Loop.fold_while(aux, n); +``` From ce6ccab728b33b56eadcd29d73c442bea1b5eac2 Mon Sep 17 00:00:00 2001 From: Sander Date: Fri, 3 Jan 2020 13:01:13 +0000 Subject: [PATCH 40/43] Add support for empty constructors. --- src/passes/2-simplify/cameligo.ml | 10 +++++-- src/passes/2-simplify/pascaligo.ml | 5 ++++ src/test/contracts/empty_case.ligo | 9 ++++++ src/test/contracts/empty_case.mligo | 8 +++++ src/test/contracts/empty_case.religo | 9 ++++++ src/test/integration_tests.ml | 45 ++++++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/test/contracts/empty_case.ligo create mode 100644 src/test/contracts/empty_case.mligo create mode 100644 src/test/contracts/empty_case.religo diff --git a/src/passes/2-simplify/cameligo.ml b/src/passes/2-simplify/cameligo.ml index 762215450..b2bef414c 100644 --- a/src/passes/2-simplify/cameligo.ml +++ b/src/passes/2-simplify/cameligo.ml @@ -89,7 +89,7 @@ module Errors = struct fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc) ] in error ~data title message - + let unsupported_non_var_pattern p = let title () = "pattern is not a variable" in let message () = @@ -238,7 +238,7 @@ let rec simpl_type_expression : Raw.type_expr -> type_expression result = fun te and simpl_list_type_expression (lst:Raw.type_expr list) : type_expression result = match lst with - | [] -> assert false + | [] -> ok @@ t_unit | [hd] -> simpl_type_expression hd | lst -> let%bind lst = bind_map_list simpl_type_expression lst in @@ -779,7 +779,11 @@ and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching result = | PConstr v -> let const, pat_opt = match v with - PConstrApp {value; _} -> value + PConstrApp {value; _} -> + (match value with + | constr, None -> + constr, Some (PVar {value = "unit"; region = Region.ghost}) + | _ -> value) | PSomeApp {value=region,pat; _} -> {value="Some"; region}, Some pat | PNone region -> diff --git a/src/passes/2-simplify/pascaligo.ml b/src/passes/2-simplify/pascaligo.ml index e945be8eb..0707ee85a 100644 --- a/src/passes/2-simplify/pascaligo.ml +++ b/src/passes/2-simplify/pascaligo.ml @@ -952,6 +952,11 @@ and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching result = let get_constr (t: Raw.pattern) = match t with | PConstr (PConstrApp v) -> ( + let value = v.value in + match value with + | constr, None -> + ok (constr.value, "unit") + | _ -> let const, pat_opt = v.value in let%bind pat = trace_option (unsupported_cst_constr t) @@ diff --git a/src/test/contracts/empty_case.ligo b/src/test/contracts/empty_case.ligo new file mode 100644 index 000000000..30771c774 --- /dev/null +++ b/src/test/contracts/empty_case.ligo @@ -0,0 +1,9 @@ +type foo is + | Bar of int + | Baz + +function main (const f: foo) : int is + (case f of + | Bar (n) -> n + | Baz -> -1 + end) diff --git a/src/test/contracts/empty_case.mligo b/src/test/contracts/empty_case.mligo new file mode 100644 index 000000000..844897f01 --- /dev/null +++ b/src/test/contracts/empty_case.mligo @@ -0,0 +1,8 @@ +type foo = + | Bar of int + | Baz + +let main (f: foo): int = + match f with + | Bar i -> i + | Baz -> -1 \ No newline at end of file diff --git a/src/test/contracts/empty_case.religo b/src/test/contracts/empty_case.religo new file mode 100644 index 000000000..c5d6bdc5a --- /dev/null +++ b/src/test/contracts/empty_case.religo @@ -0,0 +1,9 @@ +type foo = + | Bar(int) + | Baz; + +let main = (f: foo): int => + switch (f) { + | Bar(i) => i + | Baz => (-1) + }; diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index c4610dc89..caa4c7c01 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -1830,6 +1830,48 @@ let bytes_unpack () : unit result = let%bind () = expect_eq program "id_address" (e_address addr) (e_some (e_address addr)) in ok () +let empty_case () : unit result = + let%bind program = type_file "./contracts/empty_case.ligo" in + let%bind () = + let input _ = e_constructor "Bar" (e_int 1) in + let expected _ = e_int 1 in + expect_eq_n program "main" input expected + in + let%bind () = + let input _ = e_constructor "Baz" (e_unit ()) in + let expected _ = e_int (-1) in + expect_eq_n program "main" input expected + in + ok () + +let empty_case_mligo () : unit result = + let%bind program = mtype_file "./contracts/empty_case.mligo" in + let%bind () = + let input _ = e_constructor "Bar" (e_int 1) in + let expected _ = e_int 1 in + expect_eq_n program "main" input expected + in + let%bind () = + let input _ = e_constructor "Baz" (e_unit ()) in + let expected _ = e_int (-1) in + expect_eq_n program "main" input expected + in + ok () + +let empty_case_religo () : unit result = + let%bind program = retype_file "./contracts/empty_case.religo" in + let%bind () = + let input _ = e_constructor "Bar" (e_int 1) in + let expected _ = e_int 1 in + expect_eq_n program "main" input expected + in + let%bind () = + let input _ = e_constructor "Baz" (e_unit ()) in + let expected _ = e_int (-1) in + expect_eq_n program "main" input expected + in + ok () + let main = test_suite "Integration (End to End)" [ test "bytes unpack" bytes_unpack ; test "key hash" key_hash ; @@ -1973,4 +2015,7 @@ let main = test_suite "Integration (End to End)" [ test "type tuple destruct (mligo)" type_tuple_destruct ; test "let in multi-bind (mligo)" let_in_multi_bind ; test "tuple param destruct (mligo)" tuple_param_destruct ; + test "empty case" empty_case ; + test "empty case (mligo)" empty_case_mligo ; + test "empty case (religo)" empty_case_religo ; ] From e834e2ac202a75d0eec2eca70a52d259bc5f535b Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Tue, 31 Dec 2019 19:14:42 +0100 Subject: [PATCH 41/43] More informative errors when calling michelson typecheck function --- src/main/compile/of_michelson.ml | 35 ++++++++++++++++--- .../proto-alpha-utils/x_memory_proto_alpha.ml | 16 +++++++-- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/main/compile/of_michelson.ml b/src/main/compile/of_michelson.ml index 5e73d07c2..5b80fc993 100644 --- a/src/main/compile/of_michelson.ml +++ b/src/main/compile/of_michelson.ml @@ -2,20 +2,45 @@ open Tezos_utils open Proto_alpha_utils open Trace +module Errors = struct + let title_type_check_msg () = "Invalid contract" + let bad_parameter () = + let message () = + "bad contract parameter type (some michelson type are forbidden as contract parameter)" in + error title_type_check_msg message + let bad_storage () = + let message () = + "bad storage type (some michelson type are forbidden as contract storage)" in + error title_type_check_msg message + let bad_contract () = + let message () = + "bad contract type (contract entry point is expected to be of the form `parameter * storage -> list(operation) * storage`)" in + error title_type_check_msg message + let unknown () = + let message () = + "unknown error" in + error title_type_check_msg message +end + let build_contract : Compiler.compiled_expression -> Michelson.michelson result = fun compiled -> let%bind ((Ex_ty _param_ty),(Ex_ty _storage_ty)) = Self_michelson.fetch_contract_inputs compiled.expr_ty in let%bind param_michelson = - Trace.trace_tzresult_lwt (simple_error "Invalid contract: Could not unparse parameter") @@ + Trace.trace_tzresult_lwt (simple_error "Could not unparse parameter") @@ Proto_alpha_utils.Memory_proto_alpha.unparse_ty_michelson _param_ty in let%bind storage_michelson = - Trace.trace_tzresult_lwt (simple_error "Invalid contract: Could not unparse storage") @@ + Trace.trace_tzresult_lwt (simple_error "Could not unparse storage") @@ Proto_alpha_utils.Memory_proto_alpha.unparse_ty_michelson _storage_ty in let contract = Michelson.contract param_michelson storage_michelson compiled.expr in - let%bind () = - Trace.trace_tzresult_lwt (simple_error "Invalid contract: Contract did not typecheck") @@ + let%bind res = + Trace.trace_tzresult_lwt (simple_error "Could not typecheck the code") @@ Proto_alpha_utils.Memory_proto_alpha.typecheck_contract contract in - ok contract + match res with + | Type_checked -> ok contract + | Err_parameter -> fail @@ Errors.bad_parameter () + | Err_storage -> fail @@ Errors.bad_storage () + | Err_contract -> fail @@ Errors.bad_contract () + | Err_unknown -> fail @@ Errors.unknown () type check_type = Check_parameter | Check_storage let assert_equal_contract_type : check_type -> Compiler.compiled_expression -> Compiler.compiled_expression -> unit result = diff --git a/vendors/ligo-utils/proto-alpha-utils/x_memory_proto_alpha.ml b/vendors/ligo-utils/proto-alpha-utils/x_memory_proto_alpha.ml index d47b85086..c613c86a4 100644 --- a/vendors/ligo-utils/proto-alpha-utils/x_memory_proto_alpha.ml +++ b/vendors/ligo-utils/proto-alpha-utils/x_memory_proto_alpha.ml @@ -1103,10 +1103,20 @@ let unparse_ty_michelson ty = Script_ir_translator.unparse_ty dummy_environment.tezos_context ty >>=?? fun (n,_) -> return n +type typecheck_res = + | Type_checked + | Err_parameter | Err_storage | Err_contract + | Err_unknown + let typecheck_contract contract = let contract' = Tezos_micheline.Micheline.strip_locations contract in - Script_ir_translator.typecheck_code dummy_environment.tezos_context contract' >>=?? - fun _ -> return () + Script_ir_translator.typecheck_code dummy_environment.tezos_context contract' >>= fun x -> + match x with + | Ok _res -> return Type_checked + | Error (Script_tc_errors.Ill_formed_type (Some "parameter", _code, _)::_) -> return Err_parameter + | Error (Script_tc_errors.Ill_formed_type (Some "storage", _code, _)::_) -> return Err_storage + | Error (Script_tc_errors.Ill_typed_contract (_code, _)::_) -> return @@ Err_contract + | Error _ -> return Err_unknown let assert_equal_michelson_type ty1 ty2 = (* alpha_wrap (Script_ir_translator.ty_eq tezos_context a b) >>? fun (Eq, _) -> *) @@ -1117,7 +1127,7 @@ type 'a interpret_res = | Fail of Script_repr.expr let failure_interpret - ?(options = default_options) + ?(options = default_options) (instr:('a, 'b) descr) (bef:'a stack) : 'b interpret_res tzresult Lwt.t = let { From 5108b820cf7f7057836e1dd93b76113bc7578562 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 1 Jan 2020 14:15:49 -0800 Subject: [PATCH 42/43] Fix minor typos in wrong michelson contract parameter/storage msgs --- src/main/compile/of_michelson.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/compile/of_michelson.ml b/src/main/compile/of_michelson.ml index 5b80fc993..8aff10104 100644 --- a/src/main/compile/of_michelson.ml +++ b/src/main/compile/of_michelson.ml @@ -6,15 +6,15 @@ module Errors = struct let title_type_check_msg () = "Invalid contract" let bad_parameter () = let message () = - "bad contract parameter type (some michelson type are forbidden as contract parameter)" in + "bad contract parameter type (some michelson types are forbidden as contract parameter)" in error title_type_check_msg message let bad_storage () = let message () = - "bad storage type (some michelson type are forbidden as contract storage)" in + "bad storage type (some michelson types are forbidden as contract storage)" in error title_type_check_msg message let bad_contract () = let message () = - "bad contract type (contract entry point is expected to be of the form `parameter * storage -> list(operation) * storage`)" in + "bad contract type (contract entry point is expected to be of the form \"parameter * storage -> list(operation) * storage\")" in error title_type_check_msg message let unknown () = let message () = @@ -32,7 +32,7 @@ let build_contract : Compiler.compiled_expression -> Michelson.michelson result Trace.trace_tzresult_lwt (simple_error "Could not unparse storage") @@ Proto_alpha_utils.Memory_proto_alpha.unparse_ty_michelson _storage_ty in let contract = Michelson.contract param_michelson storage_michelson compiled.expr in - let%bind res = + let%bind res = Trace.trace_tzresult_lwt (simple_error "Could not typecheck the code") @@ Proto_alpha_utils.Memory_proto_alpha.typecheck_contract contract in match res with @@ -54,4 +54,4 @@ let assert_equal_contract_type : check_type -> Compiler.compiled_expression -> C let%bind _ = Trace.trace_tzresult (simple_error "Passed parameter does not match the contract type") @@ Proto_alpha_utils.Memory_proto_alpha.assert_equal_michelson_type expected_ty actual_ty in - ok () \ No newline at end of file + ok () From 72f4ed35f15aee65be82d87e4f9bcba931ce8d69 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 2 Jan 2020 12:31:10 +0100 Subject: [PATCH 43/43] print ill-typed michelson code --- src/main/compile/of_michelson.ml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/compile/of_michelson.ml b/src/main/compile/of_michelson.ml index 8aff10104..0b070fb79 100644 --- a/src/main/compile/of_michelson.ml +++ b/src/main/compile/of_michelson.ml @@ -3,18 +3,26 @@ open Proto_alpha_utils open Trace module Errors = struct - let title_type_check_msg () = "Invalid contract" - let bad_parameter () = +(* + TODO: those errors should have been caught in the earlier stages on the ligo pipeline + Here, in case of contract not typechecking, we should write a warning with a "please report" + on stderr and print the ill-typed michelson code; +*) + let title_type_check_msg () = "Invalid contract (This might be a compiler bug, please report) " + let bad_parameter c () = let message () = - "bad contract parameter type (some michelson types are forbidden as contract parameter)" in + let code = Format.asprintf "%a" Michelson.pp c in + "bad contract parameter type (some michelson types are forbidden as contract parameter):\n"^code in error title_type_check_msg message - let bad_storage () = + let bad_storage c () = let message () = - "bad storage type (some michelson types are forbidden as contract storage)" in + let code = Format.asprintf "%a" Michelson.pp c in + "bad storage type (some michelson types are forbidden as contract storage):\n"^code in error title_type_check_msg message - let bad_contract () = + let bad_contract c () = let message () = - "bad contract type (contract entry point is expected to be of the form \"parameter * storage -> list(operation) * storage\")" in + let code = Format.asprintf "%a" Michelson.pp c in + "bad contract type (contract entry point is expected to be of the form \"parameter * storage -> list(operation) * storage\"):\n"^code in error title_type_check_msg message let unknown () = let message () = @@ -37,9 +45,9 @@ let build_contract : Compiler.compiled_expression -> Michelson.michelson result Proto_alpha_utils.Memory_proto_alpha.typecheck_contract contract in match res with | Type_checked -> ok contract - | Err_parameter -> fail @@ Errors.bad_parameter () - | Err_storage -> fail @@ Errors.bad_storage () - | Err_contract -> fail @@ Errors.bad_contract () + | Err_parameter -> fail @@ Errors.bad_parameter contract () + | Err_storage -> fail @@ Errors.bad_storage contract () + | Err_contract -> fail @@ Errors.bad_contract contract () | Err_unknown -> fail @@ Errors.unknown () type check_type = Check_parameter | Check_storage