summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKathy Gray2015-02-04 18:05:06 +0000
committerKathy Gray2015-02-04 18:05:06 +0000
commit45925f6aaf9a130fa48d9fbec2b7c05da2d7bb42 (patch)
tree08a89d1f90bce4449586294c2f5d730975750a9d /src
parentacbc92fe72f196d06b28e3e7137a9d304a2c79d3 (diff)
collect and carry around more data for dependency tracking
Diffstat (limited to 'src')
-rw-r--r--src/process_file.ml2
-rw-r--r--src/type_check.ml728
-rw-r--r--src/type_check.mli2
-rw-r--r--src/type_internal.ml48
-rw-r--r--src/type_internal.mli19
5 files changed, 410 insertions, 389 deletions
diff --git a/src/process_file.ml b/src/process_file.ml
index deca5d53..7caf5172 100644
--- a/src/process_file.ml
+++ b/src/process_file.ml
@@ -98,7 +98,7 @@ let check_ast (defs : Type_internal.tannot Ast.defs) (k : kind Envmap.t) (o:Ast.
Type_internal.default_o =
{Type_internal.order = (match o with | (Ast.Ord_aux(Ast.Ord_inc,_)) -> Type_internal.Oinc
| (Ast.Ord_aux(Ast.Ord_dec,_)) -> Type_internal.Odec)};} in
- Type_check.check (Type_check.Env (d_env, Type_internal.initial_typ_env)) defs
+ Type_check.check (Type_check.Env (d_env, Type_internal.initial_typ_env,Type_internal.nob)) defs
let open_output_with_check file_name =
let (temp_file_name, o) = Filename.open_temp_file "ll_temp" "" in
diff --git a/src/type_check.ml b/src/type_check.ml
index a91dba87..5117e9c2 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -6,7 +6,7 @@ type typ = Type_internal.t
type 'a exp = 'a Ast.exp
type 'a emap = 'a Envmap.t
-type envs = Env of def_envs * tannot emap
+type envs = Env of def_envs * tannot emap * bounds_env
type 'a envs_out = 'a * envs
let id_to_string (Id_aux(id,l)) =
@@ -133,7 +133,7 @@ and aorder_to_ord (Ord_aux(o,l) : Ast.order) =
| Ord_inc -> {order = Oinc}
| Ord_dec -> {order = Odec}
-let rec quants_to_consts ((Env (d_env,t_env)) as env) qis : (t_params * t_arg list * nexp_range list) =
+let rec quants_to_consts ((Env (d_env,t_env,b_env)) as env) qis : (t_params * t_arg list * nexp_range list) =
match qis with
| [] -> [],[],[]
| (QI_aux(qi,l))::qis ->
@@ -189,8 +189,8 @@ let into_register d_env (t : tannot) : tannot =
| _ -> Base((ids, {t= Tapp("register",[TA_typ ty'])}),tag,constraints,eft,bindings))
| t -> t
-let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat) * (tannot emap) * nexp_range list * t) =
- let (Env(d_env,t_env)) = envs in
+let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat) * (tannot emap) * nexp_range list * bounds_env * t) =
+ let (Env(d_env,t_env,b_env)) = envs in
let expect_t,cs = get_abbrev d_env expect_t in
let expect_actual = match expect_t.t with | Tabbrev(_,t) -> t | _ -> expect_t in
match p with
@@ -229,38 +229,34 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
| L_undef -> typ_error l' "Cannot pattern match on undefined") in
let t',cs' = type_consistent (Patt l) d_env true t expect_t in
let cs_l = cs@cs' in
- (P_aux(P_lit(L_aux(lit,l')),(l,Base(([],t),emp_tag,cs_l,pure_e,nob))),Envmap.empty,cs_l,t)
+ (P_aux(P_lit(L_aux(lit,l')),(l,cons_tag_annot t emp_tag cs_l)),Envmap.empty,cs_l,nob,t)
| P_wild ->
- (P_aux(p,(l,constrained_annot expect_t cs)),Envmap.empty,cs,expect_t)
+ (P_aux(p,(l,cons_tag_annot expect_t emp_tag cs)),Envmap.empty,cs,nob,expect_t)
| P_as(pat,id) ->
let v = id_to_string id in
- let (pat',env,constraints,t) = check_pattern envs emp_tag expect_t pat in
- let tannot = Base(([],t),emp_tag,cs,pure_e,build_binding d_env v t) in
- (P_aux(P_as(pat',id),(l,tannot)),Envmap.insert env (v,tannot),cs@constraints,t)
+ let (pat',env,constraints,bounds,t) = check_pattern envs emp_tag expect_t pat in
+ let bounds = extract_bounds d_env v t in
+ let tannot = Base(([],t),emp_tag,cs,pure_e,bounds) in
+ (P_aux(P_as(pat',id),(l,tannot)),Envmap.insert env (v,tannot),cs@constraints,bounds,t)
| P_typ(typ,pat) ->
let t = typ_to_t false false typ in
- let (pat',env,constraints,u) = check_pattern envs emp_tag t pat in
- let binding =
- match pat' with
- | P_aux(P_id id,_) ->
- build_binding d_env (id_to_string id) t
- | _ -> nob in
- (*TODO Potentially this should refine more bindings *)
- (P_aux(P_typ(typ,pat'),(l,Base(([],t),Emp_local,[],pure_e,binding))),env,cs@constraints,t)
+ let (pat',env,constraints,bounds,u) = check_pattern envs emp_tag t pat in
+ (*potentially this should refine bounds*)
+ (P_aux(P_typ(typ,pat'),(l,tag_annot t emp_tag)),env,cs@constraints,bounds,t)
| P_id id ->
let i = id_to_string id in
- let default = let tannot = Base(([],expect_t),emp_tag,cs,pure_e,nob) in
- (P_aux(p,(l,tannot)),Envmap.from_list [(i,tannot)],cs,expect_t) in
- (*TODO This is where bindings come from part 2, with a twist as we don't know the type yet usually*)
+ let default_bounds = extract_bounds d_env i expect_t in
+ let default = let tannot = Base(([],expect_t),emp_tag,cs,pure_e,default_bounds) in
+ (P_aux(p,(l,tannot)),Envmap.from_list [(i,tannot)],cs,default_bounds,expect_t) in
(match Envmap.apply t_env i with
- | Some(Base((params,t),Constructor,cs,ef,bindings)) ->
+ | Some(Base((params,t),Constructor,cs,ef,bounds)) ->
let t,cs,ef = subst params t cs ef in
(match t.t with
| Tfn({t = Tid "unit"},t',IP_none,ef) ->
if conforms_to_t d_env false false t' expect_t
then
let tp,cp = type_consistent (Expr l) d_env false t' expect_t in
- (P_aux(P_app(id,[]),(l,(Base(([],t),Constructor,[],pure_e,nob)))),Envmap.empty,cs@cp,tp)
+ (P_aux(P_app(id,[]),(l,tag_annot t Constructor)),Envmap.empty,cs@cp,bounds,tp)
else default
| Tfn(t1,t',IP_none,e) ->
if conforms_to_t d_env false false t' expect_t
@@ -272,60 +268,60 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
let i = id_to_string id in
(match Envmap.apply t_env i with
| None | Some NoTyp | Some Overload _ -> typ_error l ("Constructor " ^ i ^ " in pattern is undefined")
- | Some(Base((params,t),Constructor,constraints,eft,bindings)) ->
+ | Some(Base((params,t),Constructor,constraints,eft,bounds)) ->
let t,constraints,_ = subst params t constraints eft in
(match t.t with
- | Tid id -> if pats = [] then
- let t',constraints' = type_consistent (Patt l) d_env false t expect_t in
- (P_aux(p,(l,Base(([],t'),Constructor,constraints,pure_e,nob))),
- Envmap.empty,constraints@constraints',t')
+ | Tid id -> if pats = []
+ then let t',constraints' = type_consistent (Patt l) d_env false t expect_t in
+ (P_aux(p,(l,cons_tag_annot t' Constructor constraints)), Envmap.empty,constraints@constraints',nob,t')
else typ_error l ("Constructor " ^ i ^ " does not expect arguments")
| Tfn(t1,t2,IP_none,ef) ->
(match pats with
| [] -> let _ = type_consistent (Patt l) d_env false unit_t t1 in
let t',constraints' = type_consistent (Patt l) d_env false t2 expect_t in
- (P_aux(P_app(id,[]),(l,Base(([],t'),Constructor,constraints,pure_e,bindings))),Envmap.empty,constraints@constraints',t')
- | [p] -> let (p',env,constraints,u) = check_pattern envs emp_tag t1 p in
+ (P_aux(P_app(id,[]),(l,cons_tag_annot t' Constructor constraints)), Envmap.empty,constraints@constraints',nob,t')
+ | [p] -> let (p',env,constraints,bounds,u) = check_pattern envs emp_tag t1 p in
let t',constraints' = type_consistent (Patt l) d_env false t2 expect_t in
- (P_aux(P_app(id,[p']),(l,Base(([],t'),Constructor,constraints,pure_e,bindings))),env,constraints@constraints',t')
- | pats -> let (pats',env,constraints,u) =
+ (P_aux(P_app(id,[p']),(l,cons_tag_annot t' Constructor constraints)),env,constraints@constraints',bounds,t')
+ | pats -> let (pats',env,constraints,bounds,u) =
match check_pattern envs emp_tag t1 (P_aux(P_tup(pats),(l,annot))) with
- | ((P_aux(P_tup(pats'),_)),env,constraints,u) -> pats',env,constraints,u
+ | ((P_aux(P_tup(pats'),_)),env,constraints,bounds,u) -> (pats',env,constraints,bounds,u)
| _ -> assert false in
let t',constraints' = type_consistent (Patt l) d_env false t2 expect_t in
- (P_aux(P_app(id,pats'),(l,Base(([],t'),Constructor,constraints,pure_e,bindings))),env,constraints@constraints',t'))
- | _ -> typ_error l ("Identifier " ^ i ^ " is not bound to a constructor"))
- | Some(Base((params,t),tag,constraints,eft,bindings)) -> typ_error l ("Identifier " ^ i ^ " used in pattern is not a constructor"))
+ (P_aux(P_app(id,pats'),(l,cons_tag_annot t' Constructor constraints)),env,constraints@constraints',bounds,t'))
+ | _ -> typ_error l ("Identifier " ^ i ^ " must be a union constructor"))
+ | Some(Base((params,t),tag,constraints,eft,bounds)) ->
+ typ_error l ("Identifier " ^ i ^ " used in pattern is not a union constructor"))
| P_record(fpats,_) ->
(match (fields_to_rec fpats d_env.rec_env) with
| None -> typ_error l ("No struct exists with the listed fields")
| Some(id,typ_pats) ->
let pat_checks =
List.map (fun (tan,id,l,pat) ->
- let (Base((vs,t),tag,cs,eft,bindings)) = tan in
+ let (Base((vs,t),tag,cs,eft,bounds)) = tan in
let t,cs,_ = subst vs t cs eft in
- let (pat,env,constraints,u) = check_pattern envs emp_tag t pat in
- (*TODO This is a location where a binding is introduced part 3, no twists*)
- let pat = FP_aux(FP_Fpat(id,pat),(l,Base(([],t),tag,cs,pure_e,bindings))) in
- (pat,env,cs@constraints)) typ_pats in
- let pats' = List.map (fun (a,b,c) -> a) pat_checks in
+ let (pat,env,constraints,new_bounds,u) = check_pattern envs emp_tag t pat in
+ let pat = FP_aux(FP_Fpat(id,pat),(l,Base(([],t),tag,cs,pure_e,bounds))) in
+ (pat,env,cs@constraints,merge_bounds bounds new_bounds)) typ_pats in
+ let pats' = List.map (fun (a,_,_,_) -> a) pat_checks in
(*Need to check for variable duplication here*)
- let env = List.fold_right (fun (_,env,_) env' -> Envmap.union env env') pat_checks Envmap.empty in
- let constraints = List.fold_right (fun (_,_,cs) cons -> cs@cons) pat_checks [] in
+ let env = List.fold_right (fun (_,env,_,_) env' -> Envmap.union env env') pat_checks Envmap.empty in
+ let constraints = (List.fold_right (fun (_,_,cs,_) cons -> cs@cons) pat_checks [])@cs in
+ let bounds = List.fold_right (fun (_,_,_,bounds) b_env -> merge_bounds bounds b_env) pat_checks nob in
let t = {t=Tid id} in
let t',cs' = type_consistent (Patt l) d_env false t expect_t in
- (P_aux((P_record(pats',false)),(l,Base(([],t'),Emp_local,constraints@cs',pure_e,nob))),env,constraints@cs',t'))
+ (P_aux((P_record(pats',false)),(l,cons_tag_annot t' emp_tag (cs@cs'))),env,constraints@cs',bounds,t'))
| P_vector pats ->
let (item_t, base, rise, ord) = match expect_actual.t with
| Tapp("vector",[TA_nexp b;TA_nexp r;TA_ord o;TA_typ i]) -> (i,b,r,o)
| Tuvar _ -> (new_t (),new_n (),new_n(), d_env.default_o)
- | _ -> typ_error l ("Expected a vector by pattern form, but a " ^ t_to_string expect_actual ^ " by type") in
- let (pats',ts,t_envs,constraints) =
+ | _ -> typ_error l ("Expected a " ^ t_to_string expect_actual ^ " but found a vector") in
+ let (pats',ts,t_envs,constraints,bounds) =
List.fold_right
- (fun pat (pats,ts,t_envs,constraints) ->
- let (pat',t_env,cons,t) = check_pattern envs emp_tag item_t pat in
- ((pat'::pats),(t::ts),(t_env::t_envs),(cons@constraints)))
- pats ([],[],[],[]) in
+ (fun pat (pats,ts,t_envs,constraints,bounds) ->
+ let (pat',t_env,cons,bs,t) = check_pattern envs emp_tag item_t pat in
+ ((pat'::pats),(t::ts),(t_env::t_envs),(cons@constraints),merge_bounds bs bounds))
+ pats ([],[],[],[],nob) in
let env = List.fold_right (fun e env -> Envmap.union e env) t_envs Envmap.empty in (*Need to check for non-duplication of variables*)
let (u,cs) = List.fold_right (fun u (t,cs) -> let t',cs = type_consistent (Patt l) d_env true u t in t',cs) ts (item_t,[]) in
let len = List.length ts in
@@ -343,7 +339,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
TA_typ u;])}
| _ -> raise (Reporting_basic.err_unreachable l "Default order not set") in
(*TODO Should gather the constraints here, with regard to the expected base and rise, and potentially reset them above*)
- (P_aux(P_vector(pats'),(l,Base(([],t),Emp_local,cs,pure_e,nob))), env,cs@constraints,t)
+ (P_aux(P_vector(pats'),(l,cons_tag_annot t emp_tag cs)), env,cs@constraints,bounds,t)
| P_vector_indexed(ipats) ->
let item_t = match expect_actual.t with
| Tapp("vector",[b;r;o;TA_typ i]) -> i
@@ -364,12 +360,12 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
false)
else typ_error l "Indexed vector cannot be determined as either increasing or decreasing" in
let base,rise = new_n (), new_n () in
- let (pats',ts,t_envs,constraints) =
+ let (pats',ts,t_envs,constraints,bounds) =
List.fold_right
- (fun (i,pat) (pats,ts,t_envs,constraints) ->
- let (pat',env,cons,t) = check_pattern envs emp_tag item_t pat in
- (((i,pat')::pats),(t::ts),(env::t_envs),(cons@constraints)))
- ipats ([],[],[],[]) in
+ (fun (i,pat) (pats,ts,t_envs,constraints,bounds) ->
+ let (pat',env,cons,new_bounds,t) = check_pattern envs emp_tag item_t pat in
+ (((i,pat')::pats),(t::ts),(env::t_envs),(cons@constraints),merge_bounds new_bounds bounds))
+ ipats ([],[],[],[],nob) in
let co = Patt l in
let env = List.fold_right (fun e env -> Envmap.union e env) t_envs Envmap.empty in (*TODO Need to check for non-duplication of variables*)
let (u,cs) = List.fold_right (fun u (t,cs) -> type_consistent co d_env true u t) ts (item_t,[]) in
@@ -380,7 +376,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
GtEq(co,rise, {nexp = Nconst (big_int_of_int (lst-fst))});]@cs
else [GtEq(co,base, {nexp = Nconst (big_int_of_int fst)});
LtEq(co,rise, { nexp = Nconst (big_int_of_int (fst -lst))});]@cs in
- (P_aux(P_vector_indexed(pats'),(l,Base(([],t),Emp_local,cs,pure_e,nob))), env,constraints@cs,t)
+ (P_aux(P_vector_indexed(pats'),(l,cons_tag_annot t emp_tag cs)), env,constraints@cs,bounds,t)
| P_tup(pats) ->
let item_ts = match expect_actual.t with
| Ttup ts ->
@@ -389,15 +385,15 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
else typ_error l ("Expected a pattern with a tuple with " ^ (string_of_int (List.length ts)) ^ " elements")
| Tuvar _ -> List.map (fun _ -> new_t ()) pats
| _ -> typ_error l ("Expected a tuple by pattern form, but a " ^ (t_to_string expect_actual) ^ " by type") in
- let (pats',ts,t_envs,constraints) =
+ let (pats',ts,t_envs,constraints,bounds) =
List.fold_right
- (fun (pat,t) (pats,ts,t_envs,constraints) ->
- let (pat',env,cons,t) = check_pattern envs emp_tag t pat in
- ((pat'::pats),(t::ts),(env::t_envs),cons@constraints))
- (List.combine pats item_ts) ([],[],[],[]) in
+ (fun (pat,t) (pats,ts,t_envs,constraints,bounds) ->
+ let (pat',env,cons,new_bounds,t) = check_pattern envs emp_tag t pat in
+ ((pat'::pats),(t::ts),(env::t_envs),cons@constraints,merge_bounds new_bounds bounds))
+ (List.combine pats item_ts) ([],[],[],[],nob) in
let env = List.fold_right (fun e env -> Envmap.union e env) t_envs Envmap.empty in (*Need to check for non-duplication of variables*)
let t = {t = Ttup ts} in
- (P_aux(P_tup(pats'),(l,Base(([],t),Emp_local,[],pure_e,nob))), env,constraints,t)
+ (P_aux(P_tup(pats'),(l,tag_annot t emp_tag)), env,constraints,bounds,t)
| P_vector_concat pats ->
let item_t,base,rise,order =
match expect_t.t with
@@ -405,12 +401,12 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
| Tabbrev(_,{t=Tapp("vector",[TA_nexp(b);TA_nexp(r);TA_ord(o);TA_typ item])}) -> item,b,r,o
| _ -> new_t (),new_n (), new_n (), d_env.default_o in
let vec_ti _ = {t= Tapp("vector",[TA_nexp (new_n ());TA_nexp (new_n ());TA_ord order;TA_typ item_t])} in
- let (pats',ts,envs,constraints) =
+ let (pats',ts,envs,constraints,bounds) =
List.fold_right
- (fun pat (pats,ts,t_envs,constraints) ->
- let (pat',env,cons,t) = check_pattern envs emp_tag (vec_ti ()) pat in
- (pat'::pats,t::ts,env::t_envs,cons@constraints))
- pats ([],[],[],[]) in
+ (fun pat (pats,ts,t_envs,constraints,bounds) ->
+ let (pat',env,cons,new_bounds,t) = check_pattern envs emp_tag (vec_ti ()) pat in
+ (pat'::pats,t::ts,env::t_envs,cons@constraints,merge_bounds new_bounds bounds))
+ pats ([],[],[],[],nob) in
let env =
List.fold_right (fun e env -> Envmap.union e env) envs Envmap.empty in (*Need to check for non-duplication of variables*)
let t = {t = Tapp("vector",[(TA_nexp base);(TA_nexp rise);(TA_ord order);(TA_typ item_t)])} in
@@ -423,60 +419,60 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
| Tapp("vector",[(TA_nexp b);(TA_nexp r);(TA_ord o);(TA_typ u)]) -> {nexp = Nadd(r,rn)}
| _ -> raise (Reporting_basic.err_unreachable l "vector concat pattern impossibility") ) (List.tl ts) r1 in
let cs = [Eq((Patt l),rise,range_c)]@cs in
- (P_aux(P_vector_concat(pats'),(l,Base(([],t),Emp_local,cs,pure_e,nob))), env,constraints@cs,t)
+ (P_aux(P_vector_concat(pats'),(l,cons_tag_annot t emp_tag cs)), env,constraints@cs,bounds,t)
| P_list(pats) ->
let item_t = match expect_actual.t with
| Tapp("list",[TA_typ i]) -> i
| Tuvar _ -> new_t ()
| _ -> typ_error l ("Expected a list here by pattern form, but expected a " ^ t_to_string expect_actual ^ " by type") in
- let (pats',ts,envs,constraints) =
+ let (pats',ts,envs,constraints,bounds) =
List.fold_right
- (fun pat (pats,ts,t_envs,constraints) ->
- let (pat',env,cons,t) = check_pattern envs emp_tag item_t pat in
- (pat'::pats,t::ts,env::t_envs,cons@constraints))
- pats ([],[],[],[]) in
+ (fun pat (pats,ts,t_envs,constraints,bounds) ->
+ let (pat',env,cons,new_bounds,t) = check_pattern envs emp_tag item_t pat in
+ (pat'::pats,t::ts,env::t_envs,cons@constraints,merge_bounds new_bounds bounds))
+ pats ([],[],[],[],nob) in
let env = List.fold_right (fun e env -> Envmap.union e env) envs Envmap.empty in (*TODO Need to check for non-duplication of variables*)
let u,cs = List.fold_right (fun u (t,cs) -> let t',cs' = type_consistent (Patt l) d_env true u t in t',cs@cs') ts (item_t,[]) in
let t = {t = Tapp("list",[TA_typ u])} in
- (P_aux(P_list(pats'),(l,Base(([],t),Emp_local,cs,pure_e,nob))), env,constraints@cs,t)
+ (P_aux(P_list(pats'),(l,cons_tag_annot t emp_tag cs)), env,constraints@cs,bounds,t)
-let simp_exp e l t = E_aux(e,(l,Base(([],t),Emp_local,[],pure_e,nob)))
+let simp_exp e l t = E_aux(e,(l,simple_annot t))
-let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):tannot exp): (tannot exp * t * tannot emap * nexp_range list * effect) =
- let Env(d_env,t_env) = envs in
+let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):tannot exp): (tannot exp * t * tannot emap * nexp_range list * bounds_env * effect) =
+ let Env(d_env,t_env,b_env) = envs in
let expect_t,_ = get_abbrev d_env expect_t in
let rebuild annot = E_aux(e,(l,annot)) in
match e with
| E_block exps ->
- let (exps',annot',t_env',sc,t,ef) = check_block t_env envs imp_param expect_t exps in
- (E_aux(E_block(exps'),(l,annot')),t, t_env',sc,ef)
+ let (exps',annot',sc,t,ef) = check_block envs imp_param expect_t exps in
+ (E_aux(E_block(exps'),(l,annot')),t,Envmap.empty,sc,nob,ef)
| E_nondet exps ->
let (ces, sc, ef) =
- List.fold_right (fun e (es,sc,ef) -> let (e,_,_,sc',ef') = (check_exp envs imp_param unit_t e) in
+ List.fold_right (fun e (es,sc,ef) -> let (e,_,_,sc',_,ef') = (check_exp envs imp_param unit_t e) in
(e::es,sc@sc',union_effects ef ef')) exps ([],[],pure_e) in
let _,cs = type_consistent (Expr l) d_env false unit_t expect_t in
- (E_aux (E_nondet ces,(l,Base(([],unit_t), Emp_local,sc,ef,nob))),unit_t,t_env,sc,ef)
+ (E_aux (E_nondet ces,(l,cons_ef_annot unit_t sc ef)),unit_t,t_env,sc,nob,ef)
| E_id id ->
let i = id_to_string id in
(match Envmap.apply t_env i with
- | Some(Base((params,t),Constructor,cs,ef,bindings)) ->
+ | Some(Base((params,t),Constructor,cs,ef,bounds)) ->
let t,cs,ef = subst params t cs ef in
(match t.t with
| Tfn({t = Tid "unit"},t',IP_none,ef) ->
let t',cs',ef',e' = type_coerce (Expr l) d_env false false t'
- (rebuild (Base(([],{t=Tfn(unit_t,t',IP_none,ef)}),Constructor,cs,ef,bindings))) expect_t in
- (e',t',t_env,cs@cs',union_effects ef ef')
+ (rebuild (Base(([],{t=Tfn(unit_t,t',IP_none,ef)}),Constructor,cs,ef,bounds))) expect_t in
+ (e',t',t_env,cs@cs',nob,union_effects ef ef')
| Tfn(t1,t',IP_none,e) ->
typ_error l ("Constructor " ^ i ^ " expects arguments of type " ^ (t_to_string t) ^ ", found none")
| _ -> raise (Reporting_basic.err_unreachable l "Constructor tannot does not have function type"))
- | Some(Base((params,t),Enum,cs,ef,bindings)) ->
+ | Some(Base((params,t),Enum,cs,ef,bounds)) ->
let t',cs,_ = subst params t cs ef in
let t',cs',ef',e' =
- type_coerce (Expr l) d_env false false t' (rebuild (Base(([],t'),Enum,cs,pure_e,bindings))) expect_t in
- (e',t',t_env,cs@cs',ef')
+ type_coerce (Expr l) d_env false false t' (rebuild (cons_tag_annot t' Enum cs)) expect_t in
+ (e',t',t_env,cs@cs',nob,ef')
| Some(Base(tp,Default,cs,ef,_)) | Some(Base(tp,Spec,cs,ef,_)) ->
typ_error l ("Identifier " ^ i ^ " must be defined, not just specified, before use")
- | Some(Base((params,t),tag,cs,ef,bindings)) ->
+ | Some(Base((params,t),tag,cs,ef,bounds)) ->
let ((t,cs,ef),is_alias) =
match tag with | Emp_global | External _ -> (subst params t cs ef),false
| Alias -> (t,cs, add_effect (BE_aux(BE_rreg, Parse_ast.Unknown)) ef),true | _ -> (t,cs,ef),false in
@@ -491,32 +487,32 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
(match t_actual.t,expect_actual.t with
| Tfn _,_ -> typ_error l ("Identifier " ^ (id_to_string id) ^ " is bound to a function and cannot be used as a value")
| Tapp("register",[TA_typ(t')]),Tapp("register",[TA_typ(expect_t')]) ->
- let tannot = Base(([],t),Emp_global,cs,ef,bindings) in
+ let tannot = Base(([],t),Emp_global,cs,ef,bounds) in
let t',cs' = type_consistent (Expr l) d_env false t' expect_t' in
- (rebuild tannot,t,t_env,cs@cs',ef)
+ (rebuild tannot,t,t_env,cs@cs',bounds,ef)
| Tapp("register",[TA_typ(t')]),Tuvar _ ->
let ef' = add_effect (BE_aux(BE_rreg,l)) ef in
- let tannot = Base(([],t),(if is_alias then Alias else External (Some i)),cs,ef',bindings) in
+ let tannot = Base(([],t),(if is_alias then Alias else External (Some i)),cs,ef',bounds) in
let t',cs',_,e' = type_coerce (Expr l) d_env false false t' (rebuild tannot) expect_actual in
- (e',t,t_env,cs@cs',ef')
+ (e',t,t_env,cs@cs',bounds,ef')
| Tapp("register",[TA_typ(t')]),_ ->
let ef' = add_effect (BE_aux(BE_rreg,l)) ef in
- let tannot = Base(([],t),(if is_alias then Alias else External (Some i)),cs,ef',bindings) in
+ let tannot = Base(([],t),(if is_alias then Alias else External (Some i)),cs,ef',bounds) in
let t',cs',_,e' = type_coerce (Expr l) d_env false false t' (rebuild tannot) expect_actual in
- (e',t',t_env,cs@cs',ef')
+ (e',t',t_env,cs@cs',bounds,ef')
| Tapp("reg",[TA_typ(t')]),_ ->
- let tannot = Base(([],t),Emp_local,cs,pure_e,bindings) in
+ let tannot = cons_bs_annot t cs bounds in
let t',cs',_,e' = type_coerce (Expr l) d_env false false t' (rebuild tannot) expect_actual in
- (e',t',t_env,cs@cs',pure_e)
+ (e',t',t_env,cs@cs',bounds,pure_e)
| _ ->
let t',cs',ef',e' =
- type_coerce (Expr l) d_env false false t (rebuild (Base(([],t),tag,cs,pure_e,bindings))) expect_t in
- (e',t',t_env,cs@cs',ef')
+ type_coerce (Expr l) d_env false false t (rebuild (Base(([],t),tag,cs,pure_e,bounds))) expect_t in
+ (e',t',t_env,cs@cs',bounds,ef')
)
| Some NoTyp | Some Overload _ | None -> typ_error l ("Identifier " ^ (id_to_string id) ^ " is unbound"))
| E_lit (L_aux(lit,l')) ->
let e,cs,effect = (match lit with
- | L_unit -> (rebuild (Base (([],unit_t), Emp_local,[],pure_e,nob))),[],pure_e
+ | L_unit -> (rebuild (simple_annot unit_t)),[],pure_e
| L_zero ->
(match expect_t.t with
| Tid "bool" -> simp_exp (E_lit(L_aux(L_zero,l'))) l bool_t,[],pure_e
@@ -543,7 +539,7 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let t = {t=Tapp("range", [TA_nexp n;TA_nexp {nexp = Nconst zero};])} in
let cs = [LtEq(Expr l,n,{nexp = N2n(rise,None)})] in
let f = match o.order with | Oinc -> "to_vec_inc" | Odec -> "to_vec_dec" | _ -> "to_vec_inc" (*Change to follow a default?*) in
- let tannot = (l,Base(([],expect_t),External (Some f),cs,pure_e,nob)) in
+ let tannot = (l,cons_tag_annot expect_t (External (Some f)) cs) in
E_aux(E_app((Id_aux((Id f),l)),[(E_aux (E_internal_exp tannot, tannot));simp_exp e l t]),tannot),cs,pure_e
| _ -> simp_exp e l {t = Tapp("atom", [TA_nexp{nexp = Nconst (big_int_of_int i)}])},[],pure_e)
| L_hex s -> simp_exp e l {t = Tapp("vector",
@@ -566,23 +562,23 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
E_aux(E_app((Id_aux((Id f),l)),[(E_aux (E_internal_exp tannot, tannot));simp_exp e l bit_t]),tannot),[],ef
| _ -> simp_exp e l (new_t ()),[],ef)) in
let t',cs',_,e' = type_coerce (Expr l) d_env false true (get_e_typ e) e expect_t in
- (e',t',t_env,cs@cs',effect)
+ (e',t',t_env,cs@cs',nob,effect)
| E_cast(typ,e) ->
let cast_t = typ_to_t false false typ in
let cast_t,cs_a = get_abbrev d_env cast_t in
let ct = {t = Toptions(cast_t,None)} in
- let (e',u,t_env,cs,ef) = check_exp envs imp_param ct e in
+ let (e',u,t_env,cs,bounds,ef) = check_exp envs imp_param ct e in
let t',cs2,ef',e' = type_coerce (Expr l) d_env true false u e' cast_t in
let t',cs3,ef'',e'' = type_coerce (Expr l) d_env false false cast_t e' expect_t in
- (e'',t',t_env,cs_a@cs@cs3,union_effects ef' (union_effects ef'' ef))
+ (e'',t',t_env,cs_a@cs@cs3,bounds,union_effects ef' (union_effects ef'' ef))
| E_app(id,parms) ->
let i = id_to_string id in
let check_parms p_typ parms = (match parms with
| [] -> let (_,cs') = type_consistent (Expr l) d_env false unit_t p_typ in [],unit_t,cs',pure_e
- | [parm] -> let (parm',arg_t,t_env,cs',ef_p) = check_exp envs imp_param p_typ parm in [parm'],arg_t,cs',ef_p
+ | [parm] -> let (parm',arg_t,t_env,cs',_,ef_p) = check_exp envs imp_param p_typ parm in [parm'],arg_t,cs',ef_p
| parms ->
(match check_exp envs imp_param p_typ (E_aux (E_tuple parms,(l,NoTyp))) with
- | ((E_aux(E_tuple parms',tannot')),arg_t,t_env,cs',ef_p) -> parms',arg_t,cs',ef_p
+ | ((E_aux(E_tuple parms',tannot')),arg_t,t_env,cs',_,ef_p) -> parms',arg_t,cs',ef_p
| _ -> raise (Reporting_basic.err_unreachable l "check_exp, given a tuple and a tuple type, didn't return a tuple")))
in
let coerce_parms arg_t parms expect_arg_t =
@@ -597,7 +593,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let check_result ret imp tag cs ef parms =
(*TODO How do I want to pass the information about start along?*)
- (* TODO MAJOR!!!! It may be that the return is a tuple or some bigger structure. THIS IS OK. I need to tie the variable in the implicit to the variable in the type and then put that type here. *)
+ (* TODO MAJOR!!!! It may be that the return is a tuple or some bigger structure. THIS IS OK. I need to tie the variable in the implicit to the variable in the type and then put that type here.
+ COME BACK AND look at return type more, look in bounds etc*)
match (imp,imp_param) with
| (IP_length,None) | (IP_var _,None) ->
(*let _ = Printf.printf "implicit length or var required, no imp_param\n!" in*)
@@ -605,9 +602,9 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let internal_exp = match expect_t.t,ret.t with
| Tapp("vector",_),_ ->
(*let _ = Printf.printf "adding internal exp on expext_t: %s %s \n" (t_to_string expect_t) (t_to_string ret) in*)
- E_aux (E_internal_exp (l,Base(([],expect_t),Emp_local,[],pure_e,nob)), (l,Base(([],nat_t),Emp_local,[],pure_e,nob)))
+ E_aux (E_internal_exp (l,simple_annot expect_t), (l,simple_annot nat_t))
| _,Tapp("vector",_) ->
- E_aux (E_internal_exp (l,Base(([],ret),Emp_local,[],pure_e,nob)), (l,Base(([],nat_t),Emp_local,[],pure_e,nob)))
+ E_aux (E_internal_exp (l,simple_annot ret), (l,simple_annot nat_t))
| _ -> typ_error l (i ^ " expected either the return type or the expected type to be a vector") in
type_coerce (Expr l) d_env false false ret (E_aux (E_app(id, internal_exp::parms),(l,(Base(([],ret),tag,cs,ef,nob))))) expect_t
| (IP_length,Some ne) | (IP_var _,Some ne) ->
@@ -615,29 +612,25 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let internal_exp = (match expect_t.t,ret.t with
| Tapp("vector",[_;TA_nexp len;_;_]),_ ->
if nexp_eq ne len
- then E_aux (E_internal_exp (l, Base(([], expect_t), Emp_local,[],pure_e,nob)),
- (l,Base(([],nat_t),Emp_local,[],pure_e,nob))) (*TODO This shouldn't be nat_t but should be a range bounded by the length of the vector *)
- else E_aux (E_internal_exp (l, Base(([], {t= Tapp("implicit",[TA_nexp ne])}), Emp_local,[],pure_e,nob)),
- (l,Base(([],nat_t),Emp_local,[],pure_e,nob))) (*TODO as above*)
+ (*TODO This shouldn't be nat_t but should be a range bounded by the length of the vector *)
+ then E_aux (E_internal_exp (l, simple_annot expect_t), (l, simple_annot nat_t))
+ else E_aux (E_internal_exp (l, simple_annot {t= Tapp("implicit",[TA_nexp ne])}), (l, simple_annot nat_t))
| _,Tapp("vector",[_;TA_nexp len;_;_]) ->
if nexp_eq ne len
- then E_aux (E_internal_exp (l, Base(([], ret), Emp_local,[],pure_e,nob)),
- (l,Base(([],nat_t),Emp_local,[],pure_e,nob))) (*TODO This shouldn't be nat_t but should be a range bounded by the length of the vector *)
- else E_aux (E_internal_exp (l, Base(([], {t= Tapp("implicit",[TA_nexp ne])}), Emp_local,[],pure_e,nob)),
- (l,Base(([],nat_t),Emp_local,[],pure_e,nob))) (*TODO as above*)
- | _ -> E_aux (E_internal_exp (l, Base(([], {t= Tapp("implicit",[TA_nexp ne])}), Emp_local,[],pure_e,nob)),
- (l,Base(([],nat_t), Emp_local,[],pure_e,nob))) (*TODO as above*)) in
+ then E_aux (E_internal_exp (l, simple_annot ret), (l, simple_annot nat_t))
+ else E_aux (E_internal_exp (l, simple_annot {t= Tapp("implicit",[TA_nexp ne])}),(l, simple_annot nat_t))
+ | _ -> E_aux (E_internal_exp (l, simple_annot {t= Tapp("implicit",[TA_nexp ne])}),(l, simple_annot nat_t))) in
type_coerce (Expr l) d_env false false ret (E_aux (E_app(id,internal_exp::parms),(l,(Base(([],ret),tag,cs,ef,nob))))) expect_t
| (IP_none,_) ->
(*let _ = Printf.printf "no implicit length or var required\n" in*)
type_coerce (Expr l) d_env false false ret (E_aux (E_app(id, parms),(l,(Base(([],ret),tag,cs,ef,nob))))) expect_t
in
(match Envmap.apply t_env i with
- | Some(Base(tp,Enum,cs,ef,bindings)) ->
+ | Some(Base(tp,Enum,_,_,_)) ->
typ_error l ("Expected function with name " ^ i ^ " but found an enumeration identifier")
- | Some(Base(tp,Default,cs,ef,bindings)) ->
+ | Some(Base(tp,Default,_,_,_)) ->
typ_error l ("Function " ^ i ^ " must be defined, not just declared as a default, before use")
- | Some(Base((params,t),tag,cs,ef,bindings)) ->
+ | Some(Base((params,t),tag,cs,ef,bounds)) ->
let t,cs,ef = subst params t cs ef in
(match t.t with
| Tfn(arg,ret,imp,ef') ->
@@ -646,9 +639,9 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
(*let _ = Printf.printf "Checked parms of %s\n" i in*)
let (ret_t,cs_r,ef_r,e') = check_result ret imp tag cs ef' parms in
(*let _ = Printf.printf "Checked result of %s\n" i in*)
- (e',ret_t,t_env,cs@cs_p@cs_r, union_effects ef' (union_effects ef_p ef_r))
+ (e',ret_t,t_env,cs@cs_p@cs_r, bounds,union_effects ef' (union_effects ef_p ef_r))
| _ -> typ_error l ("Expected a function or constructor, found identifier " ^ i ^ " bound to type " ^ (t_to_string t)))
- | Some(Overload(Base((params,t),tag,cs,ef,bindings),overload_return,variants)) ->
+ | Some(Overload(Base((params,t),tag,cs,ef,_),overload_return,variants)) ->
let t_p,cs_p,ef_p = subst params t cs ef in
let args,arg_t,arg_cs,arg_ef =
(match t_p.t with
@@ -658,45 +651,44 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
^ " bound to type " ^ (t_to_string t))) in
(match (select_overload_variant d_env true overload_return variants arg_t) with
| [] -> typ_error l
- ("No matching function found with name " ^ i ^ " that expects parameters " ^
- (t_to_string arg_t))
- | [Base((params,t),tag,cs,ef,bindings)] ->
+ ("No function found with name " ^ i ^ " that expects parameters " ^ (t_to_string arg_t))
+ | [Base((params,t),tag,cs,ef,bounds)] ->
(match t.t with
| Tfn(arg,ret,imp,ef') ->
let args',arg_ef',arg_cs' = coerce_parms arg_t args arg in
let (ret_t,cs_r,ef_r,e') = check_result ret imp tag cs ef' args' in
- (e',ret_t,t_env,cs_p@arg_cs@arg_cs'@cs_r,
- union_effects ef_r (union_effects ef_p (union_effects (union_effects arg_ef' arg_ef) ef')))
+ (e',ret_t,t_env,cs_p@arg_cs@arg_cs'@cs_r,nob,
+ union_effects ef_r (union_effects ef_p (union_effects (union_effects arg_ef' arg_ef) ef')))
| _ -> raise (Reporting_basic.err_unreachable l "Overloaded variant not a function"))
| variants' ->
(match select_overload_variant d_env false true variants' expect_t with
| [] ->
- typ_error l ("No matching function found with name " ^ i ^ ", expecting parameters " ^ (t_to_string arg_t) ^ " and returning " ^ (t_to_string expect_t))
- | [Base((params,t),tag,cs,ef,bindings)] ->
+ typ_error l ("No function found with name " ^ i ^ ", expecting parameters " ^ (t_to_string arg_t) ^ " and returning " ^ (t_to_string expect_t))
+ | [Base((params,t),tag,cs,ef,bounds)] ->
(match t.t with
|Tfn(arg,ret,imp,ef') ->
let args',arg_ef',arg_cs' = coerce_parms arg_t args arg in
let (ret_t,cs_r,ef_r,e') = check_result ret imp tag cs ef' args' in
- (e',ret_t,t_env,cs_p@arg_cs@arg_cs'@cs_r,
+ (e',ret_t,t_env,cs_p@arg_cs@arg_cs'@cs_r,nob,
union_effects ef_r (union_effects ef_p (union_effects (union_effects arg_ef arg_ef') ef')))
| _ -> raise (Reporting_basic.err_unreachable l "Overloaded variant not a function"))
| _ ->
- typ_error l ("More than one variant of " ^ i ^ " found with type " ^ (t_to_string arg_t) ^ " -> " ^ (t_to_string expect_t) ^ ". A cast may be required")))
- | _ -> typ_error l ("Unbound function " ^ i))
+ typ_error l ("More than one definition of " ^ i ^ " found with type " ^ (t_to_string arg_t) ^ " -> " ^ (t_to_string expect_t) ^ ". A cast may be required")))
+ | _ -> typ_error l ("Unbound function " ^ i))
| E_app_infix(lft,op,rht) ->
let i = id_to_string op in
let check_parms arg_t lft rht =
match check_exp envs imp_param arg_t (E_aux(E_tuple [lft;rht],(l,NoTyp))) with
- | ((E_aux(E_tuple [lft';rht'],_)),arg_t,_,cs',ef') -> (lft',rht',arg_t,cs',ef')
+ | ((E_aux(E_tuple [lft';rht'],_)),arg_t,_,cs',_,ef') -> (lft',rht',arg_t,cs',ef')
| _ -> raise (Reporting_basic.err_unreachable l "check exp given tuple and tuple type and returned non-tuple") in
let check_result ret imp tag cs ef lft rht =
match imp with
| IP_length ->
let internal_exp = match expect_t.t,ret.t with
| Tapp("vector",_),_ ->
- E_aux (E_internal_exp (l,Base(([],expect_t),Emp_local,[],pure_e,nob)), (l,Base(([],nat_t),Emp_local,[],pure_e,nob)))
+ E_aux (E_internal_exp (l,simple_annot expect_t), (l, simple_annot nat_t))
| _,Tapp("vector",_) ->
- E_aux (E_internal_exp (l,Base(([],ret),Emp_local,[],pure_e,nob)), (l,Base(([],nat_t),Emp_local,[],pure_e,nob)))
+ E_aux (E_internal_exp (l,simple_annot ret), (l,simple_annot nat_t))
| _ -> typ_error l (i ^ " expected either the return type or the expected type to be a vector") in
type_coerce (Expr l) d_env false false ret (E_aux (E_app(op, [internal_exp;lft;rht]),(l,(Base(([],ret),tag,cs,ef,nob))))) expect_t
| IP_none ->
@@ -704,16 +696,16 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
in
(match Envmap.apply t_env i with
| Some(Base(tp,Enum,cs,ef,b)) -> typ_error l ("Expected function with name " ^ i ^ " but found an enumeration identifier")
- | Some(Base(tp,Default,cs,ef,b)) -> typ_error l ("Function " ^ i ^ " must be defined, not just declared as a default, before use")
+ | Some(Base(tp,Default,cs,ef,b)) -> typ_error l ("Function " ^ i ^ " must be defined, not just declared as default, before use")
| Some(Base((params,t),tag,cs,ef,b)) ->
let t,cs,ef = subst params t cs ef in
(match t.t with
| Tfn(arg,ret,imp,ef) ->
let (lft',rht',arg_t,cs_p,ef_p) = check_parms arg lft rht in
let ret_t,cs_r',ef_r,e' = check_result ret imp tag cs ef lft' rht' in
- (e',ret_t,t_env,cs@cs_p@cs_r',union_effects ef (union_effects ef_p ef_r))
+ (e',ret_t,t_env,cs@cs_p@cs_r',nob,union_effects ef (union_effects ef_p ef_r))
| _ -> typ_error l ("Expected a function or constructor, found identifier " ^ i ^ " bound to type " ^ (t_to_string t)))
- | Some(Overload(Base((params,t),tag,cs,ef,b),overload_return,variants)) ->
+ | Some(Overload(Base((params,t),tag,cs,ef,_),overload_return,variants)) ->
let t_p,cs_p,ef_p = subst params t cs ef in
let lft',rht',arg_t,arg_cs,arg_ef =
(match t_p.t with
@@ -723,7 +715,7 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
(*let _ = Printf.eprintf "Looking for overloaded function %s, generic type is %s, arg_t is %s\n" i (t_to_string t_p) (t_to_string arg_t) in*)
(match (select_overload_variant d_env true overload_return variants arg_t) with
| [] ->
- typ_error l ("No matching function found with name " ^ i ^
+ typ_error l ("No function found with name " ^ i ^
" that expects parameters " ^ (t_to_string arg_t))
| [Base((params,t),tag,cs,ef,b)] ->
(*let _ = Printf.eprintf "Selected an overloaded function for %s,
@@ -736,7 +728,7 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
(*let (_,cs_lft,ef_lft,lft') = type_coerce (Expr l) d_env false tlft_t lft' tlft in
let (_,cs_rght,ef_rght,rht') = type_coerce (Expr l) d_env false trght_t rht' trght in*)
let (ret_t,cs_r,ef_r,e') = check_result ret imp tag cs ef lft' rht' in
- (e',ret_t,t_env,cs_p@arg_cs@cs@cs_r,
+ (e',ret_t,t_env,cs_p@arg_cs@cs@cs_r,nob,
union_effects ef_r (union_effects ef_p (union_effects arg_ef ef')))
|_ -> raise (Reporting_basic.err_unreachable l "function no longer has tuple type"))
| _ -> raise (Reporting_basic.err_unreachable l "overload variant does not have function"))
@@ -757,7 +749,7 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
(*let (_,cs_lft,ef_lft,lft') = type_coerce (Expr l) d_env false tlft_t lft' tlft in
let (_,cs_rght,ef_rght,rht') = type_coerce (Expr l) d_env false trght_t rht' trght in
*)let (ret_t,cs_r,ef_r,e') = check_result ret imp tag cs ef lft' rht' in
- (e',ret_t,t_env,cs_p@arg_cs@cs@cs_r,
+ (e',ret_t,t_env,cs_p@arg_cs@cs@cs_r,nob,
union_effects ef_r (union_effects ef_p (union_effects arg_ef ef')))
|_ -> raise (Reporting_basic.err_unreachable l "function no longer has tuple type"))
| _ -> raise (Reporting_basic.err_unreachable l "overload variant does not have function"))
@@ -773,70 +765,73 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let exps,typs,consts,effect =
List.fold_right2
(fun e t (exps,typs,consts,effect) ->
- let (e',t',_,c,ef) = check_exp envs imp_param t e in ((e'::exps),(t'::typs),c@consts,union_effects ef effect))
+ let (e',t',_,c,_,ef) = check_exp envs imp_param t e in ((e'::exps),(t'::typs),c@consts,union_effects ef effect))
exps ts ([],[],[],pure_e) in
let t = {t = Ttup typs} in
- (E_aux(E_tuple(exps),(l,Base(([],t),Emp_local,[],pure_e,nob))),t,t_env,consts,effect)
+ (E_aux(E_tuple(exps),(l,simple_annot t)),t,t_env,consts,nob,effect)
else typ_error l ("Expected a tuple with length " ^ (string_of_int tl) ^ " found one of length " ^ (string_of_int el))
| _ ->
let exps,typs,consts,effect =
List.fold_right
(fun e (exps,typs,consts,effect) ->
- let (e',t,_,c,ef) = check_exp envs imp_param (new_t ()) e in
+ let (e',t,_,c,_,ef) = check_exp envs imp_param (new_t ()) e in
((e'::exps),(t::typs),c@consts,union_effects ef effect))
exps ([],[],[],pure_e) in
let t = { t=Ttup typs } in
let t',cs',ef',e' =
- type_coerce (Expr l) d_env false false t (E_aux(E_tuple(exps),(l,Base(([],t),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,consts@cs',union_effects ef' effect))
+ type_coerce (Expr l) d_env false false t (E_aux(E_tuple(exps),(l,simple_annot t))) expect_t in
+ (e',t',t_env,consts@cs',nob,union_effects ef' effect))
| E_if(cond,then_,else_) ->
- let (cond',_,_,c1,ef1) = check_exp envs imp_param bit_t cond in
+ let (cond',_,_,c1,_,ef1) = check_exp envs imp_param bit_t cond in
(match expect_t.t with
| Tuvar _ ->
- let then',then_t,then_env,then_c,then_ef = check_exp envs imp_param (new_t ()) then_ in
- let else',else_t,else_env,else_c,else_ef = check_exp envs imp_param (new_t ()) else_ in
+ let then',then_t,then_env,then_c,then_bs,then_ef = check_exp envs imp_param (new_t ()) then_ in
+ let else',else_t,else_env,else_c,else_bs,else_ef = check_exp envs imp_param (new_t ()) else_ in
let then_t',then_c' = type_consistent (Expr l) d_env true then_t expect_t in
let else_t',else_c' = type_consistent (Expr l) d_env true else_t then_t' in
let t_cs = CondCons((Expr l),c1,then_c@then_c') in
let e_cs = CondCons((Expr l),[],else_c@else_c') in
- (E_aux(E_if(cond',then',else'),(l,Base(([],expect_t),Emp_local,[],pure_e,nob))),
+ (E_aux(E_if(cond',then',else'),(l,simple_annot expect_t)),
expect_t,Envmap.intersect_merge (tannot_merge (Expr l) d_env true) then_env else_env,[t_cs;e_cs],
+ merge_bounds then_bs else_bs, (*Should be an intersecting merge*)
union_effects ef1 (union_effects then_ef else_ef))
| _ ->
- let then',then_t,then_env,then_c,then_ef = check_exp envs imp_param expect_t then_ in
- let else',else_t,else_env,else_c,else_ef = check_exp envs imp_param expect_t else_ in
+ let then',then_t,then_env,then_c,then_bs,then_ef = check_exp envs imp_param expect_t then_ in
+ let else',else_t,else_env,else_c,else_bs,else_ef = check_exp envs imp_param expect_t else_ in
let t_cs = CondCons((Expr l),c1,then_c) in
let e_cs = CondCons((Expr l),[],else_c) in
- (E_aux(E_if(cond',then',else'),(l,Base(([],expect_t),Emp_local,[],pure_e,nob))),
+ (E_aux(E_if(cond',then',else'),(l,simple_annot expect_t)),
expect_t,Envmap.intersect_merge (tannot_merge (Expr l) d_env true) then_env else_env,[t_cs;e_cs],
+ merge_bounds then_bs else_bs,
union_effects ef1 (union_effects then_ef else_ef)))
| E_for(id,from,to_,step,order,block) ->
let fb,fr,tb,tr,sb,sr = new_n(),new_n(),new_n(),new_n(),new_n(),new_n() in
let ft,tt,st = {t=Tapp("range",[TA_nexp fb;TA_nexp fr])},
{t=Tapp("range",[TA_nexp tb;TA_nexp tr])},{t=Tapp("range",[TA_nexp sb;TA_nexp sr])} in
- let from',from_t,_,from_c,from_ef = check_exp envs imp_param ft from in
- let to_',to_t,_,to_c,to_ef = check_exp envs imp_param tt to_ in
- let step',step_t,_,step_c,step_ef = check_exp envs imp_param st step in
+ let from',from_t,_,from_c,_,from_ef = check_exp envs imp_param ft from in
+ let to_',to_t,_,to_c,_,to_ef = check_exp envs imp_param tt to_ in
+ let step',step_t,_,step_c,_,step_ef = check_exp envs imp_param st step in
let new_annot,local_cs =
match (aorder_to_ord order).order with
| Oinc ->
- (Base(([],{t=Tapp("range",[TA_nexp fb;TA_nexp {nexp=Nadd(tb,tr)}])}),Emp_local,[],pure_e,nob),
+ (simple_annot {t=Tapp("range",[TA_nexp fb;TA_nexp {nexp=Nadd(tb,tr)}])},
[LtEq((Expr l),{nexp=Nadd(fb,fr)},{nexp=Nadd(tb,tr)});LtEq((Expr l),fb,tb)])
| Odec ->
- (Base(([],{t=Tapp("range",[TA_nexp tb; TA_nexp {nexp=Nadd(fb,fr)}])}),Emp_local,[],pure_e,nob),
+ (simple_annot {t=Tapp("range",[TA_nexp tb; TA_nexp {nexp=Nadd(fb,fr)}])},
[GtEq((Expr l),{nexp=Nadd(fb,fr)},{nexp=Nadd(tb,tr)});GtEq((Expr l),fb,tb)])
| _ -> (typ_error l "Order specification in a foreach loop must be either inc or dec, not polymorphic")
+ in
+ (*TODO Might want to extend bounds here for the introduced variable*)
+ let (block',b_t,_,b_c,_,b_ef)=check_exp (Env(d_env,Envmap.insert t_env (id_to_string id,new_annot),b_env)) imp_param expect_t block
in
- let (block',b_t,_,b_c,b_ef)=check_exp (Env(d_env,Envmap.insert t_env (id_to_string id,new_annot))) imp_param expect_t block
- in
- (E_aux(E_for(id,from',to_',step',order,block'),(l,Base(([],b_t),Emp_local,local_cs,pure_e,nob))),expect_t,Envmap.empty,
- b_c@from_c@to_c@step_c@local_cs,(union_effects b_ef (union_effects step_ef (union_effects to_ef from_ef))))
+ (E_aux(E_for(id,from',to_',step',order,block'),(l,constrained_annot b_t local_cs)),expect_t,Envmap.empty,
+ b_c@from_c@to_c@step_c@local_cs,nob,(union_effects b_ef (union_effects step_ef (union_effects to_ef from_ef))))
| E_vector(es) ->
let item_t,ord = match expect_t.t with
| Tapp("vector",[base;rise;TA_ord ord;TA_typ item_t]) -> item_t,ord
| _ -> new_t (),d_env.default_o in
let es,cs,effect = (List.fold_right
- (fun (e,_,_,c,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect)
+ (fun (e,_,_,c,_,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect)
(List.map (check_exp envs imp_param item_t) es) ([],[],pure_e)) in
let len = List.length es in
let t = match ord.order,d_env.default_o.order with
@@ -847,8 +842,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
{t = Tapp("vector",[TA_nexp {nexp=Nconst (big_int_of_int (len-1))};
TA_nexp {nexp=Nconst (big_int_of_int len)};
TA_ord {order= Odec}; TA_typ item_t])} in
- let t',cs',ef',e' = type_coerce (Expr l) d_env false false t (E_aux(E_vector es,(l,Base(([],t),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,cs@cs',union_effects effect ef')
+ let t',cs',ef',e' = type_coerce (Expr l) d_env false false t (E_aux(E_vector es,(l,simple_annot t))) expect_t in
+ (e',t',t_env,cs@cs',nob,union_effects effect ef')
| E_vector_indexed(eis,(Def_val_aux(default,(ld,annot)))) ->
let item_t,base_n,rise_n = match expect_t.t with
| Tapp("vector",[TA_nexp base;TA_nexp rise;ord;TA_typ item_t]) -> item_t,base,rise
@@ -866,18 +861,17 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
else if i = prev
then (typ_error l ("Indexed vector contains a duplicate definition of index " ^ (string_of_int i)))
else (typ_error l ("Indexed vector is not consistently " ^ (if is_increasing then "increasing" else "decreasing"))))
- (List.map (fun (i,e) -> let (e,_,_,cs,eft) = (check_exp envs imp_param item_t e) in ((i,e),cs,eft))
+ (List.map (fun (i,e) -> let (e,_,_,cs,_,eft) = (check_exp envs imp_param item_t e) in ((i,e),cs,eft))
eis) ([],[],pure_e,false,(if is_increasing then (last+1) else (last-1)))) in
let (default',fully_enumerate,cs_d,ef_d) = match (default,contains_skip) with
- | (Def_val_empty,false) -> (Def_val_aux(Def_val_empty,(ld,Base(([],item_t),Emp_local,[],pure_e,nob))),true,[],pure_e)
+ | (Def_val_empty,false) -> (Def_val_aux(Def_val_empty,(ld,simple_annot item_t)),true,[],pure_e)
| (Def_val_empty,true) ->
let ef = add_effect (BE_aux(BE_unspec,l)) pure_e in
- let (de,_,_,_,ef_d) = check_exp envs imp_param item_t (E_aux(E_lit (L_aux(L_undef,l)), (l,NoTyp))) in
- (Def_val_aux(Def_val_dec de,
- (l,Base(([],item_t),Emp_local,[],ef,nob))),false,[],ef)
- | (Def_val_dec e,_) -> let (de,t,_,cs_d,ef_d) = (check_exp envs imp_param item_t e) in
+ let (de,_,_,_,_,ef_d) = check_exp envs imp_param item_t (E_aux(E_lit (L_aux(L_undef,l)), (l,NoTyp))) in
+ (Def_val_aux(Def_val_dec de, (l, cons_ef_annot item_t [] ef)),false,[],ef)
+ | (Def_val_dec e,_) -> let (de,t,_,cs_d,_,ef_d) = (check_exp envs imp_param item_t e) in
(*Check that ef_d doesn't write to memory or registers? *)
- (Def_val_aux(Def_val_dec de,(ld,(Base(([],item_t),Emp_local,cs_d,ef_d,nob)))),false,cs_d,ef_d) in
+ (Def_val_aux(Def_val_dec de,(ld,cons_ef_annot item_t cs_d ef_d)),false,cs_d,ef_d) in
let (base_bound,length_bound,cs_bounds) =
if fully_enumerate
then ({nexp=Nconst (big_int_of_int first)},{nexp = Nconst (big_int_of_int (List.length eis))},[])
@@ -887,16 +881,16 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
[TA_nexp(base_bound);TA_nexp length_bound;
TA_ord({order= if is_increasing then Oinc else Odec});TA_typ item_t])} in
let t',cs',ef',e' = type_coerce (Expr l) d_env false false t
- (E_aux (E_vector_indexed(es,default'),(l,Base(([],t),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,cs@cs_d@cs_bounds@cs',union_effects ef_d (union_effects ef' effect))
+ (E_aux (E_vector_indexed(es,default'),(l,simple_annot t))) expect_t in
+ (e',t',t_env,cs@cs_d@cs_bounds@cs',nob,union_effects ef_d (union_effects ef' effect))
| E_vector_access(vec,i) ->
let base,rise,ord = new_n(),new_n(),new_o() in
let item_t = new_t () in
let min,m_rise = new_n(),new_n() in
let vt = {t= Tapp("vector",[TA_nexp base;TA_nexp rise;TA_ord ord; TA_typ item_t])} in
- let (vec',t',_,cs,ef) = check_exp envs imp_param vt vec in
+ let (vec',t',_,cs,_,ef) = check_exp envs imp_param vt vec in
let it = {t= Tapp("range",[TA_nexp min;TA_nexp m_rise])} in
- let (i',ti',_,cs_i,ef_i) = check_exp envs imp_param it i in
+ let (i',ti',_,cs_i,_,ef_i) = check_exp envs imp_param it i in
let ord,item_t = match t'.t with
| Tabbrev(_,{t=Tapp("vector",[_;_;TA_ord ord;TA_typ t])}) | Tapp("vector",[_;_;TA_ord ord;TA_typ t]) -> ord,t
| _ -> ord,item_t in
@@ -913,8 +907,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| _ -> typ_error l "A vector must be either increasing or decreasing to access a single element"
in
(*let _ = Printf.eprintf "Type checking vector access. item_t is %s and expect_t is %s\n" (t_to_string item_t) (t_to_string expect_t) in*)
- let t',cs',ef',e'=type_coerce (Expr l) d_env false false item_t (E_aux(E_vector_access(vec',i'),(l,Base(([],item_t),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,cs_loc@cs_i@cs@cs',union_effects ef (union_effects ef' ef_i))
+ let t',cs',ef',e'=type_coerce (Expr l) d_env false false item_t (E_aux(E_vector_access(vec',i'),(l,simple_annot item_t))) expect_t in
+ (e',t',t_env,cs_loc@cs_i@cs@cs',nob,union_effects ef (union_effects ef' ef_i))
| E_vector_subrange(vec,i1,i2) ->
let base,rise,ord = new_n(),new_n(),new_o() in
let new_base,new_rise = new_n(),new_n() in
@@ -924,11 +918,11 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| Tapp("vector",[TA_nexp base_n;TA_nexp rise_n; TA_ord ord_n; TA_typ item_t]) -> base_n,rise_n,ord_n,item_t
| _ -> new_n(),new_n(),new_o(),new_t() in
let vt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise;TA_ord ord;TA_typ item_t])} in
- let (vec',t',_,cs,ef) = check_exp envs imp_param vt vec in
+ let (vec',t',_,cs,_,ef) = check_exp envs imp_param vt vec in
let i1t = {t=Tapp("atom",[TA_nexp n1])} in
- let (i1', ti1, _,cs_i1,ef_i1) = check_exp envs imp_param i1t i1 in
+ let (i1', ti1, _,cs_i1,_,ef_i1) = check_exp envs imp_param i1t i1 in
let i2t = {t=Tapp("atom",[TA_nexp n2])} in
- let (i2', ti2, _,cs_i2,ef_i2) = check_exp envs imp_param i2t i2 in
+ let (i2', ti2, _,cs_i2,_,ef_i2) = check_exp envs imp_param i2t i2 in
let cs_loc =
match (ord.order,d_env.default_o.order) with
| (Oinc,_) ->
@@ -971,8 +965,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let nt = {t=Tapp("vector",[TA_nexp new_base;TA_nexp new_rise; TA_ord ord;TA_typ item_t])} in
let (t,cs3,ef3,e') =
type_coerce (Expr l) d_env false false nt
- (E_aux(E_vector_subrange(vec',i1',i2'),(l,Base(([],nt),Emp_local,cs_loc,pure_e,nob)))) expect_t in
- (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc,(union_effects ef (union_effects ef3 (union_effects ef_i1 ef_i2))))
+ (E_aux(E_vector_subrange(vec',i1',i2'),(l,constrained_annot nt cs_loc))) expect_t in
+ (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc,nob,(union_effects ef (union_effects ef3 (union_effects ef_i1 ef_i2))))
| E_vector_update(vec,i,e) ->
let base,rise,ord = new_n(),new_n(),new_o() in
let min,m_rise = new_n(),new_n() in
@@ -980,10 +974,10 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| Tapp("vector",[TA_nexp base_n;TA_nexp rise_n; TA_ord ord_n; TA_typ item_t]) -> item_t
| _ -> new_t() in
let vt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise;TA_ord ord;TA_typ item_t])} in
- let (vec',t',_,cs,ef) = check_exp envs imp_param vt vec in
+ let (vec',t',_,cs,_,ef) = check_exp envs imp_param vt vec in
let it = {t=Tapp("range",[TA_nexp min;TA_nexp m_rise])} in
- let (i', ti, _,cs_i,ef_i) = check_exp envs imp_param it i in
- let (e', te, _,cs_e,ef_e) = check_exp envs imp_param item_t e in
+ let (i', ti, _,cs_i,_,ef_i) = check_exp envs imp_param it i in
+ let (e', te, _,cs_e,_,ef_e) = check_exp envs imp_param item_t e in
let cs_loc =
match (ord.order,d_env.default_o.order) with
| (Oinc,_) ->
@@ -998,8 +992,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
in
let nt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise; TA_ord ord;TA_typ item_t])} in
let (t,cs3,ef3,e') =
- type_coerce (Expr l) d_env false false nt (E_aux(E_vector_update(vec',i',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e,nob)))) expect_t in
- (e',t,t_env,cs3@cs@cs_i@cs_e@cs_loc,(union_effects ef (union_effects ef3 (union_effects ef_i ef_e))))
+ type_coerce (Expr l) d_env false false nt (E_aux(E_vector_update(vec',i',e'),(l,constrained_annot nt cs_loc))) expect_t in
+ (e',t,t_env,cs3@cs@cs_i@cs_e@cs_loc,nob,(union_effects ef (union_effects ef3 (union_effects ef_i ef_e))))
| E_vector_update_subrange(vec,i1,i2,e) ->
let base,rise,ord = new_n(),new_n(),new_o() in
let min1,m_rise1 = new_n(),new_n() in
@@ -1008,19 +1002,19 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| Tapp("vector",[TA_nexp base_n;TA_nexp rise_n; TA_ord ord_n; TA_typ item_t]) -> item_t
| _ -> new_t() in
let vt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise;TA_ord ord;TA_typ item_t])} in
- let (vec',t',_,cs,ef) = check_exp envs imp_param vt vec in
+ let (vec',t',_,cs,_,ef) = check_exp envs imp_param vt vec in
let i1t = {t=Tapp("range",[TA_nexp min1;TA_nexp m_rise1])} in
- let (i1', ti1, _,cs_i1,ef_i1) = check_exp envs imp_param i1t i1 in
+ let (i1', ti1, _,cs_i1,_,ef_i1) = check_exp envs imp_param i1t i1 in
let i2t = {t=Tapp("range",[TA_nexp min2;TA_nexp m_rise2])} in
- let (i2', ti2, _,cs_i2,ef_i2) = check_exp envs imp_param i2t i2 in
- let (e',item_t',_,cs_e,ef_e) =
+ let (i2', ti2, _,cs_i2,_,ef_i2) = check_exp envs imp_param i2t i2 in
+ let (e',item_t',_,cs_e,_,ef_e) =
try check_exp envs imp_param item_t e with
| _ ->
let (base_e,rise_e) = new_n(),new_n() in
- let (e',ti',env_e,cs_e,ef_e) =
+ let (e',ti',env_e,cs_e,bs_e,ef_e) =
check_exp envs imp_param {t=Tapp("vector",[TA_nexp base_e;TA_nexp rise_e;TA_ord ord;TA_typ item_t])} e in
let cs_add = [Eq((Expr l),base_e,min1);LtEq((Expr l),rise,m_rise2)] in
- (e',ti',env_e,cs_e@cs_add,ef_e) in
+ (e',ti',env_e,cs_e@cs_add,bs_e,ef_e) in
let cs_loc =
match (ord.order,d_env.default_o.order) with
| (Oinc,_) ->
@@ -1038,8 +1032,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| _ -> typ_error l "A vector must be either increasing or decreasing to modify a slice" in
let nt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise; TA_ord ord;TA_typ item_t])} in
let (t,cs3,ef3,e') =
- type_coerce (Expr l) d_env false false nt (E_aux(E_vector_update_subrange(vec',i1',i2',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e,nob)))) expect_t in
- (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc@cs_e,(union_effects ef (union_effects ef3 (union_effects ef_i1 (union_effects ef_i2 ef_e)))))
+ type_coerce (Expr l) d_env false false nt (E_aux(E_vector_update_subrange(vec',i1',i2',e'),(l,constrained_annot nt cs_loc))) expect_t in
+ (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc@cs_e,nob,(union_effects ef (union_effects ef3 (union_effects ef_i1 (union_effects ef_i2 ef_e)))))
| E_vector_append(v1,v2) ->
let item_t,ord = match expect_t.t with
| Tapp("vector",[_;_;TA_ord o;TA_typ i]) -> i,o
@@ -1047,35 +1041,35 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| _ -> new_t (),new_o () in
let base1,rise1 = new_n(), new_n() in
let base2,rise2 = new_n(),new_n() in
- let (v1',t1',_,cs_1,ef_1) = check_exp envs imp_param {t=Tapp("vector",[TA_nexp base1;TA_nexp rise1;TA_ord ord;TA_typ item_t])} v1 in
- let (v2',t2',_,cs_2,ef_2) = check_exp envs imp_param {t=Tapp("vector",[TA_nexp base2;TA_nexp rise2;TA_ord ord;TA_typ item_t])} v2 in
+ let (v1',t1',_,cs_1,_,ef_1) = check_exp envs imp_param {t=Tapp("vector",[TA_nexp base1;TA_nexp rise1;TA_ord ord;TA_typ item_t])} v1 in
+ let (v2',t2',_,cs_2,_,ef_2) = check_exp envs imp_param {t=Tapp("vector",[TA_nexp base2;TA_nexp rise2;TA_ord ord;TA_typ item_t])} v2 in
let ti = {t=Tapp("vector",[TA_nexp base1;TA_nexp {nexp = Nadd(rise1,rise2)};TA_ord ord; TA_typ item_t])} in
let cs_loc = match ord.order with
| Odec -> [GtEq((Expr l),base1,{nexp = Nadd(rise1,rise2)})]
| _ -> [] in
let (t,cs_c,ef_c,e') =
- type_coerce (Expr l) d_env false false ti (E_aux(E_vector_append(v1',v2'),(l,Base(([],ti),Emp_local,cs_loc,pure_e,nob)))) expect_t in
- (e',t,t_env,cs_loc@cs_1@cs_2,(union_effects ef_c (union_effects ef_1 ef_2)))
+ type_coerce (Expr l) d_env false false ti (E_aux(E_vector_append(v1',v2'),(l,constrained_annot ti cs_loc))) expect_t in
+ (e',t,t_env,cs_loc@cs_1@cs_2,nob,(union_effects ef_c (union_effects ef_1 ef_2)))
| E_list(es) ->
let item_t = match expect_t.t with
| Tapp("list",[TA_typ i]) -> i
| _ -> new_t() in
let es,cs,effect =
- (List.fold_right (fun (e,_,_,c,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect)
+ (List.fold_right (fun (e,_,_,c,_,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect)
(List.map (check_exp envs imp_param item_t) es) ([],[],pure_e)) in
let t = {t = Tapp("list",[TA_typ item_t])} in
- let t',cs',ef',e' = type_coerce (Expr l) d_env false false t (E_aux(E_list es,(l,Base(([],t),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,cs@cs',union_effects ef' effect)
+ let t',cs',ef',e' = type_coerce (Expr l) d_env false false t (E_aux(E_list es,(l,simple_annot t))) expect_t in
+ (e',t',t_env,cs@cs',nob,union_effects ef' effect)
| E_cons(ls,i) ->
let item_t = match expect_t.t with
| Tapp("list",[TA_typ i]) -> i
| _ -> new_t() in
let lt = {t=Tapp("list",[TA_typ item_t])} in
- let (ls',t',_,cs,ef) = check_exp envs imp_param lt ls in
- let (i', ti, _,cs_i,ef_i) = check_exp envs imp_param item_t i in
+ let (ls',t',_,cs,_,ef) = check_exp envs imp_param lt ls in
+ let (i', ti, _,cs_i,_,ef_i) = check_exp envs imp_param item_t i in
let (t',cs',ef',e') =
- type_coerce (Expr l) d_env false false lt (E_aux(E_cons(ls',i'),(l,Base(([],lt),Emp_local,[],pure_e,nob)))) expect_t in
- (e',t',t_env,cs@cs'@cs_i,union_effects ef' (union_effects ef ef_i))
+ type_coerce (Expr l) d_env false false lt (E_aux(E_cons(ls',i'),(l,simple_annot lt))) expect_t in
+ (e',t',t_env,cs@cs'@cs_i,nob,union_effects ef' (union_effects ef ef_i))
| E_record(FES_aux(FES_Fexps(fexps,_),l')) ->
let u,_ = get_abbrev d_env expect_t in
let u_actual = match u.t with | Tabbrev(_, u) -> u | _ -> u in
@@ -1093,12 +1087,12 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| NoTyp ->
typ_error l ("Expected a struct of type " ^ n ^ ", which should not have a field " ^ i)
| Overload _ -> raise (Reporting_basic.err_unreachable l "Field given overload tannot")
- | Base((params,et),tag,cs,ef,bindings) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,_ = subst params et cs ef in
- let (e,t',_,c,ef) = check_exp envs imp_param et exp in
- (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,bindings)))::fexps,cons@cs@c,union_effects ef ef'))
+ let (e,t',_,c,_,ef) = check_exp envs imp_param et exp in
+ (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,bounds)))::fexps,cons@cs@c,union_effects ef ef'))
fexps ([],[],pure_e) in
- E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,Base(([],u),Emp_local,[],pure_e,nob))),expect_t,t_env,cons,ef
+ E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,simple_annot u)),expect_t,t_env,cons,nob,ef
else typ_error l ("Expected a struct of type " ^ n ^ ", which should have " ^ string_of_int (List.length fields) ^ " fields")
| Some(i,Register,fields) -> typ_error l ("Expected a value with register type, found a struct"))
| Tuvar _ ->
@@ -1115,15 +1109,15 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
| Base((params,et),tag,cs,ef,binding) ->
let et,cs,_ = subst params et cs ef in
- let (e,t',_,c,ef) = check_exp envs imp_param et exp in
+ let (e,t',_,c,_,ef) = check_exp envs imp_param et exp in
(FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,binding)))::fexps,cons@cs@c,union_effects ef ef'))
fexps ([],[],pure_e) in
expect_t.t <- Tid i; (*TODO THis should use equate_t !!*)
- E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,Base(([],expect_t),Emp_local,[],pure_e,nob))),expect_t,t_env,cons,ef
+ E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,simple_annot expect_t)),expect_t,t_env,cons,nob,ef
| Some(i,Register,fields) -> typ_error l "Expected a value with register type, found a struct")
| _ -> typ_error l ("Expected an expression of type " ^ t_to_string expect_t ^ " but found a struct"))
| E_record_update(exp,FES_aux(FES_Fexps(fexps,_),l')) ->
- let (e',t',_,c,ef) = check_exp envs imp_param expect_t exp in
+ let (e',t',_,c,_,ef) = check_exp envs imp_param expect_t exp in
(match t'.t with
| Tid i | Tabbrev(_, {t=Tid i}) ->
(match lookup_record_typ i d_env.rec_env with
@@ -1140,13 +1134,12 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| NoTyp ->
typ_error l ("Expected a struct with type " ^ i ^ ", which does not have a field " ^ fi)
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
- | Base((params,et),tag,cs,ef,binding) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,_ = subst params et cs ef in
- let (e,t',_,c,ef) = check_exp envs imp_param et exp in
- (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,binding)))::fexps,cons@cs@c,union_effects ef ef'))
+ let (e,t',_,c,_,ef) = check_exp envs imp_param et exp in
+ (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,bounds)))::fexps,cons@cs@c,union_effects ef ef'))
fexps ([],[],pure_e) in
- E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')),
- (l,Base(([],expect_t),Emp_local,[],pure_e,nob))),expect_t,t_env,cons,ef
+ E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')), (l,simple_annot expect_t)),expect_t,t_env,cons,nob,ef
else typ_error l ("Expected fields from struct " ^ i ^ ", given more fields than struct includes"))
| Tuvar _ ->
let field_names = List.map (fun (FE_aux(FE_Fexp(id,exp),(l,annot))) -> id_to_string id) fexps in
@@ -1160,19 +1153,18 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
match lookup_field_type i r with
| NoTyp -> raise (Reporting_basic.err_unreachable l "field_match didn't have a full match")
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
- | Base((params,et),tag,cs,ef,binding) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,_ = subst params et cs ef in
- let (e,t',_,c,ef) = check_exp envs imp_param et exp in
- (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,binding)))::fexps,cons@cs@c,union_effects ef ef'))
+ let (e,t',_,c,_,ef) = check_exp envs imp_param et exp in
+ (FE_aux(FE_Fexp(id,e),(l,Base(([],t'),tag,cs@c,ef,bounds)))::fexps,cons@cs@c,union_effects ef ef'))
fexps ([],[],pure_e) in
- expect_t.t <- Tid i;
- E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')),
- (l,Base(([],expect_t),Emp_local,[],pure_e,nob))),expect_t,t_env,cons,ef
+ expect_t.t <- Tid i; (*Should be equate_t*)
+ E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')), (l,simple_annot expect_t)),expect_t,t_env,cons,nob,ef
| [(i,Register,fields)] -> typ_error l "Expected a value with register type, found a struct"
| records -> typ_error l "Multiple structs contain this set of fields, try adding a cast to disambiguate")
| _ -> typ_error l ("Expected a struct to update but found an expression of type " ^ t_to_string expect_t))
| E_field(exp,id) ->
- let (e',t',_,c,ef) = check_exp envs imp_param (new_t()) exp in
+ let (e',t',_,c,_,ef) = check_exp envs imp_param (new_t()) exp in
(match t'.t with
| Tabbrev({t=Tid i}, t2) ->
(match lookup_record_typ i d_env.rec_env with
@@ -1183,11 +1175,11 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| NoTyp ->
typ_error l ("Type " ^ i ^ " does not have a field " ^ fi)
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
- | Base((params,et),tag,cs,ef,binding) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,ef = subst params et cs ef in
let (et',c',ef',acc) =
- type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,binding)))) expect_t in
- (acc,et',t_env,cs@c',union_effects ef' ef)))
+ type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,bounds)))) expect_t in
+ (acc,et',t_env,cs@c',nob,union_effects ef' ef)))
| Tid i ->
(match lookup_record_typ i d_env.rec_env with
| None -> typ_error l ("Expected a struct or register for this access, instead found an expression with type " ^ i)
@@ -1197,11 +1189,11 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| NoTyp ->
typ_error l ("Type " ^ i ^ " does not have a field " ^ fi)
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
- | Base((params,et),tag,cs,ef,binding) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,ef = subst params et cs ef in
let (et',c',ef',acc) =
- type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,binding)))) expect_t in
- (acc,et',t_env,cs@c',union_effects ef' ef)))
+ type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,bounds)))) expect_t in
+ (acc,et',t_env,cs@c',nob,union_effects ef' ef)))
| Tuvar _ ->
let fi = id_to_string id in
(match lookup_possible_records [fi] d_env.rec_env with
@@ -1212,17 +1204,17 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| NoTyp ->
raise (Reporting_basic.err_unreachable l "lookup_possible_records returned a record that didn't include the field")
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
- | Base((params,et),tag,cs,ef,binding) ->
+ | Base((params,et),tag,cs,ef,bounds) ->
let et,cs,ef = subst params et cs ef in
let (et',c',ef',acc) =
- type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,binding)))) expect_t in
+ type_coerce (Expr l) d_env false false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef,bounds)))) expect_t in
equate_t t' {t=Tid i};
- (acc,et',t_env,cs@c',union_effects ef' ef))
+ (acc,et',t_env,cs@c',nob,union_effects ef' ef))
| records -> typ_error l ("Multiple structs contain field " ^ fi ^ ", try adding a cast to disambiguate"))
| _ -> typ_error l ("Expected a struct or register for access but found an expression of type " ^ t_to_string t'))
| E_case(exp,pexps) ->
(*let check_t = new_t() in*)
- let (e',t',_,cs,ef) = check_exp envs imp_param (new_t()) exp in
+ let (e',t',_,cs,_,ef) = check_exp envs imp_param (new_t()) exp in
(*let _ = Printf.eprintf "Type of pattern after expression check %s\n" (t_to_string t') in*)
let t' =
match t'.t with
@@ -1230,105 +1222,115 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| _ -> t' in
(*let _ = Printf.eprintf "Type of pattern after register check %s\n" (t_to_string t') in*)
let (pexps',t,cs',ef') = check_cases envs imp_param t' expect_t pexps in
- (E_aux(E_case(e',pexps'),(l,Base(([],t),Emp_local,[],pure_e,nob))),t,t_env,cs@cs',union_effects ef ef')
+ (E_aux(E_case(e',pexps'),(l,simple_annot t)),t,t_env,cs@cs',nob,union_effects ef ef')
| E_let(lbind,body) ->
- let (lb',t_env',cs,ef) = (check_lbind envs imp_param false Emp_local lbind) in
- let (e,t,_,cs',ef') = check_exp (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env false) t_env t_env')) imp_param expect_t body in
- (E_aux(E_let(lb',e),(l,Base(([],t),Emp_local,[],pure_e,nob))),t,t_env,cs@cs',union_effects ef ef')
+ let (lb',t_env',cs,b_env',ef) = (check_lbind envs imp_param false Emp_local lbind) in
+ let new_env = (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env false) t_env t_env', merge_bounds b_env' b_env)) in
+ let (e,t,_,cs',_,ef') = check_exp new_env imp_param expect_t body in
+ (E_aux(E_let(lb',e),(l,simple_annot t)),t,t_env,cs@cs',nob,union_effects ef ef')
| E_assign(lexp,exp) ->
- let (lexp',t',t_env',tag,cs,ef) = check_lexp envs imp_param true lexp in
- let (exp',t'',_,cs',ef') = check_exp envs imp_param t' exp in
+ let (lexp',t',t_env',tag,cs,b_env',ef) = check_lexp envs imp_param true lexp in
+ let (exp',t'',_,cs',_,ef') = check_exp envs imp_param t' exp in
let (t',c') = type_consistent (Expr l) d_env false unit_t expect_t in
- (E_aux(E_assign(lexp',exp'),(l,(Base(([],unit_t),tag,[],ef,nob)))),unit_t,t_env',cs@cs'@c',union_effects ef ef')
+ (E_aux(E_assign(lexp',exp'),(l,(Base(([],unit_t),tag,[],ef,nob)))),unit_t,t_env',cs@cs'@c',b_env',union_effects ef ef')
| E_exit e ->
- let (e',t',_,_,_) = check_exp envs imp_param (new_t ()) e in
- (E_aux (E_exit e',(l,(Base(([],expect_t),Emp_local,[],pure_e,nob)))),expect_t,t_env,[],pure_e)
+ let (e',t',_,_,_,_) = check_exp envs imp_param (new_t ()) e in
+ (E_aux (E_exit e',(l,(simple_annot expect_t))),expect_t,t_env,[],nob,pure_e)
| E_internal_cast _ | E_internal_exp _ -> raise (Reporting_basic.err_unreachable l "Internal expression passed back into type checker")
-and check_block orig_envs envs imp_param expect_t exps:((tannot exp) list * tannot * tannot emap * nexp_range list * t * effect) =
- let Env(d_env,t_env) = envs in
+and check_block envs imp_param expect_t exps:((tannot exp) list * tannot * nexp_range list * t * effect) =
+ let Env(d_env,t_env,b_env) = envs in
match exps with
- | [] -> ([],NoTyp,orig_envs,[],unit_t,pure_e)
- | [e] -> let (E_aux(e',(l,annot)),t,envs,sc,ef) = check_exp envs imp_param expect_t e in
- ([E_aux(e',(l,annot))],annot,orig_envs,sc,t,ef)
- | e::exps -> let (e',t',t_env',sc,ef') = check_exp envs imp_param unit_t e in
- let (exps',annot',orig_envs,sc',t,ef) =
- check_block orig_envs
- (Env(d_env,Envmap.union_merge (tannot_merge (Expr Parse_ast.Unknown) d_env false) t_env t_env')) imp_param expect_t exps in
- ((e'::exps'),annot',orig_envs,sc@sc',t,union_effects ef ef')
+ | [] -> ([],NoTyp,[],unit_t,pure_e)
+ | [e] ->
+ let (E_aux(e',(l,annot)),t,envs,sc,_,ef) = check_exp envs imp_param expect_t e in
+ ([E_aux(e',(l,annot))],annot,sc,t,ef)
+ | e::exps ->
+ let (e',t',t_env',sc,b_env',ef') = check_exp envs imp_param unit_t e in
+ let (exps',annot',sc',t,ef) =
+ check_block (Env(d_env,
+ Envmap.union_merge (tannot_merge (Expr Parse_ast.Unknown) d_env false) t_env t_env',
+ merge_bounds b_env' b_env)) imp_param expect_t exps in
+ ((e'::exps'),annot',sc@sc',t,union_effects ef ef')
and check_cases envs imp_param check_t expect_t pexps : ((tannot pexp) list * typ * nexp_range list * effect) =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
match pexps with
| [] -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "switch with no cases found")
| [(Pat_aux(Pat_exp(pat,exp),(l,annot)))] ->
- let pat',env,cs_p,u = check_pattern envs Emp_local check_t pat in
- let e,t,_,cs_e,ef = check_exp (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env env)) imp_param expect_t exp in
+ let pat',env,cs_p,bounds,u = check_pattern envs Emp_local check_t pat in
+ let e,t,_,cs_e,_,ef =
+ check_exp (Env(d_env,
+ Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env env,
+ merge_bounds b_env bounds)) imp_param expect_t exp in
let cs = [CondCons(Expr l, cs_p, cs_e)] in
- [Pat_aux(Pat_exp(pat',e),(l,Base(([],t),Emp_local,cs,ef,nob)))],t,cs,ef
+ [Pat_aux(Pat_exp(pat',e),(l,cons_ef_annot t cs ef))],t,cs,ef
| ((Pat_aux(Pat_exp(pat,exp),(l,annot)))::pexps) ->
- let pat',env,cs_p,u = check_pattern envs Emp_local check_t pat in
- let (e,t,_,cs_e,ef) = check_exp (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env env)) imp_param expect_t exp in
+ let pat',env,cs_p,bounds,u = check_pattern envs Emp_local check_t pat in
+ let (e,t,_,cs_e,_,ef) =
+ check_exp (Env(d_env,
+ Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env env,
+ merge_bounds b_env bounds)) imp_param expect_t exp in
let cs = CondCons(Expr l,cs_p,cs_e) in
let (pes,tl,csl,efl) = check_cases envs imp_param check_t expect_t pexps in
- ((Pat_aux(Pat_exp(pat',e),(l,(Base(([],t),Emp_local,[cs],ef,nob)))))::pes,
- tl,
- cs::csl,union_effects efl ef)
+ ((Pat_aux(Pat_exp(pat',e),(l,cons_ef_annot t [cs] ef)))::pes,tl,cs::csl,union_effects efl ef)
-and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp * typ * tannot emap * tag *nexp_range list *effect ) =
- let (Env(d_env,t_env)) = envs in
+and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp * typ * tannot emap * tag *nexp_range list * bounds_env *effect ) =
+ let (Env(d_env,t_env,b_env)) = envs in
match lexp with
| LEXP_id id ->
let i = id_to_string id in
(match Envmap.apply t_env i with
+ (*TODO Should probably change this to use the default as the expected type*)
| Some(Base((parms,t),Default,_,_,_)) ->
typ_error l ("Identifier " ^ i ^ " cannot be assigned when only a default specification exists")
| Some(Base(([],t),Alias,_,_,_)) ->
(match Envmap.apply d_env.alias_env i with
- | Some(OneReg(reg, (Base(([],t'),_,_,_,_)))) ->
- let ef = {effect=Eset[BE_aux(BE_wreg,l)]} in
- (LEXP_aux(lexp,(l,(Base(([],t'),Alias,[],ef,nob)))), t, Envmap.empty, External (Some reg),[],ef)
- | Some(TwoReg(reg1,reg2, (Base(([],t'),_,_,_,_)))) ->
- let ef = {effect=Eset [BE_aux(BE_wreg,l)]} in
- let u = match t.t with
- | Tapp("register", [TA_typ u]) -> u in
- (LEXP_aux(lexp,(l,Base(([],t'),Alias,[],ef,nob))), u, Envmap.empty, External None,[],ef)
- | _ -> assert false)
+ | Some(OneReg(reg, (Base(([],t'),_,_,_,_)))) ->
+ let ef = {effect=Eset[BE_aux(BE_wreg,l)]} in
+ (LEXP_aux(lexp,(l,(Base(([],t'),Alias,[],ef,nob)))), t, Envmap.empty, External (Some reg),[],nob,ef)
+ | Some(TwoReg(reg1,reg2, (Base(([],t'),_,_,_,_)))) ->
+ let ef = {effect=Eset [BE_aux(BE_wreg,l)]} in
+ let u = match t.t with
+ | Tapp("register", [TA_typ u]) -> u in
+ (LEXP_aux(lexp,(l,Base(([],t'),Alias,[],ef,nob))), u, Envmap.empty, External None,[],nob,ef)
+ | _ -> assert false)
| Some(Base((parms,t),tag,cs,_,b)) ->
let t,cs,_ = match tag with | External _ | Emp_global -> subst parms t cs pure_e | _ -> t,cs,pure_e in
let t,cs' = get_abbrev d_env t in
- let t_actual = match t.t with
- | Tabbrev(i,t) -> t
- | _ -> t in
+ let t_actual = match t.t with | Tabbrev(i,t) -> t | _ -> t in
(*let _ = Printf.eprintf "Assigning to %s, t is %s\n" i (t_to_string t_actual) in*)
(match t_actual.t,is_top with
| Tapp("register",[TA_typ u]),_ ->
let ef = {effect=Eset[BE_aux(BE_wreg,l)]} in
- (LEXP_aux(lexp,(l,(Base(([],t),External (Some i),cs@cs',ef,b)))),u,Envmap.empty,External (Some i),[],ef)
+ (LEXP_aux(lexp,(l,(Base(([],t),External (Some i),cs@cs',ef,nob)))),u,Envmap.empty,External (Some i),[],nob,ef)
| Tapp("reg",[TA_typ u]),_ ->
- (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs@cs',pure_e,b)))),u,Envmap.empty,Emp_local,[],pure_e)
+ (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs@cs',pure_e,b)))),u,Envmap.empty,Emp_local,[],nob,pure_e)
| Tapp("vector",_),false ->
- (LEXP_aux(lexp,(l,(Base(([],t),tag,cs@cs',pure_e,b)))),t,Envmap.empty,Emp_local,[],pure_e)
+ (LEXP_aux(lexp,(l,(Base(([],t),tag,cs@cs',pure_e,b)))),t,Envmap.empty,Emp_local,[],nob,pure_e)
| (Tfn _ ,_) ->
(match tag with
| External _ | Spec | Emp_global ->
let u = new_t() in
let t = {t = Tapp("reg",[TA_typ u])} in
- let tannot = (Base(([],t),Emp_local,[],pure_e,b)) in
- (LEXP_aux(lexp,(l,tannot)),u,Envmap.from_list [i,tannot],Emp_local,[],pure_e)
+ let bounds = extract_bounds d_env i t in
+ let tannot = (Base(([],t),Emp_local,[],pure_e,bounds)) in
+ (LEXP_aux(lexp,(l,tannot)),u,Envmap.from_list [i,tannot],Emp_local,[],bounds,pure_e)
| _ ->
- typ_error l ("Can only assign to identifiers with type register or reg, found identifier " ^ i ^ " with type " ^ t_to_string t))
+ typ_error l ("Can only assign to registers or regs, found identifier " ^ i ^ " with type " ^ t_to_string t))
| _,_ ->
if is_top
then typ_error l
- ("Can only assign to identifiers with type register or reg, found identifier " ^ i ^ " with type " ^ t_to_string t)
+ ("Can only assign to registers or regs, found identifier " ^ i ^ " with type " ^ t_to_string t)
else
- (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs@cs',pure_e,nob)))),t,Envmap.empty,Emp_local,[],pure_e) (* TODO, make sure this is a record *))
+ (* TODO, make sure this is a record *)
+ (LEXP_aux(lexp,(l,constrained_annot t (cs@cs'))),t,Envmap.empty,Emp_local,[],nob,pure_e))
| _ ->
let u = new_t() in
let t = {t=Tapp("reg",[TA_typ u])} in
- let tannot = (Base(([],t),Emp_local,[],pure_e,nob)) in
- (LEXP_aux(lexp,(l,tannot)),u,Envmap.from_list [i,tannot],Emp_local,[],pure_e))
+ let bounds = extract_bounds d_env i u in
+ let tannot = (Base(([],t),Emp_local,[],pure_e,bounds)) in
+ (LEXP_aux(lexp,(l,tannot)),u,Envmap.from_list [i,tannot],Emp_local,[],bounds,pure_e))
| LEXP_memory(id,exps) ->
let i = id_to_string id in
(match Envmap.apply t_env i with
@@ -1353,28 +1355,28 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
let (es, cs_es, ef_es) =
match args,exps with
| [],[] -> ([],[],pure_e)
- | [],[e] -> let (e',_,_,cs_e,ef_e) = check_exp envs imp_param unit_t e in ([e'],cs_e,ef_e)
+ | [],[e] -> let (e',_,_,cs_e,_,ef_e) = check_exp envs imp_param unit_t e in ([e'],cs_e,ef_e)
| [],es -> typ_error l ("Expected no arguments for assignment function " ^ i)
| args,[] ->
typ_error l ("Expected arguments with types " ^ (t_to_string args_t) ^
"for assignment function " ^ i)
| args,es ->
(match check_exp envs imp_param args_t (E_aux (E_tuple exps,(l,NoTyp))) with
- | (E_aux(E_tuple es,(l',tannot)),_,_,cs_e,ef_e) -> (es,cs_e,ef_e)
+ | (E_aux(E_tuple es,(l',tannot)),_,_,cs_e,_,ef_e) -> (es,cs_e,ef_e)
| _ -> raise (Reporting_basic.err_unreachable l "Gave check_exp a tuple, didn't get a tuple back"))
in
let ef_all = union_effects ef' ef_es in
(LEXP_aux(LEXP_memory(id,es),(l,Base(([],out),tag,cs_call,ef',nob))),
- item_t,Envmap.empty,tag,cs_call@cs_es,ef_all)
+ item_t,Envmap.empty,tag,cs_call@cs_es,nob,ef_all)
| _ ->
let e = match exps with
| [] -> E_aux(E_lit(L_aux(L_unit,l)),(l,NoTyp))
| [(E_aux(E_lit(L_aux(L_unit,_)),(_,NoTyp)) as e)] -> e
| es -> typ_error l ("Expected no arguments for assignment function " ^ i) in
- let (e,_,_,cs_e,ef_e) = check_exp envs imp_param apps e in
+ let (e,_,_,cs_e,_,ef_e) = check_exp envs imp_param apps e in
let ef_all = union_effects ef ef_e in
(LEXP_aux(LEXP_memory(id,[e]),(l,Base(([],out),tag,cs_call,ef,nob))),
- app,Envmap.empty,tag,cs_call@cs_e,ef_all))
+ app,Envmap.empty,tag,cs_call@cs_e,nob,ef_all))
else typ_error l ("Assignments require functions with a wmem or wreg effect")
| _ -> typ_error l ("Assignments require functions with a wmem or wreg effect"))
| _ -> typ_error l ("Assignments require a function here, found " ^ i ^ " which has type " ^ (t_to_string t)))
@@ -1382,34 +1384,32 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
| LEXP_cast(typ,id) ->
let i = id_to_string id in
let ty = typ_to_t false false typ in
+ let new_bounds = extract_bounds d_env i ty in
(match Envmap.apply t_env i with
- | Some(Base((parms,t),Default,_,_,_)) ->
- typ_error l ("Identifier " ^ i ^ " cannot be assigned when only a default specification exists")
- | Some(Base((parms,t),tag,cs,_,_)) ->
+ | Some(Base((parms,t),tag,cs,_,bounds)) ->
let t,cs,_ = match tag with | External _ | Emp_global -> subst parms t cs pure_e | _ -> t,cs,pure_e in
let t,cs' = get_abbrev d_env t in
let t_actual = match t.t with | Tabbrev(_,t) -> t | _ -> t in
+ let bs = merge_bounds bounds new_bounds in
(match t_actual.t,is_top with
| Tapp("register",[TA_typ u]),_ ->
let t',cs = type_consistent (Expr l) d_env false ty u in
let ef = {effect=Eset[BE_aux(BE_wreg,l)]} in
- (LEXP_aux(lexp,(l,(Base(([],t),External (Some i),cs,ef,nob)))),ty,Envmap.empty,External (Some i),[],ef)
+ (LEXP_aux(lexp,(l,(Base(([],t),External (Some i),cs,ef,nob)))),ty,Envmap.empty,External (Some i),[],nob,ef)
| Tapp("reg",[TA_typ u]),_ ->
let t',cs = type_consistent (Expr l) d_env false ty u in
- (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,nob)))),ty,Envmap.empty,Emp_local,[],pure_e)
+ (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,bs)))),ty,Envmap.empty,Emp_local,[],bs,pure_e)
| Tapp("vector",_),false ->
- (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,nob)))),ty,Envmap.empty,Emp_local,[],pure_e)
+ (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,bs)))),ty,Envmap.empty,Emp_local,[],bs,pure_e)
| Tuvar _,_ ->
let u' = {t=Tapp("reg",[TA_typ ty])} in
- t.t <- u'.t;
- (LEXP_aux(lexp,(l,(Base((([],u'),Emp_local,cs,pure_e,nob))))),ty,Envmap.empty,Emp_local,[],pure_e)
+ t.t <- u'.t; (*Should be equate_t*)
+ (LEXP_aux(lexp,(l,(Base((([],u'),Emp_local,cs,pure_e,bs))))),ty,Envmap.empty,Emp_local,[],bs,pure_e)
| (Tfn _ ,_) ->
(match tag with
| External _ | Spec | Emp_global ->
- let u = new_t() in
- let t = {t = Tapp("reg",[TA_typ u])} in
- let tannot = (Base(([],t),Emp_local,[],pure_e,nob)) in
- (LEXP_aux(lexp,(l,tannot)),u,Envmap.from_list [i,tannot],Emp_local,[],pure_e)
+ let tannot = (Base(([],ty),Emp_local,[],pure_e,new_bounds)) in
+ (LEXP_aux(lexp,(l,tannot)),ty,Envmap.from_list [i,tannot],Emp_local,[],new_bounds,pure_e)
| _ ->
typ_error l ("Can only assign to identifiers with type register or reg, found identifier " ^ i ^ " with type " ^ t_to_string t))
| _,_ ->
@@ -1417,13 +1417,14 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
then typ_error l
("Can only assign to identifiers with type register or reg, found identifier " ^ i ^ " with type " ^ t_to_string t)
else
- (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,nob)))),ty,Envmap.empty,Emp_local,[],pure_e)) (* TODO, make sure this is a record *)
+ (* TODO, make sure this is a record *)
+ (LEXP_aux(lexp,(l,(Base(([],t),Emp_local,cs,pure_e,nob)))),ty,Envmap.empty,Emp_local,[],nob,pure_e))
| _ ->
let t = {t=Tapp("reg",[TA_typ ty])} in
- let tannot = (Base(([],t),Emp_local,[],pure_e,nob)) in
- (LEXP_aux(lexp,(l,tannot)),ty,Envmap.from_list [i,tannot],Emp_local,[],pure_e))
+ let tannot = (Base(([],t),Emp_local,[],pure_e,new_bounds)) in
+ (LEXP_aux(lexp,(l,tannot)),ty,Envmap.from_list [i,tannot],Emp_local,[],new_bounds,pure_e))
| LEXP_vector(vec,acc) ->
- let (vec',item_t,env,tag,csi,ef) = check_lexp envs imp_param false vec in
+ let (vec',item_t,env,tag,csi,bounds,ef) = check_lexp envs imp_param false vec in
let item_t,cs' = get_abbrev d_env item_t in
let item_actual = match item_t.t with | Tabbrev(_,t) -> t | _ -> item_t in
(match item_actual.t with
@@ -1433,17 +1434,17 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
| Odec -> {t = Tapp("range",[TA_nexp {nexp = Nadd(base,{nexp=Nneg rise})};TA_nexp rise])}
| _ -> typ_error l ("Assignment to one vector element requires either inc or dec order")
in
- let (e,t',_,cs',ef_e) = check_exp envs imp_param acc_t acc in
+ let (e,t',_,cs',_,ef_e) = check_exp envs imp_param acc_t acc in
let t,add_reg_write =
match t.t with
| Tapp("register",[TA_typ t]) | Tabbrev(_,{t=Tapp("register",[TA_typ t])}) -> t,true
| _ -> t,false in
let ef = if add_reg_write then add_effect (BE_aux(BE_wreg,l)) ef else ef in
- (LEXP_aux(LEXP_vector(vec',e),(l,Base(([],t),tag,csi,ef,nob))),t,env,tag,csi@cs',union_effects ef ef_e)
- | Tuvar _ -> typ_error l "Assignment to one position expected a vector with a known order, found a polymorphic value, try adding a cast"
+ (LEXP_aux(LEXP_vector(vec',e),(l,Base(([],t),tag,csi,ef,nob))),t,env,tag,csi@cs',bounds,union_effects ef ef_e)
+ | Tuvar _ -> typ_error l "Assignment to one position expected a vector with a known order, found a polymorphic value, try adding an annotation"
| _ -> typ_error l ("Assignment expected vector, found assignment to type " ^ (t_to_string item_t)))
| LEXP_vector_range(vec,e1,e2)->
- let (vec',item_t,env,tag,csi,ef) = check_lexp envs imp_param false vec in
+ let (vec',item_t,env,tag,csi,bounds,ef) = check_lexp envs imp_param false vec in
let item_t,cs = get_abbrev d_env item_t in
let item_actual = match item_t.t with | Tabbrev(_,t) -> t | _ -> item_t in
let item_actual,add_reg_write,cs =
@@ -1457,8 +1458,8 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
let base_e1,range_e1,base_e2,range_e2 = new_n(),new_n(),new_n(),new_n() in
let base_t = {t=Tapp("range",[TA_nexp base_e1;TA_nexp range_e1])} in
let range_t = {t=Tapp("range",[TA_nexp base_e2;TA_nexp range_e2])} in
- let (e1',base_t',_,cs1,ef_e) = check_exp envs imp_param base_t e1 in
- let (e2',range_t',_,cs2,ef_e') = check_exp envs imp_param range_t e2 in
+ let (e1',base_t',_,cs1,_,ef_e) = check_exp envs imp_param base_t e1 in
+ let (e2',range_t',_,cs2,_,ef_e') = check_exp envs imp_param range_t e2 in
let base_e1,range_e1,base_e2,range_e2 = match base_t'.t,range_t'.t with
| (Tapp("range",[TA_nexp base_e1;TA_nexp range_e1]),
Tapp("range",[TA_nexp base_e2;TA_nexp range_e2])) -> base_e1,range_e1,base_e2,range_e2
@@ -1481,11 +1482,11 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
in
let cs = cs_t@cs@cs1@cs2 in
let ef = union_effects ef (union_effects ef_e ef_e') in
- (LEXP_aux(LEXP_vector_range(vec',e1',e2'),(l,Base(([],item_t),tag,cs,ef,nob))),res_t,env,tag,cs,ef)
- | Tuvar _ -> typ_error l "Assignement to a range of elements requires a vector with a known order, found a polymorphic value, try addinga cast"
+ (LEXP_aux(LEXP_vector_range(vec',e1',e2'),(l,Base(([],item_t),tag,cs,ef,nob))),res_t,env,tag,cs,bounds,ef)
+ | Tuvar _ -> typ_error l "Assignement to a range of elements requires a vector with a known order, found a polymorphic value, try adding an annotation"
| _ -> typ_error l ("Assignment expected vector, found assignment to type " ^ (t_to_string item_t)))
| LEXP_field(vec,id)->
- let (vec',item_t,env,tag,csi,ef) = check_lexp envs imp_param false vec in
+ let (vec',item_t,env,tag,csi,bounds,ef) = check_lexp envs imp_param false vec in
let vec_t = match vec' with
| LEXP_aux(_,(l',Base((parms,t),_,_,_,_))) -> t
| _ -> item_t in
@@ -1502,46 +1503,46 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot))) : (tannot lexp *
| Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot")
| Base((params,et),_,cs,_,_) ->
let et,cs,ef = subst params et cs ef in
- (LEXP_aux(LEXP_field(vec',id),(l,(Base(([],vec_t),tag,csi@cs,ef,nob)))),et,env,tag,csi@cs,ef)))
+ (LEXP_aux(LEXP_field(vec',id),(l,(Base(([],vec_t),tag,csi@cs,ef,nob)))),et,env,tag,csi@cs,bounds,ef)))
| _ -> typ_error l ("Expected a register binding here, found " ^ (t_to_string item_t)))
-and check_lbind envs imp_param is_top_level emp_tag (LB_aux(lbind,(l,annot))) : tannot letbind * tannot emap * nexp_range list * effect =
- let Env(d_env,t_env) = envs in
+and check_lbind envs imp_param is_top_level emp_tag (LB_aux(lbind,(l,annot))) : tannot letbind * tannot emap * nexp_range list * bounds_env * effect =
+ let Env(d_env,t_env,b_env) = envs in
match lbind with
| LB_val_explicit(typ,pat,e) ->
let tan = typschm_to_tannot envs false false typ emp_tag in
(match tan with
| Base((params,t),tag,cs,ef,b) ->
let t,cs,ef = subst params t cs ef in
- let (pat',env,cs1,u) = check_pattern envs emp_tag t pat in
- let (e,t,_,cs2,ef2) = check_exp envs imp_param t e in
+ let (pat',env,cs1,bounds,u) = check_pattern envs emp_tag t pat in
+ let (e,t,_,cs2,_,ef2) = check_exp envs imp_param t e in
let cs = if is_top_level then resolve_constraints cs@cs1@cs2 else cs@cs1@cs2 in
let ef = union_effects ef ef2 in
let tannot = if is_top_level
- then check_tannot l (Base((params,t),tag,cs,ef,b)) None cs ef (*in top level, must be pure_e*)
- else (Base ((params,t),tag,cs,ef,b))
+ then check_tannot l (Base((params,t),tag,cs,ef,bounds)) None cs ef (*in top level, must be pure_e*)
+ else (Base ((params,t),tag,cs,ef,bounds))
in
- (LB_aux (LB_val_explicit(typ,pat',e),(l,tannot)),env,cs,ef)
+ (LB_aux (LB_val_explicit(typ,pat',e),(l,tannot)),env,cs,bounds,ef)
| NoTyp | Overload _ -> raise (Reporting_basic.err_unreachable l "typschm_to_tannot failed to produce a Base"))
| LB_val_implicit(pat,e) ->
let t = new_t () in
- let (pat',env,cs1,u) = check_pattern envs emp_tag (new_t ()) pat in
- let (e,t',_,cs2,ef) = check_exp envs imp_param u e in
+ let (pat',env,cs1,bounds,u) = check_pattern envs emp_tag (new_t ()) pat in
+ let (e,t',_,cs2,_,ef) = check_exp envs imp_param u e in
let cs = if is_top_level then resolve_constraints cs1@cs2 else cs1@cs2 in
let tannot =
- if is_top_level then check_tannot l (Base(([],t'),emp_tag,cs,ef,nob)) None cs ef (* see above *)
- else (Base (([],t'),emp_tag,cs,ef,nob))
+ if is_top_level then check_tannot l (Base(([],t'),emp_tag,cs,ef,bounds)) None cs ef (* see above *)
+ else (Base (([],t'),emp_tag,cs,ef,bounds))
in
- (LB_aux (LB_val_implicit(pat',e),(l,tannot)), env,cs,ef)
+ (LB_aux (LB_val_implicit(pat',e),(l,tannot)), env,cs,bounds,ef)
(*val check_type_def : envs -> (tannot type_def) -> (tannot type_def) envs_out*)
let check_type_def envs (TD_aux(td,(l,annot))) =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
match td with
| TD_abbrev(id,nmscm,typschm) ->
let tan = typschm_to_tannot envs false false typschm Emp_global in
(TD_aux(td,(l,tan)),
- Env( { d_env with abbrevs = Envmap.insert d_env.abbrevs ((id_to_string id),tan)},t_env))
+ Env( { d_env with abbrevs = Envmap.insert d_env.abbrevs ((id_to_string id),tan)},t_env,b_env))
| TD_record(id,nmscm,typq,fields,_) ->
let id' = id_to_string id in
let (params,typarms,constraints) = typq_to_params envs typq in
@@ -1550,7 +1551,7 @@ let check_type_def envs (TD_aux(td,(l,annot))) =
(*TODO This should create some bindings*)
let fields' = List.map
(fun (ty,i)->(id_to_string i),Base((params,(typ_to_t false false ty)),Emp_global,constraints,pure_e,nob)) fields in
- (TD_aux(td,(l,tyannot)),Env({d_env with rec_env = (id',Record,fields')::d_env.rec_env},t_env))
+ (TD_aux(td,(l,tyannot)),Env({d_env with rec_env = (id',Record,fields')::d_env.rec_env},t_env,b_env))
| TD_variant(id,nmscm,typq,arms,_) ->
let id' = id_to_string id in
let (params,typarms,constraints) = typq_to_params envs typq in
@@ -1566,14 +1567,14 @@ let check_type_def envs (TD_aux(td,(l,annot))) =
| Tu_ty_id(typ,i)-> ((id_to_string i),(arm_t (typ_to_t false false typ))))
arms in
let t_env = List.fold_right (fun (id,tann) t_env -> Envmap.insert t_env (id,tann)) arms' t_env in
- (TD_aux(td,(l,tyannot)),(Env (d_env,t_env)))
+ (TD_aux(td,(l,tyannot)),(Env (d_env,t_env,b_env)))
| TD_enum(id,nmscm,ids,_) ->
let id' = id_to_string id in
let ids' = List.map id_to_string ids in
let ty = Base (([],{t = Tid id' }),Enum,[],pure_e,nob) in
let t_env = List.fold_right (fun id t_env -> Envmap.insert t_env (id,ty)) ids' t_env in
let enum_env = Envmap.insert d_env.enum_env (id',ids') in
- (TD_aux(td,(l,ty)),Env({d_env with enum_env = enum_env;},t_env))
+ (TD_aux(td,(l,ty)),Env({d_env with enum_env = enum_env;},t_env,b_env))
| TD_register(id,base,top,ranges) ->
let id' = id_to_string id in
let basei = normalize_nexp(anexp_to_nexp base) in
@@ -1606,7 +1607,7 @@ let check_type_def envs (TD_aux(td,(l,annot))) =
let tannot = into_register d_env (Base(([],ty),Emp_global,[],pure_e,nob)) in
(TD_aux(td,(l,tannot)),
Env({d_env with rec_env = ((id',Register,franges)::d_env.rec_env);
- abbrevs = Envmap.insert d_env.abbrevs (id',tannot)},t_env)))
+ abbrevs = Envmap.insert d_env.abbrevs (id',tannot)},t_env,b_env)))
else (
let ty = {t = Tapp("vector",[TA_nexp basei; TA_nexp{nexp=Nconst(add_big_int (sub_big_int b t) one)};
TA_ord({order = Odec}); TA_typ({t = Tid "bit"});])} in
@@ -1635,38 +1636,39 @@ let check_type_def envs (TD_aux(td,(l,annot))) =
let tannot = into_register d_env (Base(([],ty),Emp_global,[],pure_e,nob)) in
(TD_aux(td,(l,tannot)),
Env({d_env with rec_env = (id',Register,franges)::d_env.rec_env;
- abbrevs = Envmap.insert d_env.abbrevs (id',tannot)},t_env)))
+ abbrevs = Envmap.insert d_env.abbrevs (id',tannot)},t_env,b_env)))
| _,_ -> raise (Reporting_basic.err_unreachable l "Nexps in register declaration do not evaluate to constants")
let check_val_spec envs (VS_aux(vs,(l,annot))) =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
match vs with
| VS_val_spec(typs,id) ->
let tannot = typschm_to_tannot envs true true typs Spec in
(VS_aux(vs,(l,tannot)),
- Env(d_env,(Envmap.insert t_env (id_to_string id,tannot))))
+ (*Should maybe add to bounds here*)
+ Env(d_env,(Envmap.insert t_env (id_to_string id,tannot)),b_env))
| VS_extern_no_rename(typs,id) ->
let tannot = typschm_to_tannot envs true true typs (External None) in
(VS_aux(vs,(l,tannot)),
- Env(d_env,(Envmap.insert t_env (id_to_string id,tannot))))
+ Env(d_env,(Envmap.insert t_env (id_to_string id,tannot)),b_env))
| VS_extern_spec(typs,id,s) ->
let tannot = typschm_to_tannot envs true true typs (External (Some s)) in
(VS_aux(vs,(l,tannot)),
- Env(d_env,(Envmap.insert t_env (id_to_string id,tannot))))
+ Env(d_env,(Envmap.insert t_env (id_to_string id,tannot)), b_env))
let check_default envs (DT_aux(ds,l)) =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
match ds with
| DT_kind _ -> ((DT_aux(ds,l)),envs)
- | DT_order ord -> (DT_aux(ds,l), Env({d_env with default_o = (aorder_to_ord ord)},t_env))
+ | DT_order ord -> (DT_aux(ds,l), Env({d_env with default_o = (aorder_to_ord ord)},t_env,b_env))
| DT_typ(typs,id) ->
let tannot = typschm_to_tannot envs false false typs Default in
(DT_aux(ds,l),
- Env(d_env,(Envmap.insert t_env (id_to_string id,tannot))))
+ Env(d_env,(Envmap.insert t_env (id_to_string id,tannot)),b_env))
let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,annot))) =
(*let _ = Printf.printf "checking fundef\n" in*)
- let Env(d_env,t_env) = envs in
+ let Env(d_env,t_env,b_env) = envs in
let _ = reset_fresh () in
let is_rec = match recopt with
| Rec_aux(Rec_nonrec,_) -> false
@@ -1691,11 +1693,11 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
List.split
(List.map (fun (FCL_aux((FCL_Funcl(id,pat,exp)),(l,_))) ->
(*let _ = Printf.printf "checking function %s : %s -> %s\n" (id_to_string id) (t_to_string param_t) (t_to_string ret_t) in*)
- let (pat',t_env',cs_p,t') = check_pattern (Env(d_env,t_env)) Emp_local param_t pat in
+ let (pat',t_env',cs_p,b_env',t') = check_pattern (Env(d_env,t_env,b_env)) Emp_local param_t pat in
(*let _ = Printf.printf "about to check that %s and %s are consistent\n" (t_to_string t') (t_to_string param_t) in*)
let t', _ = type_consistent (Patt l) d_env false param_t t' in
- let exp',_,_,cs_e,ef =
- check_exp (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env t_env')) imp_param ret_t exp in
+ let exp',_,_,cs_e,_,ef =
+ check_exp (Env(d_env,Envmap.union_merge (tannot_merge (Expr l) d_env true) t_env t_env', merge_bounds b_env b_env')) imp_param ret_t exp in
(*let _ = Printf.printf "checked function %s : %s -> %s\n" (id_to_string id) (t_to_string param_t) (t_to_string ret_t) in*)
let cs = [CondCons(Fun l,cs_p,cs_e)] in
(FCL_aux((FCL_Funcl(id,pat',exp')),(l,(Base(([],ret_t),Emp_global,cs,ef,nob)))),(cs,ef))) funcls) in
@@ -1727,7 +1729,7 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
| Some {nexp = Nvar i} -> List.map (update_pattern i) funcls in
(*let _ = Printf.printf "done funcheck case 1\n" in*)
(FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,tannot))),
- Env(d_env,Envmap.insert t_env (id,tannot))
+ Env(d_env,Envmap.insert t_env (id,tannot),b_env)
| _ , _->
let t_env = if is_rec then Envmap.insert t_env (id,tannot) else t_env in
let funcls,cs_ef = check t_env None in
@@ -1736,11 +1738,11 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
let tannot = check_tannot l tannot None cs' ef in
(*let _ = Printf.printf "done funcheck case2\n" in*)
(FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,tannot))),
- Env(d_env,(if is_rec then t_env else Envmap.insert t_env (id,tannot)))
+ Env(d_env,(if is_rec then t_env else Envmap.insert t_env (id,tannot)),b_env)
(*TODO Only works for inc vectors, need to add support for dec*)
let check_alias_spec envs alias (AL_aux(al,(l,annot))) e_typ =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
let check_reg (RI_aux ((RI_id (Id_aux(_,l) as id)), _)) : (string * tannot reg_id * typ * typ) =
let i = id_to_string id in
(match Envmap.apply t_env i with
@@ -1775,7 +1777,7 @@ let check_alias_spec envs alias (AL_aux(al,(l,annot))) e_typ =
| _ -> let _ = Printf.printf "%s\n" (t_to_string reg_t) in assert false)
| AL_bit(reg_a,bit) ->
let (reg,reg_a,reg_t,t) = check_reg reg_a in
- let (E_aux(bit,(le,eannot)),_,_,_,_) = check_exp envs None (new_t ()) bit in
+ let (E_aux(bit,(le,eannot)),_,_,_,_,_) = check_exp envs None (new_t ()) bit in
(match t.t with
| Tapp("vector",[TA_nexp base;TA_nexp len;TA_ord order;TA_typ item_t]) ->
match (base.nexp,len.nexp,order.order, bit) with
@@ -1789,8 +1791,8 @@ let check_alias_spec envs alias (AL_aux(al,(l,annot))) e_typ =
| _ -> assert false)
| AL_slice(reg_a,sl1,sl2) ->
let (reg,reg_a,reg_t,t) = check_reg reg_a in
- let (E_aux(sl1,(le1,eannot1)),_,_,_,_) = check_exp envs None (new_t ()) sl1 in
- let (E_aux(sl2,(le2,eannot2)),_,_,_,_) = check_exp envs None (new_t ()) sl2 in
+ let (E_aux(sl1,(le1,eannot1)),_,_,_,_,_) = check_exp envs None (new_t ()) sl1 in
+ let (E_aux(sl2,(le2,eannot2)),_,_,_,_,_) = check_exp envs None (new_t ()) sl2 in
(match t.t with
| Tapp("vector",[TA_nexp base;TA_nexp len;TA_ord order;TA_typ item_t]) ->
match (base.nexp,len.nexp,order.order, sl1,sl2) with
@@ -1819,7 +1821,7 @@ let check_alias_spec envs alias (AL_aux(al,(l,annot))) e_typ =
(*val check_def : envs -> tannot def -> (tannot def) envs_out*)
let check_def envs def =
- let (Env(d_env,t_env)) = envs in
+ let (Env(d_env,t_env,b_env)) = envs in
match def with
| DEF_type tdef ->
(*let _ = Printf.printf "checking type def\n" in*)
@@ -1833,9 +1835,9 @@ let check_def envs def =
(DEF_fundef fd,envs)
| DEF_val letdef ->
(*let _ = Printf.eprintf "checking letdef\n" in*)
- let (letbind,t_env_let,_,eft) = check_lbind envs None true Emp_global letdef in
+ let (letbind,t_env_let,_,b_env_let,eft) = check_lbind envs None true Emp_global letdef in
(*let _ = Printf.eprintf "checked letdef\n" in*)
- (DEF_val letbind,Env(d_env,Envmap.union t_env t_env_let))
+ (DEF_val letbind,Env(d_env,Envmap.union t_env t_env_let, merge_bounds b_env b_env_let))
| DEF_spec spec ->
(*let _ = Printf.eprintf "checking spec\n" in*)
let vs,envs = check_val_spec envs spec in
@@ -1849,20 +1851,20 @@ let check_def envs def =
let i = id_to_string id in
let tannot = into_register d_env (Base(([],t),External (Some i),[],pure_e,nob)) in
(*let _ = Printf.eprintf "done checking reg dec\n" in*)
- (DEF_reg_dec(DEC_aux(DEC_reg(typ,id),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot))))
+ (DEF_reg_dec(DEC_aux(DEC_reg(typ,id),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot),b_env)))
| DEF_reg_dec(DEC_aux(DEC_alias(id,aspec), (l,annot))) ->
(*let _ = Printf.eprintf "checking reg dec b\n" in*)
let i = id_to_string id in
let (aspec,tannot,d_env) = check_alias_spec envs i aspec None in
(*let _ = Printf.eprintf "done checking reg dec b\n" in *)
- (DEF_reg_dec(DEC_aux(DEC_alias(id,aspec),(l,tannot))),(Env(d_env, Envmap.insert t_env (i,tannot))))
+ (DEF_reg_dec(DEC_aux(DEC_alias(id,aspec),(l,tannot))),(Env(d_env, Envmap.insert t_env (i,tannot),b_env)))
| DEF_reg_dec(DEC_aux(DEC_typ_alias(typ,id,aspec),(l,tannot))) ->
(*let _ = Printf.eprintf "checking reg dec c\n" in*)
let i = id_to_string id in
let t = typ_to_t false false typ in
let (aspec,tannot,d_env) = check_alias_spec envs i aspec (Some t) in
(*let _ = Printf.eprintf "done checking reg dec c\n" in*)
- (DEF_reg_dec(DEC_aux(DEC_typ_alias(typ,id,aspec),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot))))
+ (DEF_reg_dec(DEC_aux(DEC_typ_alias(typ,id,aspec),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot),b_env)))
| DEF_scattered _ -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "Scattered given to type checker")
diff --git a/src/type_check.mli b/src/type_check.mli
index a5056ee7..4802a831 100644
--- a/src/type_check.mli
+++ b/src/type_check.mli
@@ -4,7 +4,7 @@ type kind = Type_internal.kind
type typ = Type_internal.t
type 'a emap = 'a Envmap.t
-type envs = Env of def_envs * tannot emap
+type envs = Env of def_envs * tannot emap * bounds_env
type 'a envs_out = 'a * envs
diff --git a/src/type_internal.ml b/src/type_internal.ml
index 385cb4a3..7a745ee6 100644
--- a/src/type_internal.ml
+++ b/src/type_internal.ml
@@ -97,17 +97,20 @@ type nexp_range =
| BranchCons of constraint_origin * nexp_range list
type variable_range =
- | VR_Eq of string * nexp
- | VR_Range of string * nexp_range list
+ | VR_eq of string * nexp
+ | VR_range of string * nexp_range list
+ | VR_vec_eq of string * nexp
+ | VR_vec_r of string * nexp_range list
+ | VR_recheck of string * t (*For cases where inference hasn't yet determined the type of v*)
-type bound_env =
+type bounds_env =
| No_bounds
| Bounds of variable_range list
type t_params = (string * kind) list
type tannot =
| NoTyp
- | Base of (t_params * t) * tag * nexp_range list * effect * bound_env
+ | Base of (t_params * t) * tag * nexp_range list * effect * bounds_env
(* First tannot is the most polymorphic version; the list includes all variants. All included t are Tfn *)
| Overload of tannot * bool * tannot list
@@ -828,6 +831,9 @@ let simple_annot t = Base(([],t),Emp_local,[],pure_e,nob)
let global_annot t = Base(([],t),Emp_global,[],pure_e,nob)
let tag_annot t tag = Base(([],t),tag,[],pure_e,nob)
let constrained_annot t cs = Base(([],t),Emp_local,cs,pure_e,nob)
+let cons_tag_annot t tag cs = Base(([],t),tag,cs,pure_e,nob)
+let cons_ef_annot t cs ef = Base(([],t),Emp_local,cs,ef,nob)
+let cons_bs_annot t cs bs = Base(([],t),Emp_local,cs,pure_e,bs)
let initial_abbrev_env =
Envmap.from_list [
@@ -1766,20 +1772,22 @@ let build_variable_range d_env v typ =
let t,_ = get_abbrev d_env typ in
let t_actual = match t.t with | Tabbrev(_,t) -> t | _ -> t in
match t_actual.t with
- | Tapp("atom", [TA_nexp n]) -> Some(VR_Eq(v,n))
- | Tapp("range", [TA_nexp base;TA_nexp top]) -> Some(VR_Range(v,[LtEq((Patt Unknown),base,top)]))
+ | Tapp("atom", [TA_nexp n]) -> Some(VR_eq(v,n))
+ | Tapp("range", [TA_nexp base;TA_nexp top]) -> Some(VR_range(v,[LtEq((Patt Unknown),base,top)]))
+ | Tapp("vector", [TA_nexp start; TA_nexp rise; _; _]) -> Some(VR_vec_eq(v,rise))
+ | Tuvar _ -> Some(VR_recheck(v,t_actual))
| _ -> None
-let get_vr_var = function | VR_Eq (v,_) | VR_Range(v,_) -> v
+let get_vr_var = function | VR_eq (v,_) | VR_range(v,_) -> v | VR_vec_eq(v,_) -> v | VR_vec_r(v,_) -> v | VR_recheck(v,_) -> v
let compare_variable_range v1 v2 = compare (get_vr_var v1) (get_vr_var v2)
-let build_binding d_env v typ =
+let extract_bounds d_env v typ =
match build_variable_range d_env v typ with
| None -> No_bounds
| Some vb -> Bounds [vb]
-let find_binding v bounds = match bounds with
+let find_bounds v bounds = match bounds with
| No_bounds -> None
| Bounds bs ->
let rec find_rec bs = match bs with
@@ -1787,7 +1795,7 @@ let find_binding v bounds = match bounds with
| b::bs -> if (get_vr_var b) = v then Some(b) else find_rec bs in
find_rec bs
-let merge_binding b1 b2 =
+let merge_bounds b1 b2 =
match b1,b2 with
| No_bounds,b | b,No_bounds -> b
| Bounds b1s,Bounds b2s ->
@@ -1800,11 +1808,15 @@ let merge_binding b1 b2 =
| -1 -> b1::(merge b1s (b2::b2s))
| 1 -> b2::(merge (b1::b1s) b2s)
| 0 -> (match b1,b2 with
- | VR_Eq(v,n1),VR_Eq(_,n2) ->
- if nexp_eq n1 n2 then b1 else VR_Range(v,[Eq((Patt Unknown),n1,n2)])
- | VR_Eq(v,n),VR_Range(_,ranges) |
- VR_Range(v,ranges),VR_Eq(_,n) -> VR_Range(v,(Eq((Patt Unknown),n,n))::ranges)
- | VR_Range(v,ranges1),VR_Range(_,ranges2) -> VR_Range(v,ranges1@ranges2)
+ | VR_eq(v,n1),VR_eq(_,n2) ->
+ if nexp_eq n1 n2 then b1 else VR_range(v,[Eq((Patt Unknown),n1,n2)])
+ | VR_eq(v,n),VR_range(_,ranges) |
+ VR_range(v,ranges),VR_eq(_,n) -> VR_range(v,(Eq((Patt Unknown),n,n))::ranges)
+ | VR_range(v,ranges1),VR_range(_,ranges2) -> VR_range(v,ranges1@ranges2)
+ | VR_vec_eq(v,n1),VR_vec_eq(_,n2) ->
+ if nexp_eq n1 n2 then b1 else VR_vec_r(v,[Eq((Patt Unknown),n1,n2)])
+ | VR_vec_eq(v,n),VR_vec_r(_,ranges) |
+ VR_vec_r(v,ranges),VR_vec_eq(_,n) -> VR_vec_r(v,(Eq((Patt Unknown),n,n)::ranges))
)::(merge b1s b2s) in
Bounds (merge b1s b2s)
@@ -2389,19 +2401,19 @@ let tannot_merge co denv widen t_older t_newer =
| NoTyp,NoTyp -> NoTyp
| NoTyp,_ -> t_newer
| _,NoTyp -> t_older
- | Base((ps_o,t_o),tag_o,cs_o,ef_o,bindings_o),Base((ps_n,t_n),tag_n,cs_n,ef_n,bindings_n) ->
+ | Base((ps_o,t_o),tag_o,cs_o,ef_o,bounds_o),Base((ps_n,t_n),tag_n,cs_n,ef_n,bounds_n) ->
(match tag_o,tag_n with
| Default,tag ->
(match t_n.t with
| Tuvar _ -> let t_o,cs_o,ef_o = subst ps_o t_o cs_o ef_o in
let t,_ = type_consistent co denv false t_n t_o in
- Base(([],t),tag_n,cs_o,ef_o,bindings_o)
+ Base(([],t),tag_n,cs_o,ef_o,bounds_o)
| _ -> t_newer)
| Emp_local, Emp_local ->
(*let _ = Printf.printf "local-local case\n" in*)
(*TODO Check conforms to first; if true check consistent, if false replace with t_newer *)
let t,cs_b = type_consistent co denv widen t_n t_o in
(*let _ = Printf.printf "types consistent\n" in*)
- Base(([],t),Emp_local,cs_o@cs_n@cs_b,union_effects ef_o ef_n, merge_binding bindings_o bindings_n)
+ Base(([],t),Emp_local,cs_o@cs_n@cs_b,union_effects ef_o ef_n, merge_bounds bounds_o bounds_n)
| _,_ -> t_newer)
| _ -> t_newer
diff --git a/src/type_internal.mli b/src/type_internal.mli
index c14828c4..f3a2249c 100644
--- a/src/type_internal.mli
+++ b/src/type_internal.mli
@@ -104,17 +104,20 @@ val n_one : nexp
val n_two : nexp
type variable_range =
- | VR_Eq of string * nexp
- | VR_Range of string * nexp_range list
+ | VR_eq of string * nexp
+ | VR_range of string * nexp_range list
+ | VR_vec_eq of string * nexp
+ | VR_vec_r of string * nexp_range list
+ | VR_recheck of string * t (*For cases where inference hasn't yet determined the type of v*)
-type bound_env =
+type bounds_env =
| No_bounds
| Bounds of variable_range list
type t_params = (string * kind) list
type tannot =
| NoTyp
- | Base of (t_params * t) * tag * nexp_range list * effect * bound_env
+ | Base of (t_params * t) * tag * nexp_range list * effect * bounds_env
(* First tannot is the most polymorphic version; the list includes all variants. All t to be Tfn *)
| Overload of tannot * bool * tannot list
@@ -151,12 +154,15 @@ val unit_t : t
val bool_t : t
val bit_t : t
val pure_e : effect
-val nob : bound_env
+val nob : bounds_env
val simple_annot : t -> tannot
val global_annot : t -> tannot
val tag_annot : t -> tag -> tannot
val constrained_annot : t -> nexp_range list -> tannot
+val cons_tag_annot : t -> tag -> nexp_range list -> tannot
+val cons_ef_annot : t -> nexp_range list -> effect -> tannot
+val cons_bs_annot : t -> nexp_range list -> bounds_env -> tannot
val t_to_string : t -> string
val n_to_string : nexp -> string
@@ -175,7 +181,8 @@ val equate_t : t -> t -> unit
val subst : (string * kind) list -> t -> nexp_range list -> effect -> t * nexp_range list * effect
val get_abbrev : def_envs -> t -> (t * nexp_range list)
-val build_binding : def_envs -> string -> t -> bound_env
+val extract_bounds : def_envs -> string -> t -> bounds_env
+val merge_bounds : bounds_env -> bounds_env -> bounds_env
val normalize_nexp : nexp -> nexp
val get_index : nexp -> int (*TEMPORARILY expose nindex through this for debugging purposes*)