Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad4c341a4a | |||
| f964fa89a1 | |||
| 8d8d9c6b83 | |||
| c98ea25e8b |
+11
-1
@@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
### Changed
|
### Changed
|
||||||
### Removed
|
### Removed
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
## [7.0.1]
|
||||||
|
### Added
|
||||||
|
- Add CONTRIBUTING.md file.
|
||||||
|
### Changed
|
||||||
|
- Update Sophia syntax docs to include missing information about existing syntax.
|
||||||
|
### Fixed
|
||||||
|
- [404](https://github.com/aeternity/aesophia/issues/404) Contract polymorphism crashes on non-obvious child contract typing.
|
||||||
|
|
||||||
## [7.0.0]
|
## [7.0.0]
|
||||||
### Added
|
### Added
|
||||||
@@ -352,7 +361,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Simplify calldata creation - instead of passing a compiled contract, simply
|
- Simplify calldata creation - instead of passing a compiled contract, simply
|
||||||
pass a (stubbed) contract string.
|
pass a (stubbed) contract string.
|
||||||
|
|
||||||
[Unreleased]: https://github.com/aeternity/aesophia/compare/v7.0.0...HEAD
|
[Unreleased]: https://github.com/aeternity/aesophia/compare/v7.0.1...HEAD
|
||||||
|
[7.0.1]: https://github.com/aeternity/aesophia/compare/v7.0.0...v7.0.1
|
||||||
[7.0.0]: https://github.com/aeternity/aesophia/compare/v6.1.0...v7.0.0
|
[7.0.0]: https://github.com/aeternity/aesophia/compare/v6.1.0...v7.0.0
|
||||||
[6.1.0]: https://github.com/aeternity/aesophia/compare/v6.0.2...v6.1.0
|
[6.1.0]: https://github.com/aeternity/aesophia/compare/v6.0.2...v6.1.0
|
||||||
[6.0.2]: https://github.com/aeternity/aesophia/compare/v6.0.1...v6.0.2
|
[6.0.2]: https://github.com/aeternity/aesophia/compare/v6.0.1...v6.0.2
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Contributing to Sophia
|
||||||
|
|
||||||
|
## Checklist For Creating New Pull Requests
|
||||||
|
|
||||||
|
The following points should be considered before creating a new PR to the Sophia compiler.
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- The [Changelog](CHANGELOG.md) file should be updated for all PRs.
|
||||||
|
- If a PR introduces a new feature that is relevant to the users of the language, the [Sophia Features Documentation](docs/sophia_features.md) should be updated to describe the new feature.
|
||||||
|
- If a PR introduces new syntax (e.g. changes in [aeso_syntax.erl](src/aeso_syntax.erl), [aeso_scan.erl](src/aeso_scan.erl), or [aeso_parser.erl](src/aeso_parser.erl)), the [Sophia Syntax Documentation](docs/sophia_syntax.md) should be updated to include the new syntax.
|
||||||
|
- If a PR introduces a new library, the public interface of the new library should be fully documented in the [Sophia Standard Library Documentation](docs/sophia_stdlib.md).
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- If a PR introduces new syntax (e.g. changes in [aeso_syntax.erl](src/aeso_syntax.erl), [aeso_scan.erl](src/aeso_scan.erl), or [aeso_parser.erl](src/aeso_parser.erl)), the contract [all_syntax.aes](test/contracts/all_syntax.aes) should be updated to include the new syntax.
|
||||||
|
- If a PR fixes a bug, the code that replicates the bug should be added as a new passing test contract.
|
||||||
|
- If a PR introduces a new feature, add tests for both successful and failing usage of that feature. In order to run the entire compilation pipeline and to avoid erroring during intermediate steps, failing tests should not be mixed with the successful ones.
|
||||||
|
|
||||||
|
### Source Code
|
||||||
|
|
||||||
|
- If a PR introduces new syntax (e.g. changes in [aeso_syntax.erl](src/aeso_syntax.erl), [aeso_scan.erl](src/aeso_scan.erl), or [aeso_parser.erl](src/aeso_parser.erl)), the following code should be updated to handle the new syntax:
|
||||||
|
- The function `aeso_syntax_utils:fold/4` in the file [aeso_syntax_utils.erl](src/aeso_syntax_utils.erl).
|
||||||
|
- Any related pretty printing function in the file [aeso_pretty.erl](src/aeso_pretty.erl), depending on the type of the newly added syntax.
|
||||||
|
|
||||||
|
## Checklist For Creating a Release
|
||||||
|
|
||||||
|
- Update the version in the file [aesophia.app.src](src/aesophia.app.src).
|
||||||
|
- Update the version in the file [rebar.config](rebar.config).
|
||||||
|
- In the [Changelog](CHANGELOG.md):
|
||||||
|
- Update the `Unreleased` changes to be under the new version.
|
||||||
|
- Update the version at the bottom of the file.
|
||||||
|
- Commit and the changes and create a new PR (check the commit of [v6.1.0](https://github.com/aeternity/aesophia/commit/5ad5270e381f6e810d7b8b5cdc168d283e7a90bb) for reference).
|
||||||
|
- Create a release after merging the new PR to `master` branch.
|
||||||
|
- After releasing `aesophia`, refer to each of the following repositories and create new releases as well, using the new `aesophia` release:
|
||||||
|
- [aesophia_cli](https://github.com/aeternity/aesophia_cli)
|
||||||
|
- [aesophia_http](https://github.com/aeternity/aesophia_http)
|
||||||
|
- [aerepl](https://github.com/aeternity/aerepl)
|
||||||
@@ -14,6 +14,7 @@ The compiler is currently being used three places
|
|||||||
* [Features](docs/sophia_features.md)
|
* [Features](docs/sophia_features.md)
|
||||||
* [Standard library](docs/sophia_stdlib.md)
|
* [Standard library](docs/sophia_stdlib.md)
|
||||||
* [Contract examples](docs/sophia_examples.md)
|
* [Contract examples](docs/sophia_examples.md)
|
||||||
|
* [Contributing](CONTRIBUTING.md)
|
||||||
|
|
||||||
Additionally you can check out the [contracts section](https://github.com/aeternity/protocol/blob/master/contracts/contracts.md) of the æternity blockchain specification.
|
Additionally you can check out the [contracts section](https://github.com/aeternity/protocol/blob/master/contracts/contracts.md) of the æternity blockchain specification.
|
||||||
|
|
||||||
|
|||||||
+27
-8
@@ -10,8 +10,9 @@ and `*/` and can be nested.
|
|||||||
### Keywords
|
### Keywords
|
||||||
|
|
||||||
```
|
```
|
||||||
contract elif else entrypoint false function if import include let mod namespace
|
contract include let switch type record datatype if elif else function
|
||||||
private payable stateful switch true type record datatype main interface
|
stateful payable true false mod public entrypoint private indexed namespace
|
||||||
|
interface main using as for hiding
|
||||||
```
|
```
|
||||||
|
|
||||||
### Tokens
|
### Tokens
|
||||||
@@ -91,18 +92,30 @@ A Sophia file consists of a sequence of *declarations* in a layout block.
|
|||||||
```c
|
```c
|
||||||
File ::= Block(TopDecl)
|
File ::= Block(TopDecl)
|
||||||
|
|
||||||
TopDecl ::= ['payable'] 'contract' Con '=' Block(Decl)
|
TopDecl ::= ['payable'] ['main'] 'contract' Con [Implement] '=' Block(Decl)
|
||||||
|
| 'contract' 'interface' Con [Implement] '=' Block(Decl)
|
||||||
| 'namespace' Con '=' Block(Decl)
|
| 'namespace' Con '=' Block(Decl)
|
||||||
| '@compiler' PragmaOp Version
|
| '@compiler' PragmaOp Version
|
||||||
| 'include' String
|
| 'include' String
|
||||||
|
| Using
|
||||||
|
|
||||||
|
Implement ::= ':' Sep1(Con, ',')
|
||||||
|
|
||||||
Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
| 'record' Id ['(' TVar* ')'] '=' RecordType
|
| 'record' Id ['(' TVar* ')'] '=' RecordType
|
||||||
| 'datatype' Id ['(' TVar* ')'] '=' DataType
|
| 'datatype' Id ['(' TVar* ')'] '=' DataType
|
||||||
| (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
|
| (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
|
||||||
|
| Using
|
||||||
|
|
||||||
FunDecl ::= Id ':' Type // Type signature
|
FunDecl ::= Id ':' Type // Type signature
|
||||||
| Id Args [':' Type] '=' Block(Stmt) // Definition
|
| Id Args [':' Type] '=' Block(Stmt) // Definition
|
||||||
|
| Id Args [':' Type] Block(GuardedDef) // Guarded definitions
|
||||||
|
|
||||||
|
GuardedDef ::= '|' Sep1(Expr, ',') '=' Block(Stmt)
|
||||||
|
|
||||||
|
Using ::= 'using' Con ['as' Con] [UsingParts]
|
||||||
|
UsingParts ::= 'for' '[' Sep1(Id, ',') ']'
|
||||||
|
| 'hiding' '[' Sep1(Id, ',') ']'
|
||||||
|
|
||||||
PragmaOp ::= '<' | '=<' | '==' | '>=' | '>'
|
PragmaOp ::= '<' | '=<' | '==' | '>=' | '>'
|
||||||
Version ::= Sep1(Int, '.')
|
Version ::= Sep1(Int, '.')
|
||||||
@@ -172,12 +185,17 @@ Stmt ::= 'switch' '(' Expr ')' Block(Case)
|
|||||||
| 'elif' '(' Expr ')' Block(Stmt)
|
| 'elif' '(' Expr ')' Block(Stmt)
|
||||||
| 'else' Block(Stmt)
|
| 'else' Block(Stmt)
|
||||||
| 'let' LetDef
|
| 'let' LetDef
|
||||||
|
| Using
|
||||||
| Expr
|
| Expr
|
||||||
|
|
||||||
LetDef ::= Id Args [':' Type] '=' Block(Stmt) // Function definition
|
LetDef ::= Id Args [':' Type] '=' Block(Stmt) // Function definition
|
||||||
| Pattern '=' Block(Stmt) // Value definition
|
| Pattern '=' Block(Stmt) // Value definition
|
||||||
|
|
||||||
Case ::= Pattern '=>' Block(Stmt)
|
Case ::= Pattern '=>' Block(Stmt)
|
||||||
|
| Pattern Block(GuardedCase)
|
||||||
|
|
||||||
|
GuardedCase ::= '|' Sep1(Expr, ',') '=>' Block(Stmt)
|
||||||
|
|
||||||
Pattern ::= Expr
|
Pattern ::= Expr
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -215,6 +233,7 @@ Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x +
|
|||||||
| '[' Expr '..' Expr ']' // List range [1..n]
|
| '[' Expr '..' Expr ']' // List range [1..n]
|
||||||
| '{' Sep(FieldUpdate, ',') '}' // Record or map value {x = 0, y = 1}, {[key] = val}
|
| '{' Sep(FieldUpdate, ',') '}' // Record or map value {x = 0, y = 1}, {[key] = val}
|
||||||
| '(' Expr ')' // Parens (1 + 2) * 3
|
| '(' Expr ')' // Parens (1 + 2) * 3
|
||||||
|
| '(' Expr '=' Expr ')' // Assign pattern (y = 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
|
||||||
@@ -244,12 +263,12 @@ UnOp ::= '-' | '!'
|
|||||||
| Operators | Type
|
| Operators | Type
|
||||||
| --- | ---
|
| --- | ---
|
||||||
| `-` `+` `*` `/` `mod` `^` | arithmetic operators
|
| `-` `+` `*` `/` `mod` `^` | arithmetic operators
|
||||||
| `!` `&&` `\|\|` | logical operators
|
| `!` `&&` `||` | logical operators
|
||||||
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
|
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
|
||||||
| `::` `++` | list operators
|
| `::` `++` | list operators
|
||||||
| `\|>` | functional operators
|
| `|>` | functional operators
|
||||||
|
|
||||||
## Operator precendences
|
## Operator precedence
|
||||||
|
|
||||||
In order of highest to lowest precedence.
|
In order of highest to lowest precedence.
|
||||||
|
|
||||||
@@ -263,5 +282,5 @@ In order of highest to lowest precedence.
|
|||||||
| `::` `++` | right
|
| `::` `++` | right
|
||||||
| `<` `>` `=<` `>=` `==` `!=` | none
|
| `<` `>` `=<` `>=` `==` `!=` | none
|
||||||
| `&&` | right
|
| `&&` | right
|
||||||
| `\|\|` | right
|
| `||` | right
|
||||||
| `\|>` | left
|
| `|>` | left
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
|
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{relx, [{release, {aesophia, "7.0.0"},
|
{relx, [{release, {aesophia, "7.0.1"},
|
||||||
[aesophia, aebytecode, getopt]},
|
[aesophia, aebytecode, getopt]},
|
||||||
|
|
||||||
{dev_mode, true},
|
{dev_mode, true},
|
||||||
|
|||||||
@@ -693,7 +693,7 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
%% Function calls
|
%% Function calls
|
||||||
expr_to_fcode(Env, Type, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, _}}, Args}) ->
|
expr_to_fcode(Env, _, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, Type}}, Args}) ->
|
||||||
Args1 = get_named_args(NamedArgsT, Args),
|
Args1 = get_named_args(NamedArgsT, Args),
|
||||||
FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1],
|
FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1],
|
||||||
case expr_to_fcode(Env, Fun) of
|
case expr_to_fcode(Env, Fun) of
|
||||||
|
|||||||
@@ -430,6 +430,7 @@ lc_bind(Let) ->
|
|||||||
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
|
||||||
|
bin_prec('|>') -> {150, 150, 200};
|
||||||
bin_prec('||') -> {200, 300, 200};
|
bin_prec('||') -> {200, 300, 200};
|
||||||
bin_prec('&&') -> {300, 400, 300};
|
bin_prec('&&') -> {300, 400, 300};
|
||||||
bin_prec('<') -> {400, 500, 500};
|
bin_prec('<') -> {400, 500, 500};
|
||||||
|
|||||||
+1
-1
@@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^'
|
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^'
|
||||||
| '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!='
|
| '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!='
|
||||||
| '||' | '&&' | '..'.
|
| '||' | '&&' | '..' | '|>'.
|
||||||
-type un_op() :: '-' | '!'.
|
-type un_op() :: '-' | '!'.
|
||||||
|
|
||||||
-type expr()
|
-type expr()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{application, aesophia,
|
{application, aesophia,
|
||||||
[{description, "Compiler for Aeternity Sophia language"},
|
[{description, "Compiler for Aeternity Sophia language"},
|
||||||
{vsn, "7.0.0"},
|
{vsn, "7.0.1"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications,
|
{applications,
|
||||||
[kernel,
|
[kernel,
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ compilable_contracts() ->
|
|||||||
"polymorphism_contract_interface_extensions",
|
"polymorphism_contract_interface_extensions",
|
||||||
"polymorphism_contract_interface_same_decl_multi_interface",
|
"polymorphism_contract_interface_same_decl_multi_interface",
|
||||||
"polymorphism_contract_interface_same_name_same_type",
|
"polymorphism_contract_interface_same_name_same_type",
|
||||||
|
"polymorphism_variance_switching_chain_create",
|
||||||
"missing_init_fun_state_unit",
|
"missing_init_fun_state_unit",
|
||||||
"complex_compare_leq",
|
"complex_compare_leq",
|
||||||
"complex_compare",
|
"complex_compare",
|
||||||
@@ -1025,6 +1026,20 @@ failing_contracts() ->
|
|||||||
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
"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)`">>
|
"when checking the type of the pattern `q15 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Cat, Animal)`">>
|
||||||
])
|
])
|
||||||
|
, ?TYPE_ERROR(polymorphism_variance_switching_chain_create_fail,
|
||||||
|
[<<?Pos(9,22)
|
||||||
|
"I is not implemented.\n"
|
||||||
|
"when resolving arguments of variadic function `Chain.create`">>,
|
||||||
|
<<?Pos(10,13)
|
||||||
|
"Cannot unify `I` and `C` in a covariant context\n"
|
||||||
|
"when checking the type of the pattern `c2 : C` against the expected type `I`">>,
|
||||||
|
<<?Pos(10,22)
|
||||||
|
"I is not implemented.\n"
|
||||||
|
"when resolving arguments of variadic function `Chain.create`">>,
|
||||||
|
<<?Pos(11,22)
|
||||||
|
"I is not implemented.\n"
|
||||||
|
"when resolving arguments of variadic function `Chain.create`">>
|
||||||
|
])
|
||||||
, ?TYPE_ERROR(missing_definition,
|
, ?TYPE_ERROR(missing_definition,
|
||||||
[<<?Pos(2,14)
|
[<<?Pos(2,14)
|
||||||
"Missing definition of function `foo`">>
|
"Missing definition of function `foo`">>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
contract interface I =
|
||||||
|
entrypoint f : () => int
|
||||||
|
|
||||||
|
contract C1 : I =
|
||||||
|
entrypoint f() = 123
|
||||||
|
|
||||||
|
contract C2 : I =
|
||||||
|
entrypoint f() = 888
|
||||||
|
|
||||||
|
namespace Make =
|
||||||
|
stateful function new1() : I = Chain.create() : C1
|
||||||
|
stateful function new2() : I = Chain.create() : C2
|
||||||
|
|
||||||
|
stateful function new(c : I) : int = c.f()
|
||||||
|
|
||||||
|
main contract Main =
|
||||||
|
stateful entrypoint test1() =
|
||||||
|
let c = Make.new1()
|
||||||
|
Make.new(c)
|
||||||
|
|
||||||
|
stateful entrypoint test2() =
|
||||||
|
let c = Make.new2()
|
||||||
|
Make.new(c)
|
||||||
|
|
||||||
|
stateful entrypoint test3() =
|
||||||
|
let c1 = Chain.create() : C1 // succeeds
|
||||||
|
let c2 : I = Chain.create() : C1 // succeeds
|
||||||
|
let c3 : C1 = Chain.create() // succeeds
|
||||||
|
()
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
contract interface I =
|
||||||
|
entrypoint f : () => int
|
||||||
|
|
||||||
|
contract C : I =
|
||||||
|
entrypoint f() = 123
|
||||||
|
|
||||||
|
main contract Main =
|
||||||
|
stateful entrypoint test() =
|
||||||
|
let c1 : I = Chain.create() // fails
|
||||||
|
let c2 : C = Chain.create() : I // fails
|
||||||
|
let c3 = Chain.create() : I // fails
|
||||||
|
()
|
||||||
Reference in New Issue
Block a user