diff --git a/rebar.config b/rebar.config index 7107fa8..771f30e 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"7f0d309"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"951db9f"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", diff --git a/rebar.lock b/rebar.lock index 54e0e24..477ca9f 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.1.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"7f0d3090d4dc6c4d5fca7645b0c21eb0e65ad208"}}, + {ref,"951db9f38412a1f798987403d24c512d82fec8c7"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 095d8ff..ea58d01 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -1468,7 +1468,7 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) -> _ -> NamedArgsVar = fresh_uvar(Ann), NamedArgs1 = [ infer_named_arg(Env, NamedArgsVar, Arg) || Arg <- NamedArgs ], - NewFun = {typed, _, _, FunType0} = infer_expr(Env, Fun), + NewFun0 = {typed, _, _, FunType0} = infer_expr(Env, Fun), NewArgs = [infer_expr(Env, A) || A <- Args], ArgTypes = [T || {typed, _, _, T} <- NewArgs], FunType = @@ -1491,6 +1491,7 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) -> end, GeneralResultType = fresh_uvar(Ann), ResultType = fresh_uvar(Ann), + NewFun1 = setelement(4, NewFun0, FunType), When = {infer_app, Fun, NamedArgs1, Args, FunType, ArgTypes}, unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When), add_named_argument_constraint( @@ -1499,7 +1500,7 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) -> general_type = GeneralResultType, specialized_type = ResultType, context = {check_return, App} }), - {typed, Ann, {app, Ann, NewFun, NamedArgs1 ++ NewArgs}, dereference(ResultType)} + {typed, Ann, {app, Ann, NewFun1, NamedArgs1 ++ NewArgs}, dereference(ResultType)} end; infer_expr(Env, {'if', Attrs, Cond, Then, Else}) -> NewCond = check_expr(Env, Cond, {id, Attrs, "bool"}), @@ -2381,6 +2382,9 @@ unify1(_Env, {bytes_t, _, Len}, {bytes_t, _, Len}, _When) -> unify1(Env, {if_t, _, {id, _, Id}, Then1, Else1}, {if_t, _, {id, _, Id}, Then2, Else2}, When) -> unify(Env, Then1, Then2, When) andalso unify(Env, Else1, Else2, When); + +unify1(Env, {fun_t, _, Named1, _, Result1}, {fun_t, _, Named2, var_args, Result2}, When) -> + error(unify_varargs); %% TODO unify1(Env, {fun_t, _, Named1, var_args, Result1}, {fun_t, _, Named2, Args2, Result2}, When) -> error(unify_varargs); %% TODO unify1(Env, {fun_t, _, Named1, Args1, Result1}, {fun_t, _, Named2, Args2, Result2}, When) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index e9b01f9..58f7a54 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -477,6 +477,8 @@ type_to_fcode(_Env, _Sub, {bytes_t, _, N}) -> {bytes, N}; type_to_fcode(_Env, Sub, {tvar, _, X}) -> maps:get(X, Sub, {tvar, X}); +type_to_fcode(_Env, _Sub, {fun_t, Ann, _, var_args, _}) -> + fcode_error({var_args_not_set, {id, Ann, "a very suspicious function"}}); type_to_fcode(Env, Sub, {fun_t, _, Named, Args, Res}) -> FNamed = [type_to_fcode(Env, Sub, Arg) || {named_arg_t, _, _, Arg, _} <- Named], FArgs = [type_to_fcode(Env, Sub, Arg) || Arg <- Args], @@ -692,17 +694,17 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> end; %% Function calls -expr_to_fcode(Env, _Type, {app, _, Fun = {typed, _, _, {fun_t, _, NamedArgsT, ArgsT, _}}, Args}) -> +expr_to_fcode(Env, _Type, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, _}}, Args}) -> Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of {builtin_u, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); {builtin_u, chain_clone, _Ar} -> case ArgsT of - [_Con|InitArgs] -> - FInitArgsT = {tuple, [type_to_fcode(Env, T) || T <- InitArgs]}, - builtin_to_fcode(state_layout(Env), chain_clone, [FInitArgsT|FArgs]); - [] -> error(wtf) %% FIXME + var_args -> fcode_error({var_args_not_set, FunE}); + _ -> + FInitArgsT = {typerep, {tuple, [type_to_fcode(Env, T) || T <- ArgsT]}}, + builtin_to_fcode(state_layout(Env), chain_clone, [{lit, FInitArgsT}|FArgs]) end; {builtin_u, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); {def_u, F, _Ar} -> {def, F, FArgs}; diff --git a/src/aeso_code_errors.erl b/src/aeso_code_errors.erl index bb2568d..6c05ff6 100644 --- a/src/aeso_code_errors.erl +++ b/src/aeso_code_errors.erl @@ -87,6 +87,10 @@ format({higher_order_state, {type_def, Ann, _, _, State}}) -> Msg = io_lib:format("Invalid state type\n~s\n", [pp_type(2, State)]), Cxt = "The state cannot contain functions in the AEVM. Use FATE if you need this.\n", mk_err(pos(Ann), Msg, Cxt); +format({var_args_not_set, Expr}) -> + mk_err( pos(Expr), "Could not deduce type of variadic arguments" + , "When compiling " ++ pp_expr(Expr) + ); format(Err) -> mk_err(aeso_errors:pos(0, 0), io_lib:format("Unknown error: ~p\n", [Err])). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 175c183..659fcab 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -559,17 +559,9 @@ builtin_to_scode(_Env, auth_tx, []) -> builtin_to_scode(Env, chain_bytecode_hash, [_Addr] = Args) -> call_to_scode(Env, aeb_fate_ops:bytecode_hash(?a), Args); builtin_to_scode(Env, chain_clone, - [InitArgs, _GasCap = {con,[0,1],0,[]}, Prot, Value, Contract | InitArgs]) -> - error(InitArgs), - TypeRep = xd, - call_to_scode(Env, aeb_fate_ops:clone(?a, ?a, ?a, ?a), - [Contract, TypeRep, Value, Prot | InitArgs] - ); -builtin_to_scode(Env, chain_clone, - [_GasCap = {con,[0,1],0,[]}, Prot, Value, Contract | InitArgs]) -> - TypeRep = xd, - call_to_scode(Env, aeb_fate_ops:clone(?a, ?a, ?a, ?a), - [Contract, TypeRep, Value, Prot | InitArgs] + [TypeRep, GasCap, Value, Prot, Contract | InitArgs]) -> + call_to_scode(Env, aeb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a), + [Contract, TypeRep, Value, GasCap, Prot | InitArgs] ); builtin_to_scode(Env, chain_create, [_GasCap = {con,[0,1],0,[]}, Prot, Value, Contract | InitArgs]) -> @@ -965,6 +957,10 @@ attributes(I) -> {'STR_TO_LOWER', A, B} -> Pure(A, [B]); {'CHAR_TO_INT', A, B} -> Pure(A, [B]); {'CHAR_FROM_INT', A, B} -> Pure(A, [B]); + {'CREATE', A, B, C} -> Impure(?a, [A, B, C]); + {'CLONE', A, B, C, D} -> Impure(?a, [A, B, C, D]); + {'CLONE_G', A, B, C, D, E} -> Impure(?a, [A, B, C, D, E]); + {'BYTECODE_HASH', A, B} -> Pure(A, [B]); {'ABORT', A} -> Impure(pc, A); {'EXIT', A} -> Impure(pc, A); 'NOP' -> Pure(none, []) @@ -1718,6 +1714,9 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL'; element(1, I) == 'CALL_R'; element(1, I) == 'CALL_GR'; element(1, I) == 'CALL_PGR'; + element(1, I) == 'CREATE'; + element(1, I) == 'CLONE'; + element(1, I) == 'CLONE_G'; element(1, I) == 'jumpif' -> split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) ->