diff options
| author | Brian Campbell | 2018-02-01 12:59:03 +0000 |
|---|---|---|
| committer | Brian Campbell | 2018-02-01 18:40:34 +0000 |
| commit | 36f26eeedbd5d953df9dc92558882e0bbb555fa8 (patch) | |
| tree | bd89a126e9fecb87794e8d40a558ba6bd39b6548 /src | |
| parent | 9997a4f944d08357cdd07c2cb16015995ffd7a04 (diff) | |
Proper substitution and propagation of size from last commit
Diffstat (limited to 'src')
| -rw-r--r-- | src/monomorphise.ml | 177 |
1 files changed, 99 insertions, 78 deletions
diff --git a/src/monomorphise.ml b/src/monomorphise.ml index aef6829c..663e46d2 100644 --- a/src/monomorphise.ml +++ b/src/monomorphise.ml @@ -799,9 +799,10 @@ let construct_lit_vector args = in the pattern. *) type split = | NoSplit - | VarSplit of (tannot pat * (* pattern for this case *) - (id * tannot Ast.exp) list * (* substitutions for arguments *) - (Parse_ast.l * (int * (id * tannot exp) list)) list) (* optional locations of case expressions to reduce *) + | VarSplit of (tannot pat * (* pattern for this case *) + (id * tannot Ast.exp) list * (* substitutions for arguments *) + (Parse_ast.l * (int * (id * tannot exp) list)) list * (* optional locations of case expressions to reduce *) + (kid * nexp) list) (* substitutions for type variables *) list | ConstrSplit of (tannot pat * nexp KBindings.t) list @@ -1383,26 +1384,26 @@ let split_defs all_errors splits defs = in if all_errors then (no_errors_happened := false; print_error error; - [P_aux (P_id var,(pat_l,annot)),[],[]]) + [P_aux (P_id var,(pat_l,annot)),[],[],[]]) else raise (Fatal_error error) in match ty with | Typ_id (Id_aux (Id "bool",_)) -> - [P_aux (P_lit (L_aux (L_true,new_l)),(l,annot)),[var, E_aux (E_lit (L_aux (L_true,new_l)),(new_l,annot))],[]; - P_aux (P_lit (L_aux (L_false,new_l)),(l,annot)),[var, E_aux (E_lit (L_aux (L_false,new_l)),(new_l,annot))],[]] + [P_aux (P_lit (L_aux (L_true,new_l)),(l,annot)),[var, E_aux (E_lit (L_aux (L_true,new_l)),(new_l,annot))],[],[]; + P_aux (P_lit (L_aux (L_false,new_l)),(l,annot)),[var, E_aux (E_lit (L_aux (L_false,new_l)),(new_l,annot))],[],[]] | Typ_id id -> (try (* enumerations *) let ns = Env.get_enum id env in List.map (fun n -> (P_aux (P_id (renew_id n),(l,annot)), - [var,E_aux (E_id (renew_id n),(new_l,annot))],[])) ns + [var,E_aux (E_id (renew_id n),(new_l,annot))],[],[])) ns with Type_error _ -> match id with | Id_aux (Id "bit",_) -> List.map (fun b -> P_aux (P_lit (L_aux (b,new_l)),(l,annot)), - [var,E_aux (E_lit (L_aux (b,new_l)),(new_l, annot))],[]) + [var,E_aux (E_lit (L_aux (b,new_l)),(new_l, annot))],[],[]) [L_zero; L_one] | _ -> cannot ("don't know about type " ^ string_of_id id)) @@ -1412,25 +1413,26 @@ let split_defs all_errors splits defs = let lits = make_vectors (Big_int.to_int sz) in List.map (fun lit -> P_aux (P_lit lit,(l,annot)), - [var,E_aux (E_lit lit,(new_l,annot))],[]) lits + [var,E_aux (E_lit lit,(new_l,annot))],[],[]) lits | _ -> cannot ("length not constant, " ^ string_of_nexp len) ) (* set constrained numbers *) | Typ_app (Id_aux (Id "atom",_), [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (value,_) as nexp),_)]) -> begin - let mk_lit i = + let mk_lit kid i = let lit = L_aux (L_num i,new_l) in P_aux (P_lit lit,(l,annot)), - [var,E_aux (E_lit lit,(new_l,annot))],[] + [var,E_aux (E_lit lit,(new_l,annot))],[], + match kid with None -> [] | Some k -> [(k,nconstant i)] in match value with - | Nexp_constant i -> [mk_lit i] + | Nexp_constant i -> [mk_lit None i] | Nexp_var kvar -> let ncs = Env.get_constraints env in let nc = List.fold_left nc_and nc_true ncs in (match extract_set_nc l kvar nc with - | (is,_) -> List.map mk_lit is + | (is,_) -> List.map (mk_lit (Some kvar)) is | exception Reporting_basic.Fatal_error (Reporting_basic.Err_general (_,msg)) -> cannot msg) | _ -> cannot ("unsupport atom nexp " ^ string_of_nexp nexp) end @@ -1464,32 +1466,32 @@ let split_defs all_errors splits defs = | h::t -> let t' = match list f t with - | None -> [t,[],[]] + | None -> [t,[],[],[]] | Some t' -> t' in let h' = match f h with - | None -> [h,[],[]] + | None -> [h,[],[],[]] | Some ps -> ps in Some (List.concat - (List.map (fun (h,hsubs,hpchoices) -> - List.map (fun (t,tsubs,tpchoices) -> - (h::t, hsubs@tsubs, hpchoices@tpchoices)) t') h')) + (List.map (fun (h,hsubs,hpchoices,hksubs) -> + List.map (fun (t,tsubs,tpchoices,tksubs) -> + (h::t, hsubs@tsubs, hpchoices@tpchoices, hksubs@tksubs)) t') h')) in let rec spl (P_aux (p,(l,annot))) = let relist f ctx ps = optmap (list f ps) (fun ps -> - List.map (fun (ps,sub,pchoices) -> P_aux (ctx ps,(l,annot)),sub,pchoices) ps) + List.map (fun (ps,sub,pchoices,ksub) -> P_aux (ctx ps,(l,annot)),sub,pchoices,ksub) ps) in let re f p = optmap (spl p) - (fun ps -> List.map (fun (p,sub,pchoices) -> (P_aux (f p,(l,annot)), sub, pchoices)) ps) + (fun ps -> List.map (fun (p,sub,pchoices,ksub) -> (P_aux (f p,(l,annot)), sub, pchoices, ksub)) ps) in let fpat (FP_aux ((FP_Fpat (id,p),annot))) = optmap (spl p) - (fun ps -> List.map (fun (p,sub,pchoices) -> FP_aux (FP_Fpat (id,p), annot), sub, pchoices) ps) + (fun ps -> List.map (fun (p,sub,pchoices,ksub) -> FP_aux (FP_Fpat (id,p), annot), sub, pchoices, ksub) ps) in match p with | P_lit _ @@ -1515,14 +1517,24 @@ let split_defs all_errors splits defs = match p with | P_aux (P_lit lit,(pl,pannot)) when (match lit with L_aux (L_undef,_) -> false | _ -> true) -> - p,[id,E_aux (E_lit lit,(Generated pl,pannot))],[l,(i,[])] + let orig_typ = Env.base_typ_of (env_of_annot (l,annot)) (typ_of_annot (l,annot)) in + let kid_subst = match lit, orig_typ with + | L_aux (L_num i,_), + Typ_aux + (Typ_app (Id_aux (Id "atom",_), + [Typ_arg_aux (Typ_arg_nexp + (Nexp_aux (Nexp_var var,_)),_)]),_) -> + [var,nconstant i] + | _ -> [] + in + p,[id,E_aux (E_lit lit,(Generated pl,pannot))],[l,(i,[])],kid_subst | _ -> let p',subst = freshen_pat_bindings p in match p' with | P_aux (P_wild,_) -> - P_aux (P_id id,(l,annot)),[],[l,(i,subst)] + P_aux (P_id id,(l,annot)),[],[l,(i,subst)],[] | _ -> - P_aux (P_as (p',id),(l,annot)),[],[l,(i,subst)]) + P_aux (P_as (p',id),(l,annot)),[],[l,(i,subst)],[]) pats) ) | P_app (id,ps) -> @@ -1541,10 +1553,10 @@ let split_defs all_errors splits defs = match spl p1, spl p2 with | None, None -> None | p1', p2' -> - let p1' = match p1' with None -> [p1,[],[]] | Some p1' -> p1' in - let p2' = match p2' with None -> [p2,[],[]] | Some p2' -> p2' in - let ps = List.map (fun (p1',subs1,pchoices1) -> List.map (fun (p2',subs2,pchoices2) -> - P_aux (P_cons (p1',p2'),(l,annot)),subs1@subs2,pchoices1@pchoices2) p2') p1' in + let p1' = match p1' with None -> [p1,[],[],[]] | Some p1' -> p1' in + let p2' = match p2' with None -> [p2,[],[],[]] | Some p2' -> p2' in + let ps = List.map (fun (p1',subs1,pchoices1,ksub1) -> List.map (fun (p2',subs2,pchoices2,ksub2) -> + P_aux (P_cons (p1',p2'),(l,annot)),subs1@subs2,pchoices1@pchoices2,ksub1@ksub2) p2') p1' in Some (List.concat ps) in spl p in @@ -1686,8 +1698,9 @@ let split_defs all_errors splits defs = | NoSplit -> nosplit | VarSplit patsubsts -> if check_split_size patsubsts (pat_loc p) then - List.map (fun (pat',substs,pchoices) -> - let exp' = subst_exp substs e in + List.map (fun (pat',substs,pchoices,ksubsts) -> + let exp' = nexp_subst_exp (kbindings_from_list ksubsts) e in + let exp' = subst_exp substs exp' in let exp' = apply_pat_choices pchoices exp' in Pat_aux (Pat_exp (pat', map_exp exp'),l)) patsubsts @@ -1704,10 +1717,12 @@ let split_defs all_errors splits defs = | NoSplit -> nosplit | VarSplit patsubsts -> if check_split_size patsubsts (pat_loc p) then - List.map (fun (pat',substs,pchoices) -> - let exp1' = subst_exp substs e1 in + List.map (fun (pat',substs,pchoices,ksubsts) -> + let exp1' = nexp_subst_exp (kbindings_from_list ksubsts) e1 in + let exp1' = subst_exp substs exp1' in let exp1' = apply_pat_choices pchoices exp1' in - let exp2' = subst_exp substs e2 in + let exp2' = nexp_subst_exp (kbindings_from_list ksubsts) e2 in + let exp2' = subst_exp substs exp2' in let exp2' = apply_pat_choices pchoices exp2' in Pat_aux (Pat_when (pat', map_exp exp1', map_exp exp2'),l)) patsubsts @@ -2729,13 +2744,11 @@ and analyse_lexp fn_id env assigns deps (LEXP_aux (lexp,_)) = | LEXP_field (lexp,_) -> analyse_lexp fn_id env assigns deps lexp -let translate_id (Id_aux (_,l) as id) = - let rec aux l = - match l with - | Range (pos,_) -> Some (id,(pos.Lexing.pos_fname,pos.Lexing.pos_lnum)) - | Generated l -> aux l - | _ -> None - in aux l +let rec translate_loc l = + match l with + | Range (pos,_) -> Some (pos.Lexing.pos_fname,pos.Lexing.pos_lnum) + | Generated l -> translate_loc l + | _ -> None let initial_env fn_id fn_l (TypQ_aux (tq,_)) pat set_assertions = let pats = @@ -2778,10 +2791,10 @@ let initial_env fn_id fn_l (TypQ_aux (tq,_)) pat set_assertions = | P_as (pat,id) -> begin let s,v,k = aux pat in - match translate_id id with - | Some id' -> - ArgSplits.add id' Total s, - Bindings.add id (Have (ArgSplits.singleton id' Total, ExtraSplits.empty)) v, + match translate_loc (id_loc id) with + | Some loc -> + ArgSplits.add (id,loc) Total s, + Bindings.add id (Have (ArgSplits.singleton (id,loc) Total, ExtraSplits.empty)) v, k | None -> s, @@ -2791,11 +2804,11 @@ let initial_env fn_id fn_l (TypQ_aux (tq,_)) pat set_assertions = | P_typ (_,pat) -> aux pat | P_id id -> begin - match translate_id id with - | Some id' -> + match translate_loc (id_loc id) with + | Some loc -> let kid_opt = kid_of_annot (l,annot) in let split = Util.option_cases kid_opt (default_split annot) (fun () -> Total) in - let s = ArgSplits.singleton id' split in + let s = ArgSplits.singleton (id,loc) split in s, Bindings.singleton id (Have (s, ExtraSplits.empty)), (match kid_opt with @@ -2975,12 +2988,14 @@ let analyse_def debug env = function | _ -> empty +let detail_to_split = function + | Total -> None + | Partial (pats,l) -> Some (pats,l) let argset_to_list splits = let l = ArgSplits.bindings splits in let argelt = function - | ((id,(file,loc)),Total) -> ((file,loc),string_of_id id,None) - | ((id,(file,loc)),Partial (pats,l)) -> ((file,loc),string_of_id id,Some (pats,l)) + | ((id,(file,loc)),detail) -> ((file,loc),string_of_id id,detail_to_split detail) in List.map argelt l @@ -3031,46 +3046,51 @@ let analyse_defs debug env (Defs defs) = end +let fresh_sz_var = + let counter = ref 0 in + fun () -> + let n = !counter in + let () = counter := n+1 in + mk_id ("sz#" ^ string_of_int n) + let add_extra_splits extras (Defs defs) = let success = ref true in let add_to_body extras (E_aux (_,(l,annot)) as e) = - let l = Generated l in - KBindings.fold (fun kid detail exp -> - match detail with - | Analysis.Total -> - (success := false; - Reporting_basic.print_err false true (kid_loc kid) "Monomorphisation" - ("Don't know how to case split type variable " ^ string_of_kid kid); - e) - | Analysis.Partial (pats,_) -> - let ksubst = function - | P_aux (P_lit (L_aux (L_num i,_)),_) -> KBindings.singleton kid (nconstant i) - | _ -> KBindings.empty - in - let pexps = List.map (fun p -> Pat_aux (Pat_exp (p,nexp_subst_exp (ksubst p) e),(l,annot))) pats - in + let l' = Generated l in + KBindings.fold (fun kid detail (exp,split_list) -> let nexp = Nexp_aux (Nexp_var kid,l) in - E_aux (E_case - (E_aux (E_sizeof nexp, - (l,Some (env_of e,atom_typ nexp,no_effect))), - pexps),(l,annot)) - ) extras e + let var = fresh_sz_var () in + let size_annot = Some (env_of e,atom_typ nexp,no_effect) in + let loc = match Analysis.translate_loc l with + | Some l -> l + | None -> + (Reporting_basic.print_err false false l "Monomorphisation" + "Internal error: bad location for added case"; + ("",0)) + in + let pexps = [Pat_aux (Pat_exp (P_aux (P_id var,(l,size_annot)),exp),(l',annot))] in + E_aux (E_case (E_aux (E_sizeof nexp, (l',size_annot)), pexps),(l',annot)), + ((loc, string_of_id var, Analysis.detail_to_split detail)::split_list) + ) extras (e,[]) in let add_to_funcl (FCL_aux (FCL_Funcl (id,Pat_aux (pexp,peannot)),(l,annot))) = - let pexp = + let pexp, splits = match Analysis.ExtraSplits.find (id,l) extras with | extras -> (match pexp with - | Pat_exp (p,e) -> Pat_exp (p,add_to_body extras e) - | Pat_when (p,g,e) -> Pat_when (p,g,add_to_body extras e)) - | exception Not_found -> pexp - in FCL_aux (FCL_Funcl (id,Pat_aux (pexp,peannot)),(l,annot)) + | Pat_exp (p,e) -> let e',sp = add_to_body extras e in Pat_exp (p,e'), sp + | Pat_when (p,g,e) -> let e',sp = add_to_body extras e in Pat_when (p,g,e'), sp) + | exception Not_found -> pexp, [] + in FCL_aux (FCL_Funcl (id,Pat_aux (pexp,peannot)),(l,annot)), splits in let add_to_def = function | DEF_fundef (FD_aux (FD_function (re,ta,ef,funcls),annot)) -> - DEF_fundef (FD_aux (FD_function (re,ta,ef,List.map add_to_funcl funcls),annot)) - | d -> d - in !success, Defs (List.map add_to_def defs) + let funcls,splits = List.split (List.map add_to_funcl funcls) in + DEF_fundef (FD_aux (FD_function (re,ta,ef,funcls),annot)), List.concat splits + | d -> d, [] + in + let defs, splits = List.split (List.map add_to_def defs) in + !success, Defs defs, List.concat splits module MonoRewrites = struct @@ -3323,7 +3343,8 @@ let monomorphise opts splits env defs = else raise (Reporting_basic.err_general Unknown "Unable to monomorphise program") else true, [], Analysis.ExtraSplits.empty in let splits = new_splits @ (List.map (fun (loc,id) -> (loc,id,None)) splits) in - let ok_extras, defs = add_extra_splits extra_splits defs in + let ok_extras, defs, extra_splits = add_extra_splits extra_splits defs in + let splits = splits @ extra_splits in let () = if ok_extras || opts.all_split_errors || opts.continue_anyway then () else raise (Reporting_basic.err_general Unknown "Unable to monomorphise program") |
