Added list comprehensions and standard List, Option, Func, Pair, and Triple library #596

Merged
zxq9 merged 19 commits from github/fork/radrow/list-comprehension into master 2019-08-14 20:53:58 +09:00
5 changed files with 66 additions and 43 deletions
Showing only changes of commit d170dd00eb - Show all commits

View File

@ -36,6 +36,7 @@
| pp_assembler | pp_assembler
| pp_bytecode | pp_bytecode
| no_code | no_code
| no_implicit_stdlib
| {backend, aevm | fate} | {backend, aevm | fate}
| {include, {file_system, [string()]} | | {include, {file_system, [string()]} |
{explicit_files, #{string() => binary()}}} {explicit_files, #{string() => binary()}}}

View File

@ -6,6 +6,7 @@
-export([string/1, -export([string/1,
string/2, string/2,
string/3,
type/1]). type/1]).
-include("aeso_parse_lib.hrl"). -include("aeso_parse_lib.hrl").
@ -16,13 +17,25 @@
-spec string(string()) -> parse_result(). -spec string(string()) -> parse_result().
string(String) -> string(String) ->
string(String, []). string(String, sets:new(), []).
-spec string(string(), aeso_compiler:options()) -> parse_result().
-spec string(string(), compiler:options()) -> parse_result().
string(String, Opts) -> string(String, Opts) ->
string(String, sets:new(), Opts).
-spec string(string(), sets:set(string()), aeso_compiler:options()) -> parse_result().
string(String, Included, Opts) ->
case parse_and_scan(file(), String, Opts) of case parse_and_scan(file(), String, Opts) of
{ok, AST} -> {ok, AST} ->
expand_includes(AST, Opts); STD = case lists:member(no_implicit_stdlib, Opts) of
false -> [{ include, [{src_file, File}, {origin, system}]
, {string, [{src_file, File}, {origin, system}], File}}
|| {File, _} <- aeso_stdlib:stdlib_list()
];
true -> []
end,
expand_includes(STD ++ AST, Included, Opts);
Err = {error, _} -> Err = {error, _} ->
Err Err
end. end.
@ -230,7 +243,7 @@ exprAtom() ->
, {bool, keyword(false), false} , {bool, keyword(false), false}
, ?LET_P(Fs, brace_list(?LAZY_P(field_assignment())), record(Fs)) , ?LET_P(Fs, brace_list(?LAZY_P(field_assignment())), record(Fs))
, {list, [], bracket_list(Expr)} , {list, [], bracket_list(Expr)}
, ?RULE(keyword('['), Expr, tok('|'), comma_sep(?LAZY_P(comprehension_bind())), tok(']'), list_comp_e(_1, _2, _4)) , ?RULE(keyword('['), Expr, token('|'), comma_sep(?LAZY_P(comprehension_bind())), tok(']'), list_comp_e(_1, _2, _4))
, ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4)) , ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4))
, ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2)) , ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2))
]) ])
@ -527,35 +540,40 @@ bad_expr_err(Reason, E) ->
prettypr:nest(2, aeso_pretty:expr(E))])). prettypr:nest(2, aeso_pretty:expr(E))])).
%% -- Helper functions ------------------------------------------------------- %% -- Helper functions -------------------------------------------------------
expand_includes(AST, Opts) -> expand_includes(AST, Included, Opts) ->
expand_includes(AST, [], Opts). expand_includes(AST, Included, [], Opts).
expand_includes([], Acc, _Opts) -> expand_includes([], _Included, Acc, _Opts) ->
{ok, lists:reverse(Acc)}; {ok, lists:reverse(Acc)};
expand_includes([{include, Ann, S = {string, _, File}} | AST], Acc, Opts) -> expand_includes([{include, Ann, S = {string, _, File}} | AST], Included, Acc, Opts) ->
case sets:is_element(File, Included) of
false ->
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}),
Included1 = sets:add_element(File, Included),
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,_ }} -> {{ok, _}, {ok,_ }} ->
return_error(ann_pos(Ann), "Illegal redefinition of standard library " ++ File); return_error(ann_pos(Ann), "Illegal redefinition of standard library " ++ File);
{_, {ok, Lib}} -> {_, {ok, Lib}} ->
case string(Lib) of case string(Lib, Included1, Opts1) of
{ok, AST1} -> {ok, AST1} ->
expand_includes(AST1 ++ AST, Acc, Opts); expand_includes(AST1 ++ AST, Included1, Acc, Opts);
Err = {error, _} -> Err = {error, _} ->
Err Err
end; end;
{{ok, Bin}, _} -> {{ok, Bin}, _} ->
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}), case string(binary_to_list(Bin), Included1, Opts1) of
case string(binary_to_list(Bin), Opts1) of
{ok, AST1} -> {ok, AST1} ->
expand_includes(AST1 ++ AST, Acc, Opts); expand_includes(AST1 ++ AST, Included1, Acc, Opts);
Err = {error, _} -> Err = {error, _} ->
Err Err
end; end;
{{error, _}, _} -> {_, _} ->
{error, {get_pos(S), include_error, File}} {error, {get_pos(S), include_error, File}}
end; end;
expand_includes([E | AST], Acc, Opts) -> true -> expand_includes(AST, Included, Acc, Opts)
expand_includes(AST, [E | Acc], Opts). end;
expand_includes([E | AST], Included, Acc, Opts) ->
expand_includes(AST, Included, [E | Acc], Opts).
read_file(File, Opts) -> read_file(File, Opts) ->
case proplists:get_value(include, Opts, {explicit_files, #{}}) of case proplists:get_value(include, Opts, {explicit_files, #{}}) of

View File

@ -10,14 +10,15 @@
-module(aeso_stdlib). -module(aeso_stdlib).
-export([stdlib/0]). -export([stdlib/0, stdlib_list/0]).
stdlib() -> stdlib() ->
maps:from_list( maps:from_list(stdlib_list()).
stdlib_list() ->
[ {<<"List.aes">>, std_list()} [ {<<"List.aes">>, std_list()}
%% , {<<"Func.aes">>, std_function()} %% , {<<"Func.aes">>, std_function()}
] ].
).
std_function() -> std_function() ->
" "
@ -51,7 +52,8 @@ namespace Func =
". ".
std_list() -> std_list() ->
" "namespace List =\n function flat_map() = 3\n".
x() ->"
namespace List = namespace List =
function empty(l) = switch(l) function empty(l) = switch(l)

View File

@ -9,7 +9,7 @@ simple_aci_test_() ->
test_contract(N) -> test_contract(N) ->
{Contract,MapACI,DecACI} = test_cases(N), {Contract,MapACI,DecACI} = test_cases(N),
{ok,JSON} = aeso_aci:contract_interface(json, Contract), {ok,JSON} = aeso_aci:contract_interface(json, Contract, [no_implicit_stdlib]),
?assertEqual([MapACI], JSON), ?assertEqual([MapACI], JSON),
?assertEqual({ok, DecACI}, aeso_aci:render_aci_json(JSON)). ?assertEqual({ok, DecACI}, aeso_aci:render_aci_json(JSON)).
@ -98,7 +98,7 @@ aci_test_contract(Name) ->
{ok, ContractStub} = aeso_aci:render_aci_json(JSON), {ok, ContractStub} = aeso_aci:render_aci_json(JSON),
io:format("STUB:\n~s\n", [ContractStub]), io:format("STUB:\n~s\n", [ContractStub]),
check_stub(ContractStub, [{src_file, Name}]), check_stub(ContractStub, [{src_file, Name}, no_implicit_stdlib]),
ok. ok.

View File

@ -15,7 +15,7 @@ simple_contracts_test_() ->
?assertMatch( ?assertMatch(
[{contract, _, {con, _, "Identity"}, [{contract, _, {con, _, "Identity"},
[{letfun, _, {id, _, "id"}, [{arg, _, {id, _, "x"}, {id, _, "_"}}], {id, _, "_"}, [{letfun, _, {id, _, "id"}, [{arg, _, {id, _, "x"}, {id, _, "_"}}], {id, _, "_"},
{id, _, "x"}}]}], parse_string(Text)), {id, _, "x"}}]}], parse_string(Text, [no_implicit_stdlib])),
ok ok
end}, end},
{"Operator precedence test.", {"Operator precedence test.",
@ -71,21 +71,23 @@ parse_contract(Name) ->
roundtrip_contract(Name) -> roundtrip_contract(Name) ->
round_trip(aeso_test_utils:read_contract(Name)). round_trip(aeso_test_utils:read_contract(Name)).
parse_string(Text) -> parse_string(Text) -> parse_string(Text, []).
case aeso_parser:string(Text) of
parse_string(Text, Opts) ->
case aeso_parser:string(Text, Opts) of
{ok, Contract} -> Contract; {ok, Contract} -> Contract;
Err -> error(Err) Err -> error(Err)
end. end.
parse_expr(Text) -> parse_expr(Text) ->
[{letval, _, _, _, Expr}] = [{letval, _, _, _, Expr}] =
parse_string("let _ = " ++ Text), parse_string("let _ = " ++ Text, [no_implicit_stdlib]),
Expr. Expr.
round_trip(Text) -> round_trip(Text) ->
Contract = parse_string(Text), Contract = parse_string(Text, [no_implicit_stdlib]),
Text1 = prettypr:format(aeso_pretty:decls(Contract)), Text1 = prettypr:format(aeso_pretty:decls(Contract)),
Contract1 = parse_string(Text1), Contract1 = parse_string(Text1, [no_implicit_stdlib]),
NoSrcLoc = remove_line_numbers(Contract), NoSrcLoc = remove_line_numbers(Contract),
NoSrcLoc1 = remove_line_numbers(Contract1), NoSrcLoc1 = remove_line_numbers(Contract1),
?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)). ?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)).