Merge
This commit is contained in:
commit
40fd4cc2fe
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,6 @@ Its files are in `parser/parser_name`.
|
||||
## Concrete Syntax Tree
|
||||
The CST is the aforementioned structured representation of the program. Is is structurally very close to the source code, and is mostly an intermediary there because manipulating string is not practical.
|
||||
Its files are in `parser/parser_name`.
|
||||
## Simplifier
|
||||
A Simplifier is a function that takes a CST and outputs the corresponding Common AST. This is the actual bridge between a given syntax and LIGO.
|
||||
## Sugar_to_core
|
||||
A Sugar_to_core is a function that takes a CST and outputs the corresponding Common AST. This is the actual bridge between a given syntax and LIGO.
|
||||
Its files are in `simplify/parser_name`.
|
||||
|
@ -6,7 +6,7 @@ title: Middle End
|
||||
The Middle-End is the core of LIGO. It is also composed of three parts.
|
||||
## Common AST
|
||||
The Common AST is the closest thing to what could be called “LIGO lang”. As such, it should be as simple as possible. Collapsing particular cases in more general constructs is encouraged. Documenting it is crucial for people who’ll write new parsers or editor support for Front-end related things.
|
||||
Its files are in `ast_simplified/`, of interest is the definition of the AST itself in `ast_simplified/types.ml`.
|
||||
Its files are in `ast_core/`, of interest is the definition of the AST itself in `ast_core/types.ml`.
|
||||
## Type Checker
|
||||
The Type Checker, among other things, checks that a given AST is valid with regard to type-safety. It also annotates expressions with their types, free-variables and local environments.
|
||||
As time passes, we want to make the type-system stronger, to encode arbitrarily complex properties in an extensible manner.
|
||||
|
@ -102,7 +102,7 @@ What's going on is similar to the last program: `expect_eq_evaluate` runs a prog
|
||||
|
||||
For example, once the program stops running the value of `address` is `"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"`. The *comparison*, however, is made to a constructed expression.
|
||||
|
||||
Remember that we're testing from OCaml, but the program is written and evaluated as LIGO. In order to provide a proper comparison, we convert our expected test values into LIGO expressions and data. Constructors such as `e_list` and `e_address` provide a bridge between LIGO and OCaml. Their definitions can be found in files such as [src/stages/ast_simplified/combinators.ml](https://gitlab.com/ligolang/ligo/blob/dev/src/stages/ast_simplified/combinators.ml), or using [Merlin's definition point finder](https://github.com/ocaml/merlin/wiki). These same functions are used during the simplification stage of LIGO compilation, so becoming familiar with them will help prepare you to work on the [front end](contributors/big-picture/front-end/).
|
||||
Remember that we're testing from OCaml, but the program is written and evaluated as LIGO. In order to provide a proper comparison, we convert our expected test values into LIGO expressions and data. Constructors such as `e_list` and `e_address` provide a bridge between LIGO and OCaml. Their definitions can be found in files such as [src/stages/ast_core/combinators.ml](https://gitlab.com/ligolang/ligo/blob/dev/src/stages/ast_core/combinators.ml), or using [Merlin's definition point finder](https://github.com/ocaml/merlin/wiki). These same functions are used during the simplification stage of LIGO compilation, so becoming familiar with them will help prepare you to work on the [front end](contributors/big-picture/front-end/).
|
||||
|
||||
## How To Write A Test For LIGO
|
||||
|
||||
|
11
gitlab-pages/docs/intro/FAQ.md
Normal file
11
gitlab-pages/docs/intro/FAQ.md
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
id: faq
|
||||
title: FAQ
|
||||
---
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
Before you ask...
|
||||
|
||||
## Question One
|
||||
Answer.
|
@ -299,6 +299,41 @@ gitlab-pages/docs/language-basics/src/functions/incr_map.religo incr_map
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Nested functions (also known as closures)
|
||||
It's possible to place functions inside other functions. These functions
|
||||
have access to variables in the same scope.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function closure_example (const i : int) : int is
|
||||
block {
|
||||
function closure (const j : int) : int is i + j
|
||||
} with closure (i)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let closure_example (i : int) : int =
|
||||
let closure : int -> int = fun (j : int) -> i + j in
|
||||
closure i
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
let closure_example = (i : int) : int => {
|
||||
let closure = (j: int): int => i + j;
|
||||
closure(i);
|
||||
};
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
## Recursive function
|
||||
|
||||
LIGO functions are not recursive by default, the user need to indicate that the function is recursive.
|
||||
|
@ -8,12 +8,16 @@ hide_table_of_contents: true
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
A lazily deserialized map that's intended to store large amounts of data.
|
||||
A lazily deserialized map that's intended to store large amounts of data.
|
||||
Lazily means that storage is read or written per key on demand. Therefore
|
||||
there are no `map`, `fold`, and `iter` operations as in
|
||||
[Map](./map-reference).
|
||||
|
||||
The gast costs of deserialized maps are higher than standard maps as data is lazily deserialized.
|
||||
The gast costs of big maps are higher than standard maps as data is lazily
|
||||
deserialized.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type big_map (key, value)
|
||||
type big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type ('key, 'value) big_map
|
||||
@ -45,24 +49,27 @@ type register = (address, move) big_map
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
The type of a big map from values of type `key` to
|
||||
values of type `value` is `big_map (key, value)`.
|
||||
values of type `value` is `big_map(key, value)`.
|
||||
|
||||
```reasonligo group=big_map
|
||||
type move = (int, int);
|
||||
type register = big_map (address, move);
|
||||
type register = big_map(address, move);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
Be aware that a `big_map` cannot appear inside another `big_map`.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function empty : big_map (key, value)
|
||||
function empty : big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val empty : ('key, 'value) big_map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let empty: big_map ('key, 'value)
|
||||
let empty: big_map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Create an empty big_map.
|
||||
@ -90,14 +97,14 @@ let empty : register = Big_map.empty
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=big_map
|
||||
let empty : register = Big_map.empty
|
||||
let empty: register = Big_map.empty
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function literal : list (key * value) -> big_map (key, value)
|
||||
function literal : list ('key * 'value) -> big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val literal : ('key * 'value) list -> ('key, 'value) big_map
|
||||
@ -140,7 +147,7 @@ let moves : register =
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=big_map
|
||||
let moves : register =
|
||||
let moves: register =
|
||||
Big_map.literal ([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
|
||||
@ -149,13 +156,13 @@ let moves : register =
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function find_opt : key -> big_map (key, value) -> option value
|
||||
function find_opt : 'key -> big_map ('key, 'value) -> option 'value
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val find_opt : 'key -> ('key, 'value) big_map -> 'value option
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let find_opt : ('key, big_map ('key, 'value)) => option ('value)
|
||||
let find_opt: ('key, big_map ('key, 'value)) => option ('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Retrieve a value from a big map with the given key.
|
||||
@ -190,20 +197,20 @@ let my_balance : move option =
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=big_map
|
||||
let my_balance : option (move) =
|
||||
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
|
||||
let my_balance: option (move) =
|
||||
Big_map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function update : key -> option value -> big_map (key, value) -> big_map (key, value)
|
||||
function update : 'key -> option 'value -> big_map ('key, 'value) -> big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val update: 'key -> 'value option -> ('key, 'value) big_map -> ('key, 'value) big_map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let update: ('key, option('value), big_map ('key, 'value)) => big_map ('key, 'value)
|
||||
let update: ('key, option('value), big_map('key, 'value)) => big_map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Note: when `None` is used as a value, the value is removed from the big_map.
|
||||
@ -254,15 +261,15 @@ let updated_map : register =
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=big_map
|
||||
let updated_map : register =
|
||||
let updated_map: register =
|
||||
Big_map.update
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function add : key -> value -> big_map (key, value) -> big_map (key, value)
|
||||
function add : 'key -> 'value -> big_map ('key, 'value) -> big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val add : 'key -> 'value -> ('key, 'value) big_map -> ('key, 'value) big_map
|
||||
@ -291,20 +298,20 @@ let add (m : register) : register =
|
||||
```reasonligo group=big_map
|
||||
let add = (m: register): register =>
|
||||
Big_map.add
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (4,9), m);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function remove: key -> big_map (key, value) -> big_map (key, value)
|
||||
function remove: 'key -> big_map ('key, 'value) -> big_map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val remove: 'key -> ('key, 'value) big_map -> ('key, 'value) big_map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let remove: (key, big_map ('key, 'value)) => big_map ('key, 'value)
|
||||
let remove: ('key, big_map('key, 'value)) => big_map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -339,8 +346,8 @@ let updated_map : register =
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=big_map
|
||||
let updated_map : register =
|
||||
Big_map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
|
||||
let updated_map: register =
|
||||
Big_map.remove(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
69
gitlab-pages/docs/reference/bitwise.md
Normal file
69
gitlab-pages/docs/reference/bitwise.md
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
id: bitwise-reference
|
||||
title: Bitwise
|
||||
description: Operations on bytes
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function and : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val and : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let and: (nat, nat) -> nat
|
||||
</SyntaxTitle>
|
||||
|
||||
A bitwise `and` operation.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function or : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val or : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let or: (nat, nat) -> nat
|
||||
</SyntaxTitle>
|
||||
|
||||
A bitwise `or` operation.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function xor : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val xor : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let xor: (nat, nat) -> nat
|
||||
</SyntaxTitle>
|
||||
|
||||
A bitwise `xor` operation.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function shift_left : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val shift_left : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let shift_left: (nat, nat) -> nat
|
||||
</SyntaxTitle>
|
||||
|
||||
A bitwise shift left operation.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function shift_right : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val shift_right : nat -> nat -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let shift_right: (nat, nat) -> nat
|
||||
</SyntaxTitle>
|
||||
|
||||
A bitwise shift right operation.
|
@ -1,21 +1,43 @@
|
||||
---
|
||||
id: bytes-reference
|
||||
title: Bytes — Manipulate bytes data
|
||||
title: Bytes
|
||||
description: Operations on bytes
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
## Bytes.concat(b1: bytes, b2: bytes) : bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function concat : bytes -> bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val concat : bytes -> bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let concat: (bytes, bytes) => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Concatenate together two `bytes` arguments and return the result.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function concat_op (const s : bytes) : bytes is
|
||||
begin skip end with bytes_concat(s , 0x7070)
|
||||
function concat_op (const s : bytes) : bytes is Bytes.concat(s , 0x7070)
|
||||
```
|
||||
|
||||
> Note that `bytes_concat` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -33,41 +55,58 @@ let concat_op = (s: bytes): bytes => Bytes.concat(s, 0x7070);
|
||||
|
||||
</Syntax>
|
||||
|
||||
## Bytes.slice(pos1: nat, pos2: nat, data: bytes) : bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function sub : nat -> nat -> bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val sub : nat -> nat -> bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let sub : (nat, nat, bytes) => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Extract the bytes between `pos1` and `pos2`. **Positions are zero indexed and
|
||||
inclusive**. For example if you gave the input "ff7a7aff" to the following:
|
||||
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function slice_op (const s : bytes) : bytes is
|
||||
begin skip end with bytes_slice(1n , 2n , s)
|
||||
function slice_op (const s : bytes) : bytes is Bytes.sub(1n , 2n , s)
|
||||
```
|
||||
|
||||
> Note that `bytes_slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let slice_op (s : bytes) : bytes =
|
||||
Bytes.slice 1n 2n s
|
||||
let slice_op (s : bytes) : bytes = Bytes.sub 1n 2n s
|
||||
```
|
||||
|
||||
> Note that `Bytes.slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```
|
||||
let slice_op = (s: bytes): bytes => Bytes.slice(1n, 2n, s);
|
||||
let slice_op = (s: bytes): bytes => Bytes.sub(1n, 2n, s);
|
||||
```
|
||||
|
||||
> Note that `Bytes.slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
It would return "7a7a" rather than "ff7a" or "ff" or "7a".
|
||||
|
||||
## Bytes.pack(data: a') : bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function pack : 'a -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val pack : 'a -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let pack : 'a => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Converts Michelson data structures to a binary format for serialization.
|
||||
|
||||
@ -105,10 +144,19 @@ let id_string = (p: string) : option(string) => {
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Bytes.unpack(packed: bytes) : a'
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function unpack : bytes -> option 'a
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val unpack : bytes -> 'a option
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let unpack: bytes => option('a)
|
||||
</SyntaxTitle>
|
||||
|
||||
Reverses the result of using `unpack` on data, going from Michelson's binary
|
||||
serialization format to the `option` type annotated on the call.
|
||||
Reverses the result of using `pack` on data.
|
||||
|
||||
As the conversion might fail an option type is returned.
|
||||
|
||||
> ⚠️ `PACK` and `UNPACK` are features of Michelson that are intended to be used by people that really know what they're doing. There are several failure cases (such as `UNPACK`ing a lambda from an untrusted source), most of which are beyond the scope of this document. Don't use these functions without doing your homework first.
|
||||
|
||||
@ -143,3 +191,12 @@ let id_string = (p: string) : option(string) => {
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function length : bytes -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val length : bytes -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let length: bytes => nat
|
||||
</SyntaxTitle>
|
||||
|
@ -1,11 +1,58 @@
|
||||
---
|
||||
id: crypto-reference
|
||||
title: Crypto — Cryptographic functions
|
||||
title: Crypto
|
||||
description: Cryptographic operations
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
## Crypto.blake2b(data: bytes): bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type key
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type key
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type key
|
||||
</SyntaxTitle>
|
||||
|
||||
A public cryptographic key.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type key_hash
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type key_hash
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type key_hash
|
||||
</SyntaxTitle>
|
||||
|
||||
The hash of a public cryptographic key.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type signature
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type signature
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type signature
|
||||
</SyntaxTitle>
|
||||
|
||||
A cryptographic signature.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function blake2b : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val blake2b : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let blake2b: bytes => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Runs the [blake2b hash algorithm](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2)
|
||||
over the given `bytes` data and returns a `bytes` representing the hash.
|
||||
@ -15,9 +62,11 @@ over the given `bytes` data and returns a `bytes` representing the hash.
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function hasherman_blake (const s: bytes) : bytes is blake2b(s)
|
||||
function hasherman_blake (const s: bytes) : bytes is Crypto.blake2b(s)
|
||||
```
|
||||
|
||||
> Note that `blake2b` is *deprecated*. Please use `Crypto.blake2b`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -25,6 +74,8 @@ function hasherman_blake (const s: bytes) : bytes is blake2b(s)
|
||||
let hasherman_blake (s: bytes) : bytes = Crypto.blake2b s
|
||||
```
|
||||
|
||||
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
@ -34,8 +85,15 @@ let hasherman_blake = (s: bytes) => Crypto.blake2b(s);
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Crypto.sha256(data: bytes) : bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function sha256 : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val sha256 : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let sha256: bytes => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Runs the [sha256 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the given
|
||||
`bytes` data and returns a `bytes` representing the hash.
|
||||
@ -45,10 +103,11 @@ Runs the [sha256 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the g
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function hasherman (const s : bytes) : bytes is
|
||||
begin skip end with sha_256(s)
|
||||
function hasherman (const s : bytes) : bytes is Crypto.sha256(s)
|
||||
```
|
||||
|
||||
> Note that `sha_256` is *deprecated*. Please use `Crypto.sha256`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -66,8 +125,15 @@ let hasherman = (s: bytes): bytes => Crypto.sha256(s);
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Crypto.sha512(data: bytes) : bytes
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function sha512 : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val sha512 : bytes -> bytes
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let sha512: bytes => bytes
|
||||
</SyntaxTitle>
|
||||
|
||||
Runs the [sha512 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the given
|
||||
`bytes` data and returns a `bytes` representing the hash.
|
||||
@ -77,9 +143,11 @@ Runs the [sha512 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the g
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function hasherman512 (const s: bytes) : bytes is sha_512(s)
|
||||
function hasherman512 (const s: bytes) : bytes is Crypto.sha512(s)
|
||||
```
|
||||
|
||||
> Note that `sha_512` is *deprecated*. Please use `Crypto.sha512`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -96,8 +164,15 @@ let hasherman512 = (s: bytes) => Crypto.sha512(s);
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Crypto.hash_key(k: key) : key_hash
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function hash_key : key -> key_hash
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val hash_key : key -> key_hash
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let hash_key: key => key_hash
|
||||
</SyntaxTitle>
|
||||
|
||||
Hashes a key for easy comparison and storage.
|
||||
|
||||
@ -108,11 +183,13 @@ Hashes a key for easy comparison and storage.
|
||||
```pascaligo
|
||||
function check_hash_key (const kh1 : key_hash; const k2 : key) : bool * key_hash is block {
|
||||
var ret : bool := False ;
|
||||
var kh2 : key_hash := crypto_hash_key(k2) ;
|
||||
var kh2 : key_hash := Crypto.hash_key(k2) ;
|
||||
if kh1 = kh2 then ret := True else skip;
|
||||
} with (ret, kh2)
|
||||
```
|
||||
|
||||
> Note that `hash_key` is *deprecated*. Please use `Crypto.hash_key`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -141,8 +218,15 @@ let check_hash_key = ((kh1, k2): (key_hash, key)) : (bool, key_hash) => {
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Crypto.check(pk: key, signed: signature, data: bytes) : bool
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function check : key -> signature -> bytes -> bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val check : key -> signature -> bytes -> bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let check: (key, signature, bytes) => bool
|
||||
</SyntaxTitle>
|
||||
|
||||
Check that a message has been signed by a particular key.
|
||||
|
||||
@ -157,9 +241,11 @@ function check_signature
|
||||
(const pk: key;
|
||||
const signed: signature;
|
||||
const msg: bytes) : bool
|
||||
is crypto_check(pk, signed, msg)
|
||||
is Crypto.check(pk, signed, msg)
|
||||
```
|
||||
|
||||
> Note that `crypto_check` is *deprecated*. Please use `Crypto.check`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
|
@ -1,11 +1,96 @@
|
||||
---
|
||||
id: current-reference
|
||||
title: Tezos - Things relating to the current execution context
|
||||
title: Tezos
|
||||
description: General operations for Tezos
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
# Tezos.balance
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type timestamp
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type timestamp
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type timestamp
|
||||
</SyntaxTitle>
|
||||
|
||||
A date in the real world.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type mutez
|
||||
</SyntaxTitle>
|
||||
|
||||
A specific type for tokens.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type address
|
||||
</SyntaxTitle>
|
||||
|
||||
An untyped address which can refer to a smart contract or account.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type contract('parameter)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type 'parameter contract
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type contract('parameter)
|
||||
</SyntaxTitle>
|
||||
|
||||
A typed contract.
|
||||
|
||||
Use `unit` as `parameter` to indicate an implicit account.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type operation
|
||||
</SyntaxTitle>
|
||||
|
||||
An operation emitted by the contract
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type chain_id
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type chain_id
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type chain_id
|
||||
</SyntaxTitle>
|
||||
|
||||
The identifier of a chain, used to indicate test or main chains.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function balance : mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val balance : mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let balance: mutez
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the balance for the contract.
|
||||
|
||||
@ -18,7 +103,7 @@ function main (const p : unit; const s: tez) : list (operation) * tez is
|
||||
((nil : list (operation)), Tezos.balance)
|
||||
```
|
||||
|
||||
> Note that `balance` and `Current.balance` are *deprecated*.
|
||||
> Note that `balance` and `Current.balance` are *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -42,7 +127,15 @@ let main = ((p,s) : (unit, tez)) =>
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Tezos.now
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function now : timestamp
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val now : timestamp
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let now: timestamp
|
||||
</SyntaxTitle>
|
||||
|
||||
Returns the current time as a [unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
|
||||
|
||||
@ -64,7 +157,7 @@ const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp);
|
||||
const one_day_later: timestamp = some_date + one_day;
|
||||
```
|
||||
|
||||
> Note that `now` is *deprecated*.
|
||||
> Note that `now` is *deprecated*. Please use `Tezos.now`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -106,7 +199,7 @@ const one_day: int = 86_400;
|
||||
const in_24_hrs: timestamp = today - one_day;
|
||||
```
|
||||
|
||||
> Note that `now` is *deprecated*.
|
||||
> Note that `now` is *deprecated*. Please use `Tezos.now`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -145,7 +238,7 @@ for numbers
|
||||
const not_tommorow: bool = (Tezos.now = in_24_hrs)
|
||||
```
|
||||
|
||||
> Note that `now` is *deprecated*.
|
||||
> Note that `now` is *deprecated*. Please use `Tezos.now`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -169,7 +262,15 @@ let not_tomorrow: bool = (Tezos.now == in_24_hrs);
|
||||
|
||||
|
||||
|
||||
## Amount
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function amount : mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val amount : mutez
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let amount: mutez
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the amount of tez provided by the sender to complete this
|
||||
transaction.
|
||||
@ -207,7 +308,15 @@ let threshold = (p : unit) : int =>
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Sender
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function sender : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val sender : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let sender: address
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the address that initiated the current transaction.
|
||||
|
||||
@ -219,7 +328,7 @@ Get the address that initiated the current transaction.
|
||||
function main (const p : unit) : address is Tezos.sender
|
||||
```
|
||||
|
||||
> Note that `sender` is *deprecated*.
|
||||
> Note that `sender` is *deprecated*. Please use `Tezos.sender`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -243,7 +352,15 @@ let main = (p : unit) : address => Tezos.sender;
|
||||
|
||||
|
||||
|
||||
## Address
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function address : contract 'a -> address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val address : 'a contract -> address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let address: contract('a) => address
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the address associated with a value of type `contract`.
|
||||
|
||||
@ -257,7 +374,7 @@ function main (const p : key_hash) : address is block {
|
||||
} with Tezos.address(c)
|
||||
```
|
||||
|
||||
> Note that `implicit_account` and `address` are *deprecated*.
|
||||
> Note that `implicit_account` and `address` are *deprecated*. Please use `Tezos.implicit_account` and `Tezos.address` instead.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -287,7 +404,15 @@ let main = (p : key_hash) : address => {
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Self Address
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function self_address : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val self_address : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let self_address: address
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the address of the currently running contract.
|
||||
|
||||
@ -299,7 +424,7 @@ Get the address of the currently running contract.
|
||||
function main (const p : unit) : address is Tezos.self_address
|
||||
```
|
||||
|
||||
> Note that `self_address` is *deprecated*.
|
||||
> Note that `self_address` is *deprecated*. Please use `Tezos.self_address`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -320,8 +445,15 @@ let main = (p : unit) : address => Tezos.self_address;
|
||||
> Note that `Current.self_address` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
|
||||
## Self
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function self : string -> contract 'a
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val self : string -> 'a contract
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let self: string => contract('a)
|
||||
</SyntaxTitle>
|
||||
|
||||
Typecast the currently running contract with an entrypoint annotation.
|
||||
If your are using entrypoints: use "%bar" for constructor Bar
|
||||
@ -353,13 +485,21 @@ let main = (p: unit) : contract(unit) =>
|
||||
|
||||
</Syntax>
|
||||
|
||||
## Implicit Account
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function implicit_account : key_hash -> contract 'a
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val implicit_account : key_hash -> 'a contract
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let implicit_account: key_hash => contract('a)
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the default contract associated with an on-chain key-pair. This
|
||||
contract does not execute code, instead it exists to receive tokens on
|
||||
behalf of a key's owner.
|
||||
|
||||
|
||||
See also: http://tezos.gitlab.io/user/glossary.html#implicit-account
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
@ -368,7 +508,7 @@ function main (const kh: key_hash) : contract (unit) is
|
||||
Tezos.implicit_account (kh)
|
||||
```
|
||||
|
||||
> Note that `implicit_account` is *deprecated*.
|
||||
> Note that `implicit_account` is *deprecated*. Please use `Tezos.implicit_account`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -392,7 +532,15 @@ let main = (kh : key_hash): contract (unit) =>
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Source
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function source : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val source : address
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let source: address
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the _originator_ (address) of the current transaction. That is, if
|
||||
a chain of transactions led to the current execution get the address
|
||||
@ -426,7 +574,7 @@ current transaction.
|
||||
function main (const p: unit) : address is Tezos.source
|
||||
```
|
||||
|
||||
> Note that `source` is *deprecated*.
|
||||
> Note that `source` is *deprecated*. Please use `Tezos.source`.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -449,7 +597,15 @@ let main = (p : unit) : address => Tezos.source;
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Failwith
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function failwith : string -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
function failwith : string -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
function failwith : string -> unit
|
||||
</SyntaxTitle>
|
||||
|
||||
Cause the contract to fail with an error message.
|
||||
|
||||
@ -485,3 +641,125 @@ let main = ((p,s) : (int, unit)) =>
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function chain_id : chain_id
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val chain_id : chain_id
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let chain_id: chain_id
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the identifier of the chain to distinguish between main and test chains.
|
||||
|
||||
This is mainly intended to avoid replay attacks between the chains, and can currently
|
||||
only be used together with `Bytes.pack` and `Bytes.unpack`.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
type storage is bytes
|
||||
|
||||
function main (const ignore : unit; const storage: storage) :
|
||||
(list(operation) * storage) is block {
|
||||
const packed : bytes = Bytes.pack (Tezos.chain_id);
|
||||
if (storage =/= packed) then {
|
||||
failwith("wrong chain")
|
||||
} else
|
||||
skip;
|
||||
} with ((nil: list(operation)), packed)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
type storage = bytes
|
||||
|
||||
let main ((ignore, storage): (unit * storage)) =
|
||||
let packed = Bytes.pack Tezos.chain_id in
|
||||
if (storage <> packed) then
|
||||
(failwith "wrong chain" : (operation list * storage))
|
||||
else
|
||||
(([]: operation list), (packed: storage))
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
type storage = bytes;
|
||||
|
||||
let main = ((ignore, storage): (unit, storage)) => {
|
||||
let packed = Bytes.pack(Tezos.chain_id);
|
||||
if (storage != packed) {
|
||||
(failwith("wrong chain"): (list(operation), storage));
|
||||
} else {
|
||||
([]: list(operation), packed);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function transaction : 'parameter -> mutez -> contract('parameter) -> operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val transaction : 'parameter -> mutez -> 'parameter contract -> operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let transaction: 'parameter -> mutez -> contract('parameter) -> operation
|
||||
</SyntaxTitle>
|
||||
|
||||
Create a transaction to a contract or account.
|
||||
|
||||
To indicate an account, use `unit` as `parameter`.
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function set_delegate : option(key_hash) -> operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val set_delegate : key_hash option -> operation
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let set_delegate: option(key_hash) => operation
|
||||
</SyntaxTitle>
|
||||
|
||||
Create a delegation.
|
||||
|
||||
See also: http://tezos.gitlab.io/user/glossary.html?highlight=delegate#delegate
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function get_contract_opt : address -> option(contract('parameter))
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val get_contract_opt : address -> 'parameter contract option
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let get_contract_opt : address => option(contract('parameter))
|
||||
</SyntaxTitle>
|
||||
|
||||
Get a contract from an address.
|
||||
|
||||
When no contract is found or the contract doesn't match the type,
|
||||
`None` is returned.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function get_entrypoint_opt : string -> address -> option(contract('parameter))
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
function get_entrypoint_opt : string -> address -> 'parameter contract option
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
function get_entrypoint_opt: (string, address) => option(contract('parameter))
|
||||
</SyntaxTitle>
|
||||
|
||||
Get a contract from an address and entrypoint.
|
||||
|
||||
Entrypoints are written in the form of: `%entrypoint`.
|
||||
|
||||
When no contract is found or the contract doesn't match the type,
|
||||
`None` is returned.
|
||||
|
@ -1,96 +1,62 @@
|
||||
---
|
||||
id: list-reference
|
||||
title: Lists — Linear Collections
|
||||
title: List
|
||||
description: List operations
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
Lists are linear collections of elements of the same type. Linear
|
||||
means that, in order to reach an element in a list, we must visit all
|
||||
the elements before (sequential access). Elements can be repeated, as
|
||||
only their order in the collection matters. The first element is
|
||||
called the *head*, and the sub-list after the head is called the
|
||||
*tail*. For those familiar with algorithmic data structure, you can
|
||||
think of a list a *stack*, where the top is written on the left.
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type list ('t)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type 't list
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type list('t)
|
||||
</SyntaxTitle>
|
||||
|
||||
# Defining Lists
|
||||
A sequence of elements of the same type.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function length : nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val length : nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let length: nat
|
||||
</SyntaxTitle>
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
Get the number of elements in a list.
|
||||
|
||||
```pascaligo group=lists
|
||||
const empty_list : list (int) = nil // Or list []
|
||||
const my_list : list (int) = list [1; 2; 2] // The head is 1
|
||||
```
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function size : nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val size : nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let size: nat
|
||||
</SyntaxTitle>
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
Get the number of elements in a list.
|
||||
|
||||
```cameligo group=lists
|
||||
let empty_list : int list = []
|
||||
let my_list : int list = [1; 2; 2] // The head is 1
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=lists
|
||||
let empty_list : list (int) = [];
|
||||
let my_list : list (int) = [1, 2, 2]; // The head is 1
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
# Adding to Lists
|
||||
|
||||
Lists can be augmented by adding an element before the head (or, in
|
||||
terms of stack, by *pushing an element on top*).
|
||||
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=lists
|
||||
const larger_list : list (int) = 5 # my_list // [5;1;2;2]
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=lists
|
||||
let larger_list : int list = 5 :: my_list // [5;1;2;2]
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=lists
|
||||
let larger_list : list (int) = [5, ...my_list]; // [5,1,2,2]
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
|
||||
# Functional Iteration over Lists
|
||||
|
||||
A *functional iterator* is a function that traverses a data structure
|
||||
and calls in turn a given function over the elements of that structure
|
||||
to compute some value. Another approach is possible in PascaLIGO:
|
||||
*loops* (see the relevant section).
|
||||
|
||||
There are three kinds of functional iterations over LIGO lists: the
|
||||
*iterated operation*, the *map operation* (not to be confused with the
|
||||
*map data structure*) and the *fold operation*.
|
||||
|
||||
## Iterated Operation over Lists
|
||||
|
||||
The first, the *iterated operation*, is an iteration over the list
|
||||
with a unit return value. It is useful to enforce certain invariants
|
||||
on the element of a list, or fail.
|
||||
Synonym for `List.length`.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function iter : ('a -> unit) -> list('a) -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val iter : ('a -> unit) -> 'a list -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let iter: (('a => unit), list('a)) => unit
|
||||
</SyntaxTitle>
|
||||
|
||||
Iterate over items in a list.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
@ -104,6 +70,8 @@ function iter_op (const l : list (int)) : unit is
|
||||
|
||||
> Note that `list_iter` is *deprecated*.
|
||||
|
||||
Alternatively it's also possible to use [loops](../language-basics/loops.md).
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -126,17 +94,23 @@ let iter_op = (l : list (int)) : unit => {
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Mapped Operation over Lists
|
||||
|
||||
We may want to change all the elements of a given list by applying to
|
||||
them a function. This is called a *map operation*, not to be confused
|
||||
with the map data structure.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function map : ('a -> 'b) -> list('a) -> list('b)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val map : ('a -> 'b) -> 'a list -> 'b list
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let map: (('a => 'b), list('a)) => list('b)
|
||||
</SyntaxTitle>
|
||||
|
||||
Apply a function to items of a list to create a new list.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=lists
|
||||
const larger_list: list(int) = list [1; 2; 3]
|
||||
|
||||
function increment (const i : int): int is i + 1
|
||||
|
||||
// Creates a new list with all elements incremented by 1
|
||||
@ -149,6 +123,8 @@ const plus_one : list (int) = List.map (increment, larger_list)
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=lists
|
||||
let larger_list: int list = [1; 2; 3]
|
||||
|
||||
let increment (i : int) : int = i + 1
|
||||
|
||||
// Creates a new list with all elements incremented by 1
|
||||
@ -159,6 +135,8 @@ let plus_one : int list = List.map increment larger_list
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=lists
|
||||
let larger_list: list(int) = [1, 2, 3];
|
||||
|
||||
let increment = (i : int) : int => i + 1;
|
||||
|
||||
// Creates a new list with all elements incremented by 1
|
||||
@ -167,22 +145,25 @@ let plus_one : list (int) = List.map (increment, larger_list);
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function fold : (('accumulator -> 'item -> 'accumulator) -> list('item) -> 'accumulator) -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val fold : ('accumulator -> 'item -> 'accumulator) -> 'item list -> 'accumulator -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let fold: ((('accumulator, 'item) => 'accumulator), list('item), 'accumulator) => 'accumulator
|
||||
</SyntaxTitle>
|
||||
|
||||
|
||||
## Folded Operation over Lists
|
||||
|
||||
A *folded operation* is the most general of iterations. The folded
|
||||
function takes two arguments: an *accumulator* and the structure
|
||||
*element* at hand, with which it then produces a new accumulator. This
|
||||
enables having a partial result that becomes complete when the
|
||||
traversal of the data structure is over.
|
||||
|
||||
|
||||
[Fold over items in a list](../language-basics/sets-lists-tuples#folded-operation-over-lists);
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=lists
|
||||
const my_list: list(int) = list [1; 2; 3]
|
||||
|
||||
function sum (const acc : int; const i : int): int is acc + i
|
||||
|
||||
const sum_of_elements : int = List.fold (sum, my_list, 0)
|
||||
```
|
||||
|
||||
@ -192,7 +173,10 @@ const sum_of_elements : int = List.fold (sum, my_list, 0)
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=lists
|
||||
let sum (acc, i: int * int) : int = acc + i
|
||||
let my_list : int list = [1; 2; 3]
|
||||
|
||||
let sum (acc, i : int * int) : int = acc + i
|
||||
|
||||
let sum_of_elements : int = List.fold sum my_list 0
|
||||
```
|
||||
|
||||
@ -200,40 +184,11 @@ let sum_of_elements : int = List.fold sum my_list 0
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=lists
|
||||
let my_list : list(int) = [1, 2, 3];
|
||||
|
||||
let sum = ((result, i): (int, int)): int => result + i;
|
||||
|
||||
let sum_of_elements : int = List.fold (sum, my_list, 0);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
# List Length
|
||||
|
||||
Get the number of elements in a list.
|
||||
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function size_of (const l : list (int)) : nat is List.length (l)
|
||||
```
|
||||
|
||||
> Note that `size` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let size_of (l : int list) : nat = List.length l
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
let size_of = (l : list (int)) : nat => List.length (l);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
@ -1,22 +1,28 @@
|
||||
---
|
||||
id: map-reference
|
||||
title: Maps
|
||||
title: Map
|
||||
description: Map operations
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
*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.
|
||||
|
||||
# Declaring a Map
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
The type of a map from values of type `key` to
|
||||
values of type `value` is `map (key, value)`.
|
||||
|
||||
```pascaligo group=maps
|
||||
type move is int * int
|
||||
type register is map (address, move)
|
||||
@ -25,6 +31,9 @@ type register is map (address, move)
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
The type of a map from values of type `key` to values
|
||||
of type `value` is `(key, value) map`.
|
||||
|
||||
```cameligo group=maps
|
||||
type move = int * int
|
||||
type register = (address, move) map
|
||||
@ -33,6 +42,9 @@ type register = (address, move) map
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
The type of a map from values of type `key` to
|
||||
values of type `value` is `map (key, value)`.
|
||||
|
||||
```reasonligo group=maps
|
||||
type move = (int, int);
|
||||
type register = map (address, move);
|
||||
@ -40,13 +52,26 @@ type register = map (address, move);
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function empty : map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val empty : ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let empty: map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
# Creating an Empty Map
|
||||
|
||||
|
||||
Create an empty map.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
const empty : register = Map.empty
|
||||
```
|
||||
|
||||
Or
|
||||
|
||||
```pascaligo group=maps
|
||||
const empty : register = map []
|
||||
```
|
||||
@ -68,16 +93,34 @@ let empty : register = Map.empty
|
||||
</Syntax>
|
||||
|
||||
|
||||
# Creating a Non-empty Map
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function literal : list ('key * 'value) -> map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val literal : ('key * 'value) list -> ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let literal: list(('key, 'value)) => map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Create a non-empty map.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
const moves : register =
|
||||
Map.literal (list [
|
||||
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]);
|
||||
```
|
||||
|
||||
Alternative way of creating an empty map:
|
||||
|
||||
```pascaligo group=maps
|
||||
const moves_alternative : register =
|
||||
map [
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)];
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
@ -103,14 +146,32 @@ let moves : register =
|
||||
</Syntax>
|
||||
|
||||
|
||||
# Accessing Map Bindings
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function find_opt : 'key -> map ('key, 'value) -> option 'value
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val find_opt : 'key -> ('key, 'value) map -> 'value option
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let find_opt : ('key, map ('key, 'value)) => option ('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Retrieve a (option) value from a map with the given key. Returns `None` if the
|
||||
key is missing and the value otherwise.
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
const my_balance : option (move) =
|
||||
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
|
||||
Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves)
|
||||
```
|
||||
|
||||
Alternatively:
|
||||
|
||||
```pascaligo group=maps
|
||||
const my_balance_alternative : option (move) =
|
||||
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)];
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
@ -126,67 +187,40 @@ let my_balance : move option =
|
||||
|
||||
```reasonligo group=maps
|
||||
let my_balance : option (move) =
|
||||
Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves);
|
||||
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
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*.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function update : 'key -> option 'value -> map ('key, 'value) -> map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val update: 'key -> 'value option -> ('key, 'value) map -> ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let update: ('key, option('value), map('key, 'value)) => map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Note: when `None` is used as a value, the key and associated value is removed
|
||||
from the map.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
function force_access (const key : address; const moves : register) : move is
|
||||
case moves[key] of
|
||||
Some (move) -> move
|
||||
| None -> (failwith ("No move.") : move)
|
||||
end
|
||||
const updated_map : register = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some (4,9), moves);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=maps
|
||||
let force_access (key, moves : address * register) : move =
|
||||
match Map.find_opt key moves with
|
||||
Some move -> move
|
||||
| None -> (failwith "No move." : move)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=maps
|
||||
let force_access = ((key, moves) : (address, register)) : move => {
|
||||
switch (Map.find_opt (key, moves)) {
|
||||
| Some (move) => move
|
||||
| None => failwith ("No move.") : move
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
# 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. All
|
||||
those operations are called *updates*.
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
Alternatively:
|
||||
|
||||
```pascaligo group=maps
|
||||
function assign (var m : register) : register is
|
||||
|
||||
function update (var m : register) : register is
|
||||
block {
|
||||
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
|
||||
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9);
|
||||
} with m
|
||||
|
||||
```
|
||||
|
||||
If multiple bindings need to be updated, PascaLIGO offers a *patch
|
||||
@ -206,14 +240,40 @@ function assignments (var m : register) : register is
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=maps
|
||||
let assign (m : register) : register =
|
||||
let updated_map : register =
|
||||
Map.update
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
|
||||
```
|
||||
Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had
|
||||
use `None` instead, that would have meant that the binding is removed.
|
||||
|
||||
As a particular case, we can only add a key and its associated value.
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=maps
|
||||
let updated_map : register =
|
||||
Map.update
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function add : 'key -> 'value -> map ('key, 'value) -> map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val add : 'key -> 'value -> ('key, 'value) map -> ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let add: ('key, 'value, map('key, 'value)) => map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
const added_item : register = Map.add (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4, 9), moves)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=maps
|
||||
let add (m : register) : register =
|
||||
@ -225,18 +285,7 @@ let add (m : register) : register =
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=maps
|
||||
let assign = (m : register) : register =>
|
||||
Map.update
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m);
|
||||
```
|
||||
|
||||
Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had
|
||||
use `None` instead, that would have meant that the binding is removed.
|
||||
|
||||
As a particular case, we can only add a key and its associated value.
|
||||
|
||||
```reasonligo group=maps
|
||||
let add = (m : register) : register =>
|
||||
let add = (m: register): register =>
|
||||
Map.add
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
|
||||
```
|
||||
@ -244,57 +293,63 @@ let add = (m : register) : register =>
|
||||
</Syntax>
|
||||
|
||||
|
||||
To remove a binding from a map, we need its key.
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function remove : 'key -> map ('key, 'value) -> map ('key, 'value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val remove : 'key -> ('key, 'value) map -> ('key, 'value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let remove: (key, map('key, 'value)) => map('key, 'value)
|
||||
</SyntaxTitle>
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=maps
|
||||
function delete (const key : address; var moves : register) : register is
|
||||
const updated_map : register =
|
||||
Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
|
||||
```
|
||||
|
||||
Alternatively, the instruction `remove key from map m` removes the key
|
||||
`key` from the map `m`.
|
||||
|
||||
```pascaligo group=maps
|
||||
function rem (var m : register) : register is
|
||||
block {
|
||||
remove key from map moves
|
||||
} with moves
|
||||
remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves
|
||||
} with m
|
||||
|
||||
const updated_map : register = rem (moves)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=maps
|
||||
let delete (key, moves : address * register) : register =
|
||||
Map.remove key moves
|
||||
let updated_map : register =
|
||||
Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=maps
|
||||
let delete = ((key, moves) : (address, register)) : register =>
|
||||
Map.remove (key, moves);
|
||||
let updated_map : register =
|
||||
Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
|
||||
# Functional Iteration over Maps
|
||||
|
||||
A *functional iterator* is a function that traverses a data structure
|
||||
and calls in turn a given function over the elements of that structure
|
||||
to compute some value. Another approach is possible in PascaLIGO:
|
||||
*loops* (see the relevant section).
|
||||
|
||||
There are three kinds of functional iterations over LIGO maps: the
|
||||
*iterated operation*, the *map operation* (not to be confused with the
|
||||
*map data structure*) and the *fold operation*.
|
||||
|
||||
## Iterated Operation over Maps
|
||||
|
||||
The first, the *iterated operation*, is an iteration over the map with
|
||||
no return value: its only use is to produce 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, and fail with an error otherwise.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function iter : ((key, value) -> unit) -> map (key, value) -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val iter : (('key * 'value) -> unit) -> ('key, 'value) map -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let iter: ((('key, 'value)) => unit, map('key, 'value)) => unit
|
||||
</SyntaxTitle>
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -330,14 +385,15 @@ let iter_op = (m : register) : unit => {
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Map Operations over Maps
|
||||
|
||||
We may want to change all the bindings of a map by applying to them a
|
||||
function. This is called a *map operation*, not to be confused with
|
||||
the map data structure. The predefined functional iterator
|
||||
implementing the map operation over maps is called `Map.map`.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function map : (('key, 'value) -> ('mapped_key, 'mapped_item)) -> map ('key, 'value) -> map ('mapped_key, 'mapped_value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val map : (('key * 'value) -> ('mapped_key * 'mapped_item)) -> (key, value) map -> (mapped_key, mapped_value) map
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let map: ((('key, 'value)) => ('mapped_key, 'mapped_item), map(key, value)) => map(mapped_key, mapped_value)
|
||||
</SyntaxTitle>
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -374,14 +430,15 @@ let map_op = (m : register) : register => {
|
||||
</Syntax>
|
||||
|
||||
|
||||
## Folded Operations over Maps
|
||||
|
||||
A *folded operation* is the most general of iterations. The folded
|
||||
function takes two arguments: an *accumulator* and the structure
|
||||
*element* at hand, with which it then produces a new accumulator. This
|
||||
enables having a partial result that becomes complete when the
|
||||
traversal of the data structure is over.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function fold : (('accumulator -> ('key, 'value) -> 'accumulator) -> map ('key, 'value) -> 'accumulator) -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val fold : ('accumulator -> ('key * 'value) -> 'accumulator) -> ('key, 'value) map -> 'accumulator -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let fold: ((('accumulator, ('key, 'value)) => 'accumulator), map('key, 'value), 'accumulator) => 'accumulator
|
||||
</SyntaxTitle>
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -417,3 +474,28 @@ let fold_op = (m : register) : int => {
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function size : map ('key, 'value) -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val size : ('key, 'value) map -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let size: map('key, 'value) => nat
|
||||
</SyntaxTitle>
|
||||
|
||||
Returns the number of items in the map.
|
||||
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function mem : key -> map (key, value) -> bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val mem : 'key -> ('key, 'value) map => bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let mem : ('key, map('key, 'value)) => bool
|
||||
</SyntaxTitle>
|
||||
|
||||
Checks if a key exists in the map.
|
||||
|
||||
|
@ -1,20 +1,45 @@
|
||||
---
|
||||
id: set-reference
|
||||
title: Sets — Unordered unique collection of a type
|
||||
title: Set
|
||||
description: Set operations
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
Sets are unordered collections of values of the same type, like lists
|
||||
are ordered collections. Like the mathematical sets and lists, sets
|
||||
can be empty and, if not, elements of sets in LIGO are *unique*,
|
||||
whereas they can be repeated in a *list*.
|
||||
Sets are unordered collections of unique values of the same type.
|
||||
|
||||
# Empty Sets
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type set ('value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type 'value set
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type set('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function empty : set('value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val empty : 'value set
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let empty: set('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Create an empty set.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=sets
|
||||
const my_set : set (int) = Set.empty
|
||||
```
|
||||
|
||||
Alternative syntax:
|
||||
|
||||
```pascaligo group=sets
|
||||
const my_set : set (int) = set []
|
||||
```
|
||||
@ -35,12 +60,26 @@ let my_set : set (int) = Set.empty;
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function literal : list('value) -> set('value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val literal : 'value list -> 'value set
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let literal: list('value) => set('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
# Non-empty Sets
|
||||
|
||||
Create a non-empty set.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=sets
|
||||
const my_set : set (int) = Set.literal (list [3; 2; 2; 1])
|
||||
```
|
||||
|
||||
Or use the following syntax sugar:
|
||||
|
||||
```pascaligo group=sets
|
||||
const my_set : set (int) = set [3; 2; 2; 1]
|
||||
```
|
||||
@ -50,7 +89,7 @@ const my_set : set (int) = set [3; 2; 2; 1]
|
||||
|
||||
```cameligo group=sets
|
||||
let my_set : int set =
|
||||
Set.add 3 (Set.add 2 (Set.add 2 (Set.add 1 (Set.empty : int set))))
|
||||
Set.literal [3; 2; 2; 1]
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
@ -58,19 +97,33 @@ let my_set : int set =
|
||||
|
||||
```reasonligo group=sets
|
||||
let my_set : set (int) =
|
||||
Set.add (3, Set.add (2, Set.add (2, Set.add (1, Set.empty : set (int)))));
|
||||
Set.literal ([3, 2, 2, 1]);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function mem : 'value -> set('value) -> 'bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val mem : 'value -> 'value set -> bool
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let mem: ('value, set('value)) => bool
|
||||
</SyntaxTitle>
|
||||
|
||||
# Set Membership
|
||||
|
||||
Checks if a value exists in the set.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo group=sets
|
||||
const contains_3 : bool = my_set contains 3
|
||||
const contains_3 : bool = Set.mem(3, my_set)
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```pascaligo group=sets
|
||||
const contains_3_alt : bool = my_set contains 3
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
@ -89,12 +142,17 @@ let contains_3 : bool = Set.mem (3, my_set);
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function cardinal : set('value) -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val cardinal : 'value set -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let cardinal: set('value) => nat
|
||||
</SyntaxTitle>
|
||||
|
||||
# Cardinal of Sets
|
||||
|
||||
The predefined function `Set.size` returns the number of
|
||||
elements in a given set as follows.
|
||||
|
||||
Number of elements in a set.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
@ -102,7 +160,7 @@ elements in a given set as follows.
|
||||
const cardinal : nat = Set.size (my_set)
|
||||
```
|
||||
|
||||
> Note that `size` is *deprecated*.
|
||||
> Note that `size` is *deprecated*. Please use `Set.size`
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
@ -120,72 +178,41 @@ let cardinal : nat = Set.size (my_set);
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function add : 'value -> set('value) -> set('value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val add : 'value -> 'value set -> 'value set
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let add: ('value, set('value)) => set('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
# Updating Sets
|
||||
Add a value to a set.
|
||||
|
||||
There are two ways to update a set, that is to add or remove from it.
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function remove : 'value -> set('value) -> set('value)
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val remove : 'value -> 'value set -> 'value set
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let remove: ('value, set('value)) => set('value)
|
||||
</SyntaxTitle>
|
||||
|
||||
Remove a value from a set.
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function iter : ('a -> unit) -> set('a) -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val iter : ('a -> unit) -> 'a set -> unit
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let iter: (('a => unit), set('a)) => unit
|
||||
</SyntaxTitle>
|
||||
|
||||
In PascaLIGO, either we create a new set from the given one, or we
|
||||
modify it in-place. First, let us consider the former way:
|
||||
```pascaligo group=sets
|
||||
const larger_set : set (int) = Set.add (4, my_set)
|
||||
const smaller_set : set (int) = Set.remove (3, my_set)
|
||||
```
|
||||
|
||||
> Note that `set_add` and `set_remove` are *deprecated*.
|
||||
|
||||
If we are in a block, we can use an instruction to modify the set
|
||||
bound to a given variable. This is called a *patch*. It is only
|
||||
possible to add elements by means of a patch, not remove any: it is
|
||||
the union of two sets.
|
||||
|
||||
```pascaligo group=sets
|
||||
function update (var s : set (int)) : set (int) is block {
|
||||
patch s with set [4; 7]
|
||||
} with s
|
||||
|
||||
const new_set : set (int) = update (my_set)
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo group=sets
|
||||
let larger_set : int set = Set.add 4 my_set
|
||||
let smaller_set : int set = Set.remove 3 my_set
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo group=sets
|
||||
let larger_set : set (int) = Set.add (4, my_set);
|
||||
let smaller_set : set (int) = Set.remove (3, my_set);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
# Functional Iteration over Sets
|
||||
|
||||
A *functional iterator* is a function that traverses a data structure
|
||||
and calls in turn a given function over the elements of that structure
|
||||
to compute some value. Another approach is possible in PascaLIGO:
|
||||
*loops* (see the relevant section).
|
||||
|
||||
There are three kinds of functional iterations over LIGO maps: the
|
||||
*iterated operation*, the *mapped operation* (not to be confused with
|
||||
the *map data structure*) and the *folded operation*.
|
||||
|
||||
## Iterated Operation
|
||||
|
||||
The first, the *iterated operation*, is an iteration over the map with
|
||||
no return value: its only use is to produce 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, and fail with an error otherwise.
|
||||
Iterate over values in a set.
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -221,15 +248,17 @@ let iter_op = (s : set (int)) : unit => {
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function fold : (('accumulator -> 'item -> 'accumulator) -> set ('item) -> 'accumulator) -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val fold : ('accumulator -> 'item -> 'accumulator) -> 'set list -> 'accumulator -> 'accumulator
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let fold: ((('accumulator, 'item) => 'accumulator), set('item), 'accumulator) => 'accumulator
|
||||
</SyntaxTitle>
|
||||
|
||||
## Folded Operation
|
||||
|
||||
A *folded operation* is the most general of iterations. The folded
|
||||
function takes two arguments: an *accumulator* and the structure
|
||||
*element* at hand, with which it then produces a new accumulator. This
|
||||
enables having a partial result that becomes complete when the
|
||||
traversal of the data structure is over.
|
||||
|
||||
[Fold over values in a set](../language-basics/sets-lists-tuples#folded-operation)
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
@ -241,17 +270,6 @@ const sum_of_elements : int = Set.fold (sum, my_set, 0)
|
||||
|
||||
> Note that `set_fold` is *deprecated*.
|
||||
|
||||
It is possible to use a *loop* over a set as well.
|
||||
|
||||
```pascaligo group=sets
|
||||
function loop (const s : set (int)) : int is block {
|
||||
var sum : int := 0;
|
||||
for element in set s block {
|
||||
sum := sum + element
|
||||
}
|
||||
} with sum
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
@ -269,4 +287,3 @@ let sum_of_elements : int = Set.fold (sum, my_set, 0);
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
@ -1,78 +1,120 @@
|
||||
---
|
||||
id: string-reference
|
||||
title: String — Manipulate string data
|
||||
title: String
|
||||
description: Operations for strings.
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import Syntax from '@theme/Syntax';
|
||||
import SyntaxTitle from '@theme/SyntaxTitle';
|
||||
|
||||
## String.size(s: string) : nat
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
type string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
type string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
type string
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the size of a string. [Michelson only supports ASCII strings](http://tezos.gitlab.io/whitedoc/michelson.html#constants)
|
||||
A sequence of characters.
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function length : string -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val length : string -> nat
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let length: string => nat
|
||||
</SyntaxTitle>
|
||||
|
||||
Get the size of a string.
|
||||
|
||||
[Michelson only supports ASCII strings](http://tezos.gitlab.io/whitedoc/michelson.html#constants)
|
||||
so for now you can assume that each character takes one byte of storage.
|
||||
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function string_size (const s: string) : nat is size(s)
|
||||
function string_size (const s: string) : nat is String.length(s)
|
||||
```
|
||||
|
||||
> Note that `size` and `String.size` are *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let size_op (s: string) : nat = String.size s
|
||||
let size_op (s: string) : nat = String.length s
|
||||
```
|
||||
|
||||
> Note that `String.size` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
let size_op = (s: string): nat => String.size(s);
|
||||
let size_op = (s: string): nat => String.length(s);
|
||||
```
|
||||
|
||||
> Note that `String.size` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function sub : nat -> nat -> string -> string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val sub : nat -> nat -> string -> string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let sub: (nat, nat, string) => string
|
||||
</SyntaxTitle>
|
||||
|
||||
## String.length(s: string) : nat
|
||||
|
||||
Alias for `String.size`.
|
||||
|
||||
## String.slice(pos1: nat, pos2: nat, s: string) : string
|
||||
|
||||
Get the substring of `s` between `pos1` inclusive and `pos2` inclusive. For example
|
||||
the string "tata" given to the function below would return "at".
|
||||
Extract a substring from a string based on the given offset and length. For
|
||||
example the string "abcd" given to the function below would return "bc".
|
||||
|
||||
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function slice_op (const s : string) : string is string_slice(1n , 2n , s)
|
||||
function slice_op (const s : string) : string is String.sub(1n , 2n , s)
|
||||
```
|
||||
|
||||
> Note that `string_slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let slice_op (s: string) : string = String.slice 1n 2n s
|
||||
let slice_op (s: string) : string = String.sub 1n 2n s
|
||||
```
|
||||
|
||||
> Note that `String.slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
let slice_op = (s: string): string => String.slice(1n, 2n, s);
|
||||
let slice_op = (s: string): string => String.sub(1n, 2n, s);
|
||||
```
|
||||
|
||||
> Note that `String.slice` is *deprecated*.
|
||||
|
||||
</Syntax>
|
||||
|
||||
|
||||
## String.sub(pos1: nat, pos2: nat, s: string) : string
|
||||
|
||||
Alias for `String.slice`.
|
||||
|
||||
## String.concat(s1: string, s2: string) : string
|
||||
<SyntaxTitle syntax="pascaligo">
|
||||
function concat : string -> string -> string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="cameligo">
|
||||
val concat : string -> string -> string
|
||||
</SyntaxTitle>
|
||||
<SyntaxTitle syntax="reasonligo">
|
||||
let concat: (string, string) => string
|
||||
</SyntaxTitle>
|
||||
|
||||
Concatenate two strings and return the result.
|
||||
|
||||
@ -81,21 +123,40 @@ Concatenate two strings and return the result.
|
||||
<Syntax syntax="pascaligo">
|
||||
|
||||
```pascaligo
|
||||
function concat_op (const s : string) : string is s ^ "toto"
|
||||
function concat_op (const s : string) : string is String.concat(s, "toto")
|
||||
```
|
||||
|
||||
Alternatively:
|
||||
|
||||
```pascaligo
|
||||
function concat_op_alt (const s : string) : string is s ^ "toto"
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="cameligo">
|
||||
|
||||
```cameligo
|
||||
let concat_syntax (s: string) = s ^ "test_literal"
|
||||
let concat_syntax (s: string) = String.concat s "test_literal"
|
||||
```
|
||||
|
||||
Alternatively:
|
||||
|
||||
```cameligo
|
||||
let concat_syntax_alt (s: string) = s ^ "test_literal"
|
||||
```
|
||||
|
||||
|
||||
</Syntax>
|
||||
<Syntax syntax="reasonligo">
|
||||
|
||||
```reasonligo
|
||||
let concat_syntax = (s: string) => s ++ "test_literal";
|
||||
let concat_syntax = (s: string) => String.concat(s, "test_literal");
|
||||
```
|
||||
|
||||
Alternatively:
|
||||
|
||||
```reasonligo
|
||||
let concat_syntax_alt = (s: string) => s ++ "test_literal";
|
||||
```
|
||||
|
||||
</Syntax>
|
||||
|
@ -169,7 +169,7 @@ function buy_taco (const taco_kind_index : nat ; var taco_shop_storage : taco_sh
|
||||
const receiver : contract(unit) = get_contract (ownerAddress);
|
||||
const payoutOperation : operation = transaction (unit, amount, receiver);
|
||||
const operations : list(operation) = list [payoutOperation]
|
||||
} with ((nil : list (operation)), taco_shop_storage)
|
||||
} with ((operations : list (operation)), taco_shop_storage)
|
||||
```
|
||||
|
||||
### Dry-run the Contract
|
||||
|
@ -21,17 +21,20 @@
|
||||
"advanced/first-contract",
|
||||
"advanced/michelson-and-ligo"
|
||||
],
|
||||
"API & Reference": [
|
||||
"Reference": [
|
||||
"api/cli-commands",
|
||||
"api/cheat-sheet",
|
||||
"api/cheat-sheet"
|
||||
],
|
||||
"API":[
|
||||
"reference/big-map-reference",
|
||||
"reference/bitwise-reference",
|
||||
"reference/bytes-reference",
|
||||
"reference/crypto-reference",
|
||||
"reference/current-reference",
|
||||
"reference/crypto-reference",
|
||||
"reference/list-reference",
|
||||
"reference/map-reference",
|
||||
"reference/set-reference",
|
||||
"reference/string-reference"
|
||||
"reference/string-reference",
|
||||
"reference/current-reference"
|
||||
]
|
||||
},
|
||||
"contributors-docs": {
|
||||
|
@ -166,7 +166,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
{showCopied ? 'Copied' : 'Copy'}
|
||||
</button>
|
||||
|
||||
<code ref={target} className={styles.codeBlockLines} style={style}>
|
||||
<code ref={target} className={styles.codeBlockLines}>
|
||||
{tokens.map((line, i) => {
|
||||
if (line.length === 1 && line[0].content === '') {
|
||||
line[0].content = '\n'; // eslint-disable-line no-param-reassign
|
||||
|
@ -989,21 +989,43 @@ a:hover {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ReasonLIGO specific syntax highlighting */
|
||||
.language-reasonligo .hljs-operator {
|
||||
color: #a626a4;
|
||||
}
|
||||
.language-reasonligo .hljs-character {
|
||||
color: #50a14f;
|
||||
}
|
||||
.language-reasonligo .hljs-module-identifier {
|
||||
color: #00f;
|
||||
}
|
||||
.language-reasonligo .hljs-constructor {
|
||||
color: #a31515;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.codeTable {
|
||||
display: grid;
|
||||
grid-template-columns: 30% 70%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.codeTable > .primitive {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
text-align: right;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.codeTable > div:nth-child(4n+1) {
|
||||
background-color: var(--ifm-table-stripe-background);
|
||||
}
|
||||
|
||||
.codeTable > div:nth-child(4n+2) {
|
||||
background-color: var(--ifm-table-stripe-background);
|
||||
}
|
||||
|
||||
|
||||
.codeTable > .example {
|
||||
padding-top: var(--ifm-leading);
|
||||
}
|
||||
|
||||
.codeTable > .example pre,
|
||||
.codeTable > .example .codeBlockLines_src-theme-CodeBlock- {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
126
src/bin/cli.ml
126
src/bin/cli.ml
@ -140,8 +140,7 @@ module Run = Ligo.Run.Of_michelson
|
||||
let compile_file =
|
||||
let f source_file entry_point syntax display_format disable_typecheck michelson_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed,_ = Compile.Of_simplified.compile (Contract entry_point) simplified in
|
||||
let%bind typed,_ = Compile.Utils.type_file source_file syntax (Contract entry_point) in
|
||||
let%bind mini_c = Compile.Of_typed.compile typed in
|
||||
let%bind michelson = Compile.Of_mini_c.aggregate_and_compile_contract mini_c entry_point in
|
||||
let%bind contract = Compile.Of_michelson.build_contract ~disable_typecheck michelson in
|
||||
@ -168,8 +167,8 @@ let print_cst =
|
||||
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
|
||||
let%bind imperative = Compile.Utils.to_imperatve source_file syntax in
|
||||
ok @@ Format.asprintf "%a\n" Compile.Of_imperative.pretty_print imperative
|
||||
)
|
||||
in
|
||||
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
|
||||
@ -177,24 +176,46 @@ let print_ast =
|
||||
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_ast_sugar =
|
||||
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 Env simplified in
|
||||
let%bind sugar = Compile.Utils.to_sugar source_file syntax in
|
||||
ok @@ Format.asprintf "%a\n" Compile.Of_sugar.pretty_print sugar
|
||||
)
|
||||
in
|
||||
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
|
||||
let cmdname = "print-ast-sugar" 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_ast_core =
|
||||
let f source_file syntax display_format = (
|
||||
toplevel ~display_format @@
|
||||
let%bind core = Compile.Utils.to_core source_file syntax in
|
||||
ok @@ Format.asprintf "%a\n" Compile.Of_core.pretty_print core
|
||||
)
|
||||
in
|
||||
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
|
||||
let cmdname = "print-ast-core" 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_ast_typed =
|
||||
let f source_file syntax display_format = (
|
||||
toplevel ~display_format @@
|
||||
let%bind typed,_ = Compile.Utils.type_file source_file syntax Env in
|
||||
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 cmdname = "print-ast-typed" 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 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 Env simplified in
|
||||
let%bind typed,_ = Compile.Utils.type_file source_file syntax Env in
|
||||
let%bind mini_c = Compile.Of_typed.compile typed in
|
||||
ok @@ Format.asprintf "%a\n" Compile.Of_mini_c.pretty_print mini_c
|
||||
)
|
||||
@ -207,11 +228,7 @@ let print_mini_c =
|
||||
let measure_contract =
|
||||
let f source_file entry_point 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 (Contract entry_point) simplified in
|
||||
let%bind mini_c = Compile.Of_typed.compile typed in
|
||||
let%bind michelson = Compile.Of_mini_c.aggregate_and_compile_contract mini_c entry_point in
|
||||
let%bind contract = Compile.Of_michelson.build_contract michelson in
|
||||
let%bind contract = Compile.Utils.compile_file source_file syntax entry_point in
|
||||
let open Tezos_utils in
|
||||
ok @@ Format.asprintf "%d bytes\n" (Michelson.measure contract)
|
||||
in
|
||||
@ -224,8 +241,7 @@ let measure_contract =
|
||||
let compile_parameter =
|
||||
let f source_file entry_point expression syntax amount balance sender source predecessor_timestamp display_format michelson_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,state = Compile.Of_simplified.compile (Contract entry_point) simplified in
|
||||
let%bind typed_prg,state = Compile.Utils.type_file source_file syntax (Contract entry_point) in
|
||||
let%bind mini_c_prg = Compile.Of_typed.compile typed_prg in
|
||||
let%bind michelson_prg = Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg entry_point in
|
||||
let env = Ast_typed.program_environment typed_prg in
|
||||
@ -233,9 +249,7 @@ let compile_parameter =
|
||||
(* fails if the given entry point is not a valid contract *)
|
||||
Compile.Of_michelson.build_contract michelson_prg in
|
||||
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
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 (typed_param,_) = Compile.Utils.type_expression (Some source_file) syntax expression env state in
|
||||
let%bind mini_c_param = Compile.Of_typed.compile_expression typed_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_parameter entry_point typed_prg typed_param in
|
||||
@ -255,16 +269,13 @@ let interpret =
|
||||
toplevel ~display_format @@
|
||||
let%bind (decl_list,state,env) = match init_file with
|
||||
| Some init_file ->
|
||||
let%bind simplified = Compile.Of_source.compile init_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,state = Compile.Of_simplified.compile Env simplified in
|
||||
let%bind typed_prg,state = Compile.Utils.type_file init_file syntax Env in
|
||||
let%bind mini_c_prg = Compile.Of_typed.compile typed_prg in
|
||||
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
|
||||
let%bind (typed_exp,_) = Compile.Utils.type_expression init_file syntax expression env state in
|
||||
let%bind mini_c_exp = Compile.Of_typed.compile_expression typed_exp in
|
||||
let%bind compiled_exp = Compile.Of_mini_c.aggregate_and_compile_expression decl_list mini_c_exp in
|
||||
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; balance ; sender ; source } in
|
||||
@ -274,8 +285,8 @@ 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_expression value' in
|
||||
ok @@ Format.asprintf "%a\n" Ast_simplified.PP.expression simplified_output
|
||||
let%bind core_output = Uncompile.uncompile_expression typed_exp.type_expression value' in
|
||||
ok @@ Format.asprintf "%a\n" Ast_core.PP.expression core_output
|
||||
in
|
||||
let term =
|
||||
Term.(const f $ expression "EXPRESSION" 0 $ init_file $ syntax $ amount $ balance $ sender $ source $ predecessor_timestamp $ display_format ) in
|
||||
@ -286,8 +297,7 @@ let interpret =
|
||||
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 Env simplified in
|
||||
let%bind typed,_ = Compile.Utils.type_file source_file syntax Env in
|
||||
let%bind res = Compile.Of_typed.some_interpret typed in
|
||||
ok @@ Format.asprintf "%s\n" res
|
||||
in
|
||||
@ -300,8 +310,7 @@ let temp_ligo_interpreter =
|
||||
let compile_storage =
|
||||
let f source_file entry_point expression syntax amount balance sender source predecessor_timestamp display_format michelson_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,state = Compile.Of_simplified.compile (Contract entry_point) simplified in
|
||||
let%bind typed_prg,state = Compile.Utils.type_file source_file syntax (Contract entry_point) in
|
||||
let%bind mini_c_prg = Compile.Of_typed.compile typed_prg in
|
||||
let%bind michelson_prg = Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg entry_point in
|
||||
let env = Ast_typed.program_environment typed_prg in
|
||||
@ -309,9 +318,7 @@ let compile_storage =
|
||||
(* fails if the given entry point is not a valid contract *)
|
||||
Compile.Of_michelson.build_contract michelson_prg in
|
||||
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
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 (typed_param,_) = Compile.Utils.type_expression (Some source_file) syntax expression env state in
|
||||
let%bind mini_c_param = Compile.Of_typed.compile_expression typed_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
|
||||
@ -329,8 +336,7 @@ let compile_storage =
|
||||
let dry_run =
|
||||
let f source_file entry_point storage input amount balance sender source predecessor_timestamp syntax display_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,state = Compile.Of_simplified.compile (Contract entry_point) simplified in
|
||||
let%bind typed_prg,state = Compile.Utils.type_file source_file syntax (Contract entry_point) in
|
||||
let env = Ast_typed.program_environment typed_prg in
|
||||
let%bind mini_c_prg = Compile.Of_typed.compile typed_prg in
|
||||
let%bind michelson_prg = Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg entry_point in
|
||||
@ -338,11 +344,7 @@ let dry_run =
|
||||
(* fails if the given entry point is not a valid contract *)
|
||||
Compile.Of_michelson.build_contract michelson_prg in
|
||||
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
let%bind simplified = Compile.Of_source.compile_contract_input storage input v_syntax in
|
||||
let%bind typed,_ = Compile.Of_simplified.compile_expression ~env ~state simplified in
|
||||
let%bind mini_c = Compile.Of_typed.compile_expression typed in
|
||||
let%bind compiled_params = Compile.Of_mini_c.aggregate_and_compile_expression mini_c_prg mini_c in
|
||||
let%bind compiled_params = Compile.Utils.compile_storage storage input source_file syntax env state mini_c_prg in
|
||||
let%bind args_michelson = Run.evaluate_expression compiled_params.expr compiled_params.expr_ty in
|
||||
|
||||
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; balance ; sender ; source } in
|
||||
@ -352,8 +354,8 @@ let dry_run =
|
||||
let%bind failstring = Run.failwith_to_string fail_res in
|
||||
ok @@ Format.asprintf "%s" failstring
|
||||
| Success michelson_output ->
|
||||
let%bind simplified_output = Uncompile.uncompile_typed_program_entry_function_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_simplified.PP.expression simplified_output
|
||||
let%bind core_output = Uncompile.uncompile_typed_program_entry_function_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_core.PP.expression core_output
|
||||
in
|
||||
let term =
|
||||
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ expression "STORAGE" 3 $ amount $ balance $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
|
||||
@ -364,16 +366,17 @@ let dry_run =
|
||||
let run_function =
|
||||
let f source_file entry_point parameter amount balance sender source predecessor_timestamp syntax display_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
let%bind simplified_prg = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,state = Compile.Of_simplified.compile Env simplified_prg in
|
||||
let%bind typed_prg,state = Compile.Utils.type_file source_file syntax Env in
|
||||
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
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
let%bind imperative_param = Compile.Of_source.compile_expression v_syntax parameter in
|
||||
let%bind sugar_param = Compile.Of_imperative.compile_expression imperative_param in
|
||||
let%bind core_param = Compile.Of_sugar.compile_expression sugar_param in
|
||||
let%bind app = Compile.Of_core.apply entry_point core_param in
|
||||
let%bind (typed_app,_) = Compile.Of_core.compile_expression ~env ~state app in
|
||||
let%bind compiled_applied = Compile.Of_typed.compile_expression typed_app in
|
||||
|
||||
let%bind michelson = Compile.Of_mini_c.aggregate_and_compile_expression mini_c_prg compiled_applied in
|
||||
@ -384,8 +387,8 @@ let run_function =
|
||||
let%bind failstring = Run.failwith_to_string fail_res in
|
||||
ok @@ Format.asprintf "%s" failstring
|
||||
| Success michelson_output ->
|
||||
let%bind simplified_output = Uncompile.uncompile_typed_program_entry_function_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_simplified.PP.expression simplified_output
|
||||
let%bind core_output = Uncompile.uncompile_typed_program_entry_function_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_core.PP.expression core_output
|
||||
in
|
||||
let term =
|
||||
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ amount $ balance $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
|
||||
@ -396,15 +399,14 @@ let run_function =
|
||||
let evaluate_value =
|
||||
let f source_file entry_point amount balance sender source predecessor_timestamp syntax display_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
|
||||
let%bind typed_prg,_ = Compile.Of_simplified.compile Env simplified in
|
||||
let%bind typed_prg,_ = Compile.Utils.type_file source_file syntax Env in
|
||||
let%bind mini_c = Compile.Of_typed.compile typed_prg in
|
||||
let%bind (exp,_) = Mini_c.get_entry mini_c entry_point in
|
||||
let%bind compiled = Compile.Of_mini_c.aggregate_and_compile_expression mini_c exp in
|
||||
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; balance ; sender ; source } in
|
||||
let%bind michelson_output = Run.run_no_failwith ~options compiled.expr compiled.expr_ty in
|
||||
let%bind simplified_output = Uncompile.uncompile_typed_program_entry_expression_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_simplified.PP.expression simplified_output
|
||||
let%bind core_output = Uncompile.uncompile_typed_program_entry_expression_result typed_prg entry_point michelson_output in
|
||||
ok @@ Format.asprintf "%a\n" Ast_core.PP.expression core_output
|
||||
in
|
||||
let term =
|
||||
Term.(const f $ source_file 0 $ entry_point 1 $ amount $ balance $ sender $ source $ predecessor_timestamp $ syntax $ display_format) in
|
||||
@ -415,13 +417,9 @@ let evaluate_value =
|
||||
let compile_expression =
|
||||
let f expression syntax display_format michelson_format =
|
||||
toplevel ~display_format @@
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (None) in
|
||||
let env = Ast_typed.Environment.full_empty in
|
||||
let state = Typer.Solver.initial_state in
|
||||
let%bind simplified = Compile.Of_source.compile_expression v_syntax expression in
|
||||
let%bind (typed_exp,_) = Compile.Of_simplified.compile_expression ~env ~state simplified in
|
||||
let%bind mini_c_exp = Compile.Of_typed.compile_expression typed_exp in
|
||||
let%bind compiled_exp = Compile.Of_mini_c.compile_expression mini_c_exp in
|
||||
let%bind compiled_exp = Compile.Utils.compile_expression None syntax expression env state in
|
||||
let%bind value = Run.evaluate_expression compiled_exp.expr compiled_exp.expr_ty in
|
||||
ok @@ Format.asprintf "%a\n" (Main.Display.michelson_pp michelson_format) value
|
||||
in
|
||||
@ -442,8 +440,8 @@ let dump_changelog =
|
||||
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
|
||||
let%bind core_prg = Compile.Utils.to_core source_file syntax in
|
||||
let json_decl = List.map (fun decl -> `String decl) @@ Compile.Of_core.list_declarations core_prg in
|
||||
ok @@ J.to_string @@ `Assoc [ ("source_file", `String source_file) ; ("declarations", `List json_decl) ]
|
||||
in
|
||||
let term =
|
||||
@ -467,7 +465,9 @@ let run ?argv () =
|
||||
dump_changelog ;
|
||||
print_cst ;
|
||||
print_ast ;
|
||||
print_typed_ast ;
|
||||
print_ast_sugar ;
|
||||
print_ast_core ;
|
||||
print_ast_typed ;
|
||||
print_mini_c ;
|
||||
list_declarations ;
|
||||
]
|
||||
|
@ -1174,7 +1174,7 @@ let%expect_test _ =
|
||||
let%expect_test _ =
|
||||
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return let rhs#812 = #P in let p = rhs#812.0 in let s = rhs#812.1 in ( list[] : (TO_list(operation)) , store ) , NONE() : (TO_option(key_hash)) , 300000000mutez , \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"}
|
||||
ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return let rhs#654 = #P in let p = rhs#654.0 in let s = rhs#654.1 in ( list[] : (TO_list(operation)) , store ) , NONE() : (TO_option(key_hash)) , 300000000mutez , \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"}
|
||||
|
||||
|
||||
If you're not sure how to fix this error, you can
|
||||
@ -1187,7 +1187,7 @@ ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8,
|
||||
|
||||
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return let rhs#815 = #P in let p = rhs#815.0 in let s = rhs#815.1 in ( list[] : (TO_list(operation)) , a ) , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"}
|
||||
ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return let rhs#657 = #P in let p = rhs#657.0 in let s = rhs#657.1 in ( list[] : (TO_list(operation)) , a ) , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"}
|
||||
|
||||
|
||||
If you're not sure how to fix this error, you can
|
||||
@ -1344,4 +1344,56 @@ 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' |}]
|
||||
* Check the changelog by running 'ligo changelog' |}];
|
||||
|
||||
run_ligo_bad ["compile-contract"; bad_contract "nested_bigmap_1.religo"; "main"];
|
||||
[%expect {|
|
||||
ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
|
||||
|
||||
|
||||
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"; bad_contract "nested_bigmap_2.religo"; "main"];
|
||||
[%expect {|
|
||||
ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
|
||||
|
||||
|
||||
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"; bad_contract "nested_bigmap_3.religo"; "main"];
|
||||
[%expect {|
|
||||
ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
|
||||
|
||||
|
||||
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"; bad_contract "nested_bigmap_4.religo"; "main"];
|
||||
[%expect {|
|
||||
ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
|
||||
|
||||
|
||||
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' |}]
|
@ -57,6 +57,18 @@ let%expect_test _ =
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-core
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-sugar
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-typed
|
||||
Subcommand: Print the typed AST. Warning: Intended for development
|
||||
of LIGO and can break at any time.
|
||||
|
||||
print-cst
|
||||
Subcommand: Print the CST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
@ -65,10 +77,6 @@ let%expect_test _ =
|
||||
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
|
||||
of LIGO and can break at any time.
|
||||
|
||||
run-function
|
||||
Subcommand: Run a function with the given parameter.
|
||||
|
||||
@ -136,6 +144,18 @@ let%expect_test _ =
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-core
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-sugar
|
||||
Subcommand: Print the AST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
|
||||
print-ast-typed
|
||||
Subcommand: Print the typed AST. Warning: Intended for development
|
||||
of LIGO and can break at any time.
|
||||
|
||||
print-cst
|
||||
Subcommand: Print the CST. Warning: Intended for development of
|
||||
LIGO and can break at any time.
|
||||
@ -144,10 +164,6 @@ let%expect_test _ =
|
||||
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
|
||||
of LIGO and can break at any time.
|
||||
|
||||
run-function
|
||||
Subcommand: Run a function with the given parameter.
|
||||
|
||||
|
@ -5,14 +5,20 @@
|
||||
simple-utils
|
||||
tezos-utils
|
||||
parser
|
||||
simplify
|
||||
interpreter
|
||||
ast_simplified
|
||||
self_ast_simplified
|
||||
concrete_to_imperative
|
||||
ast_imperative
|
||||
self_ast_imperative
|
||||
imperative_to_sugar
|
||||
ast_sugar
|
||||
self_ast_sugar
|
||||
sugar_to_core
|
||||
ast_core
|
||||
self_ast_core
|
||||
typer_new
|
||||
typer
|
||||
ast_typed
|
||||
self_ast_typed
|
||||
interpreter
|
||||
transpiler
|
||||
mini_c
|
||||
self_mini_c
|
||||
|
@ -23,55 +23,55 @@ 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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Pascaligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting expression") @@
|
||||
Concrete_to_imperative.Pascaligo.compile_expression raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Cameligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting expression") @@
|
||||
Concrete_to_imperative.Cameligo.compile_expression raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Cameligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting expression") @@
|
||||
Concrete_to_imperative.Cameligo.compile_expression raw
|
||||
in ok imperative
|
||||
|
||||
let parsify syntax source =
|
||||
let%bind parsify =
|
||||
@ -80,7 +80,7 @@ let parsify syntax source =
|
||||
| CameLIGO -> ok parsify_cameligo
|
||||
| ReasonLIGO -> ok parsify_reasonligo in
|
||||
let%bind parsified = parsify source in
|
||||
let%bind applied = Self_ast_simplified.all_program parsified
|
||||
let%bind applied = Self_ast_imperative.all_program parsified
|
||||
in ok applied
|
||||
|
||||
let parsify_expression syntax source =
|
||||
@ -89,35 +89,35 @@ let parsify_expression syntax source =
|
||||
| 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
|
||||
let%bind applied = Self_ast_imperative.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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Cameligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Pascaligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
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
|
||||
let%bind imperative =
|
||||
trace (simple_error "abstracting") @@
|
||||
Concrete_to_imperative.Cameligo.compile_program raw
|
||||
in ok imperative
|
||||
|
||||
let parsify_string syntax source =
|
||||
let%bind parsify =
|
||||
@ -126,7 +126,7 @@ let parsify_string syntax source =
|
||||
| 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
|
||||
let%bind applied = Self_ast_imperative.all_program parsified
|
||||
in ok applied
|
||||
|
||||
let pretty_print_pascaligo source =
|
||||
|
@ -4,7 +4,7 @@ type form =
|
||||
| Contract of string
|
||||
| Env
|
||||
|
||||
let compile (cform: form) (program : Ast_simplified.program) : (Ast_typed.program * Typer.Solver.state) result =
|
||||
let compile (cform: form) (program : Ast_core.program) : (Ast_typed.program * Typer.Solver.state) result =
|
||||
let%bind (prog_typed , state) = Typer.type_program program in
|
||||
let () = Typer.Solver.discard_state state in
|
||||
let%bind applied = Self_ast_typed.all_program prog_typed in
|
||||
@ -13,31 +13,31 @@ let compile (cform: form) (program : Ast_simplified.program) : (Ast_typed.progra
|
||||
| Env -> ok applied in
|
||||
ok @@ (applied', state)
|
||||
|
||||
let compile_expression ?(env = Ast_typed.Environment.full_empty) ~(state : Typer.Solver.state) (ae : Ast_simplified.expression)
|
||||
let compile_expression ?(env = Ast_typed.Environment.full_empty) ~(state : Typer.Solver.state) (e : Ast_core.expression)
|
||||
: (Ast_typed.expression * Typer.Solver.state) result =
|
||||
let%bind (ae_typed,state) = Typer.type_expression_subst env state ae in
|
||||
let%bind (ae_typed,state) = Typer.type_expression_subst env state e in
|
||||
let () = Typer.Solver.discard_state state in
|
||||
let%bind ae_typed' = Self_ast_typed.all_expression ae_typed in
|
||||
ok @@ (ae_typed',state)
|
||||
|
||||
let apply (entry_point : string) (param : Ast_simplified.expression) : Ast_simplified.expression result =
|
||||
let apply (entry_point : string) (param : Ast_core.expression) : Ast_core.expression result =
|
||||
let name = Var.of_name entry_point in
|
||||
let entry_point_var : Ast_simplified.expression =
|
||||
{ expression_content = Ast_simplified.E_variable name ;
|
||||
let entry_point_var : Ast_core.expression =
|
||||
{ expression_content = Ast_core.E_variable name ;
|
||||
location = Virtual "generated entry-point variable" } in
|
||||
let applied : Ast_simplified.expression =
|
||||
{ expression_content = Ast_simplified.E_application {expr1=entry_point_var; expr2=param} ;
|
||||
let applied : Ast_core.expression =
|
||||
{ expression_content = Ast_core.E_application {lamb=entry_point_var; args=param} ;
|
||||
location = Virtual "generated application" } in
|
||||
ok applied
|
||||
|
||||
let pretty_print formatter (program : Ast_simplified.program) =
|
||||
Ast_simplified.PP.program formatter program
|
||||
let pretty_print formatter (program : Ast_core.program) =
|
||||
Ast_core.PP.program formatter program
|
||||
|
||||
let list_declarations (program : Ast_simplified.program) : string list =
|
||||
let list_declarations (program : Ast_core.program) : string list =
|
||||
List.fold_left
|
||||
(fun prev el ->
|
||||
let open Location in
|
||||
let open Ast_simplified in
|
||||
let open Ast_core in
|
||||
match el.wrap_content with
|
||||
| Declaration_constant (var,_,_,_) -> (Var.to_name var)::prev
|
||||
| _ -> prev)
|
25
src/main/compile/of_imperative.ml
Normal file
25
src/main/compile/of_imperative.ml
Normal file
@ -0,0 +1,25 @@
|
||||
open Trace
|
||||
open Ast_imperative
|
||||
open Imperative_to_sugar
|
||||
|
||||
type form =
|
||||
| Contract of string
|
||||
| Env
|
||||
|
||||
let compile (program : program) : Ast_sugar.program result =
|
||||
compile_program program
|
||||
|
||||
let compile_expression (e : expression) : Ast_sugar.expression result =
|
||||
compile_expression e
|
||||
|
||||
let pretty_print formatter (program : program) =
|
||||
PP.program formatter program
|
||||
|
||||
let list_declarations (program : program) : string list =
|
||||
List.fold_left
|
||||
(fun prev el ->
|
||||
let open Location in
|
||||
match el.wrap_content with
|
||||
| Declaration_constant (var,_,_,_) -> (Var.to_name var)::prev
|
||||
| _ -> prev)
|
||||
[] program
|
@ -1,23 +1,23 @@
|
||||
open Trace
|
||||
open Helpers
|
||||
|
||||
let compile (source_filename:string) syntax : Ast_simplified.program result =
|
||||
let compile (source_filename:string) syntax : Ast_imperative.program result =
|
||||
let%bind syntax = syntax_to_variant syntax (Some source_filename) in
|
||||
let%bind simplified = parsify syntax source_filename in
|
||||
ok simplified
|
||||
let%bind abstract = parsify syntax source_filename in
|
||||
ok abstract
|
||||
|
||||
let compile_string (source:string) syntax : Ast_simplified.program result =
|
||||
let%bind simplified = parsify_string syntax source in
|
||||
ok simplified
|
||||
let compile_string (source:string) syntax : Ast_imperative.program result =
|
||||
let%bind abstract = parsify_string syntax source in
|
||||
ok abstract
|
||||
|
||||
let compile_expression : v_syntax -> string -> Ast_simplified.expression result =
|
||||
let compile_expression : v_syntax -> string -> Ast_imperative.expression result =
|
||||
fun syntax exp ->
|
||||
parsify_expression syntax exp
|
||||
|
||||
let compile_contract_input : string -> string -> v_syntax -> Ast_simplified.expression result =
|
||||
let compile_contract_input : string -> string -> v_syntax -> Ast_imperative.expression result =
|
||||
fun storage parameter syntax ->
|
||||
let%bind (storage,parameter) = bind_map_pair (compile_expression syntax) (storage,parameter) in
|
||||
ok @@ Ast_simplified.e_pair storage parameter
|
||||
ok @@ Ast_imperative.e_pair storage parameter
|
||||
|
||||
let pretty_print source_filename syntax =
|
||||
Helpers.pretty_print syntax source_filename
|
||||
Helpers.pretty_print syntax source_filename
|
||||
|
25
src/main/compile/of_sugar.ml
Normal file
25
src/main/compile/of_sugar.ml
Normal file
@ -0,0 +1,25 @@
|
||||
open Trace
|
||||
open Ast_sugar
|
||||
open Sugar_to_core
|
||||
|
||||
type form =
|
||||
| Contract of string
|
||||
| Env
|
||||
|
||||
let compile (program : program) : Ast_core.program result =
|
||||
compile_program program
|
||||
|
||||
let compile_expression (e : expression) : Ast_core.expression result =
|
||||
compile_expression e
|
||||
|
||||
let pretty_print formatter (program : program) =
|
||||
PP.program formatter program
|
||||
|
||||
let list_declarations (program : program) : string list =
|
||||
List.fold_left
|
||||
(fun prev el ->
|
||||
let open Location in
|
||||
match el.wrap_content with
|
||||
| Declaration_constant (var,_,_,_) -> (Var.to_name var)::prev
|
||||
| _ -> prev)
|
||||
[] program
|
65
src/main/compile/utils.ml
Normal file
65
src/main/compile/utils.ml
Normal file
@ -0,0 +1,65 @@
|
||||
open Trace
|
||||
|
||||
let to_imperatve f stx =
|
||||
let%bind imperative = Of_source.compile f (Syntax_name stx) in
|
||||
ok @@ imperative
|
||||
|
||||
let to_sugar f stx =
|
||||
let%bind imperative = to_imperatve f stx in
|
||||
let%bind sugar = Of_imperative.compile imperative in
|
||||
ok @@ sugar
|
||||
|
||||
let to_core f stx =
|
||||
let%bind sugar = to_sugar f stx in
|
||||
let%bind core = Of_sugar.compile sugar in
|
||||
ok @@ core
|
||||
|
||||
let type_file f stx env =
|
||||
let%bind core = to_core f stx in
|
||||
let%bind typed,state = Of_core.compile env core in
|
||||
ok @@ (typed,state)
|
||||
|
||||
let to_mini_c f stx env =
|
||||
let%bind typed, _ = type_file f stx env in
|
||||
let%bind mini_c = Of_typed.compile typed in
|
||||
ok @@ mini_c
|
||||
|
||||
let compile_file f stx ep =
|
||||
let%bind typed, _ = type_file f stx @@ Contract ep in
|
||||
let%bind mini_c = Of_typed.compile typed in
|
||||
let%bind michelson = Of_mini_c.aggregate_and_compile_contract mini_c ep in
|
||||
let%bind contract = Of_michelson.build_contract michelson in
|
||||
ok @@ contract
|
||||
|
||||
let type_expression source_file syntax expression env state =
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) source_file in
|
||||
let%bind imperative_exp = Of_source.compile_expression v_syntax expression in
|
||||
let%bind sugar_exp = Of_imperative.compile_expression imperative_exp in
|
||||
let%bind core_exp = Of_sugar.compile_expression sugar_exp in
|
||||
let%bind (typed_exp,state) = Of_core.compile_expression ~env ~state core_exp in
|
||||
ok @@ (typed_exp,state)
|
||||
|
||||
let expression_to_mini_c source_file syntax expression env state =
|
||||
let%bind (typed_exp,_) = type_expression source_file syntax expression env state in
|
||||
let%bind mini_c_exp = Of_typed.compile_expression typed_exp in
|
||||
ok @@ mini_c_exp
|
||||
|
||||
let compile_expression source_file syntax expression env state =
|
||||
let%bind mini_c_exp = expression_to_mini_c source_file syntax expression env state in
|
||||
let%bind compiled = Of_mini_c.compile_expression mini_c_exp in
|
||||
ok @@ compiled
|
||||
|
||||
let compile_and_aggregate_expression source_file syntax expression env state mini_c_prg =
|
||||
let%bind mini_c_exp = expression_to_mini_c source_file syntax expression env state in
|
||||
let%bind compiled = Of_mini_c.aggregate_and_compile_expression mini_c_prg mini_c_exp in
|
||||
ok @@ compiled
|
||||
|
||||
let compile_storage storage input source_file syntax env state mini_c_prg =
|
||||
let%bind v_syntax = Helpers.syntax_to_variant (Syntax_name syntax) (Some source_file) in
|
||||
let%bind imperative = Of_source.compile_contract_input storage input v_syntax in
|
||||
let%bind sugar = Of_imperative.compile_expression imperative in
|
||||
let%bind core = Of_sugar.compile_expression sugar in
|
||||
let%bind typed,_ = Of_core.compile_expression ~env ~state core in
|
||||
let%bind mini_c = Of_typed.compile_expression typed in
|
||||
let%bind compiled = Of_mini_c.aggregate_and_compile_expression mini_c_prg mini_c in
|
||||
ok @@ compiled
|
@ -5,8 +5,10 @@
|
||||
simple-utils
|
||||
tezos-utils
|
||||
parser
|
||||
simplify
|
||||
ast_simplified
|
||||
concrete_to_imperative
|
||||
self_ast_imperative
|
||||
sugar_to_core
|
||||
ast_core
|
||||
typer_new
|
||||
typer
|
||||
ast_typed
|
||||
|
@ -4,6 +4,8 @@
|
||||
(libraries
|
||||
simple-utils
|
||||
compiler
|
||||
imperative_to_sugar
|
||||
sugar_to_core
|
||||
typer_new
|
||||
typer
|
||||
ast_typed
|
||||
|
@ -10,7 +10,8 @@ let uncompile_value func_or_expr program entry ex_ty_value =
|
||||
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
|
||||
Typer.untype_expression typed
|
||||
let%bind core = Typer.untype_expression typed in
|
||||
ok @@ core
|
||||
|
||||
let uncompile_typed_program_entry_expression_result program entry ex_ty_value =
|
||||
uncompile_value Expression program entry ex_ty_value
|
||||
|
@ -24,23 +24,21 @@ type 'a sequence_or_record =
|
||||
|
||||
let (<@) f g x = f (g x)
|
||||
|
||||
(**
|
||||
Covert nsepseq to a chain of TFun's.
|
||||
(*
|
||||
Convert a nsepseq to a chain of TFun's.
|
||||
|
||||
Necessary to handle cases like:
|
||||
`type foo = (int, int) => int;`
|
||||
[type foo = (int, int) => int;]
|
||||
*)
|
||||
let rec nsepseq_to_curry hd rest =
|
||||
match hd, rest with
|
||||
| hd, (sep, item) :: rest ->
|
||||
let start = type_expr_to_region hd in
|
||||
let stop = nsepseq_to_region type_expr_to_region (hd, rest) in
|
||||
let region = cover start stop in
|
||||
TFun {
|
||||
value = hd, sep, (nsepseq_to_curry item rest);
|
||||
region
|
||||
}
|
||||
| hd, [] -> hd
|
||||
|
||||
let rec curry hd = function
|
||||
(sep, item)::rest ->
|
||||
let stop = nsepseq_to_region type_expr_to_region (hd, rest)
|
||||
and start = type_expr_to_region hd in
|
||||
let region = cover start stop
|
||||
and value = hd, sep, curry item rest
|
||||
in TFun {value; region}
|
||||
| [] -> hd
|
||||
|
||||
(* END HEADER *)
|
||||
%}
|
||||
@ -58,6 +56,7 @@ let rec nsepseq_to_curry hd rest =
|
||||
can be reduced to [expr -> Ident], but also to
|
||||
[field_assignment -> Ident].
|
||||
*)
|
||||
|
||||
%nonassoc Ident
|
||||
%nonassoc COLON
|
||||
|
||||
@ -175,42 +174,32 @@ type_decl:
|
||||
in {region; value} }
|
||||
|
||||
type_expr:
|
||||
cartesian | sum_type | record_type { $1 }
|
||||
fun_type | sum_type | record_type { $1 }
|
||||
|
||||
type_expr_func:
|
||||
"=>" cartesian {
|
||||
$1, $2
|
||||
fun_type:
|
||||
type_name "=>" fun_type {
|
||||
let region = cover $1.region (type_expr_to_region $3)
|
||||
in TFun {region; value = TVar $1, $2, $3}
|
||||
}
|
||||
| "(" fun_type ")" "=>" fun_type {
|
||||
let region = cover $1 (type_expr_to_region $5)
|
||||
in TFun {region; value = $2,$4,$5}
|
||||
}
|
||||
| "(" tuple(fun_type) ")" "=>" fun_type {
|
||||
let hd, rest = $2 in curry hd (rest @ [($4,$5)])
|
||||
}
|
||||
| "(" tuple(fun_type) ")" {
|
||||
TProd {region = cover $1 $3; value = $2}
|
||||
}
|
||||
| core_type { $1 }
|
||||
|
||||
cartesian:
|
||||
core_type { $1 }
|
||||
| type_name type_expr_func {
|
||||
let (arrow, c) = $2 in
|
||||
let value = TVar $1, arrow, c in
|
||||
let region = cover $1.region (type_expr_to_region c) in
|
||||
TFun { region; value }
|
||||
}
|
||||
| "(" cartesian ")" type_expr_func {
|
||||
let (arrow, c) = $4 in
|
||||
let value = $2, arrow, c in
|
||||
let region = cover $1 (type_expr_to_region c) in
|
||||
TFun { region; value }
|
||||
}
|
||||
| "(" cartesian "," nsepseq(cartesian,",") ")" type_expr_func? {
|
||||
match $6 with
|
||||
| Some (arrow, c) ->
|
||||
let (hd, rest) = Utils.nsepseq_cons $2 $3 $4 in
|
||||
let rest = rest @ [(arrow, c)] in
|
||||
nsepseq_to_curry hd rest
|
||||
| None ->
|
||||
let value = Utils.nsepseq_cons $2 $3 $4 in
|
||||
let region = cover $1 $5 in
|
||||
TProd {region; value}
|
||||
}
|
||||
type_args:
|
||||
tuple(fun_type) { $1 }
|
||||
| fun_type { $1, [] }
|
||||
|
||||
core_type:
|
||||
type_name { TVar $1 }
|
||||
| par(cartesian) { TPar $1 }
|
||||
| par(fun_type) { TPar $1 }
|
||||
| module_name "." type_name {
|
||||
let module_name = $1.value in
|
||||
let type_name = $3.value in
|
||||
@ -218,12 +207,9 @@ core_type:
|
||||
let region = cover $1.region $3.region
|
||||
in TVar {region; value}
|
||||
}
|
||||
| type_name par(nsepseq(core_type,",") { $1 }) {
|
||||
let constr, arg = $1, $2 in
|
||||
let start = constr.region
|
||||
and stop = arg.region in
|
||||
let region = cover start stop
|
||||
in TApp {region; value = constr,arg} }
|
||||
| type_name par(type_args) {
|
||||
let region = cover $1.region $2.region
|
||||
in TApp {region; value = $1,$2} }
|
||||
|
||||
sum_type:
|
||||
ioption("|") nsepseq(variant,"|") {
|
||||
@ -233,7 +219,7 @@ sum_type:
|
||||
|
||||
variant:
|
||||
"<constr>" { {$1 with value={constr=$1; arg=None}} }
|
||||
| "<constr>" "(" cartesian ")" {
|
||||
| "<constr>" "(" fun_type ")" {
|
||||
let region = cover $1.region $4
|
||||
and value = {constr=$1; arg = Some (ghost,$3)}
|
||||
in {region; value} }
|
||||
@ -274,9 +260,6 @@ let_declaration:
|
||||
let region = cover $2 stop
|
||||
in {region; value} }
|
||||
|
||||
es6_func:
|
||||
"=>" expr { $1,$2 }
|
||||
|
||||
let_binding:
|
||||
"<ident>" type_annotation? "=" expr {
|
||||
Scoping.check_reserved_name $1;
|
||||
@ -452,13 +435,12 @@ type_expr_simple:
|
||||
type_annotation_simple:
|
||||
":" type_expr_simple { $1,$2 }
|
||||
|
||||
|
||||
fun_expr:
|
||||
disj_expr_level es6_func {
|
||||
let arrow, body = $2 in
|
||||
let kwd_fun = ghost in
|
||||
let start = expr_to_region $1 in
|
||||
let stop = expr_to_region body in
|
||||
disj_expr_level "=>" expr {
|
||||
let arrow, body = $2, $3
|
||||
and kwd_fun = ghost in
|
||||
let start = expr_to_region $1
|
||||
and stop = expr_to_region body in
|
||||
let region = cover start stop in
|
||||
|
||||
let rec arg_to_pattern = function
|
||||
@ -525,8 +507,8 @@ fun_expr:
|
||||
match type_expr with
|
||||
| TProd {value; _} ->
|
||||
let (hd, rest) = value in
|
||||
let rest = rest @ [(arrow, expr_to_type body)] in
|
||||
nsepseq_to_curry hd rest
|
||||
let rest = rest @ [(arrow, expr_to_type body)]
|
||||
in curry hd rest
|
||||
| e ->
|
||||
TFun {
|
||||
value = e, arrow, expr_to_type body;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -270,7 +270,7 @@ and eval_literal : Ast_typed.literal -> value result = function
|
||||
and eval : Ast_typed.expression -> env -> value result
|
||||
= fun term env ->
|
||||
match term.expression_content with
|
||||
| E_application ({expr1 = f; expr2 = args}) -> (
|
||||
| E_application ({lamb = f; args}) -> (
|
||||
let%bind f' = eval f env in
|
||||
let%bind args' = eval args env in
|
||||
match f' with
|
@ -253,9 +253,9 @@ and transpile_annotated_expression (ae:AST.expression) : expression result =
|
||||
let%bind tv = transpile_environment_element_type ele in
|
||||
return ~tv @@ E_variable (name)
|
||||
)
|
||||
| E_application {expr1;expr2} ->
|
||||
let%bind a = transpile_annotated_expression expr1 in
|
||||
let%bind b = transpile_annotated_expression expr2 in
|
||||
| E_application {lamb; args} ->
|
||||
let%bind a = transpile_annotated_expression lamb in
|
||||
let%bind b = transpile_annotated_expression args in
|
||||
return @@ E_application (a, b)
|
||||
| E_constructor {constructor;element} -> (
|
||||
let%bind param' = transpile_annotated_expression element in
|
||||
@ -550,10 +550,10 @@ and transpile_recursive {fun_name; fun_type; lambda} =
|
||||
E_matching m ->
|
||||
let%bind ty = transpile_type e.type_expression in
|
||||
matching fun_name loop_type shadowed m ty |
|
||||
E_application {expr1;expr2} -> (
|
||||
match expr1.expression_content,shadowed with
|
||||
E_application {lamb;args} -> (
|
||||
match lamb.expression_content,shadowed with
|
||||
E_variable name, false when Var.equal fun_name name ->
|
||||
let%bind expr = transpile_annotated_expression expr2 in
|
||||
let%bind expr = transpile_annotated_expression args in
|
||||
ok @@ Expression.make (E_constant {cons_name=C_LOOP_CONTINUE;arguments=[expr]}) loop_type |
|
||||
_ ->
|
||||
let%bind expr = transpile_annotated_expression e in
|
@ -1,7 +1,7 @@
|
||||
[@@@warning "-45"]
|
||||
|
||||
open Trace
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
|
||||
module Raw = Parser.Cameligo.AST
|
||||
module SMap = Map.String
|
||||
@ -114,8 +114,8 @@ module Errors = struct
|
||||
] in
|
||||
error ~data title message
|
||||
|
||||
let simplifying_expr t =
|
||||
let title () = "Simplifying expression" in
|
||||
let abstracting_expr t =
|
||||
let title () = "abstracting expression" in
|
||||
let message () = "" in
|
||||
let data = [
|
||||
("expression" ,
|
||||
@ -156,7 +156,7 @@ end
|
||||
|
||||
open Errors
|
||||
|
||||
open Operators.Simplify.Cameligo
|
||||
open Operators.Concrete_to_imperative.Cameligo
|
||||
|
||||
let r_split = Location.r_split
|
||||
|
||||
@ -205,7 +205,7 @@ let rec typed_pattern_to_typed_vars : Raw.pattern -> _ = fun pattern ->
|
||||
| Raw.PTyped pt ->
|
||||
let (p,t) = pt.value.pattern,pt.value.type_expr in
|
||||
let%bind p = tuple_pattern_to_vars p in
|
||||
let%bind t = simpl_type_expression t in
|
||||
let%bind t = compile_type_expression t in
|
||||
ok @@ (p,t)
|
||||
| other -> (fail @@ wrong_pattern "parenthetical or type annotation" other)
|
||||
|
||||
@ -213,10 +213,10 @@ and unpar_pattern : Raw.pattern -> Raw.pattern = function
|
||||
| PPar p -> unpar_pattern p.value.inside
|
||||
| _ as p -> p
|
||||
|
||||
and simpl_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
trace (simple_info "simplifying this type expression...") @@
|
||||
and compile_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
trace (simple_info "abstracting this type expression...") @@
|
||||
match te with
|
||||
TPar x -> simpl_type_expression x.value.inside
|
||||
TPar x -> compile_type_expression x.value.inside
|
||||
| TVar v -> (
|
||||
match type_constants v.value with
|
||||
| Ok (s,_) -> ok @@ make_t @@ T_constant s
|
||||
@ -225,8 +225,8 @@ and simpl_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
| TFun x -> (
|
||||
let%bind (type1 , type2) =
|
||||
let (a , _ , b) = x.value in
|
||||
let%bind a = simpl_type_expression a in
|
||||
let%bind b = simpl_type_expression b in
|
||||
let%bind a = compile_type_expression a in
|
||||
let%bind b = compile_type_expression b in
|
||||
ok (a , b)
|
||||
in
|
||||
ok @@ make_t @@ T_arrow {type1;type2}
|
||||
@ -234,18 +234,18 @@ and simpl_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
| TApp x -> (
|
||||
let (name, tuple) = x.value in
|
||||
let lst = npseq_to_list tuple.value.inside in
|
||||
let%bind lst' = bind_map_list simpl_type_expression lst in
|
||||
let%bind lst' = bind_map_list compile_type_expression lst in
|
||||
let%bind cst =
|
||||
trace (unknown_predefined_type name) @@
|
||||
type_operators name.value in
|
||||
t_operator cst lst'
|
||||
)
|
||||
| TProd p -> (
|
||||
let%bind tpl = simpl_list_type_expression @@ npseq_to_list p.value in
|
||||
let%bind tpl = compile_list_type_expression @@ npseq_to_list p.value in
|
||||
ok tpl
|
||||
)
|
||||
| TRecord r ->
|
||||
let aux = fun (x, y) -> let%bind y = simpl_type_expression y in ok (x, y) in
|
||||
let aux = fun (x, y) -> let%bind y = compile_type_expression y in ok (x, y) in
|
||||
let apply (x:Raw.field_decl Raw.reg) =
|
||||
(x.value.field_name.value, x.value.field_type) in
|
||||
let%bind lst =
|
||||
@ -262,7 +262,7 @@ and simpl_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
None -> []
|
||||
| Some (_, TProd product) -> npseq_to_list product.value
|
||||
| Some (_, t_expr) -> [t_expr] in
|
||||
let%bind te = simpl_list_type_expression @@ args in
|
||||
let%bind te = compile_list_type_expression @@ args in
|
||||
ok (v.value.constr.value, te) in
|
||||
let%bind lst = bind_list
|
||||
@@ List.map aux
|
||||
@ -270,18 +270,18 @@ and simpl_type_expression : Raw.type_expr -> type_expression result = fun te ->
|
||||
let m = List.fold_left (fun m (x, y) -> CMap.add (Constructor x) y m) CMap.empty lst in
|
||||
ok @@ make_t @@ T_sum m
|
||||
|
||||
and simpl_list_type_expression (lst:Raw.type_expr list) : type_expression result =
|
||||
and compile_list_type_expression (lst:Raw.type_expr list) : type_expression result =
|
||||
match lst with
|
||||
| [] -> ok @@ t_unit
|
||||
| [hd] -> simpl_type_expression hd
|
||||
| [hd] -> compile_type_expression hd
|
||||
| lst ->
|
||||
let%bind lst = bind_map_list simpl_type_expression lst in
|
||||
let%bind lst = bind_map_list compile_type_expression lst in
|
||||
ok @@ t_tuple lst
|
||||
|
||||
let rec simpl_expression :
|
||||
let rec compile_expression :
|
||||
Raw.expr -> expr result = fun t ->
|
||||
let return x = ok x in
|
||||
let simpl_projection = fun (p:Raw.projection Region.reg) ->
|
||||
let compile_projection = fun (p:Raw.projection Region.reg) ->
|
||||
let (p , loc) = r_split p in
|
||||
let var =
|
||||
let name = Var.of_name p.struct_name.value in
|
||||
@ -296,7 +296,7 @@ let rec simpl_expression :
|
||||
List.map aux @@ npseq_to_list path in
|
||||
return @@ List.fold_left (e_accessor ~loc ) var path'
|
||||
in
|
||||
let simpl_path : Raw.path -> string * label list = fun p ->
|
||||
let compile_path : Raw.path -> string * label list = fun p ->
|
||||
match p with
|
||||
| Raw.Name v -> (v.value , [])
|
||||
| Raw.Path p -> (
|
||||
@ -313,9 +313,9 @@ let rec simpl_expression :
|
||||
(var , path')
|
||||
)
|
||||
in
|
||||
let simpl_update = fun (u:Raw.update Region.reg) ->
|
||||
let compile_update = fun (u:Raw.update Region.reg) ->
|
||||
let (u, loc) = r_split u in
|
||||
let (name, path) = simpl_path u.record in
|
||||
let (name, path) = compile_path u.record in
|
||||
let record = match path with
|
||||
| [] -> e_variable (Var.of_name name)
|
||||
| _ ->
|
||||
@ -325,7 +325,7 @@ let rec simpl_expression :
|
||||
let%bind updates' =
|
||||
let aux (f:Raw.field_path_assign Raw.reg) =
|
||||
let (f,_) = r_split f in
|
||||
let%bind expr = simpl_expression f.field_expr in
|
||||
let%bind expr = compile_expression f.field_expr in
|
||||
ok ( List.map (fun (x: _ Raw.reg) -> x.value) (npseq_to_list f.field_path), expr)
|
||||
in
|
||||
bind_map_list aux @@ npseq_to_list updates
|
||||
@ -342,7 +342,7 @@ let rec simpl_expression :
|
||||
bind_fold_list aux record updates'
|
||||
in
|
||||
|
||||
trace (simplifying_expr t) @@
|
||||
trace (abstracting_expr t) @@
|
||||
match t with
|
||||
Raw.ELetIn e ->
|
||||
let Raw.{kwd_rec; binding; body; attributes; _} = e.value in
|
||||
@ -352,20 +352,20 @@ let rec simpl_expression :
|
||||
| (p, []) ->
|
||||
let%bind variables = tuple_pattern_to_typed_vars p in
|
||||
let%bind ty_opt =
|
||||
bind_map_option (fun (_,te) -> simpl_type_expression te) lhs_type in
|
||||
let%bind rhs = simpl_expression let_rhs in
|
||||
bind_map_option (fun (_,te) -> compile_type_expression te) lhs_type in
|
||||
let%bind rhs = compile_expression let_rhs in
|
||||
let rhs_b = Var.fresh ~name: "rhs" () in
|
||||
let rhs',rhs_b_expr =
|
||||
match ty_opt with
|
||||
None -> rhs, e_variable rhs_b
|
||||
| Some ty -> (e_annotation rhs ty), e_annotation (e_variable rhs_b) ty in
|
||||
let%bind body = simpl_expression body in
|
||||
let%bind body = compile_expression body in
|
||||
let prepare_variable (ty_var: Raw.variable * Raw.type_expr option) =
|
||||
let variable, ty_opt = ty_var in
|
||||
let var_expr = Var.of_name variable.value in
|
||||
let%bind ty_expr_opt =
|
||||
match ty_opt with
|
||||
| Some ty -> bind_map_option simpl_type_expression (Some ty)
|
||||
| Some ty -> bind_map_option compile_type_expression (Some ty)
|
||||
| None -> ok None
|
||||
in ok (var_expr, ty_expr_opt)
|
||||
in
|
||||
@ -397,7 +397,7 @@ let rec simpl_expression :
|
||||
| None -> (match let_rhs with
|
||||
| EFun {value={binders;lhs_type}} ->
|
||||
let f_args = nseq_to_list (binders) in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> simpl_type_expression (snd x)) lhs_type in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> compile_type_expression (snd x)) lhs_type in
|
||||
let%bind ty = bind_map_list typed_pattern_to_typed_vars f_args in
|
||||
let aux acc ty = Option.map (t_function (snd ty)) acc in
|
||||
ok @@ (List.fold_right' aux lhs_type' ty)
|
||||
@ -444,8 +444,8 @@ let rec simpl_expression :
|
||||
end
|
||||
| Raw.EAnnot a ->
|
||||
let Raw.{inside=expr, _, type_expr; _}, loc = r_split a in
|
||||
let%bind expr' = simpl_expression expr in
|
||||
let%bind type_expr' = simpl_type_expression type_expr in
|
||||
let%bind expr' = compile_expression expr in
|
||||
let%bind type_expr' = compile_type_expression type_expr in
|
||||
return @@ e_annotation ~loc expr' type_expr'
|
||||
| EVar c ->
|
||||
let (c',loc) = r_split c in
|
||||
@ -454,7 +454,7 @@ let rec simpl_expression :
|
||||
| Ok (s,_) -> return @@ e_constant s [])
|
||||
| ECall x -> (
|
||||
let ((e1 , e2) , loc) = r_split x in
|
||||
let%bind args = bind_map_list simpl_expression (nseq_to_list e2) in
|
||||
let%bind args = bind_map_list compile_expression (nseq_to_list e2) in
|
||||
let rec chain_application (f: expression) (args: expression list) =
|
||||
match args with
|
||||
| hd :: tl -> chain_application (e_application ~loc f hd) tl
|
||||
@ -468,29 +468,29 @@ let rec simpl_expression :
|
||||
| Ok (s, _) -> return @@ e_constant ~loc s args
|
||||
)
|
||||
| e1 ->
|
||||
let%bind e1' = simpl_expression e1 in
|
||||
let%bind e1' = compile_expression e1 in
|
||||
return @@ chain_application e1' args
|
||||
)
|
||||
| EPar x -> simpl_expression x.value.inside
|
||||
| EPar x -> compile_expression x.value.inside
|
||||
| EUnit reg ->
|
||||
let (_ , loc) = r_split reg in
|
||||
return @@ e_literal ~loc Literal_unit
|
||||
| EBytes x ->
|
||||
let (x , loc) = r_split x in
|
||||
return @@ e_literal ~loc (Literal_bytes (Hex.to_bytes @@ snd x))
|
||||
| ETuple tpl -> simpl_tuple_expression @@ (npseq_to_list tpl.value)
|
||||
| ETuple tpl -> compile_tuple_expression @@ (npseq_to_list tpl.value)
|
||||
| ERecord r ->
|
||||
let (r , loc) = r_split r in
|
||||
let%bind fields = bind_list
|
||||
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = simpl_expression v in ok (k.value, v))
|
||||
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = compile_expression v in ok (k.value, v))
|
||||
@@ List.map (fun (x:Raw.field_assign Raw.reg) -> (x.value.field_name, x.value.field_expr))
|
||||
@@ npseq_to_list r.ne_elements in
|
||||
return @@ e_record_ez ~loc fields
|
||||
| EProj p -> simpl_projection p
|
||||
| EUpdate u -> simpl_update u
|
||||
| EProj p -> compile_projection p
|
||||
| EUpdate u -> compile_update u
|
||||
| EConstr (ESomeApp a) ->
|
||||
let (_, args), loc = r_split a in
|
||||
let%bind arg = simpl_expression args in
|
||||
let%bind arg = compile_expression args in
|
||||
return @@ e_constant ~loc C_SOME [arg]
|
||||
| EConstr (ENone reg) ->
|
||||
let loc = Location.lift reg in
|
||||
@ -502,18 +502,18 @@ let rec simpl_expression :
|
||||
match args with
|
||||
None -> []
|
||||
| Some arg -> [arg] in
|
||||
let%bind arg = simpl_tuple_expression @@ args
|
||||
let%bind arg = compile_tuple_expression @@ args
|
||||
in return @@ e_constructor ~loc c_name arg
|
||||
| EArith (Add c) ->
|
||||
simpl_binop "ADD" c
|
||||
compile_binop "ADD" c
|
||||
| EArith (Sub c) ->
|
||||
simpl_binop "SUB" c
|
||||
compile_binop "SUB" c
|
||||
| EArith (Mult c) ->
|
||||
simpl_binop "TIMES" c
|
||||
compile_binop "TIMES" c
|
||||
| EArith (Div c) ->
|
||||
simpl_binop "DIV" c
|
||||
compile_binop "DIV" c
|
||||
| EArith (Mod c) ->
|
||||
simpl_binop "MOD" c
|
||||
compile_binop "MOD" c
|
||||
| EArith (Int n) -> (
|
||||
let (n , loc) = r_split n in
|
||||
let n = Z.to_int @@ snd @@ n in
|
||||
@ -529,7 +529,7 @@ let rec simpl_expression :
|
||||
let n = Z.to_int @@ snd @@ n in
|
||||
return @@ e_literal ~loc (Literal_mutez n)
|
||||
)
|
||||
| EArith (Neg e) -> simpl_unop "NEG" e
|
||||
| EArith (Neg e) -> compile_unop "NEG" e
|
||||
| EString (String s) -> (
|
||||
let (s , loc) = r_split s in
|
||||
let s' =
|
||||
@ -540,24 +540,24 @@ let rec simpl_expression :
|
||||
)
|
||||
| EString (Cat c) ->
|
||||
let (c, loc) = r_split c in
|
||||
let%bind string_left = simpl_expression c.arg1 in
|
||||
let%bind string_right = simpl_expression c.arg2 in
|
||||
let%bind string_left = compile_expression c.arg1 in
|
||||
let%bind string_right = compile_expression c.arg2 in
|
||||
return @@ e_string_cat ~loc string_left string_right
|
||||
| ELogic l -> simpl_logic_expression l
|
||||
| EList l -> simpl_list_expression l
|
||||
| ELogic l -> compile_logic_expression l
|
||||
| EList l -> compile_list_expression l
|
||||
| ECase c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind e = simpl_expression c.expr in
|
||||
let%bind e = compile_expression c.expr in
|
||||
let%bind lst =
|
||||
let aux (x : Raw.expr Raw.case_clause) =
|
||||
let%bind expr = simpl_expression x.rhs in
|
||||
let%bind expr = compile_expression x.rhs in
|
||||
ok (x.pattern, expr) in
|
||||
bind_list
|
||||
@@ List.map aux
|
||||
@@ List.map get_value
|
||||
@@ npseq_to_list c.cases.value in
|
||||
let default_action () =
|
||||
let%bind cases = simpl_cases lst in
|
||||
let%bind cases = compile_cases lst in
|
||||
return @@ e_matching ~loc e cases in
|
||||
(* Hack to take care of patterns introduced by `parser/cameligo/Parser.mly` in "norm_fun_expr". TODO: Still needed? *)
|
||||
match lst with
|
||||
@ -571,7 +571,7 @@ let rec simpl_expression :
|
||||
match x'.pattern with
|
||||
| Raw.PVar y ->
|
||||
let var_name = Var.of_name y.value in
|
||||
let%bind type_expr = simpl_type_expression x'.type_expr in
|
||||
let%bind type_expr = compile_type_expression x'.type_expr in
|
||||
return @@ e_let_in (var_name , Some type_expr) false false e rhs
|
||||
| _ -> default_action ()
|
||||
)
|
||||
@ -581,29 +581,29 @@ let rec simpl_expression :
|
||||
)
|
||||
| _ -> default_action ()
|
||||
)
|
||||
| EFun lamb -> simpl_fun lamb
|
||||
| EFun lamb -> compile_fun lamb
|
||||
| ESeq s -> (
|
||||
let (s , loc) = r_split s in
|
||||
let items : Raw.expr list = pseq_to_list s.elements in
|
||||
(match items with
|
||||
[] -> return @@ e_skip ~loc ()
|
||||
| expr::more ->
|
||||
let expr' = simpl_expression expr in
|
||||
let expr' = compile_expression expr in
|
||||
let apply (e1: Raw.expr) (e2: expression Trace.result) =
|
||||
let%bind a = simpl_expression e1 in
|
||||
let%bind a = compile_expression e1 in
|
||||
let%bind e2' = e2 in
|
||||
return @@ e_sequence a e2'
|
||||
in List.fold_right apply more expr')
|
||||
)
|
||||
| ECond c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind expr = simpl_expression c.test in
|
||||
let%bind match_true = simpl_expression c.ifso in
|
||||
let%bind match_false = simpl_expression c.ifnot in
|
||||
let%bind expr = compile_expression c.test in
|
||||
let%bind match_true = compile_expression c.ifso in
|
||||
let%bind match_false = compile_expression c.ifnot in
|
||||
return @@ e_matching ~loc expr (Match_bool {match_true; match_false})
|
||||
)
|
||||
|
||||
and simpl_fun lamb' : expr result =
|
||||
and compile_fun lamb' : expr result =
|
||||
let return x = ok x in
|
||||
let (lamb , loc) = r_split lamb' in
|
||||
let%bind params' =
|
||||
@ -649,7 +649,7 @@ and simpl_fun lamb' : expr result =
|
||||
| _ , None ->
|
||||
fail @@ untyped_fun_param var
|
||||
| _ , Some ty -> (
|
||||
let%bind ty' = simpl_type_expression ty in
|
||||
let%bind ty' = compile_type_expression ty in
|
||||
ok (var , ty')
|
||||
)
|
||||
in
|
||||
@ -700,8 +700,8 @@ and simpl_fun lamb' : expr result =
|
||||
in
|
||||
let%bind (body , body_type) = expr_to_typed_expr body in
|
||||
let%bind output_type =
|
||||
bind_map_option simpl_type_expression body_type in
|
||||
let%bind body = simpl_expression body in
|
||||
bind_map_option compile_type_expression body_type in
|
||||
let%bind body = compile_expression body in
|
||||
let rec layer_arguments (arguments: (Raw.variable * type_expression) list) =
|
||||
match arguments with
|
||||
| hd :: tl ->
|
||||
@ -714,7 +714,7 @@ and simpl_fun lamb' : expr result =
|
||||
return @@ ret_lamb
|
||||
|
||||
|
||||
and simpl_logic_expression ?te_annot (t:Raw.logic_expr) : expr result =
|
||||
and compile_logic_expression ?te_annot (t:Raw.logic_expr) : expr result =
|
||||
let return x = ok @@ make_option_typed x te_annot in
|
||||
match t with
|
||||
| BoolExpr (False reg) -> (
|
||||
@ -726,61 +726,61 @@ and simpl_logic_expression ?te_annot (t:Raw.logic_expr) : expr result =
|
||||
return @@ e_literal ~loc (Literal_bool true)
|
||||
)
|
||||
| BoolExpr (Or b) ->
|
||||
simpl_binop "OR" b
|
||||
compile_binop "OR" b
|
||||
| BoolExpr (And b) ->
|
||||
simpl_binop "AND" b
|
||||
compile_binop "AND" b
|
||||
| BoolExpr (Not b) ->
|
||||
simpl_unop "NOT" b
|
||||
compile_unop "NOT" b
|
||||
| CompExpr (Lt c) ->
|
||||
simpl_binop "LT" c
|
||||
compile_binop "LT" c
|
||||
| CompExpr (Gt c) ->
|
||||
simpl_binop "GT" c
|
||||
compile_binop "GT" c
|
||||
| CompExpr (Leq c) ->
|
||||
simpl_binop "LE" c
|
||||
compile_binop "LE" c
|
||||
| CompExpr (Geq c) ->
|
||||
simpl_binop "GE" c
|
||||
compile_binop "GE" c
|
||||
| CompExpr (Equal c) ->
|
||||
simpl_binop "EQ" c
|
||||
compile_binop "EQ" c
|
||||
| CompExpr (Neq c) ->
|
||||
simpl_binop "NEQ" c
|
||||
compile_binop "NEQ" c
|
||||
|
||||
and simpl_list_expression (t:Raw.list_expr) : expression result =
|
||||
and compile_list_expression (t:Raw.list_expr) : expression result =
|
||||
let return x = ok @@ x in
|
||||
match t with
|
||||
ECons c -> simpl_binop "CONS" c
|
||||
ECons c -> compile_binop "CONS" c
|
||||
| EListComp lst -> (
|
||||
let (lst , loc) = r_split lst in
|
||||
let%bind lst' =
|
||||
bind_map_list simpl_expression @@
|
||||
bind_map_list compile_expression @@
|
||||
pseq_to_list lst.elements in
|
||||
return @@ e_list ~loc lst'
|
||||
)
|
||||
|
||||
and simpl_binop (name:string) (t:_ Raw.bin_op Region.reg) : expression result =
|
||||
and compile_binop (name:string) (t:_ Raw.bin_op Region.reg) : expression result =
|
||||
let return x = ok @@ x in
|
||||
let (args , loc) = r_split t in
|
||||
let%bind a = simpl_expression args.arg1 in
|
||||
let%bind b = simpl_expression args.arg2 in
|
||||
let%bind a = compile_expression args.arg1 in
|
||||
let%bind b = compile_expression args.arg2 in
|
||||
let%bind name = constants name in
|
||||
return @@ e_constant ~loc name [ a ; b ]
|
||||
|
||||
and simpl_unop (name:string) (t:_ Raw.un_op Region.reg) : expression result =
|
||||
and compile_unop (name:string) (t:_ Raw.un_op Region.reg) : expression result =
|
||||
let return x = ok @@ x in
|
||||
let (t , loc) = r_split t in
|
||||
let%bind a = simpl_expression t.arg in
|
||||
let%bind a = compile_expression t.arg in
|
||||
let%bind name = constants name in
|
||||
return @@ e_constant ~loc name [ a ]
|
||||
|
||||
and simpl_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
||||
and compile_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
||||
let return x = ok @@ x in
|
||||
match lst with
|
||||
| [] -> return @@ e_literal ?loc Literal_unit
|
||||
| [hd] -> simpl_expression hd
|
||||
| [hd] -> compile_expression hd
|
||||
| lst ->
|
||||
let%bind lst = bind_list @@ List.map simpl_expression lst in
|
||||
let%bind lst = bind_list @@ List.map compile_expression lst in
|
||||
return @@ e_tuple ?loc lst
|
||||
|
||||
and simpl_declaration : Raw.declaration -> declaration Location.wrap list result =
|
||||
and compile_declaration : Raw.declaration -> declaration Location.wrap list result =
|
||||
fun t ->
|
||||
let open! Raw in
|
||||
let loc : 'a . 'a Raw.reg -> _ -> _ =
|
||||
@ -788,7 +788,7 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
match t with
|
||||
| TypeDecl x ->
|
||||
let {name;type_expr} : Raw.type_decl = x.value in
|
||||
let%bind type_expression = simpl_type_expression type_expr in
|
||||
let%bind type_expression = compile_type_expression type_expr in
|
||||
ok @@ [loc x @@ Declaration_type (Var.of_name name.value , type_expression)]
|
||||
| Let x -> (
|
||||
let (_, recursive, let_binding, attributes), _ = r_split x in
|
||||
@ -798,17 +798,16 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
let (hd, _) = binders in
|
||||
match hd with
|
||||
| PTuple pt ->
|
||||
let process_variable (var_pair: pattern * Raw.expr) :
|
||||
Ast_simplified.declaration Location.wrap result =
|
||||
let process_variable (var_pair: pattern * Raw.expr) =
|
||||
(let (par_var, rhs_expr) = var_pair in
|
||||
let%bind (v, v_type) = pattern_to_typed_var par_var in
|
||||
let%bind v_type_expression =
|
||||
match v_type with
|
||||
| Some v_type -> ok (to_option (simpl_type_expression v_type))
|
||||
| Some v_type -> ok (to_option (compile_type_expression v_type))
|
||||
| None -> ok None
|
||||
in
|
||||
let%bind simpl_rhs_expr = simpl_expression rhs_expr in
|
||||
ok @@ loc x @@ Declaration_constant (Var.of_name v.value, v_type_expression, inline, simpl_rhs_expr) )
|
||||
let%bind compile_rhs_expr = compile_expression rhs_expr in
|
||||
ok @@ loc x @@ Declaration_constant (Var.of_name v.value, v_type_expression, inline, compile_rhs_expr) )
|
||||
in let%bind variables = ok @@ npseq_to_list pt.value
|
||||
in let%bind expr_bind_lst =
|
||||
match let_rhs with
|
||||
@ -840,7 +839,7 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
gen_access_tuple name ~i: (i + 1) ~accesses
|
||||
in ok (gen_access_tuple name)
|
||||
(* TODO: Improve this error message *)
|
||||
| other -> fail @@ simplifying_expr other
|
||||
| other -> fail @@ abstracting_expr other
|
||||
in let%bind decls =
|
||||
(* TODO: Rewrite the gen_access_tuple so there's no List.rev *)
|
||||
bind_map_list process_variable (List.combine variables (List.rev expr_bind_lst))
|
||||
@ -848,7 +847,7 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
| PPar {region = _ ; value = { lpar = _ ; inside = pt; rpar = _; } } ->
|
||||
(* Extract parenthetical multi-bind *)
|
||||
let (wild, recursive, _, attributes) = fst @@ r_split x in
|
||||
simpl_declaration
|
||||
compile_declaration
|
||||
(Let {
|
||||
region = x.region;
|
||||
value = (wild, recursive, {binders = (pt, []);
|
||||
@ -863,7 +862,7 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
let%bind var = pattern_to_var hd in
|
||||
ok (var , tl)
|
||||
in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> simpl_type_expression (snd x)) lhs_type in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> compile_type_expression (snd x)) lhs_type in
|
||||
let%bind let_rhs,lhs_type = match args with
|
||||
| [] -> ok (let_rhs, lhs_type')
|
||||
| param1::others ->
|
||||
@ -879,12 +878,12 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
let aux acc ty = Option.map (t_function (snd ty)) acc in
|
||||
ok (Raw.EFun {region=Region.ghost ; value=fun_},List.fold_right' aux lhs_type' ty)
|
||||
in
|
||||
let%bind rhs' = simpl_expression let_rhs in
|
||||
let%bind rhs' = compile_expression let_rhs in
|
||||
let%bind lhs_type = match lhs_type with
|
||||
| None -> (match let_rhs with
|
||||
| EFun {value={binders;lhs_type}} ->
|
||||
let f_args = nseq_to_list (binders) in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> simpl_type_expression (snd x)) lhs_type in
|
||||
let%bind lhs_type' = bind_map_option (fun x -> compile_type_expression (snd x)) lhs_type in
|
||||
let%bind ty = bind_map_list typed_pattern_to_typed_vars f_args in
|
||||
let aux acc ty = Option.map (t_function (snd ty)) acc in
|
||||
ok @@ (List.fold_right' aux lhs_type' ty)
|
||||
@ -907,7 +906,7 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap list result
|
||||
ok @@ [loc x @@ (Declaration_constant (Var.of_name var.value , lhs_type , inline, rhs'))]
|
||||
)
|
||||
|
||||
and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching_content result =
|
||||
and compile_cases : type a . (Raw.pattern * a) list -> (a, unit) matching_content result =
|
||||
fun t ->
|
||||
let open Raw in
|
||||
let rec get_var (t:Raw.pattern) =
|
||||
@ -1027,6 +1026,6 @@ and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching_content
|
||||
| _ -> simple_fail "bad option pattern"
|
||||
in bind_or (as_option () , as_variant ())
|
||||
|
||||
let simpl_program : Raw.ast -> program result = fun t ->
|
||||
let%bind decls = bind_map_list simpl_declaration @@ nseq_to_list t.decl in
|
||||
let compile_program : Raw.ast -> program result = fun t ->
|
||||
let%bind decls = bind_map_list compile_declaration @@ nseq_to_list t.decl in
|
||||
ok @@ List.concat @@ decls
|
@ -1,8 +1,7 @@
|
||||
[@@@warning "-45"]
|
||||
|
||||
open Trace
|
||||
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
|
||||
module Raw = Parser.Cameligo.AST
|
||||
module SMap = Map.String
|
||||
@ -29,7 +28,7 @@ module Errors : sig
|
||||
val unsupported_tuple_pattern : Raw.pattern -> unit -> error
|
||||
val unsupported_cst_constr : Raw.pattern -> unit -> error
|
||||
val unsupported_non_var_pattern : Raw.pattern -> unit -> error
|
||||
val simplifying_expr : Raw.expr -> unit -> error
|
||||
val abstracting_expr : Raw.expr -> unit -> error
|
||||
val only_constructors : Raw.pattern -> unit -> error
|
||||
val unsupported_sugared_lists : Raw.wild -> unit -> error
|
||||
val bad_set_definition : unit -> error
|
||||
@ -46,18 +45,18 @@ val pattern_to_var : Raw.pattern -> Raw.variable result
|
||||
val pattern_to_typed_var : Raw.pattern -> ( Raw.variable * Raw.type_expr option ) result
|
||||
val expr_to_typed_expr : Raw.expr -> ( Raw.expr * Raw.type_expr option ) result
|
||||
val patterns_to_var : Raw.pattern list -> Raw.variable result
|
||||
val simpl_type_expression : Raw.type_expr -> type_expression result
|
||||
val simpl_list_type_expression : Raw.type_expr list -> type_expression result
|
||||
val compile_type_expression : Raw.type_expr -> type_expression result
|
||||
val compile_list_type_expression : Raw.type_expr list -> type_expression result
|
||||
*)
|
||||
val simpl_expression : Raw.expr -> expr result
|
||||
val compile_expression : Raw.expr -> expr result
|
||||
(*
|
||||
val simpl_fun : Raw.fun_expr Raw.reg -> expr result
|
||||
val simpl_logic_expression : ?te_annot:type_expression -> Raw.logic_expr -> expr result
|
||||
val simpl_list_expression : Raw.list_expr -> expression result
|
||||
val simpl_binop : string -> Raw.wild Raw.bin_op Region.reg -> expression result
|
||||
val simpl_unop : string -> Raw.wild Raw.un_op Region.reg -> expression result
|
||||
val simpl_tuple_expression : ?loc:Location.t -> Raw.expr list -> expression result
|
||||
val simpl_declaration : Raw.declaration -> declaration Location.wrap result
|
||||
val simpl_cases : (Raw.pattern * 'a) list -> 'a matching result
|
||||
val compile_fun : Raw.fun_expr Raw.reg -> expr result
|
||||
val compile_logic_expression : ?te_annot:type_expression -> Raw.logic_expr -> expr result
|
||||
val compile_list_expression : Raw.list_expr -> expression result
|
||||
val compile_binop : string -> Raw.wild Raw.bin_op Region.reg -> expression result
|
||||
val compile_unop : string -> Raw.wild Raw.un_op Region.reg -> expression result
|
||||
val compile_tuple_expression : ?loc:Location.t -> Raw.expr list -> expression result
|
||||
val compile_declaration : Raw.declaration -> declaration Location.wrap result
|
||||
val compile_cases : (Raw.pattern * 'a) list -> 'a matching result
|
||||
*)
|
||||
val simpl_program : Raw.ast -> program result
|
||||
val compile_program : Raw.ast -> program result
|
@ -1,7 +1,7 @@
|
||||
open Trace
|
||||
open Function
|
||||
module I = Parser.Cameligo.Ast
|
||||
module O = Ast_simplified
|
||||
module O = Ast_core
|
||||
open O.Combinators
|
||||
|
||||
let unwrap : type a . a Location.wrap -> a = Location.unwrap
|
||||
@ -252,7 +252,7 @@ and expression_main : I.expression_main Location.wrap -> O.expression result = f
|
||||
let%bind (a' , b') = bind_map_pair expression_main ab in
|
||||
return @@ e_binop name a' b' in
|
||||
let error_main =
|
||||
let title () = "simplifying main_expression" in
|
||||
let title () = "abstracting main_expression" in
|
||||
let content () = Format.asprintf "%a" I.pp_expression_main (unwrap em) in
|
||||
error title content
|
||||
in
|
@ -1,14 +1,14 @@
|
||||
(library
|
||||
(name simplify)
|
||||
(public_name ligo.simplify)
|
||||
(name concrete_to_imperative)
|
||||
(public_name ligo.concrete_to_imperative)
|
||||
(libraries
|
||||
simple-utils
|
||||
tezos-utils
|
||||
parser
|
||||
ast_simplified
|
||||
self_ast_simplified
|
||||
ast_imperative
|
||||
self_ast_imperative
|
||||
operators)
|
||||
(modules cameligo pascaligo simplify)
|
||||
(modules cameligo pascaligo concrete_to_imperative)
|
||||
(preprocess
|
||||
(pps
|
||||
ppx_let
|
@ -1,5 +1,5 @@
|
||||
open Trace
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
|
||||
module Raw = Parser.Pascaligo.AST
|
||||
module SMap = Map.String
|
||||
@ -15,7 +15,7 @@ let pseq_to_list = function
|
||||
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
||||
|
||||
and repair_mutable_variable_in_matching (for_body : expression) (element_names : expression_variable list) (env : expression_variable) =
|
||||
let%bind captured_names = Self_ast_simplified.fold_map_expression
|
||||
let%bind captured_names = Self_ast_imperative.fold_map_expression
|
||||
(* TODO : these should use Variables sets *)
|
||||
(fun (decl_var,free_var : expression_variable list * expression_variable list) (ass_exp : expression) ->
|
||||
match ass_exp.expression_content with
|
||||
@ -47,7 +47,7 @@ and repair_mutable_variable_in_matching (for_body : expression) (element_names :
|
||||
ok @@ captured_names
|
||||
|
||||
and repair_mutable_variable_in_loops (for_body : expression) (element_names : expression_variable list) (env : expression_variable) =
|
||||
let%bind captured_names = Self_ast_simplified.fold_map_expression
|
||||
let%bind captured_names = Self_ast_imperative.fold_map_expression
|
||||
(* TODO : these should use Variables sets *)
|
||||
(fun (decl_var,free_var : expression_variable list * expression_variable list) (ass_exp : expression) ->
|
||||
match ass_exp.expression_content with
|
||||
@ -186,7 +186,7 @@ module Errors = struct
|
||||
|
||||
(* Logging *)
|
||||
|
||||
let simplifying_instruction t =
|
||||
let abstracting_instruction t =
|
||||
let title () = "\nSimplifiying instruction" in
|
||||
let message () = "" in
|
||||
(** TODO: The labelled arguments should be flowing from the CLI. *)
|
||||
@ -199,14 +199,14 @@ module Errors = struct
|
||||
end
|
||||
|
||||
open Errors
|
||||
open Operators.Simplify.Pascaligo
|
||||
open Operators.Concrete_to_imperative.Pascaligo
|
||||
|
||||
let r_split = Location.r_split
|
||||
|
||||
(* Statements can't be simplified in isolation. [a ; b ; c] can get
|
||||
simplified either as [let x = expr in (b ; c)] if [a] is a [const x
|
||||
= expr] declaration or as [sequence(a, sequence(b, c))] for
|
||||
everything else. Because of this, simplifying sequences depend on
|
||||
everything else. Because of this, abstracting sequences depend on
|
||||
their contents. To avoid peeking in their contents, we instead
|
||||
simplify sequences elements as functions from their next elements
|
||||
to the actual result.
|
||||
@ -229,9 +229,9 @@ let return_statement expr = ok @@ fun expr'_opt ->
|
||||
| Some expr' -> ok @@ e_sequence expr expr'
|
||||
|
||||
|
||||
let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
||||
let rec compile_type_expression (t:Raw.type_expr) : type_expression result =
|
||||
match t with
|
||||
TPar x -> simpl_type_expression x.value.inside
|
||||
TPar x -> compile_type_expression x.value.inside
|
||||
| TVar v -> (
|
||||
match type_constants v.value with
|
||||
| Ok (s,_) -> ok @@ make_t @@ T_constant s
|
||||
@ -240,25 +240,25 @@ let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
||||
| TFun x -> (
|
||||
let%bind (a , b) =
|
||||
let (a , _ , b) = x.value in
|
||||
bind_map_pair simpl_type_expression (a , b) in
|
||||
bind_map_pair compile_type_expression (a , b) in
|
||||
ok @@ make_t @@ T_arrow {type1=a;type2=b}
|
||||
)
|
||||
| TApp x ->
|
||||
let (name, tuple) = x.value in
|
||||
let lst = npseq_to_list tuple.value.inside in
|
||||
let%bind lst =
|
||||
bind_list @@ List.map simpl_type_expression lst in (** TODO: fix constant and operator*)
|
||||
bind_list @@ List.map compile_type_expression lst in (** TODO: fix constant and operator*)
|
||||
let%bind cst =
|
||||
trace (unknown_predefined_type name) @@
|
||||
type_operators name.value in
|
||||
t_operator cst lst
|
||||
| TProd p ->
|
||||
let%bind tpl = simpl_list_type_expression
|
||||
let%bind tpl = compile_list_type_expression
|
||||
@@ npseq_to_list p.value in
|
||||
ok tpl
|
||||
| TRecord r ->
|
||||
let aux = fun (x, y) ->
|
||||
let%bind y = simpl_type_expression y in
|
||||
let%bind y = compile_type_expression y in
|
||||
ok (x, y)
|
||||
in
|
||||
let apply =
|
||||
@ -276,7 +276,7 @@ let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
||||
None -> []
|
||||
| Some (_, TProd product) -> npseq_to_list product.value
|
||||
| Some (_, t_expr) -> [t_expr] in
|
||||
let%bind te = simpl_list_type_expression @@ args in
|
||||
let%bind te = compile_list_type_expression @@ args in
|
||||
ok (v.value.constr.value, te)
|
||||
in
|
||||
let%bind lst = bind_list
|
||||
@ -285,15 +285,15 @@ let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
||||
let m = List.fold_left (fun m (x, y) -> CMap.add (Constructor x) y m) CMap.empty lst in
|
||||
ok @@ make_t @@ T_sum m
|
||||
|
||||
and simpl_list_type_expression (lst:Raw.type_expr list) : type_expression result =
|
||||
and compile_list_type_expression (lst:Raw.type_expr list) : type_expression result =
|
||||
match lst with
|
||||
| [] -> ok @@ t_unit
|
||||
| [hd] -> simpl_type_expression hd
|
||||
| [hd] -> compile_type_expression hd
|
||||
| lst ->
|
||||
let%bind lst = bind_list @@ List.map simpl_type_expression lst in
|
||||
let%bind lst = bind_list @@ List.map compile_type_expression lst in
|
||||
ok @@ t_tuple lst
|
||||
|
||||
let simpl_projection : Raw.projection Region.reg -> _ = fun p ->
|
||||
let compile_projection : Raw.projection Region.reg -> _ = fun p ->
|
||||
let (p' , loc) = r_split p in
|
||||
let var =
|
||||
let name = Var.of_name p'.struct_name.value in
|
||||
@ -309,13 +309,13 @@ let simpl_projection : Raw.projection Region.reg -> _ = fun p ->
|
||||
ok @@ List.fold_left (e_accessor ~loc) var path'
|
||||
|
||||
|
||||
let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let rec compile_expression (t:Raw.expr) : expr result =
|
||||
let return x = ok x in
|
||||
match t with
|
||||
| EAnnot a -> (
|
||||
let ((expr , type_expr) , loc) = r_split a in
|
||||
let%bind expr' = simpl_expression expr in
|
||||
let%bind type_expr' = simpl_type_expression type_expr in
|
||||
let%bind expr' = compile_expression expr in
|
||||
let%bind type_expr' = compile_type_expression type_expr in
|
||||
return @@ e_annotation ~loc expr' type_expr'
|
||||
)
|
||||
| EVar c -> (
|
||||
@ -333,19 +333,19 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let (f_name , f_loc) = r_split name in
|
||||
match constants f_name with
|
||||
| Error _ ->
|
||||
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
||||
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
||||
return @@ e_application ~loc (e_variable ~loc:f_loc (Var.of_name f_name)) arg
|
||||
| Ok (s,_) ->
|
||||
let%bind lst = bind_map_list simpl_expression args' in
|
||||
let%bind lst = bind_map_list compile_expression args' in
|
||||
return @@ e_constant ~loc s lst
|
||||
)
|
||||
| f -> (
|
||||
let%bind f' = simpl_expression f in
|
||||
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
||||
let%bind f' = compile_expression f in
|
||||
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
||||
return @@ e_application ~loc f' arg
|
||||
)
|
||||
)
|
||||
| EPar x -> simpl_expression x.value.inside
|
||||
| EPar x -> compile_expression x.value.inside
|
||||
| EUnit reg ->
|
||||
let loc = Location.lift reg in
|
||||
return @@ e_literal ~loc Literal_unit
|
||||
@ -354,16 +354,16 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
return @@ e_literal ~loc (Literal_bytes (Hex.to_bytes @@ snd x'))
|
||||
| ETuple tpl ->
|
||||
let (tpl' , loc) = r_split tpl in
|
||||
simpl_tuple_expression ~loc @@ npseq_to_list tpl'.inside
|
||||
compile_tuple_expression ~loc @@ npseq_to_list tpl'.inside
|
||||
| ERecord r ->
|
||||
let%bind fields = bind_list
|
||||
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = simpl_expression v in ok (k.value, v))
|
||||
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = compile_expression v in ok (k.value, v))
|
||||
@@ List.map (fun (x:Raw.field_assign Raw.reg) -> (x.value.field_name, x.value.field_expr))
|
||||
@@ npseq_to_list r.value.ne_elements in
|
||||
let aux prev (k, v) = SMap.add k v prev in
|
||||
return @@ e_record (List.fold_left aux SMap.empty fields)
|
||||
| EProj p -> simpl_projection p
|
||||
| EUpdate u -> simpl_update u
|
||||
| EProj p -> compile_projection p
|
||||
| EUpdate u -> compile_update u
|
||||
| EConstr (ConstrApp c) -> (
|
||||
let ((c, args) , loc) = r_split c in
|
||||
match args with
|
||||
@ -372,7 +372,7 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
| Some args ->
|
||||
let args, args_loc = r_split args in
|
||||
let%bind arg =
|
||||
simpl_tuple_expression ~loc:args_loc
|
||||
compile_tuple_expression ~loc:args_loc
|
||||
@@ npseq_to_list args.inside in
|
||||
return @@ e_constructor ~loc c.value arg
|
||||
)
|
||||
@ -380,7 +380,7 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let ((_, args) , loc) = r_split a in
|
||||
let (args , args_loc) = r_split args in
|
||||
let%bind arg =
|
||||
simpl_tuple_expression ~loc:args_loc
|
||||
compile_tuple_expression ~loc:args_loc
|
||||
@@ npseq_to_list args.inside in
|
||||
return @@ e_constant ~loc C_SOME [arg]
|
||||
| EConstr (NoneExpr reg) -> (
|
||||
@ -388,15 +388,15 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
return @@ e_none ~loc ()
|
||||
)
|
||||
| EArith (Add c) ->
|
||||
simpl_binop "ADD" c
|
||||
compile_binop "ADD" c
|
||||
| EArith (Sub c) ->
|
||||
simpl_binop "SUB" c
|
||||
compile_binop "SUB" c
|
||||
| EArith (Mult c) ->
|
||||
simpl_binop "TIMES" c
|
||||
compile_binop "TIMES" c
|
||||
| EArith (Div c) ->
|
||||
simpl_binop "DIV" c
|
||||
compile_binop "DIV" c
|
||||
| EArith (Mod c) ->
|
||||
simpl_binop "MOD" c
|
||||
compile_binop "MOD" c
|
||||
| EArith (Int n) -> (
|
||||
let (n , loc) = r_split n in
|
||||
let n = Z.to_int @@ snd n in
|
||||
@ -412,7 +412,7 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let n = Z.to_int @@ snd @@ n in
|
||||
return @@ e_literal ~loc (Literal_mutez n)
|
||||
)
|
||||
| EArith (Neg e) -> simpl_unop "NEG" e
|
||||
| EArith (Neg e) -> compile_unop "NEG" e
|
||||
| EString (String s) ->
|
||||
let (s , loc) = r_split s in
|
||||
let s' =
|
||||
@ -422,17 +422,17 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
return @@ e_literal ~loc (Literal_string s')
|
||||
| EString (Cat bo) ->
|
||||
let (bo , loc) = r_split bo in
|
||||
let%bind sl = simpl_expression bo.arg1 in
|
||||
let%bind sr = simpl_expression bo.arg2 in
|
||||
let%bind sl = compile_expression bo.arg1 in
|
||||
let%bind sr = compile_expression bo.arg2 in
|
||||
return @@ e_string_cat ~loc sl sr
|
||||
| ELogic l -> simpl_logic_expression l
|
||||
| EList l -> simpl_list_expression l
|
||||
| ESet s -> simpl_set_expression s
|
||||
| ELogic l -> compile_logic_expression l
|
||||
| EList l -> compile_list_expression l
|
||||
| ESet s -> compile_set_expression s
|
||||
| ECond c ->
|
||||
let (c , loc) = r_split c in
|
||||
let%bind expr = simpl_expression c.test in
|
||||
let%bind match_true = simpl_expression c.ifso in
|
||||
let%bind match_false = simpl_expression c.ifnot in
|
||||
let%bind expr = compile_expression c.test in
|
||||
let%bind match_true = compile_expression c.ifso in
|
||||
let%bind match_false = compile_expression c.ifnot in
|
||||
let match_expr = e_matching expr ~loc (Match_bool {match_true; match_false}) in
|
||||
let env = Var.fresh () in
|
||||
let%bind (_, match_expr) = repair_mutable_variable_in_matching match_expr [] env in
|
||||
@ -440,16 +440,16 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
|
||||
| ECase c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind e = simpl_expression c.expr in
|
||||
let%bind e = compile_expression c.expr in
|
||||
let%bind lst =
|
||||
let aux (x : Raw.expr Raw.case_clause) =
|
||||
let%bind expr = simpl_expression x.rhs in
|
||||
let%bind expr = compile_expression x.rhs in
|
||||
ok (x.pattern, expr) in
|
||||
bind_list
|
||||
@@ List.map aux
|
||||
@@ List.map get_value
|
||||
@@ npseq_to_list c.cases.value in
|
||||
let%bind cases = simpl_cases lst in
|
||||
let%bind cases = compile_cases lst in
|
||||
let match_expr = e_matching ~loc e cases in
|
||||
let env = Var.fresh () in
|
||||
let%bind (_, match_expr) = repair_mutable_variable_in_matching match_expr [] env in
|
||||
@ -461,8 +461,8 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
||||
let aux : Raw.binding -> (expression * expression) result =
|
||||
fun b ->
|
||||
let%bind src = simpl_expression b.source in
|
||||
let%bind dst = simpl_expression b.image in
|
||||
let%bind src = compile_expression b.source in
|
||||
let%bind dst = compile_expression b.image in
|
||||
ok (src, dst) in
|
||||
bind_map_list aux lst in
|
||||
return @@ e_map ~loc lst
|
||||
@ -473,8 +473,8 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
||||
let aux : Raw.binding -> (expression * expression) result =
|
||||
fun b ->
|
||||
let%bind src = simpl_expression b.source in
|
||||
let%bind dst = simpl_expression b.image in
|
||||
let%bind src = compile_expression b.source in
|
||||
let%bind dst = compile_expression b.image in
|
||||
ok (src, dst) in
|
||||
bind_map_list aux lst in
|
||||
return @@ e_big_map ~loc lst
|
||||
@ -486,20 +486,20 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
||||
let (v , loc) = r_split v in
|
||||
return @@ e_variable ~loc (Var.of_name v)
|
||||
)
|
||||
| Path p -> simpl_projection p
|
||||
| Path p -> compile_projection p
|
||||
in
|
||||
let%bind index = simpl_expression lu.index.value.inside in
|
||||
let%bind index = compile_expression lu.index.value.inside in
|
||||
return @@ e_look_up ~loc path index
|
||||
)
|
||||
| EFun f ->
|
||||
let (f , loc) = r_split f in
|
||||
let%bind (_ty_opt, f') = simpl_fun_expression ~loc f
|
||||
let%bind (_ty_opt, f') = compile_fun_expression ~loc f
|
||||
in return @@ f'
|
||||
|
||||
|
||||
and simpl_update = fun (u:Raw.update Region.reg) ->
|
||||
and compile_update = fun (u:Raw.update Region.reg) ->
|
||||
let (u, loc) = r_split u in
|
||||
let (name, path) = simpl_path u.record in
|
||||
let (name, path) = compile_path u.record in
|
||||
let record = match path with
|
||||
| [] -> e_variable (Var.of_name name)
|
||||
| _ -> e_accessor_list (e_variable (Var.of_name name)) path in
|
||||
@ -507,7 +507,7 @@ and simpl_update = fun (u:Raw.update Region.reg) ->
|
||||
let%bind updates' =
|
||||
let aux (f:Raw.field_path_assign Raw.reg) =
|
||||
let (f,_) = r_split f in
|
||||
let%bind expr = simpl_expression f.field_expr in
|
||||
let%bind expr = compile_expression f.field_expr in
|
||||
ok ( List.map (fun (x: _ Raw.reg) -> x.value) (npseq_to_list f.field_path), expr)
|
||||
in
|
||||
bind_map_list aux @@ npseq_to_list updates
|
||||
@ -523,7 +523,7 @@ and simpl_update = fun (u:Raw.update Region.reg) ->
|
||||
aux ur path in
|
||||
bind_fold_list aux record updates'
|
||||
|
||||
and simpl_logic_expression (t:Raw.logic_expr) : expression result =
|
||||
and compile_logic_expression (t:Raw.logic_expr) : expression result =
|
||||
let return x = ok x in
|
||||
match t with
|
||||
| BoolExpr (False reg) -> (
|
||||
@ -535,92 +535,92 @@ and simpl_logic_expression (t:Raw.logic_expr) : expression result =
|
||||
return @@ e_literal ~loc (Literal_bool true)
|
||||
)
|
||||
| BoolExpr (Or b) ->
|
||||
simpl_binop "OR" b
|
||||
compile_binop "OR" b
|
||||
| BoolExpr (And b) ->
|
||||
simpl_binop "AND" b
|
||||
compile_binop "AND" b
|
||||
| BoolExpr (Not b) ->
|
||||
simpl_unop "NOT" b
|
||||
compile_unop "NOT" b
|
||||
| CompExpr (Lt c) ->
|
||||
simpl_binop "LT" c
|
||||
compile_binop "LT" c
|
||||
| CompExpr (Gt c) ->
|
||||
simpl_binop "GT" c
|
||||
compile_binop "GT" c
|
||||
| CompExpr (Leq c) ->
|
||||
simpl_binop "LE" c
|
||||
compile_binop "LE" c
|
||||
| CompExpr (Geq c) ->
|
||||
simpl_binop "GE" c
|
||||
compile_binop "GE" c
|
||||
| CompExpr (Equal c) ->
|
||||
simpl_binop "EQ" c
|
||||
compile_binop "EQ" c
|
||||
| CompExpr (Neq c) ->
|
||||
simpl_binop "NEQ" c
|
||||
compile_binop "NEQ" c
|
||||
|
||||
and simpl_list_expression (t:Raw.list_expr) : expression result =
|
||||
and compile_list_expression (t:Raw.list_expr) : expression result =
|
||||
let return x = ok x in
|
||||
match t with
|
||||
ECons c ->
|
||||
simpl_binop "CONS" c
|
||||
compile_binop "CONS" c
|
||||
| EListComp lst ->
|
||||
let (lst , loc) = r_split lst in
|
||||
let%bind lst' =
|
||||
bind_map_list simpl_expression @@
|
||||
bind_map_list compile_expression @@
|
||||
pseq_to_list lst.elements in
|
||||
return @@ e_list ~loc lst'
|
||||
| ENil reg ->
|
||||
let loc = Location.lift reg in
|
||||
return @@ e_list ~loc []
|
||||
|
||||
and simpl_set_expression (t:Raw.set_expr) : expression result =
|
||||
and compile_set_expression (t:Raw.set_expr) : expression result =
|
||||
match t with
|
||||
| SetMem x -> (
|
||||
let (x' , loc) = r_split x in
|
||||
let%bind set' = simpl_expression x'.set in
|
||||
let%bind element' = simpl_expression x'.element in
|
||||
let%bind set' = compile_expression x'.set in
|
||||
let%bind element' = compile_expression x'.element in
|
||||
ok @@ e_constant ~loc C_SET_MEM [ element' ; set' ]
|
||||
)
|
||||
| SetInj x -> (
|
||||
let (x' , loc) = r_split x in
|
||||
let elements = pseq_to_list x'.elements in
|
||||
let%bind elements' = bind_map_list simpl_expression elements in
|
||||
let%bind elements' = bind_map_list compile_expression elements in
|
||||
ok @@ e_set ~loc elements'
|
||||
)
|
||||
|
||||
and simpl_binop (name:string) (t:_ Raw.bin_op Region.reg) : expression result =
|
||||
and compile_binop (name:string) (t:_ Raw.bin_op Region.reg) : expression result =
|
||||
let return x = ok x in
|
||||
let (t , loc) = r_split t in
|
||||
let%bind a = simpl_expression t.arg1 in
|
||||
let%bind b = simpl_expression t.arg2 in
|
||||
let%bind a = compile_expression t.arg1 in
|
||||
let%bind b = compile_expression t.arg2 in
|
||||
let%bind name = constants name in
|
||||
return @@ e_constant ~loc name [ a ; b ]
|
||||
|
||||
and simpl_unop (name:string) (t:_ Raw.un_op Region.reg) : expression result =
|
||||
and compile_unop (name:string) (t:_ Raw.un_op Region.reg) : expression result =
|
||||
let return x = ok x in
|
||||
let (t , loc) = r_split t in
|
||||
let%bind a = simpl_expression t.arg in
|
||||
let%bind a = compile_expression t.arg in
|
||||
let%bind name = constants name in
|
||||
return @@ e_constant ~loc name [ a ]
|
||||
|
||||
and simpl_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
||||
and compile_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
||||
let return x = ok x in
|
||||
match lst with
|
||||
| [] -> return @@ e_literal Literal_unit
|
||||
| [hd] -> simpl_expression hd
|
||||
| [hd] -> compile_expression hd
|
||||
| lst ->
|
||||
let%bind lst = bind_list @@ List.map simpl_expression lst
|
||||
let%bind lst = bind_list @@ List.map compile_expression lst
|
||||
in return @@ e_tuple ?loc lst
|
||||
|
||||
and simpl_data_declaration : Raw.data_decl -> _ result =
|
||||
and compile_data_declaration : Raw.data_decl -> _ result =
|
||||
fun t ->
|
||||
match t with
|
||||
| LocalVar x ->
|
||||
let (x , loc) = r_split x in
|
||||
let name = x.name.value in
|
||||
let%bind t = simpl_type_expression x.var_type in
|
||||
let%bind expression = simpl_expression x.init in
|
||||
let%bind t = compile_type_expression x.var_type in
|
||||
let%bind expression = compile_expression x.init in
|
||||
return_let_in ~loc (Var.of_name name, Some t) false false expression
|
||||
| LocalConst x ->
|
||||
let (x , loc) = r_split x in
|
||||
let name = x.name.value in
|
||||
let%bind t = simpl_type_expression x.const_type in
|
||||
let%bind expression = simpl_expression x.init in
|
||||
let%bind t = compile_type_expression x.const_type in
|
||||
let%bind expression = compile_expression x.init in
|
||||
let inline =
|
||||
match x.attributes with
|
||||
None -> false
|
||||
@ -630,7 +630,7 @@ and simpl_data_declaration : Raw.data_decl -> _ result =
|
||||
in return_let_in ~loc (Var.of_name name, Some t) false inline expression
|
||||
| LocalFun f ->
|
||||
let (f , loc) = r_split f in
|
||||
let%bind (binder, expr) = simpl_fun_decl ~loc f in
|
||||
let%bind (binder, expr) = compile_fun_decl ~loc f in
|
||||
let inline =
|
||||
match f.attributes with
|
||||
None -> false
|
||||
@ -639,22 +639,22 @@ and simpl_data_declaration : Raw.data_decl -> _ result =
|
||||
|> List.exists (fun Region.{value; _} -> value = "\"inline\"")
|
||||
in return_let_in ~loc binder false inline expr
|
||||
|
||||
and simpl_param :
|
||||
and compile_param :
|
||||
Raw.param_decl -> (string * type_expression) result =
|
||||
fun t ->
|
||||
match t with
|
||||
| ParamConst c ->
|
||||
let c = c.value in
|
||||
let param_name = c.var.value in
|
||||
let%bind type_expression = simpl_type_expression c.param_type in
|
||||
let%bind type_expression = compile_type_expression c.param_type in
|
||||
ok (param_name , type_expression)
|
||||
| ParamVar v ->
|
||||
let c = v.value in
|
||||
let param_name = c.var.value in
|
||||
let%bind type_expression = simpl_type_expression c.param_type in
|
||||
let%bind type_expression = compile_type_expression c.param_type in
|
||||
ok (param_name , type_expression)
|
||||
|
||||
and simpl_fun_decl :
|
||||
and compile_fun_decl :
|
||||
loc:_ -> Raw.fun_decl ->
|
||||
((expression_variable * type_expression option) * expression) result =
|
||||
fun ~loc x ->
|
||||
@ -674,11 +674,11 @@ and simpl_fun_decl :
|
||||
in
|
||||
(match param.value.inside with
|
||||
a, [] -> (
|
||||
let%bind input = simpl_param a in
|
||||
let%bind input = compile_param a in
|
||||
let (binder , input_type) = input in
|
||||
let%bind instructions = simpl_statement_list statements in
|
||||
let%bind result = simpl_expression return in
|
||||
let%bind output_type = simpl_type_expression ret_type in
|
||||
let%bind instructions = compile_statement_list statements in
|
||||
let%bind result = compile_expression return in
|
||||
let%bind output_type = compile_type_expression ret_type in
|
||||
let body = instructions in
|
||||
let%bind result =
|
||||
let aux prec cur = cur (Some prec) in
|
||||
@ -699,7 +699,7 @@ and simpl_fun_decl :
|
||||
let lst = npseq_to_list lst in
|
||||
(* TODO wrong, should be fresh? *)
|
||||
let arguments_name = Var.of_name "arguments" in
|
||||
let%bind params = bind_map_list simpl_param lst in
|
||||
let%bind params = bind_map_list compile_param lst in
|
||||
let (binder , input_type) =
|
||||
let type_expression = t_tuple (List.map snd params) in
|
||||
(arguments_name , type_expression) in
|
||||
@ -712,9 +712,9 @@ and simpl_fun_decl :
|
||||
ass
|
||||
in
|
||||
bind_list @@ List.mapi aux params in
|
||||
let%bind instructions = simpl_statement_list statements in
|
||||
let%bind result = simpl_expression return in
|
||||
let%bind output_type = simpl_type_expression ret_type in
|
||||
let%bind instructions = compile_statement_list statements in
|
||||
let%bind result = compile_expression return in
|
||||
let%bind output_type = compile_type_expression ret_type in
|
||||
let body = tpl_declarations @ instructions in
|
||||
let%bind result =
|
||||
let aux prec cur = cur (Some prec) in
|
||||
@ -732,7 +732,7 @@ and simpl_fun_decl :
|
||||
)
|
||||
)
|
||||
|
||||
and simpl_fun_expression :
|
||||
and compile_fun_expression :
|
||||
loc:_ -> Raw.fun_expr -> (type_expression option * expression) result =
|
||||
fun ~loc x ->
|
||||
let open! Raw in
|
||||
@ -740,11 +740,12 @@ and simpl_fun_expression :
|
||||
let statements = [] in
|
||||
(match param.value.inside with
|
||||
a, [] -> (
|
||||
let%bind input = simpl_param a in
|
||||
let%bind input = compile_param a in
|
||||
let (binder , input_type) = input in
|
||||
let%bind instructions = simpl_statement_list statements in
|
||||
let%bind result = simpl_expression return in
|
||||
let%bind output_type = simpl_type_expression ret_type in
|
||||
let%bind instructions = compile_statement_list statements in
|
||||
let%bind result = compile_expression return in
|
||||
let%bind output_type = compile_type_expression ret_type in
|
||||
|
||||
let body = instructions in
|
||||
let%bind result =
|
||||
let aux prec cur = cur (Some prec) in
|
||||
@ -762,7 +763,7 @@ and simpl_fun_expression :
|
||||
let lst = npseq_to_list lst in
|
||||
(* TODO wrong, should be fresh? *)
|
||||
let arguments_name = Var.of_name "arguments" in
|
||||
let%bind params = bind_map_list simpl_param lst in
|
||||
let%bind params = bind_map_list compile_param lst in
|
||||
let (binder , input_type) =
|
||||
let type_expression = t_tuple (List.map snd params) in
|
||||
(arguments_name , type_expression) in
|
||||
@ -774,9 +775,9 @@ and simpl_fun_expression :
|
||||
ass
|
||||
in
|
||||
bind_list @@ List.mapi aux params in
|
||||
let%bind instructions = simpl_statement_list statements in
|
||||
let%bind result = simpl_expression return in
|
||||
let%bind output_type = simpl_type_expression ret_type in
|
||||
let%bind instructions = compile_statement_list statements in
|
||||
let%bind result = compile_expression return in
|
||||
let%bind output_type = compile_type_expression ret_type in
|
||||
let body = tpl_declarations @ instructions in
|
||||
let%bind result =
|
||||
let aux prec cur = cur (Some prec) in
|
||||
@ -791,7 +792,7 @@ and simpl_fun_expression :
|
||||
)
|
||||
)
|
||||
|
||||
and simpl_statement_list statements =
|
||||
and compile_statement_list statements =
|
||||
let open Raw in
|
||||
let rec hook acc = function
|
||||
[] -> acc
|
||||
@ -813,9 +814,9 @@ and simpl_statement_list statements =
|
||||
(* Detached attributes are erased. TODO: Warning. *)
|
||||
hook acc statements
|
||||
| Instr i :: statements ->
|
||||
hook (simpl_instruction i :: acc) statements
|
||||
hook (compile_instruction i :: acc) statements
|
||||
| Data d :: statements ->
|
||||
hook (simpl_data_declaration d :: acc) statements
|
||||
hook (compile_data_declaration d :: acc) statements
|
||||
in bind_list @@ hook [] (List.rev statements)
|
||||
|
||||
and get_case_variables (t:Raw.pattern) : expression_variable list result =
|
||||
@ -847,7 +848,7 @@ and get_case_variables (t:Raw.pattern) : expression_variable list result =
|
||||
| PVar v -> ok @@ [Var.of_name v.value]
|
||||
| p -> fail @@ unsupported_cst_constr p
|
||||
|
||||
and simpl_single_instruction : Raw.instruction -> (_ -> expression result) result =
|
||||
and compile_single_instruction : Raw.instruction -> (_ -> expression result) result =
|
||||
fun t ->
|
||||
match t with
|
||||
| ProcCall x -> (
|
||||
@ -859,15 +860,15 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
let (f_name , f_loc) = r_split name in
|
||||
match constants f_name with
|
||||
| Error _ ->
|
||||
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
||||
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
||||
return_statement @@ e_application ~loc (e_variable ~loc:f_loc (Var.of_name f_name)) arg
|
||||
| Ok (s,_) ->
|
||||
let%bind lst = bind_map_list simpl_expression args' in
|
||||
let%bind lst = bind_map_list compile_expression args' in
|
||||
return_statement @@ e_constant ~loc s lst
|
||||
)
|
||||
| f -> (
|
||||
let%bind f' = simpl_expression f in
|
||||
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
||||
let%bind f' = compile_expression f in
|
||||
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
||||
return_statement @@ e_application ~loc f' arg
|
||||
)
|
||||
)
|
||||
@ -876,35 +877,35 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
return_statement @@ e_skip ~loc ()
|
||||
)
|
||||
| Loop (While l) ->
|
||||
simpl_while_loop l.value
|
||||
compile_while_loop l.value
|
||||
| Loop (For (ForInt fi)) -> (
|
||||
let%bind loop = simpl_for_int fi.value in
|
||||
let%bind loop = compile_for_int fi.value in
|
||||
ok loop
|
||||
)
|
||||
| Loop (For (ForCollect fc)) ->
|
||||
let%bind loop = simpl_for_collect fc.value in
|
||||
let%bind loop = compile_for_collect fc.value in
|
||||
ok loop
|
||||
| Cond c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind expr = simpl_expression c.test in
|
||||
let%bind expr = compile_expression c.test in
|
||||
let%bind match_true = match c.ifso with
|
||||
ClauseInstr i ->
|
||||
simpl_single_instruction i
|
||||
compile_single_instruction i
|
||||
| ClauseBlock b ->
|
||||
match b with
|
||||
LongBlock {value; _} ->
|
||||
simpl_block value
|
||||
compile_block value
|
||||
| ShortBlock {value; _} ->
|
||||
simpl_statements @@ fst value.inside in
|
||||
compile_statements @@ fst value.inside in
|
||||
let%bind match_false = match c.ifnot with
|
||||
ClauseInstr i ->
|
||||
simpl_single_instruction i
|
||||
compile_single_instruction i
|
||||
| ClauseBlock b ->
|
||||
match b with
|
||||
LongBlock {value; _} ->
|
||||
simpl_block value
|
||||
compile_block value
|
||||
| ShortBlock {value; _} ->
|
||||
simpl_statements @@ fst value.inside in
|
||||
compile_statements @@ fst value.inside in
|
||||
let env = Var.fresh () in
|
||||
|
||||
let%bind match_true' = match_true None in
|
||||
@ -928,10 +929,10 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
)
|
||||
| Assign a -> (
|
||||
let (a , loc) = r_split a in
|
||||
let%bind value_expr = simpl_expression a.rhs in
|
||||
let%bind value_expr = compile_expression a.rhs in
|
||||
match a.lhs with
|
||||
| Path path -> (
|
||||
let (name , path') = simpl_path path in
|
||||
let (name , path') = compile_path path in
|
||||
let (let_binder, mut, rhs, inline) = e_assign_with_let ~loc name path' value_expr in
|
||||
return_let_in let_binder mut inline rhs
|
||||
)
|
||||
@ -940,11 +941,11 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
let%bind (varname,map,path) = match v'.path with
|
||||
| Name name -> ok (name.value , e_variable (Var.of_name name.value), [])
|
||||
| Path p ->
|
||||
let (name,p') = simpl_path v'.path in
|
||||
let%bind accessor = simpl_projection p in
|
||||
let (name,p') = compile_path v'.path in
|
||||
let%bind accessor = compile_projection p in
|
||||
ok @@ (name , accessor , p')
|
||||
in
|
||||
let%bind key_expr = simpl_expression v'.index.value.inside in
|
||||
let%bind key_expr = compile_expression v'.index.value.inside in
|
||||
let expr' = e_map_add key_expr value_expr map in
|
||||
let (let_binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr' in
|
||||
return_let_in let_binder mut inline rhs
|
||||
@ -952,20 +953,20 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
)
|
||||
| CaseInstr c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind expr = simpl_expression c.expr in
|
||||
let%bind expr = compile_expression c.expr in
|
||||
let env = Var.fresh () in
|
||||
let%bind (fv,cases) =
|
||||
let aux fv (x : Raw.if_clause Raw.case_clause Raw.reg) =
|
||||
let%bind case_clause =
|
||||
match x.value.rhs with
|
||||
ClauseInstr i ->
|
||||
simpl_single_instruction i
|
||||
compile_single_instruction i
|
||||
| ClauseBlock b ->
|
||||
match b with
|
||||
LongBlock {value; _} ->
|
||||
simpl_block value
|
||||
compile_block value
|
||||
| ShortBlock {value; _} ->
|
||||
simpl_statements @@ fst value.inside in
|
||||
compile_statements @@ fst value.inside in
|
||||
let%bind case_clause'= case_clause @@ None in
|
||||
let%bind case_clause = case_clause @@ Some(e_variable env) in
|
||||
let%bind case_vars = get_case_variables x.value.pattern in
|
||||
@ -975,11 +976,11 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
let free_vars = List.concat fv in
|
||||
if (List.length free_vars == 0) then (
|
||||
let cases = List.map (fun case -> let (a,_,b) = case in (a,b)) cases in
|
||||
let%bind m = simpl_cases cases in
|
||||
let%bind m = compile_cases cases in
|
||||
return_statement @@ e_matching ~loc expr m
|
||||
) else (
|
||||
let cases = List.map (fun case -> let (a,b,_) = case in (a,b)) cases in
|
||||
let%bind m = simpl_cases cases in
|
||||
let%bind m = compile_cases cases in
|
||||
let match_expr = e_matching ~loc expr m in
|
||||
let return_expr = fun expr ->
|
||||
e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
@ -1001,8 +1002,8 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
region=r.record_inj.region
|
||||
} in
|
||||
let u : Raw.update = {record=r.path;kwd_with=r.kwd_with; updates=update} in
|
||||
let%bind expr = simpl_update {value=u;region=reg} in
|
||||
let (name , access_path) = simpl_path r.path in
|
||||
let%bind expr = compile_update {value=u;region=reg} in
|
||||
let (name , access_path) = compile_path r.path in
|
||||
let loc = Some loc in
|
||||
let (binder, mut, rhs, inline) = e_assign_with_let ?loc name access_path expr in
|
||||
return_let_in binder mut inline rhs
|
||||
@ -1010,13 +1011,13 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
)
|
||||
| MapPatch patch -> (
|
||||
let (map_p, loc) = r_split patch in
|
||||
let (name, access_path) = simpl_path map_p.path in
|
||||
let (name, access_path) = compile_path map_p.path in
|
||||
let%bind inj = bind_list
|
||||
@@ List.map (fun (x:Raw.binding Region.reg) ->
|
||||
let x = x.value in
|
||||
let (key, value) = x.source, x.image in
|
||||
let%bind key' = simpl_expression key in
|
||||
let%bind value' = simpl_expression value
|
||||
let%bind key' = compile_expression key in
|
||||
let%bind value' = compile_expression value
|
||||
in ok @@ (key', value')
|
||||
)
|
||||
@@ npseq_to_list map_p.map_inj.value.ne_elements in
|
||||
@ -1033,10 +1034,10 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
)
|
||||
| SetPatch patch -> (
|
||||
let (setp, loc) = r_split patch in
|
||||
let (name , access_path) = simpl_path setp.path in
|
||||
let (name , access_path) = compile_path setp.path in
|
||||
let%bind inj =
|
||||
bind_list @@
|
||||
List.map simpl_expression @@
|
||||
List.map compile_expression @@
|
||||
npseq_to_list setp.set_inj.value.ne_elements in
|
||||
match inj with
|
||||
| [] -> return_statement @@ e_skip ~loc ()
|
||||
@ -1053,11 +1054,11 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
let%bind (varname,map,path) = match v.map with
|
||||
| Name v -> ok (v.value , e_variable (Var.of_name v.value) , [])
|
||||
| Path p ->
|
||||
let (name,p') = simpl_path v.map in
|
||||
let%bind accessor = simpl_projection p in
|
||||
let (name,p') = compile_path v.map in
|
||||
let%bind accessor = compile_projection p in
|
||||
ok @@ (name , accessor , p')
|
||||
in
|
||||
let%bind key' = simpl_expression key in
|
||||
let%bind key' = compile_expression key in
|
||||
let expr = e_constant ~loc C_MAP_REMOVE [key' ; map] in
|
||||
let (binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr in
|
||||
return_let_in binder mut inline rhs
|
||||
@ -1067,17 +1068,17 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
|
||||
let%bind (varname, set, path) = match set_rm.set with
|
||||
| Name v -> ok (v.value, e_variable (Var.of_name v.value), [])
|
||||
| Path path ->
|
||||
let(name, p') = simpl_path set_rm.set in
|
||||
let%bind accessor = simpl_projection path in
|
||||
let(name, p') = compile_path set_rm.set in
|
||||
let%bind accessor = compile_projection path in
|
||||
ok @@ (name, accessor, p')
|
||||
in
|
||||
let%bind removed' = simpl_expression set_rm.element in
|
||||
let%bind removed' = compile_expression set_rm.element in
|
||||
let expr = e_constant ~loc C_SET_REMOVE [removed' ; set] in
|
||||
let (binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr in
|
||||
return_let_in binder mut inline rhs
|
||||
)
|
||||
|
||||
and simpl_path : Raw.path -> string * string list = fun p ->
|
||||
and compile_path : Raw.path -> string * string list = fun p ->
|
||||
match p with
|
||||
| Raw.Name v -> (v.value , [])
|
||||
| Raw.Path p -> (
|
||||
@ -1094,7 +1095,7 @@ and simpl_path : Raw.path -> string * string list = fun p ->
|
||||
(var , path')
|
||||
)
|
||||
|
||||
and simpl_cases : (Raw.pattern * expression) list -> matching_expr result = fun t ->
|
||||
and compile_cases : (Raw.pattern * expression) list -> matching_expr result = fun t ->
|
||||
let open Raw in
|
||||
let get_var (t:Raw.pattern) =
|
||||
match t with
|
||||
@ -1185,13 +1186,13 @@ and simpl_cases : (Raw.pattern * expression) list -> matching_expr result = fun
|
||||
bind_map_list aux lst in
|
||||
ok @@ ez_match_variant constrs
|
||||
|
||||
and simpl_instruction : Raw.instruction -> (_ -> expression result) result =
|
||||
fun t -> trace (simplifying_instruction t) @@ simpl_single_instruction t
|
||||
and compile_instruction : Raw.instruction -> (_ -> expression result) result =
|
||||
fun t -> trace (abstracting_instruction t) @@ compile_single_instruction t
|
||||
|
||||
and simpl_statements : Raw.statements -> (_ -> expression result) result =
|
||||
and compile_statements : Raw.statements -> (_ -> expression result) result =
|
||||
fun statements ->
|
||||
let lst = npseq_to_list statements in
|
||||
let%bind fs = simpl_statement_list lst in
|
||||
let%bind fs = compile_statement_list lst in
|
||||
let aux : _ -> (expression option -> expression result) -> _ =
|
||||
fun prec cur ->
|
||||
let%bind res = cur prec
|
||||
@ -1200,19 +1201,19 @@ and simpl_statements : Raw.statements -> (_ -> expression result) result =
|
||||
let%bind ret = bind_fold_right_list aux expr' fs in
|
||||
ok @@ Option.unopt_exn ret
|
||||
|
||||
and simpl_block : Raw.block -> (_ -> expression result) result =
|
||||
fun t -> simpl_statements t.statements
|
||||
and compile_block : Raw.block -> (_ -> expression result) result =
|
||||
fun t -> compile_statements t.statements
|
||||
|
||||
and simpl_while_loop : Raw.while_loop -> (_ -> expression result) result = fun wl ->
|
||||
and compile_while_loop : Raw.while_loop -> (_ -> expression result) result = fun wl ->
|
||||
let env_rec = Var.fresh () in
|
||||
let binder = Var.fresh () in
|
||||
|
||||
let%bind cond = simpl_expression wl.cond in
|
||||
let%bind cond = compile_expression wl.cond in
|
||||
let ctrl =
|
||||
(e_variable binder)
|
||||
in
|
||||
|
||||
let%bind for_body = simpl_block wl.block.value in
|
||||
let%bind for_body = compile_block wl.block.value in
|
||||
let%bind for_body = for_body @@ Some( ctrl ) in
|
||||
let%bind ((_,captured_name_list),for_body) = repair_mutable_variable_in_loops for_body [] binder in
|
||||
|
||||
@ -1237,15 +1238,15 @@ and simpl_while_loop : Raw.while_loop -> (_ -> expression result) result = fun w
|
||||
restore_mutable_variable return_expr captured_name_list env_rec
|
||||
|
||||
|
||||
and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
||||
and compile_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
||||
let env_rec = Var.fresh () in
|
||||
let binder = Var.fresh () in
|
||||
let name = fi.assign.value.name.value in
|
||||
let it = Var.of_name name in
|
||||
let var = e_variable it in
|
||||
(*Make the cond and the step *)
|
||||
let%bind value = simpl_expression fi.assign.value.expr in
|
||||
let%bind bound = simpl_expression fi.bound in
|
||||
let%bind value = compile_expression fi.assign.value.expr in
|
||||
let%bind bound = compile_expression fi.bound in
|
||||
let cond = e_annotation (e_constant C_LE [var ; bound]) t_bool in
|
||||
let step = e_int 1 in
|
||||
let continue_expr = e_constant C_FOLD_CONTINUE [(e_variable binder)] in
|
||||
@ -1255,7 +1256,7 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
||||
continue_expr
|
||||
in
|
||||
(* Modify the body loop*)
|
||||
let%bind for_body = simpl_block fi.block.value in
|
||||
let%bind for_body = compile_block fi.block.value in
|
||||
let%bind for_body = for_body @@ Some ctrl in
|
||||
let%bind ((_,captured_name_list),for_body) = repair_mutable_variable_in_loops for_body [it] binder in
|
||||
|
||||
@ -1285,19 +1286,19 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
||||
in
|
||||
restore_mutable_variable return_expr captured_name_list env_rec
|
||||
|
||||
and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun fc ->
|
||||
and compile_for_collect : Raw.for_collect -> (_ -> expression result) result = fun fc ->
|
||||
let binder = Var.of_name "arguments" in
|
||||
let%bind element_names = ok @@ match fc.bind_to with
|
||||
| Some v -> [Var.of_name fc.var.value;Var.of_name (snd v).value]
|
||||
| None -> [Var.of_name fc.var.value] in
|
||||
|
||||
let env = Var.fresh () in
|
||||
let%bind for_body = simpl_block fc.block.value in
|
||||
let%bind for_body = compile_block fc.block.value in
|
||||
let%bind for_body = for_body @@ Some (e_accessor (e_variable binder) "0") in
|
||||
let%bind ((_,free_vars), for_body) = repair_mutable_variable_in_loops for_body element_names binder in
|
||||
|
||||
let init_record = store_mutable_variable free_vars in
|
||||
let%bind collect = simpl_expression fc.expr in
|
||||
let%bind collect = compile_expression fc.expr in
|
||||
let aux name expr=
|
||||
e_let_in (name,None) false false (e_accessor (e_accessor (e_variable binder) "0") (Var.to_name name)) expr
|
||||
in
|
||||
@ -1319,8 +1320,7 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
|
||||
in
|
||||
restore_mutable_variable fold free_vars env
|
||||
|
||||
and simpl_declaration_list declarations :
|
||||
Ast_simplified.declaration Location.wrap list result =
|
||||
and compile_declaration_list declarations : declaration Location.wrap list result =
|
||||
let open Raw in
|
||||
let rec hook acc = function
|
||||
[] -> acc
|
||||
@ -1344,16 +1344,16 @@ and simpl_declaration_list declarations :
|
||||
| TypeDecl decl :: declarations ->
|
||||
let decl, loc = r_split decl in
|
||||
let {name; type_expr} : Raw.type_decl = decl in
|
||||
let%bind type_expression = simpl_type_expression type_expr in
|
||||
let%bind type_expression = compile_type_expression type_expr in
|
||||
let new_decl =
|
||||
Declaration_type (Var.of_name name.value, type_expression) in
|
||||
let res = Location.wrap ~loc new_decl in
|
||||
hook (bind_list_cons res acc) declarations
|
||||
| ConstDecl decl :: declarations ->
|
||||
let simpl_const_decl =
|
||||
let compile_const_decl =
|
||||
fun {name;const_type; init; attributes} ->
|
||||
let%bind expression = simpl_expression init in
|
||||
let%bind t = simpl_type_expression const_type in
|
||||
let%bind expression = compile_expression init in
|
||||
let%bind t = compile_type_expression const_type in
|
||||
let type_annotation = Some t in
|
||||
let inline =
|
||||
match attributes with
|
||||
@ -1366,11 +1366,11 @@ and simpl_declaration_list declarations :
|
||||
(Var.of_name name.value, type_annotation, inline, expression)
|
||||
in ok new_decl in
|
||||
let%bind res =
|
||||
bind_map_location simpl_const_decl (Location.lift_region decl)
|
||||
bind_map_location compile_const_decl (Location.lift_region decl)
|
||||
in hook (bind_list_cons res acc) declarations
|
||||
| FunDecl fun_decl :: declarations ->
|
||||
let decl, loc = r_split fun_decl in
|
||||
let%bind ((name, ty_opt), expr) = simpl_fun_decl ~loc decl in
|
||||
let%bind ((name, ty_opt), expr) = compile_fun_decl ~loc decl in
|
||||
let inline =
|
||||
match fun_decl.value.attributes with
|
||||
None -> false
|
||||
@ -1383,5 +1383,5 @@ and simpl_declaration_list declarations :
|
||||
hook (bind_list_cons res acc) declarations
|
||||
in hook (ok @@ []) (List.rev declarations)
|
||||
|
||||
let simpl_program : Raw.ast -> program result =
|
||||
fun t -> simpl_declaration_list @@ nseq_to_list t.decl
|
||||
let compile_program : Raw.ast -> program result =
|
||||
fun t -> compile_declaration_list @@ nseq_to_list t.decl
|
15
src/passes/2-concrete_to_imperative/pascaligo.mli
Normal file
15
src/passes/2-concrete_to_imperative/pascaligo.mli
Normal file
@ -0,0 +1,15 @@
|
||||
(** Converts PascaLIGO programs to the Simplified Abstract Syntax Tree. *)
|
||||
|
||||
open Trace
|
||||
open Ast_imperative
|
||||
|
||||
module Raw = Parser.Pascaligo.AST
|
||||
module SMap = Map.String
|
||||
|
||||
(** Convert a concrete PascaLIGO expression AST to the imperative
|
||||
expression AST used by the compiler. *)
|
||||
val compile_expression : Raw.expr -> expr result
|
||||
|
||||
(** Convert a concrete PascaLIGO program AST to the miperative program
|
||||
AST used by the compiler. *)
|
||||
val compile_program : Raw.ast -> program result
|
@ -1,15 +0,0 @@
|
||||
(** Converts PascaLIGO programs to the Simplified Abstract Syntax Tree. *)
|
||||
|
||||
open Trace
|
||||
open Ast_simplified
|
||||
|
||||
module Raw = Parser.Pascaligo.AST
|
||||
module SMap = Map.String
|
||||
|
||||
(** Convert a concrete PascaLIGO expression AST to the simplified
|
||||
expression AST used by the compiler. *)
|
||||
val simpl_expression : Raw.expr -> expr result
|
||||
|
||||
(** Convert a concrete PascaLIGO program AST to the simplified program
|
||||
AST used by the compiler. *)
|
||||
val simpl_program : Raw.ast -> program result
|
@ -1,9 +1,9 @@
|
||||
(library
|
||||
(name self_ast_simplified)
|
||||
(public_name ligo.self_ast_simplified)
|
||||
(name self_ast_imperative)
|
||||
(public_name ligo.self_ast_imperative)
|
||||
(libraries
|
||||
simple-utils
|
||||
ast_simplified
|
||||
ast_imperative
|
||||
proto-alpha-utils
|
||||
)
|
||||
(preprocess
|
@ -1,4 +1,4 @@
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
open Trace
|
||||
open Stage_common.Helpers
|
||||
|
@ -1,4 +1,4 @@
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
open Trace
|
||||
open Stage_common.Helpers
|
||||
|
||||
@ -19,8 +19,8 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini
|
||||
| E_look_up ab ->
|
||||
let%bind res = bind_fold_pair self init' ab in
|
||||
ok res
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
| E_application {lamb;args} -> (
|
||||
let ab = (lamb,args) in
|
||||
let%bind res = bind_fold_pair self init' ab in
|
||||
ok res
|
||||
)
|
||||
@ -59,6 +59,11 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini
|
||||
| E_recursive { lambda={result=e;_}; _} ->
|
||||
let%bind res = self init' e in
|
||||
ok res
|
||||
| E_sequence {expr1;expr2} ->
|
||||
let ab = (expr1,expr2) in
|
||||
let%bind res = bind_fold_pair self init' ab in
|
||||
ok res
|
||||
|
||||
|
||||
and fold_cases : 'a folder -> 'a -> matching_expr -> 'a result = fun f init m ->
|
||||
match m with
|
||||
@ -145,10 +150,10 @@ let rec map_expression : exp_mapper -> expression -> expression result = fun f e
|
||||
let%bind e' = self c.element in
|
||||
return @@ E_constructor {c with element = e'}
|
||||
)
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
let%bind (a,b) = bind_map_pair self ab in
|
||||
return @@ E_application {expr1=a;expr2=b}
|
||||
| E_application {lamb;args} -> (
|
||||
let ab = (lamb,args) in
|
||||
let%bind (lamb,args) = bind_map_pair self ab in
|
||||
return @@ E_application {lamb;args}
|
||||
)
|
||||
| E_let_in { let_binder ; mut; rhs ; let_result; inline } -> (
|
||||
let%bind rhs = self rhs in
|
||||
@ -167,6 +172,10 @@ let rec map_expression : exp_mapper -> expression -> expression result = fun f e
|
||||
let%bind args = bind_map_list self c.arguments in
|
||||
return @@ E_constant {c with arguments=args}
|
||||
)
|
||||
| E_sequence {expr1;expr2} -> (
|
||||
let%bind (expr1,expr2) = bind_map_pair self (expr1,expr2) in
|
||||
return @@ E_sequence {expr1;expr2}
|
||||
)
|
||||
| E_literal _ | E_variable _ | E_skip as e' -> return e'
|
||||
|
||||
and map_type_expression : ty_exp_mapper -> type_expression -> type_expression result = fun f te ->
|
||||
@ -288,10 +297,10 @@ let rec fold_map_expression : 'a fold_mapper -> 'a -> expression -> ('a * expres
|
||||
let%bind (res,e') = self init' c.element in
|
||||
ok (res, return @@ E_constructor {c with element = e'})
|
||||
)
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
| E_application {lamb;args} -> (
|
||||
let ab = (lamb,args) in
|
||||
let%bind (res,(a,b)) = bind_fold_map_pair self init' ab in
|
||||
ok (res, return @@ E_application {expr1=a;expr2=b})
|
||||
ok (res, return @@ E_application {lamb=a;args=b})
|
||||
)
|
||||
| E_let_in { let_binder ; mut; rhs ; let_result; inline } -> (
|
||||
let%bind (res,rhs) = self init' rhs in
|
||||
@ -310,6 +319,10 @@ let rec fold_map_expression : 'a fold_mapper -> 'a -> expression -> ('a * expres
|
||||
let%bind (res,args) = bind_fold_map_list self init' c.arguments in
|
||||
ok (res, return @@ E_constant {c with arguments=args})
|
||||
)
|
||||
| E_sequence {expr1;expr2} -> (
|
||||
let%bind (res,(expr1,expr2)) = bind_fold_map_pair self init' (expr1,expr2) in
|
||||
ok (res, return @@ E_sequence {expr1;expr2})
|
||||
)
|
||||
| E_literal _ | E_variable _ | E_skip as e' -> ok (init', return e')
|
||||
|
||||
and fold_map_cases : 'a fold_mapper -> 'a -> matching_expr -> ('a * matching_expr) result = fun f init m ->
|
@ -1,4 +1,4 @@
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
open Trace
|
||||
open Proto_alpha_utils
|
||||
|
||||
@ -6,7 +6,7 @@ module Errors = struct
|
||||
|
||||
let bad_format e () =
|
||||
let title = (thunk ("Badly formatted literal")) in
|
||||
let message () = Format.asprintf "%a" Ast_simplified.PP.expression e in
|
||||
let message () = Format.asprintf "%a" PP.expression e in
|
||||
let data = [
|
||||
("location" , fun () -> Format.asprintf "%a" Location.pp e.location)
|
||||
] in
|
@ -1,4 +1,4 @@
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
open Trace
|
||||
|
||||
let peephole_expression : expression -> expression result = fun e ->
|
@ -6,7 +6,7 @@ let all_expression_mapper = [
|
||||
Literals.peephole_expression ;
|
||||
]
|
||||
let all_type_expression_mapper = [
|
||||
Entrypoints_lenght_limit.peephole_type_expression ;
|
||||
Entrypoints_length_limit.peephole_type_expression ;
|
||||
]
|
||||
|
||||
let all_exp = List.map (fun el -> Helpers.Expression el) all_expression_mapper
|
@ -1,4 +1,4 @@
|
||||
open Ast_simplified
|
||||
open Ast_imperative
|
||||
open Trace
|
||||
|
||||
module Errors = struct
|
14
src/passes/4-imperative_to_sugar/dune
Normal file
14
src/passes/4-imperative_to_sugar/dune
Normal file
@ -0,0 +1,14 @@
|
||||
(library
|
||||
(name imperative_to_sugar)
|
||||
(public_name ligo.imperative_to_sugar)
|
||||
(libraries
|
||||
simple-utils
|
||||
ast_imperative
|
||||
ast_sugar
|
||||
proto-alpha-utils
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||
)
|
363
src/passes/4-imperative_to_sugar/imperative_to_sugar.ml
Normal file
363
src/passes/4-imperative_to_sugar/imperative_to_sugar.ml
Normal file
@ -0,0 +1,363 @@
|
||||
module I = Ast_imperative
|
||||
module O = Ast_sugar
|
||||
open Trace
|
||||
|
||||
let rec compile_type_expression : I.type_expression -> O.type_expression result =
|
||||
fun te ->
|
||||
let return te = ok @@ O.make_t te in
|
||||
match te.type_content with
|
||||
| I.T_sum sum ->
|
||||
let sum = I.CMap.to_kv_list sum in
|
||||
let%bind sum =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = compile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) sum
|
||||
in
|
||||
return @@ O.T_sum (O.CMap.of_list sum)
|
||||
| I.T_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = compile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ O.T_record (O.LMap.of_list record)
|
||||
| I.T_arrow {type1;type2} ->
|
||||
let%bind type1 = compile_type_expression type1 in
|
||||
let%bind type2 = compile_type_expression type2 in
|
||||
return @@ T_arrow {type1;type2}
|
||||
| I.T_variable type_variable -> return @@ T_variable type_variable
|
||||
| I.T_constant type_constant -> return @@ T_constant type_constant
|
||||
| I.T_operator type_operator ->
|
||||
let%bind type_operator = compile_type_operator type_operator in
|
||||
return @@ T_operator type_operator
|
||||
|
||||
and compile_type_operator : I.type_operator -> O.type_operator result =
|
||||
fun t_o ->
|
||||
match t_o with
|
||||
| TC_contract c ->
|
||||
let%bind c = compile_type_expression c in
|
||||
ok @@ O.TC_contract c
|
||||
| TC_option o ->
|
||||
let%bind o = compile_type_expression o in
|
||||
ok @@ O.TC_option o
|
||||
| TC_list l ->
|
||||
let%bind l = compile_type_expression l in
|
||||
ok @@ O.TC_list l
|
||||
| TC_set s ->
|
||||
let%bind s = compile_type_expression s in
|
||||
ok @@ O.TC_set s
|
||||
| TC_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair compile_type_expression (k,v) in
|
||||
ok @@ O.TC_map (k,v)
|
||||
| TC_big_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair compile_type_expression (k,v) in
|
||||
ok @@ O.TC_big_map (k,v)
|
||||
| TC_arrow (i,o) ->
|
||||
let%bind (i,o) = bind_map_pair compile_type_expression (i,o) in
|
||||
ok @@ O.TC_arrow (i,o)
|
||||
|
||||
let rec compile_expression : I.expression -> O.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ O.make_expr ~loc:e.location expr in
|
||||
match e.expression_content with
|
||||
| I.E_literal literal -> return @@ O.E_literal literal
|
||||
| I.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list compile_expression arguments in
|
||||
return @@ O.E_constant {cons_name;arguments}
|
||||
| I.E_variable name -> return @@ O.E_variable name
|
||||
| I.E_application {lamb;args} ->
|
||||
let%bind lamb = compile_expression lamb in
|
||||
let%bind args = compile_expression args in
|
||||
return @@ O.E_application {lamb;args}
|
||||
| I.E_lambda lambda ->
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_lambda lambda
|
||||
| I.E_recursive {fun_name;fun_type;lambda} ->
|
||||
let%bind fun_type = compile_type_expression fun_type in
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_recursive {fun_name;fun_type;lambda}
|
||||
| I.E_let_in {let_binder;mut=_;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option compile_type_expression ty_opt in
|
||||
let%bind rhs = compile_expression rhs in
|
||||
let%bind let_result = compile_expression let_result in
|
||||
return @@ O.E_let_in {let_binder=(binder,ty_opt);inline;rhs;let_result}
|
||||
| I.E_constructor {constructor;element} ->
|
||||
let%bind element = compile_expression element in
|
||||
return @@ O.E_constructor {constructor;element}
|
||||
| I.E_matching {matchee; cases} ->
|
||||
let%bind matchee = compile_expression matchee in
|
||||
let%bind cases = compile_matching cases in
|
||||
return @@ O.E_matching {matchee;cases}
|
||||
| I.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v =compile_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ O.E_record (O.LMap.of_list record)
|
||||
| I.E_record_accessor {expr;label} ->
|
||||
let%bind expr = compile_expression expr in
|
||||
return @@ O.E_record_accessor {expr;label}
|
||||
| I.E_record_update {record;path;update} ->
|
||||
let%bind record = compile_expression record in
|
||||
let%bind update = compile_expression update in
|
||||
return @@ O.E_record_update {record;path;update}
|
||||
| I.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) map
|
||||
in
|
||||
return @@ O.E_map map
|
||||
| I.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) big_map
|
||||
in
|
||||
return @@ O.E_big_map big_map
|
||||
| I.E_list lst ->
|
||||
let%bind lst = bind_map_list compile_expression lst in
|
||||
return @@ O.E_list lst
|
||||
| I.E_set set ->
|
||||
let%bind set = bind_map_list compile_expression set in
|
||||
return @@ O.E_set set
|
||||
| I.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair compile_expression look_up in
|
||||
return @@ O.E_look_up look_up
|
||||
| I.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = compile_expression anno_expr in
|
||||
let%bind type_annotation = compile_type_expression type_annotation in
|
||||
return @@ O.E_ascription {anno_expr; type_annotation}
|
||||
| I.E_sequence {expr1; expr2} ->
|
||||
let%bind expr1 = compile_expression expr1 in
|
||||
let%bind expr2 = compile_expression expr2 in
|
||||
return @@ O.E_sequence {expr1; expr2}
|
||||
| I.E_skip -> return @@ O.E_skip
|
||||
and compile_lambda : I.lambda -> O.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
let%bind input_type = bind_map_option compile_type_expression input_type in
|
||||
let%bind output_type = bind_map_option compile_type_expression output_type in
|
||||
let%bind result = compile_expression result in
|
||||
ok @@ O.{binder;input_type;output_type;result}
|
||||
and compile_matching : I.matching_expr -> O.matching_expr result =
|
||||
fun m ->
|
||||
match m with
|
||||
| I.Match_bool {match_true;match_false} ->
|
||||
let%bind match_true = compile_expression match_true in
|
||||
let%bind match_false = compile_expression match_false in
|
||||
ok @@ O.Match_bool {match_true;match_false}
|
||||
| I.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil = compile_expression match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}
|
||||
| I.Match_option {match_none;match_some} ->
|
||||
let%bind match_none = compile_expression match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_option {match_none; match_some=(n,expr,tv)}
|
||||
| I.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_tuple ((lst,expr), tv)
|
||||
| I.Match_variant (lst,tv) ->
|
||||
let%bind lst = bind_map_list (
|
||||
fun ((c,n),expr) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ ((c,n),expr)
|
||||
) lst
|
||||
in
|
||||
ok @@ O.Match_variant (lst,tv)
|
||||
|
||||
let compile_declaration : I.declaration Location.wrap -> _ =
|
||||
fun {wrap_content=declaration;location} ->
|
||||
let return decl = ok @@ Location.wrap ~loc:location decl in
|
||||
match declaration with
|
||||
| I.Declaration_constant (n, te_opt, inline, expr) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
let%bind te_opt = bind_map_option compile_type_expression te_opt in
|
||||
return @@ O.Declaration_constant (n, te_opt, inline, expr)
|
||||
| I.Declaration_type (n, te) ->
|
||||
let%bind te = compile_type_expression te in
|
||||
return @@ O.Declaration_type (n,te)
|
||||
|
||||
let compile_program : I.program -> O.program result =
|
||||
fun p ->
|
||||
bind_map_list compile_declaration p
|
||||
|
||||
(* uncompiling *)
|
||||
let rec uncompile_type_expression : O.type_expression -> I.type_expression result =
|
||||
fun te ->
|
||||
let return te = ok @@ I.make_t te in
|
||||
match te.type_content with
|
||||
| O.T_sum sum ->
|
||||
let sum = I.CMap.to_kv_list sum in
|
||||
let%bind sum =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) sum
|
||||
in
|
||||
return @@ I.T_sum (O.CMap.of_list sum)
|
||||
| O.T_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ I.T_record (O.LMap.of_list record)
|
||||
| O.T_arrow {type1;type2} ->
|
||||
let%bind type1 = uncompile_type_expression type1 in
|
||||
let%bind type2 = uncompile_type_expression type2 in
|
||||
return @@ T_arrow {type1;type2}
|
||||
| O.T_variable type_variable -> return @@ T_variable type_variable
|
||||
| O.T_constant type_constant -> return @@ T_constant type_constant
|
||||
| O.T_operator type_operator ->
|
||||
let%bind type_operator = uncompile_type_operator type_operator in
|
||||
return @@ T_operator type_operator
|
||||
|
||||
and uncompile_type_operator : O.type_operator -> I.type_operator result =
|
||||
fun t_o ->
|
||||
match t_o with
|
||||
| TC_contract c ->
|
||||
let%bind c = uncompile_type_expression c in
|
||||
ok @@ I.TC_contract c
|
||||
| TC_option o ->
|
||||
let%bind o = uncompile_type_expression o in
|
||||
ok @@ I.TC_option o
|
||||
| TC_list l ->
|
||||
let%bind l = uncompile_type_expression l in
|
||||
ok @@ I.TC_list l
|
||||
| TC_set s ->
|
||||
let%bind s = uncompile_type_expression s in
|
||||
ok @@ I.TC_set s
|
||||
| TC_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair uncompile_type_expression (k,v) in
|
||||
ok @@ I.TC_map (k,v)
|
||||
| TC_big_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair uncompile_type_expression (k,v) in
|
||||
ok @@ I.TC_big_map (k,v)
|
||||
| TC_arrow (i,o) ->
|
||||
let%bind (i,o) = bind_map_pair uncompile_type_expression (i,o) in
|
||||
ok @@ I.TC_arrow (i,o)
|
||||
|
||||
let rec uncompile_expression : O.expression -> I.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ I.make_expr ~loc:e.location expr in
|
||||
match e.expression_content with
|
||||
O.E_literal lit -> return @@ I.E_literal lit
|
||||
| O.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list uncompile_expression arguments in
|
||||
return @@ I.E_constant {cons_name;arguments}
|
||||
| O.E_variable name -> return @@ I.E_variable name
|
||||
| O.E_application {lamb; args} ->
|
||||
let%bind lamb = uncompile_expression lamb in
|
||||
let%bind args = uncompile_expression args in
|
||||
return @@ I.E_application {lamb; args}
|
||||
| O.E_lambda lambda ->
|
||||
let%bind lambda = uncompile_lambda lambda in
|
||||
return @@ I.E_lambda lambda
|
||||
| O.E_recursive {fun_name;fun_type;lambda} ->
|
||||
let%bind fun_type = uncompile_type_expression fun_type in
|
||||
let%bind lambda = uncompile_lambda lambda in
|
||||
return @@ I.E_recursive {fun_name;fun_type;lambda}
|
||||
| O.E_let_in {let_binder;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option uncompile_type_expression ty_opt in
|
||||
let%bind rhs = uncompile_expression rhs in
|
||||
let%bind let_result = uncompile_expression let_result in
|
||||
return @@ I.E_let_in {let_binder=(binder,ty_opt);mut=false;inline;rhs;let_result}
|
||||
| O.E_constructor {constructor;element} ->
|
||||
let%bind element = uncompile_expression element in
|
||||
return @@ I.E_constructor {constructor;element}
|
||||
| O.E_matching {matchee; cases} ->
|
||||
let%bind matchee = uncompile_expression matchee in
|
||||
let%bind cases = uncompile_matching cases in
|
||||
return @@ I.E_matching {matchee;cases}
|
||||
| O.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ I.E_record (O.LMap.of_list record)
|
||||
| O.E_record_accessor {expr;label} ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
return @@ I.E_record_accessor {expr;label}
|
||||
| O.E_record_update {record;path;update} ->
|
||||
let%bind record = uncompile_expression record in
|
||||
let%bind update = uncompile_expression update in
|
||||
return @@ I.E_record_update {record;path;update}
|
||||
| O.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
) map
|
||||
in
|
||||
return @@ I.E_map map
|
||||
| O.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
) big_map
|
||||
in
|
||||
return @@ I.E_big_map big_map
|
||||
| O.E_list lst ->
|
||||
let%bind lst = bind_map_list uncompile_expression lst in
|
||||
return @@ I.E_list lst
|
||||
| O.E_set set ->
|
||||
let%bind set = bind_map_list uncompile_expression set in
|
||||
return @@ I.E_set set
|
||||
| O.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair uncompile_expression look_up in
|
||||
return @@ I.E_look_up look_up
|
||||
| O.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = uncompile_expression anno_expr in
|
||||
let%bind type_annotation = uncompile_type_expression type_annotation in
|
||||
return @@ I.E_ascription {anno_expr; type_annotation}
|
||||
| O.E_sequence {expr1; expr2} ->
|
||||
let%bind expr1 = uncompile_expression expr1 in
|
||||
let%bind expr2 = uncompile_expression expr2 in
|
||||
return @@ I.E_sequence {expr1; expr2}
|
||||
| O.E_skip -> return @@ I.E_skip
|
||||
|
||||
and uncompile_lambda : O.lambda -> I.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
let%bind input_type = bind_map_option uncompile_type_expression input_type in
|
||||
let%bind output_type = bind_map_option uncompile_type_expression output_type in
|
||||
let%bind result = uncompile_expression result in
|
||||
ok @@ I.{binder;input_type;output_type;result}
|
||||
and uncompile_matching : O.matching_expr -> I.matching_expr result =
|
||||
fun m ->
|
||||
match m with
|
||||
| O.Match_bool {match_true;match_false} ->
|
||||
let%bind match_true = uncompile_expression match_true in
|
||||
let%bind match_false = uncompile_expression match_false in
|
||||
ok @@ I.Match_bool {match_true;match_false}
|
||||
| O.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil = uncompile_expression match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ I.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}
|
||||
| O.Match_option {match_none;match_some} ->
|
||||
let%bind match_none = uncompile_expression match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ I.Match_option {match_none; match_some=(n,expr,tv)}
|
||||
| O.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ O.Match_tuple ((lst,expr), tv)
|
||||
| O.Match_variant (lst,tv) ->
|
||||
let%bind lst = bind_map_list (
|
||||
fun ((c,n),expr) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ ((c,n),expr)
|
||||
) lst
|
||||
in
|
||||
ok @@ I.Match_variant (lst,tv)
|
13
src/passes/5-self_ast_sugar/dune
Normal file
13
src/passes/5-self_ast_sugar/dune
Normal file
@ -0,0 +1,13 @@
|
||||
(library
|
||||
(name self_ast_sugar)
|
||||
(public_name ligo.self_ast_sugar)
|
||||
(libraries
|
||||
simple-utils
|
||||
ast_sugar
|
||||
proto-alpha-utils
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||
)
|
14
src/passes/6-sugar_to_core/dune
Normal file
14
src/passes/6-sugar_to_core/dune
Normal file
@ -0,0 +1,14 @@
|
||||
(library
|
||||
(name sugar_to_core)
|
||||
(public_name ligo.sugar_to_core)
|
||||
(libraries
|
||||
simple-utils
|
||||
ast_sugar
|
||||
ast_core
|
||||
proto-alpha-utils
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||
)
|
363
src/passes/6-sugar_to_core/sugar_to_core.ml
Normal file
363
src/passes/6-sugar_to_core/sugar_to_core.ml
Normal file
@ -0,0 +1,363 @@
|
||||
module I = Ast_sugar
|
||||
module O = Ast_core
|
||||
open Trace
|
||||
|
||||
let rec idle_type_expression : I.type_expression -> O.type_expression result =
|
||||
fun te ->
|
||||
let return te = ok @@ O.make_t te in
|
||||
match te.type_content with
|
||||
| I.T_sum sum ->
|
||||
let sum = I.CMap.to_kv_list sum in
|
||||
let%bind sum =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = idle_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) sum
|
||||
in
|
||||
return @@ O.T_sum (O.CMap.of_list sum)
|
||||
| I.T_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = idle_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ O.T_record (O.LMap.of_list record)
|
||||
| I.T_arrow {type1;type2} ->
|
||||
let%bind type1 = idle_type_expression type1 in
|
||||
let%bind type2 = idle_type_expression type2 in
|
||||
return @@ T_arrow {type1;type2}
|
||||
| I.T_variable type_variable -> return @@ T_variable type_variable
|
||||
| I.T_constant type_constant -> return @@ T_constant type_constant
|
||||
| I.T_operator type_operator ->
|
||||
let%bind type_operator = idle_type_operator type_operator in
|
||||
return @@ T_operator type_operator
|
||||
|
||||
and idle_type_operator : I.type_operator -> O.type_operator result =
|
||||
fun t_o ->
|
||||
match t_o with
|
||||
| TC_contract c ->
|
||||
let%bind c = idle_type_expression c in
|
||||
ok @@ O.TC_contract c
|
||||
| TC_option o ->
|
||||
let%bind o = idle_type_expression o in
|
||||
ok @@ O.TC_option o
|
||||
| TC_list l ->
|
||||
let%bind l = idle_type_expression l in
|
||||
ok @@ O.TC_list l
|
||||
| TC_set s ->
|
||||
let%bind s = idle_type_expression s in
|
||||
ok @@ O.TC_set s
|
||||
| TC_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair idle_type_expression (k,v) in
|
||||
ok @@ O.TC_map (k,v)
|
||||
| TC_big_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair idle_type_expression (k,v) in
|
||||
ok @@ O.TC_big_map (k,v)
|
||||
| TC_arrow (i,o) ->
|
||||
let%bind (i,o) = bind_map_pair idle_type_expression (i,o) in
|
||||
ok @@ O.TC_arrow (i,o)
|
||||
|
||||
let rec compile_expression : I.expression -> O.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ O.make_expr ~loc:e.location expr in
|
||||
match e.expression_content with
|
||||
| I.E_literal literal -> return @@ O.E_literal literal
|
||||
| I.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list compile_expression arguments in
|
||||
return @@ O.E_constant {cons_name;arguments}
|
||||
| I.E_variable name -> return @@ O.E_variable name
|
||||
| I.E_application {lamb;args} ->
|
||||
let%bind lamb = compile_expression lamb in
|
||||
let%bind args = compile_expression args in
|
||||
return @@ O.E_application {lamb; args}
|
||||
| I.E_lambda lambda ->
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_lambda lambda
|
||||
| I.E_recursive {fun_name;fun_type;lambda} ->
|
||||
let%bind fun_type = idle_type_expression fun_type in
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_recursive {fun_name;fun_type;lambda}
|
||||
| I.E_let_in {let_binder;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option idle_type_expression ty_opt in
|
||||
let%bind rhs = compile_expression rhs in
|
||||
let%bind let_result = compile_expression let_result in
|
||||
return @@ O.E_let_in {let_binder=(binder,ty_opt);inline;rhs;let_result}
|
||||
| I.E_constructor {constructor;element} ->
|
||||
let%bind element = compile_expression element in
|
||||
return @@ O.E_constructor {constructor;element}
|
||||
| I.E_matching {matchee; cases} ->
|
||||
let%bind matchee = compile_expression matchee in
|
||||
let%bind cases = compile_matching cases in
|
||||
return @@ O.E_matching {matchee;cases}
|
||||
| I.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v =compile_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ O.E_record (O.LMap.of_list record)
|
||||
| I.E_record_accessor {expr;label} ->
|
||||
let%bind expr = compile_expression expr in
|
||||
return @@ O.E_record_accessor {expr;label}
|
||||
| I.E_record_update {record;path;update} ->
|
||||
let%bind record = compile_expression record in
|
||||
let%bind update = compile_expression update in
|
||||
return @@ O.E_record_update {record;path;update}
|
||||
| I.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) map
|
||||
in
|
||||
return @@ O.E_map map
|
||||
| I.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) big_map
|
||||
in
|
||||
return @@ O.E_big_map big_map
|
||||
| I.E_list lst ->
|
||||
let%bind lst = bind_map_list compile_expression lst in
|
||||
return @@ O.E_list lst
|
||||
| I.E_set set ->
|
||||
let%bind set = bind_map_list compile_expression set in
|
||||
return @@ O.E_set set
|
||||
| I.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair compile_expression look_up in
|
||||
return @@ O.E_look_up look_up
|
||||
| I.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = compile_expression anno_expr in
|
||||
let%bind type_annotation = idle_type_expression type_annotation in
|
||||
return @@ O.E_ascription {anno_expr; type_annotation}
|
||||
| I.E_sequence {expr1; expr2} ->
|
||||
let%bind expr1 = compile_expression expr1 in
|
||||
let%bind expr2 = compile_expression expr2 in
|
||||
return @@ O.E_let_in {let_binder=(Var.of_name "_", Some O.t_unit); rhs=expr1;let_result=expr2; inline=false}
|
||||
| I.E_skip -> ok @@ O.e_unit ~loc:e.location ()
|
||||
|
||||
and compile_lambda : I.lambda -> O.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
let%bind input_type = bind_map_option idle_type_expression input_type in
|
||||
let%bind output_type = bind_map_option idle_type_expression output_type in
|
||||
let%bind result = compile_expression result in
|
||||
ok @@ O.{binder;input_type;output_type;result}
|
||||
and compile_matching : I.matching_expr -> O.matching_expr result =
|
||||
fun m ->
|
||||
match m with
|
||||
| I.Match_bool {match_true;match_false} ->
|
||||
let%bind match_true = compile_expression match_true in
|
||||
let%bind match_false = compile_expression match_false in
|
||||
ok @@ O.Match_bool {match_true;match_false}
|
||||
| I.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil = compile_expression match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}
|
||||
| I.Match_option {match_none;match_some} ->
|
||||
let%bind match_none = compile_expression match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_option {match_none; match_some=(n,expr,tv)}
|
||||
| I.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.Match_tuple ((lst,expr), tv)
|
||||
| I.Match_variant (lst,tv) ->
|
||||
let%bind lst = bind_map_list (
|
||||
fun ((c,n),expr) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ ((c,n),expr)
|
||||
) lst
|
||||
in
|
||||
ok @@ O.Match_variant (lst,tv)
|
||||
|
||||
let compile_declaration : I.declaration Location.wrap -> _ =
|
||||
fun {wrap_content=declaration;location} ->
|
||||
let return decl = ok @@ Location.wrap ~loc:location decl in
|
||||
match declaration with
|
||||
| I.Declaration_constant (n, te_opt, inline, expr) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
let%bind te_opt = bind_map_option idle_type_expression te_opt in
|
||||
return @@ O.Declaration_constant (n, te_opt, inline, expr)
|
||||
| I.Declaration_type (n, te) ->
|
||||
let%bind te = idle_type_expression te in
|
||||
return @@ O.Declaration_type (n,te)
|
||||
|
||||
let compile_program : I.program -> O.program result =
|
||||
fun p ->
|
||||
bind_map_list compile_declaration p
|
||||
|
||||
(* uncompiling *)
|
||||
let rec uncompile_type_expression : O.type_expression -> I.type_expression result =
|
||||
fun te ->
|
||||
let return te = ok @@ I.make_t te in
|
||||
match te.type_content with
|
||||
| O.T_sum sum ->
|
||||
let sum = I.CMap.to_kv_list sum in
|
||||
let%bind sum =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) sum
|
||||
in
|
||||
return @@ I.T_sum (O.CMap.of_list sum)
|
||||
| O.T_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_type_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ I.T_record (O.LMap.of_list record)
|
||||
| O.T_arrow {type1;type2} ->
|
||||
let%bind type1 = uncompile_type_expression type1 in
|
||||
let%bind type2 = uncompile_type_expression type2 in
|
||||
return @@ T_arrow {type1;type2}
|
||||
| O.T_variable type_variable -> return @@ T_variable type_variable
|
||||
| O.T_constant type_constant -> return @@ T_constant type_constant
|
||||
| O.T_operator type_operator ->
|
||||
let%bind type_operator = uncompile_type_operator type_operator in
|
||||
return @@ T_operator type_operator
|
||||
|
||||
and uncompile_type_operator : O.type_operator -> I.type_operator result =
|
||||
fun t_o ->
|
||||
match t_o with
|
||||
| TC_contract c ->
|
||||
let%bind c = uncompile_type_expression c in
|
||||
ok @@ I.TC_contract c
|
||||
| TC_option o ->
|
||||
let%bind o = uncompile_type_expression o in
|
||||
ok @@ I.TC_option o
|
||||
| TC_list l ->
|
||||
let%bind l = uncompile_type_expression l in
|
||||
ok @@ I.TC_list l
|
||||
| TC_set s ->
|
||||
let%bind s = uncompile_type_expression s in
|
||||
ok @@ I.TC_set s
|
||||
| TC_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair uncompile_type_expression (k,v) in
|
||||
ok @@ I.TC_map (k,v)
|
||||
| TC_big_map (k,v) ->
|
||||
let%bind (k,v) = bind_map_pair uncompile_type_expression (k,v) in
|
||||
ok @@ I.TC_big_map (k,v)
|
||||
| TC_arrow (i,o) ->
|
||||
let%bind (i,o) = bind_map_pair uncompile_type_expression (i,o) in
|
||||
ok @@ I.TC_arrow (i,o)
|
||||
|
||||
let rec uncompile_expression : O.expression -> I.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ I.make_expr ~loc:e.location expr in
|
||||
match e.expression_content with
|
||||
O.E_literal lit -> return @@ I.E_literal lit
|
||||
| O.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list uncompile_expression arguments in
|
||||
return @@ I.E_constant {cons_name;arguments}
|
||||
| O.E_variable name -> return @@ I.E_variable name
|
||||
| O.E_application {lamb; args} ->
|
||||
let%bind lamb = uncompile_expression lamb in
|
||||
let%bind args = uncompile_expression args in
|
||||
return @@ I.E_application {lamb; args}
|
||||
| O.E_lambda lambda ->
|
||||
let%bind lambda = uncompile_lambda lambda in
|
||||
return @@ I.E_lambda lambda
|
||||
| O.E_recursive {fun_name;fun_type;lambda} ->
|
||||
let%bind fun_type = uncompile_type_expression fun_type in
|
||||
let%bind lambda = uncompile_lambda lambda in
|
||||
return @@ I.E_recursive {fun_name;fun_type;lambda}
|
||||
| O.E_let_in {let_binder;inline=false;rhs=expr1;let_result=expr2} when let_binder = (Var.of_name "_", Some O.t_unit) ->
|
||||
let%bind expr1 = uncompile_expression expr1 in
|
||||
let%bind expr2 = uncompile_expression expr2 in
|
||||
return @@ I.E_sequence {expr1;expr2}
|
||||
| O.E_let_in {let_binder;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option uncompile_type_expression ty_opt in
|
||||
let%bind rhs = uncompile_expression rhs in
|
||||
let%bind let_result = uncompile_expression let_result in
|
||||
return @@ I.E_let_in {let_binder=(binder,ty_opt);inline;rhs;let_result}
|
||||
| O.E_constructor {constructor;element} ->
|
||||
let%bind element = uncompile_expression element in
|
||||
return @@ I.E_constructor {constructor;element}
|
||||
| O.E_matching {matchee; cases} ->
|
||||
let%bind matchee = uncompile_expression matchee in
|
||||
let%bind cases = uncompile_matching cases in
|
||||
return @@ I.E_matching {matchee;cases}
|
||||
| O.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ I.E_record (O.LMap.of_list record)
|
||||
| O.E_record_accessor {expr;label} ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
return @@ I.E_record_accessor {expr;label}
|
||||
| O.E_record_update {record;path;update} ->
|
||||
let%bind record = uncompile_expression record in
|
||||
let%bind update = uncompile_expression update in
|
||||
return @@ I.E_record_update {record;path;update}
|
||||
| O.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
) map
|
||||
in
|
||||
return @@ I.E_map map
|
||||
| O.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
) big_map
|
||||
in
|
||||
return @@ I.E_big_map big_map
|
||||
| O.E_list lst ->
|
||||
let%bind lst = bind_map_list uncompile_expression lst in
|
||||
return @@ I.E_list lst
|
||||
| O.E_set set ->
|
||||
let%bind set = bind_map_list uncompile_expression set in
|
||||
return @@ I.E_set set
|
||||
| O.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair uncompile_expression look_up in
|
||||
return @@ I.E_look_up look_up
|
||||
| O.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = uncompile_expression anno_expr in
|
||||
let%bind type_annotation = uncompile_type_expression type_annotation in
|
||||
return @@ I.E_ascription {anno_expr; type_annotation}
|
||||
|
||||
and uncompile_lambda : O.lambda -> I.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
let%bind input_type = bind_map_option uncompile_type_expression input_type in
|
||||
let%bind output_type = bind_map_option uncompile_type_expression output_type in
|
||||
let%bind result = uncompile_expression result in
|
||||
ok @@ I.{binder;input_type;output_type;result}
|
||||
and uncompile_matching : O.matching_expr -> I.matching_expr result =
|
||||
fun m ->
|
||||
match m with
|
||||
| O.Match_bool {match_true;match_false} ->
|
||||
let%bind match_true = uncompile_expression match_true in
|
||||
let%bind match_false = uncompile_expression match_false in
|
||||
ok @@ I.Match_bool {match_true;match_false}
|
||||
| O.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil = uncompile_expression match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ I.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}
|
||||
| O.Match_option {match_none;match_some} ->
|
||||
let%bind match_none = uncompile_expression match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ I.Match_option {match_none; match_some=(n,expr,tv)}
|
||||
| O.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ O.Match_tuple ((lst,expr), tv)
|
||||
| O.Match_variant (lst,tv) ->
|
||||
let%bind lst = bind_map_list (
|
||||
fun ((c,n),expr) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
ok @@ ((c,n),expr)
|
||||
) lst
|
||||
in
|
||||
ok @@ I.Match_variant (lst,tv)
|
13
src/passes/7-self_ast_core/dune
Normal file
13
src/passes/7-self_ast_core/dune
Normal file
@ -0,0 +1,13 @@
|
||||
(library
|
||||
(name self_ast_core)
|
||||
(public_name ligo.self_ast_core)
|
||||
(libraries
|
||||
simple-utils
|
||||
ast_core
|
||||
proto-alpha-utils
|
||||
)
|
||||
(preprocess
|
||||
(pps ppx_let bisect_ppx --conditional)
|
||||
)
|
||||
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
|
||||
)
|
@ -4,7 +4,7 @@
|
||||
(libraries
|
||||
simple-utils
|
||||
tezos-utils
|
||||
ast_simplified
|
||||
ast_core
|
||||
ast_typed
|
||||
operators
|
||||
UnionFind
|
@ -3,7 +3,7 @@ open Trace
|
||||
module Core = Typesystem.Core
|
||||
|
||||
module Wrap = struct
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module T = Ast_typed
|
||||
module O = Core
|
||||
|
@ -1,6 +1,6 @@
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
open O.Combinators
|
||||
|
||||
@ -446,10 +446,6 @@ and type_expression : environment -> Solver.state -> ?tv_opt:O.type_expression -
|
||||
| E_literal (Literal_void) -> (
|
||||
failwith "TODO: missing implementation for literal void"
|
||||
)
|
||||
| E_skip -> (
|
||||
(* E_skip just returns unit *)
|
||||
return_wrapped (e_unit ()) state @@ Wrap.literal (t_unit ())
|
||||
)
|
||||
(* | E_literal (Literal_string s) -> (
|
||||
* L.log (Format.asprintf "literal_string option type: %a" PP_helpers.(option O.PP.type_expression) tv_opt) ;
|
||||
* match Option.map Ast_typed.get_type' tv_opt with
|
||||
@ -683,11 +679,11 @@ and type_expression : environment -> Solver.state -> ?tv_opt:O.type_expression -
|
||||
* let%bind (name', tv) =
|
||||
* type_constant name tv_lst tv_opt ae.location in
|
||||
* return (E_constant (name' , lst')) tv *)
|
||||
| E_application {expr1;expr2} ->
|
||||
let%bind (f' , state') = type_expression e state expr1 in
|
||||
let%bind (arg , state'') = type_expression e state' expr2 in
|
||||
let wrapped = Wrap.application f'.type_expression arg.type_expression in
|
||||
return_wrapped (E_application {expr1=f';expr2=arg}) state'' wrapped
|
||||
| E_application {lamb;args} ->
|
||||
let%bind (f' , state') = type_expression e state lamb in
|
||||
let%bind (args , state'') = type_expression e state' args in
|
||||
let wrapped = Wrap.application f'.type_expression args.type_expression in
|
||||
return_wrapped (E_application {lamb=f';args}) state'' wrapped
|
||||
|
||||
(* | E_look_up dsi ->
|
||||
* let%bind (ds, ind) = bind_map_pair (type_expression e) dsi in
|
||||
@ -872,7 +868,7 @@ let untype_type_value (t:O.type_expression) : (I.type_expression) result =
|
||||
(* TODO: we ended up with two versions of type_program… ??? *)
|
||||
|
||||
(*
|
||||
Apply type_declaration on all the node of the AST_simplified from the root p
|
||||
Apply type_declaration on all the node of the AST_core from the root p
|
||||
*)
|
||||
let type_program_returns_state ((env, state, p) : environment * Solver.state * I.program) : (environment * Solver.state * O.program) result =
|
||||
let aux ((e : environment), (s : Solver.state) , (ds : O.declaration Location.wrap list)) (d:I.declaration Location.wrap) =
|
||||
@ -950,10 +946,10 @@ let type_program' : I.program -> O.program result = fun p ->
|
||||
ok p'
|
||||
|
||||
(*
|
||||
Tranform a Ast_typed type_expression into an ast_simplified type_expression
|
||||
Tranform a Ast_typed type_expression into an ast_core type_expression
|
||||
*)
|
||||
let rec untype_type_expression (t:O.type_expression) : (I.type_expression) result =
|
||||
(* TODO: or should we use t.simplified if present? *)
|
||||
(* TODO: or should we use t.core if present? *)
|
||||
let%bind t = match t.type_content with
|
||||
| O.T_sum x ->
|
||||
let%bind x' = Stage_common.Helpers.bind_map_cmap untype_type_expression x in
|
||||
@ -999,13 +995,13 @@ let rec untype_type_expression (t:O.type_expression) : (I.type_expression) resul
|
||||
in
|
||||
ok @@ I.make_t t
|
||||
|
||||
(* match t.simplified with *)
|
||||
(* match t.core with *)
|
||||
(* | Some s -> ok s *)
|
||||
(* | _ -> fail @@ internal_assertion_failure "trying to untype generated type" *)
|
||||
|
||||
|
||||
(*
|
||||
Tranform a Ast_typed literal into an ast_simplified literal
|
||||
Tranform a Ast_typed literal into an ast_core literal
|
||||
*)
|
||||
let untype_literal (l:O.literal) : I.literal result =
|
||||
let open I in
|
||||
@ -1027,7 +1023,7 @@ let untype_literal (l:O.literal) : I.literal result =
|
||||
| Literal_operation s -> ok (Literal_operation s)
|
||||
|
||||
(*
|
||||
Tranform a Ast_typed expression into an ast_simplified matching
|
||||
Tranform a Ast_typed expression into an ast_core matching
|
||||
*)
|
||||
let rec untype_expression (e:O.expression) : (I.expression) result =
|
||||
let open I in
|
||||
@ -1041,9 +1037,9 @@ let rec untype_expression (e:O.expression) : (I.expression) result =
|
||||
return (e_constant cons_name lst')
|
||||
| E_variable (n) ->
|
||||
return (e_variable (n))
|
||||
| E_application {expr1;expr2} ->
|
||||
let%bind f' = untype_expression expr1 in
|
||||
let%bind arg' = untype_expression expr2 in
|
||||
| E_application {lamb;args} ->
|
||||
let%bind f' = untype_expression lamb in
|
||||
let%bind arg' = untype_expression args in
|
||||
return (e_application f' arg')
|
||||
| E_lambda lambda ->
|
||||
let%bind lambda = untype_lambda e.type_expression lambda in
|
||||
@ -1094,7 +1090,7 @@ let rec untype_expression (e:O.expression) : (I.expression) result =
|
||||
let%bind tv = untype_type_value rhs.type_expression in
|
||||
let%bind rhs = untype_expression rhs in
|
||||
let%bind result = untype_expression let_result in
|
||||
return (e_let_in (let_binder , (Some tv)) false inline rhs result)
|
||||
return (e_let_in (let_binder , (Some tv)) inline rhs result)
|
||||
| E_recursive {fun_name; fun_type; lambda} ->
|
||||
let%bind lambda = untype_lambda fun_type lambda in
|
||||
let%bind fun_type = untype_type_expression fun_type in
|
||||
@ -1107,7 +1103,7 @@ and untype_lambda ty {binder; result} : I.lambda result =
|
||||
ok ({binder;input_type = Some input_type; output_type = Some output_type; result}: I.lambda)
|
||||
|
||||
(*
|
||||
Tranform a Ast_typed matching into an ast_simplified matching
|
||||
Tranform a Ast_typed matching into an ast_core matching
|
||||
*)
|
||||
and untype_matching : (O.expression -> I.expression result) -> O.matching_expr -> I.matching_expr result = fun f m ->
|
||||
let open I in
|
@ -1,6 +1,6 @@
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
open O.Combinators
|
||||
|
||||
@ -736,7 +736,7 @@ and type_constant (name:string) (lst:O.type_expression list) (tv_opt:O.type_expr
|
||||
typer lst tv_opt
|
||||
|
||||
let untype_type_expression (t:O.type_expression) : (I.type_expression) result =
|
||||
match t.simplified with
|
||||
match t.core with
|
||||
| Some s -> ok s
|
||||
| _ -> fail @@ internal_assertion_failure "trying to untype generated type"
|
||||
|
@ -1,6 +1,6 @@
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
|
||||
module Environment = O.Environment
|
@ -4,7 +4,7 @@
|
||||
(libraries
|
||||
simple-utils
|
||||
tezos-utils
|
||||
ast_simplified
|
||||
ast_core
|
||||
ast_typed
|
||||
typer_new
|
||||
operators
|
@ -1,6 +1,6 @@
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
open O.Combinators
|
||||
|
||||
@ -423,7 +423,7 @@ and type_expression' : environment -> ?tv_opt:O.type_expression -> I.expression
|
||||
return (E_variable name) tv'.type_value
|
||||
| E_literal (Literal_bool b) ->
|
||||
return (E_literal (Literal_bool b)) (t_bool ())
|
||||
| E_literal Literal_unit | E_skip ->
|
||||
| E_literal Literal_unit ->
|
||||
return (E_literal (Literal_unit)) (t_unit ())
|
||||
| E_literal Literal_void -> return (E_literal (Literal_void)) (t_unit ()) (* TODO : IS this really a t_unit ?*)
|
||||
| E_literal (Literal_string s) ->
|
||||
@ -688,21 +688,21 @@ and type_expression' : environment -> ?tv_opt:O.type_expression -> I.expression
|
||||
let%bind (name', tv) =
|
||||
type_constant cons_name tv_lst tv_opt in
|
||||
return (E_constant {cons_name=name';arguments=lst'}) tv
|
||||
| E_application {expr1;expr2} ->
|
||||
let%bind expr1' = type_expression' e expr1 in
|
||||
let%bind expr2 = type_expression' e expr2 in
|
||||
let%bind tv = match expr1'.type_expression.type_content with
|
||||
| E_application {lamb; args} ->
|
||||
let%bind lamb' = type_expression' e lamb in
|
||||
let%bind args' = type_expression' e args in
|
||||
let%bind tv = match lamb'.type_expression.type_content with
|
||||
| T_arrow {type1;type2} ->
|
||||
let%bind _ = O.assert_type_expression_eq (type1, expr2.type_expression) in
|
||||
let%bind _ = O.assert_type_expression_eq (type1, args'.type_expression) in
|
||||
ok type2
|
||||
| _ ->
|
||||
fail @@ type_error_approximate
|
||||
~expected:"should be a function type"
|
||||
~expression:expr1
|
||||
~actual:expr1'.type_expression
|
||||
expr1'.location
|
||||
~expression:lamb
|
||||
~actual:lamb'.type_expression
|
||||
lamb'.location
|
||||
in
|
||||
return (E_application {expr1=expr1';expr2}) tv
|
||||
return (E_application {lamb=lamb'; args=args'}) tv
|
||||
| E_look_up dsi ->
|
||||
let%bind (ds, ind) = bind_map_pair (type_expression' e) dsi in
|
||||
let%bind (src, dst) = bind_map_or (get_t_map , get_t_big_map) ds.type_expression in
|
||||
@ -841,9 +841,9 @@ let rec untype_expression (e:O.expression) : (I.expression) result =
|
||||
return (e_constant cons_name lst')
|
||||
| E_variable n ->
|
||||
return (e_variable (n))
|
||||
| E_application {expr1;expr2} ->
|
||||
let%bind f' = untype_expression expr1 in
|
||||
let%bind arg' = untype_expression expr2 in
|
||||
| E_application {lamb;args} ->
|
||||
let%bind f' = untype_expression lamb in
|
||||
let%bind arg' = untype_expression args in
|
||||
return (e_application f' arg')
|
||||
| E_lambda {binder ; result} -> (
|
||||
let%bind io = get_t_function ty in
|
||||
@ -893,7 +893,7 @@ let rec untype_expression (e:O.expression) : (I.expression) result =
|
||||
let%bind tv = untype_type_expression rhs.type_expression in
|
||||
let%bind rhs = untype_expression rhs in
|
||||
let%bind result = untype_expression let_result in
|
||||
return (e_let_in (let_binder , (Some tv)) false inline rhs result)
|
||||
return (e_let_in (let_binder , (Some tv)) inline rhs result)
|
||||
| E_recursive {fun_name;fun_type; lambda} ->
|
||||
let%bind fun_type = untype_type_expression fun_type in
|
||||
let%bind unty_expr= untype_expression_content ty @@ E_lambda lambda in
|
@ -1,6 +1,6 @@
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
|
||||
module Environment = O.Environment
|
@ -4,7 +4,7 @@
|
||||
(libraries
|
||||
simple-utils
|
||||
tezos-utils
|
||||
ast_simplified
|
||||
ast_core
|
||||
ast_typed
|
||||
typer_old
|
||||
typer_new
|
@ -1,6 +1,6 @@
|
||||
let use_new_typer = false
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
|
||||
module Environment = O.Environment
|
@ -2,7 +2,7 @@ val use_new_typer : bool
|
||||
|
||||
open Trace
|
||||
|
||||
module I = Ast_simplified
|
||||
module I = Ast_core
|
||||
module O = Ast_typed
|
||||
|
||||
module Environment = O.Environment
|
@ -19,8 +19,8 @@ let rec fold_expression : 'a folder -> 'a -> expression -> 'a result = fun f ini
|
||||
| E_look_up ab ->
|
||||
let%bind res = bind_fold_pair self init' ab in
|
||||
ok res
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
| E_application {lamb; args} -> (
|
||||
let ab = (lamb, args) in
|
||||
let%bind res = bind_fold_pair self init' ab in
|
||||
ok res
|
||||
)
|
||||
@ -135,10 +135,10 @@ let rec map_expression : mapper -> expression -> expression result = fun f e ->
|
||||
let%bind e' = self c.element in
|
||||
return @@ E_constructor {c with element = e'}
|
||||
)
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
| E_application {lamb; args} -> (
|
||||
let ab = (lamb, args) in
|
||||
let%bind (a,b) = bind_map_pair self ab in
|
||||
return @@ E_application {expr1=a;expr2=b}
|
||||
return @@ E_application {lamb=a;args=b}
|
||||
)
|
||||
| E_let_in { let_binder ; rhs ; let_result; inline } -> (
|
||||
let%bind rhs = self rhs in
|
||||
@ -251,10 +251,10 @@ let rec fold_map_expression : 'a fold_mapper -> 'a -> expression -> ('a * expres
|
||||
let%bind (res,e') = self init' c.element in
|
||||
ok (res, return @@ E_constructor {c with element = e'})
|
||||
)
|
||||
| E_application {expr1;expr2} -> (
|
||||
let ab = (expr1,expr2) in
|
||||
| E_application {lamb;args} -> (
|
||||
let ab = (lamb, args) in
|
||||
let%bind (res,(a,b)) = bind_fold_map_pair self init' ab in
|
||||
ok (res, return @@ E_application {expr1=a;expr2=b})
|
||||
ok (res, return @@ E_application {lamb=a;args=b})
|
||||
)
|
||||
| E_let_in { let_binder ; rhs ; let_result; inline } -> (
|
||||
let%bind (res,rhs) = self init' rhs in
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user