Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion doc/md/examples/grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<implicit> ::=
'implicit'

<id_wild> ::=
'_'

<typ_obj_sort> ::=
'object'
'actor'
Expand Down Expand Up @@ -70,8 +73,8 @@
<typ> 'or' <typ>

<typ_item> ::=
<implicit> <typ>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has this disappeared?

<id> ':' <typ>
<id_wild> ':' <typ>
<typ>

<typ_args> ::=
Expand Down
4 changes: 4 additions & 0 deletions src/mo_frontend/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ seplist1(X, SEP) :
%inline implicit :
| IMPLICIT { "implicit" @@ at $sloc }

%inline id_wild :
| UNDERSCORE { "_" @@ at $sloc }

%inline typ_id :
| id=ID { id @= at $sloc }

Expand Down Expand Up @@ -486,6 +489,7 @@ typ :

typ_item :
| i=id COLON t=typ { Some i, t }
| i=id_wild COLON t=typ { Some i, t }
| t=typ { None, t }

typ_args :
Expand Down
22 changes: 15 additions & 7 deletions src/mo_frontend/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2454,16 +2454,24 @@ and infer_callee env exp =
infer_exp_promote env exp, None

and insert_holes at ts es =
let mk_hole pos hole_id =
let hole_sort = if hole_id = "" then Anon pos else Named hole_id in
{it = HoleE (hole_sort, ref {it = PrimE "hole"; at; note=empty_typ_note });
at;
note = empty_typ_note }
in
let rec go n ts es =
match (ts, es) with
| (T.Named ("implicit", T.Named (arg_name, t))) :: ts1, es ->
(mk_hole n arg_name) :: go (n + 1) ts1 es
| (T.Named ("implicit", t)) :: ts1, es ->
{it = HoleE (Anon n, ref {it = PrimE "hole"; at; note=empty_typ_note });
at;
note = empty_typ_note } :: go (n+1) ts1 es
| (T.Named (arg_name, (T.Named ("implicit", t)))) :: ts1, es ->
{it = HoleE (Named arg_name, ref {it = PrimE "hole"; at; note=empty_typ_note });
at;
note = empty_typ_note } :: go (n+1) ts1 es
(mk_hole n "_") :: go (n + 1) ts1 es
| (T.Named (_inf_arg_name, (T.Named ("implicit", T.Named (arg_name, t))))) :: ts1, es ->
(* override inferred arg_name *)
(mk_hole n arg_name) :: go (n + 1) ts1 es
| (T.Named (inf_arg_name, (T.Named ("implicit", t)))) :: ts1, es ->
(* non-overriden, use inferred arg_name *)
(mk_hole n inf_arg_name) :: go (n + 1) ts1 es
| (t :: ts1, e::es1) -> e :: go (n+1) ts1 es1
| _, [] -> []
| [], es -> es
Expand Down
14 changes: 14 additions & 0 deletions test/fail/implicit.mo
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,17 @@ func mkZero<T>(zero : implicit T) : T {
};

ignore mkZero<{ x : Nat }>();

// tricky case: if we have two implicit arguments of the same name we currently need to add a second type annotation
func c <T, U>(p1 : (T, U), p2 : (T, U),
cT : implicit (c : (T, T) -> Order),
cU : implicit (c : (U, U) -> Order))
: Order {
switch (cT(p1.0, p2.0)) {
case (#equal) { cU(p1.1, p2.1) };
case ord { ord };
};
};

ignore c((1,"a"),(0,"b")); // accepted

Loading