Fix error messages for some illegal constructions, fix absolute path includes #742

Merged
zxq9 merged 8 commits from github/fork/radrow/error-msgs into lima 2020-03-30 21:52:17 +09:00
8 changed files with 97 additions and 63 deletions
Showing only changes of commit f2c80af091 - Show all commits

View File

@ -2262,6 +2262,22 @@ mk_t_err(Pos, Msg) ->
mk_t_err(Pos, Msg, Ctxt) -> mk_t_err(Pos, Msg, Ctxt) ->
aeso_errors:new(type_error, Pos, lists:flatten(Msg), lists:flatten(Ctxt)). aeso_errors:new(type_error, Pos, lists:flatten(Msg), lists:flatten(Ctxt)).
mk_error({higher_kinded_typevar, T}) ->
Msg = io_lib:format("Type ~s is higher kinded (takes a type argument that takes\n"
"a type argument)\n", [pp(instantiate(T))]
),
mk_t_err(pos(T), Msg);
mk_error({wrong_type_arguments, X, ArityGiven, ArityReal}) ->
Msg = io_lib:format("Arity for ~s doesn't match. Expected ~p, got ~p\n"
, [pp(instantiate(X)), ArityReal, ArityGiven]
),
mk_t_err(pos(X), Msg);
mk_error({unnamed_map_update_with_default, Upd}) ->
Msg = "Invalid map update with default\n",
mk_t_err(pos(Upd), Msg);
mk_error({fundecl_must_have_funtype, _Ann, Id, _Type}) ->
Msg = io_lib:format("Function/entrypoint declaration must have a function type\n"),
mk_t_err(pos(Id), Msg);
mk_error({cannot_unify, A, B, When}) -> mk_error({cannot_unify, A, B, When}) ->
Msg = io_lib:format("Cannot unify ~s\n and ~s\n", Msg = io_lib:format("Cannot unify ~s\n and ~s\n",
[pp(instantiate(A)), pp(instantiate(B))]), [pp(instantiate(A)), pp(instantiate(B))]),
@ -2344,14 +2360,6 @@ mk_error({indexed_type_must_be_word, Type, Type1}) ->
Msg = io_lib:format("The indexed type ~s (at ~s) equals ~s which is not a word type\n", Msg = io_lib:format("The indexed type ~s (at ~s) equals ~s which is not a word type\n",
[pp_type("", Type), pp_loc(Type), pp_type("", Type1)]), [pp_type("", Type), pp_loc(Type), pp_type("", Type1)]),
mk_t_err(pos(Type), Msg); mk_t_err(pos(Type), Msg);
mk_error({payload_type_must_be_string, Type, Type}) ->
Msg = io_lib:format("The payload type ~s (at ~s) should be string\n",
[pp_type("", Type), pp_loc(Type)]),
mk_t_err(pos(Type), Msg);
mk_error({payload_type_must_be_string, Type, Type1}) ->
Msg = io_lib:format("The payload type ~s (at ~s) equals ~s but it should be string\n",
[pp_type("", Type), pp_loc(Type), pp_type("", Type1)]),
mk_t_err(pos(Type), Msg);
mk_error({event_0_to_3_indexed_values, Constr}) -> mk_error({event_0_to_3_indexed_values, Constr}) ->
Msg = io_lib:format("The event constructor ~s (at ~s) has too many indexed values (max 3)\n", Msg = io_lib:format("The event constructor ~s (at ~s) has too many indexed values (max 3)\n",
[name(Constr), pp_loc(Constr)]), [name(Constr), pp_loc(Constr)]),
@ -2398,10 +2406,14 @@ mk_error({namespace, _Pos, {con, Pos, Name}, _Def}) ->
Msg = io_lib:format("Nested namespace not allowed\nNamespace '~s' at ~s not defined at top level.\n", Msg = io_lib:format("Nested namespace not allowed\nNamespace '~s' at ~s not defined at top level.\n",
[Name, pp_loc(Pos)]), [Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg); mk_t_err(pos(Pos), Msg);
mk_error({repeated_arg, Fun, Arg}) -> mk_error({type_decl, _, {id, Pos, Name}, _}) ->
Msg = io_lib:format("Repeated argument ~s to function ~s (at ~s).\n", Msg = io_lib:format("Empty type declarations are not supported\nType ~s at ~s lacks a definition\n",
[Arg, pp(Fun), pp_loc(Fun)]), [Name, pp_loc(Pos)]),
mk_t_err(pos(Fun), Msg); mk_t_err(pos(Pos), Msg);
mk_error({letval, _Pos, {id, Pos, Name}, _Def}) ->
Msg = io_lib:format("Toplevel \"let\" definitions are not supported\nValue ~s at ~s could be replaced by 0-argument function\n",
[Name, pp_loc(Pos)]),
mk_t_err(pos(Pos), Msg);
mk_error({stateful_not_allowed, Id, Fun}) -> mk_error({stateful_not_allowed, Id, Fun}) ->
Msg = io_lib:format("Cannot reference stateful function ~s (at ~s)\nin the definition of non-stateful function ~s.\n", Msg = io_lib:format("Cannot reference stateful function ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
[pp(Id), pp_loc(Id), pp(Fun)]), [pp(Id), pp_loc(Id), pp(Fun)]),

View File

@ -291,7 +291,6 @@ decls_to_fcode(Env, Decls) ->
end, Env1, Decls). end, Env1, Decls).
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env(). -spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
decl_to_fcode(Env, {type_decl, _, _, _}) -> Env;
decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, _, Id, _}) -> decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, _, Id, _}) ->
case is_no_code(Env) of case is_no_code(Env) of
false -> fcode_error({missing_definition, Id}); false -> fcode_error({missing_definition, Id});

