|
|
|
@@ -623,7 +623,9 @@ check_scope_name_clash(Env, Kind, Name) ->
|
|
|
|
|
-spec infer_contract_top(env(), main_contract | contract | namespace, [aeso_syntax:decl()], list(option())) ->
|
|
|
|
|
{env(), [aeso_syntax:decl()]}.
|
|
|
|
|
infer_contract_top(Env, Kind, Defs0, Options) ->
|
|
|
|
|
create_type_errors(),
|
|
|
|
|
Defs = desugar(Defs0),
|
|
|
|
|
destroy_and_report_type_errors(Env),
|
|
|
|
|
infer_contract(Env, Kind, Defs, Options).
|
|
|
|
|
|
|
|
|
|
%% infer_contract takes a proplist mapping global names to types, and
|
|
|
|
@@ -706,7 +708,12 @@ expose_internals(Defs, What) ->
|
|
|
|
|
main_contract -> [{entrypoint, true}|Ann]; % minor duplication
|
|
|
|
|
contract -> Ann
|
|
|
|
|
end,
|
|
|
|
|
setelement(2, Def, NewAnn)
|
|
|
|
|
Def1 = setelement(2, Def, NewAnn),
|
|
|
|
|
case Def1 of % fix inner clauses
|
|
|
|
|
{fun_clauses, Ans, Id, T, Clauses} ->
|
|
|
|
|
{fun_clauses, Ans, Id, T, expose_internals(Clauses, What)};
|
|
|
|
|
_ -> Def1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|| Def <- Defs
|
|
|
|
|
].
|
|
|
|
@@ -1550,6 +1557,15 @@ free_vars(L) when is_list(L) ->
|
|
|
|
|
[V || Elem <- L,
|
|
|
|
|
V <- free_vars(Elem)].
|
|
|
|
|
|
|
|
|
|
next_count() ->
|
|
|
|
|
V = case get(counter) of
|
|
|
|
|
undefined ->
|
|
|
|
|
0;
|
|
|
|
|
X -> X
|
|
|
|
|
end,
|
|
|
|
|
put(counter, V + 1),
|
|
|
|
|
V.
|
|
|
|
|
|
|
|
|
|
%% Clean up all the ets tables (in case of an exception)
|
|
|
|
|
|
|
|
|
|
ets_tables() ->
|
|
|
|
@@ -1595,6 +1611,18 @@ ets_tab2list(Name) ->
|
|
|
|
|
TabId = ets_tabid(Name),
|
|
|
|
|
ets:tab2list(TabId).
|
|
|
|
|
|
|
|
|
|
ets_insert_ordered(_, []) -> true;
|
|
|
|
|
ets_insert_ordered(Name, [H|T]) ->
|
|
|
|
|
ets_insert_ordered(Name, H),
|
|
|
|
|
ets_insert_ordered(Name, T);
|
|
|
|
|
ets_insert_ordered(Name, Object) ->
|
|
|
|
|
Count = next_count(),
|
|
|
|
|
TabId = ets_tabid(Name),
|
|
|
|
|
ets:insert(TabId, {Count, Object}).
|
|
|
|
|
|
|
|
|
|
ets_tab2list_ordered(Name) ->
|
|
|
|
|
[E || {_, E} <- ets_tab2list(Name)].
|
|
|
|
|
|
|
|
|
|
%% Options
|
|
|
|
|
|
|
|
|
|
create_options(Options) ->
|
|
|
|
@@ -1630,17 +1658,17 @@ destroy_and_report_unsolved_constraints(Env) ->
|
|
|
|
|
%% -- Named argument constraints --
|
|
|
|
|
|
|
|
|
|
create_named_argument_constraints() ->
|
|
|
|
|
ets_new(named_argument_constraints, [bag]).
|
|
|
|
|
ets_new(named_argument_constraints, [ordered_set]).
|
|
|
|
|
|
|
|
|
|
destroy_named_argument_constraints() ->
|
|
|
|
|
ets_delete(named_argument_constraints).
|
|
|
|
|
|
|
|
|
|
get_named_argument_constraints() ->
|
|
|
|
|
ets_tab2list(named_argument_constraints).
|
|
|
|
|
ets_tab2list_ordered(named_argument_constraints).
|
|
|
|
|
|
|
|
|
|
-spec add_named_argument_constraint(named_argument_constraint()) -> ok.
|
|
|
|
|
add_named_argument_constraint(Constraint) ->
|
|
|
|
|
ets_insert(named_argument_constraints, Constraint),
|
|
|
|
|
ets_insert_ordered(named_argument_constraints, Constraint),
|
|
|
|
|
ok.
|
|
|
|
|
|
|
|
|
|
solve_named_argument_constraints(Env) ->
|
|
|
|
@@ -1679,14 +1707,14 @@ destroy_and_report_unsolved_named_argument_constraints(Env) ->
|
|
|
|
|
| {add_bytes, aeso_syntax:ann(), concat | split, utype(), utype(), utype()}.
|
|
|
|
|
|
|
|
|
|
create_bytes_constraints() ->
|
|
|
|
|
ets_new(bytes_constraints, [bag]).
|
|
|
|
|
ets_new(bytes_constraints, [ordered_set]).
|
|
|
|
|
|
|
|
|
|
get_bytes_constraints() ->
|
|
|
|
|
ets_tab2list(bytes_constraints).
|
|
|
|
|
ets_tab2list_ordered(bytes_constraints).
|
|
|
|
|
|
|
|
|
|
-spec add_bytes_constraint(byte_constraint()) -> true.
|
|
|
|
|
add_bytes_constraint(Constraint) ->
|
|
|
|
|
ets_insert(bytes_constraints, Constraint).
|
|
|
|
|
ets_insert_ordered(bytes_constraints, Constraint).
|
|
|
|
|
|
|
|
|
|
solve_bytes_constraints(Env) ->
|
|
|
|
|
[ solve_bytes_constraint(Env, C) || C <- get_bytes_constraints() ],
|
|
|
|
@@ -1740,18 +1768,18 @@ check_bytes_constraint(Env, {add_bytes, Ann, Fun, A0, B0, C0}) ->
|
|
|
|
|
|
|
|
|
|
create_field_constraints() ->
|
|
|
|
|
%% A relation from uvars to constraints
|
|
|
|
|
ets_new(field_constraints, [bag]).
|
|
|
|
|
ets_new(field_constraints, [ordered_set]).
|
|
|
|
|
|
|
|
|
|
destroy_field_constraints() ->
|
|
|
|
|
ets_delete(field_constraints).
|
|
|
|
|
|
|
|
|
|
-spec constrain([field_constraint()]) -> true.
|
|
|
|
|
constrain(FieldConstraints) ->
|
|
|
|
|
ets_insert(field_constraints, FieldConstraints).
|
|
|
|
|
ets_insert_ordered(field_constraints, FieldConstraints).
|
|
|
|
|
|
|
|
|
|
-spec get_field_constraints() -> [field_constraint()].
|
|
|
|
|
get_field_constraints() ->
|
|
|
|
|
ets_tab2list(field_constraints).
|
|
|
|
|
ets_tab2list_ordered(field_constraints).
|
|
|
|
|
|
|
|
|
|
solve_field_constraints(Env) ->
|
|
|
|
|
FieldCs =
|
|
|
|
@@ -2581,6 +2609,9 @@ mk_error({mixed_record_and_map, Expr}) ->
|
|
|
|
|
Msg = io_lib:format("Mixed record fields and map keys in\n~s",
|
|
|
|
|
[pp_expr(" ", Expr)]),
|
|
|
|
|
mk_t_err(pos(Expr), Msg);
|
|
|
|
|
mk_error({conflicting_updates_for_field, Upd, Key}) ->
|
|
|
|
|
Msg = io_lib:format("Conflicting updates for field '~s'\n", [Key]),
|
|
|
|
|
mk_t_err(pos(Upd), Msg);
|
|
|
|
|
mk_error(Err) ->
|
|
|
|
|
Msg = io_lib:format("Unknown error: ~p\n", [Err]),
|
|
|
|
|
mk_t_err(pos(0, 0), Msg).
|
|
|
|
@@ -2803,7 +2834,7 @@ desugar_updates([Upd | Updates]) ->
|
|
|
|
|
{More, Updates1} = updates_key(Key, Updates),
|
|
|
|
|
%% Check conflicts
|
|
|
|
|
case length([ [] || [] <- [Rest | More] ]) of
|
|
|
|
|
N when N > 1 -> error({conflicting_updates_for_field, Upd, Key});
|
|
|
|
|
N when N > 1 -> type_error({conflicting_updates_for_field, Upd, Key});
|
|
|
|
|
_ -> ok
|
|
|
|
|
end,
|
|
|
|
|
[MakeField(lists:append([Rest | More])) | desugar_updates(Updates1)].
|
|
|
|
|