Renaming and preparing to remove oracles
This commit is contained in:
parent
927cd42592
commit
1b7a8e8fcd
@ -1,53 +0,0 @@
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
aebuilder:
|
||||
docker:
|
||||
- image: aeternity/builder:bionic-otp24
|
||||
user: builder
|
||||
working_directory: ~/aesophia
|
||||
|
||||
jobs:
|
||||
verify_rebar_lock:
|
||||
executor: aebuilder
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Ensure lock file is up-to-date
|
||||
command: |
|
||||
./rebar3 upgrade
|
||||
git diff --quiet -- rebar.lock || (echo "rebar.lock is not up-to-date" && exit 1)
|
||||
build:
|
||||
executor: aebuilder
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- dialyzer-cache-v2-{{ .Branch }}-{{ .Revision }}
|
||||
- dialyzer-cache-v2-{{ .Branch }}-
|
||||
- dialyzer-cache-v2-
|
||||
- run:
|
||||
name: Build
|
||||
command: ./rebar3 compile
|
||||
- run:
|
||||
name: Static Analysis
|
||||
command: ./rebar3 dialyzer
|
||||
- run:
|
||||
name: Eunit
|
||||
command: ./rebar3 eunit
|
||||
- run:
|
||||
name: Common Tests
|
||||
command: ./rebar3 ct
|
||||
- save_cache:
|
||||
key: dialyzer-cache-v2-{{ .Branch }}-{{ .Revision }}
|
||||
paths:
|
||||
- _build/default/rebar3_20.3.8_plt
|
||||
- store_artifacts:
|
||||
path: _build/test/logs
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_test:
|
||||
jobs:
|
||||
- build
|
||||
- verify_rebar_lock
|
21
.github/workflows/docs-develop.yml
vendored
21
.github/workflows/docs-develop.yml
vendored
@ -1,21 +0,0 @@
|
||||
name: Publish development docs
|
||||
on:
|
||||
push:
|
||||
branches: ['master']
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- run: pip3 install -r .github/workflows/requirements.txt -U
|
||||
- run: git config --global user.email "github-action@users.noreply.github.com"
|
||||
- run: git config --global user.name "GitHub Action"
|
||||
- run: |
|
||||
cd .docssite
|
||||
mike deploy --push master
|
22
.github/workflows/docs-release.yml
vendored
22
.github/workflows/docs-release.yml
vendored
@ -1,22 +0,0 @@
|
||||
name: Publish release docs
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- run: pip3 install -r .github/workflows/requirements.txt -U
|
||||
- run: git config --global user.email "github-action@users.noreply.github.com"
|
||||
- run: git config --global user.name "GitHub Action"
|
||||
- run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
|
||||
- run: |
|
||||
cd .docssite
|
||||
mike deploy --push --update-aliases $RELEASE_VERSION latest
|
5
.github/workflows/requirements.txt
vendored
5
.github/workflows/requirements.txt
vendored
@ -1,5 +0,0 @@
|
||||
mkdocs==1.4.2
|
||||
mkdocs-simple-hooks==0.1.5
|
||||
mkdocs-material==9.0.9
|
||||
mike==1.1.2
|
||||
pygments==2.17.2
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,7 +18,7 @@ _build
|
||||
rebar3.crashdump
|
||||
*.erl~
|
||||
*.aes~
|
||||
aesophia
|
||||
sophia
|
||||
.qcci
|
||||
current_counterexample.eqc
|
||||
test/contracts/test.aes
|
||||
|
1
Emakefile
Normal file
1
Emakefile
Normal file
@ -0,0 +1 @@
|
||||
{"src/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}.
|
1
LICENSE
1
LICENSE
@ -1,5 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2025, QPQ AG
|
||||
Copyright (c) 2017, æternity developers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
|
16
README.md
16
README.md
@ -1,11 +1,11 @@
|
||||
# aesophia
|
||||
# The Sophia smart contract language
|
||||
|
||||
This is the __sophia__ compiler for the æternity system which compiles contracts written in __sophia__ to [FATE](https://github.com/aeternity/protocol/blob/master/contracts/fate.md) instructions.
|
||||
This is the __sophia__ compiler which compiles contracts written in __sophia__ to [FATE](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/contracts/fate.md) instructions.
|
||||
|
||||
The compiler is currently being used three places
|
||||
- [The command line compiler](https://github.com/aeternity/aesophia_cli)
|
||||
- [The HTTP compiler](https://github.com/aeternity/aesophia_http)
|
||||
- In [æternity node](https://github.com/aeternity/aeternity) tests
|
||||
- [The command line compiler](https://git.qpq.swiss/QPQ-AG/sophia_cli)
|
||||
- [Desktop wallet](https://git.qpq.swiss/QPQ-AG/GajuDesk)
|
||||
- In the [Gajumaru core node](https://git.qpq.swiss/QPQ-AG/gajumaru) tests
|
||||
|
||||
## Documentation
|
||||
|
||||
@ -16,7 +16,7 @@ The compiler is currently being used three places
|
||||
* [Contract examples](docs/sophia_examples.md)
|
||||
* [Contributing](CONTRIBUTING.md)
|
||||
|
||||
Additionally you can check out the [contracts section](https://github.com/aeternity/protocol/blob/master/contracts/contracts.md) of the æternity blockchain specification.
|
||||
Additionally you can check out the [contracts section](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/contracts) of the Gajumaru blockchain specification.
|
||||
|
||||
## Versioning
|
||||
|
||||
@ -31,5 +31,5 @@ Versioning should follow the [semantic versioning](https://semver.org/spec/v2.0.
|
||||
|
||||
The basic modules for interfacing the compiler:
|
||||
|
||||
* [aeso_compiler: the Sophia compiler](docs/aeso_compiler.md)
|
||||
* [aeso_aci: the ACI interface](docs/aeso_aci.md)
|
||||
* [so_compiler: the Sophia compiler](docs/so_compiler.md)
|
||||
* [so_aci: the ACI interface](docs/so_aci.md)
|
||||
|
@ -1,12 +1,9 @@
|
||||
# Introduction
|
||||
Sophia is a functional language designed for smart contract development. It is strongly typed and has
|
||||
restricted mutable state.
|
||||
Sophia is a functional language designed for smart contract development.
|
||||
It is strongly typed and has restricted mutable state.
|
||||
|
||||
Sophia is customized for smart contracts, which can be published
|
||||
to a blockchain. Thus some features of conventional
|
||||
languages, such as floating point arithmetic, are not present in Sophia, and
|
||||
some [æternity blockchain](https://aeternity.com) specific primitives, constructions and types have been added.
|
||||
Sophia is customized for smart contracts, which can be published to a blockchain.
|
||||
Thus some features of conventional languages (such as floating point arithmetic) are not present in Sophia,
|
||||
and some blockchain specific primitives, constructions and types have been added.
|
||||
|
||||
!!! Note
|
||||
- For rapid prototyping of smart contracts check out [AEstudio](https://studio.aepps.com/)!
|
||||
- For playing around and diving deeper into the language itself check out the [REPL](https://repl.aeternity.io/)!
|
||||
The file extension used for Sophia source files is ".aes", reflecting Sophia's Aeternity heritage.
|
||||
|
@ -1,8 +1,8 @@
|
||||
# aeso_aci
|
||||
# so_aci
|
||||
|
||||
### Module
|
||||
|
||||
### aeso_aci
|
||||
### so_aci
|
||||
|
||||
The ACI interface encoder and decoder.
|
||||
|
||||
@ -123,7 +123,7 @@ be included inside another contract.
|
||||
``` erlang
|
||||
1> {ok,Contract} = file:read_file("aci_test.aes").
|
||||
{ok,<<"contract Answers =\n record state = { a : answers }\n type answers() = map(string, int)\n\n stateful function"...>>}
|
||||
2> {ok,JsonACI} = aeso_aci:contract_interface(json, Contract).
|
||||
2> {ok,JsonACI} = so_aci:contract_interface(json, Contract).
|
||||
{ok,[#{contract =>
|
||||
#{functions =>
|
||||
[#{arguments => [],name => <<"init">>,
|
||||
@ -144,7 +144,7 @@ be included inside another contract.
|
||||
vars => []}]}}]}
|
||||
3> file:write_file("aci_test.aci", jsx:encode(JsonACI)).
|
||||
ok
|
||||
4> {ok,InterfaceStub} = aeso_aci:render_aci_json(JsonACI).
|
||||
4> {ok,InterfaceStub} = so_aci:render_aci_json(JsonACI).
|
||||
{ok,<<"contract Answers =\n record state = {a : Answers.answers}\n type answers = map(string, int)\n function init "...>>}
|
||||
5> file:write_file("aci_test.include", InterfaceStub).
|
||||
ok
|
@ -1,8 +1,8 @@
|
||||
# aeso_compiler
|
||||
# so_compiler
|
||||
|
||||
### Module
|
||||
|
||||
### aeso_compiler
|
||||
### so_compiler
|
||||
|
||||
The Sophia compiler
|
||||
|
@ -65,9 +65,3 @@ contract FundMe =
|
||||
amount = state.contributions[to]})
|
||||
put(state{ contributions @ c = Map.delete(to, c) })
|
||||
```
|
||||
|
||||
## Repositories
|
||||
This is a list with repositories that include smart contracts written in Sophia:
|
||||
|
||||
- [aepp-sophia-examples](https://github.com/aeternity/aepp-sophia-examples)
|
||||
- A repository that contains lots of different examples. The functionality of these examples is - to some extent - also covered by tests written in JavaScript.
|
@ -274,12 +274,6 @@ counterpart in `Args1`.
|
||||
- A map type `map(A1, A2)` is a subtype of `map(B1, B2)` if `A1` is a subtype
|
||||
of `B1`, and `A2` is a subtype of `B2`.
|
||||
|
||||
- An oracle type `oracle(A1, A2)` is a subtype of `oracle(B1, B2)` if `B1` is
|
||||
a subtype of `A1`, and `A2` is a subtype of `B2`.
|
||||
|
||||
- An oracle_query type `oracle_query(A1, A2)` is a subtype of `oracle_query(B1, B2)`
|
||||
if `A1` is a subtype of `B1`, and `A2` is a subtype of `B2`.
|
||||
|
||||
- A user-defined datatype `t(Args1)` is a subtype of `t(Args2)`
|
||||
|
||||
- When a user-defined type `t('a)` is covariant in `'a`, then `t(A)` is a
|
||||
@ -340,10 +334,6 @@ Without the `stateful` annotation the compiler does not allow the call to
|
||||
* Use a stateful primitive function. These are
|
||||
- `put`
|
||||
- `Chain.spend`
|
||||
- `Oracle.register`
|
||||
- `Oracle.query`
|
||||
- `Oracle.respond`
|
||||
- `Oracle.extend`
|
||||
- `AENS.preclaim`
|
||||
- `AENS.claim`
|
||||
- `AENS.transfer`
|
||||
@ -556,8 +546,6 @@ Sophia has the following types:
|
||||
| hash | A 32-byte hash - equivalent to `bytes(32)` | |
|
||||
| signature | A signature - equivalent to `bytes(64)` | |
|
||||
| Chain.ttl | Time-to-live (fixed height or relative to current block) | ```FixedTTL(1050)``` ```RelativeTTL(50)``` |
|
||||
| oracle('a, 'b) | And oracle answering questions of type 'a with answers of type 'b | ```Oracle.register(acct, qfee, ttl)``` |
|
||||
| oracle_query('a, 'b) | A specific oracle query | ```Oracle.query(o, q, qfee, qttl, rttl)``` |
|
||||
| contract | A user defined, typed, contract address | ```function call_remote(r : RemoteContract) = r.fun()``` |
|
||||
|
||||
## Literals
|
||||
@ -580,8 +568,6 @@ Sophia has the following types:
|
||||
| hash | `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
||||
| signature | `sg_MhibzTP1wWzGCTjtPFr1TiPqRJrrJqw7auvEuF5i3FdoALWqXLBDY6xxRRNUSPHK3EQTnTzF12EyspkxrSMxVHKsZeSMj`, `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
||||
| Chain.ttl | `FixedTTL(1050)`, `RelativeTTL(50)` |
|
||||
| oracle('a, 'b) | `ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5` |
|
||||
| oracle_query('a, 'b) | `oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY` |
|
||||
| contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` |
|
||||
|
||||
## Hole expression
|
||||
@ -891,77 +877,9 @@ wrapping a transaction.) The transaction and the transaction hash is available i
|
||||
`Auth.tx` and `Auth.tx_hash` respectively, they are *only* available during authentication if invoked by a
|
||||
normal contract call they return `None`.
|
||||
|
||||
## Oracle interface
|
||||
You can attach an oracle to the current contract and you can interact with oracles
|
||||
through the Oracle interface.
|
||||
|
||||
For a full description of how Oracle works see
|
||||
[Oracles](https://github.com/aeternity/protocol/blob/master/oracles/oracles.md#oracles).
|
||||
For a functionality documentation refer to the [standard library](sophia_stdlib.md#oracle).
|
||||
|
||||
### Example
|
||||
|
||||
Example for an oracle answering questions of type `string` with answers of type `int`:
|
||||
```sophia
|
||||
contract Oracles =
|
||||
|
||||
stateful entrypoint registerOracle(acct : address,
|
||||
sign : signature, // Signed network id + oracle address + contract address
|
||||
qfee : int,
|
||||
ttl : Chain.ttl) : oracle(string, int) =
|
||||
Oracle.register(acct, signature = sign, qfee, ttl)
|
||||
|
||||
entrypoint queryFee(o : oracle(string, int)) : int =
|
||||
Oracle.query_fee(o)
|
||||
|
||||
payable stateful entrypoint createQuery(o : oracle_query(string, int),
|
||||
q : string,
|
||||
qfee : int,
|
||||
qttl : Chain.ttl,
|
||||
rttl : int) : oracle_query(string, int) =
|
||||
require(qfee =< Call.value, "insufficient value for qfee")
|
||||
Oracle.query(o, q, qfee, qttl, RelativeTTL(rttl))
|
||||
|
||||
stateful entrypoint extendOracle(o : oracle(string, int),
|
||||
ttl : Chain.ttl) : unit =
|
||||
Oracle.extend(o, ttl)
|
||||
|
||||
stateful entrypoint signExtendOracle(o : oracle(string, int),
|
||||
sign : signature, // Signed network id + oracle address + contract address
|
||||
ttl : Chain.ttl) : unit =
|
||||
Oracle.extend(o, signature = sign, ttl)
|
||||
|
||||
stateful entrypoint respond(o : oracle(string, int),
|
||||
q : oracle_query(string, int),
|
||||
sign : signature, // Signed network id + oracle query id + contract address
|
||||
r : int) =
|
||||
Oracle.respond(o, q, signature = sign, r)
|
||||
|
||||
entrypoint getQuestion(o : oracle(string, int),
|
||||
q : oracle_query(string, int)) : string =
|
||||
Oracle.get_question(o, q)
|
||||
|
||||
entrypoint hasAnswer(o : oracle(string, int),
|
||||
q : oracle_query(string, int)) =
|
||||
switch(Oracle.get_answer(o, q))
|
||||
None => false
|
||||
Some(_) => true
|
||||
|
||||
entrypoint getAnswer(o : oracle(string, int),
|
||||
q : oracle_query(string, int)) : option(int) =
|
||||
Oracle.get_answer(o, q)
|
||||
```
|
||||
|
||||
### Sanity checks
|
||||
|
||||
When an Oracle literal is passed to a contract, no deep checks are performed.
|
||||
For extra safety [Oracle.check](sophia_stdlib.md#check) and [Oracle.check_query](sophia_stdlib.md#check_query)
|
||||
functions are provided.
|
||||
|
||||
## AENS interface
|
||||
|
||||
Contracts can interact with the [æternity naming
|
||||
system](https://github.com/aeternity/protocol/blob/master/AENS.md). For this
|
||||
Contracts can interact with the [æternity naming system](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/AENS.md). For this
|
||||
purpose the [AENS](sophia_stdlib.md#aens) and later the
|
||||
[AENSv2](sophia_stdlib.md#aensv2) library was exposed.
|
||||
|
||||
@ -1009,10 +927,9 @@ automatically removed so they will not appear in the pointers map.
|
||||
|
||||
## Events
|
||||
|
||||
Sophia contracts log structured messages to an event log in the resulting
|
||||
blockchain transaction. The event log is quite similar to [Events in
|
||||
Solidity](https://solidity.readthedocs.io/en/v0.4.24/contracts.html#events).
|
||||
Events are further discussed in the [protocol](https://github.com/aeternity/protocol/blob/master/contracts/events.md).
|
||||
Sophia contracts log structured messages to an event log in the resulting blockchain transaction.
|
||||
The event log is quite similar to [Events in Solidity](https://solidity.readthedocs.io/en/v0.4.24/contracts.html#events).
|
||||
Events are further discussed in the [protocol](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/contracts/events.md).
|
||||
|
||||
|
||||
To use events a contract must declare a datatype `event`, and events are then
|
||||
@ -1032,8 +949,6 @@ field is indexed if it fits in a 32-byte word, i.e.
|
||||
- `int`
|
||||
- `bits`
|
||||
- `address`
|
||||
- `oracle(_, _)`
|
||||
- `oracle_query(_, _)`
|
||||
- contract types
|
||||
- `bytes(n)` for `n` ≤ 32, in particular `hash`
|
||||
|
||||
@ -1113,34 +1028,15 @@ however is in the gas consumption — while `abort` returns unused gas, a call t
|
||||
|
||||
## Delegation signature
|
||||
|
||||
Some chain operations (`Oracle.<operation>` and `AENSv2.<operation>`) have an
|
||||
Some chain operations (`AENSv2.<operation>`) have an
|
||||
optional delegation signature. This is typically used when a user/accounts
|
||||
would like to allow a contract to act on it's behalf.
|
||||
|
||||
### From Ceres
|
||||
|
||||
From the Ceres protocol version the delegation signatures have more structure,
|
||||
including a unique tag, `network_id` and identifiers; there are five different
|
||||
delegation signatures:
|
||||
There are five different delegation signatures:
|
||||
|
||||
- AENS wildcard - the user signs: `owner account + contract`
|
||||
- `AENS_PRECLAIM` - the user signs: `owner account + contract`
|
||||
- `AENS_CLAIM, AENS_UPDATE, AENS_TRANSFER, AENS_REVOKE` - the user signs: `owner account + name hash + contract`
|
||||
- `ORACLE_REGISTER, ORACLE_EXTEND` - the user signs: `owner account + contract`
|
||||
- `ORACLE_RESPOND` - the user signs: `query id + contract`
|
||||
|
||||
See [Serialized signature
|
||||
data](https://github.com/aeternity/protocol/blob/master/contracts/fate.md#from-ceres-serialized-signature-data)
|
||||
See [Serialized signature data](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/serializations.md)
|
||||
for the exact structure used.
|
||||
|
||||
### Before ceres
|
||||
|
||||
The exact data to be signed varies for the different operations, but in all
|
||||
cases you should prepend the signature data with the `network_id` (`ae_mainnet`
|
||||
for the æternity mainnet, etc.).
|
||||
|
||||
There are four different delegation signatures:
|
||||
- `AENS_PRECLAIM` - the user signs: owner `network_id + account + contract`
|
||||
- `AENS_CLAIM, AENS_UPDATE, AENS_TRANSFER, AENS_REVOKE` - the user signs: `network_id + owner account + name hash + contract`
|
||||
- `ORACLE_REGISTER, ORACLE_EXTEND` - the user signs: `network_id + owner account + contract`
|
||||
- `ORACLE_RESPOND` - the user signs: `network_id + query id + contract`
|
||||
|
@ -25,7 +25,6 @@ The out-of-the-box namespaces are:
|
||||
- [Crypto](#crypto)
|
||||
- [Int](#int)
|
||||
- [Map](#map)
|
||||
- [Oracle](#oracle)
|
||||
|
||||
The following ones need to be included as regular files with `.aes` suffix, for example
|
||||
```
|
||||
@ -72,14 +71,6 @@ Address.is_contract(a : address) : bool
|
||||
Is the address a contract
|
||||
|
||||
|
||||
#### is_oracle
|
||||
```
|
||||
Address.is_oracle(a : address) : bool
|
||||
```
|
||||
|
||||
Is the address a registered oracle
|
||||
|
||||
|
||||
#### is_payable
|
||||
```
|
||||
Address.is_payable(a : address) : bool
|
||||
@ -99,7 +90,7 @@ 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
|
||||
contracts from before Ceres, compiled using sophia compiler version 7.x and
|
||||
earlier. Used in [AENSCompat](#aenscompat) when converting between old and new
|
||||
pointers.
|
||||
|
||||
@ -114,8 +105,9 @@ datatype name = Name(address, Chain.ttl, map(string, AENS.pointee))
|
||||
##### pointee
|
||||
|
||||
```
|
||||
datatype pointee = AccountPt(address) | OraclePt(address)
|
||||
| ContractPt(address) | ChannelPt(address)
|
||||
datatype pointee = AccountPt(address)
|
||||
| ContractPt(address)
|
||||
| ChannelPt(address)
|
||||
```
|
||||
|
||||
### AENSv2
|
||||
@ -127,7 +119,7 @@ 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),
|
||||
id](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/consensus/README.md#transaction-signature),
|
||||
i.e. the signature material should be prefixed by the network id.
|
||||
|
||||
#### Types
|
||||
@ -141,8 +133,10 @@ datatype name = Name(address, Chain.ttl, map(string, AENSv2.pointee))
|
||||
##### pointee
|
||||
|
||||
```
|
||||
datatype pointee = AccountPt(address) | OraclePt(address)
|
||||
| ContractPt(address) | ChannelPt(address) | DataPt(bytes())
|
||||
datatype pointee = AccountPt(address)
|
||||
| ContractPt(address)
|
||||
| ChannelPt(address)
|
||||
| DataPt(bytes())
|
||||
```
|
||||
|
||||
Note: on-chain there is a maximum length enforced for `DataPt`, it is 1024 bytes.
|
||||
@ -185,8 +179,7 @@ The [signature](./sophia_features.md#delegation-signature) should be a
|
||||
serialized structure containing `network id`, `owner address`, and
|
||||
`Contract.address`.
|
||||
|
||||
From Ceres (i.e. FATE VM version 3) the
|
||||
[signature](./sophia_features.md#delegation-signature) can also be generic
|
||||
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. containing `network id`, `owner address`, `Contract.address`.
|
||||
|
||||
@ -287,7 +280,6 @@ namespace Chain =
|
||||
datatype ga_meta_tx = GAMetaTx(address, int)
|
||||
datatype paying_for_tx = PayingForTx(address, int)
|
||||
datatype base_tx = SpendTx(address, int, string)
|
||||
| OracleRegisterTx | OracleQueryTx | OracleResponseTx | OracleExtendTx
|
||||
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
||||
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
||||
| ChannelCreateTx(address) | ChannelDepositTx(address, int) | ChannelWithdrawTx(address, int) |
|
||||
@ -305,7 +297,7 @@ 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)
|
||||
[aeserialisation](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/serializations.md)
|
||||
specification for details.
|
||||
|
||||
|
||||
@ -537,7 +529,6 @@ datatype paying_for_tx = PayingForTx(address, int)
|
||||
##### base_tx
|
||||
```
|
||||
datatype base_tx = SpendTx(address, int, string)
|
||||
| OracleRegisterTx | OracleQueryTx | OracleResponseTx | OracleExtendTx
|
||||
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
||||
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
||||
| ChannelCreateTx(address) | ChannelDepositTx(address, int) | ChannelWithdrawTx(address, int) |
|
||||
@ -944,118 +935,6 @@ Returns a list containing pairs of keys and their respective elements.
|
||||
Turns a list of pairs of form `(key, value)` into a map
|
||||
|
||||
|
||||
### Oracle
|
||||
|
||||
#### register
|
||||
```
|
||||
Oracle.register(<signature : bytes(64)>, acct : address, qfee : int, ttl : Chain.ttl) : oracle('a, 'b)
|
||||
```
|
||||
|
||||
Registers new oracle answering questions of type `'a` with answers of type `'b`.
|
||||
|
||||
* The `acct` is the address of the oracle to register (can be the same as the contract).
|
||||
* The [signature](./sophia_features.md#delegation-signature) should be a
|
||||
serialized structure containing `network id`, `account address`, and
|
||||
`contract address`. Using the private key of `account address` for signing.
|
||||
Proving you have the private key of the oracle to be. If the address is the same
|
||||
as the contract `sign` is ignored and can be left out entirely.
|
||||
* The `qfee` is the minimum query fee to be paid by a user when asking a question of the oracle.
|
||||
* The `ttl` is the Time To Live for the oracle in key blocks, either relative to the current
|
||||
key block height (`RelativeTTL(delta)`) or a fixed key block height (`FixedTTL(height)`).
|
||||
* The type `'a` is the type of the question to ask.
|
||||
* The type `'b` is the type of the oracle answers.
|
||||
|
||||
Examples:
|
||||
```
|
||||
Oracle.register(addr0, 25, RelativeTTL(400))
|
||||
Oracle.register(addr1, 25, RelativeTTL(500), signature = sign1)
|
||||
```
|
||||
|
||||
|
||||
#### get\_question
|
||||
```
|
||||
Oracle.get_question(o : oracle('a, 'b), q : oracle_query('a, 'b)) : 'a
|
||||
```
|
||||
|
||||
Checks what was the question of query `q` on oracle `o`
|
||||
|
||||
|
||||
#### respond
|
||||
```
|
||||
Oracle.respond(<signature : bytes(64)>, o : oracle('a, 'b), q : oracle_query('a, 'b), 'b) : unit
|
||||
```
|
||||
|
||||
Responds to the question `q` on `o`. Unless the contract address is the same
|
||||
as the oracle address the `signature` (which is an optional, named argument)
|
||||
needs to be provided. Proving that we have the private key of the oracle by
|
||||
[signing](./sophia_features.md#delegation-signature) should be a serialized
|
||||
structure containing `network id`, `oracle query id`, and `contract address`.
|
||||
|
||||
|
||||
#### extend
|
||||
```
|
||||
Oracle.extend(<signature : bytes(64)>, o : oracle('a, 'b), ttl : Chain.ttl) : unit
|
||||
```
|
||||
|
||||
Extends TTL of an oracle.
|
||||
* `singature` is a named argument and thus optional. Must be the same as for `Oracle.register`
|
||||
* `o` is the oracle being extended
|
||||
* `ttl` must be `RelativeTTL`. The time to live of `o` will be extended by this value.
|
||||
|
||||
#### query\_fee
|
||||
```
|
||||
Oracle.query_fee(o : oracle('a, 'b)) : int
|
||||
```
|
||||
|
||||
Returns the query fee of the oracle
|
||||
|
||||
|
||||
#### query
|
||||
```
|
||||
Oracle.query(o : oracle('a, 'b), q : 'a, qfee : int, qttl : Chain.ttl, rttl : Chain.ttl) : oracle_query('a, 'b)
|
||||
```
|
||||
|
||||
Asks the oracle a question.
|
||||
* The `qfee` is the query fee debited to the contract account (`Contract.address`).
|
||||
* The `qttl` controls the last height at which the oracle can submit a response
|
||||
and can be either fixed or relative.
|
||||
* The `rttl` must be relative and controls how long an answer is kept on the chain.
|
||||
The call fails if the oracle could expire before an answer.
|
||||
|
||||
|
||||
#### get\_answer
|
||||
```
|
||||
Oracle.get_answer(o : oracle('a, 'b), q : oracle_query('a, 'b)) : option('b)
|
||||
```
|
||||
|
||||
Checks what is the optional query answer
|
||||
|
||||
|
||||
#### expiry
|
||||
|
||||
```
|
||||
Oracle.expiry(o : oracle('a, 'b)) : int
|
||||
```
|
||||
|
||||
Ask the oracle when it expires. The result is the block height at which it will happen.
|
||||
|
||||
|
||||
#### check
|
||||
```
|
||||
Oracle.check(o : oracle('a, 'b)) : bool
|
||||
```
|
||||
|
||||
Returns `true` iff the oracle `o` exists and has correct type
|
||||
|
||||
|
||||
#### check_query
|
||||
```
|
||||
Oracle.check_query(o : oracle('a, 'b), q : oracle_query('a, 'b)) : bool
|
||||
```
|
||||
|
||||
It returns `true` iff the oracle query exist and has the expected type.
|
||||
|
||||
|
||||
## Includable namespaces
|
||||
|
||||
These need to be explicitly included (with `.aes` suffix)
|
||||
@ -1664,7 +1543,7 @@ point where the error would exceed the `loss` value.
|
||||
|
||||
For debugging. If it ever returns false in a code that doesn't call `frac` constructors or
|
||||
accept arbitrary `frac`s from the surface you should report it as a
|
||||
[bug](https://github.com/aeternity/aesophia/issues/new)
|
||||
[bug](https://git.qpq.swiss/QPQ-AG/sophia/issues/new)
|
||||
|
||||
If you expect getting calls with malformed `frac`s in your contract, you should use
|
||||
this function to verify the input.
|
||||
|
@ -28,8 +28,6 @@ interface main using as for hiding
|
||||
- `Char` character literal enclosed in `'` with escape character `\`
|
||||
- `AccountAddress` base58-encoded 32 byte account pubkey with `ak_` prefix
|
||||
- `ContractAddress` base58-encoded 32 byte contract address with `ct_` prefix
|
||||
- `OracleAddress` base58-encoded 32 byte oracle address with `ok_` prefix
|
||||
- `OracleQueryId` base58-encoded 32 byte oracle query id with `oq_` prefix
|
||||
- `Signature` base58-encoded 64 byte cryptographic signature with `sg_` prefix
|
||||
|
||||
Valid string escape codes are
|
||||
@ -46,7 +44,7 @@ Valid string escape codes are
|
||||
| `\xHexDigits` | *HexDigits* | |
|
||||
|
||||
|
||||
See the [identifier encoding scheme](https://github.com/aeternity/protocol/blob/master/node/api/api_encoding.md) for the
|
||||
See the [identifier encoding scheme](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/node/api/api_encoding.md) for the
|
||||
details on the base58 literals.
|
||||
|
||||
## Layout blocks
|
||||
@ -239,7 +237,6 @@ Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x +
|
||||
| Id | Con | QId | QCon // Identifiers x, None, Map.member, AELib.Token
|
||||
| Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%'
|
||||
| AccountAddress | ContractAddress // Chain identifiers
|
||||
| OracleAddress | OracleQueryId // Chain identifiers
|
||||
| Signature // Signature
|
||||
| '???' // Hole expression 1 + ???
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
-define(LET_P(X, P, Q), aeso_parse_lib:bind(P, fun(X) -> Q end)).
|
||||
-define(LAZY_P(P), aeso_parse_lib:lazy(fun() -> P end)).
|
||||
-define(MEMO_P(P), aeso_parse_lib:lazy(aeso_parse_lib:memoised(fun() -> P end))).
|
||||
-define(LET_P(X, P, Q), so_parse_lib:bind(P, fun(X) -> Q end)).
|
||||
-define(LAZY_P(P), so_parse_lib:lazy(fun() -> P end)).
|
||||
-define(MEMO_P(P), so_parse_lib:lazy(so_parse_lib:memoised(fun() -> P end))).
|
||||
|
||||
-define(GUARD_P(G, P),
|
||||
case G of
|
||||
@ -18,7 +18,7 @@
|
||||
-define(RULE(A, B, C, D, E, F, G, Do), map(fun({_1, _2, _3, _4, _5, _6, _7}) -> Do end, {A, B, C, D, E, F, G} )).
|
||||
-define(RULE(A, B, C, D, E, F, G, H, Do), map(fun({_1, _2, _3, _4, _5, _6, _7, _8}) -> Do end, {A, B, C, D, E, F, G, H})).
|
||||
|
||||
-import(aeso_parse_lib,
|
||||
-import(so_parse_lib,
|
||||
[tok/1, tok/2, between/3, many/1, many1/1, sep/2, sep1/2,
|
||||
infixl/1, infixr/1, choice/1, choice/2, return/1, layout/0,
|
||||
fail/0, fail/1, fail/2, map/2, infixl/2, infixr/2, infixl1/2, infixr1/2,
|
@ -2,7 +2,9 @@
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {tag, "v3.4.1"}}}
|
||||
{deps, [ {gmbytecode,
|
||||
{git, "https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||
{ref, "97cea33be8f3a35d26055664da7aa59531ff5537"}}}
|
||||
, {eblake2, "1.0.0"}
|
||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}}
|
||||
]}.
|
||||
@ -13,10 +15,11 @@
|
||||
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
|
||||
]}.
|
||||
|
||||
{relx, [{release, {aesophia, "8.0.1"},
|
||||
[aesophia, aebytecode]},
|
||||
{relx, [{release, {sophia, "8.0.1"},
|
||||
[sophia, gmbytecode]},
|
||||
|
||||
{dev_mode, true},
|
||||
{include_erts, false},
|
||||
|
||||
{extended_start_script, true}]}.
|
||||
|
||||
|
37
rebar.lock
37
rebar.lock
@ -1,31 +1,30 @@
|
||||
{"1.2.0",
|
||||
[{<<"aebytecode">>,
|
||||
{git,"https://github.com/aeternity/aebytecode.git",
|
||||
{ref,"6bd6f82c70d800950ea1a2c70c364a4181ff5291"}},
|
||||
[{<<"gmbytecode">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||
{ref, "97cea33be8f3a35d26055664da7aa59531ff5537"}},
|
||||
0},
|
||||
{<<"aeserialization">>,
|
||||
{git,"https://github.com/aeternity/aeserialization.git",
|
||||
{ref,"b26e6d105424748ba1c27917267b7cff07f37802"}},
|
||||
{<<"gmserialization">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||
{ref,"ac64e01b0f675c1a34c70a827062f381920742db"}},
|
||||
1},
|
||||
{<<"base58">>,
|
||||
{git,"https://github.com/aeternity/erl-base58.git",
|
||||
{ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}},
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/erl-base58.git",
|
||||
{ref,"e6aa62eeae3d4388311401f06e4b939bf4e94b9c"}},
|
||||
2},
|
||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||
{<<"eblake2">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/eblake2.git",
|
||||
{ref,"b29d585b8760746142014884007eb8441a3b6a14"}},
|
||||
0},
|
||||
{<<"enacl">>,
|
||||
{git,"https://github.com/aeternity/enacl.git",
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/enacl.git",
|
||||
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
|
||||
2},
|
||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},1},
|
||||
{<<"getopt">>,
|
||||
{git,"https://git.qpq.swiss/QPQ-AG/getopt.git",
|
||||
{ref,"dbab6262a2430809430deda9d8650f58f9d80898"}},
|
||||
1},
|
||||
{<<"jsx">>,
|
||||
{git,"https://github.com/talentdeficit/jsx.git",
|
||||
{ref,"3074d4865b3385a050badf7828ad31490d860df5"}},
|
||||
0}]}.
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
||||
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
|
||||
{pkg_hash_ext,[
|
||||
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>},
|
||||
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
|
||||
].
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Robert Virding
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% ACI interface
|
||||
%%% @end
|
||||
%%% Created : 12 Jan 2019
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_aci).
|
||||
-module(so_aci).
|
||||
|
||||
-export([ file/2
|
||||
, file/3
|
||||
@ -21,7 +21,7 @@
|
||||
, json_encode_expr/1
|
||||
, json_encode_type/1]).
|
||||
|
||||
-include("aeso_utils.hrl").
|
||||
-include("so_utils.hrl").
|
||||
|
||||
-type aci_type() :: json | string.
|
||||
-type json() :: jsx:json_term().
|
||||
@ -35,7 +35,7 @@ file(Type, File) ->
|
||||
file(Type, File, []).
|
||||
|
||||
file(Type, File, Options0) ->
|
||||
Options = aeso_compiler:add_include_path(File, Options0),
|
||||
Options = so_compiler:add_include_path(File, Options0),
|
||||
case file:read_file(File) of
|
||||
{ok, BinCode} ->
|
||||
do_contract_interface(Type, binary_to_list(BinCode), Options);
|
||||
@ -56,11 +56,11 @@ contract_interface(Type, ContractString, CompilerOpts) ->
|
||||
render_aci_json(Json) ->
|
||||
do_render_aci_json(Json).
|
||||
|
||||
-spec json_encode_expr(aeso_syntax:expr()) -> json().
|
||||
-spec json_encode_expr(so_syntax:expr()) -> json().
|
||||
json_encode_expr(Expr) ->
|
||||
encode_expr(Expr).
|
||||
|
||||
-spec json_encode_type(aeso_syntax:type()) -> json().
|
||||
-spec json_encode_type(so_syntax:type()) -> json().
|
||||
json_encode_type(Type) ->
|
||||
encode_type(Type).
|
||||
|
||||
@ -69,8 +69,8 @@ do_contract_interface(Type, Contract, Options) when is_binary(Contract) ->
|
||||
do_contract_interface(Type, binary_to_list(Contract), Options);
|
||||
do_contract_interface(Type, ContractString, Options) ->
|
||||
try
|
||||
Ast = aeso_compiler:parse(ContractString, Options),
|
||||
{TypedAst, _, _} = aeso_ast_infer_types:infer(Ast, [dont_unfold | Options]),
|
||||
Ast = so_compiler:parse(ContractString, Options),
|
||||
{TypedAst, _, _} = so_ast_infer_types:infer(Ast, [dont_unfold | Options]),
|
||||
from_typed_ast(Type, TypedAst)
|
||||
catch
|
||||
throw:{error, Errors} -> {error, Errors}
|
||||
@ -200,7 +200,7 @@ encode_expr({bytes, _, B}) ->
|
||||
encode_expr({Lit, _, L}) when Lit == oracle_pubkey; Lit == oracle_query_id;
|
||||
Lit == contract_pubkey; Lit == account_pubkey;
|
||||
Lit == signature ->
|
||||
aeser_api_encoder:encode(Lit, L);
|
||||
gmser_api_encoder:encode(Lit, L);
|
||||
encode_expr({app, _, {'-', _}, [{int, _, N}]}) ->
|
||||
encode_expr({int, [], -N});
|
||||
encode_expr({app, _, F, As}) ->
|
||||
@ -361,14 +361,14 @@ is_type(_) -> false.
|
||||
|
||||
sort_decls(Ds) ->
|
||||
Sort = fun (D1, D2) ->
|
||||
aeso_syntax:get_ann(line, D1, 0) =<
|
||||
aeso_syntax:get_ann(line, D2, 0)
|
||||
so_syntax:get_ann(line, D1, 0) =<
|
||||
so_syntax:get_ann(line, D2, 0)
|
||||
end,
|
||||
lists:sort(Sort, Ds).
|
||||
|
||||
is_entrypoint(Node) -> aeso_syntax:get_ann(entrypoint, Node, false).
|
||||
is_stateful(Node) -> aeso_syntax:get_ann(stateful, Node, false).
|
||||
is_payable(Node) -> aeso_syntax:get_ann(payable, Node, false).
|
||||
is_entrypoint(Node) -> so_syntax:get_ann(entrypoint, Node, false).
|
||||
is_stateful(Node) -> so_syntax:get_ann(stateful, Node, false).
|
||||
is_payable(Node) -> so_syntax:get_ann(payable, Node, false).
|
||||
|
||||
typedef_name({type_def, _, {id, _, Name}, _, _}) -> Name.
|
||||
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_ast).
|
||||
-module(so_ast).
|
||||
|
||||
-export([int/2,
|
||||
line/1,
|
||||
@ -17,11 +17,11 @@ line({symbol, Line, _}) -> Line.
|
||||
symbol_name({symbol, _, Name}) -> Name.
|
||||
|
||||
pp(Ast) ->
|
||||
String = prettypr:format(aeso_pretty:decls(Ast, [])),
|
||||
String = prettypr:format(so_pretty:decls(Ast, [])),
|
||||
io:format("Ast:\n~s\n", [String]).
|
||||
|
||||
pp_typed(TypedAst) ->
|
||||
%% io:format("Typed tree:\n~p\n",[TypedAst]),
|
||||
String = prettypr:format(aeso_pretty:decls(TypedAst, [show_generated])),
|
||||
String = prettypr:format(so_pretty:decls(TypedAst, [show_generated])),
|
||||
io:format("Type ast:\n~s\n",[String]).
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,17 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Ulf Norell
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Compiler from Aeterinty Sophia language to Fate intermediate code.
|
||||
%%% Compiler from Sophia language to Fate intermediate code.
|
||||
%%% @end
|
||||
%%% Created : 26 Mar 2019
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_ast_to_fcode).
|
||||
-module(so_ast_to_fcode).
|
||||
|
||||
-export([ast_to_fcode/2, format_fexpr/1]).
|
||||
-export_type([fcode/0, fexpr/0, fun_def/0]).
|
||||
|
||||
-include("aeso_utils.hrl").
|
||||
-include("so_utils.hrl").
|
||||
|
||||
%% -- Type definitions -------------------------------------------------------
|
||||
|
||||
@ -53,16 +52,14 @@
|
||||
| {bytes, binary()}
|
||||
| {account_pubkey, binary()}
|
||||
| {contract_pubkey, binary()}
|
||||
| {oracle_pubkey, binary()}
|
||||
| {oracle_query_id, binary()}
|
||||
| {signature, binary()}
|
||||
| {bool, false | true}
|
||||
| {contract_code, string()} %% for CREATE, by name
|
||||
| {typerep, ftype()}.
|
||||
|
||||
-type fann() :: [ {file, aeso_syntax:ann_file()} |
|
||||
{line, aeso_syntax:ann_line()} |
|
||||
{col, aeso_syntax:ann_col()}
|
||||
-type fann() :: [ {file, so_syntax:ann_file()} |
|
||||
{line, so_syntax:ann_line()} |
|
||||
{col, so_syntax:ann_col()}
|
||||
].
|
||||
|
||||
-type fexpr() :: {lit, fann(), flit()}
|
||||
@ -115,8 +112,6 @@
|
||||
| address
|
||||
| {bytes, non_neg_integer()}
|
||||
| contract
|
||||
| {oracle, ftype(), ftype()} %% Query type, Response type
|
||||
| oracle_query
|
||||
| name
|
||||
| channel
|
||||
| bits
|
||||
@ -166,7 +161,7 @@
|
||||
fun_env := fun_env(),
|
||||
con_env := con_env(),
|
||||
child_con_env := child_con_env(),
|
||||
event_type => aeso_syntax:typedef(),
|
||||
event_type => so_syntax:typedef(),
|
||||
builtins := builtins(),
|
||||
options := [option()],
|
||||
state_layout => state_layout(),
|
||||
@ -181,9 +176,9 @@
|
||||
|
||||
%% -- Entrypoint -------------------------------------------------------------
|
||||
|
||||
%% Main entrypoint. Takes typed syntax produced by aeso_ast_infer_types:infer/1,2
|
||||
%% Main entrypoint. Takes typed syntax produced by so_ast_infer_types:infer/1,2
|
||||
%% and produces Fate intermediate code.
|
||||
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> {env(), fcode()}.
|
||||
-spec ast_to_fcode(so_syntax:ast(), [option()]) -> {env(), fcode()}.
|
||||
ast_to_fcode(Code, Options) ->
|
||||
init_fresh_names(Options),
|
||||
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
||||
@ -305,7 +300,7 @@ builtins() ->
|
||||
{"to_any_size", 1}, {"size", 1}, {"split_any", 2}]},
|
||||
{["Int"], [{"to_str", 1}, {"to_bytes", 2}, {"mulmod", 2}]},
|
||||
{["Address"], [{"to_str", 1}, {"to_bytes", 1}, {"to_contract", 1},
|
||||
{"is_oracle", 1}, {"is_contract", 1}, {"is_payable", 1}]}
|
||||
{"is_contract", 1}, {"is_payable", 1}]}
|
||||
],
|
||||
maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}}
|
||||
|| {NS, Funs} <- Scopes,
|
||||
@ -333,8 +328,6 @@ init_type_env() ->
|
||||
["address"] => ?type(address),
|
||||
["hash"] => ?type(hash),
|
||||
["signature"] => ?type(signature),
|
||||
["oracle"] => ?type(Q, R, {oracle, Q, R}),
|
||||
["oracle_query"] => ?type(_, _, oracle_query), %% TODO: not in Fate
|
||||
["list"] => ?type(T, {list, T}),
|
||||
["map"] => ?type(K, V, {map, K, V}),
|
||||
["option"] => ?type(T, {variant, [[], [T]]}),
|
||||
@ -364,7 +357,7 @@ get_option(Opt, Env, Default) ->
|
||||
|
||||
%% -- Compilation ------------------------------------------------------------
|
||||
|
||||
-spec to_fcode(env(), aeso_syntax:ast()) -> {env(), fcode()}.
|
||||
-spec to_fcode(env(), so_syntax:ast()) -> {env(), fcode()}.
|
||||
to_fcode(Env, [{Contract, Attrs, {con, _, Name}, _Impls, Decls}|Rest])
|
||||
when ?IS_CONTRACT_HEAD(Contract) ->
|
||||
case Contract =:= contract_interface of
|
||||
@ -405,7 +398,7 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) ->
|
||||
Env1 = decls_to_fcode(Env#{ context => {namespace, Con} }, Decls),
|
||||
to_fcode(Env1, Code).
|
||||
|
||||
-spec ann_loc(aeso_syntax:ann() | fann()) -> {File, Line, Column} when
|
||||
-spec ann_loc(so_syntax:ann() | fann()) -> {File, Line, Column} when
|
||||
File :: string() | none,
|
||||
Line :: non_neg_integer() | none,
|
||||
Column :: non_neg_integer() | none.
|
||||
@ -415,7 +408,7 @@ ann_loc(Ann) ->
|
||||
Col = proplists:get_value(col, Ann, none),
|
||||
{File, Line, Col}.
|
||||
|
||||
-spec to_fann(aeso_syntax:ann()) -> fann().
|
||||
-spec to_fann(so_syntax:ann()) -> fann().
|
||||
to_fann(Ann) ->
|
||||
{File, Line, Col} = ann_loc(Ann),
|
||||
[ {Tag, X} ||
|
||||
@ -426,7 +419,7 @@ to_fann(Ann) ->
|
||||
-spec get_fann(fexpr()) -> fann().
|
||||
get_fann(FExpr) -> element(2, FExpr).
|
||||
|
||||
-spec decls_to_fcode(env(), [aeso_syntax:decl()]) -> env().
|
||||
-spec decls_to_fcode(env(), [so_syntax:decl()]) -> env().
|
||||
decls_to_fcode(Env, Decls) ->
|
||||
%% First compute mapping from Sophia names to fun_names and add it to the
|
||||
%% environment.
|
||||
@ -434,7 +427,7 @@ decls_to_fcode(Env, Decls) ->
|
||||
lists:foldl(fun(D, E) -> decl_to_fcode(E, D)
|
||||
end, Env1, Decls).
|
||||
|
||||
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
|
||||
-spec decl_to_fcode(env(), so_syntax:decl()) -> env().
|
||||
decl_to_fcode(Env, {fun_decl, _, _, _}) -> Env;
|
||||
decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) ->
|
||||
typedef_to_fcode(Env, Name, Args, Def);
|
||||
@ -458,7 +451,7 @@ decl_to_fcode(Env = #{ consts := Consts }, {letval, _, {typed, _, {id, _, X}, _}
|
||||
NewConsts = Consts#{ qname(Env, X) => FVal },
|
||||
Env#{ consts := NewConsts }.
|
||||
|
||||
-spec typedef_to_fcode(env(), aeso_syntax:id(), [aeso_syntax:tvar()], aeso_syntax:typedef()) -> env().
|
||||
-spec typedef_to_fcode(env(), so_syntax:id(), [so_syntax:tvar()], so_syntax:typedef()) -> env().
|
||||
typedef_to_fcode(Env, {id, _, Name}, Xs, Def) ->
|
||||
Q = qname(Env, Name),
|
||||
FDef = fun(Args) when length(Args) == length(Xs) ->
|
||||
@ -525,11 +518,11 @@ compute_state_layout(R, [H | T]) ->
|
||||
compute_state_layout(R, _) ->
|
||||
{R + 1, {reg, R}}.
|
||||
|
||||
-spec type_to_fcode(env(), aeso_syntax:type()) -> ftype().
|
||||
-spec type_to_fcode(env(), so_syntax:type()) -> ftype().
|
||||
type_to_fcode(Env, Type) ->
|
||||
type_to_fcode(Env, #{}, Type).
|
||||
|
||||
-spec type_to_fcode(env(), #{var_name() => ftype()}, aeso_syntax:type()) -> ftype().
|
||||
-spec type_to_fcode(env(), #{var_name() => ftype()}, so_syntax:type()) -> ftype().
|
||||
type_to_fcode(_Env, _Sub, {con, _, _}) -> contract;
|
||||
type_to_fcode(Env, Sub, {app_t, _, T = {Id, _, _}, Types}) when Id == id; Id == qid ->
|
||||
lookup_type(Env, T, [type_to_fcode(Env, Sub, Type) || Type <- Types]);
|
||||
@ -555,7 +548,7 @@ type_to_fcode(Env, Sub, {if_t, _, _, _, Else}) ->
|
||||
type_to_fcode(_Env, _Sub, Type) ->
|
||||
error({todo, Type}).
|
||||
|
||||
-spec args_to_fcode(env(), [aeso_syntax:pat()]) -> [{var_name(), ftype()}].
|
||||
-spec args_to_fcode(env(), [so_syntax:pat()]) -> [{var_name(), ftype()}].
|
||||
args_to_fcode(Env, Args) ->
|
||||
[ case Arg of
|
||||
{id, _, Name} -> {Name, type_to_fcode(Env, Type)};
|
||||
@ -586,13 +579,13 @@ let_bind(Binds, Body) ->
|
||||
lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end,
|
||||
Body, Binds).
|
||||
|
||||
-spec expr_to_fcode(env(), aeso_syntax:expr()) -> fexpr().
|
||||
-spec expr_to_fcode(env(), so_syntax:expr()) -> fexpr().
|
||||
expr_to_fcode(Env, {typed, _, Expr, Type}) ->
|
||||
expr_to_fcode(Env, Type, Expr);
|
||||
expr_to_fcode(Env, Expr) ->
|
||||
expr_to_fcode(Env, no_type, Expr).
|
||||
|
||||
-spec expr_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:expr()) -> fexpr().
|
||||
-spec expr_to_fcode(env(), so_syntax:type() | no_type, so_syntax:expr()) -> fexpr().
|
||||
|
||||
%% Literals
|
||||
expr_to_fcode(_Env, _Type, {int, Ann, N}) -> {lit, to_fann(Ann), {int, N}};
|
||||
@ -602,25 +595,12 @@ expr_to_fcode(_Env, _Type, {string, Ann, S}) -> {lit, to_fann(Ann), {st
|
||||
expr_to_fcode(_Env, _Type, {account_pubkey, Ann, K}) -> {lit, to_fann(Ann), {account_pubkey, K}};
|
||||
expr_to_fcode(_Env, _Type, {signature, Ann, K}) -> {lit, to_fann(Ann), {signature, K}};
|
||||
expr_to_fcode(_Env, _Type, {contract_pubkey, Ann, K}) -> {lit, to_fann(Ann), {contract_pubkey, K}};
|
||||
expr_to_fcode(_Env, _Type, {oracle_pubkey, Ann, K}) -> {lit, to_fann(Ann), {oracle_pubkey, K}};
|
||||
expr_to_fcode(_Env, _Type, {oracle_query_id, Ann, K}) -> {lit, to_fann(Ann), {oracle_query_id, K}};
|
||||
expr_to_fcode(_Env, _Type, {bytes, Ann, B}) -> {lit, to_fann(Ann), {bytes, B}};
|
||||
|
||||
%% Variables
|
||||
expr_to_fcode(Env, _Type, {id, Ann, X}) -> resolve_var(Env, Ann, [X]);
|
||||
expr_to_fcode(Env, Type, {qid, Ann, X}) ->
|
||||
case resolve_var(Env, Ann, X) of
|
||||
{builtin_u, FAnn, B, Ar} when B =:= oracle_query;
|
||||
B =:= oracle_get_question;
|
||||
B =:= oracle_get_answer;
|
||||
B =:= oracle_respond;
|
||||
B =:= oracle_register;
|
||||
B =:= oracle_check;
|
||||
B =:= oracle_check_query ->
|
||||
OType = get_oracle_type(B, Type),
|
||||
{oracle, QType, RType} = type_to_fcode(Env, OType),
|
||||
TypeArgs = [{lit, FAnn, {typerep, QType}}, {lit, FAnn, {typerep, RType}}],
|
||||
{builtin_u, FAnn, B, Ar, TypeArgs};
|
||||
{builtin_u, FAnn, B = aens_resolve, Ar} ->
|
||||
{fun_t, _, _, _, ResType} = Type,
|
||||
AensType = type_to_fcode(Env, ResType),
|
||||
@ -705,7 +685,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) ->
|
||||
|
||||
%% Lists
|
||||
expr_to_fcode(Env, _Type, {list, Ann, Es}) ->
|
||||
lists:foldr(fun(E, L) -> {op, to_fann(aeso_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end,
|
||||
lists:foldr(fun(E, L) -> {op, to_fann(so_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end,
|
||||
{nil, to_fann(Ann)}, Es);
|
||||
|
||||
expr_to_fcode(Env, _Type, {app, As, {'..', _}, [A, B]}) ->
|
||||
@ -783,15 +763,15 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A
|
||||
var_args -> fcode_error({var_args_not_set, FunE});
|
||||
_ ->
|
||||
%% Here we little cheat on the typechecker, but this inconsistency
|
||||
%% is to be solved in `aeso_fcode_to_fate:type_to_scode/1`
|
||||
FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]),
|
||||
%% is to be solved in `so_fcode_to_fate:type_to_scode/1`
|
||||
FInitArgsT = gmb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]),
|
||||
builtin_to_fcode(state_layout(Env), FAnn, chain_clone, [{lit, FAnn, FInitArgsT}|FArgs])
|
||||
end;
|
||||
{builtin_u, FAnn, chain_create, _Ar} ->
|
||||
case {ArgsT, Type} of
|
||||
{var_args, _} -> fcode_error({var_args_not_set, FunE});
|
||||
{_, {con, _, Contract}} ->
|
||||
FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]),
|
||||
FInitArgsT = gmb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]),
|
||||
builtin_to_fcode(state_layout(Env), FAnn, chain_create, [{lit, FAnn, {contract_code, Contract}}, {lit, FAnn, FInitArgsT}|FArgs]);
|
||||
{_, _} -> fcode_error({not_a_contract_type, Type})
|
||||
end;
|
||||
@ -884,21 +864,10 @@ make_tuple_fpat(Ps) -> {tuple, Ps}.
|
||||
strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T);
|
||||
strip_singleton_tuples(T) -> T.
|
||||
|
||||
-spec get_oracle_type(OracleFun, FunT) -> OracleType when
|
||||
OracleFun :: atom(),
|
||||
FunT :: aeso_syntax:type(),
|
||||
OracleType :: aeso_syntax:type().
|
||||
get_oracle_type(oracle_register, {fun_t, _, _, _, OType}) -> OType;
|
||||
get_oracle_type(oracle_query, {fun_t, _, _, [OType | _], _}) -> OType;
|
||||
get_oracle_type(oracle_get_question, {fun_t, _, _, [OType | _], _}) -> OType;
|
||||
get_oracle_type(oracle_get_answer, {fun_t, _, _, [OType | _], _}) -> OType;
|
||||
get_oracle_type(oracle_check, {fun_t, _, _, [OType | _], _}) -> OType;
|
||||
get_oracle_type(oracle_check_query, {fun_t, _, _, [OType | _], _}) -> OType;
|
||||
get_oracle_type(oracle_respond, {fun_t, _, _, [OType | _], _}) -> OType.
|
||||
|
||||
%% -- Pattern matching --
|
||||
|
||||
-spec alts_to_fcode(env(), ftype(), var_name(), [aeso_syntax:alt()], aeso_syntax:expr()) -> fsplit().
|
||||
-spec alts_to_fcode(env(), ftype(), var_name(), [so_syntax:alt()], so_syntax:expr()) -> fsplit().
|
||||
alts_to_fcode(Env, Type, X, Alts, Switch) ->
|
||||
FAlts = remove_guards(Env, Alts, Switch),
|
||||
split_tree(Env, [{X, Type}], FAlts).
|
||||
@ -915,7 +884,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) ->
|
||||
| {con, arities(), tag(), [fpat()]}
|
||||
| {assign, fpat(), fpat()}.
|
||||
|
||||
-spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()].
|
||||
-spec remove_guards(env(), [so_syntax:alt()], so_syntax:expr()) -> [falt()].
|
||||
remove_guards(_Env, [], _Switch) ->
|
||||
[];
|
||||
remove_guards(Env, [Alt = {'case', _, _, [{guarded, _, [], _Expr}]} | Rest], Switch) ->
|
||||
@ -1080,19 +1049,19 @@ next_split(Pats) ->
|
||||
[I | _] -> I
|
||||
end.
|
||||
|
||||
-spec alt_to_fcode(env(), aeso_syntax:alt()) -> falt().
|
||||
-spec alt_to_fcode(env(), so_syntax:alt()) -> falt().
|
||||
alt_to_fcode(Env, {'case', _, Pat, [{guarded, _, [], Expr}]}) ->
|
||||
FPat = pat_to_fcode(Env, Pat),
|
||||
FExpr = expr_to_fcode(bind_vars(Env, pat_vars(FPat)), Expr),
|
||||
{'case', [FPat], FExpr}.
|
||||
|
||||
-spec pat_to_fcode(env(), aeso_syntax:pat()) -> fpat().
|
||||
-spec pat_to_fcode(env(), so_syntax:pat()) -> fpat().
|
||||
pat_to_fcode(Env, {typed, _, Pat, Type}) ->
|
||||
pat_to_fcode(Env, Type, Pat);
|
||||
pat_to_fcode(Env, Pat) ->
|
||||
pat_to_fcode(Env, no_type, Pat).
|
||||
|
||||
-spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat().
|
||||
-spec pat_to_fcode(env(), so_syntax:type() | no_type, so_syntax:pat()) -> fpat().
|
||||
pat_to_fcode(_Env, _Type, {id, _, X}) -> {var, X};
|
||||
pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon ->
|
||||
#con_tag{tag = I, arities = As} = lookup_con(Env, Con),
|
||||
@ -1134,7 +1103,7 @@ pat_to_fcode(_Env, Type, Pat) ->
|
||||
| {atom, fexpr()}
|
||||
| {'if', fexpr(), decision_tree(), decision_tree()}.
|
||||
|
||||
-spec decision_op(aeso_syntax:op(), decision_tree(), decision_tree()) -> decision_tree().
|
||||
-spec decision_op(so_syntax:op(), decision_tree(), decision_tree()) -> decision_tree().
|
||||
decision_op('&&', {atom, A}, B) -> {'if', A, B, false};
|
||||
decision_op('&&', false, _) -> false;
|
||||
decision_op('&&', true, B) -> B;
|
||||
@ -1144,7 +1113,7 @@ decision_op('||', true, _) -> true;
|
||||
decision_op(Op, {'if', A, Then, Else}, B) ->
|
||||
{'if', A, decision_op(Op, Then, B), decision_op(Op, Else, B)}.
|
||||
|
||||
-spec expr_to_decision_tree(env(), aeso_syntax:expr()) -> decision_tree().
|
||||
-spec expr_to_decision_tree(env(), so_syntax:expr()) -> decision_tree().
|
||||
expr_to_decision_tree(Env, {app, _Ann, {Op, _}, [A, B]}) when Op == '&&'; Op == '||' ->
|
||||
decision_op(Op, expr_to_decision_tree(Env, A), expr_to_decision_tree(Env, B));
|
||||
expr_to_decision_tree(Env, {typed, _, Expr, _}) -> expr_to_decision_tree(Env, Expr);
|
||||
@ -1163,7 +1132,7 @@ decision_tree_to_fcode({'if', A, Then, Else}) ->
|
||||
|
||||
%% -- Statements --
|
||||
|
||||
-spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr().
|
||||
-spec stmts_to_fcode(env(), [so_syntax:stmt()]) -> fexpr().
|
||||
stmts_to_fcode(Env, [{letval, Ann, {typed, _, {id, _, X}, _}, Expr} | Stmts]) ->
|
||||
{'let', to_fann(Ann), X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)};
|
||||
stmts_to_fcode(Env, [{letval, Ann, Pat, Expr} | Stmts]) ->
|
||||
@ -1178,7 +1147,7 @@ stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Ex
|
||||
stmts_to_fcode(Env, [Expr]) ->
|
||||
expr_to_fcode(Env, Expr);
|
||||
stmts_to_fcode(Env, [Expr | Stmts]) ->
|
||||
{'let', to_fann(aeso_syntax:get_ann(Expr)), "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}.
|
||||
{'let', to_fann(so_syntax:get_ann(Expr)), "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}.
|
||||
|
||||
%% -- Builtins --
|
||||
|
||||
@ -1810,7 +1779,7 @@ used_functions(Used, [Name | Rest], Defs) ->
|
||||
|
||||
%% -- Types --
|
||||
|
||||
-spec lookup_type(env(), aeso_syntax:id() | aeso_syntax:qid() | sophia_name(), [ftype()]) -> ftype().
|
||||
-spec lookup_type(env(), so_syntax:id() | so_syntax:qid() | sophia_name(), [ftype()]) -> ftype().
|
||||
lookup_type(Env, {id, _, Name}, Args) ->
|
||||
lookup_type(Env, [Name], Args);
|
||||
lookup_type(Env, {qid, _, Name}, Args) ->
|
||||
@ -1842,7 +1811,7 @@ bind_constructors(Env = #{ con_env := ConEnv }, NewCons) ->
|
||||
add_child_con(Env = #{child_con_env := CEnv}, Name, Fcode) ->
|
||||
Env#{ child_con_env := CEnv#{Name => Fcode} }.
|
||||
|
||||
-spec add_fun_env(env(), [aeso_syntax:decl()]) -> env().
|
||||
-spec add_fun_env(env(), [so_syntax:decl()]) -> env().
|
||||
add_fun_env(Env = #{ context := {abstract_contract, _} }, _) -> Env; %% no functions from abstract contracts
|
||||
add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
||||
Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) ->
|
||||
@ -1853,7 +1822,7 @@ add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
||||
FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)),
|
||||
Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }.
|
||||
|
||||
-spec make_fun_name(env(), aeso_syntax:ann(), aeso_syntax:name()) -> fun_name().
|
||||
-spec make_fun_name(env(), so_syntax:ann(), so_syntax:name()) -> fun_name().
|
||||
make_fun_name(#{ context := Context }, Ann, Name) ->
|
||||
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
||||
case Context of
|
||||
@ -1884,7 +1853,7 @@ lookup_fun(#{ fun_env := FunEnv }, Name) ->
|
||||
{FName, _} -> FName
|
||||
end.
|
||||
|
||||
-spec lookup_con(env(), aeso_syntax:con() | aeso_syntax:qcon() | sophia_name()) -> con_tag().
|
||||
-spec lookup_con(env(), so_syntax:con() | so_syntax:qcon() | sophia_name()) -> con_tag().
|
||||
lookup_con(Env, {con, _, Con}) -> lookup_con(Env, [Con]);
|
||||
lookup_con(Env, {qcon, _, Con}) -> lookup_con(Env, Con);
|
||||
lookup_con(#{ con_env := ConEnv }, Con) ->
|
||||
@ -1900,7 +1869,7 @@ bind_vars(Env, Xs) ->
|
||||
-spec bind_var(env(), var_name()) -> env().
|
||||
bind_var(Env = #{ vars := Vars }, X) -> Env#{ vars := [X | Vars] }.
|
||||
|
||||
-spec resolve_var(env(), aeso_syntax:ann(), [aeso_syntax:name()]) -> fexpr().
|
||||
-spec resolve_var(env(), so_syntax:ann(), [so_syntax:name()]) -> fexpr().
|
||||
resolve_var(#{ vars := Vars } = Env, Ann, [X]) ->
|
||||
case lists:member(X, Vars) of
|
||||
true -> {var, to_fann(Ann), X};
|
||||
@ -1922,7 +1891,7 @@ resolve_const(#{ consts := Consts }, Q) ->
|
||||
Val -> Val
|
||||
end.
|
||||
|
||||
-spec resolve_fun(env(), aeso_syntax:ann(), [aeso_syntax:name()]) -> fexpr().
|
||||
-spec resolve_fun(env(), so_syntax:ann(), [so_syntax:name()]) -> fexpr().
|
||||
resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Ann, Q) ->
|
||||
case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of
|
||||
{not_found, not_found} -> internal_error({unbound_variable, Q});
|
||||
@ -2102,7 +2071,7 @@ bottom_up(F, Env, Expr) ->
|
||||
{'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)}
|
||||
end).
|
||||
|
||||
-spec get_named_args([aeso_syntax:named_arg_t()], [aeso_syntax:arg_expr()]) -> [aeso_syntax:expr()].
|
||||
-spec get_named_args([so_syntax:named_arg_t()], [so_syntax:arg_expr()]) -> [so_syntax:expr()].
|
||||
get_named_args(NamedArgsT, Args) ->
|
||||
IsNamed = fun({named_arg, _, _, _}) -> true;
|
||||
(_) -> false end,
|
||||
@ -2110,7 +2079,7 @@ get_named_args(NamedArgsT, Args) ->
|
||||
NamedArgs = [get_named_arg(NamedArg, Named) || NamedArg <- NamedArgsT],
|
||||
NamedArgs ++ NotNamed.
|
||||
|
||||
-spec get_named_arg(aeso_syntax:named_arg_t(), [aeso_syntax:arg_expr()]) -> aeso_syntax:expr().
|
||||
-spec get_named_arg(so_syntax:named_arg_t(), [so_syntax:arg_expr()]) -> so_syntax:expr().
|
||||
get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) ->
|
||||
case [ Val || {named_arg, _, {id, _, X}, Val} <- Args, X == Name ] of
|
||||
[Val] -> Val;
|
||||
@ -2236,15 +2205,15 @@ update_rename(OldRen, NewRen) ->
|
||||
|
||||
%% -- Records --
|
||||
|
||||
-spec field_index(aeso_syntax:typedef(), aeso_syntax:name()) -> integer().
|
||||
-spec field_index(so_syntax:typedef(), so_syntax:name()) -> integer().
|
||||
field_index({record_t, Fields}, X) ->
|
||||
IsX = fun({field_t, _, {id, _, Y}, _}) -> X == Y end,
|
||||
[I] = [ I || {I, Field} <- indexed(Fields), IsX(Field) ],
|
||||
I - 1. %% Tuples are 0-indexed
|
||||
|
||||
-spec field_value(aeso_syntax:field_t(), [aeso_syntax:field(aeso_syntax:pat())]) -> Res when
|
||||
Res :: {upd, aeso_syntax:name(), Expr} | {set, Expr} | false,
|
||||
Expr :: aeso_syntax:expr().
|
||||
-spec field_value(so_syntax:field_t(), [so_syntax:field(so_syntax:pat())]) -> Res when
|
||||
Res :: {upd, so_syntax:name(), Expr} | {set, Expr} | false,
|
||||
Expr :: so_syntax:expr().
|
||||
field_value({field_t, _, {id, _, X}, _}, Fields) ->
|
||||
View = fun({field, _, [{proj, _, {id, _, Y}}], E}) -> {Y, {set, E}};
|
||||
({field_upd, _, [{proj, _, {id, _, Y}}],
|
||||
@ -2256,13 +2225,13 @@ field_value({field_t, _, {id, _, X}, _}, Fields) ->
|
||||
|
||||
%% -- Attributes --
|
||||
|
||||
-spec get_attributes(aeso_syntax:ann()) -> [stateful | payable | private].
|
||||
-spec get_attributes(so_syntax:ann()) -> [stateful | payable | private].
|
||||
get_attributes(Ann) ->
|
||||
[stateful || proplists:get_value(stateful, Ann, false)] ++
|
||||
[payable || proplists:get_value(payable, Ann, false)] ++
|
||||
[private || not proplists:get_value(entrypoint, Ann, false)].
|
||||
|
||||
-spec get_attributes_debug(aeso_syntax:ann()) -> [stateful | payable | private | fann()].
|
||||
-spec get_attributes_debug(so_syntax:ann()) -> [stateful | payable | private | fann()].
|
||||
get_attributes_debug(Ann) ->
|
||||
get_attributes(Ann) ++ to_fann(Ann).
|
||||
|
||||
@ -2283,14 +2252,14 @@ setnth(I, X, Xs) ->
|
||||
|
||||
-spec fcode_error(string()) -> no_return().
|
||||
fcode_error(Error) ->
|
||||
Pos = aeso_errors:pos(0, 0),
|
||||
Pos = so_errors:pos(0, 0),
|
||||
Msg = lists:flatten(io_lib:format("Unknown error: ~p\n", [Error])),
|
||||
aeso_errors:throw(aeso_errors:new(code_error, Pos, Msg)).
|
||||
so_errors:throw(so_errors:new(code_error, Pos, Msg)).
|
||||
|
||||
-spec internal_error(string()) -> no_return().
|
||||
internal_error(Error) ->
|
||||
Msg = lists:flatten(io_lib:format("~p\n", [Error])),
|
||||
aeso_errors:throw(aeso_errors:new(internal_error, aeso_errors:pos(0, 0), Msg)).
|
||||
so_errors:throw(so_errors:new(internal_error, so_errors:pos(0, 0), Msg)).
|
||||
|
||||
%% -- Pretty printing --------------------------------------------------------
|
||||
|
||||
@ -2367,7 +2336,7 @@ pp_fexpr({lit, _, {typerep, T}}) ->
|
||||
pp_fexpr({lit, _, {contract_code, Contract}}) ->
|
||||
pp_beside(pp_text("contract "), pp_text(Contract));
|
||||
pp_fexpr({lit, _, {Tag, Lit}}) ->
|
||||
aeso_pretty:expr({Tag, [], Lit});
|
||||
so_pretty:expr({Tag, [], Lit});
|
||||
pp_fexpr({nil, _}) ->
|
||||
pp_text("[]");
|
||||
pp_fexpr({var, _, X}) -> pp_text(X);
|
||||
@ -2451,7 +2420,6 @@ pp_ftype(T) when is_atom(T) -> pp_text(T);
|
||||
pp_ftype(any) -> pp_text("_");
|
||||
pp_ftype({tvar, X}) -> pp_text(X);
|
||||
pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, [], {int, N}}]);
|
||||
pp_ftype({oracle, Q, R}) -> pp_call_t("oracle", [Q, R]);
|
||||
pp_ftype({tuple, Ts}) ->
|
||||
pp_parens(pp_par(pp_punctuate(pp_text(" *"), [pp_ftype(T) || T <- Ts])));
|
||||
pp_ftype({list, T}) ->
|
@ -1,12 +1,12 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Happi (Erik Stenman)
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Compiler from Aeterinty Sophia language to FATE.
|
||||
%%% Compiler from Sophia language to FATE.
|
||||
%%% @end
|
||||
%%% Created : 12 Dec 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_compiler).
|
||||
-module(so_compiler).
|
||||
|
||||
-export([ file/1
|
||||
, file/2
|
||||
@ -27,8 +27,8 @@
|
||||
, validate_byte_code/3
|
||||
]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||
-include("aeso_utils.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||
-include("so_utils.hrl").
|
||||
|
||||
|
||||
-type option() :: pp_sophia_code
|
||||
@ -43,7 +43,7 @@
|
||||
{explicit_files, #{string() => binary()}}}
|
||||
| {src_file, string()}
|
||||
| {src_dir, string()}
|
||||
| {aci, aeso_aci:aci_type()}.
|
||||
| {aci, so_aci:aci_type()}.
|
||||
-type options() :: [option()].
|
||||
|
||||
-export_type([ option/0
|
||||
@ -52,15 +52,15 @@
|
||||
|
||||
-spec version() -> {ok, binary()} | {error, term()}.
|
||||
version() ->
|
||||
case lists:keyfind(aesophia, 1, application:loaded_applications()) of
|
||||
case lists:keyfind(sophia, 1, application:loaded_applications()) of
|
||||
false ->
|
||||
case application:load(aesophia) of
|
||||
case application:load(sophia) of
|
||||
ok ->
|
||||
case application:get_key(aesophia, vsn) of
|
||||
case application:get_key(sophia, vsn) of
|
||||
{ok, VsnString} ->
|
||||
{ok, list_to_binary(VsnString)};
|
||||
undefined ->
|
||||
{error, failed_to_load_aesophia}
|
||||
{error, failed_to_load_sophia}
|
||||
end;
|
||||
Err = {error, _} ->
|
||||
Err
|
||||
@ -80,20 +80,20 @@ numeric_version() ->
|
||||
Err
|
||||
end.
|
||||
|
||||
-spec file(string()) -> {ok, map()} | {error, [aeso_errors:error()]}.
|
||||
-spec file(string()) -> {ok, map()} | {error, [so_errors:error()]}.
|
||||
file(Filename) ->
|
||||
file(Filename, []).
|
||||
|
||||
-spec file(string(), options()) -> {ok, map()} | {error, [aeso_errors:error()]}.
|
||||
-spec file(string(), options()) -> {ok, map()} | {error, [so_errors:error()]}.
|
||||
file(File, Options0) ->
|
||||
Options = add_include_path(File, Options0),
|
||||
case read_contract(File) of
|
||||
{ok, Bin} ->
|
||||
SrcDir = aeso_utils:canonical_dir(filename:dirname(File)),
|
||||
SrcDir = so_utils:canonical_dir(filename:dirname(File)),
|
||||
from_string(Bin, [{src_file, File}, {src_dir, SrcDir} | Options]);
|
||||
{error, Error} ->
|
||||
Msg = lists:flatten([File,": ",file:format_error(Error)]),
|
||||
{error, [aeso_errors:new(file_error, Msg)]}
|
||||
{error, [so_errors:new(file_error, Msg)]}
|
||||
end.
|
||||
|
||||
add_include_path(File, Options) ->
|
||||
@ -102,10 +102,10 @@ add_include_path(File, Options) ->
|
||||
false ->
|
||||
Dir = filename:dirname(File),
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
[{include, {file_system, [Cwd, aeso_utils:canonical_dir(Dir)]}} | Options]
|
||||
[{include, {file_system, [Cwd, so_utils:canonical_dir(Dir)]}} | Options]
|
||||
end.
|
||||
|
||||
-spec from_string(binary() | string(), options()) -> {ok, map()} | {error, [aeso_errors:error()]}.
|
||||
-spec from_string(binary() | string(), options()) -> {ok, map()} | {error, [so_errors:error()]}.
|
||||
from_string(ContractBin, Options) when is_binary(ContractBin) ->
|
||||
from_string(binary_to_list(ContractBin), Options);
|
||||
from_string(ContractString, Options) ->
|
||||
@ -122,16 +122,16 @@ from_string1(ContractString, Options) ->
|
||||
, warnings := Warnings } = string_to_code(ContractString, Options),
|
||||
#{ child_con_env := ChildContracts } = FCodeEnv,
|
||||
SavedFreshNames = maps:get(saved_fresh_names, FCodeEnv, #{}),
|
||||
FateCode = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options),
|
||||
FateCode = so_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options),
|
||||
pp_assembler(FateCode, Options),
|
||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
||||
ByteCode = gmb_fate_code:serialize(FateCode, []),
|
||||
{ok, Version} = version(),
|
||||
Res = #{byte_code => ByteCode,
|
||||
compiler_version => Version,
|
||||
contract_source => ContractString,
|
||||
type_info => [],
|
||||
fate_code => FateCode,
|
||||
abi_version => aeb_fate_abi:abi_version(),
|
||||
abi_version => gmb_fate_abi:abi_version(),
|
||||
payable => maps:get(payable, FCode),
|
||||
warnings => Warnings
|
||||
},
|
||||
@ -142,7 +142,7 @@ maybe_generate_aci(Result, FoldedTypedAst, Options) ->
|
||||
undefined ->
|
||||
Result;
|
||||
Type ->
|
||||
{ok, Aci} = aeso_aci:from_typed_ast(Type, FoldedTypedAst),
|
||||
{ok, Aci} = so_aci:from_typed_ast(Type, FoldedTypedAst),
|
||||
maps:put(aci, Aci, Result)
|
||||
end.
|
||||
|
||||
@ -151,9 +151,9 @@ string_to_code(ContractString, Options) ->
|
||||
Ast = parse(ContractString, Options),
|
||||
pp_sophia_code(Ast, Options),
|
||||
pp_ast(Ast, Options),
|
||||
{TypeEnv, FoldedTypedAst, UnfoldedTypedAst, Warnings} = aeso_ast_infer_types:infer(Ast, [return_env | Options]),
|
||||
{TypeEnv, FoldedTypedAst, UnfoldedTypedAst, Warnings} = so_ast_infer_types:infer(Ast, [return_env | Options]),
|
||||
pp_typed_ast(UnfoldedTypedAst, Options),
|
||||
{Env, Fcode} = aeso_ast_to_fcode:ast_to_fcode(UnfoldedTypedAst, [{original_src, ContractString}|Options]),
|
||||
{Env, Fcode} = so_ast_to_fcode:ast_to_fcode(UnfoldedTypedAst, [{original_src, ContractString}|Options]),
|
||||
#{ fcode => Fcode
|
||||
, fcode_env => Env
|
||||
, unfolded_typed_ast => UnfoldedTypedAst
|
||||
@ -171,7 +171,7 @@ string_to_code(ContractString, Options) ->
|
||||
%% NOTE: Special treatment for "init" since it might be implicit and has
|
||||
%% a special return type (typerep, T)
|
||||
-spec check_call(string(), string(), [string()], options()) -> {ok, string(), [term()]}
|
||||
| {error, [aeso_errors:error()]}.
|
||||
| {error, [so_errors:error()]}.
|
||||
check_call(Source, "init" = FunName, Args, Options) ->
|
||||
case check_call1(Source, FunName, Args, Options) of
|
||||
Err = {error, _} when Args == [] ->
|
||||
@ -190,7 +190,7 @@ check_call1(ContractString0, FunName, Args, Options) ->
|
||||
case add_extra_call(ContractString0, {call, FunName, Args}, Options) of
|
||||
{ok, CallName, Code} ->
|
||||
{def, _, _, FcodeArgs} = get_call_body(CallName, Code),
|
||||
{ok, FunName, [ aeso_fcode_to_fate:term_to_fate(A) || A <- FcodeArgs ]};
|
||||
{ok, FunName, [ so_fcode_to_fate:term_to_fate(A) || A <- FcodeArgs ]};
|
||||
Err = {error, _} ->
|
||||
Err
|
||||
end.
|
||||
@ -201,9 +201,9 @@ add_extra_call(Contract0, Call, Options) ->
|
||||
#{fcode := OrgFcode
|
||||
, fcode_env := #{child_con_env := ChildContracts}
|
||||
, ast := Ast} = string_to_code(Contract0, Options),
|
||||
FateCode = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []),
|
||||
FateCode = so_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []),
|
||||
%% collect all hashes and compute the first name without hash collision to
|
||||
SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)),
|
||||
SymbolHashes = maps:keys(gmb_fate_code:symbols(FateCode)),
|
||||
CallName = first_none_match(?CALL_NAME, SymbolHashes,
|
||||
lists:seq($1, $9) ++ lists:seq($A, $Z) ++ lists:seq($a, $z)),
|
||||
Contract = insert_call_function(Ast, Contract0, CallName, Call),
|
||||
@ -220,7 +220,7 @@ encode_value(Contract0, Type, Value, Options) ->
|
||||
case add_extra_call(Contract0, {value, Type, Value}, Options) of
|
||||
{ok, CallName, Code} ->
|
||||
Body = get_call_body(CallName, Code),
|
||||
{ok, aeb_fate_encoding:serialize(aeso_fcode_to_fate:term_to_fate(Body))};
|
||||
{ok, gmb_fate_encoding:serialize(so_fcode_to_fate:term_to_fate(Body))};
|
||||
Err = {error, _} ->
|
||||
Err
|
||||
end.
|
||||
@ -231,7 +231,7 @@ decode_value(Contract0, Type, FateValue, Options) ->
|
||||
#{ folded_typed_ast := TypedAst
|
||||
, type_env := TypeEnv} = Code,
|
||||
{ok, _, Type0} = get_decode_type(CallName, TypedAst),
|
||||
Type1 = aeso_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
Type1 = so_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
[ unfold_record_types
|
||||
, unfold_variant_types
|
||||
, not_unfold_system_alias_types ]),
|
||||
@ -243,7 +243,7 @@ decode_value(Contract0, Type, FateValue, Options) ->
|
||||
first_none_match(_CallName, _Hashes, []) ->
|
||||
error(unable_to_find_unique_call_name);
|
||||
first_none_match(CallName, Hashes, [Char|Chars]) ->
|
||||
case not lists:member(aeb_fate_code:symbol_identifier(list_to_binary(CallName)), Hashes) of
|
||||
case not lists:member(gmb_fate_code:symbol_identifier(list_to_binary(CallName)), Hashes) of
|
||||
true ->
|
||||
CallName;
|
||||
false ->
|
||||
@ -251,7 +251,7 @@ first_none_match(CallName, Hashes, [Char|Chars]) ->
|
||||
end.
|
||||
|
||||
%% Add the __call function to a contract.
|
||||
-spec insert_call_function(aeso_syntax:ast(), string(), string(),
|
||||
-spec insert_call_function(so_syntax:ast(), string(), string(),
|
||||
{call, string(), [string()]} | {value, string(), string()} | {type, string()}) -> string().
|
||||
insert_call_function(Ast, Code, Call, {call, FunName, Args}) ->
|
||||
Ind = last_contract_indent(Ast),
|
||||
@ -290,25 +290,25 @@ insert_init_function(Code, Options) ->
|
||||
|
||||
last_contract_indent(Decls) ->
|
||||
case lists:last(Decls) of
|
||||
{_, _, _, _, [Decl | _]} -> aeso_syntax:get_ann(col, Decl, 1) - 1;
|
||||
{_, _, _, _, [Decl | _]} -> so_syntax:get_ann(col, Decl, 1) - 1;
|
||||
_ -> 0
|
||||
end.
|
||||
|
||||
-spec to_sophia_value(string(), string(), ok | error | revert, binary()) ->
|
||||
{ok, aeso_syntax:expr()} | {error, [aeso_errors:error()]}.
|
||||
{ok, so_syntax:expr()} | {error, [so_errors:error()]}.
|
||||
to_sophia_value(ContractString, Fun, ResType, Data) ->
|
||||
to_sophia_value(ContractString, Fun, ResType, Data, []).
|
||||
-spec to_sophia_value(string(), string(), ok | error | revert, binary(), options()) ->
|
||||
{ok, aeso_syntax:expr()} | {error, [aeso_errors:error()]}.
|
||||
{ok, so_syntax:expr()} | {error, [so_errors:error()]}.
|
||||
to_sophia_value(_, _, error, Err, _Options) ->
|
||||
{ok, {app, [], {id, [], "error"}, [{string, [], Err}]}};
|
||||
to_sophia_value(_, _, revert, Data, _Options) ->
|
||||
try aeso_vm_decode:from_fate({id, [], "string"}, aeb_fate_encoding:deserialize(Data)) of
|
||||
try so_vm_decode:from_fate({id, [], "string"}, gmb_fate_encoding:deserialize(Data)) of
|
||||
Err ->
|
||||
{ok, {app, [], {id, [], "abort"}, [Err]}}
|
||||
catch _:_ ->
|
||||
Msg = "Could not deserialize the revert message",
|
||||
{error, [aeso_errors:new(data_error, Msg)]}
|
||||
{error, [so_errors:new(data_error, Msg)]}
|
||||
end;
|
||||
to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
||||
Options = [no_code | Options0],
|
||||
@ -316,7 +316,7 @@ to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
||||
Code = string_to_code(ContractString, Options),
|
||||
#{ folded_typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
||||
{ok, _, Type0} = get_decode_type(FunName, TypedAst),
|
||||
Type = aeso_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
Type = so_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
[ unfold_record_types
|
||||
, unfold_variant_types
|
||||
, not_unfold_system_alias_types]),
|
||||
@ -328,40 +328,40 @@ to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
||||
|
||||
fate_data_to_sophia_value(Type, UnfoldedType, FateData) ->
|
||||
try
|
||||
{ok, aeso_vm_decode:from_fate(UnfoldedType, aeb_fate_encoding:deserialize(FateData))}
|
||||
{ok, so_vm_decode:from_fate(UnfoldedType, gmb_fate_encoding:deserialize(FateData))}
|
||||
catch throw:cannot_translate_to_sophia ->
|
||||
Type1 = prettypr:format(aeso_pretty:type(Type)),
|
||||
Type1 = prettypr:format(so_pretty:type(Type)),
|
||||
Msg = io_lib:format("Cannot translate FATE value ~p\n of Sophia type ~s",
|
||||
[aeb_fate_encoding:deserialize(FateData), Type1]),
|
||||
{error, [aeso_errors:new(data_error, Msg)]};
|
||||
[gmb_fate_encoding:deserialize(FateData), Type1]),
|
||||
{error, [so_errors:new(data_error, Msg)]};
|
||||
_:_ ->
|
||||
Type1 = prettypr:format(aeso_pretty:type(Type)),
|
||||
Type1 = prettypr:format(so_pretty:type(Type)),
|
||||
Msg = io_lib:format("Failed to decode binary as type ~s", [Type1]),
|
||||
{error, [aeso_errors:new(data_error, Msg)]}
|
||||
{error, [so_errors:new(data_error, Msg)]}
|
||||
end.
|
||||
|
||||
-spec create_calldata(string(), string(), [string()]) ->
|
||||
{ok, binary()} | {error, [aeso_errors:error()]}.
|
||||
{ok, binary()} | {error, [so_errors:error()]}.
|
||||
create_calldata(Code, Fun, Args) ->
|
||||
create_calldata(Code, Fun, Args, []).
|
||||
-spec create_calldata(string(), string(), [string()], [{atom(), any()}]) ->
|
||||
{ok, binary()} | {error, [aeso_errors:error()]}.
|
||||
{ok, binary()} | {error, [so_errors:error()]}.
|
||||
create_calldata(Code, Fun, Args, Options0) ->
|
||||
Options = [no_code | Options0],
|
||||
case check_call(Code, Fun, Args, Options) of
|
||||
{ok, FunName, FateArgs} ->
|
||||
aeb_fate_abi:create_calldata(FunName, FateArgs);
|
||||
gmb_fate_abi:create_calldata(FunName, FateArgs);
|
||||
{error, _} = Err -> Err
|
||||
end.
|
||||
|
||||
-spec decode_calldata(string(), string(), binary()) ->
|
||||
{ok, [aeso_syntax:type()], [aeso_syntax:expr()]}
|
||||
| {error, [aeso_errors:error()]}.
|
||||
{ok, [so_syntax:type()], [so_syntax:expr()]}
|
||||
| {error, [so_errors:error()]}.
|
||||
decode_calldata(ContractString, FunName, Calldata) ->
|
||||
decode_calldata(ContractString, FunName, Calldata, []).
|
||||
-spec decode_calldata(string(), string(), binary(), options()) ->
|
||||
{ok, [aeso_syntax:type()], [aeso_syntax:expr()]}
|
||||
| {error, [aeso_errors:error()]}.
|
||||
{ok, [so_syntax:type()], [so_syntax:expr()]}
|
||||
| {error, [so_errors:error()]}.
|
||||
decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
||||
Options = [no_code | Options0],
|
||||
try
|
||||
@ -373,26 +373,26 @@ decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
||||
ArgTypes = lists:map(GetType, Args),
|
||||
Type0 = {tuple_t, [], ArgTypes},
|
||||
%% user defined data types such as variants needed to match against
|
||||
Type = aeso_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
Type = so_ast_infer_types:unfold_types_in_type(TypeEnv, Type0,
|
||||
[ unfold_record_types
|
||||
, unfold_variant_types
|
||||
, not_unfold_system_alias_types]),
|
||||
case aeb_fate_abi:decode_calldata(FunName, Calldata) of
|
||||
case gmb_fate_abi:decode_calldata(FunName, Calldata) of
|
||||
{ok, FateArgs} ->
|
||||
try
|
||||
{tuple_t, [], ArgTypes1} = Type,
|
||||
AstArgs = [ aeso_vm_decode:from_fate(ArgType, FateArg)
|
||||
AstArgs = [ so_vm_decode:from_fate(ArgType, FateArg)
|
||||
|| {ArgType, FateArg} <- lists:zip(ArgTypes1, FateArgs)],
|
||||
{ok, ArgTypes, AstArgs}
|
||||
catch throw:cannot_translate_to_sophia ->
|
||||
Type0Str = prettypr:format(aeso_pretty:type(Type0)),
|
||||
Type0Str = prettypr:format(so_pretty:type(Type0)),
|
||||
Msg = io_lib:format("Cannot translate FATE value ~p\n to Sophia type ~s",
|
||||
[FateArgs, Type0Str]),
|
||||
{error, [aeso_errors:new(data_error, Msg)]}
|
||||
{error, [so_errors:new(data_error, Msg)]}
|
||||
end;
|
||||
{error, _} ->
|
||||
Msg = io_lib:format("Failed to decode calldata binary", []),
|
||||
{error, [aeso_errors:new(data_error, Msg)]}
|
||||
{error, [so_errors:new(data_error, Msg)]}
|
||||
end
|
||||
catch
|
||||
throw:{error, Errors} -> {error, Errors}
|
||||
@ -410,8 +410,8 @@ get_decode_type(FunName, [{Contract, Ann, _, _, Defs}]) when ?IS_CONTRACT_HEAD(C
|
||||
"init" -> {ok, [], {tuple_t, [], []}};
|
||||
_ ->
|
||||
Msg = io_lib:format("Function '~s' is missing in contract", [FunName]),
|
||||
Pos = aeso_errors:pos(Ann),
|
||||
aeso_errors:throw(aeso_errors:new(data_error, Pos, Msg))
|
||||
Pos = so_errors:pos(Ann),
|
||||
so_errors:throw(so_errors:new(data_error, Pos, Msg))
|
||||
end
|
||||
end;
|
||||
get_decode_type(FunName, [_ | Contracts]) ->
|
||||
@ -419,12 +419,12 @@ get_decode_type(FunName, [_ | Contracts]) ->
|
||||
get_decode_type(FunName, Contracts).
|
||||
|
||||
pp_sophia_code(C, Opts)-> pp(C, Opts, pp_sophia_code, fun(Code) ->
|
||||
io:format("~s\n", [prettypr:format(aeso_pretty:decls(Code))])
|
||||
io:format("~s\n", [prettypr:format(so_pretty:decls(Code))])
|
||||
end).
|
||||
pp_ast(C, Opts) -> pp(C, Opts, pp_ast, fun aeso_ast:pp/1).
|
||||
pp_typed_ast(C, Opts)-> pp(C, Opts, pp_typed_ast, fun aeso_ast:pp_typed/1).
|
||||
pp_ast(C, Opts) -> pp(C, Opts, pp_ast, fun so_ast:pp/1).
|
||||
pp_typed_ast(C, Opts)-> pp(C, Opts, pp_typed_ast, fun so_ast:pp_typed/1).
|
||||
|
||||
pp_assembler(C, Opts) -> pp(C, Opts, pp_assembler, fun(Asm) -> io:format("~s", [aeb_fate_asm:pp(Asm)]) end).
|
||||
pp_assembler(C, Opts) -> pp(C, Opts, pp_assembler, fun(Asm) -> io:format("~s", [gmb_fate_asm:pp(Asm)]) end).
|
||||
|
||||
pp(Code, Options, Option, PPFun) ->
|
||||
case proplists:lookup(Option, Options) of
|
||||
@ -438,18 +438,18 @@ pp(Code, Options, Option, PPFun) ->
|
||||
|
||||
-define(protect(Tag, Code), fun() -> try Code catch _:Err1 -> throw({Tag, Err1}) end end()).
|
||||
|
||||
-spec validate_byte_code(map(), string(), options()) -> ok | {error, [aeso_errors:error()]}.
|
||||
-spec validate_byte_code(map(), string(), options()) -> ok | {error, [so_errors:error()]}.
|
||||
validate_byte_code(#{ byte_code := ByteCode, payable := Payable }, Source, Options) ->
|
||||
Fail = fun(Err) -> {error, [aeso_errors:new(data_error, Err)]} end,
|
||||
Fail = fun(Err) -> {error, [so_errors:new(data_error, Err)]} end,
|
||||
try
|
||||
FCode1 = ?protect(deserialize, aeb_fate_code:strip_init_function(aeb_fate_code:deserialize(ByteCode))),
|
||||
FCode1 = ?protect(deserialize, gmb_fate_code:strip_init_function(gmb_fate_code:deserialize(ByteCode))),
|
||||
{FCode2, SrcPayable} =
|
||||
?protect(compile,
|
||||
begin
|
||||
{ok, #{ byte_code := SrcByteCode, payable := SrcPayable }} =
|
||||
from_string1(Source, Options),
|
||||
FCode = aeb_fate_code:deserialize(SrcByteCode),
|
||||
{aeb_fate_code:strip_init_function(FCode), SrcPayable}
|
||||
FCode = gmb_fate_code:deserialize(SrcByteCode),
|
||||
{gmb_fate_code:strip_init_function(FCode), SrcPayable}
|
||||
end),
|
||||
case compare_fate_code(FCode1, FCode2) of
|
||||
ok when SrcPayable /= Payable ->
|
||||
@ -465,10 +465,10 @@ validate_byte_code(#{ byte_code := ByteCode, payable := Payable }, Source, Optio
|
||||
end.
|
||||
|
||||
compare_fate_code(FCode1, FCode2) ->
|
||||
Funs1 = aeb_fate_code:functions(FCode1),
|
||||
Funs2 = aeb_fate_code:functions(FCode2),
|
||||
Syms1 = aeb_fate_code:symbols(FCode1),
|
||||
Syms2 = aeb_fate_code:symbols(FCode2),
|
||||
Funs1 = gmb_fate_code:functions(FCode1),
|
||||
Funs2 = gmb_fate_code:functions(FCode2),
|
||||
Syms1 = gmb_fate_code:symbols(FCode1),
|
||||
Syms2 = gmb_fate_code:symbols(FCode2),
|
||||
FunHashes1 = maps:keys(Funs1),
|
||||
FunHashes2 = maps:keys(Funs2),
|
||||
case FunHashes1 == FunHashes2 of
|
||||
@ -513,13 +513,13 @@ pp_fate_type(T) -> io_lib:format("~w", [T]).
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
-spec parse(string(), aeso_compiler:options()) -> none() | aeso_syntax:ast().
|
||||
-spec parse(string(), so_compiler:options()) -> none() | so_syntax:ast().
|
||||
parse(Text, Options) ->
|
||||
parse(Text, sets:new(), Options).
|
||||
|
||||
-spec parse(string(), sets:set(), aeso_compiler:options()) -> none() | aeso_syntax:ast().
|
||||
-spec parse(string(), sets:set(), so_compiler:options()) -> none() | so_syntax:ast().
|
||||
parse(Text, Included, Options) ->
|
||||
aeso_parser:string(Text, Included, Options).
|
||||
so_parser:string(Text, Included, Options).
|
||||
|
||||
read_contract(Name) ->
|
||||
file:read_file(Name).
|
@ -1,11 +1,12 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc ADT for structured error messages + formatting.
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_errors).
|
||||
-module(so_errors).
|
||||
|
||||
-type src_file() :: no_file | iolist().
|
||||
|
||||
@ -55,9 +56,9 @@ new(Type, Pos, Msg, Ctxt) ->
|
||||
#err{ type = Type, pos = Pos, message = Msg, context = Ctxt }.
|
||||
|
||||
pos(Ann) ->
|
||||
File = aeso_syntax:get_ann(file, Ann, no_file),
|
||||
Line = aeso_syntax:get_ann(line, Ann, 0),
|
||||
Col = aeso_syntax:get_ann(col, Ann, 0),
|
||||
File = so_syntax:get_ann(file, Ann, no_file),
|
||||
Line = so_syntax:get_ann(line, Ann, 0),
|
||||
Col = so_syntax:get_ann(col, Ann, 0),
|
||||
pos(File, Line, Col).
|
||||
|
||||
pos(Line, Col) ->
|
@ -1,13 +1,12 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Ulf Norell
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Fate backend for Sophia compiler
|
||||
%%% @end
|
||||
%%% Created : 11 Jan 2019
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_fcode_to_fate).
|
||||
-module(so_fcode_to_fate).
|
||||
|
||||
-export([compile/3, compile/4, term_to_fate/1, term_to_fate/2]).
|
||||
|
||||
@ -23,7 +22,7 @@
|
||||
| loop
|
||||
| tuple() | atom(). %% FATE instruction
|
||||
|
||||
-type arg() :: tuple(). %% Not exported: aeb_fate_ops:fate_arg().
|
||||
-type arg() :: tuple(). %% Not exported: gmb_fate_ops:fate_arg().
|
||||
|
||||
%% Annotated scode
|
||||
-type scode_a() :: [sinstr_a()].
|
||||
@ -72,9 +71,9 @@ debug(Tag, Options, Fun) ->
|
||||
|
||||
-dialyzer({nowarn_function, [code_error/1]}).
|
||||
code_error(Err) ->
|
||||
Pos = aeso_errors:pos(0, 0),
|
||||
Pos = so_errors:pos(0, 0),
|
||||
Msg = lists:flatten(io_lib:format("Unknown error: ~p\n", [Err])),
|
||||
aeso_errors:throw(aeso_errors:new(code_error, Pos, Msg)).
|
||||
so_errors:throw(so_errors:new(code_error, Pos, Msg)).
|
||||
|
||||
%% -- Main -------------------------------------------------------------------
|
||||
|
||||
@ -87,14 +86,14 @@ compile(ChildContracts, FCode, SavedFreshNames, Options) ->
|
||||
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options),
|
||||
SFuns1 = optimize_scode(SFuns, Options),
|
||||
FateCode = to_basic_blocks(SFuns1),
|
||||
?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]),
|
||||
?debug(compile, Options, "~s\n", [gmb_fate_asm:pp(FateCode)]),
|
||||
case proplists:get_value(include_child_contract_symbols, Options, false) of
|
||||
false -> FateCode;
|
||||
true -> add_child_symbols(ChildContracts, FateCode)
|
||||
end.
|
||||
|
||||
make_function_id(X) ->
|
||||
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
||||
gmb_fate_code:symbol_identifier(make_function_name(X)).
|
||||
|
||||
make_function_name(event) -> <<"Chain.event">>;
|
||||
make_function_name({entrypoint, Name}) -> Name;
|
||||
@ -103,7 +102,7 @@ make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs,
|
||||
add_child_symbols(ChildContracts, FateCode) ->
|
||||
Funs = lists:flatten([ maps:keys(ChildFuns) || {_, #{functions := ChildFuns}} <- maps:to_list(ChildContracts) ]),
|
||||
Symbols = maps:from_list([ {make_function_id(FName), make_function_name(FName)} || FName <- Funs ]),
|
||||
aeb_fate_code:update_symbols(FateCode, Symbols).
|
||||
gmb_fate_code:update_symbols(FateCode, Symbols).
|
||||
|
||||
functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options) ->
|
||||
FunNames = maps:keys(Functions),
|
||||
@ -140,8 +139,6 @@ type_to_scode(string) -> string;
|
||||
type_to_scode(address) -> address;
|
||||
type_to_scode({bytes, N}) -> {bytes, N};
|
||||
type_to_scode(contract) -> contract;
|
||||
type_to_scode({oracle, _, _}) -> oracle;
|
||||
type_to_scode(oracle_query) -> oracle_query;
|
||||
type_to_scode(name) -> name;
|
||||
type_to_scode(channel) -> channel;
|
||||
type_to_scode(bits) -> bits;
|
||||
@ -212,17 +209,17 @@ serialize_contract_code(Env, C) ->
|
||||
SavedFreshNames = Env#env.saved_fresh_names,
|
||||
FCode = maps:get(C, Env#env.child_contracts),
|
||||
FateCode = compile(Env#env.child_contracts, FCode, SavedFreshNames, Options),
|
||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
||||
{ok, Version} = aeso_compiler:version(),
|
||||
ByteCode = gmb_fate_code:serialize(FateCode, []),
|
||||
{ok, Version} = so_compiler:version(),
|
||||
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
||||
Code = #{byte_code => ByteCode,
|
||||
compiler_version => Version,
|
||||
source_hash => crypto:hash(sha256, OriginalSourceCode ++ [0] ++ C),
|
||||
type_info => [],
|
||||
abi_version => aeb_fate_abi:abi_version(),
|
||||
abi_version => gmb_fate_abi:abi_version(),
|
||||
payable => maps:get(payable, FCode)
|
||||
},
|
||||
Serialized = aeser_contract_code:serialize(Code),
|
||||
Serialized = gmser_contract_code:serialize(Code),
|
||||
put(contract_code_cache, maps:put(C, Serialized, Cache)),
|
||||
Serialized;
|
||||
Serialized -> Serialized
|
||||
@ -230,17 +227,15 @@ serialize_contract_code(Env, C) ->
|
||||
|
||||
lit_to_fate(Env, L) ->
|
||||
case L of
|
||||
{int, N} -> aeb_fate_data:make_integer(N);
|
||||
{string, S} -> aeb_fate_data:make_string(S);
|
||||
{bytes, B} -> aeb_fate_data:make_bytes(B);
|
||||
{bool, B} -> aeb_fate_data:make_boolean(B);
|
||||
{account_pubkey, K} -> aeb_fate_data:make_address(K);
|
||||
{signature, S} -> aeb_fate_data:make_bytes(S);
|
||||
{contract_pubkey, K} -> aeb_fate_data:make_contract(K);
|
||||
{oracle_pubkey, K} -> aeb_fate_data:make_oracle(K);
|
||||
{oracle_query_id, H} -> aeb_fate_data:make_oracle_query(H);
|
||||
{contract_code, C} -> aeb_fate_data:make_contract_bytearray(serialize_contract_code(Env, C));
|
||||
{typerep, T} -> aeb_fate_data:make_typerep(type_to_scode(T))
|
||||
{int, N} -> gmb_fate_data:make_integer(N);
|
||||
{string, S} -> gmb_fate_data:make_string(S);
|
||||
{bytes, B} -> gmb_fate_data:make_bytes(B);
|
||||
{bool, B} -> gmb_fate_data:make_boolean(B);
|
||||
{account_pubkey, K} -> gmb_fate_data:make_address(K);
|
||||
{signature, S} -> gmb_fate_data:make_bytes(S);
|
||||
{contract_pubkey, K} -> gmb_fate_data:make_contract(K);
|
||||
{contract_code, C} -> gmb_fate_data:make_contract_bytearray(serialize_contract_code(Env, C));
|
||||
{typerep, T} -> gmb_fate_data:make_typerep(type_to_scode(T))
|
||||
end.
|
||||
|
||||
term_to_fate(E) -> term_to_fate(#env{}, #{}, E).
|
||||
@ -250,21 +245,21 @@ term_to_fate(GlobEnv, _Env, {lit, _, L}) ->
|
||||
lit_to_fate(GlobEnv, L);
|
||||
%% negative literals are parsed as 0 - N
|
||||
term_to_fate(_GlobEnv, _Env, {op, _, '-', [{lit, _, {int, 0}}, {lit, _, {int, N}}]}) ->
|
||||
aeb_fate_data:make_integer(-N);
|
||||
gmb_fate_data:make_integer(-N);
|
||||
term_to_fate(_GlobEnv, _Env, {nil, _}) ->
|
||||
aeb_fate_data:make_list([]);
|
||||
gmb_fate_data:make_list([]);
|
||||
term_to_fate(GlobEnv, Env, {op, _, '::', [Hd, Tl]}) ->
|
||||
%% The Tl will translate into a list, because FATE lists are just lists
|
||||
[term_to_fate(GlobEnv, Env, Hd) | term_to_fate(GlobEnv, Env, Tl)];
|
||||
term_to_fate(GlobEnv, Env, {tuple, _, As}) ->
|
||||
aeb_fate_data:make_tuple(list_to_tuple([ term_to_fate(GlobEnv, Env, A) || A<-As]));
|
||||
gmb_fate_data:make_tuple(list_to_tuple([ term_to_fate(GlobEnv, Env, A) || A<-As]));
|
||||
term_to_fate(GlobEnv, Env, {con, _, Ar, I, As}) ->
|
||||
FateAs = [ term_to_fate(GlobEnv, Env, A) || A <- As ],
|
||||
aeb_fate_data:make_variant(Ar, I, list_to_tuple(FateAs));
|
||||
gmb_fate_data:make_variant(Ar, I, list_to_tuple(FateAs));
|
||||
term_to_fate(_GlobEnv, _Env, {builtin, _, bits_all, []}) ->
|
||||
aeb_fate_data:make_bits(-1);
|
||||
gmb_fate_data:make_bits(-1);
|
||||
term_to_fate(_GlobEnv, _Env, {builtin, _, bits_none, []}) ->
|
||||
aeb_fate_data:make_bits(0);
|
||||
gmb_fate_data:make_bits(0);
|
||||
term_to_fate(GlobEnv, _Env, {op, _, bits_set, [B, I]}) ->
|
||||
{bits, N} = term_to_fate(GlobEnv, B),
|
||||
J = term_to_fate(GlobEnv, I),
|
||||
@ -282,7 +277,7 @@ term_to_fate(_GlobEnv, Env, {var, _, X}) ->
|
||||
V -> V
|
||||
end;
|
||||
term_to_fate(_GlobEnv, _Env, {builtin, _, map_empty, []}) ->
|
||||
aeb_fate_data:make_map(#{});
|
||||
gmb_fate_data:make_map(#{});
|
||||
term_to_fate(GlobEnv, Env, {op, _, map_set, [M, K, V]}) ->
|
||||
Map = term_to_fate(GlobEnv, Env, M),
|
||||
Map#{term_to_fate(GlobEnv, Env, K) => term_to_fate(GlobEnv, Env, V)};
|
||||
@ -304,7 +299,7 @@ to_scode1(Env, {lit, Ann, L}) ->
|
||||
[ dbg_loc(Env, Ann), push(?i(lit_to_fate(Env, L))) ];
|
||||
|
||||
to_scode1(Env, {nil, Ann}) ->
|
||||
[ dbg_loc(Env, Ann), aeb_fate_ops:nil(?a) ];
|
||||
[ dbg_loc(Env, Ann), gmb_fate_ops:nil(?a) ];
|
||||
|
||||
to_scode1(Env, {var, Ann, X}) ->
|
||||
[ dbg_loc(Env, Ann), push(lookup_var(Env, X)) ];
|
||||
@ -313,7 +308,7 @@ to_scode1(Env, {con, Ann, Ar, I, As}) ->
|
||||
N = length(As),
|
||||
[ dbg_loc(Env, Ann),
|
||||
[to_scode(notail(Env), A) || A <- As],
|
||||
aeb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ];
|
||||
gmb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ];
|
||||
|
||||
to_scode1(Env, {tuple, Ann, As}) ->
|
||||
N = length(As),
|
||||
@ -324,13 +319,13 @@ to_scode1(Env, {tuple, Ann, As}) ->
|
||||
to_scode1(Env, {proj, Ann, E, I}) ->
|
||||
[ dbg_loc(Env, Ann),
|
||||
to_scode(notail(Env), E),
|
||||
aeb_fate_ops:element_op(?a, ?i(I), ?a) ];
|
||||
gmb_fate_ops:element_op(?a, ?i(I), ?a) ];
|
||||
|
||||
to_scode1(Env, {set_proj, Ann, R, I, E}) ->
|
||||
[ dbg_loc(Env, Ann),
|
||||
to_scode(notail(Env), E),
|
||||
to_scode(notail(Env), R),
|
||||
aeb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ];
|
||||
gmb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ];
|
||||
|
||||
to_scode1(Env, {op, Ann, Op, Args}) ->
|
||||
[ dbg_loc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ];
|
||||
@ -341,7 +336,7 @@ to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) ->
|
||||
to_scode1(Env, {'let', Ann, X, Expr, Body}) ->
|
||||
{I, Env1} = bind_local(X, Env),
|
||||
SCode = [ to_scode(notail(Env), Expr),
|
||||
aeb_fate_ops:store({var, I}, {stack, 0}),
|
||||
gmb_fate_ops:store({var, I}, {stack, 0}),
|
||||
to_scode(Env1, Body) ],
|
||||
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ];
|
||||
|
||||
@ -355,18 +350,18 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false
|
||||
{I, Env2} = bind_local("_", Env1),
|
||||
ArgCode = to_scode(notail(Env2), Arg),
|
||||
Acc1 = [Acc, ArgCode,
|
||||
aeb_fate_ops:store({var, I}, ?a)],
|
||||
gmb_fate_ops:store({var, I}, ?a)],
|
||||
{[I | Is], Acc1, Env2}
|
||||
end, {[], [], Env}, Args),
|
||||
[ dbg_loc(Env, Ann),
|
||||
Code,
|
||||
[ aeb_fate_ops:store({arg, I}, {var, J})
|
||||
[ gmb_fate_ops:store({arg, I}, {var, J})
|
||||
|| {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1),
|
||||
lists:reverse(Vars)) ],
|
||||
loop ];
|
||||
to_scode1(Env, {def, Ann, Fun, Args}) ->
|
||||
FName = make_function_id(Fun),
|
||||
Lbl = aeb_fate_data:make_string(FName),
|
||||
Lbl = gmb_fate_data:make_string(FName),
|
||||
[ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ];
|
||||
to_scode1(Env, {funcall, Ann, Fun, Args}) ->
|
||||
[ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ];
|
||||
@ -377,23 +372,23 @@ to_scode1(Env, {builtin, Ann, B, Args}) ->
|
||||
to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) ->
|
||||
Lbl = make_function_id(Fun),
|
||||
{ArgTypes, RetType0} = typesig_to_scode([{"_", T} || T <- ArgsT], RetT),
|
||||
ArgType = ?i(aeb_fate_data:make_typerep({tuple, ArgTypes})),
|
||||
RetType = ?i(aeb_fate_data:make_typerep(RetType0)),
|
||||
ArgType = ?i(gmb_fate_data:make_typerep({tuple, ArgTypes})),
|
||||
RetType = ?i(gmb_fate_data:make_typerep(RetType0)),
|
||||
SCode = case Protected of
|
||||
{lit, _, {bool, false}} ->
|
||||
case Gas of
|
||||
{builtin, _, call_gas_left, _} ->
|
||||
Call = aeb_fate_ops:call_r(?a, Lbl, ArgType, RetType, ?a),
|
||||
Call = gmb_fate_ops:call_r(?a, Lbl, ArgType, RetType, ?a),
|
||||
call_to_scode(Env, Call, [Ct, Value | Args]);
|
||||
_ ->
|
||||
Call = aeb_fate_ops:call_gr(?a, Lbl, ArgType, RetType, ?a, ?a),
|
||||
Call = gmb_fate_ops:call_gr(?a, Lbl, ArgType, RetType, ?a, ?a),
|
||||
call_to_scode(Env, Call, [Ct, Value, Gas | Args])
|
||||
end;
|
||||
{lit, _, {bool, true}} ->
|
||||
Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?i(true)),
|
||||
Call = gmb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?i(true)),
|
||||
call_to_scode(Env, Call, [Ct, Value, Gas | Args]);
|
||||
_ ->
|
||||
Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a),
|
||||
Call = gmb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a),
|
||||
call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args])
|
||||
end,
|
||||
[ dbg_loc(Env, Ann) | SCode ];
|
||||
@ -409,8 +404,8 @@ to_scode1(Env, {closure, Ann, Fun, FVs}) ->
|
||||
to_scode1(Env, {switch, Ann, Case}) ->
|
||||
[ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ].
|
||||
|
||||
local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun);
|
||||
local_call(_Env, Fun) -> aeb_fate_ops:call(Fun).
|
||||
local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> gmb_fate_ops:call_t(Fun);
|
||||
local_call(_Env, Fun) -> gmb_fate_ops:call(Fun).
|
||||
|
||||
split_to_scode(Env, {nosplit, Renames, Expr}) ->
|
||||
[switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))];
|
||||
@ -448,13 +443,13 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
||||
[{'case', {'::', Y, Z}, S} | _] ->
|
||||
{I, Env1} = bind_local(Y, Env),
|
||||
{J, Env2} = bind_local(Z, Env1),
|
||||
[aeb_fate_ops:hd({var, I}, Arg),
|
||||
aeb_fate_ops:tl({var, J}, Arg),
|
||||
[gmb_fate_ops:hd({var, I}, Arg),
|
||||
gmb_fate_ops:tl({var, J}, Arg),
|
||||
split_to_scode(Env2, S)]
|
||||
end
|
||||
end,
|
||||
SAlts = [GetAlt('::'), GetAlt(nil)],
|
||||
[aeb_fate_ops:is_nil(?a, Arg),
|
||||
[gmb_fate_ops:is_nil(?a, Arg),
|
||||
{switch, ?a, boolean, SAlts, Def}];
|
||||
split_to_scode(Env, {split, Type, X, Alts}) when Type == integer; Type == string ->
|
||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||
@ -488,9 +483,9 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T
|
||||
end,
|
||||
SLit = case Lit of
|
||||
{int, N} -> N;
|
||||
{string, S} -> aeb_fate_data:make_string(S)
|
||||
{string, S} -> gmb_fate_data:make_string(S)
|
||||
end,
|
||||
[aeb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
||||
[gmb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
||||
{switch, ?a, boolean, [False, True], Def}].
|
||||
|
||||
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
||||
@ -504,10 +499,10 @@ catchall_to_scode(_, _, [], Acc) -> {missing, lists:reverse(Acc)}.
|
||||
|
||||
%% Tuple is in the accumulator. Arguments are the variable names.
|
||||
match_tuple(Env, Arg, Xs) ->
|
||||
match_tuple(Env, 0, fun aeb_fate_ops:element_op/3, Arg, Xs).
|
||||
match_tuple(Env, 0, fun gmb_fate_ops:element_op/3, Arg, Xs).
|
||||
|
||||
match_variant(Env, Arg, Xs) ->
|
||||
Elem = fun(Dst, I, Val) -> aeb_fate_ops:variant_element(Dst, Val, I) end,
|
||||
Elem = fun(Dst, I, Val) -> gmb_fate_ops:variant_element(Dst, Val, I) end,
|
||||
match_tuple(Env, 0, Elem, Arg, Xs).
|
||||
|
||||
match_tuple(Env, I, Elem, Arg, ["_" | Xs]) ->
|
||||
@ -526,239 +521,215 @@ call_to_scode(Env, CallCode, Args) ->
|
||||
CallCode].
|
||||
|
||||
builtin_to_scode(Env, chain_event, Args) ->
|
||||
call_to_scode(Env, [erlang:apply(aeb_fate_ops, log, lists:duplicate(length(Args), ?a)),
|
||||
call_to_scode(Env, [erlang:apply(gmb_fate_ops, log, lists:duplicate(length(Args), ?a)),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(_Env, map_empty, []) ->
|
||||
[aeb_fate_ops:map_empty(?a)];
|
||||
[gmb_fate_ops:map_empty(?a)];
|
||||
builtin_to_scode(_Env, bits_none, []) ->
|
||||
[aeb_fate_ops:bits_none(?a)];
|
||||
[gmb_fate_ops:bits_none(?a)];
|
||||
builtin_to_scode(_Env, bits_all, []) ->
|
||||
[aeb_fate_ops:bits_all(?a)];
|
||||
[gmb_fate_ops:bits_all(?a)];
|
||||
builtin_to_scode(Env, bytes_to_int, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_to_int(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_to_int(?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_to_str, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_to_str(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_to_str(?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_concat, [_, _] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_concat(?a, ?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_concat(?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_split, [_, _] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_split(?a, ?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_split(?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_split_any, [_, _] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_split_any(?a, ?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_split_any(?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_to_fixed_size, [_, _] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_to_fixed_size(?a, ?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_to_fixed_size(?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, bytes_to_any_size, [A]) ->
|
||||
[to_scode(Env, A)]; %% no_op!
|
||||
builtin_to_scode(Env, bytes_size, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytes_size(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytes_size(?a, ?a), Args);
|
||||
builtin_to_scode(Env, abort, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:abort(?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:abort(?a), Args);
|
||||
builtin_to_scode(Env, exit, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:exit(?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:exit(?a), Args);
|
||||
builtin_to_scode(Env, chain_spend, [_, _] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:spend(?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:spend(?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, chain_balance, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:balance_other(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:balance_other(?a, ?a), Args);
|
||||
builtin_to_scode(Env, chain_block_hash, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:blockhash(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:blockhash(?a, ?a), Args);
|
||||
builtin_to_scode(_Env, chain_coinbase, []) ->
|
||||
[aeb_fate_ops:beneficiary(?a)];
|
||||
[gmb_fate_ops:beneficiary(?a)];
|
||||
builtin_to_scode(_Env, chain_timestamp, []) ->
|
||||
[aeb_fate_ops:timestamp(?a)];
|
||||
[gmb_fate_ops:timestamp(?a)];
|
||||
builtin_to_scode(_Env, chain_block_height, []) ->
|
||||
[aeb_fate_ops:generation(?a)];
|
||||
[gmb_fate_ops:generation(?a)];
|
||||
builtin_to_scode(_Env, chain_difficulty, []) ->
|
||||
[aeb_fate_ops:difficulty(?a)];
|
||||
[gmb_fate_ops:difficulty(?a)];
|
||||
builtin_to_scode(_Env, chain_gas_limit, []) ->
|
||||
[aeb_fate_ops:gaslimit(?a)];
|
||||
[gmb_fate_ops:gaslimit(?a)];
|
||||
builtin_to_scode(_Env, chain_network_id, []) ->
|
||||
[aeb_fate_ops:network_id(?a)];
|
||||
[gmb_fate_ops:network_id(?a)];
|
||||
builtin_to_scode(_Env, contract_balance, []) ->
|
||||
[aeb_fate_ops:balance(?a)];
|
||||
[gmb_fate_ops:balance(?a)];
|
||||
builtin_to_scode(_Env, contract_address, []) ->
|
||||
[aeb_fate_ops:address(?a)];
|
||||
[gmb_fate_ops:address(?a)];
|
||||
builtin_to_scode(_Env, contract_creator, []) ->
|
||||
[aeb_fate_ops:contract_creator(?a)];
|
||||
[gmb_fate_ops:contract_creator(?a)];
|
||||
builtin_to_scode(_Env, call_origin, []) ->
|
||||
[aeb_fate_ops:origin(?a)];
|
||||
[gmb_fate_ops:origin(?a)];
|
||||
builtin_to_scode(_Env, call_caller, []) ->
|
||||
[aeb_fate_ops:caller(?a)];
|
||||
[gmb_fate_ops:caller(?a)];
|
||||
builtin_to_scode(_Env, call_value, []) ->
|
||||
[aeb_fate_ops:call_value(?a)];
|
||||
[gmb_fate_ops:call_value(?a)];
|
||||
builtin_to_scode(_Env, call_gas_price, []) ->
|
||||
[aeb_fate_ops:gasprice(?a)];
|
||||
[gmb_fate_ops:gasprice(?a)];
|
||||
builtin_to_scode(_Env, call_fee, []) ->
|
||||
[aeb_fate_ops:fee(?a)];
|
||||
[gmb_fate_ops:fee(?a)];
|
||||
builtin_to_scode(_Env, call_gas_left, []) ->
|
||||
[aeb_fate_ops:gas(?a)];
|
||||
builtin_to_scode(Env, oracle_register, [_Sign,_Account,_QFee,_TTL,_QType,_RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_register(?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_expiry, [_Oracle] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_expiry(?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_query_fee, [_Oracle] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_query_fee(?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_query, [_Oracle, _Question, _QFee, _QTTL, _RTTL, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_query(?a, ?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_get_question, [_Oracle, _QueryId, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_get_question(?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_respond, [_Sign, _Oracle, _QueryId, _Response, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:oracle_respond(?a, ?a, ?a, ?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, oracle_extend, [_Sign, _Oracle, _TTL] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:oracle_extend(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, oracle_get_answer, [_Oracle, _QueryId, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_get_answer(?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_check, [_Oracle, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_check(?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_check_query, [_Oracle, _Query, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_check_query(?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, address_is_oracle, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:is_oracle(?a, ?a), Args);
|
||||
[gmb_fate_ops:gas(?a)];
|
||||
builtin_to_scode(Env, address_is_contract, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:is_contract(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:is_contract(?a, ?a), Args);
|
||||
builtin_to_scode(Env, address_is_payable, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:is_payable(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:is_payable(?a, ?a), Args);
|
||||
builtin_to_scode(Env, aens_resolve, [_Name, _Key, _Type] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:aens_resolve(?a, ?a, ?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:aens_resolve(?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, aens_preclaim, [_Sign, _Account, _Hash] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt, _NameFee] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_claim(?a, ?a, ?a, ?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:aens_claim(?a, ?a, ?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_revoke, [_Sign, _Account, _Name] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_revoke(?a, ?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:aens_revoke(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_update, [_Sign, _Account, _NameString, _TTL, _ClientTTL, _Pointers] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_update(?a, ?a, ?a, ?a, ?a, ?a),
|
||||
call_to_scode(Env, [gmb_fate_ops:aens_update(?a, ?a, ?a, ?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_lookup, [_Name] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:aens_lookup(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:aens_lookup(?a, ?a), Args);
|
||||
builtin_to_scode(_Env, auth_tx_hash, []) ->
|
||||
[aeb_fate_ops:auth_tx_hash(?a)];
|
||||
[gmb_fate_ops:auth_tx_hash(?a)];
|
||||
builtin_to_scode(_Env, auth_tx, []) ->
|
||||
[aeb_fate_ops:auth_tx(?a)];
|
||||
[gmb_fate_ops:auth_tx(?a)];
|
||||
builtin_to_scode(Env, chain_bytecode_hash, [_Addr] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:bytecode_hash(?a, ?a), Args);
|
||||
call_to_scode(Env, gmb_fate_ops:bytecode_hash(?a, ?a), Args);
|
||||
builtin_to_scode(Env, chain_clone,
|
||||
[InitArgsT, GasCap, Value, Prot, Contract | InitArgs]) ->
|
||||
case GasCap of
|
||||
{builtin, _, call_gas_left, _} ->
|
||||
call_to_scode(Env, aeb_fate_ops:clone(?a, ?a, ?a, ?a),
|
||||
call_to_scode(Env, gmb_fate_ops:clone(?a, ?a, ?a, ?a),
|
||||
[Contract, InitArgsT, Value, Prot | InitArgs]
|
||||
);
|
||||
_ ->
|
||||
call_to_scode(Env, aeb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a),
|
||||
call_to_scode(Env, gmb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a),
|
||||
[Contract, InitArgsT, Value, GasCap, Prot | InitArgs]
|
||||
)
|
||||
end;
|
||||
|
||||
builtin_to_scode(Env, chain_create,
|
||||
[ Code, InitArgsT, Value | InitArgs]) ->
|
||||
call_to_scode(Env, aeb_fate_ops:create(?a, ?a, ?a),
|
||||
call_to_scode(Env, gmb_fate_ops:create(?a, ?a, ?a),
|
||||
[Code, InitArgsT, Value | InitArgs]
|
||||
).
|
||||
|
||||
%% -- Operators --
|
||||
|
||||
op_to_scode('+') -> aeb_fate_ops:add(?a, ?a, ?a);
|
||||
op_to_scode('-') -> aeb_fate_ops:sub(?a, ?a, ?a);
|
||||
op_to_scode('*') -> aeb_fate_ops:mul(?a, ?a, ?a);
|
||||
op_to_scode('/') -> aeb_fate_ops:divide(?a, ?a, ?a);
|
||||
op_to_scode(mod) -> aeb_fate_ops:modulo(?a, ?a, ?a);
|
||||
op_to_scode('^') -> aeb_fate_ops:pow(?a, ?a, ?a);
|
||||
op_to_scode('++') -> aeb_fate_ops:append(?a, ?a, ?a);
|
||||
op_to_scode('::') -> aeb_fate_ops:cons(?a, ?a, ?a);
|
||||
op_to_scode('<') -> aeb_fate_ops:lt(?a, ?a, ?a);
|
||||
op_to_scode('>') -> aeb_fate_ops:gt(?a, ?a, ?a);
|
||||
op_to_scode('=<') -> aeb_fate_ops:elt(?a, ?a, ?a);
|
||||
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);
|
||||
op_to_scode(map_from_list) -> aeb_fate_ops:map_from_list(?a, ?a);
|
||||
op_to_scode(map_to_list) -> aeb_fate_ops:map_to_list(?a, ?a);
|
||||
op_to_scode(map_delete) -> aeb_fate_ops:map_delete(?a, ?a, ?a);
|
||||
op_to_scode(map_member) -> aeb_fate_ops:map_member(?a, ?a, ?a);
|
||||
op_to_scode(map_size) -> aeb_fate_ops:map_size_(?a, ?a);
|
||||
op_to_scode(stringinternal_length) -> aeb_fate_ops:str_length(?a, ?a);
|
||||
op_to_scode(stringinternal_concat) -> aeb_fate_ops:str_join(?a, ?a, ?a);
|
||||
op_to_scode(stringinternal_to_bytes) -> aeb_fate_ops:str_to_bytes(?a, ?a);
|
||||
op_to_scode(stringinternal_to_list) -> aeb_fate_ops:str_to_list(?a, ?a);
|
||||
op_to_scode(stringinternal_from_list) -> aeb_fate_ops:str_from_list(?a, ?a);
|
||||
op_to_scode(stringinternal_to_lower) -> aeb_fate_ops:str_to_lower(?a, ?a);
|
||||
op_to_scode(stringinternal_to_upper) -> aeb_fate_ops:str_to_upper(?a, ?a);
|
||||
op_to_scode(char_to_int) -> aeb_fate_ops:char_to_int(?a, ?a);
|
||||
op_to_scode(char_from_int) -> aeb_fate_ops:char_from_int(?a, ?a);
|
||||
op_to_scode(bits_set) -> aeb_fate_ops:bits_set(?a, ?a, ?a);
|
||||
op_to_scode(bits_clear) -> aeb_fate_ops:bits_clear(?a, ?a, ?a);
|
||||
op_to_scode(bits_test) -> aeb_fate_ops:bits_test(?a, ?a, ?a);
|
||||
op_to_scode(bits_sum) -> aeb_fate_ops:bits_sum(?a, ?a);
|
||||
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_to_bytes) -> aeb_fate_ops:int_to_bytes(?a, ?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);
|
||||
op_to_scode(crypto_verify_sig_secp256k1) -> aeb_fate_ops:verify_sig_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecverify_secp256k1) -> aeb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecrecover_secp256k1) -> aeb_fate_ops:ecrecover_secp256k1(?a, ?a, ?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);
|
||||
op_to_scode(mcl_bls12_381_g1_neg) -> aeb_fate_ops:bls12_381_g1_neg(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_norm) -> aeb_fate_ops:bls12_381_g1_norm(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_valid) -> aeb_fate_ops:bls12_381_g1_valid(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_is_zero) -> aeb_fate_ops:bls12_381_g1_is_zero(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_add) -> aeb_fate_ops:bls12_381_g1_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_mul) -> aeb_fate_ops:bls12_381_g1_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_neg) -> aeb_fate_ops:bls12_381_g2_neg(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_norm) -> aeb_fate_ops:bls12_381_g2_norm(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_valid) -> aeb_fate_ops:bls12_381_g2_valid(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_is_zero) -> aeb_fate_ops:bls12_381_g2_is_zero(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_add) -> aeb_fate_ops:bls12_381_g2_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_mul) -> aeb_fate_ops:bls12_381_g2_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_inv) -> aeb_fate_ops:bls12_381_gt_inv(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_add) -> aeb_fate_ops:bls12_381_gt_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_mul) -> aeb_fate_ops:bls12_381_gt_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_pow) -> aeb_fate_ops:bls12_381_gt_pow(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_is_one) -> aeb_fate_ops:bls12_381_gt_is_one(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_pairing) -> aeb_fate_ops:bls12_381_pairing(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_miller_loop) -> aeb_fate_ops:bls12_381_miller_loop(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_final_exp) -> aeb_fate_ops:bls12_381_final_exp(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_int_to_fr) -> aeb_fate_ops:bls12_381_int_to_fr(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_int_to_fp) -> aeb_fate_ops:bls12_381_int_to_fp(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_fr_to_int) -> aeb_fate_ops:bls12_381_fr_to_int(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_fp_to_int) -> aeb_fate_ops:bls12_381_fp_to_int(?a, ?a).
|
||||
op_to_scode('+') -> gmb_fate_ops:add(?a, ?a, ?a);
|
||||
op_to_scode('-') -> gmb_fate_ops:sub(?a, ?a, ?a);
|
||||
op_to_scode('*') -> gmb_fate_ops:mul(?a, ?a, ?a);
|
||||
op_to_scode('/') -> gmb_fate_ops:divide(?a, ?a, ?a);
|
||||
op_to_scode(mod) -> gmb_fate_ops:modulo(?a, ?a, ?a);
|
||||
op_to_scode('^') -> gmb_fate_ops:pow(?a, ?a, ?a);
|
||||
op_to_scode('++') -> gmb_fate_ops:append(?a, ?a, ?a);
|
||||
op_to_scode('::') -> gmb_fate_ops:cons(?a, ?a, ?a);
|
||||
op_to_scode('<') -> gmb_fate_ops:lt(?a, ?a, ?a);
|
||||
op_to_scode('>') -> gmb_fate_ops:gt(?a, ?a, ?a);
|
||||
op_to_scode('=<') -> gmb_fate_ops:elt(?a, ?a, ?a);
|
||||
op_to_scode('>=') -> gmb_fate_ops:egt(?a, ?a, ?a);
|
||||
op_to_scode('==') -> gmb_fate_ops:eq(?a, ?a, ?a);
|
||||
op_to_scode('!=') -> gmb_fate_ops:neq(?a, ?a, ?a);
|
||||
op_to_scode('!') -> gmb_fate_ops:not_op(?a, ?a);
|
||||
op_to_scode('bnot') -> gmb_fate_ops:bin_not(?a, ?a);
|
||||
op_to_scode('band') -> gmb_fate_ops:bin_and(?a, ?a, ?a);
|
||||
op_to_scode('bor') -> gmb_fate_ops:bin_or(?a, ?a, ?a);
|
||||
op_to_scode('bxor') -> gmb_fate_ops:bin_xor(?a, ?a, ?a);
|
||||
op_to_scode('<<') -> gmb_fate_ops:bin_sl(?a, ?a, ?a);
|
||||
op_to_scode('>>') -> gmb_fate_ops:bin_sr(?a, ?a, ?a);
|
||||
op_to_scode(map_get) -> gmb_fate_ops:map_lookup(?a, ?a, ?a);
|
||||
op_to_scode(map_get_d) -> gmb_fate_ops:map_lookup(?a, ?a, ?a, ?a);
|
||||
op_to_scode(map_set) -> gmb_fate_ops:map_update(?a, ?a, ?a, ?a);
|
||||
op_to_scode(map_from_list) -> gmb_fate_ops:map_from_list(?a, ?a);
|
||||
op_to_scode(map_to_list) -> gmb_fate_ops:map_to_list(?a, ?a);
|
||||
op_to_scode(map_delete) -> gmb_fate_ops:map_delete(?a, ?a, ?a);
|
||||
op_to_scode(map_member) -> gmb_fate_ops:map_member(?a, ?a, ?a);
|
||||
op_to_scode(map_size) -> gmb_fate_ops:map_size_(?a, ?a);
|
||||
op_to_scode(stringinternal_length) -> gmb_fate_ops:str_length(?a, ?a);
|
||||
op_to_scode(stringinternal_concat) -> gmb_fate_ops:str_join(?a, ?a, ?a);
|
||||
op_to_scode(stringinternal_to_bytes) -> gmb_fate_ops:str_to_bytes(?a, ?a);
|
||||
op_to_scode(stringinternal_to_list) -> gmb_fate_ops:str_to_list(?a, ?a);
|
||||
op_to_scode(stringinternal_from_list) -> gmb_fate_ops:str_from_list(?a, ?a);
|
||||
op_to_scode(stringinternal_to_lower) -> gmb_fate_ops:str_to_lower(?a, ?a);
|
||||
op_to_scode(stringinternal_to_upper) -> gmb_fate_ops:str_to_upper(?a, ?a);
|
||||
op_to_scode(char_to_int) -> gmb_fate_ops:char_to_int(?a, ?a);
|
||||
op_to_scode(char_from_int) -> gmb_fate_ops:char_from_int(?a, ?a);
|
||||
op_to_scode(bits_set) -> gmb_fate_ops:bits_set(?a, ?a, ?a);
|
||||
op_to_scode(bits_clear) -> gmb_fate_ops:bits_clear(?a, ?a, ?a);
|
||||
op_to_scode(bits_test) -> gmb_fate_ops:bits_test(?a, ?a, ?a);
|
||||
op_to_scode(bits_sum) -> gmb_fate_ops:bits_sum(?a, ?a);
|
||||
op_to_scode(bits_intersection) -> gmb_fate_ops:bits_and(?a, ?a, ?a);
|
||||
op_to_scode(bits_union) -> gmb_fate_ops:bits_or(?a, ?a, ?a);
|
||||
op_to_scode(bits_difference) -> gmb_fate_ops:bits_diff(?a, ?a, ?a);
|
||||
op_to_scode(address_to_str) -> gmb_fate_ops:addr_to_str(?a, ?a);
|
||||
op_to_scode(address_to_bytes) -> gmb_fate_ops:addr_to_bytes(?a, ?a);
|
||||
op_to_scode(int_to_str) -> gmb_fate_ops:int_to_str(?a, ?a);
|
||||
op_to_scode(int_to_bytes) -> gmb_fate_ops:int_to_bytes(?a, ?a, ?a);
|
||||
op_to_scode(int_mulmod) -> gmb_fate_ops:mulmod(?a, ?a, ?a, ?a);
|
||||
op_to_scode(contract_to_address) -> gmb_fate_ops:contract_to_address(?a, ?a);
|
||||
op_to_scode(address_to_contract) -> gmb_fate_ops:address_to_contract(?a, ?a);
|
||||
op_to_scode(crypto_verify_sig) -> gmb_fate_ops:verify_sig(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_verify_sig_secp256k1) -> gmb_fate_ops:verify_sig_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecverify_secp256k1) -> gmb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a);
|
||||
op_to_scode(crypto_ecrecover_secp256k1) -> gmb_fate_ops:ecrecover_secp256k1(?a, ?a, ?a);
|
||||
op_to_scode(crypto_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
||||
op_to_scode(crypto_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
||||
op_to_scode(crypto_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
||||
op_to_scode(crypto_poseidon) -> gmb_fate_ops:poseidon(?a, ?a, ?a);
|
||||
op_to_scode(stringinternal_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
||||
op_to_scode(stringinternal_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
||||
op_to_scode(stringinternal_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_neg) -> gmb_fate_ops:bls12_381_g1_neg(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_norm) -> gmb_fate_ops:bls12_381_g1_norm(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_valid) -> gmb_fate_ops:bls12_381_g1_valid(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_is_zero) -> gmb_fate_ops:bls12_381_g1_is_zero(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_add) -> gmb_fate_ops:bls12_381_g1_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g1_mul) -> gmb_fate_ops:bls12_381_g1_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_neg) -> gmb_fate_ops:bls12_381_g2_neg(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_norm) -> gmb_fate_ops:bls12_381_g2_norm(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_valid) -> gmb_fate_ops:bls12_381_g2_valid(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_is_zero) -> gmb_fate_ops:bls12_381_g2_is_zero(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_add) -> gmb_fate_ops:bls12_381_g2_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_g2_mul) -> gmb_fate_ops:bls12_381_g2_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_inv) -> gmb_fate_ops:bls12_381_gt_inv(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_add) -> gmb_fate_ops:bls12_381_gt_add(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_mul) -> gmb_fate_ops:bls12_381_gt_mul(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_pow) -> gmb_fate_ops:bls12_381_gt_pow(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_gt_is_one) -> gmb_fate_ops:bls12_381_gt_is_one(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_pairing) -> gmb_fate_ops:bls12_381_pairing(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_miller_loop) -> gmb_fate_ops:bls12_381_miller_loop(?a, ?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_final_exp) -> gmb_fate_ops:bls12_381_final_exp(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_int_to_fr) -> gmb_fate_ops:bls12_381_int_to_fr(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_int_to_fp) -> gmb_fate_ops:bls12_381_int_to_fp(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_fr_to_int) -> gmb_fate_ops:bls12_381_fr_to_int(?a, ?a);
|
||||
op_to_scode(mcl_bls12_381_fp_to_int) -> gmb_fate_ops:bls12_381_fp_to_int(?a, ?a).
|
||||
|
||||
%% PUSH and STORE ?a are the same, so we use STORE to make optimizations
|
||||
%% easier, and specialize to PUSH (which is cheaper) at the end.
|
||||
push(A) -> {'STORE', ?a, A}.
|
||||
|
||||
tuple(0) -> push(?i({tuple, {}}));
|
||||
tuple(N) -> aeb_fate_ops:tuple(?a, N).
|
||||
tuple(N) -> gmb_fate_ops:tuple(?a, N).
|
||||
|
||||
%% -- Debug info functions --
|
||||
|
||||
@ -825,8 +796,8 @@ dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) ->
|
||||
true -> tuple_to_list(SCode);
|
||||
false -> [SCode]
|
||||
end,
|
||||
Op = aeb_fate_opcodes:m_to_op(Mnemonic),
|
||||
case aeb_fate_opcodes:end_bb(Op) of
|
||||
Op = gmb_fate_opcodes:m_to_op(Mnemonic),
|
||||
case gmb_fate_opcodes:end_bb(Op) of
|
||||
true -> [Undef, SCode];
|
||||
false -> [SCode, Undef]
|
||||
end.
|
||||
@ -898,7 +869,7 @@ pp_ann(_, []) -> [].
|
||||
pp_op(switch_body) -> "SWITCH-BODY";
|
||||
pp_op(loop) -> "LOOP";
|
||||
pp_op(I) ->
|
||||
aeb_fate_pp:format_op(I, #{}).
|
||||
gmb_fate_pp:format_op(I, #{}).
|
||||
|
||||
pp_arg(?i(I)) -> io_lib:format("~w", [I]);
|
||||
pp_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
||||
@ -1668,14 +1639,14 @@ unannotate(Code) when is_list(Code) ->
|
||||
unannotate({i, _Ann, I}) -> [I].
|
||||
|
||||
%% Desugar and specialize
|
||||
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_ops:inc()];
|
||||
desugar({'ADD', A, ?i(1), A}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
||||
desugar({'ADD', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:inc()];
|
||||
desugar({'ADD', A, A, ?i(1)}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
||||
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:dec()];
|
||||
desugar({'SUB', A, A, ?i(1)}) -> [aeb_fate_ops:dec(desugar_arg(A))];
|
||||
desugar({'STORE', ?a, A}) -> [aeb_fate_ops:push(desugar_arg(A))];
|
||||
desugar({'STORE', R, ?a}) -> [aeb_fate_ops:pop(desugar_arg(R))];
|
||||
desugar({'ADD', ?a, ?i(1), ?a}) -> [gmb_fate_ops:inc()];
|
||||
desugar({'ADD', A, ?i(1), A}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
||||
desugar({'ADD', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:inc()];
|
||||
desugar({'ADD', A, A, ?i(1)}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
||||
desugar({'SUB', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:dec()];
|
||||
desugar({'SUB', A, A, ?i(1)}) -> [gmb_fate_ops:dec(desugar_arg(A))];
|
||||
desugar({'STORE', ?a, A}) -> [gmb_fate_ops:push(desugar_arg(A))];
|
||||
desugar({'STORE', R, ?a}) -> [gmb_fate_ops:pop(desugar_arg(R))];
|
||||
desugar({switch, Arg, Type, Alts, Def}) ->
|
||||
[{switch, desugar_arg(Arg), Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
||||
desugar(missing) -> missing;
|
||||
@ -1695,11 +1666,11 @@ desugar_arg(A) -> A.
|
||||
%% Constructing basic blocks
|
||||
|
||||
to_basic_blocks(Funs) ->
|
||||
to_basic_blocks(maps:to_list(Funs), aeb_fate_code:new()).
|
||||
to_basic_blocks(maps:to_list(Funs), gmb_fate_code:new()).
|
||||
|
||||
to_basic_blocks([{Name, {Attrs, Sig, Code}}|Left], Acc) ->
|
||||
BB = bb(Name, Code ++ [aeb_fate_ops:return()]),
|
||||
to_basic_blocks(Left, aeb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
||||
BB = bb(Name, Code ++ [gmb_fate_ops:return()]),
|
||||
to_basic_blocks(Left, gmb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
||||
to_basic_blocks([], Acc) ->
|
||||
Acc.
|
||||
|
||||
@ -1770,7 +1741,7 @@ block(Blk = #blk{code = [{switch, Arg, Type, Alts, Default} | Code],
|
||||
{DefRef, DefBlk} =
|
||||
case Default of
|
||||
missing when Catchall == none ->
|
||||
FreshBlk([aeb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
||||
FreshBlk([gmb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
||||
missing -> {Catchall, []};
|
||||
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
||||
%% ^ fall-through to the outer catchall
|
||||
@ -1945,14 +1916,14 @@ split_calls(Ref, [I | Code], Acc, Blocks) ->
|
||||
|
||||
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
||||
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
||||
set_labels(_Labels, loop) -> aeb_fate_ops:jump(0);
|
||||
set_labels(Labels, {jump, Ref}) -> aeb_fate_ops:jump(maps:get(Ref, Labels));
|
||||
set_labels(Labels, {jumpif, Arg, Ref}) -> aeb_fate_ops:jumpif(Arg, maps:get(Ref, Labels));
|
||||
set_labels(_Labels, loop) -> gmb_fate_ops:jump(0);
|
||||
set_labels(Labels, {jump, Ref}) -> gmb_fate_ops:jump(maps:get(Ref, Labels));
|
||||
set_labels(Labels, {jumpif, Arg, Ref}) -> gmb_fate_ops:jumpif(Arg, maps:get(Ref, Labels));
|
||||
set_labels(Labels, {switch, Arg, Refs}) ->
|
||||
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
||||
[R1, R2] -> aeb_fate_ops:switch(Arg, R1, R2);
|
||||
[R1, R2, R3] -> aeb_fate_ops:switch(Arg, R1, R2, R3);
|
||||
Rs -> aeb_fate_ops:switch(Arg, Rs)
|
||||
[R1, R2] -> gmb_fate_ops:switch(Arg, R1, R2);
|
||||
[R1, R2, R3] -> gmb_fate_ops:switch(Arg, R1, R2, R3);
|
||||
Rs -> gmb_fate_ops:switch(Arg, Rs)
|
||||
end;
|
||||
set_labels(_, I) -> I.
|
||||
|
@ -1,12 +1,13 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc Parser combinators for the Sophia parser. Based on
|
||||
%%% Koen Claessen. 2004. Parallel Parsing Processes. J. Functional
|
||||
%%% Programming 14, 6 (November 2004)
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_parse_lib).
|
||||
-module(so_parse_lib).
|
||||
|
||||
-export([parse/2,
|
||||
return/1, fail/0, fail/1, fail/2, map/2, bind/2,
|
||||
@ -27,16 +28,16 @@
|
||||
-type tokens() :: [token()].
|
||||
-type error() :: {pos(), string() | no_error}.
|
||||
|
||||
-define(lazy(F), {aeso_parse_lazy, F}).
|
||||
-define(fail(Err), {aeso_parse_fail, Err}).
|
||||
-define(choice(Ps), {aeso_parse_choice, Ps}).
|
||||
-define(bind(P, F), {aeso_parse_bind, P, F}).
|
||||
-define(right(P, Q), {aeso_parse_right, P, Q}).
|
||||
-define(left(P, Q), {aeso_parse_left, P, Q}).
|
||||
-define(map(F, P), {aeso_parse_map, F, P}).
|
||||
-define(layout, aeso_parse_layout).
|
||||
-define(tok(Atom), {aeso_parse_tok, Atom}).
|
||||
-define(return(X), {aeso_parse_return, X}).
|
||||
-define(lazy(F), {so_parse_lazy, F}).
|
||||
-define(fail(Err), {so_parse_fail, Err}).
|
||||
-define(choice(Ps), {so_parse_choice, Ps}).
|
||||
-define(bind(P, F), {so_parse_bind, P, F}).
|
||||
-define(right(P, Q), {so_parse_right, P, Q}).
|
||||
-define(left(P, Q), {so_parse_left, P, Q}).
|
||||
-define(map(F, P), {so_parse_map, F, P}).
|
||||
-define(layout, so_parse_layout).
|
||||
-define(tok(Atom), {so_parse_tok, Atom}).
|
||||
-define(return(X), {so_parse_return, X}).
|
||||
|
||||
%% Type synonyms since you can't have function types as macro arguments for some reason.
|
||||
-type delayed(A) :: fun(() -> A).
|
@ -1,8 +1,8 @@
|
||||
%%% File : aeso_parser.erl
|
||||
%%% File : so_parser.erl
|
||||
%%% Author : Ulf Norell
|
||||
%%% Description :
|
||||
%%% Created : 1 Mar 2018 by Ulf Norell
|
||||
-module(aeso_parser).
|
||||
-module(so_parser).
|
||||
-compile({no_auto_import,[map_get/2]}).
|
||||
|
||||
-export([string/1,
|
||||
@ -17,12 +17,12 @@
|
||||
run_parser/2,
|
||||
run_parser/3]).
|
||||
|
||||
-include("aeso_parse_lib.hrl").
|
||||
-import(aeso_parse_lib, [current_file/0, set_current_file/1,
|
||||
-include("so_parse_lib.hrl").
|
||||
-import(so_parse_lib, [current_file/0, set_current_file/1,
|
||||
current_dir/0, set_current_dir/1,
|
||||
current_include_type/0, set_current_include_type/1]).
|
||||
|
||||
-type parse_result() :: aeso_syntax:ast() | {aeso_syntax:ast(), sets:set(include_hash())} | none().
|
||||
-type parse_result() :: so_syntax:ast() | {so_syntax:ast(), sets:set(include_hash())} | none().
|
||||
|
||||
-type include_hash() :: {string(), binary()}.
|
||||
|
||||
@ -36,14 +36,14 @@ escape_errors({error, Err}) ->
|
||||
string(String) ->
|
||||
string(String, sets:new(), []).
|
||||
|
||||
-spec string(string(), aeso_compiler:options()) -> parse_result().
|
||||
-spec string(string(), so_compiler:options()) -> parse_result().
|
||||
string(String, Opts) ->
|
||||
case lists:keyfind(src_file, 1, Opts) of
|
||||
{src_file, File} -> string(String, sets:add_element(File, sets:new()), Opts);
|
||||
false -> string(String, sets:new(), Opts)
|
||||
end.
|
||||
|
||||
-spec string(string(), sets:set(include_hash()), aeso_compiler:options()) -> parse_result().
|
||||
-spec string(string(), sets:set(include_hash()), so_compiler:options()) -> parse_result().
|
||||
string(String, Included, Opts) ->
|
||||
AST = run_parser(file(), String, Opts),
|
||||
case expand_includes(AST, Included, Opts) of
|
||||
@ -61,18 +61,18 @@ parse_and_scan(P, S, Opts) ->
|
||||
set_current_file(proplists:get_value(src_file, Opts, no_file)),
|
||||
set_current_dir(proplists:get_value(src_dir, Opts, no_file)),
|
||||
set_current_include_type(proplists:get_value(include_type, Opts, none)),
|
||||
case aeso_scan:scan(S) of
|
||||
{ok, Tokens} -> aeso_parse_lib:parse(P, Tokens);
|
||||
case so_scan:scan(S) of
|
||||
{ok, Tokens} -> so_parse_lib:parse(P, Tokens);
|
||||
{error, {{Input, Pos}, _}} ->
|
||||
{error, {Pos, scan_error, Input}}
|
||||
end.
|
||||
|
||||
-dialyzer({nowarn_function, parse_error/1}).
|
||||
parse_error(Err) ->
|
||||
aeso_errors:throw(mk_error(Err)).
|
||||
so_errors:throw(mk_error(Err)).
|
||||
|
||||
mk_p_err(Pos, Msg) ->
|
||||
aeso_errors:new(parse_error, mk_pos(Pos), lists:flatten(Msg)).
|
||||
so_errors:new(parse_error, mk_pos(Pos), lists:flatten(Msg)).
|
||||
|
||||
mk_error({Pos, scan_error, Input}) ->
|
||||
mk_p_err(Pos, io_lib:format("Lexical error on input: ~s\n", [Input]));
|
||||
@ -86,8 +86,8 @@ mk_error({Pos, include_error, File}) ->
|
||||
Msg = io_lib:format("Couldn't find include file '~s'\n", [File]),
|
||||
mk_p_err(Pos, Msg).
|
||||
|
||||
mk_pos({Line, Col}) -> aeso_errors:pos(Line, Col);
|
||||
mk_pos({File, Line, Col}) -> aeso_errors:pos(File, Line, Col).
|
||||
mk_pos({Line, Col}) -> so_errors:pos(Line, Col);
|
||||
mk_pos({File, Line, Col}) -> so_errors:pos(File, Line, Col).
|
||||
|
||||
%% -- Parsing rules ----------------------------------------------------------
|
||||
|
||||
@ -411,7 +411,7 @@ map_key(Key, {ok, {_, Val}}) -> {map_key, Key, Val}.
|
||||
|
||||
elim(E, []) -> E;
|
||||
elim(E, [{proj, Ann, P} | Es]) -> elim({proj, Ann, E, P}, Es);
|
||||
elim(E, [{app, _Ann, Args} | Es]) -> elim({app, aeso_syntax:get_ann(E), E, Args}, Es);
|
||||
elim(E, [{app, _Ann, Args} | Es]) -> elim({app, so_syntax:get_ann(E), E, Args}, Es);
|
||||
elim(E, [{rec_upd, Ann, Flds} | Es]) -> elim(record_update(Ann, E, Flds), Es);
|
||||
elim(E, [{map_get, Ann, Key} | Es]) -> elim({map_get, Ann, E, Key}, Es);
|
||||
elim(E, [{map_get, Ann, Key, Val} | Es]) -> elim({map_get, Ann, E, Key, Val}, Es).
|
||||
@ -528,7 +528,7 @@ parse_addr_literal(Id = {id, Ann, Name}) ->
|
||||
case lists:member(lists:sublist(Name, 3), ["ak_", "ok_", "oq_", "ct_", "sg_"]) of
|
||||
false -> Id;
|
||||
true ->
|
||||
try aeser_api_encoder:decode(list_to_binary(Name)) of
|
||||
try gmser_api_encoder:decode(list_to_binary(Name)) of
|
||||
{Type, Bin} -> {Type, Ann, Bin}
|
||||
catch _:_ ->
|
||||
Id
|
||||
@ -557,9 +557,9 @@ bracket_list(P) -> brackets(comma_sep(P)).
|
||||
|
||||
%% -- Annotations ------------------------------------------------------------
|
||||
|
||||
-type ann() :: aeso_syntax:ann().
|
||||
-type ann_line() :: aeso_syntax:ann_line().
|
||||
-type ann_col() :: aeso_syntax:ann_col().
|
||||
-type ann() :: so_syntax:ann().
|
||||
-type ann_line() :: so_syntax:ann_line().
|
||||
-type ann_col() :: so_syntax:ann_col().
|
||||
|
||||
-spec pos_ann(ann_line(), ann_col()) -> ann().
|
||||
pos_ann(Line, Col) ->
|
||||
@ -647,7 +647,7 @@ tuple_e(Ann, Exprs) -> {tuple, Ann, Exprs}.
|
||||
|
||||
list_comp_e(Ann, Expr, Binds) -> {list_comp, Ann, Expr, Binds}.
|
||||
|
||||
-spec parse_pattern(aeso_syntax:expr()) -> aeso_parse_lib:parser(aeso_syntax:pat()).
|
||||
-spec parse_pattern(so_syntax:expr()) -> so_parse_lib:parser(so_syntax:pat()).
|
||||
parse_pattern({letpat, Ann, Id, Pat}) ->
|
||||
{letpat, Ann, Id, parse_pattern(Pat)};
|
||||
parse_pattern({app, Ann, Con = {'::', _}, Es}) ->
|
||||
@ -674,19 +674,19 @@ parse_pattern(E = {string, _, _}) -> E;
|
||||
parse_pattern(E = {char, _, _}) -> E;
|
||||
parse_pattern(E) -> bad_expr_err("Not a valid pattern", E).
|
||||
|
||||
-spec parse_field_pattern(aeso_syntax:field(aeso_syntax:expr())) -> aeso_parse_lib:parser(aeso_syntax:field(aeso_syntax:pat())).
|
||||
-spec parse_field_pattern(so_syntax:field(so_syntax:expr())) -> so_parse_lib:parser(so_syntax:field(so_syntax:pat())).
|
||||
parse_field_pattern({field, Ann, F, E}) ->
|
||||
{field, Ann, F, parse_pattern(E)}.
|
||||
|
||||
-spec ret_doc_err(ann(), prettypr:document()) -> aeso_parse_lib:parser(none()).
|
||||
-spec ret_doc_err(ann(), prettypr:document()) -> so_parse_lib:parser(none()).
|
||||
ret_doc_err(Ann, Doc) ->
|
||||
fail(ann_pos(Ann), prettypr:format(Doc)).
|
||||
|
||||
-spec bad_expr_err(string(), aeso_syntax:expr()) -> aeso_parse_lib:parser(none()).
|
||||
-spec bad_expr_err(string(), so_syntax:expr()) -> so_parse_lib:parser(none()).
|
||||
bad_expr_err(Reason, E) ->
|
||||
ret_doc_err(get_ann(E),
|
||||
prettypr:sep([prettypr:text(Reason ++ ":"),
|
||||
prettypr:nest(2, aeso_pretty:expr(E))])).
|
||||
prettypr:nest(2, so_pretty:expr(E))])).
|
||||
|
||||
%% -- Helper functions -------------------------------------------------------
|
||||
|
||||
@ -748,7 +748,7 @@ read_file(File, Opts) ->
|
||||
Escript = escript:script_name(),
|
||||
{ok, Sections} = escript:extract(Escript, []),
|
||||
Archive = proplists:get_value(archive, Sections),
|
||||
FileName = binary_to_list(filename:join([aesophia, priv, stdlib, File])),
|
||||
FileName = binary_to_list(filename:join([sophia, priv, stdlib, File])),
|
||||
case zip:extract(Archive, [{file_list, [FileName]}, memory]) of
|
||||
{ok, [{_, Src}]} -> {ok, escript, Src};
|
||||
_ -> {error, not_found}
|
||||
@ -761,12 +761,12 @@ read_file(File, Opts) ->
|
||||
read_file_(Path, File) ->
|
||||
AbsFile = filename:join(Path, File),
|
||||
case file:read_file(AbsFile) of
|
||||
{ok, Bin} -> {ok, aeso_utils:canonical_dir(filename:dirname(AbsFile)), Bin};
|
||||
{ok, Bin} -> {ok, so_utils:canonical_dir(filename:dirname(AbsFile)), Bin};
|
||||
Err -> Err
|
||||
end.
|
||||
|
||||
stdlib_options() ->
|
||||
StdLibDir = aeso_stdlib:stdlib_include_path(),
|
||||
StdLibDir = so_stdlib:stdlib_include_path(),
|
||||
case filelib:is_dir(StdLibDir) of
|
||||
true -> [{include, {file_system, [StdLibDir]}}];
|
||||
false -> [{include, escript}]
|
@ -1,11 +1,12 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc Pretty printer for Sophia.
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_pretty).
|
||||
-module(so_pretty).
|
||||
|
||||
-import(prettypr, [text/1, sep/1, above/2, beside/2, nest/2, empty/0]).
|
||||
|
||||
@ -13,7 +14,7 @@
|
||||
|
||||
-export_type([options/0]).
|
||||
|
||||
-include("aeso_utils.hrl").
|
||||
-include("so_utils.hrl").
|
||||
|
||||
-type doc() :: prettypr:document().
|
||||
-type options() :: [{indent, non_neg_integer()} | show_generated].
|
||||
@ -24,11 +25,11 @@
|
||||
|
||||
%% -- Options ----------------------------------------------------------------
|
||||
|
||||
-define(aeso_pretty_opts, aeso_pretty_opts).
|
||||
-define(so_pretty_opts, so_pretty_opts).
|
||||
|
||||
-spec options() -> options().
|
||||
options() ->
|
||||
case get(?aeso_pretty_opts) of
|
||||
case get(?so_pretty_opts) of
|
||||
undefined -> [];
|
||||
Opts -> Opts
|
||||
end.
|
||||
@ -45,9 +46,9 @@ indent() -> option(indent, 2).
|
||||
|
||||
-spec with_options(options(), fun(() -> A)) -> A.
|
||||
with_options(Options, Fun) ->
|
||||
put(?aeso_pretty_opts, Options),
|
||||
put(?so_pretty_opts, Options),
|
||||
Res = Fun(),
|
||||
erase(?aeso_pretty_opts),
|
||||
erase(?so_pretty_opts),
|
||||
Res.
|
||||
|
||||
%% -- Pretty printing helpers ------------------------------------------------
|
||||
@ -125,9 +126,9 @@ record(Ds) ->
|
||||
equals(A, B) -> follow(hsep(A, text("=")), B).
|
||||
|
||||
%% typed(A, B) -> A : B.
|
||||
-spec typed(doc(), aeso_syntax:type()) -> doc().
|
||||
-spec typed(doc(), so_syntax:type()) -> doc().
|
||||
typed(A, Type) ->
|
||||
case aeso_syntax:get_ann(origin, Type) == system andalso
|
||||
case so_syntax:get_ann(origin, Type) == system andalso
|
||||
not show_generated() of
|
||||
true -> A;
|
||||
false -> follow(hsep(A, text(":")), type(Type))
|
||||
@ -139,18 +140,18 @@ contract_head(contract_interface) -> text("contract interface").
|
||||
|
||||
%% -- Exports ----------------------------------------------------------------
|
||||
|
||||
-spec decls([aeso_syntax:decl()], options()) -> doc().
|
||||
-spec decls([so_syntax:decl()], options()) -> doc().
|
||||
decls(Ds, Options) ->
|
||||
with_options(Options, fun() -> decls(Ds) end).
|
||||
|
||||
-spec decls([aeso_syntax:decl()]) -> doc().
|
||||
-spec decls([so_syntax:decl()]) -> doc().
|
||||
decls(Ds) -> above([ decl(D) || D <- Ds ]).
|
||||
|
||||
-spec decl(aeso_syntax:decl(), options()) -> doc().
|
||||
-spec decl(so_syntax:decl(), options()) -> doc().
|
||||
decl(D, Options) ->
|
||||
with_options(Options, fun() -> decl(D) end).
|
||||
|
||||
-spec decl(aeso_syntax:decl()) -> doc().
|
||||
-spec decl(so_syntax:decl()) -> doc().
|
||||
decl({Con, Attrs, C, Is, Ds}) when ?IS_CONTRACT_HEAD(Con) ->
|
||||
Mod = fun({Mod, true}) when Mod == payable ->
|
||||
text(atom_to_list(Mod));
|
||||
@ -172,7 +173,7 @@ decl({fun_decl, Ann, F, T}) ->
|
||||
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
||||
text(atom_to_list(Mod));
|
||||
(_) -> empty() end,
|
||||
Fun = case aeso_syntax:get_ann(entrypoint, Ann, false) of
|
||||
Fun = case so_syntax:get_ann(entrypoint, Ann, false) of
|
||||
true -> text("entrypoint");
|
||||
false -> text("function")
|
||||
end,
|
||||
@ -181,7 +182,7 @@ decl(D = {letfun, Attrs, _, _, _, _}) ->
|
||||
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
||||
text(atom_to_list(Mod));
|
||||
(_) -> empty() end,
|
||||
Fun = case aeso_syntax:get_ann(entrypoint, Attrs, false) of
|
||||
Fun = case so_syntax:get_ann(entrypoint, Attrs, false) of
|
||||
true -> "entrypoint";
|
||||
false -> "function"
|
||||
end,
|
||||
@ -192,20 +193,20 @@ decl(D = {letval, _, _, _}) -> letdecl("let", D);
|
||||
decl({block, _, Ds}) ->
|
||||
above([ decl(D) || D <- Ds ]).
|
||||
|
||||
-spec pragma(aeso_syntax:pragma()) -> doc().
|
||||
-spec pragma(so_syntax:pragma()) -> doc().
|
||||
pragma({compiler, Op, Ver}) ->
|
||||
text("@compiler " ++ atom_to_list(Op) ++ " " ++ string:join([integer_to_list(N) || N <- Ver], ".")).
|
||||
|
||||
-spec expr(aeso_syntax:expr(), options()) -> doc().
|
||||
-spec expr(so_syntax:expr(), options()) -> doc().
|
||||
expr(E, Options) ->
|
||||
with_options(Options, fun() -> expr(E) end).
|
||||
|
||||
-spec expr(aeso_syntax:expr()) -> doc().
|
||||
-spec expr(so_syntax:expr()) -> doc().
|
||||
expr(E) -> expr_p(0, E).
|
||||
|
||||
%% -- Not exported -----------------------------------------------------------
|
||||
|
||||
-spec name(aeso_syntax:id() | aeso_syntax:qid() | aeso_syntax:con() | aeso_syntax:qcon() | aeso_syntax:tvar()) -> doc().
|
||||
-spec name(so_syntax:id() | so_syntax:qid() | so_syntax:con() | so_syntax:qcon() | so_syntax:tvar()) -> doc().
|
||||
name({id, _, Name}) -> text(Name);
|
||||
name({con, _, Name}) -> text(Name);
|
||||
name({qid, _, Names}) -> text(string:join(Names, "."));
|
||||
@ -213,7 +214,7 @@ name({qcon, _, Names}) -> text(string:join(Names, "."));
|
||||
name({tvar, _, Name}) -> text(Name);
|
||||
name({typed, _, Name, _}) -> name(Name).
|
||||
|
||||
-spec letdecl(string(), aeso_syntax:letbind()) -> doc().
|
||||
-spec letdecl(string(), so_syntax:letbind()) -> doc().
|
||||
letdecl(Let, {letval, _, P, E}) ->
|
||||
block_expr(0, hsep([text(Let), expr(P), text("=")]), E);
|
||||
letdecl(Let, {letfun, _, F, Args, T, [GuardedBody]}) ->
|
||||
@ -221,14 +222,14 @@ letdecl(Let, {letfun, _, F, Args, T, [GuardedBody]}) ->
|
||||
letdecl(Let, {letfun, _, F, Args, T, GuardedBodies}) ->
|
||||
block(hsep([text(Let), typed(beside(name(F), expr({tuple, [], Args})), T)]), above(lists:map(fun(GB) -> guarded_body(GB, "=") end, GuardedBodies))).
|
||||
|
||||
-spec args([aeso_syntax:arg()]) -> doc().
|
||||
-spec args([so_syntax:arg()]) -> doc().
|
||||
args(Args) ->
|
||||
tuple(lists:map(fun arg/1, Args)).
|
||||
|
||||
-spec arg(aeso_syntax:arg()) -> doc().
|
||||
-spec arg(so_syntax:arg()) -> doc().
|
||||
arg({arg, _, X, T}) -> typed(name(X), T).
|
||||
|
||||
-spec typedecl(alias_t | record_t | variant_t, aeso_syntax:id(), [aeso_syntax:tvar()]) -> doc().
|
||||
-spec typedecl(alias_t | record_t | variant_t, so_syntax:id(), [so_syntax:tvar()]) -> doc().
|
||||
typedecl(Kind, T, Vars) ->
|
||||
KW = case Kind of
|
||||
alias_t -> text("type");
|
||||
@ -241,26 +242,26 @@ typedecl(Kind, T, Vars) ->
|
||||
tuple(lists:map(fun name/1, Vars)))
|
||||
end.
|
||||
|
||||
-spec typedef(aeso_syntax:typedef()) -> doc().
|
||||
-spec typedef(so_syntax:typedef()) -> doc().
|
||||
typedef({alias_t, Type}) -> type(Type);
|
||||
typedef({record_t, Fields}) ->
|
||||
record(lists:map(fun field_t/1, Fields));
|
||||
typedef({variant_t, Constructors}) ->
|
||||
par(punctuate(text(" |"), lists:map(fun constructor_t/1, Constructors))).
|
||||
|
||||
-spec constructor_t(aeso_syntax:constructor_t()) -> doc().
|
||||
-spec constructor_t(so_syntax:constructor_t()) -> doc().
|
||||
constructor_t({constr_t, _, C, []}) -> name(C);
|
||||
constructor_t({constr_t, _, C, Args}) -> beside(name(C), args_type(Args)).
|
||||
|
||||
-spec field_t(aeso_syntax:field_t()) -> doc().
|
||||
-spec field_t(so_syntax:field_t()) -> doc().
|
||||
field_t({field_t, _, Name, Type}) ->
|
||||
typed(name(Name), Type).
|
||||
|
||||
-spec type(aeso_syntax:type(), options()) -> doc().
|
||||
-spec type(so_syntax:type(), options()) -> doc().
|
||||
type(Type, Options) ->
|
||||
with_options(Options, fun() -> type(Type) end).
|
||||
|
||||
-spec type(aeso_syntax:type()) -> doc().
|
||||
-spec type(so_syntax:type()) -> doc().
|
||||
type(F = {fun_t, _, _, var_args, _}) ->
|
||||
type(setelement(4, F, [var_args]));
|
||||
type({fun_t, _, Named, Args, Ret}) ->
|
||||
@ -296,11 +297,11 @@ type(T = {tvar, _, _}) -> name(T);
|
||||
|
||||
type(var_args) -> text("var_args").
|
||||
|
||||
-spec args_type([aeso_syntax:type()]) -> doc().
|
||||
-spec args_type([so_syntax:type()]) -> doc().
|
||||
args_type(Args) ->
|
||||
tuple(lists:map(fun type/1, Args)).
|
||||
|
||||
-spec tuple_type([aeso_syntax:type()]) -> doc().
|
||||
-spec tuple_type([so_syntax:type()]) -> doc().
|
||||
tuple_type([]) ->
|
||||
text("unit");
|
||||
tuple_type(Factors) ->
|
||||
@ -310,7 +311,7 @@ tuple_type(Factors) ->
|
||||
, text(")")
|
||||
]).
|
||||
|
||||
-spec expr_p(integer(), aeso_syntax:arg_expr()) -> doc().
|
||||
-spec expr_p(integer(), so_syntax:arg_expr()) -> doc().
|
||||
expr_p(P, {letpat, _, Id, Pat}) ->
|
||||
paren(P > 100, follow(hsep(expr(Id), text("=")), expr(Pat)));
|
||||
expr_p(P, {named_arg, _, Name, E}) ->
|
||||
@ -318,7 +319,7 @@ expr_p(P, {named_arg, _, Name, E}) ->
|
||||
expr_p(P, {lam, _, Args, E}) ->
|
||||
paren(P > 100, follow(hsep(args(Args), text("=>")), expr_p(100, E)));
|
||||
expr_p(P, If = {'if', Ann, Cond, Then, Else}) ->
|
||||
Format = aeso_syntax:get_ann(format, If),
|
||||
Format = so_syntax:get_ann(format, If),
|
||||
if Format == '?:' ->
|
||||
paren(P > 100,
|
||||
follow(expr_p(200, Cond),
|
||||
@ -361,7 +362,7 @@ expr_p(P, {assign, _, LV, E}) ->
|
||||
expr_p(_, {app, _, {'..', _}, [A, B]}) ->
|
||||
list([infix(0, '..', A, B)]);
|
||||
expr_p(P, E = {app, _, F = {Op, _}, Args}) when is_atom(Op) ->
|
||||
case {aeso_syntax:get_ann(format, E), Args} of
|
||||
case {so_syntax:get_ann(format, E), Args} of
|
||||
{infix, [A, B]} -> infix(P, Op, A, B);
|
||||
{prefix, [A]} -> prefix(P, Op, A);
|
||||
_ -> app(P, F, Args)
|
||||
@ -372,7 +373,7 @@ expr_p(P, {app, _, F, Args}) ->
|
||||
app(P, F, Args);
|
||||
%% -- Constants
|
||||
expr_p(_, E = {int, _, N}) ->
|
||||
S = case aeso_syntax:get_ann(format, E) of
|
||||
S = case so_syntax:get_ann(format, E) of
|
||||
hex -> "0x" ++ integer_to_list(N, 16);
|
||||
_ -> integer_to_list(N)
|
||||
end,
|
||||
@ -389,7 +390,7 @@ expr_p(_, {Type, _, Bin})
|
||||
Type == oracle_pubkey;
|
||||
Type == oracle_query_id;
|
||||
Type == signature ->
|
||||
text(binary_to_list(aeser_api_encoder:encode(Type, Bin)));
|
||||
text(binary_to_list(gmser_api_encoder:encode(Type, Bin)));
|
||||
expr_p(_, {string, _, <<>>}) -> text("\"\"");
|
||||
expr_p(_, {string, _, S}) ->
|
||||
text(io_lib:format("\"~s\"", [binary_to_list(S)]));
|
||||
@ -402,7 +403,7 @@ expr_p(_, {char, _, C}) ->
|
||||
text("'" ++ tl(lists:droplast(S)) ++ "'");
|
||||
_ ->
|
||||
S = lists:flatten(
|
||||
io_lib:format("'~ts'", [list_to_binary(aeso_scan:utf8_encode([C]))])),
|
||||
io_lib:format("'~ts'", [list_to_binary(so_scan:utf8_encode([C]))])),
|
||||
text(S)
|
||||
end;
|
||||
%% -- Names
|
||||
@ -421,7 +422,7 @@ stmt_p({elif, _, Cond, Then}) ->
|
||||
block_expr(200, beside(text("elif"), paren(expr(Cond))), Then);
|
||||
stmt_p({'else', Else}) ->
|
||||
HideGenerated = not show_generated(),
|
||||
case aeso_syntax:get_ann(origin, Else) of
|
||||
case so_syntax:get_ann(origin, Else) of
|
||||
system when HideGenerated -> empty();
|
||||
_ -> block_expr(200, text("else"), Else)
|
||||
end.
|
||||
@ -433,7 +434,7 @@ lc_bind({comprehension_if, _, E}) ->
|
||||
lc_bind(Let) ->
|
||||
letdecl("let", Let).
|
||||
|
||||
-spec bin_prec(aeso_syntax:bin_op()) -> {integer(), integer(), integer()}.
|
||||
-spec bin_prec(so_syntax:bin_op()) -> {integer(), integer(), integer()}.
|
||||
bin_prec('..') -> { 0, 0, 0}; %% Always printed inside '[ ]'
|
||||
bin_prec('=') -> { 0, 0, 0}; %% Always printed inside '[ ]'
|
||||
bin_prec('@') -> { 0, 0, 0}; %% Only in error messages
|
||||
@ -460,7 +461,7 @@ bin_prec('/') -> {700, 700, 750};
|
||||
bin_prec(mod) -> {700, 700, 750};
|
||||
bin_prec('^') -> {750, 750, 800}.
|
||||
|
||||
-spec un_prec(aeso_syntax:un_op()) -> {integer(), integer()}.
|
||||
-spec un_prec(so_syntax:un_op()) -> {integer(), integer()}.
|
||||
un_prec('-') -> {650, 650};
|
||||
un_prec('!') -> {800, 800};
|
||||
un_prec('bnot') -> {850, 850}.
|
||||
@ -468,7 +469,7 @@ un_prec('bnot') -> {850, 850}.
|
||||
equals(Ann, A, B) ->
|
||||
{app, [{format, infix} | Ann], {'=', Ann}, [A, B]}.
|
||||
|
||||
-spec infix(integer(), aeso_syntax:bin_op(), aeso_syntax:expr(), aeso_syntax:expr()) -> doc().
|
||||
-spec infix(integer(), so_syntax:bin_op(), so_syntax:expr(), so_syntax:expr()) -> doc().
|
||||
infix(P, Op, A, B) ->
|
||||
{Top, L, R} = bin_prec(Op),
|
||||
paren(P > Top,
|
||||
@ -530,7 +531,7 @@ statement(E) -> expr(E).
|
||||
get_elifs(Expr) -> get_elifs(Expr, []).
|
||||
|
||||
get_elifs(If = {'if', Ann, Cond, Then, Else}, Elifs) ->
|
||||
case aeso_syntax:get_ann(format, If) of
|
||||
case so_syntax:get_ann(format, If) of
|
||||
elif -> get_elifs(Else, [{elif, Ann, Cond, Then} | Elifs]);
|
||||
_ -> {lists:reverse(Elifs), If}
|
||||
end;
|
@ -1,15 +1,16 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc The Sophia lexer.
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_scan).
|
||||
-module(so_scan).
|
||||
|
||||
-export([scan/1, utf8_encode/1]).
|
||||
|
||||
-import(aeso_scan_lib, [token/1, token/2, symbol/0, skip/0,
|
||||
-import(so_scan_lib, [token/1, token/2, symbol/0, skip/0,
|
||||
override/2, push/2, pop/1]).
|
||||
|
||||
lexer() ->
|
||||
@ -79,8 +80,8 @@ lexer() ->
|
||||
[{code, Rules}, {comment, CommentRules}].
|
||||
|
||||
scan(String) ->
|
||||
Lexer = aeso_scan_lib:compile(lexer()),
|
||||
aeso_scan_lib:string(Lexer, code, String).
|
||||
Lexer = so_scan_lib:compile(lexer()),
|
||||
so_scan_lib:string(Lexer, code, String).
|
||||
|
||||
%% -- Helpers ----------------------------------------------------------------
|
||||
|
@ -1,10 +1,11 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc A customisable lexer.
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_scan_lib).
|
||||
-module(so_scan_lib).
|
||||
|
||||
-export([compile/1, string/3,
|
||||
token/1, token/2, symbol/0, skip/0,
|
@ -1,17 +1,16 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Radosław Rowicki
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Standard library for Sophia
|
||||
%%% @end
|
||||
%%% Created : 6 July 2019
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_stdlib).
|
||||
-module(so_stdlib).
|
||||
|
||||
-export([stdlib_include_path/0]).
|
||||
|
||||
stdlib_include_path() ->
|
||||
filename:join([code:priv_dir(aesophia), "stdlib"]).
|
||||
filename:join([code:priv_dir(sophia), "stdlib"]).
|
||||
|
@ -1,12 +1,13 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc Sophia abstract syntax types.
|
||||
%%%
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_syntax).
|
||||
-module(so_syntax).
|
||||
|
||||
-export([get_ann/1, get_ann/2, get_ann/3, set_ann/2, qualify/2]).
|
||||
|
@ -1,10 +1,11 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Sophia syntax utilities.
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_syntax_utils).
|
||||
-module(so_syntax_utils).
|
||||
|
||||
-export([used_ids/1, used_ids/2, used_types/2, used/1]).
|
||||
|
||||
@ -17,19 +18,19 @@
|
||||
-type kind() :: decl | type | bind_type | expr | bind_expr.
|
||||
|
||||
-spec fold(alg(A), fun((kind(), _) -> A), kind(), E | [E]) -> A
|
||||
when E :: aeso_syntax:decl()
|
||||
| aeso_syntax:typedef()
|
||||
| aeso_syntax:field_t()
|
||||
| aeso_syntax:constructor_t()
|
||||
| aeso_syntax:type()
|
||||
| aeso_syntax:expr()
|
||||
| aeso_syntax:pat()
|
||||
| aeso_syntax:arg()
|
||||
| aeso_syntax:alt()
|
||||
| aeso_syntax:elim()
|
||||
| aeso_syntax:arg_expr()
|
||||
| aeso_syntax:field(aeso_syntax:expr())
|
||||
| aeso_syntax:stmt().
|
||||
when E :: so_syntax:decl()
|
||||
| so_syntax:typedef()
|
||||
| so_syntax:field_t()
|
||||
| so_syntax:constructor_t()
|
||||
| so_syntax:type()
|
||||
| so_syntax:expr()
|
||||
| so_syntax:pat()
|
||||
| so_syntax:arg()
|
||||
| so_syntax:alt()
|
||||
| so_syntax:elim()
|
||||
| so_syntax:arg_expr()
|
||||
| so_syntax:field(so_syntax:expr())
|
||||
| so_syntax:stmt().
|
||||
fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) ->
|
||||
ExprKind = if K == bind_expr -> bind_expr; true -> expr end,
|
||||
TypeKind = if K == bind_type -> bind_type; true -> type end,
|
||||
@ -132,7 +133,7 @@ used_types([Top] = _CurrentNS, T) ->
|
||||
| {type, [string()]}
|
||||
| {namespace, [string()]}.
|
||||
|
||||
-spec entity_alg() -> alg(#{entity() => aeso_syntax:ann()}).
|
||||
-spec entity_alg() -> alg(#{entity() => so_syntax:ann()}).
|
||||
entity_alg() ->
|
||||
IsBound = fun({K, _}) -> lists:member(K, [bound_term, bound_type]) end,
|
||||
Unbind = fun(bound_term) -> term; (bound_type) -> type end,
|
||||
@ -147,7 +148,7 @@ entity_alg() ->
|
||||
, plus = fun maps:merge/2
|
||||
, scoped = Scoped }.
|
||||
|
||||
-spec used(_) -> [{entity(), aeso_syntax:ann()}].
|
||||
-spec used(_) -> [{entity(), so_syntax:ann()}].
|
||||
used(D) ->
|
||||
Kind = fun(expr) -> term;
|
||||
(bind_expr) -> bound_term;
|
@ -1,10 +1,11 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Sophia utility functions.
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(aeso_utils).
|
||||
-module(so_utils).
|
||||
|
||||
-export([scc/1, canonical_dir/1]).
|
||||
|
@ -1,22 +1,21 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2025, QPQ AG
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc Decoding fate data to AST
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_vm_decode).
|
||||
-module(so_vm_decode).
|
||||
|
||||
-export([ from_fate/2 ]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_fate_data.hrl").
|
||||
-include_lib("gmbytecode/include/gmb_fate_data.hrl").
|
||||
|
||||
-spec from_fate(aeso_syntax:type(), aeb_fate_data:fate_type()) -> aeso_syntax:expr().
|
||||
-spec from_fate(so_syntax:type(), gmb_fate_data:fate_type()) -> so_syntax:expr().
|
||||
from_fate({id, _, "address"}, ?FATE_ADDRESS(Bin)) -> {account_pubkey, [], Bin};
|
||||
from_fate({id, _, "signature"}, ?FATE_BYTES(Bin)) -> {signature, [], Bin};
|
||||
from_fate({id, _, "hash"}, ?FATE_BYTES(Bin)) -> {bytes, [], Bin};
|
||||
from_fate({id, _, "unit"}, ?FATE_UNIT) -> {tuple, [], []};
|
||||
from_fate({app_t, _, {id, _, "oracle"}, _}, ?FATE_ORACLE(Bin)) -> {oracle_pubkey, [], Bin};
|
||||
from_fate({app_t, _, {id, _, "oracle_query"}, _}, ?FATE_ORACLE_Q(Bin)) -> {oracle_query_id, [], Bin};
|
||||
from_fate({con, _, _Name}, ?FATE_CONTRACT(Bin)) -> {contract_pubkey, [], Bin};
|
||||
from_fate({bytes_t, _, any}, ?FATE_BYTES(Bin)) -> make_any_bytes(Bin);
|
||||
from_fate({bytes_t, _, N}, ?FATE_BYTES(Bin)) when byte_size(Bin) == N -> {bytes, [], Bin};
|
@ -1,6 +1,6 @@
|
||||
-module(aeso_warnings).
|
||||
-module(so_warnings).
|
||||
|
||||
-record(warn, { pos :: aeso_errors:pos()
|
||||
-record(warn, { pos :: so_errors:pos()
|
||||
, message :: iolist()
|
||||
}).
|
||||
|
||||
@ -16,16 +16,16 @@
|
||||
]).
|
||||
|
||||
new(Msg) ->
|
||||
new(aeso_errors:pos(0, 0), Msg).
|
||||
new(so_errors:pos(0, 0), Msg).
|
||||
|
||||
new(Pos, Msg) ->
|
||||
#warn{ pos = Pos, message = Msg }.
|
||||
|
||||
warn_to_err(Kind, #warn{ pos = Pos, message = Msg }) ->
|
||||
aeso_errors:new(Kind, Pos, lists:flatten(Msg)).
|
||||
so_errors:new(Kind, Pos, lists:flatten(Msg)).
|
||||
|
||||
sort_warnings(Warnings) ->
|
||||
lists:sort(fun(W1, W2) -> W1#warn.pos =< W2#warn.pos end, Warnings).
|
||||
|
||||
pp(#warn{ pos = Pos, message = Msg }) ->
|
||||
lists:flatten(io_lib:format("Warning~s:\n~s", [aeso_errors:pp_pos(Pos), Msg])).
|
||||
lists:flatten(io_lib:format("Warning~s:\n~s", [so_errors:pp_pos(Pos), Msg])).
|
@ -1,5 +1,5 @@
|
||||
{application, aesophia,
|
||||
[{description, "Compiler for Aeternity Sophia language"},
|
||||
{application, sophia,
|
||||
[{description, "Compiler for Sophia language"},
|
||||
{vsn, "8.0.1"},
|
||||
{registered, []},
|
||||
{applications,
|
||||
@ -7,7 +7,7 @@
|
||||
stdlib,
|
||||
jsx,
|
||||
syntax_tools,
|
||||
aebytecode,
|
||||
gmbytecode,
|
||||
eblake2
|
||||
]},
|
||||
{env,[]},
|
@ -1,22 +0,0 @@
|
||||
-module(aeso_eunit_SUITE).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-include_lib("common_test/include/ct.hrl").
|
||||
|
||||
all() ->
|
||||
[{group, eunit}].
|
||||
|
||||
groups() ->
|
||||
[{eunit, [], [ aeso_scan_tests
|
||||
, aeso_parser_tests
|
||||
, aeso_compiler_tests
|
||||
, aeso_abi_tests
|
||||
, aeso_aci_tests
|
||||
]}].
|
||||
|
||||
aeso_scan_tests(_Config) -> ok = eunit:test(aeso_scan_tests).
|
||||
aeso_parser_tests(_Config) -> ok = eunit:test(aeso_parser_tests).
|
||||
aeso_compiler_tests(_Config) -> ok = eunit:test(aeso_compiler_tests).
|
||||
aeso_abi_tests(_Config) -> ok = eunit:test(aeso_abi_tests).
|
||||
aeso_aci_tests(_Config) -> ok = eunit:test(aeso_aci_tests).
|
@ -2,27 +2,12 @@ contract interface Remote =
|
||||
entrypoint main_fun : (int) => unit
|
||||
|
||||
contract AddrChain =
|
||||
type o_type = oracle(string, map(string, int))
|
||||
type oq_type = oracle_query(string, map(string, int))
|
||||
|
||||
entrypoint is_o(a : address) =
|
||||
Address.is_oracle(a)
|
||||
|
||||
entrypoint is_c(a : address) =
|
||||
Address.is_contract(a)
|
||||
|
||||
// entrypoint get_o(a : address) : option(o_type) =
|
||||
// Address.get_oracle(a)
|
||||
|
||||
// entrypoint get_c(a : address) : option(Remote) =
|
||||
// Address.get_contract(a)
|
||||
|
||||
entrypoint check_o(o : o_type) =
|
||||
Oracle.check(o)
|
||||
|
||||
entrypoint check_oq(o : o_type, oq : oq_type) =
|
||||
Oracle.check_query(o, oq)
|
||||
|
||||
// entrypoint h_to_i(h : hash) : int =
|
||||
// Hash.to_int(h)
|
||||
|
||||
|
@ -5,10 +5,6 @@ contract interface Remote =
|
||||
contract AddressLiterals =
|
||||
entrypoint addr() : address =
|
||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||
entrypoint oracle() : oracle(int, bool) =
|
||||
ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
entrypoint query() : oracle_query(int, bool) =
|
||||
oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
entrypoint contr() : Remote =
|
||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||
entrypoint contr_addr() : Remote =
|
||||
|
@ -14,12 +14,6 @@ main contract AENSTest =
|
||||
stateful entrypoint resolve_contract(name : string, key : string) : option(C) =
|
||||
AENSv2.resolve(name, key)
|
||||
|
||||
stateful entrypoint resolve_oracle(name : string, key : string) : option(oracle(int, int)) =
|
||||
AENSv2.resolve(name, key)
|
||||
|
||||
stateful entrypoint resolve_oracle_query(name : string, key : string) : option(oracle_query(int, int)) =
|
||||
AENSv2.resolve(name, key)
|
||||
|
||||
// Transactions
|
||||
|
||||
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
||||
|
@ -14,7 +14,7 @@ main contract AENSUpdate =
|
||||
let p5 : AENSv2.pointee = AENSv2.DataPt(String.to_bytes("any something will do"))
|
||||
let p6 : AENSv2.pointee = AENSv2.DataPt(Int.to_bytes(1345, 4))
|
||||
AENSv2.update(owner, name, None, None,
|
||||
Some({ ["account_pubkey"] = p1, ["oracle_pubkey"] = p2,
|
||||
Some({ ["account_pubkey"] = p1,
|
||||
["contract_pubkey"] = p3, ["misc"] = p4, ["data"] = p5, ["data2"] = p6 }))
|
||||
|
||||
stateful entrypoint old_interaction(c : OldAENSContract, owner : address, name : string) =
|
||||
@ -27,6 +27,3 @@ main contract AENSUpdate =
|
||||
entrypoint get_ttl(name : string) =
|
||||
switch(AENSv2.lookup(name))
|
||||
Some(AENSv2.Name(_, FixedTTL(ttl), _)) => ttl
|
||||
|
||||
entrypoint expiry(o : oracle(int, int)) : int =
|
||||
Oracle.expiry(o)
|
||||
|
@ -7,27 +7,9 @@ contract AddressLiterals =
|
||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||
entrypoint addr2() : Remote =
|
||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||
entrypoint addr3() : oracle(int, bool) =
|
||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||
|
||||
entrypoint oracle1() : oracle_query(int, bool) =
|
||||
ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
entrypoint oracle2() : bytes(32) =
|
||||
ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
entrypoint oracle3() : Remote =
|
||||
ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
|
||||
entrypoint query1() : oracle(int, bool) =
|
||||
oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
entrypoint query2() : bytes(32) =
|
||||
oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
entrypoint query3() : Remote =
|
||||
oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
|
||||
entrypoint contr1() : address =
|
||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||
entrypoint contr2() : oracle(int, bool) =
|
||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||
entrypoint contr3() : bytes(32) =
|
||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||
entrypoint contr4() : address =
|
||||
|
@ -11,8 +11,6 @@ contract Events =
|
||||
type ix5 = hash // bytes(32)
|
||||
type ix6 = address
|
||||
type ix7 = Remote
|
||||
type ix8 = oracle(int, int)
|
||||
type ix9 = oracle_query(int, int)
|
||||
|
||||
// Valid payload types
|
||||
type data1 = string
|
||||
@ -26,7 +24,6 @@ contract Events =
|
||||
| Nodata3(ix4, ix5, ix6)
|
||||
| Data0(data1)
|
||||
| Data1(data2, ix7)
|
||||
| Data2(ix8, data3, ix9)
|
||||
| Data3(ix1, ix2, ix5, data1)
|
||||
|
||||
entrypoint nodata0() = Chain.event(Nodata0)
|
||||
@ -35,6 +32,5 @@ contract Events =
|
||||
entrypoint nodata3(ix4, ix5, ix6) = Chain.event(Nodata3(ix4, ix5, ix6))
|
||||
entrypoint data0(data1) = Chain.event(Data0(data1))
|
||||
entrypoint data1(data2, ix7) = Chain.event(Data1(data2, ix7))
|
||||
entrypoint data2(ix8, data3, ix9) = Chain.event(Data2(ix8, data3, ix9))
|
||||
entrypoint data3(ix1, ix2, ix5, data1) = Chain.event(Data3(ix1, ix2, ix5, data1))
|
||||
|
||||
|
@ -31,12 +31,6 @@ contract FunctionArguments =
|
||||
entrypoint trettiotva(b : bytes(32)) =
|
||||
b
|
||||
|
||||
entrypoint find_oracle(o : oracle(int, bool)) =
|
||||
true
|
||||
|
||||
entrypoint find_query(q : oracle_query(int, bool)) =
|
||||
true
|
||||
|
||||
datatype colour() = Green | Yellow | Red | Pantone(int)
|
||||
|
||||
entrypoint traffic_light(c : colour) =
|
||||
|
@ -1,5 +0,0 @@
|
||||
contract HigherOrderQueryType =
|
||||
stateful function foo(o) : oracle_query(_, string ) =
|
||||
Oracle.query(o, (x) => x + 1, 100, RelativeTTL(100), RelativeTTL(100))
|
||||
|
||||
entrypoint main_fun() = ()
|
@ -1,5 +0,0 @@
|
||||
contract HigherOrderResponseType =
|
||||
stateful function foo(o, q : oracle_query(string, _)) =
|
||||
Oracle.respond(o, q, (x) => x + 1)
|
||||
|
||||
entrypoint main_fun() = ()
|
@ -1,110 +0,0 @@
|
||||
contract Oracles =
|
||||
|
||||
type fee = int
|
||||
type ttl = Chain.ttl
|
||||
|
||||
type query_t = string
|
||||
type answer_t = int
|
||||
|
||||
type oracle_id = oracle(query_t, answer_t)
|
||||
type query_id = oracle_query(query_t, answer_t)
|
||||
|
||||
stateful entrypoint registerOracle(acct : address,
|
||||
qfee : fee,
|
||||
ttl : ttl) : oracle_id =
|
||||
Oracle.register(acct, qfee, ttl)
|
||||
|
||||
stateful entrypoint registerIntIntOracle(acct : address,
|
||||
qfee : fee,
|
||||
ttl : ttl) : oracle(int, int) =
|
||||
Oracle.register(acct, qfee, ttl)
|
||||
|
||||
stateful entrypoint registerStringStringOracle(acct : address,
|
||||
qfee : fee,
|
||||
ttl : ttl) : oracle(string, string) =
|
||||
Oracle.register(acct, qfee, ttl)
|
||||
|
||||
stateful entrypoint signedRegisterOracle(acct : address,
|
||||
sign : signature,
|
||||
qfee : fee,
|
||||
ttl : ttl) : oracle_id =
|
||||
Oracle.register(acct, qfee, ttl, signature = sign)
|
||||
|
||||
entrypoint queryFee(o : oracle_id) : fee =
|
||||
Oracle.query_fee(o)
|
||||
|
||||
stateful entrypoint createQuery(o : oracle_id,
|
||||
q : query_t,
|
||||
qfee : fee,
|
||||
qttl : ttl,
|
||||
rttl : ttl) : query_id =
|
||||
require(qfee =< Call.value, "insufficient value for qfee")
|
||||
Oracle.query(o, q, qfee, qttl, rttl)
|
||||
|
||||
// Do not use in production!
|
||||
stateful entrypoint unsafeCreateQuery(o : oracle_id,
|
||||
q : query_t,
|
||||
qfee : fee,
|
||||
qttl : ttl,
|
||||
rttl : ttl) : query_id =
|
||||
Oracle.query(o, q, qfee, qttl, rttl)
|
||||
|
||||
// Do not use in production!
|
||||
stateful entrypoint unsafeCreateQueryThenErr(o : oracle_id,
|
||||
q : query_t,
|
||||
qfee : fee,
|
||||
qttl : ttl,
|
||||
rttl : ttl) : query_id =
|
||||
let res = Oracle.query(o, q, qfee, qttl, rttl)
|
||||
require(qfee >= 100000000000000000, "causing a late error")
|
||||
res
|
||||
|
||||
stateful entrypoint extendOracle(o : oracle_id,
|
||||
ttl : ttl) : unit =
|
||||
Oracle.extend(o, ttl)
|
||||
|
||||
stateful entrypoint signedExtendOracle(o : oracle_id,
|
||||
sign : signature, // Signed oracle address
|
||||
ttl : ttl) : unit =
|
||||
Oracle.extend(o, signature = sign, ttl)
|
||||
|
||||
stateful entrypoint respond(o : oracle_id,
|
||||
q : query_id,
|
||||
r : answer_t) : unit =
|
||||
Oracle.respond(o, q, r)
|
||||
|
||||
stateful entrypoint signedRespond(o : oracle_id,
|
||||
q : query_id,
|
||||
sign : signature,
|
||||
r : answer_t) : unit =
|
||||
Oracle.respond(o, q, signature = sign, r)
|
||||
|
||||
entrypoint getQuestion(o : oracle_id,
|
||||
q : query_id) : query_t =
|
||||
Oracle.get_question(o, q)
|
||||
|
||||
entrypoint hasAnswer(o : oracle_id,
|
||||
q : query_id) =
|
||||
switch(Oracle.get_answer(o, q))
|
||||
None => false
|
||||
Some(_) => true
|
||||
|
||||
entrypoint getAnswer(o : oracle_id,
|
||||
q : query_id) : option(answer_t) =
|
||||
Oracle.get_answer(o, q)
|
||||
|
||||
datatype complexQuestion = Why(int) | How(string)
|
||||
datatype complexAnswer = NoAnswer | Answer(complexQuestion, string, int)
|
||||
|
||||
stateful entrypoint complexOracle(question) =
|
||||
let o = Oracle.register(Contract.address, 0, FixedTTL(1000)) : oracle(complexQuestion, complexAnswer)
|
||||
let q = Oracle.query(o, question, 0, RelativeTTL(100), RelativeTTL(100))
|
||||
Oracle.respond(o, q, Answer(question, "magic", 1337))
|
||||
Oracle.get_answer(o, q)
|
||||
|
||||
stateful entrypoint signedComplexOracle(question, sig) =
|
||||
let o = Oracle.register(signature = sig, Contract.address, 0, FixedTTL(1000)) : oracle(complexQuestion, complexAnswer)
|
||||
let q = Oracle.query(o, question, 0, RelativeTTL(100), RelativeTTL(100))
|
||||
Oracle.respond(o, q, Answer(question, "magic", 1337), signature = sig)
|
||||
Oracle.get_answer(o, q)
|
||||
|
@ -1,5 +0,0 @@
|
||||
contract PolymorphicQueryType =
|
||||
stateful function is_oracle(o) =
|
||||
Oracle.check(o)
|
||||
|
||||
entrypoint main_fun() = ()
|
@ -1,5 +0,0 @@
|
||||
contract PolymorphicResponseType =
|
||||
function is_oracle(o : oracle(string, 'r)) =
|
||||
Oracle.check(o)
|
||||
|
||||
entrypoint main_fun(o : oracle(string, int)) = is_oracle(o)
|
@ -1,47 +0,0 @@
|
||||
contract interface Animal =
|
||||
entrypoint sound : () => string
|
||||
|
||||
contract Cat : Animal =
|
||||
entrypoint sound() = "meow"
|
||||
|
||||
main contract Main =
|
||||
entrypoint oracle() = ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
|
||||
entrypoint query() = oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
|
||||
entrypoint init() =
|
||||
let o01 : oracle(Animal, Animal) = oracle() : oracle(Animal, Animal) // success
|
||||
let o02 : oracle(Animal, Animal) = oracle() : oracle(Animal, Cat) // success
|
||||
let o03 : oracle(Animal, Animal) = oracle() : oracle(Cat, Animal) // fail
|
||||
let o04 : oracle(Animal, Animal) = oracle() : oracle(Cat, Cat) // fail
|
||||
let o05 : oracle(Animal, Cat) = oracle() : oracle(Animal, Animal) // fail
|
||||
let o06 : oracle(Animal, Cat) = oracle() : oracle(Animal, Cat) // success
|
||||
let o07 : oracle(Animal, Cat) = oracle() : oracle(Cat, Animal) // fail
|
||||
let o08 : oracle(Animal, Cat) = oracle() : oracle(Cat, Cat) // fail
|
||||
let o09 : oracle(Cat, Animal) = oracle() : oracle(Animal, Animal) // success
|
||||
let o10 : oracle(Cat, Animal) = oracle() : oracle(Animal, Cat) // success
|
||||
let o11 : oracle(Cat, Animal) = oracle() : oracle(Cat, Animal) // success
|
||||
let o12 : oracle(Cat, Animal) = oracle() : oracle(Cat, Cat) // success
|
||||
let o13 : oracle(Cat, Cat) = oracle() : oracle(Animal, Animal) // fail
|
||||
let o14 : oracle(Cat, Cat) = oracle() : oracle(Animal, Cat) // success
|
||||
let o15 : oracle(Cat, Cat) = oracle() : oracle(Cat, Animal) // fail
|
||||
let o16 : oracle(Cat, Cat) = oracle() : oracle(Cat, Cat) // success
|
||||
|
||||
let q01 : oracle_query(Animal, Animal) = query() : oracle_query(Animal, Animal) // success
|
||||
let q02 : oracle_query(Animal, Animal) = query() : oracle_query(Animal, Cat) // success
|
||||
let q03 : oracle_query(Animal, Animal) = query() : oracle_query(Cat, Animal) // success
|
||||
let q04 : oracle_query(Animal, Animal) = query() : oracle_query(Cat, Cat) // success
|
||||
let q05 : oracle_query(Animal, Cat) = query() : oracle_query(Animal, Animal) // fail
|
||||
let q06 : oracle_query(Animal, Cat) = query() : oracle_query(Animal, Cat) // success
|
||||
let q07 : oracle_query(Animal, Cat) = query() : oracle_query(Cat, Animal) // fail
|
||||
let q08 : oracle_query(Animal, Cat) = query() : oracle_query(Cat, Cat) // success
|
||||
let q09 : oracle_query(Cat, Animal) = query() : oracle_query(Animal, Animal) // fail
|
||||
let q10 : oracle_query(Cat, Animal) = query() : oracle_query(Animal, Cat) // fail
|
||||
let q11 : oracle_query(Cat, Animal) = query() : oracle_query(Cat, Animal) // success
|
||||
let q12 : oracle_query(Cat, Animal) = query() : oracle_query(Cat, Cat) // success
|
||||
let q13 : oracle_query(Cat, Cat) = query() : oracle_query(Animal, Animal) // fail
|
||||
let q14 : oracle_query(Cat, Cat) = query() : oracle_query(Animal, Cat) // fail
|
||||
let q15 : oracle_query(Cat, Cat) = query() : oracle_query(Cat, Animal) // fail
|
||||
let q16 : oracle_query(Cat, Cat) = query() : oracle_query(Cat, Cat) // success
|
||||
|
||||
()
|
@ -1,5 +1,5 @@
|
||||
// This is a custom test file if you need to run a compiler without
|
||||
// changing aeso_compiler_tests.erl
|
||||
// changing so_compiler_tests.erl
|
||||
|
||||
include "List.aes"
|
||||
|
||||
|
@ -28,8 +28,6 @@ contract C =
|
||||
let c16 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
||||
let c17 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
||||
let c18 = RelativeTTL(50)
|
||||
let c19 = ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
||||
let c20 = oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
||||
let c21 = ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ : C
|
||||
let c22 = N.nsconst
|
||||
let c23 = c01
|
||||
@ -54,8 +52,6 @@ contract C =
|
||||
entrypoint f16() = c16
|
||||
entrypoint f17() = c17
|
||||
entrypoint f18() = c18
|
||||
entrypoint f19() = c19
|
||||
entrypoint f20() = c20
|
||||
entrypoint f21() = c21
|
||||
entrypoint f22() = c22
|
||||
entrypoint f23() = c23
|
||||
|
@ -1,16 +1,12 @@
|
||||
// Builtins without named arguments can appear unapplied.
|
||||
// Named argument builtins are:
|
||||
// Oracle.register
|
||||
// Oracle.respond
|
||||
// AENSv2.preclaim
|
||||
// AENSv2.claim
|
||||
// AENSv2.transfer
|
||||
// AENSv2.revoke
|
||||
// Oracle.extend
|
||||
include "String.aes"
|
||||
contract UnappliedBuiltins =
|
||||
entrypoint main_fun() = ()
|
||||
type o = oracle(int, int)
|
||||
type t = list(int * string)
|
||||
type m = map(int, int)
|
||||
datatype event = Event(int)
|
||||
@ -21,13 +17,6 @@ contract UnappliedBuiltins =
|
||||
function call_gas_left() = Call.gas_left
|
||||
function b_abort() = abort
|
||||
function b_require() = require
|
||||
function oracle_query_fee() = Oracle.query_fee
|
||||
function oracle_expiry() = Oracle.expiry
|
||||
stateful function oracle_query() = Oracle.query : (o, _, _, _, _) => _
|
||||
function oracle_get_question() = Oracle.get_question : (o, _) => _
|
||||
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 map_lookup() = Map.lookup : (_, m) => _
|
||||
function map_lookup_default() = Map.lookup_default : (_, m, _) => _
|
||||
@ -57,7 +46,6 @@ contract UnappliedBuiltins =
|
||||
function bits_sum() = Bits.sum
|
||||
function int_to_str() = Int.to_str
|
||||
function address_to_str() = Address.to_str
|
||||
function address_is_oracle() = Address.is_oracle
|
||||
function address_is_contract() = Address.is_contract
|
||||
function address_is_payable() = Address.is_payable
|
||||
function bytes_to_int() = Bytes.to_int : bytes(10) => int
|
||||
|
@ -1,4 +0,0 @@
|
||||
contract UnappliedNamedArgBuiltin =
|
||||
stateful entrypoint main_fun(s) =
|
||||
let reg = Oracle.register
|
||||
reg(signature = s, Contract.address, 100, RelativeTTL(100)) : oracle(int, int)
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_abi_tests).
|
||||
-module(so_abi_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
@ -65,15 +65,15 @@ to_sophia_value_mcl_bls12_381_test() ->
|
||||
|
||||
Opts = [{backend, fate}],
|
||||
|
||||
CallValue32 = aeb_fate_encoding:serialize({bytes, <<20:256>>}),
|
||||
CallValue48 = aeb_fate_encoding:serialize({bytes, <<55:384>>}),
|
||||
CallValueTp = aeb_fate_encoding:serialize({tuple, {{bytes, <<15:256>>}, {bytes, <<160:256>>}, {bytes, <<1234:256>>}}}),
|
||||
CallValue32 = gmb_fate_encoding:serialize({bytes, <<20:256>>}),
|
||||
CallValue48 = gmb_fate_encoding:serialize({bytes, <<55:384>>}),
|
||||
CallValueTp = gmb_fate_encoding:serialize({tuple, {{bytes, <<15:256>>}, {bytes, <<160:256>>}, {bytes, <<1234:256>>}}}),
|
||||
|
||||
{ok, _} = aeso_compiler:to_sophia_value(Code, "test_bls12_381_fp", ok, CallValue32, Opts),
|
||||
{error, _} = aeso_compiler:to_sophia_value(Code, "test_bls12_381_fp", ok, CallValue48, Opts),
|
||||
{ok, _} = aeso_compiler:to_sophia_value(Code, "test_bls12_381_fr", ok, CallValue48, Opts),
|
||||
{error, _} = aeso_compiler:to_sophia_value(Code, "test_bls12_381_fr", ok, CallValue32, Opts),
|
||||
{ok, _} = aeso_compiler:to_sophia_value(Code, "test_bls12_381_g1", ok, CallValueTp, Opts),
|
||||
{ok, _} = so_compiler:to_sophia_value(Code, "test_bls12_381_fp", ok, CallValue32, Opts),
|
||||
{error, _} = so_compiler:to_sophia_value(Code, "test_bls12_381_fp", ok, CallValue48, Opts),
|
||||
{ok, _} = so_compiler:to_sophia_value(Code, "test_bls12_381_fr", ok, CallValue48, Opts),
|
||||
{error, _} = so_compiler:to_sophia_value(Code, "test_bls12_381_fr", ok, CallValue32, Opts),
|
||||
{ok, _} = so_compiler:to_sophia_value(Code, "test_bls12_381_g1", ok, CallValueTp, Opts),
|
||||
|
||||
ok.
|
||||
|
||||
@ -81,11 +81,11 @@ to_sophia_value_neg_test() ->
|
||||
Code = [ "contract Foo =\n"
|
||||
" entrypoint f(x : int) : string = \"hello\"\n" ],
|
||||
|
||||
{error, [Err1]} = aeso_compiler:to_sophia_value(Code, "f", ok, encode(12)),
|
||||
?assertEqual("Data error:\nCannot translate FATE value 12\n of Sophia type string\n", aeso_errors:pp(Err1)),
|
||||
{error, [Err1]} = so_compiler:to_sophia_value(Code, "f", ok, encode(12)),
|
||||
?assertEqual("Data error:\nCannot translate FATE value 12\n of Sophia type string\n", so_errors:pp(Err1)),
|
||||
|
||||
{error, [Err2]} = aeso_compiler:to_sophia_value(Code, "f", revert, encode(12)),
|
||||
?assertEqual("Data error:\nCould not deserialize the revert message\n", aeso_errors:pp(Err2)),
|
||||
{error, [Err2]} = so_compiler:to_sophia_value(Code, "f", revert, encode(12)),
|
||||
?assertEqual("Data error:\nCould not deserialize the revert message\n", so_errors:pp(Err2)),
|
||||
ok.
|
||||
|
||||
encode_calldata_neg_test() ->
|
||||
@ -97,8 +97,8 @@ encode_calldata_neg_test() ->
|
||||
" `f : (int) => string`\n"
|
||||
"to arguments\n"
|
||||
" `true : bool`\n",
|
||||
{error, [Err1]} = aeso_compiler:create_calldata(Code, "f", ["true"]),
|
||||
?assertEqual(ExpErr1, aeso_errors:pp(Err1)),
|
||||
{error, [Err1]} = so_compiler:create_calldata(Code, "f", ["true"]),
|
||||
?assertEqual(ExpErr1, so_errors:pp(Err1)),
|
||||
|
||||
ok.
|
||||
|
||||
@ -108,15 +108,15 @@ decode_calldata_neg_test() ->
|
||||
Code2 = [ "contract Foo =\n"
|
||||
" entrypoint f(x : string) : int = 42\n" ],
|
||||
|
||||
{ok, CallDataFATE} = aeso_compiler:create_calldata(Code1, "f", ["42"]),
|
||||
{ok, CallDataFATE} = so_compiler:create_calldata(Code1, "f", ["42"]),
|
||||
|
||||
{error, [Err1]} = aeso_compiler:decode_calldata(Code2, "f", <<1,2,3>>),
|
||||
?assertEqual("Data error:\nFailed to decode calldata binary\n", aeso_errors:pp(Err1)),
|
||||
{error, [Err2]} = aeso_compiler:decode_calldata(Code2, "f", CallDataFATE),
|
||||
?assertEqual("Data error:\nCannot translate FATE value \"*\"\n to Sophia type (string)\n", aeso_errors:pp(Err2)),
|
||||
{error, [Err1]} = so_compiler:decode_calldata(Code2, "f", <<1,2,3>>),
|
||||
?assertEqual("Data error:\nFailed to decode calldata binary\n", so_errors:pp(Err1)),
|
||||
{error, [Err2]} = so_compiler:decode_calldata(Code2, "f", CallDataFATE),
|
||||
?assertEqual("Data error:\nCannot translate FATE value \"*\"\n to Sophia type (string)\n", so_errors:pp(Err2)),
|
||||
|
||||
{error, [Err3]} = aeso_compiler:decode_calldata(Code2, "x", CallDataFATE),
|
||||
?assertEqual("Data error at line 1, col 1:\nFunction 'x' is missing in contract\n", aeso_errors:pp(Err3)),
|
||||
{error, [Err3]} = so_compiler:decode_calldata(Code2, "x", CallDataFATE),
|
||||
?assertEqual("Data error at line 1, col 1:\nFunction 'x' is missing in contract\n", so_errors:pp(Err3)),
|
||||
ok.
|
||||
|
||||
|
||||
@ -128,12 +128,12 @@ encode_decode_sophia_string(SophiaType, String) ->
|
||||
, " record r = {x : an_alias(int), y : variant}\n"
|
||||
, " datatype variant = Red | Blue(map(string, int))\n"
|
||||
, " entrypoint foo : arg_type => arg_type\n" ],
|
||||
case aeso_compiler:check_call(lists:flatten(Code), "foo", [String], [no_code]) of
|
||||
case so_compiler:check_call(lists:flatten(Code), "foo", [String], [no_code]) of
|
||||
{ok, _, [Arg]} ->
|
||||
Data = encode(Arg),
|
||||
case aeso_compiler:to_sophia_value(Code, "foo", ok, Data, [no_code]) of
|
||||
case so_compiler:to_sophia_value(Code, "foo", ok, Data, [no_code]) of
|
||||
{ok, Sophia} ->
|
||||
lists:flatten(io_lib:format("~s", [prettypr:format(aeso_pretty:expr(Sophia))]));
|
||||
lists:flatten(io_lib:format("~s", [prettypr:format(so_pretty:expr(Sophia))]));
|
||||
{error, Err} ->
|
||||
io:format("~s\n", [Err]),
|
||||
{error, Err}
|
||||
@ -194,40 +194,18 @@ parameterized_contract(ExtraCode, FunName, Types) ->
|
||||
" datatype variant = Red | Blue(map(string, int))\n"
|
||||
" entrypoint ", FunName, " : (", string:join(Types, ", "), ") => int\n" ]).
|
||||
|
||||
oracle_test() ->
|
||||
Contract =
|
||||
"contract OracleTest =\n"
|
||||
" entrypoint question(o, q : oracle_query(list(string), option(int))) =\n"
|
||||
" Oracle.get_question(o, q)\n",
|
||||
?assertEqual({ok, "question", [{oracle, <<291:256>>}, {oracle_query, <<1110:256>>}]},
|
||||
aeso_compiler:check_call(Contract, "question", ["ok_111111111111111111111111111111ZrdqRz9",
|
||||
"oq_1111111111111111111111111111113AFEFpt5"], [no_code])),
|
||||
|
||||
ok.
|
||||
|
||||
permissive_literals_fail_test() ->
|
||||
Contract =
|
||||
"contract OracleTest =\n"
|
||||
" stateful entrypoint haxx(o : oracle(list(string), option(int))) =\n"
|
||||
" Chain.spend(o, 1000000)\n",
|
||||
{error, [Err]} =
|
||||
aeso_compiler:check_call(Contract, "haxx", ["#123"], []),
|
||||
?assertMatch("Type error at line 3, col 5:\nCannot unify" ++ _, aeso_errors:pp(Err)),
|
||||
?assertEqual(type_error, aeso_errors:type(Err)),
|
||||
ok.
|
||||
|
||||
encode_decode_calldata(FunName, Types, Args) ->
|
||||
Code = parameterized_contract(FunName, Types),
|
||||
encode_decode_calldata_(Code, FunName, Args).
|
||||
|
||||
encode_decode_calldata_(Code, FunName, Args) ->
|
||||
{ok, Calldata} = aeso_compiler:create_calldata(Code, FunName, Args, []),
|
||||
{ok, _, _} = aeso_compiler:check_call(Code, FunName, Args, [no_code]),
|
||||
{ok, Calldata} = so_compiler:create_calldata(Code, FunName, Args, []),
|
||||
{ok, _, _} = so_compiler:check_call(Code, FunName, Args, [no_code]),
|
||||
case FunName of
|
||||
"init" ->
|
||||
[];
|
||||
_ ->
|
||||
{ok, FateArgs} = aeb_fate_abi:decode_calldata(FunName, Calldata),
|
||||
{ok, FateArgs} = gmb_fate_abi:decode_calldata(FunName, Calldata),
|
||||
FateArgs
|
||||
end.
|
||||
|
||||
@ -236,7 +214,7 @@ encode_decode(D) ->
|
||||
D.
|
||||
|
||||
encode(D) ->
|
||||
aeb_fate_encoding:serialize(D).
|
||||
gmb_fate_encoding:serialize(D).
|
||||
|
||||
decode(B) ->
|
||||
aeb_fate_encoding:deserialize(B).
|
||||
gmb_fate_encoding:deserialize(B).
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_aci_tests).
|
||||
-module(so_aci_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@ -9,11 +9,11 @@ simple_aci_test_() ->
|
||||
|
||||
test_contract(N) ->
|
||||
{Contract,MapACI,DecACI} = test_cases(N),
|
||||
{ok,JSON} = aeso_aci:contract_interface(json, Contract),
|
||||
{ok,JSON} = so_aci:contract_interface(json, Contract),
|
||||
?assertEqual([MapACI], JSON),
|
||||
?assertEqual({ok, DecACI}, aeso_aci:render_aci_json(JSON)),
|
||||
?assertEqual({ok, DecACI}, so_aci:render_aci_json(JSON)),
|
||||
%% Check if the compiler provides correct aci
|
||||
{ok,#{aci := JSON2}} = aeso_compiler:from_string(Contract, [{aci, json}]),
|
||||
{ok,#{aci := JSON2}} = so_compiler:from_string(Contract, [{aci, json}]),
|
||||
?assertEqual(JSON, JSON2).
|
||||
|
||||
test_cases(1) ->
|
||||
@ -95,39 +95,39 @@ aci_test_() ->
|
||||
fun() -> aci_test_contract(ContractName) end}
|
||||
|| ContractName <- all_contracts()].
|
||||
|
||||
all_contracts() -> aeso_compiler_tests:compilable_contracts().
|
||||
all_contracts() -> so_compiler_tests:compilable_contracts().
|
||||
|
||||
aci_test_contract(Name) ->
|
||||
String = aeso_test_utils:read_contract(Name),
|
||||
Opts = case lists:member(Name, aeso_compiler_tests:debug_mode_contracts()) of
|
||||
String = so_test_utils:read_contract(Name),
|
||||
Opts = case lists:member(Name, so_compiler_tests:debug_mode_contracts()) of
|
||||
true -> [debug_mode];
|
||||
false -> []
|
||||
end ++ [{include, {file_system, [aeso_test_utils:contract_path()]}}],
|
||||
JSON = case aeso_aci:contract_interface(json, String, Opts) of
|
||||
end ++ [{include, {file_system, [so_test_utils:contract_path()]}}],
|
||||
JSON = case so_aci:contract_interface(json, String, Opts) of
|
||||
{ok, J} -> J;
|
||||
{error, ErrorStringJ} when is_binary(ErrorStringJ) -> error(ErrorStringJ);
|
||||
{error, ErrorJ} -> aeso_compiler_tests:print_and_throw(ErrorJ)
|
||||
{error, ErrorJ} -> so_compiler_tests:print_and_throw(ErrorJ)
|
||||
end,
|
||||
case aeso_compiler:from_string(String, [{aci, json} | Opts]) of
|
||||
case so_compiler:from_string(String, [{aci, json} | Opts]) of
|
||||
{ok, #{aci := JSON1}} ->
|
||||
?assertEqual(JSON, JSON1),
|
||||
io:format("JSON:\n~p\n", [JSON]),
|
||||
{ok, ContractStub} = aeso_aci:render_aci_json(JSON),
|
||||
{ok, ContractStub} = so_aci:render_aci_json(JSON),
|
||||
|
||||
io:format("STUB:\n~s\n", [ContractStub]),
|
||||
check_stub(ContractStub, [{src_file, Name}]),
|
||||
|
||||
ok;
|
||||
{error, ErrorString} when is_binary(ErrorString) -> error(ErrorString);
|
||||
{error, Error} -> aeso_compiler_tests:print_and_throw(Error)
|
||||
{error, Error} -> so_compiler_tests:print_and_throw(Error)
|
||||
end.
|
||||
|
||||
check_stub(Stub, Options) ->
|
||||
try aeso_parser:string(binary_to_list(Stub), Options) of
|
||||
try so_parser:string(binary_to_list(Stub), Options) of
|
||||
Ast ->
|
||||
try
|
||||
%% io:format("AST: ~120p\n", [Ast]),
|
||||
aeso_ast_infer_types:infer(Ast, [no_code])
|
||||
so_ast_infer_types:infer(Ast, [no_code])
|
||||
catch throw:{type_errors, TE} ->
|
||||
io:format("Type error:\n~s\n", [TE]),
|
||||
error(TE);
|
||||
@ -136,6 +136,6 @@ check_stub(Stub, Options) ->
|
||||
error(R)
|
||||
end
|
||||
catch throw:{error, Errs} ->
|
||||
_ = [ io:format("~s\n", [aeso_errors:pp(E)]) || E <- Errs ],
|
||||
_ = [ io:format("~s\n", [so_errors:pp(E)]) || E <- Errs ],
|
||||
error({parse_errors, Errs})
|
||||
end.
|
@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_calldata_tests).
|
||||
-module(so_calldata_tests).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
calldata_test_() ->
|
||||
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||
fun() ->
|
||||
ContractString = aeso_test_utils:read_contract(ContractName),
|
||||
ContractString = so_test_utils:read_contract(ContractName),
|
||||
FateExprs = ast_exprs(ContractString, Fun, Args),
|
||||
ParsedExprs = parse_args(Fun, Args),
|
||||
?assertEqual(ParsedExprs, FateExprs),
|
||||
@ -28,8 +28,8 @@ calldata_test_() ->
|
||||
calldata_aci_test_() ->
|
||||
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||
fun() ->
|
||||
ContractString = aeso_test_utils:read_contract(ContractName),
|
||||
{ok, ContractACIBin} = aeso_aci:contract_interface(string, ContractString, [no_code]),
|
||||
ContractString = so_test_utils:read_contract(ContractName),
|
||||
{ok, ContractACIBin} = so_aci:contract_interface(string, ContractString, [no_code]),
|
||||
ContractACI = binary_to_list(ContractACIBin),
|
||||
io:format("ACI:\n~s\n", [ContractACIBin]),
|
||||
FateExprs = ast_exprs(ContractACI, Fun, Args),
|
||||
@ -40,7 +40,7 @@ calldata_aci_test_() ->
|
||||
|
||||
parse_args(Fun, Args) ->
|
||||
[{contract_main, _, _, _, [{letfun, _, _, _, _, [{guarded, _, [], {app, _, _, AST}}]}]}] =
|
||||
aeso_parser:string("main contract Temp = function foo() = " ++ Fun ++ "(" ++ string:join(Args, ", ") ++ ")"),
|
||||
so_parser:string("main contract Temp = function foo() = " ++ Fun ++ "(" ++ string:join(Args, ", ") ++ ")"),
|
||||
strip_ann(AST).
|
||||
|
||||
strip_ann(T) when is_tuple(T) ->
|
||||
@ -58,8 +58,8 @@ strip_ann1(X) -> X.
|
||||
ast_exprs(ContractString, Fun, Args) ->
|
||||
ast_exprs(ContractString, Fun, Args, []).
|
||||
ast_exprs(ContractString, Fun, Args, Opts) ->
|
||||
{ok, Data} = (catch aeso_compiler:create_calldata(ContractString, Fun, Args, Opts)),
|
||||
{ok, _Types, Exprs} = (catch aeso_compiler:decode_calldata(ContractString, Fun, Data, Opts)),
|
||||
{ok, Data} = (catch so_compiler:create_calldata(ContractString, Fun, Args, Opts)),
|
||||
{ok, _Types, Exprs} = (catch so_compiler:decode_calldata(ContractString, Fun, Data, Opts)),
|
||||
?assert(is_list(Exprs)),
|
||||
strip_ann(Exprs).
|
||||
|
||||
@ -90,8 +90,6 @@ compilable_contracts() ->
|
||||
{"funargs", "sextiosju", ["#01020304050607080910111213141516171819202122232425262728293031323334353637383940"
|
||||
"414243444546474849505152535455565758596061626364656667"]},
|
||||
{"funargs", "trettiotva", ["#0102030405060708091011121314151617181920212223242526272829303132"]},
|
||||
{"funargs", "find_oracle", ["ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5"]},
|
||||
{"funargs", "find_query", ["oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY"]},
|
||||
{"funargs", "traffic_light", ["Green"]},
|
||||
{"funargs", "traffic_light", ["Pantone(12)"]},
|
||||
{"funargs", "tuples", ["()"]},
|
@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_compiler_tests).
|
||||
-module(so_compiler_tests).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
@ -28,14 +28,14 @@ simple_compile_test_() ->
|
||||
fun() ->
|
||||
case compile(ContractName) of
|
||||
#{fate_code := Code} ->
|
||||
Code1 = aeb_fate_code:deserialize(aeb_fate_code:serialize(Code)),
|
||||
Code1 = gmb_fate_code:deserialize(gmb_fate_code:serialize(Code)),
|
||||
?assertMatch({X, X}, {Code1, Code});
|
||||
Error -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
||||
end
|
||||
end} || ContractName <- compilable_contracts()] ++
|
||||
[ {"Test file not found error",
|
||||
fun() ->
|
||||
{error, Errors} = aeso_compiler:file("does_not_exist.aes"),
|
||||
{error, Errors} = so_compiler:file("does_not_exist.aes"),
|
||||
ExpErr = <<"File error:\ndoes_not_exist.aes: no such file or directory">>,
|
||||
check_errors([ExpErr], Errors)
|
||||
end} ] ++
|
||||
@ -49,7 +49,7 @@ simple_compile_test_() ->
|
||||
fun() ->
|
||||
FileSystem = maps:from_list(
|
||||
[ begin
|
||||
{ok, Bin} = file:read_file(filename:join([aeso_test_utils:contract_path(), File])),
|
||||
{ok, Bin} = file:read_file(filename:join([so_test_utils:contract_path(), File])),
|
||||
{File, Bin}
|
||||
end || File <- ["included.aes", "../contracts/included2.aes"] ]),
|
||||
#{byte_code := Code1} = compile("include", [{include, {explicit_files, FileSystem}}]),
|
||||
@ -77,14 +77,14 @@ simple_compile_test_() ->
|
||||
|
||||
%% Check if all modules in the standard library compile
|
||||
stdlib_test_() ->
|
||||
{ok, Files} = file:list_dir(aeso_stdlib:stdlib_include_path()),
|
||||
{ok, Files} = file:list_dir(so_stdlib:stdlib_include_path()),
|
||||
[ { "Testing " ++ File ++ " from the stdlib",
|
||||
fun() ->
|
||||
String = "include \"" ++ File ++ "\"\nmain contract Test =\n entrypoint f(x) = x",
|
||||
Options = [{src_file, File}],
|
||||
case aeso_compiler:from_string(String, Options) of
|
||||
case so_compiler:from_string(String, Options) of
|
||||
{ok, #{fate_code := Code}} ->
|
||||
Code1 = aeb_fate_code:deserialize(aeb_fate_code:serialize(Code)),
|
||||
Code1 = gmb_fate_code:deserialize(gmb_fate_code:serialize(Code)),
|
||||
?assertMatch({X, X}, {Code1, Code});
|
||||
{error, Error} -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
||||
end
|
||||
@ -97,7 +97,7 @@ check_errors(Expect, #{}) ->
|
||||
?assertEqual({error, Expect}, ok);
|
||||
check_errors(Expect0, Actual0) ->
|
||||
Expect = lists:sort(Expect0),
|
||||
Actual = [ list_to_binary(string:trim(aeso_errors:pp(Err))) || Err <- Actual0 ],
|
||||
Actual = [ list_to_binary(string:trim(so_errors:pp(Err))) || Err <- Actual0 ],
|
||||
case {Expect -- Actual, Actual -- Expect} of
|
||||
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
||||
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
||||
@ -106,7 +106,7 @@ check_errors(Expect0, Actual0) ->
|
||||
|
||||
check_warnings(Expect0, Actual0) ->
|
||||
Expect = lists:sort(Expect0),
|
||||
Actual = [ list_to_binary(string:trim(aeso_warnings:pp(Warn))) || Warn <- Actual0 ],
|
||||
Actual = [ list_to_binary(string:trim(so_warnings:pp(Warn))) || Warn <- Actual0 ],
|
||||
case {Expect -- Actual, Actual -- Expect} of
|
||||
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
||||
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
||||
@ -114,19 +114,19 @@ check_warnings(Expect0, Actual0) ->
|
||||
end.
|
||||
|
||||
compile(Name) ->
|
||||
compile( Name, [{include, {file_system, [aeso_test_utils:contract_path()]}}]).
|
||||
compile( Name, [{include, {file_system, [so_test_utils:contract_path()]}}]).
|
||||
|
||||
compile(Name, Options) ->
|
||||
String = aeso_test_utils:read_contract(Name),
|
||||
String = so_test_utils:read_contract(Name),
|
||||
Options1 =
|
||||
case lists:member(Name, debug_mode_contracts()) of
|
||||
true -> [debug_mode];
|
||||
false -> []
|
||||
end ++
|
||||
[ {src_file, Name ++ ".aes"}
|
||||
, {include, {file_system, [aeso_test_utils:contract_path()]}}
|
||||
, {include, {file_system, [so_test_utils:contract_path()]}}
|
||||
] ++ Options,
|
||||
case aeso_compiler:from_string(String, Options1) of
|
||||
case so_compiler:from_string(String, Options1) of
|
||||
{ok, Map} -> Map;
|
||||
{error, ErrorString} when is_binary(ErrorString) -> ErrorString;
|
||||
{error, Errors} -> Errors
|
||||
@ -145,7 +145,6 @@ compilable_contracts() ->
|
||||
"fundme",
|
||||
"identity",
|
||||
"maps",
|
||||
"oracles",
|
||||
"remote_call",
|
||||
"remote_call_ambiguous_record",
|
||||
"simple",
|
||||
@ -223,7 +222,6 @@ compilable_contracts() ->
|
||||
"polymorphic_entrypoint_return",
|
||||
"polymorphic_map_keys",
|
||||
"unapplied_contract_call",
|
||||
"unapplied_named_arg_builtin",
|
||||
"resolve_field_constraint_by_arity",
|
||||
"toplevel_constants",
|
||||
"ceres",
|
||||
@ -299,7 +297,7 @@ warnings() ->
|
||||
]).
|
||||
|
||||
failing_contracts() ->
|
||||
{ok, V} = aeso_compiler:numeric_version(),
|
||||
{ok, V} = so_compiler:numeric_version(),
|
||||
Version = list_to_binary(string:join([integer_to_list(N) || N <- V], ".")),
|
||||
%% Parse errors
|
||||
[ ?PARSE_ERROR(field_parse_error,
|
||||
@ -466,11 +464,7 @@ failing_contracts() ->
|
||||
[<<?Pos(2, 12)
|
||||
"Nested contracts are not allowed. Contract `Con` is not defined at top level.">>])
|
||||
, ?TYPE_ERROR(bad_address_literals,
|
||||
[<<?Pos(11, 5)
|
||||
"Cannot unify `address` and `oracle(int, bool)`\n"
|
||||
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
||||
"against the expected type `oracle(int, bool)`">>,
|
||||
<<?Pos(9, 5)
|
||||
[<<?Pos(9, 5)
|
||||
"Cannot unify `address` and `Remote`\n"
|
||||
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
||||
"against the expected type `Remote`">>,
|
||||
@ -478,52 +472,17 @@ failing_contracts() ->
|
||||
"Cannot unify `address` and `bytes(32)`\n"
|
||||
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
||||
"against the expected type `bytes(32)`">>,
|
||||
<<?Pos(14, 5)
|
||||
"Cannot unify `oracle('a, 'b)` and `oracle_query(int, bool)`\n"
|
||||
"when checking the type of the expression "
|
||||
"`ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5 : oracle('a, 'b)` "
|
||||
"against the expected type `oracle_query(int, bool)`">>,
|
||||
<<?Pos(16, 5)
|
||||
"Cannot unify `oracle('c, 'd)` and `bytes(32)`\n"
|
||||
"when checking the type of the expression "
|
||||
"`ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5 : oracle('c, 'd)` "
|
||||
"against the expected type `bytes(32)`">>,
|
||||
<<?Pos(18, 5)
|
||||
"Cannot unify `oracle('e, 'f)` and `Remote`\n"
|
||||
"when checking the type of the expression "
|
||||
"`ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5 : oracle('e, 'f)` "
|
||||
"against the expected type `Remote`">>,
|
||||
<<?Pos(21, 5)
|
||||
"Cannot unify `oracle_query('g, 'h)` and `oracle(int, bool)`\n"
|
||||
"when checking the type of the expression "
|
||||
"`oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY : oracle_query('g, 'h)` "
|
||||
"against the expected type `oracle(int, bool)`">>,
|
||||
<<?Pos(23, 5)
|
||||
"Cannot unify `oracle_query('i, 'j)` and `bytes(32)`\n"
|
||||
"when checking the type of the expression "
|
||||
"`oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY : oracle_query('i, 'j)` "
|
||||
"against the expected type `bytes(32)`">>,
|
||||
<<?Pos(25, 5)
|
||||
"Cannot unify `oracle_query('k, 'l)` and `Remote`\n"
|
||||
"when checking the type of the expression "
|
||||
"`oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY : oracle_query('k, 'l)` "
|
||||
"against the expected type `Remote`">>,
|
||||
<<?Pos(28, 5)
|
||||
<<?Pos(12, 5)
|
||||
"The type `address` is not a contract type\n"
|
||||
"when checking that the contract literal "
|
||||
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
||||
"has the type `address`">>,
|
||||
<<?Pos(30, 5)
|
||||
"The type `oracle(int, bool)` is not a contract type\n"
|
||||
"when checking that the contract literal "
|
||||
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
||||
"has the type `oracle(int, bool)`">>,
|
||||
<<?Pos(32, 5)
|
||||
<<?Pos(14, 5)
|
||||
"The type `bytes(32)` is not a contract type\n"
|
||||
"when checking that the contract literal "
|
||||
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
||||
"has the type `bytes(32)`">>,
|
||||
<<?Pos(34, 5),
|
||||
<<?Pos(16, 5),
|
||||
"The type `address` is not a contract type\n"
|
||||
"when checking that the call to `Address.to_contract` "
|
||||
"has the type `address`">>])
|
||||
@ -1036,56 +995,6 @@ failing_contracts() ->
|
||||
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
||||
"when checking the type of the pattern `r11 : rec_inv(Cat)` against the expected type `Main.rec_inv(Animal)`">>
|
||||
])
|
||||
, ?TYPE_ERROR(polymorphism_variance_switching_oracles,
|
||||
[<<?Pos(15,13)
|
||||
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
||||
"when checking the type of the pattern `o03 : oracle(Animal, Animal)` against the expected type `oracle(Cat, Animal)`">>,
|
||||
<<?Pos(16,13)
|
||||
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
||||
"when checking the type of the pattern `o04 : oracle(Animal, Animal)` against the expected type `oracle(Cat, Cat)`">>,
|
||||
<<?Pos(17,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `o05 : oracle(Animal, Cat)` against the expected type `oracle(Animal, Animal)`">>,
|
||||
<<?Pos(19,13)
|
||||
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
||||
"when checking the type of the pattern `o07 : oracle(Animal, Cat)` against the expected type `oracle(Cat, Animal)`">>,
|
||||
<<?Pos(19,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `o07 : oracle(Animal, Cat)` against the expected type `oracle(Cat, Animal)`">>,
|
||||
<<?Pos(20,13)
|
||||
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
||||
"when checking the type of the pattern `o08 : oracle(Animal, Cat)` against the expected type `oracle(Cat, Cat)`">>,
|
||||
<<?Pos(25,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `o13 : oracle(Cat, Cat)` against the expected type `oracle(Animal, Animal)`">>,
|
||||
<<?Pos(27,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `o15 : oracle(Cat, Cat)` against the expected type `oracle(Cat, Animal)`">>,
|
||||
<<?Pos(34,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q05 : oracle_query(Animal, Cat)` against the expected type `oracle_query(Animal, Animal)`">>,
|
||||
<<?Pos(36,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q07 : oracle_query(Animal, Cat)` against the expected type `oracle_query(Cat, Animal)`">>,
|
||||
<<?Pos(38,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q09 : oracle_query(Cat, Animal)` against the expected type `oracle_query(Animal, Animal)`">>,
|
||||
<<?Pos(39,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q10 : oracle_query(Cat, Animal)` against the expected type `oracle_query(Animal, Cat)`">>,
|
||||
<<?Pos(42,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q13 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Animal, Animal)`">>,
|
||||
<<?Pos(42,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q13 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Animal, Animal)`">>,
|
||||
<<?Pos(43,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q14 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Animal, Cat)`">>,
|
||||
<<?Pos(44,13)
|
||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
||||
"when checking the type of the pattern `q15 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Cat, Animal)`">>
|
||||
])
|
||||
, ?TYPE_ERROR(polymorphism_variance_switching_chain_create_fail,
|
||||
[<<?Pos(9,22)
|
||||
"I is not implemented.\n"
|
||||
@ -1156,34 +1065,6 @@ failing_contracts() ->
|
||||
" `list(int)`\n"
|
||||
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
|
||||
])
|
||||
, ?TYPE_ERROR(polymorphic_query_type,
|
||||
[<<?Pos(3,5)
|
||||
"Invalid oracle type\n"
|
||||
" `oracle('a, 'b)`\n"
|
||||
"The query type must not be polymorphic (contain type variables)">>,
|
||||
<<?Pos(3,5)
|
||||
"Invalid oracle type\n"
|
||||
" `oracle('a, 'b)`\n"
|
||||
"The response type must not be polymorphic (contain type variables)">>
|
||||
])
|
||||
, ?TYPE_ERROR(polymorphic_response_type,
|
||||
[<<?Pos(3,5)
|
||||
"Invalid oracle type\n"
|
||||
" `oracle(string, 'r)`\n"
|
||||
"The response type must not be polymorphic (contain type variables)">>
|
||||
])
|
||||
, ?TYPE_ERROR(higher_order_query_type,
|
||||
[<<?Pos(3,5)
|
||||
"Invalid oracle type\n"
|
||||
" `oracle((int) => int, string)`\n"
|
||||
"The query type must not be higher-order (contain function types)">>
|
||||
])
|
||||
, ?TYPE_ERROR(higher_order_response_type,
|
||||
[<<?Pos(3,5)
|
||||
"Invalid oracle type\n"
|
||||
" `oracle(string, (int) => int)`\n"
|
||||
"The response type must not be higher-order (contain function types)">>
|
||||
])
|
||||
, ?TYPE_ERROR(var_args_unify_let,
|
||||
[<<?Pos(3,9)
|
||||
"Cannot infer types for variable argument list.\n"
|
||||
@ -1345,16 +1226,16 @@ validation_fails() ->
|
||||
validate(Contract1, Contract2) ->
|
||||
case compile(Contract1) of
|
||||
ByteCode = #{ fate_code := FCode } ->
|
||||
FCode1 = aeb_fate_code:serialize(aeb_fate_code:strip_init_function(FCode)),
|
||||
Source = aeso_test_utils:read_contract(Contract2),
|
||||
aeso_compiler:validate_byte_code(
|
||||
FCode1 = gmb_fate_code:serialize(gmb_fate_code:strip_init_function(FCode)),
|
||||
Source = so_test_utils:read_contract(Contract2),
|
||||
so_compiler:validate_byte_code(
|
||||
ByteCode#{ byte_code := FCode1 }, Source,
|
||||
case lists:member(Contract2, debug_mode_contracts()) of
|
||||
true -> [debug_mode];
|
||||
false -> []
|
||||
end ++
|
||||
[ {src_file, lists:concat([Contract2, ".aes"])}
|
||||
, {include, {file_system, [aeso_test_utils:contract_path()]}}
|
||||
, {include, {file_system, [so_test_utils:contract_path()]}}
|
||||
]);
|
||||
Error -> print_and_throw(Error)
|
||||
end.
|
||||
@ -1365,6 +1246,6 @@ print_and_throw(Err) ->
|
||||
io:format("\n~s", [ErrBin]),
|
||||
error(ErrBin);
|
||||
Errors ->
|
||||
io:format("Compilation error:\n~s", [string:join([aeso_errors:pp(E) || E <- Errors], "\n\n")]),
|
||||
io:format("Compilation error:\n~s", [string:join([so_errors:pp(E) || E <- Errors], "\n\n")]),
|
||||
error(compilation_error)
|
||||
end.
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_encode_decode_tests).
|
||||
-module(so_encode_decode_tests).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
@ -9,9 +9,9 @@
|
||||
encode_decode_test_() ->
|
||||
[ {lists:flatten(io_lib:format("Testing encode-decode roundtrip for ~p : ~p", [Value, {EType, DType}])),
|
||||
fun() ->
|
||||
{ok, SerRes} = aeso_compiler:encode_value(?EMPTY, EType, Value, []),
|
||||
{ok, Expr} = aeso_compiler:decode_value(?EMPTY, DType, SerRes, []),
|
||||
Value2 = prettypr:format(aeso_pretty:expr(Expr)),
|
||||
{ok, SerRes} = so_compiler:encode_value(?EMPTY, EType, Value, []),
|
||||
{ok, Expr} = so_compiler:decode_value(?EMPTY, DType, SerRes, []),
|
||||
Value2 = prettypr:format(so_pretty:expr(Expr)),
|
||||
?assertEqual(Value, Value2)
|
||||
end} || {Value, EType, DType} <- test_data() ].
|
||||
|
22
test/so_eunit_SUITE.erl
Normal file
22
test/so_eunit_SUITE.erl
Normal file
@ -0,0 +1,22 @@
|
||||
-module(so_eunit_SUITE).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-include_lib("common_test/include/ct.hrl").
|
||||
|
||||
all() ->
|
||||
[{group, eunit}].
|
||||
|
||||
groups() ->
|
||||
[{eunit, [], [ so_scan_tests
|
||||
, so_parser_tests
|
||||
, so_compiler_tests
|
||||
, so_abi_tests
|
||||
, so_aci_tests
|
||||
]}].
|
||||
|
||||
so_scan_tests(_Config) -> ok = eunit:test(so_scan_tests).
|
||||
so_parser_tests(_Config) -> ok = eunit:test(so_parser_tests).
|
||||
so_compiler_tests(_Config) -> ok = eunit:test(so_compiler_tests).
|
||||
so_abi_tests(_Config) -> ok = eunit:test(so_abi_tests).
|
||||
so_aci_tests(_Config) -> ok = eunit:test(so_aci_tests).
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_parser_tests).
|
||||
-module(so_parser_tests).
|
||||
|
||||
-export([parse_contract/1]).
|
||||
|
||||
@ -68,15 +68,15 @@ simple_contracts_test_() ->
|
||||
}.
|
||||
|
||||
parse_contract(Name) ->
|
||||
parse_string(aeso_test_utils:read_contract(Name)).
|
||||
parse_string(so_test_utils:read_contract(Name)).
|
||||
|
||||
roundtrip_contract(Name) ->
|
||||
round_trip(aeso_test_utils:read_contract(Name)).
|
||||
round_trip(so_test_utils:read_contract(Name)).
|
||||
|
||||
parse_string(Text) -> parse_string(Text, []).
|
||||
|
||||
parse_string(Text, Opts) ->
|
||||
aeso_parser:string(Text, Opts).
|
||||
so_parser:string(Text, Opts).
|
||||
|
||||
parse_expr(Text) ->
|
||||
[{letval, _, _, Expr}] =
|
||||
@ -85,8 +85,8 @@ parse_expr(Text) ->
|
||||
|
||||
round_trip(Text) ->
|
||||
Contract = parse_string(Text),
|
||||
Text1 = prettypr:format(aeso_pretty:decls(strip_stdlib(Contract))),
|
||||
Contract1 = parse_string(aeso_scan:utf8_encode(Text1)),
|
||||
Text1 = prettypr:format(so_pretty:decls(strip_stdlib(Contract))),
|
||||
Contract1 = parse_string(so_scan:utf8_encode(Text1)),
|
||||
NoSrcLoc = remove_line_numbers(Contract),
|
||||
NoSrcLoc1 = remove_line_numbers(Contract1),
|
||||
?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)).
|
@ -1,4 +1,4 @@
|
||||
-module(aeso_scan_tests).
|
||||
-module(so_scan_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@ -13,7 +13,7 @@ empty_contract_test_() ->
|
||||
[{"Scan an empty contract.",
|
||||
fun() ->
|
||||
Text = " ",
|
||||
{ok, []} = aeso_scan:scan(Text),
|
||||
{ok, []} = so_scan:scan(Text),
|
||||
ok
|
||||
end}
|
||||
]}.
|
||||
@ -26,7 +26,7 @@ all_tokens_test_() ->
|
||||
Tokens = all_tokens(),
|
||||
Text = string:join(lists:map(fun show_token/1, Tokens), " "),
|
||||
io:format("~s\n", [Text]),
|
||||
{ok, Tokens1} = aeso_scan:scan(Text),
|
||||
{ok, Tokens1} = so_scan:scan(Text),
|
||||
true = compare_tokens(Tokens, Tokens1),
|
||||
ok
|
||||
end}
|
@ -6,12 +6,12 @@
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
-module(aeso_test_utils).
|
||||
-module(so_test_utils).
|
||||
|
||||
-export([read_contract/1, contract_path/0]).
|
||||
|
||||
contract_path() ->
|
||||
filename:join(code:lib_dir(aesophia, test), "contracts").
|
||||
filename:join(code:lib_dir(sophia, test), "contracts").
|
||||
|
||||
%% Read a contract file from the test/contracts directory.
|
||||
-spec read_contract(string() | atom()) -> string().
|
20
zomp.meta
Normal file
20
zomp.meta
Normal file
@ -0,0 +1,20 @@
|
||||
{name,"Sophia Compiler"}.
|
||||
{type,lib}.
|
||||
{modules,[]}.
|
||||
{prefix,none}.
|
||||
{desc,"The Sophia smart contract language for the FATE VM"}.
|
||||
{author,"QPQ AG"}.
|
||||
{package_id,{"otpr","sophia",{8,0,1}}}.
|
||||
{deps,[{"otpr","gmbytecode",{3,4,1}},
|
||||
{"otpr","getopt",{1,0,2}},
|
||||
{"otpr","eblake2",{1,0,0}},
|
||||
{"otpr","zj",{1,1,0}}]}.
|
||||
{key_name,none}.
|
||||
{a_email,[]}.
|
||||
{c_email,[]}.
|
||||
{copyright,"(c) 2024 QPQ AG"}.
|
||||
{file_exts,[]}.
|
||||
{license,skip}.
|
||||
{repo_url,"https://git.qpq.swiss/QPQ-AG/sophia"}.
|
||||
{tags,["gaju","gajumaru","blockchain","sophia","crypto","compiler","puck"]}.
|
||||
{ws_url,[]}.
|
19
zomp_prep
Executable file
19
zomp_prep
Executable file
@ -0,0 +1,19 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This is a small pre-packaging source generation and include correction script that should be
|
||||
# run before packaging this project for use with ZX/Zomp.
|
||||
|
||||
rm -rf _build
|
||||
cd src
|
||||
for f in $(ls *.erl)
|
||||
do
|
||||
echo "Updating includes in: $f"
|
||||
sed -i 's/gmbytecode\/include\///g' "$f"
|
||||
sed -i 's/\.\.\/include\///g' "$f"
|
||||
sed -i 's/include_lib/include/g' "$f"
|
||||
done
|
||||
sed -i 's/gmb_opcodes\.hrl/\$gmbytecode_include\/gmb_opcodes\.hrl/' so_compiler.erl
|
||||
sed -i 's/gmb_fate_data\.hrl/\$gmbytecode_include\/gmb_fate_data\.hrl/' so_vm_decode.erl
|
||||
cd ..
|
||||
rm -f ebin/*.beam
|
||||
rm -f rebar*
|
Loading…
x
Reference in New Issue
Block a user