Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd6cde535e | |||
| b25339bb8f | |||
| cf793667ca | |||
| c54a0cec3d | |||
| bc47c25138 | |||
| 3b2ce63fa7 | |||
| 8b4a1aaf0d | |||
| c6e7db2381 | |||
| b8002029cf | |||
| 4630f8a09b | |||
| 1a14602f36 |
+2
-2
@@ -686,8 +686,8 @@ will emit one Event of each kind in the example.
|
|||||||
|
|
||||||
```
|
```
|
||||||
entrypoint emit_events() : () =
|
entrypoint emit_events() : () =
|
||||||
Chain.event(TheFirstEvent(42))
|
Chain.event(Event1(42, 34, "foo"))
|
||||||
Chain.event(AnotherEvent(Contract.address, "This is not indexed"))
|
Chain.event(Event2("This is not indexed", Contract.address))
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Argument order
|
#### Argument order
|
||||||
|
|||||||
+13
-2
@@ -569,12 +569,15 @@ Call.caller : address
|
|||||||
|
|
||||||
The address of the entity (possibly another contract) calling the contract.
|
The address of the entity (possibly another contract) calling the contract.
|
||||||
|
|
||||||
|
|
||||||
### value
|
### value
|
||||||
```
|
```
|
||||||
Call.value : int
|
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
|
### gas
|
||||||
@@ -975,12 +978,20 @@ List.unzip(l : list('a * 'b)) : list('a) * list('b)
|
|||||||
Opposite to the `zip` operation. Takes a list of pairs and returns pair of lists with respective elements on same indices.
|
Opposite to the `zip` operation. Takes a list of pairs and returns pair of lists with respective elements on same indices.
|
||||||
|
|
||||||
|
|
||||||
|
### merge
|
||||||
|
```
|
||||||
|
List.merge(lesser_cmp : ('a, 'a) => bool, l1 : list('a), l2 : list('a)) : list('a)
|
||||||
|
```
|
||||||
|
|
||||||
|
Merges two sorted lists into a single sorted list. O(length(l1) + length(l2))
|
||||||
|
|
||||||
|
|
||||||
### sort
|
### sort
|
||||||
```
|
```
|
||||||
List.sort(lesser_cmp : ('a, 'a) => bool, l : list('a)) : list('a)
|
List.sort(lesser_cmp : ('a, 'a) => bool, l : list('a)) : list('a)
|
||||||
```
|
```
|
||||||
|
|
||||||
Sorts a list using given comparator. `lesser_cmp(x, y)` should return `true` iff `x < y`. If `lesser_cmp` is not transitive or there exists an element `x` such that `lesser_cmp(x, x)` or there exists a pair of elements `x` and `y` such that `lesser_cmp(x, y) && lesser_cmp(y, x)` then the result is undefined. Currently O(n^2).
|
Sorts a list using given comparator. `lesser_cmp(x, y)` should return `true` iff `x < y`. If `lesser_cmp` is not transitive or there exists an element `x` such that `lesser_cmp(x, x)` or there exists a pair of elements `x` and `y` such that `lesser_cmp(x, y) && lesser_cmp(y, x)` then the result is undefined. O(length(l) * log_2(length(l))).
|
||||||
|
|
||||||
|
|
||||||
### intersperse
|
### intersperse
|
||||||
|
|||||||
+61
-5
@@ -227,11 +227,67 @@ namespace List =
|
|||||||
(left, right)::t => unzip_(t, left::acc_l, right::acc_r)
|
(left, right)::t => unzip_(t, left::acc_l, right::acc_r)
|
||||||
|
|
||||||
|
|
||||||
// TODO: Improve?
|
/** Merges two sorted lists using `lt` comparator
|
||||||
function sort(lesser_cmp : ('a, 'a) => bool, l : list('a)) : list('a) = switch(l)
|
*/
|
||||||
[] => []
|
function
|
||||||
h::t => switch (partition((x) => lesser_cmp(x, h), t))
|
merge : (('a, 'a) => bool, list('a), list('a)) => list('a)
|
||||||
(lesser, bigger) => sort(lesser_cmp, lesser) ++ h::sort(lesser_cmp, bigger)
|
merge(lt, x::xs, y::ys) =
|
||||||
|
if(lt(x, y)) x::merge(lt, xs, y::ys)
|
||||||
|
else y::merge(lt, x::xs, ys)
|
||||||
|
merge(_, [], ys) = ys
|
||||||
|
merge(_, xs, []) = xs
|
||||||
|
|
||||||
|
|
||||||
|
/** Mergesort inspired by
|
||||||
|
* https://hackage.haskell.org/package/base-4.14.1.0/docs/src/Data.OldList.html#sort
|
||||||
|
*/
|
||||||
|
function
|
||||||
|
sort : (('a, 'a) => bool, list('a)) => list('a)
|
||||||
|
sort(_, []) = []
|
||||||
|
sort(lt, l) =
|
||||||
|
merge_all(lt, monotonic_subs(lt, l))
|
||||||
|
|
||||||
|
/** Splits list into compound increasing sublists
|
||||||
|
*/
|
||||||
|
private function
|
||||||
|
monotonic_subs : (('a, 'a) => bool, list('a)) => list(list('a))
|
||||||
|
monotonic_subs(lt, x::y::rest) =
|
||||||
|
if(lt(y, x)) desc(lt, y, [x], rest)
|
||||||
|
else asc(lt, y, [x], rest)
|
||||||
|
monotonic_subs(_, l) = [l]
|
||||||
|
|
||||||
|
/** Extracts the longest descending prefix and proceeds with monotonic split
|
||||||
|
*/
|
||||||
|
private function
|
||||||
|
desc : (('a, 'a) => bool, 'a, list('a), list('a)) => list(list('a))
|
||||||
|
desc(lt, x, acc, h::t) =
|
||||||
|
if(lt(x, h)) (x::acc) :: monotonic_subs(lt, h::t)
|
||||||
|
else desc(lt, h, x::acc, t)
|
||||||
|
desc(_, x, acc, []) = [x::acc]
|
||||||
|
|
||||||
|
/** Extracts the longest ascending prefix and proceeds with monotonic split
|
||||||
|
*/
|
||||||
|
private function
|
||||||
|
asc : (('a, 'a) => bool, 'a, list('a), list('a)) => list(list('a))
|
||||||
|
asc(lt, x, acc, h::t) =
|
||||||
|
if(lt(h, x)) List.reverse(x::acc) :: monotonic_subs(lt, h::t)
|
||||||
|
else asc(lt, h, x::acc, t)
|
||||||
|
asc(_, x, acc, []) = [List.reverse(x::acc)]
|
||||||
|
|
||||||
|
/** Merges list of sorted lists
|
||||||
|
*/
|
||||||
|
private function
|
||||||
|
merge_all : (('a, 'a) => bool, list(list('a))) => list('a)
|
||||||
|
merge_all(_, [part]) = part
|
||||||
|
merge_all(lt, parts) = merge_all(lt, merge_pairs(lt, parts))
|
||||||
|
|
||||||
|
/** Single round of `merge_all` – pairs of lists in a list of list
|
||||||
|
*/
|
||||||
|
private function
|
||||||
|
merge_pairs : (('a, 'a) => bool, list(list('a))) => list(list('a))
|
||||||
|
merge_pairs(lt, x::y::rest) = merge(lt, x, y) :: merge_pairs(lt, rest)
|
||||||
|
merge_pairs(_, l) = l
|
||||||
|
|
||||||
|
|
||||||
/** Puts `delim` between every two members of the list
|
/** Puts `delim` between every two members of the list
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
%%% @author Happi (Erik Stenman)
|
%%% @author Happi (Erik Stenman)
|
||||||
%%% @copyright (C) 2017, Aeternity Anstalt
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Compiler from Aeterinty Sophia language to the Aeternity VM, aevm.
|
%%% Compiler from Aeterinty Sophia language to both AEVM and FATE VM.
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 12 Dec 2017
|
%%% Created : 12 Dec 2017
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|||||||
+15
-7
@@ -74,25 +74,31 @@
|
|||||||
%% first argument. I.e. no backtracking to the second argument if the first
|
%% first argument. I.e. no backtracking to the second argument if the first
|
||||||
%% fails.
|
%% 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.
|
%% 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).
|
-spec apply_p(parser(A), fun((A) -> parser1(B))) -> parser1(B).
|
||||||
apply_p(?lazy(F), K) -> apply_p(F(), K);
|
apply_p(?lazy(F), K) -> apply_p(F(), K);
|
||||||
apply_p(?fail(Err), _) -> {fail, Err};
|
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(?choice([P | Ps]), K) -> lists:foldl(fun(Q, R) -> choice1(trampoline(apply_p(Q, K)), R) end,
|
||||||
apply_p(P, K), Ps);
|
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(?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(?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(?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(?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(?layout, K) -> {layout, K, {fail, {expected, layout_block}}};
|
||||||
apply_p(?tok(Atom), K) -> {tok_bind, #{Atom => K}};
|
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([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(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) ->
|
apply_p(M, K) when is_map(M) ->
|
||||||
{Keys, Ps} = lists:unzip(maps:to_list(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(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 --------------------------------------------------
|
%% -- Primitive combinators --------------------------------------------------
|
||||||
|
|
||||||
@@ -160,7 +166,7 @@ layout() -> ?layout.
|
|||||||
%% @doc Parse a sequence of tokens using a parser. Fails if the parse is ambiguous.
|
%% @doc Parse a sequence of tokens using a parser. Fails if the parse is ambiguous.
|
||||||
-spec parse(parser(A), tokens()) -> {ok, A} | {error, term()}.
|
-spec parse(parser(A), tokens()) -> {ok, A} | {error, term()}.
|
||||||
parse(P, S) ->
|
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)}};
|
{[], {Pos, Err}} -> {error, {add_current_file(Pos), parse_error, flatten_error(Err)}};
|
||||||
{[A], _} -> {ok, A};
|
{[A], _} -> {ok, A};
|
||||||
{As, _} -> {error, {{1, 1}, ambiguous_parse, As}}
|
{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.
|
%% If both parsers want the next token we grab it and merge the continuations.
|
||||||
choice1({tok_bind, Map1}, {tok_bind, Map2}) ->
|
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.
|
%% 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)};
|
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
|
%% 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.
|
%% will commit to a layout block is there is one.
|
||||||
choice1({layout, F, P}, {layout, G, Q}) ->
|
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({layout, F, P}, Q) -> {layout, F, choice1(P, Q)};
|
||||||
choice1(P, {layout, G, Q}) -> {layout, G, 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
|
%% The main work horse. Returns a list of possible parses and an error message in case parsing
|
||||||
%% fails.
|
%% fails.
|
||||||
-spec parse1(parser1(A), #ts{}, [A], term()) -> {[A], error()}.
|
-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) ->
|
parse1({tok_bind, Map}, Ts, Acc, Err) ->
|
||||||
case next_token(Ts) of
|
case next_token(Ts) of
|
||||||
{T, Ts1} ->
|
{T, Ts1} ->
|
||||||
|
|||||||
Reference in New Issue
Block a user