Added list comprehensions and standard List, Option, Func, Pair, and Triple library #596
@ -448,8 +448,8 @@ expr_to_fcode(Env, _Type, {list_comp, _, Yield, []}) ->
|
|||||||
expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, {typed, {id, _, Arg}, _}, BindExpr}|Rest]}) ->
|
expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, {typed, {id, _, Arg}, _}, BindExpr}|Rest]}) ->
|
||||||
Env1 = bind_var(Env, Arg),
|
Env1 = bind_var(Env, Arg),
|
||||||
Bind = {lam, [Arg], expr_to_fcode(Env1, {list_comp, As, Yield, Rest})},
|
Bind = {lam, [Arg], expr_to_fcode(Env1, {list_comp, As, Yield, Rest})},
|
||||||
{funcall, resolve_fun(Env, ["List", "flat_map"]), [expr_to_fcode(Env, BindExpr), Bind]};
|
{def_u, FlatMap, _} = resolve_fun(Env, ["List", "flat_map"]),
|
||||||
|
{def, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]};
|
||||||
|
|
||||||
%% Conditionals
|
%% Conditionals
|
||||||
expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) ->
|
expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) ->
|
||||||
|
@ -505,7 +505,7 @@ parse_pattern(E = {bool, _, _}) -> E;
|
|||||||
parse_pattern(E = {bytes, _, _}) -> E;
|
parse_pattern(E = {bytes, _, _}) -> E;
|
||||||
parse_pattern(E = {string, _, _}) -> E;
|
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 patxstern", 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(aeso_syntax:field(aeso_syntax:expr())) -> aeso_parse_lib:parser(aeso_syntax:field(aeso_syntax:pat())).
|
||||||
parse_field_pattern({field, Ann, F, E}) ->
|
parse_field_pattern({field, Ann, F, E}) ->
|
||||||
@ -532,8 +532,10 @@ expand_includes(AST, Opts) ->
|
|||||||
|
|
||||||
expand_includes([], Acc, _Opts) ->
|
expand_includes([], Acc, _Opts) ->
|
||||||
{ok, lists:reverse(Acc)};
|
{ok, lists:reverse(Acc)};
|
||||||
expand_includes([{include, _, S = {string, _, File}} | AST], Acc, Opts) ->
|
expand_includes([{include, Ann, S = {string, _, File}} | AST], Acc, Opts) ->
|
||||||
case {read_file(File, Opts), maps:find(File, aeso_stdlib:stdlib())} of
|
case {read_file(File, Opts), maps:find(File, aeso_stdlib:stdlib())} of
|
||||||
|
{{ok, _}, {ok,_ }} ->
|
||||||
|
return_error(ann_pos(Ann), "Illegal redefinition of standard library " ++ File);
|
||||||
{_, {ok, Lib}} ->
|
{_, {ok, Lib}} ->
|
||||||
case string(Lib) of
|
case string(Lib) of
|
||||||
{ok, AST1} ->
|
{ok, AST1} ->
|
||||||
|
@ -21,10 +21,15 @@ stdlib() ->
|
|||||||
std_list() ->
|
std_list() ->
|
||||||
"
|
"
|
||||||
namespace List =
|
namespace List =
|
||||||
|
|
||||||
|
function empty(l) = switch(l)
|
||||||
|
[] => true
|
||||||
|
_ => false
|
||||||
|
|
||||||
function length(l) = length_(l, 0)
|
function length(l) = length_(l, 0)
|
||||||
private function length_(l, n) = switch(l)
|
private function length_(l, acc) = switch(l)
|
||||||
[] => n
|
[] => acc
|
||||||
_::t => length_(t, n + 1)
|
_::t => length_(t, acc + 1)
|
||||||
|
|
||||||
function foldr(cons, nil, l) = switch(l)
|
function foldr(cons, nil, l) = switch(l)
|
||||||
[] => nil
|
[] => nil
|
||||||
@ -34,8 +39,7 @@ namespace List =
|
|||||||
[] => acc
|
[] => acc
|
||||||
h::t => foldl(rcons, rcons(acc, h), t)
|
h::t => foldl(rcons, rcons(acc, h), t)
|
||||||
|
|
||||||
function reverse(l) =
|
function reverse(l) = foldl((lst, el) => el :: lst, [], l)
|
||||||
foldr((el, cont) => (lst) => cont(el::lst), (x) => x, l)([])
|
|
||||||
|
|
||||||
function map(f, l) = map_(f, l, [])
|
function map(f, l) = map_(f, l, [])
|
||||||
private function map_(f, l, acc) = switch(l)
|
private function map_(f, l, acc) = switch(l)
|
||||||
@ -45,4 +49,62 @@ namespace List =
|
|||||||
function flat_map(f, l) = switch(l)
|
function flat_map(f, l) = switch(l)
|
||||||
[] => []
|
[] => []
|
||||||
h::t => f(h) ++ flat_map(f, t)
|
h::t => f(h) ++ flat_map(f, t)
|
||||||
|
|
||||||
|
function concats(ll) = foldr((l1, l2) => l1 ++ l2, [], ll)
|
||||||
|
|
||||||
|
function filter(p, l) = filter_(p, l, [])
|
||||||
|
private function filter_(p, l, acc) = switch(l)
|
||||||
|
[] => reverse(acc)
|
||||||
|
h::t => filter_(p, t, if(p(h)) h::acc else acc)
|
||||||
|
|
||||||
|
function all(p, l) = foldl((prev, next) => prev && p(next), true, l)
|
||||||
|
function any(p, l) = foldl((prev, next) => prev || p(next), false, l)
|
||||||
|
|
||||||
|
/* Take `n` first elements */
|
||||||
|
function take(n, l) = if(n < 0) abort(\"Take negative number of elements\") else take_(n, l, [])
|
||||||
|
private function take_(n, l, acc) =
|
||||||
|
if(n == 0) reverse(acc)
|
||||||
|
else switch(l)
|
||||||
|
[] => reverse(acc)
|
||||||
|
h::t => take_(n-1, t, h::acc)
|
||||||
|
|
||||||
|
/* Drop `n` first elements */
|
||||||
|
function drop(n, l) =
|
||||||
|
if(n < 0) abort(\"Drop negative number of elements\")
|
||||||
|
elif (n == 0) l
|
||||||
|
else switch(l)
|
||||||
|
[] => []
|
||||||
|
h::t => drop(n-1, t)
|
||||||
|
|
||||||
|
/* Get the longest prefix of a list in which every element matches predicate `p` */
|
||||||
|
function take_while(p, l) = take_while_(p, l, [])
|
||||||
|
private function take_while_(p, l, acc) = switch(l)
|
||||||
|
[] => reverse(acc)
|
||||||
|
h::t => if(p(h)) take_while_(p, t, h::acc) else reverse(acc)
|
||||||
|
|
||||||
|
/* Drop elements from `l` until `p` holds */
|
||||||
|
function drop_while(p, l) = switch(l)
|
||||||
|
[] => []
|
||||||
|
h::t => if(p(h)) drop_while(p, t) else l
|
||||||
|
|
||||||
|
/* Zips two list by applying bimapping function on respective elements. Drops longer tail. */
|
||||||
|
function zip_with(f, l1, l2) = zip_with_(f, l1, l2, [])
|
||||||
|
private function zip_with_(f, l1, l2, acc) = switch ((l1, l2))
|
||||||
|
(h1::t1, h2::t2) => zip_with_(f, t1, t2, f(h1, h2)::acc)
|
||||||
|
_ => reverse(acc)
|
||||||
|
|
||||||
|
/* Zips two lists into list of pairs. Drops longer tail. */
|
||||||
|
function zip(l1, l2) = zip_with((a, b) => (a, b), l1, l2)
|
||||||
|
|
||||||
|
/* Splits list into two lists of elements that respectively match and don't match predicate `p` */
|
||||||
|
function partition(p, l) = partition_(p, l, [], [])
|
||||||
|
private function partition_(p, l, acc_t, acc_f) = switch(l)
|
||||||
|
[] => (reverse(acc_t), reverse(acc_f))
|
||||||
|
h::t => if(p(h)) partition_(p, t, h::acc_t, acc_f) else partition_(p, t, acc_t, h::acc_f)
|
||||||
|
|
||||||
|
// TODO: Improve?
|
||||||
|
function sort(lesser_cmp, l) = switch(l)
|
||||||
|
[] => []
|
||||||
|
h::t => switch (partition((x) => lesser_cmp(x, h), t))
|
||||||
|
(lesser, bigger) => sort(lesser_cmp, lesser) ++ h::sort(lesser_cmp, bigger)
|
||||||
".
|
".
|
||||||
|
Loading…
x
Reference in New Issue
Block a user