View File

@ -37,20 +37,24 @@
-type decl() :: {contract, ann(), con(), [decl()]} -type decl() :: {contract, ann(), con(), [decl()]}
| {namespace, ann(), con(), [decl()]} | {namespace, ann(), con(), [decl()]}
| {pragma, ann(), pragma()} | {pragma, ann(), pragma()}
| {type_decl, ann(), id(), [tvar()]} | {type_decl, ann(), id(), [tvar()]} % Only for error msgs
| {type_def, ann(), id(), [tvar()], typedef()} | {type_def, ann(), id(), [tvar()], typedef()}
| {fun_decl, ann(), id(), type()} | {fun_decl, ann(), id(), type()}
| {fun_clauses, ann(), id(), type(), [letbind()]} | {fun_clauses, ann(), id(), type(), [letbind()]}
| {block, ann(), [decl()]} | {block, ann(), [decl()]}
| letbind(). | letfun()
| letval(). % Only for error msgs
-type compiler_version() :: [non_neg_integer()]. -type compiler_version() :: [non_neg_integer()].
-type pragma() :: {compiler, '==' | '<' | '>' | '=<' | '>=', compiler_version()}. -type pragma() :: {compiler, '==' | '<' | '>' | '=<' | '>=', compiler_version()}.
-type letval() :: {letval, ann(), pat(), expr()}.
-type letfun() :: {letfun, ann(), id(), [pat()], type(), expr()}.
-type letbind() -type letbind()
:: {letval, ann(), pat(), expr()} :: letfun()
| {letfun, ann(), id(), [pat()], type(), expr()}. | letval().
-type arg() :: {arg, ann(), id(), type()}. -type arg() :: {arg, ann(), id(), type()}.

View File

@ -45,7 +45,6 @@ fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) ->
%% decl() %% decl()
{contract, _, _, Ds} -> Decl(Ds); {contract, _, _, Ds} -> Decl(Ds);
{namespace, _, _, Ds} -> Decl(Ds); {namespace, _, _, Ds} -> Decl(Ds);
{type_decl, _, I, _} -> BindType(I);
{type_def, _, I, _, D} -> Plus(BindType(I), Decl(D)); {type_def, _, I, _, D} -> Plus(BindType(I), Decl(D));
{fun_decl, _, _, T} -> Type(T); {fun_decl, _, _, T} -> Type(T);
{letval, _, P, E} -> Scoped(BindExpr(P), Expr(E)); {letval, _, P, E} -> Scoped(BindExpr(P), Expr(E));

View File

@ -58,8 +58,7 @@ contract Greeter =
let state = { greeting = "Hello" } let state = { greeting = "Hello" }
let setGreeting = function setGreeting(greeting: string) =
(greeting: string) =>
state{ greeting = greeting } state{ greeting = greeting }

View File

