Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd6cde535e | |||
| b25339bb8f | |||
| cf793667ca | |||
| c54a0cec3d | |||
| bc47c25138 | |||
| 3b2ce63fa7 | |||
| 8b4a1aaf0d | |||
| c6e7db2381 | |||
| 4e60d019ca | |||
| b8002029cf | |||
| 4630f8a09b |
+2
-2
@@ -686,8 +686,8 @@ will emit one Event of each kind in the example.
|
||||
|
||||
```
|
||||
entrypoint emit_events() : () =
|
||||
Chain.event(TheFirstEvent(42))
|
||||
Chain.event(AnotherEvent(Contract.address, "This is not indexed"))
|
||||
Chain.event(Event1(42, 34, "foo"))
|
||||
Chain.event(Event2("This is not indexed", Contract.address))
|
||||
```
|
||||
|
||||
#### Argument order
|
||||
|
||||
@@ -569,12 +569,15 @@ Call.caller : address
|
||||
|
||||
The address of the entity (possibly another contract) calling the contract.
|
||||
|
||||
|
||||
### value
|
||||
```
|
||||
Call.value : int
|
||||
```
|
||||
|
||||
The amount of coins transferred to the contract in the call.
|
||||
The amount of coins transferred to the contract in the call. Note that in the `init`
|
||||
entrypoint this value will be always `0` – in order to get the contract creation value
|
||||
one needs to inspect `Contract.balance`.
|
||||
|
||||
|
||||
### gas
|
||||
|
||||
@@ -1557,6 +1557,15 @@ free_vars(L) when is_list(L) ->
|
||||
[V || Elem <- L,
|
||||
V <- free_vars(Elem)].
|
||||
|
||||
next_count() ->
|
||||
V = case get(counter) of
|
||||
undefined ->
|
||||
0;
|
||||
X -> X
|
||||
end,
|
||||
put(counter, V + 1),
|
||||
V.
|
||||
|
||||
%% Clean up all the ets tables (in case of an exception)
|
||||
|
||||
ets_tables() ->
|
||||
@@ -1602,6 +1611,18 @@ ets_tab2list(Name) ->
|
||||
TabId = ets_tabid(Name),
|
||||
ets:tab2list(TabId).
|
||||
|
||||
ets_insert_ordered(_, []) -> true;
|
||||
ets_insert_ordered(Name, [H|T]) ->
|
||||
ets_insert_ordered(Name, H),
|
||||
ets_insert_ordered(Name, T);
|
||||
ets_insert_ordered(Name, Object) ->
|
||||
Count = next_count(),
|
||||
TabId = ets_tabid(Name),
|
||||
ets:insert(TabId, {Count, Object}).
|
||||
|
||||
ets_tab2list_ordered(Name) ->
|
||||
[E || {_, E} <- ets_tab2list(Name)].
|
||||
|
||||
%% Options
|
||||
|
||||
create_options(Options) ->
|
||||
@@ -1637,17 +1658,17 @@ destroy_and_report_unsolved_constraints(Env) ->
|
||||
%% -- Named argument constraints --
|
||||
|
||||
create_named_argument_constraints() ->
|
||||
ets_new(named_argument_constraints, [bag]).
|
||||
ets_new(named_argument_constraints, [ordered_set]).
|
||||
|
||||
destroy_named_argument_constraints() ->
|
||||
ets_delete(named_argument_constraints).
|
||||
|
||||
get_named_argument_constraints() ->
|
||||
ets_tab2list(named_argument_constraints).
|
||||
ets_tab2list_ordered(named_argument_constraints).
|
||||
|
||||
-spec add_named_argument_constraint(named_argument_constraint()) -> ok.
|
||||
add_named_argument_constraint(Constraint) ->
|
||||
ets_insert(named_argument_constraints, Constraint),
|
||||
ets_insert_ordered(named_argument_constraints, Constraint),
|
||||
ok.
|
||||
|
||||
solve_named_argument_constraints(Env) ->
|
||||
@@ -1686,14 +1707,14 @@ destroy_and_report_unsolved_named_argument_constraints(Env) ->
|
||||
| {add_bytes, aeso_syntax:ann(), concat | split, utype(), utype(), utype()}.
|
||||
|
||||
create_bytes_constraints() ->
|
||||
ets_new(bytes_constraints, [bag]).
|
||||
ets_new(bytes_constraints, [ordered_set]).
|
||||
|
||||
get_bytes_constraints() ->
|
||||
ets_tab2list(bytes_constraints).
|
||||
ets_tab2list_ordered(bytes_constraints).
|
||||
|
||||
-spec add_bytes_constraint(byte_constraint()) -> true.
|
||||
add_bytes_constraint(Constraint) ->
|
||||
ets_insert(bytes_constraints, Constraint).
|
||||
ets_insert_ordered(bytes_constraints, Constraint).
|
||||
|
||||
solve_bytes_constraints(Env) ->
|
||||
[ solve_bytes_constraint(Env, C) || C <- get_bytes_constraints() ],
|
||||
@@ -1747,18 +1768,18 @@ check_bytes_constraint(Env, {add_bytes, Ann, Fun, A0, B0, C0}) ->
|
||||
|
||||
create_field_constraints() ->
|
||||
%% A relation from uvars to constraints
|
||||
ets_new(field_constraints, [bag]).
|
||||
ets_new(field_constraints, [ordered_set]).
|
||||
|
||||
destroy_field_constraints() ->
|
||||
ets_delete(field_constraints).
|
||||
|
||||
-spec constrain([field_constraint()]) -> true.
|
||||
constrain(FieldConstraints) ->
|
||||
ets_insert(field_constraints, FieldConstraints).
|
||||
ets_insert_ordered(field_constraints, FieldConstraints).
|
||||
|
||||
-spec get_field_constraints() -> [field_constraint()].
|
||||
get_field_constraints() ->
|
||||
ets_tab2list(field_constraints).
|
||||
ets_tab2list_ordered(field_constraints).
|
||||
|
||||
solve_field_constraints(Env) ->
|
||||
FieldCs =
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%%% @author Happi (Erik Stenman)
|
||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Compiler from Aeterinty Sophia language to the Aeternity VM, aevm.
|
||||
%%% Compiler from Aeterinty Sophia language to both AEVM and FATE VM.
|
||||
%%% @end
|
||||
%%% Created : 12 Dec 2017
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
+15
-7
@@ -74,25 +74,31 @@
|
||||
%% first argument. I.e. no backtracking to the second argument if the first
|
||||
%% fails.
|
||||
|
||||
trampoline({bounce, Cont}) when is_function(Cont, 0) ->
|
||||
trampoline(Cont());
|
||||
trampoline(Res) ->
|
||||
Res.
|
||||
-define(BOUNCE(X), {bounce, fun() -> X end}).
|
||||
|
||||
%% Apply a parser to its continuation. This compiles a parser to its low-level representation.
|
||||
-spec apply_p(parser(A), fun((A) -> parser1(B))) -> parser1(B).
|
||||
apply_p(?lazy(F), K) -> apply_p(F(), K);
|
||||
apply_p(?fail(Err), _) -> {fail, Err};
|
||||
apply_p(?choice([P | Ps]), K) -> lists:foldl(fun(Q, R) -> choice1(apply_p(Q, K), R) end,
|
||||
apply_p(P, K), Ps);
|
||||
apply_p(?choice([P | Ps]), K) -> lists:foldl(fun(Q, R) -> choice1(trampoline(apply_p(Q, K)), R) end,
|
||||
trampoline(apply_p(P, K)), Ps);
|
||||
apply_p(?bind(P, F), K) -> apply_p(P, fun(X) -> apply_p(F(X), K) end);
|
||||
apply_p(?right(P, Q), K) -> apply_p(P, fun(_) -> apply_p(Q, K) end);
|
||||
apply_p(?left(P, Q), K) -> apply_p(P, fun(X) -> apply_p(Q, fun(_) -> K(X) end) end);
|
||||
apply_p(?map(F, P), K) -> apply_p(P, fun(X) -> K(F(X)) end);
|
||||
apply_p(?layout, K) -> {layout, K, {fail, {expected, layout_block}}};
|
||||
apply_p(?tok(Atom), K) -> {tok_bind, #{Atom => K}};
|
||||
apply_p(?return(X), K) -> K(X);
|
||||
apply_p(?return(X), K) -> ?BOUNCE(K(X));
|
||||
apply_p([P | Q], K) -> apply_p(P, fun(H) -> apply_p(Q, fun(T) -> K([H | T]) end) end);
|
||||
apply_p(T, K) when is_tuple(T) -> apply_p(tuple_to_list(T), fun(Xs) -> K(list_to_tuple(Xs)) end);
|
||||
apply_p(M, K) when is_map(M) ->
|
||||
{Keys, Ps} = lists:unzip(maps:to_list(M)),
|
||||
apply_p(Ps, fun(Vals) -> K(maps:from_list(lists:zip(Keys, Vals))) end);
|
||||
apply_p(X, K) -> K(X).
|
||||
apply_p(X, K) -> ?BOUNCE(K(X)).
|
||||
|
||||
%% -- Primitive combinators --------------------------------------------------
|
||||
|
||||
@@ -160,7 +166,7 @@ layout() -> ?layout.
|
||||
%% @doc Parse a sequence of tokens using a parser. Fails if the parse is ambiguous.
|
||||
-spec parse(parser(A), tokens()) -> {ok, A} | {error, term()}.
|
||||
parse(P, S) ->
|
||||
case parse1(apply_p(P, fun(X) -> {return_plus, X, {fail, no_error}} end), S) of
|
||||
case parse1(trampoline(apply_p(P, fun(X) -> {return_plus, X, {fail, no_error}} end)), S) of
|
||||
{[], {Pos, Err}} -> {error, {add_current_file(Pos), parse_error, flatten_error(Err)}};
|
||||
{[A], _} -> {ok, A};
|
||||
{As, _} -> {error, {{1, 1}, ambiguous_parse, As}}
|
||||
@@ -241,7 +247,7 @@ col(T) when is_tuple(T) -> element(2, pos(T)).
|
||||
|
||||
%% If both parsers want the next token we grab it and merge the continuations.
|
||||
choice1({tok_bind, Map1}, {tok_bind, Map2}) ->
|
||||
{tok_bind, merge_with(fun(F, G) -> fun(T) -> choice1(F(T), G(T)) end end, Map1, Map2)};
|
||||
{tok_bind, merge_with(fun(F, G) -> fun(T) -> choice1(trampoline(F(T)), trampoline(G(T))) end end, Map1, Map2)};
|
||||
|
||||
%% If both parsers fail we combine the error messages. If only one fails we discard it.
|
||||
choice1({fail, E1}, {fail, E2}) -> {fail, add_error(E1, E2)};
|
||||
@@ -255,7 +261,7 @@ choice1(P, {return_plus, X, Q}) -> {return_plus, X, choice1(P, Q)};
|
||||
%% If both sides want a layout block we combine them. If only one side wants a layout block we
|
||||
%% will commit to a layout block is there is one.
|
||||
choice1({layout, F, P}, {layout, G, Q}) ->
|
||||
{layout, fun(N) -> choice1(F(N), G(N)) end, choice1(P, Q)};
|
||||
{layout, fun(N) -> choice1(trampoline(F(N)), trampoline(G(N))) end, choice1(P, Q)};
|
||||
choice1({layout, F, P}, Q) -> {layout, F, choice1(P, Q)};
|
||||
choice1(P, {layout, G, Q}) -> {layout, G, choice1(P, Q)}.
|
||||
|
||||
@@ -278,6 +284,8 @@ parse1(P, S) ->
|
||||
%% The main work horse. Returns a list of possible parses and an error message in case parsing
|
||||
%% fails.
|
||||
-spec parse1(parser1(A), #ts{}, [A], term()) -> {[A], error()}.
|
||||
parse1({bounce, F}, Ts, Acc, Err) ->
|
||||
parse1(F(), Ts, Acc, Err);
|
||||
parse1({tok_bind, Map}, Ts, Acc, Err) ->
|
||||
case next_token(Ts) of
|
||||
{T, Ts1} ->
|
||||
|
||||
Reference in New Issue
Block a user