summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/_tags2
-rw-r--r--src/type_check.ml54
-rw-r--r--src/type_internal.ml400
-rw-r--r--src/type_internal.mli2
4 files changed, 241 insertions, 217 deletions
diff --git a/src/_tags b/src/_tags
index a90c5e30..8ec7acb9 100644
--- a/src/_tags
+++ b/src/_tags
@@ -6,7 +6,7 @@ true: -traverse, debug
# see http://caml.inria.fr/mantis/view.php?id=4943
<lem_interp/*> and not <lem_interp/*.cmxa>: use_nums, use_lem
-<test/*> and not <test/*.cmxa>: use_nums, use_lem, use_str, use_batteries
+<test/*> and not <test/*.cmxa>: use_nums, use_lem, use_str
# disable partial match and unused variable warnings
<**/*.ml>: warn_y
diff --git a/src/type_check.ml b/src/type_check.ml
index e6c11eb1..4364acd5 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -271,7 +271,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
(P_aux(p,(l,pat_annot)),Envmap.from_list [(i,id_annot)],cs,default_bounds,expect_t) in
(match Envmap.apply t_env i with
| Some(Base((params,t),Constructor n,cs,efl,efr,bounds)) ->
- let t,cs,ef,_ = subst params false t cs efl in
+ let t,cs,ef,_ = subst params false false t cs efl in
(match t.t with
| Tfn({t = Tid "unit"},t',IP_none,ef) ->
if conforms_to_t d_env false false t' expect_t
@@ -285,7 +285,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
else default
| _ -> raise (Reporting_basic.err_unreachable l "Constructor tannot does not have function type"))
| Some(Base((params,t),Enum max,cs,efl,efr,bounds)) ->
- let t,cs,ef,_ = subst params false t cs efl in
+ let t,cs,ef,_ = subst params false false t cs efl in
if conforms_to_t d_env false false t expect_t
then
let tp,cp = type_consistent (Expr l) d_env Guarantee false t expect_t in
@@ -298,7 +298,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
(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 n,constraints,efl,efr,bounds)) ->
- let t,dec_cs,_,_ = subst params false t constraints efl in
+ let t,dec_cs,_,_ = subst params false false t constraints efl in
(match t.t with
| Tid id -> if pats = []
then let t',ret_cs = type_consistent (Patt l) d_env Guarantee false t expect_t in
@@ -330,7 +330,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
| (Base((vs,t),tag,cs,eft,_,bounds)) ->
(*let tup = {t = Ttup(List.map (fun (t,_,_,_) -> t) typ_pats)} in*)
(*let ft = {t = Tfn(tup,t, IP_none,pure_e) } in*)
- let (ft_subst,cs,_,_) = subst vs false t cs pure_e in
+ let (ft_subst,cs,_,_) = subst vs false false t cs pure_e in
let subst_rtyp,subst_typs =
match ft_subst.t with | Tfn({t=Ttup tups},rt,_,_) -> rt,tups
| _ -> raise (Reporting_basic.err_unreachable l "fields_to_rec gave a non function type") in
@@ -493,7 +493,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
let i = id_to_string id in
(match Envmap.apply t_env i with
| Some(Base((params,t),(Constructor n),cs,ef,_,bounds)) ->
- let t,cs,ef,_ = subst params false t cs ef in
+ let t,cs,ef,_ = subst params false false t cs ef in
(match t.t with
| Tfn({t = Tid "unit"},t',IP_none,ef) ->
let e = E_aux(E_app(id, []),
@@ -504,7 +504,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
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 max),cs,ef,_,bounds)) ->
- let t',cs,_,_ = subst params false t cs ef in
+ let t',cs,_,_ = subst params false false t cs ef in
let t',cs',ef',e' =
type_coerce (Expr l) d_env Require false false b_env t' (rebuild (cons_tag_annot t' (Enum max) cs)) expect_t in
(e',t',t_env,cs@cs',nob,ef')
@@ -512,7 +512,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
typ_error l ("Identifier " ^ i ^ " must be defined, not just specified, before use")
| Some(Base((params,t),tag,cs,ef,_,bounds)) ->
let ((t,cs,ef,_),is_alias) =
- match tag with | Emp_global | External _ -> (subst params false t cs ef),false
+ match tag with | Emp_global | External _ -> (subst params false false t cs ef),false
| Alias alias_inf -> (t,cs, add_effect (BE_aux(BE_rreg, Parse_ast.Unknown)) ef, Envmap.empty),true
| _ -> (t,cs,ef,Envmap.empty),false
in
@@ -671,7 +671,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
let check_result ret imp tag cs ef efr parms =
match (imp,imp_param) with
| (IP_length n ,None) | (IP_user n,None) | (IP_start n,None) ->
- (*let _ = Printf.eprintf "implicit length or var required, no imp_param %s\n!" (n_to_string n) in*)
+ (*let _ = Printf.eprintf "app of %s implicit required, no imp_param %s\n!" i (n_to_string n) in*)
let internal_exp =
let _ = set_imp_param n in
let implicit = {t= Tapp("implicit",[TA_nexp n])} in
@@ -680,8 +680,8 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
type_coerce (Expr l) d_env Require false false b_env ret
(E_aux (E_app(id, internal_exp::parms),(l,(Base(([],ret),tag,cs,ef,efr,nob))))) expect_t
| (IP_length n ,Some ne) | (IP_user n,Some ne) | (IP_start n,Some ne) ->
- (*let _ = Printf.eprintf "implicit length or var required %s with imp_param %s\n"
- (n_to_string n) (n_to_string ne) in
+ (*let _ = Printf.eprintf "app of %s implicit length or var required %s with imp_param %s\n"
+ i (n_to_string n) (n_to_string ne) in
let _ = Printf.eprintf "and expected type is %s and return type is %s\n"
(t_to_string expect_t) (t_to_string ret) in*)
let _ = set_imp_param n; set_imp_param ne in
@@ -695,7 +695,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
type_coerce (Expr l) d_env Require false false b_env ret
(E_aux (E_app(id,internal_exp::parms),(l,(Base(([],ret),tag,cs,ef,efr,nob))))) expect_t
| (IP_none,_) ->
- (*let _ = Printf.eprintf "no implicit length or var required: ret %s and expect_t %s\n" (t_to_string ret) (t_to_string expect_t) in*)
+ (*let _ = Printf.eprintf "no implicit: ret %s and expect_t %s\n" (t_to_string ret) (t_to_string expect_t) in*)
type_coerce (Expr l) d_env Require false false b_env ret
(E_aux (E_app(id, parms),(l,(Base(([],ret),tag,cs,ef,efr,nob))))) expect_t
in
@@ -707,7 +707,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| Some(Base((params,t),tag,cs,efl,_,bounds)) ->
(*let _ = Printf.eprintf "Going to check a function call %s with unsubstituted types %s and constraints %s \n"
i (t_to_string t) (constraints_to_string cs) in*)
- let t,cs,efl,_ = subst params false t cs efl in
+ let t,cs,efl,_ = subst params false false t cs efl in
(match t.t with
| Tfn(arg,ret,imp,efl') ->
(*let _ = Printf.eprintf "Checking funcation call of %s\n" i in
@@ -723,7 +723,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
("Expected a function or constructor, found identifier " ^ i ^ " bound to type " ^
(t_to_string t)))
| Some(Overload(Base((params,t),tag,cs,efl,_,_),overload_return,variants)) ->
- let t_p,cs_p,ef_p,_ = subst params false t cs efl in
+ let t_p,cs_p,ef_p,_ = subst params false false t cs efl in
let args,arg_t,arg_cs,arg_ef =
(match t_p.t with
| Tfn(arg,ret,_,ef') -> check_parms arg parms
@@ -781,7 +781,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| 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 false t cs ef in
+ let t,cs,ef,_ = subst params false false 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
@@ -791,7 +791,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| _ ->
typ_error l ("Expected a function, found identifier " ^ i ^ " bound to type " ^ (t_to_string t)))
| Some(Overload(Base((params,t),tag,cs,ef,_,_),overload_return,variants)) ->
- let t_p,cs_p,ef_p,_ = subst params false t cs ef in
+ let t_p,cs_p,ef_p,_ = subst params false false t cs ef in
let lft',rht',arg_t,arg_cs,arg_ef =
(match t_p.t with
| Tfn(arg,ret,_,ef') -> check_parms arg lft rht
@@ -1196,7 +1196,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| Tid(n) | Tapp(n,_)->
(match lookup_record_typ n d_env.rec_env with
| Some(((i,Record,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r)) ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
if (List.length fexps = List.length fields)
then let fexps,cons,ef = List.fold_right (field_walker r subst_env bounds tag n) fexps ([],[],pure_e) in
let e = E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,simple_annot_efr u ef)) in
@@ -1210,7 +1210,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
let field_names = List.map (fun (FE_aux(FE_Fexp(id,exp),(l,annot))) -> id_to_string id) fexps in
(match lookup_record_fields field_names d_env.rec_env with
| Some(((i,Record,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r)) ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
let fexps,cons,ef = List.fold_right (field_walker r subst_env bounds tag i) fexps ([],[],pure_e) in
let e = E_aux(E_record(FES_aux(FES_Fexps(fexps,false),l')),(l,simple_annot_efr ts ef)) in
let (t',cs',ef',e') = type_coerce (Expr l) d_env Guarantee false false b_env ts e expect_t in
@@ -1236,7 +1236,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| Some(((i,Record,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r)) ->
if (List.length fexps <= List.length fields)
then
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
let fexps,cons,ef = List.fold_right (field_walker r subst_env bounds tag i) fexps ([],[],pure_e) in
let e = E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')), (l,simple_annot_efr ts ef)) in
let (t',cs',ef',e') = type_coerce (Expr l) d_env Guarantee false false b_env ts e expect_t in
@@ -1249,7 +1249,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
(match lookup_possible_records field_names d_env.rec_env with
| [] -> typ_error l "No struct matches the set of fields given for this struct update"
| [(((i,Record,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r))] ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
let fexps,cons,ef = List.fold_right (field_walker r subst_env bounds tag i) fexps ([],[],pure_e) in
let e = E_aux(E_record_update(e',FES_aux(FES_Fexps(fexps,false),l')), (l,simple_annot_efr ts ef)) in
let (t',cs',ef',e') = type_coerce (Expr l) d_env Guarantee false false b_env ts e expect_t in
@@ -1264,7 +1264,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
| Tabbrev({t=Tid i}, _) | Tabbrev({t=Tapp(i,_)},_) | Tid i | Tapp(i,_) ->
(match lookup_record_typ i d_env.rec_env with
| Some(((i,rec_kind,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r)) ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
(match lookup_field_type fi r with
| None -> typ_error l ("Type " ^ i ^ " does not have a field " ^ fi)
| Some t ->
@@ -1289,7 +1289,7 @@ let rec check_exp envs (imp_param:nexp option) (widen:bool) (expect_t:t) (E_aux(
(match lookup_possible_records [fi] d_env.rec_env with
| [] -> typ_error l ("No struct or register has a field " ^ fi)
| [(((i,rec_kind,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r))] ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
(match lookup_field_type fi r with
| None ->
raise
@@ -1436,7 +1436,7 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot)))
| _ -> assert false)
| Some(Base((parms,t),tag,cs,_,_,b)) ->
let t,cs,ef,_ =
- match tag with | External _ | Emp_global -> subst parms false t cs pure_e
+ match tag with | External _ | Emp_global -> subst parms false false t cs pure_e
| _ -> t,cs,{effect = Eset[BE_aux(BE_lset,l)]},Envmap.empty
in
let t,cs' = get_abbrev d_env t in
@@ -1483,7 +1483,7 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot)))
let i = id_to_string id in
(match Envmap.apply t_env i with
| Some(Base((parms,t),tag,cs,ef,_,_)) ->
- let t,cs,ef,_ = subst parms false t cs ef in
+ let t,cs,ef,_ = subst parms false false t cs ef in
(match t.t with
| Tfn(apps,out,_,ef') ->
(match ef'.effect with
@@ -1544,7 +1544,7 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot)))
(match Envmap.apply t_env i with
| Some(Base((parms,t),tag,cs,_,_,bounds)) ->
let t,cs,ef,_ =
- match tag with | External _ | Emp_global -> subst parms false t cs pure_e
+ match tag with | External _ | Emp_global -> subst parms false false t cs pure_e
| _ -> t,cs,{effect=Eset[BE_aux(BE_lset,l)]},Envmap.empty
in
let t,cs' = get_abbrev d_env t in
@@ -1692,7 +1692,7 @@ and check_lexp envs imp_param is_top (LEXP_aux(lexp,(l,annot)))
| Tid i | Tabbrev({t=Tid i},_) | Tabbrev({t=Tapp(i,_)},_) | Tapp(i,_)->
(match lookup_record_typ i d_env.rec_env with
| Some(((i,rec_kind,(Base((params,t),tag,cs,eft,_,bounds)),fields) as r)) ->
- let (ts,cs,eft,subst_env) = subst params false t cs eft in
+ let (ts,cs,eft,subst_env) = subst params false false t cs eft in
(match lookup_field_type fi r with
| None -> typ_error l ("Type " ^ i ^ " does not have a field " ^ fi)
| Some t ->
@@ -1713,7 +1713,7 @@ and check_lbind envs imp_param is_top_level emp_tag (LB_aux(lbind,(l,annot))) :
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,tp_env' = subst params false t cs ef in
+ let t,cs,ef,tp_env' = subst params false true t cs ef in
let envs' = (Env(d_env,t_env,b_env,Envmap.union tp_env tp_env')) 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 true t e in
@@ -1982,7 +1982,7 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
let (ids,_,constraints) = typq_to_params envs typq in
let t = typ_to_t envs false false typ in
(*TODO add check that ids == typ_params when has_spec*)
- let t,constraints,_,t_param_env = subst (if has_spec then typ_params else ids) true t constraints pure_e in
+ let t,constraints,_,t_param_env = subst (if has_spec then typ_params else ids) true true t constraints pure_e in
let p_t = new_t () in
let ef = new_e () in
t,p_t,Base((ids,{t=Tfn(p_t,t,IP_none,ef)}),Emp_global,constraints,ef,pure_e,nob),t_param_env in
diff --git a/src/type_internal.ml b/src/type_internal.ml
index 6f5d2002..8e965df5 100644
--- a/src/type_internal.ml
+++ b/src/type_internal.ml
@@ -35,7 +35,7 @@ and t_aux =
| Tabbrev of t * t
| Toptions of t * t option
| Tuvar of t_uvar
-and t_uvar = { index : int; mutable subst : t option }
+and t_uvar = { index : int; mutable subst : t option ; mutable torig_name : string option}
and implicit_parm =
| IP_none | IP_length of nexp | IP_start of nexp | IP_user of nexp
and nexp = { mutable nexp : nexp_aux; mutable imp_param : bool}
@@ -54,7 +54,11 @@ and nexp_aux =
| Ninexact (*Result of +inf + -inf which is neither less than nor greater than other numbers really *)
| Nuvar of n_uvar
and n_uvar =
- { nindex : int; mutable nsubst : nexp option; mutable nin : bool; mutable leave_var : bool; orig_var : string option}
+ (*nindex is a counter; insubst are substitions 'inward'; outsubst are substitions 'outward'. Inward can be non nu
+ nin is in an in clause; leave_var flags if we should try to stay a variable; orig_var out inwardmost, name to use
+ *)
+ { nindex : int; mutable insubst : nexp option; mutable outsubst : nexp option;
+ mutable nin : bool; mutable leave_var : bool; mutable orig_var : string option ; mutable been_collapsed : bool }
and effect = { mutable effect : effect_aux }
and effect_aux =
| Evar of string
@@ -253,6 +257,14 @@ let get_index n =
let get_c_loc = function
| Patt l | Expr l | Specc l | Fun l -> l
+let rec get_outer_most n = match n.nexp with
+ | Nuvar {outsubst= Some n} -> get_outer_most n
+ | _ -> n
+
+let rec get_inner_most n = match n.nexp with
+ | Nuvar {insubst=Some n} -> get_inner_most n
+ | _ -> n
+
(*To string functions *)
let debug_mode = ref true;;
@@ -307,9 +319,14 @@ and n_to_string n =
| N2n(n,Some i) -> "2**" ^ (n_to_string n) ^ "(*" ^ (string_of_big_int i) ^ "*)"
| Npow(n, i) -> "(" ^ (n_to_string n) ^ ")**" ^ (string_of_int i)
| Nneg n -> "-" ^ (n_to_string n)
- | Nuvar({nindex=i;nsubst=a}) ->
+ | Nuvar _ ->
if !debug_mode
- then "Nu_" ^ string_of_int i ^ "(" ^ (match a with | None -> "None" | Some n -> n_to_string n) ^ ")"
+ then
+ let rec show_nuvar n = match n.nexp with
+ | Nuvar{insubst=None; nindex = i;} -> "Nu_" ^ string_of_int i ^ "()"
+ | Nuvar{insubst=Some n; nindex =i;} -> "Nu_" ^ string_of_int i ^ "(" ^ show_nuvar n ^ ")"
+ | _ -> n_to_string n in
+ show_nuvar (get_outer_most n)
else "_"
and ef_to_string (Ast.BE_aux(b,l)) =
match b with
@@ -508,22 +525,33 @@ let rec contains_const n =
let rec is_all_nuvar n =
match n.nexp with
- | Nuvar { nsubst = None } -> true
- | Nuvar { nsubst = Some n } -> is_all_nuvar n
+ | Nuvar { insubst = None } -> true
+ | Nuvar { insubst = Some n } -> is_all_nuvar n
| _ -> false
let rec first_non_nu n =
match n.nexp with
- | Nuvar {nsubst = None } -> None
- | Nuvar { nsubst = Some n} -> first_non_nu n
+ | Nuvar {insubst = None } -> None
+ | Nuvar { insubst = Some n} -> first_non_nu n
| _ -> Some n
-let rec change_nuvar_base n new_base =
- match n.nexp with
- | Nuvar {nsubst = Some ({nexp= Nuvar _} as in_n)} -> change_nuvar_base in_n new_base
- | Nuvar ({nsubst = Some _} as nu) -> nu.nsubst <- Some new_base; true
- | Nuvar {nsubst = None } -> false
- | _ -> false
+(*Adds new_base to inner most position of n, when that is None
+ Report whether mutation happened*)
+let add_to_nuvar_tail n new_base =
+ if n.nexp == new_base.nexp
+ then false
+ else
+ let n' = get_inner_most n in
+ let new_base' = get_outer_most new_base in
+ match n'.nexp,new_base'.nexp with
+ | Nuvar ({insubst = None} as nmu), Nuvar(nbmu) ->
+ nmu.insubst <- Some new_base';
+ nbmu.outsubst <- Some n'; true
+ | Nuvar({insubst = None} as nmu),_ ->
+ if new_base.nexp == new_base'.nexp
+ then begin nmu.insubst <- Some new_base; true end
+ else false
+ | _ -> false
let rec get_var n =
match n.nexp with
@@ -807,7 +835,7 @@ let rec normalize_n_rec recur_ok n =
(mk_add (mk_mult n11 n22)
(mk_add (mk_mult n12 n21) (mk_mult n12 n22))))
| Nuvar _, Nvar _ | Nmult _, N2n _-> mk_mult n1' n2'
- | Nuvar _, Nmult(n1,n2) | Nvar _, Nmult(n1,n2) ->
+ | Nuvar _, Nmult(n1,n2) | Nvar _, Nmult(n1,n2) -> (*TODO What's happend to n1'*)
(match get_var n1, get_var n2 with
| Some(nv1),Some(nv2) ->
(match compare_nexps nv1 nv2, n2.nexp with
@@ -873,20 +901,28 @@ let new_id _ =
let new_t _ =
let i = !t_count in
t_count := i + 1;
- let t = {t = Tuvar { index = i; subst = None }} in
+ let t = {t = Tuvar { index = i; subst = None ; torig_name = None}} in
+ tuvars := t::!tuvars;
+ t
+let new_tv rv =
+ let i = !t_count in
+ t_count := i + 1;
+ let t = {t = Tuvar { index = i; subst = None ; torig_name = Some rv}} in
tuvars := t::!tuvars;
t
let new_n _ =
let i = !n_count in
n_count := i + 1;
- let n = { nexp = Nuvar { nindex = i; nsubst = None ; nin = false ; leave_var = false; orig_var = None};
+ let n = { nexp = Nuvar { nindex = i; insubst = None; outsubst = None;
+ nin = false ; leave_var = false; orig_var = None; been_collapsed = false};
imp_param = false} in
nuvars := n::!nuvars;
n
let new_nv s =
let i = !n_count in
n_count := i + 1;
- let n = { nexp = Nuvar { nindex = i; nsubst = None ; nin = false ; leave_var = false ; orig_var = Some s};
+ let n = { nexp = Nuvar { nindex = i; insubst = None ; outsubst = None;
+ nin = false ; leave_var = false ; orig_var = Some s; been_collapsed = false};
imp_param = false} in
nuvars := n::!nuvars;
n
@@ -921,13 +957,6 @@ let rec resolve_tsubst (t : t) : t =
| Tuvar(_) -> u.subst <- Some(t''); t''
| x -> t.t <- x; t)
| _ -> t
-let rec resolve_nsubst (n : nexp) : nexp = match n.nexp with
- | Nuvar({ nsubst=Some(n') } as u) ->
- let n'' = resolve_nsubst n' in
- (match n''.nexp with
- | Nuvar(m) -> if u.nin then m.nin <- true else (); u.nsubst <- Some(n''); n''
- | x -> n.nexp <- x; n)
- | _ -> n
let rec resolve_osubst (o : order) : order = match o.order with
| Ouvar({ osubst=Some(o') } as u) ->
let o'' = resolve_osubst o' in
@@ -966,14 +995,14 @@ and occurs_check_ta (ta_box : t_arg) (ta : t_arg) : unit =
| TA_ord obox, TA_ord o -> occurs_check_o obox o
| TA_eft ebox, TA_eft e -> occurs_check_e ebox e
| _,_ -> ()
+(*light-weight occurs check, does not look within nuvar chains*)
and occurs_check_n (n_box : nexp) (n : nexp) : unit =
- let n = resolve_nsubst n in
- if n_box == n then
+ if n_box.nexp == n.nexp then
raise (Occurs_exn (TA_nexp n))
else
match n.nexp with
- | Nadd(n1,n2) | Nmult(n1,n2) -> occurs_check_n n_box n1; occurs_check_n n_box n2
- | N2n(n,_) | Nneg n -> occurs_check_n n_box n
+ | Nadd(n1,n2) | Nmult(n1,n2) | Nsub(n1,n2) -> occurs_check_n n_box n1; occurs_check_n n_box n2
+ | N2n(n,_) | Nneg n | Npow(n,_) -> occurs_check_n n_box n
| _ -> ()
and occurs_check_o (o_box : order) (o : order) : unit =
let o = resolve_osubst o in
@@ -1248,82 +1277,87 @@ let equate_t (t_box : t) (t : t) : unit =
| _ ->
t_box.t <- t.t)
-let rec occurs_in_pending_subst n_box n : bool =
- if n_box.nexp == n.nexp then true
- else match n_box.nexp with
- | Nuvar( { nsubst= Some(n') }) ->
- if n'.nexp == n.nexp
- then true
- else occurs_in_pending_subst n' n
- | Nuvar( { nsubst = None } ) ->
- (match n.nexp with
- | Nuvar( { nsubst = None }) | Nvar _ | Nid _| Nconst _ | Npos_inf | Nneg_inf | Ninexact -> false
- | Nadd(n1,n2) | Nsub(n1,n2) | Nmult(n1,n2) -> occurs_in_nexp n_box n1 || occurs_in_nexp n_box n2
- | Nneg n1 | N2n(n1,_) | Npow(n1,_) -> occurs_in_nexp n_box n1
- | Nuvar( { nsubst = Some n'}) -> occurs_in_pending_subst n_box n')
- | _ -> occurs_in_nexp n_box n
+(*Assumes that both are nuvar, and both set initially on outermost of chain *)
+let rec occurs_in_nuvar_chain n_box n : bool =
+ n_box.nexp == n.nexp || (*if both are at outermost and they are the same, then n occurs in n_box *)
+ let n_box' = get_inner_most n_box in
+ match n_box'.nexp with
+ | Nuvar( { insubst= None }) -> false
+ | Nuvar( { insubst= Some(n_box') }) -> occurs_in_nexp n_box' n
+ | _ -> occurs_in_nexp n_box' n
+(*Heavy-weight occurs check, including nuvar chains. Assumes second argument always a nuvar*)
and occurs_in_nexp n_box nuvar : bool =
(* let _ = Printf.eprintf "occurs_in_nexp given n_box %s nuvar %s eq? %b\n"
(n_to_string n_box) (n_to_string nuvar) (n_box.nexp == nuvar.nexp) in*)
if n_box.nexp == nuvar.nexp then true
else match n_box.nexp with
- | Nuvar _ -> occurs_in_pending_subst n_box nuvar
+ | Nuvar _ -> occurs_in_nuvar_chain (get_outer_most n_box) (get_outer_most nuvar)
| Nadd (nb1,nb2) | Nsub(nb1,nb2)| Nmult (nb1,nb2) -> occurs_in_nexp nb1 nuvar || occurs_in_nexp nb2 nuvar
| Nneg nb | N2n(nb,None) | Npow(nb,_) -> occurs_in_nexp nb nuvar
| _ -> false
-let rec reduce_n_unifications n =
- (*let _ = Printf.eprintf "reduce_n_unifications %s\n" (n_to_string n) in*)
- (match n.nexp with
- | Nvar _ | Nid _ | Nconst _ | Npos_inf | Nneg_inf | Ninexact-> ()
- | N2n(n1,_) | Npow(n1,_) | Nneg n1 -> reduce_n_unifications n1
- | Nadd(n1,n2) | Nsub(n1,n2) | Nmult(n1,n2) -> reduce_n_unifications n1; reduce_n_unifications n2
- | Nuvar nu ->
- (match nu.nsubst with
- | None -> ()
- | Some(nexp) ->
- reduce_n_unifications(nexp);
- if nu.leave_var then ignore(leave_nuvar(nexp)) else ();
- n.nexp <- nexp.nexp));
- (*let _ = Printf.eprintf "n reduced to %s\n" (n_to_string n) in*) ()
+(*Assumes that n is set to it's outermost n*)
+let collapse_nuvar_chain n =
+ let rec collapse n =
+ match n.nexp with
+ | Nuvar { insubst = None } -> (n,[n])
+ | Nuvar ({insubst = Some ni } as u) ->
+ (*let _ = Printf.eprintf "Collapsing %s, about to collapse it's insubst\n" (n_to_string n) in*)
+ let _,internals = collapse ni in
+ (*let _ = Printf.eprintf "Collapsed %s, with inner %s\n" (n_to_string n) (n_to_string ni) in*)
+ (match ni.nexp with
+ | Nuvar nim ->
+ u.leave_var <- u.leave_var || nim.leave_var;
+ u.nin <- u.nin || nim.nin;
+ u.orig_var <- (match u.orig_var,nim.orig_var with
+ | None, None -> None
+ | Some i, Some j -> if i = j then Some i else None
+ | Some i,_ | _, Some i -> Some i);
+ u.insubst <- None;
+ u.outsubst <- None;
+ u.been_collapsed <- true;
+ (*Shouldn't need this but Somewhere somethings going wonky*)
+ (*nim.nindex <- u.nindex; *)
+ (n,n::internals)
+ | _ -> if u.leave_var then u.insubst <- Some ni else n.nexp <- ni.nexp; (n,[n]))
+ | _ -> (n,[n])
+ in
+ let rec set_nexp n_from n_to_s = match n_to_s with
+ | [] -> n_from
+ | n_to::n_to_s -> n_to.nexp <- n_from.nexp; set_nexp n_from n_to_s in
+ let (n,all) = collapse n in
+ set_nexp n (List.tl all)
+(*assumes called on outermost*)
let rec leave_nu_as_var n =
match n.nexp with
| Nuvar nu ->
- (match nu.nsubst with
+ (match nu.insubst with
| None -> nu.leave_var
| Some(nexp) -> nu.leave_var || leave_nu_as_var nexp)
| _ -> false
let equate_n (n_box : nexp) (n : nexp) : bool =
(*let _ = Printf.eprintf "equate_n given n_box %s and n %s\n" (n_to_string n_box) (n_to_string n) in*)
+ let n_box = get_outer_most n_box in
+ let n = get_outer_most n in
if n_box.nexp == n.nexp then true
- else
- let n = resolve_nsubst n in
- let n_box = resolve_nsubst n_box in
- let occur_nbox_n = occurs_in_pending_subst n_box n in
- let occur_n_nbox = occurs_in_pending_subst n n_box in
- let rec set_bottom_nsubst swap u new_bot =
- match u.nsubst with
- | None -> u.nsubst <- Some(new_bot); true
- | Some({nexp = Nuvar(u)}) -> set_bottom_nsubst swap u new_bot
- | Some(n_new) ->
- if swap
- then set_bottom_nsubst false (match new_bot.nexp with | Nuvar u -> u | _ -> assert false) n_new
- else if nexp_eq n_new new_bot then true
- else false in
+ else
+ let occur_nbox_n = occurs_in_nexp n_box n in
+ let occur_n_nbox = occurs_in_nexp n n_box in
match (occur_nbox_n,occur_n_nbox) with
| true,true -> false
| true,false | false,true -> true
| false,false ->
(*let _ = Printf.eprintf "equate_n has does not occur in %s and %s\n"
- (n_to_string n_box) (n_to_string n) in *)
+ (n_to_string n_box) (n_to_string n) in *)
+ (*If one is empty, set the empty one into the bottom of the other one if you can, but put it in the chain
+ If neither are empty, merge but make sure to set the nexp to be the same (not yet being done)
+ *)
match n_box.nexp,n.nexp with
- | Nuvar(u), Nuvar _ -> set_bottom_nsubst true u n
- | Nuvar(u), _ -> set_bottom_nsubst false u n
- | _,Nuvar u -> set_bottom_nsubst false u n_box
- | _ -> false
+ | Nuvar _, Nuvar _ | Nuvar _, _ | _, Nuvar _ -> add_to_nuvar_tail n_box n
+ | _ -> false
let equate_o (o_box : order) (o : order) : unit =
let o = resolve_osubst o in
if o_box == o then ()
@@ -1351,8 +1385,8 @@ let equate_e (e_box : effect) (e : effect) : unit =
| _ ->
e_box.effect <- e.effect)
-let fresh_var prefix i mkr bindings =
- let v = "'" ^ prefix ^ (string_of_int i) in
+let fresh_var just_use_base varbase i mkr bindings =
+ let v = if just_use_base then varbase else "'" ^ varbase ^ (string_of_int i) in
match Envmap.apply bindings v with
| Some _ -> mkr v false
| None -> mkr v true
@@ -1360,7 +1394,7 @@ let fresh_var prefix i mkr bindings =
let rec fresh_tvar bindings t =
match t.t with
| Tuvar { index = i;subst = None } ->
- fresh_var "tv" i (fun v add -> equate_t t {t=Tvar v}; if add then Some (v,{k=K_Typ}) else None) bindings
+ fresh_var false "tv" i (fun v add -> equate_t t {t=Tvar v}; if add then Some (v,{k=K_Typ}) else None) bindings
| Tuvar { index = i; subst = Some ({t = Tuvar _} as t') } ->
let kv = fresh_tvar bindings t' in
equate_t t t';
@@ -1372,26 +1406,22 @@ let rec fresh_tvar bindings t =
let rec fresh_nvar bindings n =
(*let _ = Printf.eprintf "fresh_nvar for %s\n" (n_to_string n) in*)
match n.nexp with
- | Nuvar { nindex = i;nsubst = None ; orig_var = None } ->
- fresh_var "nv" i (fun v add -> n.nexp <- (Nvar v);
+ | Nuvar { nindex = i;insubst = None ; orig_var = None } ->
+ fresh_var false "nv" i (fun v add -> n.nexp <- (Nvar v);
(*(Printf.eprintf "fresh nvar set %i to %s : %s\n" i v (n_to_string n));*)
if add then Some(v,{k=K_Nat}) else None) bindings
- | Nuvar { nindex = i;nsubst = None ; orig_var = Some v } ->
- fresh_var v 0 (fun v add -> n.nexp <- (Nvar v);
+ | Nuvar { nindex = i;insubst = None ; orig_var = Some v } ->
+ fresh_var true v 0 (fun v add -> n.nexp <- (Nvar v);
(*(Printf.eprintf "fresh nvar set %i to %s : %s\n" i v (n_to_string n));*)
if add then Some(v,{k=K_Nat}) else None) bindings
- | Nuvar { nindex = i; nsubst = Some({nexp=Nuvar _} as n')} ->
- let kv = fresh_nvar bindings n' in
- n.nexp <- n'.nexp;
- kv
- | Nuvar { nindex = i; nsubst = Some n' } ->
+ | Nuvar { nindex = i; insubst = Some n' } ->
n.nexp <- n'.nexp;
None
| _ -> None
let rec fresh_ovar bindings o =
match o.order with
| Ouvar { oindex = i;osubst = None } ->
- fresh_var "ov" i (fun v add -> equate_o o {order = (Ovar v)}; if add then Some(v,{k=K_Nat}) else None) bindings
+ fresh_var false "ov" i (fun v add -> equate_o o {order = (Ovar v)}; if add then Some(v,{k=K_Nat}) else None) bindings
| Ouvar { oindex = i; osubst = Some({order=Ouvar _} as o')} ->
let kv = fresh_ovar bindings o' in
equate_o o o';
@@ -1403,7 +1433,7 @@ let rec fresh_ovar bindings o =
let rec fresh_evar bindings e =
match e.effect with
| Euvar { eindex = i;esubst = None } ->
- fresh_var "ev" i (fun v add -> equate_e e {effect = (Evar v)}; if add then Some(v,{k=K_Nat}) else None) bindings
+ fresh_var false "ev" i (fun v add -> equate_e e {effect = (Evar v)}; if add then Some(v,{k=K_Nat}) else None) bindings
| Euvar { eindex = i; esubst = Some({effect=Euvar _} as e')} ->
let kv = fresh_evar bindings e' in
equate_e e e';
@@ -2402,7 +2432,7 @@ and n_subst s_env n =
| Nuvar _ -> new_n()
| Nconst _ | Npos_inf | Nneg_inf | Ninexact -> n
| N2n(n1,None) -> mk_2n (n_subst s_env n1)
- | N2n(n1,Some(i)) -> n
+ | N2n(n1,Some(i)) -> mk_2nc (n_subst s_env n1) i
| Npow(n1,i) -> mk_pow (n_subst s_env n1) i
| Nneg n1 -> mk_neg (n_subst s_env n1)
| Nadd(n1,n2) -> mk_add (n_subst s_env n1) (n_subst s_env n2)
@@ -2448,13 +2478,13 @@ let rec cs_subst t_env cs =
let subst_with_env env leave_imp t cs e =
(typ_subst env leave_imp t, cs_subst env cs, e_subst env e, env)
-let subst (k_env : (Envmap.k * kind) list) (leave_imp:bool)
+let subst (k_env : (Envmap.k * kind) list) (leave_imp:bool) (use_var:bool)
(t : t) (cs : nexp_range list) (e : effect) : (t * nexp_range list * effect * t_arg emap) =
let subst_env = Envmap.from_list
(List.map (fun (id,k) -> (id,
match k.k with
- | K_Typ -> TA_typ (new_t ())
- | K_Nat -> TA_nexp (new_n id)
+ | K_Typ -> TA_typ (if use_var then (new_tv id) else (new_t ()))
+ | K_Nat -> TA_nexp (if use_var then (new_nv id) else (new_n ()))
| K_Ord -> TA_ord (new_o ())
| K_Efct -> TA_eft (new_e ())
| _ -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "substitution given an environment with a non-base-kind kind"))) k_env)
@@ -2500,7 +2530,7 @@ let rec t_remove_unifications s_env t =
| _ -> ignore(resolve_tsubst t); s_env)
| Tfn(t1,t2,_,e) -> e_remove_unifications (t_remove_unifications (t_remove_unifications s_env t1) t2) e
| Ttup(ts) -> List.fold_right (fun t s_env -> t_remove_unifications s_env t) ts s_env
- | Tapp(i,args) -> List.fold_right (fun t s_env -> ta_remove_unifications s_env t) args s_env
+ | Tapp(i,args) -> List.fold_left (fun s_env t -> ta_remove_unifications s_env t) s_env args
| Tabbrev(ti,ta) -> (t_remove_unifications (t_remove_unifications s_env ti) ta)
| Toptions(t1,t2) -> assert false (*This should really be removed by this point*)
and ta_remove_unifications s_env ta =
@@ -2513,17 +2543,12 @@ and n_remove_unifications s_env n =
(*let _ = Printf.eprintf "n_remove_unifications %s\n" (n_to_string n) in*)
match n.nexp with
| Nvar _ | Nid _ | Nconst _ | Npos_inf | Nneg_inf | Ninexact -> s_env
- | Nuvar nu ->
- let n' = match nu.nsubst with
- | None -> n
- | _ -> ignore (resolve_nsubst n); n in
- (match n'.nexp with
- | Nuvar _ ->
- (*let _ = Printf.eprintf "nuvar is before turning into var %s\n" (n_to_string n') in*)
- (match fresh_nvar s_env n with
- | Some ks -> Envmap.insert s_env ks
- | None -> s_env)
- | _ -> s_env)
+ | Nuvar _ ->
+ let _ = collapse_nuvar_chain (get_outer_most n) in
+ (*let _ = Printf.eprintf "nuvar is before turning into var %s\n" (n_to_string n) in*)
+ (match fresh_nvar s_env n with
+ | Some ks -> Envmap.insert s_env ks
+ | None -> s_env)
| N2n(n1,_) | Npow(n1,_) | Nneg n1 -> (n_remove_unifications s_env n1)
| Nadd(n1,n2) | Nsub(n1,n2) | Nmult(n1,n2) -> (n_remove_unifications (n_remove_unifications s_env n1) n2)
and o_remove_unifications s_env o =
@@ -2605,7 +2630,7 @@ let rec get_abbrev d_env t =
| Tid i ->
(match Envmap.apply d_env.abbrevs i with
| Some(Base((params,ta),tag,cs,efct,_,_)) ->
- let ta,cs,_,_ = subst params false ta cs efct in
+ let ta,cs,_,_ = subst params false false ta cs efct in
let ta,cs' = get_abbrev d_env ta in
(match ta.t with
| Tabbrev(t',ta) -> ({t=Tabbrev({t=Tabbrev(t,t')},ta)},cs@cs')
@@ -3237,7 +3262,7 @@ let rec select_overload_variant d_env params_check get_all variants actual_type
select_overload_variant d_env params_check get_all variants actual_type
| Base((parms,t_orig),tag,cs,ef,_,bindings)::variants ->
(*let _ = Printf.eprintf "About to check a variant %s\n" (t_to_string t_orig) in*)
- let t,cs,ef,_ = if parms=[] then t_orig,cs,ef,Envmap.empty else subst parms false t_orig cs ef in
+ let t,cs,ef,_ = if parms=[] then t_orig,cs,ef,Envmap.empty else subst parms false false t_orig cs ef in
(*let _ = Printf.eprintf "And after substitution %s\n" (t_to_string t) in*)
let t,cs' = get_abbrev d_env t in
let recur _ = select_overload_variant d_env params_check get_all variants actual_type in
@@ -3318,7 +3343,7 @@ let rec subst_nuvars nus n =
let new_n =
match n.nexp with
| Nconst _ | Nvar _ | Nid _ | Npos_inf | Nneg_inf | Ninexact -> n
- | Nuvar _ ->
+ | Nuvar _ ->
(match Nexpmap.apply nus n with
| None -> n
| Some nc -> nc)
@@ -3363,7 +3388,7 @@ let rec prepare_constraints = function
| CondCons(l,(Positive|Negative|Switch as kind),None,cs_p,cs_e)::cs ->
let (new_pred_cs,my_substs) = freshen_constraints cs_p in
let new_expr_cs = subst_nuvars_cs my_substs cs_e in
- CondCons(l,kind,Some(my_substs),cs_p,(prepare_constraints new_expr_cs))::(prepare_constraints cs)
+ CondCons(l,kind,Some(my_substs),new_pred_cs,(prepare_constraints new_expr_cs))::(prepare_constraints cs)
| CondCons(l,Solo,None,cs_p,cs_e)::cs ->
CondCons(l,Solo,None,cs_p,(prepare_constraints cs_e))::(prepare_constraints cs)
| BranchCons(l,_,bs)::cs -> BranchCons(l,None, prepare_constraints bs)::(prepare_constraints cs)
@@ -3393,66 +3418,73 @@ let rec make_merged_constraints acc = function
cs
let merge_branch_constraints merge_nuvars constraint_sets =
+ (*let _ = Printf.eprintf "merge_branch_constraints called\n" in*)
(*Separate variables into only occurs in one set, or occurs in multiple sets*)
+ (*assumes k and n outermost and all nuvar*)
let conditionally_set k n =
- (occurs_in_nexp k n) || (occurs_in_nexp n k) || equate_n k n in
- let set_nuvars_on_merge k n =
- let def_try_set = merge_nuvars && is_all_nuvar n in
- if def_try_set
- then (conditionally_set n k),[],None
- else if merge_nuvars
- then match first_non_nu n with
+ not(merge_nuvars) || ((occurs_in_nexp k n) || (occurs_in_nexp n k) || equate_n k n) in
+ (*This function assumes n outermost and k all nuvar;
+ inserts a new nuvar at bottom, and an eq to k for non-nuvar*)
+ let conditionally_lift_to_nuvars_on_merge k n =
+ if not(merge_nuvars) || is_all_nuvar n
+ then [],None
+ else
+ let new_nuvar = new_n () in
+ let new_temp = new_n () in
+ match first_non_nu n with
| Some n' ->
- if change_nuvar_base n k
- then (true, [Eq(Patt(Parse_ast.Unknown),k,n')], None)
- else (false, [Eq(Patt(Parse_ast.Unknown),k,n')], Some(Nexpmap.from_list [n',k]))
- | None -> (false, [Eq(Patt(Parse_ast.Unknown),k,n)], None)
- else (false,[],None) in
+ new_temp.nexp <- n'.nexp; (*Save equation*)
+ n'.nexp <- new_nuvar.nexp; (*Put a nuvar in place*)
+ [Eq(Patt(Parse_ast.Unknown),k,new_temp)], Some(Nexpmap.from_list [k,new_temp])
+ | None -> [],None
+ in
let merged_constraints = make_merged_constraints Nexpmap.empty constraint_sets in
- (*let _ = Printf.eprintf "merge branch constraints: found these shared var mappings %s\n%!"
- (nexpmap_to_string merged_constraints) in*)
let shared_path_distinct_constraints =
Nexpmap.fold
(fun (sc,new_cs,new_map) k v -> match v with
| One n ->
- (*let _ = Printf.eprintf "Variables in one path: merge_nuvars %b, key %s, one %s\n%!"
- merge_nuvars (n_to_string k) (n_to_string n) in*)
- let (_,new_cs',nm) =
- (match (k.nexp, n.nexp) with
- | Nuvar _, Nuvar _ -> set_nuvars_on_merge k n
- | _ -> (conditionally_set k n,[],None)) in
- (sc,new_cs'@new_cs,merge_option_maps nm new_map)
+ (*let _ = Printf.eprintf "Variables in one path: merge_nuvars %b, key %s, one %s\n%!"
+ merge_nuvars (n_to_string k) (n_to_string n) in*)
+ let k,n = get_outer_most k, get_outer_most n in
+ if (is_all_nuvar k || is_all_nuvar n) && conditionally_set k n
+ then (sc,new_cs,new_map)
+ else (sc, (Eq(Patt(Parse_ast.Unknown),k,n))::new_cs,new_map)
| Two(n1,n2) ->
(*let _ = Printf.eprintf "Variables in two paths: merge_nuvars %b, key %s, n1 %s, n2 %s\n%!"
- merge_nuvars (n_to_string k) (n_to_string n1) (n_to_string n2) in*)
- (match n1.nexp,n2.nexp with
- | Nuvar _, Nuvar _ ->
- let (set1,ncs1,nm1) = set_nuvars_on_merge k n1 in
- let (set2,ncs2,nm2) = set_nuvars_on_merge k n2 in
- if (set1 && set2)
- then (sc,ncs1@ncs2@new_cs,merge_option_maps new_map (merge_option_maps nm1 nm2))
- else (Nexpmap.insert sc (k,v),new_cs,merge_option_maps new_map (merge_option_maps nm1 nm2))
- | Nuvar _, _ ->
- let (_,cs1, nm1) = set_nuvars_on_merge k n1 in
- (Nexpmap.insert sc (k,v),cs1@new_cs,merge_option_maps new_map nm1)
- | _, Nuvar _ ->
- let (_,cs2, nm2) = set_nuvars_on_merge k n2 in
- (Nexpmap.insert sc (k,v),cs2@new_cs,merge_option_maps new_map nm2)
- | _ ->
- if nexp_eq n1 n2 && conditionally_set k n1 && conditionally_set k n2
- then (sc,new_cs,new_map)
- else (Nexpmap.insert sc (k,v),new_cs,new_map))
+ merge_nuvars (n_to_string k) (n_to_string n1) (n_to_string n2) in*)
+ let k,n1,n2 = get_outer_most k, get_outer_most n1, get_outer_most n2 in
+ let all_nk, all_nn1, all_nn2 = is_all_nuvar k, is_all_nuvar n1, is_all_nuvar n2 in
+ if all_nk && all_nn1 && all_nn2
+ then
+ let set1,set2 = conditionally_set k n1, conditionally_set k n2 in
+ if set1 && set2 then sc,new_cs,new_map
+ else (Nexpmap.insert sc (k,v),new_cs,new_map)
+ else (if all_nk
+ then
+ let ncs1,nm1 = conditionally_lift_to_nuvars_on_merge k n1 in
+ let ncs2,nm2 = conditionally_lift_to_nuvars_on_merge k n2 in
+ let set1,set2 = conditionally_set k n1, conditionally_set k n2 in
+ if set1 && set2
+ then sc,ncs1@ncs2@new_cs,merge_option_maps new_map (merge_option_maps nm1 nm2)
+ else (Nexpmap.insert sc (k,v),new_cs,merge_option_maps new_map (merge_option_maps nm1 nm2))
+ else (Nexpmap.insert sc (k,v),new_cs,new_map))
| Many ns ->
(*let _ = Printf.eprintf "Variables in many paths: merge_nuvars %b, key %s, ["
merge_nuvars (n_to_string k) in
- let _ = List.iter (fun n -> Printf.eprintf "%s " (n_to_string n)) ns in
- let _ = Printf.eprintf "\n%!" in*)
- let sets = List.map (set_nuvars_on_merge k) ns in
- let css = (List.flatten (List.map (fun (_,c,_) -> c) sets))@ new_cs in
- let map = List.fold_right merge_option_maps (List.map (fun (_,_,m) -> m) sets) new_map in
- if List.for_all (fun (b,_,_) -> b) sets
- then (sc,css,map)
- else
+ let _ = List.iter (fun n -> Printf.eprintf "%s ;" (n_to_string n)) ns in
+ let _ = Printf.eprintf "]\n%!" in*)
+ let k, ns = get_outer_most k, List.map get_outer_most ns in
+ let is_all_nuvars = List.for_all is_all_nuvar ns in
+ if not(merge_nuvars)
+ then Nexpmap.insert sc (k,v),new_cs,new_map
+ else if is_all_nuvars
+ then if List.for_all (conditionally_set k) ns
+ then (sc,new_cs,new_map)
+ else (Nexpmap.insert sc (k,v),new_cs,new_map)
+ else
+ let sets = List.map (conditionally_lift_to_nuvars_on_merge k) ns in
+ let css = (List.flatten (List.map fst sets))@ new_cs in
+ let map = List.fold_right merge_option_maps (List.map snd sets) new_map in
let rec all_eq = function
| [] | [_] -> true
| n1::n2::ns ->
@@ -3460,8 +3492,8 @@ let merge_branch_constraints merge_nuvars constraint_sets =
in
if (all_eq ns) && not(ns = [])
then if List.for_all (conditionally_set k) ns
- then (sc,css, map)
- else (Nexpmap.insert sc (k,v),css, map)
+ then (sc,new_cs,new_map)
+ else (Nexpmap.insert sc (k,v),new_cs,new_map)
else (Nexpmap.insert sc (k,v),css, map))
(Nexpmap.empty,[],None) merged_constraints in
(*let _ = if merge_nuvars then
@@ -3477,7 +3509,8 @@ let rec extract_path_substs = function
| _ -> if nexp_eq n v then () else assert false (*Get a location to here*)
in
let updated_substs =
- Nexpmap.fold (fun substs key newvar ->
+ Nexpmap.fold (fun substs key newvar ->
+ (*let _ = Printf.eprintf "building substs sets: %s |-> %s\n" (n_to_string key) (n_to_string newvar) in*)
match key.nexp with
| Nuvar _ -> Nexpmap.insert substs (key,newvar)
| _ -> begin set key newvar; substs end) Nexpmap.empty substs in
@@ -3515,13 +3548,12 @@ let rec equate_nuvars in_env cs =
| Nuvar u1, Nuvar u2 ->
(*let _ = Printf.eprintf "setting two nuvars, %s and %s in equate\n" (n_to_string n1) (n_to_string n2) in*)
let occurs = (occurs_in_nexp n1 n2) || (occurs_in_nexp n2 n1) in
+ (*let _ = Printf.eprintf "did they occur? %b\n" occurs in*)
if not(occurs)
- then begin ignore(resolve_nsubst n1); ignore(resolve_nsubst n2);
- if (equate_n n1 n2) then equate cs else c::equate cs end
+ then if (equate_n n1 n2) then equate cs else c::equate cs
else c::equate cs
| _ -> c::equate cs)
| CondCons(co,kind,substs,pats,exps):: cs ->
- (*let _ = Printf.eprintf "equate_nuvars: condcons: %s\n%!" (constraints_to_string [c]) in*)
let pats' = equate pats in
let exps' = equate exps in
(match pats',exps' with
@@ -3559,8 +3591,7 @@ let rec simple_constraint_check in_env cs =
^ n_to_string new_n ^ " to equal 0, not " ^ string_of_big_int i)
| Nuvar u1 ->
if ok_to_set
- then begin ignore(resolve_nsubst new_n);
- if (equate_n new_n n_zero) then None else Some(Eq(co,new_n,n_zero)) end
+ then if (equate_n new_n n_zero) then None else Some(Eq(co,new_n,n_zero))
else Some(Eq(co,new_n,n_zero))
| Nadd(new_n1,new_n2) ->
(match new_n1.nexp, new_n2.nexp with
@@ -3587,38 +3618,36 @@ let rec simple_constraint_check in_env cs =
(n_to_string n1) (n_to_string n2) ok_to_set in*)
let occurs = (occurs_in_nexp n1' n2') || (occurs_in_nexp n2' n1') in
if ok_to_set && not(occurs)
- then begin ignore(resolve_nsubst n1'); ignore(resolve_nsubst n2');
- if (equate_n n1' n2') then None else Some(Eq(co,n1',n2')) end
+ then if (equate_n n1' n2') then None else Some(Eq(co,n1',n2'))
else if occurs then eq_to_zero ok_to_set n1' n2'
else Some(Eq(co,n1',n2'))
| _, Nuvar u ->
(*let _ = Printf.eprintf "setting right nuvar\n" in*)
let occurs = occurs_in_nexp n1' n2' in
- let leave = leave_nu_as_var n2' in
+ let leave = leave_nu_as_var (get_outer_most n2') in
(*let _ = Printf.eprintf "occurs? %b, leave? %b n1' %s in n2' %s\n"
occurs leave (n_to_string n1') (n_to_string n2') in*)
if (*not(u.nin) &&*) ok_to_set && not(occurs) && not(leave)
then if (equate_n n2' n1') then None else (Some (Eq(co,n1',n2')))
else if occurs
- then begin (reduce_n_unifications n1'); (reduce_n_unifications n2'); eq_to_zero ok_to_set n1' n2' end
+ then eq_to_zero ok_to_set n1' n2'
else Some (Eq(co,n1',n2'))
| Nuvar u, _ ->
(*let _ = Printf.eprintf "setting left nuvar\n" in*)
let occurs = occurs_in_nexp n2' n1' in
- let leave = leave_nu_as_var n1' in
+ let leave = leave_nu_as_var (get_outer_most n1') in
(*let _ = Printf.eprintf "occurs? %b, leave? %b n2' %s in n1' %s\n"
occurs leave (n_to_string n2') (n_to_string n1') in*)
if (*not(u.nin) &&*) ok_to_set && not(occurs) && not(leave)
then if equate_n n1' n2' then None else (Some (Eq(co,n1',n2')))
else if occurs
- then begin (reduce_n_unifications n1'); (reduce_n_unifications n2'); eq_to_zero ok_to_set n1' n2' end
+ then eq_to_zero ok_to_set n1' n2'
else Some (Eq(co,n1',n2'))
| _,_ ->
if nexp_eq_check n1' n2'
then None
else eq_to_zero ok_to_set n1' n2')
in
- let _ = reduce_n_unifications n1; reduce_n_unifications n2 in
(match check_eq true n1 n2 with
| None -> (check cs)
| Some(c) -> c::(check cs))
@@ -3663,7 +3692,6 @@ let rec simple_constraint_check in_env cs =
| None -> (check cs)
| Some(c) -> c::(check cs))
| GtEq(co,enforce,n1,n2)::cs ->
- let n1,n2 = resolve_nsubst n1, resolve_nsubst n2 in
(*let _ = Printf.eprintf ">= check, about to normalize_nexp of %s, %s\n"
(n_to_string n1) (n_to_string n2) in *)
let n1',n2' = normalize_nexp n1,normalize_nexp n2 in
@@ -3704,7 +3732,6 @@ let rec simple_constraint_check in_env cs =
^ n_to_string new_n ^ " to be greater than or equal to 0, not " ^ string_of_big_int i)
| _ -> GtEq(co,enforce,n1',n2')::(check cs))))
| Gt(co,enforce,n1,n2)::cs ->
- let n1,n2 = resolve_nsubst n1, resolve_nsubst n2 in
(*let _ = Printf.eprintf "> check, about to normalize_nexp of %s, %s\n"
(n_to_string n1) (n_to_string n2) in *)
let n1',n2' = normalize_nexp n1,normalize_nexp n2 in
@@ -3725,7 +3752,6 @@ let rec simple_constraint_check in_env cs =
^ n_to_string new_n ^ " to be greater than or equal to 0, not " ^ string_of_big_int i)
| _ -> Gt(co,enforce,n1',n2')::(check cs)))
| LtEq(co,enforce,n1,n2)::cs ->
- let n1,n2 = resolve_nsubst n1, resolve_nsubst n2 in
(*let _ = Printf.eprintf "<= check, about to normalize_nexp of %s, %s\n"
(n_to_string n1) (n_to_string n2) in *)
let n1',n2' = normalize_nexp n1,normalize_nexp n2 in
@@ -3745,7 +3771,6 @@ let rec simple_constraint_check in_env cs =
" to be less than or equal to " ^ (n_to_string n2))
| Maybe -> LtEq(co,enforce,n1',n2')::(check cs)))
| Lt(co,enforce,n1,n2)::cs ->
- let n1,n2 = resolve_nsubst n1, resolve_nsubst n2 in
(*let _ = Printf.eprintf "< check, about to normalize_nexp of %s, %s\n"
(n_to_string n1) (n_to_string n2) in *)
let n1',n2' = normalize_nexp n1,normalize_nexp n2 in
@@ -3817,16 +3842,19 @@ let resolve_constraints cs =
let len' = constraint_size cs' in
if len > len' then fix checker len' cs'
else cs' in
-(* let _ = Printf.eprintf "Original constraints are %s\n%!" (constraints_to_string cs) in*)
+ (*let _ = Printf.eprintf "Original constraints are %s\n%!" (constraints_to_string cs) in*)
let branch_freshened = prepare_constraints cs in
+ (*let _ = Printf.eprintf "Constraints after prepare constraints are %s\n"
+ (constraints_to_string branch_freshened) in*)
let nuvar_equated = fix equate_nuvars (constraint_size branch_freshened) branch_freshened in
+ (*let _ = Printf.eprintf "Constraints after nuvar equated are %s\n%!" (constraints_to_string nuvar_equated) in*)
let complex_constraints =
fix (fun in_env cs -> let (ncs,_) = merge_paths false (simple_constraint_check in_env cs) in ncs)
(constraint_size nuvar_equated) nuvar_equated in
let (complex_constraints,map) = merge_paths true complex_constraints in
(*let _ = Printf.eprintf "Resolved as many constraints as possible, leaving %i\n"
- (constraint_size complex_constraints) in*)
- (*let _ = Printf.eprintf "%s\n" (constraints_to_string complex_constraints) in*)
+ (constraint_size complex_constraints) in
+ let _ = Printf.eprintf "%s\n" (constraints_to_string complex_constraints) in*)
(complex_constraints,map)
@@ -3835,16 +3863,12 @@ let check_tannot l annot imp_param constraints efs =
| Base((params,t),tag,cs,ef,_,bindings) ->
let efs = remove_lsets efs in
ignore(effects_eq (Specc l) efs ef);
- let s_env = (t_remove_unifications (Envmap.from_list params) t) in
+ let s_env = (t_remove_unifications Envmap.empty t) in
let params = Envmap.to_list s_env in
- (*let _ = Printf.eprintf "parameters going to save are " in
- let _ = List.iter (fun (s,_) -> Printf.eprintf "%s " s) params in
- let _ = Printf.eprintf "\n" in*)
ignore (remove_internal_unifications s_env);
- (*let _ = Printf.eprintf "Checked tannot, t after removing uvars is %s\n" (t_to_string t) in*)
let t' = match (t.t,imp_param) with
| Tfn(p,r,_,e),Some x -> {t = Tfn(p,r,IP_user x,e) }
- | _ -> t in
+ | _ -> t in
Base((params,t'),tag,cs,ef,pure_e,bindings)
| NoTyp -> raise (Reporting_basic.err_unreachable l "check_tannot given the place holder annotation")
| Overload _ -> raise (Reporting_basic.err_unreachable l "check_tannot given overload")
@@ -3859,7 +3883,7 @@ let tannot_merge co denv widen t_older t_newer =
(match tag_o,tag_n with
| Default,tag ->
(match t_n.t with
- | Tuvar _ -> let t_o,cs_o,ef_o,_ = subst ps_o false t_o cs_o efl_o in
+ | Tuvar _ -> let t_o,cs_o,ef_o,_ = subst ps_o false false t_o cs_o efl_o in
let t,_ = type_consistent co denv Guarantee false t_n t_o in
Base(([],t),tag_n,cs_o,ef_o,pure_e,bounds_o)
| _ -> t_newer)
diff --git a/src/type_internal.mli b/src/type_internal.mli
index 4d1879fa..17e7aaed 100644
--- a/src/type_internal.mli
+++ b/src/type_internal.mli
@@ -249,7 +249,7 @@ val new_e : unit -> effect
val equate_t : t -> t -> unit
val typ_subst : t_arg emap -> bool -> t -> t
-val subst : (Envmap.k * kind) list -> bool -> t -> nexp_range list -> effect -> t * nexp_range list * effect * t_arg emap
+val subst : (Envmap.k * kind) list -> bool -> bool -> t -> nexp_range list -> effect -> t * nexp_range list * effect * t_arg emap
val subst_with_env : t_arg emap -> bool -> t -> nexp_range list -> effect -> t * nexp_range list * effect * t_arg emap
val type_param_consistent : Parse_ast.l -> t_arg emap -> t_arg emap -> nexp_range list