diff --git a/.gitignore b/.gitignore
index d2d2464e1..7c9d772a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,9 +5,11 @@ cache/*
Version.ml
/_opam/
/*.pp.ligo
+/*.pp.mligo
+/*.pp.religo
**/.DS_Store
.vscode/
/ligo.install
*.coverage
/_coverage/
-/_coverage_*/
+/_coverage_*/
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6a41afad7..b5b1229ad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,13 +3,25 @@ variables:
GIT_SUBMODULE_STRATEGY: recursive
build_binary_script: "./scripts/distribution/generic/build.sh"
package_binary_script: "./scripts/distribution/generic/package.sh"
+ LIGO_REGISTRY_IMAGE_BASE_NAME: "${CI_PROJECT_PATH}/${CI_PROJECT_NAME}"
+ WEBIDE_IMAGE_NAME: "registry.gitlab.com/${CI_PROJECT_PATH}/ligo_webide"
stages:
- test
- build_and_package_binaries
- build_docker
- - build_and_deploy_docker
- - build_and_deploy_website
+ - build_and_deploy
+ - ide-build
+ - ide-e2e-test
+ - ide-deploy
+
+# TODO provide sensible CI for master
+dont-merge-to-master:
+ stage: test
+ script:
+ - "false"
+ only:
+ - master
.build_binary: &build_binary
# To run in sequence and save CPU usage, use stage: build_and_package_binaries
@@ -22,7 +34,7 @@ stages:
- dist/package/**/*
.website_build: &website_build
- stage: build_and_deploy_website
+ stage: build_and_deploy
image: node:8
dependencies:
- build-and-package-debian-9
@@ -30,6 +42,7 @@ stages:
- build-and-package-ubuntu-18-04
- build-and-package-ubuntu-19-04
before_script:
+ - export TERM=dumb
- scripts/install_native_dependencies.sh
- scripts/install_opam.sh # TODO: or scripts/install_build_environment.sh ?
- export PATH="/usr/local/bin${PATH:+:}${PATH:-}"
@@ -67,15 +80,16 @@ stages:
- public
.docker: &docker
- image: docker:1.11
+ image: docker:19
services:
- - docker:dind
+ - docker:19-dind
.before_script: &before_script
before_script:
# Install dependencies
# rsync is needed by opam to sync a package installed from a local directory with the copy in ~/.opam
+ - export TERM=dumb
- scripts/install_native_dependencies.sh
- scripts/install_opam.sh # TODO: or scripts/install_build_environment.sh ?
- export PATH="/usr/local/bin${PATH:+:}${PATH:-}"
@@ -95,6 +109,9 @@ local-dune-job:
artifacts:
paths:
- _coverage_all
+ only:
+ - merge_requests
+ - dev
# Run a docker build without publishing to the registry
build-current-docker-image:
@@ -105,24 +122,25 @@ build-current-docker-image:
script:
- sh scripts/build_docker_image.sh
- sh scripts/test_cli.sh
- except:
- - master
- - dev
+ only:
+ - merge_requests
# When a MR/PR is merged to dev
# take the previous build and publish it to Docker Hub
build-and-publish-latest-docker-image:
- stage: build_and_deploy_docker
+ stage: build_and_deploy
<<: *docker
dependencies:
- build-and-package-debian-10
script:
- sh scripts/build_docker_image.sh
- sh scripts/test_cli.sh
- - docker login -u $LIGO_REGISTRY_USER -p $LIGO_REGISTRY_PASSWORD
- - docker push $LIGO_REGISTRY_IMAGE:next
- only:
- - dev
+ - echo ${LIGO_REGISTRY_PASSWORD} | docker login -u ${LIGO_REGISTRY_USER} --password-stdin
+ - docker push ${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next
+ rules:
+ # Only deploy docker when from the dev branch AND on the canonical ligolang/ligo repository
+ - if: '$CI_COMMIT_REF_NAME == "dev" && $CI_PROJECT_PATH == "ligolang/ligo"'
+ when: always
# It'd be a good idea to generate those jobs dynamically,
# based on desired targets
@@ -130,46 +148,120 @@ build-and-package-debian-9:
<<: *docker
# To run in sequence and save CPU usage, use stage: build_and_package_binaries
stage: test
- variables:
+ variables:
target_os_family: "debian"
target_os: "debian"
target_os_version: "9"
<<: *build_binary
+ only:
+ - dev
build-and-package-debian-10:
<<: *docker
# To run in sequence and save CPU usage, use stage: build_and_package_binaries
stage: test
- variables:
+ variables:
target_os_family: "debian"
target_os: "debian"
target_os_version: "10"
<<: *build_binary
+ # this one is merge_requests and dev, because the debian 10 binary
+ # is used for build-current-docker-image and for
+ # build-and-publish-latest-docker-image
+ only:
+ - merge_requests
+ - dev
build-and-package-ubuntu-18-04:
<<: *docker
# To run in sequence and save CPU usage, use stage: build_and_package_binaries
stage: test
- variables:
+ variables:
target_os_family: "debian"
target_os: "ubuntu"
target_os_version: "18.04"
<<: *build_binary
+ only:
+ - dev
build-and-package-ubuntu-19-04:
<<: *docker
# To run in sequence and save CPU usage, use stage: build_and_package_binaries
stage: test
- variables:
+ variables:
target_os_family: "debian"
target_os: "ubuntu"
target_os_version: "19.04"
<<: *build_binary
+ only:
+ - dev
-# Pages are deployed from both master & dev, be careful not to override 'next'
+# Pages are deployed from dev, be careful not to override 'next'
# in case something gets merged into 'dev' while releasing.
pages:
<<: *website_build
+ rules:
+ - if: '$CI_COMMIT_REF_NAME == "dev" && $CI_PROJECT_PATH == "ligolang/ligo"'
+ when: always
+
+# WEBIDE jobs
+
+run-webide-unit-tests:
+ stage: test
+ image: node:12-alpine
+ script:
+ - cd tools/webide/packages/server
+ - npm ci
+ - npm run test
only:
- - master
- - dev
+ changes:
+ - tools/webide/**
+
+build-publish-ide-image:
+ stage: build_and_deploy
+ <<: *docker
+ script:
+ - ls -F
+ - find dist/
+ - find dist/package/ -name '*ligo_*deb'
+ - mv $(realpath dist/package/debian-10/*.deb) tools/webide/ligo_deb10.deb
+ - cd tools/webide
+ - echo "${CI_BUILD_TOKEN}" | docker login -u gitlab-ci-token --password-stdin registry.gitlab.com
+ - >
+ docker build
+ -t "${WEBIDE_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
+ --build-arg GIT_TAG="${CI_COMMIT_SHA}"
+ --build-arg GIT_COMMIT="${CI_COMMIT_SHORT_SHA}"
+ .
+ - docker push "${WEBIDE_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: always
+ - if: '$CI_COMMIT_REF_NAME == "dev"'
+ when: always
+
+run-webide-e2e-tests:
+ stage: ide-e2e-test
+ <<: *docker
+ image: tmaier/docker-compose
+ script:
+ - cd tools/webide/packages/e2e
+ - export WEBIDE_IMAGE="${WEBIDE_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
+ - docker-compose run e2e
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: always
+ - if: '$CI_COMMIT_REF_NAME == "dev"'
+ when: always
+
+deploy-handoff:
+ # Handoff deployment duties to private repo
+ stage: ide-deploy
+ variables:
+ IDE_DOCKER_IMAGE: "registry.gitlab.com/${CI_PROJECT_PATH}/ligo_webide"
+ LIGO_COMMIT_REF_NAME: "${CI_COMMIT_SHORT_SHA}"
+ trigger: ligolang/ligo-webide-deploy
+ rules:
+ - if: '$CI_COMMIT_REF_NAME == "dev"'
+ when: always
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc0b56a81..b40924f28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,18 @@
## [Unreleased]
+## [9164206ef1fcf3e577820442b5afbad92d03ffa4] - 2020-02-09
+### Changed
+- Mutation of variables inside lambdas passed to list_iter do not have effect anymore. Side-effects used to survive iterations of list_iter via a quirk in the Michelson list_iter. Now, either use a list_fold and explicitly pass through the updated variables (e.g. storage) to the next iteration, or use a `for` loop which automatically detects mutations within the loop body and lifts the affected variables to a record that is passed from iteration to iteration.
+
+## [Add crypto reference page to docs](https://gitlab.com/ligolang/ligo/-/merge_requests/370)
+### Changed
+- Corrected typo in CameLIGO/ReasonLIGO front end where Crypto.blake2b was 'Crypto.black2b'
+
## [Failwith do not fail](https://gitlab.com/ligolang/ligo/merge_requests/337) - 2020-01-17
### Added
- running failing code in `ligo interpret`, `ligo dry-run`, `ligo run-function` will no longer be an error (return value : 0)
-
+
## [1899dfe8d7285580b3aa30fab933ed589f8f1bc5] - 2020-01-08
### Added
- Partial application and OCaml-like currying behavior to CameLIGO & ReasonLIGO
diff --git a/gitlab-pages/docs/advanced/entrypoints-contracts.md b/gitlab-pages/docs/advanced/entrypoints-contracts.md
index 51942c01b..15fa7cb75 100644
--- a/gitlab-pages/docs/advanced/entrypoints-contracts.md
+++ b/gitlab-pages/docs/advanced/entrypoints-contracts.md
@@ -1,104 +1,240 @@
---
id: entrypoints-contracts
-title: Entrypoints, Contracts
+title: Access function and Entrypoints
---
-## Entrypoints
+## Access Functions
-Each LIGO smart contract is essentially a single function, that has the following *(pseudo)* type signature:
+A LIGO contract is made of a series of constant and function
+declarations. Only functions having a special type can be called when
+the contract is activated: we called them *access functions*. An
+access function takes two parameters, the *contract parameter* and the
+*on-chain storage*, and returns a pair made of a *list of operations*
+and a (new) storage.
+
+When the contract is originated, the initial value of the storage is
+provided. When an access function is later called, only the parameter
+is provided, but the type of an access function contains both.
+
+The type of the contract parameter and the storage are up to the
+contract designer, but the type for list operations is not. The return
+type of an access function is as follows, assuming that the type
+`storage` has been defined elsewhere. (Note that you can use any type
+with any name for the storage.)
-
-```
-(const parameter: my_type, const store: my_store_type): (list(operation), my_store_type)
+
+```pascaligo skip
+type storage is ... // Any name, any type
+type return is list (operation) * storage
```
-```
-(parameter, store: my_type * my_store_type) : operation list * my_store_type
+```cameligo skip
+type storage = ... // Any name, any type
+type return = operation list * storage
```
+```reasonligo skip
+type storage = ...; // Any name, any type
+type return = (list (operation), storage);
```
-(parameter_store: (my_type, my_store_type)) : (list(operation), my_store_type)
-```
-
-This means that every smart contract needs at least one entrypoint function, here's an example:
+The contract storage can only be modified by activating an access
+function. It is important to understand what that means. What it does
+*not* mean is that some global variable holding the storage is
+modified by the access function. Instead, what it *does* mean is that,
+given the state of the storage *on-chain*, an access function
+specifies how to create another state for it, depending on a
+parameter.
-> đź’ˇ The contract below literally does *nothing*
+Here is an example where the storage is a single natural number that
+is updated by the parameter.
-
+
+
+
```pascaligo group=a
-type parameter is unit;
-type store is unit;
-function main(const parameter: parameter; const store: store): (list(operation) * store) is
- block { skip } with ((nil : list(operation)), store)
+type parameter is nat
+type storage is nat
+type return is list (operation) * storage
+
+function save (const action : parameter; const store : storage) : return is
+ ((nil : list (operation)), store)
```
```cameligo group=a
-type parameter = unit
-type store = unit
-let main (parameter, store: parameter * store) : operation list * store =
- (([]: operation list), store)
+type parameter = nat
+type storage = nat
+type return = operation list * storage
+
+let save (action, store: parameter * storage) : return =
+ (([] : operation list), store)
```
```reasonligo group=a
-type parameter = unit;
-type store = unit;
-let main = ((parameter, store): (parameter, store)) : (list(operation), store) => {
- (([]: list(operation)), store);
-};
-```
+type parameter = nat;
+type storage = nat;
+type return = (list (operation), storage);
+let main = ((action, store): (parameter, storage)) : return =>
+ (([] : list (operation)), store);
+```
-Each entrypoint function receives two arguments:
-- `parameter` - this is the parameter received in the invocation operation
-- `storage` - this is the current (real) on-chain storage value
+## Entrypoints
-Storage can only be modified by running the smart contract entrypoint, which is responsible for returning a list of operations, and a new storage at the end of it's execution.
+In LIGO, the design pattern is to have *one* access function that
+dispatches the control flow according to its parameter. Those
+functions called for those actions are called *entrypoints*.
+As an analogy, in the C programming language, the `main` function is
+the unique access function and any function called from it would be an
+entrypoint.
-## Built-in contract variables
+The parameter of the contract is then a variant type, and, depending
+on the constructors of that type, different functions in the contract
+are called. In other terms, the unique access function dispatches the
+control flow depending on a *pattern matching* on the contract
+parameter.
-Each LIGO smart contract deployed on the Tezos blockchain, has access to certain built-in variables/constants that can be used to determine a range
-of useful things. In this section you'll find how those built-ins can be utilized.
-
-### Accepting/declining money in a smart contract
-
-This example shows how `amount` and `failwith` can be used to decline a transaction that sends more tez than `0mutez`.
+In the following example, the storage contains a counter of type `nat`
+and a name of type `string`. Depending on the parameter of the
+contract, either the counter or the name is updated.
-
+
+
```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
- } with ((nil : list(operation)), unit);
+type parameter is
+ Action_A of nat
+| Action_B of string
+
+type storage is record [
+ counter : nat;
+ name : string
+]
+
+type return is list (operation) * storage
+
+function entry_A (const n : nat; const store : storage) : return is
+ ((nil : list (operation)), store with record [counter = n])
+
+function entry_B (const s : string; const store : storage) : return is
+ ((nil : list (operation)), store with record [name = s])
+
+function access (const action : parameter; const store : storage): return is
+ case action of
+ Action_A (n) -> entry_A (n, store)
+ | Action_B (s) -> entry_B (s, store)
+ end
```
```cameligo group=b
-let main (p, s: unit * unit) : operation list * unit =
- if amount > 0mutez
- then (failwith "This contract does not accept tez": operation list * unit)
- else (([]: operation list), unit)
+type parameter =
+ Action_A of nat
+| Action_B of string
+
+type storage = {
+ counter : nat;
+ name : string
+}
+
+type return = operation list * storage
+
+let entry_A (n, store : nat * storage) : return =
+ ([] : operation list), {store with counter = n}
+
+let entry_B (s, store : string * storage) : return =
+ ([] : operation list), {store with name = s}
+
+let access (action, store: parameter * storage) : return =
+ match action with
+ Action_A n -> entry_A (n, store)
+ | Action_B s -> entry_B (s, store)
```
```reasonligo group=b
-let main = ((p,s): (unit, unit)) : (list(operation), unit) => {
- if (amount > 0mutez) {
- (failwith("This contract does not accept tez"): (list(operation), unit));
- }
- else {
- (([]: list(operation)), ());
+type parameter =
+| Action_A (nat)
+| Action_B (string);
+
+type storage = {
+ counter : nat,
+ name : string
+};
+
+type return = (list (operation), storage);
+
+let entry_A = ((n, store): (nat, storage)) : return =>
+ (([] : list (operation)), {...store, counter : n});
+
+let entry_B = ((s, store): (string, storage)) : return =>
+ (([] : list (operation)), {...store, name : s});
+
+let access = ((action, store): (parameter, storage)) : return =>
+ switch (action) {
+ | Action_A (n) => entry_A ((n, store))
+ | Action_B (s) => entry_B ((s, store))
};
+```
+
+
+
+## Tezos-specific Built-ins
+
+A LIGO smart contract can query part of the state of the Tezos
+blockchain by means of built-in values. In this section you will find
+how those built-ins can be utilized.
+
+### Accepting or Declining Tokens in a Smart Contract
+
+This example shows how `amount` and `failwith` can be used to decline
+any transaction that sends more tez than `0mutez`, that is, no
+incoming tokens are accepted.
+
+
+
+```pascaligo group=c
+type parameter is unit
+type storage is unit
+type return is list (operation) * storage
+
+function deny (const action : parameter; const store : storage) : return is
+ if amount > 0mutez then
+ (failwith ("This contract does not accept tokens.") : return)
+ else ((nil : list (operation)), store)
+```
+
+
+```cameligo group=c
+type parameter = unit
+type storage = unit
+type return = operation list * storage
+
+let deny (action, store : parameter * storage) : return =
+ if amount > 0mutez then
+ (failwith "This contract does not accept tokens.": return)
+ else (([] : operation list), store)
+```
+
+
+```reasonligo group=c
+type parameter = unit;
+type storage = unit;
+type return = (list (operation), storage);
+
+let deny = ((action, store): (parameter, storage)) : return => {
+ if (amount > 0mutez) {
+ (failwith("This contract does not accept tokens."): return); }
+ else { (([] : list (operation)), store); };
};
```
@@ -109,130 +245,168 @@ let main = ((p,s): (unit, unit)) : (list(operation), unit) => {
This example shows how `sender` or `source` can be used to deny access to an entrypoint.
-
+
```pascaligo group=c
-const owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
-function main (const p : unit ; const s : unit) : (list(operation) * unit) is
- block {
- if source =/= owner then failwith("This address can't call the contract") else skip
- } with ((nil : list(operation)), unit);
+const owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
+
+function filter (const action : parameter; const store : storage) : return is
+ if source =/= owner then (failwith ("Access denied.") : return)
+ else ((nil : list(operation)), store)
```
```cameligo group=c
-let owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)
-let main (p,s: unit * unit) : operation list * unit =
- if source <> owner
- then (failwith "This address can't call the contract": operation list * unit)
- else (([]: operation list), ())
+let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)
+
+let filter (action, store: parameter * storage) : return =
+ if source <> owner then (failwith "Access denied." : return)
+ else (([] : operation list), store)
```
```reasonligo group=c
-let owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
-let main = ((p,s): (unit, unit)) : (list(operation), unit) => {
- if (source != owner) {
- (failwith("This address can't call the contract"): (list(operation), unit));
- }
- else {
- (([]: list(operation)), ());
- };
+let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
+
+let access = ((action, store): (parameter, storage)) : storage => {
+ if (source != owner) { (failwith ("Access denied.") : return); }
+ else { (([] : list (operation)), store); };
};
```
-### Cross contract calls
+### Inter-Contract Invocations
-This example shows how a contract can invoke another contract by emiting a transaction operation at the end of an entrypoint.
+It would be somewhat misleading to speak of "contract calls", as this
+wording may wrongly suggest an analogy between contract "calls" and
+function "calls". Indeed, the control flow returns to the site of a
+function call, and composed function calls therefore are *stacked*,
+that is, they follow a last in, first out ordering. This is not what
+happens when a contract invokes another: the invocation is *queued*,
+that is, follows a first in, first our ordering, and the dequeuing
+only starts at the normal end of a contract (no failure). That is why
+we speak of "contract invocations" instead of "calls".
-> The same technique can be used to transfer tez to an implicit account (tz1, ...), all you have to do is use `unit` instead of a parameter for a smart contract.
+The following example shows how a contract can invoke another by
+emiting a transaction operation at the end of an entrypoint.
-In our case, we have a `counter.ligo` contract that accepts a parameter of type `action`, and we have a `proxy.ligo` contract that accepts the same parameter type, and forwards the call to the deployed counter contract.
+> The same technique can be used to transfer tokens to an implicit
+> account (tz1, ...): all you have to do is use a unit value as the
+> parameter of the smart contract.
+
+In our case, we have a `counter.ligo` contract that accepts an action
+of type `parameter`, and we have a `proxy.ligo` contract that accepts
+the same parameter type, and forwards the call to the deployed counter
+contract.
-
-```pascaligo
-// counter.ligo
-type action is
-| Increment of int
-| Decrement of int
-| Reset of unit
+
+```pascaligo skip
+// counter.ligo
+type parameter is
+ Increment of nat
+| Decrement of nat
+| Reset
+
+type storage is unit
+
+type return is list (operation) * storage
```
-```pascaligo skip
+```pascaligo group=d
// proxy.ligo
-type action is
-| Increment of int
-| Decrement of int
-| Reset of unit
+type parameter is
+ Increment of nat
+| Decrement of nat
+| Reset
-const dest: address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3": address);
+type storage is unit
-function proxy(const param: action; const store: unit): (list(operation) * unit)
- is block {
- const counter: contract(action) = get_contract(dest);
- // re-use the param passed to the proxy in the subsequent transaction
- // e.g.:
- // const mockParam: action = Increment(5);
- const op: operation = transaction(param, 0mutez, counter);
- const opList: list(operation) = list op; end;
- } with (opList, store)
+type return is list (operation) * storage
+
+const dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
+
+function proxy (const action : parameter; const store : storage): return is
+ block {
+ const counter : contract (parameter) = get_contract (dest);
+ (* Reuse the parameter in the subsequent
+ transaction or use another one, `mock_param`. *)
+ const mock_param : parameter = Increment (5n);
+ const op : operation = transaction (action, 0mutez, counter);
+ const ops : list (operation) = list [op]
+ } with (ops, store)
```
+
-```cameligo
+```cameligo skip
// counter.mligo
-type action =
-| Increment of int
-| Decrement of int
-| Reset of unit
+
+type parameter =
+ Increment of nat
+| Decrement of nat
+| Reset
// ...
```
-```cameligo
+```cameligo group=d
// proxy.mligo
-type action =
-| Increment of int
-| Decrement of int
-| Reset of unit
+type parameter =
+ Increment of nat
+| Decrement of nat
+| Reset
-let dest: address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3": address)
+type storage = unit
-let proxy (param, storage: action * unit): operation list * unit =
- let counter: action contract = Operation.get_contract dest in
- let op: operation = Operation.transaction param 0mutez counter in
- [op], storage
+type return = operation list * storage
+
+let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
+
+let proxy (action, store : parameter * storage) : return =
+ let counter : parameter contract = Operation.get_contract dest in
+ (* Reuse the parameter in the subsequent
+ transaction or use another one, `mock_param`. *)
+ let mock_param : parameter = Increment (5n) in
+ let op : operation = Operation.transaction action 0mutez counter
+ in [op], store
```
-```reasonligo
+```reasonligo skip
// counter.religo
-type action =
- | Increment(int)
- | Decrement(int)
- | Reset(unit);
+type parameter =
+| Increment (nat)
+| Decrement (nat)
+| Reset
// ...
```
-```reasonligo
+```reasonligo group=d
// proxy.religo
-type action =
- | Increment(int)
- | Decrement(int)
- | Reset(unit);
+type parameter =
+| Increment (nat)
+| Decrement (nat)
+| Reset;
-let dest: address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3": address);
+type storage = unit;
-let proxy = ((param, s): (action, unit)): (list(operation), unit) =>
- let counter: contract(action) = Operation.get_contract(dest);
- let op: operation = Operation.transaction(param, 0mutez, counter);
- ([op], s);
+type return = (list (operation), storage);
+
+let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address);
+
+let proxy = ((action, store): (parameter, storage)) : return => {
+ let counter : contract (parameter) = Operation.get_contract (dest);
+ (* Reuse the parameter in the subsequent
+ transaction or use another one, `mock_param`. *)
+ let mock_param : parameter = Increment (5n);
+ let op : operation = Operation.transaction (action, 0mutez, counter);
+ ([op], store)
+};
```
diff --git a/gitlab-pages/docs/advanced/first-contract.md b/gitlab-pages/docs/advanced/first-contract.md
index 19861291f..7da4e8cf7 100644
--- a/gitlab-pages/docs/advanced/first-contract.md
+++ b/gitlab-pages/docs/advanced/first-contract.md
@@ -3,20 +3,24 @@ id: first-contract
title: First contract
---
-So far so good, we've learned enough of the LIGO language, we're confident enough to write out first smart contract.
+So far so good, we have learned enough of the LIGO language, we are
+confident enough to write out first smart contract.
-We'll be implementing a counter contract, let's go.
+We will be implementing a counter contract.
-## Dry-running a contract
+## Dry-running a Contract
-Testing a contract can be quite easy if we utilize LIGO's built-in dry run feature. Dry-run works by simulating the entrypoint execution, as if it were deployed on a real chain. You need to provide the following:
+Testing a contract can be quite easy if we utilize LIGO's built-in dry
+run feature. Dry-run works by simulating the access function
+execution, as if it were deployed on a real chain. You need to provide
+the following:
- `file` - contract to run
- `entrypoint` - name of the function to execute
-- `parameter` - parameter passed to the entrypoint (in a theoretical invocation operation)
+- `parameter` - parameter passed to the access function (in a theoretical invocation operation)
- `storage` - a mock storage value, as if it were stored on a real chain
-Here's a full example:
+Here is a full example:
@@ -29,25 +33,29 @@ ligo dry-run src/basic.ligo main Unit Unit
```
-Output of the `dry-run` is the return value of our entrypoint function, we can see the operations emited - in our case an empty list, and the new storage value being returned - which in our case is still `Unit`.
+Output of the `dry-run` is the return value of our access function, we
+can see the operations emited - in our case an empty list, and the new
+storage value being returned - which in our case is still `Unit`.
-## Building a counter contract
+## A Counter Contract
-Our counter contract will store a single `int` as it's storage, and will accept an `action` variant in order to re-route our single `main` entrypoint into two entrypoints for `addition` and `subtraction`.
+Our counter contract will store a single `int` as it's storage, and
+will accept an `action` variant in order to re-route our single `main`
+access function to two entrypoints for `addition` and `subtraction`.
```
type action is
-| Increment of int
+ Increment of int
| Decrement of int
function main (const p : action ; const s : int) : (list(operation) * int) is
- block {skip} with ((nil : list(operation)),
- case p of
+ ((nil : list(operation)),
+ (case p of
| Increment (n) -> s + n
| Decrement (n) -> s - n
- end)
+ end))
```
@@ -98,11 +106,13 @@ ligo dry-run src/counter.ligo main "Increment(5)" 5
-Yay, our contract's storage has been successfuly incremented to `10`.
+Our contract's storage has been successfuly incremented to `10`.
## Deploying and interacting with a contract on a live-chain
-In order to deploy the counter contract to a real Tezos network, we'd have to compile it first, this can be done with the help of the `compile-contract` CLI command:
+In order to deploy the counter contract to a real Tezos network, we'd
+have to compile it first, this can be done with the help of the
+`compile-contract` CLI command:
@@ -156,7 +166,10 @@ Command above will output the following Michelson code:
```
-However in order to originate a Michelson contract on Tezos, we also need to provide the initial storage value, we can use `compile-storage` to compile the LIGO representation of the storage to Michelson.
+However in order to originate a Michelson contract on Tezos, we also
+need to provide the initial storage value, we can use
+`compile-storage` to compile the LIGO representation of the storage to
+Michelson.
@@ -167,7 +180,7 @@ ligo compile-storage src/counter.ligo main 5
-In our case the LIGO storage value maps 1:1 to it's Michelson representation, however this will not be the case once the parameter is of a more complex data type, like a record.
+In our case the LIGO storage value maps 1:1 to its Michelson representation, however this will not be the case once the parameter is of a more complex data type, like a record.
## Invoking a LIGO contract
@@ -182,4 +195,5 @@ ligo compile-parameter src/counter.ligo main 'Increment(5)'
-Now we can use `(Right 5)` which is a Michelson value, to invoke our contract - e.g. via `tezos-client`
+Now we can use `(Right 5)` which is a Michelson value, to invoke our
+contract - e.g. via `tezos-client`
diff --git a/gitlab-pages/docs/advanced/include.md b/gitlab-pages/docs/advanced/include.md
index 956d4a80e..21094102e 100644
--- a/gitlab-pages/docs/advanced/include.md
+++ b/gitlab-pages/docs/advanced/include.md
@@ -3,13 +3,12 @@ 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.
+Let us say that we have a contract that is getting a too large. 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`:
+You take the code that you want to include and put it in a separate
+file, for example `included.ligo`:
@@ -23,7 +22,6 @@ const foo : int = 144
```cameligo
-
// Demonstrate CameLIGO inclusion statements, see includer.mligo
let foo : int = 144
@@ -31,7 +29,6 @@ let foo : int = 144
```reasonligo
-
// Demonstrate ReasonLIGO inclusion statements, see includer.religo
let foo : int = 144;
@@ -46,7 +43,6 @@ And then you can include this code using the `#include` statement like so:
```pascaligo
-
#include "included.ligo"
const bar : int = foo
@@ -54,7 +50,6 @@ const bar : int = foo
```cameligo
-
#include "included.mligo"
let bar : int = foo
@@ -62,7 +57,6 @@ let bar : int = foo
```reasonligo
-
#include "included.religo"
let bar : int = foo;
diff --git a/gitlab-pages/docs/advanced/src/entrypoints-contracts/amount.ligo b/gitlab-pages/docs/advanced/src/entrypoints-contracts/amount.ligo
deleted file mode 100644
index fce71cde2..000000000
--- a/gitlab-pages/docs/advanced/src/entrypoints-contracts/amount.ligo
+++ /dev/null
@@ -1,4 +0,0 @@
-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
- } with ((nil : list(operation)), unit);
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/src/entrypoints-contracts/owner.ligo b/gitlab-pages/docs/advanced/src/entrypoints-contracts/owner.ligo
deleted file mode 100644
index b35b7c9fc..000000000
--- a/gitlab-pages/docs/advanced/src/entrypoints-contracts/owner.ligo
+++ /dev/null
@@ -1,5 +0,0 @@
-const owner: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
-function main (const p : unit ; const s : unit) : (list(operation) * unit) is
- block {
- if source =/= owner then failwith("This address can't call the contract") else skip
- } with ((nil : list(operation)), unit);
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.ligo b/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.ligo
deleted file mode 100644
index 0c5f0c6d7..000000000
--- a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.ligo
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "counter.types.ligo"
-
-function counter (const p : action ; const s : int): (list(operation) * int) is
- block { skip } with ((nil : list(operation)),
- case p of
- | Increment(n) -> s + n
- | Decrement(n) -> s - n
- | Reset(n) -> 0
- end)
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.types.ligo b/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.types.ligo
deleted file mode 100644
index be37bbf30..000000000
--- a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/counter.types.ligo
+++ /dev/null
@@ -1,4 +0,0 @@
-type action is
-| Increment of int
-| Decrement of int
-| Reset of unit
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/proxy.ligo b/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/proxy.ligo
deleted file mode 100644
index 47b7b1f64..000000000
--- a/gitlab-pages/docs/advanced/src/entrypoints-contracts/transaction/proxy.ligo
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "counter.types.ligo"
-
-// Replace the following address with your deployed counter contract address
-const address: address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3": address);
-
-function proxy(const param: action; const store: unit): (list(operation) * unit)
- is block {
- const counter: contract(action) = get_contract(address);
- // re-use the param passed to the proxy in the subsequent transaction
- // e.g.:
- // const mockParam: action = Increment(5);
- const op: operation = transaction(param, 0mutez, counter);
- const opList: list(operation) = list op; end;
- } with (opList, store)
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/src/timestamps/timestamp.ligo b/gitlab-pages/docs/advanced/src/timestamps/timestamp.ligo
deleted file mode 100644
index 5c46e43b6..000000000
--- a/gitlab-pages/docs/advanced/src/timestamps/timestamp.ligo
+++ /dev/null
@@ -1,9 +0,0 @@
-const today: timestamp = now;
-const one_day: int = 86400;
-const in_24_hrs: timestamp = today + one_day;
-
-const today: timestamp = now;
-const one_day: int = 86400;
-const a_24_hrs_ago: timestamp = today - one_day;
-
-const not_tommorow: bool = (now = in_24_hrs)
\ No newline at end of file
diff --git a/gitlab-pages/docs/advanced/timestamps-addresses.md b/gitlab-pages/docs/advanced/timestamps-addresses.md
index e77ba76ee..fb2154bc8 100644
--- a/gitlab-pages/docs/advanced/timestamps-addresses.md
+++ b/gitlab-pages/docs/advanced/timestamps-addresses.md
@@ -3,179 +3,204 @@ id: timestamps-addresses
title: Timestamps, Addresses
---
-## Timestamps
+## Timestamps
-Timestamps in LIGO, or in Michelson in general are available in smart contracts, while bakers baking the block (including the transaction in a block) are responsible for providing the given current timestamp for the contract.
+LIGO features timestamps, as Michelson does, while bakers baking the
+block (including the transaction in a block) are responsible for
+providing the given current timestamp for the contract.
-### Current time
-
-You can obtain the current time using the built-in syntax specific expression, please be aware that it's up to the baker to set the current timestamp value.
+### Current Time
+You can obtain the current time using the built-in syntax specific
+expression, please be aware that it is up to the baker to set the
+current timestamp value.
-
+
```pascaligo group=a
-const today: timestamp = now;
+const today : timestamp = now
```
```cameligo group=a
-let today: timestamp = Current.time
+let today : timestamp = Current.time
```
```reasonligo group=a
-let today: timestamp = Current.time;
+let today : timestamp = Current.time;
```
-> When running code with ligo CLI, the option `--predecessor-timestamp` allows you to control what `now` returns.
+> When running code, the LIGO CLI option
+> `--predecessor-timestamp` allows you to control what `now` returns.
-### Timestamp arithmetic
+### Timestamp Arithmetics
-In LIGO, timestamps can be added with `int`(s), this enables you to set e.g. time constraints for your smart contracts like this:
+In LIGO, timestamps can be added to integers, allowing you to set time
+constraints on your smart contracts. Consider the following scenarios.
#### In 24 hours
+
-
+
```pascaligo group=b
-const today: timestamp = now;
-const one_day: int = 86400;
-const in_24_hrs: timestamp = today + one_day;
-const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp);
-const one_day_later: timestamp = some_date + one_day;
+const today : timestamp = now
+const one_day : int = 86400
+const in_24_hrs : timestamp = today + one_day
+const some_date : timestamp = ("2000-01-01T10:10:10Z" : timestamp)
+const one_day_later : timestamp = some_date + one_day
```
```cameligo group=b
-let today: timestamp = Current.time
-let one_day: int = 86400
-let in_24_hrs: timestamp = today + one_day
-let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp)
-let one_day_later: timestamp = some_date + one_day
+let today : timestamp = Current.time
+let one_day : int = 86400
+let in_24_hrs : timestamp = today + one_day
+let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp)
+let one_day_later : timestamp = some_date + one_day
```
```reasonligo group=b
-let today: timestamp = Current.time;
-let one_day: int = 86400;
-let in_24_hrs: timestamp = today + one_day;
-let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp);
-let one_day_later: timestamp = some_date + one_day;
+let today : timestamp = Current.time;
+let one_day : int = 86400;
+let in_24_hrs : timestamp = today + one_day;
+let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp);
+let one_day_later : timestamp = some_date + one_day;
```
-#### 24 hours ago
+#### 24 hours Ago
+
-
+
```pascaligo group=c
-const today: timestamp = now;
-const one_day: int = 86400;
-const in_24_hrs: timestamp = today - one_day;
+const today : timestamp = now
+const one_day : int = 86400
+const in_24_hrs : timestamp = today - one_day
```
```cameligo group=c
-let today: timestamp = Current.time
-let one_day: int = 86400
-let in_24_hrs: timestamp = today - one_day
+let today : timestamp = Current.time
+let one_day : int = 86400
+let in_24_hrs : timestamp = today - one_day
```
```reasonligo group=c
-let today: timestamp = Current.time;
-let one_day: int = 86400;
-let in_24_hrs: timestamp = today - one_day;
+let today : timestamp = Current.time;
+let one_day : int = 86400;
+let in_24_hrs : timestamp = today - one_day;
```
-### Comparing timestamps
+### Comparing Timestamps
-You can also compare timestamps using the same comparison operators as for numbers:
+You can compare timestamps using the same comparison operators
+applying to numbers.
-
+
```pascaligo group=c
-const not_tommorow: bool = (now = in_24_hrs)
+const not_tommorow : bool = (now = in_24_hrs)
```
```cameligo group=c
-let not_tomorrow: bool = (Current.time = in_24_hrs)
+let not_tomorrow : bool = (Current.time = in_24_hrs)
```
```reasonligo group=c
-let not_tomorrow: bool = (Current.time == in_24_hrs);
+let not_tomorrow : bool = (Current.time == in_24_hrs);
```
## Addresses
-`address` is a LIGO datatype used for Tezos addresses (tz1, tz2, tz3, KT1, ...).
-
-Here's how you can define an address:
+The `address` type in LIGO denotes Tezos addresses (tz1, tz2, tz3,
+KT1, ...). Currently, addresses are created by casting a string to the
+`address` type. Beware of failures if the address is invalid. Consider
+the following examples.
-
+
```pascaligo group=d
-const my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
+const my_account : address =
+ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
```
```cameligo group=d
-let my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)
+let my_account : address =
+ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
```
```reasonligo group=d
-let my_account: address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
+let my_account : address =
+ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
```
## Signatures
-`signature` is a LIGO datatype used for Tezos signature (edsig, spsig).
+The `signature` type in LIGO datatype is used for Tezos signatures
+(edsig, spsig). Signatures are created by casting a string. Beware of
+failure if the signature is invalid.
-Here's how you can define a signature:
+Here is how you can define a signature:
-
+
```pascaligo group=e
-const my_signature: signature = ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7": signature);
+const my_sig : signature =
+ ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" :
+ signature)
```
```cameligo group=e
-let my_signature: signature = ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7": signature)
+let my_sig : signature =
+ ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" :
+ signature)
```
```reasonligo group=e
-let my_signature: signature = ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7": signature);
+let my_sig : signature =
+("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" :
+signature);
```
-## keys
+## Keys
-`key` is a LIGO datatype used for Tezos public key.
+The `key` type in LIGO is used for Tezos public keys. Do not confuse
+them with map keys. Keys are made by casting strings. Beware of
+failure if the key is invalid.
-Here's how you can define a key:
+Here is how you can define a key.
-
+
```pascaligo group=f
-const my_key: key = ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav": key);
+const my_key : key =
+("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" : key)
```
```cameligo group=f
-let my_key: key = ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav": key)
+let my_key : key =
+ ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" : key)
```
```reasonligo group=f
-let my_key: key = ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav": key);
+let my_key : key =
+ ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" : key);
```
diff --git a/gitlab-pages/docs/api/cheat-sheet.md b/gitlab-pages/docs/api/cheat-sheet.md
index 920ae6376..8f8baebdb 100644
--- a/gitlab-pages/docs/api/cheat-sheet.md
+++ b/gitlab-pages/docs/api/cheat-sheet.md
@@ -4,6 +4,9 @@ title: Cheat Sheet
---
let price: option(tez) = Map.find_opt(50n, prices);
let prices: prices = Map.update(200n, Some (5mutez), prices);
|
+|Contracts & Accounts|
let destination_address : address = "tz1..."; let contract : contract(unit) = Operation.get_contract(destination_address);
|
+|Transactions|
let payment : operation = Operation.transaction (unit, amount, receiver);
|
+|Exception/Failure|`failwith("Your descriptive error message for the user goes here.");`|
diff --git a/gitlab-pages/docs/contributors/getting-started.md b/gitlab-pages/docs/contributors/getting-started.md
index 7b186dfad..5a98402d3 100644
--- a/gitlab-pages/docs/contributors/getting-started.md
+++ b/gitlab-pages/docs/contributors/getting-started.md
@@ -23,9 +23,9 @@ The first issues will most likely be:
>Tests are **really** important, we don’t have lots of them, and mostly regression ones. This can’t be stressed enough. Some features are missing not because we can’t add them, but because we don’t know as no tests tell us they are missing.
## How
-Issues will be added to Gitlab tagged with `On-boarding and Front-End` / `Middle-End` / `Back-End` / `Everything`.
+Issues will be added to GitLab tagged with `On-boarding and Front-End` / `Middle-End` / `Back-End` / `Everything`.
-If you try to tackle an issue and you have **any** problem, please tell us by creating a new Gitlab issue, contacting us on Riot, on Discord, or even by mail!
+If you try to tackle an issue and you have **any** problem, please tell us by creating a new GitLab issue, contacting us on Riot, on Discord, or even by mail!
Problems might include:
* Installing the repository or the tools needed to work on it
diff --git a/gitlab-pages/docs/contributors/ligo_test_guide.md b/gitlab-pages/docs/contributors/ligo_test_guide.md
index 4726c7fe3..eea05d77d 100644
--- a/gitlab-pages/docs/contributors/ligo_test_guide.md
+++ b/gitlab-pages/docs/contributors/ligo_test_guide.md
@@ -111,4 +111,4 @@ What if we want to write a test of our own? If the test is in the integration te
1. Write a test contract which uses the new syntax or feature in [src/test/contracts](https://gitlab.com/ligolang/ligo/tree/dev/src/test/contracts).
2. Write an integration test in [src/test/integration_tests.ml](https://gitlab.com/ligolang/ligo/blob/dev/src/test/integration_tests.ml) in the vein of existing tests, make sure you add it to the test runner that is currently located at the bottom of the file.
3. Write the feature, assuming it doesn't already exist. Build the resulting version of LIGO without errors.
-4. Run the test suite, see if your test(s) pass. If they do, you're probably done. If not it's time to go debugging.
+4. Run the test suite, see if your test(s) pass. If they do, you're probably done. If not, it's time to go debugging.
diff --git a/gitlab-pages/docs/contributors/origin.md b/gitlab-pages/docs/contributors/origin.md
index 9c8df5900..6b20863a3 100644
--- a/gitlab-pages/docs/contributors/origin.md
+++ b/gitlab-pages/docs/contributors/origin.md
@@ -3,8 +3,8 @@ id: origin
title: Origin
---
-LIGO is a programming language that aims to provide developers with an uncomplicated and safe way to implement smart-contracts. Since it is being implemented for the Tezos blockchain LIGO compiles to Michelson—the native smart-contract language of Tezos.
+LIGO is a programming language that aims to provide developers with an uncomplicated and safe way to implement smart contracts. Since it is being implemented for the Tezos blockchain LIGO compiles to Michelson—the native smart contract language of Tezos.
-> Smart-contracts are programs that run within a blockchain network.
+> Smart contracts are programs that run within a blockchain network.
LIGO was meant to be a language for developing Marigold on top of a hacky framework called Meta-Michelson. However, due to the attention received by the Tezos community, LIGO is now a standalone language being developed to support Tezos directly.
\ No newline at end of file
diff --git a/gitlab-pages/docs/contributors/philosophy.md b/gitlab-pages/docs/contributors/philosophy.md
index 0af6e606b..351a470e2 100644
--- a/gitlab-pages/docs/contributors/philosophy.md
+++ b/gitlab-pages/docs/contributors/philosophy.md
@@ -6,7 +6,7 @@ title: Philosophy
To understand LIGO’s design choices it’s important to understand its philosophy. We have two main concerns in mind while building LIGO.
## Safety
-Once a smart-contract is deployed, it will likely be impossible to change it. You must get it right on the first try, and LIGO should help as much as possible. There are multiple ways to make LIGO a safer language for smart-contracts.
+Once a smart contract is deployed, it will likely be impossible to change it. You must get it right on the first try, and LIGO should help as much as possible. There are multiple ways to make LIGO a safer language for smart contracts.
### Automated Testing
Automated Testing is the process through which a program runs another program, and checks that this other program behaves correctly.
@@ -18,7 +18,7 @@ Static analysis is the process of having a program analyze another one.
For instance, type systems are a kind of static analysis through which it is possible to find lots of bugs. LIGO already has a simple type system, and we plan to make it much stronger.
### Conciseness
-Writing less code gives you less room to introduce errors. That's why LIGO encourages writing lean rather than chunky smart-contracts.
+Writing less code gives you less room to introduce errors. That's why LIGO encourages writing lean rather than chunky smart contracts.
---
diff --git a/gitlab-pages/docs/intro/installation.md b/gitlab-pages/docs/intro/installation.md
index cd45491ab..307e470c9 100644
--- a/gitlab-pages/docs/intro/installation.md
+++ b/gitlab-pages/docs/intro/installation.md
@@ -15,12 +15,12 @@ executable (see below). This manages the Docker bits for you.
* Use the Docker image available at [Docker Hub](https://hub.docker.com/r/ligolang/ligo).
This lets you run multiple versions and keep your installation(s) self contained, but requires more familiarity with Docker.
-Sources for the image can be found on [Gitlab](https://gitlab.com/ligolang/ligo/blob/master/docker/Dockerfile).
+Sources for the image can be found on [GitLab](https://gitlab.com/ligolang/ligo/blob/master/docker/Dockerfile).
If this is your first time using Docker, you probably want to set up a global LIGO executable as shown below.
### Setting up a globally available `ligo` executable
-> You can install additional ligo versions by replacing `next` with the required version number
+> You can install additional ligo versions by replacing `next` with the desired version number
Download the latest binaries here: https://gitlab.com/ligolang/ligo/pipelines/85536879/builds or get the latest pre-release:
diff --git a/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.ligo b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.ligo
index 989afba07..4fd886fb7 100644
--- a/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.ligo
+++ b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.ligo
@@ -1,12 +1,25 @@
-type action is
-| Increment of int
-| Decrement of int
-| Reset of unit
+type storage is int
-function main (const p : action ; const s : int) : (list(operation) * int) is
- block { skip } with ((nil : list(operation)),
- case p of
- | Increment(n) -> s + n
- | Decrement(n) -> s - n
- | Reset(n) -> 0
- end)
\ No newline at end of file
+type parameter is
+ Increment of int
+| Decrement of int
+| Reset
+
+type return is list (operation) * storage
+
+(* Two entrypoints *)
+
+function add (const store : storage; const delta : int) : storage is store + delta
+
+function sub (const store : storage; const delta : int) : storage is store - delta
+
+(* Main access point that dispatches to the entrypoints according to
+ the smart contract parameter. *)
+
+function main (const action : parameter; const store : storage) : return is
+ ((nil : list (operation)), // No operations
+ case action of
+ Increment (n) -> add (store, n)
+ | Decrement (n) -> sub (store, n)
+ | Reset -> 0
+ end)
diff --git a/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.mligo b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.mligo
new file mode 100644
index 000000000..3cfa8551f
--- /dev/null
+++ b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.mligo
@@ -0,0 +1,23 @@
+type storage = int
+
+type parameter =
+ Increment of int
+| Decrement of int
+| Reset
+
+type return = operation list * storage
+
+(* Two entrypoints *)
+
+let add (store, delta : storage * int) : storage = store + delta
+let sub (store, delta : storage * int) : storage = store - delta
+
+(* Main access point that dispatches to the entrypoints according to
+ the smart contract parameter. *)
+
+let main (action, store : parameter * storage) : return =
+ ([] : operation list), // No operations
+ (match action with
+ Increment (n) -> add (store, n)
+ | Decrement (n) -> sub (store, n)
+ | Reset -> 0)
diff --git a/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.religo b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.religo
new file mode 100644
index 000000000..74292563c
--- /dev/null
+++ b/gitlab-pages/docs/intro/src/what-and-why/ligo-counter.religo
@@ -0,0 +1,26 @@
+type storage = int;
+
+type parameter =
+ Increment (int)
+| Decrement (int)
+| Reset;
+
+type return = (list (operation), storage);
+
+(* Two entrypoints *)
+
+let add = ((store, delta) : (storage, int)) : storage => store + delta;
+
+let sub = ((store, delta) : (storage, int)) : storage => store - delta;
+
+(* Main access point that dispatches to the entrypoints according to
+ the smart contract parameter. *)
+
+let main = ((action, store) : (parameter, storage)) : return => {
+ (([] : list (operation)), // No operations
+ (switch (action) {
+ | Increment (n) => add ((store, n))
+ | Decrement (n) => sub ((store, n))
+ | Reset => 0
+ }))
+};
diff --git a/gitlab-pages/docs/intro/what-and-why.md b/gitlab-pages/docs/intro/what-and-why.md
index fdd1d2887..f195b97a7 100644
--- a/gitlab-pages/docs/intro/what-and-why.md
+++ b/gitlab-pages/docs/intro/what-and-why.md
@@ -1,14 +1,73 @@
---
id: what-and-why
-title: What & Why
+title: Michelson and LIGO
---
-Before we get into what LIGO is and why LIGO needs to exist, let's take a look at what options the Tezos blockchain offers us out of the box. If you want to implement smart contracts natively on Tezos, you have to learn [Michelson](https://tezos.gitlab.io/whitedoc/michelson.html).
+Before we get into what LIGO is and why LIGO needs to exist, let us
+take a look at what options the Tezos blockchain offers us out of the
+box. If you want to implement smart contracts natively on Tezos, you
+have to learn
+[Michelson](https://tezos.gitlab.io/whitedoc/michelson.html).
-> đź’ˇ The (Michelson) language is stack-based, with high level data types and primitives and strict static type checking.
+**The rationale and design of Michelson**
+The language native to the Tezos blockchain for writing smart
+contracts is *Michelson*, a Domain-Specific Language (DSL) inspired by
+Lisp and Forth. This unusual lineage aims at satisfying unusual
+constraints, but entails some tensions in the design.
-Here's an example of Michelson code:
+First, to measure stepwise gas consumption, *Michelson is interpreted*.
+
+On the one hand, to assess gas usage per instruction, instructions
+should be simple, which points to low-level features (a RISC-like
+language). On the other hand, it was originally thought that users
+will want to write in Michelson instead of lowering a language to
+Michelson, because the gas cost would otherwise be harder to
+predict. This means that *high-level features* were deemed necessary
+(like a restricted variant of Lisp lambdas, a way to encode algebraic
+data types, as well as built-in sets, maps and lists).
+
+To avoid ambiguous and otherwise misleading contracts, the layout of
+Michelson contracts has been constrained (e.g., indentation, no
+UTF-8), and a *canonical form* was designed and enforced when storing
+contracts on the chain.
+
+To reduce the size of the code, Michelson was designed as *a
+stack-based language*, whence the lineage from Forth and other
+concatenative languages like PostScript, Joy, Cat, Factor etc. (Java
+bytecode would count too.)
+
+Programs in those languages are *compact* because they assume an
+implicit stack in which some input values are popped, and output
+values are pushed, according to the current instruction being
+executed.
+
+*Each Michelson instruction modifies a prefix of the stack*, that is,
+a segment starting at the top.
+
+Whilst the types of Michelson instructions can be polymorphic, their
+instantiations must be monomorphic, hence *Michelson instructions are
+not first-class values* and cannot be partially interpreted.
+
+This enables a simple *static type checking*, as opposed to a complex
+type inference. It can be performed efficiently: *contract type
+checking consumes gas*. Basically, type checking aims at validating
+the composition of instructions, therefore is key to safely composing
+contracts (concatenation, activations). Once a contract passes type
+checking, it cannot fail due to inconsistent assumptions on the
+storage and other values (there are no null values, no casts), but it
+can still fail for other reasons: division by zero, token exhaustion,
+gas exhaustion, or an explicit `FAILWITH` instruction. This property
+is called *type safety*. Also, such a contract cannot remain stuck:
+this is the *progress property*.
+
+The existence of a formal type system for Michelson, of a formal
+specification of its dynamic semantics (evaluation), of a Michelson
+interpreter in Coq, of proofs in Coq of properties of some typical
+contracts, all those achievements are instances of *formal methods in
+Tezos*.
+
+Here is an example of a Michelson contract.
**`counter.tz`**
```text
@@ -21,118 +80,167 @@ Here's an example of Michelson code:
NIL operation ; PAIR } }
```
-The contract above maintains an `int` in its storage. It has two entrypoints *(functions)* `add` and `sub` to modify it, and the default *entrypoint* of type unit will reset it to 0.
+The contract above maintains an `int` as its storage. It has two
+[entrypoints](https://tezos.gitlab.io/whitedoc/michelson.html#entrypoints),
+`add` and `sub`, to modify it, and the `default` entrypoint of type
+`unit` will reset it to `0`.
-The contract itself contains three main parts:
+The contract itself contains three sections:
+- `parameter` - The argument provided by a transaction invoking the contract.
+- `storage` - The type definition for the contract's data storage.
+- `code` - Actual Michelson code that has the provided parameter and
+ the current storage value in its initial stack. It outputs in the
+ resulting stack a pair made of a list of operations and a new
+ storage value.
-- `parameter` - Argument provided by a transaction invoking the contract
-- `storage` - Type definition for the contract's data storage.
-- `code` - Actual Michelson code that has the provided parameter & the current storage value in its initial stack. It outputs a pair of operations and a new storage value as its resulting stack.
+Michelson code consists of *instructions* like `IF_LEFT`, `PUSH ...`,
+`UNPAIR` etc. that are composed sequentially in what is called a
+*sequence*. The implicit stack contains at all times the state of the
+evaluation of the program, whilst the storage represents the
+persistent state. If the contract execution is successful, the new
+storage state will be committed to the chain and become visible to all
+the nodes. Instructions are used to transform a prefix of the stack,
+that is, the topmost part of it, for example, by duplicating its top
+element, dropping it, subtracting the first two etc.
-Michelson code consists of *instructions* like `IF_LEFT`, `PUSH ...`, `UNPAIR` that are bundled togeter in what is called a *sequence*. Stack represents an intermediate state of the program, while **storage represents a persistent state**. Instructions are used to modify the run-time stack in order to yield a desired stack value when the program terminates.
+> đź’ˇ A Michelson program running on the Tezos blockchain is meant to
+> output a pair of values including a `list of operations` to include
+> in a transaction, and a new `storage` value to persist on the chain.
-> đź’ˇ A Michelson program running on the Tezos blockchain is meant to output a pair of values including a `list of operations` to emit and a new `storage` value to persist
+## Stack versus variables
-## Differences between a stack and traditional variable management
-
-Stack management might be a little bit challanging, especially if you're coming from a *C-like language*. Let's implement a similar program in Javascript:
+Perhaps the biggest challenge when programming in Michelson is the
+lack of *variables* to denote the data: the stack layout has to be
+kept in mind when retrieving and storing data. For example, let us
+implement a program in Javascript that is similar to the Michelson
+above:
**`counter.js`**
```javascript
var storage = 0;
-function add(a) {
- storage += a
-}
+function add (a) { storage += a; }
+function sub (a) { storage -= a; }
-function sub(a) {
- storage -= a
-}
+// We are calling this function "reset" instead of "default"
+// because `default` is a Javascript keyword
-// We're calling this function reset instead of default
-// because `default` is a javascript keyword
-function reset() {
- storage = 0;
-}
+function reset () { storage = 0; }
```
-In our javascript program the initial `storage` value is `0` and it can be modified by running the functions `add(a)`, `sub(a)` and `reset()`.
+In our Javascript program the initial `storage` value is `0` and it
+can be modified by calling `add (a)`, `sub (a)` and `reset ()`.
-Unfortunately (???), we **can't run Javascript on the Tezos blockchain** at the moment. But we can choose LIGO, which will abstract the stack management and allow us to create readable, type-safe, and efficient smart contracts.
+We cannot run Javascript on the Tezos blockchain, but we can choose
+LIGO, which will abstract the stack management and allow us to create
+readable, type-safe, and efficient smart contracts.
-> đź’ˇ You can try running the javascript program [here](https://codepen.io/maht0rz/pen/dyyvoPQ?editors=0012)
+## LIGO for Programming Smart Contracts on Tezos
-## C-like smart contracts instead of Michelson
+Perhaps the most striking feature of LIGO is that it comes in
+different concrete syntaxes, and even different programming
+paradigms. In other words, LIGO is not defined by one syntax and one
+paradigm, like imperative versus functional.
-Let's take a look at a similar LIGO program. Don't worry if it's a little confusing at first; we'll explain all the syntax in the upcoming sections of the documentation.
+ - There is **PascaLIGO**, which is inspired by Pascal, hence is an
+ imperative language with lots of keywords, where values can be
+ locally mutated after they have been annotated with their types
+ (declaration).
+
+ - There is **CameLIGO**, which is inspired by the pure subset of
+ [OCaml](https://ocaml.org/), hence is a functional language with
+ few keywords, where values cannot be mutated, but still require
+ type annotations (unlike OCaml, whose compiler performs almost
+ full type inference).
+
+ - There is **ReasonLIGO**, which is inspired by the pure subset of
+ [ReasonML](https://reasonml.github.io/), which is based upon
+ OCaml.
+
+Let us decline the same LIGO contract in the three flavours above. Do
+not worry if it is a little confusing at first; we will explain all
+the syntax in the upcoming sections of the documentation.
-
-```pascaligo
-type action is
-| Increment of int
-| Decrement of int
-| Reset of unit
+
+```pascaligo group=a
+type storage is int
-function main (const p : action ; const s : int) : (list(operation) * int) is
- block { skip } with ((nil : list(operation)),
- case p of
- | Increment(n) -> s + n
- | Decrement(n) -> s - n
- | Reset(n) -> 0
+type parameter is
+ Increment of int
+| Decrement of int
+| Reset
+
+type return is list (operation) * storage
+
+function main (const action : parameter; const store : storage) : return is
+ ((nil : list (operation)),
+ case action of
+ Increment (n) -> store + n
+ | Decrement (n) -> store - n
+ | Reset -> 0
end)
```
-```cameligo
-type action =
-| Increment of int
-| Decrement of int
-| Reset of unit
+```cameligo group=a
+type storage = int
-let main (p, s: action * int) : operation list * int =
- let result =
- match p with
- | Increment n -> s + n
- | Decrement n -> s - n
- | Reset n -> 0
- in
- (([]: operation list), result)
+type parameter =
+ Increment of int
+| Decrement of int
+| Reset
+
+type return = operation list * storage
+
+let main (action, store : parameter * storage) : return =
+ ([] : operation list),
+ (match action with
+ Increment n -> store + n
+ | Decrement n -> store - n
+ | Reset -> 0)
```
-```reasonligo
-type action =
-| Increment(int)
-| Decrement(int)
-| Reset(unit);
+```reasonligo group=a
+type storage = int;
-let main = ((p,s): (action, int)) : (list(operation), int) => {
- let result =
- switch (p) {
- | Increment(n) => s + n
- | Decrement(n) => s - n
- | Reset n => 0
- };
- (([]: list(operation)), result);
+type parameter =
+ Increment (int)
+| Decrement (int)
+| Reset;
+
+type return = (list (operation), storage);
+
+let main = ((action, store): (parameter, storage)) : return => {
+ (([] : list (operation)),
+ (switch (action) {
+ | Increment (n) => store + n
+ | Decrement (n) => store - n
+ | Reset => 0}));
};
```
+
+
-> đź’ˇ You can find the Michelson compilation output of the contract above in **`ligo-counter.tz`**
+This LIGO contract behaves almost exactly* like the Michelson
+contract we saw first, and it accepts the following LIGO expressions:
+`Increment(n)`, `Decrement(n)` and `Reset`. Those serve as
+`entrypoint` identification, same as `%add` `%sub` or `%default` in
+the Michelson contract.
-The LIGO contract behaves exactly* like the Michelson contract we've saw first, and it accepts the following LIGO expressions/values: `Increment(n)`, `Decrement(n)` and `Reset(n)`. Those serve as `entrypoint` identification, same as `%add` `%sub` or `%default` in the Michelson contract.
-
-**not exactly, the Michelson contract also checks if the `AMOUNT` sent is `0`*
+**The Michelson contract also checks if the `AMOUNT` sent is `0`*
---
## Runnable code snippets & exercises
Some of the sections in this documentation will include runnable code snippets and exercises. Sources for those are available at
-the [LIGO Gitlab repository](https://gitlab.com/ligolang/ligo).
+the [LIGO Gitlab repository](https://gitlab.com/ligolang/ligo).
### Snippets
For example **code snippets** for the *Types* subsection of this doc, can be found here:
@@ -141,7 +249,7 @@ For example **code snippets** for the *Types* subsection of this doc, can be fou
### Exercises
Solutions to exercises can be found e.g. here: `gitlab-pages/docs/language-basics/exercises/types/**/solutions/**`
-### Running snippets / excercise solutions
+### Running snippets / exercise solutions
In certain cases it makes sense to be able to run/evaluate the given snippet or a solution, usually there'll be an example command which you can use, such as:
```shell
diff --git a/gitlab-pages/docs/language-basics/boolean-if-else.md b/gitlab-pages/docs/language-basics/boolean-if-else.md
index d57e6fa99..8a872d777 100644
--- a/gitlab-pages/docs/language-basics/boolean-if-else.md
+++ b/gitlab-pages/docs/language-basics/boolean-if-else.md
@@ -1,205 +1,205 @@
---
id: boolean-if-else
-title: Boolean, If, Else
+title: Booleans and Conditionals
---
-## Boolean
+## Booleans
-The type of a Boolean is `bool` and the possible values are `True` and `False`.
-
-Here's how to define a boolean:
+The type of a boolean value is `bool`. Here is how to define a boolean
+value:
-
+
```pascaligo group=a
-const a: bool = True;
-const b: bool = False;
+const a : bool = True // Notice the capital letter
+const b : bool = False // Same.
```
```cameligo group=a
-let a: bool = true
-let b: bool = false
+let a : bool = true
+let b : bool = false
```
-
```reasonligo group=a
-let a: bool = true;
-let b: bool = false;
+let a : bool = true;
+let b : bool = false;
```
+## Comparing Values
-## Comparing two values
+In LIGO, only values of the same type can be compared. Moreover, not
+all values of the same type can be compared, only those with
+*comparable types*, which is a concept lifted from
+Michelson. Comparable types include, for instance, `int`, `nat`,
+`string`, `tez`, `timestamp`, `address`, etc. As an example of
+non-comparable types: maps, sets or lists are not comparable: if you
+wish to compare them, you will have to write your own comparison
+function.
-In LIGO, only values of the same type can be compared. We call these "comparable types." Comparable types include e.g. `int`, `nat`, `string`, `tez`, `timestamp`, `address`, ...
-
-### Comparing strings
+### Comparing Strings
-
+
```pascaligo group=b
-const a: string = "Alice";
-const b: string = "Alice";
-// True
-const c: bool = (a = b);
+const a : string = "Alice"
+const b : string = "Alice"
+const c : bool = (a = b) // True
```
```cameligo group=b
-let a: string = "Alice"
-let b: string = "Alice"
-// true
-let c: bool = (a = b)
+let a : string = "Alice"
+let b : string = "Alice"
+let c : bool = (a = b) // true
```
```reasonligo group=b
-let a: string = "Alice";
-let b: string = "Alice";
-(* true *)
-let c: bool = (a == b);
+let a : string = "Alice";
+let b : string = "Alice";
+let c : bool = (a == b); // true
```
-
### Comparing numbers
-
+
```pascaligo group=c
-const a: int = 5;
-const b: int = 4;
-const c: bool = (a = b);
-const d: bool = (a > b);
-const e: bool = (a < b);
-const f: bool = (a <= b);
-const g: bool = (a >= b);
-const h: bool = (a =/= b);
+const a : int = 5
+const b : int = 4
+const c : bool = (a = b)
+const d : bool = (a > b)
+const e : bool = (a < b)
+const f : bool = (a <= b)
+const g : bool = (a >= b)
+const h : bool = (a =/= b)
```
```cameligo group=c
-let a: int = 5
-let b: int = 4
-let c: bool = (a = b)
-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 a : int = 5
+let b : int = 4
+let c : bool = (a = b)
+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)
```
```reasonligo group=c
-let a: int = 5;
-let b: int = 4;
-let c: bool = (a == b);
-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 a : int = 5;
+let b : int = 4;
+let c : bool = (a == b);
+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);
```
-
### Comparing tez
-> đź’ˇ Comparing `tez` values is especially useful when dealing with an `amount` sent in a transaction.
+> đź’ˇ Comparing `tez` values is especially useful when dealing with an
+> amount sent in a transaction.
-
+
```pascaligo group=d
-const a: tez = 5mutez;
-const b: tez = 10mutez;
-const c: bool = (a = b);
+const a : tez = 5mutez
+const b : tez = 10mutez
+const c : bool = (a = b) // False
```
```cameligo group=d
-let a: tez = 5mutez
-let b: tez = 10mutez
-// false
-let c: bool = (a = b)
+let a : tez = 5mutez
+let b : tez = 10mutez
+let c : bool = (a = b) // false
```
```reasonligo group=d
-let a: tez = 5mutez;
-let b: tez = 10mutez;
-(* false *)
-let c: bool = (a == b);
+let a : tez = 5mutez;
+let b : tez = 10mutez;
+let c : bool = (a == b); // false
```
-## Conditionals, if staments, and more
+## Conditionals
-Conditional logic is an important part of every real world program.
-
-### If/else statements
+Conditional logic enables forking the control flow depending on the
+state.
-
+
```pascaligo group=e
-const min_age: nat = 16n;
+type magnitude is Small | Large // See variant types.
-(*
- 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.
-*)
-function is_adult(const age: nat): bool is
- block {
- var is_adult: bool := False;
- if (age > min_age) then begin
- is_adult := True;
- end else begin
- is_adult := False;
- end
- } with is_adult
+function compare (const n : nat) : magnitude is
+ if n < 10n then Small (Unit) else Large (Unit) // Unit is needed for now.
```
-> You can run the function above with
-> ```
-> ligo run-function -s pascaligo src/if-else.ligo is_adult 21n
-> ```
+You can run the `compare` function defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/boolean-if-else/cond.ligo compare 21n'
+# Outputs: Large (Unit)
+```
+
+When the branches of the conditional are not a single expression, as
+above, we need a block:
+
+```pascaligo skip
+if x < y then
+ block {
+ const z : nat = x;
+ x := y; y := z
+ }
+else skip;
+```
+
+As an exception to the rule, the blocks in a conditional branch do not
+need to be introduced by the keywor `block`, so, we could have written
+instead:
+```pascaligo skip
+if x < y then {
+ const z : nat = x;
+ x := y; y := z
+}
+else skip;
+```
```cameligo group=e
-let min_age: nat = 16n
+type magnitude = Small | Large // See variant types.
-(**
-
- 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) then true else false
+let compare (n : nat) : magnitude =
+ if n < 10n then Small else Large
```
+
+You can run the `compare` function defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/boolean-if-else/cond.mligo compare 21n'
+# Outputs: Large
+```
+
```reasonligo group=e
-let min_age: nat = 16n;
+type magnitude = | Small | Large; // See variant types.
-(**
-
- 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) {
- true;
- } else {
- false;
- };
+let compare = (n : nat) : magnitude =>
+ if (n < 10n) { Small; } else { Large; };
```
-> You can run the function above with
-> ```
-> ligo run-function -s reasonligo src/if-else.religo is_adult 21n
-> ```
-
-
\ No newline at end of file
+You can run the `compare` function defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/boolean-if-else/cond.religo compare 21n'
+# Outputs: Large
+```
+
diff --git a/gitlab-pages/docs/language-basics/functions.md b/gitlab-pages/docs/language-basics/functions.md
index 5cf99f761..d0344a754 100644
--- a/gitlab-pages/docs/language-basics/functions.md
+++ b/gitlab-pages/docs/language-basics/functions.md
@@ -3,131 +3,270 @@ id: functions
title: Functions
---
-Writing code is fun as long as it doesn't get out of hand. To make sure our code doesn't turn into spaghetti we can group some logic into functions.
+LIGO functions are the basic building block of contracts. For example,
+entrypoints are functions.
-## Instruction blocks
-
-With `block`(s) you can wrap *instructions* and *expressions* into an isolated scope.
-Each `block` needs to include at least one `instruction`, or a *placeholder* instruction called `skip`.
+## Declaring Functions
-
+
+
+There are two ways in PascaLIGO to define functions: with or without a
+*block*.
+
+### Blocks
+
+In PascaLIGO, *blocks* enable the sequential composition of
+instructions into an isolated scope. Each block needs to include at
+least one instruction.
```pascaligo skip
-// shorthand syntax
-block { skip }
-// verbose syntax
-begin
- skip
-end
+block { a := a + 1 }
```
-
+If we need a placeholder, we use the instruction `skip` which leaves
+the state unchanged. The rationale for `skip` instead of a truly
+empty block is that it prevents you from writing an empty block by
+mistake.
-## Defining a function
+```pascaligo skip
+block { skip }
+```
-
-
+Blocks are more versatile than simply containing instructions: they
+can also include *declarations* of values, like so:
-Functions in PascaLIGO are defined using the `function` keyword followed by their `name`, `parameters` and `return` type definitions.
+```pascaligo skip
+block { const a : int = 1 }
+```
-Here's how you define a basic function that accepts two `ints` and returns a single `int`:
+Functions in PascaLIGO are defined using the `function` keyword
+followed by their `name`, `parameters` and `return` type definitions.
+Here is how you define a basic function that computes the sum of two
+integers:
```pascaligo group=a
-function add(const a: int; const b: int): int is
- begin
- const result: int = a + b;
- end with result;
+function add (const a : int; const b : int) : int is
+ block {
+ const sum : int = a + b
+ } with sum
```
The function body consists of two parts:
-- `block {}` - logic of the function
-- `with ` - the return value of the function
+- `block { }` is the logic of the function;
+- `with ` is the value returned by the function.
-#### Blockless functions
+### Blockless functions
-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:
+Functions that can contain all of their logic into a single
+*expression* can be defined without the need of a block:
+
+```pascaligo
+function identity (const n : int) : int is block { skip } with n // Bad! Empty block not needed!
+
+function identity (const n : int) : int is n // Blockless
+```
+
+The value of the expression is implicitly returned by the
+function. Another example is as follows:
```pascaligo group=b
-function add(const a: int; const b: int): int is a + b
+function add (const a: int; const b : int) : int is a + b
+```
+
+You can call the function `add` defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function gitlab-pages/docs/language-basics/src/functions/blockless.ligo add '(1,2)'
+# Outputs: 3
```
-Functions in CameLIGO are defined using the `let` keyword, like value bindings.
-The difference is that after the value name a list of function parameters is provided,
-along with a return type.
-
-CameLIGO is a little different from other syntaxes when it comes to function
-parameters. In OCaml, functions can only take one parameter. To get functions
-with multiple arguments like we're used to in traditional programming languages,
-a technique called [currying](https://en.wikipedia.org/wiki/Currying) is used.
-Currying essentially translates a function with multiple arguments into a series
-of single argument functions, each returning a new function accepting the next
-argument until every parameter is filled. This is useful because it means that
-CameLIGO can support [partial application](https://en.wikipedia.org/wiki/Partial_application).
-
-Currying is however *not* the preferred way to pass function arguments in CameLIGO.
-While this approach is faithful to the original OCaml, it's costlier in Michelson
-than naive function execution accepting multiple arguments. Instead for most
-functions with more than one parameter we should place the arguments in a
-[tuple](language-basics/sets-lists-tuples.md) and pass the tuple in as a single
-parameter.
-
-Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
-
-```cameligo group=b
-
-let add (a,b: int * int) : int = a + b
-
-let add_curry (a: int) (b: int) : int = a + b
+Functions in CameLIGO are defined using the `let` keyword, like other
+values. The difference is that a succession of parameters is provided
+after the value name, followed by the return type. This follows OCaml
+syntax. For example:
+```cameligo group=c
+let add (a : int) (b : int) : int = a + b
```
-The function body is a series of expressions, which are evaluated to give the return
-value.
+You can call the function `add` defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function gitlab-pages/docs/language-basics/src/functions/blockless.mligo add '(1,2)'
+# Outputs: 3
+```
+CameLIGO is a little different from other syntaxes when it comes to
+function parameters. In OCaml, functions can only take one
+parameter. To get functions with multiple arguments like we are used
+to in imperative programming languages, a technique called
+[currying](https://en.wikipedia.org/wiki/Currying) is used. Currying
+essentially translates a function with multiple arguments into a
+series of single argument functions, each returning a new function
+accepting the next argument until every parameter is filled. This is
+useful because it means that CameLIGO supports
+[partial application](https://en.wikipedia.org/wiki/Partial_application).
+
+Currying is however *not* the preferred way to pass function arguments
+in CameLIGO. While this approach is faithful to the original OCaml,
+it is costlier in Michelson than naive function execution accepting
+multiple arguments. Instead, for most functions with more than one
+parameter, we should gather the arguments in a
+[tuple](language-basics/sets-lists-tuples.md) and pass the tuple in as
+a single parameter.
+
+Here is how you define a basic function that accepts two integers and
+returns an integer as well:
+
+```cameligo group=b
+let add (a, b : int * int) : int = a + b // Uncurried
+let add_curry (a : int) (b : int) : int = add (a, b) // Curried
+let increment (b : int) : int = add_curry 1 // Partial application
+```
+
+You can run the `increment` function defined above using the LIGO
+compiler like this:
+```shell
+ligo run-function gitlab-pages/docs/language-basics/src/functions/curry.mligo increment 5
+# Outputs: 6
+```
+
+The function body is a single expression, whose value is returned.
-Functions in ReasonLIGO are defined using the `let` keyword, like value bindings.
-The difference is that after the value name a list of function parameters is provided,
-along with a return type.
-
-Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
+Functions in ReasonLIGO are defined using the `let` keyword, like
+other values. The difference is that a tuple of parameters is provided
+after the value name, with its type, then followed by the return type.
+Here is how you define a basic function that sums two integers:
```reasonligo group=b
-let add = ((a,b): (int, int)) : int => a + b;
+let add = ((a, b): (int, int)) : int => a + b;
```
-The function body is a series of expressions, which are evaluated to give the return
-value.
+You can call the function `add` defined above using the LIGO compiler
+like this:
+```shell
+ligo run-function gitlab-pages/docs/language-basics/src/functions/blockless.religo add '(1,2)'
+# Outputs: 3
+```
+
+As in CameLIGO and with blockless functions in PascaLIGO, the function
+body is a single expression, whose value is returned.
+
+If the body contains more than a single expression, you use block
+between braces:
+```reasonligo group=b
+let myFun = ((x, y) : (int, int)) : int => {
+ let doubleX = x + x;
+ let doubleY = y + y;
+ doubleX + doubleY
+};
+```
-## Anonymous functions
+## Anonymous functions (a.k.a. lambdas)
-Functions without a name, also known as anonymous functions are useful in cases when you want to pass the function as an argument or assign it to a key in a record/map.
+It is possible to define functions without assigning them a name. They
+are useful when you want to pass them as arguments, or assign them to
+a key in a record or a map.
+
+Here is how to define an anonymous function:
-Here's how to define an anonymous function assigned to a variable `increment`, with it's appropriate function type signature.
-
+
```pascaligo group=c
-const increment : (int -> int) = (function (const i : int) : int is i + 1);
-// a = 2
-const a: int = increment(1);
+function increment (const b : int) : int is
+ (function (const a : int) : int is a + 1) (b)
+const a : int = increment (1); // a = 2
+```
+
+You can check the value of `a` defined above using the LIGO compiler
+like this:
+```shell
+ligo evaluate-value gitlab-pages/docs/language-basics/src/functions/anon.ligo a
+# Outputs: 2
```
```cameligo group=c
-let increment : (int -> int) = fun (i: int) -> i + 1
+let increment (b : int) : int = (fun (a : int) -> a + 1) b
+let a : int = increment 1 // a = 2
+```
+
+You can check the value of `a` defined above using the LIGO compiler
+like this:
+```shell
+ligo evaluate-value gitlab-pages/docs/language-basics/src/functions/anon.mligo a
+# Outputs: 2
```
```reasonligo group=c
-let increment: (int => int) = (i: int) => i + 1;
+let increment = (b : int) : int => ((a : int) : int => a + 1) (b);
+let a : int = increment (1); // a == 2
+```
+
+You can check the value of `a` defined above using the LIGO compiler
+like this:
+```shell
+ligo evaluate-value gitlab-pages/docs/language-basics/src/functions/anon.religo a
+# Outputs: 2
+```
+
+
+
+If the example above seems contrived, here is a more common design
+pattern for lambdas: to be used as parameters to functions. Consider
+the use case of having a list of integers and mapping the increment
+function to all its elements.
+
+
+
+```pascaligo group=c
+function incr_map (const l : list (int)) : list (int) is
+ list_map (function (const i : int) : int is i + 1, l)
+```
+You can call the function `incr_map` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/functions/incr_map.ligo incr_map
+"list [1;2;3]"
+# Outputs: [ 2 ; 3 ; 4 ]
+```
+
+
+```cameligo group=c
+let incr_map (l : int list) : int list =
+ List.map (fun (i : int) -> i + 1) l
+```
+You can call the function `incr_map` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/functions/incr_map.mligo incr_map
+"list [1;2;3]"
+# Outputs: [ 2 ; 3 ; 4 ]
+```
+
+
+```reasonligo group=c
+let incr_map = (l : list (int)) : list (int) =>
+ List.map ((i : int) => i + 1, l);
+```
+You can call the function `incr_map` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/functions/incr_map.religo incr_map
+"list [1;2;3]"
+# Outputs: [ 2 ; 3 ; 4 ]
```
diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md
index 9fd26d024..bb31e124f 100644
--- a/gitlab-pages/docs/language-basics/loops.md
+++ b/gitlab-pages/docs/language-basics/loops.md
@@ -3,108 +3,246 @@ id: loops
title: Loops
---
-
-
-## While Loop
+## General Iteration
-
+
-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.
+General iteration in PascaLIGO takes the shape of general loops, which
+should be familiar to programmers of imperative languages as "while
+loops". Those loops are of the form `while `. Their
+associated block is repeatedly evaluated until the condition becomes
+true, or never evaluated if the condition is false at the start. The
+loop never terminates if the condition never becomes true. Because we
+are writing smart contracts on Tezos, when the condition of a "while"
+loops fails to become true, the execution will run out of gas and stop
+with a failure anyway.
-> ⚠️ 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.
+Here is how to compute the greatest common divisors of two natural
+numbers by means of Euclid's algorithm:
-```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
+```pascaligo group=a
+function gcd (var x : nat; var y : nat) : nat is
+ block {
+ if x < y then {
+ const z : nat = x;
+ x := y; y := z
+ }
+ else skip;
+ var r : nat := 0n;
+ while y =/= 0n block {
+ r := x mod y;
+ x := y;
+ y := r
+ }
+ } with x
+```
+
+You can call the function `gcd` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/gcd.ligo gcd '(2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)'
+# Outputs: +12
```
-`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 is a functional language where user-defined values are
+constant, therefore it makes no sense in CameLIGO to feature loops,
+which we understand as syntactic constructs where the state of a
+stopping condition is mutated, as with "while" loops in PascaLIGO.
-`continue` and `stop` are provided as syntactic sugar for the return values.
+Instead, CameLIGO implements a *folded operation* by means of a
+predefined function named `Loop.fold_while`. It takes an initial value
+of a certain type, called an *accumulator*, and repeatedly calls a
+given function, called *folded function*, that takes that
+accumulator and returns the next value of the accumulator, until a
+condition is met and the fold stops with the final value of the
+accumulator. The iterated function needs to have a special type: if
+the type of the accumulator is `t`, then it must have the type `bool *
+t` (not simply `t`). It is the boolean value that denotes whether the
+stopping condition has been reached.
-```cameligo
-let aux (i: int) : bool * int =
- if i < 100 then continue (i + 1) else stop i
+Here is how to compute the greatest common divisors of two natural
+numbers by means of Euclid's algorithm:
-let counter_simple (n: int) : int =
- Loop.fold_while aux n
+```cameligo group=a
+let iter (x,y : nat * nat) : bool * (nat * nat) =
+ if y = 0n then false, (x,y) else true, (y, x mod y)
+
+let gcd (x,y : nat * nat) : nat =
+ let x,y = if x < y then y,x else x,y in
+ let x,y = Loop.fold_while iter (x,y)
+ in x
+```
+
+To ease the writing and reading of the iterated functions (here,
+`iter`), two predefined functions are provided: `continue` and `stop`:
+
+```cameligo group=a
+let iter (x,y : nat * nat) : bool * (nat * nat) =
+ if y = 0n then stop (x,y) else continue (y, x mod y)
+
+let gcd (x,y : nat * nat) : nat =
+ let x,y = if x < y then y,x else x,y in
+ let x,y = Loop.fold_while iter (x,y)
+ in x
+```
+You can call the function `gcd` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/gcd.mligo gcd (2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)'
+# Outputs: +12
```
-`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)`.
+ReasonLIGO is a functional language where user-defined values are
+constant, therefore it makes no sense in ReasonLIGO to feature loops,
+which we understand as syntactic constructs where the state of a
+stopping condition is mutated, as with "while" loops in PascaLIGO.
-`continue` and `stop` are provided as syntactic sugar for the return values.
+Instead, ReasonLIGO features a *fold operation* as a predefined
+function named `Loop.fold_while`. It takes an initial value of a
+certain type, called an *accumulator*, and repeatedly calls a given
+function, called *iterated function*, that takes that accumulator and
+returns the next value of the accumulator, until a condition is met
+and the fold stops with the final value of the accumulator. The
+iterated function needs to have a special type: if the type of the
+accumulator is `t`, then it must have the type `bool * t` (not simply
+`t`). It is the boolean value that denotes whether the stopping
+condition has been reached.
-```reasonligo
-let aux = (i: int): (bool, int) =>
- if (i < 100) {
- continue(i + 1);
- } else {
- stop(i);
- };
+Here is how to compute the greatest common divisors of two natural
+numbers by means of Euclid's algorithm:
-let counter_simple = (n: int): int => Loop.fold_while(aux, n);
+```reasonligo group=a
+let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) =>
+ if (y == 0n) { (false, (x,y)); } else { (true, (y, x mod y)); };
+
+let gcd = ((x,y) : (nat, nat)) : nat => {
+ let (x,y) = if (x < y) { (y,x); } else { (x,y); };
+ let (x,y) = Loop.fold_while (iter, (x,y));
+ x
+};
```
+To ease the writing and reading of the iterated functions (here,
+`iter`), two predefined functions are provided: `continue` and `stop`:
+
+```reasonligo group=b
+let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) =>
+ if (y == 0n) { stop ((x,y)); } else { continue ((y, x mod y)); };
+
+let gcd = ((x,y) : (nat, nat)) : nat => {
+ let (x,y) = if (x < y) { (y,x); } else { (x,y); };
+ let (x,y) = Loop.fold_while (iter, (x,y));
+ x
+};
+```
-## For Loop
+## Bounded Loops
-
-
+In addition to general loops, PascaLIGO features a specialised kind of
+*loop to iterate over bounded intervals*. These loops are familiarly
+known as "for loops" and they have the form `for
+to `, as found in imperative languages.
-To iterate over a range of integers you use a loop of the form `for to `.
+Consider how to sum the natural numbers up to `n`:
-```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
+```pascaligo group=c
+function sum (var n : nat) : int is block {
+ var acc : int := 0;
+ for i := 1 to int (n) block {
+ acc := acc + i
+ }
} with acc
```
-
+(Please do not use that function: there exists a closed form formula.)
-
-
-
-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)
+You can call the function `sum` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/sum.ligo sum 7n
+# Outputs: 28
```
-
+PascaLIGO "for" loops can also iterate through the contents of a
+collection, that is, a list, a set or a map. This is done with a loop
+of the form `for in
+`, where `` is any of the following keywords:
+`list`, `set` or `map`.
+
+Here is an example where the integers in a list are summed up.
+
+```pascaligo group=d
+function sum_list (var l : list (int)) : int is block {
+ var total : int := 0;
+ for i in list l block {
+ total := total + i
+ }
+} with total
+```
+
+You can call the function `sum_list` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/collection.ligo sum_list
+'list [1;2;3]'
+# Outputs: 6
+```
+
+Here is an example where the integers in a set are summed up.
+
+```pascaligo group=d
+function sum_set (var s : set (int)) : int is block {
+ var total : int := 0;
+ for i in set s block {
+ total := total + i
+ }
+} with total
+```
+
+You can call the function `sum_set` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/collection.ligo sum_set
+'set [1;2;3]'
+# Outputs: 6
+```
+
+Loops over maps are actually loops over the bindings of the map, that
+is, a pair key-value noted `key -> value` (or any other
+variables). Given a map from strings to integers, here is how to sum
+all the integers and concatenate all the strings.
+
+Here is an example where the keys are concatenated and the values are
+summed up.
+
+```pascaligo group=d
+function sum_map (var m : map (string, int)) : string * int is block {
+ var string_total : string := "";
+ var int_total : int := 0;
+ for key -> value in map m block {
+ string_total := string_total ^ key;
+ int_total := int_total + value
+ }
+} with (string_total, int_total)
+```
+
+You can call the function `sum_map` defined above using the LIGO compiler
+like so:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/loops/collection.ligo sum_map
+'map ["1"->1; "2"->2; "3"->3]'
+# Outputs: ( "123", 6 )
+```
diff --git a/gitlab-pages/docs/language-basics/maps-records.md b/gitlab-pages/docs/language-basics/maps-records.md
index 5f51de96c..d691d588e 100644
--- a/gitlab-pages/docs/language-basics/maps-records.md
+++ b/gitlab-pages/docs/language-basics/maps-records.md
@@ -1,510 +1,899 @@
---
id: maps-records
-title: Maps, Records
+title: Records and Maps
---
-So far we've seen pretty basic data types. LIGO also offers more complex built-in constructs, such as Maps and Records.
+So far we have seen pretty basic data types. LIGO also offers more
+complex built-in constructs, such as *records* and *maps*.
-## Maps
+## Records
-Maps are natively available in Michelson, and LIGO builds on top of them. A requirement for a Map is that its keys be of the same type, and that type must be comparable.
+Records are one way data of different types can be packed into a
+single type. A record is made of a set of *fields*, which are made of
+a *field name* and a *field type*. Given a value of a record type, the
+value bound to a field can be accessed by giving its field name to a
+special operator (`.`).
-Here's how a custom map type is defined:
+Let us first consider and example of record type declaration.
-
-```pascaligo
-type move is (int * int);
-type moveset is map(address, move);
-```
-
-```cameligo
-type move = int * int
-type moveset = (address, move) map
-```
-
-
-```reasonligo
-type move = (int, int);
-type moveset = map(address, move);
-```
-
-
-
-And here's how a map value is populated:
-
-
-
-
-```pascaligo
-const moves: moveset = map
- ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2);
- ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3);
-end
-```
-> Notice the `->` between the key and its value and `;` to separate individual map entries.
->
-> `("": address)` means that we type-cast a string into an address.
-
-
-
-```cameligo
-let moves: moveset = Map.literal
- [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ;
- (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ;
+
+```pascaligo group=a
+type user is
+ record [
+ id : nat;
+ is_admin : bool;
+ name : string
]
```
-> Map.literal constructs the map from a list of key-value pair tuples, `(, )`.
-> Note also the `;` to separate individual map entries.
->
-> `("": address)` means that we type-cast a string into an address.
-
-
-
-```reasonligo
-let moves : moveset =
- Map.literal([
- ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)),
- ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)),
- ]);
-```
-> Map.literal constructs the map from a list of key-value pair tuples, `(, )`.
->
-> `("": address)` means that we type-cast a string into an address.
-
-
-
-### Accessing map values by key
-
-If we want to access a move from our moveset above, we can use the `[]` operator/accessor to read the associated `move` value. However, the value we'll get will be wrapped as an optional; in our case `option(move)`. Here's an example:
-
-
-
-```pascaligo
-const my_balance : option(move) = moves[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)];
-```
-
-```cameligo
-let my_balance : move option = Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
+```cameligo group=a
+type user = {
+ id : nat;
+ is_admin : bool;
+ name : string
+}
```
-
-```reasonligo
-let my_balance : option(move) =
- Map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
-```
-
-
-#### Obtaining a map value forcefully
-
-Accessing a value in a map yields an option, however you can also get the value directly:
-
-
-
-```pascaligo
-const my_balance : move = get_force(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves);
-```
-
-
-
-```cameligo
-let my_balance : move = Map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
-```
-
-
-
-```reasonligo
-let my_balance : move =
- Map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
-```
-
-
-
-### Updating the contents of a map
-
-
-
-
-
-The values of a PascaLIGO map can be updated using the ordinary assignment syntax:
-
-```pascaligo
-
-function set_ (var m: moveset) : moveset is
- block {
- m[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9);
- } with m
-```
-
-
-
-We can update a map in CameLIGO using the `Map.update` built-in:
-
-```cameligo
-
-let updated_map: moveset = Map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) (Some (4,9)) moves
-```
-
-
-
-We can update a map in ReasonLIGO using the `Map.update` built-in:
-
-```reasonligo
-
-let updated_map: moveset = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves);
-```
-
-
-
-
-### Iteration over the contents of a map
-
-There are three kinds of iteration on LIGO maps, `iter`, `map` and `fold`. `iter`
-is an iteration over the map with no return value, its only use is to
-generate side effects. This can be useful if for example you would like to check
-that each value inside of a map is within a certain range, with an error thrown
-otherwise.
-
-
-
-```pascaligo
-function iter_op (const m : moveset) : unit is
- block {
- function aggregate (const i : address ; const j : move) : unit is block
- { if (j.1 > 1) then skip else failwith("fail") } with unit ;
- } with map_iter(aggregate, m) ;
-```
-
-
-```cameligo
-let iter_op (m : moveset) : unit =
- let assert_eq = fun (i,j: address * move) -> assert (j.0 > 1)
- in Map.iter assert_eq m
-```
-
-
-```reasonligo
-let iter_op = (m: moveset): unit => {
- let assert_eq = ((i,j): (address, move)) => assert(j[0] > 1);
- Map.iter(assert_eq, m);
+```reasonligo group=a
+type user = {
+ id : nat,
+ is_admin : bool,
+ name : string
};
```
-`map` is a way to create a new map by modifying the contents of an existing one.
+And here is how a record value is defined:
-
-```pascaligo
-function map_op (const m : moveset) : moveset is
- block {
- function increment (const i : address ; const j : move) : move is block { skip } with (j.0, j.1 + 1) ;
- } with map_map(increment, m) ;
+
+```pascaligo group=a
+const alice : user =
+ record [
+ id = 1n;
+ is_admin = True;
+ name = "Alice"
+ ]
```
-```cameligo
-let map_op (m : moveset) : moveset =
- let increment = fun (i,j: address * move) -> (j.0, j.1 + 1)
+```cameligo group=a
+let alice : user = {
+ id = 1n;
+ is_admin = true;
+ name = "Alice"
+}
+```
+
+
+```reasonligo group=a
+let alice : user = {
+ id : 1n,
+ is_admin : true,
+ name : "Alice"
+};
+```
+
+
+### Accessing Record Fields
+
+If we want the contents of a given field, we use the (`.`) infix
+operator, like so:
+
+
+
+```pascaligo group=a
+const alice_admin : bool = alice.is_admin
+```
+
+
+```cameligo group=a
+let alice_admin : bool = alice.is_admin
+```
+
+
+```reasonligo group=a
+let alice_admin : bool = alice.is_admin;
+```
+
+
+### Functional Updates
+
+Given a record value, it is a common design pattern to update only a
+small number of its fields. Instead of copying the fields that are
+unchanged, LIGO offers a way to only update the fields that are
+modified.
+
+One way to understand the update of record values is the *functional
+update*. The idea is to have an *expression* whose value is the
+updated record.
+
+Let us consider defining a function that translates three-dimensional
+points on a plane.
+
+
+
+
+
+In PascaLIGO, the shape of that expression is ` with
+`. The record variable is the record to update and the
+record value is the update itself.
+
+```pascaligo group=b
+type point is record [x : int; y : int; z : int]
+type vector is record [dx : int; dy : int]
+
+const origin : point = record [x = 0; y = 0; z = 0]
+
+function xy_translate (var p : point; const vec : vector) : point is
+ p with record [x = p.x + vec.dx; y = p.y + vec.dy]
+```
+
+You can call the function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_update.ligo
+translate "(record [x=2;y=3;z=1], record [dx=3;dy=4])"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+You have to understand that `p` has not been changed by the functional
+update: a namless new version of it has been created and returned by
+the blockless function.
+
+
+
+The syntax for the functional updates of record in CameLIGO follows
+that of OCaml:
+
+```cameligo group=b
+type point = {x : int; y : int; z : int}
+type vector = {dx : int; dy : int}
+
+let origin : point = {x = 0; y = 0; z = 0}
+
+let xy_translate (p, vec : point * vector) : point =
+ {p with x = p.x + vec.dx; y = p.y + vec.dy}
+```
+
+You can call the function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_update.mligo
+xy_translate "({x=2;y=3;z=1}, {dx=3;dy=4})"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+> You have to understand that `p` has not been changed by the
+> functional update: a nameless new version of it has been created and
+> returned.
+
+
+
+The syntax for the functional updates of record in ReasonLIGO follows
+that of ReasonML:
+
+```reasonligo group=b
+type point = {x : int, y : int, z : int};
+type vector = {dx : int, dy : int};
+
+let origin : point = {x : 0, y : 0, z : 0};
+
+let xy_translate = ((p, vec) : (point, vector)) : point =>
+ {...p, x : p.x + vec.dx, y : p.y + vec.dy};
+```
+
+
+You can call the function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_update.religo
+xy_translate "({x:2,y:3,z:1}, {dx:3,dy:4})"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+You have to understand that `p` has not been changed by the functional
+update: a nameless new version of it has been created and returned.
+
+### Record Patches
+
+Another way to understand what it means to update a record value is to
+make sure that any further reference to the value afterwards will
+exhibit the modification. This is called a `patch` and this is only
+possible in PascaLIGO, because a patch is an *instruction*, therefore
+we can only use it in a block. Similarly to a *functional update*, a
+patch takes a record to be updated and a record with a subset of the
+fields to update, then applies the latter to the former (hence the
+name "patch").
+
+Let us consider defining a function that translates three-dimensional
+points on a plane.
+
+```pascaligo group=c
+type point is record [x : int; y : int; z : int]
+type vector is record [dx : int; dy : int]
+
+const origin : point = record [x = 0; y = 0; z = 0]
+
+function xy_translate (var p : point; const vec : vector) : point is
+ block {
+ patch p with record [x = p.x + vec.dx];
+ patch p with record [y = p.y + vec.dy]
+ } with p
+```
+
+You can call the function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_patch.ligo
+xy_translate "(record [x=2;y=3;z=1], record [dx=3;dy=4])"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+Of course, we can actually translate the point with only one `patch`,
+as the previous example was meant to show that, after the first patch,
+the value of `p` indeed changed. So, a shorter version would be
+
+```pascaligo group=d
+type point is record [x : int; y : int; z : int]
+type vector is record [dx : int; dy : int]
+
+const origin : point = record [x = 0; y = 0; z = 0]
+
+function xy_translate (var p : point; const vec : vector) : point is
+ block {
+ patch p with record [x = p.x + vec.dx; y = p.y + vec.dy]
+ } with p
+```
+
+You can call the new function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_patch2.ligo
+xy_translate "(record [x=2;y=3;z=1], record [dx=3;dy=4])"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+Record patches can actually be simulated with functional updates. All
+we have to do is *declare a new record value with the same name as the
+one we want to update* and use a functional update, like so:
+
+```pascaligo group=e
+type point is record [x : int; y : int; z : int]
+type vector is record [dx : int; dy : int]
+
+const origin : point = record [x = 0; y = 0; z = 0]
+
+function xy_translate (var p : point; const vec : vector) : point is
+ block {
+ const p : point = p with record [x = p.x + vec.dx; y = p.y + vec.dy]
+ } with p
+```
+
+You can call the new function `xy_translate` defined above by running the
+following command of the shell:
+```shell
+ligo run-function
+gitlab-pages/docs/language-basics/src/maps-records/record_simu.ligo
+xy_translate "(record [x=2;y=3;z=1], record [dx=3;dy=4])"
+# Outputs: {z = 1 , y = 7 , x = 5}
+```
+
+The hiding of a variable by another (here `p`) is called `shadowing`.
+
+## Maps
+
+*Maps* are a data structure which associate values of the same type to
+values of the same type. The former are called *key* and the latter
+*values*. Together they make up a *binding*. An additional requirement
+is that the type of the keys must be *comparable*, in the Michelson
+sense.
+
+Here is how a custom map from addresses to a pair of integers is
+defined.
+
+
+
+```pascaligo group=f
+type move is int * int
+type register is map (address, move)
+```
+
+
+```cameligo group=f
+type move = int * int
+type register = (address, move) map
+```
+
+
+```reasonligo group=f
+type move = (int, int);
+type register = map (address, move);
+```
+
+
+And here is how a map value is defined:
+
+
+
+
+```pascaligo group=f
+const moves : register =
+ map [
+ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
+ ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
+```
+
+> Notice the `->` between the key and its value and `;` to separate
+> individual map entries. The annotated value `("" :
+> address)` means that we cast a string into an address. Also, `map`
+> is a keyword.
+
+
+```cameligo group=f
+let moves : register =
+ Map.literal [
+ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
+ (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
+```
+
+> The `Map.literal` predefined function builds a map from a list of
+> key-value pair tuples, `(, )`. Note also the `;` to
+> separate individual map entries. `("": address)`
+> means that we type-cast a string into an address.
+
+
+```reasonligo group=f
+let moves : register =
+ Map.literal ([
+ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
+ ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
+```
+
+> The `Map.literal` predefined function builds a map from a list of
+> key-value pair tuples, `(, )`. Note also the `;` to
+> separate individual map entries. `("": address)`
+> means that we type-cast a string into an address.
+
+
+
+### Accessing Map Bindings
+
+
+
+
+In PascaLIGO, we can use the postfix `[]` operator to read the `move`
+value associated to a given key (`address` here) in the register. Here
+is an example:
+
+```pascaligo group=f
+const my_balance : option (move) =
+ moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
+```
+
+
+```cameligo group=f
+let my_balance : move option =
+ Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
+```
+
+
+```reasonligo group=f
+let my_balance : option (move) =
+ Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves);
+```
+
+
+Notice how the value we read is an optional value: this is to force
+the reader to account for a missing key in the map. This requires
+*pattern matching*.
+
+
+
+
+```pascaligo group=f
+function force_access (const key : address; const moves : register) : move is
+ case moves[key] of
+ Some (move) -> move
+ | None -> (failwith ("No move.") : move)
+ end
+```
+
+
+```cameligo group=f
+let force_access (key, moves : address * register) : move =
+ match Map.find_opt key moves with
+ Some move -> move
+ | None -> (failwith "No move." : move)
+```
+
+
+```reasonligo group=f
+let force_access = ((key, moves) : (address, register)) : move => {
+ switch (Map.find_opt (key, moves)) {
+ | Some (move) => move
+ | None => failwith ("No move.") : move
+ }
+};
+```
+
+
+
+### Updating a Map
+
+Given a map, we may want to add a new binding, remove one, or modify
+one by changing the value associated to an already existing key. We
+may even want to retain the key but not the associated value. All
+those operations are called *updates*.
+
+
+
+
+
+The values of a PascaLIGO map can be updated using the usual
+assignment syntax `
diff --git a/gitlab-pages/website/siteConfig.js b/gitlab-pages/website/siteConfig.js
index c42f07a31..d98334e97 100644
--- a/gitlab-pages/website/siteConfig.js
+++ b/gitlab-pages/website/siteConfig.js
@@ -4,7 +4,7 @@ let reasonHighlightJs = require('reason-highlightjs');
const siteConfig = {
title: 'LIGO', // Title for your website.
- tagline: 'LIGO is a friendly smart-contract language for Tezos',
+ tagline: 'LIGO is a friendly smart contract language for Tezos',
taglineSub: 'Michelson was never so easy',
url: 'https://ligolang.org', // Your website URL
baseUrl: '/', // Base URL for your project */
@@ -14,7 +14,7 @@ const siteConfig = {
// Used for publishing and more
projectName: 'ligo',
- organizationName: 'marigold',
+ organizationName: 'TBN',
// For top-level user or org sites, the organization is still the same.
// e.g., for the https://JoelMarcey.github.io site, it would be set like...
// organizationName: 'JoelMarcey'
@@ -29,7 +29,7 @@ const siteConfig = {
label: 'Tutorials'
},
{ blog: true, label: 'Blog' },
- // TODO: { href: "/odoc", label: "Api" },
+ // TODO: { href: "/odoc", label: "API" },
// { doc: 'contributors/origin', label: 'Contribute' },
{ href: '/contact', label: 'Ask Questions' },
{ search: true }
@@ -40,14 +40,24 @@ const siteConfig = {
{ doc: 'intro/installation', label: 'Install' },
{ doc: 'api/cli-commands', label: 'CLI Commands' },
{ doc: 'contributors/origin', label: 'Contribute' },
- { href: '/odoc', label: 'Api Documentation' }
+ { href: '/odoc', label: 'API Documentation' }
],
community: [
+ {
+ href: 'https://forum.tezosagora.org/tag/ligo',
+ label: 'Tezos Agora Forum',
+ blankTarget: true
+ },
{
href: 'https://tezos.stackexchange.com/questions/tagged/ligo',
label: 'Tezos Stack Exchange',
blankTarget: true
},
+ {
+ href: 'https://t.me/LigoLang',
+ label: 'Telegram',
+ blankTarget: true
+ },
{
href: 'https://discord.gg/9rhYaEt',
label: 'Discord',
@@ -59,7 +69,7 @@ const siteConfig = {
doc: 'tutorials/get-started/tezos-taco-shop-smart-contract',
label: 'Tutorials'
},
- { href: repoUrl, label: 'Gitlab' }
+ { href: repoUrl, label: 'GitLab' }
]
},
@@ -87,10 +97,11 @@ const siteConfig = {
beginKeywords: '',
keywords: {
keyword:
- 'and begin block case const contains down else end fail for ' +
- 'from function if in is list map mod nil not of or patch ' +
- 'procedure record remove set skip step then to type var while with',
- literal: 'true false unit int string some none bool nat list'
+ 'and attributes begin big_map block case const contains else'
+ + ' end False for from function if in is list map mod nil'
+ + ' not of or patch record remove set skip then to True type'
+ + ' var while with',
+ literal: 'true false unit int string Some None bool nat list'
},
lexemes: '[a-zA-Z][a-zA-Z0-9_]*',
contains: [
@@ -139,6 +150,7 @@ const siteConfig = {
indexName: 'ligolang',
algoliaOptions: {} // Optional, if provided by Algolia
},
+ docsSideNavCollapsible: true,
gaTrackingId: 'UA-153751765-1',
gaGtag: true
};
diff --git a/gitlab-pages/website/static/img/telegram.svg b/gitlab-pages/website/static/img/telegram.svg
new file mode 100644
index 000000000..cd4c3a0de
--- /dev/null
+++ b/gitlab-pages/website/static/img/telegram.svg
@@ -0,0 +1,18 @@
+
diff --git a/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md b/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md
index 3b3820ef0..72b6002ac 100644
--- a/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md
+++ b/gitlab-pages/website/versioned_docs/version-next/contributors/origin.md
@@ -4,8 +4,8 @@ title: Origin
original_id: origin
---
-LIGO is a programming language that aims to provide developers with an uncomplicated and safer way to implement smart-contracts. LIGO is currently being implemented for the Tezos blockchain and as a result, it compiles down to Michelson - the native smart-contract language of Tezos.
+LIGO is a programming language that aims to provide developers with an uncomplicated and safe way to implement smart contracts. Since it is being implemented for the Tezos blockchain LIGO compiles to Michelson—the native smart contract language of Tezos.
-> Smart-contracts are programs that run within a blockchain network.
+> Smart contracts are programs that run within a blockchain network.
-LIGO was initially meant to be a language for developing Marigold, on top of a hacky framework called Meta-Michelson. However, due to the attention received by the Tezos community, a decision has been put into action to develop LIGO as a standalone language that will support Tezos directly as well.
\ No newline at end of file
+LIGO was meant to be a language for developing Marigold on top of a hacky framework called Meta-Michelson. However, due to the attention received by the Tezos community, LIGO is now a standalone language being developed to support Tezos directly.
\ No newline at end of file
diff --git a/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md b/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md
index 349c6d131..99c4d7c00 100644
--- a/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md
+++ b/gitlab-pages/website/versioned_docs/version-next/contributors/philosophy.md
@@ -4,23 +4,22 @@ title: Philosophy
original_id: philosophy
---
-To understand LIGO’s design choices, it’s important to get its philosophy. There are two main concerns that we have in mind when building LIGO.
-
-
+To understand LIGO’s design choices it’s important to understand its philosophy. We have two main concerns in mind while building LIGO.
## Safety
-Once a smart-contract is deployed, it will likely be impossible to change it. You must get it right on the first try, and LIGO should help as much as possible. There are multiple ways to make LIGO a safer language for smart-contracts.
+Once a smart contract is deployed, it will likely be impossible to change it. You must get it right on the first try, and LIGO should help as much as possible. There are multiple ways to make LIGO a safer language for smart contracts.
### Automated Testing
-Automated Testing is the process through which a program will run some other program, and check that this other program behaves correctly.
+Automated Testing is the process through which a program runs another program, and checks that this other program behaves correctly.
+
There already is a testing library for LIGO programs written in OCaml that is used to test LIGO itself. Making it accessible to users will greatly improve safety. A way to do so would be to make it accessible from within LIGO.
### Static Analysis
Static analysis is the process of having a program analyze another one.
-For instance, type systems are a kind of static analysis through which it is possible to find lots of bugs. There is already a fairly simple type system in LIGO, and we plan to make it much stronger.
+For instance, type systems are a kind of static analysis through which it is possible to find lots of bugs. LIGO already has a simple type system, and we plan to make it much stronger.
### Conciseness
-Writing less code gives you less room to introduce errors and that's why LIGO encourages writing lean rather than chunky smart-contracts.
+Writing less code gives you less room to introduce errors. That's why LIGO encourages writing lean rather than chunky smart contracts.
---
diff --git a/gitlab-pages/website/versioned_sidebars/version-next-sidebars.json b/gitlab-pages/website/versioned_sidebars/version-next-sidebars.json
index e74ff6d36..07fc287dd 100644
--- a/gitlab-pages/website/versioned_sidebars/version-next-sidebars.json
+++ b/gitlab-pages/website/versioned_sidebars/version-next-sidebars.json
@@ -6,15 +6,27 @@
"version-next-intro/editor-support"
],
"Language Basics": [
- "version-next-language-basics/cheat-sheet",
"version-next-language-basics/types",
- "version-next-language-basics/variables",
+ "version-next-language-basics/constants-and-variables",
+ "version-next-language-basics/math-numbers-tez",
+ "version-next-language-basics/strings",
"version-next-language-basics/functions",
- "version-next-language-basics/entrypoints",
- "version-next-language-basics/operators"
+ "version-next-language-basics/boolean-if-else",
+ "version-next-language-basics/loops",
+ "version-next-language-basics/unit-option-pattern-matching",
+ "version-next-language-basics/maps-records",
+ "version-next-language-basics/sets-lists-tuples",
+ "version-next-language-basics/tezos-specific"
+ ],
+ "Advanced": [
+ "version-next-advanced/timestamps-addresses",
+ "version-next-advanced/entrypoints-contracts",
+ "version-next-advanced/include",
+ "version-next-advanced/first-contract"
],
"API": [
- "version-next-api-cli-commands"
+ "version-next-api/cli-commands",
+ "version-next-api/cheat-sheet"
]
},
"version-next-contributors-docs": {
diff --git a/ligo.opam b/ligo.opam
index 92b0e4051..167e004a8 100644
--- a/ligo.opam
+++ b/ligo.opam
@@ -4,7 +4,7 @@ maintainer: "ligolang@gmail.com"
authors: [ "Galfour" ]
homepage: "https://gitlab.com/ligolang/tezos"
bug-reports: "https://gitlab.com/ligolang/tezos/issues"
-synopsis: "A higher-level language which compiles to Michelson"
+synopsis: "A high-level language which compiles to Michelson"
dev-repo: "git+https://gitlab.com/ligolang/tezos.git"
license: "MIT"
depends: [
@@ -21,6 +21,8 @@ depends: [
"yojson"
"alcotest" { with-test }
"getopt"
+ "terminal_size"
+ "pprint"
# work around upstream in-place update
"ocaml-migrate-parsetree" { = "1.4.0" }
]
diff --git a/scripts/distribution/generic/parameters.sh b/scripts/distribution/generic/parameters.sh
index 436b48bf0..3899711d8 100644
--- a/scripts/distribution/generic/parameters.sh
+++ b/scripts/distribution/generic/parameters.sh
@@ -1,4 +1,4 @@
-# This script accepts three arguments, os family, os and it's version,
+# This script accepts three arguments, os family, os and its version,
# which are subsequently used to fetch the respective docker
# image from the ocaml/infrastructure project.
#
diff --git a/scripts/installer.sh b/scripts/installer.sh
old mode 100755
new mode 100644
index c8623c6a7..ca7c17b83
--- a/scripts/installer.sh
+++ b/scripts/installer.sh
@@ -62,7 +62,7 @@ else
# && redirect the output of the wget download to the temporary file
# ) || clean up temporary file if any command in the previous block failed
- wget "$url" -O - \
+ (wget "$url" -O - 2>/dev/null || echo "ERROR: wget $url failed.") \
| sed -e "s/next/$version/g" \
| sudo sh -c ' \
( \
diff --git a/scripts/test_cli.sh b/scripts/test_cli.sh
index cc9170f5f..5bda10f9f 100755
--- a/scripts/test_cli.sh
+++ b/scripts/test_cli.sh
@@ -7,7 +7,7 @@ dry_run_output=$(./scripts/ligo_ci.sh dry-run src/test/contracts/website2.ligo m
expected_compiled_parameter="(Right 1)";
expected_compiled_storage=1;
-expected_dry_run_output="( [] , 2 )";
+expected_dry_run_output="( list[] , 2 )";
if [ "$compiled_storage" != "$expected_compiled_storage" ]; then
echo "Expected $expected_compiled_storage as compile-storage output, got $compiled_storage instead";
diff --git a/src/bin/cli.ml b/src/bin/cli.ml
index 42cecfd4f..92716d380 100644
--- a/src/bin/cli.ml
+++ b/src/bin/cli.ml
@@ -19,7 +19,7 @@ let source_file n =
let open Arg in
let info =
let docv = "SOURCE_FILE" in
- let doc = "$(docv) is the path to the .ligo or .mligo file of the contract." in
+ let doc = "$(docv) is the path to the smart contract file." in
info ~docv ~doc [] in
required @@ pos n (some string) None info
@@ -42,7 +42,7 @@ let syntax =
let open Arg in
let info =
let docv = "SYNTAX" in
- let doc = "$(docv) is the syntax that will be used. Currently supported syntaxes are \"pascaligo\" and \"cameligo\". By default, the syntax is guessed from the extension (.ligo and .mligo, respectively)." in
+ let doc = "$(docv) is the syntax that will be used. Currently supported syntaxes are \"pascaligo\", \"cameligo\" and \"reasonligo\". By default, the syntax is guessed from the extension (.ligo, .mligo, .religo respectively)." in
info ~docv ~doc ["syntax" ; "s"] in
value @@ opt string "auto" info
@@ -50,7 +50,7 @@ let req_syntax n =
let open Arg in
let info =
let docv = "SYNTAX" in
- let doc = "$(docv) is the syntax that will be used. Currently supported syntaxes are \"pascaligo\" and \"cameligo\". By default, the syntax is guessed from the extension (.ligo and .mligo, respectively)." in
+ let doc = "$(docv) is the syntax that will be used. Currently supported syntaxes are \"pascaligo\", \"cameligo\" and \"reasonligo\". By default, the syntax is guessed from the extension (.ligo, .mligo, .religo respectively)." in
info ~docv ~doc [] in
required @@ pos n (some string) None info
@@ -58,7 +58,7 @@ let init_file =
let open Arg in
let info =
let docv = "INIT_FILE" in
- let doc = "$(docv) is the path to the .ligo or .mligo file to be used for context initialization." in
+ let doc = "$(docv) is the path to smart contract file to be used for context initialization." in
info ~docv ~doc ["init-file"] in
value @@ opt (some string) None info
@@ -66,7 +66,7 @@ let amount =
let open Arg in
let info =
let docv = "AMOUNT" in
- let doc = "$(docv) is the amount the michelson interpreter will use." in
+ let doc = "$(docv) is the amount the Michelson interpreter will use." in
info ~docv ~doc ["amount"] in
value @@ opt string "0" info
@@ -74,7 +74,7 @@ let sender =
let open Arg in
let info =
let docv = "SENDER" in
- let doc = "$(docv) is the sender the michelson interpreter transaction will use." in
+ let doc = "$(docv) is the sender the Michelson interpreter transaction will use." in
info ~docv ~doc ["sender"] in
value @@ opt (some string) None info
@@ -82,7 +82,7 @@ let source =
let open Arg in
let info =
let docv = "SOURCE" in
- let doc = "$(docv) is the source the michelson interpreter transaction will use." in
+ let doc = "$(docv) is the source the Michelson interpreter transaction will use." in
info ~docv ~doc ["source"] in
value @@ opt (some string) None info
@@ -90,7 +90,7 @@ let predecessor_timestamp =
let open Arg in
let info =
let docv = "PREDECESSOR_TIMESTAMP" in
- let doc = "$(docv) is the pedecessor_timestamp (now value minus one minute) the michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')" in
+ let doc = "$(docv) is the predecessor_timestamp (now value minus one minute) the Michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')" in
info ~docv ~doc ["predecessor-timestamp"] in
value @@ opt (some string) None info
@@ -135,58 +135,58 @@ let compile_file =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ syntax $ display_format $ michelson_code_format) in
let cmdname = "compile-contract" in
- let doc = "Subcommand: compile a contract." in
+ let doc = "Subcommand: Compile a contract." in
(Term.ret term , Term.info ~doc cmdname)
-let print_cst =
+let print_cst =
let f source_file syntax display_format = (
toplevel ~display_format @@
- let%bind pp = Compile.Of_source.pretty_print source_file (Syntax_name syntax) in
+ let%bind pp = Compile.Of_source.pretty_print source_file (Syntax_name syntax) in
ok @@ Format.asprintf "%s \n" (Buffer.contents pp)
)
in
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
- let cmdname = "print-cst" in
- let doc = "Subcommand: print the cst. Warning: intended for development of LIGO and can break at any time." in
+ let cmdname = "print-cst" in
+ let doc = "Subcommand: Print the CST.\nWarning: Intended for development of LIGO and can break at any time." in
(Term.ret term, Term.info ~doc cmdname)
-let print_ast =
+let print_ast =
let f source_file syntax display_format = (
toplevel ~display_format @@
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
- ok @@ Format.asprintf "%a\n" Compile.Of_simplified.pretty_print simplified
+ ok @@ Format.asprintf "%a\n" Compile.Of_simplified.pretty_print simplified
)
in
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
- let cmdname = "print-ast" in
- let doc = "Subcommand: print the ast. Warning: intended for development of LIGO and can break at any time." in
+ let cmdname = "print-ast" in
+ let doc = "Subcommand: Print the AST.\n Warning: Intended for development of LIGO and can break at any time." in
(Term.ret term, Term.info ~doc cmdname)
-let print_typed_ast =
+let print_typed_ast =
let f source_file syntax display_format = (
toplevel ~display_format @@
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
let%bind typed,_ = Compile.Of_simplified.compile simplified in
- ok @@ Format.asprintf "%a\n" Compile.Of_typed.pretty_print typed
+ ok @@ Format.asprintf "%a\n" Compile.Of_typed.pretty_print typed
)
in
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
- let cmdname = "print-typed-ast" in
- let doc = "Subcommand: print the typed ast. Warning: intended for development of LIGO and can break at any time." in
+ let cmdname = "print-typed-ast" in
+ let doc = "Subcommand: Print the typed AST.\n Warning: Intended for development of LIGO and can break at any time." in
(Term.ret term, Term.info ~doc cmdname)
-let print_mini_c =
+let print_mini_c =
let f source_file syntax display_format = (
toplevel ~display_format @@
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
let%bind typed,_ = Compile.Of_simplified.compile simplified in
let%bind mini_c = Compile.Of_typed.compile typed in
- ok @@ Format.asprintf "%a\n" Compile.Of_mini_c.pretty_print mini_c
+ ok @@ Format.asprintf "%a\n" Compile.Of_mini_c.pretty_print mini_c
)
in
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
- let cmdname = "print-mini-c" in
- let doc = "Subcommand: print mini c. Warning: intended for development of LIGO and can break at any time." in
+ let cmdname = "print-mini-c" in
+ let doc = "Subcommand: Print Mini-C. Warning: Intended for development of LIGO and can break at any time." in
(Term.ret term, Term.info ~doc cmdname)
let measure_contract =
@@ -203,7 +203,7 @@ let measure_contract =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ syntax $ display_format) in
let cmdname = "measure-contract" in
- let doc = "Subcommand: measure a contract's compiled size in bytes." in
+ let doc = "Subcommand: Measure a contract's compiled size in bytes." in
(Term.ret term , Term.info ~doc cmdname)
let compile_parameter =
@@ -232,7 +232,7 @@ let compile_parameter =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ syntax $ amount $ sender $ source $ predecessor_timestamp $ display_format $ michelson_code_format) in
let cmdname = "compile-parameter" in
- let doc = "Subcommand: compile parameters to a michelson expression. The resulting michelson expression can be passed as an argument in a transaction which calls a contract." in
+ let doc = "Subcommand: Compile parameters to a Michelson expression. The resulting Michelson expression can be passed as an argument in a transaction which calls a contract." in
(Term.ret term , Term.info ~doc cmdname)
let interpret =
@@ -246,7 +246,7 @@ let interpret =
let env = Ast_typed.program_environment typed_prg in
ok (mini_c_prg,state,env)
| None -> ok ([],Typer.Solver.initial_state,Ast_typed.Environment.full_empty) in
-
+
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) init_file in
let%bind simplified_exp = Compile.Of_source.compile_expression v_syntax expression in
let%bind (typed_exp,_) = Compile.Of_simplified.compile_expression ~env ~state simplified_exp in
@@ -259,15 +259,28 @@ let interpret =
let%bind failstring = Run.failwith_to_string fail_res in
ok @@ Format.asprintf "%s" failstring
| Success value' ->
- let%bind simplified_output = Uncompile.uncompile_expression typed_exp.type_annotation value' in
+ let%bind simplified_output = Uncompile.uncompile_expression typed_exp.type_expression value' in
ok @@ Format.asprintf "%a\n" Ast_simplified.PP.expression simplified_output
in
let term =
Term.(const f $ expression "EXPRESSION" 0 $ init_file $ syntax $ amount $ sender $ source $ predecessor_timestamp $ display_format ) in
let cmdname = "interpret" in
- let doc = "Subcommand: interpret the expression in the context initialized by the provided source file." in
+ let doc = "Subcommand: Interpret the expression in the context initialized by the provided source file." in
(Term.ret term , Term.info ~doc cmdname)
+let temp_ligo_interpreter =
+ let f source_file syntax display_format =
+ toplevel ~display_format @@
+ let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
+ let%bind typed,_ = Compile.Of_simplified.compile simplified in
+ let%bind res = Compile.Of_typed.some_interpret typed in
+ ok @@ Format.asprintf "%s\n" res
+ in
+ let term =
+ Term.(const f $ source_file 0 $ syntax $ display_format ) in
+ let cmdname = "ligo-interpret" in
+ let doc = "Subcommand: (temporary / dev only) uses LIGO interpret." in
+ (Term.ret term , Term.info ~doc cmdname)
let compile_storage =
let f source_file entry_point expression syntax amount sender source predecessor_timestamp display_format michelson_format =
@@ -285,7 +298,7 @@ let compile_storage =
let%bind simplified_param = Compile.Of_source.compile_expression v_syntax expression in
let%bind (typed_param,_) = Compile.Of_simplified.compile_expression ~env ~state simplified_param in
let%bind mini_c_param = Compile.Of_typed.compile_expression typed_param in
- let%bind compiled_param = Compile.Of_mini_c.compile_expression mini_c_param in
+ let%bind compiled_param = Compile.Of_mini_c.aggregate_and_compile_expression mini_c_prg mini_c_param in
let%bind () = Compile.Of_typed.assert_equal_contract_type Check_storage entry_point typed_prg typed_param in
let%bind () = Compile.Of_michelson.assert_equal_contract_type Check_storage michelson_prg compiled_param in
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; sender ; source } in
@@ -295,7 +308,7 @@ let compile_storage =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "STORAGE" 2 $ syntax $ amount $ sender $ source $ predecessor_timestamp $ display_format $ michelson_code_format) in
let cmdname = "compile-storage" in
- let doc = "Subcommand: compile an initial storage in ligo syntax to a michelson expression. The resulting michelson expression can be passed as an argument in a transaction which originates a contract." in
+ let doc = "Subcommand: Compile an initial storage in ligo syntax to a Michelson expression. The resulting Michelson expression can be passed as an argument in a transaction which originates a contract." in
(Term.ret term , Term.info ~doc cmdname)
let dry_run =
@@ -330,7 +343,7 @@ let dry_run =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ expression "STORAGE" 3 $ amount $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
let cmdname = "dry-run" in
- let doc = "Subcommand: run a smart-contract with the given storage and input." in
+ let doc = "Subcommand: Run a smart-contract with the given storage and input." in
(Term.ret term , Term.info ~doc cmdname)
let run_function =
@@ -342,6 +355,7 @@ let run_function =
let env = Ast_typed.program_environment typed_prg in
let%bind mini_c_prg = Compile.Of_typed.compile typed_prg in
+
let%bind simplified_param = Compile.Of_source.compile_expression v_syntax parameter in
let%bind app = Compile.Of_simplified.apply entry_point simplified_param in
let%bind (typed_app,_) = Compile.Of_simplified.compile_expression ~env ~state app in
@@ -361,7 +375,7 @@ let run_function =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ amount $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
let cmdname = "run-function" in
- let doc = "Subcommand: run a function with the given parameter." in
+ let doc = "Subcommand: Run a function with the given parameter." in
(Term.ret term , Term.info ~doc cmdname)
let evaluate_value =
@@ -380,7 +394,7 @@ let evaluate_value =
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ amount $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
let cmdname = "evaluate-value" in
- let doc = "Subcommand: evaluate a given definition." in
+ let doc = "Subcommand: Evaluate a given definition." in
(Term.ret term , Term.info ~doc cmdname)
let compile_expression =
@@ -399,7 +413,7 @@ let compile_expression =
let term =
Term.(const f $ expression "" 1 $ req_syntax 0 $ display_format $ michelson_code_format) in
let cmdname = "compile-expression" in
- let doc = "Subcommand: compile to a michelson value." in
+ let doc = "Subcommand: Compile to a michelson value." in
(Term.ret term , Term.info ~doc cmdname)
let dump_changelog =
@@ -410,8 +424,22 @@ let dump_changelog =
let doc = "Dump the LIGO changelog to stdout." in
(Term.ret term , Term.info ~doc cmdname)
+let list_declarations =
+ let f source_file syntax =
+ toplevel ~display_format:(`Human_readable) @@
+ let%bind simplified_prg = Compile.Of_source.compile source_file (Syntax_name syntax) in
+ let json_decl = List.map (fun decl -> `String decl) @@ Compile.Of_simplified.list_declarations simplified_prg in
+ ok @@ J.to_string @@ `Assoc [ ("source_file", `String source_file) ; ("declarations", `List json_decl) ]
+ in
+ let term =
+ Term.(const f $ source_file 0 $ syntax ) in
+ let cmdname = "list-declarations" in
+ let doc = "Subcommand: List all the top-level declarations." in
+ (Term.ret term , Term.info ~doc cmdname)
+
let run ?argv () =
Term.eval_choice ?argv main [
+ temp_ligo_interpreter ;
compile_file ;
measure_contract ;
compile_parameter ;
@@ -425,5 +453,6 @@ let run ?argv () =
print_cst ;
print_ast ;
print_typed_ast ;
- print_mini_c
+ print_mini_c ;
+ list_declarations ;
]
diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml
index 443102d80..2a3c4bd8d 100644
--- a/src/bin/expect_tests/contract_tests.ml
+++ b/src/bin/expect_tests/contract_tests.ml
@@ -7,13 +7,13 @@ let bad_contract basename =
let%expect_test _ =
run_ligo_good [ "measure-contract" ; contract "coase.ligo" ; "main" ] ;
- [%expect {| 2066 bytes |}] ;
+ [%expect {| 1747 bytes |}] ;
run_ligo_good [ "measure-contract" ; contract "multisig.ligo" ; "main" ] ;
- [%expect {| 1093 bytes |}] ;
+ [%expect {| 1358 bytes |}] ;
run_ligo_good [ "measure-contract" ; contract "multisig-v2.ligo" ; "main" ] ;
- [%expect {| 2717 bytes |}] ;
+ [%expect {| 3294 bytes |}] ;
run_ligo_good [ "measure-contract" ; contract "vote.mligo" ; "main" ] ;
[%expect {| 642 bytes |}] ;
@@ -26,7 +26,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-storage" ; contract "coase.ligo" ; "main" ; "Buy_single (record card_to_buy = 1n end)" ] ;
[%expect {|
- ligo: different kinds: {"a":"record[next_id -> nat , cards -> (TO_Map (nat,record[card_pattern -> nat , card_owner -> address])) , card_patterns -> (TO_Map (nat,record[quantity -> nat , coefficient -> mutez]))]","b":"sum[Transfer_single -> record[destination -> address , card_to_transfer -> nat] , Sell_single -> record[card_to_sell -> nat] , Buy_single -> record[card_to_buy -> nat]]"}
+ ligo: different kinds: {"a":"record[card_patterns -> (TO_Map (nat,record[coefficient -> mutez , quantity -> nat])) , cards -> (TO_Map (nat,record[card_owner -> address , card_pattern -> nat])) , next_id -> nat]","b":"sum[Buy_single -> record[card_to_buy -> nat] , Sell_single -> record[card_to_sell -> nat] , Transfer_single -> record[card_to_transfer -> nat , destination -> address]]"}
If you're not sure how to fix this error, you can
@@ -39,7 +39,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-parameter" ; contract "coase.ligo" ; "main" ; "record cards = (map end : cards) ; card_patterns = (map end : card_patterns) ; next_id = 3n ; end" ] ;
[%expect {|
- ligo: different kinds: {"a":"sum[Transfer_single -> record[destination -> address , card_to_transfer -> nat] , Sell_single -> record[card_to_sell -> nat] , Buy_single -> record[card_to_buy -> nat]]","b":"record[next_id -> nat , cards -> (TO_Map (nat,record[card_pattern -> nat , card_owner -> address])) , card_patterns -> (TO_Map (nat,record[quantity -> nat , coefficient -> mutez]))]"}
+ ligo: different kinds: {"a":"sum[Buy_single -> record[card_to_buy -> nat] , Sell_single -> record[card_to_sell -> nat] , Transfer_single -> record[card_to_transfer -> nat , destination -> address]]","b":"record[card_patterns -> (TO_Map (nat,record[coefficient -> mutez , quantity -> nat])) , cards -> (TO_Map (nat,record[card_owner -> address , card_pattern -> nat])) , next_id -> nat]"}
If you're not sure how to fix this error, you can
@@ -86,7 +86,7 @@ let%expect_test _ =
SWAP ;
DIP { DUP ; CAR ; CAR } ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
DUP ;
CAR ;
DIP { DUP ; CDR ; PUSH nat 1 ; ADD } ;
@@ -97,65 +97,56 @@ let%expect_test _ =
COMPARE ;
GT ;
IF { PUSH string "Not enough money" ; FAILWITH } { PUSH unit Unit } ;
- DROP ;
- NIL operation ;
DIP 2 { DUP } ;
DIG 2 ;
- CDR ;
- PUSH nat 1 ;
- ADD ;
- DIP { DIP 2 { DUP } ; DIG 2 ; CAR } ;
- SWAP ;
- PAIR ;
- DIP 3 { DROP } ;
- DUG 2 ;
DIP 3 { DUP } ;
DIG 3 ;
- CAR ;
- CAR ;
- DIP 5 { DUP } ;
- DIG 5 ;
- DIP { DIP 3 { DUP } ; DIG 3 ; SOME ; DIP { DUP } } ;
- UPDATE ;
- DIP { DROP } ;
- DUP ;
- DIP { DIP 4 { DUP } ; DIG 4 ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
- PAIR ;
- PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- DIP 4 { DUP } ;
- DIG 4 ;
- CAR ;
- CDR ;
- DIP 5 { DUP } ;
- DIG 5 ;
- CDR ;
- DIP { DIP 6 { DUP } ; DIG 6 ; SOURCE ; PAIR ; SOME ; DIP { DUP } } ;
- UPDATE ;
- DIP { DROP } ;
- DUP ;
- DIP { DIP 5 { DUP } ; DIG 5 ; DUP ; CDR ; SWAP ; CAR ; CAR } ;
- SWAP ;
- PAIR ;
- PAIR ;
- DIP 6 { DROP } ;
- DUG 5 ;
- DIP 5 { DUP } ;
- DIG 5 ;
CDR ;
PUSH nat 1 ;
ADD ;
- DIP { DIP 5 { DUP } ; DIG 5 ; CAR } ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 6 { DUP } ;
+ DIG 6 ;
+ DIP { DIP { DUP } ;
+ SWAP ;
+ SOME ;
+ DIP { DIP 5 { DUP } ; DIG 5 ; CAR ; CAR } } ;
+ UPDATE ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CDR } ;
+ PAIR ;
+ PAIR ;
+ DUP ;
+ DIP { DUP } ;
+ SWAP ;
+ CDR ;
+ DIP { DIP 7 { DUP } ;
+ DIG 7 ;
+ SOURCE ;
+ PAIR ;
+ SOME ;
+ DIP { DIP { DUP } ; SWAP ; CAR ; CDR } } ;
+ UPDATE ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
SWAP ;
PAIR ;
- DIP 6 { DROP } ;
- DUG 5 ;
- DIP 2 { DUP } ;
- DIG 2 ;
- DIP { DIP 5 { DUP } ; DIG 5 } ;
PAIR ;
- DIP { DROP 9 } }
+ DUP ;
+ DIP { DUP } ;
+ SWAP ;
+ CDR ;
+ PUSH nat 1 ;
+ ADD ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DUP ;
+ NIL operation ;
+ PAIR ;
+ DIP { DROP 11 } }
{ DUP ;
DIP { DIP 2 { DUP } ; DIG 2 } ;
PAIR ;
@@ -168,7 +159,7 @@ let%expect_test _ =
SWAP ;
DIP { DUP ; CAR ; CDR } ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
DUP ;
CAR ;
SOURCE ;
@@ -177,54 +168,40 @@ let%expect_test _ =
NEQ ;
IF { PUSH string "This card doesn't belong to you" ; FAILWITH }
{ PUSH unit Unit } ;
- DROP ;
- DUP ;
+ DIP { DUP } ;
+ SWAP ;
CDR ;
- DIP { DIP { DUP } ; SWAP ; CAR ; CAR } ;
+ DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR } ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
DUP ;
+ DIP { DUP } ;
+ SWAP ;
CDR ;
PUSH nat 1 ;
SWAP ;
SUB ;
ABS ;
- DIP { DUP ; CAR } ;
SWAP ;
+ CAR ;
PAIR ;
- DIP { DROP } ;
- DIP 2 { DUP } ;
- DIG 2 ;
- CAR ;
- CAR ;
- DIP 2 { DUP } ;
- DIG 2 ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
CDR ;
- DIP { DIP { DUP } ; SWAP ; SOME ; DIP { DUP } } ;
+ DIP { DIP { DUP } ;
+ SWAP ;
+ SOME ;
+ DIP { DIP 5 { DUP } ; DIG 5 ; CAR ; CAR } } ;
UPDATE ;
- DIP { DROP } ;
- DUP ;
- DIP { DIP 3 { DUP } ; DIG 3 ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CDR } ;
PAIR ;
PAIR ;
- DIP 4 { DROP } ;
- DUG 3 ;
- DIP 3 { DUP } ;
- DIG 3 ;
- CAR ;
- CDR ;
- DIP 5 { DUP } ;
- DIG 5 ;
- DIP { DUP ; NONE (pair (address %card_owner) (nat %card_pattern)) } ;
+ DIP 6 { DUP } ;
+ DIG 6 ;
+ DIP { DUP ; CAR ; CDR ; NONE (pair (address %card_owner) (nat %card_pattern)) } ;
UPDATE ;
- DIP { DROP } ;
- DUP ;
- DIP { DIP 4 { DUP } ; DIG 4 ; DUP ; CDR ; SWAP ; CAR ; CAR } ;
- SWAP ;
- PAIR ;
- PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
DIP 2 { DUP } ;
DIG 2 ;
CAR ;
@@ -242,9 +219,16 @@ let%expect_test _ =
NIL operation ;
SWAP ;
CONS ;
- DIP { DIP 7 { DUP } ; DIG 7 } ;
+ DIP { DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
+ SWAP ;
+ PAIR ;
+ PAIR } ;
PAIR ;
- DIP { DROP 11 } } ;
+ DIP { DROP 13 } } ;
DIP { DROP } }
{ DUP ;
DIP { DIP { DUP } ; SWAP } ;
@@ -262,7 +246,7 @@ let%expect_test _ =
CAR ;
DIP { DUP } ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
DUP ;
CAR ;
SOURCE ;
@@ -271,33 +255,30 @@ let%expect_test _ =
NEQ ;
IF { PUSH string "This card doesn't belong to you" ; FAILWITH }
{ PUSH unit Unit } ;
- DROP ;
- DIP 3 { DUP } ;
- DIG 3 ;
- CDR ;
- DIP { DUP ; CDR } ;
- PAIR ;
- DIP { DROP } ;
DIP 3 { DUP } ;
DIG 3 ;
+ DIP 5 { DUP } ;
+ DIG 5 ;
CAR ;
- DIP { DUP ; SOME ; DIP { DIP { DUP } ; SWAP } } ;
+ DIP { DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP 6 { DUP } ;
+ DIG 6 ;
+ CDR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ SOME ;
+ DIP { DIP 3 { DUP } ; DIG 3 } } ;
UPDATE ;
- DIP { DIP { DUP } ; SWAP ; DROP } ;
- SWAP ;
- DIP { DIP { DROP } ; DUP } ;
- SWAP ;
- DIP { DIP 2 { DUP } ; DIG 2 ; DUP ; CDR ; SWAP ; CAR ; CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
SWAP ;
PAIR ;
PAIR ;
- DIP 3 { DROP } ;
- DUG 2 ;
- DIP 2 { DUP } ;
- DIG 2 ;
NIL operation ;
PAIR ;
- DIP { DROP 6 } } ;
+ DIP { DROP 7 } } ;
DIP { DROP 2 } } } |} ]
let%expect_test _ =
@@ -305,7 +286,7 @@ let%expect_test _ =
[%expect {|
{ parameter
(pair (pair (nat %counter) (lambda %message unit (list operation)))
- (list %signatures (pair key_hash signature))) ;
+ (list %signatures (pair (key_hash %0) (signature %1)))) ;
storage
(pair (pair (list %auth key) (nat %counter)) (pair (string %id) (nat %threshold))) ;
code { DUP ;
@@ -321,112 +302,170 @@ let%expect_test _ =
SWAP ;
CAR ;
CDR ;
- DIP 2 { DUP } ;
- DIG 2 ;
+ DUP ;
+ DIP { DIP 2 { DUP } ; DIG 2 } ;
+ PAIR ;
+ DIP { DIP { DUP } ; SWAP } ;
+ PAIR ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
CAR ;
CAR ;
- DIP { DIP { DUP } ; SWAP ; CAR ; CDR } ;
+ DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CDR } ;
COMPARE ;
NEQ ;
IF { PUSH string "Counters does not match" ; FAILWITH }
- { DUP ;
- DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR } ;
- PAIR ;
- DIP { DIP { DUP } ; SWAP ; CDR ; CAR ; CHAIN_ID ; SWAP ; PAIR } ;
- PAIR ;
- PACK ;
- PUSH nat 0 ;
- DIP 3 { DUP } ;
+ { DIP 3 { DUP } ;
DIG 3 ;
- CAR ;
- CAR ;
- DIP 5 { DUP } ;
- DIG 5 ;
CDR ;
- DIP { DUP ; DIP { DIP { DUP } ; SWAP } ; PAIR } ;
+ DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR ; PUSH nat 0 ; SWAP ; PAIR } ;
ITER { SWAP ;
PAIR ;
DUP ;
CAR ;
- DIP { DUP } ;
- SWAP ;
- CDR ;
+ CAR ;
DIP { DUP } ;
SWAP ;
CAR ;
+ CDR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ CDR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP { DIP { DUP } ; SWAP } ;
+ PAIR ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
IF_CONS
- { DIP { DUP } ;
- SWAP ;
- DIP { DIP 3 { DUP } ; DIG 3 ; CDR } ;
- PAIR ;
- DIP 4 { DROP } ;
- DUG 3 ;
- DIP 2 { DUP } ;
- DIG 2 ;
+ { DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
CAR ;
- DIP { DUP ; HASH_KEY } ;
+ DIP { DIP { DUP } ; SWAP ; HASH_KEY } ;
COMPARE ;
EQ ;
- IF { DUP ;
- DIP { DIP 2 { DUP } ; DIG 2 ; CDR ; DIP { DIP 7 { DUP } ; DIG 7 } } ;
+ IF { DIP 5 { DUP } ;
+ DIG 5 ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP { DIP 5 { DUP } ;
+ DIG 5 ;
+ CDR ;
+ DIP { DIP 10 { DUP } ;
+ DIG 10 ;
+ DIP { DIP 12 { DUP } ; DIG 12 ; CAR ; CAR } ;
+ PAIR ;
+ DIP { DIP 11 { DUP } ; DIG 11 ; CDR ; CAR ; CHAIN_ID ; SWAP ; PAIR } ;
+ PAIR ;
+ PACK } } ;
CHECK_SIGNATURE ;
- IF { DIP 3 { DUP } ;
- DIG 3 ;
- CDR ;
+ IF { DIP 6 { DUP } ;
+ DIG 6 ;
PUSH nat 1 ;
ADD ;
- DIP { DIP 3 { DUP } ; DIG 3 ; CAR } ;
+ DIP { DUP } ;
SWAP ;
- PAIR ;
- DIP 4 { DROP } ;
- DUG 3 ;
- PUSH unit Unit }
- { PUSH string "Invalid signature" ; FAILWITH } }
- { PUSH unit Unit } ;
- DIP { DROP 2 } }
- { PUSH unit Unit } ;
- DROP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DROP 2 } }
+ { PUSH string "Invalid signature" ; FAILWITH } ;
+ DIP { DROP ; DUP } ;
+ SWAP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DROP 2 } }
+ { DUP } ;
+ DIP { DROP } ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DROP 3 } }
+ { DUP } ;
+ DIP { DROP } ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 5 { DUP } ;
+ DIG 5 ;
+ CAR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ CDR ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ DUP ;
DIP { DUP } ;
SWAP ;
- DIP { DROP 3 } } ;
- DUP ;
- CAR ;
- DIP { DIP { DUP } ; SWAP ; DROP } ;
- SWAP ;
- DIP { DIP { DROP } } ;
- DUP ;
- CDR ;
- DIP { DIP 2 { DUP } ; DIG 2 ; DROP } ;
- DIP 3 { DROP } ;
- DUG 2 ;
- DROP ;
+ CAR ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
+ CAR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ CAR ;
+ DIP { DROP 6 } } ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
DIP { DUP } ;
SWAP ;
+ CDR ;
DIP { DIP 4 { DUP } ; DIG 4 ; CDR ; CDR } ;
COMPARE ;
LT ;
IF { PUSH string "Not enough signatures passed the check" ; FAILWITH }
{ DIP 4 { DUP } ;
DIG 4 ;
+ DIP 5 { DUP } ;
+ DIG 5 ;
CAR ;
CDR ;
PUSH nat 1 ;
ADD ;
- DIP { DIP 4 { DUP } ; DIG 4 ; DUP ; CDR ; SWAP ; CAR ; CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
SWAP ;
PAIR ;
PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- PUSH unit Unit } ;
- DIP { DROP 3 } } ;
- DROP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DROP 2 } } ;
+ DIP { DROP } ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DROP 2 } } ;
+ DIP { DROP } ;
DUP ;
+ CAR ;
+ CAR ;
UNIT ;
EXEC ;
- DIP { DIP { DUP } ; SWAP } ;
+ DIP { DUP ; CDR } ;
PAIR ;
- DIP { DROP 5 } } } |} ]
+ DIP { DROP 6 } } } |} ]
let%expect_test _ =
run_ligo_good [ "compile-contract" ; contract "multisig-v2.ligo" ; "main" ] ;
@@ -461,194 +500,183 @@ let%expect_test _ =
MEM ;
NOT ;
IF { PUSH string "Unauthorized address" ; FAILWITH } { PUSH unit Unit } ;
- DROP ;
- DIP { DUP } ;
- SWAP ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
CAR ;
DUP ;
PACK ;
DUP ;
SIZE ;
- DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR ; CDR } ;
+ DIP { DIP 3 { DUP } ; DIG 3 ; CAR ; CAR ; CDR } ;
COMPARE ;
GT ;
IF { PUSH string "Message size exceed maximum limit" ; FAILWITH }
{ PUSH unit Unit } ;
- DROP ;
- DUP ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
EMPTY_SET address ;
- SWAP ;
- DIP { DIP 3 { DUP } ; DIG 3 ; CAR ; CDR ; CDR } ;
+ PAIR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP { DIP 5 { DUP } ; DIG 5 ; CAR ; CDR ; CDR } ;
GET ;
IF_NONE
- { DIP 3 { DUP } ;
- DIG 3 ;
+ { DIP 5 { DUP } ;
+ DIG 5 ;
+ DIP 6 { DUP } ;
+ DIG 6 ;
CDR ;
CAR ;
CAR ;
SENDER ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
PUSH nat 1 ;
ADD ;
SOME ;
- DIP { DIP 3 { DUP } ; DIG 3 ; CDR ; CAR ; CAR } ;
+ DIP { DIP 6 { DUP } ; DIG 6 ; CDR ; CAR ; CAR } ;
SENDER ;
UPDATE ;
- DIP { DIP 3 { DUP } ;
- DIG 3 ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- CDR } ;
+ DIP { DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
PAIR ;
PAIR ;
SWAP ;
PAIR ;
- DIP 4 { DROP } ;
- DUG 3 ;
+ DIP { DUP } ;
+ SWAP ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
EMPTY_SET address ;
PUSH bool True ;
SENDER ;
UPDATE ;
- DIP { DROP } ;
- PUSH unit Unit }
- { DUP ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ DIP { DROP } }
+ { DIP 6 { DUP } ;
+ DIG 6 ;
+ DIP { DUP } ;
+ SWAP ;
SENDER ;
MEM ;
- IF { PUSH unit Unit }
- { DIP 4 { DUP } ;
- DIG 4 ;
+ IF { DUP }
+ { DIP 7 { DUP } ;
+ DIG 7 ;
+ DIP 8 { DUP } ;
+ DIG 8 ;
CDR ;
CAR ;
CAR ;
SENDER ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
PUSH nat 1 ;
ADD ;
SOME ;
- DIP { DIP 4 { DUP } ; DIG 4 ; CDR ; CAR ; CAR } ;
+ DIP { DIP 8 { DUP } ; DIG 8 ; CDR ; CAR ; CAR } ;
SENDER ;
UPDATE ;
- DIP { DIP 4 { DUP } ;
- DIG 4 ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- CDR } ;
+ DIP { DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
PAIR ;
PAIR ;
SWAP ;
PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- PUSH unit Unit } ;
- DROP ;
- DUP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DROP 2 } } ;
+ DIP { DROP } ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
PUSH bool True ;
SENDER ;
UPDATE ;
- DIP { DIP { DUP } ; SWAP ; DROP } ;
SWAP ;
- DROP ;
- DIP { DROP } ;
- PUSH unit Unit } ;
- DROP ;
- DIP 3 { DUP } ;
- DIG 3 ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ DIP { DROP 2 } } ;
+ DIP { DROP } ;
+ DUP ;
+ CAR ;
+ DIP { DUP } ;
+ SWAP ;
+ CDR ;
+ DUP ;
CDR ;
CAR ;
CAR ;
SENDER ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
DUP ;
- DIP { DIP 4 { DUP } ; DIG 4 ; CAR ; CDR ; CAR } ;
+ DIP { DIP { DUP } ; SWAP ; CAR ; CDR ; CAR } ;
COMPARE ;
GT ;
IF { PUSH string "Maximum number of proposal reached" ; FAILWITH }
{ PUSH unit Unit } ;
- DROP ;
- NIL operation ;
- DIP 2 { DUP } ;
- DIG 2 ;
+ DIP 7 { DUP } ;
+ DIG 7 ;
+ DIP { DIP 3 { DUP } ; DIG 3 } ;
+ PAIR ;
+ DIP { DIP 6 { DUP } ; DIG 6 ; NIL operation ; SWAP ; PAIR } ;
+ PAIR ;
+ DIP { DIP 2 { DUP } ; DIG 2 } ;
+ PAIR ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
SIZE ;
- DIP { DIP 5 { DUP } ; DIG 5 ; CDR ; CDR } ;
+ DIP { DIP 3 { DUP } ; DIG 3 ; CDR ; CDR } ;
COMPARE ;
GE ;
IF { DIP 3 { DUP } ;
DIG 3 ;
- DIP { DIP 5 { DUP } ; DIG 5 ; CAR ; CDR ; CDR ; NONE (set address) } ;
+ DIP 8 { DUP } ;
+ DIG 8 ;
+ DIP { DIP 4 { DUP } ; DIG 4 ; CAR ; CDR ; CDR ; NONE (set address) } ;
UPDATE ;
- DIP { DIP 5 { DUP } ;
- DIG 5 ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CAR } ;
SWAP ;
PAIR ;
SWAP ;
PAIR ;
PAIR ;
- DIP 6 { DROP } ;
- DUG 5 ;
- DIP 5 { DUP } ;
- DIG 5 ;
+ DUP ;
CDR ;
CAR ;
CDR ;
- DIP { DIP 4 { DUP } ; DIG 4 } ;
+ DIP { DIP 9 { DUP } ; DIG 9 } ;
EXEC ;
- DIP { DROP } ;
- DIP 5 { DUP } ;
- DIG 5 ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
CDR ;
CAR ;
CDR ;
- DIP { DIP 3 { DUP } ; DIG 3 } ;
+ DIP { DIP 10 { DUP } ; DIG 10 } ;
CONCAT ;
SHA256 ;
- DIP { DIP 5 { DUP } ;
- DIG 5 ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- CAR } ;
+ DIP { DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; CAR } ;
SWAP ;
PAIR ;
PAIR ;
SWAP ;
PAIR ;
- DIP 6 { DROP } ;
- DUG 5 ;
- DIP 5 { DUP } ;
- DIG 5 ;
+ DUP ;
CDR ;
CAR ;
CAR ;
- DIP { DIP 5 { DUP } ; DIG 5 } ;
+ DIP { DUP } ;
ITER { SWAP ;
PAIR ;
DUP ;
@@ -663,78 +691,103 @@ let%expect_test _ =
CDR ;
DIP { DUP } ;
SWAP ;
- DIP { DIP 6 { DUP } ; DIG 6 } ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DIP 2 { DUP } ; DIG 2 } ;
+ PAIR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP { DIP 12 { DUP } ; DIG 12 } ;
MEM ;
- IF { DIP { DUP } ;
- SWAP ;
- DIP { DUP ;
+ IF { DIP 3 { DUP } ;
+ DIG 3 ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
+ DIP { DIP 2 { DUP } ;
+ DIG 2 ;
PUSH nat 1 ;
SWAP ;
SUB ;
ABS ;
SOME ;
- DIP { DIP 2 { DUP } ; DIG 2 ; CDR ; CAR ; CAR } } ;
+ DIP { DIP 4 { DUP } ; DIG 4 ; CDR ; CAR ; CAR } } ;
UPDATE ;
- DIP { DIP 2 { DUP } ;
- DIG 2 ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- CDR } ;
+ DIP { DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
PAIR ;
PAIR ;
SWAP ;
PAIR ;
- DIP 3 { DROP } ;
- DUG 2 ;
- PUSH unit Unit }
- { PUSH unit Unit } ;
- DROP ;
+ DIP { DUP } ;
+ SWAP ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DROP } }
+ { DUP } ;
+ DIP { DROP } ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 5 { DUP } ;
+ DIG 5 ;
+ CAR ;
DIP 2 { DUP } ;
DIG 2 ;
- DIP { DROP 4 } } ;
- DUP ;
- DIP { DIP 6 { DUP } ; DIG 6 ; DROP } ;
- DIP 7 { DROP } ;
- DUG 6 ;
- DROP ;
- PUSH unit Unit }
- { DIP 3 { DUP } ;
+ CDR ;
+ DIP { DROP ; CDR } ;
+ PAIR ;
+ CAR ;
+ DIP { DROP 5 } } ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DIP 3 { DUP } ;
DIG 3 ;
- DIP { DIP 2 { DUP } ;
- DIG 2 ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CAR } ;
+ SWAP ;
+ PAIR ;
+ SWAP ;
+ PAIR ;
+ PAIR ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DROP 4 } }
+ { DUP ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 9 { DUP } ;
+ DIG 9 ;
+ DIP { DIP 6 { DUP } ;
+ DIG 6 ;
SOME ;
DIP { DIP 5 { DUP } ; DIG 5 ; CAR ; CDR ; CDR } } ;
UPDATE ;
- DIP { DIP 5 { DUP } ;
- DIG 5 ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CAR } ;
SWAP ;
PAIR ;
SWAP ;
PAIR ;
PAIR ;
- DIP 6 { DROP } ;
- DUG 5 ;
- PUSH unit Unit } ;
- DROP ;
+ SWAP ;
+ CAR ;
+ PAIR } ;
+ DIP { DROP } ;
DUP ;
- DIP { DIP 5 { DUP } ; DIG 5 } ;
+ CAR ;
+ CDR ;
+ CDR ;
+ DIP { DUP ; CDR } ;
PAIR ;
- DIP { DROP 8 } } ;
+ DIP { DROP 13 } } ;
DIP { DROP } }
{ DUP ;
DIP { DIP { DUP } ; SWAP } ;
@@ -744,115 +797,149 @@ let%expect_test _ =
DIP { DUP } ;
SWAP ;
CAR ;
- DUP ;
PACK ;
DUP ;
+ DIP { DIP { DUP } ; SWAP } ;
+ PAIR ;
+ DIP { DUP } ;
+ SWAP ;
DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CDR ; CDR } ;
GET ;
IF_NONE
- { PUSH unit Unit }
+ { DUP }
{ DUP ;
PUSH bool False ;
SENDER ;
UPDATE ;
- DIP { DUP } ;
- SWAP ;
+ DIP 4 { DUP } ;
+ DIG 4 ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
SIZE ;
- DIP { DUP ; SIZE } ;
+ DIP { DIP { DUP } ; SWAP ; SIZE } ;
COMPARE ;
NEQ ;
- IF { DIP 4 { DUP } ;
- DIG 4 ;
+ IF { DIP 5 { DUP } ;
+ DIG 5 ;
+ DIP 6 { DUP } ;
+ DIG 6 ;
CDR ;
CAR ;
CAR ;
SENDER ;
GET ;
- IF_NONE { PUSH string "GET_FORCE" ; FAILWITH } {} ;
+ IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
PUSH nat 1 ;
SWAP ;
SUB ;
ABS ;
SOME ;
- DIP { DIP 4 { DUP } ; DIG 4 ; CDR ; CAR ; CAR } ;
+ DIP { DIP 6 { DUP } ; DIG 6 ; CDR ; CAR ; CAR } ;
SENDER ;
UPDATE ;
- DIP { DIP 4 { DUP } ;
- DIG 4 ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- CDR } ;
+ DIP { DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; CDR } ;
PAIR ;
PAIR ;
SWAP ;
PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- PUSH unit Unit }
- { PUSH unit Unit } ;
- DROP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DUP } ;
+ SWAP ;
+ DIP { DROP 2 } }
+ { DUP } ;
+ DIP { DROP } ;
DUP ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ DIP { DIP 5 { DUP } ; DIG 5 } ;
+ PAIR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP 3 { DUP } ;
+ DIG 3 ;
SIZE ;
PUSH nat 0 ;
SWAP ;
COMPARE ;
EQ ;
- IF { DIP 2 { DUP } ;
- DIG 2 ;
- DIP { DIP 4 { DUP } ; DIG 4 ; CAR ; CDR ; CDR ; NONE (set address) } ;
+ IF { DIP { DUP } ;
+ SWAP ;
+ DIP 7 { DUP } ;
+ DIG 7 ;
+ DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CDR ; CDR ; NONE (set address) } ;
UPDATE ;
- DIP { DIP 4 { DUP } ;
- DIG 4 ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CAR } ;
SWAP ;
PAIR ;
SWAP ;
PAIR ;
PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- PUSH unit Unit }
- { DIP 2 { DUP } ;
+ DIP { DUP } ;
+ SWAP ;
+ CAR ;
+ DIP { DUP } ;
+ PAIR ;
+ DIP { DROP } }
+ { DUP ;
+ DIP 2 { DUP } ;
DIG 2 ;
- DIP { DUP ; SOME ; DIP { DIP 4 { DUP } ; DIG 4 ; CAR ; CDR ; CDR } } ;
+ DIP 8 { DUP } ;
+ DIG 8 ;
+ DIP { DIP 5 { DUP } ;
+ DIG 5 ;
+ SOME ;
+ DIP { DIP 3 { DUP } ; DIG 3 ; CAR ; CDR ; CDR } } ;
UPDATE ;
- DIP { DIP 4 { DUP } ;
- DIG 4 ;
- DUP ;
- CDR ;
- SWAP ;
- CAR ;
- DUP ;
- CAR ;
- SWAP ;
- CDR ;
- CAR } ;
+ DIP { DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CAR } ;
SWAP ;
PAIR ;
SWAP ;
PAIR ;
PAIR ;
- DIP 5 { DROP } ;
- DUG 4 ;
- PUSH unit Unit } ;
- DIP { DROP 2 } } ;
- DROP ;
- DIP 2 { DUP } ;
- DIG 2 ;
+ SWAP ;
+ CAR ;
+ PAIR } ;
+ DIP { DROP } ;
+ DIP 5 { DUP } ;
+ DIG 5 ;
+ DIP 2 { DUP } ;
+ DIG 2 ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DIP { DUP } ;
+ SWAP ;
+ CAR ;
+ CDR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ DIP { DUP } ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DIP { DUP } ;
+ SWAP ;
+ CAR ;
+ CDR ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ PAIR ;
+ DIP { DUP } ;
+ SWAP ;
+ CDR ;
+ SWAP ;
+ CAR ;
+ PAIR ;
+ DIP { DROP 5 } } ;
+ DIP { DROP } ;
+ DUP ;
+ CDR ;
NIL operation ;
PAIR ;
DIP { DROP 5 } } ;
@@ -978,7 +1065,7 @@ let%expect_test _ =
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 literal: address "KT1badaddr" {"location":"in file \"bad_address_format.religo\", line 2, characters 25-47"}
+ ligo: in file "bad_address_format.religo", line 2, characters 25-47. Badly formatted literal: @"KT1badaddr" {"location":"in file \"bad_address_format.religo\", line 2, characters 25-47"}
If you're not sure how to fix this error, you can
@@ -992,7 +1079,7 @@ let%expect_test _ =
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; contract "bad_timestamp.ligo" ; "main" ] ;
[%expect {|
- ligo: in file "bad_timestamp.ligo", line 5, characters 29-43. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 5, characters 29-43"}
+ ligo: in file "bad_timestamp.ligo", line 7, characters 30-44. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 7, characters 30-44"}
If you're not sure how to fix this error, you can
@@ -1005,11 +1092,11 @@ let%expect_test _ =
let%expect_test _ =
run_ligo_good [ "dry-run" ; contract "redeclaration.ligo" ; "main" ; "unit" ; "0" ] ;
- [%expect {|( [] , 0 ) |}]
+ [%expect {|( list[] , 0 ) |}]
let%expect_test _ =
run_ligo_good [ "dry-run" ; contract "double_main.ligo" ; "main" ; "unit" ; "0" ] ;
- [%expect {|( [] , 2 ) |}]
+ [%expect {|( list[] , 2 ) |}]
let%expect_test _ =
run_ligo_good [ "compile-contract" ; contract "subtle_nontail_fail.mligo" ; "main" ] ;
@@ -1037,4 +1124,16 @@ let%expect_test _ =
* Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
* Ask a question on our Discord: https://discord.gg/9rhYaEt
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
- * Check the changelog by running 'ligo changelog' |}]
\ No newline at end of file
+ * Check the changelog by running 'ligo changelog' |}]
+
+let%expect_test _ =
+ run_ligo_good [ "compile-storage" ; contract "big_map.ligo" ; "main" ; "(big_map1,unit)" ] ;
+ [%expect {|
+ (Pair { Elt 23 0 ; Elt 42 0 } Unit) |}]
+
+let%expect_test _ =
+ run_ligo_good [ "compile-contract" ; contract "key_hash_comparable.ligo" ; "main" ] ;
+ [%expect {|
+ { parameter int ;
+ storage (pair (map %one key_hash nat) (big_map %two key_hash bool)) ;
+ code { DUP ; CDR ; NIL operation ; PAIR ; DIP { DROP } } } |}]
\ No newline at end of file
diff --git a/src/bin/expect_tests/error_messages_tests.ml b/src/bin/expect_tests/error_messages_tests.ml
new file mode 100644
index 000000000..284b21e89
--- /dev/null
+++ b/src/bin/expect_tests/error_messages_tests.ml
@@ -0,0 +1,38 @@
+open Cli_expect
+
+let%expect_test _ =
+ run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/gitlab_111.religo" ; "main" ] ;
+ [%expect {|
+ ligo: : Parse error in file "gitlab_111.religo", line 2, characters 0-3, after "=" and before "let":
+ This is an incorrect let binding.
+ -
+ Examples of correct let bindings:
+ let a: int = 4;
+ let (a: int, b: int) = (1, 2);
+ let func = (a: int, b: int) => a + b;
+ {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |} ] ;
+
+ run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/missing_rpar.religo" ; "main" ] ;
+ [%expect {|
+ ligo: : Parse error in file "missing_rpar.religo", line 5, characters 0-3, after "m" and before "let":
+ Missing `)`.
+ {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |} ] ;
+
diff --git a/src/bin/expect_tests/eval_value_tests.ml b/src/bin/expect_tests/eval_value_tests.ml
deleted file mode 100644
index ef4ccd1bd..000000000
--- a/src/bin/expect_tests/eval_value_tests.ml
+++ /dev/null
@@ -1,10 +0,0 @@
-open Cli_expect
-
-let%expect_test _ =
- run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "a" ] ;
- [%expect {|
- {foo = +0 , bar = "bar"} |} ];
-
- run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "b" ] ;
- [%expect {|
- 2 |} ]
\ No newline at end of file
diff --git a/src/bin/expect_tests/failwith_tests.ml b/src/bin/expect_tests/failwith_tests.ml
new file mode 100644
index 000000000..a66d462ee
--- /dev/null
+++ b/src/bin/expect_tests/failwith_tests.ml
@@ -0,0 +1,36 @@
+open Cli_expect
+
+let contract basename =
+ "../../test/contracts/" ^ basename
+let bad_contract basename =
+ "../../test/contracts/negative/" ^ basename
+
+let%expect_test _ =
+ run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ;
+ [%expect {|
+ failwith("some_string") |}];
+
+ run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ; "--format=json" ] ;
+ [%expect {|
+ {"status":"ok","content":"failwith(\"some_string\")"} |}];
+
+
+ run_ligo_good [ "dry-run" ; contract "subtle_nontail_fail.mligo" ; "main" ; "()" ; "()" ] ;
+ [%expect {|
+ failwith("This contract always fails") |}];
+
+ run_ligo_good [ "interpret" ; "assert(1=1)" ; "--syntax=pascaligo" ] ;
+ [%expect {|
+ unit |}];
+
+ run_ligo_good [ "interpret" ; "assert(1=2)" ; "--syntax=pascaligo" ] ;
+ [%expect {|
+ failwith("failed assertion") |}];
+
+ run_ligo_good [ "interpret" ; "assert(1=1)" ; "--syntax=cameligo" ] ;
+ [%expect {|
+ unit |}];
+
+ run_ligo_good [ "interpret" ; "assert(1=2)" ; "--syntax=cameligo" ] ;
+ [%expect {|
+ failwith("failed assertion") |}];
diff --git a/src/bin/expect_tests/help_tests.ml b/src/bin/expect_tests/help_tests.ml
index b385abd14..bd5824881 100644
--- a/src/bin/expect_tests/help_tests.ml
+++ b/src/bin/expect_tests/help_tests.ml
@@ -18,53 +18,59 @@ let%expect_test _ =
Dump the LIGO changelog to stdout.
compile-contract
- Subcommand: compile a contract.
+ Subcommand: Compile a contract.
compile-expression
- Subcommand: compile to a michelson value.
+ Subcommand: Compile to a michelson value.
compile-parameter
- Subcommand: compile parameters to a michelson expression. The
- resulting michelson expression can be passed as an argument in a
+ Subcommand: Compile parameters to a Michelson expression. The
+ resulting Michelson expression can be passed as an argument in a
transaction which calls a contract.
compile-storage
- Subcommand: compile an initial storage in ligo syntax to a
- michelson expression. The resulting michelson expression can be
+ Subcommand: Compile an initial storage in ligo syntax to a
+ Michelson expression. The resulting Michelson expression can be
passed as an argument in a transaction which originates a
contract.
dry-run
- Subcommand: run a smart-contract with the given storage and input.
+ Subcommand: Run a smart-contract with the given storage and input.
evaluate-value
- Subcommand: evaluate a given definition.
+ Subcommand: Evaluate a given definition.
interpret
- Subcommand: interpret the expression in the context initialized by
+ Subcommand: Interpret the expression in the context initialized by
the provided source file.
+ ligo-interpret
+ Subcommand: (temporary / dev only) uses LIGO interpret.
+
+ list-declarations
+ Subcommand: List all the top-level declarations.
+
measure-contract
- Subcommand: measure a contract's compiled size in bytes.
+ Subcommand: Measure a contract's compiled size in bytes.
print-ast
- Subcommand: print the ast. Warning: intended for development of
+ Subcommand: Print the AST. Warning: Intended for development of
LIGO and can break at any time.
print-cst
- Subcommand: print the cst. Warning: intended for development of
+ Subcommand: Print the CST. Warning: Intended for development of
LIGO and can break at any time.
print-mini-c
- Subcommand: print mini c. Warning: intended for development of
+ Subcommand: Print Mini-C. Warning: Intended for development of
LIGO and can break at any time.
print-typed-ast
- Subcommand: print the typed ast. Warning: intended for development
+ Subcommand: Print the typed AST. Warning: Intended for development
of LIGO and can break at any time.
run-function
- Subcommand: run a function with the given parameter.
+ Subcommand: Run a function with the given parameter.
OPTIONS
--help[=FMT] (default=auto)
@@ -91,53 +97,59 @@ let%expect_test _ =
Dump the LIGO changelog to stdout.
compile-contract
- Subcommand: compile a contract.
+ Subcommand: Compile a contract.
compile-expression
- Subcommand: compile to a michelson value.
+ Subcommand: Compile to a michelson value.
compile-parameter
- Subcommand: compile parameters to a michelson expression. The
- resulting michelson expression can be passed as an argument in a
+ Subcommand: Compile parameters to a Michelson expression. The
+ resulting Michelson expression can be passed as an argument in a
transaction which calls a contract.
compile-storage
- Subcommand: compile an initial storage in ligo syntax to a
- michelson expression. The resulting michelson expression can be
+ Subcommand: Compile an initial storage in ligo syntax to a
+ Michelson expression. The resulting Michelson expression can be
passed as an argument in a transaction which originates a
contract.
dry-run
- Subcommand: run a smart-contract with the given storage and input.
+ Subcommand: Run a smart-contract with the given storage and input.
evaluate-value
- Subcommand: evaluate a given definition.
+ Subcommand: Evaluate a given definition.
interpret
- Subcommand: interpret the expression in the context initialized by
+ Subcommand: Interpret the expression in the context initialized by
the provided source file.
+ ligo-interpret
+ Subcommand: (temporary / dev only) uses LIGO interpret.
+
+ list-declarations
+ Subcommand: List all the top-level declarations.
+
measure-contract
- Subcommand: measure a contract's compiled size in bytes.
+ Subcommand: Measure a contract's compiled size in bytes.
print-ast
- Subcommand: print the ast. Warning: intended for development of
+ Subcommand: Print the AST. Warning: Intended for development of
LIGO and can break at any time.
print-cst
- Subcommand: print the cst. Warning: intended for development of
+ Subcommand: Print the CST. Warning: Intended for development of
LIGO and can break at any time.
print-mini-c
- Subcommand: print mini c. Warning: intended for development of
+ Subcommand: Print Mini-C. Warning: Intended for development of
LIGO and can break at any time.
print-typed-ast
- Subcommand: print the typed ast. Warning: intended for development
+ Subcommand: Print the typed AST. Warning: Intended for development
of LIGO and can break at any time.
run-function
- Subcommand: run a function with the given parameter.
+ Subcommand: Run a function with the given parameter.
OPTIONS
--help[=FMT] (default=auto)
@@ -151,7 +163,7 @@ let%expect_test _ =
run_ligo_good [ "compile-contract" ; "--help" ] ;
[%expect {|
NAME
- ligo-compile-contract - Subcommand: compile a contract.
+ ligo-compile-contract - Subcommand: Compile a contract.
SYNOPSIS
ligo compile-contract [OPTION]... SOURCE_FILE ENTRY_POINT
@@ -161,8 +173,7 @@ let%expect_test _ =
ENTRY_POINT is entry-point that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
OPTIONS
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
@@ -185,8 +196,9 @@ let%expect_test _ =
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--version
Show version information. |} ] ;
@@ -194,8 +206,8 @@ let%expect_test _ =
run_ligo_good [ "compile-parameter" ; "--help" ] ;
[%expect {|
NAME
- ligo-compile-parameter - Subcommand: compile parameters to a michelson
- expression. The resulting michelson expression can be passed as an
+ ligo-compile-parameter - Subcommand: Compile parameters to a Michelson
+ expression. The resulting Michelson expression can be passed as an
argument in a transaction which calls a contract.
SYNOPSIS
@@ -210,12 +222,11 @@ let%expect_test _ =
PARAMETER_EXPRESSION is the expression that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
OPTIONS
--amount=AMOUNT (absent=0)
- AMOUNT is the amount the michelson interpreter will use.
+ AMOUNT is the amount the Michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
@@ -236,21 +247,22 @@ let%expect_test _ =
are 'text' (default), 'json' and 'hex'.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
- PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value minus
- one minute) the michelson interpreter will use (e.g.
+ PREDECESSOR_TIMESTAMP is the predecessor_timestamp (now value
+ minus one minute) the Michelson interpreter will use (e.g.
'2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--sender=SENDER
- SENDER is the sender the michelson interpreter transaction will
+ SENDER is the sender the Michelson interpreter transaction will
use.
--source=SOURCE
- SOURCE is the source the michelson interpreter transaction will
+ SOURCE is the source the Michelson interpreter transaction will
use.
--version
@@ -259,8 +271,8 @@ let%expect_test _ =
run_ligo_good [ "compile-storage" ; "--help" ] ;
[%expect {|
NAME
- ligo-compile-storage - Subcommand: compile an initial storage in ligo
- syntax to a michelson expression. The resulting michelson expression
+ ligo-compile-storage - Subcommand: Compile an initial storage in ligo
+ syntax to a Michelson expression. The resulting Michelson expression
can be passed as an argument in a transaction which originates a
contract.
@@ -273,15 +285,14 @@ let%expect_test _ =
ENTRY_POINT is entry-point that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
STORAGE_EXPRESSION (required)
STORAGE_EXPRESSION is the expression that will be compiled.
OPTIONS
--amount=AMOUNT (absent=0)
- AMOUNT is the amount the michelson interpreter will use.
+ AMOUNT is the amount the Michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
@@ -302,21 +313,22 @@ let%expect_test _ =
are 'text' (default), 'json' and 'hex'.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
- PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value minus
- one minute) the michelson interpreter will use (e.g.
+ PREDECESSOR_TIMESTAMP is the predecessor_timestamp (now value
+ minus one minute) the Michelson interpreter will use (e.g.
'2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--sender=SENDER
- SENDER is the sender the michelson interpreter transaction will
+ SENDER is the sender the Michelson interpreter transaction will
use.
--source=SOURCE
- SOURCE is the source the michelson interpreter transaction will
+ SOURCE is the source the Michelson interpreter transaction will
use.
--version
@@ -325,7 +337,7 @@ let%expect_test _ =
run_ligo_good [ "dry-run" ; "--help" ] ;
[%expect {|
NAME
- ligo-dry-run - Subcommand: run a smart-contract with the given storage
+ ligo-dry-run - Subcommand: Run a smart-contract with the given storage
and input.
SYNOPSIS
@@ -340,15 +352,14 @@ let%expect_test _ =
PARAMETER_EXPRESSION is the expression that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
STORAGE_EXPRESSION (required)
STORAGE_EXPRESSION is the expression that will be compiled.
OPTIONS
--amount=AMOUNT (absent=0)
- AMOUNT is the amount the michelson interpreter will use.
+ AMOUNT is the amount the Michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
@@ -364,21 +375,22 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
- PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value minus
- one minute) the michelson interpreter will use (e.g.
+ PREDECESSOR_TIMESTAMP is the predecessor_timestamp (now value
+ minus one minute) the Michelson interpreter will use (e.g.
'2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--sender=SENDER
- SENDER is the sender the michelson interpreter transaction will
+ SENDER is the sender the Michelson interpreter transaction will
use.
--source=SOURCE
- SOURCE is the source the michelson interpreter transaction will
+ SOURCE is the source the Michelson interpreter transaction will
use.
--version
@@ -387,7 +399,7 @@ let%expect_test _ =
run_ligo_good [ "run-function" ; "--help" ] ;
[%expect {|
NAME
- ligo-run-function - Subcommand: run a function with the given
+ ligo-run-function - Subcommand: Run a function with the given
parameter.
SYNOPSIS
@@ -402,12 +414,11 @@ let%expect_test _ =
PARAMETER_EXPRESSION is the expression that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
OPTIONS
--amount=AMOUNT (absent=0)
- AMOUNT is the amount the michelson interpreter will use.
+ AMOUNT is the amount the Michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
@@ -423,21 +434,22 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
- PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value minus
- one minute) the michelson interpreter will use (e.g.
+ PREDECESSOR_TIMESTAMP is the predecessor_timestamp (now value
+ minus one minute) the Michelson interpreter will use (e.g.
'2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--sender=SENDER
- SENDER is the sender the michelson interpreter transaction will
+ SENDER is the sender the Michelson interpreter transaction will
use.
--source=SOURCE
- SOURCE is the source the michelson interpreter transaction will
+ SOURCE is the source the Michelson interpreter transaction will
use.
--version
@@ -446,7 +458,7 @@ let%expect_test _ =
run_ligo_good [ "evaluate-value" ; "--help" ] ;
[%expect {|
NAME
- ligo-evaluate-value - Subcommand: evaluate a given definition.
+ ligo-evaluate-value - Subcommand: Evaluate a given definition.
SYNOPSIS
ligo evaluate-value [OPTION]... SOURCE_FILE ENTRY_POINT
@@ -456,12 +468,11 @@ let%expect_test _ =
ENTRY_POINT is entry-point that will be compiled.
SOURCE_FILE (required)
- SOURCE_FILE is the path to the .ligo or .mligo file of the
- contract.
+ SOURCE_FILE is the path to the smart contract file.
OPTIONS
--amount=AMOUNT (absent=0)
- AMOUNT is the amount the michelson interpreter will use.
+ AMOUNT is the amount the Michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
@@ -477,21 +488,22 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
- PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value minus
- one minute) the michelson interpreter will use (e.g.
+ PREDECESSOR_TIMESTAMP is the predecessor_timestamp (now value
+ minus one minute) the Michelson interpreter will use (e.g.
'2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
--sender=SENDER
- SENDER is the sender the michelson interpreter transaction will
+ SENDER is the sender the Michelson interpreter transaction will
use.
--source=SOURCE
- SOURCE is the source the michelson interpreter transaction will
+ SOURCE is the source the Michelson interpreter transaction will
use.
--version
@@ -500,7 +512,7 @@ let%expect_test _ =
run_ligo_good [ "compile-expression" ; "--help" ] ;
[%expect {|
NAME
- ligo-compile-expression - Subcommand: compile to a michelson value.
+ ligo-compile-expression - Subcommand: Compile to a michelson value.
SYNOPSIS
ligo compile-expression [OPTION]... SYNTAX _EXPRESSION
@@ -511,8 +523,9 @@ let%expect_test _ =
SYNTAX (required)
SYNTAX is the syntax that will be used. Currently supported
- syntaxes are "pascaligo" and "cameligo". By default, the syntax is
- guessed from the extension (.ligo and .mligo, respectively).
+ syntaxes are "pascaligo", "cameligo" and "reasonligo". By default,
+ the syntax is guessed from the extension (.ligo, .mligo, .religo
+ respectively).
OPTIONS
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
diff --git a/src/bin/expect_tests/lexer_tests.ml b/src/bin/expect_tests/lexer_tests.ml
index 99c75f077..f55d9a8cb 100644
--- a/src/bin/expect_tests/lexer_tests.ml
+++ b/src/bin/expect_tests/lexer_tests.ml
@@ -3,9 +3,10 @@ open Cli_expect
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/lexer/broken_string.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: The string starting here is interrupted by a line break.
+ligo: : Lexical error in file "broken_string.ligo", line 1, characters 18-19:
+ The string starting here is interrupted by a line break.
Hint: Remove the break, close the string before or insert a backslash.
- {"parser_loc":"in file \"broken_string.ligo\", line 1, characters 18-19"}
+ {}
If you're not sure how to fix this error, you can
@@ -19,9 +20,10 @@ ligo: lexer error: The string starting here is interrupted by a line break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/broken_string.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: The string starting here is interrupted by a line break.
+ligo: : Lexical error in file "broken_string.mligo", line 1, characters 8-9:
+ The string starting here is interrupted by a line break.
Hint: Remove the break, close the string before or insert a backslash.
- {"parser_loc":"in file \"broken_string.mligo\", line 1, characters 8-9"}
+ {}
If you're not sure how to fix this error, you can
@@ -35,9 +37,10 @@ ligo: lexer error: The string starting here is interrupted by a line break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/broken_string.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: The string starting here is interrupted by a line break.
+ligo: : Lexical error in file "broken_string.religo", line 1, characters 8-9:
+ The string starting here is interrupted by a line break.
Hint: Remove the break, close the string before or insert a backslash.
- {"parser_loc":"in file \"broken_string.religo\", line 1, characters 8-9"}
+ {}
If you're not sure how to fix this error, you can
@@ -51,9 +54,10 @@ ligo: lexer error: The string starting here is interrupted by a line break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/negative_byte_sequence.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Negative byte sequence.
+ligo: : Lexical error in file "negative_byte_sequence.ligo", line 1, characters 18-23:
+ Negative byte sequence.
Hint: Remove the leading minus sign.
- {"parser_loc":"in file \"negative_byte_sequence.ligo\", line 1, characters 18-23"}
+ {}
If you're not sure how to fix this error, you can
@@ -67,9 +71,10 @@ ligo: lexer error: Negative byte sequence.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/negative_byte_sequence.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Negative byte sequence.
+ligo: : Lexical error in file "negative_byte_sequence.mligo", line 1, characters 8-13:
+ Negative byte sequence.
Hint: Remove the leading minus sign.
- {"parser_loc":"in file \"negative_byte_sequence.mligo\", line 1, characters 8-13"}
+ {}
If you're not sure how to fix this error, you can
@@ -83,9 +88,10 @@ ligo: lexer error: Negative byte sequence.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/negative_byte_sequence.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Negative byte sequence.
+ligo: : Lexical error in file "negative_byte_sequence.religo", line 1, characters 8-13:
+ Negative byte sequence.
Hint: Remove the leading minus sign.
- {"parser_loc":"in file \"negative_byte_sequence.religo\", line 1, characters 8-13"}
+ {}
If you're not sure how to fix this error, you can
@@ -99,9 +105,10 @@ ligo: lexer error: Negative byte sequence.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/reserved_name.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Reserved name: arguments.
+ligo: : Lexical error in file "reserved_name.ligo", line 1, characters 4-13:
+ Reserved name: "arguments".
Hint: Change the name.
- {"parser_loc":"in file \"reserved_name.ligo\", line 1, characters 4-13"}
+ {}
If you're not sure how to fix this error, you can
@@ -115,9 +122,10 @@ ligo: lexer error: Reserved name: arguments.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/reserved_name.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Reserved name: end.
+ligo: : Lexical error in file "reserved_name.religo", line 1, characters 4-7:
+ Reserved name: "end".
Hint: Change the name.
- {"parser_loc":"in file \"reserved_name.religo\", line 1, characters 4-7"}
+ {}
If you're not sure how to fix this error, you can
@@ -131,9 +139,10 @@ ligo: lexer error: Reserved name: end.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/reserved_name.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Reserved name: object.
+ligo: : Lexical error in file "reserved_name.mligo", line 1, characters 4-10:
+ Reserved name: "object".
Hint: Change the name.
- {"parser_loc":"in file \"reserved_name.mligo\", line 1, characters 4-10"}
+ {}
If you're not sure how to fix this error, you can
@@ -147,8 +156,9 @@ ligo: lexer error: Reserved name: object.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/unexpected_character.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Unexpected character '\239'.
- {"parser_loc":"in file \"unexpected_character.ligo\", line 1, characters 18-19"}
+ligo: : Lexical error in file "unexpected_character.ligo", line 1, characters 18-19:
+ Unexpected character '\239'.
+ {}
If you're not sure how to fix this error, you can
@@ -162,8 +172,9 @@ ligo: lexer error: Unexpected character '\239'.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/unexpected_character.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Unexpected character '\239'.
- {"parser_loc":"in file \"unexpected_character.mligo\", line 1, characters 8-9"}
+ligo: : Lexical error in file "unexpected_character.mligo", line 1, characters 8-9:
+ Unexpected character '\239'.
+ {}
If you're not sure how to fix this error, you can
@@ -177,8 +188,9 @@ ligo: lexer error: Unexpected character '\239'.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/unexpected_character.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Unexpected character '\239'.
- {"parser_loc":"in file \"unexpected_character.religo\", line 1, characters 8-9"}
+ligo: : Lexical error in file "unexpected_character.religo", line 1, characters 8-9:
+ Unexpected character '\239'.
+ {}
If you're not sure how to fix this error, you can
@@ -192,9 +204,10 @@ ligo: lexer error: Unexpected character '\239'.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/unterminated_comment.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Unterminated comment.
+ligo: : Lexical error in file "unterminated_comment.mligo", line 1, characters 0-2:
+ Unterminated comment.
Hint: Close with "*)".
- {"parser_loc":"in file \"unterminated_comment.mligo\", line 1, characters 0-2"}
+ {}
If you're not sure how to fix this error, you can
@@ -208,9 +221,10 @@ ligo: lexer error: Unterminated comment.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_symbol.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid symbol.
+ligo: : Lexical error in file "invalid_symbol.ligo", line 1, characters 17-20:
+ Invalid symbol.
Hint: Check the LIGO syntax you use.
- {"parser_loc":"in file \"invalid_symbol.ligo\", line 1, characters 17-20"}
+ {}
If you're not sure how to fix this error, you can
@@ -224,9 +238,10 @@ ligo: lexer error: Invalid symbol.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_symbol.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid symbol.
+ligo: : Lexical error in file "invalid_symbol.mligo", line 1, characters 10-13:
+ Invalid symbol.
Hint: Check the LIGO syntax you use.
- {"parser_loc":"in file \"invalid_symbol.mligo\", line 1, characters 10-13"}
+ {}
If you're not sure how to fix this error, you can
@@ -240,9 +255,10 @@ ligo: lexer error: Invalid symbol.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_symbol.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid symbol.
+ligo: : Lexical error in file "invalid_symbol.religo", line 1, characters 10-11:
+ Invalid symbol.
Hint: Check the LIGO syntax you use.
- {"parser_loc":"in file \"invalid_symbol.religo\", line 1, characters 10-11"}
+ {}
If you're not sure how to fix this error, you can
@@ -256,9 +272,10 @@ ligo: lexer error: Invalid symbol.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/missing_break.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Missing break.
+ligo: : Lexical error in file "missing_break.ligo", line 1, characters 18-18:
+ Missing break.
Hint: Insert some space.
- {"parser_loc":"in file \"missing_break.ligo\", line 1, characters 18-18"}
+ {}
If you're not sure how to fix this error, you can
@@ -272,9 +289,10 @@ ligo: lexer error: Missing break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/missing_break.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Missing break.
+ligo: : Lexical error in file "missing_break.mligo", line 1, characters 11-11:
+ Missing break.
Hint: Insert some space.
- {"parser_loc":"in file \"missing_break.mligo\", line 1, characters 11-11"}
+ {}
If you're not sure how to fix this error, you can
@@ -288,9 +306,10 @@ ligo: lexer error: Missing break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/missing_break.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Missing break.
+ligo: : Lexical error in file "missing_break.religo", line 1, characters 11-11:
+ Missing break.
Hint: Insert some space.
- {"parser_loc":"in file \"missing_break.religo\", line 1, characters 11-11"}
+ {}
If you're not sure how to fix this error, you can
@@ -304,9 +323,10 @@ ligo: lexer error: Missing break.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_character_in_string.ligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid character in string.
+ligo: : Lexical error in file "invalid_character_in_string.ligo", line 1, characters 19-20:
+ Invalid character in string.
Hint: Remove or replace the character.
- {"parser_loc":"in file \"invalid_character_in_string.ligo\", line 1, characters 19-20"}
+ {}
If you're not sure how to fix this error, you can
@@ -320,9 +340,10 @@ ligo: lexer error: Invalid character in string.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_character_in_string.mligo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid character in string.
+ligo: : Lexical error in file "invalid_character_in_string.mligo", line 1, characters 9-10:
+ Invalid character in string.
Hint: Remove or replace the character.
- {"parser_loc":"in file \"invalid_character_in_string.mligo\", line 1, characters 9-10"}
+ {}
If you're not sure how to fix this error, you can
@@ -336,9 +357,10 @@ ligo: lexer error: Invalid character in string.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/invalid_character_in_string.religo" ; "main" ] ;
[%expect {|
-ligo: lexer error: Invalid character in string.
+ligo: : Lexical error in file "invalid_character_in_string.religo", line 1, characters 9-10:
+ Invalid character in string.
Hint: Remove or replace the character.
- {"parser_loc":"in file \"invalid_character_in_string.religo\", line 1, characters 9-10"}
+ {}
If you're not sure how to fix this error, you can
diff --git a/src/bin/expect_tests/ligo_interpreter_tests.ml b/src/bin/expect_tests/ligo_interpreter_tests.ml
new file mode 100644
index 000000000..ac381ea71
--- /dev/null
+++ b/src/bin/expect_tests/ligo_interpreter_tests.ml
@@ -0,0 +1,56 @@
+open Cli_expect
+
+let contract basename =
+ "../../test/contracts/" ^ basename
+
+let%expect_test _ =
+ run_ligo_good [ "ligo-interpret" ; contract "interpret_test.mligo" ] ;
+ [%expect {|
+ val lambda_call = 16 : int
+ val higher_order1 = 5 : int
+ val higher_order2 = 5 : int
+ val higher_order3 = 5 : int
+ val higher_order4 = 5 : int
+ val concats = 0x7070 : bytes
+ val record_concat = "ab" : string
+ val record_patch = { ; a = ("a" : string) ; b = ("c" : string) }
+ val record_lambda = 5 : int
+ val variant_exp = { ; 0 = (Foo(unit)) ; 1 = (Bar(1 : int)) ; 2 = (Baz("b" : string)) }
+ val variant_match = 2 : int
+ val bool_match = 1 : int
+ val list_match = [ ; 1 : int ; 1 : int ; 2 : int ; 3 : int ; 4 : int]
+ val tuple_proj = true
+ val list_const = [ ; 0 : int ; 1 : int ; 2 : int ; 3 : int ; 4 : int]
+ val options_match_some = 0 : int
+ val options_match_none = 0 : int
+ val is_nat_nat = { ; 0 = (Some(1 : nat)) ; 1 = (None(unit)) }
+ val abs_int = 5 : int
+ val nat_int = 5 : int
+ val map_list = [ ; 2 : int ; 3 : int ; 4 : int ; 5 : int]
+ val fail_alone = "you failed" : failure
+ val iter_list_fail = "you failed" : failure
+ val fold_list = 10 : int
+ val comparison_int = { ; 0 = (false) ; 1 = (true) ; 2 = (false) ; 3 = (true) }
+ val comparison_string = { ; 0 = (false) ; 1 = (true) }
+ val divs = { ; 0 = (0 : int) ; 1 = (0 : nat) ; 2 = (500000 : mutez) ; 3 = (0 : nat) }
+ val var_neg = -2 : int
+ val sizes = { ; 0 = (5 : nat) ; 1 = (5 : nat) ; 2 = (5 : nat) ; 3 = (3 : nat) ; 4 = (2 : nat) }
+ val modi = 1 : nat
+ val fold_while = { ; 0 = (20 : int) ; 1 = (10 : int) }
+ val assertion_pass = unit
+ val assertion_fail = "failed assertion" : failure
+ val lit_address = "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" : address
+ val map_finds = Some(2 : int)
+ val map_finds_fail = "failed map find" : failure
+ val map_empty = { ; 0 = ([]) ; 1 = ([]) }
+ val m = [ ; "one" : string -> 1 : int ; "two" : string -> 2 : int ; "three" : string -> 3 : int]
+ val map_fold = 4 : int
+ val map_iter = unit
+ val map_map = [ ; "one" : string -> 4 : int ; "two" : string -> 5 : int ; "three" : string -> 8 : int]
+ val map_mem = { ; 0 = (true) ; 1 = (false) }
+ val map_remove = { ; 0 = ([ ; "two" : string -> 2 : int ; "three" : string -> 3 : int]) ; 1 = ([ ; "one" : string -> 1 : int ; "two" : string -> 2 : int ; "three" : string -> 3 : int]) }
+ val map_update = { ; 0 = ([ ; "one" : string -> 1 : int]) ; 1 = ([]) ; 2 = ([]) ; 3 = ([ ; "one" : string -> 1 : int]) }
+ val s = { ; 1 : int ; 2 : int ; 3 : int}
+ val set_add = { ; 0 = ({ ; 1 : int ; 2 : int ; 3 : int}) ; 1 = ({ ; 1 : int ; 2 : int ; 3 : int ; 4 : int}) ; 2 = ({ ; 1 : int}) }
+ val set_iter_fail = "set_iter_fail" : failure
+ val set_mem = { ; 0 = (true) ; 1 = (false) ; 2 = (false) } |}] ;
\ No newline at end of file
diff --git a/src/bin/expect_tests/literals.ml b/src/bin/expect_tests/literals.ml
index 9d945c4d0..da8a4333d 100644
--- a/src/bin/expect_tests/literals.ml
+++ b/src/bin/expect_tests/literals.ml
@@ -2,12 +2,12 @@ open Cli_expect
let%expect_test _ =
run_ligo_good ["interpret" ; "(\"edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7\":signature)" ; "--syntax=pascaligo"] ;
- [%expect {| signature edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7 |}]
+ [%expect {| Signature edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7 |}]
let%expect_test _ =
run_ligo_bad ["interpret" ; "(\"thisisnotasignature\":signature)" ; "--syntax=pascaligo"] ;
[%expect {|
- ligo: in file "", line 0, characters 1-32. Badly formatted literal: signature thisisnotasignature {"location":"in file \"\", line 0, characters 1-32"}
+ ligo: in file "", line 0, characters 1-32. Badly formatted literal: Signature thisisnotasignature {"location":"in file \"\", line 0, characters 1-32"}
If you're not sure how to fix this error, you can
diff --git a/src/bin/expect_tests/misc_cli_commands.ml b/src/bin/expect_tests/misc_cli_commands.ml
new file mode 100644
index 000000000..a5a5873c0
--- /dev/null
+++ b/src/bin/expect_tests/misc_cli_commands.ml
@@ -0,0 +1,22 @@
+open Cli_expect
+
+(* evaluate-value *)
+let%expect_test _ =
+ run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "a" ] ;
+ [%expect {|
+ record[bar -> "bar" , foo -> +0] |} ];
+
+ run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "b" ] ;
+ [%expect {|
+ 2 |} ]
+
+(* list-declarations *)
+let%expect_test _ =
+ run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.ligo" ] ;
+ [%expect {| {"source_file":"../../test/contracts/loop.ligo","declarations":["inner_capture_in_conditional_block","dummy","nested_for_collection_local_var","nested_for_collection","for_collection_map_k","for_collection_map_kv","for_collection_empty","for_collection_with_patches","for_collection_comp_with_acc","for_collection_proc_call","for_collection_rhs_capture","for_collection_if_and_local_var","for_collection_set","for_collection_list","for_sum","while_sum","counter"]} |} ];
+
+ run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.mligo" ] ;
+ [%expect {| {"source_file":"../../test/contracts/loop.mligo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ];
+
+ run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.religo" ] ;
+ [%expect {| {"source_file":"../../test/contracts/loop.religo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ];
diff --git a/src/bin/expect_tests/syntax_error_tests.ml b/src/bin/expect_tests/syntax_error_tests.ml
index 7082dbcf9..8969c68a7 100644
--- a/src/bin/expect_tests/syntax_error_tests.ml
+++ b/src/bin/expect_tests/syntax_error_tests.ml
@@ -3,8 +3,8 @@ open Cli_expect
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/error_syntax.ligo" ; "main" ] ;
[%expect {|
- ligo: parser error: Parse error at "-" from (1, 16) to (1, 17). In file "|../../test/contracts/negative/error_syntax.ligo"
- {"parser_loc":"in file \"\", line 1, characters 16-17"}
+ ligo: : Parse error in file "error_syntax.ligo", line 1, characters 16-17, after "bar" and before "-":
+ 15: {}
If you're not sure how to fix this error, you can
@@ -15,3 +15,22 @@ let%expect_test _ =
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
* Check the changelog by running 'ligo changelog' |} ] ;
+ run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/error_function_arguments.religo" ; "main" ] ;
+ [%expect {|
+ ligo: in file "error_function_arguments.religo", line 1, characters 14-27. : It looks like you are defining a function, however we do not
+ understand the parameters declaration.
+ Examples of valid functions:
+ let x = (a: string, b: int) : int => 3;
+ let tuple = ((a, b): (int, int)) => a + b;
+ let x = (a: string) : string => "Hello, " ++ a;
+ {"location":"in file \"error_function_arguments.religo\", line 1, characters 14-27"}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |} ] ;
+
diff --git a/src/bin/expect_tests/typer_error_tests.ml b/src/bin/expect_tests/typer_error_tests.ml
index 67429e040..041fb2e93 100644
--- a/src/bin/expect_tests/typer_error_tests.ml
+++ b/src/bin/expect_tests/typer_error_tests.ml
@@ -41,7 +41,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/error_typer_3.mligo" ; "main" ] ;
[%expect {|
- ligo: in file "error_typer_3.mligo", line 3, characters 34-53. tuples have different sizes: Expected these two types to be the same, but they're different (both are tuples, but with a different number of arguments) {"a":"tuple[int , string , bool]","b":"tuple[int , string]"}
+ ligo: in file "error_typer_3.mligo", line 3, characters 34-53. tuples have different sizes: Expected these two types to be the same, but they're different (both are tuples, but with a different number of arguments) {"a":"( int * string * bool )","b":"( int * string )"}
If you're not sure how to fix this error, you can
@@ -54,7 +54,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/error_typer_4.mligo" ; "main" ] ;
[%expect {|
- ligo: in file "error_typer_4.mligo", line 4, characters 17-56. different keys in record: {"key_a":"d","key_b":"c"}
+ ligo: in file "error_typer_4.mligo", line 4, characters 17-56. different keys in records: {"key_a":"c","key_b":"b","a":"record[a -> int , c -> bool , d -> string]","b":"record[a -> int , b -> string , c -> bool]"}
If you're not sure how to fix this error, you can
@@ -93,7 +93,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/error_typer_7.mligo" ; "main" ] ;
[%expect {|
- ligo: in file "error_typer_7.mligo", line 4, characters 18-48. records have different sizes: Expected these two types to be the same, but they're different (both are records, but with a different number of arguments) {"a":"record[b -> string , a -> int]","b":"record[c -> bool , b -> string , a -> int]"}
+ ligo: in file "error_typer_7.mligo", line 4, characters 18-48. records have different sizes: Expected these two types to be the same, but they're different (both are records, but with a different number of arguments) {"a":"record[a -> int , b -> string]","b":"record[a -> int , b -> string , c -> bool]"}
If you're not sure how to fix this error, you can
@@ -106,7 +106,7 @@ let%expect_test _ =
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/id.mligo" ; "main" ] ;
[%expect {|
- ligo: in file "id.mligo", line 45, characters 4-51. Expected a different type: Expected the type option but got the type record[profile -> bytes , owner -> address , controller -> address]
+ ligo: in file "id.mligo", line 45, characters 4-51. Expected a different type: Expected the type option but got the type record[controller -> address , owner -> address , profile -> bytes]
If you're not sure how to fix this error, you can
do one of the following:
diff --git a/src/main/compile/dune b/src/main/compile/dune
index 90c858e1d..e59679ba5 100644
--- a/src/main/compile/dune
+++ b/src/main/compile/dune
@@ -6,6 +6,7 @@
tezos-utils
parser
simplify
+ interpreter
ast_simplified
self_ast_simplified
typer_new
diff --git a/src/main/compile/helpers.ml b/src/main/compile/helpers.ml
index b7daab8fe..95038a5b9 100644
--- a/src/main/compile/helpers.ml
+++ b/src/main/compile/helpers.ml
@@ -1,173 +1,171 @@
open Trace
type s_syntax = Syntax_name of string
-type v_syntax = Pascaligo | Cameligo | ReasonLIGO
+type v_syntax = PascaLIGO | CameLIGO | ReasonLIGO
-let syntax_to_variant : s_syntax -> string option -> v_syntax result =
- fun syntax source_filename ->
- let subr s n =
- String.sub s (String.length s - n) n in
- let endswith s suffix =
- let suffixlen = String.length suffix in
- ( String.length s >= suffixlen
- && String.equal (subr s suffixlen) suffix)
- in
- let (Syntax_name syntax) = syntax in
- match (syntax , source_filename) with
- | "auto" , Some sf when endswith sf ".ligo" -> ok Pascaligo
- | "auto" , Some sf when endswith sf ".mligo" -> ok Cameligo
- | "auto" , Some sf when endswith sf ".religo" -> ok ReasonLIGO
- | "auto" , _ -> simple_fail "cannot auto-detect syntax, pleas use -s name_of_syntax"
- | "pascaligo" , _ -> ok Pascaligo
- | "cameligo" , _ -> ok Cameligo
- | "reasonligo", _ -> ok ReasonLIGO
- | _ -> simple_fail "unrecognized parser"
+let syntax_to_variant (Syntax_name syntax) source =
+ match syntax, source with
+ "auto", Some sf ->
+ (match Filename.extension sf with
+ ".ligo" | ".pligo" -> ok PascaLIGO
+ | ".mligo" -> ok CameLIGO
+ | ".religo" -> ok ReasonLIGO
+ | _ -> simple_fail "Cannot auto-detect the syntax.\n\
+ Hint: Use -s \n")
+ | ("pascaligo" | "PascaLIGO"), _ -> ok PascaLIGO
+ | ("cameligo" | "CameLIGO"), _ -> ok CameLIGO
+ | ("reasonligo" | "ReasonLIGO"), _ -> ok ReasonLIGO
+ | _ -> simple_fail "Invalid syntax name.\n\
+ Hint: Use \"pascaligo\", \"cameligo\" \
+ or \"reasonligo\".\n"
-let parsify_pascaligo = fun source ->
+let parsify_pascaligo source =
let%bind raw =
trace (simple_error "parsing") @@
Parser.Pascaligo.parse_file source in
let%bind simplified =
trace (simple_error "simplifying") @@
- Simplify.Pascaligo.simpl_program raw in
- ok simplified
+ Simplify.Pascaligo.simpl_program raw
+ in ok simplified
-let parsify_expression_pascaligo = fun source ->
+let parsify_expression_pascaligo source =
let%bind raw =
trace (simple_error "parsing expression") @@
Parser.Pascaligo.parse_expression source in
let%bind simplified =
trace (simple_error "simplifying expression") @@
- Simplify.Pascaligo.simpl_expression raw in
- ok simplified
+ Simplify.Pascaligo.simpl_expression raw
+ in ok simplified
-let parsify_cameligo = fun source ->
+let parsify_cameligo source =
let%bind raw =
trace (simple_error "parsing") @@
Parser.Cameligo.parse_file source in
let%bind simplified =
trace (simple_error "simplifying") @@
- Simplify.Cameligo.simpl_program raw in
- ok simplified
+ Simplify.Cameligo.simpl_program raw
+ in ok simplified
-let parsify_expression_cameligo = fun source ->
+let parsify_expression_cameligo source =
let%bind raw =
trace (simple_error "parsing expression") @@
Parser.Cameligo.parse_expression source in
let%bind simplified =
trace (simple_error "simplifying expression") @@
- Simplify.Cameligo.simpl_expression raw in
- ok simplified
+ Simplify.Cameligo.simpl_expression raw
+ in ok simplified
-let parsify_reasonligo = fun source ->
+let parsify_reasonligo source =
let%bind raw =
trace (simple_error "parsing") @@
Parser.Reasonligo.parse_file source in
let%bind simplified =
trace (simple_error "simplifying") @@
- Simplify.Cameligo.simpl_program raw in
- ok simplified
+ Simplify.Cameligo.simpl_program raw
+ in ok simplified
-let parsify_expression_reasonligo = fun source ->
+let parsify_expression_reasonligo source =
let%bind raw =
trace (simple_error "parsing expression") @@
Parser.Reasonligo.parse_expression source in
let%bind simplified =
trace (simple_error "simplifying expression") @@
- Simplify.Cameligo.simpl_expression raw in
- ok simplified
+ Simplify.Cameligo.simpl_expression raw
+ in ok simplified
-let parsify = fun (syntax : v_syntax) source_filename ->
- let%bind parsify = match syntax with
- | Pascaligo -> ok parsify_pascaligo
- | Cameligo -> ok parsify_cameligo
- | ReasonLIGO -> ok parsify_reasonligo
- in
- let%bind parsified = parsify source_filename in
- let%bind applied = Self_ast_simplified.all_program parsified in
- ok applied
-
-let parsify_expression = fun syntax source ->
- let%bind parsify = match syntax with
- | Pascaligo -> ok parsify_expression_pascaligo
- | Cameligo -> ok parsify_expression_cameligo
- | ReasonLIGO -> ok parsify_expression_reasonligo
- in
+let parsify syntax source =
+ let%bind parsify =
+ match syntax with
+ PascaLIGO -> ok parsify_pascaligo
+ | CameLIGO -> ok parsify_cameligo
+ | ReasonLIGO -> ok parsify_reasonligo in
let%bind parsified = parsify source in
- let%bind applied = Self_ast_simplified.all_expression parsified in
- ok applied
+ let%bind applied = Self_ast_simplified.all_program parsified
+ in ok applied
-let parsify_string_reasonligo = fun source ->
+let parsify_expression syntax source =
+ let%bind parsify = match syntax with
+ PascaLIGO -> ok parsify_expression_pascaligo
+ | CameLIGO -> ok parsify_expression_cameligo
+ | ReasonLIGO -> ok parsify_expression_reasonligo in
+ let%bind parsified = parsify source in
+ let%bind applied = Self_ast_simplified.all_expression parsified
+ in ok applied
+
+let parsify_string_reasonligo 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
+ Simplify.Cameligo.simpl_program raw
+ in ok simplified
-let parsify_string_pascaligo = fun source ->
+let parsify_string_pascaligo 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
+ Simplify.Pascaligo.simpl_program raw
+ in ok simplified
-let parsify_string_cameligo = fun source ->
+let parsify_string_cameligo 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
+ 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
+let parsify_string syntax source =
+ 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 in
+ let%bind applied = Self_ast_simplified.all_program parsified
+ in ok applied
-let pretty_print_pascaligo = fun source ->
+let pretty_print_pascaligo source =
let%bind ast = Parser.Pascaligo.parse_file source in
let buffer = Buffer.create 59 in
- let state = Parser_pascaligo.ParserLog.mk_state
- ~offsets:true
- ~mode:`Byte
- ~buffer in
+ let state =
+ Parser_pascaligo.ParserLog.mk_state
+ ~offsets:true
+ ~mode:`Byte
+ ~buffer in
Parser_pascaligo.ParserLog.pp_ast state ast;
ok buffer
-let pretty_print_cameligo = fun source ->
+let pretty_print_cameligo source =
let%bind ast = Parser.Cameligo.parse_file source in
let buffer = Buffer.create 59 in
- let state = Parser_cameligo.ParserLog.mk_state
- ~offsets:true
- ~mode:`Byte
- ~buffer in
+ let state = (* TODO: Should flow from the CLI *)
+ Parser_cameligo.ParserLog.mk_state
+ ~offsets:true
+ ~mode:`Point
+ ~buffer in
Parser.Cameligo.ParserLog.pp_ast state ast;
ok buffer
-let pretty_print_reasonligo = fun source ->
+let pretty_print_reasonligo source =
let%bind ast = Parser.Reasonligo.parse_file source in
let buffer = Buffer.create 59 in
- let state = Parser.Reasonligo.ParserLog.mk_state
- ~offsets:true
- ~mode:`Byte
- ~buffer in
+ let state = (* TODO: Should flow from the CLI *)
+ Parser.Reasonligo.ParserLog.mk_state
+ ~offsets:true
+ ~mode:`Point
+ ~buffer in
Parser.Reasonligo.ParserLog.pp_ast state ast;
ok buffer
-let pretty_print = fun syntax source_filename ->
- let%bind v_syntax = syntax_to_variant syntax (Some source_filename) in
- (match v_syntax with
- | Pascaligo -> pretty_print_pascaligo
- | Cameligo -> pretty_print_cameligo
- | ReasonLIGO -> pretty_print_reasonligo)
- source_filename
+let pretty_print syntax source =
+ let%bind v_syntax =
+ syntax_to_variant syntax (Some source) in
+ match v_syntax with
+ PascaLIGO -> pretty_print_pascaligo source
+ | CameLIGO -> pretty_print_cameligo source
+ | ReasonLIGO -> pretty_print_reasonligo source
diff --git a/src/main/compile/of_mini_c.ml b/src/main/compile/of_mini_c.ml
index 4d99be97a..8b95d9a2d 100644
--- a/src/main/compile/of_mini_c.ml
+++ b/src/main/compile/of_mini_c.ml
@@ -9,15 +9,13 @@ let compile_contract : expression -> Compiler.compiled_expression result = fun e
let%bind body = Compiler.Program.translate_function_body body [] input_ty in
let expr = Self_michelson.optimize body in
let%bind expr_ty = Compiler.Type.Ty.type_ e.type_value in
- let open! Compiler.Program in
- ok { expr_ty ; expr }
+ ok ({ expr_ty ; expr } : Compiler.Program.compiled_expression)
let compile_expression : expression -> Compiler.compiled_expression result = fun e ->
let%bind expr = Compiler.Program.translate_expression e Compiler.Environment.empty in
let expr = Self_michelson.optimize expr in
let%bind expr_ty = Compiler.Type.Ty.type_ e.type_value in
- let open! Compiler.Program in
- ok { expr_ty ; expr }
+ ok ({ expr_ty ; expr } : Compiler.Program.compiled_expression)
let aggregate_and_compile = fun program form ->
let%bind aggregated = aggregate_entry program form in
diff --git a/src/main/compile/of_simplified.ml b/src/main/compile/of_simplified.ml
index 072243a9c..488e809ac 100644
--- a/src/main/compile/of_simplified.ml
+++ b/src/main/compile/of_simplified.ml
@@ -6,18 +6,29 @@ let compile (program : Ast_simplified.program) : (Ast_typed.program * Typer.Solv
ok @@ (prog_typed, state)
let compile_expression ?(env = Ast_typed.Environment.full_empty) ~(state : Typer.Solver.state) (ae : Ast_simplified.expression)
- : (Ast_typed.value * Typer.Solver.state) result =
- Typer.type_expression env state ae
+ : (Ast_typed.expression * Typer.Solver.state) result =
+ let () = Typer.Solver.discard_state state in
+ Typer.type_expression_subst env state ae
let apply (entry_point : string) (param : Ast_simplified.expression) : Ast_simplified.expression result =
let name = Var.of_name entry_point in
let entry_point_var : Ast_simplified.expression =
- { expression = Ast_simplified.E_variable name ;
+ { expression_content = Ast_simplified.E_variable name ;
location = Virtual "generated entry-point variable" } in
let applied : Ast_simplified.expression =
- { expression = Ast_simplified.E_application (entry_point_var, param) ;
+ { expression_content = Ast_simplified.E_application {expr1=entry_point_var; expr2=param} ;
location = Virtual "generated application" } in
ok applied
let pretty_print formatter (program : Ast_simplified.program) =
- Ast_simplified.PP.program formatter program
\ No newline at end of file
+ Ast_simplified.PP.program formatter program
+
+let list_declarations (program : Ast_simplified.program) : string list =
+ List.fold_left
+ (fun prev el ->
+ let open Location in
+ let open Ast_simplified in
+ match el.wrap_content with
+ | Declaration_constant (var,_,_,_) -> (Var.to_name var)::prev
+ | _ -> prev)
+ [] program
diff --git a/src/main/compile/of_typed.ml b/src/main/compile/of_typed.ml
index a69f32c9d..43b2216fe 100644
--- a/src/main/compile/of_typed.ml
+++ b/src/main/compile/of_typed.ml
@@ -4,24 +4,28 @@ open Ast_typed
let compile : Ast_typed.program -> Mini_c.program result = fun p ->
Transpiler.transpile_program p
-let compile_expression : annotated_expression -> Mini_c.expression result = fun e ->
+let compile_expression : expression -> Mini_c.expression result = fun e ->
Transpiler.transpile_annotated_expression e
type check_type = Check_parameter | Check_storage
-let assert_equal_contract_type : check_type -> string -> Ast_typed.program -> Ast_typed.value -> unit result =
+let assert_equal_contract_type : check_type -> string -> Ast_typed.program -> Ast_typed.expression -> unit result =
fun c entry contract param -> Trace.trace (simple_info "Check argument type against contract type") (
let%bind entry_point = Ast_typed.get_entry contract entry in
- match entry_point.type_annotation.type_value' with
- | T_arrow (args,_) -> (
- match args.type_value' with
- | T_tuple [param_exp;storage_exp] -> (
+ match entry_point.type_expression.type_content with
+ | T_arrow {type1=args} -> (
+ match args.type_content with
+ | T_record m when LMap.cardinal m = 2 -> (
+ let param_exp = LMap.find (Label "0") m in
+ let storage_exp = LMap.find (Label "1") m in
match c with
- | Check_parameter -> assert_type_value_eq (param_exp, param.type_annotation)
- | Check_storage -> assert_type_value_eq (storage_exp, param.type_annotation)
+ | Check_parameter -> assert_type_expression_eq (param_exp, param.type_expression)
+ | Check_storage -> assert_type_expression_eq (storage_exp, param.type_expression)
)
| _ -> dummy_fail
)
| _ -> dummy_fail )
let pretty_print ppf program =
- Ast_typed.PP.program ppf program
\ No newline at end of file
+ Ast_typed.PP.program ppf program
+
+let some_interpret = Interpreter.dummy
diff --git a/src/main/compile/wrapper.ml b/src/main/compile/wrapper.ml
new file mode 100644
index 000000000..ae8f9043e
--- /dev/null
+++ b/src/main/compile/wrapper.ml
@@ -0,0 +1,12 @@
+open Trace
+
+let source_to_typed syntax source_file =
+ let%bind simplified = Of_source.compile source_file syntax in
+ let%bind typed,state = Of_simplified.compile simplified in
+ let env = Ast_typed.program_environment typed in
+ ok (typed,state,env)
+
+let source_to_typed_expression ~env ~state parameter syntax =
+ let%bind simplified = Of_source.compile_expression syntax parameter in
+ let%bind (typed,_) = Of_simplified.compile_expression ~env ~state simplified in
+ ok typed
diff --git a/src/main/uncompile/uncompile.ml b/src/main/uncompile/uncompile.ml
index 2fa1ee14d..6d43fba15 100644
--- a/src/main/uncompile/uncompile.ml
+++ b/src/main/uncompile/uncompile.ml
@@ -4,9 +4,9 @@ type ret_type = Function | Expression
let uncompile_value func_or_expr program entry ex_ty_value =
let%bind entry_expression = Ast_typed.get_entry program entry in
let%bind output_type = match func_or_expr with
- | Expression -> ok entry_expression.type_annotation
+ | Expression -> ok entry_expression.type_expression
| Function ->
- let%bind (_,output_type) = Ast_typed.get_t_function entry_expression.type_annotation in
+ let%bind (_,output_type) = Ast_typed.get_t_function entry_expression.type_expression in
ok output_type in
let%bind mini_c = Compiler.Uncompiler.translate_value ex_ty_value in
let%bind typed = Transpiler.untranspile mini_c output_type in
@@ -21,4 +21,4 @@ let uncompile_typed_program_entry_function_result program entry ex_ty_value =
let uncompile_expression type_value ex_ty_value =
let%bind mini_c = Compiler.Uncompiler.translate_value ex_ty_value in
let%bind typed = Transpiler.untranspile mini_c type_value in
- Typer.untype_expression typed
\ No newline at end of file
+ Typer.untype_expression typed
diff --git a/src/passes/1-parser/cameligo.ml b/src/passes/1-parser/cameligo.ml
index d69da91b4..575445a0a 100644
--- a/src/passes/1-parser/cameligo.ml
+++ b/src/passes/1-parser/cameligo.ml
@@ -1,129 +1,180 @@
-open Trace
-
-module Parser = Parser_cameligo.Parser
-module AST = Parser_cameligo.AST
-module ParserLog = Parser_cameligo.ParserLog
+module AST = Parser_cameligo.AST
module LexToken = Parser_cameligo.LexToken
-module Lexer = Lexer.Make(LexToken)
+module Lexer = Lexer.Make(LexToken)
+module Scoping = Parser_cameligo.Scoping
+module Region = Simple_utils.Region
+module ParErr = Parser_cameligo.ParErr
+module SSet = Utils.String.Set
-module Errors = struct
+(* Mock IOs TODO: Fill them with CLI options *)
- let lexer_error (e: Lexer.error AST.reg) =
- let title () = "lexer error" in
- let message () = Lexer.error_to_string e.value in
- let data = [
- ("parser_loc",
- fun () -> Format.asprintf "%a" Location.pp_lift @@ e.region
- )
- ] in
- error ~data title message
+module type IO =
+ sig
+ val ext : string
+ val options : EvalOpt.options
+ end
- let parser_error source (start: Lexing.position) (stop: Lexing.position) lexbuf =
- let title () = "parser error" in
- let file = if source = "" then
- ""
- else
- Format.sprintf "In file \"%s|%s\"" start.pos_fname source
- in
- let str = Format.sprintf
- "Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
- (Lexing.lexeme lexbuf)
- start.pos_lnum (start.pos_cnum - start.pos_bol)
- stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
- file
- in
- let message () = str in
- let loc = if start.pos_cnum = -1 then
- Region.make
- ~start:(Pos.min ~file:source)
- ~stop:(Pos.from_byte stop)
- else
- Region.make
- ~start:(Pos.from_byte start)
- ~stop:(Pos.from_byte stop)
- in
- let data =
- [
- ("parser_loc",
- fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
- )
- ]
- in
- error ~data title message
+module PreIO =
+ struct
+ let ext = ".ligo"
+ let pre_options =
+ EvalOpt.make ~libs:[]
+ ~verbose:SSet.empty
+ ~offsets:true
+ ~mode:`Point
+ ~cmd:EvalOpt.Quiet
+ ~mono:false
+ end
- let unrecognized_error source (start: Lexing.position) (stop: Lexing.position) lexbuf =
- let title () = "unrecognized error" in
- let file = if source = "" then
- ""
- else
- Format.sprintf "In file \"%s|%s\"" start.pos_fname source
- in
- let str = Format.sprintf
- "Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
- (Lexing.lexeme lexbuf)
- start.pos_lnum (start.pos_cnum - start.pos_bol)
- stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
- file
- in
- let message () = str in
- let loc = Region.make
- ~start:(Pos.from_byte start)
- ~stop:(Pos.from_byte stop)
- in
- let data = [
- ("unrecognized_loc",
- fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
- )
- ] in
- error ~data title message
+module Parser =
+ struct
+ type ast = AST.t
+ type expr = AST.expr
+ include Parser_cameligo.Parser
+ end
-end
+module ParserLog =
+ struct
+ type ast = AST.t
+ type expr = AST.expr
+ include Parser_cameligo.ParserLog
+ end
-open Errors
+module PreUnit =
+ ParserUnit.Make (Lexer)(AST)(Parser)(ParErr)(ParserLog)
-type 'a parser = (Lexing.lexbuf -> LexToken.token) -> Lexing.lexbuf -> 'a
+module Errors =
+ struct
+ (* let data =
+ [("location",
+ fun () -> Format.asprintf "%a" Location.pp_lift @@ loc)] *)
-let parse (parser: 'a parser) source lexbuf =
- let Lexer.{read ; close ; _} = Lexer.open_token_stream None in
- let result =
- try
- ok (parser read lexbuf)
- with
- | Parser.Error ->
- let start = Lexing.lexeme_start_p lexbuf in
- let stop = Lexing.lexeme_end_p lexbuf in
- fail @@ (parser_error source start stop lexbuf)
- | Lexer.Error e ->
- fail @@ (lexer_error e)
- | _ ->
- let _ = Printexc.print_backtrace Pervasives.stdout in
- let start = Lexing.lexeme_start_p lexbuf in
- let stop = Lexing.lexeme_end_p lexbuf in
- fail @@ (unrecognized_error source start stop lexbuf)
- in
- close ();
- result
+ let generic message =
+ let title () = ""
+ and message () = message.Region.value
+ in Trace.error ~data:[] title message
+ end
-let parse_file (source: string) : AST.t result =
+let parse (module IO : IO) parser =
+ let module Unit = PreUnit (IO) in
+ let local_fail error =
+ Trace.fail
+ @@ Errors.generic
+ @@ Unit.format_error ~offsets:IO.options#offsets
+ IO.options#mode error in
+ match parser () with
+ Stdlib.Ok semantic_value -> Trace.ok semantic_value
+
+ (* Lexing and parsing errors *)
+
+ | Stdlib.Error error -> Trace.fail @@ Errors.generic error
+ (* Scoping errors *)
+
+ | exception Scoping.Error (Scoping.Reserved_name name) ->
+ let token =
+ Lexer.Token.mk_ident name.Region.value name.Region.region in
+ (match token with
+ Stdlib.Error LexToken.Reserved_name ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost "Reserved name."
+ | Ok invalid ->
+ local_fail
+ ("Reserved name.\nHint: Change the name.\n", None, invalid))
+
+ | exception Scoping.Error (Scoping.Duplicate_variant name) ->
+ let token =
+ Lexer.Token.mk_constr name.Region.value name.Region.region
+ in local_fail
+ ("Duplicate constructor in this sum type declaration.\n\
+ Hint: Change the constructor.\n", None, token)
+
+ | exception Scoping.Error (Scoping.Non_linear_pattern var) ->
+ let token =
+ Lexer.Token.mk_ident var.Region.value var.Region.region in
+ (match token with
+ Stdlib.Error LexToken.Reserved_name ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost "Reserved name."
+ | Ok invalid ->
+ local_fail ("Repeated variable in this pattern.\n\
+ Hint: Change the name.\n",
+ None, invalid))
+
+ | exception Scoping.Error (Scoping.Duplicate_field name) ->
+ let token =
+ Lexer.Token.mk_ident name.Region.value name.Region.region in
+ (match token with
+ Stdlib.Error LexToken.Reserved_name ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost "Reserved name."
+ | Ok invalid ->
+ local_fail
+ ("Duplicate field name in this record declaration.\n\
+ Hint: Change the name.\n",
+ None, invalid))
+
+let parse_file (source: string) =
+ let module IO =
+ struct
+ let ext = PreIO.ext
+ let options =
+ PreIO.pre_options ~input:(Some source) ~expr:false
+ end in
+ let lib_path =
+ match IO.options#libs with
+ [] -> ""
+ | libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path
+ in List.fold_right mk_I libs "" in
+ let prefix =
+ match IO.options#input with
+ None | Some "-" -> "temp"
+ | Some file -> Filename.(remove_extension @@ basename file) in
+ let suffix = ".pp" ^ IO.ext in
let pp_input =
- let prefix = Filename.(source |> basename |> remove_extension)
- and suffix = ".pp.mligo"
- in prefix ^ suffix in
-
- let cpp_cmd = Printf.sprintf "cpp -traditional-cpp %s > %s"
- source pp_input in
+ if SSet.mem "cpp" IO.options#verbose
+ then prefix ^ suffix
+ else let pp_input, pp_out =
+ Filename.open_temp_file prefix suffix
+ in close_out pp_out; pp_input in
+ let cpp_cmd =
+ match IO.options#input with
+ None | Some "-" ->
+ Printf.sprintf "cpp -traditional-cpp%s - > %s"
+ lib_path pp_input
+ | Some file ->
+ Printf.sprintf "cpp -traditional-cpp%s %s > %s"
+ lib_path file pp_input in
+ let open Trace in
let%bind () = sys_command cpp_cmd in
+ let module Unit = PreUnit (IO) in
+ match Lexer.(open_token_stream @@ File pp_input) with
+ Ok instance ->
+ let thunk () = Unit.apply instance Unit.parse_contract
+ in parse (module IO) thunk
+ | Stdlib.Error (Lexer.File_opening msg) ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost msg
- let%bind channel =
- generic_try (simple_error "error opening file") @@
- (fun () -> open_in pp_input) in
- let lexbuf = Lexing.from_channel channel in
- parse (Parser.contract) source lexbuf
+let parse_string (s: string) =
+ let module IO =
+ struct
+ let ext = PreIO.ext
+ let options = PreIO.pre_options ~input:None ~expr:false
+ end in
+ let module Unit = PreUnit (IO) in
+ match Lexer.(open_token_stream @@ String s) with
+ Ok instance ->
+ let thunk () = Unit.apply instance Unit.parse_contract
+ in parse (module IO) thunk
+ | Stdlib.Error (Lexer.File_opening msg) ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost msg
-let parse_string (s:string) : AST.t result =
- let lexbuf = Lexing.from_string s in
- parse Parser.contract "" lexbuf
-
-let parse_expression (s:string) : AST.expr result =
- let lexbuf = Lexing.from_string s in
- parse Parser.interactive_expr "" lexbuf
+let parse_expression (s: string) =
+ let module IO =
+ struct
+ let ext = PreIO.ext
+ let options = PreIO.pre_options ~input:None ~expr:true
+ end in
+ let module Unit = PreUnit (IO) in
+ match Lexer.(open_token_stream @@ String s) with
+ Ok instance ->
+ let thunk () = Unit.apply instance Unit.parse_expr
+ in parse (module IO) thunk
+ | Stdlib.Error (Lexer.File_opening msg) ->
+ Trace.fail @@ Errors.generic @@ Region.wrap_ghost msg
diff --git a/src/passes/1-parser/cameligo/AST.ml b/src/passes/1-parser/cameligo/AST.ml
index d00cf9cd7..84aebb96e 100644
--- a/src/passes/1-parser/cameligo/AST.ml
+++ b/src/passes/1-parser/cameligo/AST.ml
@@ -333,10 +333,15 @@ and update = {
lbrace : lbrace;
record : path;
kwd_with : kwd_with;
- updates : record reg;
+ updates : field_path_assign reg ne_injection reg;
rbrace : rbrace;
}
+and field_path_assign = {
+ field_path : (field_name, dot) nsepseq;
+ assignment : equal;
+ field_expr : expr
+}
and path =
Name of variable
| Path of projection reg
@@ -459,10 +464,10 @@ let expr_to_region = function
| EList e -> list_expr_to_region e
| EConstr e -> constr_expr_to_region e
| EAnnot {region;_ } | ELetIn {region;_} | EFun {region;_}
-| ECond {region;_} | ETuple {region;_} | ECase {region;_}
-| ECall {region;_} | EVar {region; _} | EProj {region; _}
-| EUnit {region;_} | EPar {region;_} | EBytes {region; _}
-| ESeq {region; _} | ERecord {region; _} | EUpdate {region; _} -> region
+| ECond {region;_} | ETuple {region;_} | ECase {region;_}
+| ECall {region;_} | EVar {region; _} | EProj {region; _}
+| EUnit {region;_} | EPar {region;_} | EBytes {region; _}
+| ESeq {region; _} | ERecord {region; _} | EUpdate {region; _} -> region
let selection_to_region = function
FieldName f -> f.region
diff --git a/src/passes/1-parser/cameligo/LexerMain.ml b/src/passes/1-parser/cameligo/LexerMain.ml
index e9775b803..5ef471c37 100644
--- a/src/passes/1-parser/cameligo/LexerMain.ml
+++ b/src/passes/1-parser/cameligo/LexerMain.ml
@@ -1,4 +1,4 @@
-(** Driver for the CameLIGO lexer *)
+(* Driver for the CameLIGO lexer *)
module IO =
struct
@@ -7,3 +7,8 @@ module IO =
end
module M = LexerUnit.Make (IO) (Lexer.Make (LexToken))
+
+let () =
+ match M.trace () with
+ Stdlib.Ok () -> ()
+ | Error Region.{value; _} -> Utils.highlight value
diff --git a/src/passes/1-parser/cameligo/ParErr.ml b/src/passes/1-parser/cameligo/ParErr.ml
deleted file mode 100644
index f1be602f1..000000000
--- a/src/passes/1-parser/cameligo/ParErr.ml
+++ /dev/null
@@ -1,442 +0,0 @@
-
-(* This file was auto-generated based on "Parser.msg". *)
-
-(* Please note that the function [message] can raise [Not_found]. *)
-
-let message =
- fun s ->
- match s with
- | 0 ->
- "\n"
- | 1 ->
- "\n"
- | 2 ->
- "\n"
- | 3 ->
- "\n"
- | 4 ->
- "\n"
- | 5 ->
- "\n"
- | 7 ->
- "\n"
- | 49 ->
- "\n"
- | 51 ->
- "\n"
- | 52 ->
- "\n"
- | 53 ->
- "\n"
- | 18 ->
- "\n"
- | 8 ->
- "\n"
- | 9 ->
- "\n"
- | 10 ->
- "\n"
- | 42 ->
- "\n"
- | 43 ->
- "\n"
- | 46 ->
- "\n"
- | 47 ->
- "\n"
- | 33 ->
- "\n"
- | 478 ->
- "\n"
- | 27 ->
- "\n"
- | 31 ->
- "\n"
- | 28 ->
- "\n"
- | 35 ->
- "\n"
- | 12 ->
- "\n"
- | 16 ->
- "\n"
- | 6 ->
- "\n"
- | 13 ->
- "\n"
- | 61 ->
- "\n"
- | 133 ->
- "\n"
- | 379 ->
- "\n"
- | 381 ->
- "\n"
- | 472 ->
- "\n"
- | 169 ->
- "\n"
- | 134 ->
- "\n"
- | 136 ->
- "\n"
- | 137 ->
- "\n"
- | 153 ->
- "\n"
- | 380 ->
- "\n"
- | 63 ->
- "\n"
- | 142 ->
- "\n"
- | 143 ->
- "\n"
- | 128 ->
- "\n"
- | 145 ->
- "\n"
- | 72 ->
- "\n"
- | 94 ->
- "\n"
- | 106 ->
- "\n"
- | 95 ->
- "\n"
- | 108 ->
- "\n"
- | 109 ->
- "\n"
- | 110 ->
- "\n"
- | 73 ->
- "\n"
- | 91 ->
- "\n"
- | 93 ->
- "\n"
- | 92 ->
- "\n"
- | 90 ->
- "\n"
- | 77 ->
- "\n"
- | 78 ->
- "\n"
- | 65 ->
- "\n"
- | 66 ->
- "\n"
- | 67 ->
- "\n"
- | 120 ->
- "\n"
- | 121 ->
- "\n"
- | 124 ->
- "\n"
- | 125 ->
- "\n"
- | 147 ->
- "\n"
- | 148 ->
- "\n"
- | 149 ->
- "\n"
- | 157 ->
- "\n"
- | 156 ->
- "\n"
- | 481 ->
- "\n"
- | 483 ->
- "\n"
- | 221 ->
- "\n"
- | 246 ->
- "\n"
- | 223 ->
- "\n"
- | 225 ->
- "\n"
- | 219 ->
- "\n"
- | 230 ->
- "\n"
- | 259 ->
- "\n"
- | 260 ->
- "\n"
- | 247 ->
- "\n"
- | 268 ->
- "\n"
- | 232 ->
- "\n"
- | 261 ->
- "\n"
- | 262 ->
- "\n"
- | 270 ->
- "\n"
- | 272 ->
- "\n"
- | 274 ->
- "\n"
- | 276 ->
- "\n"
- | 278 ->
- "\n"
- | 195 ->
- "\n"
- | 263 ->
- "\n"
- | 289 ->
- "\n"
- | 292 ->
- "\n"
- | 249 ->
- "\n"
- | 297 ->
- "\n"
- | 266 ->
- "\n"
- | 160 ->
- "\n"
- | 164 ->
- "\n"
- | 445 ->
- "\n"
- | 337 ->
- "\n"
- | 317 ->
- "\n"
- | 447 ->
- "\n"
- | 319 ->
- "\n"
- | 320 ->
- "\n"
- | 321 ->
- "\n"
- | 448 ->
- "\n"
- | 462 ->
- "\n"
- | 463 ->
- "\n"
- | 449 ->
- "\n"
- | 450 ->
- "\n"
- | 452 ->
- "\n"
- | 451 ->
- "\n"
- | 453 ->
- "\n"
- | 454 ->
- "\n"
- | 455 ->
- "\n"
- | 457 ->
- "\n"
- | 333 ->
- "\n"
- | 335 ->
- "\n"
- | 339 ->
- "\n"
- | 336 ->
- "\n"
- | 334 ->
- "\n"
- | 345 ->
- "\n"
- | 346 ->
- "\n"
- | 348 ->
- "\n"
- | 347 ->
- "\n"
- | 349 ->
- "\n"
- | 350 ->
- "\n"
- | 351 ->
- "\n"
- | 373 ->
- "\n"
- | 352 ->
- "\n"
- | 354 ->
- "\n"
- | 458 ->
- "\n"
- | 460 ->
- "\n"
- | 464 ->
- "\n"
- | 446 ->
- "\n"
- | 316 ->
- "\n"
- | 444 ->
- "\n"
- | 165 ->
- "\n"
- | 167 ->
- "\n"
- | 168 ->
- "\n"
- | 172 ->
- "\n"
- | 171 ->
- "\n"
- | 163 ->
- "\n"
- | 465 ->
- "\n"
- | 467 ->
- "\n"
- | 468 ->
- "\n"
- | 166 ->
- "\n"
- | 239 ->
- "\n"
- | 240 ->
- "\n"
- | 243 ->
- "\n"
- | 244 ->
- "\n"
- | 441 ->
- "\n"
- | 173 ->
- "\n"
- | 428 ->
- "\n"
- | 429 ->
- "\n"
- | 174 ->
- "\n"
- | 175 ->
- "\n"
- | 434 ->
- "\n"
- | 435 ->
- "\n"
- | 438 ->
- "\n"
- | 439 ->
- "\n"
- | 427 ->
- "\n"
- | 421 ->
- "\n"
- | 422 ->
- "\n"
- | 423 ->
- "\n"
- | 177 ->
- "\n"
- | 308 ->
- "\n"
- | 309 ->
- "\n"
- | 412 ->
- "\n"
- | 419 ->
- "\n"
- | 411 ->
- "\n"
- | 310 ->
- "\n"
- | 312 ->
- "\n"
- | 324 ->
- "\n"
- | 325 ->
- "\n"
- | 326 ->
- "\n"
- | 327 ->
- "\n"
- | 329 ->
- "\n"
- | 328 ->
- "\n"
- | 330 ->
- "\n"
- | 331 ->
- "\n"
- | 332 ->
- "\n"
- | 384 ->
- "\n"
- | 385 ->
- "\n"
- | 387 ->
- "\n"
- | 340 ->
- "\n"
- | 314 ->
- "\n"
- | 311 ->
- "\n"
- | 401 ->
- "\n"
- | 402 ->
- "\n"
- | 404 ->
- "\n"
- | 403 ->
- "\n"
- | 405 ->
- "\n"
- | 406 ->
- "\n"
- | 407 ->
- "\n"
- | 415 ->
- "\n"
- | 408 ->
- "\n"
- | 410 ->
- "\n"
- | 178 ->
- "\n"
- | 179 ->
- "\n"
- | 182 ->
- "\n"
- | 183 ->
- "\n"
- | 186 ->
- "\n"
- | 306 ->
- "\n"
- | 304 ->
- "\n"
- | 188 ->
- "\n"
- | 190 ->
- "\n"
- | 191 ->
- "\n"
- | 192 ->
- "\n"
- | 193 ->
- "\n"
- | 198 ->
- "\n"
- | 218 ->
- "\n"
- | 197 ->
- "\n"
- | 214 ->
- "\n"
- | _ ->
- raise Not_found
diff --git a/src/passes/1-parser/cameligo/Parser.mly b/src/passes/1-parser/cameligo/Parser.mly
index e6cc6f903..0901ab875 100644
--- a/src/passes/1-parser/cameligo/Parser.mly
+++ b/src/passes/1-parser/cameligo/Parser.mly
@@ -90,7 +90,7 @@ tuple(item):
(* Possibly empty semicolon-separated values between brackets *)
-list(item):
+list__(item):
"[" sep_or_term_list(item,";")? "]" {
let compound = Brackets ($1,$3)
and region = cover $1 $3 in
@@ -182,7 +182,7 @@ sum_type:
variant:
"" { {$1 with value={constr=$1; arg=None}} }
-| "" "of" cartesian {
+| "" "of" fun_type {
let region = cover $1.region (type_expr_to_region $3)
and value = {constr=$1; arg = Some ($2,$3)}
in {region; value} }
@@ -217,6 +217,7 @@ let_declaration:
let_binding:
"" nseq(sub_irrefutable) type_annotation? "=" expr {
+ Scoping.check_reserved_name $1;
let binders = Utils.nseq_cons (PVar $1) $2 in
Utils.nseq_iter Scoping.check_pattern binders;
{binders; lhs_type=$3; eq=$4; let_rhs=$5}
@@ -293,7 +294,7 @@ core_pattern:
| "false" { PFalse $1 }
| "true" { PTrue $1 }
| par(ptuple) { PPar $1 }
-| list(tail) { PList (PListComp $1) }
+| list__(tail) { PList (PListComp $1) }
| constr_pattern { PConstr $1 }
| record_pattern { PRecord $1 }
@@ -584,7 +585,7 @@ core_expr:
| unit { EUnit $1 }
| "false" { ELogic (BoolExpr (False $1)) }
| "true" { ELogic (BoolExpr (True $1)) }
-| list(expr) { EList (EListComp $1) }
+| list__(expr) { EList (EListComp $1) }
| sequence { ESeq $1 }
| record_expr { ERecord $1 }
| update_record { EUpdate $1 }
@@ -627,7 +628,7 @@ record_expr:
in {region; value} }
update_record:
- "{" path "with" sep_or_term_list(field_assignment,";") "}" {
+ "{" path "with" sep_or_term_list(field_path_assignment,";") "}" {
let region = cover $1 $5 in
let ne_elements, terminator = $4 in
let value = {
@@ -641,6 +642,14 @@ update_record:
rbrace = $5}
in {region; value} }
+field_path_assignment :
+ nsepseq(field_name,".") "=" expr {
+ let region = cover (nsepseq_to_region (fun x -> x.region) $1) (expr_to_region $3) in
+ let value = {field_path = $1;
+ assignment = $2;
+ field_expr = $3}
+ in {region; value}}
+
field_assignment:
field_name "=" expr {
let start = $1.region in
diff --git a/src/passes/1-parser/cameligo/ParserLog.ml b/src/passes/1-parser/cameligo/ParserLog.ml
index e0b7fd09b..aa847e245 100644
--- a/src/passes/1-parser/cameligo/ParserLog.ml
+++ b/src/passes/1-parser/cameligo/ParserLog.ml
@@ -188,7 +188,7 @@ and print_update state {value; _} =
print_token state lbrace "{";
print_path state record;
print_token state kwd_with "with";
- print_record_expr state updates;
+ print_ne_injection state print_field_path_assign updates;
print_token state rbrace "}"
and print_path state = function
@@ -513,6 +513,12 @@ and print_field_assign state {value; _} =
print_token state assignment "=";
print_expr state field_expr
+and print_field_path_assign state {value; _} =
+ let {field_path; assignment; field_expr} = value in
+ print_nsepseq state "." print_var field_path;
+ print_token state assignment "=";
+ print_expr state field_expr
+
and print_sequence state seq =
print_injection state print_expr seq
@@ -905,7 +911,7 @@ and pp_projection state proj =
and pp_update state update =
pp_path state update.record;
- pp_ne_injection pp_field_assign state update.updates.value
+ pp_ne_injection pp_field_path_assign state update.updates.value
and pp_path state = function
Name name ->
@@ -928,6 +934,12 @@ and pp_field_assign state {value; _} =
pp_ident (state#pad 2 0) value.field_name;
pp_expr (state#pad 2 1) value.field_expr
+and pp_field_path_assign state {value; _} =
+ pp_node state "";
+ let path = Utils.nsepseq_to_list value.field_path in
+ List.iter (pp_ident (state#pad 2 0)) path;
+ pp_expr (state#pad 2 1) value.field_expr
+
and pp_constr_expr state = function
ENone region ->
pp_loc_node state "ENone" region
diff --git a/src/passes/1-parser/cameligo/ParserMain.ml b/src/passes/1-parser/cameligo/ParserMain.ml
index 2880157db..9c481f178 100644
--- a/src/passes/1-parser/cameligo/ParserMain.ml
+++ b/src/passes/1-parser/cameligo/ParserMain.ml
@@ -27,12 +27,11 @@ module Unit =
(* Main *)
-let issue_error point =
- let error = Unit.format_error ~offsets:IO.options#offsets
- IO.options#mode point
- in Stdlib.Error error
+let issue_error error : ('a, string Region.reg) Stdlib.result =
+ Stdlib.Error (Unit.format_error ~offsets:IO.options#offsets
+ IO.options#mode error)
-let parse parser : ('a,string) Stdlib.result =
+let parse parser : ('a, string Region.reg) Stdlib.result =
try parser () with
(* Scoping errors *)
@@ -81,11 +80,61 @@ let parse parser : ('a,string) Stdlib.result =
None, invalid
in issue_error point)
+(* Preprocessing the input source with CPP *)
+
+module SSet = Utils.String.Set
+let sprintf = Printf.sprintf
+
+(* Path for CPP inclusions (#include) *)
+
+let lib_path =
+ match IO.options#libs with
+ [] -> ""
+ | libs -> let mk_I dir path = sprintf " -I %s%s" dir path
+ in List.fold_right mk_I libs ""
+
+let prefix =
+ match IO.options#input with
+ None | Some "-" -> "temp"
+ | Some file -> Filename.(file |> basename |> remove_extension)
+
+let suffix = ".pp" ^ IO.ext
+
+let pp_input =
+ if SSet.mem "cpp" IO.options#verbose
+ then prefix ^ suffix
+ else let pp_input, pp_out =
+ Filename.open_temp_file prefix suffix
+ in close_out pp_out; pp_input
+
+let cpp_cmd =
+ match IO.options#input with
+ None | Some "-" ->
+ sprintf "cpp -traditional-cpp%s - > %s"
+ lib_path pp_input
+ | Some file ->
+ sprintf "cpp -traditional-cpp%s %s > %s"
+ lib_path file pp_input
+
let () =
- if IO.options#expr
- then match parse (fun () -> Unit.parse Unit.parse_expr) with
- Stdlib.Ok _ -> ()
- | Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg
- else match parse (fun () -> Unit.parse Unit.parse_contract) with
- Stdlib.Ok _ -> ()
- | Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg
+ if Sys.command cpp_cmd <> 0 then
+ Printf.eprintf "External error: \"%s\" failed." cpp_cmd
+
+(* Instantiating the lexer and calling the parser *)
+
+let lexer_inst =
+ match Lexer.open_token_stream (Lexer.File pp_input) with
+ Ok instance ->
+ if IO.options#expr
+ then
+ match parse (fun () -> Unit.apply instance Unit.parse_expr) with
+ Stdlib.Ok _ -> ()
+ | Error Region.{value; _} ->
+ Printf.eprintf "\027[31m%s\027[0m%!" value
+ else
+ (match parse (fun () -> Unit.apply instance Unit.parse_contract) with
+ Stdlib.Ok _ -> ()
+ | Error Region.{value; _} ->
+ Printf.eprintf "\027[31m%s\027[0m%!" value)
+ | Stdlib.Error (Lexer.File_opening msg) ->
+ Printf.eprintf "\027[31m%s\027[0m%!" msg
diff --git a/src/passes/1-parser/cameligo/Scoping.ml b/src/passes/1-parser/cameligo/Scoping.ml
index 5f45c643b..483262deb 100644
--- a/src/passes/1-parser/cameligo/Scoping.ml
+++ b/src/passes/1-parser/cameligo/Scoping.ml
@@ -31,19 +31,30 @@ module VarSet = Set.Make (Ord)
let reserved =
let open SSet in
empty
+ |> add "abs"
+ |> add "address"
+ |> add "amount"
|> add "assert"
|> add "balance"
- |> add "time"
- |> add "amount"
- |> add "gas"
- |> add "sender"
- |> add "source"
- |> add "failwith"
+ |> add "black2b"
+ |> add "check"
|> add "continue"
- |> add "stop"
+ |> add "failwith"
+ |> add "gas"
+ |> add "hash"
+ |> add "hash_key"
+ |> add "implicit_account"
|> add "int"
- |> add "abs"
+ |> add "pack"
+ |> add "self_address"
+ |> add "sender"
+ |> add "sha256"
+ |> add "sha512"
+ |> add "source"
+ |> add "stop"
+ |> add "time"
|> add "unit"
+ |> add "unpack"
let check_reserved_names vars =
let is_reserved elt = SSet.mem elt.value reserved in
diff --git a/src/passes/1-parser/cameligo/dune b/src/passes/1-parser/cameligo/dune
index 57806ff56..8824fdcd4 100644
--- a/src/passes/1-parser/cameligo/dune
+++ b/src/passes/1-parser/cameligo/dune
@@ -15,17 +15,16 @@
(name parser_cameligo)
(public_name ligo.parser.cameligo)
(modules
- Scoping AST cameligo Parser ParserLog LexToken)
+ Scoping AST cameligo Parser ParserLog LexToken ParErr)
(libraries
menhirLib
parser_shared
str
simple-utils
- tezos-utils
- getopt)
+ tezos-utils)
(preprocess
(pps bisect_ppx --conditional))
- (flags (:standard -open Simple_utils -open Parser_shared)))
+ (flags (:standard -open Parser_shared -open Simple_utils)))
;; Build of the unlexer (for covering the
;; error states of the LR automaton)
@@ -52,8 +51,7 @@
(executable
(name ParserMain)
(libraries parser_cameligo)
- (modules
- ParErr ParserMain)
+ (modules ParserMain)
(preprocess
(pps bisect_ppx --conditional))
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
@@ -70,4 +68,105 @@
(rule
(targets all.mligo)
(deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe)
- (action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=mligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly )))
\ No newline at end of file
+ (action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=mligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly )))
+
+;; Error messages
+
+;; Generate error messages from scratch
+; (rule
+; (targets error.messages)
+; (deps Parser.mly ParToken.mly error.messages.checked-in)
+; (action
+; (with-stdout-to %{targets}
+; (bash
+; "menhir \
+; --unused-tokens \
+; --list-errors \
+; --table \
+; --strict \
+; --external-tokens LexToken.mli \
+; --base Parser.mly \
+; ParToken.mly \
+; Parser.mly
+; "
+; )
+; ))
+; )
+
+(rule
+ (targets error.messages)
+ (deps Parser.mly ParToken.mly error.messages.checked-in LexToken.mli)
+ (action
+ (with-stdout-to %{targets}
+ (run
+ menhir
+ --unused-tokens
+ --update-errors error.messages.checked-in
+ --table
+ --strict
+ --external-tokens LexToken.mli
+ --base Parser.mly
+ ParToken.mly
+ Parser.mly
+ )
+ ))
+)
+
+(rule
+ (target error.messages.new)
+ (action
+ (with-stdout-to %{target}
+ (run
+ menhir
+ --unused-tokens
+ --list-errors
+ --table
+ --strict
+ --external-tokens LexToken.mli
+ --base Parser.mly
+ ParToken.mly
+ Parser.mly
+ )
+ )
+ )
+)
+
+(alias
+ (name runtest)
+ (deps error.messages error.messages.new)
+ (action
+ (run
+ menhir
+ --unused-tokens
+ --table
+ --strict
+ --external-tokens LexToken.mli
+ --base Parser.mly
+ ParToken.mly
+ Parser.mly
+ --compare-errors error.messages.new
+ --compare-errors error.messages
+ )
+ )
+ )
+
+
+
+(rule
+ (targets ParErr.ml)
+ (deps Parser.mly ParToken.mly error.messages.checked-in LexToken.mli)
+ (action
+ (with-stdout-to %{targets}
+ (run
+ menhir
+ --unused-tokens
+ --table
+ --strict
+ --external-tokens LexToken.mli
+ --base Parser.mly
+ ParToken.mly
+ Parser.mly
+ --compile-errors error.messages.checked-in
+ )
+ ))
+)
diff --git a/src/passes/1-parser/cameligo/error.messages.checked-in b/src/passes/1-parser/cameligo/error.messages.checked-in
new file mode 100644
index 000000000..d0cbf4a33
--- /dev/null
+++ b/src/passes/1-parser/cameligo/error.messages.checked-in
@@ -0,0 +1,3541 @@
+interactive_expr: Begin True RBRACKET
+##
+## Ends in an error in state: 214.
+##
+## sequence -> Begin option(sep_or_term_list(expr,SEMI)) . End [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Begin option(sep_or_term_list(expr,SEMI))
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 221, spurious reduction of production call_expr_level -> core_expr
+## In state 228, spurious reduction of production unary_expr_level -> call_expr_level
+## In state 210, spurious reduction of production mult_expr_level -> unary_expr_level
+## In state 218, spurious reduction of production add_expr_level -> mult_expr_level
+## In state 258, spurious reduction of production cons_expr_level -> add_expr_level
+## In state 248, spurious reduction of production cat_expr_level -> cons_expr_level
+## In state 280, spurious reduction of production comp_expr_level -> cat_expr_level
+## In state 287, spurious reduction of production conj_expr_level -> comp_expr_level
+## In state 294, spurious reduction of production disj_expr_level -> conj_expr_level
+## In state 246, spurious reduction of production base_expr(expr) -> disj_expr_level
+## In state 300, spurious reduction of production base_cond__open(expr) -> base_expr(expr)
+## In state 301, spurious reduction of production expr -> base_cond__open(expr)
+## In state 239, spurious reduction of production nsepseq(expr,SEMI) -> expr
+## In state 217, spurious reduction of production sep_or_term_list(expr,SEMI) -> nsepseq(expr,SEMI)
+## In state 213, spurious reduction of production option(sep_or_term_list(expr,SEMI)) -> sep_or_term_list(expr,SEMI)
+##
+
+
+
+interactive_expr: Begin With
+##
+## Ends in an error in state: 197.
+##
+## sequence -> Begin . option(sep_or_term_list(expr,SEMI)) End [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Begin
+##
+
+
+
+interactive_expr: C_None WILD
+##
+## Ends in an error in state: 218.
+##
+## add_expr_level -> mult_expr_level . [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE PLUS Or NE MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+## bin_op(mult_expr_level,Mod,unary_expr_level) -> mult_expr_level . Mod unary_expr_level [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+## bin_op(mult_expr_level,SLASH,unary_expr_level) -> mult_expr_level . SLASH unary_expr_level [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+## bin_op(mult_expr_level,TIMES,unary_expr_level) -> mult_expr_level . TIMES unary_expr_level [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## mult_expr_level
+##
+
+
+
+interactive_expr: C_Some With
+##
+## Ends in an error in state: 198.
+##
+## constr_expr -> C_Some . core_expr [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## C_Some
+##
+
+
+
+interactive_expr: Constr DOT Ident DOT With
+##
+## Ends in an error in state: 193.
+##
+## projection -> Constr DOT Ident DOT . nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Constr DOT Ident DOT
+##
+
+
+
+interactive_expr: Constr DOT Ident WILD
+##
+## Ends in an error in state: 192.
+##
+## module_field -> Constr DOT Ident . [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+## projection -> Constr DOT Ident . DOT nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Constr DOT Ident
+##
+
+
+
+interactive_expr: Constr DOT With
+##
+## Ends in an error in state: 191.
+##
+## module_field -> Constr DOT . Ident [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+## projection -> Constr DOT . Ident DOT nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Constr DOT
+##
+
+
+
+interactive_expr: Constr WILD
+##
+## Ends in an error in state: 190.
+##
+## constr_expr -> Constr . core_expr [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+## constr_expr -> Constr . [ With VBAR Type Then TIMES SLASH SEMI RPAR RBRACKET RBRACE PLUS Or NE Mod MINUS Let LT LE In GT GE End Else EQ EOF CONS COMMA COLON CAT BOOL_OR BOOL_AND Attr ]
+## module_field -> Constr . DOT Ident [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+## projection -> Constr . DOT Ident DOT nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Constr
+##
+
+
+
+interactive_expr: Fun WILD ARROW With
+##
+## Ends in an error in state: 188.
+##
+## fun_expr(expr) -> Fun nseq(irrefutable) ARROW . expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Fun nseq(irrefutable) ARROW
+##
+
+
+
+interactive_expr: Fun WILD RPAR
+##
+## Ends in an error in state: 304.
+##
+## nseq(irrefutable) -> irrefutable . seq(irrefutable) [ ARROW ]
+##
+## The known suffix of the stack is as follows:
+## irrefutable
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 133, spurious reduction of production irrefutable -> sub_irrefutable
+##
+
+
+
+interactive_expr: Fun WILD WILD RPAR
+##
+## Ends in an error in state: 306.
+##
+## seq(irrefutable) -> irrefutable . seq(irrefutable) [ ARROW ]
+##
+## The known suffix of the stack is as follows:
+## irrefutable
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 133, spurious reduction of production irrefutable -> sub_irrefutable
+##
+
+
+
+interactive_expr: Fun With
+##
+## Ends in an error in state: 186.
+##
+## fun_expr(expr) -> Fun . nseq(irrefutable) ARROW expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Fun
+##
+
+
+
+interactive_expr: Ident DOT Int DOT With
+##
+## Ends in an error in state: 183.
+##
+## nsepseq(selection,DOT) -> selection DOT . nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## selection DOT
+##
+
+
+
+interactive_expr: Ident DOT Int WILD
+##
+## Ends in an error in state: 182.
+##
+## nsepseq(selection,DOT) -> selection . [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+## nsepseq(selection,DOT) -> selection . DOT nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## selection
+##
+
+
+
+interactive_expr: Ident DOT With
+##
+## Ends in an error in state: 179.
+##
+## projection -> Ident DOT . nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Ident DOT
+##
+
+
+
+interactive_expr: Ident WILD
+##
+## Ends in an error in state: 178.
+##
+## core_expr -> Ident . [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+## projection -> Ident . DOT nsepseq(selection,DOT) [ With VBAR Type True Then TIMES String SLASH SEMI RPAR RBRACKET RBRACE PLUS Or Nat NE Mutez Mod MINUS Let LT LPAR LE LBRACKET LBRACE Int In Ident GT GE False End Else EQ EOF Constr CONS COMMA COLON CAT Bytes Begin BOOL_OR BOOL_AND Attr ]
+##
+## The known suffix of the stack is as follows:
+## Ident
+##
+
+
+
+interactive_expr: If True Then Fun WILD ARROW With
+##
+## Ends in an error in state: 410.
+##
+## fun_expr(closed_if) -> Fun nseq(irrefutable) ARROW . closed_if [ Else ]
+## fun_expr(expr) -> Fun nseq(irrefutable) ARROW . expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Fun nseq(irrefutable) ARROW
+##
+
+
+
+interactive_expr: If True Then Fun With
+##
+## Ends in an error in state: 408.
+##
+## fun_expr(closed_if) -> Fun . nseq(irrefutable) ARROW closed_if [ Else ]
+## fun_expr(expr) -> Fun . nseq(irrefutable) ARROW expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Fun
+##
+
+
+
+interactive_expr: If True Then If True Then True Else With
+##
+## Ends in an error in state: 415.
+##
+## if_then_else(closed_if) -> If expr Then closed_if Else . closed_if [ Else ]
+## if_then_else(expr) -> If expr Then closed_if Else . expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## If expr Then closed_if Else
+##
+
+
+
+interactive_expr: If True Then If True Then With
+##
+## Ends in an error in state: 407.
+##
+## if_then(expr) -> If expr Then . expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(closed_if) -> If expr Then . closed_if Else closed_if [ Else ]
+## if_then_else(expr) -> If expr Then . closed_if Else expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## If expr Then
+##
+
+
+
+interactive_expr: If True Then If True With
+##
+## Ends in an error in state: 406.
+##
+## if_then(expr) -> If expr . Then expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(closed_if) -> If expr . Then closed_if Else closed_if [ Else ]
+## if_then_else(expr) -> If expr . Then closed_if Else expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## If expr
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 221, spurious reduction of production call_expr_level -> core_expr
+## In state 228, spurious reduction of production unary_expr_level -> call_expr_level
+## In state 210, spurious reduction of production mult_expr_level -> unary_expr_level
+## In state 218, spurious reduction of production add_expr_level -> mult_expr_level
+## In state 258, spurious reduction of production cons_expr_level -> add_expr_level
+## In state 248, spurious reduction of production cat_expr_level -> cons_expr_level
+## In state 280, spurious reduction of production comp_expr_level -> cat_expr_level
+## In state 287, spurious reduction of production conj_expr_level -> comp_expr_level
+## In state 294, spurious reduction of production disj_expr_level -> conj_expr_level
+## In state 246, spurious reduction of production base_expr(expr) -> disj_expr_level
+## In state 300, spurious reduction of production base_cond__open(expr) -> base_expr(expr)
+## In state 301, spurious reduction of production expr -> base_cond__open(expr)
+##
+
+
+
+interactive_expr: If True Then If With
+##
+## Ends in an error in state: 405.
+##
+## if_then(expr) -> If . expr Then expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(closed_if) -> If . expr Then closed_if Else closed_if [ Else ]
+## if_then_else(expr) -> If . expr Then closed_if Else expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## If
+##
+
+
+
+interactive_expr: If True Then Let WILD EQ Bytes Attr Type
+##
+## Ends in an error in state: 403.
+##
+## let_expr(closed_if) -> Let let_binding seq(Attr) . In closed_if [ Else ]
+## let_expr(expr) -> Let let_binding seq(Attr) . In expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Let let_binding seq(Attr)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 169, spurious reduction of production seq(Attr) ->
+## In state 170, spurious reduction of production seq(Attr) -> Attr seq(Attr)
+##
+
+
+
+interactive_expr: If True Then Let WILD EQ Bytes In With
+##
+## Ends in an error in state: 404.
+##
+## let_expr(closed_if) -> Let let_binding seq(Attr) In . closed_if [ Else ]
+## let_expr(expr) -> Let let_binding seq(Attr) In . expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Let let_binding seq(Attr) In
+##
+
+
+
+interactive_expr: If True Then Let WILD EQ Bytes With
+##
+## Ends in an error in state: 402.
+##
+## let_expr(closed_if) -> Let let_binding . seq(Attr) In closed_if [ Else ]
+## let_expr(expr) -> Let let_binding . seq(Attr) In expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Let let_binding
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 221, spurious reduction of production call_expr_level -> core_expr
+## In state 228, spurious reduction of production unary_expr_level -> call_expr_level
+## In state 210, spurious reduction of production mult_expr_level -> unary_expr_level
+## In state 218, spurious reduction of production add_expr_level -> mult_expr_level
+## In state 258, spurious reduction of production cons_expr_level -> add_expr_level
+## In state 248, spurious reduction of production cat_expr_level -> cons_expr_level
+## In state 280, spurious reduction of production comp_expr_level -> cat_expr_level
+## In state 287, spurious reduction of production conj_expr_level -> comp_expr_level
+## In state 294, spurious reduction of production disj_expr_level -> conj_expr_level
+## In state 246, spurious reduction of production base_expr(expr) -> disj_expr_level
+## In state 300, spurious reduction of production base_cond__open(expr) -> base_expr(expr)
+## In state 301, spurious reduction of production expr -> base_cond__open(expr)
+## In state 382, spurious reduction of production let_binding -> irrefutable option(type_annotation) EQ expr
+##
+
+
+
+interactive_expr: If True Then Let With
+##
+## Ends in an error in state: 401.
+##
+## let_expr(closed_if) -> Let . let_binding seq(Attr) In closed_if [ Else ]
+## let_expr(expr) -> Let . let_binding seq(Attr) In expr [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+##
+## The known suffix of the stack is as follows:
+## Let
+##
+
+
+
+interactive_expr: If True Then Match True Type
+##
+## Ends in an error in state: 311.
+##
+## match_expr(base_cond) -> Match expr . With option(VBAR) cases(base_cond) [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## match_expr(base_if_then_else) -> Match expr . With option(VBAR) cases(base_if_then_else) [ Else ]
+##
+## The known suffix of the stack is as follows:
+## Match expr
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 221, spurious reduction of production call_expr_level -> core_expr
+## In state 228, spurious reduction of production unary_expr_level -> call_expr_level
+## In state 210, spurious reduction of production mult_expr_level -> unary_expr_level
+## In state 218, spurious reduction of production add_expr_level -> mult_expr_level
+## In state 258, spurious reduction of production cons_expr_level -> add_expr_level
+## In state 248, spurious reduction of production cat_expr_level -> cons_expr_level
+## In state 280, spurious reduction of production comp_expr_level -> cat_expr_level
+## In state 287, spurious reduction of production conj_expr_level -> comp_expr_level
+## In state 294, spurious reduction of production disj_expr_level -> conj_expr_level
+## In state 246, spurious reduction of production base_expr(expr) -> disj_expr_level
+## In state 300, spurious reduction of production base_cond__open(expr) -> base_expr(expr)
+## In state 301, spurious reduction of production expr -> base_cond__open(expr)
+##
+
+
+
+interactive_expr: If True Then Match True With VBAR Begin
+##
+## Ends in an error in state: 314.
+##
+## match_expr(base_cond) -> Match expr With option(VBAR) . cases(base_cond) [ With Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## match_expr(base_if_then_else) -> Match expr With option(VBAR) . cases(base_if_then_else) [ Else ]
+##
+## The known suffix of the stack is as follows:
+## Match expr With option(VBAR)
+##
+
+
+
+interactive_expr: If True Then Match True With WILD ARROW Bytes VBAR With
+##
+## Ends in an error in state: 340.
+##
+## cases(base_cond) -> cases(base_cond) VBAR . case_clause(base_cond) [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## cases(base_if_then_else) -> cases(base_cond) VBAR . case_clause(base_if_then_else) [ Else ]
+##
+## The known suffix of the stack is as follows:
+## cases(base_cond) VBAR
+##
+
+
+
+interactive_expr: If True Then Match True With WILD ARROW Fun WILD ARROW With
+##
+## Ends in an error in state: 387.
+##
+## fun_expr(base_cond) -> Fun nseq(irrefutable) ARROW . base_cond [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## fun_expr(base_if_then_else) -> Fun nseq(irrefutable) ARROW . base_if_then_else [ Else ]
+##
+## The known suffix of the stack is as follows:
+## Fun nseq(irrefutable) ARROW
+##
+
+
+
+interactive_expr: If True Then Match True With WILD ARROW Fun With
+##
+## Ends in an error in state: 385.
+##
+## fun_expr(base_cond) -> Fun . nseq(irrefutable) ARROW base_cond [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## fun_expr(base_if_then_else) -> Fun . nseq(irrefutable) ARROW base_if_then_else [ Else ]
+##
+## The known suffix of the stack is as follows:
+## Fun
+##
+
+
+
+interactive_expr: If True Then Match True With WILD ARROW If True Then True Else With
+##
+## Ends in an error in state: 384.
+##
+## if_then_else(base_cond) -> If expr Then closed_if Else . base_cond [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(base_if_then_else) -> If expr Then closed_if Else . base_if_then_else [ Else ]
+##
+## The known suffix of the stack is as follows:
+## If expr Then closed_if Else
+##
+
+
+
+interactive_expr: If True Then Match True With WILD ARROW If True Then With
+##
+## Ends in an error in state: 332.
+##
+## if_then(base_cond) -> If expr Then . base_cond [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(base_cond) -> If expr Then . closed_if Else base_cond [ With VBAR Type Then SEMI RPAR RBRACKET RBRACE Let In End EOF COLON Attr ]
+## if_then_else(base_if_then_else) -> If expr Then . closed_if Else base_if_then_else [ Else ]
+##
+## The known suffix of the stack is as follows:
+## If expr Then
+##
+
+