From d37ef8cec2cee5216c92c6c08ed4d56071a82108 Mon Sep 17 00:00:00 2001 From: Ulf Norell Date: Mon, 1 Apr 2019 16:04:59 +0200 Subject: [PATCH] Basic tuple patterns --- src/aeso_ast_to_fcode.erl | 18 ++++++++++++++++-- src/aeso_fcode_to_fate.erl | 23 +++++++++++++++++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index c596ed9..fe4addd 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -33,9 +33,10 @@ | {'if', fexpr(), fexpr(), fexpr()} | {switch, fexpr(), [falt()]}. --type fpat() :: {var, var_name()}. +-type fpat() :: {var, var_name()} + | {tuple, [fpat()]}. --type falt() :: {fpat(), fexpr()}. +-type falt() :: {'case', fpat(), fexpr()}. -type ftype() :: aeb_fate_data:fate_type_type(). @@ -151,6 +152,8 @@ type_to_fcode(Env, {app_t, T = {Id, _, _}, Types}) when Id == id; Id == qid -> lookup_type(Env, T, [type_to_fcode(Env, Type) || Type <- Types]); type_to_fcode(Env, T = {Id, _, _}) when Id == id; Id == qid -> lookup_type(Env, T, []); +type_to_fcode(Env, {tuple_t, _, Types}) -> + {tuple, [type_to_fcode(Env, T) || T <- Types]}; type_to_fcode(_Env, Type) -> {todo, Type}. @@ -179,6 +182,11 @@ expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) -> expr_to_fcode(Env, Then), expr_to_fcode(Env, Else)}; +%% Switch +expr_to_fcode(Env, _Type, {switch, _, Expr, Alts}) -> + {switch, expr_to_fcode(Env, Expr), + [ alt_to_fcode(Env, Alt) || Alt <- Alts ]}; + %% Blocks expr_to_fcode(Env, _Type, {block, _, Stmts}) -> stmts_to_fcode(Env, Stmts); @@ -193,6 +201,10 @@ expr_to_fcode(_Env, Type, Expr) -> binop_to_fcode(Op) when Op == '+'; Op == '-'; Op == '==' -> Op. +-spec alt_to_fcode(env(), aeso_syntax:alt()) -> falt(). +alt_to_fcode(Env, {'case', _, Pat, Expr}) -> + {'case', pat_to_fcode(Env, Pat), expr_to_fcode(Env, Expr)}. + -spec pat_to_fcode(env(), aeso_syntax:pattern()) -> fpat(). pat_to_fcode(Env, {typed, _, Pat, Type}) -> pat_to_fcode(Env, type_to_fcode(Env, Type), Pat); @@ -201,6 +213,8 @@ pat_to_fcode(Env, Pat) -> -spec pat_to_fcode(env(), ftype() | no_type, aeso_syntax:pattern()) -> fpat(). pat_to_fcode(_Env, _Type, {id, _, X}) -> {var, X}; +pat_to_fcode(Env, _Type, {tuple, _, Pats}) -> + {tuple, [ pat_to_fcode(Env, Pat) || Pat <- Pats ]}; pat_to_fcode(_Env, Type, Pat) -> {todo, Pat, ':', Type}. -spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr(). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 6b824da..f1b4b5b 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -56,7 +56,11 @@ compile(ICode, Options) -> SFuns = functions_to_scode(Functions, Options), SFuns1 = optimize_scode(SFuns, Options), BBFuns = to_basic_blocks(SFuns1, Options), - #{ functions => BBFuns }. + FateCode = #{ functions => BBFuns, + symbols => #{}, + annotations => #{} }, + debug(Options, "~s\n", [aeb_fate_asm:pp(FateCode)]), + FateCode. make_function_name(init) -> <<"init">>; make_function_name({entrypoint, Name}) -> Name; @@ -123,10 +127,22 @@ to_scode(Env, {switch, Expr, Alts}) -> to_scode(_Env, Icode) -> ?TODO(Icode). -alts_to_scode(Env, [{{var, X}, Body}]) -> +alts_to_scode(Env, [{'case', {var, X}, Body}]) -> {I, Env1} = bind_local(X, Env), [ aeb_fate_code:store({var, I}, {stack, 0}), to_scode(Env1, Body) ]; +alts_to_scode(Env, Alts = [{'case', {tuple, Pats}, Body}]) -> + Xs = lists:flatmap(fun({var, X}) -> [X]; (_) -> [] end, Pats), + case length(Xs) == length(Pats) of + false -> ?TODO(Alts); + true -> + {Is, Env1} = lists:foldl(fun(X, {Is, E}) -> {I, E1} = bind_local(X, E), {[I|Is], E1} end, + {[], Env}, Xs), + [ [[aeb_fate_code:dup(), + aeb_fate_code:element_op({var, X}, ?i(J), ?a)] + || {J, X} <- with_ixs(lists:reverse(Is))], + to_scode(Env1, Body) ] + end; alts_to_scode(_Env, Alts) -> ?TODO(Alts). @@ -201,12 +217,11 @@ to_basic_blocks(Funs, Options) -> bb(Name, Code ++ [aeb_fate_code:return()], Options)}} || {Name, {{Args, Res}, Code}} <- maps:to_list(Funs) ]). -bb(Name, Code, Options) -> +bb(_Name, Code, _Options) -> Blocks0 = blocks(Code), Blocks = optimize_blocks(Blocks0), Labels = maps:from_list([ {Ref, I} || {I, {Ref, _}} <- with_ixs(Blocks) ]), BBs = [ set_labels(Labels, B) || B <- Blocks ], - debug(Options, "Final code for ~s:\n ~p\n", [Name, BBs]), maps:from_list(BBs). %% -- Break up scode into basic blocks --