diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 3eedc24..ecb00a5 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -175,11 +175,12 @@ builtins() -> {["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none}, {"timestamp", none}, {"block_height", none}, {"difficulty", none}, {"gas_limit", none}]}, - {["Contract"], [{"address", none}, {"balance", none}]}, + {["Contract"], [{"address", none}, {"balance", none}, {"creator", none}]}, {["Call"], [{"origin", none}, {"caller", none}, {"value", none}, {"gas_price", none}, {"gas_left", 0}]}, {["Oracle"], [{"register", 4}, {"query_fee", 1}, {"query", 5}, {"get_question", 2}, - {"respond", 4}, {"extend", 3}, {"get_answer", 2}]}, + {"respond", 4}, {"extend", 3}, {"get_answer", 2}, + {"check", 1}, {"check_query", 2}]}, {["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 4}, {"transfer", 4}, {"revoke", 3}]}, {["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2}, @@ -192,7 +193,7 @@ builtins() -> {"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]}, {["Bytes"], [{"to_int", 1}, {"to_str", 1}]}, {["Int"], [{"to_str", 1}]}, - {["Address"], [{"to_str", 1}]} + {["Address"], [{"to_str", 1}, {"is_oracle", 1}, {"is_contract", 1}]} ], maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}} || {NS, Funs} <- Scopes, @@ -475,7 +476,9 @@ expr_to_fcode(Env, Type, {app, _Ann, Fun = {typed, _, _, {fun_t, _, NamedArgsT, B =:= oracle_get_question; B =:= oracle_get_answer; B =:= oracle_respond; - B =:= oracle_register -> + B =:= oracle_register; + B =:= oracle_check; + B =:= oracle_check_query -> %% Get the type of the oracle from the args or the expression itself OType = get_oracle_type(B, Type, Args1), {oracle, QType, RType} = type_to_fcode(Env, OType), @@ -547,10 +550,12 @@ make_if(Cond, Then, Else) -> get_oracle_type(oracle_register, OType, _Args) -> OType; -get_oracle_type(oracle_query, _Type, [{typed, _,_Expr, OType}|_]) -> OType; -get_oracle_type(oracle_get_question, _Type, [{typed, _,_Expr, OType}|_]) -> OType; -get_oracle_type(oracle_get_answer, _Type, [{typed, _,_Expr, OType}|_]) -> OType; -get_oracle_type(oracle_respond, _Type, [_,{typed, _,_Expr, OType}|_]) -> OType. +get_oracle_type(oracle_query, _Type, [{typed, _, _Expr, OType} | _]) -> OType; +get_oracle_type(oracle_get_question, _Type, [{typed, _, _Expr, OType} | _]) -> OType; +get_oracle_type(oracle_get_answer, _Type, [{typed, _, _Expr, OType} | _]) -> OType; +get_oracle_type(oracle_check, _Type, [{typed, _, _Expr, OType}]) -> OType; +get_oracle_type(oracle_check_query, _Type, [{typed, _, _Expr, OType} | _]) -> OType; +get_oracle_type(oracle_respond, _Type, [_, {typed, _,_Expr, OType} | _]) -> OType. %% -- Pattern matching -- @@ -1261,6 +1266,8 @@ pp_punctuate(Sep, [X | Xs]) -> [pp_beside(X, Sep) | pp_punctuate(Sep, Xs)]. pp_par([]) -> prettypr:empty(); pp_par(Xs) -> prettypr:par(Xs). +pp_fexpr({lit, {typerep, T}}) -> + pp_ftype(T); pp_fexpr({lit, {Tag, Lit}}) -> aeso_pretty:expr({Tag, [], Lit}); pp_fexpr(nil) -> @@ -1321,18 +1328,23 @@ pp_fexpr({switch, Split}) -> pp_split(Split). pp_call(Fun, Args) -> pp_beside(Fun, pp_fexpr({tuple, Args})). +pp_call_t(Fun, Args) -> + pp_beside(pp_text(Fun), pp_ftype({tuple, Args})). + +-spec pp_ftype(ftype()) -> prettypr:doc(). pp_ftype(T) when is_atom(T) -> pp_text(T); pp_ftype(any) -> pp_text("_"); pp_ftype({tvar, X}) -> pp_text(X); -pp_ftype({bytes, N}) -> pp_text("bytes(" ++ integer_to_list(N) ++ ")"); +pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, {int, N}}]); +pp_ftype({oracle, Q, R}) -> pp_call_t("oracle", [Q, R]); pp_ftype({tuple, Ts}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_ftype(T) || T <- Ts]))); pp_ftype({list, T}) -> - pp_beside([pp_text("list("), pp_ftype(T), pp_text(")")]); + pp_call_t("list", [T]); pp_ftype({function, Args, Res}) -> pp_par([pp_ftype({tuple, Args}), pp_text("=>"), pp_ftype(Res)]); pp_ftype({map, Key, Val}) -> - pp_beside([pp_text("map"), pp_ftype({tuple, [Key, Val]})]); + pp_call_t("map", [Key, Val]); pp_ftype({variant, Cons}) -> pp_par( pp_punctuate(pp_text(" |"), diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index c79459e..a86ec74 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -104,6 +104,11 @@ Op =:= 'AUTH_TX_HASH' orelse Op =:= 'BYTES_TO_INT' orelse Op =:= 'BYTES_TO_STR' orelse + Op =:= 'ORACLE_CHECK' orelse + Op =:= 'ORACLE_CHECK_QUERY' orelse + Op =:= 'IS_ORACLE' orelse + Op =:= 'IS_CONTRACT' orelse + Op =:= 'CREATOR' orelse false)). -record(env, { contract, vars = [], locals = [], tailpos = true }). @@ -499,6 +504,8 @@ builtin_to_scode(_Env, contract_balance, []) -> [aeb_fate_ops:balance(?a)]; builtin_to_scode(_Env, contract_address, []) -> [aeb_fate_ops:address(?a)]; +builtin_to_scode(_Env, contract_creator, []) -> + [aeb_fate_ops:contract_creator(?a)]; builtin_to_scode(_Env, call_origin, []) -> [aeb_fate_ops:origin(?a)]; builtin_to_scode(_Env, call_caller, []) -> @@ -525,6 +532,14 @@ builtin_to_scode(Env, oracle_extend, [_Sign, _Oracle, _TTL] = Args) -> tuple(0)], Args); builtin_to_scode(Env, oracle_get_answer, [_Oracle, _QueryId, _QType, _RType] = Args) -> call_to_scode(Env, aeb_fate_ops:oracle_get_answer(?a, ?a, ?a, ?a, ?a), Args); +builtin_to_scode(Env, oracle_check, [_Oracle, _QType, _RType] = Args) -> + call_to_scode(Env, aeb_fate_ops:oracle_check(?a, ?a, ?a, ?a), Args); +builtin_to_scode(Env, oracle_check_query, [_Oracle, _Query, _QType, _RType] = Args) -> + call_to_scode(Env, aeb_fate_ops:oracle_check_query(?a, ?a, ?a, ?a, ?a), Args); +builtin_to_scode(Env, address_is_oracle, [_] = Args) -> + call_to_scode(Env, aeb_fate_ops:is_oracle(?a, ?a), Args); +builtin_to_scode(Env, address_is_contract, [_] = Args) -> + call_to_scode(Env, aeb_fate_ops:is_contract(?a, ?a), Args); builtin_to_scode(_Env, aens_resolve, [_, _] = _Args) -> ?TODO(fate_aens_resolve_instruction); builtin_to_scode(_Env, aens_preclaim, [_, _, _] = _Args) -> @@ -810,6 +825,11 @@ attributes(I) -> {'AUTH_TX_HASH', A} -> Pure(A, []); {'BYTES_TO_INT', A, B} -> Pure(A, [B]); {'BYTES_TO_STR', A, B} -> Pure(A, [B]); + {'ORACLE_CHECK', A, B, C, D} -> Impure(A, [B, C, D]); + {'ORACLE_CHECK_QUERY', A, B, C, D, E} -> Impure(A, [B, C, D, E]); + {'IS_ORACLE', A, B} -> Impure(A, [B]); + {'IS_CONTRACT', A, B} -> Impure(A, [B]); + {'CREATOR', A} -> Pure(A, []); {'ADDRESS', A} -> Pure(A, []); {'BALANCE', A} -> Impure(A, []); {'BALANCE_OTHER', A, B} -> Impure(A, [B]); diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index f2095df..f8b7d2f 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -120,10 +120,7 @@ compilable_contracts() -> ]. not_yet_compilable(fate) -> - ["events", %% events - "address_literals", %% oracle_query_id literals - "address_chain" %% Oracle.check_query - ]; + ["events"]; not_yet_compilable(aevm) -> []. %% Contracts that should produce type errors