@ -1,44 +1,78 @@
// Try to cover all syntactic constructs. // Try to cover all syntactic constructs.
@compiler > 0
@compiler =< 10.1.1.1.1.1.2.3.4
contract AllSyntaxType = contract AllSyntaxType =
type typeDecl /* bla */
type paramTypeDecl('a, 'b)
/** Multi- /** Multi-
* line * line
* comment * comment
*/ */
function foo : _ function foo : _
entrypoint bar : int => (int * 'a)
/*
namespace Ns =
datatype d('a) = D | S(int) | M('a, list('a), int)
private function f() = 123
entrypoint
f : (int, 'a) => ('a * 'b) => 'a
f (1, x) = (_) => x
f (_, _) = (t : 'a * 'b) => switch(t)
(l, r) => l
_ => abort("tuple exploit")
contract AllSyntax = contract AllSyntax =
type typeDecl = int datatype mickiewicz = Adam | Mickiewicz
type paramTypeDecl('a, 'b) = (('a, 'b) => 'b) => list('a) => 'b => 'b record goethe('a, 'b) = {
johann : int,
wolfgang : 'a,
von : 'a * 'b * int,
goethe : unit
}
type dante = Ns.d(int)
type shakespeare('a) = goethe('a, 'a)
record nestedRecord = { x : int } type state = shakespeare(int)
record recordType = { z : nestedRecord, y : int }
datatype variantType('a) = None | Some('a)
let valWithType : map(int, int) => option(int) = (m) => Map.get(m, 42) entrypoint init() = {
let valNoType = johann = 1000,
if(valWithType(Map.empty) == None) wolfgang = -10,
print(42 mod 10 * 5 / 3) von = (2 + 2, 0, List.sum([x | k <- [1,2,3]
, let l = k + 1
, if(l < 10)
, let f(x) = x + 100
, Adam <- [Adam, Mickiewicz]
, let x = f(l)
])),
goethe = () }
function funWithType(x : int, y) : int * list(int) = (x, 0 :: [y] ++ []) function f() =
function funNoType() = let p = "Пушкин"
let foo = (x, y : bool) => let k(x : bytes(8)) : bytes(8) = Bytes.to_int(#fedcba9876543210)
if (! (y && x =< 0x0b || true)) [x]
else [11..20]
let setY(r : recordType) : unit = r{ y = 5 }
let setX(r : recordType, x : int) : recordType = r { z.x = x } // nested record update
let getY(r) = switch(r) {y = y} => y
switch (funWithType(1, -2))
(x, [y, z]) => bar({x = z, y = -y + - -z * (-1)})
(x, y :: _) => ()
let hash : address = #01ab0fff11 let f : () => address = () => ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt
let b = false if(Bits.test(Bits.all, 10))
let qcon = Mod.Con abort("ohno")
let str = "blabla\nfoo" if(true && false)
let chr = '"' require(true, "ohyes")
elif(false || 2 == 2)
()
else
()
if(true) f(1,2)((1,2))
else switch(1::[1,2,3])
[] => 1
a::b => 123
1::2::3 => 123123
[2,3,4] => 1
_ => 13
1::[2] => 2138
put(state{johann = 1})
let m = {["foo"] = 19, /*hey wanna talk about inlined comments?*/ ["bar"] = 42}
let n = {}
m{ ["x" = 0] @ z = z + state.johann }
let sh : shakespeare(shakespeare(int)) =
{wolfgang = state}
sh{wolfgang.wolfgang = sh.wolfgang} // comment
/*

View File

@ -15,7 +15,7 @@ contract MultiSig =
| OwnerRemoved (address) // of { .removedOwner : Address } | OwnerRemoved (address) // of { .removedOwner : Address }
| ReqChanged (int) // of { .newReq : int } | ReqChanged (int) // of { .newReq : int }
let maxOwners : int = 250 function maxOwners() : int = 250
record state = { nRequired : int record state = { nRequired : int
, nOwners : int , nOwners : int
@ -68,7 +68,7 @@ contract MultiSig =
switch(check_pending(callhash())) switch(check_pending(callhash()))
CheckFail(state') => { state = state' } CheckFail(state') => { state = state' }
CheckOk(state') => CheckOk(state') =>
if(state.nOwners >= maxOwners) () /* TODO */ if(state.nOwners >= maxOwners()) () /* TODO */
else else
let nOwners' = state'.nOwners + 1 let nOwners' = state'.nOwners + 1
{ state = state' { owners = Map.insert(nOwners', newOwner, state'.owners) { state = state' { owners = Map.insert(nOwners', newOwner, state'.owners)

View File

@ -1,16 +1,3 @@
/* Contract type */
contract VotingType =
type state
function init : list(string) => state
function giveRightToVote : address => unit
function delegate : address => unit
function vote : int => unit
function winnerName : unit => string
function currentTally : unit => list(string * int)
/* Contract implementation */
contract Voting = contract Voting =
// Types // Types