Compare commits

..

9 Commits

Author SHA1 Message Date
Hans Svensson 311bf49505 Prepare v7.1.0 release (#438) 2023-02-24 09:40:06 +01:00
Denis Davidyuk 0e3bcba07d Fix markup in sophia_features.md (#437) 2023-02-15 13:27:29 +03:00
Marco Walz 699d1f7ab8 fix: use latest pygments version to generate docs (#435) 2023-02-02 08:32:54 +01:00
Marco Walz 1a40a93157 chore(deps): mkdocs version update (#434) 2023-02-02 10:16:27 +03:00
Gaith Hallak c078119bc4 Add hole expression (#433)
* Add hole expressions

* Fix the issue of unreported holes

* Add tests

* New line in the end of the test file

* Update CHANGELOG

* Add hole expression to the docs

* Do not treat hole as a special type

* Update docs

* Update docs/sophia_features.md

Co-authored-by: Radosław Rowicki <35342116+radrow@users.noreply.github.com>

Co-authored-by: Radosław Rowicki <35342116+radrow@users.noreply.github.com>
2023-01-12 16:23:36 +03:00
Gaith Hallak 31fd8fe24f Hide warning when calling with non-0 value arg (#431)
* Hide warning when calling with non-0 value arg

* Update the tests

* Update CHANGELOG
2022-12-12 11:44:24 +03:00
Nikita Fuchs 9ad8e26e88 Add clarification for Chain.timestamp in the stdlib docs (#429) 2022-12-07 17:34:55 +03:00
Gaith Hallak 5adeb6c93e Ban using contracts as namespaces (#428)
* Ban calling contracts functions as functions namespaces

* Ban using contracts as namespaces

* Add tests

* Update CHANGELOG

* Separate guards with a semicolon
2022-11-23 12:03:24 +03:00
Gaith Hallak 256df25af4 Check contracts and entrypoints modifiers when implementing interfaces (#427)
* Check contracts and entrypoints modifiers when implementing interfaces

* Fix existing tests

* Add passing tests

* Add failing tests

* Update docs

* Update CHANGELOG
2022-11-17 11:40:57 +03:00
39 changed files with 577 additions and 373 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
mkdocs==1.2.4
mkdocs==1.4.2
mkdocs-simple-hooks==0.1.5
mkdocs-material==7.3.6
mkdocs-material==9.0.9
mike==1.1.2
pygments==2.12.0
pygments==2.14.0
+9 -17
View File
@@ -4,25 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [CERES 8.0.0]
## [Unreleased]
### Added
- Bitwise operations for integers: `band`, `bor`, `bxor`, `bnot`, `<<` and `>>`.
- `Int.mulmod` - combined builtin operation for multiplication and modulus.
- `Crypto.poseidon` - a ZK/SNARK-friendly hash function (over the BLS12-381 scalar field).
- `Address.to_bytes` - convert an address to its binary representation (for hashing, etc.).
- Raw data pointers added to AENS. In short we have introduced a new namespace
`AENSv2`; they contain types similar to the old `AENS`; `AENS.name` and
`AENS.pointee`, where the latter now has a constructor `DataPt(string)`. All
AENS actions have been moved to `AENSv2`, and `AENSv2.lookup` and
`AENSv2.update` consume and produce the new types. The old `AENS` namespace
only contains the old datatypes, that can be used to interface existing
contracts. Standard library `AENSCompat` is added to convert between old and
new pointers.
### Changed
### Removed
- `Bitwise.aes` standard library is removed - the builtin operations are superior.
### Fixed
## [Unreleased]
## [7.1.0]
### Added
- Options to enable/disable certain optimizations.
- The ability to call a different instance of the current contract
@@ -32,9 +20,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
entrypoint f(c : Main) : int = c.spend(10)
```
- Return a mapping from variables to FATE registers in the compilation output.
- Hole expression.
### Changed
- Type definitions serialised to ACI as `typedefs` field instead of `type_defs` to increase compatibility.
### Removed
- Check contracts and entrypoints modifiers when implementing interfaces.
- Contracts can no longer be used as namespaces.
- Do not show unused stateful warning for functions that call other contracts with a non-zero value argument.
### Fixed
- Typechecker crashes if Chain.create or Chain.clone are used without arguments.
@@ -389,7 +380,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Simplify calldata creation - instead of passing a compiled contract, simply
pass a (stubbed) contract string.
[Unreleased]: https://github.com/aeternity/aesophia/compare/v7.0.1...HEAD
[Unreleased]: https://github.com/aeternity/aesophia/compare/v7.1.0...HEAD
[7.1.0]: https://github.com/aeternity/aesophia/compare/v7.0.1...v7.1.0
[7.0.1]: https://github.com/aeternity/aesophia/compare/v7.0.0...v7.0.1
[7.0.0]: https://github.com/aeternity/aesophia/compare/v6.1.0...v7.0.0
[6.1.0]: https://github.com/aeternity/aesophia/compare/v6.0.2...v6.1.0
+28 -12
View File
@@ -191,6 +191,17 @@ contract interface X : Z =
entrypoint z() = 1
```
#### Adding or removing modifiers
When a `contract` or a `contract interface` implements another `contract interface`, the `payable` and `stateful` modifiers can be kept or changed, both in the contract and in the entrypoints, according to the following rules:
1. A `payable` contract or interface can implement a `payable` interface or a non-`payable` interface.
2. A non-`payable` contract or interface can only implement a non-`payable` interface, and cannot implement a `payable` interface.
3. A `payable` entrypoint can implement a `payable` entrypoint or a non-`payable` entrypoint.
4. A non-`payable` entrypoint can only implement a non-`payable` entrypoint, and cannot implement a `payable` entrypoint.
5. A non-`stateful` entrypoint can implement a `stateful` entrypoint or a non-`stateful` entrypoint.
6. A `stateful` entrypoint can only implement a `stateful` entrypoint, and cannot implement a non-`stateful` entrypoint.
#### Subtyping and variance
Subtyping in Sophia follows common rules that take type variance into account. As described by [Wikipedia](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)),
@@ -245,10 +256,10 @@ datatype bi('a) = Bi // bi is bivariant on 'a
The following facts apply here:
- `co('a)` is a subtype of `co('b) when `'a` is a subtype of `'b`
- `ct('a)` is a subtype of `ct('b) when `'b` is a subtype of `'a`
- `in('a)` is a subtype of `in('b) when `'a` is equal to `'b`
- `bi('a)` is a subtype of `bi('b) always
- `co('a)` is a subtype of `co('b)` when `'a` is a subtype of `'b`
- `ct('a)` is a subtype of `ct('b)` when `'b` is a subtype of `'a`
- `in('a)` is a subtype of `in('b)` when `'a` is equal to `'b`
- `bi('a)` is a subtype of `bi('b)` always
That altogether induce the following rules of subtyping in Sophia:
@@ -549,6 +560,19 @@ Sophia has the following types:
| oracle_query('a, 'b) | `oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY` |
| contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` |
## Hole expression
Hole expressions, written as `???`, are expressions that are used as a placeholder. During compilation, the compiler will generate a type error indication the type of the hole expression.
```
include "List.aes"
contract C =
entrypoint f() =
List.sum(List.map(???, [1,2,3]))
```
A hole expression found in the example above will generate the error `` Found a hole of type `(int) => int` ``. This says that the compiler expects a function from `int` to `int` in place of the `???` placeholder.
## Arithmetic
Sophia integers (`int`) are represented by arbitrary-sized signed words and support the following
@@ -564,14 +588,6 @@ All operations are *safe* with respect to overflow and underflow.
The division and modulo operations throw an arithmetic error if the
right-hand operand is zero.
Sophia arbitrary-sized integers (FATE) also supports the following bitwise operations:
- bitwise and (`x band y`)
- bitwise or (`x bor y`)
- bitwise xor (`x bxor y`)
- bitwise not (`bnot x`)
- arithmetic bitshift left (`x << n`)
- arithmetic bitshift right (`x >> n`)
## Bit fields
Sophia integers do not support bit arithmetic. Instead there is a separate
+96 -105
View File
@@ -14,7 +14,6 @@ The out-of-the-box namespaces are:
- [Address](#address)
- [AENS](#aens)
- [AENSv2](#aensv2)
- [Auth](#auth)
- [Bits](#bits)
- [Bytes](#bytes)
@@ -32,7 +31,6 @@ The following ones need to be included as regular files with `.aes` suffix, for
include "List.aes"
```
- [AENSCompat](#aenscompat)
- [Bitwise](#bitwise)
- [BLS12_381](#bls12_381)
- [Func](#func)
@@ -92,10 +90,13 @@ Cast address to contract type C (where `C` is a contract)
### AENS
The old AENS namespace, kept in the compiler to be able to interact with
contracts from before Ceres, compiled using aesophia compiler version 7.x and
earlier. Used in [AENSCompat](#aenscompat) when converting between old and new
pointers.
The following functionality is available for interacting with the æternity
naming system (AENS).
If `owner` is equal to `Contract.address` the signature `signature` is
ignored, and can be left out since it is a named argument. Otherwise we need
a signature to prove that we are allowed to do AENS operations on behalf of
`owner`. The [signature is tied to a network id](https://github.com/aeternity/protocol/blob/iris/consensus/consensus.md#transaction-signature),
i.e. the signature material should be prefixed by the network id.
#### Types
@@ -112,41 +113,12 @@ datatype pointee = AccountPt(address) | OraclePt(address)
| ContractPt(address) | ChannelPt(address)
```
### AENSv2
Note: introduced in v8.0
The following functionality is available for interacting with the æternity
naming system (AENS). If `owner` is equal to `Contract.address` the signature
`signature` is ignored, and can be left out since it is a named argument.
Otherwise we need a signature to prove that we are allowed to do AENS
operations on behalf of `owner`. The [signature is tied to a network
id](https://github.com/aeternity/protocol/blob/iris/consensus/consensus.md#transaction-signature),
i.e. the signature material should be prefixed by the network id.
#### Types
##### name
```
datatype name = Name(address, Chain.ttl, map(string, AENSv2.pointee))
```
##### pointee
```
datatype pointee = AccountPt(address) | OraclePt(address)
| ContractPt(address) | ChannelPt(address) | DataPt(string)
```
Note: on-chain there is a maximum length enforced for `DataPt`, it is 1024 bytes.
Sophia itself does _not_ enforce this.
#### Functions
##### resolve
```
AENSv2.resolve(name : string, key : string) : option('a)
AENS.resolve(name : string, key : string) : option('a)
```
Name resolution. Here `name` should be a registered name and `key` one of the attributes
@@ -157,53 +129,41 @@ type checked against this type at run time.
##### lookup
```
AENSv2.lookup(name : string) : option(AENSv2.name)
AENS.lookup(name : string) : option(AENS.name)
```
If `name` is an active name `AENSv2.lookup` returns a name object.
If `name` is an active name `AENS.lookup` returns a name object.
The three arguments to `Name` are `owner`, `expiry` and a map of the
`pointees` for the name. Note: the expiry of the name is always a fixed TTL.
For example:
```
let Some(AENSv2.Name(owner, FixedTTL(expiry), ptrs)) = AENSv2.lookup("example.chain")
let Some(Name(owner, FixedTTL(expiry), ptrs)) = AENS.lookup("example.chain")
```
Note: Changed to produce `AENSv2.name` in v8.0 (Ceres protocol upgrade).
##### preclaim
```
AENSv2.preclaim(owner : address, commitment_hash : hash, <signature : signature>) : unit
AENS.preclaim(owner : address, commitment_hash : hash, <signature : signature>) : unit
```
The [signature](./sophia_features.md#delegation-signature) should be over
`network id` + `owner address` + `Contract.address` (concatenated as byte arrays).
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### claim
```
AENSv2.claim(owner : address, name : string, salt : int, name_fee : int, <signature : signature>) : unit
AENS.claim(owner : address, name : string, salt : int, name_fee : int, <signature : signature>) : unit
```
The [signature](./sophia_features.md#delegation-signature) should be over
`network id` + `owner address` + `name_hash` + `Contract.address` (concatenated
as byte arrays) using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
`network id` + `owner address` + `name_hash` + `Contract.address`
(concatenated as byte arrays)
using the private key of the `owner` account for signing.
##### transfer
```
AENSv2.transfer(owner : address, new_owner : address, name : string, <signature : signature>) : unit
AENS.transfer(owner : address, new_owner : address, name : string, <signature : signature>) : unit
```
Transfers name to the new owner.
@@ -213,16 +173,10 @@ The [signature](./sophia_features.md#delegation-signature) should be over
(concatenated as byte arrays)
using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### revoke
```
AENSv2.revoke(owner : address, name : string, <signature : signature>) : unit
AENS.revoke(owner : address, name : string, <signature : signature>) : unit
```
Revokes the name to extend the ownership time.
@@ -232,24 +186,17 @@ The [signature](./sophia_features.md#delegation-signature) should be over
(concatenated as byte arrays)
using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### update
```
AENSv2.update(owner : address, name : string, expiry : option(Chain.ttl), client_ttl : option(int),
new_ptrs : map(string, AENSv2.pointee), <signature : signature>) : unit
AENS.update(owner : address, name : string, expiry : option(Chain.ttl), client_ttl : option(int),
new_ptrs : map(string, AENS.pointee), <signature : signature>) : unit
```
Updates the name. If the optional parameters are set to `None` that parameter
will not be updated, for example if `None` is passed as `expiry` the expiry
block of the name is not changed.
Note: Changed to consume `AENSv2.pointee` in v8.0 (Ceres protocol upgrade).
### Auth
@@ -289,10 +236,7 @@ namespace Chain =
Auth.tx_hash : option(hash)
```
Gets the transaction hash during authentication. Note: `Auth.tx_hash`
computation differs between protocol versions (changed in Ceres!), see
[aeserialisation](https://github.com/aeternity/protocol/blob/master/serializations.md)
specification for details.
Gets the transaction hash during authentication.
### Bits
@@ -437,12 +381,6 @@ Call.gas_price : int
The gas price of the current call.
#### mulmod
```
Int.mulmod : (a : int, b : int, q : int) : int
```
Combined multiplication and modulus, returns `(a * b) mod q`.
#### fee
```
@@ -531,13 +469,6 @@ Chain.block_height : int"
The height of the current block (i.e. the block in which the current call will be included).
#### to_bytes
```
Address.to_bytes(a : address) : bytes(32)
```
The binary representation of the address.
##### coinbase
```
@@ -552,7 +483,7 @@ The address of the account that mined the current block.
Chain.timestamp : int
```
The timestamp of the current block.
The timestamp of the current block (unix time, milliseconds).
##### difficulty
@@ -607,13 +538,6 @@ charging the calling contract. Note that this won't be visible in `Call.value`
in the `init` call of the new contract. It will be included in
`Contract.balance`, however.
#### poseidon
```
Crypto.poseidon(x1 : int, x2 : int) : int
```
Hash two integers (in the scalar field of BLS12-381) to another integer (in the scalar
field of BLS12-281). This is a ZK/SNARK-friendly hash function.
The type `'c` must be instantiated with a contract.
@@ -990,21 +914,88 @@ It returns `true` iff the oracle query exist and has the expected type.
These need to be explicitly included (with `.aes` suffix)
### AENSCompat
### Bitwise
#### pointee\_to\_V2
Bitwise operations on arbitrary precision integers.
#### bsr
```
AENSCompat.pointee_to_V2(p : AENS.pointee) : AENSv2.pointee
Bitwise.bsr(n : int, x : int) : int
```
Translate old pointee format to new, this is always possible.
Logical bit shift `x` right `n` positions.
#### pointee\_from\_V2
#### bsl
```
AENSCompat.pointee_from_V2(p2 : AENSv2.pointee) : option(AENS.pointee)
Bitwise.bsl(n : int, x : int) : int
```
Translate new pointee format to old, `DataPt` can't be translated, so `None` is returned in this case.
Logical bit shift `x` left `n` positions.
#### bsli
```
Bitwise.bsli(n : int, x : int, lim : int) : int
```
Logical bit shift `x` left `n` positions, limit to `lim` bits.
#### band
```
Bitwise.band(x : int, y : int) : int
```
Bitwise `and` of `x` and `y`.
#### bor
```
Bitwise.bor(x : int, y : int) : int
```
Bitwise `or` of `x` and `y`.
#### bxor
```
Bitwise.bxor(x : int, y : int) : int
```
Bitwise `xor` of `x` and `y`.
#### bnot
```
Bitwise.bnot(x : int) : int
```
Bitwise `not` of `x`. Defined and implemented as `bnot(x) = bxor(x, -1)`.
#### uband
```
Bitwise.uband(x : int, y : int) : int
```
Bitwise `and` of _non-negative_ numbers `x` and `y`.
#### ubor
```
Bitwise.ubor(x : int, y : int) : int
```
Bitwise `or` of _non-negative_ `x` and `y`.
#### ubxor
```
Bitwise.ubxor(x : int, y : int) : int
```
Bitwise `xor` of _non-negative_ `x` and `y`.
### BLS12\_381
+4 -8
View File
@@ -238,6 +238,7 @@ Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x +
| Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%'
| AccountAddress | ContractAddress // Chain identifiers
| OracleAddress | OracleQueryId // Chain identifiers
| '???' // Hole expression 1 + ???
Generator ::= Pattern '<-' Expr // Generator
| 'if' '(' Expr ')' // Guard
@@ -254,8 +255,8 @@ Path ::= Id // Record field
BinOp ::= '||' | '&&' | '<' | '>' | '=<' | '>=' | '==' | '!='
| '::' | '++' | '+' | '-' | '*' | '/' | 'mod' | '^'
| 'band' | 'bor' | 'bxor' | '<<' | '>>' | '|>'
UnOp ::= '-' | '!' | 'bnot'
| '|>'
UnOp ::= '-' | '!'
```
## Operators types
@@ -264,7 +265,6 @@ UnOp ::= '-' | '!' | 'bnot'
| --- | ---
| `-` `+` `*` `/` `mod` `^` | arithmetic operators
| `!` `&&` `||` | logical operators
| `band` `bor` `bxor` `bnot` `<<` `>>` | bitwise operators
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
| `::` `++` | list operators
| `|>` | functional operators
@@ -275,17 +275,13 @@ In order of highest to lowest precedence.
| Operators | Associativity
| --- | ---
| `!` `bnot`| right
| `!` | right
| `^` | left
| `*` `/` `mod` | left
| `-` (unary) | right
| `+` `-` | left
| `<<` `>>` | left
| `::` `++` | right
| `<` `>` `=<` `>=` `==` `!=` | none
| `band` | left
| `bxor` | left
| `bor` | left
| `&&` | right
| `||` | right
| `|>` | left
-17
View File
@@ -1,17 +0,0 @@
namespace AENSCompat =
// Translate old format to new format - always possible
function pointee_to_V2(p : AENS.pointee) : AENSv2.pointee =
switch(p)
AENS.AccountPt(a) => AENSv2.AccountPt(a)
AENS.OraclePt(a) => AENSv2.OraclePt(a)
AENS.ContractPt(a) => AENSv2.ContractPt(a)
AENS.ChannelPt(a) => AENSv2.ChannelPt(a)
// Translate new format to old format - option type!
function pointee_from_V2(p2 : AENSv2.pointee) : option(AENS.pointee) =
switch(p2)
AENSv2.AccountPt(a) => Some(AENS.AccountPt(a))
AENSv2.OraclePt(a) => Some(AENS.OraclePt(a))
AENSv2.ContractPt(a) => Some(AENS.ContractPt(a))
AENSv2.ChannelPt(a) => Some(AENS.ChannelPt(a))
AENSv2.DataPt(_) => None
+126
View File
@@ -0,0 +1,126 @@
@compiler >= 4.3
namespace Bitwise =
// bit shift 'x' right 'n' postions
function bsr(n : int, x : int) : int =
let step = 2^n
let res = x / step
if (x >= 0 || x mod step == 0)
res
else
res - 1
// bit shift 'x' left 'n' positions
function bsl(n : int, x : int) : int =
x * 2^n
// bit shift 'x' left 'n' positions, limit at 'lim' bits
function bsli(n : int, x : int, lim : int) : int =
(x * 2^n) mod (2^lim)
// bitwise 'and' for arbitrary precision integers
function band(a : int, b : int) : int =
if (a >= 0 && b >= 0)
uband_(a, b)
elif (b >= 0)
ubnand_(b, -1 - a)
elif (a >= 0)
ubnand_(a, -1 - b)
else
-1 - ubor_(-1 - a, -1 - b)
// bitwise 'or' for arbitrary precision integers
function
bor : (int, int) => int
bor(0, b) = b
bor(a, 0) = a
bor(a : int, b : int) : int =
if (a >= 0 && b >= 0)
ubor_(a, b)
elif (b >= 0)
-1 - ubnand_(-1 - a, b)
elif (a >= 0)
-1 - ubnand_(-1 - b, a)
else
-1 - uband_(-1 - a, -1 - b)
// bitwise 'xor' for arbitrary precision integers
function
bxor : (int, int) => int
bxor(0, b) = b
bxor(a, 0) = a
bxor(a, b) =
if (a >= 0 && b >= 0)
ubxor_(a, b)
elif (b >= 0)
-1 - ubxor_(-1 - a, b)
elif (a >= 0)
-1 - ubxor_(a, -1 - b)
else
ubxor_(-1 - a, -1 - b)
// bitwise 'not' for arbitrary precision integers
function bnot(a : int) = bxor(a, -1)
// Bitwise 'and' for non-negative integers
function uband(a : int, b : int) : int =
require(a >= 0 && b >= 0, "uband is only defined for non-negative integers")
switch((a, b))
(0, _) => 0
(_, 0) => 0
_ => uband__(a, b, 1, 0)
private function uband_(a, b) = uband__(a, b, 1, 0)
private function
uband__(0, b, val, acc) = acc
uband__(a, 0, val, acc) = acc
uband__(a, b, val, acc) =
switch (a mod 2 + b mod 2)
2 => uband__(a / 2, b / 2, val * 2, acc + val)
_ => uband__(a / 2, b / 2, val * 2, acc)
// Bitwise 'or' for non-negative integers
function ubor(a, b) =
require(a >= 0 && b >= 0, "ubor is only defined for non-negative integers")
switch((a, b))
(0, _) => b
(_, 0) => a
_ => ubor__(a, b, 1, 0)
private function ubor_(a, b) = ubor__(a, b, 1, 0)
private function
ubor__(0, 0, val, acc) = acc
ubor__(a, b, val, acc) =
switch (a mod 2 + b mod 2)
0 => ubor__(a / 2, b / 2, val * 2, acc)
_ => ubor__(a / 2, b / 2, val * 2, acc + val)
//Bitwise 'xor' for non-negative integers
function
ubxor : (int, int) => int
ubxor(0, b) = b
ubxor(a, 0) = a
ubxor(a, b) =
require(a >= 0 && b >= 0, "ubxor is only defined for non-negative integers")
ubxor__(a, b, 1, 0)
private function ubxor_(a, b) = ubxor__(a, b, 1, 0)
private function
ubxor__(0, 0, val, acc) = acc
ubxor__(a, b, val, acc) =
switch(a mod 2 + b mod 2)
1 => ubxor__(a / 2, b / 2, val * 2, acc + val)
_ => ubxor__(a / 2, b / 2, val * 2, acc)
private function ubnand_(a, b) = ubnand__(a, b, 1, 0)
private function
ubnand__(0, b, val, acc) = acc
ubnand__(a, b, val, acc) =
switch((a mod 2, b mod 2))
(1, 0) => ubnand__(a / 2, b / 2, val * 2, acc + val)
_ => ubnand__(a / 2, b / 2, val * 2, acc)
+1 -1
View File
@@ -14,7 +14,7 @@
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
]}.
{relx, [{release, {aesophia, "8.0.0"},
{relx, [{release, {aesophia, "7.1.0"},
[aesophia, aebytecode, getopt]},
{dev_mode, true},
+109 -54
View File
@@ -229,7 +229,7 @@ force_bind_fun(X, Type, Env = #env{ what = What }) ->
NoCode = get_option(no_code, false),
Entry = if X == "init", What == contract, not NoCode ->
{reserved_init, Ann, Type};
What == contract_interface -> {contract_fun, Ann, Type};
What == contract; What == contract_interface -> {contract_fun, Ann, Type};
true -> {Ann, Type}
end,
on_current_scope(Env, fun(Scope = #scope{ funs = Funs }) ->
@@ -426,6 +426,7 @@ lookup_env(Env, Kind, Ann, Name) ->
lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes = Scopes }, Kind, Ann, QName) ->
Qual = lists:droplast(QName),
Name = lists:last(QName),
QNameIsEvent = lists:suffix(["Chain", "event"], QName),
AllowPrivate = lists:prefix(Qual, Current),
%% Get the scope
case maps:get(Qual, Scopes, false) of
@@ -441,6 +442,8 @@ lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes
{reserved_init, Ann1, Type} ->
type_error({cannot_call_init_function, Ann}),
{QName, {Ann1, Type}}; %% Return the type to avoid an extra not-in-scope error
{contract_fun, Ann1, Type} when AllowPrivate orelse QNameIsEvent ->
{QName, {Ann1, Type}};
{contract_fun, Ann1, Type} ->
type_error({contract_treated_as_namespace, Ann, QName}),
{QName, {Ann1, Type}};
@@ -540,8 +543,6 @@ global_env() ->
TTL = {qid, Ann, ["Chain", "ttl"]},
Pointee = {qid, Ann, ["AENS", "pointee"]},
AENSName = {qid, Ann, ["AENS", "name"]},
PointeeV2 = {qid, Ann, ["AENSv2", "pointee"]},
AENSNameV2 = {qid, Ann, ["AENSv2", "name"]},
Fr = {qid, Ann, ["MCL_BLS12_381", "fr"]},
Fp = {qid, Ann, ["MCL_BLS12_381", "fp"]},
Fp2 = {tuple_t, Ann, [Fp, Fp]},
@@ -677,7 +678,14 @@ global_env() ->
AENSScope = #scope
{ funs = MkDefs(
[%% AENS pointee constructors
[{"resolve", Fun([String, String], option_t(Ann, A))},
{"preclaim", SignFun([Address, Hash], Unit)},
{"claim", SignFun([Address, String, Int, Int], Unit)},
{"transfer", SignFun([Address, Address, String], Unit)},
{"revoke", SignFun([Address, String], Unit)},
{"update", SignFun([Address, String, Option(TTL), Option(Int), Option(Map(String, Pointee))], Unit)},
{"lookup", Fun([String], option_t(Ann, AENSName))},
%% AENS pointee constructors
{"AccountPt", Fun1(Address, Pointee)},
{"OraclePt", Fun1(Address, Pointee)},
{"ContractPt", Fun1(Address, Pointee)},
@@ -687,26 +695,6 @@ global_env() ->
])
, types = MkDefs([{"pointee", 0}, {"name", 0}]) },
AENSv2Scope = #scope
{ funs = MkDefs(
[{"resolve", Fun([String, String], option_t(Ann, A))},
{"preclaim", SignFun([Address, Hash], Unit)},
{"claim", SignFun([Address, String, Int, Int], Unit)},
{"transfer", SignFun([Address, Address, String], Unit)},
{"revoke", SignFun([Address, String], Unit)},
{"update", SignFun([Address, String, Option(TTL), Option(Int), Option(Map(String, PointeeV2))], Unit)},
{"lookup", Fun([String], option_t(Ann, AENSNameV2))},
%% AENS pointee constructors v2
{"AccountPt", Fun1(Address, PointeeV2)},
{"OraclePt", Fun1(Address, PointeeV2)},
{"ContractPt", Fun1(Address, PointeeV2)},
{"ChannelPt", Fun1(Address, PointeeV2)},
{"DataPt", Fun1(String, PointeeV2)},
%% Name object constructor v2
{"Name", Fun([Address, TTL, Map(String, PointeeV2)], AENSNameV2)}
])
, types = MkDefs([{"pointee", 0}, {"name", 0}]) },
MapScope = #scope
{ funs = MkDefs(
[{"from_list", Fun1(List(Pair(K, V)), Map(K, V))},
@@ -726,8 +714,7 @@ global_env() ->
{"ecrecover_secp256k1", Fun([Hash, Bytes(65)], Option(Bytes(20)))},
{"sha3", Fun1(A, Hash)},
{"sha256", Fun1(A, Hash)},
{"blake2b", Fun1(A, Hash)},
{"poseidon", Fun([Int, Int], Int)}]) },
{"blake2b", Fun1(A, Hash)}]) },
%% Fancy BLS12-381 crypto operations
MCL_BLS12_381_Scope = #scope
@@ -812,16 +799,14 @@ global_env() ->
]) },
%% Conversion
IntScope = #scope{ funs = MkDefs([{"to_str", Fun1(Int, String)},
{"mulmod", Fun([Int, Int, Int], Int)}]) },
IntScope = #scope{ funs = MkDefs([{"to_str", Fun1(Int, String)}]) },
AddressScope = #scope{ funs = MkDefs([{"to_str", Fun1(Address, String)},
{"to_bytes", Fun1(Address, Bytes(32))},
{"to_contract", FunC(address_to_contract, [Address], A)},
{"is_oracle", Fun1(Address, Bool)},
{"is_contract", Fun1(Address, Bool)},
{"is_payable", Fun1(Address, Bool)}]) },
#env{ scopes =
#{ [] => TopScope
, ["Chain"] => ChainScope
@@ -829,7 +814,6 @@ global_env() ->
, ["Call"] => CallScope
, ["Oracle"] => OracleScope
, ["AENS"] => AENSScope
, ["AENSv2"] => AENSv2Scope
, ["Map"] => MapScope
, ["Auth"] => AuthScope
, ["Crypto"] => CryptoScope
@@ -925,6 +909,7 @@ infer1(Env0, [Contract0 = {Contract, Ann, ConName, Impls, Code} | Rest], Acc, Op
contract -> ets_insert(defined_contracts, {qname(ConName)});
contract_interface -> ok
end,
check_contract_preserved_payability(Env, ConName, Ann, Impls, Acc, What),
populate_functions_to_implement(Env, ConName, Impls, Acc),
Env1 = bind_contract(untyped, Contract0, Env),
{Env2, Code1} = infer_contract_top(push_scope(contract, ConName, Env1), What, Code, Options),
@@ -950,6 +935,25 @@ infer1(Env, [{pragma, _, _} | Rest], Acc, Options) ->
%% Pragmas are checked in check_modifiers
infer1(Env, Rest, Acc, Options).
-spec check_contract_preserved_payability(env(), Con, Ann, Impls, Contracts, Kind) -> ok | no_return() when
Con :: aeso_syntax:con(),
Ann :: aeso_syntax:ann(),
Impls :: [Con],
Contracts :: [aeso_syntax:decl()],
Kind :: contract | contract_interface.
check_contract_preserved_payability(Env, ContractName, ContractAnn, Impls, DefinedContracts, Kind) ->
Payable = proplists:get_value(payable, ContractAnn, false),
ImplsNames = [ name(I) || I <- Impls ],
Interfaces = [ Con || I = {contract_interface, _, Con, _, _} <- DefinedContracts,
lists:member(name(Con), ImplsNames),
aeso_syntax:get_ann(payable, I, false) ],
create_type_errors(),
[ type_error({unpreserved_payablity, Kind, ContractName, I}) || I <- Interfaces, Payable == false ],
destroy_and_report_type_errors(Env),
ok.
%% Report all functions that were not implemented by the contract ContractName.
-spec report_unimplemented_functions(env(), ContractName) -> ok | no_return() when
ContractName :: aeso_syntax:con().
@@ -1253,6 +1257,10 @@ check_usings(Env = #env{ used_namespaces = UsedNamespaces }, [{using, Ann, Con,
create_type_errors(),
type_error({using_undefined_namespace, Ann, qname(Con)}),
destroy_and_report_type_errors(Env);
#scope{kind = contract} ->
create_type_errors(),
type_error({using_undefined_namespace, Ann, qname(Con)}),
destroy_and_report_type_errors(Env);
Scope ->
Nsp = case Parts of
none ->
@@ -1506,19 +1514,37 @@ check_reserved_entrypoints(Funs) ->
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) ->
Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type),
TypeSig = {type_sig, Ann, none, Named, Args, Ret},
register_implementation(Name),
register_implementation(Id, TypeSig),
{{Name, TypeSig}, {fun_decl, Ann, Id, Type1}};
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
type_error({fundecl_must_have_funtype, Ann, Id, Type}),
{{Name, {type_sig, Ann, none, [], [], Type}}, check_type(Env, Type)}.
%% Register the function FunName as implemented by deleting it from the functions
%% Register the function FunId as implemented by deleting it from the functions
%% to be implemented table if it is included there, or return true otherwise.
-spec register_implementation(FunName) -> true | no_return() when
FunName :: string().
register_implementation(Name) ->
-spec register_implementation(FunId, FunSig) -> true | no_return() when
FunId :: aeso_syntax:id(),
FunSig :: typesig().
register_implementation(Id, Sig) ->
Name = name(Id),
case ets_lookup(functions_to_implement, Name) of
[{Name, _, {fun_decl, _, _, _}}] ->
[{Name, Interface, Decl = {fun_decl, _, DeclId, _}}] ->
DeclStateful = aeso_syntax:get_ann(stateful, Decl, false),
DeclPayable = aeso_syntax:get_ann(payable, Decl, false),
SigEntrypoint = aeso_syntax:get_ann(entrypoint, Sig, false),
SigStateful = aeso_syntax:get_ann(stateful, Sig, false),
SigPayable = aeso_syntax:get_ann(payable, Sig, false),
[ type_error({function_should_be_entrypoint, Id, DeclId, Interface})
|| not SigEntrypoint ],
[ type_error({entrypoint_cannot_be_stateful, Id, DeclId, Interface})
|| SigStateful andalso not DeclStateful ],
[ type_error({entrypoint_must_be_payable, Id, DeclId, Interface})
|| not SigPayable andalso DeclPayable ],
ets_delete(functions_to_implement, Name);
[] ->
true;
@@ -1528,9 +1554,9 @@ register_implementation(Name) ->
infer_nonrec(Env, LetFun) ->
create_constraints(),
NewLetFun = {{FunName, _}, _} = infer_letfun(Env, LetFun),
NewLetFun = {{_, Sig}, _} = infer_letfun(Env, LetFun),
check_special_funs(Env, NewLetFun),
register_implementation(FunName),
register_implementation(get_letfun_id(LetFun), Sig),
solve_then_destroy_and_report_unsolved_constraints(Env),
Result = {TypeSig, _} = instantiate(NewLetFun),
print_typesig(TypeSig),
@@ -1559,8 +1585,8 @@ infer_letrec(Env, Defs) ->
ExtendEnv = bind_funs(Funs, Env),
Inferred =
[ begin
Res = {{Name, TypeSig}, _} = infer_letfun(ExtendEnv, LF),
register_implementation(Name),
Res = {{Name, TypeSig}, LetFun} = infer_letfun(ExtendEnv, LF),
register_implementation(get_letfun_id(LetFun), TypeSig),
Got = proplists:get_value(Name, Funs),
Expect = typesig_to_fun_t(TypeSig),
unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}),
@@ -1612,6 +1638,9 @@ infer_letfun1(Env0 = #env{ namespace = NS }, {letfun, Attrib, Fun = {id, NameAtt
{{Name, TypeSig},
{letfun, Attrib, {id, NameAttrib, Name}, TypedArgs, ResultType, NewGuardedBodies}}.
get_letfun_id({fun_clauses, _, Id, _, _}) -> Id;
get_letfun_id({letfun, _, Id, _, _, _}) -> Id.
desugar_clauses(Ann, Fun, {type_sig, _, _, _, ArgTypes, RetType}, Clauses) ->
NeedDesugar =
case Clauses of
@@ -1689,10 +1718,14 @@ check_stateful(#env { current_function = Fun }, _Id, _Type) ->
%% Hack: don't allow passing the 'value' named arg if not stateful. This only
%% works since the user can't create functions with named arguments.
check_stateful_named_arg(#env{ stateful = false, current_function = Fun }, {id, _, "value"}, Default) ->
check_stateful_named_arg(#env{ stateful = Stateful, current_function = Fun }, {id, _, "value"}, Default) ->
case Default of
{int, _, 0} -> ok;
_ -> type_error({value_arg_not_allowed, Default, Fun})
_ ->
case Stateful of
true -> when_warning(warn_unused_stateful, fun() -> used_stateful(Fun) end);
false -> type_error({value_arg_not_allowed, Default, Fun})
end
end;
check_stateful_named_arg(_, _, _) -> ok.
@@ -1810,6 +1843,10 @@ infer_expr(_Env, Body={contract_pubkey, As, _}) ->
{typed, As, Body, Con};
infer_expr(_Env, Body={id, As, "_"}) ->
{typed, As, Body, fresh_uvar(As)};
infer_expr(_Env, Body={id, As, "???"}) ->
T = fresh_uvar(As),
type_error({hole_found, As, T}),
{typed, As, Body, T};
infer_expr(Env, Id = {Tag, As, _}) when Tag == id; Tag == qid ->
{QName, Type} = lookup_name(Env, As, Id),
{typed, As, QName, Type};
@@ -1899,7 +1936,7 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) ->
unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When),
when_warning(warn_negative_spend, fun() -> warn_potential_negative_spend(Ann, NewFun1, NewArgs) end),
[ add_constraint({aens_resolve_type, GeneralResultType})
|| element(3, FunName) =:= ["AENSv2", "resolve"] ],
|| element(3, FunName) =:= ["AENS", "resolve"] ],
[ add_constraint({oracle_type, Ann, OType})
|| OType <- [get_oracle_type(FunName, ArgTypes, GeneralResultType)],
OType =/= false ],
@@ -2186,11 +2223,6 @@ infer_infix({IntOp, As})
IntOp == '^'; IntOp == 'mod' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int, Int], Int};
infer_infix({BitOp, As})
when BitOp == 'band'; BitOp == 'bor'; BitOp == 'bxor';
BitOp == '<<'; BitOp == '>>' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int, Int], Int};
infer_infix({RelOp, As})
when RelOp == '=='; RelOp == '!=';
RelOp == '<'; RelOp == '>';
@@ -2218,9 +2250,6 @@ infer_infix({'|>', As}) ->
infer_prefix({'!',As}) ->
Bool = {id, As, "bool"},
{fun_t, As, [], [Bool], Bool};
infer_prefix({BitOp,As}) when BitOp =:= 'bnot' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int], Int};
infer_prefix({IntOp,As}) when IntOp =:= '-' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int], Int}.
@@ -3371,6 +3400,9 @@ mk_error({cannot_unify, A, B, Cxt, When}) ->
[pp(instantiate(A)), pp(instantiate(B))]),
{Pos, Ctxt} = pp_when(When),
mk_t_err(Pos, Msg, Ctxt);
mk_error({hole_found, Ann, Type}) ->
Msg = io_lib:format("Found a hole of type `~s`", [pp(instantiate(Type))]),
mk_t_err(pos(Ann), Msg);
mk_error({unbound_variable, Id}) ->
Msg = io_lib:format("Unbound variable `~s`", [pp(Id)]),
case Id of
@@ -3686,7 +3718,7 @@ mk_error({empty_record_definition, Ann, Name}) ->
Msg = io_lib:format("Empty record definitions are not allowed. Cannot define the record `~s`", [Name]),
mk_t_err(pos(Ann), Msg);
mk_error({unimplemented_interface_function, ConId, InterfaceName, FunName}) ->
Msg = io_lib:format("Unimplemented function `~s` from the interface `~s` in the contract `~s`", [FunName, InterfaceName, pp(ConId)]),
Msg = io_lib:format("Unimplemented entrypoint `~s` from the interface `~s` in the contract `~s`", [FunName, InterfaceName, pp(ConId)]),
mk_t_err(pos(ConId), Msg);
mk_error({referencing_undefined_interface, InterfaceId}) ->
Msg = io_lib:format("Trying to implement or extend an undefined interface `~s`", [pp(InterfaceId)]),
@@ -3718,7 +3750,7 @@ mk_error({higher_order_entrypoint, Ann, {id, _, Name}, Thing}) ->
[ThingS, Name, Bad]),
mk_t_err(pos(Ann), Msg);
mk_error({invalid_aens_resolve_type, Ann, T}) ->
Msg = io_lib:format("Invalid return type of `AENSv2.resolve`:\n"
Msg = io_lib:format("Invalid return type of `AENS.resolve`:\n"
"~s`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)",
[pp_type(" `", T)]),
@@ -3734,6 +3766,29 @@ mk_error({interface_implementation_conflict, Contract, I1, I2, Fun}) ->
"the contract `~s` have a function called `~s`",
[name(I1), name(I2), name(Contract), name(Fun)]),
mk_t_err(pos(Contract), Msg);
mk_error({function_should_be_entrypoint, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` must be declared as an entrypoint instead of a function "
"in order to implement the entrypoint `~s` from the interface `~s`",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({entrypoint_cannot_be_stateful, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` cannot be stateful because the entrypoint `~s` in the "
"interface `~s` is not stateful",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({entrypoint_must_be_payable, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` must be payable because the entrypoint `~s` in the "
"interface `~s` is payable",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({unpreserved_payablity, Kind, ContractCon, InterfaceCon}) ->
KindStr = case Kind of
contract -> "contract";
contract_interface -> "interface"
end,
Msg = io_lib:format("Non-payable ~s `~s` cannot implement payable interface `~s`",
[KindStr, name(ContractCon), name(InterfaceCon)]),
mk_t_err(pos(ContractCon), Msg);
mk_error(Err) ->
Msg = io_lib:format("Unknown error: ~p", [Err]),
mk_t_err(pos(0, 0), Msg).
+13 -27
View File
@@ -32,13 +32,12 @@
-type op() :: '+' | '-' | '*' | '/' | mod | '^' | '++' | '::' |
'<' | '>' | '=<' | '>=' | '==' | '!=' | '!' |
'band' | 'bor' | 'bxor' | 'bnot' | '<<' | '>>' |
map_get | map_get_d | map_set | map_from_list | map_to_list |
map_delete | map_member | map_size | string_length |
string_concat | bits_set | bits_clear | bits_test | bits_sum |
bits_intersection | bits_union | bits_difference |
contract_to_address | address_to_contract | crypto_verify_sig | crypto_verify_sig_secp256k1 |
crypto_sha3 | crypto_sha256 | crypto_blake2b | crypto_poseidon |
crypto_sha3 | crypto_sha256 | crypto_blake2b |
crypto_ecverify_secp256k1 | crypto_ecrecover_secp256k1 |
mcl_bls12_381_g1_neg | mcl_bls12_381_g1_norm | mcl_bls12_381_g1_valid |
mcl_bls12_381_g1_is_zero | mcl_bls12_381_g1_add | mcl_bls12_381_g1_mul |
@@ -215,12 +214,6 @@ init_env(Options) ->
["AENS", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1] },
["AENS", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1] },
["AENS", "Name"] => #con_tag{ tag = 0, arities = [3] },
["AENSv2", "AccountPt"] => #con_tag{ tag = 0, arities = [1, 1, 1, 1, 1] },
["AENSv2", "OraclePt"] => #con_tag{ tag = 1, arities = [1, 1, 1, 1, 1] },
["AENSv2", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1, 1] },
["AENSv2", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1, 1] },
["AENSv2", "DataPt"] => #con_tag{ tag = 4, arities = [1, 1, 1, 1, 1] },
["AENSv2", "Name"] => #con_tag{ tag = 0, arities = [3] },
["Chain", "GAMetaTx"] => #con_tag{ tag = 0, arities = [2] },
["Chain", "PayingForTx"] => #con_tag{ tag = 0, arities = [2] },
["Chain", "SpendTx"] => #con_tag{ tag = 0, arities = ChainTxArities },
@@ -252,11 +245,8 @@ init_env(Options) ->
-spec builtins() -> builtins().
builtins() ->
MkName = fun
(["AENSv2"], Fun) ->
list_to_atom(string:to_lower("AENS_" ++ Fun));
(NS, Fun) ->
list_to_atom(string:to_lower(string:join(NS ++ [Fun], "_")))
MkName = fun(NS, Fun) ->
list_to_atom(string:to_lower(string:join(NS ++ [Fun], "_")))
end,
Scopes = [{[], [{"abort", 1}, {"require", 2}, {"exit", 1}]},
{["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none},
@@ -268,13 +258,13 @@ builtins() ->
{["Oracle"], [{"register", 4}, {"expiry", 1}, {"query_fee", 1}, {"query", 5}, {"get_question", 2},
{"respond", 4}, {"extend", 3}, {"get_answer", 2},
{"check", 1}, {"check_query", 2}]},
{["AENSv2"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4},
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4},
{"revoke", 3}, {"update", 6}, {"lookup", 1}]},
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
{["Crypto"], [{"verify_sig", 3}, {"verify_sig_secp256k1", 3},
{"ecverify_secp256k1", 3}, {"ecrecover_secp256k1", 2},
{"sha3", 1}, {"sha256", 1}, {"blake2b", 1}, {"poseidon", 2}]},
{"sha3", 1}, {"sha256", 1}, {"blake2b", 1}]},
{["MCL_BLS12_381"], [{"g1_neg", 1}, {"g1_norm", 1}, {"g1_valid", 1}, {"g1_is_zero", 1}, {"g1_add", 2}, {"g1_mul", 2},
{"g2_neg", 1}, {"g2_norm", 1}, {"g2_valid", 1}, {"g2_is_zero", 1}, {"g2_add", 2}, {"g2_mul", 2},
{"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1},
@@ -287,9 +277,8 @@ builtins() ->
{["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2},
{"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]},
{["Bytes"], [{"to_int", 1}, {"to_str", 1}, {"concat", 2}, {"split", 1}]},
{["Int"], [{"to_str", 1}, {"mulmod", 2}]},
{["Address"], [{"to_str", 1}, {"to_bytes", 1}, {"to_contract", 1},
{"is_oracle", 1}, {"is_contract", 1}, {"is_payable", 1}]}
{["Int"], [{"to_str", 1}]},
{["Address"], [{"to_str", 1}, {"to_contract", 1}, {"is_oracle", 1}, {"is_contract", 1}, {"is_payable", 1}]}
],
maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}}
|| {NS, Funs} <- Scopes,
@@ -324,13 +313,11 @@ init_type_env() ->
["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}),
["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}),
["AENS", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address]]}}]]}),
["AENSv2", "pointee"] => ?type({variant, [[address], [address], [address], [address], [string]]}),
["AENSv2", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address], [string]]}}]]}),
["Chain", "ga_meta_tx"] => ?type({variant, [[address, integer]]}),
["Chain", "paying_for_tx"] => ?type({variant, [[address, integer]]}),
["Chain", "base_tx"] => ?type(BaseTx),
["MCL_BLS12_381", "fr"] => ?type({bytes, 32}),
["MCL_BLS12_381", "fp"] => ?type({bytes, 48})
["MCL_BLS12_381", "fr"] => ?type({bytes, 32}),
["MCL_BLS12_381", "fp"] => ?type({bytes, 48})
}.
is_no_code(Env) ->
@@ -707,9 +694,8 @@ expr_to_fcode(Env, Type, {app, Ann, {Op, _}, [A, B]}) when is_atom(Op) ->
end;
expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
case Op of
'-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]};
'bnot' -> {op, 'bnot', [expr_to_fcode(Env, A)]};
'!' -> {op, '!', [expr_to_fcode(Env, A)]}
'-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]};
'!' -> {op, '!', [expr_to_fcode(Env, A)]}
end;
%% Function calls
@@ -1100,9 +1086,9 @@ op_builtins() ->
stringinternal_sha3, stringinternal_sha256, stringinternal_blake2b,
char_to_int, char_from_int, stringinternal_to_lower, stringinternal_to_upper,
bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union,
bits_difference, int_to_str, int_mulmod, address_to_str, address_to_bytes, crypto_verify_sig,
bits_difference, int_to_str, address_to_str, crypto_verify_sig,
address_to_contract,
crypto_verify_sig_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b, crypto_poseidon,
crypto_verify_sig_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b,
crypto_ecverify_secp256k1, crypto_ecrecover_secp256k1,
mcl_bls12_381_g1_neg, mcl_bls12_381_g1_norm, mcl_bls12_381_g1_valid,
mcl_bls12_381_g1_is_zero, mcl_bls12_381_g1_add, mcl_bls12_381_g1_mul,
-18
View File
@@ -682,12 +682,6 @@ op_to_scode('>=') -> aeb_fate_ops:egt(?a, ?a, ?a);
op_to_scode('==') -> aeb_fate_ops:eq(?a, ?a, ?a);
op_to_scode('!=') -> aeb_fate_ops:neq(?a, ?a, ?a);
op_to_scode('!') -> aeb_fate_ops:not_op(?a, ?a);
op_to_scode('bnot') -> aeb_fate_ops:bin_not(?a, ?a);
op_to_scode('band') -> aeb_fate_ops:bin_and(?a, ?a, ?a);
op_to_scode('bor') -> aeb_fate_ops:bin_or(?a, ?a, ?a);
op_to_scode('bxor') -> aeb_fate_ops:bin_xor(?a, ?a, ?a);
op_to_scode('<<') -> aeb_fate_ops:bin_sl(?a, ?a, ?a);
op_to_scode('>>') -> aeb_fate_ops:bin_sr(?a, ?a, ?a);
op_to_scode(map_get) -> aeb_fate_ops:map_lookup(?a, ?a, ?a);
op_to_scode(map_get_d) -> aeb_fate_ops:map_lookup(?a, ?a, ?a, ?a);
op_to_scode(map_set) -> aeb_fate_ops:map_update(?a, ?a, ?a, ?a);
@@ -712,9 +706,7 @@ op_to_scode(bits_intersection) -> aeb_fate_ops:bits_and(?a, ?a, ?a);
op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a);
op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a);
op_to_scode(address_to_str) -> aeb_fate_ops:addr_to_str(?a, ?a);
op_to_scode(address_to_bytes) -> aeb_fate_ops:addr_to_bytes(?a, ?a);
op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a);
op_to_scode(int_mulmod) -> aeb_fate_ops:mulmod(?a, ?a, ?a, ?a);
op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a);
op_to_scode(address_to_contract) -> aeb_fate_ops:address_to_contract(?a, ?a);
op_to_scode(crypto_verify_sig) -> aeb_fate_ops:verify_sig(?a, ?a, ?a, ?a);
@@ -724,7 +716,6 @@ op_to_scode(crypto_ecrecover_secp256k1) -> aeb_fate_ops:ecrecover_secp256k1(?a,
op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a);
op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a);
op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
op_to_scode(crypto_poseidon) -> aeb_fate_ops:poseidon(?a, ?a, ?a);
op_to_scode(stringinternal_sha3) -> aeb_fate_ops:sha3(?a, ?a);
op_to_scode(stringinternal_sha256) -> aeb_fate_ops:sha256(?a, ?a);
op_to_scode(stringinternal_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
@@ -922,13 +913,6 @@ attributes(I) ->
{'DIV', A, B, C} -> Pure(A, [B, C]);
{'MOD', A, B, C} -> Pure(A, [B, C]);
{'POW', A, B, C} -> Pure(A, [B, C]);
{'MULMOD', A, B, C, D} -> Pure(A, [B, C, D]);
{'BAND', A, B, C} -> Pure(A, [B, C]);
{'BOR', A, B, C} -> Pure(A, [B, C]);
{'BXOR', A, B, C} -> Pure(A, [B, C]);
{'BNOT', A, B} -> Pure(A, [B]);
{'BSL', A, B, C} -> Pure(A, [B, C]);
{'BSR', A, B, C} -> Pure(A, [B, C]);
{'LT', A, B, C} -> Pure(A, [B, C]);
{'GT', A, B, C} -> Pure(A, [B, C]);
{'EQ', A, B, C} -> Pure(A, [B, C]);
@@ -981,14 +965,12 @@ attributes(I) ->
{'SHA3', A, B} -> Pure(A, [B]);
{'SHA256', A, B} -> Pure(A, [B]);
{'BLAKE2B', A, B} -> Pure(A, [B]);
{'POSEIDON', A, B, C} -> Pure(A, [B, C]);
{'VERIFY_SIG', A, B, C, D} -> Pure(A, [B, C, D]);
{'VERIFY_SIG_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
{'ECVERIFY_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
{'ECRECOVER_SECP256K1', A, B, C} -> Pure(A, [B, C]);
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
{'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]);
{'ADDRESS_TO_BYTES', A, B} -> Pure(A, [B]);
{'AUTH_TX_HASH', A} -> Pure(A, []);
{'AUTH_TX', A} -> Pure(A, []);
{'BYTES_TO_INT', A, B} -> Pure(A, [B]);
+6 -8
View File
@@ -333,19 +333,14 @@ expr100() ->
expr150() -> infixl(expr200(), binop('|>')).
expr200() -> infixr(expr300(), binop('||')).
expr300() -> infixr(expr325(), binop('&&')).
expr325() -> infixl(expr350(), binop('bor')).
expr350() -> infixl(expr375(), binop('bxor')).
expr375() -> infixl(expr400(), binop('band')).
expr300() -> infixr(expr400(), binop('&&')).
expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])).
expr500() -> infixr(expr550(), binop(['::', '++'])).
expr550() -> infixl(expr600(), binop(['<<', '>>'])).
expr500() -> infixr(expr600(), binop(['::', '++'])).
expr600() -> infixl(expr650(), binop(['+', '-'])).
expr650() -> ?RULE(many(token('-')), expr700(), prefixes(_1, _2)).
expr700() -> infixl(expr750(), binop(['*', '/', mod])).
expr750() -> infixl(expr800(), binop(['^'])).
expr800() -> ?RULE(many(token('!')), expr850(), prefixes(_1, _2)).
expr850() -> ?RULE(many(token('bnot')), expr900(), prefixes(_1, _2)).
expr800() -> ?RULE(many(token('!')), expr900(), prefixes(_1, _2)).
expr900() -> ?RULE(exprAtom(), many(elim()), elim(_1, _2)).
exprAtom() ->
@@ -364,9 +359,12 @@ exprAtom() ->
, ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4))
, ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2))
, letpat()
, hole()
])
end).
hole() -> ?RULE(token('???'), {id, get_ann(_1), "???"}).
comprehension_exp() ->
?LAZY_P(choice(
[ comprehension_bind()
+4 -10
View File
@@ -436,20 +436,15 @@ bin_prec('=') -> { 0, 0, 0}; %% Always printed inside '[ ]'
bin_prec('@') -> { 0, 0, 0}; %% Only in error messages
bin_prec('|>') -> {150, 150, 200};
bin_prec('||') -> {200, 300, 200};
bin_prec('&&') -> {300, 325, 300};
bin_prec('bor') -> {325, 350, 325};
bin_prec('bxor') -> {350, 375, 350};
bin_prec('band') -> {375, 400, 375};
bin_prec('&&') -> {300, 400, 300};
bin_prec('<') -> {400, 500, 500};
bin_prec('>') -> {400, 500, 500};
bin_prec('=<') -> {400, 500, 500};
bin_prec('>=') -> {400, 500, 500};
bin_prec('==') -> {400, 500, 500};
bin_prec('!=') -> {400, 500, 500};
bin_prec('++') -> {500, 550, 500};
bin_prec('::') -> {500, 550, 500};
bin_prec('<<') -> {550, 600, 550};
bin_prec('>>') -> {550, 600, 550};
bin_prec('++') -> {500, 600, 500};
bin_prec('::') -> {500, 600, 500};
bin_prec('+') -> {600, 600, 650};
bin_prec('-') -> {600, 600, 650};
bin_prec('*') -> {700, 700, 750};
@@ -459,8 +454,7 @@ bin_prec('^') -> {750, 750, 800}.
-spec un_prec(aeso_syntax:un_op()) -> {integer(), integer()}.
un_prec('-') -> {650, 650};
un_prec('!') -> {800, 800};
un_prec('bnot') -> {850, 850}.
un_prec('!') -> {800, 800}.
equals(Ann, A, B) ->
{app, [{format, infix} | Ann], {'=', Ann}, [A, B]}.
+1 -1
View File
@@ -45,7 +45,7 @@ lexer() ->
Keywords = ["contract", "include", "let", "switch", "type", "record", "datatype", "if", "elif", "else", "function",
"stateful", "payable", "true", "false", "mod", "public", "entrypoint", "private", "indexed", "namespace",
"interface", "main", "using", "as", "for", "hiding", "band", "bor", "bxor", "bnot"
"interface", "main", "using", "as", "for", "hiding"
],
KW = string:join(Keywords, "|"),
+2 -2
View File
@@ -106,8 +106,8 @@
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^'
| '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!='
| '||' | '&&' | '..' | 'band' | 'bor' | 'bxor' | '>>' | '<<' | '|>'.
-type un_op() :: '-' | '!' | 'bnot'.
| '||' | '&&' | '..' | '|>'.
-type un_op() :: '-' | '!'.
-type expr()
:: {lam, ann(), [arg()], expr()}
+1 -16
View File
@@ -88,7 +88,7 @@ from_fate_builtin(QType, Val) ->
{["AENS", "name"], {variant, [3], 0, {Addr, TTL, Ptrs}}} ->
App(["AENS","Name"], [Chk(Adr, Addr), Chk(Qid(["Chain", "ttl"]), TTL),
Chk(Map(Str, Qid(["AENS", "pointee"])), Ptrs)]);
Chk(Map(Str, Qid(["AENS", "pointee"])), Ptrs)]);
{["AENS", "pointee"], {variant, [1, 1, 1, 1], 0, {Addr}}} ->
App(["AENS","AccountPt"], [Chk(Adr, Addr)]);
@@ -99,21 +99,6 @@ from_fate_builtin(QType, Val) ->
{["AENS", "pointee"], {variant, [1, 1, 1, 1], 3, {Addr}}} ->
App(["AENS","ChannelPt"], [Chk(Adr, Addr)]);
{["AENSv2", "name"], {variant, [3], 0, {Addr, TTL, Ptrs}}} ->
App(["AENSv2","Name"], [Chk(Adr, Addr), Chk(Qid(["Chain", "ttl"]), TTL),
Chk(Map(Str, Qid(["AENSv2", "pointee"])), Ptrs)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 0, {Val}}} ->
App(["AENSv2","AccountPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 1, {Val}}} ->
App(["AENSv2","OraclePt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 2, {Val}}} ->
App(["AENSv2","ContractPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 3, {Val}}} ->
App(["AENSv2","ChannelPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 4, {Val}}} ->
App(["AENSv2","DataPt"], [Chk(Str, Val)]);
{["Chain", "ga_meta_tx"], {variant, [2], 0, {Addr, X}}} ->
App(["Chain","GAMetaTx"], [Chk(Adr, Addr), Chk(Int, X)]);
+1 -1
View File
@@ -1,6 +1,6 @@
{application, aesophia,
[{description, "Compiler for Aeternity Sophia language"},
{vsn, "8.0.0"},
{vsn, "7.1.0"},
{registered, []},
{applications,
[kernel,
+44 -5
View File
@@ -205,6 +205,9 @@ compilable_contracts() ->
"polymorphism_variance_switching_chain_create",
"polymorphism_variance_switching_void_supertype",
"polymorphism_variance_switching_unify_with_interface_decls",
"polymorphism_preserve_or_add_payable_contract",
"polymorphism_preserve_or_add_payable_entrypoint",
"polymorphism_preserve_or_remove_stateful_entrypoint",
"missing_init_fun_state_unit",
"complex_compare_leq",
"complex_compare",
@@ -218,7 +221,6 @@ compilable_contracts() ->
"unapplied_contract_call",
"unapplied_named_arg_builtin",
"resolve_field_constraint_by_arity",
"ceres",
"test" % Custom general-purpose test file. Keep it last on the list.
].
@@ -869,7 +871,7 @@ failing_contracts() ->
" - line 9, column 5">>])
, ?TYPE_ERROR(polymorphism_contract_missing_implementation,
[<<?Pos(4,20)
"Unimplemented function `f` from the interface `I1` in the contract `I2`">>
"Unimplemented entrypoint `f` from the interface `I1` in the contract `I2`">>
])
, ?TYPE_ERROR(polymorphism_contract_same_decl_multi_interface,
[<<?Pos(7,10)
@@ -1096,19 +1098,19 @@ failing_contracts() ->
])
, ?TYPE_ERROR(polymorphic_aens_resolve,
[<<?Pos(4,5)
"Invalid return type of `AENSv2.resolve`:\n"
"Invalid return type of `AENS.resolve`:\n"
" `'a`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
])
, ?TYPE_ERROR(bad_aens_resolve,
[<<?Pos(6,5)
"Invalid return type of `AENSv2.resolve`:\n"
"Invalid return type of `AENS.resolve`:\n"
" `list(int)`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
])
, ?TYPE_ERROR(bad_aens_resolve_using,
[<<?Pos(7,5)
"Invalid return type of `AENSv2.resolve`:\n"
"Invalid return type of `AENS.resolve`:\n"
" `list(int)`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
])
@@ -1153,6 +1155,43 @@ failing_contracts() ->
"to arguments\n"
" `Chain.create : (value : int, var_args) => 'c`">>
])
, ?TYPE_ERROR(polymorphism_add_stateful_entrypoint,
[<<?Pos(5,25)
"`f` cannot be stateful because the entrypoint `f` in the interface `I` is not stateful">>
])
, ?TYPE_ERROR(polymorphism_change_entrypoint_to_function,
[<<?Pos(6,14)
"`f` must be declared as an entrypoint instead of a function in order to implement the entrypoint `f` from the interface `I`">>
])
, ?TYPE_ERROR(polymorphism_non_payable_contract_implement_payable,
[<<?Pos(4,10)
"Non-payable contract `C` cannot implement payable interface `I`">>
])
, ?TYPE_ERROR(polymorphism_non_payable_interface_implement_payable,
[<<?Pos(4,20)
"Non-payable interface `H` cannot implement payable interface `I`">>
])
, ?TYPE_ERROR(polymorphism_remove_payable_entrypoint,
[<<?Pos(5,16)
"`f` must be payable because the entrypoint `f` in the interface `I` is payable">>
])
, ?TYPE_ERROR(calling_child_contract_entrypoint,
[<<?Pos(5,20)
"Invalid call to contract entrypoint `F.g`.\n"
"It must be called as `c.g` for some `c : F`.">>])
, ?TYPE_ERROR(using_contract_as_namespace,
[<<?Pos(5,3)
"Cannot use undefined namespace F">>])
, ?TYPE_ERROR(hole_expression,
[<<?Pos(5,13)
"Found a hole of type `bool`">>,
<<?Pos(6,17)
"Found a hole of type `string`">>,
<<?Pos(9,37)
"Found a hole of type `(int) => int`">>,
<<?Pos(13,20)
"Found a hole of type `'a`">>
])
].
validation_test_() ->
+1 -1
View File
@@ -53,7 +53,7 @@ simple_contracts_test_() ->
%% associativity
[ RightAssoc(Op) || Op <- ["||", "&&", "::", "++"] ],
[ NonAssoc(Op) || Op <- ["==", "!=", "<", ">", "=<", ">="] ],
[ LeftAssoc(Op) || Op <- ["+", "-", "*", "/", "mod", "band", "bor", "bxor", "<<", ">>"] ],
[ LeftAssoc(Op) || Op <- ["+", "-", "*", "/", "mod"] ],
%% precedence
[ Stronger(Op2, Op1) || [T1 , T2 | _] <- tails(Tiers), Op1 <- T1, Op2 <- T2 ],
+1 -2
View File
@@ -39,8 +39,7 @@ all_tokens() ->
%% Symbols
lists:map(Lit, [',', '.', ';', '|', ':', '(', ')', '[', ']', '{', '}']) ++
%% Operators
lists:map(Lit, ['=', '==', '!=', '>', '<', '>=', '=<', '-', '+', '++', '*', '/', mod,
':', '::', '->', '=>', '||', '&&', '!', 'band', 'bor', 'bxor', 'bnot' ,'<<', '>>']) ++
lists:map(Lit, ['=', '==', '!=', '>', '<', '>=', '=<', '-', '+', '++', '*', '/', mod, ':', '::', '->', '=>', '||', '&&', '!']) ++
%% Keywords
lists:map(Lit, [contract, type, 'let', switch]) ++
%% Comment token (not an actual token), just for tests
+17 -17
View File
@@ -6,77 +6,77 @@ main contract AENSTest =
// Name resolution
stateful entrypoint resolve_word(name : string, key : string) : option(address) =
AENSv2.resolve(name, key)
AENS.resolve(name, key)
stateful entrypoint resolve_string(name : string, key : string) : option(string) =
AENSv2.resolve(name, key)
AENS.resolve(name, key)
stateful entrypoint resolve_contract(name : string, key : string) : option(C) =
AENSv2.resolve(name, key)
AENS.resolve(name, key)
stateful entrypoint resolve_oracle(name : string, key : string) : option(oracle(int, int)) =
AENSv2.resolve(name, key)
AENS.resolve(name, key)
stateful entrypoint resolve_oracle_query(name : string, key : string) : option(oracle_query(int, int)) =
AENSv2.resolve(name, key)
AENS.resolve(name, key)
// Transactions
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
chash : hash) : unit = // Commitment hash
AENSv2.preclaim(addr, chash)
AENS.preclaim(addr, chash)
stateful entrypoint signedPreclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
chash : hash, // Commitment hash
sign : signature) : unit = // Signed by addr (if not Contract.address)
AENSv2.preclaim(addr, chash, signature = sign)
AENS.preclaim(addr, chash, signature = sign)
stateful entrypoint claim(addr : address,
name : string,
salt : int,
name_fee : int) : unit =
AENSv2.claim(addr, name, salt, name_fee)
AENS.claim(addr, name, salt, name_fee)
stateful entrypoint signedClaim(addr : address,
name : string,
salt : int,
name_fee : int,
sign : signature) : unit =
AENSv2.claim(addr, name, salt, name_fee, signature = sign)
AENS.claim(addr, name, salt, name_fee, signature = sign)
stateful entrypoint update(owner : address,
name : string,
ttl : option(Chain.ttl),
client_ttl : option(int),
pointers : option(map(string, AENSv2.pointee))) : unit =
AENSv2.update(owner, name, ttl, client_ttl, pointers)
pointers : option(map(string, AENS.pointee))) : unit =
AENS.update(owner, name, ttl, client_ttl, pointers)
stateful entrypoint signedUpdate(owner : address,
name : string,
ttl : option(Chain.ttl),
client_ttl : option(int),
pointers : option(map(string, AENSv2.pointee)),
pointers : option(map(string, AENS.pointee)),
sign : signature) : unit =
AENSv2.update(owner, name, ttl, client_ttl, pointers, signature = sign)
AENS.update(owner, name, ttl, client_ttl, pointers, signature = sign)
stateful entrypoint transfer(owner : address,
new_owner : address,
name : string) : unit =
AENSv2.transfer(owner, new_owner, name)
AENS.transfer(owner, new_owner, name)
stateful entrypoint signedTransfer(owner : address,
new_owner : address,
name : string,
sign : signature) : unit =
AENSv2.transfer(owner, new_owner, name, signature = sign)
AENS.transfer(owner, new_owner, name, signature = sign)
stateful entrypoint revoke(owner : address,
name : string) : unit =
AENSv2.revoke(owner, name)
AENS.revoke(owner, name)
stateful entrypoint signedRevoke(owner : address,
name : string,
sign : signature) : unit =
AENSv2.revoke(owner, name, signature = sign)
AENS.revoke(owner, name, signature = sign)
+11 -24
View File
@@ -1,30 +1,17 @@
include "Option.aes"
include "AENSCompat.aes"
contract interface OldAENSContract =
entrypoint set : (string, string, AENS.pointee) => unit
entrypoint lookup : (string, string) => AENS.pointee
main contract AENSUpdate =
contract AENSUpdate =
stateful entrypoint update_name(owner : address, name : string) =
let p1 : AENSv2.pointee = AENSv2.AccountPt(Call.caller)
let p2 : AENSv2.pointee = AENSv2.OraclePt(Call.caller)
let p3 : AENSv2.pointee = AENSv2.ContractPt(Call.caller)
let p4 : AENSv2.pointee = AENSv2.ChannelPt(Call.caller)
let p5 : AENSv2.pointee = AENSv2.DataPt("any something will do")
AENSv2.update(owner, name, None, None,
Some({ ["account_pubkey"] = p1, ["oracle_pubkey"] = p2,
["contract_pubkey"] = p3, ["misc"] = p4, ["data"] = p5 }))
stateful entrypoint old_interaction(c : OldAENSContract, owner : address, name : string) =
let p : AENS.pointee = c.lookup(name, "key1")
AENSv2.update(owner, name, None, None, Some({ ["key1"] = AENSCompat.pointee_to_V2(p) }))
switch(AENSv2.lookup(name))
Some(AENSv2.Name(_, _, pt_map)) =>
c.set(name, "key2", Option.force(AENSCompat.pointee_from_V2(pt_map["key1"])))
let p1 : AENS.pointee = AENS.AccountPt(Call.caller)
let p2 : AENS.pointee = AENS.OraclePt(Call.caller)
let p3 : AENS.pointee = AENS.ContractPt(Call.caller)
let p4 : AENS.pointee = AENS.ChannelPt(Call.caller)
AENS.update(owner, name, None, None,
Some({ ["account_pubkey"] = p1, ["oracle_pubkey"] = p2,
["contract_pubkey"] = p3, ["misc"] = p4 }))
entrypoint get_ttl(name : string) =
switch(AENSv2.lookup(name))
Some(AENSv2.Name(_, FixedTTL(ttl), _)) => ttl
switch(AENS.lookup(name))
Some(AENS.Name(_, FixedTTL(ttl), _)) => ttl
entrypoint expiry(o : oracle(int, int)) : int =
Oracle.expiry(o)
+1 -1
View File
@@ -3,7 +3,7 @@ contract BadAENSresolve =
type t('a) = option(list('a))
function fail() : t(int) =
AENSv2.resolve("foo.aet", "whatever")
AENS.resolve("foo.aet", "whatever")
entrypoint main_fun() = ()
+2 -2
View File
@@ -1,9 +1,9 @@
contract BadAENSresolve =
using AENSv2
using AENS
type t('a) = option(list('a))
function fail() : t(int) =
resolve("foo.aet", "whatever")
entrypoint main_fun() = ()
entrypoint main_fun() = ()
@@ -0,0 +1,5 @@
contract F =
entrypoint g() = 1
main contract C =
entrypoint f() = F.g()
-14
View File
@@ -1,14 +0,0 @@
contract C =
entrypoint test() =
let a : int = 23
let b : int = 52
let c = a bor b
let d = c bxor b
let e = d band b
let f = bnot a
let g = f << 2
let h = g >> 2
let i = Int.mulmod(a, b, h)
let j = Crypto.poseidon(i, a)
let k : bytes(32) = Address.to_bytes(Call.origin)
(a bor b band c bxor a << bnot b >> a, k)
+13
View File
@@ -0,0 +1,13 @@
include "List.aes"
contract C =
entrypoint f() =
let ??? = true
let v = ???
let q = v == "str"
let xs = [1, 2, 3, 4]
switch (List.first(List.map(???, xs)))
Some(x) => x + 1
None => 0
function g() = ???
+1 -1
View File
@@ -1,7 +1,7 @@
contract PolymorphicAENSresolve =
function fail() : option('a) =
AENSv2.resolve("foo.aet", "whatever")
AENS.resolve("foo.aet", "whatever")
entrypoint main_fun() = ()
@@ -0,0 +1,5 @@
contract interface I =
entrypoint f : () => int
contract C : I =
stateful entrypoint f() = 1
@@ -0,0 +1,6 @@
contract interface I =
entrypoint f : () => int
contract C : I =
entrypoint init() = ()
function f() = 1
@@ -0,0 +1,5 @@
payable contract interface I =
payable entrypoint f : () => int
contract C : I =
entrypoint f() = 123
@@ -0,0 +1,8 @@
payable contract interface I =
payable entrypoint f : () => int
contract interface H : I =
payable entrypoint f : () => int
payable contract C : H =
entrypoint f() = 123
@@ -0,0 +1,14 @@
contract interface F =
entrypoint f : () => int
payable contract interface G : F =
payable entrypoint f : () => int
entrypoint g : () => int
payable contract interface H =
payable entrypoint h : () => int
payable contract C : G, H =
payable entrypoint f() = 1
payable entrypoint g() = 2
payable entrypoint h() = 3
@@ -0,0 +1,7 @@
contract interface I =
payable entrypoint f : () => int
entrypoint g : () => int
contract C : I =
payable entrypoint f() = 1
payable entrypoint g() = 2
@@ -0,0 +1,7 @@
contract interface I =
stateful entrypoint f : () => int
stateful entrypoint g : () => int
contract C : I =
stateful entrypoint f() = 1
entrypoint g() = 2
@@ -0,0 +1,5 @@
contract interface I =
payable entrypoint f : () => int
contract C : I =
entrypoint f() = 1
+5 -5
View File
@@ -2,10 +2,10 @@
// Named argument builtins are:
// Oracle.register
// Oracle.respond
// AENSv2.preclaim
// AENSv2.claim
// AENSv2.transfer
// AENSv2.revoke
// AENS.preclaim
// AENS.claim
// AENS.transfer
// AENS.revoke
// Oracle.extend
include "String.aes"
contract UnappliedBuiltins =
@@ -28,7 +28,7 @@ contract UnappliedBuiltins =
function oracle_get_answer() = Oracle.get_answer : (o, _) => _
function oracle_check() = Oracle.check : o => _
function oracle_check_query() = Oracle.check_query : (o, _) => _
function aens_resolve() = AENSv2.resolve : (_, _) => option(string)
function aens_resolve() = AENS.resolve : (_, _) => option(string)
function map_lookup() = Map.lookup : (_, m) => _
function map_lookup_default() = Map.lookup_default : (_, m, _) => _
function map_member() = Map.member : (_, m) => _
@@ -0,0 +1,7 @@
contract F =
entrypoint g() = 1
main contract C =
using F for [g]
entrypoint f() = g()
+8 -1
View File
@@ -12,7 +12,7 @@ namespace UnusedNamespace =
// Unused
private function h() = 3
contract Warnings =
main contract Warnings =
type state = int
@@ -58,3 +58,10 @@ namespace FunctionsAsArgs =
private function inc(n : int) : int = n + 1
// Never used
private function dec(n : int) : int = n - 1
contract Remote =
entrypoint id(_) = 0
contract C =
payable stateful entrypoint
call_missing_con() : int = (ct_1111111111111111111111111111112JF6Dz72 : Remote).id(value = 1, 0)