From dbda9df3216cf6e21178a0fd3e301b4af622150e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20=C5=A0ima?= Date: Sat, 9 Nov 2019 14:40:53 +0000 Subject: [PATCH 1/9] Feature/fix docs --- .../{language-basics => api}/cheat-sheet.md | 0 .../cli-commands.md} | 2 +- .../docs/language-basics/boolean-if-else.md | 8 ++-- .../docs/language-basics/entrypoints.md | 46 ------------------- .../docs/language-basics/maps-records.md | 8 ++-- .../get-started/tezos-taco-shop-payout.md | 2 +- .../tezos-taco-shop-smart-contract.md | 4 +- .../blog/2019-06-13-public-launch-of-ligo.md | 2 +- gitlab-pages/website/core/Footer.js | 8 ++-- gitlab-pages/website/pages/en/index.js | 2 +- gitlab-pages/website/pages/en/versions.js | 6 +-- gitlab-pages/website/sidebars.json | 6 ++- 12 files changed, 25 insertions(+), 69 deletions(-) rename gitlab-pages/docs/{language-basics => api}/cheat-sheet.md (100%) rename gitlab-pages/docs/{api-cli-commands.md => api/cli-commands.md} (97%) delete mode 100644 gitlab-pages/docs/language-basics/entrypoints.md diff --git a/gitlab-pages/docs/language-basics/cheat-sheet.md b/gitlab-pages/docs/api/cheat-sheet.md similarity index 100% rename from gitlab-pages/docs/language-basics/cheat-sheet.md rename to gitlab-pages/docs/api/cheat-sheet.md diff --git a/gitlab-pages/docs/api-cli-commands.md b/gitlab-pages/docs/api/cli-commands.md similarity index 97% rename from gitlab-pages/docs/api-cli-commands.md rename to gitlab-pages/docs/api/cli-commands.md index aa75e3a0b..1e4a88fce 100644 --- a/gitlab-pages/docs/api-cli-commands.md +++ b/gitlab-pages/docs/api/cli-commands.md @@ -1,5 +1,5 @@ --- -id: api-cli-commands +id: cli-commands title: CLI Commands --- diff --git a/gitlab-pages/docs/language-basics/boolean-if-else.md b/gitlab-pages/docs/language-basics/boolean-if-else.md index fd4384c29..a2059b697 100644 --- a/gitlab-pages/docs/language-basics/boolean-if-else.md +++ b/gitlab-pages/docs/language-basics/boolean-if-else.md @@ -82,14 +82,14 @@ let h: bool = (a =/= b) ```pascaligo -const a: tez = 5mtz; -const b: tez = 10mtz; +const a: tez = 5mutez; +const b: tez = 10mutez; const c: bool = (a = b); ``` ```cameligo -let a: tez = 5mtz -let b: tez = 10mtz +let a: tez = 5mutez +let b: tez = 10mutez // false let c: bool = (a = b) ``` diff --git a/gitlab-pages/docs/language-basics/entrypoints.md b/gitlab-pages/docs/language-basics/entrypoints.md deleted file mode 100644 index fca89e7db..000000000 --- a/gitlab-pages/docs/language-basics/entrypoints.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: entrypoints -title: Entrypoints ---- - -Entrypoints are the gates to a smart contract. In LIGO each entrypoint is a function that accepts two arguments. The first is the parameter used to invoke the contract, and the second is the current storage of the contract. Each entrypoint must return a list of operations to apply as a result of the smart contract call, and a new storage value. - -> If you don't want to update the storage, don't worry, just re-cycle your last storage value. - -## Defining an entry point - -The contract below is effectively an empty contract. It takes a `unit` as a parameter, and returns a `unit`. - - - -```pascaligo -function main (const p : unit ; const s : unit) : (list(operation) * unit) is - block {skip} with ((nil : list(operation)), s) -``` - - -## Multiple entry points - -Multiple entrypoints are currently not supported in Michelson. But with Ligo you can work around that by using variants & pattern matching. - -In the example below we have a simple counter contract, that can be either `Increment(int)`-ed, or `Decrement(int)`-ed. - - - -```pascaligo -// variant defining pseudo multi-entrypoint actions -type action is -| Increment of int -| Decrement of int - -// real entrypoint that re-routes the flow based on the action (parameter) provided -function main (const action: action ; const counter: int) : (list(operation) * int) is - block {skip} with ((nil : list(operation)), - case action of - | Increment(number) -> counter + number - | Decrement(number) -> counter - number - end) -``` - - - diff --git a/gitlab-pages/docs/language-basics/maps-records.md b/gitlab-pages/docs/language-basics/maps-records.md index b81dfd8c7..96a5bca9b 100644 --- a/gitlab-pages/docs/language-basics/maps-records.md +++ b/gitlab-pages/docs/language-basics/maps-records.md @@ -31,8 +31,8 @@ And here's how a map value is populated: ```pascaligo const ledger: ledger = map - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> 1000mtz; - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> 2000mtz; + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> 1000mutez; + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> 2000mutez; end ``` > Notice the `->` between the key and its value and `;` to separate individual map entries. @@ -43,8 +43,8 @@ end ```cameligo let ledger: ledger = Map.literal - [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), 1000mtz) ; - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), 2000mtz) ; + [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), 1000mutez) ; + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), 2000mutez) ; ] ``` > Map.literal constructs the map from a list of key-value pair tuples, `(, )`. 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 ffc6e5687..9ca0346eb 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 @@ -72,7 +72,7 @@ const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"; const receiver : contract(unit) = get_contract(ownerAddress); ``` -> Would you like to learn more about addresses, contracts and operations in LIGO? Check out the [LIGO cheat sheet](language-basics/cheat-sheet.md) +> Would you like to learn more about addresses, contracts and operations in LIGO? Check out the [LIGO cheat sheet](api/cheat-sheet.md) ### Adding the transaction to the list of output operations 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. 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 59ea39198..5a48d0b08 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 @@ -57,7 +57,7 @@ current_purchase_price = max_price / available_stock ## Installing LIGO -In this tutorial, we'll use LIGO's dockerized version for the sake of simplicity. You can find the installation instructions [here](setup/installation.md#dockerized-installation-recommended). +In this tutorial, we'll use LIGO's dockerized version for the sake of simplicity. You can find the installation instructions [here](intro/installation.md#dockerized-installation-recommended). The best way to install the dockerized LIGO is as a **global executable** through the installation script, as shown in the screenshot below: @@ -66,7 +66,7 @@ The best way to install the dockerized LIGO is as a **global executable** throug ## Implementing our first entry point -> From now on we'll get a bit more technical. If you run into something we have not covered yet - please try checking out the [LIGO cheat sheet](language-basics/cheat-sheet.md) for some extra tips & tricks. +> From now on we'll get a bit more technical. If you run into something we have not covered yet - please try checking out the [LIGO cheat sheet](api/cheat-sheet.md) for some extra tips & tricks. 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. diff --git a/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md b/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md index c59729ff7..fb6373d46 100644 --- a/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md +++ b/gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md @@ -15,7 +15,7 @@ The core language is being developed by The Marigold Project. George Dupéron an Our previous Medium posts about LIGO can be found [here](https://medium.com/tezos/introducing-ligo-a-new-smart-contract-language-for-tezos-233fa17f21c7) and [here](https://medium.com/tezos/ligo-becomes-polyglot-a474e2cb0c24). ## The State of LIGO -Today, we are publicly releasing LIGO in beta\*. We've focused on making the onboarding process for LIGO as painless as possible and encourage you to check out our [tutorials](/docs/tutorials/get-started/tezos-taco-shop-smart-contract) and [documentation](https://ligolang.org/docs/next/setup/installation). +Today, we are publicly releasing LIGO in beta\*. We've focused on making the onboarding process for LIGO as painless as possible and encourage you to check out our [tutorials](/docs/tutorials/get-started/tezos-taco-shop-smart-contract) and [documentation](https://ligolang.org/docs/next/intro/installation). We are fixing bugs and adding features to LIGO (e.g. some Michelson primitives like iterators are missing) by the day. Please submit issues about bugs and missing features you need when you encounter them, and you just might find those solved in the following week. diff --git a/gitlab-pages/website/core/Footer.js b/gitlab-pages/website/core/Footer.js index d5f79c25b..561b47836 100644 --- a/gitlab-pages/website/core/Footer.js +++ b/gitlab-pages/website/core/Footer.js @@ -28,13 +28,13 @@ class Footer extends React.Component {
Docs
- + Installation - + CLI Commands - + Contribute @@ -59,7 +59,7 @@ class Footer extends React.Component {
diff --git a/gitlab-pages/website/pages/en/index.js b/gitlab-pages/website/pages/en/index.js index 7f2cf0fde..3cbc9da91 100644 --- a/gitlab-pages/website/pages/en/index.js +++ b/gitlab-pages/website/pages/en/index.js @@ -196,7 +196,7 @@ class HomeSplash extends React.Component { Try Online Get Started diff --git a/gitlab-pages/website/pages/en/versions.js b/gitlab-pages/website/pages/en/versions.js index 6abeaa02e..4ea4a4f4f 100644 --- a/gitlab-pages/website/pages/en/versions.js +++ b/gitlab-pages/website/pages/en/versions.js @@ -37,7 +37,7 @@ function Versions(props) { + }intro/installation`}> Documentation @@ -61,7 +61,7 @@ function Versions(props) { + }next/intro/installation`}> Documentation @@ -86,7 +86,7 @@ function Versions(props) { + }${version}/intro/installation`}> Documentation diff --git a/gitlab-pages/website/sidebars.json b/gitlab-pages/website/sidebars.json index 71827e978..13ce03e4e 100644 --- a/gitlab-pages/website/sidebars.json +++ b/gitlab-pages/website/sidebars.json @@ -2,7 +2,6 @@ "docs": { "Intro": ["intro/what-and-why", "intro/installation", "intro/editor-support"], "Language Basics": [ - "language-basics/cheat-sheet", "language-basics/types", "language-basics/constants-and-variables", "language-basics/math-numbers-tez", @@ -18,7 +17,10 @@ "advanced/entrypoints-contracts", "advanced/first-contract" ], - "API": ["api-cli-commands"] + "API": [ + "api/cli-commands", + "api/cheat-sheet" + ] }, "contributors-docs": { "Introduction": [ From aa231cec27fc3b73ca9560e70cadee7f37f834e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20=C5=A0ima?= Date: Sat, 9 Nov 2019 22:34:20 +0000 Subject: [PATCH 2/9] Feature/smaller docker image --- .dockerignore | 1 - .gitlab-ci.yml | 11 ++++++----- dist/.gitignore | 4 ---- docker/distribution/debian/distribute.Dockerfile | 9 +++++++++ docker/distribution/debian/package.Dockerfile | 2 +- scripts/build_docker_image.sh | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) delete mode 100644 dist/.gitignore diff --git a/.dockerignore b/.dockerignore index ccf03db24..b20e30eb1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,3 @@ -dist _opam _build docker diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9589ea238..2aa87413e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,10 +5,10 @@ variables: package_binary_script: "./scripts/distribution/generic/package.sh" stages: - - build_docker - test - - build_and_deploy_docker - build_and_package_binaries + - build_docker + - build_and_deploy_docker - build_and_deploy_website .build_binary: &build_binary @@ -19,9 +19,6 @@ stages: artifacts: paths: - dist/package/**/* - only: - - master - - dev .website_build: &website_build stage: build_and_deploy_website @@ -92,6 +89,8 @@ local-dune-job: # Run a docker build without publishing to the registry build-current-docker-image: stage: build_docker + dependencies: + - build-and-package-debian-10 <<: *docker script: - sh scripts/build_docker_image.sh @@ -105,6 +104,8 @@ build-current-docker-image: build-and-publish-latest-docker-image: stage: build_and_deploy_docker <<: *docker + dependencies: + - build-and-package-debian-10 script: - sh scripts/build_docker_image.sh - sh scripts/test_cli.sh diff --git a/dist/.gitignore b/dist/.gitignore deleted file mode 100644 index 86d0cb272..000000000 --- a/dist/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/docker/distribution/debian/distribute.Dockerfile b/docker/distribution/debian/distribute.Dockerfile index e69de29bb..ad4fbbeec 100644 --- a/docker/distribution/debian/distribute.Dockerfile +++ b/docker/distribution/debian/distribute.Dockerfile @@ -0,0 +1,9 @@ +FROM jgoerzen/debian-base-minimal:buster + +COPY ./dist/package/debian-10 /package/dist + +RUN apt-get update -qq +RUN apt-get -y -f install "/package/dist/$(ls /package/dist)" +RUN rm -r /package/dist + +ENTRYPOINT [ "ligo" ] \ No newline at end of file diff --git a/docker/distribution/debian/package.Dockerfile b/docker/distribution/debian/package.Dockerfile index 440496521..6debfad84 100644 --- a/docker/distribution/debian/package.Dockerfile +++ b/docker/distribution/debian/package.Dockerfile @@ -19,7 +19,7 @@ RUN echo "Package: ligo\n\ Version: $version\n\ Architecture: all\n\ Maintainer: info@ligolang.org\n\ -Depends: libev-dev, perl, pkg-config, libgmp-dev, libhidapi-dev, m4, libcap-dev, bubblewrap, rsync\n\ +Depends: libev4, libgmp10, libgmpxx4ldbl, cpp\n\ Homepage: http://ligolang.org\n\ Description: LIGO is a statically typed high-level smart-contract language that compiles down to Michelson." >> /package/DEBIAN/control diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh index 21e3a2bf5..260a530c7 100755 --- a/scripts/build_docker_image.sh +++ b/scripts/build_docker_image.sh @@ -1,3 +1,3 @@ #!/bin/sh set -e -docker build --build-arg target="4.07" -t "${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next" -f ./docker/distribution/generic/build.Dockerfile . +docker build -t "${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next" -f ./docker/distribution/debian/distribute.Dockerfile . \ No newline at end of file From f91de985d0b7d1ab043948635ccdaada7cb50a65 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Tue, 12 Nov 2019 14:28:58 +0000 Subject: [PATCH 3/9] remove 'Access_Map' --- src/passes/3-self_ast_simplified/helpers.ml | 52 ++++++--------------- src/passes/4-typer-new/solver.ml | 15 ------ src/passes/4-typer-new/typer.ml | 19 -------- src/passes/4-typer-new/typer.ml.old | 9 ---- src/passes/4-typer-old/typer.ml | 18 ------- src/passes/6-transpiler/transpiler.ml | 1 - src/stages/ast_simplified/PP.ml | 1 - src/stages/ast_simplified/combinators.ml | 3 +- src/stages/ast_simplified/types.ml | 1 - src/stages/ast_typed/PP.ml | 1 - src/stages/ast_typed/types.ml | 1 - 11 files changed, 16 insertions(+), 105 deletions(-) diff --git a/src/passes/3-self_ast_simplified/helpers.ml b/src/passes/3-self_ast_simplified/helpers.ml index 04b641f87..7044f3f63 100644 --- a/src/passes/3-self_ast_simplified/helpers.ml +++ b/src/passes/3-self_ast_simplified/helpers.ml @@ -8,26 +8,25 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini match e.expression with | E_literal _ | E_variable _ | E_skip -> ok init' | E_list lst | E_set lst | E_tuple lst | E_constant (_ , lst) -> ( - let%bind res' = bind_fold_list self init' lst in - ok res' + let%bind res = bind_fold_list self init' lst in + ok res ) | E_map lst | E_big_map lst -> ( - let%bind res' = bind_fold_list (bind_fold_pair self) init' lst in - ok res' + let%bind res = bind_fold_list (bind_fold_pair self) init' lst in + ok res ) | E_look_up ab | E_sequence ab | E_loop ab | E_application ab -> ( - let%bind res' = bind_fold_pair self init' ab in - ok res' + let%bind res = bind_fold_pair self init' ab in + ok res ) | E_lambda { binder = _ ; input_type = _ ; output_type = _ ; result = e } | E_annotation (e , _) | E_constructor (_ , e) -> ( - let%bind res' = self init' e in - ok res' + let%bind res = self init' e in + ok res ) - | E_assign (_ , path , e) | E_accessor (e , path) -> ( - let%bind res' = fold_path f init' path in - let%bind res' = self res' e in - ok res' + | E_assign (_ , _path , e) | E_accessor (e , _path) -> ( + let%bind res = self init' e in + ok res ) | E_matching (e , cases) -> ( let%bind res = self init' e in @@ -36,8 +35,8 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini ) | E_record m -> ( let aux init'' _ expr = - let%bind res' = fold_expression self init'' expr in - ok res' + let%bind res = fold_expression self init'' expr in + ok res in let%bind res = bind_fold_smap aux (ok init') m in ok res @@ -48,16 +47,6 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini ok res ) -and fold_path : 'a folder -> 'a -> access_path -> 'a result = fun f init p -> bind_fold_list (fold_access f) init p - -and fold_access : 'a folder -> 'a -> access -> 'a result = fun f init a -> - match a with - | Access_map e -> ( - let%bind e' = fold_expression f init e in - ok e' - ) - | _ -> ok init - and fold_cases : 'a folder -> 'a -> matching_expr -> 'a result = fun f init m -> match m with | Match_bool { match_true ; match_false } -> ( @@ -127,8 +116,7 @@ let rec map_expression : mapper -> expression -> expression result = fun f e -> ) | E_assign (name , path , e) -> ( let%bind e' = self e in - let%bind path' = map_path f path in - return @@ E_assign (name , path' , e') + return @@ E_assign (name , path , e') ) | E_matching (e , cases) -> ( let%bind e' = self e in @@ -137,8 +125,7 @@ let rec map_expression : mapper -> expression -> expression result = fun f e -> ) | E_accessor (e , path) -> ( let%bind e' = self e in - let%bind path' = map_path f path in - return @@ E_accessor (e' , path') + return @@ E_accessor (e' , path) ) | E_record m -> ( let%bind m' = bind_map_smap self m in @@ -171,15 +158,6 @@ let rec map_expression : mapper -> expression -> expression result = fun f e -> ) | E_literal _ | E_variable _ | E_skip as e' -> return e' -and map_path : mapper -> access_path -> access_path result = fun f p -> bind_map_list (map_access f) p - -and map_access : mapper -> access -> access result = fun f a -> - match a with - | Access_map e -> ( - let%bind e' = map_expression f e in - ok @@ Access_map e' - ) - | a -> ok a and map_cases : mapper -> matching_expr -> matching_expr result = fun f m -> match m with diff --git a/src/passes/4-typer-new/solver.ml b/src/passes/4-typer-new/solver.ml index f134ddf6e..af7a68c38 100644 --- a/src/passes/4-typer-new/solver.ml +++ b/src/passes/4-typer-new/solver.ml @@ -150,7 +150,6 @@ module Wrap = struct (* let t_literal_t = t *) let t_literal_bool = bool let t_literal_string = string - let t_access_map = forall2 "k" "v" @@ fun k v -> map k v --> k --> v let t_application = forall2 "a" "b" @@ fun a b -> (a --> b) --> a --> b let t_look_up = forall2 "ind" "v" @@ fun ind v -> map ind v --> ind --> option v let t_sequence = forall "b" @@ fun b -> unit --> b --> b @@ -166,20 +165,6 @@ module Wrap = struct let access_int ~base ~index = access_label ~base ~label:(L_int index) let access_string ~base ~property = access_label ~base ~label:(L_string property) - let access_map : base:T.type_value -> key:T.type_value -> (constraints * T.type_name) = - let mk_map_type key_type element_type = - O.P_constant O.(C_map , [P_variable element_type; P_variable key_type]) in - fun ~base ~key -> - let key_type = Core.fresh_type_variable () in - let element_type = Core.fresh_type_variable () in - let base' = type_expression_to_type_value base in - let key' = type_expression_to_type_value key in - let base_expected = mk_map_type key_type element_type in - let expr_type = Core.fresh_type_variable () in - O.[C_equation (base' , base_expected); - C_equation (key' , P_variable key_type); - C_equation (P_variable expr_type , P_variable element_type)] , Type_name expr_type - let constructor : T.type_value -> T.type_value -> T.type_value -> (constraints * T.type_name) = fun t_arg c_arg sum -> diff --git a/src/passes/4-typer-new/typer.ml b/src/passes/4-typer-new/typer.ml index 6f7b82eea..ad7edacf9 100644 --- a/src/passes/4-typer-new/typer.ml +++ b/src/passes/4-typer-new/typer.ml @@ -191,15 +191,6 @@ module Errors = struct ] in error ~data title message () - let not_supported_yet (message : string) (ae : I.expression) () = - let title = (thunk "not supported yet") in - let message () = message in - let data = [ - ("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae) ; - ("location" , fun () -> Format.asprintf "%a" Location.pp ae.location) - ] in - error ~data title message () - let not_supported_yet_untranspile (message : string) (ae : O.expression) () = let title = (thunk "not supported yet") in let message () = message in @@ -491,14 +482,6 @@ and type_expression : environment -> Solver.state -> ?tv_opt:O.type_value -> I.e let wrapped = Wrap.access_string ~base:base'.type_annotation ~property in return_wrapped (E_record_accessor (base' , property)) state' wrapped ) - | E_accessor (base , [Access_map key_ae]) -> ( - let%bind (base' , state') = type_expression e state base in - let%bind (key_ae' , state'') = type_expression e state' key_ae in - let xyz = get_type_annotation key_ae' in - let wrapped = Wrap.access_map ~base:base'.type_annotation ~key:xyz in - return_wrapped (E_look_up (base' , key_ae')) state'' wrapped - ) - | E_accessor (_base , []) | E_accessor (_base , _ :: _ :: _) -> ( failwith "The simplifier should produce E_accessor with only a single path element, not a list of path elements." @@ -791,8 +774,6 @@ and type_expression : environment -> Solver.state -> ?tv_opt:O.type_value -> I.e Map.String.find_opt property m in ok (tv' , prec_path @ [O.Access_record property]) ) - | Access_map _ -> - fail @@ not_supported_yet "assign expressions with maps are not supported yet" ae in bind_fold_list aux (typed_name.type_value , []) path in let%bind (expr' , state') = type_expression e state expr in diff --git a/src/passes/4-typer-new/typer.ml.old b/src/passes/4-typer-new/typer.ml.old index dfd99cbbe..0e471a081 100644 --- a/src/passes/4-typer-new/typer.ml.old +++ b/src/passes/4-typer-new/typer.ml.old @@ -449,13 +449,6 @@ and type_expression : environment -> ?tv_opt:O.type_expression -> I.expression - @@ (fun () -> SMap.find property r_tv) in return (E_record_accessor (prev , property)) tv ) - | Access_map ae' -> ( - let%bind ae'' = type_expression e ae' in - let%bind (k , v) = get_t_map prev.type_annotation in - let%bind () = - Ast_typed.assert_type_expression_eq (k , get_type_annotation ae'') in - return (E_look_up (prev , ae'')) v - ) in trace (simple_info "accessing") @@ bind_fold_list aux e' path @@ -725,8 +718,6 @@ and type_expression : environment -> ?tv_opt:O.type_expression -> I.expression - Map.String.find_opt property m in ok (tv' , prec_path @ [O.Access_record property]) ) - | Access_map _ -> - fail @@ not_supported_yet "assign expressions with maps are not supported yet" ae in bind_fold_list aux (typed_name.type_expression , []) path in let%bind expr' = type_expression e expr in diff --git a/src/passes/4-typer-old/typer.ml b/src/passes/4-typer-old/typer.ml index 8abdca6db..cc9280531 100644 --- a/src/passes/4-typer-old/typer.ml +++ b/src/passes/4-typer-old/typer.ml @@ -191,15 +191,6 @@ module Errors = struct ] in error ~data title message () - let not_supported_yet (message : string) (ae : I.expression) () = - let title = (thunk "not suported yet") in - let message () = message in - let data = [ - ("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae) ; - ("location" , fun () -> Format.asprintf "%a" Location.pp ae.location) - ] in - error ~data title message () - let not_supported_yet_untranspile (message : string) (ae : O.expression) () = let title = (thunk "not suported yet") in let message () = message in @@ -450,13 +441,6 @@ and type_expression' : environment -> ?tv_opt:O.type_value -> I.expression -> O. @@ (fun () -> SMap.find property r_tv) in return (E_record_accessor (prev , property)) tv ) - | Access_map ae' -> ( - let%bind ae'' = type_expression' e ae' in - let%bind (k , v) = bind_map_or (get_t_map , get_t_big_map) prev.type_annotation in - let%bind () = - Ast_typed.assert_type_value_eq (k , get_type_annotation ae'') in - return (E_look_up (prev , ae'')) v - ) in trace (simple_info "accessing") @@ bind_fold_list aux e' path @@ -758,8 +742,6 @@ and type_expression' : environment -> ?tv_opt:O.type_value -> I.expression -> O. Map.String.find_opt property m in ok (tv' , prec_path @ [O.Access_record property]) ) - | Access_map _ -> - fail @@ not_supported_yet "assign expressions with maps are not supported yet" ae in bind_fold_list aux (typed_name.type_value , []) path in let%bind expr' = type_expression' e ~tv_opt:assign_tv expr in diff --git a/src/passes/6-transpiler/transpiler.ml b/src/passes/6-transpiler/transpiler.ml index f8dab5d8e..86bb79f3c 100644 --- a/src/passes/6-transpiler/transpiler.ml +++ b/src/passes/6-transpiler/transpiler.ml @@ -510,7 +510,6 @@ and transpile_annotated_expression (ae:AST.annotated_expression) : expression re (Map.String.find_opt prop ty_map) in ok (prop_in_ty_map, acc @ path') ) - | Access_map _k -> fail (corner_case ~loc:__LOC__ "no patch for map yet") in let%bind (_, path) = bind_fold_right_list aux (ty, []) path in let%bind expr' = transpile_annotated_expression expr in diff --git a/src/stages/ast_simplified/PP.ml b/src/stages/ast_simplified/PP.ml index b99e7e62e..d69dff9ae 100644 --- a/src/stages/ast_simplified/PP.ml +++ b/src/stages/ast_simplified/PP.ml @@ -82,7 +82,6 @@ and access ppf (a:access) = match a with | Access_tuple n -> fprintf ppf "%d" n | Access_record s -> fprintf ppf "%s" s - | Access_map s -> fprintf ppf "(%a)" expression s and access_path ppf (p:access_path) = fprintf ppf "%a" (list_sep access (const ".")) p diff --git a/src/stages/ast_simplified/combinators.ml b/src/stages/ast_simplified/combinators.ml index d50df9ba1..48bdbca08 100644 --- a/src/stages/ast_simplified/combinators.ml +++ b/src/stages/ast_simplified/combinators.ml @@ -148,8 +148,7 @@ let assert_e_accessor = fun t -> let get_access_record : access -> string result = fun a -> match a with - | Access_tuple _ - | Access_map _ -> simple_fail "not an access record" + | Access_tuple _ -> simple_fail "not an access record" | Access_record s -> ok s let get_e_pair = fun t -> diff --git a/src/stages/ast_simplified/types.ml b/src/stages/ast_simplified/types.ml index ca30d42b4..f066b3be2 100644 --- a/src/stages/ast_simplified/types.ml +++ b/src/stages/ast_simplified/types.ml @@ -81,7 +81,6 @@ and expression = { and access = | Access_tuple of int | Access_record of string - | Access_map of expr and access_path = access list diff --git a/src/stages/ast_typed/PP.ml b/src/stages/ast_typed/PP.ml index c60eec0dd..930fba72b 100644 --- a/src/stages/ast_typed/PP.ml +++ b/src/stages/ast_typed/PP.ml @@ -98,7 +98,6 @@ and matching : type a . (formatter -> a -> unit) -> _ -> a matching -> unit = fu and pre_access ppf (a:access) = match a with | Access_record n -> fprintf ppf ".%s" n | Access_tuple i -> fprintf ppf ".%d" i - | Access_map n -> fprintf ppf ".%a" annotated_expression n let declaration ppf (d:declaration) = match d with diff --git a/src/stages/ast_typed/types.ml b/src/stages/ast_typed/types.ml index ba34c433e..a818463f3 100644 --- a/src/stages/ast_typed/types.ml +++ b/src/stages/ast_typed/types.ml @@ -131,7 +131,6 @@ and literal = and access = | Access_tuple of int | Access_record of string - | Access_map of ae and access_path = access list From 273ec8c280cff3465c7859f9f7fd1a516f7bc2ff Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Tue, 12 Nov 2019 08:01:18 -0800 Subject: [PATCH 4/9] Add ability to access balance to PascaLIGO --- src/passes/operators/operators.ml | 1 + src/test/contracts/balance_constant.ligo | 11 +++++++++++ src/test/integration_tests.ml | 10 +++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/test/contracts/balance_constant.ligo diff --git a/src/passes/operators/operators.ml b/src/passes/operators/operators.ml index ac4d68bfc..2546357cb 100644 --- a/src/passes/operators/operators.ml +++ b/src/passes/operators/operators.ml @@ -64,6 +64,7 @@ module Simplify = struct ("int" , "INT") ; ("abs" , "ABS") ; ("amount" , "AMOUNT") ; + ("balance", "BALANCE") ; ("now" , "NOW") ; ("unit" , "UNIT") ; ("source" , "SOURCE") ; diff --git a/src/test/contracts/balance_constant.ligo b/src/test/contracts/balance_constant.ligo new file mode 100644 index 000000000..6f78d339a --- /dev/null +++ b/src/test/contracts/balance_constant.ligo @@ -0,0 +1,11 @@ +(** + +This test makes sure that the balance is accessible in PascaLIGO. +It's there to detect a regression of: https://gitlab.com/ligolang/ligo/issues/68 + +*) + +type storage is tez + +function main (const p : unit; const s: int) : list(operation) * storage is + ((nil : list(operation)), balance) diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index a971527aa..77bcc74a9 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -1151,6 +1151,13 @@ let website2_mligo () : unit result = expect_eq_n program "main" make_input make_expected let balance_constant () : unit result = + let%bind program = type_file "./contracts/balance_constant.ligo" in + let input = e_tuple [e_unit () ; e_mutez 0] in + let expected = e_tuple [e_list []; e_mutez 4000000000000] in + expect_eq program "main" input expected + + +let balance_constant_mligo () : unit result = let%bind program = mtype_file "./contracts/balance_constant.mligo" in let input = e_tuple [e_unit () ; e_mutez 0] in let expected = e_tuple [e_list []; e_mutez 4000000000000] in @@ -1236,5 +1243,6 @@ let main = test_suite "Integration (End to End)" [ test "website1 ligo" website1_ligo ; test "website2 ligo" website2_ligo ; test "website2 (mligo)" website2_mligo ; - test "balance constant (mligo)" balance_constant ; + test "balance constant" balance_constant ; + test "balance constant (mligo)" balance_constant_mligo ; ] From 29a86ad4113a03c7524e21aead0a68045a894ad8 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Tue, 12 Nov 2019 17:07:09 +0000 Subject: [PATCH 5/9] Fix: deep access --- src/passes/4-typer-old/typer.ml | 17 ++++++++++++++--- src/stages/ast_simplified/types.ml | 1 + src/test/contracts/deep_access.ligo | 22 ++++++++++++++++++++++ src/test/contracts/simple_access.ligo | 21 +++++++++++++++++++++ src/test/integration_tests.ml | 13 +++++++++++++ 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 src/test/contracts/deep_access.ligo create mode 100644 src/test/contracts/simple_access.ligo diff --git a/src/passes/4-typer-old/typer.ml b/src/passes/4-typer-old/typer.ml index cc9280531..daaa684bf 100644 --- a/src/passes/4-typer-old/typer.ml +++ b/src/passes/4-typer-old/typer.ml @@ -432,18 +432,29 @@ and type_expression' : environment -> ?tv_opt:O.type_value -> I.expression -> O. let%bind tv = generic_try (bad_tuple_index index ae' prev.type_annotation ae.location) @@ (fun () -> List.nth tpl_tv index) in - return (E_tuple_accessor (prev , index)) tv + let location = ae.location in + ok @@ make_a_e ~location (E_tuple_accessor(prev , index)) tv e ) | Access_record property -> ( let%bind r_tv = get_t_record prev.type_annotation in let%bind tv = generic_try (bad_record_access property ae' prev.type_annotation ae.location) @@ (fun () -> SMap.find property r_tv) in - return (E_record_accessor (prev , property)) tv + let location = ae.location in + ok @@ make_a_e ~location (E_record_accessor (prev , property)) tv e ) in + let%bind ae = trace (simple_info "accessing") @@ - bind_fold_list aux e' path + bind_fold_list aux e' path in + (* check type annotation of the final accessed element *) + let%bind () = + match tv_opt with + | None -> ok () + | Some tv' -> O.assert_type_value_eq (tv' , ae.type_annotation) in + ok(ae) + + (* Sum *) | E_constructor (c, expr) -> let%bind (c_tv, sum_tv) = diff --git a/src/stages/ast_simplified/types.ml b/src/stages/ast_simplified/types.ml index f066b3be2..43302e44d 100644 --- a/src/stages/ast_simplified/types.ml +++ b/src/stages/ast_simplified/types.ml @@ -56,6 +56,7 @@ and expression' = | E_constructor of (name * expr) (* For user defined constructors *) (* E_record *) | E_record of expr_map + (* TODO: Change it to (expr * access) *) | E_accessor of (expr * access_path) (* Data Structures *) | E_map of (expr * expr) list diff --git a/src/test/contracts/deep_access.ligo b/src/test/contracts/deep_access.ligo new file mode 100644 index 000000000..bacbf3467 --- /dev/null +++ b/src/test/contracts/deep_access.ligo @@ -0,0 +1,22 @@ +//Test deep_access in PascalLigo +type pii is (int*int) +type ppi is record x:pii; y:pii end +type ppp is (ppi*ppi) + +function main (const toto : unit) : int is +var a : ppp := +( +record +x = (0,1); +y = (10,11); +end +, +record +x = (100,101); +y = (110,111); +end +) +begin + a.0.x.0 := 2; + const b:int = a.0.x.0; +end with b diff --git a/src/test/contracts/simple_access.ligo b/src/test/contracts/simple_access.ligo new file mode 100644 index 000000000..6cfa85a1e --- /dev/null +++ b/src/test/contracts/simple_access.ligo @@ -0,0 +1,21 @@ +//Test simple_access in PascalLigo +type tpi is (int*int) +type rpi is record +x : int; +y : int; +end +type mpi is map(string,int) + +function main (const toto : tpi) : int is + var a : tpi := toto; + var b : rpi := record x = 0; y=1 ; end; + var m : mpi := map "y" -> 1; end; + begin + a.0 := 2; + b.x := a.0; + m["x"] := b.x; + end with + case m["x"] of + | Some (s) -> s + | None -> 42 + end diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index a971527aa..c32aa3b01 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -1155,6 +1155,17 @@ let balance_constant () : unit result = let input = e_tuple [e_unit () ; e_mutez 0] in let expected = e_tuple [e_list []; e_mutez 4000000000000] in expect_eq program "main" input expected +let simple_access_ligo () : unit result = + let%bind program = type_file "./contracts/simple_access.ligo" in + let make_input = e_tuple [e_int 0; e_int 1] in + let make_expected = e_int 2 in + expect_eq program "main" make_input make_expected + +let deep_access_ligo () : unit result = + let%bind program = type_file "./contracts/deep_access.ligo" in + let make_input = e_unit () in + let make_expected = e_int 2 in + expect_eq program "main" make_input make_expected let main = test_suite "Integration (End to End)" [ test "type alias" type_alias ; @@ -1237,4 +1248,6 @@ let main = test_suite "Integration (End to End)" [ test "website2 ligo" website2_ligo ; test "website2 (mligo)" website2_mligo ; test "balance constant (mligo)" balance_constant ; + test "simple_access (ligo)" simple_access_ligo; + test "deep_access (ligo)" deep_access_ligo; ] From 5b60109606dd3d6de07080ba8a6bcab4da255f77 Mon Sep 17 00:00:00 2001 From: Tom Jack Date: Wed, 13 Nov 2019 13:43:03 -0600 Subject: [PATCH 6/9] Improve purity test for dead code elimination --- src/passes/7-self_mini_c/self_mini_c.ml | 62 ++++++++++++++++++++++--- src/stages/mini_c/misc.ml | 5 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/passes/7-self_mini_c/self_mini_c.ml b/src/passes/7-self_mini_c/self_mini_c.ml index 96f134c91..57831e93b 100644 --- a/src/passes/7-self_mini_c/self_mini_c.ml +++ b/src/passes/7-self_mini_c/self_mini_c.ml @@ -1,14 +1,62 @@ open Mini_c open Trace -(* Overly conservative for now: ok to treat pure things as impure, +(* Overly conservative purity test: ok to treat pure things as impure, must not treat impure things as pure. *) -let is_pure : expression -> bool = fun e -> - match e.content with - | E_closure _ -> true + +(* true if the name names a pure constant -- i.e. if uses will be pure + assuming arguments are pure *) +let is_pure_constant : string -> bool = + function + | "CAR" + | "CDR" + | "PAIR" + -> true + (* TODO... *) | _ -> false -let rec elim_dead_lambdas : expression -> expression result = fun e -> +let rec is_pure : expression -> bool = fun e -> + match e.content with + | E_literal _ + | E_closure _ + | E_skip + | E_variable _ + | E_make_empty_map _ + | E_make_empty_list _ + | E_make_empty_set _ + | E_make_none _ + -> true + + | E_if_bool (cond, bt, bf) + | E_if_none (cond, bt, (_, bf)) + | E_if_cons (cond, bt, (_, bf)) + | E_if_left (cond, (_, bt), (_, bf)) + -> List.for_all is_pure [ cond ; bt ; bf ] + + | E_let_in (_, e1, e2) + | E_sequence (e1, e2) + -> List.for_all is_pure [ e1 ; e2 ] + + | E_constant (c, args) + -> is_pure_constant c && List.for_all is_pure args + + (* I'm not sure about these. Maybe can be tested better? *) + | E_application _ + | E_iterator _ + | E_fold _ + -> false + + (* Could be pure, but, divergence is an effect, so halting problem + is near... *) + | E_while _ -> false + + (* definitely not pure *) + | E_assignment _ -> false + + +(* Eliminate dead `let` with pure rhs *) + +let rec elim_dead_code : expression -> expression result = fun e -> let changed = ref false in (* ugh *) let mapper : Helpers.mapper = fun e -> match e.content with @@ -22,8 +70,8 @@ let rec elim_dead_lambdas : expression -> expression result = fun e -> | _ -> ok e in let%bind e = Helpers.map_expression mapper e in if !changed - then elim_dead_lambdas e + then elim_dead_code e else ok e let all_expression : expression -> expression result = - elim_dead_lambdas + elim_dead_code diff --git a/src/stages/mini_c/misc.ml b/src/stages/mini_c/misc.ml index fb6d86449..0cc51fcd0 100644 --- a/src/stages/mini_c/misc.ml +++ b/src/stages/mini_c/misc.ml @@ -75,9 +75,8 @@ module Free_variables = struct expression (union (singleton v) b) body ; ] | E_sequence (x, y) -> union (self x) (self y) - (* we do not consider the assigned variable free... seems strange, - but, matches ast_typed, and does not cause any troubles? *) - | E_assignment (_, _, e) -> self e + (* NB different from ast_typed... *) + | E_assignment (v, _, e) -> unions [ var_name b v ; self e ] | E_while (cond , body) -> union (self cond) (self body) and var_name : bindings -> var_name -> bindings = fun b n -> From a73ede31e7371e914949df1ea4a2d0acbc0dbb9d Mon Sep 17 00:00:00 2001 From: Tom Jack Date: Fri, 15 Nov 2019 10:02:22 -0600 Subject: [PATCH 7/9] Work around upstream in-place update --- src/ligo.opam | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ligo.opam b/src/ligo.opam index deef07ad5..d83d0aa15 100644 --- a/src/ligo.opam +++ b/src/ligo.opam @@ -18,6 +18,8 @@ depends: [ "yojson" "alcotest" { with-test } "getopt" + # work around upstream in-place update + "ocaml-migrate-parsetree" { = "1.3.1" } ] build: [ [ "dune" "build" "-p" name "-j" jobs ] From 683bc0a72b1b521549d0659459b9e9d77699e280 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 15 Nov 2019 15:49:50 +0100 Subject: [PATCH 8/9] fix problems with nested for collection loop --- src/passes/2-simplify/pascaligo.ml | 40 ++++++++---------------------- src/test/contracts/loop.ligo | 34 ++++++++++++++----------- src/test/integration_tests.ml | 7 +++--- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/src/passes/2-simplify/pascaligo.ml b/src/passes/2-simplify/pascaligo.ml index e7863e4ba..6d2384e9a 100644 --- a/src/passes/2-simplify/pascaligo.ml +++ b/src/passes/2-simplify/pascaligo.ml @@ -116,17 +116,6 @@ module Errors = struct ] in error ~data title message - let unsupported_deep_access_for_collection for_col = - let title () = "deep access in loop over collection" in - let message () = - Format.asprintf "currently, we do not support deep \ - accesses in loops over collection" in - let data = [ - ("pattern_loc", - fun () -> Format.asprintf "%a" Location.pp_lift @@ for_col.Region.region) - ] in - error ~data title message - (* Logging *) let simplifying_instruction t = @@ -1047,10 +1036,8 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun (fun (prev : type_name list) (ass_exp : expression) -> match ass_exp.expression with | E_assign ( name , _ , _ ) -> - if (String.contains name '#') then - ok prev - else - ok (name::prev) + if (String.contains name '#') then ok prev + else ok (name::prev) | _ -> ok prev ) [] for_body in @@ -1063,12 +1050,13 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun match exp.expression with (* replace references to fold accumulator as rhs *) | E_assign ( name , path , expr ) -> ( - match path with - | [] -> ok @@ e_assign "#COMPILER#acc" [Access_record name] expr - (* This fails for deep accesses, see LIGO-131 LIGO-134 *) - | _ -> - (* ok @@ e_assign "#COMPILER#acc" ((Access_record name)::path) expr) *) - fail @@ unsupported_deep_access_for_collection fc.block ) + let path' = List.filter + ( fun el -> + match el with + | Access_record name -> not (String.contains name '#') + | _ -> true ) + ((Access_record name)::path) in + ok @@ e_assign "#COMPILER#acc" path' expr) | E_variable name -> ( if (List.mem name captured_name_list) then (* replace references to fold accumulator as lhs *) @@ -1107,16 +1095,10 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun let ( arg_access: Types.access_path -> expression ) = e_accessor (e_variable "arguments") in ( match fc.collection with | Map _ -> - (* let acc = arg_access [Access_tuple 0 ; Access_tuple 0] in + let acc = arg_access [Access_tuple 0 ] in let collec_elt_v = arg_access [Access_tuple 1 ; Access_tuple 0] in - let collec_elt_k = arg_access [Access_tuple 1 ; Access_tuple 1] in *) - (* The above should work, but not yet (see LIGO-131) *) - let temp_kv = arg_access [Access_tuple 1] in - let acc = arg_access [Access_tuple 0] in - let collec_elt_v = e_accessor (e_variable "#COMPILER#temp_kv") [Access_tuple 0] in - let collec_elt_k = e_accessor (e_variable "#COMPILER#temp_kv") [Access_tuple 1] in + let collec_elt_k = arg_access [Access_tuple 1 ; Access_tuple 1] in e_let_in ("#COMPILER#acc", None) acc @@ - e_let_in ("#COMPILER#temp_kv", None) temp_kv @@ e_let_in ("#COMPILER#collec_elt_k", None) collec_elt_v @@ e_let_in ("#COMPILER#collec_elt_v", None) collec_elt_k (for_body) | _ -> diff --git a/src/test/contracts/loop.ligo b/src/test/contracts/loop.ligo index ef3af8527..9640a864e 100644 --- a/src/test/contracts/loop.ligo +++ b/src/test/contracts/loop.ligo @@ -134,20 +134,26 @@ function for_collection_map_k (var nee : unit) : string is block { end } with st -// function nested_for_collection (var nee : unit) : (int*string) is block { -// var myint : int := 0; -// var myst : string := ""; -// var mylist : list(int) := list 1 ; 2 ; 3 end ; -// for i : int in list mylist -// begin -// myint := myint + i ; -// var myset : set(string) := set "1" ; "2" ; "3" end ; -// for st : string in set myset -// begin -// myst := myst ^ st ; -// end -// end -// } with (myint,myst) +function nested_for_collection (var nee : unit) : (int*string) is block { + var myint : int := 0; + var mystoo : string := ""; + var mylist : list(int) := list 1 ; 2 ; 3 end ; + var mymap : map(string,string) := map " one" -> "," ; "two" -> " " end ; + + for i in list mylist + begin + myint := myint + i ; + var myset : set(string) := set "1" ; "2" ; "3" end ; + for st in set myset + begin + mystoo := mystoo ^ st ; + for k -> v in map mymap + begin + mystoo := mystoo ^ k ^ v ; + end + end + end +} with (myint,mystoo) function dummy (const n : nat) : nat is block { while False block { skip } diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index 1c7eb60ae..7d44abdaa 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -812,9 +812,10 @@ let loop () : unit result = let%bind () = let expected = (e_int 20) in expect_eq program "for_collection_comp_with_acc" input expected in - (* let%bind () = - let expected = e_pair (e_int 6) (e_string "123123123") in - expect_eq program "nested_for_collection" input expected in *) + let%bind () = + let expected = e_pair (e_int 6) + (e_string "1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two ") in + expect_eq program "nested_for_collection" input expected in let%bind () = let ez lst = let open Ast_simplified.Combinators in From e689d3d3b7b3e8f0495635a02df2716f80cde8c1 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 15 Nov 2019 18:10:24 +0100 Subject: [PATCH 9/9] more doc --- src/passes/2-simplify/pascaligo.ml | 33 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/passes/2-simplify/pascaligo.ml b/src/passes/2-simplify/pascaligo.ml index 6d2384e9a..6c4629425 100644 --- a/src/passes/2-simplify/pascaligo.ml +++ b/src/passes/2-simplify/pascaligo.ml @@ -12,6 +12,7 @@ let pseq_to_list = function | None -> [] | Some lst -> npseq_to_list lst let get_value : 'a Raw.reg -> 'a = fun x -> x.value +let is_compiler_generated = fun name -> String.contains name '#' module Errors = struct let unsupported_cst_constr p = @@ -990,6 +991,16 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi -> 2) Detect the free variables and build a list of their names (myint and myst in the previous example) + Free variables are simply variables being assigned. + Note: In the case of a nested loops, assignements to a compiler + generated value (#COMPILER#acc) correspond to variables + that were already renamed in the inner loop. + e.g : + ``` + #COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt ; + #COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ; + ``` + They must not be considered as free variables 3) Build the initial record (later passed as 2nd argument of `MAP/SET/LIST_FOLD`) capturing the environment using the @@ -998,11 +1009,15 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi -> 4) In the filtered body of (1), replace occurences: - free variable of name X as rhs ==> accessor `#COMPILER#acc.X` - free variable of name X as lhs ==> accessor `#COMPILER#acc.X` - And, in the case of a map: - - references to the iterated key ==> variable `#COMPILER#elt_key` - - references to the iterated value ==> variable `#COMPILER#elt_value` - in the case of a set/list: - - references to the iterated value ==> variable `#COMPILER#elt` + And, in the case of a map: + - references to the iterated key ==> variable `#COMPILER#elt_key` + - references to the iterated value ==> variable `#COMPILER#elt_value` + in the case of a set/list: + - references to the iterated value ==> variable `#COMPILER#elt` + Note: In the case of an inner loop capturing variable from an outer loop + the free variable name can be `#COMPILER#acc.Y` and because we do not + capture the accumulator record in the inner loop, we don't want to + generate `#COMPILER#acc.#COMPILER#acc.Y` but `#COMPILER#acc.Y` 5) Append the return value to the body @@ -1036,7 +1051,7 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun (fun (prev : type_name list) (ass_exp : expression) -> match ass_exp.expression with | E_assign ( name , _ , _ ) -> - if (String.contains name '#') then ok prev + if is_compiler_generated name then ok prev else ok (name::prev) | _ -> ok prev ) [] @@ -1048,18 +1063,18 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun (* STEP 4 *) let replace exp = match exp.expression with - (* replace references to fold accumulator as rhs *) + (* replace references to fold accumulator as lhs *) | E_assign ( name , path , expr ) -> ( let path' = List.filter ( fun el -> match el with - | Access_record name -> not (String.contains name '#') + | Access_record name -> not @@ is_compiler_generated name | _ -> true ) ((Access_record name)::path) in ok @@ e_assign "#COMPILER#acc" path' expr) | E_variable name -> ( if (List.mem name captured_name_list) then - (* replace references to fold accumulator as lhs *) + (* replace references to fold accumulator as rhs *) ok @@ e_accessor (e_variable "#COMPILER#acc") [Access_record name] else match fc.collection with (* loop on map *)