Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d14a0025f2 | |||
| fe0c22851f | |||
| a50730155f | |||
| e9f717a17b | |||
| 97ff1aac23 | |||
| 1ee5a57924 | |||
| cf91a27fb2 | |||
| 83d06977f9 | |||
| 41e59506ba | |||
| 062309e578 | |||
| 6408969cd3 | |||
| 71a556ce81 | |||
| 256aadd575 | |||
| f27ba528d8 | |||
| 6fd39d4cb1 | |||
| 1ce95b32ac | |||
| 076d635dbe | |||
| 1d962f2001 | |||
| 1fbfe418c7 |
@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Standard library support. `ListInternal` can be included implicitly if list comprehensions are used.
|
||||
- Added the `[a..b]` language construct, returning the list of numbers between
|
||||
`a` and `b` (inclusive). Returns the empty list if `a` > `b`.
|
||||
### Changed
|
||||
|
||||
+29
-17
@@ -32,14 +32,16 @@ namespace List =
|
||||
[] => reverse(acc)
|
||||
h::t => find_indices_(p, t, n+1, if(p(h)) n::acc else acc)
|
||||
|
||||
function nth(n : int, l : list('a)) : option('a) = switch(l)
|
||||
[] => None
|
||||
h::t => if(n == 0) Some(h) else nth(n-1, t)
|
||||
function nth(n : int, l : list('a)) : option('a) =
|
||||
switch(l)
|
||||
[] => None
|
||||
h::t => if(n == 0) Some(h) else nth(n-1, t)
|
||||
|
||||
/* Unsafe version of `nth` */
|
||||
function get(n : int, l : list('a)) : 'a = switch(l)
|
||||
[] => abort("Out of index get")
|
||||
h::t => if(n == 0) h else get(n-1, t)
|
||||
function get(n : int, l : list('a)) : 'a =
|
||||
switch(l)
|
||||
[] => abort(if(n < 0) "Negative index get" else "Out of index get")
|
||||
h::t => if(n == 0) h else get(n-1, t)
|
||||
|
||||
|
||||
function length(l : list('a)) : int = length_(l, 0)
|
||||
@@ -48,6 +50,13 @@ namespace List =
|
||||
_::t => length_(t, acc + 1)
|
||||
|
||||
|
||||
function from_to(a : int, b : int) : list(int) = [a..b]
|
||||
|
||||
function from_to_step(a : int, b : int, s : int) : list(int) = from_to_step_(a, b, s, [])
|
||||
private function from_to_step_(a, b, s, acc) =
|
||||
if (a > b) reverse(acc) else from_to_step_(a + s, b, s, a :: acc)
|
||||
|
||||
|
||||
/* Unsafe. Replaces `n`th element of `l` with `e`. Crashes on over/underflow */
|
||||
function replace_at(n : int, e : 'a, l : list('a)) : list('a) =
|
||||
if(n<0) abort("insert_at underflow") else replace_at_(n, e, l, [])
|
||||
@@ -66,14 +75,17 @@ namespace List =
|
||||
[] => abort("insert_at overflow")
|
||||
h::t => insert_at_(n-1, e, t, h::acc)
|
||||
|
||||
function insert_by(f : (('a, 'a) => bool), x : 'a, l : list('a)) : list('a) =
|
||||
function insert_by(cmp : (('a, 'a) => bool), x : 'a, l : list('a)) : list('a) =
|
||||
insert_by_(cmp, x, l, [])
|
||||
private function insert_by_(cmp : (('a, 'a) => bool), x : 'a, l : list('a), acc : list('a)) : list('a) =
|
||||
switch(l)
|
||||
[] => [x]
|
||||
(e :: l') =>
|
||||
if(f(x, e))
|
||||
e :: insert_by(f, x, l')
|
||||
[] => reverse(x::acc)
|
||||
h::t =>
|
||||
if(cmp(x, h)) // x < h
|
||||
reverse(acc) ++ (x::l)
|
||||
else
|
||||
x :: l
|
||||
insert_by_(cmp, x, t, h::acc)
|
||||
|
||||
|
||||
function foldr(cons : ('a, 'b) => 'b, nil : 'b, l : list('a)) : 'b = switch(l)
|
||||
[] => nil
|
||||
@@ -83,12 +95,12 @@ namespace List =
|
||||
[] => acc
|
||||
h::t => foldl(rcons, rcons(acc, h), t)
|
||||
|
||||
function foreach(f : 'a => unit, l : list('a)) : unit =
|
||||
function foreach(l : list('a), f : 'a => unit) : unit =
|
||||
switch(l)
|
||||
[] => ()
|
||||
e :: l' =>
|
||||
[] => ()
|
||||
e::l' =>
|
||||
f(e)
|
||||
foreach(f, l')
|
||||
foreach(l', f)
|
||||
|
||||
function reverse(l : list('a)) : list('a) = foldl((lst, el) => el :: lst, [], l)
|
||||
|
||||
@@ -144,7 +156,7 @@ namespace List =
|
||||
h::t => if(p(h)) partition_(p, t, h::acc_t, acc_f) else partition_(p, t, acc_t, h::acc_f)
|
||||
|
||||
|
||||
function concats(ll : list(list('a))) : list('a) = foldr((l1, l2) => l1 ++ l2, [], ll)
|
||||
function flatten(ll : list(list('a))) : list('a) = foldr((l1, l2) => l1 ++ l2, [], ll)
|
||||
|
||||
function all(p : 'a => bool, l : list('a)) : bool = switch(l)
|
||||
[] => true
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Option =
|
||||
|
||||
function force(o : option('a)) : 'a = default(abort("Forced None value"), o)
|
||||
|
||||
function on_elem(f : 'a => unit, o : option('a)) : unit = match((), f, o)
|
||||
function on_elem(o : option('a), f : 'a => unit) : unit = match((), f, o)
|
||||
|
||||
function map(f : 'a => 'b, o : option('a)) : option('b) = switch(o)
|
||||
None => None
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"3f85375"}}}
|
||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"72b2a58"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
, {eblake2, "1.0.0"}
|
||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git",
|
||||
|
||||
+6
-2
@@ -1,17 +1,21 @@
|
||||
{"1.1.0",
|
||||
[{<<"aebytecode">>,
|
||||
{git,"https://github.com/aeternity/aebytecode.git",
|
||||
{ref,"3f85375cb2288083e442541d5b53f9705f22053a"}},
|
||||
{ref,"72b2a581d5a6d488a208331da88de1a488ac2da1"}},
|
||||
0},
|
||||
{<<"aeserialization">>,
|
||||
{git,"https://github.com/aeternity/aeserialization.git",
|
||||
{ref,"816bf994ffb5cee218c3f22dc5fea296c9e0882e"}},
|
||||
{ref,"47aaa8f5434b365c50a35bfd1490340b19241991"}},
|
||||
1},
|
||||
{<<"base58">>,
|
||||
{git,"https://github.com/aeternity/erl-base58.git",
|
||||
{ref,"60a335668a60328a29f9731b67c4a0e9e3d50ab6"}},
|
||||
2},
|
||||
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},0},
|
||||
{<<"enacl">>,
|
||||
{git,"https://github.com/aeternity/enacl.git",
|
||||
{ref,"26180f42c0b3a450905d2efd8bc7fd5fd9cece75"}},
|
||||
2},
|
||||
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0},
|
||||
{<<"jsx">>,
|
||||
{git,"https://github.com/talentdeficit/jsx.git",
|
||||
|
||||
@@ -443,10 +443,9 @@ global_env() ->
|
||||
{ funs = MkDefs(
|
||||
[{"resolve", Fun([String, String], option_t(Ann, A))},
|
||||
{"preclaim", SignFun([Address, Hash], Unit)},
|
||||
{"claim", SignFun([Address, String, Int], Unit)},
|
||||
{"claim", SignFun([Address, String, Int, Int], Unit)},
|
||||
{"transfer", SignFun([Address, Address, String], Unit)},
|
||||
{"revoke", SignFun([Address, String], Unit)},
|
||||
{"subname", SignFun([Address, String, Map(Q, Map(K, A))], Unit)}]) },
|
||||
{"revoke", SignFun([Address, String], Unit)}]) },
|
||||
|
||||
MapScope = #scope
|
||||
{ funs = MkDefs(
|
||||
@@ -1328,7 +1327,7 @@ infer_block(Env, _, [E], BlockType) ->
|
||||
[check_expr(Env, E, BlockType)];
|
||||
infer_block(Env, Attrs, [Def={letfun, Ann, _, _, _, _}|Rest], BlockType) ->
|
||||
{{Name, TypeSig}, LetFun} = infer_letfun(Env, Def),
|
||||
FunT = freshen_type(Ann, typesig_to_fun_t(TypeSig)),
|
||||
FunT = typesig_to_fun_t(TypeSig),
|
||||
NewE = bind_var({id, Ann, Name}, FunT, Env),
|
||||
[LetFun|infer_block(NewE, Attrs, Rest, BlockType)];
|
||||
infer_block(Env, _, [{letval, Attrs, Pattern, Type, E}|Rest], BlockType) ->
|
||||
|
||||
@@ -185,8 +185,8 @@ builtins() ->
|
||||
{["Oracle"], [{"register", 4}, {"query_fee", 1}, {"query", 5}, {"get_question", 2},
|
||||
{"respond", 4}, {"extend", 3}, {"get_answer", 2},
|
||||
{"check", 1}, {"check_query", 2}]},
|
||||
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 4}, {"transfer", 4},
|
||||
{"revoke", 3}, {"subname", 3}]},
|
||||
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4},
|
||||
{"revoke", 3}]},
|
||||
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
|
||||
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
|
||||
{["Crypto"], [{"verify_sig", 3}, {"verify_sig_secp256k1", 3},
|
||||
@@ -282,10 +282,13 @@ decl_to_fcode(Env = #{ functions := Funs }, {letfun, Ann, {id, _, Name}, Args, R
|
||||
Attrs = get_attributes(Ann),
|
||||
FName = lookup_fun(Env, qname(Env, Name)),
|
||||
FArgs = args_to_fcode(Env, Args),
|
||||
FRet = type_to_fcode(Env, Ret),
|
||||
FBody = expr_to_fcode(Env#{ vars => [X || {X, _} <- FArgs] }, Body),
|
||||
[ ensure_first_order_entrypoint(Ann, FArgs, FRet)
|
||||
|| aeso_syntax:get_ann(entrypoint, Ann, false) ],
|
||||
Def = #{ attrs => Attrs,
|
||||
args => FArgs,
|
||||
return => type_to_fcode(Env, Ret),
|
||||
return => FRet,
|
||||
body => FBody },
|
||||
NewFuns = Funs#{ FName => Def },
|
||||
Env#{ functions := NewFuns }.
|
||||
@@ -510,7 +513,7 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
|
||||
end;
|
||||
|
||||
%% Function calls
|
||||
expr_to_fcode(Env, Type, {app, _Ann, Fun = {typed, _, _, {fun_t, _, NamedArgsT, _, _}}, Args}) ->
|
||||
expr_to_fcode(Env, Type, {app, _, Fun = {typed, _, _, {fun_t, _, NamedArgsT, _, _}}, Args}) ->
|
||||
Args1 = get_named_args(NamedArgsT, Args),
|
||||
FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1],
|
||||
case expr_to_fcode(Env, Fun) of
|
||||
@@ -524,11 +527,13 @@ expr_to_fcode(Env, Type, {app, _Ann, Fun = {typed, _, _, {fun_t, _, NamedArgsT,
|
||||
%% 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),
|
||||
validate_oracle_type(aeso_syntax:get_ann(Fun), QType, RType),
|
||||
TypeArgs = [{lit, {typerep, QType}}, {lit, {typerep, RType}}],
|
||||
builtin_to_fcode(B, FArgs ++ TypeArgs);
|
||||
{builtin_u, B, _} when B =:= aens_resolve ->
|
||||
%% Get the type we are assuming the name resolves to
|
||||
AensType = type_to_fcode(Env, Type),
|
||||
validate_aens_resolve_type(aeso_syntax:get_ann(Fun), AensType),
|
||||
TypeArgs = [{lit, {typerep, AensType}}],
|
||||
builtin_to_fcode(B, FArgs ++ TypeArgs);
|
||||
{builtin_u, B, _Ar} -> builtin_to_fcode(B, FArgs);
|
||||
@@ -604,6 +609,46 @@ get_oracle_type(oracle_check, _Type, [{typed, _, _Expr, OType}]) ->
|
||||
get_oracle_type(oracle_check_query, _Type, [{typed, _, _Expr, OType} | _]) -> OType;
|
||||
get_oracle_type(oracle_respond, _Type, [_, {typed, _,_Expr, OType} | _]) -> OType.
|
||||
|
||||
validate_oracle_type(Ann, QType, RType) ->
|
||||
ensure_monomorphic(QType, {polymorphic_query_type, Ann, QType}),
|
||||
ensure_monomorphic(RType, {polymorphic_response_type, Ann, RType}),
|
||||
ensure_first_order(QType, {higher_order_query_type, Ann, QType}),
|
||||
ensure_first_order(RType, {higher_order_response_type, Ann, RType}),
|
||||
ok.
|
||||
|
||||
validate_aens_resolve_type(Ann, {variant, [[], [Type]]}) ->
|
||||
ensure_monomorphic(Type, {polymorphic_aens_resolve, Ann, Type}),
|
||||
ensure_first_order(Type, {higher_order_aens_resolve, Ann, Type}),
|
||||
ok.
|
||||
|
||||
ensure_first_order_entrypoint(Ann, Args, Ret) ->
|
||||
[ ensure_first_order(T, {higher_order_entrypoint_argument, Ann, X, T})
|
||||
|| {X, T} <- Args ],
|
||||
ensure_first_order(Ret, {higher_order_entrypoint_return, Ann, Ret}),
|
||||
ok.
|
||||
|
||||
ensure_monomorphic(Type, Err) ->
|
||||
case is_monomorphic(Type) of
|
||||
true -> ok;
|
||||
false -> fcode_error(Err)
|
||||
end.
|
||||
|
||||
ensure_first_order(Type, Err) ->
|
||||
case is_first_order(Type) of
|
||||
true -> ok;
|
||||
false -> fcode_error(Err)
|
||||
end.
|
||||
|
||||
is_monomorphic({tvar, _}) -> false;
|
||||
is_monomorphic(Ts) when is_list(Ts) -> lists:all(fun is_monomorphic/1, Ts);
|
||||
is_monomorphic(Tup) when is_tuple(Tup) -> is_monomorphic(tuple_to_list(Tup));
|
||||
is_monomorphic(_) -> true.
|
||||
|
||||
is_first_order({function, _, _}) -> false;
|
||||
is_first_order(Ts) when is_list(Ts) -> lists:all(fun is_first_order/1, Ts);
|
||||
is_first_order(Tup) when is_tuple(Tup) -> is_first_order(tuple_to_list(Tup));
|
||||
is_first_order(_) -> true.
|
||||
|
||||
%% -- Pattern matching --
|
||||
|
||||
-spec alts_to_fcode(env(), ftype(), var_name(), [aeso_syntax:alt()]) -> fsplit().
|
||||
|
||||
+48
-37
@@ -93,6 +93,8 @@ contract_to_icode([{letfun, Attrib, Name, Args, _What, Body={typed,_,_,T}}|Rest]
|
||||
FunAttrs = [ stateful || proplists:get_value(stateful, Attrib, false) ] ++
|
||||
[ payable || proplists:get_value(payable, Attrib, false) ] ++
|
||||
[ private || is_private(Attrib, Icode) ],
|
||||
[ check_entrypoint_type(Attrib, Name, Args, T)
|
||||
|| aeso_syntax:get_ann(entrypoint, Attrib, false) ],
|
||||
%% TODO: Handle types
|
||||
FunName = ast_id(Name),
|
||||
%% TODO: push funname to env
|
||||
@@ -105,7 +107,7 @@ contract_to_icode([{letfun, Attrib, Name, Args, _What, Body={typed,_,_,T}}|Rest]
|
||||
#{ state_type := StateType } = Icode,
|
||||
{#tuple{ cpts = [type_value(StateType), ast_body(Body, Icode)] },
|
||||
{tuple, [typerep, ast_typerep(T, Icode)]}};
|
||||
_ -> {ast_body(Body, Icode), ast_typerep(T, Icode)}
|
||||
_ -> {ast_body(Body, Icode), ast_typerep1(T, Icode)}
|
||||
end,
|
||||
QName = aeso_icode:qualify(Name, Icode),
|
||||
NewIcode = ast_fun_to_icode(ast_id(QName), FunAttrs, FunArgs, FunBody, TypeRep, Icode),
|
||||
@@ -121,7 +123,7 @@ ast_id({id, _, Id}) -> Id;
|
||||
ast_id({qid, _, Id}) -> Id.
|
||||
|
||||
ast_args([{arg, _, Name, Type}|Rest], Acc, Icode) ->
|
||||
ast_args(Rest, [{ast_id(Name), ast_type(Type, Icode)}| Acc], Icode);
|
||||
ast_args(Rest, [{ast_id(Name), ast_typerep1(Type, Icode)}| Acc], Icode);
|
||||
ast_args([], Acc, _Icode) -> lists:reverse(Acc).
|
||||
|
||||
ast_type(T, Icode) ->
|
||||
@@ -268,10 +270,10 @@ ast_body(?qid_app(["AENS", "preclaim"], Args, _, _), Icode) ->
|
||||
[word, word, sign_t()], {tuple, []});
|
||||
|
||||
ast_body(?qid_app(["AENS", "claim"], Args, _, _), Icode) ->
|
||||
{Sign, [Addr, Name, Salt]} = get_signature_arg(Args),
|
||||
{Sign, [Addr, Name, Salt, NameFee]} = get_signature_arg(Args),
|
||||
prim_call(?PRIM_CALL_AENS_CLAIM, #integer{value = 0},
|
||||
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Salt, Icode), ast_body(Sign, Icode)],
|
||||
[word, string, word, sign_t()], {tuple, []});
|
||||
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Salt, Icode), ast_body(NameFee, Icode), ast_body(Sign, Icode)],
|
||||
[word, string, word, word, sign_t()], {tuple, []});
|
||||
|
||||
ast_body(?qid_app(["AENS", "transfer"], Args, _, _), Icode) ->
|
||||
{Sign, [FromAddr, ToAddr, Name]} = get_signature_arg(Args),
|
||||
@@ -285,18 +287,11 @@ ast_body(?qid_app(["AENS", "revoke"], Args, _, _), Icode) ->
|
||||
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Sign, Icode)],
|
||||
[word, word, sign_t()], {tuple, []});
|
||||
|
||||
ast_body(?qid_app(["AENS", "subname"], Args, _, _), Icode) ->
|
||||
{Sign, [Addr, Name, Subnames]} = get_signature_arg(Args),
|
||||
prim_call(?PRIM_CALL_AENS_SUBNAME, #integer{value = 0},
|
||||
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Subnames, Icode), ast_body(Sign, Icode)],
|
||||
[word, word, word, sign_t()], {tuple, []});
|
||||
|
||||
ast_body({qid, _, ["AENS", "resolve"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.resolve'});
|
||||
ast_body({qid, _, ["AENS", "preclaim"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.preclaim'});
|
||||
ast_body({qid, _, ["AENS", "claim"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.claim'});
|
||||
ast_body({qid, _, ["AENS", "transfer"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.transfer'});
|
||||
ast_body({qid, _, ["AENS", "revoke"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.revoke'});
|
||||
ast_body({qid, _, ["AENS", "subname"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.subname'});
|
||||
|
||||
%% Maps
|
||||
|
||||
@@ -589,7 +584,7 @@ ast_body({block,As,[E|Rest]}, Icode) ->
|
||||
#switch{expr=ast_body(E, Icode),
|
||||
cases=[{#var_ref{name="_"},ast_body({block,As,Rest}, Icode)}]};
|
||||
ast_body({lam,_,Args,Body}, Icode) ->
|
||||
#lambda{args=[#arg{name = ast_id(P), type = ast_type(T, Icode)} || {arg,_,P,T} <- Args],
|
||||
#lambda{args=[#arg{name = ast_id(P), type = ast_typerep1(T, Icode)} || {arg,_,P,T} <- Args],
|
||||
body=ast_body(Body, Icode)};
|
||||
ast_body({typed,_,{record,Attrs,Fields},{record_t,DefFields}}, Icode) ->
|
||||
%% Compile as a tuple with the fields in the order they appear in the definition.
|
||||
@@ -724,6 +719,22 @@ map_upd(Key, Default, ValFun, Map = {typed, Ann, _, MapType}, Icode) ->
|
||||
Args = [ast_body(Map, Icode), ast_body(Key, Icode), ast_body(Default, Icode), ast_body(ValFun, Icode)],
|
||||
builtin_call(FunName, Args).
|
||||
|
||||
check_entrypoint_type(Ann, Name, Args, Ret) ->
|
||||
Check = fun(T, Err) ->
|
||||
case is_simple_type(T) of
|
||||
false -> gen_error(Err);
|
||||
true -> ok
|
||||
end end,
|
||||
[ Check(T, {entrypoint_argument_must_have_simple_type, Ann1, Name, X, T})
|
||||
|| {arg, Ann1, X, T} <- Args ],
|
||||
Check(Ret, {entrypoint_must_have_simple_return_type, Ann, Name, Ret}).
|
||||
|
||||
is_simple_type({tvar, _, _}) -> false;
|
||||
is_simple_type({fun_t, _, _, _, _}) -> false;
|
||||
is_simple_type(Ts) when is_list(Ts) -> lists:all(fun is_simple_type/1, Ts);
|
||||
is_simple_type(T) when is_tuple(T) -> is_simple_type(tuple_to_list(T));
|
||||
is_simple_type(_) -> true.
|
||||
|
||||
is_monomorphic({tvar, _, _}) -> false;
|
||||
is_monomorphic([H|T]) ->
|
||||
is_monomorphic(H) andalso is_monomorphic(T);
|
||||
@@ -764,42 +775,49 @@ make_type_def(Args, Def, Icode = #{ type_vars := TypeEnv }) ->
|
||||
TVars = [ X || {tvar, _, X} <- Args ],
|
||||
fun(Types) ->
|
||||
TypeEnv1 = maps:from_list(lists:zip(TVars, Types)),
|
||||
ast_typerep(Def, Icode#{ type_vars := maps:merge(TypeEnv, TypeEnv1) })
|
||||
ast_typerep1(Def, Icode#{ type_vars := maps:merge(TypeEnv, TypeEnv1) })
|
||||
end.
|
||||
|
||||
-spec ast_typerep(aeso_syntax:type()) -> aeb_aevm_data:type().
|
||||
ast_typerep(Type) -> ast_typerep(Type, aeso_icode:new([])).
|
||||
ast_typerep(Type) ->
|
||||
ast_typerep(Type, aeso_icode:new([])).
|
||||
|
||||
ast_typerep({id, _, Name}, Icode) ->
|
||||
ast_typerep(Type, Icode) ->
|
||||
case is_simple_type(Type) of
|
||||
false -> gen_error({not_a_simple_type, Type});
|
||||
true -> ast_typerep1(Type, Icode)
|
||||
end.
|
||||
|
||||
ast_typerep1({id, _, Name}, Icode) ->
|
||||
lookup_type_id(Name, [], Icode);
|
||||
ast_typerep({qid, _, Name}, Icode) ->
|
||||
ast_typerep1({qid, _, Name}, Icode) ->
|
||||
lookup_type_id(Name, [], Icode);
|
||||
ast_typerep({con, _, _}, _) ->
|
||||
ast_typerep1({con, _, _}, _) ->
|
||||
word; %% Contract type
|
||||
ast_typerep({bytes_t, _, Len}, _) ->
|
||||
ast_typerep1({bytes_t, _, Len}, _) ->
|
||||
bytes_t(Len);
|
||||
ast_typerep({app_t, _, {I, _, Name}, Args}, Icode) when I =:= id; I =:= qid ->
|
||||
ArgReps = [ ast_typerep(Arg, Icode) || Arg <- Args ],
|
||||
ast_typerep1({app_t, _, {I, _, Name}, Args}, Icode) when I =:= id; I =:= qid ->
|
||||
ArgReps = [ ast_typerep1(Arg, Icode) || Arg <- Args ],
|
||||
lookup_type_id(Name, ArgReps, Icode);
|
||||
ast_typerep({tvar,_,A}, #{ type_vars := TypeVars }) ->
|
||||
ast_typerep1({tvar,_,A}, #{ type_vars := TypeVars }) ->
|
||||
case maps:get(A, TypeVars, undefined) of
|
||||
undefined -> word; %% We serialize type variables just as addresses in the originating VM.
|
||||
Type -> Type
|
||||
end;
|
||||
ast_typerep({tuple_t,_,Cpts}, Icode) ->
|
||||
{tuple, [ast_typerep(C, Icode) || C<-Cpts]};
|
||||
ast_typerep({record_t,Fields}, Icode) ->
|
||||
ast_typerep1({tuple_t,_,Cpts}, Icode) ->
|
||||
{tuple, [ast_typerep1(C, Icode) || C<-Cpts]};
|
||||
ast_typerep1({record_t,Fields}, Icode) ->
|
||||
{tuple, [ begin
|
||||
{field_t, _, _, T} = Field,
|
||||
ast_typerep(T, Icode)
|
||||
ast_typerep1(T, Icode)
|
||||
end || Field <- Fields]};
|
||||
ast_typerep({fun_t,_,_,_,_}, _Icode) ->
|
||||
ast_typerep1({fun_t,_,_,_,_}, _Icode) ->
|
||||
function;
|
||||
ast_typerep({alias_t, T}, Icode) -> ast_typerep(T, Icode);
|
||||
ast_typerep({variant_t, Cons}, Icode) ->
|
||||
ast_typerep1({alias_t, T}, Icode) -> ast_typerep1(T, Icode);
|
||||
ast_typerep1({variant_t, Cons}, Icode) ->
|
||||
{variant, [ begin
|
||||
{constr_t, _, _, Args} = Con,
|
||||
[ ast_typerep(Arg, Icode) || Arg <- Args ]
|
||||
[ ast_typerep1(Arg, Icode) || Arg <- Args ]
|
||||
end || Con <- Cons ]}.
|
||||
|
||||
ttl_t(Icode) ->
|
||||
@@ -848,13 +866,6 @@ type_value({map, K, V}) ->
|
||||
#tuple{ cpts = [#integer{ value = ?TYPEREP_MAP_TAG },
|
||||
type_value(K), type_value(V)] }.
|
||||
|
||||
%% As abort is a built-in in the future it will be illegal to for
|
||||
%% users to define abort. For the time being strip away all user
|
||||
%% defined abort functions.
|
||||
|
||||
ast_fun_to_icode("abort", _Atts, _Args, _Body, _TypeRep, Icode) ->
|
||||
%% Strip away all user defined abort functions.
|
||||
Icode;
|
||||
ast_fun_to_icode(Name, Attrs, Args, Body, TypeRep, #{functions := Funs} = Icode) ->
|
||||
NewFuns = [{Name, Attrs, Args, Body, TypeRep}| Funs],
|
||||
aeso_icode:set_functions(NewFuns, Icode).
|
||||
|
||||
@@ -557,8 +557,8 @@ builtin_to_scode(Env, aens_resolve, [_Name, _Key, _Type] = Args) ->
|
||||
builtin_to_scode(Env, aens_preclaim, [_Sign, _Account, _Hash] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_claim(?a, ?a, ?a, ?a),
|
||||
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt, _NameFee] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_claim(?a, ?a, ?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
||||
@@ -566,8 +566,6 @@ builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = Args) ->
|
||||
builtin_to_scode(Env, aens_revoke, [_Sign, _Account, _Name] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_revoke(?a, ?a, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, aens_subname, [_Sign, _Account, _Name, _Subnames] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:aens_subname(?a, ?a, ?a, ?a), tuple(0)], Args);
|
||||
builtin_to_scode(_Env, auth_tx_hash, []) ->
|
||||
[aeb_fate_ops:auth_tx_hash(?a)].
|
||||
|
||||
@@ -885,11 +883,10 @@ attributes(I) ->
|
||||
{'ORACLE_QUERY_FEE', A, B} -> Impure(A, [B]);
|
||||
{'AENS_RESOLVE', A, B, C, D} -> Impure(A, [B, C, D]);
|
||||
{'AENS_PRECLAIM', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'AENS_CLAIM', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
||||
{'AENS_CLAIM', A, B, C, D, E} -> Impure(none, [A, B, C, D, E]);
|
||||
'AENS_UPDATE' -> Impure(none, []);%% TODO
|
||||
{'AENS_TRANSFER', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
||||
{'AENS_REVOKE', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'AENS_SUBNAME', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'ABORT', A} -> Impure(pc, A);
|
||||
{'EXIT', A} -> Impure(pc, A);
|
||||
'NOP' -> Pure(none, [])
|
||||
|
||||
+5
-17
@@ -1,8 +1,6 @@
|
||||
// AENS tests
|
||||
contract AENSTest =
|
||||
|
||||
type subnames = map(string, map(string, address))
|
||||
|
||||
// Name resolution
|
||||
|
||||
stateful entrypoint resolve_word(name : string, key : string) : option(address) =
|
||||
@@ -24,14 +22,16 @@ contract AENSTest =
|
||||
|
||||
stateful entrypoint claim(addr : address,
|
||||
name : string,
|
||||
salt : int) : unit =
|
||||
AENS.claim(addr, name, salt)
|
||||
salt : int,
|
||||
name_fee : int) : unit =
|
||||
AENS.claim(addr, name, salt, name_fee)
|
||||
|
||||
stateful entrypoint signedClaim(addr : address,
|
||||
name : string,
|
||||
salt : int,
|
||||
name_fee : int,
|
||||
sign : signature) : unit =
|
||||
AENS.claim(addr, name, salt, signature = sign)
|
||||
AENS.claim(addr, name, salt, name_fee, signature = sign)
|
||||
|
||||
// TODO: update() -- how to handle pointers?
|
||||
|
||||
@@ -54,15 +54,3 @@ contract AENSTest =
|
||||
name : string,
|
||||
sign : signature) : unit =
|
||||
AENS.revoke(owner, name, signature = sign)
|
||||
|
||||
|
||||
stateful entrypoint subname(owner : address,
|
||||
name : string,
|
||||
subnames : subnames) : unit =
|
||||
AENS.subname(owner, name, subnames)
|
||||
|
||||
stateful entrypoint signedSubname(owner : address,
|
||||
name : string,
|
||||
subnames : subnames,
|
||||
sign : signature) : unit =
|
||||
AENS.subname(owner, name, subnames, signature = sign)
|
||||
|
||||
@@ -50,7 +50,7 @@ contract ComplexTypes =
|
||||
entrypoint remote_pair(n : int, s : string) : int * string =
|
||||
state.worker.pair(gas = 10000, n, s)
|
||||
|
||||
entrypoint map(f, xs) =
|
||||
function map(f, xs) =
|
||||
switch(xs)
|
||||
[] => []
|
||||
x :: xs => f(x) :: map(f, xs)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
contract Fail =
|
||||
|
||||
entrypoint tttt() : bool * int =
|
||||
let f(x : 'a) : 'a = x
|
||||
(f(true), f(1))
|
||||
|
||||
@@ -91,10 +91,11 @@ contract Identity =
|
||||
// }
|
||||
// let id(x) = x
|
||||
// let main(xs) = map(double,xs)
|
||||
entrypoint z(f,x) = x
|
||||
function z(f,x) = x
|
||||
function s(n) = (f,x)=>f(n(f,x))
|
||||
function add(m,n) = (f,x)=>m(f,n(f,x))
|
||||
entrypoint main(_) =
|
||||
|
||||
entrypoint main() =
|
||||
let three=s(s(s(z)))
|
||||
add(three,three)
|
||||
(((i)=>i+1),0)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
contract TuplesMatch =
|
||||
|
||||
entrypoint tuplify3() = (t) => switch(t)
|
||||
function tuplify3() = (t) => switch(t)
|
||||
(x, y, z) => 3
|
||||
|
||||
entrypoint fst(p : int * string) =
|
||||
|
||||
Reference in New Issue
Block a user