Compare commits

..

1 Commits

Author SHA1 Message Date
radrow a5cbf2fd79 Updated CHANGELOG 2020-03-23 12:48:47 +01:00
27 changed files with 133 additions and 310 deletions
+10 -25
View File
@@ -6,28 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Added documentation (actually, moved from `protocol`)
- Added standard library docs. Moved builtin docs from `sophia.md` to
`sophia_stdlib.md`
- Added library for rational numbers
### Changed
- Optimized `List.aes` library
### Removed
## [4.3.0]
### Added
- Added documentation (moved from `protocol`)
- `Frac.aes` library for rational numbers
- Added some more meaningful error messages
- Exported several parsing functionalities
- With option `keep_included` it is possible to see which files were included during the parse
- There is a function `run_parser` that be used to evaluate any parsing rule
- Exported parsers: `body`, `type` and `decl`
### Changed
- Performance improvements in the standard library
- Fixed ACI encoder to handle `-` unary operator
- Fixed including by absolute path
- Fixed variant type printing in the ACI error messages
- Fixed pretty printing of combined function clauses
### Removed
- `let` definitions are no longer supported in the toplevel of the contract
- type declarations are no longer supported
## [4.2.0] - 2020-01-15
### Added
- Allow separate entrypoint/function type signature and definition, and pattern
@@ -72,7 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
(de-)construct byte arrays.
- `[a..b]` language construct, returning the list of numbers between
`a` and `b` (inclusive). Returns the empty list if `a` > `b`.
- [Standard libraries](https://github.com/aeternity/aesophia/blob/master/docs/sophia_stdlib.md)
- [Standard libraries] (https://github.com/aeternity/protocol/blob/master/contracts/sophia_stdlib.md)
- Checks that `init` is not called from other functions.
- FATE backend - the compiler is able to produce VM code for both `AEVM` and `FATE`. Many
of the APIs now take `{backend, aevm | fate}` to decide wich backend to produce artifacts
@@ -211,11 +197,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Simplify calldata creation - instead of passing a compiled contract, simply
pass a (stubbed) contract string.
[Unreleased]: https://github.com/aeternity/aesophia/compare/v4.3.0...HEAD
[4.3.0]: https://github.com/aeternity/aesophia/compare/v4.2.0...v4.3.0
[4.2.0]: https://github.com/aeternity/aesophia/compare/v4.1.0...v4.2.0
[4.1.0]: https://github.com/aeternity/aesophia/compare/v4.0.0...v4.1.0
[4.0.0]: https://github.com/aeternity/aesophia/compare/v3.2.0...v4.0.0
[Unreleased]: https://github.com/aeternity/aesophia/compare/v4.2.0...HEAD
[4.2.0]: https://github.com/aeternity/aesophia/compare/v4.2.0...v4.1.0
[4.1.0]: https://github.com/aeternity/aesophia/compare/v4.1.0...v4.0.0
[4.0.0]: https://github.com/aeternity/aesophia/compare/v4.0.0...v3.2.0
[3.2.0]: https://github.com/aeternity/aesophia/compare/v3.1.0...v3.2.0
[3.1.0]: https://github.com/aeternity/aesophia/compare/v3.0.0...v3.1.0
[3.0.0]: https://github.com/aeternity/aesophia/compare/v2.1.0...v3.0.0
+10 -17
View File
@@ -2,6 +2,7 @@
**Table of Contents**
- [-](#-)
- [Language Features](#language-features)
- [Contracts](#contracts)
- [Calling other contracts](#calling-other-contracts)
@@ -52,7 +53,8 @@
- [Operators types](#operators-types)
- [Operator precendences](#operator-precendences)
- [Examples](#examples)
- [The lifetime of a contract](#the-lifetime-of-a-contract)
- [Killing a contract](#killing-a-contract)
## The Sophia Language
An Æternity BlockChain Language
@@ -444,13 +446,6 @@ Example syntax:
// yields [12,13,14,20,21,22,30,31,32]
```
Lists can be constructed using the range syntax using special `..` operator:
```
[1..4] == [1,2,3,4]
```
The ranges are always ascending and have step equal to 1.
Please refer to the [standard library](sophia_stdlib.md#List) for the predefined functionalities.
### Maps and records
@@ -830,17 +825,15 @@ In describing the syntax below, we use the following conventions:
A Sophia file consists of a sequence of *declarations* in a layout block.
```c
File ::= Block(TopDecl)
TopDecl ::= ['payable'] 'contract' Con '=' Block(Decl)
File ::= Block(Decl)
Decl ::= ['payable'] 'contract' Con '=' Block(Decl)
| 'namespace' Con '=' Block(Decl)
| '@compiler' PragmaOp Version
| 'include' String
Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
| 'type' Id ['(' TVar* ')'] ['=' TypeAlias]
| 'record' Id ['(' TVar* ')'] '=' RecordType
| 'datatype' Id ['(' TVar* ')'] '=' DataType
| (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
| EModifier* ('entrypoint' | 'function') Block(FunDecl)
FunDecl ::= Id ':' Type // Type signature
| Id Args [':' Type] '=' Block(Stmt) // Definition
@@ -952,7 +945,6 @@ Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x +
| '[' Sep(Expr, ',') ']' // List [1, 2, 3]
| '[' Expr '|' Sep(Generator, ',') ']'
// List comprehension [k | x <- [1], if (f(x)), let k = x+1]
| '[' Expr '..' Expr ']' // List range [1..n]
| '{' Sep(FieldUpdate, ',') '}' // Record or map value {x = 0, y = 1}, {[key] = val}
| '(' Expr ')' // Parens (1 + 2) * 3
| Id | Con | QId | QCon // Identifiers x, None, Map.member, AELib.Token
@@ -1020,8 +1012,8 @@ contract FundMe =
deadline : int,
goal : int }
stateful function spend(args : spend_args) =
Chain.spend(args.recipient, args.amount)
function spend(args : spend_args) =
raw_spend(args.recipient, args.amount)
entrypoint init(beneficiary, deadline, goal) : state =
{ contributions = {},
@@ -1060,6 +1052,7 @@ contract FundMe =
require(state.total >= state.goal, "Project was not funded")
spend({recipient = state.beneficiary,
amount = Contract.balance })
put(state{ beneficiary = #0 })
stateful function withdraw_contributor() =
if(state.total >= state.goal)
+7 -14
View File
@@ -56,14 +56,11 @@ namespace Frac =
/** Integer to rational division
*/
function make_frac(n : int, d : int) : frac =
if (d == 0) abort("Zero denominator")
if (d == 0) abort("Division by zero")
elif (n == 0) Zero
elif ((n < 0) == (d < 0)) simplify(Pos(abs_int(n), abs_int(d)))
else simplify(Neg(abs_int(n), abs_int(d)))
function one() : frac = Pos(1, 1)
function zero() : frac = Zero
function eq(a : frac, b : frac) : bool =
let (na, da) = to_pair(a)
let (nb, db) = to_pair(b)
@@ -149,10 +146,7 @@ namespace Frac =
function mul(a : frac, b : frac) : frac = make_frac(num(a) * num(b), den(a) * den(b))
function div(a : frac, b : frac) : frac = switch(b)
Neg(n, d) => mul(a, Neg(d, n))
Zero => abort("Division by zero")
Pos(n, d) => mul(a, Pos(d, n))
function div(a : frac, b : frac) : frac = mul(a, inv(b))
/** `b` to the power of `e`
*/
@@ -174,10 +168,9 @@ namespace Frac =
function optimize(f : frac, loss : frac) : frac =
require(geq(loss, Zero), "negative loss optimize")
let s = sign(f)
mul(from_int(s), run_optimize(abs(f), abs(f), loss))
private function run_optimize(orig : frac, f : frac, loss : frac) : frac =
let (n, d) = to_pair(f)
let t = make_frac((n+1)/2, (d+1)/2)
if(gt(abs(sub(t, orig)), loss)) f
mul(from_int(s), run_optimize(abs(f), loss))
private function run_optimize(f : frac, loss : frac) : frac =
let t = make_frac((num(f) + 1) / 2, (den(f) + 1)/2)
if(gt(abs(sub(t, f)), loss)) f
elif (eq(t, f)) f
else run_optimize(orig, t, loss)
else run_optimize(t, loss)
+1 -1
View File
@@ -15,7 +15,7 @@
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
]}.
{relx, [{release, {aesophia, "4.3.0"},
{relx, [{release, {aesophia, "4.2.0"},
[aesophia, aebytecode, getopt]},
{dev_mode, true},
-2
View File
@@ -194,8 +194,6 @@ encode_expr({bytes, _, B}) ->
encode_expr({Lit, _, L}) when Lit == oracle_pubkey; Lit == oracle_query_id;
Lit == contract_pubkey; Lit == account_pubkey ->
aeser_api_encoder:encode(Lit, L);
encode_expr({app, _, {'-', _}, [{int, _, N}]}) ->
encode_expr({int, [], -N});
encode_expr({app, _, F, As}) ->
Ef = encode_expr(F),
Eas = encode_exprs(As),
+14 -36
View File
@@ -12,11 +12,7 @@
-module(aeso_ast_infer_types).
-export([ infer/1
, infer/2
, unfold_types_in_type/3
, pp_type/2
]).
-export([infer/1, infer/2, unfold_types_in_type/3]).
-type utype() :: {fun_t, aeso_syntax:ann(), named_args_t(), [utype()], utype()}
| {app_t, aeso_syntax:ann(), utype(), [utype()]}
@@ -2266,24 +2262,6 @@ mk_t_err(Pos, Msg) ->
mk_t_err(Pos, Msg, Ctxt) ->
aeso_errors:new(type_error, Pos, lists:flatten(Msg), lists:flatten(Ctxt)).
mk_error({higher_kinded_typevar, T}) ->
Msg = io_lib:format("Type ~s is a higher kinded type variable\n"
"(takes another type as an argument)\n", [pp(instantiate(T))]
),
mk_t_err(pos(T), Msg);
mk_error({wrong_type_arguments, X, ArityGiven, ArityReal}) ->
Msg = io_lib:format("Arity for ~s doesn't match. Expected ~p, got ~p\n"
, [pp(instantiate(X)), ArityReal, ArityGiven]
),
mk_t_err(pos(X), Msg);
mk_error({unnamed_map_update_with_default, Upd}) ->
Msg = "Invalid map update with default\n",
mk_t_err(pos(Upd), Msg);
mk_error({fundecl_must_have_funtype, _Ann, Id, Type}) ->
Msg = io_lib:format("~s at ~s was declared with an invalid type ~s.\n"
"Entrypoints and functions must have functional types"
, [pp(Id), pp_loc(Id), pp(instantiate(Type))]),
mk_t_err(pos(Id), Msg);
mk_error({cannot_unify, A, B, When}) ->
Msg = io_lib:format("Cannot unify ~s\n and ~s\n",
[pp(instantiate(A)), pp(instantiate(B))]),
@@ -2366,6 +2344,14 @@ mk_error({indexed_type_must_be_word, Type, Type1}) ->
Msg = io_lib:format("The indexed type ~s (at ~s) equals ~s which is not a word type\n",
[pp_type("", Type), pp_loc(Type), pp_type("", Type1)]),
mk_t_err(pos(Type), Msg);
mk_error({payload_type_must_be_string, Type, Type}) ->
Msg = io_lib:format("The payload type ~s (at ~s) should be string\n",
[pp_type("", Type), pp_loc(Type)]),
mk_t_err(pos(Type), Msg);
mk_error({payload_type_must_be_string, Type, Type1}) ->
Msg = io_lib:format("The payload type ~s (at ~s) equals ~s but it should be string\n",
[pp_type("", Type), pp_loc(Type), pp_type("", Type1)]),
mk_t_err(pos(Type), Msg);
mk_error({event_0_to_3_indexed_values, Constr}) ->
Msg = io_lib:format("The event constructor ~s (at ~s) has too many indexed values (max 3)\n",
[name(Constr), pp_loc(Constr)]),
@@ -2409,21 +2395,13 @@ mk_error({include, _, {string, Pos, Name}}) ->
[binary_to_list(Name), pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({namespace, _Pos, {con, Pos, Name}, _Def}) ->
Msg = io_lib:format("Nested namespaces are not allowed\nNamespace '~s' at ~s not defined at top level.\n",
[Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({contract, _Pos, {con, Pos, Name}, _Def}) ->
Msg = io_lib:format("Nested contracts are not allowed\nContract '~s' at ~s not defined at top level.\n",
[Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({type_decl, _, {id, Pos, Name}, _}) ->
Msg = io_lib:format("Empty type declarations are not supported\nType ~s at ~s lacks a definition\n",
[Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({letval, _Pos, {id, Pos, Name}, _Def}) ->
Msg = io_lib:format("Toplevel \"let\" definitions are not supported\nValue ~s at ~s could be replaced by 0-argument function\n",
Msg = io_lib:format("Nested namespace not allowed\nNamespace '~s' at ~s not defined at top level.\n",
[Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({repeated_arg, Fun, Arg}) ->
Msg = io_lib:format("Repeated argument ~s to function ~s (at ~s).\n",
[Arg, pp(Fun), pp_loc(Fun)]),
mk_t_err(pos(Fun), Msg);
mk_error({stateful_not_allowed, Id, Fun}) ->
Msg = io_lib:format("Cannot reference stateful function ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
[pp(Id), pp_loc(Id), pp(Fun)]),
+1
View File
@@ -291,6 +291,7 @@ decls_to_fcode(Env, Decls) ->
end, Env1, Decls).
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
decl_to_fcode(Env, {type_decl, _, _, _}) -> Env;
decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, _, Id, _}) ->
case is_no_code(Env) of
false -> fcode_error({missing_definition, Id});
+3 -5
View File
@@ -38,7 +38,6 @@
| pp_assembler
| pp_bytecode
| no_code
| keep_included
| {backend, aevm | fate}
| {include, {file_system, [string()]} |
{explicit_files, #{string() => binary()}}}
@@ -337,12 +336,12 @@ to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
try
{ok, aeso_vm_decode:from_fate(Type, aeb_fate_encoding:deserialize(Data))}
catch throw:cannot_translate_to_sophia ->
Type1 = prettypr:format(aeso_pretty:type(Type0)),
Type1 = prettypr:format(aeso_pretty:type(Type)),
Msg = io_lib:format("Cannot translate FATE value ~p\n of Sophia type ~s\n",
[aeb_fate_encoding:deserialize(Data), Type1]),
{error, [aeso_errors:new(data_error, Msg)]};
_:_ ->
Type1 = prettypr:format(aeso_pretty:type(Type0)),
Type1 = prettypr:format(aeso_pretty:type(Type)),
Msg = io_lib:format("Failed to decode binary as type ~s\n", [Type1]),
{error, [aeso_errors:new(data_error, Msg)]}
end
@@ -651,9 +650,8 @@ pp_fate_type(T) -> io_lib:format("~w", [T]).
%% -------------------------------------------------------------------
-spec sophia_type_to_typerep(string()) -> {error, bad_type} | {ok, aeb_aevm_data:type()}.
sophia_type_to_typerep(String) ->
Ast = aeso_parser:run_parser(aeso_parser:type(), String),
{ok, Ast} = aeso_parser:type(String),
try aeso_ast_to_icode:ast_typerep(Ast) of
Type -> {ok, Type}
catch _:_ -> {error, bad_type}
+20 -40
View File
@@ -3,33 +3,20 @@
%%% Description :
%%% Created : 1 Mar 2018 by Ulf Norell
-module(aeso_parser).
-compile({no_auto_import,[map_get/2]}).
-export([string/1,
string/2,
string/3,
auto_imports/1,
hash_include/2,
decl/0,
type/0,
body/0,
maybe_block/1,
run_parser/2,
run_parser/3]).
type/1]).
-include("aeso_parse_lib.hrl").
-import(aeso_parse_lib, [current_file/0, set_current_file/1]).
-type parse_result() :: aeso_syntax:ast() | {aeso_syntax:ast(), sets:set(include_hash())} | none().
-type parse_result() :: aeso_syntax:ast() | none().
-type include_hash() :: {string(), binary()}.
escape_errors({ok, Ok}) ->
Ok;
escape_errors({error, Err}) ->
parse_error(Err).
-spec string(string()) -> parse_result().
string(String) ->
string(String, sets:new(), []).
@@ -43,17 +30,21 @@ string(String, Opts) ->
-spec string(string(), sets:set(include_hash()), aeso_compiler:options()) -> parse_result().
string(String, Included, Opts) ->
AST = run_parser(file(), String, Opts),
case expand_includes(AST, Included, Opts) of
{ok, AST1} -> AST1;
{error, Err} -> parse_error(Err)
case parse_and_scan(file(), String, Opts) of
{ok, AST} ->
case expand_includes(AST, Included, Opts) of
{ok, AST1} -> AST1;
{error, Err} -> parse_error(Err)
end;
{error, Err} ->
parse_error(Err)
end.
run_parser(P, Inp) ->
escape_errors(parse_and_scan(P, Inp, [])).
run_parser(P, Inp, Opts) ->
escape_errors(parse_and_scan(P, Inp, Opts)).
type(String) ->
case parse_and_scan(type(), String, []) of
{ok, AST} -> {ok, AST};
{error, Err} -> {error, [mk_error(Err)]}
end.
parse_and_scan(P, S, Opts) ->
set_current_file(proplists:get_value(src_file, Opts, no_file)),
@@ -111,7 +102,7 @@ decl() ->
%% Function declarations
, ?RULE(modifiers(), fun_or_entry(), maybe_block(fundef_or_decl()), fun_block(_1, _2, _3))
, ?RULE(keyword('let'), valdef(), set_pos(get_pos(_1), _2))
, ?RULE(keyword('let'), valdef(),set_pos(get_pos(_1), _2))
])).
fun_block(Mods, Kind, [Decl]) ->
@@ -605,13 +596,8 @@ expand_includes(AST, Included, Opts) ->
|| File <- lists:usort(auto_imports(AST)) ] ++ AST,
expand_includes(AST1, Included, [], Opts).
expand_includes([], Included, Acc, Opts) ->
case lists:member(keep_included, Opts) of
false ->
{ok, lists:reverse(Acc)};
true ->
{ok, {lists:reverse(Acc), Included}}
end;
expand_includes([], _Included, Acc, _Opts) ->
{ok, lists:reverse(Acc)};
expand_includes([{include, Ann, {string, _SAnn, File}} | AST], Included, Acc, Opts) ->
case get_include_code(File, Ann, Opts) of
{ok, Code} ->
@@ -670,14 +656,8 @@ stdlib_options() ->
get_include_code(File, Ann, Opts) ->
case {read_file(File, Opts), read_file(File, stdlib_options())} of
{{ok, Bin}, {ok, _}} ->
case filename:basename(File) == File of
true -> { error
, fail( ann_pos(Ann)
, "Illegal redefinition of standard library " ++ binary_to_list(File))};
%% If a path is provided then the stdlib takes lower priority
false -> {ok, binary_to_list(Bin)}
end;
{{ok, _}, {ok,_ }} ->
fail(ann_pos(Ann), "Illegal redefinition of standard library " ++ File);
{_, {ok, Bin}} ->
{ok, binary_to_list(Bin)};
{{ok, Bin}, _} ->
+8 -13
View File
@@ -145,12 +145,8 @@ decl(D, Options) ->
with_options(Options, fun() -> decl(D) end).
-spec decl(aeso_syntax:decl()) -> doc().
decl({contract, Attrs, C, Ds}) ->
Mod = fun({Mod, true}) when Mod == payable ->
text(atom_to_list(Mod));
(_) -> empty() end,
block(follow( hsep(lists:map(Mod, Attrs) ++ [text("contract")])
, hsep(name(C), text("="))), decls(Ds));
decl({contract, _, C, Ds}) ->
block(follow(text("contract"), hsep(name(C), text("="))), decls(Ds));
decl({namespace, _, C, Ds}) ->
block(follow(text("namespace"), hsep(name(C), text("="))), decls(Ds));
decl({pragma, _, Pragma}) -> pragma(Pragma);
@@ -159,16 +155,13 @@ decl({type_def, _, T, Vars, Def}) ->
Kind = element(1, Def),
equals(typedecl(Kind, T, Vars), typedef(Def));
decl({fun_decl, Ann, F, T}) ->
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
text(atom_to_list(Mod));
(_) -> empty() end,
Fun = case aeso_syntax:get_ann(entrypoint, Ann, false) of
true -> text("entrypoint");
false -> text("function")
end,
hsep(lists:map(Mod, Ann) ++ [Fun, typed(name(F), T)]);
hsep(Fun, typed(name(F), T));
decl(D = {letfun, Attrs, _, _, _, _}) ->
Mod = fun({Mod, true}) when Mod == private; Mod == stateful; Mod == payable ->
Mod = fun({Mod, true}) when Mod == private; Mod == stateful ->
text(atom_to_list(Mod));
(_) -> empty() end,
Fun = case aeso_syntax:get_ann(entrypoint, Attrs, false) of
@@ -371,8 +364,7 @@ expr_p(_, {Type, _, Bin})
Type == oracle_query_id ->
text(binary_to_list(aeser_api_encoder:encode(Type, Bin)));
expr_p(_, {string, _, <<>>}) -> text("\"\"");
expr_p(_, {string, _, S}) ->
text(io_lib:format("\"~s\"", [binary_to_list(S)]));
expr_p(_, {string, _, S}) -> term(binary_to_list(S));
expr_p(_, {char, _, C}) ->
case C of
$' -> text("'\\''");
@@ -494,3 +486,6 @@ get_elifs(If = {'if', Ann, Cond, Then, Else}, Elifs) ->
end;
get_elifs(Else, Elifs) -> {lists:reverse(Elifs), {else, Else}}.
fmt(Fmt, Args) -> text(lists:flatten(io_lib:format(Fmt, Args))).
term(X) -> fmt("~p", [X]).
+4 -8
View File
@@ -37,24 +37,20 @@
-type decl() :: {contract, ann(), con(), [decl()]}
| {namespace, ann(), con(), [decl()]}
| {pragma, ann(), pragma()}
| {type_decl, ann(), id(), [tvar()]} % Only for error msgs
| {type_decl, ann(), id(), [tvar()]}
| {type_def, ann(), id(), [tvar()], typedef()}
| {fun_decl, ann(), id(), type()}
| {fun_clauses, ann(), id(), type(), [letbind()]}
| {block, ann(), [decl()]}
| letfun()
| letval(). % Only for error msgs
| letbind().
-type compiler_version() :: [non_neg_integer()].
-type pragma() :: {compiler, '==' | '<' | '>' | '=<' | '>=', compiler_version()}.
-type letval() :: {letval, ann(), pat(), expr()}.
-type letfun() :: {letfun, ann(), id(), [pat()], type(), expr()}.
-type letbind()
:: letfun()
| letval().
:: {letval, ann(), pat(), expr()}
| {letfun, ann(), id(), [pat()], type(), expr()}.
-type arg() :: {arg, ann(), id(), type()}.
+1
View File
@@ -45,6 +45,7 @@ fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) ->
%% decl()
{contract, _, _, Ds} -> Decl(Ds);
{namespace, _, _, Ds} -> Decl(Ds);
{type_decl, _, I, _} -> BindType(I);
{type_def, _, I, _, D} -> Plus(BindType(I), Decl(D));
{fun_decl, _, _, T} -> Type(T);
{letval, _, P, E} -> Scoped(BindExpr(P), Expr(E));
+1 -1
View File
@@ -1,6 +1,6 @@
{application, aesophia,
[{description, "Contract Language for aeternity"},
{vsn, "4.3.0"},
{vsn, "4.2.0"},
{registered, []},
{applications,
[kernel,
+5 -47
View File
@@ -375,15 +375,11 @@ failing_contracts() ->
" r.foo : (gas : int, value : int) => Remote.themap\n"
"against the expected type\n"
" (gas : int, value : int) => map(string, int)">>])
, ?TYPE_ERROR(not_toplevel_include,
[<<?Pos(2, 11)
"Include of 'included.aes' at line 2, column 11\nnot allowed, include only allowed at top level.">>])
, ?TYPE_ERROR(not_toplevel_namespace,
[<<?Pos(2, 13)
"Nested namespaces are not allowed\nNamespace 'Foo' at line 2, column 13 not defined at top level.">>])
, ?TYPE_ERROR(not_toplevel_contract,
[<<?Pos(2, 12)
"Nested contracts are not allowed\nContract 'Con' at line 2, column 12 not defined at top level.">>])
, ?TYPE_ERROR(bad_include_and_ns,
[<<?Pos(2, 11)
"Include of 'included.aes' at line 2, column 11\nnot allowed, include only allowed at top level.">>,
<<?Pos(3, 13)
"Nested namespace not allowed\nNamespace 'Foo' at line 3, column 13 not defined at top level.">>])
, ?TYPE_ERROR(bad_address_literals,
[<<?Pos(11, 5)
"Cannot unify address\n"
@@ -616,44 +612,6 @@ failing_contracts() ->
[<<?Pos(5, 28)
"Invalid call to contract entrypoint 'Foo.foo'.\n"
"It must be called as 'c.foo' for some c : Foo.">>])
, ?TYPE_ERROR(toplevel_let,
[<<?Pos(2, 7)
"Toplevel \"let\" definitions are not supported\n"
"Value this_is_illegal at line 2, column 7 could be replaced by 0-argument function">>])
, ?TYPE_ERROR(empty_typedecl,
[<<?Pos(2, 8)
"Empty type declarations are not supported\n"
"Type t at line 2, column 8 lacks a definition">>])
, ?TYPE_ERROR(higher_kinded_type,
[<<?Pos(2, 35)
"Type 'm is a higher kinded type variable\n"
"(takes another type as an argument)">>])
, ?TYPE_ERROR(bad_arity,
[<<?Pos(3, 20)
"Arity for id doesn't match. Expected 1, got 0">>,
<<?Pos(3, 25)
"Cannot unify int\n"
" and id\n"
"when checking the type of the expression at line 3, column 25\n"
" 123 : int\n"
"against the expected type\n"
" id">>,
<<?Pos(4, 20)
"Arity for id doesn't match. Expected 1, got 2">>,
<<?Pos(4, 35)
"Cannot unify int\n"
" and id(int, int)\n"
"when checking the type of the expression at line 4, column 35\n"
" 123 : int\n"
"against the expected type\n"
" id(int, int)">>])
, ?TYPE_ERROR(bad_unnamed_map_update_default,
[<<?Pos(4, 17)
"Invalid map update with default">>])
, ?TYPE_ERROR(non_functional_entrypoint,
[<<?Pos(2, 14)
"f at line 2, column 14 was declared with an invalid type int.\n"
"Entrypoints and functions must have functional types">>])
, ?TYPE_ERROR(bad_records,
[<<?Pos(3, 16)
"Mixed record fields and map keys in\n"
+2 -1
View File
@@ -58,7 +58,8 @@ contract Greeter =
let state = { greeting = "Hello" }
function setGreeting(greeting: string) =
let setGreeting =
(greeting: string) =>
state{ greeting = greeting }
+29 -63
View File
@@ -1,78 +1,44 @@
// Try to cover all syntactic constructs.
@compiler > 0
@compiler =< 10.1.1.1.1.1.2.3.4
contract AllSyntaxType =
type typeDecl /* bla */
type paramTypeDecl('a, 'b)
namespace Ns =
datatype d('a) = D | S(int) | M('a, list('a), int)
private function fff() = 123
stateful entrypoint
f (1, x) = (_) => x
payable contract AllSyntaxType =
/** Multi-
* line
* comment
*/
stateful function foo : _
entrypoint bar : int => (int * 'a)
function foo : _
contract AllSyntax =
datatype mickiewicz = Adam | Mickiewicz
record goethe('a, 'b) = {
johann : int,
wolfgang : 'a,
von : 'a * 'b * int,
goethe : unit
}
type dante = Ns.d(int)
type shakespeare('a) = goethe('a, 'a)
type typeDecl = int
type paramTypeDecl('a, 'b) = (('a, 'b) => 'b) => list('a) => 'b => 'b
type state = shakespeare(int)
record nestedRecord = { x : int }
record recordType = { z : nestedRecord, y : int }
datatype variantType('a) = None | Some('a)
entrypoint init() = {
johann = 1000,
wolfgang = -10,
von = (2 + 2, 0, List.sum([x | k <- [1,2,3]
, let l = k + 1
, if(l < 10)
, let f(x) = x + 100
, Adam <- [Adam, Mickiewicz]
, let x = f(l)
])),
goethe = () }
let valWithType : map(int, int) => option(int) = (m) => Map.get(m, 42)
let valNoType =
if(valWithType(Map.empty) == None)
print(42 mod 10 * 5 / 3)
function f() =
let kp = "nietzsche"
let p = "Пушкин"
let k(x : bytes(8)) : bytes(8) = Bytes.to_int(#fedcba9876543210)
function funWithType(x : int, y) : int * list(int) = (x, 0 :: [y] ++ [])
function funNoType() =
let foo = (x, y : bool) =>
if (! (y && x =< 0x0b || true)) [x]
else [11..20]
let setY(r : recordType) : unit = r{ y = 5 }
let setX(r : recordType, x : int) : recordType = r { z.x = x } // nested record update
let getY(r) = switch(r) {y = y} => y
switch (funWithType(1, -2))
(x, [y, z]) => bar({x = z, y = -y + - -z * (-1)})
(x, y :: _) => ()
let f : () => address = () => ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
if(Bits.test(Bits.all, 10))
abort("ohno")
if(true && false)
require(true, "ohyes")
elif(false || 2 == 2)
()
else
()
if(true) f(1,2)((1,2))
else switch(1::[1,2,3])
[] => 1
a::b => 123
1::2::3 => 123123
[2,3,4] => 1
_ => 13
1::[2] => 2138
put(state{johann = 1})
let m = {["foo"] = 19, /*hey wanna talk about inlined comments?*/ ["bar"] = 42}
let n = {}
m{ ["x" = 0] @ z = z + state.johann }
let hash : address = #01ab0fff11
let b = false
let qcon = Mod.Con
let str = "blabla\nfoo"
let chr = '"'
let sh : shakespeare(shakespeare(int)) =
{wolfgang = state}
sh{wolfgang.wolfgang = sh.wolfgang} // comment
-4
View File
@@ -1,4 +0,0 @@
contract C =
type id('a) = 'a
entrypoint f() : id = 123
entrypoint g() : id(int, int) = 123
@@ -1,4 +1,5 @@
contract BadCon =
contract Bad =
include "included.aes"
namespace Foo =
function foo() = 42
@@ -1,5 +0,0 @@
contract C =
entrypoint f() =
let z = 123
{}{ [1 = 0] = z + 1 }
2
-3
View File
@@ -1,3 +0,0 @@
contract C =
type t
entrypoint f() = 123
-3
View File
@@ -1,3 +0,0 @@
contract IWantToBelieve =
type stateT('s, 'm, 'a) = 's => 'm('a * 's)
entrypoint s() = 123
+2 -2
View File
@@ -15,7 +15,7 @@ contract MultiSig =
| OwnerRemoved (address) // of { .removedOwner : Address }
| ReqChanged (int) // of { .newReq : int }
function maxOwners() : int = 250
let maxOwners : int = 250
record state = { nRequired : int
, nOwners : int
@@ -68,7 +68,7 @@ contract MultiSig =
switch(check_pending(callhash()))
CheckFail(state') => { state = state' }
CheckOk(state') =>
if(state.nOwners >= maxOwners()) () /* TODO */
if(state.nOwners >= maxOwners) () /* TODO */
else
let nOwners' = state'.nOwners + 1
{ state = state' { owners = Map.insert(nOwners', newOwner, state'.owners)
@@ -1,5 +0,0 @@
contract C1 =
entrypoint f : int
contract C =
entrypoint f() = 123
-6
View File
@@ -1,6 +0,0 @@
namespace BadNs =
contract Con =
entrypoint e : () => int
contract Con =
entrypoint foo() = 43
-5
View File
@@ -1,5 +0,0 @@
namespace BadNs =
include "included.aes"
contract Con =
entrypoint foo() = 43
-3
View File
@@ -1,3 +0,0 @@
contract C =
let this_is_illegal = 2/0
entrypoint this_is_legal() = 2/0
+13
View File
@@ -1,3 +1,16 @@
/* Contract type */
contract VotingType =
type state
function init : list(string) => state
function giveRightToVote : address => unit
function delegate : address => unit
function vote : int => unit
function winnerName : unit => string
function currentTally : unit => list(string * int)
/* Contract implementation */
contract Voting =
// Types