Renaming and preparing to remove oracles (#985)
All checks were successful
Sophia Tests / tests (push) Successful in 48m54s
All checks were successful
Sophia Tests / tests (push) Successful in 48m54s
A few references to oracles still remain, but they have been removed as a feature, at least. Reviewed-on: #985 Reviewed-by: Ulf Wiger <ulfwiger@qpq.swiss> Co-authored-by: Craig Everett <zxq9@zxq9.com> Co-committed-by: Craig Everett <zxq9@zxq9.com>
This commit is contained in:
parent
927cd42592
commit
dbab49936d
@ -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
|
|
14
.gitea/workflows/test.yaml
Normal file
14
.gitea/workflows/test.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: Sophia Tests
|
||||||
|
run-name: ${{ gitea.actor }} testing Sophia
|
||||||
|
on: [push, workflow_dispatch]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: linux_amd64
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: test
|
||||||
|
run: |
|
||||||
|
. /home/act_runner/.erts/27.2.1/activate
|
||||||
|
./rebar3 eunit
|
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
|
rebar3.crashdump
|
||||||
*.erl~
|
*.erl~
|
||||||
*.aes~
|
*.aes~
|
||||||
aesophia
|
sophia
|
||||||
.qcci
|
.qcci
|
||||||
current_counterexample.eqc
|
current_counterexample.eqc
|
||||||
test/contracts/test.aes
|
test/contracts/test.aes
|
||||||
|
@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
## [9.0.0]
|
||||||
|
### Changed
|
||||||
|
- stdlib dir discovery now works by finding a relative path from the loaded Sophia installation
|
||||||
|
###Removed
|
||||||
|
- Oracles
|
||||||
|
|
||||||
## [8.0.1]
|
## [8.0.1]
|
||||||
### Changed
|
### Changed
|
||||||
- Upgrade aebytecode to v3.4.1 to fix C warnings
|
- Upgrade aebytecode to v3.4.1 to fix C warnings
|
||||||
|
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
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2025, QPQ AG
|
||||||
Copyright (c) 2017, æternity developers
|
Copyright (c) 2017, æternity developers
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
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 compiler is currently being used three places
|
||||||
- [The command line compiler](https://github.com/aeternity/aesophia_cli)
|
- [The command line compiler](https://git.qpq.swiss/QPQ-AG/sophia_cli)
|
||||||
- [The HTTP compiler](https://github.com/aeternity/aesophia_http)
|
- [Desktop wallet](https://git.qpq.swiss/QPQ-AG/GajuDesk)
|
||||||
- In [æternity node](https://github.com/aeternity/aeternity) tests
|
- In the [Gajumaru core node](https://git.qpq.swiss/QPQ-AG/gajumaru) tests
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ The compiler is currently being used three places
|
|||||||
* [Contract examples](docs/sophia_examples.md)
|
* [Contract examples](docs/sophia_examples.md)
|
||||||
* [Contributing](CONTRIBUTING.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
|
## Versioning
|
||||||
|
|
||||||
@ -31,5 +31,5 @@ Versioning should follow the [semantic versioning](https://semver.org/spec/v2.0.
|
|||||||
|
|
||||||
The basic modules for interfacing the compiler:
|
The basic modules for interfacing the compiler:
|
||||||
|
|
||||||
* [aeso_compiler: the Sophia compiler](docs/aeso_compiler.md)
|
* [so_compiler: the Sophia compiler](docs/so_compiler.md)
|
||||||
* [aeso_aci: the ACI interface](docs/aeso_aci.md)
|
* [so_aci: the ACI interface](docs/so_aci.md)
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
# Introduction
|
# Introduction
|
||||||
Sophia is a functional language designed for smart contract development. It is strongly typed and has
|
Sophia is a functional language designed for smart contract development.
|
||||||
restricted mutable state.
|
It is strongly typed and has restricted mutable state.
|
||||||
|
|
||||||
Sophia is customized for smart contracts, which can be published
|
Sophia is customized for smart contracts, which can be published to a blockchain.
|
||||||
to a blockchain. Thus some features of conventional
|
Thus some features of conventional languages (such as floating point arithmetic) are not present in Sophia,
|
||||||
languages, such as floating point arithmetic, are not present in Sophia, and
|
and some blockchain specific primitives, constructions and types have been added.
|
||||||
some [æternity blockchain](https://aeternity.com) specific primitives, constructions and types have been added.
|
|
||||||
|
|
||||||
!!! Note
|
The file extension used for Sophia source files is ".aes", reflecting Sophia's Aeternity heritage.
|
||||||
- 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/)!
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# aeso_aci
|
# so_aci
|
||||||
|
|
||||||
### Module
|
### Module
|
||||||
|
|
||||||
### aeso_aci
|
### so_aci
|
||||||
|
|
||||||
The ACI interface encoder and decoder.
|
The ACI interface encoder and decoder.
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ be included inside another contract.
|
|||||||
``` erlang
|
``` erlang
|
||||||
1> {ok,Contract} = file:read_file("aci_test.aes").
|
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"...>>}
|
{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 =>
|
{ok,[#{contract =>
|
||||||
#{functions =>
|
#{functions =>
|
||||||
[#{arguments => [],name => <<"init">>,
|
[#{arguments => [],name => <<"init">>,
|
||||||
@ -144,7 +144,7 @@ be included inside another contract.
|
|||||||
vars => []}]}}]}
|
vars => []}]}}]}
|
||||||
3> file:write_file("aci_test.aci", jsx:encode(JsonACI)).
|
3> file:write_file("aci_test.aci", jsx:encode(JsonACI)).
|
||||||
ok
|
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 "...>>}
|
{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).
|
5> file:write_file("aci_test.include", InterfaceStub).
|
||||||
ok
|
ok
|
@ -1,8 +1,8 @@
|
|||||||
# aeso_compiler
|
# so_compiler
|
||||||
|
|
||||||
### Module
|
### Module
|
||||||
|
|
||||||
### aeso_compiler
|
### so_compiler
|
||||||
|
|
||||||
The Sophia compiler
|
The Sophia compiler
|
||||||
|
|
@ -65,9 +65,3 @@ contract FundMe =
|
|||||||
amount = state.contributions[to]})
|
amount = state.contributions[to]})
|
||||||
put(state{ contributions @ c = Map.delete(to, c) })
|
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
|
- 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`.
|
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)`
|
- 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
|
- 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
|
* Use a stateful primitive function. These are
|
||||||
- `put`
|
- `put`
|
||||||
- `Chain.spend`
|
- `Chain.spend`
|
||||||
- `Oracle.register`
|
|
||||||
- `Oracle.query`
|
|
||||||
- `Oracle.respond`
|
|
||||||
- `Oracle.extend`
|
|
||||||
- `AENS.preclaim`
|
- `AENS.preclaim`
|
||||||
- `AENS.claim`
|
- `AENS.claim`
|
||||||
- `AENS.transfer`
|
- `AENS.transfer`
|
||||||
@ -556,8 +546,6 @@ Sophia has the following types:
|
|||||||
| hash | A 32-byte hash - equivalent to `bytes(32)` | |
|
| hash | A 32-byte hash - equivalent to `bytes(32)` | |
|
||||||
| signature | A signature - equivalent to `bytes(64)` | |
|
| signature | A signature - equivalent to `bytes(64)` | |
|
||||||
| Chain.ttl | Time-to-live (fixed height or relative to current block) | ```FixedTTL(1050)``` ```RelativeTTL(50)``` |
|
| 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()``` |
|
| contract | A user defined, typed, contract address | ```function call_remote(r : RemoteContract) = r.fun()``` |
|
||||||
|
|
||||||
## Literals
|
## Literals
|
||||||
@ -580,8 +568,6 @@ Sophia has the following types:
|
|||||||
| hash | `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
| hash | `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
||||||
| signature | `sg_MhibzTP1wWzGCTjtPFr1TiPqRJrrJqw7auvEuF5i3FdoALWqXLBDY6xxRRNUSPHK3EQTnTzF12EyspkxrSMxVHKsZeSMj`, `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
| signature | `sg_MhibzTP1wWzGCTjtPFr1TiPqRJrrJqw7auvEuF5i3FdoALWqXLBDY6xxRRNUSPHK3EQTnTzF12EyspkxrSMxVHKsZeSMj`, `#000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f` |
|
||||||
| Chain.ttl | `FixedTTL(1050)`, `RelativeTTL(50)` |
|
| Chain.ttl | `FixedTTL(1050)`, `RelativeTTL(50)` |
|
||||||
| oracle('a, 'b) | `ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5` |
|
|
||||||
| oracle_query('a, 'b) | `oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY` |
|
|
||||||
| contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` |
|
| contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` |
|
||||||
|
|
||||||
## Hole expression
|
## 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
|
`Auth.tx` and `Auth.tx_hash` respectively, they are *only* available during authentication if invoked by a
|
||||||
normal contract call they return `None`.
|
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
|
## AENS interface
|
||||||
|
|
||||||
Contracts can interact with the [æternity naming
|
Contracts can interact with the [æternity naming system](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/AENS.md). For this
|
||||||
system](https://github.com/aeternity/protocol/blob/master/AENS.md). For this
|
|
||||||
purpose the [AENS](sophia_stdlib.md#aens) and later the
|
purpose the [AENS](sophia_stdlib.md#aens) and later the
|
||||||
[AENSv2](sophia_stdlib.md#aensv2) library was exposed.
|
[AENSv2](sophia_stdlib.md#aensv2) library was exposed.
|
||||||
|
|
||||||
@ -1009,10 +927,9 @@ automatically removed so they will not appear in the pointers map.
|
|||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
Sophia contracts log structured messages to an event log in the resulting
|
Sophia contracts log structured messages to an event log in the resulting blockchain transaction.
|
||||||
blockchain transaction. The event log is quite similar to [Events in
|
The event log is quite similar to [Events in Solidity](https://solidity.readthedocs.io/en/v0.4.24/contracts.html#events).
|
||||||
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).
|
||||||
Events are further discussed in the [protocol](https://github.com/aeternity/protocol/blob/master/contracts/events.md).
|
|
||||||
|
|
||||||
|
|
||||||
To use events a contract must declare a datatype `event`, and events are then
|
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`
|
- `int`
|
||||||
- `bits`
|
- `bits`
|
||||||
- `address`
|
- `address`
|
||||||
- `oracle(_, _)`
|
|
||||||
- `oracle_query(_, _)`
|
|
||||||
- contract types
|
- contract types
|
||||||
- `bytes(n)` for `n` ≤ 32, in particular `hash`
|
- `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
|
## 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
|
optional delegation signature. This is typically used when a user/accounts
|
||||||
would like to allow a contract to act on it's behalf.
|
would like to allow a contract to act on it's behalf.
|
||||||
|
|
||||||
### From Ceres
|
There are five different delegation signatures:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
- AENS wildcard - the user signs: `owner account + contract`
|
- AENS wildcard - the user signs: `owner account + contract`
|
||||||
- `AENS_PRECLAIM` - 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`
|
- `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
|
See [Serialized signature data](https://git.qpq.swiss/QPQ-AG/protocol/src/branch/master/serializations.md)
|
||||||
data](https://github.com/aeternity/protocol/blob/master/contracts/fate.md#from-ceres-serialized-signature-data)
|
|
||||||
for the exact structure used.
|
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)
|
- [Crypto](#crypto)
|
||||||
- [Int](#int)
|
- [Int](#int)
|
||||||
- [Map](#map)
|
- [Map](#map)
|
||||||
- [Oracle](#oracle)
|
|
||||||
|
|
||||||
The following ones need to be included as regular files with `.aes` suffix, for example
|
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 the address a contract
|
||||||
|
|
||||||
|
|
||||||
#### is_oracle
|
|
||||||
```
|
|
||||||
Address.is_oracle(a : address) : bool
|
|
||||||
```
|
|
||||||
|
|
||||||
Is the address a registered oracle
|
|
||||||
|
|
||||||
|
|
||||||
#### is_payable
|
#### is_payable
|
||||||
```
|
```
|
||||||
Address.is_payable(a : address) : bool
|
Address.is_payable(a : address) : bool
|
||||||
@ -99,7 +90,7 @@ Cast address to contract type C (where `C` is a contract)
|
|||||||
### AENS
|
### AENS
|
||||||
|
|
||||||
The old AENS namespace, kept in the compiler to be able to interact with
|
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
|
earlier. Used in [AENSCompat](#aenscompat) when converting between old and new
|
||||||
pointers.
|
pointers.
|
||||||
|
|
||||||
@ -114,8 +105,9 @@ datatype name = Name(address, Chain.ttl, map(string, AENS.pointee))
|
|||||||
##### pointee
|
##### pointee
|
||||||
|
|
||||||
```
|
```
|
||||||
datatype pointee = AccountPt(address) | OraclePt(address)
|
datatype pointee = AccountPt(address)
|
||||||
| ContractPt(address) | ChannelPt(address)
|
| ContractPt(address)
|
||||||
|
| ChannelPt(address)
|
||||||
```
|
```
|
||||||
|
|
||||||
### AENSv2
|
### 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.
|
`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
|
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
|
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.
|
i.e. the signature material should be prefixed by the network id.
|
||||||
|
|
||||||
#### Types
|
#### Types
|
||||||
@ -141,8 +133,10 @@ datatype name = Name(address, Chain.ttl, map(string, AENSv2.pointee))
|
|||||||
##### pointee
|
##### pointee
|
||||||
|
|
||||||
```
|
```
|
||||||
datatype pointee = AccountPt(address) | OraclePt(address)
|
datatype pointee = AccountPt(address)
|
||||||
| ContractPt(address) | ChannelPt(address) | DataPt(bytes())
|
| ContractPt(address)
|
||||||
|
| ChannelPt(address)
|
||||||
|
| DataPt(bytes())
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: on-chain there is a maximum length enforced for `DataPt`, it is 1024 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
|
serialized structure containing `network id`, `owner address`, and
|
||||||
`Contract.address`.
|
`Contract.address`.
|
||||||
|
|
||||||
From Ceres (i.e. FATE VM version 3) the
|
The [signature](./sophia_features.md#delegation-signature) can also be generic
|
||||||
[signature](./sophia_features.md#delegation-signature) can also be generic
|
|
||||||
(allowing _all_, existing and future, names to be delegated with one
|
(allowing _all_, existing and future, names to be delegated with one
|
||||||
signature), i.e. containing `network id`, `owner address`, `Contract.address`.
|
signature), i.e. containing `network id`, `owner address`, `Contract.address`.
|
||||||
|
|
||||||
@ -287,7 +280,6 @@ namespace Chain =
|
|||||||
datatype ga_meta_tx = GAMetaTx(address, int)
|
datatype ga_meta_tx = GAMetaTx(address, int)
|
||||||
datatype paying_for_tx = PayingForTx(address, int)
|
datatype paying_for_tx = PayingForTx(address, int)
|
||||||
datatype base_tx = SpendTx(address, int, string)
|
datatype base_tx = SpendTx(address, int, string)
|
||||||
| OracleRegisterTx | OracleQueryTx | OracleResponseTx | OracleExtendTx
|
|
||||||
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
||||||
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
||||||
| ChannelCreateTx(address) | ChannelDepositTx(address, int) | ChannelWithdrawTx(address, int) |
|
| 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`
|
Gets the transaction hash during authentication. Note: `Auth.tx_hash`
|
||||||
computation differs between protocol versions (changed in Ceres!), see
|
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.
|
specification for details.
|
||||||
|
|
||||||
|
|
||||||
@ -537,7 +529,6 @@ datatype paying_for_tx = PayingForTx(address, int)
|
|||||||
##### base_tx
|
##### base_tx
|
||||||
```
|
```
|
||||||
datatype base_tx = SpendTx(address, int, string)
|
datatype base_tx = SpendTx(address, int, string)
|
||||||
| OracleRegisterTx | OracleQueryTx | OracleResponseTx | OracleExtendTx
|
|
||||||
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
| NamePreclaimTx | NameClaimTx(hash) | NameUpdateTx(string)
|
||||||
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
| NameRevokeTx(hash) | NameTransferTx(address, string)
|
||||||
| ChannelCreateTx(address) | ChannelDepositTx(address, int) | ChannelWithdrawTx(address, int) |
|
| 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
|
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
|
## Includable namespaces
|
||||||
|
|
||||||
These need to be explicitly included (with `.aes` suffix)
|
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
|
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
|
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
|
If you expect getting calls with malformed `frac`s in your contract, you should use
|
||||||
this function to verify the input.
|
this function to verify the input.
|
||||||
|
@ -28,8 +28,6 @@ interface main using as for hiding
|
|||||||
- `Char` character literal enclosed in `'` with escape character `\`
|
- `Char` character literal enclosed in `'` with escape character `\`
|
||||||
- `AccountAddress` base58-encoded 32 byte account pubkey with `ak_` prefix
|
- `AccountAddress` base58-encoded 32 byte account pubkey with `ak_` prefix
|
||||||
- `ContractAddress` base58-encoded 32 byte contract address with `ct_` 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
|
- `Signature` base58-encoded 64 byte cryptographic signature with `sg_` prefix
|
||||||
|
|
||||||
Valid string escape codes are
|
Valid string escape codes are
|
||||||
@ -46,7 +44,7 @@ Valid string escape codes are
|
|||||||
| `\xHexDigits` | *HexDigits* | |
|
| `\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.
|
details on the base58 literals.
|
||||||
|
|
||||||
## Layout blocks
|
## 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
|
| Id | Con | QId | QCon // Identifiers x, None, Map.member, AELib.Token
|
||||||
| Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%'
|
| Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%'
|
||||||
| AccountAddress | ContractAddress // Chain identifiers
|
| AccountAddress | ContractAddress // Chain identifiers
|
||||||
| OracleAddress | OracleQueryId // Chain identifiers
|
|
||||||
| Signature // Signature
|
| Signature // Signature
|
||||||
| '???' // Hole expression 1 + ???
|
| '???' // Hole expression 1 + ???
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
-define(LET_P(X, P, Q), aeso_parse_lib:bind(P, fun(X) -> Q end)).
|
-define(LET_P(X, P, Q), so_parse_lib:bind(P, fun(X) -> Q end)).
|
||||||
-define(LAZY_P(P), aeso_parse_lib:lazy(fun() -> P end)).
|
-define(LAZY_P(P), so_parse_lib:lazy(fun() -> P end)).
|
||||||
-define(MEMO_P(P), aeso_parse_lib:lazy(aeso_parse_lib:memoised(fun() -> P end))).
|
-define(MEMO_P(P), so_parse_lib:lazy(so_parse_lib:memoised(fun() -> P end))).
|
||||||
|
|
||||||
-define(GUARD_P(G, P),
|
-define(GUARD_P(G, P),
|
||||||
case G of
|
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, 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})).
|
-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,
|
[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,
|
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,
|
fail/0, fail/1, fail/2, map/2, infixl/2, infixr/2, infixl1/2, infixr1/2,
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
{erl_opts, [debug_info]}.
|
{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"}
|
, {eblake2, "1.0.0"}
|
||||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.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]}
|
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{relx, [{release, {aesophia, "8.0.1"},
|
{relx, [{release, {sophia, "9.0.0"},
|
||||||
[aesophia, aebytecode]},
|
[sophia, gmbytecode]},
|
||||||
|
|
||||||
{dev_mode, true},
|
{dev_mode, true},
|
||||||
{include_erts, false},
|
{include_erts, false},
|
||||||
|
|
||||||
{extended_start_script, true}]}.
|
{extended_start_script, true}]}.
|
||||||
|
|
||||||
|
37
rebar.lock
37
rebar.lock
@ -1,31 +1,30 @@
|
|||||||
{"1.2.0",
|
{"1.2.0",
|
||||||
[{<<"aebytecode">>,
|
[{<<"gmbytecode">>,
|
||||||
{git,"https://github.com/aeternity/aebytecode.git",
|
{git,"https://git.qpq.swiss/QPQ-AG/gmbytecode.git",
|
||||||
{ref,"6bd6f82c70d800950ea1a2c70c364a4181ff5291"}},
|
{ref, "97cea33be8f3a35d26055664da7aa59531ff5537"}},
|
||||||
0},
|
0},
|
||||||
{<<"aeserialization">>,
|
{<<"gmserialization">>,
|
||||||
{git,"https://github.com/aeternity/aeserialization.git",
|
{git,"https://git.qpq.swiss/QPQ-AG/gmserialization.git",
|
||||||
{ref,"b26e6d105424748ba1c27917267b7cff07f37802"}},
|
{ref,"ac64e01b0f675c1a34c70a827062f381920742db"}},
|
||||||
1},
|
1},
|
||||||
{<<"base58">>,
|
{<<"base58">>,
|
||||||
{git,"https://github.com/aeternity/erl-base58.git",
|
{git,"https://git.qpq.swiss/QPQ-AG/erl-base58.git",
|
||||||
{ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}},
|
{ref,"e6aa62eeae3d4388311401f06e4b939bf4e94b9c"}},
|
||||||
2},
|
2},
|
||||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
{<<"eblake2">>,
|
||||||
|
{git,"https://git.qpq.swiss/QPQ-AG/eblake2.git",
|
||||||
|
{ref,"b29d585b8760746142014884007eb8441a3b6a14"}},
|
||||||
|
0},
|
||||||
{<<"enacl">>,
|
{<<"enacl">>,
|
||||||
{git,"https://github.com/aeternity/enacl.git",
|
{git,"https://git.qpq.swiss/QPQ-AG/enacl.git",
|
||||||
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
|
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
|
||||||
2},
|
2},
|
||||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},1},
|
{<<"getopt">>,
|
||||||
|
{git,"https://git.qpq.swiss/QPQ-AG/getopt.git",
|
||||||
|
{ref,"dbab6262a2430809430deda9d8650f58f9d80898"}},
|
||||||
|
1},
|
||||||
{<<"jsx">>,
|
{<<"jsx">>,
|
||||||
{git,"https://github.com/talentdeficit/jsx.git",
|
{git,"https://github.com/talentdeficit/jsx.git",
|
||||||
{ref,"3074d4865b3385a050badf7828ad31490d860df5"}},
|
{ref,"3074d4865b3385a050badf7828ad31490d860df5"}},
|
||||||
0}]}.
|
0}]}.
|
||||||
[
|
|
||||||
{pkg_hash,[
|
|
||||||
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>},
|
|
||||||
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
|
|
||||||
{pkg_hash_ext,[
|
|
||||||
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>},
|
|
||||||
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
|
|
||||||
].
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
%%% @author Robert Virding
|
%%% @author Robert Virding
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% ACI interface
|
%%% ACI interface
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 12 Jan 2019
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_aci).
|
-module(so_aci).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([ file/2
|
-export([ file/2
|
||||||
, file/3
|
, file/3
|
||||||
@ -21,7 +22,7 @@
|
|||||||
, json_encode_expr/1
|
, json_encode_expr/1
|
||||||
, json_encode_type/1]).
|
, json_encode_type/1]).
|
||||||
|
|
||||||
-include("aeso_utils.hrl").
|
-include("so_utils.hrl").
|
||||||
|
|
||||||
-type aci_type() :: json | string.
|
-type aci_type() :: json | string.
|
||||||
-type json() :: jsx:json_term().
|
-type json() :: jsx:json_term().
|
||||||
@ -35,7 +36,7 @@ file(Type, File) ->
|
|||||||
file(Type, File, []).
|
file(Type, File, []).
|
||||||
|
|
||||||
file(Type, File, Options0) ->
|
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
|
case file:read_file(File) of
|
||||||
{ok, BinCode} ->
|
{ok, BinCode} ->
|
||||||
do_contract_interface(Type, binary_to_list(BinCode), Options);
|
do_contract_interface(Type, binary_to_list(BinCode), Options);
|
||||||
@ -56,11 +57,11 @@ contract_interface(Type, ContractString, CompilerOpts) ->
|
|||||||
render_aci_json(Json) ->
|
render_aci_json(Json) ->
|
||||||
do_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) ->
|
json_encode_expr(Expr) ->
|
||||||
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) ->
|
json_encode_type(Type) ->
|
||||||
encode_type(Type).
|
encode_type(Type).
|
||||||
|
|
||||||
@ -69,8 +70,8 @@ do_contract_interface(Type, Contract, Options) when is_binary(Contract) ->
|
|||||||
do_contract_interface(Type, binary_to_list(Contract), Options);
|
do_contract_interface(Type, binary_to_list(Contract), Options);
|
||||||
do_contract_interface(Type, ContractString, Options) ->
|
do_contract_interface(Type, ContractString, Options) ->
|
||||||
try
|
try
|
||||||
Ast = aeso_compiler:parse(ContractString, Options),
|
Ast = so_compiler:parse(ContractString, Options),
|
||||||
{TypedAst, _, _} = aeso_ast_infer_types:infer(Ast, [dont_unfold | Options]),
|
{TypedAst, _, _} = so_ast_infer_types:infer(Ast, [dont_unfold | Options]),
|
||||||
from_typed_ast(Type, TypedAst)
|
from_typed_ast(Type, TypedAst)
|
||||||
catch
|
catch
|
||||||
throw:{error, Errors} -> {error, Errors}
|
throw:{error, Errors} -> {error, Errors}
|
||||||
@ -200,7 +201,7 @@ encode_expr({bytes, _, B}) ->
|
|||||||
encode_expr({Lit, _, L}) when Lit == oracle_pubkey; Lit == oracle_query_id;
|
encode_expr({Lit, _, L}) when Lit == oracle_pubkey; Lit == oracle_query_id;
|
||||||
Lit == contract_pubkey; Lit == account_pubkey;
|
Lit == contract_pubkey; Lit == account_pubkey;
|
||||||
Lit == signature ->
|
Lit == signature ->
|
||||||
aeser_api_encoder:encode(Lit, L);
|
gmser_api_encoder:encode(Lit, L);
|
||||||
encode_expr({app, _, {'-', _}, [{int, _, N}]}) ->
|
encode_expr({app, _, {'-', _}, [{int, _, N}]}) ->
|
||||||
encode_expr({int, [], -N});
|
encode_expr({int, [], -N});
|
||||||
encode_expr({app, _, F, As}) ->
|
encode_expr({app, _, F, As}) ->
|
||||||
@ -361,14 +362,14 @@ is_type(_) -> false.
|
|||||||
|
|
||||||
sort_decls(Ds) ->
|
sort_decls(Ds) ->
|
||||||
Sort = fun (D1, D2) ->
|
Sort = fun (D1, D2) ->
|
||||||
aeso_syntax:get_ann(line, D1, 0) =<
|
so_syntax:get_ann(line, D1, 0) =<
|
||||||
aeso_syntax:get_ann(line, D2, 0)
|
so_syntax:get_ann(line, D2, 0)
|
||||||
end,
|
end,
|
||||||
lists:sort(Sort, Ds).
|
lists:sort(Sort, Ds).
|
||||||
|
|
||||||
is_entrypoint(Node) -> aeso_syntax:get_ann(entrypoint, Node, false).
|
is_entrypoint(Node) -> so_syntax:get_ann(entrypoint, Node, false).
|
||||||
is_stateful(Node) -> aeso_syntax:get_ann(stateful, Node, false).
|
is_stateful(Node) -> so_syntax:get_ann(stateful, Node, false).
|
||||||
is_payable(Node) -> aeso_syntax:get_ann(payable, Node, false).
|
is_payable(Node) -> so_syntax:get_ann(payable, Node, false).
|
||||||
|
|
||||||
typedef_name({type_def, _, {id, _, Name}, _, _}) -> Name.
|
typedef_name({type_def, _, {id, _, Name}, _, _}) -> Name.
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
-module(aeso_ast).
|
-module(so_ast).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([int/2,
|
-export([int/2,
|
||||||
line/1,
|
line/1,
|
||||||
@ -17,11 +18,11 @@ line({symbol, Line, _}) -> Line.
|
|||||||
symbol_name({symbol, _, Name}) -> Name.
|
symbol_name({symbol, _, Name}) -> Name.
|
||||||
|
|
||||||
pp(Ast) ->
|
pp(Ast) ->
|
||||||
String = prettypr:format(aeso_pretty:decls(Ast, [])),
|
String = prettypr:format(so_pretty:decls(Ast, [])),
|
||||||
io:format("Ast:\n~s\n", [String]).
|
io:format("Ast:\n~s\n", [String]).
|
||||||
|
|
||||||
pp_typed(TypedAst) ->
|
pp_typed(TypedAst) ->
|
||||||
%% io:format("Typed tree:\n~p\n",[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]).
|
io:format("Type ast:\n~s\n",[String]).
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,18 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
%%% @author Ulf Norell
|
%%% @author Ulf Norell
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Compiler from Aeterinty Sophia language to Fate intermediate code.
|
%%% Compiler from Sophia language to Fate intermediate code.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 26 Mar 2019
|
|
||||||
%%%
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_ast_to_fcode).
|
-module(so_ast_to_fcode).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([ast_to_fcode/2, format_fexpr/1]).
|
-export([ast_to_fcode/2, format_fexpr/1]).
|
||||||
-export_type([fcode/0, fexpr/0, fun_def/0]).
|
-export_type([fcode/0, fexpr/0, fun_def/0]).
|
||||||
|
|
||||||
-include("aeso_utils.hrl").
|
-include("so_utils.hrl").
|
||||||
|
|
||||||
%% -- Type definitions -------------------------------------------------------
|
%% -- Type definitions -------------------------------------------------------
|
||||||
|
|
||||||
@ -53,16 +53,14 @@
|
|||||||
| {bytes, binary()}
|
| {bytes, binary()}
|
||||||
| {account_pubkey, binary()}
|
| {account_pubkey, binary()}
|
||||||
| {contract_pubkey, binary()}
|
| {contract_pubkey, binary()}
|
||||||
| {oracle_pubkey, binary()}
|
|
||||||
| {oracle_query_id, binary()}
|
|
||||||
| {signature, binary()}
|
| {signature, binary()}
|
||||||
| {bool, false | true}
|
| {bool, false | true}
|
||||||
| {contract_code, string()} %% for CREATE, by name
|
| {contract_code, string()} %% for CREATE, by name
|
||||||
| {typerep, ftype()}.
|
| {typerep, ftype()}.
|
||||||
|
|
||||||
-type fann() :: [ {file, aeso_syntax:ann_file()} |
|
-type fann() :: [ {file, so_syntax:ann_file()} |
|
||||||
{line, aeso_syntax:ann_line()} |
|
{line, so_syntax:ann_line()} |
|
||||||
{col, aeso_syntax:ann_col()}
|
{col, so_syntax:ann_col()}
|
||||||
].
|
].
|
||||||
|
|
||||||
-type fexpr() :: {lit, fann(), flit()}
|
-type fexpr() :: {lit, fann(), flit()}
|
||||||
@ -115,8 +113,6 @@
|
|||||||
| address
|
| address
|
||||||
| {bytes, non_neg_integer()}
|
| {bytes, non_neg_integer()}
|
||||||
| contract
|
| contract
|
||||||
| {oracle, ftype(), ftype()} %% Query type, Response type
|
|
||||||
| oracle_query
|
|
||||||
| name
|
| name
|
||||||
| channel
|
| channel
|
||||||
| bits
|
| bits
|
||||||
@ -166,7 +162,7 @@
|
|||||||
fun_env := fun_env(),
|
fun_env := fun_env(),
|
||||||
con_env := con_env(),
|
con_env := con_env(),
|
||||||
child_con_env := child_con_env(),
|
child_con_env := child_con_env(),
|
||||||
event_type => aeso_syntax:typedef(),
|
event_type => so_syntax:typedef(),
|
||||||
builtins := builtins(),
|
builtins := builtins(),
|
||||||
options := [option()],
|
options := [option()],
|
||||||
state_layout => state_layout(),
|
state_layout => state_layout(),
|
||||||
@ -181,9 +177,9 @@
|
|||||||
|
|
||||||
%% -- Entrypoint -------------------------------------------------------------
|
%% -- 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.
|
%% 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) ->
|
ast_to_fcode(Code, Options) ->
|
||||||
init_fresh_names(Options),
|
init_fresh_names(Options),
|
||||||
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
||||||
@ -305,7 +301,7 @@ builtins() ->
|
|||||||
{"to_any_size", 1}, {"size", 1}, {"split_any", 2}]},
|
{"to_any_size", 1}, {"size", 1}, {"split_any", 2}]},
|
||||||
{["Int"], [{"to_str", 1}, {"to_bytes", 2}, {"mulmod", 2}]},
|
{["Int"], [{"to_str", 1}, {"to_bytes", 2}, {"mulmod", 2}]},
|
||||||
{["Address"], [{"to_str", 1}, {"to_bytes", 1}, {"to_contract", 1},
|
{["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}}
|
maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}}
|
||||||
|| {NS, Funs} <- Scopes,
|
|| {NS, Funs} <- Scopes,
|
||||||
@ -333,8 +329,6 @@ init_type_env() ->
|
|||||||
["address"] => ?type(address),
|
["address"] => ?type(address),
|
||||||
["hash"] => ?type(hash),
|
["hash"] => ?type(hash),
|
||||||
["signature"] => ?type(signature),
|
["signature"] => ?type(signature),
|
||||||
["oracle"] => ?type(Q, R, {oracle, Q, R}),
|
|
||||||
["oracle_query"] => ?type(_, _, oracle_query), %% TODO: not in Fate
|
|
||||||
["list"] => ?type(T, {list, T}),
|
["list"] => ?type(T, {list, T}),
|
||||||
["map"] => ?type(K, V, {map, K, V}),
|
["map"] => ?type(K, V, {map, K, V}),
|
||||||
["option"] => ?type(T, {variant, [[], [T]]}),
|
["option"] => ?type(T, {variant, [[], [T]]}),
|
||||||
@ -364,7 +358,7 @@ get_option(Opt, Env, Default) ->
|
|||||||
|
|
||||||
%% -- Compilation ------------------------------------------------------------
|
%% -- 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])
|
to_fcode(Env, [{Contract, Attrs, {con, _, Name}, _Impls, Decls}|Rest])
|
||||||
when ?IS_CONTRACT_HEAD(Contract) ->
|
when ?IS_CONTRACT_HEAD(Contract) ->
|
||||||
case Contract =:= contract_interface of
|
case Contract =:= contract_interface of
|
||||||
@ -405,7 +399,7 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) ->
|
|||||||
Env1 = decls_to_fcode(Env#{ context => {namespace, Con} }, Decls),
|
Env1 = decls_to_fcode(Env#{ context => {namespace, Con} }, Decls),
|
||||||
to_fcode(Env1, Code).
|
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,
|
File :: string() | none,
|
||||||
Line :: non_neg_integer() | none,
|
Line :: non_neg_integer() | none,
|
||||||
Column :: non_neg_integer() | none.
|
Column :: non_neg_integer() | none.
|
||||||
@ -415,7 +409,7 @@ ann_loc(Ann) ->
|
|||||||
Col = proplists:get_value(col, Ann, none),
|
Col = proplists:get_value(col, Ann, none),
|
||||||
{File, Line, Col}.
|
{File, Line, Col}.
|
||||||
|
|
||||||
-spec to_fann(aeso_syntax:ann()) -> fann().
|
-spec to_fann(so_syntax:ann()) -> fann().
|
||||||
to_fann(Ann) ->
|
to_fann(Ann) ->
|
||||||
{File, Line, Col} = ann_loc(Ann),
|
{File, Line, Col} = ann_loc(Ann),
|
||||||
[ {Tag, X} ||
|
[ {Tag, X} ||
|
||||||
@ -426,7 +420,7 @@ to_fann(Ann) ->
|
|||||||
-spec get_fann(fexpr()) -> fann().
|
-spec get_fann(fexpr()) -> fann().
|
||||||
get_fann(FExpr) -> element(2, FExpr).
|
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) ->
|
decls_to_fcode(Env, Decls) ->
|
||||||
%% First compute mapping from Sophia names to fun_names and add it to the
|
%% First compute mapping from Sophia names to fun_names and add it to the
|
||||||
%% environment.
|
%% environment.
|
||||||
@ -434,7 +428,7 @@ decls_to_fcode(Env, Decls) ->
|
|||||||
lists:foldl(fun(D, E) -> decl_to_fcode(E, D)
|
lists:foldl(fun(D, E) -> decl_to_fcode(E, D)
|
||||||
end, Env1, Decls).
|
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, {fun_decl, _, _, _}) -> Env;
|
||||||
decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) ->
|
decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) ->
|
||||||
typedef_to_fcode(Env, Name, Args, Def);
|
typedef_to_fcode(Env, Name, Args, Def);
|
||||||
@ -458,7 +452,7 @@ decl_to_fcode(Env = #{ consts := Consts }, {letval, _, {typed, _, {id, _, X}, _}
|
|||||||
NewConsts = Consts#{ qname(Env, X) => FVal },
|
NewConsts = Consts#{ qname(Env, X) => FVal },
|
||||||
Env#{ consts := NewConsts }.
|
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) ->
|
typedef_to_fcode(Env, {id, _, Name}, Xs, Def) ->
|
||||||
Q = qname(Env, Name),
|
Q = qname(Env, Name),
|
||||||
FDef = fun(Args) when length(Args) == length(Xs) ->
|
FDef = fun(Args) when length(Args) == length(Xs) ->
|
||||||
@ -525,11 +519,11 @@ compute_state_layout(R, [H | T]) ->
|
|||||||
compute_state_layout(R, _) ->
|
compute_state_layout(R, _) ->
|
||||||
{R + 1, {reg, 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) ->
|
||||||
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, {con, _, _}) -> contract;
|
||||||
type_to_fcode(Env, Sub, {app_t, _, T = {Id, _, _}, Types}) when Id == id; Id == qid ->
|
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]);
|
lookup_type(Env, T, [type_to_fcode(Env, Sub, Type) || Type <- Types]);
|
||||||
@ -555,7 +549,7 @@ type_to_fcode(Env, Sub, {if_t, _, _, _, Else}) ->
|
|||||||
type_to_fcode(_Env, _Sub, Type) ->
|
type_to_fcode(_Env, _Sub, Type) ->
|
||||||
error({todo, 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) ->
|
args_to_fcode(Env, Args) ->
|
||||||
[ case Arg of
|
[ case Arg of
|
||||||
{id, _, Name} -> {Name, type_to_fcode(Env, Type)};
|
{id, _, Name} -> {Name, type_to_fcode(Env, Type)};
|
||||||
@ -586,13 +580,13 @@ let_bind(Binds, Body) ->
|
|||||||
lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end,
|
lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end,
|
||||||
Body, Binds).
|
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, {typed, _, Expr, Type}) ->
|
||||||
expr_to_fcode(Env, Type, Expr);
|
expr_to_fcode(Env, Type, Expr);
|
||||||
expr_to_fcode(Env, Expr) ->
|
expr_to_fcode(Env, Expr) ->
|
||||||
expr_to_fcode(Env, no_type, 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
|
%% Literals
|
||||||
expr_to_fcode(_Env, _Type, {int, Ann, N}) -> {lit, to_fann(Ann), {int, N}};
|
expr_to_fcode(_Env, _Type, {int, Ann, N}) -> {lit, to_fann(Ann), {int, N}};
|
||||||
@ -602,25 +596,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, {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, {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, {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}};
|
expr_to_fcode(_Env, _Type, {bytes, Ann, B}) -> {lit, to_fann(Ann), {bytes, B}};
|
||||||
|
|
||||||
%% Variables
|
%% Variables
|
||||||
expr_to_fcode(Env, _Type, {id, Ann, X}) -> resolve_var(Env, Ann, [X]);
|
expr_to_fcode(Env, _Type, {id, Ann, X}) -> resolve_var(Env, Ann, [X]);
|
||||||
expr_to_fcode(Env, Type, {qid, Ann, X}) ->
|
expr_to_fcode(Env, Type, {qid, Ann, X}) ->
|
||||||
case resolve_var(Env, Ann, X) of
|
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} ->
|
{builtin_u, FAnn, B = aens_resolve, Ar} ->
|
||||||
{fun_t, _, _, _, ResType} = Type,
|
{fun_t, _, _, _, ResType} = Type,
|
||||||
AensType = type_to_fcode(Env, ResType),
|
AensType = type_to_fcode(Env, ResType),
|
||||||
@ -705,7 +686,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) ->
|
|||||||
|
|
||||||
%% Lists
|
%% Lists
|
||||||
expr_to_fcode(Env, _Type, {list, Ann, Es}) ->
|
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);
|
{nil, to_fann(Ann)}, Es);
|
||||||
|
|
||||||
expr_to_fcode(Env, _Type, {app, As, {'..', _}, [A, B]}) ->
|
expr_to_fcode(Env, _Type, {app, As, {'..', _}, [A, B]}) ->
|
||||||
@ -783,15 +764,15 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A
|
|||||||
var_args -> fcode_error({var_args_not_set, FunE});
|
var_args -> fcode_error({var_args_not_set, FunE});
|
||||||
_ ->
|
_ ->
|
||||||
%% Here we little cheat on the typechecker, but this inconsistency
|
%% Here we little cheat on the typechecker, but this inconsistency
|
||||||
%% is to be solved in `aeso_fcode_to_fate:type_to_scode/1`
|
%% is to be solved in `so_fcode_to_fate:type_to_scode/1`
|
||||||
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_clone, [{lit, FAnn, FInitArgsT}|FArgs])
|
builtin_to_fcode(state_layout(Env), FAnn, chain_clone, [{lit, FAnn, FInitArgsT}|FArgs])
|
||||||
end;
|
end;
|
||||||
{builtin_u, FAnn, chain_create, _Ar} ->
|
{builtin_u, FAnn, chain_create, _Ar} ->
|
||||||
case {ArgsT, Type} of
|
case {ArgsT, Type} of
|
||||||
{var_args, _} -> fcode_error({var_args_not_set, FunE});
|
{var_args, _} -> fcode_error({var_args_not_set, FunE});
|
||||||
{_, {con, _, Contract}} ->
|
{_, {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]);
|
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})
|
{_, _} -> fcode_error({not_a_contract_type, Type})
|
||||||
end;
|
end;
|
||||||
@ -884,21 +865,10 @@ make_tuple_fpat(Ps) -> {tuple, Ps}.
|
|||||||
strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T);
|
strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T);
|
||||||
strip_singleton_tuples(T) -> 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 --
|
%% -- 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) ->
|
alts_to_fcode(Env, Type, X, Alts, Switch) ->
|
||||||
FAlts = remove_guards(Env, Alts, Switch),
|
FAlts = remove_guards(Env, Alts, Switch),
|
||||||
split_tree(Env, [{X, Type}], FAlts).
|
split_tree(Env, [{X, Type}], FAlts).
|
||||||
@ -915,7 +885,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) ->
|
|||||||
| {con, arities(), tag(), [fpat()]}
|
| {con, arities(), tag(), [fpat()]}
|
||||||
| {assign, fpat(), 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, [], _Switch) ->
|
||||||
[];
|
[];
|
||||||
remove_guards(Env, [Alt = {'case', _, _, [{guarded, _, [], _Expr}]} | Rest], Switch) ->
|
remove_guards(Env, [Alt = {'case', _, _, [{guarded, _, [], _Expr}]} | Rest], Switch) ->
|
||||||
@ -1080,19 +1050,19 @@ next_split(Pats) ->
|
|||||||
[I | _] -> I
|
[I | _] -> I
|
||||||
end.
|
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}]}) ->
|
alt_to_fcode(Env, {'case', _, Pat, [{guarded, _, [], Expr}]}) ->
|
||||||
FPat = pat_to_fcode(Env, Pat),
|
FPat = pat_to_fcode(Env, Pat),
|
||||||
FExpr = expr_to_fcode(bind_vars(Env, pat_vars(FPat)), Expr),
|
FExpr = expr_to_fcode(bind_vars(Env, pat_vars(FPat)), Expr),
|
||||||
{'case', [FPat], FExpr}.
|
{'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, {typed, _, Pat, Type}) ->
|
||||||
pat_to_fcode(Env, Type, Pat);
|
pat_to_fcode(Env, Type, Pat);
|
||||||
pat_to_fcode(Env, Pat) ->
|
pat_to_fcode(Env, Pat) ->
|
||||||
pat_to_fcode(Env, no_type, 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, {id, _, X}) -> {var, X};
|
||||||
pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon ->
|
pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon ->
|
||||||
#con_tag{tag = I, arities = As} = lookup_con(Env, Con),
|
#con_tag{tag = I, arities = As} = lookup_con(Env, Con),
|
||||||
@ -1134,7 +1104,7 @@ pat_to_fcode(_Env, Type, Pat) ->
|
|||||||
| {atom, fexpr()}
|
| {atom, fexpr()}
|
||||||
| {'if', fexpr(), decision_tree(), decision_tree()}.
|
| {'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('&&', {atom, A}, B) -> {'if', A, B, false};
|
||||||
decision_op('&&', false, _) -> false;
|
decision_op('&&', false, _) -> false;
|
||||||
decision_op('&&', true, B) -> B;
|
decision_op('&&', true, B) -> B;
|
||||||
@ -1144,7 +1114,7 @@ decision_op('||', true, _) -> true;
|
|||||||
decision_op(Op, {'if', A, Then, Else}, B) ->
|
decision_op(Op, {'if', A, Then, Else}, B) ->
|
||||||
{'if', A, decision_op(Op, Then, B), decision_op(Op, 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 == '||' ->
|
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));
|
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);
|
expr_to_decision_tree(Env, {typed, _, Expr, _}) -> expr_to_decision_tree(Env, Expr);
|
||||||
@ -1163,7 +1133,7 @@ decision_tree_to_fcode({'if', A, Then, Else}) ->
|
|||||||
|
|
||||||
%% -- Statements --
|
%% -- 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]) ->
|
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)};
|
{'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]) ->
|
stmts_to_fcode(Env, [{letval, Ann, Pat, Expr} | Stmts]) ->
|
||||||
@ -1178,7 +1148,7 @@ stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Ex
|
|||||||
stmts_to_fcode(Env, [Expr]) ->
|
stmts_to_fcode(Env, [Expr]) ->
|
||||||
expr_to_fcode(Env, Expr);
|
expr_to_fcode(Env, Expr);
|
||||||
stmts_to_fcode(Env, [Expr | Stmts]) ->
|
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 --
|
%% -- Builtins --
|
||||||
|
|
||||||
@ -1810,7 +1780,7 @@ used_functions(Used, [Name | Rest], Defs) ->
|
|||||||
|
|
||||||
%% -- Types --
|
%% -- 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, {id, _, Name}, Args) ->
|
||||||
lookup_type(Env, [Name], Args);
|
lookup_type(Env, [Name], Args);
|
||||||
lookup_type(Env, {qid, _, Name}, Args) ->
|
lookup_type(Env, {qid, _, Name}, Args) ->
|
||||||
@ -1842,7 +1812,7 @@ bind_constructors(Env = #{ con_env := ConEnv }, NewCons) ->
|
|||||||
add_child_con(Env = #{child_con_env := CEnv}, Name, Fcode) ->
|
add_child_con(Env = #{child_con_env := CEnv}, Name, Fcode) ->
|
||||||
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 = #{ context := {abstract_contract, _} }, _) -> Env; %% no functions from abstract contracts
|
||||||
add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
||||||
Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) ->
|
Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) ->
|
||||||
@ -1853,7 +1823,7 @@ add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
|||||||
FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)),
|
FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)),
|
||||||
Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }.
|
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) ->
|
make_fun_name(#{ context := Context }, Ann, Name) ->
|
||||||
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
||||||
case Context of
|
case Context of
|
||||||
@ -1884,7 +1854,7 @@ lookup_fun(#{ fun_env := FunEnv }, Name) ->
|
|||||||
{FName, _} -> FName
|
{FName, _} -> FName
|
||||||
end.
|
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, {con, _, Con}) -> lookup_con(Env, [Con]);
|
||||||
lookup_con(Env, {qcon, _, Con}) -> lookup_con(Env, Con);
|
lookup_con(Env, {qcon, _, Con}) -> lookup_con(Env, Con);
|
||||||
lookup_con(#{ con_env := ConEnv }, Con) ->
|
lookup_con(#{ con_env := ConEnv }, Con) ->
|
||||||
@ -1900,7 +1870,7 @@ bind_vars(Env, Xs) ->
|
|||||||
-spec bind_var(env(), var_name()) -> env().
|
-spec bind_var(env(), var_name()) -> env().
|
||||||
bind_var(Env = #{ vars := Vars }, X) -> Env#{ vars := [X | Vars] }.
|
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]) ->
|
resolve_var(#{ vars := Vars } = Env, Ann, [X]) ->
|
||||||
case lists:member(X, Vars) of
|
case lists:member(X, Vars) of
|
||||||
true -> {var, to_fann(Ann), X};
|
true -> {var, to_fann(Ann), X};
|
||||||
@ -1922,7 +1892,7 @@ resolve_const(#{ consts := Consts }, Q) ->
|
|||||||
Val -> Val
|
Val -> Val
|
||||||
end.
|
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) ->
|
resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Ann, Q) ->
|
||||||
case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of
|
case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of
|
||||||
{not_found, not_found} -> internal_error({unbound_variable, Q});
|
{not_found, not_found} -> internal_error({unbound_variable, Q});
|
||||||
@ -2102,7 +2072,7 @@ bottom_up(F, Env, Expr) ->
|
|||||||
{'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)}
|
{'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)}
|
||||||
end).
|
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) ->
|
get_named_args(NamedArgsT, Args) ->
|
||||||
IsNamed = fun({named_arg, _, _, _}) -> true;
|
IsNamed = fun({named_arg, _, _, _}) -> true;
|
||||||
(_) -> false end,
|
(_) -> false end,
|
||||||
@ -2110,7 +2080,7 @@ get_named_args(NamedArgsT, Args) ->
|
|||||||
NamedArgs = [get_named_arg(NamedArg, Named) || NamedArg <- NamedArgsT],
|
NamedArgs = [get_named_arg(NamedArg, Named) || NamedArg <- NamedArgsT],
|
||||||
NamedArgs ++ NotNamed.
|
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) ->
|
get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) ->
|
||||||
case [ Val || {named_arg, _, {id, _, X}, Val} <- Args, X == Name ] of
|
case [ Val || {named_arg, _, {id, _, X}, Val} <- Args, X == Name ] of
|
||||||
[Val] -> Val;
|
[Val] -> Val;
|
||||||
@ -2236,15 +2206,15 @@ update_rename(OldRen, NewRen) ->
|
|||||||
|
|
||||||
%% -- Records --
|
%% -- 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) ->
|
field_index({record_t, Fields}, X) ->
|
||||||
IsX = fun({field_t, _, {id, _, Y}, _}) -> X == Y end,
|
IsX = fun({field_t, _, {id, _, Y}, _}) -> X == Y end,
|
||||||
[I] = [ I || {I, Field} <- indexed(Fields), IsX(Field) ],
|
[I] = [ I || {I, Field} <- indexed(Fields), IsX(Field) ],
|
||||||
I - 1. %% Tuples are 0-indexed
|
I - 1. %% Tuples are 0-indexed
|
||||||
|
|
||||||
-spec field_value(aeso_syntax:field_t(), [aeso_syntax:field(aeso_syntax:pat())]) -> Res when
|
-spec field_value(so_syntax:field_t(), [so_syntax:field(so_syntax:pat())]) -> Res when
|
||||||
Res :: {upd, aeso_syntax:name(), Expr} | {set, Expr} | false,
|
Res :: {upd, so_syntax:name(), Expr} | {set, Expr} | false,
|
||||||
Expr :: aeso_syntax:expr().
|
Expr :: so_syntax:expr().
|
||||||
field_value({field_t, _, {id, _, X}, _}, Fields) ->
|
field_value({field_t, _, {id, _, X}, _}, Fields) ->
|
||||||
View = fun({field, _, [{proj, _, {id, _, Y}}], E}) -> {Y, {set, E}};
|
View = fun({field, _, [{proj, _, {id, _, Y}}], E}) -> {Y, {set, E}};
|
||||||
({field_upd, _, [{proj, _, {id, _, Y}}],
|
({field_upd, _, [{proj, _, {id, _, Y}}],
|
||||||
@ -2256,13 +2226,13 @@ field_value({field_t, _, {id, _, X}, _}, Fields) ->
|
|||||||
|
|
||||||
%% -- Attributes --
|
%% -- Attributes --
|
||||||
|
|
||||||
-spec get_attributes(aeso_syntax:ann()) -> [stateful | payable | private].
|
-spec get_attributes(so_syntax:ann()) -> [stateful | payable | private].
|
||||||
get_attributes(Ann) ->
|
get_attributes(Ann) ->
|
||||||
[stateful || proplists:get_value(stateful, Ann, false)] ++
|
[stateful || proplists:get_value(stateful, Ann, false)] ++
|
||||||
[payable || proplists:get_value(payable, Ann, false)] ++
|
[payable || proplists:get_value(payable, Ann, false)] ++
|
||||||
[private || not proplists:get_value(entrypoint, 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_debug(Ann) ->
|
||||||
get_attributes(Ann) ++ to_fann(Ann).
|
get_attributes(Ann) ++ to_fann(Ann).
|
||||||
|
|
||||||
@ -2283,14 +2253,14 @@ setnth(I, X, Xs) ->
|
|||||||
|
|
||||||
-spec fcode_error(string()) -> no_return().
|
-spec fcode_error(string()) -> no_return().
|
||||||
fcode_error(Error) ->
|
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])),
|
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().
|
-spec internal_error(string()) -> no_return().
|
||||||
internal_error(Error) ->
|
internal_error(Error) ->
|
||||||
Msg = lists:flatten(io_lib:format("~p\n", [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 --------------------------------------------------------
|
%% -- Pretty printing --------------------------------------------------------
|
||||||
|
|
||||||
@ -2367,7 +2337,7 @@ pp_fexpr({lit, _, {typerep, T}}) ->
|
|||||||
pp_fexpr({lit, _, {contract_code, Contract}}) ->
|
pp_fexpr({lit, _, {contract_code, Contract}}) ->
|
||||||
pp_beside(pp_text("contract "), pp_text(Contract));
|
pp_beside(pp_text("contract "), pp_text(Contract));
|
||||||
pp_fexpr({lit, _, {Tag, Lit}}) ->
|
pp_fexpr({lit, _, {Tag, Lit}}) ->
|
||||||
aeso_pretty:expr({Tag, [], Lit});
|
so_pretty:expr({Tag, [], Lit});
|
||||||
pp_fexpr({nil, _}) ->
|
pp_fexpr({nil, _}) ->
|
||||||
pp_text("[]");
|
pp_text("[]");
|
||||||
pp_fexpr({var, _, X}) -> pp_text(X);
|
pp_fexpr({var, _, X}) -> pp_text(X);
|
||||||
@ -2451,7 +2421,6 @@ pp_ftype(T) when is_atom(T) -> pp_text(T);
|
|||||||
pp_ftype(any) -> pp_text("_");
|
pp_ftype(any) -> pp_text("_");
|
||||||
pp_ftype({tvar, X}) -> pp_text(X);
|
pp_ftype({tvar, X}) -> pp_text(X);
|
||||||
pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, [], {int, N}}]);
|
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_ftype({tuple, Ts}) ->
|
||||||
pp_parens(pp_par(pp_punctuate(pp_text(" *"), [pp_ftype(T) || T <- Ts])));
|
pp_parens(pp_par(pp_punctuate(pp_text(" *"), [pp_ftype(T) || T <- Ts])));
|
||||||
pp_ftype({list, T}) ->
|
pp_ftype({list, T}) ->
|
@ -1,12 +1,13 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
%%% @author Happi (Erik Stenman)
|
%%% @author Happi (Erik Stenman)
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Compiler from Aeterinty Sophia language to FATE.
|
%%% Compiler from Sophia language to FATE.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 12 Dec 2017
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_compiler).
|
-module(so_compiler).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([ file/1
|
-export([ file/1
|
||||||
, file/2
|
, file/2
|
||||||
@ -27,8 +28,8 @@
|
|||||||
, validate_byte_code/3
|
, validate_byte_code/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
-include_lib("gmbytecode/include/gmb_opcodes.hrl").
|
||||||
-include("aeso_utils.hrl").
|
-include("so_utils.hrl").
|
||||||
|
|
||||||
|
|
||||||
-type option() :: pp_sophia_code
|
-type option() :: pp_sophia_code
|
||||||
@ -43,7 +44,7 @@
|
|||||||
{explicit_files, #{string() => binary()}}}
|
{explicit_files, #{string() => binary()}}}
|
||||||
| {src_file, string()}
|
| {src_file, string()}
|
||||||
| {src_dir, string()}
|
| {src_dir, string()}
|
||||||
| {aci, aeso_aci:aci_type()}.
|
| {aci, so_aci:aci_type()}.
|
||||||
-type options() :: [option()].
|
-type options() :: [option()].
|
||||||
|
|
||||||
-export_type([ option/0
|
-export_type([ option/0
|
||||||
@ -52,15 +53,15 @@
|
|||||||
|
|
||||||
-spec version() -> {ok, binary()} | {error, term()}.
|
-spec version() -> {ok, binary()} | {error, term()}.
|
||||||
version() ->
|
version() ->
|
||||||
case lists:keyfind(aesophia, 1, application:loaded_applications()) of
|
case lists:keyfind(sophia, 1, application:loaded_applications()) of
|
||||||
false ->
|
false ->
|
||||||
case application:load(aesophia) of
|
case application:load(sophia) of
|
||||||
ok ->
|
ok ->
|
||||||
case application:get_key(aesophia, vsn) of
|
case application:get_key(sophia, vsn) of
|
||||||
{ok, VsnString} ->
|
{ok, VsnString} ->
|
||||||
{ok, list_to_binary(VsnString)};
|
{ok, list_to_binary(VsnString)};
|
||||||
undefined ->
|
undefined ->
|
||||||
{error, failed_to_load_aesophia}
|
{error, failed_to_load_sophia}
|
||||||
end;
|
end;
|
||||||
Err = {error, _} ->
|
Err = {error, _} ->
|
||||||
Err
|
Err
|
||||||
@ -80,20 +81,20 @@ numeric_version() ->
|
|||||||
Err
|
Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec file(string()) -> {ok, map()} | {error, [aeso_errors:error()]}.
|
-spec file(string()) -> {ok, map()} | {error, [so_errors:error()]}.
|
||||||
file(Filename) ->
|
file(Filename) ->
|
||||||
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) ->
|
file(File, Options0) ->
|
||||||
Options = add_include_path(File, Options0),
|
Options = add_include_path(File, Options0),
|
||||||
case read_contract(File) of
|
case read_contract(File) of
|
||||||
{ok, Bin} ->
|
{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]);
|
from_string(Bin, [{src_file, File}, {src_dir, SrcDir} | Options]);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
Msg = lists:flatten([File,": ",file:format_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.
|
end.
|
||||||
|
|
||||||
add_include_path(File, Options) ->
|
add_include_path(File, Options) ->
|
||||||
@ -102,10 +103,10 @@ add_include_path(File, Options) ->
|
|||||||
false ->
|
false ->
|
||||||
Dir = filename:dirname(File),
|
Dir = filename:dirname(File),
|
||||||
{ok, Cwd} = file:get_cwd(),
|
{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.
|
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(ContractBin, Options) when is_binary(ContractBin) ->
|
||||||
from_string(binary_to_list(ContractBin), Options);
|
from_string(binary_to_list(ContractBin), Options);
|
||||||
from_string(ContractString, Options) ->
|
from_string(ContractString, Options) ->
|
||||||
@ -122,16 +123,16 @@ from_string1(ContractString, Options) ->
|
|||||||
, warnings := Warnings } = string_to_code(ContractString, Options),
|
, warnings := Warnings } = string_to_code(ContractString, Options),
|
||||||
#{ child_con_env := ChildContracts } = FCodeEnv,
|
#{ child_con_env := ChildContracts } = FCodeEnv,
|
||||||
SavedFreshNames = maps:get(saved_fresh_names, 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),
|
pp_assembler(FateCode, Options),
|
||||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
ByteCode = gmb_fate_code:serialize(FateCode, []),
|
||||||
{ok, Version} = version(),
|
{ok, Version} = version(),
|
||||||
Res = #{byte_code => ByteCode,
|
Res = #{byte_code => ByteCode,
|
||||||
compiler_version => Version,
|
compiler_version => Version,
|
||||||
contract_source => ContractString,
|
contract_source => ContractString,
|
||||||
type_info => [],
|
type_info => [],
|
||||||
fate_code => FateCode,
|
fate_code => FateCode,
|
||||||
abi_version => aeb_fate_abi:abi_version(),
|
abi_version => gmb_fate_abi:abi_version(),
|
||||||
payable => maps:get(payable, FCode),
|
payable => maps:get(payable, FCode),
|
||||||
warnings => Warnings
|
warnings => Warnings
|
||||||
},
|
},
|
||||||
@ -142,7 +143,7 @@ maybe_generate_aci(Result, FoldedTypedAst, Options) ->
|
|||||||
undefined ->
|
undefined ->
|
||||||
Result;
|
Result;
|
||||||
Type ->
|
Type ->
|
||||||
{ok, Aci} = aeso_aci:from_typed_ast(Type, FoldedTypedAst),
|
{ok, Aci} = so_aci:from_typed_ast(Type, FoldedTypedAst),
|
||||||
maps:put(aci, Aci, Result)
|
maps:put(aci, Aci, Result)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -151,9 +152,9 @@ string_to_code(ContractString, Options) ->
|
|||||||
Ast = parse(ContractString, Options),
|
Ast = parse(ContractString, Options),
|
||||||
pp_sophia_code(Ast, Options),
|
pp_sophia_code(Ast, Options),
|
||||||
pp_ast(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),
|
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 => Fcode
|
||||||
, fcode_env => Env
|
, fcode_env => Env
|
||||||
, unfolded_typed_ast => UnfoldedTypedAst
|
, unfolded_typed_ast => UnfoldedTypedAst
|
||||||
@ -171,7 +172,7 @@ string_to_code(ContractString, Options) ->
|
|||||||
%% NOTE: Special treatment for "init" since it might be implicit and has
|
%% NOTE: Special treatment for "init" since it might be implicit and has
|
||||||
%% a special return type (typerep, T)
|
%% a special return type (typerep, T)
|
||||||
-spec check_call(string(), string(), [string()], options()) -> {ok, string(), [term()]}
|
-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) ->
|
check_call(Source, "init" = FunName, Args, Options) ->
|
||||||
case check_call1(Source, FunName, Args, Options) of
|
case check_call1(Source, FunName, Args, Options) of
|
||||||
Err = {error, _} when Args == [] ->
|
Err = {error, _} when Args == [] ->
|
||||||
@ -190,7 +191,7 @@ check_call1(ContractString0, FunName, Args, Options) ->
|
|||||||
case add_extra_call(ContractString0, {call, FunName, Args}, Options) of
|
case add_extra_call(ContractString0, {call, FunName, Args}, Options) of
|
||||||
{ok, CallName, Code} ->
|
{ok, CallName, Code} ->
|
||||||
{def, _, _, FcodeArgs} = get_call_body(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 = {error, _} ->
|
||||||
Err
|
Err
|
||||||
end.
|
end.
|
||||||
@ -201,9 +202,9 @@ add_extra_call(Contract0, Call, Options) ->
|
|||||||
#{fcode := OrgFcode
|
#{fcode := OrgFcode
|
||||||
, fcode_env := #{child_con_env := ChildContracts}
|
, fcode_env := #{child_con_env := ChildContracts}
|
||||||
, ast := Ast} = string_to_code(Contract0, Options),
|
, 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
|
%% 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,
|
CallName = first_none_match(?CALL_NAME, SymbolHashes,
|
||||||
lists:seq($1, $9) ++ lists:seq($A, $Z) ++ lists:seq($a, $z)),
|
lists:seq($1, $9) ++ lists:seq($A, $Z) ++ lists:seq($a, $z)),
|
||||||
Contract = insert_call_function(Ast, Contract0, CallName, Call),
|
Contract = insert_call_function(Ast, Contract0, CallName, Call),
|
||||||
@ -220,7 +221,7 @@ encode_value(Contract0, Type, Value, Options) ->
|
|||||||
case add_extra_call(Contract0, {value, Type, Value}, Options) of
|
case add_extra_call(Contract0, {value, Type, Value}, Options) of
|
||||||
{ok, CallName, Code} ->
|
{ok, CallName, Code} ->
|
||||||
Body = get_call_body(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 = {error, _} ->
|
||||||
Err
|
Err
|
||||||
end.
|
end.
|
||||||
@ -231,7 +232,7 @@ decode_value(Contract0, Type, FateValue, Options) ->
|
|||||||
#{ folded_typed_ast := TypedAst
|
#{ folded_typed_ast := TypedAst
|
||||||
, type_env := TypeEnv} = Code,
|
, type_env := TypeEnv} = Code,
|
||||||
{ok, _, Type0} = get_decode_type(CallName, TypedAst),
|
{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_record_types
|
||||||
, unfold_variant_types
|
, unfold_variant_types
|
||||||
, not_unfold_system_alias_types ]),
|
, not_unfold_system_alias_types ]),
|
||||||
@ -243,7 +244,7 @@ decode_value(Contract0, Type, FateValue, Options) ->
|
|||||||
first_none_match(_CallName, _Hashes, []) ->
|
first_none_match(_CallName, _Hashes, []) ->
|
||||||
error(unable_to_find_unique_call_name);
|
error(unable_to_find_unique_call_name);
|
||||||
first_none_match(CallName, Hashes, [Char|Chars]) ->
|
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 ->
|
true ->
|
||||||
CallName;
|
CallName;
|
||||||
false ->
|
false ->
|
||||||
@ -251,7 +252,7 @@ first_none_match(CallName, Hashes, [Char|Chars]) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
%% Add the __call function to a contract.
|
%% 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().
|
{call, string(), [string()]} | {value, string(), string()} | {type, string()}) -> string().
|
||||||
insert_call_function(Ast, Code, Call, {call, FunName, Args}) ->
|
insert_call_function(Ast, Code, Call, {call, FunName, Args}) ->
|
||||||
Ind = last_contract_indent(Ast),
|
Ind = last_contract_indent(Ast),
|
||||||
@ -290,25 +291,25 @@ insert_init_function(Code, Options) ->
|
|||||||
|
|
||||||
last_contract_indent(Decls) ->
|
last_contract_indent(Decls) ->
|
||||||
case lists:last(Decls) of
|
case lists:last(Decls) of
|
||||||
{_, _, _, _, [Decl | _]} -> aeso_syntax:get_ann(col, Decl, 1) - 1;
|
{_, _, _, _, [Decl | _]} -> so_syntax:get_ann(col, Decl, 1) - 1;
|
||||||
_ -> 0
|
_ -> 0
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec to_sophia_value(string(), string(), ok | error | revert, binary()) ->
|
-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) ->
|
||||||
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()) ->
|
-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) ->
|
to_sophia_value(_, _, error, Err, _Options) ->
|
||||||
{ok, {app, [], {id, [], "error"}, [{string, [], Err}]}};
|
{ok, {app, [], {id, [], "error"}, [{string, [], Err}]}};
|
||||||
to_sophia_value(_, _, revert, Data, _Options) ->
|
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 ->
|
Err ->
|
||||||
{ok, {app, [], {id, [], "abort"}, [Err]}}
|
{ok, {app, [], {id, [], "abort"}, [Err]}}
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
Msg = "Could not deserialize the revert message",
|
Msg = "Could not deserialize the revert message",
|
||||||
{error, [aeso_errors:new(data_error, Msg)]}
|
{error, [so_errors:new(data_error, Msg)]}
|
||||||
end;
|
end;
|
||||||
to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
||||||
Options = [no_code | Options0],
|
Options = [no_code | Options0],
|
||||||
@ -316,7 +317,7 @@ to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
|||||||
Code = string_to_code(ContractString, Options),
|
Code = string_to_code(ContractString, Options),
|
||||||
#{ folded_typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
#{ folded_typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
||||||
{ok, _, Type0} = get_decode_type(FunName, TypedAst),
|
{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_record_types
|
||||||
, unfold_variant_types
|
, unfold_variant_types
|
||||||
, not_unfold_system_alias_types]),
|
, not_unfold_system_alias_types]),
|
||||||
@ -328,40 +329,40 @@ to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
|||||||
|
|
||||||
fate_data_to_sophia_value(Type, UnfoldedType, FateData) ->
|
fate_data_to_sophia_value(Type, UnfoldedType, FateData) ->
|
||||||
try
|
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 ->
|
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",
|
Msg = io_lib:format("Cannot translate FATE value ~p\n of Sophia type ~s",
|
||||||
[aeb_fate_encoding:deserialize(FateData), Type1]),
|
[gmb_fate_encoding:deserialize(FateData), Type1]),
|
||||||
{error, [aeso_errors:new(data_error, Msg)]};
|
{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]),
|
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.
|
end.
|
||||||
|
|
||||||
-spec create_calldata(string(), string(), [string()]) ->
|
-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) ->
|
||||||
create_calldata(Code, Fun, Args, []).
|
create_calldata(Code, Fun, Args, []).
|
||||||
-spec create_calldata(string(), string(), [string()], [{atom(), any()}]) ->
|
-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) ->
|
create_calldata(Code, Fun, Args, Options0) ->
|
||||||
Options = [no_code | Options0],
|
Options = [no_code | Options0],
|
||||||
case check_call(Code, Fun, Args, Options) of
|
case check_call(Code, Fun, Args, Options) of
|
||||||
{ok, FunName, FateArgs} ->
|
{ok, FunName, FateArgs} ->
|
||||||
aeb_fate_abi:create_calldata(FunName, FateArgs);
|
gmb_fate_abi:create_calldata(FunName, FateArgs);
|
||||||
{error, _} = Err -> Err
|
{error, _} = Err -> Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec decode_calldata(string(), string(), binary()) ->
|
-spec decode_calldata(string(), string(), binary()) ->
|
||||||
{ok, [aeso_syntax:type()], [aeso_syntax:expr()]}
|
{ok, [so_syntax:type()], [so_syntax:expr()]}
|
||||||
| {error, [aeso_errors:error()]}.
|
| {error, [so_errors:error()]}.
|
||||||
decode_calldata(ContractString, FunName, Calldata) ->
|
decode_calldata(ContractString, FunName, Calldata) ->
|
||||||
decode_calldata(ContractString, FunName, Calldata, []).
|
decode_calldata(ContractString, FunName, Calldata, []).
|
||||||
-spec decode_calldata(string(), string(), binary(), options()) ->
|
-spec decode_calldata(string(), string(), binary(), options()) ->
|
||||||
{ok, [aeso_syntax:type()], [aeso_syntax:expr()]}
|
{ok, [so_syntax:type()], [so_syntax:expr()]}
|
||||||
| {error, [aeso_errors:error()]}.
|
| {error, [so_errors:error()]}.
|
||||||
decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
||||||
Options = [no_code | Options0],
|
Options = [no_code | Options0],
|
||||||
try
|
try
|
||||||
@ -373,26 +374,26 @@ decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
|||||||
ArgTypes = lists:map(GetType, Args),
|
ArgTypes = lists:map(GetType, Args),
|
||||||
Type0 = {tuple_t, [], ArgTypes},
|
Type0 = {tuple_t, [], ArgTypes},
|
||||||
%% user defined data types such as variants needed to match against
|
%% 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_record_types
|
||||||
, unfold_variant_types
|
, unfold_variant_types
|
||||||
, not_unfold_system_alias_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} ->
|
{ok, FateArgs} ->
|
||||||
try
|
try
|
||||||
{tuple_t, [], ArgTypes1} = Type,
|
{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)],
|
|| {ArgType, FateArg} <- lists:zip(ArgTypes1, FateArgs)],
|
||||||
{ok, ArgTypes, AstArgs}
|
{ok, ArgTypes, AstArgs}
|
||||||
catch throw:cannot_translate_to_sophia ->
|
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",
|
Msg = io_lib:format("Cannot translate FATE value ~p\n to Sophia type ~s",
|
||||||
[FateArgs, Type0Str]),
|
[FateArgs, Type0Str]),
|
||||||
{error, [aeso_errors:new(data_error, Msg)]}
|
{error, [so_errors:new(data_error, Msg)]}
|
||||||
end;
|
end;
|
||||||
{error, _} ->
|
{error, _} ->
|
||||||
Msg = io_lib:format("Failed to decode calldata binary", []),
|
Msg = io_lib:format("Failed to decode calldata binary", []),
|
||||||
{error, [aeso_errors:new(data_error, Msg)]}
|
{error, [so_errors:new(data_error, Msg)]}
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
throw:{error, Errors} -> {error, Errors}
|
throw:{error, Errors} -> {error, Errors}
|
||||||
@ -410,8 +411,8 @@ get_decode_type(FunName, [{Contract, Ann, _, _, Defs}]) when ?IS_CONTRACT_HEAD(C
|
|||||||
"init" -> {ok, [], {tuple_t, [], []}};
|
"init" -> {ok, [], {tuple_t, [], []}};
|
||||||
_ ->
|
_ ->
|
||||||
Msg = io_lib:format("Function '~s' is missing in contract", [FunName]),
|
Msg = io_lib:format("Function '~s' is missing in contract", [FunName]),
|
||||||
Pos = aeso_errors:pos(Ann),
|
Pos = so_errors:pos(Ann),
|
||||||
aeso_errors:throw(aeso_errors:new(data_error, Pos, Msg))
|
so_errors:throw(so_errors:new(data_error, Pos, Msg))
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
get_decode_type(FunName, [_ | Contracts]) ->
|
get_decode_type(FunName, [_ | Contracts]) ->
|
||||||
@ -419,12 +420,12 @@ get_decode_type(FunName, [_ | Contracts]) ->
|
|||||||
get_decode_type(FunName, Contracts).
|
get_decode_type(FunName, Contracts).
|
||||||
|
|
||||||
pp_sophia_code(C, Opts)-> pp(C, Opts, pp_sophia_code, fun(Code) ->
|
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).
|
end).
|
||||||
pp_ast(C, Opts) -> pp(C, Opts, pp_ast, fun aeso_ast:pp/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 aeso_ast:pp_typed/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) ->
|
pp(Code, Options, Option, PPFun) ->
|
||||||
case proplists:lookup(Option, Options) of
|
case proplists:lookup(Option, Options) of
|
||||||
@ -438,18 +439,18 @@ pp(Code, Options, Option, PPFun) ->
|
|||||||
|
|
||||||
-define(protect(Tag, Code), fun() -> try Code catch _:Err1 -> throw({Tag, Err1}) end end()).
|
-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) ->
|
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
|
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} =
|
{FCode2, SrcPayable} =
|
||||||
?protect(compile,
|
?protect(compile,
|
||||||
begin
|
begin
|
||||||
{ok, #{ byte_code := SrcByteCode, payable := SrcPayable }} =
|
{ok, #{ byte_code := SrcByteCode, payable := SrcPayable }} =
|
||||||
from_string1(Source, Options),
|
from_string1(Source, Options),
|
||||||
FCode = aeb_fate_code:deserialize(SrcByteCode),
|
FCode = gmb_fate_code:deserialize(SrcByteCode),
|
||||||
{aeb_fate_code:strip_init_function(FCode), SrcPayable}
|
{gmb_fate_code:strip_init_function(FCode), SrcPayable}
|
||||||
end),
|
end),
|
||||||
case compare_fate_code(FCode1, FCode2) of
|
case compare_fate_code(FCode1, FCode2) of
|
||||||
ok when SrcPayable /= Payable ->
|
ok when SrcPayable /= Payable ->
|
||||||
@ -465,10 +466,10 @@ validate_byte_code(#{ byte_code := ByteCode, payable := Payable }, Source, Optio
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
compare_fate_code(FCode1, FCode2) ->
|
compare_fate_code(FCode1, FCode2) ->
|
||||||
Funs1 = aeb_fate_code:functions(FCode1),
|
Funs1 = gmb_fate_code:functions(FCode1),
|
||||||
Funs2 = aeb_fate_code:functions(FCode2),
|
Funs2 = gmb_fate_code:functions(FCode2),
|
||||||
Syms1 = aeb_fate_code:symbols(FCode1),
|
Syms1 = gmb_fate_code:symbols(FCode1),
|
||||||
Syms2 = aeb_fate_code:symbols(FCode2),
|
Syms2 = gmb_fate_code:symbols(FCode2),
|
||||||
FunHashes1 = maps:keys(Funs1),
|
FunHashes1 = maps:keys(Funs1),
|
||||||
FunHashes2 = maps:keys(Funs2),
|
FunHashes2 = maps:keys(Funs2),
|
||||||
case FunHashes1 == FunHashes2 of
|
case FunHashes1 == FunHashes2 of
|
||||||
@ -513,13 +514,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, Options) ->
|
||||||
parse(Text, sets:new(), 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) ->
|
parse(Text, Included, Options) ->
|
||||||
aeso_parser:string(Text, Included, Options).
|
so_parser:string(Text, Included, Options).
|
||||||
|
|
||||||
read_contract(Name) ->
|
read_contract(Name) ->
|
||||||
file:read_file(Name).
|
file:read_file(Name).
|
@ -1,11 +1,13 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc ADT for structured error messages + formatting.
|
%%% @doc ADT for structured error messages + formatting.
|
||||||
%%%
|
%%%
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_errors).
|
-module(so_errors).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-type src_file() :: no_file | iolist().
|
-type src_file() :: no_file | iolist().
|
||||||
|
|
||||||
@ -55,9 +57,9 @@ new(Type, Pos, Msg, Ctxt) ->
|
|||||||
#err{ type = Type, pos = Pos, message = Msg, context = Ctxt }.
|
#err{ type = Type, pos = Pos, message = Msg, context = Ctxt }.
|
||||||
|
|
||||||
pos(Ann) ->
|
pos(Ann) ->
|
||||||
File = aeso_syntax:get_ann(file, Ann, no_file),
|
File = so_syntax:get_ann(file, Ann, no_file),
|
||||||
Line = aeso_syntax:get_ann(line, Ann, 0),
|
Line = so_syntax:get_ann(line, Ann, 0),
|
||||||
Col = aeso_syntax:get_ann(col, Ann, 0),
|
Col = so_syntax:get_ann(col, Ann, 0),
|
||||||
pos(File, Line, Col).
|
pos(File, Line, Col).
|
||||||
|
|
||||||
pos(Line, Col) ->
|
pos(Line, Col) ->
|
@ -1,13 +1,13 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
%%% @author Ulf Norell
|
%%% @author Ulf Norell
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Fate backend for Sophia compiler
|
%%% Fate backend for Sophia compiler
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 11 Jan 2019
|
|
||||||
%%%
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_fcode_to_fate).
|
-module(so_fcode_to_fate).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([compile/3, compile/4, term_to_fate/1, term_to_fate/2]).
|
-export([compile/3, compile/4, term_to_fate/1, term_to_fate/2]).
|
||||||
|
|
||||||
@ -23,7 +23,7 @@
|
|||||||
| loop
|
| loop
|
||||||
| tuple() | atom(). %% FATE instruction
|
| 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
|
%% Annotated scode
|
||||||
-type scode_a() :: [sinstr_a()].
|
-type scode_a() :: [sinstr_a()].
|
||||||
@ -72,9 +72,9 @@ debug(Tag, Options, Fun) ->
|
|||||||
|
|
||||||
-dialyzer({nowarn_function, [code_error/1]}).
|
-dialyzer({nowarn_function, [code_error/1]}).
|
||||||
code_error(Err) ->
|
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])),
|
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 -------------------------------------------------------------------
|
%% -- Main -------------------------------------------------------------------
|
||||||
|
|
||||||
@ -87,14 +87,14 @@ compile(ChildContracts, FCode, SavedFreshNames, Options) ->
|
|||||||
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options),
|
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options),
|
||||||
SFuns1 = optimize_scode(SFuns, Options),
|
SFuns1 = optimize_scode(SFuns, Options),
|
||||||
FateCode = to_basic_blocks(SFuns1),
|
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
|
case proplists:get_value(include_child_contract_symbols, Options, false) of
|
||||||
false -> FateCode;
|
false -> FateCode;
|
||||||
true -> add_child_symbols(ChildContracts, FateCode)
|
true -> add_child_symbols(ChildContracts, FateCode)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
make_function_id(X) ->
|
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(event) -> <<"Chain.event">>;
|
||||||
make_function_name({entrypoint, Name}) -> Name;
|
make_function_name({entrypoint, Name}) -> Name;
|
||||||
@ -103,7 +103,7 @@ make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs,
|
|||||||
add_child_symbols(ChildContracts, FateCode) ->
|
add_child_symbols(ChildContracts, FateCode) ->
|
||||||
Funs = lists:flatten([ maps:keys(ChildFuns) || {_, #{functions := ChildFuns}} <- maps:to_list(ChildContracts) ]),
|
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 ]),
|
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) ->
|
functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options) ->
|
||||||
FunNames = maps:keys(Functions),
|
FunNames = maps:keys(Functions),
|
||||||
@ -140,8 +140,6 @@ type_to_scode(string) -> string;
|
|||||||
type_to_scode(address) -> address;
|
type_to_scode(address) -> address;
|
||||||
type_to_scode({bytes, N}) -> {bytes, N};
|
type_to_scode({bytes, N}) -> {bytes, N};
|
||||||
type_to_scode(contract) -> contract;
|
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(name) -> name;
|
||||||
type_to_scode(channel) -> channel;
|
type_to_scode(channel) -> channel;
|
||||||
type_to_scode(bits) -> bits;
|
type_to_scode(bits) -> bits;
|
||||||
@ -212,17 +210,17 @@ serialize_contract_code(Env, C) ->
|
|||||||
SavedFreshNames = Env#env.saved_fresh_names,
|
SavedFreshNames = Env#env.saved_fresh_names,
|
||||||
FCode = maps:get(C, Env#env.child_contracts),
|
FCode = maps:get(C, Env#env.child_contracts),
|
||||||
FateCode = compile(Env#env.child_contracts, FCode, SavedFreshNames, Options),
|
FateCode = compile(Env#env.child_contracts, FCode, SavedFreshNames, Options),
|
||||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
ByteCode = gmb_fate_code:serialize(FateCode, []),
|
||||||
{ok, Version} = aeso_compiler:version(),
|
{ok, Version} = so_compiler:version(),
|
||||||
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
||||||
Code = #{byte_code => ByteCode,
|
Code = #{byte_code => ByteCode,
|
||||||
compiler_version => Version,
|
compiler_version => Version,
|
||||||
source_hash => crypto:hash(sha256, OriginalSourceCode ++ [0] ++ C),
|
source_hash => crypto:hash(sha256, OriginalSourceCode ++ [0] ++ C),
|
||||||
type_info => [],
|
type_info => [],
|
||||||
abi_version => aeb_fate_abi:abi_version(),
|
abi_version => gmb_fate_abi:abi_version(),
|
||||||
payable => maps:get(payable, FCode)
|
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)),
|
put(contract_code_cache, maps:put(C, Serialized, Cache)),
|
||||||
Serialized;
|
Serialized;
|
||||||
Serialized -> Serialized
|
Serialized -> Serialized
|
||||||
@ -230,17 +228,15 @@ serialize_contract_code(Env, C) ->
|
|||||||
|
|
||||||
lit_to_fate(Env, L) ->
|
lit_to_fate(Env, L) ->
|
||||||
case L of
|
case L of
|
||||||
{int, N} -> aeb_fate_data:make_integer(N);
|
{int, N} -> gmb_fate_data:make_integer(N);
|
||||||
{string, S} -> aeb_fate_data:make_string(S);
|
{string, S} -> gmb_fate_data:make_string(S);
|
||||||
{bytes, B} -> aeb_fate_data:make_bytes(B);
|
{bytes, B} -> gmb_fate_data:make_bytes(B);
|
||||||
{bool, B} -> aeb_fate_data:make_boolean(B);
|
{bool, B} -> gmb_fate_data:make_boolean(B);
|
||||||
{account_pubkey, K} -> aeb_fate_data:make_address(K);
|
{account_pubkey, K} -> gmb_fate_data:make_address(K);
|
||||||
{signature, S} -> aeb_fate_data:make_bytes(S);
|
{signature, S} -> gmb_fate_data:make_bytes(S);
|
||||||
{contract_pubkey, K} -> aeb_fate_data:make_contract(K);
|
{contract_pubkey, K} -> gmb_fate_data:make_contract(K);
|
||||||
{oracle_pubkey, K} -> aeb_fate_data:make_oracle(K);
|
{contract_code, C} -> gmb_fate_data:make_contract_bytearray(serialize_contract_code(Env, C));
|
||||||
{oracle_query_id, H} -> aeb_fate_data:make_oracle_query(H);
|
{typerep, T} -> gmb_fate_data:make_typerep(type_to_scode(T))
|
||||||
{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))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
term_to_fate(E) -> term_to_fate(#env{}, #{}, E).
|
term_to_fate(E) -> term_to_fate(#env{}, #{}, E).
|
||||||
@ -250,21 +246,21 @@ term_to_fate(GlobEnv, _Env, {lit, _, L}) ->
|
|||||||
lit_to_fate(GlobEnv, L);
|
lit_to_fate(GlobEnv, L);
|
||||||
%% negative literals are parsed as 0 - N
|
%% negative literals are parsed as 0 - N
|
||||||
term_to_fate(_GlobEnv, _Env, {op, _, '-', [{lit, _, {int, 0}}, {lit, _, {int, 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, _}) ->
|
term_to_fate(_GlobEnv, _Env, {nil, _}) ->
|
||||||
aeb_fate_data:make_list([]);
|
gmb_fate_data:make_list([]);
|
||||||
term_to_fate(GlobEnv, Env, {op, _, '::', [Hd, Tl]}) ->
|
term_to_fate(GlobEnv, Env, {op, _, '::', [Hd, Tl]}) ->
|
||||||
%% The Tl will translate into a list, because FATE lists are just lists
|
%% 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, Hd) | term_to_fate(GlobEnv, Env, Tl)];
|
||||||
term_to_fate(GlobEnv, Env, {tuple, _, As}) ->
|
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}) ->
|
term_to_fate(GlobEnv, Env, {con, _, Ar, I, As}) ->
|
||||||
FateAs = [ term_to_fate(GlobEnv, Env, A) || A <- 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, []}) ->
|
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, []}) ->
|
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]}) ->
|
term_to_fate(GlobEnv, _Env, {op, _, bits_set, [B, I]}) ->
|
||||||
{bits, N} = term_to_fate(GlobEnv, B),
|
{bits, N} = term_to_fate(GlobEnv, B),
|
||||||
J = term_to_fate(GlobEnv, I),
|
J = term_to_fate(GlobEnv, I),
|
||||||
@ -282,7 +278,7 @@ term_to_fate(_GlobEnv, Env, {var, _, X}) ->
|
|||||||
V -> V
|
V -> V
|
||||||
end;
|
end;
|
||||||
term_to_fate(_GlobEnv, _Env, {builtin, _, map_empty, []}) ->
|
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]}) ->
|
term_to_fate(GlobEnv, Env, {op, _, map_set, [M, K, V]}) ->
|
||||||
Map = term_to_fate(GlobEnv, Env, M),
|
Map = term_to_fate(GlobEnv, Env, M),
|
||||||
Map#{term_to_fate(GlobEnv, Env, K) => term_to_fate(GlobEnv, Env, V)};
|
Map#{term_to_fate(GlobEnv, Env, K) => term_to_fate(GlobEnv, Env, V)};
|
||||||
@ -304,7 +300,7 @@ to_scode1(Env, {lit, Ann, L}) ->
|
|||||||
[ dbg_loc(Env, Ann), push(?i(lit_to_fate(Env, L))) ];
|
[ dbg_loc(Env, Ann), push(?i(lit_to_fate(Env, L))) ];
|
||||||
|
|
||||||
to_scode1(Env, {nil, Ann}) ->
|
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}) ->
|
to_scode1(Env, {var, Ann, X}) ->
|
||||||
[ dbg_loc(Env, Ann), push(lookup_var(Env, X)) ];
|
[ dbg_loc(Env, Ann), push(lookup_var(Env, X)) ];
|
||||||
@ -313,7 +309,7 @@ to_scode1(Env, {con, Ann, Ar, I, As}) ->
|
|||||||
N = length(As),
|
N = length(As),
|
||||||
[ dbg_loc(Env, Ann),
|
[ dbg_loc(Env, Ann),
|
||||||
[to_scode(notail(Env), A) || A <- As],
|
[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}) ->
|
to_scode1(Env, {tuple, Ann, As}) ->
|
||||||
N = length(As),
|
N = length(As),
|
||||||
@ -324,13 +320,13 @@ to_scode1(Env, {tuple, Ann, As}) ->
|
|||||||
to_scode1(Env, {proj, Ann, E, I}) ->
|
to_scode1(Env, {proj, Ann, E, I}) ->
|
||||||
[ dbg_loc(Env, Ann),
|
[ dbg_loc(Env, Ann),
|
||||||
to_scode(notail(Env), E),
|
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}) ->
|
to_scode1(Env, {set_proj, Ann, R, I, E}) ->
|
||||||
[ dbg_loc(Env, Ann),
|
[ dbg_loc(Env, Ann),
|
||||||
to_scode(notail(Env), E),
|
to_scode(notail(Env), E),
|
||||||
to_scode(notail(Env), R),
|
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}) ->
|
to_scode1(Env, {op, Ann, Op, Args}) ->
|
||||||
[ dbg_loc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ];
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ];
|
||||||
@ -341,7 +337,7 @@ to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) ->
|
|||||||
to_scode1(Env, {'let', Ann, X, Expr, Body}) ->
|
to_scode1(Env, {'let', Ann, X, Expr, Body}) ->
|
||||||
{I, Env1} = bind_local(X, Env),
|
{I, Env1} = bind_local(X, Env),
|
||||||
SCode = [ to_scode(notail(Env), Expr),
|
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) ],
|
to_scode(Env1, Body) ],
|
||||||
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ];
|
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ];
|
||||||
|
|
||||||
@ -355,18 +351,18 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false
|
|||||||
{I, Env2} = bind_local("_", Env1),
|
{I, Env2} = bind_local("_", Env1),
|
||||||
ArgCode = to_scode(notail(Env2), Arg),
|
ArgCode = to_scode(notail(Env2), Arg),
|
||||||
Acc1 = [Acc, ArgCode,
|
Acc1 = [Acc, ArgCode,
|
||||||
aeb_fate_ops:store({var, I}, ?a)],
|
gmb_fate_ops:store({var, I}, ?a)],
|
||||||
{[I | Is], Acc1, Env2}
|
{[I | Is], Acc1, Env2}
|
||||||
end, {[], [], Env}, Args),
|
end, {[], [], Env}, Args),
|
||||||
[ dbg_loc(Env, Ann),
|
[ dbg_loc(Env, Ann),
|
||||||
Code,
|
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),
|
|| {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1),
|
||||||
lists:reverse(Vars)) ],
|
lists:reverse(Vars)) ],
|
||||||
loop ];
|
loop ];
|
||||||
to_scode1(Env, {def, Ann, Fun, Args}) ->
|
to_scode1(Env, {def, Ann, Fun, Args}) ->
|
||||||
FName = make_function_id(Fun),
|
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) ];
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ];
|
||||||
to_scode1(Env, {funcall, Ann, Fun, 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) ];
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ];
|
||||||
@ -377,23 +373,23 @@ to_scode1(Env, {builtin, Ann, B, Args}) ->
|
|||||||
to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) ->
|
to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) ->
|
||||||
Lbl = make_function_id(Fun),
|
Lbl = make_function_id(Fun),
|
||||||
{ArgTypes, RetType0} = typesig_to_scode([{"_", T} || T <- ArgsT], RetT),
|
{ArgTypes, RetType0} = typesig_to_scode([{"_", T} || T <- ArgsT], RetT),
|
||||||
ArgType = ?i(aeb_fate_data:make_typerep({tuple, ArgTypes})),
|
ArgType = ?i(gmb_fate_data:make_typerep({tuple, ArgTypes})),
|
||||||
RetType = ?i(aeb_fate_data:make_typerep(RetType0)),
|
RetType = ?i(gmb_fate_data:make_typerep(RetType0)),
|
||||||
SCode = case Protected of
|
SCode = case Protected of
|
||||||
{lit, _, {bool, false}} ->
|
{lit, _, {bool, false}} ->
|
||||||
case Gas of
|
case Gas of
|
||||||
{builtin, _, call_gas_left, _} ->
|
{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_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])
|
call_to_scode(Env, Call, [Ct, Value, Gas | Args])
|
||||||
end;
|
end;
|
||||||
{lit, _, {bool, true}} ->
|
{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_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])
|
call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args])
|
||||||
end,
|
end,
|
||||||
[ dbg_loc(Env, Ann) | SCode ];
|
[ dbg_loc(Env, Ann) | SCode ];
|
||||||
@ -409,8 +405,8 @@ to_scode1(Env, {closure, Ann, Fun, FVs}) ->
|
|||||||
to_scode1(Env, {switch, Ann, Case}) ->
|
to_scode1(Env, {switch, Ann, Case}) ->
|
||||||
[ dbg_loc(Env, Ann) | split_to_scode(Env, 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 = #env{debug_info = false}, Fun) when Env#env.tailpos -> gmb_fate_ops:call_t(Fun);
|
||||||
local_call(_Env, Fun) -> aeb_fate_ops:call(Fun).
|
local_call(_Env, Fun) -> gmb_fate_ops:call(Fun).
|
||||||
|
|
||||||
split_to_scode(Env, {nosplit, Renames, Expr}) ->
|
split_to_scode(Env, {nosplit, Renames, Expr}) ->
|
||||||
[switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))];
|
[switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))];
|
||||||
@ -448,13 +444,13 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
|||||||
[{'case', {'::', Y, Z}, S} | _] ->
|
[{'case', {'::', Y, Z}, S} | _] ->
|
||||||
{I, Env1} = bind_local(Y, Env),
|
{I, Env1} = bind_local(Y, Env),
|
||||||
{J, Env2} = bind_local(Z, Env1),
|
{J, Env2} = bind_local(Z, Env1),
|
||||||
[aeb_fate_ops:hd({var, I}, Arg),
|
[gmb_fate_ops:hd({var, I}, Arg),
|
||||||
aeb_fate_ops:tl({var, J}, Arg),
|
gmb_fate_ops:tl({var, J}, Arg),
|
||||||
split_to_scode(Env2, S)]
|
split_to_scode(Env2, S)]
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
SAlts = [GetAlt('::'), GetAlt(nil)],
|
SAlts = [GetAlt('::'), GetAlt(nil)],
|
||||||
[aeb_fate_ops:is_nil(?a, Arg),
|
[gmb_fate_ops:is_nil(?a, Arg),
|
||||||
{switch, ?a, boolean, SAlts, Def}];
|
{switch, ?a, boolean, SAlts, Def}];
|
||||||
split_to_scode(Env, {split, Type, X, Alts}) when Type == integer; Type == string ->
|
split_to_scode(Env, {split, Type, X, Alts}) when Type == integer; Type == string ->
|
||||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||||
@ -488,9 +484,9 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T
|
|||||||
end,
|
end,
|
||||||
SLit = case Lit of
|
SLit = case Lit of
|
||||||
{int, N} -> N;
|
{int, N} -> N;
|
||||||
{string, S} -> aeb_fate_data:make_string(S)
|
{string, S} -> gmb_fate_data:make_string(S)
|
||||||
end,
|
end,
|
||||||
[aeb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
[gmb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
||||||
{switch, ?a, boolean, [False, True], Def}].
|
{switch, ?a, boolean, [False, True], Def}].
|
||||||
|
|
||||||
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
||||||
@ -504,10 +500,10 @@ catchall_to_scode(_, _, [], Acc) -> {missing, lists:reverse(Acc)}.
|
|||||||
|
|
||||||
%% Tuple is in the accumulator. Arguments are the variable names.
|
%% Tuple is in the accumulator. Arguments are the variable names.
|
||||||
match_tuple(Env, Arg, Xs) ->
|
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) ->
|
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, 0, Elem, Arg, Xs).
|
||||||
|
|
||||||
match_tuple(Env, I, Elem, Arg, ["_" | Xs]) ->
|
match_tuple(Env, I, Elem, Arg, ["_" | Xs]) ->
|
||||||
@ -526,239 +522,215 @@ call_to_scode(Env, CallCode, Args) ->
|
|||||||
CallCode].
|
CallCode].
|
||||||
|
|
||||||
builtin_to_scode(Env, chain_event, Args) ->
|
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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(_Env, map_empty, []) ->
|
builtin_to_scode(_Env, map_empty, []) ->
|
||||||
[aeb_fate_ops:map_empty(?a)];
|
[gmb_fate_ops:map_empty(?a)];
|
||||||
builtin_to_scode(_Env, bits_none, []) ->
|
builtin_to_scode(_Env, bits_none, []) ->
|
||||||
[aeb_fate_ops:bits_none(?a)];
|
[gmb_fate_ops:bits_none(?a)];
|
||||||
builtin_to_scode(_Env, bits_all, []) ->
|
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) ->
|
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) ->
|
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) ->
|
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) ->
|
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) ->
|
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) ->
|
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]) ->
|
builtin_to_scode(Env, bytes_to_any_size, [A]) ->
|
||||||
[to_scode(Env, A)]; %% no_op!
|
[to_scode(Env, A)]; %% no_op!
|
||||||
builtin_to_scode(Env, bytes_size, [_] = Args) ->
|
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) ->
|
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) ->
|
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) ->
|
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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, chain_balance, [_] = 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) ->
|
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, []) ->
|
builtin_to_scode(_Env, chain_coinbase, []) ->
|
||||||
[aeb_fate_ops:beneficiary(?a)];
|
[gmb_fate_ops:beneficiary(?a)];
|
||||||
builtin_to_scode(_Env, chain_timestamp, []) ->
|
builtin_to_scode(_Env, chain_timestamp, []) ->
|
||||||
[aeb_fate_ops:timestamp(?a)];
|
[gmb_fate_ops:timestamp(?a)];
|
||||||
builtin_to_scode(_Env, chain_block_height, []) ->
|
builtin_to_scode(_Env, chain_block_height, []) ->
|
||||||
[aeb_fate_ops:generation(?a)];
|
[gmb_fate_ops:generation(?a)];
|
||||||
builtin_to_scode(_Env, chain_difficulty, []) ->
|
builtin_to_scode(_Env, chain_difficulty, []) ->
|
||||||
[aeb_fate_ops:difficulty(?a)];
|
[gmb_fate_ops:difficulty(?a)];
|
||||||
builtin_to_scode(_Env, chain_gas_limit, []) ->
|
builtin_to_scode(_Env, chain_gas_limit, []) ->
|
||||||
[aeb_fate_ops:gaslimit(?a)];
|
[gmb_fate_ops:gaslimit(?a)];
|
||||||
builtin_to_scode(_Env, chain_network_id, []) ->
|
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, []) ->
|
builtin_to_scode(_Env, contract_balance, []) ->
|
||||||
[aeb_fate_ops:balance(?a)];
|
[gmb_fate_ops:balance(?a)];
|
||||||
builtin_to_scode(_Env, contract_address, []) ->
|
builtin_to_scode(_Env, contract_address, []) ->
|
||||||
[aeb_fate_ops:address(?a)];
|
[gmb_fate_ops:address(?a)];
|
||||||
builtin_to_scode(_Env, contract_creator, []) ->
|
builtin_to_scode(_Env, contract_creator, []) ->
|
||||||
[aeb_fate_ops:contract_creator(?a)];
|
[gmb_fate_ops:contract_creator(?a)];
|
||||||
builtin_to_scode(_Env, call_origin, []) ->
|
builtin_to_scode(_Env, call_origin, []) ->
|
||||||
[aeb_fate_ops:origin(?a)];
|
[gmb_fate_ops:origin(?a)];
|
||||||
builtin_to_scode(_Env, call_caller, []) ->
|
builtin_to_scode(_Env, call_caller, []) ->
|
||||||
[aeb_fate_ops:caller(?a)];
|
[gmb_fate_ops:caller(?a)];
|
||||||
builtin_to_scode(_Env, call_value, []) ->
|
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, []) ->
|
builtin_to_scode(_Env, call_gas_price, []) ->
|
||||||
[aeb_fate_ops:gasprice(?a)];
|
[gmb_fate_ops:gasprice(?a)];
|
||||||
builtin_to_scode(_Env, call_fee, []) ->
|
builtin_to_scode(_Env, call_fee, []) ->
|
||||||
[aeb_fate_ops:fee(?a)];
|
[gmb_fate_ops:fee(?a)];
|
||||||
builtin_to_scode(_Env, call_gas_left, []) ->
|
builtin_to_scode(_Env, call_gas_left, []) ->
|
||||||
[aeb_fate_ops:gas(?a)];
|
[gmb_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);
|
|
||||||
builtin_to_scode(Env, address_is_contract, [_] = Args) ->
|
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) ->
|
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) ->
|
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) ->
|
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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt, _NameFee] = 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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = 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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_revoke, [_Sign, _Account, _Name] = 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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_update, [_Sign, _Account, _NameString, _TTL, _ClientTTL, _Pointers] = 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);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_lookup, [_Name] = 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, []) ->
|
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, []) ->
|
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) ->
|
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,
|
builtin_to_scode(Env, chain_clone,
|
||||||
[InitArgsT, GasCap, Value, Prot, Contract | InitArgs]) ->
|
[InitArgsT, GasCap, Value, Prot, Contract | InitArgs]) ->
|
||||||
case GasCap of
|
case GasCap of
|
||||||
{builtin, _, call_gas_left, _} ->
|
{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]
|
[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]
|
[Contract, InitArgsT, Value, GasCap, Prot | InitArgs]
|
||||||
)
|
)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
builtin_to_scode(Env, chain_create,
|
builtin_to_scode(Env, chain_create,
|
||||||
[ Code, InitArgsT, Value | InitArgs]) ->
|
[ 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]
|
[Code, InitArgsT, Value | InitArgs]
|
||||||
).
|
).
|
||||||
|
|
||||||
%% -- Operators --
|
%% -- Operators --
|
||||||
|
|
||||||
op_to_scode('+') -> aeb_fate_ops:add(?a, ?a, ?a);
|
op_to_scode('+') -> gmb_fate_ops:add(?a, ?a, ?a);
|
||||||
op_to_scode('-') -> aeb_fate_ops:sub(?a, ?a, ?a);
|
op_to_scode('-') -> gmb_fate_ops:sub(?a, ?a, ?a);
|
||||||
op_to_scode('*') -> aeb_fate_ops:mul(?a, ?a, ?a);
|
op_to_scode('*') -> gmb_fate_ops:mul(?a, ?a, ?a);
|
||||||
op_to_scode('/') -> aeb_fate_ops:divide(?a, ?a, ?a);
|
op_to_scode('/') -> gmb_fate_ops:divide(?a, ?a, ?a);
|
||||||
op_to_scode(mod) -> aeb_fate_ops:modulo(?a, ?a, ?a);
|
op_to_scode(mod) -> gmb_fate_ops:modulo(?a, ?a, ?a);
|
||||||
op_to_scode('^') -> aeb_fate_ops:pow(?a, ?a, ?a);
|
op_to_scode('^') -> gmb_fate_ops:pow(?a, ?a, ?a);
|
||||||
op_to_scode('++') -> aeb_fate_ops:append(?a, ?a, ?a);
|
op_to_scode('++') -> gmb_fate_ops:append(?a, ?a, ?a);
|
||||||
op_to_scode('::') -> aeb_fate_ops:cons(?a, ?a, ?a);
|
op_to_scode('::') -> gmb_fate_ops:cons(?a, ?a, ?a);
|
||||||
op_to_scode('<') -> aeb_fate_ops:lt(?a, ?a, ?a);
|
op_to_scode('<') -> gmb_fate_ops:lt(?a, ?a, ?a);
|
||||||
op_to_scode('>') -> aeb_fate_ops:gt(?a, ?a, ?a);
|
op_to_scode('>') -> gmb_fate_ops:gt(?a, ?a, ?a);
|
||||||
op_to_scode('=<') -> aeb_fate_ops:elt(?a, ?a, ?a);
|
op_to_scode('=<') -> gmb_fate_ops:elt(?a, ?a, ?a);
|
||||||
op_to_scode('>=') -> aeb_fate_ops:egt(?a, ?a, ?a);
|
op_to_scode('>=') -> gmb_fate_ops:egt(?a, ?a, ?a);
|
||||||
op_to_scode('==') -> aeb_fate_ops:eq(?a, ?a, ?a);
|
op_to_scode('==') -> gmb_fate_ops:eq(?a, ?a, ?a);
|
||||||
op_to_scode('!=') -> aeb_fate_ops:neq(?a, ?a, ?a);
|
op_to_scode('!=') -> gmb_fate_ops:neq(?a, ?a, ?a);
|
||||||
op_to_scode('!') -> aeb_fate_ops:not_op(?a, ?a);
|
op_to_scode('!') -> gmb_fate_ops:not_op(?a, ?a);
|
||||||
op_to_scode('bnot') -> aeb_fate_ops:bin_not(?a, ?a);
|
op_to_scode('bnot') -> gmb_fate_ops:bin_not(?a, ?a);
|
||||||
op_to_scode('band') -> aeb_fate_ops:bin_and(?a, ?a, ?a);
|
op_to_scode('band') -> gmb_fate_ops:bin_and(?a, ?a, ?a);
|
||||||
op_to_scode('bor') -> aeb_fate_ops:bin_or(?a, ?a, ?a);
|
op_to_scode('bor') -> gmb_fate_ops:bin_or(?a, ?a, ?a);
|
||||||
op_to_scode('bxor') -> aeb_fate_ops:bin_xor(?a, ?a, ?a);
|
op_to_scode('bxor') -> gmb_fate_ops:bin_xor(?a, ?a, ?a);
|
||||||
op_to_scode('<<') -> aeb_fate_ops:bin_sl(?a, ?a, ?a);
|
op_to_scode('<<') -> gmb_fate_ops:bin_sl(?a, ?a, ?a);
|
||||||
op_to_scode('>>') -> aeb_fate_ops:bin_sr(?a, ?a, ?a);
|
op_to_scode('>>') -> gmb_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) -> gmb_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_get_d) -> gmb_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_set) -> gmb_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_from_list) -> gmb_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_to_list) -> gmb_fate_ops:map_to_list(?a, ?a);
|
||||||
op_to_scode(map_delete) -> aeb_fate_ops:map_delete(?a, ?a, ?a);
|
op_to_scode(map_delete) -> gmb_fate_ops:map_delete(?a, ?a, ?a);
|
||||||
op_to_scode(map_member) -> aeb_fate_ops:map_member(?a, ?a, ?a);
|
op_to_scode(map_member) -> gmb_fate_ops:map_member(?a, ?a, ?a);
|
||||||
op_to_scode(map_size) -> aeb_fate_ops:map_size_(?a, ?a);
|
op_to_scode(map_size) -> gmb_fate_ops:map_size_(?a, ?a);
|
||||||
op_to_scode(stringinternal_length) -> aeb_fate_ops:str_length(?a, ?a);
|
op_to_scode(stringinternal_length) -> gmb_fate_ops:str_length(?a, ?a);
|
||||||
op_to_scode(stringinternal_concat) -> aeb_fate_ops:str_join(?a, ?a, ?a);
|
op_to_scode(stringinternal_concat) -> gmb_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_bytes) -> gmb_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_to_list) -> gmb_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_from_list) -> gmb_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_lower) -> gmb_fate_ops:str_to_lower(?a, ?a);
|
||||||
op_to_scode(stringinternal_to_upper) -> aeb_fate_ops:str_to_upper(?a, ?a);
|
op_to_scode(stringinternal_to_upper) -> gmb_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_to_int) -> gmb_fate_ops:char_to_int(?a, ?a);
|
||||||
op_to_scode(char_from_int) -> aeb_fate_ops:char_from_int(?a, ?a);
|
op_to_scode(char_from_int) -> gmb_fate_ops:char_from_int(?a, ?a);
|
||||||
op_to_scode(bits_set) -> aeb_fate_ops:bits_set(?a, ?a, ?a);
|
op_to_scode(bits_set) -> gmb_fate_ops:bits_set(?a, ?a, ?a);
|
||||||
op_to_scode(bits_clear) -> aeb_fate_ops:bits_clear(?a, ?a, ?a);
|
op_to_scode(bits_clear) -> gmb_fate_ops:bits_clear(?a, ?a, ?a);
|
||||||
op_to_scode(bits_test) -> aeb_fate_ops:bits_test(?a, ?a, ?a);
|
op_to_scode(bits_test) -> gmb_fate_ops:bits_test(?a, ?a, ?a);
|
||||||
op_to_scode(bits_sum) -> aeb_fate_ops:bits_sum(?a, ?a);
|
op_to_scode(bits_sum) -> gmb_fate_ops:bits_sum(?a, ?a);
|
||||||
op_to_scode(bits_intersection) -> aeb_fate_ops:bits_and(?a, ?a, ?a);
|
op_to_scode(bits_intersection) -> gmb_fate_ops:bits_and(?a, ?a, ?a);
|
||||||
op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a);
|
op_to_scode(bits_union) -> gmb_fate_ops:bits_or(?a, ?a, ?a);
|
||||||
op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a);
|
op_to_scode(bits_difference) -> gmb_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_str) -> gmb_fate_ops:addr_to_str(?a, ?a);
|
||||||
op_to_scode(address_to_bytes) -> aeb_fate_ops:addr_to_bytes(?a, ?a);
|
op_to_scode(address_to_bytes) -> gmb_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_str) -> gmb_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_to_bytes) -> gmb_fate_ops:int_to_bytes(?a, ?a, ?a);
|
||||||
op_to_scode(int_mulmod) -> aeb_fate_ops:mulmod(?a, ?a, ?a, ?a);
|
op_to_scode(int_mulmod) -> gmb_fate_ops:mulmod(?a, ?a, ?a, ?a);
|
||||||
op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a);
|
op_to_scode(contract_to_address) -> gmb_fate_ops:contract_to_address(?a, ?a);
|
||||||
op_to_scode(address_to_contract) -> aeb_fate_ops:address_to_contract(?a, ?a);
|
op_to_scode(address_to_contract) -> gmb_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) -> gmb_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_verify_sig_secp256k1) -> gmb_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_ecverify_secp256k1) -> gmb_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_ecrecover_secp256k1) -> gmb_fate_ops:ecrecover_secp256k1(?a, ?a, ?a);
|
||||||
op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a);
|
op_to_scode(crypto_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
||||||
op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a);
|
op_to_scode(crypto_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
||||||
op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
|
op_to_scode(crypto_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
||||||
op_to_scode(crypto_poseidon) -> aeb_fate_ops:poseidon(?a, ?a, ?a);
|
op_to_scode(crypto_poseidon) -> gmb_fate_ops:poseidon(?a, ?a, ?a);
|
||||||
op_to_scode(stringinternal_sha3) -> aeb_fate_ops:sha3(?a, ?a);
|
op_to_scode(stringinternal_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
||||||
op_to_scode(stringinternal_sha256) -> aeb_fate_ops:sha256(?a, ?a);
|
op_to_scode(stringinternal_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
||||||
op_to_scode(stringinternal_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
|
op_to_scode(stringinternal_blake2b) -> gmb_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_neg) -> gmb_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_norm) -> gmb_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_valid) -> gmb_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_is_zero) -> gmb_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_add) -> gmb_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_g1_mul) -> gmb_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_neg) -> gmb_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_norm) -> gmb_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_valid) -> gmb_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_is_zero) -> gmb_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_add) -> gmb_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_g2_mul) -> gmb_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_inv) -> gmb_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_add) -> gmb_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_mul) -> gmb_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_pow) -> gmb_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_gt_is_one) -> gmb_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_pairing) -> gmb_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_miller_loop) -> gmb_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_final_exp) -> gmb_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_fr) -> gmb_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_int_to_fp) -> gmb_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_fr_to_int) -> gmb_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(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
|
%% 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.
|
%% easier, and specialize to PUSH (which is cheaper) at the end.
|
||||||
push(A) -> {'STORE', ?a, A}.
|
push(A) -> {'STORE', ?a, A}.
|
||||||
|
|
||||||
tuple(0) -> push(?i({tuple, {}}));
|
tuple(0) -> push(?i({tuple, {}}));
|
||||||
tuple(N) -> aeb_fate_ops:tuple(?a, N).
|
tuple(N) -> gmb_fate_ops:tuple(?a, N).
|
||||||
|
|
||||||
%% -- Debug info functions --
|
%% -- Debug info functions --
|
||||||
|
|
||||||
@ -825,8 +797,8 @@ dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) ->
|
|||||||
true -> tuple_to_list(SCode);
|
true -> tuple_to_list(SCode);
|
||||||
false -> [SCode]
|
false -> [SCode]
|
||||||
end,
|
end,
|
||||||
Op = aeb_fate_opcodes:m_to_op(Mnemonic),
|
Op = gmb_fate_opcodes:m_to_op(Mnemonic),
|
||||||
case aeb_fate_opcodes:end_bb(Op) of
|
case gmb_fate_opcodes:end_bb(Op) of
|
||||||
true -> [Undef, SCode];
|
true -> [Undef, SCode];
|
||||||
false -> [SCode, Undef]
|
false -> [SCode, Undef]
|
||||||
end.
|
end.
|
||||||
@ -898,7 +870,7 @@ pp_ann(_, []) -> [].
|
|||||||
pp_op(switch_body) -> "SWITCH-BODY";
|
pp_op(switch_body) -> "SWITCH-BODY";
|
||||||
pp_op(loop) -> "LOOP";
|
pp_op(loop) -> "LOOP";
|
||||||
pp_op(I) ->
|
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(?i(I)) -> io_lib:format("~w", [I]);
|
||||||
pp_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
pp_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
||||||
@ -1668,14 +1640,14 @@ unannotate(Code) when is_list(Code) ->
|
|||||||
unannotate({i, _Ann, I}) -> [I].
|
unannotate({i, _Ann, I}) -> [I].
|
||||||
|
|
||||||
%% Desugar and specialize
|
%% Desugar and specialize
|
||||||
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_ops:inc()];
|
desugar({'ADD', ?a, ?i(1), ?a}) -> [gmb_fate_ops:inc()];
|
||||||
desugar({'ADD', A, ?i(1), A}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
desugar({'ADD', A, ?i(1), A}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
||||||
desugar({'ADD', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:inc()];
|
desugar({'ADD', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:inc()];
|
||||||
desugar({'ADD', A, A, ?i(1)}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
desugar({'ADD', A, A, ?i(1)}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
||||||
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:dec()];
|
desugar({'SUB', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:dec()];
|
||||||
desugar({'SUB', A, A, ?i(1)}) -> [aeb_fate_ops:dec(desugar_arg(A))];
|
desugar({'SUB', A, A, ?i(1)}) -> [gmb_fate_ops:dec(desugar_arg(A))];
|
||||||
desugar({'STORE', ?a, A}) -> [aeb_fate_ops:push(desugar_arg(A))];
|
desugar({'STORE', ?a, A}) -> [gmb_fate_ops:push(desugar_arg(A))];
|
||||||
desugar({'STORE', R, ?a}) -> [aeb_fate_ops:pop(desugar_arg(R))];
|
desugar({'STORE', R, ?a}) -> [gmb_fate_ops:pop(desugar_arg(R))];
|
||||||
desugar({switch, Arg, Type, Alts, Def}) ->
|
desugar({switch, Arg, Type, Alts, Def}) ->
|
||||||
[{switch, desugar_arg(Arg), Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
[{switch, desugar_arg(Arg), Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
||||||
desugar(missing) -> missing;
|
desugar(missing) -> missing;
|
||||||
@ -1695,11 +1667,11 @@ desugar_arg(A) -> A.
|
|||||||
%% Constructing basic blocks
|
%% Constructing basic blocks
|
||||||
|
|
||||||
to_basic_blocks(Funs) ->
|
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) ->
|
to_basic_blocks([{Name, {Attrs, Sig, Code}}|Left], Acc) ->
|
||||||
BB = bb(Name, Code ++ [aeb_fate_ops:return()]),
|
BB = bb(Name, Code ++ [gmb_fate_ops:return()]),
|
||||||
to_basic_blocks(Left, aeb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
to_basic_blocks(Left, gmb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
||||||
to_basic_blocks([], Acc) ->
|
to_basic_blocks([], Acc) ->
|
||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
@ -1770,7 +1742,7 @@ block(Blk = #blk{code = [{switch, Arg, Type, Alts, Default} | Code],
|
|||||||
{DefRef, DefBlk} =
|
{DefRef, DefBlk} =
|
||||||
case Default of
|
case Default of
|
||||||
missing when Catchall == none ->
|
missing when Catchall == none ->
|
||||||
FreshBlk([aeb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
FreshBlk([gmb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
||||||
missing -> {Catchall, []};
|
missing -> {Catchall, []};
|
||||||
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
||||||
%% ^ fall-through to the outer catchall
|
%% ^ fall-through to the outer catchall
|
||||||
@ -1945,14 +1917,14 @@ split_calls(Ref, [I | Code], Acc, Blocks) ->
|
|||||||
|
|
||||||
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
||||||
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
||||||
set_labels(_Labels, loop) -> aeb_fate_ops:jump(0);
|
set_labels(_Labels, loop) -> gmb_fate_ops:jump(0);
|
||||||
set_labels(Labels, {jump, Ref}) -> aeb_fate_ops:jump(maps:get(Ref, Labels));
|
set_labels(Labels, {jump, Ref}) -> gmb_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, {jumpif, Arg, Ref}) -> gmb_fate_ops:jumpif(Arg, maps:get(Ref, Labels));
|
||||||
set_labels(Labels, {switch, Arg, Refs}) ->
|
set_labels(Labels, {switch, Arg, Refs}) ->
|
||||||
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
||||||
[R1, R2] -> aeb_fate_ops:switch(Arg, R1, R2);
|
[R1, R2] -> gmb_fate_ops:switch(Arg, R1, R2);
|
||||||
[R1, R2, R3] -> aeb_fate_ops:switch(Arg, R1, R2, R3);
|
[R1, R2, R3] -> gmb_fate_ops:switch(Arg, R1, R2, R3);
|
||||||
Rs -> aeb_fate_ops:switch(Arg, Rs)
|
Rs -> gmb_fate_ops:switch(Arg, Rs)
|
||||||
end;
|
end;
|
||||||
set_labels(_, I) -> I.
|
set_labels(_, I) -> I.
|
||||||
|
|
@ -1,12 +1,14 @@
|
|||||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
%%% @doc Parser combinators for the Sophia parser. Based on
|
%%% @doc Parser combinators for the Sophia parser. Based on
|
||||||
%%% Koen Claessen. 2004. Parallel Parsing Processes. J. Functional
|
%%% Koen Claessen. 2004. Parallel Parsing Processes. J. Functional
|
||||||
%%% Programming 14, 6 (November 2004)
|
%%% Programming 14, 6 (November 2004)
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_parse_lib).
|
-module(so_parse_lib).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([parse/2,
|
-export([parse/2,
|
||||||
return/1, fail/0, fail/1, fail/2, map/2, bind/2,
|
return/1, fail/0, fail/1, fail/2, map/2, bind/2,
|
||||||
@ -27,16 +29,16 @@
|
|||||||
-type tokens() :: [token()].
|
-type tokens() :: [token()].
|
||||||
-type error() :: {pos(), string() | no_error}.
|
-type error() :: {pos(), string() | no_error}.
|
||||||
|
|
||||||
-define(lazy(F), {aeso_parse_lazy, F}).
|
-define(lazy(F), {so_parse_lazy, F}).
|
||||||
-define(fail(Err), {aeso_parse_fail, Err}).
|
-define(fail(Err), {so_parse_fail, Err}).
|
||||||
-define(choice(Ps), {aeso_parse_choice, Ps}).
|
-define(choice(Ps), {so_parse_choice, Ps}).
|
||||||
-define(bind(P, F), {aeso_parse_bind, P, F}).
|
-define(bind(P, F), {so_parse_bind, P, F}).
|
||||||
-define(right(P, Q), {aeso_parse_right, P, Q}).
|
-define(right(P, Q), {so_parse_right, P, Q}).
|
||||||
-define(left(P, Q), {aeso_parse_left, P, Q}).
|
-define(left(P, Q), {so_parse_left, P, Q}).
|
||||||
-define(map(F, P), {aeso_parse_map, F, P}).
|
-define(map(F, P), {so_parse_map, F, P}).
|
||||||
-define(layout, aeso_parse_layout).
|
-define(layout, so_parse_layout).
|
||||||
-define(tok(Atom), {aeso_parse_tok, Atom}).
|
-define(tok(Atom), {so_parse_tok, Atom}).
|
||||||
-define(return(X), {aeso_parse_return, X}).
|
-define(return(X), {so_parse_return, X}).
|
||||||
|
|
||||||
%% Type synonyms since you can't have function types as macro arguments for some reason.
|
%% Type synonyms since you can't have function types as macro arguments for some reason.
|
||||||
-type delayed(A) :: fun(() -> A).
|
-type delayed(A) :: fun(() -> A).
|
@ -1,8 +1,9 @@
|
|||||||
%%% File : aeso_parser.erl
|
%%% File : so_parser.erl
|
||||||
%%% Author : Ulf Norell
|
%%% Author : Ulf Norell
|
||||||
%%% Description :
|
%%% Description :
|
||||||
%%% Created : 1 Mar 2018 by Ulf Norell
|
%%% Created : 1 Mar 2018 by Ulf Norell
|
||||||
-module(aeso_parser).
|
-module(so_parser).
|
||||||
|
-vsn("9.0.0").
|
||||||
-compile({no_auto_import,[map_get/2]}).
|
-compile({no_auto_import,[map_get/2]}).
|
||||||
|
|
||||||
-export([string/1,
|
-export([string/1,
|
||||||
@ -17,12 +18,12 @@
|
|||||||
run_parser/2,
|
run_parser/2,
|
||||||
run_parser/3]).
|
run_parser/3]).
|
||||||
|
|
||||||
-include("aeso_parse_lib.hrl").
|
-include("so_parse_lib.hrl").
|
||||||
-import(aeso_parse_lib, [current_file/0, set_current_file/1,
|
-import(so_parse_lib, [current_file/0, set_current_file/1,
|
||||||
current_dir/0, set_current_dir/1,
|
current_dir/0, set_current_dir/1,
|
||||||
current_include_type/0, set_current_include_type/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()}.
|
-type include_hash() :: {string(), binary()}.
|
||||||
|
|
||||||
@ -36,14 +37,14 @@ escape_errors({error, Err}) ->
|
|||||||
string(String) ->
|
string(String) ->
|
||||||
string(String, sets:new(), []).
|
string(String, sets:new(), []).
|
||||||
|
|
||||||
-spec string(string(), aeso_compiler:options()) -> parse_result().
|
-spec string(string(), so_compiler:options()) -> parse_result().
|
||||||
string(String, Opts) ->
|
string(String, Opts) ->
|
||||||
case lists:keyfind(src_file, 1, Opts) of
|
case lists:keyfind(src_file, 1, Opts) of
|
||||||
{src_file, File} -> string(String, sets:add_element(File, sets:new()), Opts);
|
{src_file, File} -> string(String, sets:add_element(File, sets:new()), Opts);
|
||||||
false -> string(String, sets:new(), Opts)
|
false -> string(String, sets:new(), Opts)
|
||||||
end.
|
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) ->
|
string(String, Included, Opts) ->
|
||||||
AST = run_parser(file(), String, Opts),
|
AST = run_parser(file(), String, Opts),
|
||||||
case expand_includes(AST, Included, Opts) of
|
case expand_includes(AST, Included, Opts) of
|
||||||
@ -61,18 +62,18 @@ parse_and_scan(P, S, Opts) ->
|
|||||||
set_current_file(proplists:get_value(src_file, Opts, no_file)),
|
set_current_file(proplists:get_value(src_file, Opts, no_file)),
|
||||||
set_current_dir(proplists:get_value(src_dir, 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)),
|
set_current_include_type(proplists:get_value(include_type, Opts, none)),
|
||||||
case aeso_scan:scan(S) of
|
case so_scan:scan(S) of
|
||||||
{ok, Tokens} -> aeso_parse_lib:parse(P, Tokens);
|
{ok, Tokens} -> so_parse_lib:parse(P, Tokens);
|
||||||
{error, {{Input, Pos}, _}} ->
|
{error, {{Input, Pos}, _}} ->
|
||||||
{error, {Pos, scan_error, Input}}
|
{error, {Pos, scan_error, Input}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-dialyzer({nowarn_function, parse_error/1}).
|
-dialyzer({nowarn_function, parse_error/1}).
|
||||||
parse_error(Err) ->
|
parse_error(Err) ->
|
||||||
aeso_errors:throw(mk_error(Err)).
|
so_errors:throw(mk_error(Err)).
|
||||||
|
|
||||||
mk_p_err(Pos, Msg) ->
|
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_error({Pos, scan_error, Input}) ->
|
||||||
mk_p_err(Pos, io_lib:format("Lexical error on input: ~s\n", [Input]));
|
mk_p_err(Pos, io_lib:format("Lexical error on input: ~s\n", [Input]));
|
||||||
@ -86,8 +87,8 @@ mk_error({Pos, include_error, File}) ->
|
|||||||
Msg = io_lib:format("Couldn't find include file '~s'\n", [File]),
|
Msg = io_lib:format("Couldn't find include file '~s'\n", [File]),
|
||||||
mk_p_err(Pos, Msg).
|
mk_p_err(Pos, Msg).
|
||||||
|
|
||||||
mk_pos({Line, Col}) -> aeso_errors:pos(Line, Col);
|
mk_pos({Line, Col}) -> so_errors:pos(Line, Col);
|
||||||
mk_pos({File, Line, Col}) -> aeso_errors:pos(File, Line, Col).
|
mk_pos({File, Line, Col}) -> so_errors:pos(File, Line, Col).
|
||||||
|
|
||||||
%% -- Parsing rules ----------------------------------------------------------
|
%% -- Parsing rules ----------------------------------------------------------
|
||||||
|
|
||||||
@ -411,7 +412,7 @@ map_key(Key, {ok, {_, Val}}) -> {map_key, Key, Val}.
|
|||||||
|
|
||||||
elim(E, []) -> E;
|
elim(E, []) -> E;
|
||||||
elim(E, [{proj, Ann, P} | Es]) -> elim({proj, Ann, E, P}, Es);
|
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, [{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} | Es]) -> elim({map_get, Ann, E, Key}, Es);
|
||||||
elim(E, [{map_get, Ann, Key, Val} | Es]) -> elim({map_get, Ann, E, Key, Val}, Es).
|
elim(E, [{map_get, Ann, Key, Val} | Es]) -> elim({map_get, Ann, E, Key, Val}, Es).
|
||||||
@ -528,7 +529,7 @@ parse_addr_literal(Id = {id, Ann, Name}) ->
|
|||||||
case lists:member(lists:sublist(Name, 3), ["ak_", "ok_", "oq_", "ct_", "sg_"]) of
|
case lists:member(lists:sublist(Name, 3), ["ak_", "ok_", "oq_", "ct_", "sg_"]) of
|
||||||
false -> Id;
|
false -> Id;
|
||||||
true ->
|
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}
|
{Type, Bin} -> {Type, Ann, Bin}
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
Id
|
Id
|
||||||
@ -557,9 +558,9 @@ bracket_list(P) -> brackets(comma_sep(P)).
|
|||||||
|
|
||||||
%% -- Annotations ------------------------------------------------------------
|
%% -- Annotations ------------------------------------------------------------
|
||||||
|
|
||||||
-type ann() :: aeso_syntax:ann().
|
-type ann() :: so_syntax:ann().
|
||||||
-type ann_line() :: aeso_syntax:ann_line().
|
-type ann_line() :: so_syntax:ann_line().
|
||||||
-type ann_col() :: aeso_syntax:ann_col().
|
-type ann_col() :: so_syntax:ann_col().
|
||||||
|
|
||||||
-spec pos_ann(ann_line(), ann_col()) -> ann().
|
-spec pos_ann(ann_line(), ann_col()) -> ann().
|
||||||
pos_ann(Line, Col) ->
|
pos_ann(Line, Col) ->
|
||||||
@ -647,7 +648,7 @@ tuple_e(Ann, Exprs) -> {tuple, Ann, Exprs}.
|
|||||||
|
|
||||||
list_comp_e(Ann, Expr, Binds) -> {list_comp, Ann, Expr, Binds}.
|
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}) ->
|
parse_pattern({letpat, Ann, Id, Pat}) ->
|
||||||
{letpat, Ann, Id, parse_pattern(Pat)};
|
{letpat, Ann, Id, parse_pattern(Pat)};
|
||||||
parse_pattern({app, Ann, Con = {'::', _}, Es}) ->
|
parse_pattern({app, Ann, Con = {'::', _}, Es}) ->
|
||||||
@ -674,19 +675,19 @@ parse_pattern(E = {string, _, _}) -> E;
|
|||||||
parse_pattern(E = {char, _, _}) -> E;
|
parse_pattern(E = {char, _, _}) -> E;
|
||||||
parse_pattern(E) -> bad_expr_err("Not a valid pattern", 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}) ->
|
parse_field_pattern({field, Ann, F, E}) ->
|
||||||
{field, Ann, F, parse_pattern(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) ->
|
ret_doc_err(Ann, Doc) ->
|
||||||
fail(ann_pos(Ann), prettypr:format(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) ->
|
bad_expr_err(Reason, E) ->
|
||||||
ret_doc_err(get_ann(E),
|
ret_doc_err(get_ann(E),
|
||||||
prettypr:sep([prettypr:text(Reason ++ ":"),
|
prettypr:sep([prettypr:text(Reason ++ ":"),
|
||||||
prettypr:nest(2, aeso_pretty:expr(E))])).
|
prettypr:nest(2, so_pretty:expr(E))])).
|
||||||
|
|
||||||
%% -- Helper functions -------------------------------------------------------
|
%% -- Helper functions -------------------------------------------------------
|
||||||
|
|
||||||
@ -748,7 +749,7 @@ read_file(File, Opts) ->
|
|||||||
Escript = escript:script_name(),
|
Escript = escript:script_name(),
|
||||||
{ok, Sections} = escript:extract(Escript, []),
|
{ok, Sections} = escript:extract(Escript, []),
|
||||||
Archive = proplists:get_value(archive, Sections),
|
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
|
case zip:extract(Archive, [{file_list, [FileName]}, memory]) of
|
||||||
{ok, [{_, Src}]} -> {ok, escript, Src};
|
{ok, [{_, Src}]} -> {ok, escript, Src};
|
||||||
_ -> {error, not_found}
|
_ -> {error, not_found}
|
||||||
@ -761,12 +762,12 @@ read_file(File, Opts) ->
|
|||||||
read_file_(Path, File) ->
|
read_file_(Path, File) ->
|
||||||
AbsFile = filename:join(Path, File),
|
AbsFile = filename:join(Path, File),
|
||||||
case file:read_file(AbsFile) of
|
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
|
Err -> Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
stdlib_options() ->
|
stdlib_options() ->
|
||||||
StdLibDir = aeso_stdlib:stdlib_include_path(),
|
StdLibDir = so_stdlib:stdlib_include_path(),
|
||||||
case filelib:is_dir(StdLibDir) of
|
case filelib:is_dir(StdLibDir) of
|
||||||
true -> [{include, {file_system, [StdLibDir]}}];
|
true -> [{include, {file_system, [StdLibDir]}}];
|
||||||
false -> [{include, escript}]
|
false -> [{include, escript}]
|
@ -1,11 +1,13 @@
|
|||||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc Pretty printer for Sophia.
|
%%% @doc Pretty printer for Sophia.
|
||||||
%%%
|
%%%
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_pretty).
|
-module(so_pretty).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-import(prettypr, [text/1, sep/1, above/2, beside/2, nest/2, empty/0]).
|
-import(prettypr, [text/1, sep/1, above/2, beside/2, nest/2, empty/0]).
|
||||||
|
|
||||||
@ -13,7 +15,7 @@
|
|||||||
|
|
||||||
-export_type([options/0]).
|
-export_type([options/0]).
|
||||||
|
|
||||||
-include("aeso_utils.hrl").
|
-include("so_utils.hrl").
|
||||||
|
|
||||||
-type doc() :: prettypr:document().
|
-type doc() :: prettypr:document().
|
||||||
-type options() :: [{indent, non_neg_integer()} | show_generated].
|
-type options() :: [{indent, non_neg_integer()} | show_generated].
|
||||||
@ -24,11 +26,11 @@
|
|||||||
|
|
||||||
%% -- Options ----------------------------------------------------------------
|
%% -- Options ----------------------------------------------------------------
|
||||||
|
|
||||||
-define(aeso_pretty_opts, aeso_pretty_opts).
|
-define(so_pretty_opts, so_pretty_opts).
|
||||||
|
|
||||||
-spec options() -> options().
|
-spec options() -> options().
|
||||||
options() ->
|
options() ->
|
||||||
case get(?aeso_pretty_opts) of
|
case get(?so_pretty_opts) of
|
||||||
undefined -> [];
|
undefined -> [];
|
||||||
Opts -> Opts
|
Opts -> Opts
|
||||||
end.
|
end.
|
||||||
@ -45,9 +47,9 @@ indent() -> option(indent, 2).
|
|||||||
|
|
||||||
-spec with_options(options(), fun(() -> A)) -> A.
|
-spec with_options(options(), fun(() -> A)) -> A.
|
||||||
with_options(Options, Fun) ->
|
with_options(Options, Fun) ->
|
||||||
put(?aeso_pretty_opts, Options),
|
put(?so_pretty_opts, Options),
|
||||||
Res = Fun(),
|
Res = Fun(),
|
||||||
erase(?aeso_pretty_opts),
|
erase(?so_pretty_opts),
|
||||||
Res.
|
Res.
|
||||||
|
|
||||||
%% -- Pretty printing helpers ------------------------------------------------
|
%% -- Pretty printing helpers ------------------------------------------------
|
||||||
@ -125,9 +127,9 @@ record(Ds) ->
|
|||||||
equals(A, B) -> follow(hsep(A, text("=")), B).
|
equals(A, B) -> follow(hsep(A, text("=")), B).
|
||||||
|
|
||||||
%% typed(A, B) -> A : B.
|
%% typed(A, B) -> A : B.
|
||||||
-spec typed(doc(), aeso_syntax:type()) -> doc().
|
-spec typed(doc(), so_syntax:type()) -> doc().
|
||||||
typed(A, Type) ->
|
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
|
not show_generated() of
|
||||||
true -> A;
|
true -> A;
|
||||||
false -> follow(hsep(A, text(":")), type(Type))
|
false -> follow(hsep(A, text(":")), type(Type))
|
||||||
@ -139,18 +141,18 @@ contract_head(contract_interface) -> text("contract interface").
|
|||||||
|
|
||||||
%% -- Exports ----------------------------------------------------------------
|
%% -- Exports ----------------------------------------------------------------
|
||||||
|
|
||||||
-spec decls([aeso_syntax:decl()], options()) -> doc().
|
-spec decls([so_syntax:decl()], options()) -> doc().
|
||||||
decls(Ds, Options) ->
|
decls(Ds, Options) ->
|
||||||
with_options(Options, fun() -> decls(Ds) end).
|
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 ]).
|
decls(Ds) -> above([ decl(D) || D <- Ds ]).
|
||||||
|
|
||||||
-spec decl(aeso_syntax:decl(), options()) -> doc().
|
-spec decl(so_syntax:decl(), options()) -> doc().
|
||||||
decl(D, Options) ->
|
decl(D, Options) ->
|
||||||
with_options(Options, fun() -> decl(D) end).
|
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) ->
|
decl({Con, Attrs, C, Is, Ds}) when ?IS_CONTRACT_HEAD(Con) ->
|
||||||
Mod = fun({Mod, true}) when Mod == payable ->
|
Mod = fun({Mod, true}) when Mod == payable ->
|
||||||
text(atom_to_list(Mod));
|
text(atom_to_list(Mod));
|
||||||
@ -172,7 +174,7 @@ decl({fun_decl, Ann, F, T}) ->
|
|||||||
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
||||||
text(atom_to_list(Mod));
|
text(atom_to_list(Mod));
|
||||||
(_) -> empty() end,
|
(_) -> 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");
|
true -> text("entrypoint");
|
||||||
false -> text("function")
|
false -> text("function")
|
||||||
end,
|
end,
|
||||||
@ -181,7 +183,7 @@ decl(D = {letfun, Attrs, _, _, _, _}) ->
|
|||||||
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
|
||||||
text(atom_to_list(Mod));
|
text(atom_to_list(Mod));
|
||||||
(_) -> empty() end,
|
(_) -> empty() end,
|
||||||
Fun = case aeso_syntax:get_ann(entrypoint, Attrs, false) of
|
Fun = case so_syntax:get_ann(entrypoint, Attrs, false) of
|
||||||
true -> "entrypoint";
|
true -> "entrypoint";
|
||||||
false -> "function"
|
false -> "function"
|
||||||
end,
|
end,
|
||||||
@ -192,20 +194,20 @@ decl(D = {letval, _, _, _}) -> letdecl("let", D);
|
|||||||
decl({block, _, Ds}) ->
|
decl({block, _, Ds}) ->
|
||||||
above([ decl(D) || D <- Ds ]).
|
above([ decl(D) || D <- Ds ]).
|
||||||
|
|
||||||
-spec pragma(aeso_syntax:pragma()) -> doc().
|
-spec pragma(so_syntax:pragma()) -> doc().
|
||||||
pragma({compiler, Op, Ver}) ->
|
pragma({compiler, Op, Ver}) ->
|
||||||
text("@compiler " ++ atom_to_list(Op) ++ " " ++ string:join([integer_to_list(N) || N <- 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) ->
|
expr(E, Options) ->
|
||||||
with_options(Options, fun() -> expr(E) end).
|
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).
|
expr(E) -> expr_p(0, E).
|
||||||
|
|
||||||
%% -- Not exported -----------------------------------------------------------
|
%% -- 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({id, _, Name}) -> text(Name);
|
||||||
name({con, _, Name}) -> text(Name);
|
name({con, _, Name}) -> text(Name);
|
||||||
name({qid, _, Names}) -> text(string:join(Names, "."));
|
name({qid, _, Names}) -> text(string:join(Names, "."));
|
||||||
@ -213,7 +215,7 @@ name({qcon, _, Names}) -> text(string:join(Names, "."));
|
|||||||
name({tvar, _, Name}) -> text(Name);
|
name({tvar, _, Name}) -> text(Name);
|
||||||
name({typed, _, Name, _}) -> name(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}) ->
|
letdecl(Let, {letval, _, P, E}) ->
|
||||||
block_expr(0, hsep([text(Let), expr(P), text("=")]), E);
|
block_expr(0, hsep([text(Let), expr(P), text("=")]), E);
|
||||||
letdecl(Let, {letfun, _, F, Args, T, [GuardedBody]}) ->
|
letdecl(Let, {letfun, _, F, Args, T, [GuardedBody]}) ->
|
||||||
@ -221,14 +223,14 @@ letdecl(Let, {letfun, _, F, Args, T, [GuardedBody]}) ->
|
|||||||
letdecl(Let, {letfun, _, F, Args, T, GuardedBodies}) ->
|
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))).
|
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) ->
|
args(Args) ->
|
||||||
tuple(lists:map(fun arg/1, 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).
|
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) ->
|
typedecl(Kind, T, Vars) ->
|
||||||
KW = case Kind of
|
KW = case Kind of
|
||||||
alias_t -> text("type");
|
alias_t -> text("type");
|
||||||
@ -241,26 +243,26 @@ typedecl(Kind, T, Vars) ->
|
|||||||
tuple(lists:map(fun name/1, Vars)))
|
tuple(lists:map(fun name/1, Vars)))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec typedef(aeso_syntax:typedef()) -> doc().
|
-spec typedef(so_syntax:typedef()) -> doc().
|
||||||
typedef({alias_t, Type}) -> type(Type);
|
typedef({alias_t, Type}) -> type(Type);
|
||||||
typedef({record_t, Fields}) ->
|
typedef({record_t, Fields}) ->
|
||||||
record(lists:map(fun field_t/1, Fields));
|
record(lists:map(fun field_t/1, Fields));
|
||||||
typedef({variant_t, Constructors}) ->
|
typedef({variant_t, Constructors}) ->
|
||||||
par(punctuate(text(" |"), lists:map(fun constructor_t/1, 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, []}) -> name(C);
|
||||||
constructor_t({constr_t, _, C, Args}) -> beside(name(C), args_type(Args)).
|
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}) ->
|
field_t({field_t, _, Name, Type}) ->
|
||||||
typed(name(Name), Type).
|
typed(name(Name), Type).
|
||||||
|
|
||||||
-spec type(aeso_syntax:type(), options()) -> doc().
|
-spec type(so_syntax:type(), options()) -> doc().
|
||||||
type(Type, Options) ->
|
type(Type, Options) ->
|
||||||
with_options(Options, fun() -> type(Type) end).
|
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(F = {fun_t, _, _, var_args, _}) ->
|
||||||
type(setelement(4, F, [var_args]));
|
type(setelement(4, F, [var_args]));
|
||||||
type({fun_t, _, Named, Args, Ret}) ->
|
type({fun_t, _, Named, Args, Ret}) ->
|
||||||
@ -296,11 +298,11 @@ type(T = {tvar, _, _}) -> name(T);
|
|||||||
|
|
||||||
type(var_args) -> text("var_args").
|
type(var_args) -> text("var_args").
|
||||||
|
|
||||||
-spec args_type([aeso_syntax:type()]) -> doc().
|
-spec args_type([so_syntax:type()]) -> doc().
|
||||||
args_type(Args) ->
|
args_type(Args) ->
|
||||||
tuple(lists:map(fun type/1, Args)).
|
tuple(lists:map(fun type/1, Args)).
|
||||||
|
|
||||||
-spec tuple_type([aeso_syntax:type()]) -> doc().
|
-spec tuple_type([so_syntax:type()]) -> doc().
|
||||||
tuple_type([]) ->
|
tuple_type([]) ->
|
||||||
text("unit");
|
text("unit");
|
||||||
tuple_type(Factors) ->
|
tuple_type(Factors) ->
|
||||||
@ -310,7 +312,7 @@ tuple_type(Factors) ->
|
|||||||
, text(")")
|
, 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}) ->
|
expr_p(P, {letpat, _, Id, Pat}) ->
|
||||||
paren(P > 100, follow(hsep(expr(Id), text("=")), expr(Pat)));
|
paren(P > 100, follow(hsep(expr(Id), text("=")), expr(Pat)));
|
||||||
expr_p(P, {named_arg, _, Name, E}) ->
|
expr_p(P, {named_arg, _, Name, E}) ->
|
||||||
@ -318,7 +320,7 @@ expr_p(P, {named_arg, _, Name, E}) ->
|
|||||||
expr_p(P, {lam, _, Args, E}) ->
|
expr_p(P, {lam, _, Args, E}) ->
|
||||||
paren(P > 100, follow(hsep(args(Args), text("=>")), expr_p(100, E)));
|
paren(P > 100, follow(hsep(args(Args), text("=>")), expr_p(100, E)));
|
||||||
expr_p(P, If = {'if', Ann, Cond, Then, Else}) ->
|
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 == '?:' ->
|
if Format == '?:' ->
|
||||||
paren(P > 100,
|
paren(P > 100,
|
||||||
follow(expr_p(200, Cond),
|
follow(expr_p(200, Cond),
|
||||||
@ -361,7 +363,7 @@ expr_p(P, {assign, _, LV, E}) ->
|
|||||||
expr_p(_, {app, _, {'..', _}, [A, B]}) ->
|
expr_p(_, {app, _, {'..', _}, [A, B]}) ->
|
||||||
list([infix(0, '..', A, B)]);
|
list([infix(0, '..', A, B)]);
|
||||||
expr_p(P, E = {app, _, F = {Op, _}, Args}) when is_atom(Op) ->
|
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);
|
{infix, [A, B]} -> infix(P, Op, A, B);
|
||||||
{prefix, [A]} -> prefix(P, Op, A);
|
{prefix, [A]} -> prefix(P, Op, A);
|
||||||
_ -> app(P, F, Args)
|
_ -> app(P, F, Args)
|
||||||
@ -372,7 +374,7 @@ expr_p(P, {app, _, F, Args}) ->
|
|||||||
app(P, F, Args);
|
app(P, F, Args);
|
||||||
%% -- Constants
|
%% -- Constants
|
||||||
expr_p(_, E = {int, _, N}) ->
|
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);
|
hex -> "0x" ++ integer_to_list(N, 16);
|
||||||
_ -> integer_to_list(N)
|
_ -> integer_to_list(N)
|
||||||
end,
|
end,
|
||||||
@ -389,7 +391,7 @@ expr_p(_, {Type, _, Bin})
|
|||||||
Type == oracle_pubkey;
|
Type == oracle_pubkey;
|
||||||
Type == oracle_query_id;
|
Type == oracle_query_id;
|
||||||
Type == signature ->
|
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, _, <<>>}) -> text("\"\"");
|
||||||
expr_p(_, {string, _, S}) ->
|
expr_p(_, {string, _, S}) ->
|
||||||
text(io_lib:format("\"~s\"", [binary_to_list(S)]));
|
text(io_lib:format("\"~s\"", [binary_to_list(S)]));
|
||||||
@ -402,7 +404,7 @@ expr_p(_, {char, _, C}) ->
|
|||||||
text("'" ++ tl(lists:droplast(S)) ++ "'");
|
text("'" ++ tl(lists:droplast(S)) ++ "'");
|
||||||
_ ->
|
_ ->
|
||||||
S = lists:flatten(
|
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)
|
text(S)
|
||||||
end;
|
end;
|
||||||
%% -- Names
|
%% -- Names
|
||||||
@ -421,7 +423,7 @@ stmt_p({elif, _, Cond, Then}) ->
|
|||||||
block_expr(200, beside(text("elif"), paren(expr(Cond))), Then);
|
block_expr(200, beside(text("elif"), paren(expr(Cond))), Then);
|
||||||
stmt_p({'else', Else}) ->
|
stmt_p({'else', Else}) ->
|
||||||
HideGenerated = not show_generated(),
|
HideGenerated = not show_generated(),
|
||||||
case aeso_syntax:get_ann(origin, Else) of
|
case so_syntax:get_ann(origin, Else) of
|
||||||
system when HideGenerated -> empty();
|
system when HideGenerated -> empty();
|
||||||
_ -> block_expr(200, text("else"), Else)
|
_ -> block_expr(200, text("else"), Else)
|
||||||
end.
|
end.
|
||||||
@ -433,7 +435,7 @@ lc_bind({comprehension_if, _, E}) ->
|
|||||||
lc_bind(Let) ->
|
lc_bind(Let) ->
|
||||||
letdecl("let", 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}; %% Always printed inside '[ ]'
|
bin_prec('=') -> { 0, 0, 0}; %% Always printed inside '[ ]'
|
||||||
bin_prec('@') -> { 0, 0, 0}; %% Only in error messages
|
bin_prec('@') -> { 0, 0, 0}; %% Only in error messages
|
||||||
@ -460,7 +462,7 @@ bin_prec('/') -> {700, 700, 750};
|
|||||||
bin_prec(mod) -> {700, 700, 750};
|
bin_prec(mod) -> {700, 700, 750};
|
||||||
bin_prec('^') -> {750, 750, 800}.
|
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('-') -> {650, 650};
|
||||||
un_prec('!') -> {800, 800};
|
un_prec('!') -> {800, 800};
|
||||||
un_prec('bnot') -> {850, 850}.
|
un_prec('bnot') -> {850, 850}.
|
||||||
@ -468,7 +470,7 @@ un_prec('bnot') -> {850, 850}.
|
|||||||
equals(Ann, A, B) ->
|
equals(Ann, A, B) ->
|
||||||
{app, [{format, infix} | Ann], {'=', 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) ->
|
infix(P, Op, A, B) ->
|
||||||
{Top, L, R} = bin_prec(Op),
|
{Top, L, R} = bin_prec(Op),
|
||||||
paren(P > Top,
|
paren(P > Top,
|
||||||
@ -530,7 +532,7 @@ statement(E) -> expr(E).
|
|||||||
get_elifs(Expr) -> get_elifs(Expr, []).
|
get_elifs(Expr) -> get_elifs(Expr, []).
|
||||||
|
|
||||||
get_elifs(If = {'if', Ann, Cond, Then, Else}, Elifs) ->
|
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]);
|
elif -> get_elifs(Else, [{elif, Ann, Cond, Then} | Elifs]);
|
||||||
_ -> {lists:reverse(Elifs), If}
|
_ -> {lists:reverse(Elifs), If}
|
||||||
end;
|
end;
|
@ -1,15 +1,17 @@
|
|||||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc The Sophia lexer.
|
%%% @doc The Sophia lexer.
|
||||||
%%%
|
%%%
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_scan).
|
-module(so_scan).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([scan/1, utf8_encode/1]).
|
-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]).
|
override/2, push/2, pop/1]).
|
||||||
|
|
||||||
lexer() ->
|
lexer() ->
|
||||||
@ -79,8 +81,8 @@ lexer() ->
|
|||||||
[{code, Rules}, {comment, CommentRules}].
|
[{code, Rules}, {comment, CommentRules}].
|
||||||
|
|
||||||
scan(String) ->
|
scan(String) ->
|
||||||
Lexer = aeso_scan_lib:compile(lexer()),
|
Lexer = so_scan_lib:compile(lexer()),
|
||||||
aeso_scan_lib:string(Lexer, code, String).
|
so_scan_lib:string(Lexer, code, String).
|
||||||
|
|
||||||
%% -- Helpers ----------------------------------------------------------------
|
%% -- Helpers ----------------------------------------------------------------
|
||||||
|
|
@ -1,10 +1,12 @@
|
|||||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc A customisable lexer.
|
%%% @doc A customisable lexer.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_scan_lib).
|
-module(so_scan_lib).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([compile/1, string/3,
|
-export([compile/1, string/3,
|
||||||
token/1, token/2, symbol/0, skip/0,
|
token/1, token/2, symbol/0, skip/0,
|
@ -1,17 +1,18 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
%%% @author Radosław Rowicki
|
%%% @author Radosław Rowicki
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Standard library for Sophia
|
%%% Standard library for Sophia
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 6 July 2019
|
|
||||||
%%%
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_stdlib).
|
-module(so_stdlib).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([stdlib_include_path/0]).
|
-export([stdlib_include_path/0]).
|
||||||
|
|
||||||
stdlib_include_path() ->
|
stdlib_include_path() ->
|
||||||
filename:join([code:priv_dir(aesophia), "stdlib"]).
|
{file, BEAM} = code:is_loaded(?MODULE),
|
||||||
|
filename:join(filename:dirname(filename:dirname(BEAM)), "priv/stdlib").
|
||||||
|
|
@ -1,12 +1,14 @@
|
|||||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc Sophia abstract syntax types.
|
%%% @doc Sophia abstract syntax types.
|
||||||
%%%
|
%%%
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_syntax).
|
-module(so_syntax).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([get_ann/1, get_ann/2, get_ann/3, set_ann/2, qualify/2]).
|
-export([get_ann/1, get_ann/2, get_ann/3, set_ann/2, qualify/2]).
|
||||||
|
|
@ -1,10 +1,12 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Sophia syntax utilities.
|
%%% Sophia syntax utilities.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_syntax_utils).
|
-module(so_syntax_utils).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([used_ids/1, used_ids/2, used_types/2, used/1]).
|
-export([used_ids/1, used_ids/2, used_types/2, used/1]).
|
||||||
|
|
||||||
@ -17,19 +19,19 @@
|
|||||||
-type kind() :: decl | type | bind_type | expr | bind_expr.
|
-type kind() :: decl | type | bind_type | expr | bind_expr.
|
||||||
|
|
||||||
-spec fold(alg(A), fun((kind(), _) -> A), kind(), E | [E]) -> A
|
-spec fold(alg(A), fun((kind(), _) -> A), kind(), E | [E]) -> A
|
||||||
when E :: aeso_syntax:decl()
|
when E :: so_syntax:decl()
|
||||||
| aeso_syntax:typedef()
|
| so_syntax:typedef()
|
||||||
| aeso_syntax:field_t()
|
| so_syntax:field_t()
|
||||||
| aeso_syntax:constructor_t()
|
| so_syntax:constructor_t()
|
||||||
| aeso_syntax:type()
|
| so_syntax:type()
|
||||||
| aeso_syntax:expr()
|
| so_syntax:expr()
|
||||||
| aeso_syntax:pat()
|
| so_syntax:pat()
|
||||||
| aeso_syntax:arg()
|
| so_syntax:arg()
|
||||||
| aeso_syntax:alt()
|
| so_syntax:alt()
|
||||||
| aeso_syntax:elim()
|
| so_syntax:elim()
|
||||||
| aeso_syntax:arg_expr()
|
| so_syntax:arg_expr()
|
||||||
| aeso_syntax:field(aeso_syntax:expr())
|
| so_syntax:field(so_syntax:expr())
|
||||||
| aeso_syntax:stmt().
|
| so_syntax:stmt().
|
||||||
fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) ->
|
fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) ->
|
||||||
ExprKind = if K == bind_expr -> bind_expr; true -> expr end,
|
ExprKind = if K == bind_expr -> bind_expr; true -> expr end,
|
||||||
TypeKind = if K == bind_type -> bind_type; true -> type end,
|
TypeKind = if K == bind_type -> bind_type; true -> type end,
|
||||||
@ -132,7 +134,7 @@ used_types([Top] = _CurrentNS, T) ->
|
|||||||
| {type, [string()]}
|
| {type, [string()]}
|
||||||
| {namespace, [string()]}.
|
| {namespace, [string()]}.
|
||||||
|
|
||||||
-spec entity_alg() -> alg(#{entity() => aeso_syntax:ann()}).
|
-spec entity_alg() -> alg(#{entity() => so_syntax:ann()}).
|
||||||
entity_alg() ->
|
entity_alg() ->
|
||||||
IsBound = fun({K, _}) -> lists:member(K, [bound_term, bound_type]) end,
|
IsBound = fun({K, _}) -> lists:member(K, [bound_term, bound_type]) end,
|
||||||
Unbind = fun(bound_term) -> term; (bound_type) -> type end,
|
Unbind = fun(bound_term) -> term; (bound_type) -> type end,
|
||||||
@ -147,7 +149,7 @@ entity_alg() ->
|
|||||||
, plus = fun maps:merge/2
|
, plus = fun maps:merge/2
|
||||||
, scoped = Scoped }.
|
, scoped = Scoped }.
|
||||||
|
|
||||||
-spec used(_) -> [{entity(), aeso_syntax:ann()}].
|
-spec used(_) -> [{entity(), so_syntax:ann()}].
|
||||||
used(D) ->
|
used(D) ->
|
||||||
Kind = fun(expr) -> term;
|
Kind = fun(expr) -> term;
|
||||||
(bind_expr) -> bound_term;
|
(bind_expr) -> bound_term;
|
@ -1,10 +1,12 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2018, Aeternity Anstalt
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Sophia utility functions.
|
%%% Sophia utility functions.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_utils).
|
-module(so_utils).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([scc/1, canonical_dir/1]).
|
-export([scc/1, canonical_dir/1]).
|
||||||
|
|
@ -1,22 +1,22 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2025, QPQ AG
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc Decoding fate data to AST
|
%%% @doc Decoding fate data to AST
|
||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_vm_decode).
|
-module(so_vm_decode).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-export([ from_fate/2 ]).
|
-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, _, "address"}, ?FATE_ADDRESS(Bin)) -> {account_pubkey, [], Bin};
|
||||||
from_fate({id, _, "signature"}, ?FATE_BYTES(Bin)) -> {signature, [], Bin};
|
from_fate({id, _, "signature"}, ?FATE_BYTES(Bin)) -> {signature, [], Bin};
|
||||||
from_fate({id, _, "hash"}, ?FATE_BYTES(Bin)) -> {bytes, [], Bin};
|
from_fate({id, _, "hash"}, ?FATE_BYTES(Bin)) -> {bytes, [], Bin};
|
||||||
from_fate({id, _, "unit"}, ?FATE_UNIT) -> {tuple, [], []};
|
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({con, _, _Name}, ?FATE_CONTRACT(Bin)) -> {contract_pubkey, [], Bin};
|
||||||
from_fate({bytes_t, _, any}, ?FATE_BYTES(Bin)) -> make_any_bytes(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};
|
from_fate({bytes_t, _, N}, ?FATE_BYTES(Bin)) when byte_size(Bin) == N -> {bytes, [], Bin};
|
@ -1,6 +1,7 @@
|
|||||||
-module(aeso_warnings).
|
-module(so_warnings).
|
||||||
|
-vsn("9.0.0").
|
||||||
|
|
||||||
-record(warn, { pos :: aeso_errors:pos()
|
-record(warn, { pos :: so_errors:pos()
|
||||||
, message :: iolist()
|
, message :: iolist()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
@ -16,16 +17,16 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
new(Msg) ->
|
new(Msg) ->
|
||||||
new(aeso_errors:pos(0, 0), Msg).
|
new(so_errors:pos(0, 0), Msg).
|
||||||
|
|
||||||
new(Pos, Msg) ->
|
new(Pos, Msg) ->
|
||||||
#warn{ pos = Pos, message = Msg }.
|
#warn{ pos = Pos, message = Msg }.
|
||||||
|
|
||||||
warn_to_err(Kind, #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) ->
|
sort_warnings(Warnings) ->
|
||||||
lists:sort(fun(W1, W2) -> W1#warn.pos =< W2#warn.pos end, Warnings).
|
lists:sort(fun(W1, W2) -> W1#warn.pos =< W2#warn.pos end, Warnings).
|
||||||
|
|
||||||
pp(#warn{ pos = Pos, message = Msg }) ->
|
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,13 +1,13 @@
|
|||||||
{application, aesophia,
|
{application, sophia,
|
||||||
[{description, "Compiler for Aeternity Sophia language"},
|
[{description, "Compiler for Sophia language"},
|
||||||
{vsn, "8.0.1"},
|
{vsn, "9.0.0"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications,
|
{applications,
|
||||||
[kernel,
|
[kernel,
|
||||||
stdlib,
|
stdlib,
|
||||||
jsx,
|
jsx,
|
||||||
syntax_tools,
|
syntax_tools,
|
||||||
aebytecode,
|
gmbytecode,
|
||||||
eblake2
|
eblake2
|
||||||
]},
|
]},
|
||||||
{env,[]},
|
{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
|
entrypoint main_fun : (int) => unit
|
||||||
|
|
||||||
contract AddrChain =
|
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) =
|
entrypoint is_c(a : address) =
|
||||||
Address.is_contract(a)
|
Address.is_contract(a)
|
||||||
|
|
||||||
// entrypoint get_o(a : address) : option(o_type) =
|
|
||||||
// Address.get_oracle(a)
|
|
||||||
|
|
||||||
// entrypoint get_c(a : address) : option(Remote) =
|
// entrypoint get_c(a : address) : option(Remote) =
|
||||||
// Address.get_contract(a)
|
// 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 =
|
// entrypoint h_to_i(h : hash) : int =
|
||||||
// Hash.to_int(h)
|
// Hash.to_int(h)
|
||||||
|
|
||||||
|
@ -5,10 +5,6 @@ contract interface Remote =
|
|||||||
contract AddressLiterals =
|
contract AddressLiterals =
|
||||||
entrypoint addr() : address =
|
entrypoint addr() : address =
|
||||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||||
entrypoint oracle() : oracle(int, bool) =
|
|
||||||
ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
|
||||||
entrypoint query() : oracle_query(int, bool) =
|
|
||||||
oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
|
||||||
entrypoint contr() : Remote =
|
entrypoint contr() : Remote =
|
||||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||||
entrypoint contr_addr() : Remote =
|
entrypoint contr_addr() : Remote =
|
||||||
|
@ -14,12 +14,6 @@ main contract AENSTest =
|
|||||||
stateful entrypoint resolve_contract(name : string, key : string) : option(C) =
|
stateful entrypoint resolve_contract(name : string, key : string) : option(C) =
|
||||||
AENSv2.resolve(name, key)
|
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
|
// Transactions
|
||||||
|
|
||||||
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
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 p5 : AENSv2.pointee = AENSv2.DataPt(String.to_bytes("any something will do"))
|
||||||
let p6 : AENSv2.pointee = AENSv2.DataPt(Int.to_bytes(1345, 4))
|
let p6 : AENSv2.pointee = AENSv2.DataPt(Int.to_bytes(1345, 4))
|
||||||
AENSv2.update(owner, name, None, None,
|
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 }))
|
["contract_pubkey"] = p3, ["misc"] = p4, ["data"] = p5, ["data2"] = p6 }))
|
||||||
|
|
||||||
stateful entrypoint old_interaction(c : OldAENSContract, owner : address, name : string) =
|
stateful entrypoint old_interaction(c : OldAENSContract, owner : address, name : string) =
|
||||||
@ -27,6 +27,3 @@ main contract AENSUpdate =
|
|||||||
entrypoint get_ttl(name : string) =
|
entrypoint get_ttl(name : string) =
|
||||||
switch(AENSv2.lookup(name))
|
switch(AENSv2.lookup(name))
|
||||||
Some(AENSv2.Name(_, FixedTTL(ttl), _)) => ttl
|
Some(AENSv2.Name(_, FixedTTL(ttl), _)) => ttl
|
||||||
|
|
||||||
entrypoint expiry(o : oracle(int, int)) : int =
|
|
||||||
Oracle.expiry(o)
|
|
||||||
|
@ -7,27 +7,9 @@ contract AddressLiterals =
|
|||||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
||||||
entrypoint addr2() : Remote =
|
entrypoint addr2() : Remote =
|
||||||
ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
|
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 =
|
entrypoint contr1() : address =
|
||||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||||
entrypoint contr2() : oracle(int, bool) =
|
|
||||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
|
||||||
entrypoint contr3() : bytes(32) =
|
entrypoint contr3() : bytes(32) =
|
||||||
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ
|
||||||
entrypoint contr4() : address =
|
entrypoint contr4() : address =
|
||||||
|
@ -11,8 +11,6 @@ contract Events =
|
|||||||
type ix5 = hash // bytes(32)
|
type ix5 = hash // bytes(32)
|
||||||
type ix6 = address
|
type ix6 = address
|
||||||
type ix7 = Remote
|
type ix7 = Remote
|
||||||
type ix8 = oracle(int, int)
|
|
||||||
type ix9 = oracle_query(int, int)
|
|
||||||
|
|
||||||
// Valid payload types
|
// Valid payload types
|
||||||
type data1 = string
|
type data1 = string
|
||||||
@ -26,7 +24,6 @@ contract Events =
|
|||||||
| Nodata3(ix4, ix5, ix6)
|
| Nodata3(ix4, ix5, ix6)
|
||||||
| Data0(data1)
|
| Data0(data1)
|
||||||
| Data1(data2, ix7)
|
| Data1(data2, ix7)
|
||||||
| Data2(ix8, data3, ix9)
|
|
||||||
| Data3(ix1, ix2, ix5, data1)
|
| Data3(ix1, ix2, ix5, data1)
|
||||||
|
|
||||||
entrypoint nodata0() = Chain.event(Nodata0)
|
entrypoint nodata0() = Chain.event(Nodata0)
|
||||||
@ -35,6 +32,5 @@ contract Events =
|
|||||||
entrypoint nodata3(ix4, ix5, ix6) = Chain.event(Nodata3(ix4, ix5, ix6))
|
entrypoint nodata3(ix4, ix5, ix6) = Chain.event(Nodata3(ix4, ix5, ix6))
|
||||||
entrypoint data0(data1) = Chain.event(Data0(data1))
|
entrypoint data0(data1) = Chain.event(Data0(data1))
|
||||||
entrypoint data1(data2, ix7) = Chain.event(Data1(data2, ix7))
|
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))
|
entrypoint data3(ix1, ix2, ix5, data1) = Chain.event(Data3(ix1, ix2, ix5, data1))
|
||||||
|
|
||||||
|
@ -31,12 +31,6 @@ contract FunctionArguments =
|
|||||||
entrypoint trettiotva(b : bytes(32)) =
|
entrypoint trettiotva(b : bytes(32)) =
|
||||||
b
|
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)
|
datatype colour() = Green | Yellow | Red | Pantone(int)
|
||||||
|
|
||||||
entrypoint traffic_light(c : colour) =
|
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
|
// 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"
|
include "List.aes"
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@ contract C =
|
|||||||
let c16 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
let c16 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
||||||
let c17 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
let c17 = #000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
||||||
let c18 = RelativeTTL(50)
|
let c18 = RelativeTTL(50)
|
||||||
let c19 = ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5
|
|
||||||
let c20 = oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY
|
|
||||||
let c21 = ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ : C
|
let c21 = ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ : C
|
||||||
let c22 = N.nsconst
|
let c22 = N.nsconst
|
||||||
let c23 = c01
|
let c23 = c01
|
||||||
@ -54,8 +52,6 @@ contract C =
|
|||||||
entrypoint f16() = c16
|
entrypoint f16() = c16
|
||||||
entrypoint f17() = c17
|
entrypoint f17() = c17
|
||||||
entrypoint f18() = c18
|
entrypoint f18() = c18
|
||||||
entrypoint f19() = c19
|
|
||||||
entrypoint f20() = c20
|
|
||||||
entrypoint f21() = c21
|
entrypoint f21() = c21
|
||||||
entrypoint f22() = c22
|
entrypoint f22() = c22
|
||||||
entrypoint f23() = c23
|
entrypoint f23() = c23
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
// Builtins without named arguments can appear unapplied.
|
// Builtins without named arguments can appear unapplied.
|
||||||
// Named argument builtins are:
|
// Named argument builtins are:
|
||||||
// Oracle.register
|
|
||||||
// Oracle.respond
|
|
||||||
// AENSv2.preclaim
|
// AENSv2.preclaim
|
||||||
// AENSv2.claim
|
// AENSv2.claim
|
||||||
// AENSv2.transfer
|
// AENSv2.transfer
|
||||||
// AENSv2.revoke
|
// AENSv2.revoke
|
||||||
// Oracle.extend
|
|
||||||
include "String.aes"
|
include "String.aes"
|
||||||
contract UnappliedBuiltins =
|
contract UnappliedBuiltins =
|
||||||
entrypoint main_fun() = ()
|
entrypoint main_fun() = ()
|
||||||
type o = oracle(int, int)
|
|
||||||
type t = list(int * string)
|
type t = list(int * string)
|
||||||
type m = map(int, int)
|
type m = map(int, int)
|
||||||
datatype event = Event(int)
|
datatype event = Event(int)
|
||||||
@ -21,13 +17,6 @@ contract UnappliedBuiltins =
|
|||||||
function call_gas_left() = Call.gas_left
|
function call_gas_left() = Call.gas_left
|
||||||
function b_abort() = abort
|
function b_abort() = abort
|
||||||
function b_require() = require
|
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 aens_resolve() = AENSv2.resolve : (_, _) => option(string)
|
||||||
function map_lookup() = Map.lookup : (_, m) => _
|
function map_lookup() = Map.lookup : (_, m) => _
|
||||||
function map_lookup_default() = Map.lookup_default : (_, m, _) => _
|
function map_lookup_default() = Map.lookup_default : (_, m, _) => _
|
||||||
@ -57,7 +46,6 @@ contract UnappliedBuiltins =
|
|||||||
function bits_sum() = Bits.sum
|
function bits_sum() = Bits.sum
|
||||||
function int_to_str() = Int.to_str
|
function int_to_str() = Int.to_str
|
||||||
function address_to_str() = Address.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_contract() = Address.is_contract
|
||||||
function address_is_payable() = Address.is_payable
|
function address_is_payable() = Address.is_payable
|
||||||
function bytes_to_int() = Bytes.to_int : bytes(10) => int
|
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").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
@ -65,15 +65,15 @@ to_sophia_value_mcl_bls12_381_test() ->
|
|||||||
|
|
||||||
Opts = [{backend, fate}],
|
Opts = [{backend, fate}],
|
||||||
|
|
||||||
CallValue32 = aeb_fate_encoding:serialize({bytes, <<20:256>>}),
|
CallValue32 = gmb_fate_encoding:serialize({bytes, <<20:256>>}),
|
||||||
CallValue48 = aeb_fate_encoding:serialize({bytes, <<55:384>>}),
|
CallValue48 = gmb_fate_encoding:serialize({bytes, <<55:384>>}),
|
||||||
CallValueTp = aeb_fate_encoding:serialize({tuple, {{bytes, <<15:256>>}, {bytes, <<160:256>>}, {bytes, <<1234:256>>}}}),
|
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),
|
{ok, _} = so_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),
|
{error, _} = so_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),
|
{ok, _} = so_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),
|
{error, _} = so_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_g1", ok, CallValueTp, Opts),
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -81,11 +81,11 @@ to_sophia_value_neg_test() ->
|
|||||||
Code = [ "contract Foo =\n"
|
Code = [ "contract Foo =\n"
|
||||||
" entrypoint f(x : int) : string = \"hello\"\n" ],
|
" entrypoint f(x : int) : string = \"hello\"\n" ],
|
||||||
|
|
||||||
{error, [Err1]} = aeso_compiler:to_sophia_value(Code, "f", ok, encode(12)),
|
{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", aeso_errors:pp(Err1)),
|
?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)),
|
{error, [Err2]} = so_compiler:to_sophia_value(Code, "f", revert, encode(12)),
|
||||||
?assertEqual("Data error:\nCould not deserialize the revert message\n", aeso_errors:pp(Err2)),
|
?assertEqual("Data error:\nCould not deserialize the revert message\n", so_errors:pp(Err2)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
encode_calldata_neg_test() ->
|
encode_calldata_neg_test() ->
|
||||||
@ -97,8 +97,8 @@ encode_calldata_neg_test() ->
|
|||||||
" `f : (int) => string`\n"
|
" `f : (int) => string`\n"
|
||||||
"to arguments\n"
|
"to arguments\n"
|
||||||
" `true : bool`\n",
|
" `true : bool`\n",
|
||||||
{error, [Err1]} = aeso_compiler:create_calldata(Code, "f", ["true"]),
|
{error, [Err1]} = so_compiler:create_calldata(Code, "f", ["true"]),
|
||||||
?assertEqual(ExpErr1, aeso_errors:pp(Err1)),
|
?assertEqual(ExpErr1, so_errors:pp(Err1)),
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -108,15 +108,15 @@ decode_calldata_neg_test() ->
|
|||||||
Code2 = [ "contract Foo =\n"
|
Code2 = [ "contract Foo =\n"
|
||||||
" entrypoint f(x : string) : int = 42\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>>),
|
{error, [Err1]} = so_compiler:decode_calldata(Code2, "f", <<1,2,3>>),
|
||||||
?assertEqual("Data error:\nFailed to decode calldata binary\n", aeso_errors:pp(Err1)),
|
?assertEqual("Data error:\nFailed to decode calldata binary\n", so_errors:pp(Err1)),
|
||||||
{error, [Err2]} = aeso_compiler:decode_calldata(Code2, "f", CallDataFATE),
|
{error, [Err2]} = so_compiler:decode_calldata(Code2, "f", CallDataFATE),
|
||||||
?assertEqual("Data error:\nCannot translate FATE value \"*\"\n to Sophia type (string)\n", aeso_errors:pp(Err2)),
|
?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),
|
{error, [Err3]} = so_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)),
|
?assertEqual("Data error at line 1, col 1:\nFunction 'x' is missing in contract\n", so_errors:pp(Err3)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
||||||
@ -128,12 +128,12 @@ encode_decode_sophia_string(SophiaType, String) ->
|
|||||||
, " record r = {x : an_alias(int), y : variant}\n"
|
, " record r = {x : an_alias(int), y : variant}\n"
|
||||||
, " datatype variant = Red | Blue(map(string, int))\n"
|
, " datatype variant = Red | Blue(map(string, int))\n"
|
||||||
, " entrypoint foo : arg_type => arg_type\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]} ->
|
{ok, _, [Arg]} ->
|
||||||
Data = encode(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} ->
|
{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} ->
|
{error, Err} ->
|
||||||
io:format("~s\n", [Err]),
|
io:format("~s\n", [Err]),
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -194,40 +194,18 @@ parameterized_contract(ExtraCode, FunName, Types) ->
|
|||||||
" datatype variant = Red | Blue(map(string, int))\n"
|
" datatype variant = Red | Blue(map(string, int))\n"
|
||||||
" entrypoint ", FunName, " : (", string:join(Types, ", "), ") => 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) ->
|
encode_decode_calldata(FunName, Types, Args) ->
|
||||||
Code = parameterized_contract(FunName, Types),
|
Code = parameterized_contract(FunName, Types),
|
||||||
encode_decode_calldata_(Code, FunName, Args).
|
encode_decode_calldata_(Code, FunName, Args).
|
||||||
|
|
||||||
encode_decode_calldata_(Code, FunName, Args) ->
|
encode_decode_calldata_(Code, FunName, Args) ->
|
||||||
{ok, Calldata} = aeso_compiler:create_calldata(Code, FunName, Args, []),
|
{ok, Calldata} = so_compiler:create_calldata(Code, FunName, Args, []),
|
||||||
{ok, _, _} = aeso_compiler:check_call(Code, FunName, Args, [no_code]),
|
{ok, _, _} = so_compiler:check_call(Code, FunName, Args, [no_code]),
|
||||||
case FunName of
|
case FunName of
|
||||||
"init" ->
|
"init" ->
|
||||||
[];
|
[];
|
||||||
_ ->
|
_ ->
|
||||||
{ok, FateArgs} = aeb_fate_abi:decode_calldata(FunName, Calldata),
|
{ok, FateArgs} = gmb_fate_abi:decode_calldata(FunName, Calldata),
|
||||||
FateArgs
|
FateArgs
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -236,7 +214,7 @@ encode_decode(D) ->
|
|||||||
D.
|
D.
|
||||||
|
|
||||||
encode(D) ->
|
encode(D) ->
|
||||||
aeb_fate_encoding:serialize(D).
|
gmb_fate_encoding:serialize(D).
|
||||||
|
|
||||||
decode(B) ->
|
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").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
@ -9,11 +9,11 @@ simple_aci_test_() ->
|
|||||||
|
|
||||||
test_contract(N) ->
|
test_contract(N) ->
|
||||||
{Contract,MapACI,DecACI} = test_cases(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([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
|
%% 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).
|
?assertEqual(JSON, JSON2).
|
||||||
|
|
||||||
test_cases(1) ->
|
test_cases(1) ->
|
||||||
@ -95,39 +95,39 @@ aci_test_() ->
|
|||||||
fun() -> aci_test_contract(ContractName) end}
|
fun() -> aci_test_contract(ContractName) end}
|
||||||
|| ContractName <- all_contracts()].
|
|| ContractName <- all_contracts()].
|
||||||
|
|
||||||
all_contracts() -> aeso_compiler_tests:compilable_contracts().
|
all_contracts() -> so_compiler_tests:compilable_contracts().
|
||||||
|
|
||||||
aci_test_contract(Name) ->
|
aci_test_contract(Name) ->
|
||||||
String = aeso_test_utils:read_contract(Name),
|
String = so_test_utils:read_contract(Name),
|
||||||
Opts = case lists:member(Name, aeso_compiler_tests:debug_mode_contracts()) of
|
Opts = case lists:member(Name, so_compiler_tests:debug_mode_contracts()) of
|
||||||
true -> [debug_mode];
|
true -> [debug_mode];
|
||||||
false -> []
|
false -> []
|
||||||
end ++ [{include, {file_system, [aeso_test_utils:contract_path()]}}],
|
end ++ [{include, {file_system, [so_test_utils:contract_path()]}}],
|
||||||
JSON = case aeso_aci:contract_interface(json, String, Opts) of
|
JSON = case so_aci:contract_interface(json, String, Opts) of
|
||||||
{ok, J} -> J;
|
{ok, J} -> J;
|
||||||
{error, ErrorStringJ} when is_binary(ErrorStringJ) -> error(ErrorStringJ);
|
{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,
|
end,
|
||||||
case aeso_compiler:from_string(String, [{aci, json} | Opts]) of
|
case so_compiler:from_string(String, [{aci, json} | Opts]) of
|
||||||
{ok, #{aci := JSON1}} ->
|
{ok, #{aci := JSON1}} ->
|
||||||
?assertEqual(JSON, JSON1),
|
?assertEqual(JSON, JSON1),
|
||||||
io:format("JSON:\n~p\n", [JSON]),
|
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]),
|
io:format("STUB:\n~s\n", [ContractStub]),
|
||||||
check_stub(ContractStub, [{src_file, Name}]),
|
check_stub(ContractStub, [{src_file, Name}]),
|
||||||
|
|
||||||
ok;
|
ok;
|
||||||
{error, ErrorString} when is_binary(ErrorString) -> error(ErrorString);
|
{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.
|
end.
|
||||||
|
|
||||||
check_stub(Stub, Options) ->
|
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 ->
|
Ast ->
|
||||||
try
|
try
|
||||||
%% io:format("AST: ~120p\n", [Ast]),
|
%% 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} ->
|
catch throw:{type_errors, TE} ->
|
||||||
io:format("Type error:\n~s\n", [TE]),
|
io:format("Type error:\n~s\n", [TE]),
|
||||||
error(TE);
|
error(TE);
|
||||||
@ -136,6 +136,6 @@ check_stub(Stub, Options) ->
|
|||||||
error(R)
|
error(R)
|
||||||
end
|
end
|
||||||
catch throw:{error, Errs} ->
|
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})
|
error({parse_errors, Errs})
|
||||||
end.
|
end.
|
@ -6,7 +6,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_calldata_tests).
|
-module(so_calldata_tests).
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
calldata_test_() ->
|
calldata_test_() ->
|
||||||
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||||
fun() ->
|
fun() ->
|
||||||
ContractString = aeso_test_utils:read_contract(ContractName),
|
ContractString = so_test_utils:read_contract(ContractName),
|
||||||
FateExprs = ast_exprs(ContractString, Fun, Args),
|
FateExprs = ast_exprs(ContractString, Fun, Args),
|
||||||
ParsedExprs = parse_args(Fun, Args),
|
ParsedExprs = parse_args(Fun, Args),
|
||||||
?assertEqual(ParsedExprs, FateExprs),
|
?assertEqual(ParsedExprs, FateExprs),
|
||||||
@ -28,8 +28,8 @@ calldata_test_() ->
|
|||||||
calldata_aci_test_() ->
|
calldata_aci_test_() ->
|
||||||
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||||
fun() ->
|
fun() ->
|
||||||
ContractString = aeso_test_utils:read_contract(ContractName),
|
ContractString = so_test_utils:read_contract(ContractName),
|
||||||
{ok, ContractACIBin} = aeso_aci:contract_interface(string, ContractString, [no_code]),
|
{ok, ContractACIBin} = so_aci:contract_interface(string, ContractString, [no_code]),
|
||||||
ContractACI = binary_to_list(ContractACIBin),
|
ContractACI = binary_to_list(ContractACIBin),
|
||||||
io:format("ACI:\n~s\n", [ContractACIBin]),
|
io:format("ACI:\n~s\n", [ContractACIBin]),
|
||||||
FateExprs = ast_exprs(ContractACI, Fun, Args),
|
FateExprs = ast_exprs(ContractACI, Fun, Args),
|
||||||
@ -40,7 +40,7 @@ calldata_aci_test_() ->
|
|||||||
|
|
||||||
parse_args(Fun, Args) ->
|
parse_args(Fun, Args) ->
|
||||||
[{contract_main, _, _, _, [{letfun, _, _, _, _, [{guarded, _, [], {app, _, _, AST}}]}]}] =
|
[{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(AST).
|
||||||
|
|
||||||
strip_ann(T) when is_tuple(T) ->
|
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, []).
|
ast_exprs(ContractString, Fun, Args, []).
|
||||||
ast_exprs(ContractString, Fun, Args, Opts) ->
|
ast_exprs(ContractString, Fun, Args, Opts) ->
|
||||||
{ok, Data} = (catch aeso_compiler:create_calldata(ContractString, Fun, Args, Opts)),
|
{ok, Data} = (catch so_compiler:create_calldata(ContractString, Fun, Args, Opts)),
|
||||||
{ok, _Types, Exprs} = (catch aeso_compiler:decode_calldata(ContractString, Fun, Data, Opts)),
|
{ok, _Types, Exprs} = (catch so_compiler:decode_calldata(ContractString, Fun, Data, Opts)),
|
||||||
?assert(is_list(Exprs)),
|
?assert(is_list(Exprs)),
|
||||||
strip_ann(Exprs).
|
strip_ann(Exprs).
|
||||||
|
|
||||||
@ -90,8 +90,6 @@ compilable_contracts() ->
|
|||||||
{"funargs", "sextiosju", ["#01020304050607080910111213141516171819202122232425262728293031323334353637383940"
|
{"funargs", "sextiosju", ["#01020304050607080910111213141516171819202122232425262728293031323334353637383940"
|
||||||
"414243444546474849505152535455565758596061626364656667"]},
|
"414243444546474849505152535455565758596061626364656667"]},
|
||||||
{"funargs", "trettiotva", ["#0102030405060708091011121314151617181920212223242526272829303132"]},
|
{"funargs", "trettiotva", ["#0102030405060708091011121314151617181920212223242526272829303132"]},
|
||||||
{"funargs", "find_oracle", ["ok_2YNyxd6TRJPNrTcEDCe9ra59SVUdp9FR9qWC5msKZWYD9bP9z5"]},
|
|
||||||
{"funargs", "find_query", ["oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY"]},
|
|
||||||
{"funargs", "traffic_light", ["Green"]},
|
{"funargs", "traffic_light", ["Green"]},
|
||||||
{"funargs", "traffic_light", ["Pantone(12)"]},
|
{"funargs", "traffic_light", ["Pantone(12)"]},
|
||||||
{"funargs", "tuples", ["()"]},
|
{"funargs", "tuples", ["()"]},
|
@ -6,7 +6,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_compiler_tests).
|
-module(so_compiler_tests).
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
|
|
||||||
@ -28,14 +28,14 @@ simple_compile_test_() ->
|
|||||||
fun() ->
|
fun() ->
|
||||||
case compile(ContractName) of
|
case compile(ContractName) of
|
||||||
#{fate_code := Code} ->
|
#{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});
|
?assertMatch({X, X}, {Code1, Code});
|
||||||
Error -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
Error -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
||||||
end
|
end
|
||||||
end} || ContractName <- compilable_contracts()] ++
|
end} || ContractName <- compilable_contracts()] ++
|
||||||
[ {"Test file not found error",
|
[ {"Test file not found error",
|
||||||
fun() ->
|
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">>,
|
ExpErr = <<"File error:\ndoes_not_exist.aes: no such file or directory">>,
|
||||||
check_errors([ExpErr], Errors)
|
check_errors([ExpErr], Errors)
|
||||||
end} ] ++
|
end} ] ++
|
||||||
@ -49,7 +49,7 @@ simple_compile_test_() ->
|
|||||||
fun() ->
|
fun() ->
|
||||||
FileSystem = maps:from_list(
|
FileSystem = maps:from_list(
|
||||||
[ begin
|
[ 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}
|
{File, Bin}
|
||||||
end || File <- ["included.aes", "../contracts/included2.aes"] ]),
|
end || File <- ["included.aes", "../contracts/included2.aes"] ]),
|
||||||
#{byte_code := Code1} = compile("include", [{include, {explicit_files, FileSystem}}]),
|
#{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
|
%% Check if all modules in the standard library compile
|
||||||
stdlib_test_() ->
|
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",
|
[ { "Testing " ++ File ++ " from the stdlib",
|
||||||
fun() ->
|
fun() ->
|
||||||
String = "include \"" ++ File ++ "\"\nmain contract Test =\n entrypoint f(x) = x",
|
String = "include \"" ++ File ++ "\"\nmain contract Test =\n entrypoint f(x) = x",
|
||||||
Options = [{src_file, File}],
|
Options = [{src_file, File}],
|
||||||
case aeso_compiler:from_string(String, Options) of
|
case so_compiler:from_string(String, Options) of
|
||||||
{ok, #{fate_code := Code}} ->
|
{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});
|
?assertMatch({X, X}, {Code1, Code});
|
||||||
{error, Error} -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
{error, Error} -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
||||||
end
|
end
|
||||||
@ -97,7 +97,7 @@ check_errors(Expect, #{}) ->
|
|||||||
?assertEqual({error, Expect}, ok);
|
?assertEqual({error, Expect}, ok);
|
||||||
check_errors(Expect0, Actual0) ->
|
check_errors(Expect0, Actual0) ->
|
||||||
Expect = lists:sort(Expect0),
|
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
|
case {Expect -- Actual, Actual -- Expect} of
|
||||||
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
||||||
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
||||||
@ -106,7 +106,7 @@ check_errors(Expect0, Actual0) ->
|
|||||||
|
|
||||||
check_warnings(Expect0, Actual0) ->
|
check_warnings(Expect0, Actual0) ->
|
||||||
Expect = lists:sort(Expect0),
|
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
|
case {Expect -- Actual, Actual -- Expect} of
|
||||||
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
||||||
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
||||||
@ -114,19 +114,19 @@ check_warnings(Expect0, Actual0) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
compile(Name) ->
|
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) ->
|
compile(Name, Options) ->
|
||||||
String = aeso_test_utils:read_contract(Name),
|
String = so_test_utils:read_contract(Name),
|
||||||
Options1 =
|
Options1 =
|
||||||
case lists:member(Name, debug_mode_contracts()) of
|
case lists:member(Name, debug_mode_contracts()) of
|
||||||
true -> [debug_mode];
|
true -> [debug_mode];
|
||||||
false -> []
|
false -> []
|
||||||
end ++
|
end ++
|
||||||
[ {src_file, Name ++ ".aes"}
|
[ {src_file, Name ++ ".aes"}
|
||||||
, {include, {file_system, [aeso_test_utils:contract_path()]}}
|
, {include, {file_system, [so_test_utils:contract_path()]}}
|
||||||
] ++ Options,
|
] ++ Options,
|
||||||
case aeso_compiler:from_string(String, Options1) of
|
case so_compiler:from_string(String, Options1) of
|
||||||
{ok, Map} -> Map;
|
{ok, Map} -> Map;
|
||||||
{error, ErrorString} when is_binary(ErrorString) -> ErrorString;
|
{error, ErrorString} when is_binary(ErrorString) -> ErrorString;
|
||||||
{error, Errors} -> Errors
|
{error, Errors} -> Errors
|
||||||
@ -145,7 +145,6 @@ compilable_contracts() ->
|
|||||||
"fundme",
|
"fundme",
|
||||||
"identity",
|
"identity",
|
||||||
"maps",
|
"maps",
|
||||||
"oracles",
|
|
||||||
"remote_call",
|
"remote_call",
|
||||||
"remote_call_ambiguous_record",
|
"remote_call_ambiguous_record",
|
||||||
"simple",
|
"simple",
|
||||||
@ -223,7 +222,6 @@ compilable_contracts() ->
|
|||||||
"polymorphic_entrypoint_return",
|
"polymorphic_entrypoint_return",
|
||||||
"polymorphic_map_keys",
|
"polymorphic_map_keys",
|
||||||
"unapplied_contract_call",
|
"unapplied_contract_call",
|
||||||
"unapplied_named_arg_builtin",
|
|
||||||
"resolve_field_constraint_by_arity",
|
"resolve_field_constraint_by_arity",
|
||||||
"toplevel_constants",
|
"toplevel_constants",
|
||||||
"ceres",
|
"ceres",
|
||||||
@ -299,7 +297,7 @@ warnings() ->
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
failing_contracts() ->
|
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], ".")),
|
Version = list_to_binary(string:join([integer_to_list(N) || N <- V], ".")),
|
||||||
%% Parse errors
|
%% Parse errors
|
||||||
[ ?PARSE_ERROR(field_parse_error,
|
[ ?PARSE_ERROR(field_parse_error,
|
||||||
@ -466,11 +464,7 @@ failing_contracts() ->
|
|||||||
[<<?Pos(2, 12)
|
[<<?Pos(2, 12)
|
||||||
"Nested contracts are not allowed. Contract `Con` is not defined at top level.">>])
|
"Nested contracts are not allowed. Contract `Con` is not defined at top level.">>])
|
||||||
, ?TYPE_ERROR(bad_address_literals,
|
, ?TYPE_ERROR(bad_address_literals,
|
||||||
[<<?Pos(11, 5)
|
[<<?Pos(9, 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)
|
|
||||||
"Cannot unify `address` and `Remote`\n"
|
"Cannot unify `address` and `Remote`\n"
|
||||||
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
||||||
"against the expected type `Remote`">>,
|
"against the expected type `Remote`">>,
|
||||||
@ -478,52 +472,17 @@ failing_contracts() ->
|
|||||||
"Cannot unify `address` and `bytes(32)`\n"
|
"Cannot unify `address` and `bytes(32)`\n"
|
||||||
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
||||||
"against the expected type `bytes(32)`">>,
|
"against the expected type `bytes(32)`">>,
|
||||||
<<?Pos(14, 5)
|
<<?Pos(12, 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)
|
|
||||||
"The type `address` is not a contract type\n"
|
"The type `address` is not a contract type\n"
|
||||||
"when checking that the contract literal "
|
"when checking that the contract literal "
|
||||||
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
||||||
"has the type `address`">>,
|
"has the type `address`">>,
|
||||||
<<?Pos(30, 5)
|
<<?Pos(14, 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)
|
|
||||||
"The type `bytes(32)` is not a contract type\n"
|
"The type `bytes(32)` is not a contract type\n"
|
||||||
"when checking that the contract literal "
|
"when checking that the contract literal "
|
||||||
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
||||||
"has the type `bytes(32)`">>,
|
"has the type `bytes(32)`">>,
|
||||||
<<?Pos(34, 5),
|
<<?Pos(16, 5),
|
||||||
"The type `address` is not a contract type\n"
|
"The type `address` is not a contract type\n"
|
||||||
"when checking that the call to `Address.to_contract` "
|
"when checking that the call to `Address.to_contract` "
|
||||||
"has the type `address`">>])
|
"has the type `address`">>])
|
||||||
@ -1036,56 +995,6 @@ failing_contracts() ->
|
|||||||
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
"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)`">>
|
"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,
|
, ?TYPE_ERROR(polymorphism_variance_switching_chain_create_fail,
|
||||||
[<<?Pos(9,22)
|
[<<?Pos(9,22)
|
||||||
"I is not implemented.\n"
|
"I is not implemented.\n"
|
||||||
@ -1156,34 +1065,6 @@ failing_contracts() ->
|
|||||||
" `list(int)`\n"
|
" `list(int)`\n"
|
||||||
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
|
"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,
|
, ?TYPE_ERROR(var_args_unify_let,
|
||||||
[<<?Pos(3,9)
|
[<<?Pos(3,9)
|
||||||
"Cannot infer types for variable argument list.\n"
|
"Cannot infer types for variable argument list.\n"
|
||||||
@ -1345,16 +1226,16 @@ validation_fails() ->
|
|||||||
validate(Contract1, Contract2) ->
|
validate(Contract1, Contract2) ->
|
||||||
case compile(Contract1) of
|
case compile(Contract1) of
|
||||||
ByteCode = #{ fate_code := FCode } ->
|
ByteCode = #{ fate_code := FCode } ->
|
||||||
FCode1 = aeb_fate_code:serialize(aeb_fate_code:strip_init_function(FCode)),
|
FCode1 = gmb_fate_code:serialize(gmb_fate_code:strip_init_function(FCode)),
|
||||||
Source = aeso_test_utils:read_contract(Contract2),
|
Source = so_test_utils:read_contract(Contract2),
|
||||||
aeso_compiler:validate_byte_code(
|
so_compiler:validate_byte_code(
|
||||||
ByteCode#{ byte_code := FCode1 }, Source,
|
ByteCode#{ byte_code := FCode1 }, Source,
|
||||||
case lists:member(Contract2, debug_mode_contracts()) of
|
case lists:member(Contract2, debug_mode_contracts()) of
|
||||||
true -> [debug_mode];
|
true -> [debug_mode];
|
||||||
false -> []
|
false -> []
|
||||||
end ++
|
end ++
|
||||||
[ {src_file, lists:concat([Contract2, ".aes"])}
|
[ {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)
|
Error -> print_and_throw(Error)
|
||||||
end.
|
end.
|
||||||
@ -1365,6 +1246,6 @@ print_and_throw(Err) ->
|
|||||||
io:format("\n~s", [ErrBin]),
|
io:format("\n~s", [ErrBin]),
|
||||||
error(ErrBin);
|
error(ErrBin);
|
||||||
Errors ->
|
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)
|
error(compilation_error)
|
||||||
end.
|
end.
|
@ -1,4 +1,4 @@
|
|||||||
-module(aeso_encode_decode_tests).
|
-module(so_encode_decode_tests).
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
|
|
||||||
@ -9,9 +9,9 @@
|
|||||||
encode_decode_test_() ->
|
encode_decode_test_() ->
|
||||||
[ {lists:flatten(io_lib:format("Testing encode-decode roundtrip for ~p : ~p", [Value, {EType, DType}])),
|
[ {lists:flatten(io_lib:format("Testing encode-decode roundtrip for ~p : ~p", [Value, {EType, DType}])),
|
||||||
fun() ->
|
fun() ->
|
||||||
{ok, SerRes} = aeso_compiler:encode_value(?EMPTY, EType, Value, []),
|
{ok, SerRes} = so_compiler:encode_value(?EMPTY, EType, Value, []),
|
||||||
{ok, Expr} = aeso_compiler:decode_value(?EMPTY, DType, SerRes, []),
|
{ok, Expr} = so_compiler:decode_value(?EMPTY, DType, SerRes, []),
|
||||||
Value2 = prettypr:format(aeso_pretty:expr(Expr)),
|
Value2 = prettypr:format(so_pretty:expr(Expr)),
|
||||||
?assertEqual(Value, Value2)
|
?assertEqual(Value, Value2)
|
||||||
end} || {Value, EType, DType} <- test_data() ].
|
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]).
|
-export([parse_contract/1]).
|
||||||
|
|
||||||
@ -68,15 +68,15 @@ simple_contracts_test_() ->
|
|||||||
}.
|
}.
|
||||||
|
|
||||||
parse_contract(Name) ->
|
parse_contract(Name) ->
|
||||||
parse_string(aeso_test_utils:read_contract(Name)).
|
parse_string(so_test_utils:read_contract(Name)).
|
||||||
|
|
||||||
roundtrip_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) -> parse_string(Text, []).
|
||||||
|
|
||||||
parse_string(Text, Opts) ->
|
parse_string(Text, Opts) ->
|
||||||
aeso_parser:string(Text, Opts).
|
so_parser:string(Text, Opts).
|
||||||
|
|
||||||
parse_expr(Text) ->
|
parse_expr(Text) ->
|
||||||
[{letval, _, _, Expr}] =
|
[{letval, _, _, Expr}] =
|
||||||
@ -85,8 +85,8 @@ parse_expr(Text) ->
|
|||||||
|
|
||||||
round_trip(Text) ->
|
round_trip(Text) ->
|
||||||
Contract = parse_string(Text),
|
Contract = parse_string(Text),
|
||||||
Text1 = prettypr:format(aeso_pretty:decls(strip_stdlib(Contract))),
|
Text1 = prettypr:format(so_pretty:decls(strip_stdlib(Contract))),
|
||||||
Contract1 = parse_string(aeso_scan:utf8_encode(Text1)),
|
Contract1 = parse_string(so_scan:utf8_encode(Text1)),
|
||||||
NoSrcLoc = remove_line_numbers(Contract),
|
NoSrcLoc = remove_line_numbers(Contract),
|
||||||
NoSrcLoc1 = remove_line_numbers(Contract1),
|
NoSrcLoc1 = remove_line_numbers(Contract1),
|
||||||
?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)).
|
?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)).
|
@ -1,4 +1,4 @@
|
|||||||
-module(aeso_scan_tests).
|
-module(so_scan_tests).
|
||||||
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ empty_contract_test_() ->
|
|||||||
[{"Scan an empty contract.",
|
[{"Scan an empty contract.",
|
||||||
fun() ->
|
fun() ->
|
||||||
Text = " ",
|
Text = " ",
|
||||||
{ok, []} = aeso_scan:scan(Text),
|
{ok, []} = so_scan:scan(Text),
|
||||||
ok
|
ok
|
||||||
end}
|
end}
|
||||||
]}.
|
]}.
|
||||||
@ -26,7 +26,7 @@ all_tokens_test_() ->
|
|||||||
Tokens = all_tokens(),
|
Tokens = all_tokens(),
|
||||||
Text = string:join(lists:map(fun show_token/1, Tokens), " "),
|
Text = string:join(lists:map(fun show_token/1, Tokens), " "),
|
||||||
io:format("~s\n", [Text]),
|
io:format("~s\n", [Text]),
|
||||||
{ok, Tokens1} = aeso_scan:scan(Text),
|
{ok, Tokens1} = so_scan:scan(Text),
|
||||||
true = compare_tokens(Tokens, Tokens1),
|
true = compare_tokens(Tokens, Tokens1),
|
||||||
ok
|
ok
|
||||||
end}
|
end}
|
@ -6,12 +6,12 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(aeso_test_utils).
|
-module(so_test_utils).
|
||||||
|
|
||||||
-export([read_contract/1, contract_path/0]).
|
-export([read_contract/1, contract_path/0]).
|
||||||
|
|
||||||
contract_path() ->
|
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.
|
%% Read a contract file from the test/contracts directory.
|
||||||
-spec read_contract(string() | atom()) -> string().
|
-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",{9,0,0}}}.
|
||||||
|
{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