diff --git a/src/arrange.ml b/src/arrange.ml index f8ea64c9669..f2ac44ae9a0 100644 --- a/src/arrange.ml +++ b/src/arrange.ml @@ -10,17 +10,27 @@ let rec exp e = match e.it with | VarE x -> "VarE" $$ [id x] | LitE l -> "LitE" $$ [lit !l] | UnE (ot, uo, e) -> "UnE" $$ [operator_type !ot; unop uo; exp e] - | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; binop bo; exp e2] - | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; relop ro; exp e2] + | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; binop bo; exp e2] + | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; relop ro; exp e2] | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] - | ObjE (s, i, efs) -> "ObjE" $$ [obj_sort s; id i] @ List.map exp_field efs + | ObjE (s, efs) -> "ObjE" $$ [obj_sort s] @ List.map exp_field efs | DotE (e, x) -> "DotE" $$ [exp e; id x] | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] | ArrayE (m, es) -> "ArrayE" $$ [mut m] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] + | FuncE (x, s, tp, p, t, e') -> + "FuncE" $$ [ + Atom (Type.string_of_typ e.note.note_typ); + Atom (sharing s.it); + Atom x] @ + List.map typ_bind tp @ [ + pat p; + typ t; + exp e' + ] | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] - | BlockE (ds) -> "BlockE" $$ List.map dec ds + | BlockE ds -> "BlockE" $$ List.map dec ds | NotE e -> "NotE" $$ [exp e] | AndE (e1, e2) -> "AndE" $$ [exp e1; exp e2] | OrE (e1, e2) -> "OrE" $$ [exp e1; exp e2] @@ -146,16 +156,6 @@ and dec d = match d.it with | ExpD e -> "ExpD" $$ [exp e ] | LetD (p, e) -> "LetD" $$ [pat p; exp e] | VarD (x, e) -> "VarD" $$ [id x; exp e] - | FuncD (s, x, tp, p, t, e) -> - "FuncD" $$ [ - Atom (Type.string_of_typ d.note.note_typ); - Atom (sharing s.it); - id x] @ - List.map typ_bind tp @ [ - pat p; - typ t; - exp e - ] | TypD (x, tp, t) -> "TypD" $$ [id x] @ List.map typ_bind tp @ [typ t] | ClassD (x, tp, s, p, i', efs) -> diff --git a/src/async.ml b/src/async.ml index c0319d1ad2d..cc936f914a5 100644 --- a/src/async.ml +++ b/src/async.ml @@ -68,21 +68,19 @@ module Transform() = struct [t1] (tupE []) (T.seq (new_async_ret unary t1)) in - let async = fresh_id (typ (projE call_new_async 0)) in - let fullfill = fresh_id (typ (projE call_new_async 1)) in + let async = fresh_var (typ (projE call_new_async 0)) in + let fullfill = fresh_var (typ (projE call_new_async 1)) in (async,fullfill),call_new_async - let letP p e = {it = LetD(p, e); - at = no_region; - note = {e.note with note_typ = T.unit}} + let letP p e = {it = LetD(p, e); at = no_region; note = e.note} let new_nary_async_reply t1 = let (unary_async,unary_fullfill),call_new_async = new_async t1 in - let v' = fresh_id t1 in + let v' = fresh_var t1 in let ts1 = T.as_seq t1 in (* construct the n-ary async value, coercing the continuation, if necessary *) let nary_async = - let k' = fresh_id (contT t1) in + let k' = fresh_var (contT t1) in match ts1 with | [t] -> unary_async @@ -95,23 +93,23 @@ module Transform() = struct let vs,seq_of_vs = match ts1 with | [t] -> - let v = fresh_id t in + let v = fresh_var t in [v],v | ts -> - let vs = List.map fresh_id ts in + let vs = List.map fresh_var ts in vs, tupE vs in vs -@>* (unary_fullfill -*- seq_of_vs) in - let async,reply = fresh_id (typ nary_async), fresh_id (typ nary_reply) in - (async,reply),blockE [letP (tupP [varP unary_async;varP unary_fullfill]) call_new_async; - expD (tupE [nary_async;nary_reply])] + let async,reply = fresh_var (typ nary_async), fresh_var (typ nary_reply) in + (async,reply),blockE [letP (tupP [varP unary_async; varP unary_fullfill]) call_new_async; + expD (tupE [nary_async; nary_reply])] let letEta e scope = match e.it with | VarE _ -> scope e (* pure, so reduce *) - | _ -> let f = fresh_id (typ e) in + | _ -> let f = fresh_var (typ e) in letD f e :: (scope f) (* maybe impure; sequence *) let isAwaitableFunc exp = @@ -142,11 +140,11 @@ module Transform() = struct | [] -> (expD e)::d_of_vs [] | [t] -> - let x = fresh_id t in + let x = fresh_var t in let p = varP x in (letP p e)::d_of_vs [x] | ts -> - let xs = List.map fresh_id ts in + let xs = List.map fresh_var ts in let p = tupP (List.map varP xs) in (letP p e)::d_of_vs (xs) @@ -266,10 +264,10 @@ module Transform() = struct []) -> (* TBR, why isn't this []? *) (t_typ (T.seq ts1),t_typ contT) | t -> assert false in - let k = fresh_id contT in - let v1 = fresh_id t1 in - let post = fresh_id (T.Func(T.Sharable,T.Returns,[],[],[])) in - let u = fresh_id T.unit in + let k = fresh_var contT in + let v1 = fresh_var t1 in + let post = fresh_var (T.Func(T.Sharable,T.Returns,[],[],[])) in + let u = fresh_var T.unit in let ((nary_async,nary_reply),def) = new_nary_async_reply t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply]) def; funcD k v1 (nary_reply -*- v1); @@ -361,10 +359,10 @@ module Transform() = struct let pat = t_pat pat in let reply_typ = replyT nary res_typ in let typ' = T.Tup [] in - let k = fresh_id reply_typ in + let k = fresh_var reply_typ in let pat',d = extendTupP pat (varP k) in let typbinds' = t_typ_binds typbinds in - let x = fresh_id res_typ in + let x = fresh_var res_typ in let exp' = match exp.it with | CallE(_, async,_,cps) -> diff --git a/src/await.ml b/src/await.ml index 9ae10b8d56c..bb26637368a 100644 --- a/src/await.ml +++ b/src/await.ml @@ -24,7 +24,7 @@ let letcont k scope = | ContVar k' -> scope k' (* letcont eta-contraction *) | MetaCont (typ, cont) -> let k' = fresh_cont typ in - let v = fresh_id typ in + let v = fresh_var typ in blockE [funcD k' v (cont v); (* at this point, I'm really worried about variable capture *) expD (scope k')] @@ -39,7 +39,7 @@ let ( -@- ) k exp2 = match exp2.it with | VarE _ -> k exp2 | _ -> - let u = fresh_id typ in + let u = fresh_var typ in letE u exp2 (k u) @@ -170,7 +170,7 @@ and unary context k unE e1 = and binary context k binE e1 e2 = match eff e1, eff e2 with | T.Triv, T.Await -> - let v1 = fresh_id (typ e1) in (* TBR *) + let v1 = fresh_var (typ e1) in (* TBR *) letE v1 (t_exp context e1) (c_exp context e2 (meta (typ e2) (fun v2 -> k -@- binE v1 v2))) | T.Await, T.Await -> @@ -194,7 +194,7 @@ and nary context k naryE es = | e1 :: es -> match eff e1 with | T.Triv -> - let v1 = fresh_id (typ e1) in + let v1 = fresh_var (typ e1) in letE v1 (t_exp context e1) (nary_aux (v1 :: vs) es) | T.Await -> @@ -220,8 +220,8 @@ and c_if context k e1 e2 e3 = ) and c_while context k e1 e2 = - let loop = fresh_id (contT T.unit) in - let v2 = fresh_id T.unit in + let loop = fresh_var (contT T.unit) in + let v2 = fresh_var T.unit in let e2 = match eff e2 with | T.Triv -> loop -*- t_exp context e2 | T.Await -> c_exp context e2 (ContVar loop) @@ -245,20 +245,20 @@ and c_while context k e1 e2 = expD (loop -*- unitE)] and c_loop_none context k e1 = - let loop = fresh_id (contT T.unit) in + let loop = fresh_var (contT T.unit) in match eff e1 with | T.Triv -> assert false | T.Await -> - let v1 = fresh_id T.unit in + let v1 = fresh_var T.unit in blockE [funcD loop v1 (c_exp context e1 (ContVar loop)); expD(loop -*- unitE)] and c_loop_some context k e1 e2 = - let loop = fresh_id (contT T.unit) in - let u = fresh_id T.unit in - let v1 = fresh_id T.unit in + let loop = fresh_var (contT T.unit) in + let u = fresh_var T.unit in + let v1 = fresh_var T.unit in let e2 = match eff e2 with | T.Triv -> ifE (t_exp context e2) (loop -*- unitE) @@ -283,11 +283,11 @@ and c_loop_some context k e1 e2 = expD (loop -*- unitE)] and c_for context k pat e1 e2 = - let v1 = fresh_id (typ e1) in + let v1 = fresh_var (typ e1) in let next_typ = (T.Func(T.Local, T.Returns, [], [], [T.Opt pat.note])) in let dotnext v = dotE v nextN next_typ -*- unitE in - let loop = fresh_id (contT T.unit) in - let v2 = fresh_id T.unit in + let loop = fresh_var (contT T.unit) in + let v2 = fresh_var T.unit in let e2 = match eff e2 with | T.Triv -> loop -*- t_exp context e2 | T.Await -> c_exp context e2 (ContVar loop) in @@ -462,8 +462,8 @@ and c_dec context dec (k:kont) = end | FuncD (_, id, _ (* typbinds *), _ (* pat *), _ (* typ *), _ (* exp *) ) -> let func_typ = typ dec in - let v = fresh_id func_typ in - let u = fresh_id T.unit in + let v = fresh_var func_typ in + let u = fresh_var T.unit in blockE [letD v (decE (t_dec context dec)); letD u (define_idE id constM v); expD (k -@- v)] @@ -521,7 +521,7 @@ and rename_pat' pat = | WildP | LitP _ -> (PatEnv.empty, pat.it) | VarP id -> - let v = fresh_id pat.note in + let v = fresh_var pat.note in (PatEnv.singleton id.it v, VarP (id_of_exp v)) | TupP pats -> diff --git a/src/check_ir.ml b/src/check_ir.ml index ceaede559c8..e9f07746f3c 100644 --- a/src/check_ir.ml +++ b/src/check_ir.ml @@ -696,10 +696,10 @@ and check_dec env dec = (* check typing *) let t = typ dec in match dec.it with - | ExpD exp -> + | ExpD exp | LetD (_, exp) -> check_exp env exp; (typ exp) <: t - | LetD (_, exp) | VarD (_, exp) -> + | VarD (_, exp) -> check_exp env exp; T.unit <: t | FuncD (cc, id, typ_binds, pat, t2, exp) -> diff --git a/src/construct.ml b/src/construct.ml index c90ce8eb101..58e14188801 100644 --- a/src/construct.ml +++ b/src/construct.ml @@ -42,11 +42,11 @@ let fresh () = id_stamp := !id_stamp + 1; name -let fresh_lab () = +let fresh_id () = let name = fresh () in name @@ no_region -let fresh_id typ = +let fresh_var typ = let name = fresh () in idE (name @@ no_region) typ @@ -255,15 +255,10 @@ let newObjE sort ids typ = let letP pat exp = { it = LetD (pat, exp); at = no_region; - note = { S.note_typ = T.unit; (* ! *) - S.note_eff = eff exp; } + note = exp.note; } -let letD x exp = { it = LetD (varP x, exp); - at = no_region; - note = { S.note_eff = eff exp; - S.note_typ = T.unit; } (* ! *) - } +let letD x exp = letP (varP x) exp let varD x exp = { it = VarD (x, exp); at = no_region; @@ -326,7 +321,7 @@ let answerT = T.unit let contT typ = T.Func (T.Local, T.Returns, [], T.as_seq typ, []) let cpsT typ = T.Func (T.Local, T.Returns, [], [contT typ], []) -let fresh_cont typ = fresh_id (contT typ) +let fresh_cont typ = fresh_var (contT typ) (* Sequence expressions *) diff --git a/src/construct.mli b/src/construct.mli index d14d51a48ff..0dff373d31b 100644 --- a/src/construct.mli +++ b/src/construct.mli @@ -23,8 +23,8 @@ val nextN : name (* Identifiers *) -val fresh_lab : unit -> id -val fresh_id : typ -> var +val fresh_id : unit -> id +val fresh_var : typ -> var val idE : id -> typ -> exp val id_of_exp : exp -> id @@ -59,7 +59,7 @@ val breakE: id -> exp -> exp val retE: exp -> exp val assignE : exp -> exp -> exp val labelE : id -> typ -> exp -> exp -val loopE: exp -> exp option -> exp +val loopE : exp -> exp option -> exp val declare_idE : id -> typ -> exp -> exp val define_idE : id -> mut -> exp -> exp diff --git a/src/definedness.ml b/src/definedness.ml index 794deb2e75e..8604c0274cc 100644 --- a/src/definedness.ml +++ b/src/definedness.ml @@ -89,16 +89,15 @@ let rec exp msgs e : f = match e.it with | RelE (_, e1, ro, e2)-> exps msgs [e1; e2] | TupE es -> exps msgs es | ProjE (e, i) -> exp msgs e - | ObjE (s, i, efs) -> - let f = close (exp_fields msgs efs) // i.it in - begin match s.it with - | Type.Actor -> eagerify f - | Type.Object _ -> f - end + | ObjE (s, efs) -> + (* For actors, this may be too permissive; to be revised when we work on actors again *) + (* Also see https://dfinity.atlassian.net/browse/AST-49 *) + close (exp_fields msgs efs) | DotE (e, i) -> exp msgs e | AssignE (e1, e2) -> exps msgs [e1; e2] | ArrayE (m, es) -> exps msgs es | IdxE (e1, e2) -> exps msgs [e1; e2] + | FuncE (_, s, tp, p, t, e) -> delayify (exp msgs e /// pat msgs p) | CallE (e1, ts, e2) -> eagerify (exps msgs [e1; e2]) | BlockE ds -> decs msgs ds | NotE e -> exp msgs e @@ -145,10 +144,7 @@ and exp_fields msgs efs : fd = union_binders (exp_field msgs) efs and dec msgs d = match d.it with | ExpD e -> (exp msgs e, S.empty) | LetD (p, e) -> pat msgs p +++ exp msgs e - | VarD (i, e) -> - (M.empty, S.singleton i.it) +++ exp msgs e - | FuncD (s, i, tp, p, t, e) -> - (M.empty, S.singleton i.it) +++ delayify (exp msgs e /// pat msgs p) + | VarD (i, e) -> (M.empty, S.singleton i.it) +++ exp msgs e | TypD (i, tp, t) -> (M.empty, S.empty) | ClassD (i, tp, s, p, i', efs) -> (M.empty, S.singleton i.it) +++ delayify (close (exp_fields msgs efs) /// pat msgs p // i'.it) diff --git a/src/desugar.ml b/src/desugar.ml index 2c18e2647d5..aefa6c9c5d8 100644 --- a/src/desugar.ml +++ b/src/desugar.ml @@ -41,8 +41,8 @@ and exp' at note = function | S.TupE es -> I.TupE (exps es) | S.ProjE (e, i) -> I.ProjE (exp e, i) | S.OptE e -> I.OptE (exp e) - | S.ObjE (s, i, es) -> - obj at s None i es note.S.note_typ + | S.ObjE (s, es) -> + obj at s None es note.S.note_typ | S.DotE (e, x) -> let n = {x with it = I.Name x.it} in begin match T.as_obj_sub x.it e.note.S.note_typ with @@ -54,6 +54,11 @@ and exp' at note = function let t = Type.as_array note.S.note_typ in I.ArrayE (m, Type.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) + | S.FuncE (name, s, tbs, p, ty, e) -> + let cc = Value.call_conv_of_typ note.S.note_typ in + (* TODO(joachim): Turn I.FuncD into I.FuncE *) + let i = {it = name; at; note = ()} in + I.BlockE [{it = I.FuncD (cc, i, typ_binds tbs, pat p, ty.note, exp e); at; note}] | S.CallE (e1, inst, e2) -> let cc = Value.call_conv_of_typ e1.Source.note.S.note_typ in let inst = List.map (fun t -> t.Source.note) inst in @@ -62,9 +67,17 @@ and exp' at note = function | S.BlockE [{it = S.ExpD e; _}] -> exp' e.at e.note e.it | S.BlockE ds -> let ds' = decs ds in - if Type.is_unit note.S.note_typ && not (is_expD (Lib.List.last ds')) - then I.BlockE (ds' @ [expD (tupE [])]) - else I.BlockE (ds') + let prefix, last = Lib.List.split_last ds' in + begin match Type.is_unit note.S.note_typ, last.it with + | _, I.ExpD _ -> I.BlockE (ds') + | true, _ -> I.BlockE (ds' @ [expD (tupE [])]) + | false, (I.LetD ({it = I.VarP (x); _}, _) | I.FuncD (_, x, _, _, _, _)) -> + I.BlockE (ds' @ [expD (idE x note.S.note_typ)]) + | false, I.LetD (p', e') -> + let x = fresh_var note.S.note_typ in + I.BlockE (prefix @ [letD x e'; letP p' x; expD x]) + | false, (I.VarD _ | I.TypD _) -> assert false + end | S.NotE e -> I.IfE (exp e, falseE, trueE) | S.AndE (e1, e2) -> I.IfE (exp e1, exp e2, falseE) | S.OrE (e1, e2) -> I.IfE (exp e1, trueE, exp e2) @@ -82,13 +95,17 @@ and exp' at note = function | S.AssertE e -> I.AssertE (exp e) | S.AnnotE (e, _) -> assert false -and obj at s class_id self_id es obj_typ = +and obj at s self_id es obj_typ = match s.it with - | Type.Object _ -> build_obj at None s self_id es obj_typ - | Type.Actor -> I.ActorE (self_id, exp_fields es, obj_typ) - -and build_obj at class_id s self_id es obj_typ = - let self = idE self_id obj_typ in + | Type.Object _ -> build_obj at s self_id es obj_typ + | Type.Actor -> + let id = + match self_id with + | Some id -> id + | None -> id_of_exp (fresh_var obj_typ) + in I.ActorE (id, exp_fields es, obj_typ) + +and build_obj at s self_id es obj_typ = let names = match obj_typ with | Type.Obj (_, fields) -> @@ -97,12 +114,12 @@ and build_obj at class_id s self_id es obj_typ = ) fields | _ -> assert false in - I.BlockE ( - List.map (fun ef -> dec ef.it.S.dec) es @ - [ letD self (newObjE s.it names obj_typ); - expD self - ] - ) + let obj_e = newObjE s.it names obj_typ in + let ret_ds = + match self_id with + | None -> [ expD obj_e ] + | Some id -> let self = idE id obj_typ in [ letD self obj_e; expD self ] + in I.BlockE (List.map (fun ef -> dec ef.it.S.dec) es @ ret_ds) and exp_fields fs = List.map exp_field fs @@ -125,23 +142,10 @@ and exp_field' (f : S.exp_field') = mut = S.Var @@ x.at; exp = exp e; } - | S.FuncD (_, x, _, _, _, _) -> - { I.vis = f.S.vis; - name = I.Name x.it @@ x.at; - id = x; - mut = S.Const @@ x.at; - exp = {f.S.dec with it = I.BlockE [dec f.S.dec]}; - } - | S.ClassD (x, _, _, _, _, _) -> - { I.vis = f.S.vis; - name = I.Name x.it @@ x.at; - id = {x with note = ()}; - mut = S.Const @@ x.at; - exp = {f.S.dec with it = I.BlockE [dec f.S.dec]}; - } | S.ExpD _ -> failwith "expressions not yet supported in objects" | S.LetD _ -> failwith "pattern bindings not yet supported in objects" | S.TypD _ -> failwith "type definitions not yet supported in objects" + | S.ClassD _ -> failwith "class definitions not yet supported in objects" and typ_binds tbs = List.map typ_bind tbs @@ -169,17 +173,22 @@ and decs ds = S.note_eff = T.Triv } } in - typD :: (phrase' dec' d) :: (decs ds) - | _ -> (phrase' dec' d) :: (decs ds) + typD :: phrase' dec' d :: decs ds + | _ -> phrase' dec' d :: decs ds and dec d = phrase' dec' d and dec' at n d = match d with | S.ExpD e -> I.ExpD (exp e) - | S.LetD (p, e) -> I.LetD (pat p, exp e) + | S.LetD (p, e) -> + let p' = pat p in + let e' = exp e in + (* TODO: remove this hack once IR is adapted and backend can handle it *) + begin match p'.it, e'.it with + | I.VarP i, I.ActorE (_, efs, t) -> + I.LetD (p', {e' with it = I.ActorE (i, efs, t)}) + | _ -> I.LetD (p', e') + end | S.VarD (i, e) -> I.VarD (i, exp e) - | S.FuncD (s, i, tbs, p, ty, e) -> - let cc = Value.call_conv_of_typ n.S.note_typ in - I.FuncD (cc, i, typ_binds tbs, pat p, ty.note, exp e) | S.TypD (id, typ_bind, t) -> let c = Lib.Option.value id.note in I.TypD c @@ -200,7 +209,7 @@ and dec' at n d = match d with | _ -> assert false in I.FuncD (cc, id', typ_binds tbs, pat p, obj_typ, (* TBR *) - { it = obj at s (Some id') self_id es obj_typ; + { it = obj at s (Some self_id) es obj_typ; at = at; note = { S.note_typ = obj_typ; S.note_eff = T.Triv } }) diff --git a/src/effect.ml b/src/effect.ml index 36a583e2573..1bedc4e2b2d 100644 --- a/src/effect.ml +++ b/src/effect.ml @@ -27,7 +27,8 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = match exp.it with | PrimE _ | VarE _ - | LitE _ -> + | LitE _ + | FuncE _ -> T.Triv | UnE (_, _, exp1) | ProjE (exp1, _) @@ -61,7 +62,7 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = | BlockE decs -> let es = List.map effect_dec decs in List.fold_left max_eff Type.Triv es - | ObjE (_, _, efs) -> + | ObjE (_, efs) -> effect_field_exps efs | IfE (exp1, exp2, exp3) -> let e1 = effect_exp exp1 in @@ -98,7 +99,6 @@ and infer_effect_dec dec = | VarD (_, e) -> effect_exp e | TypD _ - | FuncD _ | ClassD _ -> T.Triv @@ -192,8 +192,7 @@ module Ir = | LetD (_,e) | VarD (_, e) -> effect_exp e - | TypD _ -> - T.Triv - | FuncD (s, v, tps, p, t, e) -> + | TypD _ + | FuncD _ -> T.Triv end diff --git a/src/instrList.ml b/src/instrList.ml index d45e87863f4..4fc568e7554 100644 --- a/src/instrList.ml +++ b/src/instrList.ml @@ -89,7 +89,7 @@ let loop_ (ty : block_type) (body : t) : t = (* Remember depth *) type depth = int32 Lib.Promise.t -let new_depth_label () : depth = Lib.Promise.make_named "depth_label" +let new_depth_label () : depth = Lib.Promise.make () let remember_depth depth (is : t) : t = fun d rest -> Lib.Promise.fulfill depth d; is d rest diff --git a/src/interpret.ml b/src/interpret.ml index 03b5f95e2f0..0a694111661 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -174,14 +174,12 @@ let make_async_message id v = (* assert (false) *) -let make_message id t v : V.value = +let make_message name t v : V.value = match t with - | T.Func (_, _, _, _, []) -> - make_unit_message id.it v - | T.Func (_, _, _, _, [T.Async _]) -> - make_async_message id.it v + | T.Func (_, _, _, _, []) -> make_unit_message name v + | T.Func (_, _, _, _, [T.Async _]) -> make_async_message name v | _ -> - failwith (Printf.sprintf "actorfield: %s %s" id.it (T.string_of_typ t)) + failwith (Printf.sprintf "actorfield: %s %s" name (T.string_of_typ t)) (* assert false *) @@ -266,8 +264,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | ProjE (exp1, n) -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) - | ObjE (sort, id, fields) -> - interpret_obj env sort id fields k + | ObjE (sort, fields) -> + interpret_obj env sort fields k | DotE (exp1, id) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in @@ -294,6 +292,14 @@ and interpret_exp_mut env exp (k : V.value V.cont) = with Invalid_argument s -> trap exp.at "%s" s) ) ) + | FuncE (name, _sort, _typbinds, pat, _typ, exp2) -> + let f = interpret_func env name pat (fun env' -> interpret_exp env' exp2) in + let v = V.Func (V.call_conv_of_typ exp.note.note_typ, f) in + let v' = + match _sort.it with + | T.Sharable -> make_message name exp.note.note_typ v + | T.Local -> v + in k v' | CallE (exp1, typs, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> @@ -523,13 +529,10 @@ and match_pats pats vs ve : val_env option = (* Objects *) -and interpret_obj env sort id fields (k : V.value V.cont) = - let ve_ex, ve_in = declare_exp_fields fields V.Env.empty (declare_id id) in +and interpret_obj env sort fields (k : V.value V.cont) = + let ve_ex, ve_in = declare_exp_fields fields V.Env.empty V.Env.empty in let env' = adjoin_vals env ve_in in - interpret_exp_fields env' sort.it fields ve_ex (fun v -> - define_id env' id v; - k v - ) + interpret_exp_fields env' sort.it fields ve_ex k and declare_exp_fields fields ve_ex ve_in : val_env * val_env = match fields with @@ -560,8 +563,7 @@ and declare_dec dec : val_env = | ExpD _ | TypD _ -> V.Env.empty | LetD (pat, _) -> declare_pat pat - | VarD (id, _) - | FuncD (_, id, _, _, _, _) -> declare_id id + | VarD (id, _) -> declare_id id | ClassD (id, _, _, _, _, _) -> declare_id {id with note = ()} and declare_decs decs ve : val_env = @@ -579,7 +581,7 @@ and interpret_dec env dec (k : V.value V.cont) = | LetD (pat, exp) -> interpret_exp env exp (fun v -> define_pat env pat v; - k V.unit + k v ) | VarD (id, exp) -> interpret_exp env exp (fun v -> @@ -588,21 +590,14 @@ and interpret_dec env dec (k : V.value V.cont) = ) | TypD _ -> k V.unit - | FuncD (_sort, id, _typbinds, pat, _typ, exp) -> - let f = interpret_func env id pat - (fun env' -> interpret_exp env' exp) in - let v = V.Func (V.call_conv_of_typ dec.note.note_typ, f) in - let v = - match _sort.it with - | T.Sharable -> - make_message id dec.note.note_typ v - | T.Local -> v - in - define_id env id v; - k v | ClassD (id, _typbinds, sort, pat, id', fields) -> - let f = interpret_func env {id with note = ()} pat - (fun env' k' -> interpret_obj env' sort id' fields k') in + let f = interpret_func env id.it pat (fun env' k' -> + let env'' = adjoin_vals env' (declare_id id') in + interpret_obj env'' sort fields (fun v' -> + define_id env'' id' v'; + k' v' + ) + ) in let v = V.Func (V.call_conv_of_typ dec.note.note_typ, f) in define_id env {id with note = ()} v; k v @@ -615,8 +610,8 @@ and interpret_decs env decs (k : V.value V.cont) = interpret_dec env dec (fun _v -> interpret_decs env decs' k) -and interpret_func env id pat f v (k : V.value V.cont) = - if !Flags.trace then trace "%s%s" id.it (string_of_arg v); +and interpret_func env name pat f v (k : V.value V.cont) = + if !Flags.trace then trace "%s%s" name (string_of_arg v); match match_pat pat v with | None -> trap pat.at "argument value %s does not match parameter list" diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index a3ca5deddfc..168989508f6 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -624,7 +624,7 @@ and interpret_dec env dec (k : V.value V.cont) = | LetD (pat, exp) -> interpret_exp env exp (fun v -> define_pat env pat v; - k V.unit + k v ) | VarD (id, exp) -> interpret_exp env exp (fun v -> diff --git a/src/lib.ml b/src/lib.ml index 27ab63c89ef..4b4830efc6c 100644 --- a/src/lib.ml +++ b/src/lib.ml @@ -227,13 +227,14 @@ end module Promise = struct - type 'a t = ('a option ref * string) - - let make () = (ref None, "anonymous promise") - let make_named s = (ref None, s) - let make_fulfilled x = (ref (Some x), "anonymous promise") - let fulfill (p,s) x = if !p = None then p := Some x else failwith ("fulfill: " ^ s) - let is_fulfilled (p,_) = !p <> None - let value_opt (p,s) = !p - let value (p,s) = match !p with None -> failwith ("Promise.value: " ^ s) | Some x -> x + type 'a t = 'a option ref + + exception Promise + + let make () = ref None + let make_fulfilled x = ref (Some x) + let fulfill p x = if !p = None then p := Some x else raise Promise + let is_fulfilled p = !p <> None + let value_opt p = !p + let value p = match !p with Some x -> x | None -> raise Promise end diff --git a/src/lib.mli b/src/lib.mli index fb450591ad8..35089542d3c 100644 --- a/src/lib.mli +++ b/src/lib.mli @@ -75,8 +75,8 @@ end module Promise : sig type 'a t + exception Promise val make : unit -> 'a t - val make_named : string -> 'a t val make_fulfilled : 'a -> 'a t val fulfill : 'a t -> 'a -> unit val is_fulfilled : 'a t -> bool diff --git a/src/parser.mly b/src/parser.mly index fc7bc2bbe65..7694adf4451 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -54,6 +54,11 @@ let assign_op lhs rhs_f at = | [] -> e | ds -> BlockE (ds @ [ExpD e @? e.at]) @? at +let let_or_exp named x e' at = + if named + then LetD(VarP(x) @! at, e' @? at) @? at + else ExpD(e' @? at) @? at + let share_typ t = match t.it with | ObjT ({it = Type.Object Type.Local; _} as s, tfs) -> @@ -65,10 +70,15 @@ let share_typ t = let share_typfield tf = {tf with it = {tf.it with typ = share_typ tf.it.typ}} +let share_exp e = + match e.it with + | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> + FuncE (x, {s with it = Type.Sharable}, tbs, p, t, e) @? e.at + | _ -> e + let share_dec d = match d.it with - | FuncD ({it = Type.Local; _} as s, x, tbs, p, t, e) -> - FuncD ({s with it = Type.Sharable}, x, tbs, p, t, e) @? d.at + | LetD (p, e) -> LetD (p, share_exp e) @? d.at | _ -> d let share_expfield (ef : exp_field) = @@ -154,8 +164,8 @@ seplist1(X, SEP) : | id=ID { id @= at $sloc } %inline id_opt : - | id=id { fun _ _ -> id } - | (* empty *) { fun sort sloc -> anon sort (at sloc) @@ at sloc } + | id=id { fun _ _ -> true, id } + | (* empty *) { fun sort sloc -> false, anon sort (at sloc) @@ at sloc } %inline typ_id_opt : | id=typ_id { fun _ _ -> id } @@ -431,14 +441,6 @@ exp_nonvar : { e } | d=dec_nonvar { BlockE([d]) @? at $sloc } - (* TODO(andreas): hack, remove *) - | s=obj_sort xf=id_opt EQ? efs=obj_body - { let anon = if s.it = Type.Actor then "actor" else "object" in - let efs' = - if s.it = Type.Object Type.Local - then efs - else List.map share_expfield efs - in ObjE(s, xf anon $sloc, efs') @? at $sloc } exp : | e=exp_nonvar @@ -461,8 +463,8 @@ exp_field : | v=private_opt x=id EQ e=exp { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in {dec = d; vis = v} @@ at $sloc } - | v=private_opt s=shared_opt x=id fd=func_dec - { let d = fd s x in + | v=private_opt s=shared_opt x=id fe=func_exp + { let d = LetD(VarP(x) @! x.at, fe s x.it) @? at $sloc in {dec = d; vis = v} @@ at $sloc } (* TODO(andreas): allow any dec *) | v=private_opt d=dec_var @@ -515,24 +517,32 @@ return_typ_nullary : (* Declarations *) dec_var : - | LET p=pat EQ e=exp - { let p', e' = - match p.it with - | AnnotP (p', t) -> p', AnnotE (e, t) @? p.at - | _ -> p, e - in LetD (p', e') @? at $sloc } | VAR x=id t=return_typ? EQ e=exp { let e' = match t with | None -> e | Some t -> AnnotE (e, t) @? span t.at e.at in VarD(x, e') @? at $sloc } - -dec_nonvar : - | s=shared_opt FUNC xf=id_opt fd=func_dec - { (fd s (xf "func" $sloc)).it @? at $sloc } + | LET p=pat EQ e=exp + { let p', e' = + match p.it with + | AnnotP (p', t) -> p', AnnotE (e, t) @? p.at + | _ -> p, e + in LetD (p', e') @? at $sloc } | TYPE x=typ_id tps=typ_params_opt EQ t=typ { TypD(x, tps, t) @? at $sloc } + +dec_nonvar : + | s=obj_sort xf=id_opt EQ? efs=obj_body + { let named, x = xf "object" $sloc in + let efs' = + if s.it = Type.Object Type.Local + then efs + else List.map share_expfield efs + in let_or_exp named x (ObjE(s, efs')) (at $sloc) } + | s=shared_opt FUNC xf=id_opt fe=func_exp + { let named, x = xf "func" $sloc in + let_or_exp named x (fe s x.it).it (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_nullary xefs=class_body { let x, efs = xefs in let efs' = @@ -548,25 +558,8 @@ dec : { d } | e=exp_nondec { ExpD e @? at $sloc } - (* TODO(andreas): move to dec_nonvar once other production is gone *) - | s=obj_sort id_opt=id? EQ? efs=obj_body - { let efs' = - if s.it = Type.Object Type.Local - then efs - else List.map share_expfield efs - in - let r = at $sloc in - (* desugar anonymous objects to ExpD, named ones to LetD. *) - match id_opt with - | None -> - let sort = if s.it = Type.Actor then "actor" else "object" in - let x = anon sort r @@ r in - ExpD(ObjE(s, x, efs') @? r) @? r - | Some x -> - let p = VarP x @! r in - LetD(p, ObjE(s, x, efs') @? r) @? r } - -func_dec : + +func_exp : | tps=typ_params_opt p=pat_nullary rt=return_typ? fb=func_body { let t = Lib.Option.get rt (TupT([]) @! no_region) in (* This is a hack to support local func declarations that return a computed async. @@ -578,7 +571,7 @@ func_dec : match t.it with | AsyncT _ -> AsyncE(e) @? e.at | _ -> e - in fun s x -> FuncD(s, x, tps, p, t, e) @? at $sloc } + in fun s x -> FuncE(x, s, tps, p, t, e) @? at $sloc } func_body : | EQ e=exp { (false, e) } @@ -589,7 +582,7 @@ obj_body : { efs } class_body : - | EQ xf=id_opt efs=obj_body { xf "object" $sloc, efs } + | EQ xf=id_opt efs=obj_body { snd (xf "object" $sloc), efs } | efs=obj_body { anon "object" (at $sloc) @@ at $sloc, efs } diff --git a/src/syntax.ml b/src/syntax.ml index de1890b1372..81896a954b6 100644 --- a/src/syntax.ml +++ b/src/syntax.ml @@ -130,11 +130,12 @@ and exp' = | TupE of exp list (* tuple *) | ProjE of exp * int (* tuple projection *) | OptE of exp (* option injection *) - | ObjE of obj_sort * id * exp_field list (* object *) + | ObjE of obj_sort * exp_field list (* object *) | DotE of exp * id (* object projection *) | AssignE of exp * exp (* assignment *) | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) + | FuncE of string * sharing * typ_bind list * pat * typ * exp (* function *) | CallE of exp * typ list * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) @@ -173,8 +174,6 @@ and dec' = | ExpD of exp (* plain expression *) | LetD of pat * exp (* immutable *) | VarD of id * exp (* mutable *) - | FuncD of (* function *) - sharing * id * typ_bind list * pat * typ * exp | TypD of typ_id * typ_bind list * typ (* type *) | ClassD of (* class *) typ_id * typ_bind list * obj_sort * pat * id * exp_field list diff --git a/src/tailcall.ml b/src/tailcall.ml index d063bd00298..44aac551d1e 100644 --- a/src/tailcall.ml +++ b/src/tailcall.ml @@ -198,8 +198,8 @@ and dec' env d = | FuncD ({ Value.sort = Local; _} as cc, id, tbs, p, typT, exp0) -> let env = bind env id None in (fun env1 -> - let temp = fresh_id (Mut p.note) in - let l = fresh_lab () in + let temp = fresh_var (Mut p.note) in + let l = fresh_id () in let tail_called = ref false in let env2 = { tail_pos = true; info = Some { func = id; @@ -213,7 +213,7 @@ and dec' env d = let cs = List.map (fun (tb : typ_bind) -> Con (tb.it.con, [])) tbs in if !tail_called then let ids = match typ d with - | Func( _, _, _, dom, _) -> List.map (fun t -> fresh_id (open_ cs t)) dom + | Func( _, _, _, dom, _) -> List.map (fun t -> fresh_var (open_ cs t)) dom | _ -> assert false in let args = seqP (List.map varP ids) in diff --git a/src/typing.ml b/src/typing.ml index 1015c37992c..c6de0bd7ceb 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -412,9 +412,9 @@ and infer_exp'' env exp : T.typ = error env exp1.at "expected tuple type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) - | ObjE (sort, id, fields) -> + | ObjE (sort, fields) -> let env' = if sort.it = T.Actor then {env with async = false} else env in - infer_obj env' sort.it id T.Pre fields exp.at + infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in (try @@ -457,6 +457,41 @@ and infer_exp'' env exp : T.typ = error env exp1.at "expected array type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) + | FuncE (_, sort, typ_binds, pat, typ, exp) -> + let cs, ts, te, ce = check_typ_binds env typ_binds in + let env' = adjoin_typs env te ce in + let t1, ve = infer_pat_exhaustive env' pat in + let t2 = check_typ env' typ in + if not env.pre then begin + let env'' = + {env' with labs = T.Env.empty; rets = Some t2; async = false} in + check_exp (adjoin_vals env'' ve) t2 exp; + if sort.it = T.Sharable then begin + if not (T.sub t1 T.Shared) then + error env pat.at "shared function has non-shared parameter type\n %s" + (T.string_of_typ_expand t1); + begin match t2 with + | T.Tup [] -> () + | T.Async t2 -> + if not (T.sub t2 T.Shared) then + error env typ.at "shared function has non-shared result type\n %s" + (T.string_of_typ_expand t2); + if not (isAsyncE exp) then + error env exp.at "shared function with async type has non-async body" + | _ -> error env typ.at "shared function has non-async result type\n %s" + (T.string_of_typ_expand t2) + end + end + end; + let ts1 = match pat.it with TupP ps -> T.as_seq t1 | _ -> [t1] in + let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in + let c = + match sort.it, typ.it with + | T.Sharable, (AsyncT _) -> T.Promises (* TBR: do we want this for T.Local too? *) + | _ -> T.Returns + in + let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in + T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> let t1 = infer_exp_promote env exp1 in (try @@ -840,8 +875,7 @@ and pub_dec dec xs : region T.Env.t * region T.Env.t = match dec.it with | ExpD _ -> xs | LetD (pat, _) -> pub_pat pat xs - | VarD (id, _) - | FuncD (_, id, _, _, _, _) -> pub_val_id id xs + | VarD (id, _) -> pub_val_id id xs | ClassD (id, _, _, _, _, _) -> pub_val_id {id with note = ()} (pub_typ_id id xs) | TypD (id, _, _) -> pub_typ_id id xs @@ -862,11 +896,9 @@ and pub_val_id id (xs, ys) : region T.Env.t * region T.Env.t = (xs, T.Env.add id.it id.at ys) -and infer_obj env s id t fields at : T.typ = +and infer_obj env s fields at : T.typ = let decs = List.map (fun (field : exp_field) -> field.it.dec) fields in - let env' = add_val env id.it t in - (* Prepass to infer type for id *) - let _, scope = infer_block {env' with pre = true} decs at in + let _, scope = infer_block env decs at in let pub_typ, pub_val = pub_fields fields in (* TODO: type fields *) T.Env.iter (fun _ at' -> @@ -883,9 +915,7 @@ and infer_obj env s id t fields at : T.typ = lab (T.string_of_typ_expand typ) ) tfs end; - let t' = T.Obj (s, tfs) in - ignore (infer_block (add_val env id.it t') decs at); - t' + T.Obj (s, tfs) (* Blocks and Declarations *) @@ -918,34 +948,27 @@ and infer_block_exps env decs : T.typ = and infer_dec env dec : T.typ = let t = match dec.it with - | ExpD exp -> + | ExpD exp + | LetD (_, exp) -> infer_exp env exp - | LetD (_, exp) | VarD (_, exp) -> + | VarD (_, exp) -> if not env.pre then ignore (infer_exp env exp); T.unit - | FuncD (sort, id, typ_binds, pat, typ, exp) -> - let t = T.Env.find id.it env.vals in - if not env.pre then begin - let _cs, _ts, te, ce = check_typ_binds env typ_binds in - let env' = adjoin_typs env te ce in - let _, ve = infer_pat_exhaustive env' pat in - let t2 = check_typ env' typ in - let env'' = - {env' with labs = T.Env.empty; rets = Some t2; async = false} in - check_exp (adjoin_vals env'' ve) t2 exp - end; - t | ClassD (id, typ_binds, sort, pat, self_id, fields) -> let t = T.Env.find id.it env.vals in if not env.pre then begin + let c = T.Env.find id.it env.typs in let cs, _ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let _, ve = infer_pat_exhaustive env' pat in + let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let env'' = - {env' with labs = T.Env.empty; rets = None; async = false} in - let self_typ = - T.Con (T.Env.find id.it env.typs, List.map (fun c -> T.Con (c, [])) cs) in - ignore (infer_obj (adjoin_vals env'' ve) sort.it self_id self_typ fields dec.at) + { (add_val (adjoin_vals env' ve) self_id.it self_typ) with + labs = T.Env.empty; + rets = None; + async = false + } + in ignore (infer_obj env'' sort.it fields dec.at) end; t | TypD _ -> @@ -977,7 +1000,7 @@ and check_dec env t dec = match dec.it with | ExpD exp -> check_exp env t exp; - dec.note <- exp.note; + dec.note <- exp.note (* TBR: push in external type annotation; unfortunately, this isn't enough, because of the earlier recursive phases | FuncD (id, [], pat, typ, exp) -> @@ -1003,7 +1026,6 @@ and check_dec env t dec = *) | _ -> let t' = infer_dec env dec in - (* TBR: special-case unit? *) if not (T.eq t T.unit || T.sub t' t) then local_error env dec.at "expression of type\n %s\ncannot produce expected type\n %s" (T.string_of_typ_expand t') @@ -1015,7 +1037,7 @@ and gather_block_typdecs env decs : scope = and gather_dec_typdecs env scope dec : scope = match dec.it with - | ExpD _ | LetD _ | VarD _ | FuncD _ -> scope + | ExpD _ | LetD _ | VarD _ -> scope | TypD (id, binds, _) | ClassD (id, binds, _, _, _, _) -> if T.Env.mem id.it scope.typ_env then error env dec.at "duplicate definition for type %s in block" id.it; @@ -1037,7 +1059,7 @@ and infer_block_typdecs env decs : con_env = and infer_dec_typdecs env dec : con_env = match dec.it with - | ExpD _ | LetD _ | VarD _ | FuncD _ -> + | ExpD _ | LetD _ | VarD _ -> T.ConSet.empty | TypD (id, binds, typ) -> let c = T.Env.find id.it env.typs in @@ -1053,7 +1075,8 @@ and infer_dec_typdecs env dec : con_env = let env' = adjoin_typs {env with pre = true} te ce in let _, ve = infer_pat env' pat in let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in - let t = infer_obj (adjoin_vals env' ve) sort.it self_id self_typ fields dec.at in + let env'' = add_val (adjoin_vals env' ve) self_id.it self_typ in + let t = infer_obj env'' sort.it fields dec.at in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in infer_id_typdecs id c k @@ -1076,28 +1099,17 @@ and gather_block_valdecs env decs : val_env = and gather_dec_valdecs env ve dec : val_env = match dec.it with - | ExpD _ | TypD _ -> - ve - | LetD (pat, _) -> - gather_pat env ve pat - | VarD (id, _) - | FuncD (_, id, _, _, _, _) -> - gather_id env ve id - | ClassD (id, _ , _, _, _, _) -> - gather_id env ve {id with note = ()} + | ExpD _ | TypD _ -> ve + | LetD (pat, _) -> gather_pat env ve pat + | VarD (id, _) -> gather_id env ve id + | ClassD (id, _ , _, _, _, _) -> gather_id env ve {id with note = ()} and gather_pat env ve pat : val_env = match pat.it with - | WildP | LitP _ | SignP _ -> - ve - | VarP id -> - gather_id env ve id - | TupP pats -> - List.fold_left (gather_pat env) ve pats - | AltP (pat1, _) - | OptP pat1 - | AnnotP (pat1, _) -> - gather_pat env ve pat1 + | WildP | LitP _ | SignP _ -> ve + | VarP id -> gather_id env ve id + | TupP pats -> List.fold_left (gather_pat env) ve pats + | AltP (pat1, _) | OptP pat1 | AnnotP (pat1, _) -> gather_pat env ve pat1 and gather_id env ve id : val_env = if T.Env.mem id.it ve then @@ -1124,37 +1136,6 @@ and infer_dec_valdecs env dec : val_env = | VarD (id, exp) -> let t = infer_exp {env with pre = true} exp in T.Env.singleton id.it (T.Mut t) - | FuncD (sort, id, typ_binds, pat, typ, exp) -> - let cs, ts, te, ce = check_typ_binds env typ_binds in - let env' = adjoin_typs env te ce in - let t1, _ = infer_pat {env' with pre = true} pat in - let t2 = check_typ env' typ in - if not env.pre && sort.it = T.Sharable then begin - if not (T.sub t1 T.Shared) then - error env pat.at "shared function has non-shared parameter type\n %s" - (T.string_of_typ_expand t1); - begin match t2 with - | T.Tup [] -> () - | T.Async t2 -> - if not (T.sub t2 T.Shared) then - error env typ.at "shared function has non-shared result type\n %s" - (T.string_of_typ_expand t2); - if not (isAsyncE exp) then - error env dec.at "shared function with async type has non-async body" - | _ -> error env typ.at "shared function has non-async result type\n %s" - (T.string_of_typ_expand t2) - end; - end; - let ts1 = match pat.it with TupP ps -> T.as_seq t1 | _ -> [t1] in - let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in - let c = - match sort.it, typ.it with - | T.Sharable, (AsyncT _) -> T.Promises (* TBR: do we want this for T.Local too? *) - | _ -> T.Returns - in - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - T.Env.singleton id.it - (T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2)) | TypD _ -> T.Env.empty | ClassD (id, typ_binds, sort, pat, self_id, fields) -> diff --git a/src/value.ml b/src/value.ml index 149e36dc46c..9a4613045ca 100644 --- a/src/value.ml +++ b/src/value.ml @@ -200,7 +200,7 @@ let call_conv_of_typ typ = match typ with | Type.Func(sort, control, tbds, dom, res) -> { sort; control; n_args = List.length dom; n_res = List.length res } - | _ -> raise (Invalid_argument ("call_conv_of_typ"^T.string_of_typ typ)) + | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ T.string_of_typ typ)) type func = (value -> value cont -> unit) diff --git a/test/fail/asyncret3.as b/test/fail/asyncret3.as index 02d1325234a..01b5a29b418 100644 --- a/test/fail/asyncret3.as +++ b/test/fail/asyncret3.as @@ -1,2 +1 @@ -shared func call4(f : shared () -> async B) : async B = f() ; - +shared func call4(f : shared () -> async B) : async B = f(); diff --git a/test/fail/issue36.as b/test/fail/issue36.as index ffb96a4a4aa..f47935c9cb6 100644 --- a/test/fail/issue36.as +++ b/test/fail/issue36.as @@ -26,4 +26,4 @@ let (f, g, h) : (Float, Float, Float) = (1., 1.7, 1.8e-4); // N.B. these fail in wasm (AST-40) -let (k, l) : (Float, Float) = (0x644., 0x644.5P-1) \ No newline at end of file +let (k, l) : (Float, Float) = (0x644., 0x644.5P-1) diff --git a/test/fail/ok/asyncret3.tc.ok b/test/fail/ok/asyncret3.tc.ok index b021508f558..5cdd96a69bf 100644 --- a/test/fail/ok/asyncret3.tc.ok +++ b/test/fail/ok/asyncret3.tc.ok @@ -1 +1 @@ -asyncret3.as:1.1-1.73: type error, shared function with async type has non-async body +asyncret3.as:1.70-1.73: type error, shared function with async type has non-async body diff --git a/test/fail/ok/decl-clash.run-ir.ok b/test/fail/ok/decl-clash.run-ir.ok index e5371865582..19aced78e3a 100644 --- a/test/fail/ok/decl-clash.run-ir.ok +++ b/test/fail/ok/decl-clash.run-ir.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Env.Make(X).Clash("test") +prelude:50.1-75.2: internal error, Env.Make(X).Clash("test") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/fail/ok/decl-clash.run-low.ok b/test/fail/ok/decl-clash.run-low.ok index e5371865582..19aced78e3a 100644 --- a/test/fail/ok/decl-clash.run-low.ok +++ b/test/fail/ok/decl-clash.run-low.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Env.Make(X).Clash("test") +prelude:50.1-75.2: internal error, Env.Make(X).Clash("test") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/fail/ok/decl-clash.run.ok b/test/fail/ok/decl-clash.run.ok index e5371865582..19aced78e3a 100644 --- a/test/fail/ok/decl-clash.run.ok +++ b/test/fail/ok/decl-clash.run.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Env.Make(X).Clash("test") +prelude:50.1-75.2: internal error, Env.Make(X).Clash("test") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/fail/ok/decl-clash.tc.ok b/test/fail/ok/decl-clash.tc.ok index e5371865582..19aced78e3a 100644 --- a/test/fail/ok/decl-clash.tc.ok +++ b/test/fail/ok/decl-clash.tc.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Env.Make(X).Clash("test") +prelude:50.1-75.2: internal error, Env.Make(X).Clash("test") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/fail/ok/decl-clash.wasm.stderr.ok b/test/fail/ok/decl-clash.wasm.stderr.ok index e5371865582..19aced78e3a 100644 --- a/test/fail/ok/decl-clash.wasm.stderr.ok +++ b/test/fail/ok/decl-clash.wasm.stderr.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Env.Make(X).Clash("test") +prelude:50.1-75.2: internal error, Env.Make(X).Clash("test") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/fail/ok/use-before-define5.tc.ok b/test/fail/ok/use-before-define5.tc.ok deleted file mode 100644 index 717605b188d..00000000000 --- a/test/fail/ok/use-before-define5.tc.ok +++ /dev/null @@ -1 +0,0 @@ -use-before-define5.as:2.1-2.49: definedness error, cannot use x before x has been defined diff --git a/test/fail/ok/use-before-define5.wasm-run.ok b/test/fail/ok/use-before-define5.wasm-run.ok new file mode 100644 index 00000000000..f1fd5a677e9 --- /dev/null +++ b/test/fail/ok/use-before-define5.wasm-run.ok @@ -0,0 +1 @@ +_out/use-before-define5.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/use-before-define5.wasm.stderr.ok b/test/fail/ok/use-before-define5.wasm.stderr.ok new file mode 100644 index 00000000000..473a0223e65 --- /dev/null +++ b/test/fail/ok/use-before-define5.wasm.stderr.ok @@ -0,0 +1,18 @@ +non-closed actor: (ActorE + a + (foo + foo + (BlockE + (FuncD + (shared 0 -> 0) + foo + (TupP) + () + (AssertE (RelE Nat (VarE x) EqOp (LitE (NatLit 1)))) + ) + ) + Const + Public + ) + actor {foo : shared () -> ()} +) diff --git a/test/run-dfinity/indirect-counter.as b/test/run-dfinity/indirect-counter.as index 1090f213f74..b058ed60089 100644 --- a/test/run-dfinity/indirect-counter.as +++ b/test/run-dfinity/indirect-counter.as @@ -1,5 +1,5 @@ let a = actor { - private a = actor { + private aa = actor { private var c = 1; inc() { c += 1; @@ -9,8 +9,8 @@ let a = actor { printInt(c) }; }; - inc() { a.inc() }; - print() { a.print() }; + inc() { aa.inc() }; + print() { aa.print() }; }; a.inc(); diff --git a/test/run-dfinity/ok/actor-reexport.diff-ir.ok b/test/run-dfinity/ok/actor-reexport.diff-ir.ok index a7ecec4b432..f168a520fd4 100644 --- a/test/run-dfinity/ok/actor-reexport.diff-ir.ok +++ b/test/run-dfinity/ok/actor-reexport.diff-ir.ok @@ -1,12 +1,21 @@ --- actor-reexport.run +++ actor-reexport.run-ir -@@ -1,5 +1,4 @@ +@@ -1,5 +1,13 @@ -exported() -exported() -exported() -exported() -exported() -+(unknown location): internal error, Failure("pattern bindings not yet supported in objects") ++prelude:50.1-75.2: internal error, Failure("pattern bindings not yet supported in objects") + +Last environment: ++@new_async = func ++Array_init = func ++Array_tabulate = func ++abs = func ++ignore = func ++print = func ++printInt = func ++range = func ++revrange = func + diff --git a/test/run-dfinity/ok/actor-reexport.run-ir.ok b/test/run-dfinity/ok/actor-reexport.run-ir.ok index e96bfdfd541..cc6cd71971f 100644 --- a/test/run-dfinity/ok/actor-reexport.run-ir.ok +++ b/test/run-dfinity/ok/actor-reexport.run-ir.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Failure("pattern bindings not yet supported in objects") +prelude:50.1-75.2: internal error, Failure("pattern bindings not yet supported in objects") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/run-dfinity/ok/actor-reexport.wasm.stderr.ok b/test/run-dfinity/ok/actor-reexport.wasm.stderr.ok index e96bfdfd541..cc6cd71971f 100644 --- a/test/run-dfinity/ok/actor-reexport.wasm.stderr.ok +++ b/test/run-dfinity/ok/actor-reexport.wasm.stderr.ok @@ -1,4 +1,13 @@ -(unknown location): internal error, Failure("pattern bindings not yet supported in objects") +prelude:50.1-75.2: internal error, Failure("pattern bindings not yet supported in objects") Last environment: +@new_async = func +Array_init = func +Array_tabulate = func +abs = func +ignore = func +print = func +printInt = func +range = func +revrange = func diff --git a/test/run/actors.as b/test/run/actors.as index d1690702064..609faa0e9a3 100644 --- a/test/run/actors.as +++ b/test/run/actors.as @@ -6,9 +6,9 @@ let _ = tictac_actor.tic_msg(10); func ignore(_ : async ()) = (); -let tictac_async = new this { - tic_async(n : Int) : async () { if (n > 0) ignore(this.tac_async(n - 1)) }; - tac_async(n : Int) : async () { if (n > 0) ignore(this.tic_async(n - 1)) }; +object tictac_async { + tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; + tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; }; let _ = tictac_async.tic_async(10); diff --git a/test/run/async-calls.as b/test/run/async-calls.as index 2241722ee12..890a3e58746 100644 --- a/test/run/async-calls.as +++ b/test/run/async-calls.as @@ -5,9 +5,9 @@ let sync_object = new self { private var x : Bool = false; - bump() : () { assert (x == false); x := true; assert (x == true); }; + bump() { assert (x == false); x := true; assert (x == true); }; - test() : () { assert (x == false); self.bump(); assert (x == true); }; + test() { assert (x == false); self.bump(); assert (x == true); }; }; sync_object.test(); @@ -17,7 +17,7 @@ let async_actor = actor self { bump() { assert (x == false); x := true; assert (x == true); }; - test() : () { assert (x == false); self.bump(); assert (x == false); }; + test() { assert (x == false); self.bump(); assert (x == false); }; }; async_actor.test(); @@ -27,7 +27,7 @@ let async2_actor = actor self { bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); bump(); assert (x == false); is_true(); }; + test() { assert (x == false); bump(); assert (x == false); is_true(); }; is_true() { assert (x == true); }; }; @@ -37,7 +37,7 @@ async2_actor.test(); let async_rec_actor = actor self { private var x : Bool = false; - test(b : Bool) { + test(b : Bool) { if (b) { assert (x == false); x := true; assert (x == true); } else { assert (x == false); test(false); assert (x == false); is_true(); } }; diff --git a/test/run/coverage.as b/test/run/coverage.as index 6b54b9933f0..551da60c8f8 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -10,13 +10,13 @@ func f() { let ?_ = ?0; let ?9 = ?0; - func(_ : Nat) {}; - func(x : Nat) {}; - func(5) {}; - func(5 or 5) {}; - func(5 or _ : Nat) {}; - func(_ or 6 : Nat) {}; - func((_ or _) : Nat) {}; + func f1(_ : Nat) {}; + func f2(x : Nat) {}; + func f3(5) {}; + func f4(5 or 5) {}; + func f5(5 or _ : Nat) {}; + func f6(_ or 6 : Nat) {}; + func f7((_ or _) : Nat) {}; switch 0 { case _ {} }; switch 0 { case x {} }; diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 2d5667ab33d..b432a6df617 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -1,9 +1,9 @@ coverage.as:5.13-5.14: warning, this pattern is never matched coverage.as:7.13-7.14: warning, this pattern is never matched coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.13-16.14: warning, this pattern is never matched -coverage.as:18.13-18.14: warning, this pattern is never matched -coverage.as:19.14-19.15: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched coverage.as:24.25-24.34: warning, this case is never reached coverage.as:27.25-27.34: warning, this case is never reached coverage.as:28.25-28.34: warning, this case is never reached @@ -18,8 +18,8 @@ coverage.as:5.8-5.14: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values coverage.as:10.7-10.9: warning, this pattern does not cover all possible values coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.8-15.9: warning, this pattern does not cover all possible values -coverage.as:16.8-16.14: warning, this pattern does not cover all possible values +coverage.as:15.11-15.12: warning, this pattern does not cover all possible values +coverage.as:16.11-16.17: warning, this pattern does not cover all possible values coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 2d5667ab33d..b432a6df617 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -1,9 +1,9 @@ coverage.as:5.13-5.14: warning, this pattern is never matched coverage.as:7.13-7.14: warning, this pattern is never matched coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.13-16.14: warning, this pattern is never matched -coverage.as:18.13-18.14: warning, this pattern is never matched -coverage.as:19.14-19.15: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched coverage.as:24.25-24.34: warning, this case is never reached coverage.as:27.25-27.34: warning, this case is never reached coverage.as:28.25-28.34: warning, this case is never reached @@ -18,8 +18,8 @@ coverage.as:5.8-5.14: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values coverage.as:10.7-10.9: warning, this pattern does not cover all possible values coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.8-15.9: warning, this pattern does not cover all possible values -coverage.as:16.8-16.14: warning, this pattern does not cover all possible values +coverage.as:15.11-15.12: warning, this pattern does not cover all possible values +coverage.as:16.11-16.17: warning, this pattern does not cover all possible values coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 2d5667ab33d..b432a6df617 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -1,9 +1,9 @@ coverage.as:5.13-5.14: warning, this pattern is never matched coverage.as:7.13-7.14: warning, this pattern is never matched coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.13-16.14: warning, this pattern is never matched -coverage.as:18.13-18.14: warning, this pattern is never matched -coverage.as:19.14-19.15: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched coverage.as:24.25-24.34: warning, this case is never reached coverage.as:27.25-27.34: warning, this case is never reached coverage.as:28.25-28.34: warning, this case is never reached @@ -18,8 +18,8 @@ coverage.as:5.8-5.14: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values coverage.as:10.7-10.9: warning, this pattern does not cover all possible values coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.8-15.9: warning, this pattern does not cover all possible values -coverage.as:16.8-16.14: warning, this pattern does not cover all possible values +coverage.as:15.11-15.12: warning, this pattern does not cover all possible values +coverage.as:16.11-16.17: warning, this pattern does not cover all possible values coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index 2d5667ab33d..b432a6df617 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -1,9 +1,9 @@ coverage.as:5.13-5.14: warning, this pattern is never matched coverage.as:7.13-7.14: warning, this pattern is never matched coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.13-16.14: warning, this pattern is never matched -coverage.as:18.13-18.14: warning, this pattern is never matched -coverage.as:19.14-19.15: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched coverage.as:24.25-24.34: warning, this case is never reached coverage.as:27.25-27.34: warning, this case is never reached coverage.as:28.25-28.34: warning, this case is never reached @@ -18,8 +18,8 @@ coverage.as:5.8-5.14: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values coverage.as:10.7-10.9: warning, this pattern does not cover all possible values coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.8-15.9: warning, this pattern does not cover all possible values -coverage.as:16.8-16.14: warning, this pattern does not cover all possible values +coverage.as:15.11-15.12: warning, this pattern does not cover all possible values +coverage.as:16.11-16.17: warning, this pattern does not cover all possible values coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index 2d5667ab33d..b432a6df617 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -1,9 +1,9 @@ coverage.as:5.13-5.14: warning, this pattern is never matched coverage.as:7.13-7.14: warning, this pattern is never matched coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.13-16.14: warning, this pattern is never matched -coverage.as:18.13-18.14: warning, this pattern is never matched -coverage.as:19.14-19.15: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched coverage.as:24.25-24.34: warning, this case is never reached coverage.as:27.25-27.34: warning, this case is never reached coverage.as:28.25-28.34: warning, this case is never reached @@ -18,8 +18,8 @@ coverage.as:5.8-5.14: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values coverage.as:10.7-10.9: warning, this pattern does not cover all possible values coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.8-15.9: warning, this pattern does not cover all possible values -coverage.as:16.8-16.14: warning, this pattern does not cover all possible values +coverage.as:15.11-15.12: warning, this pattern does not cover all possible values +coverage.as:16.11-16.17: warning, this pattern does not cover all possible values coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values