summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--language/l2.lem3
-rw-r--r--language/l2.ml3
-rw-r--r--language/l2.ott3
-rw-r--r--language/l2_parse.ml1
-rw-r--r--language/l2_parse.ott1
-rw-r--r--language/l2_typ.ott1
-rw-r--r--src/initial_check.ml18
-rw-r--r--src/lem_interp/pretty_interp.ml5
-rw-r--r--src/parser.mly30
-rw-r--r--src/pretty_print.ml7
-rw-r--r--src/rewriter.ml2
-rw-r--r--src/type_check.ml51
-rw-r--r--src/type_internal.ml203
-rw-r--r--src/type_internal.mli1
14 files changed, 218 insertions, 111 deletions
diff --git a/language/l2.lem b/language/l2.lem
index d9b410cd..eb598113 100644
--- a/language/l2.lem
+++ b/language/l2.lem
@@ -50,8 +50,9 @@ type nexp_aux = (* expression of kind Nat, for vector sizes and origins *)
| Nexp_constant of integer (* constant *)
| Nexp_times of nexp * nexp (* product *)
| Nexp_sum of nexp * nexp (* sum *)
+ | Nexp_minus of nexp * nexp (* subtraction, error for nexp1 to be smaller than nexp2 *)
| Nexp_exp of nexp (* exponential *)
- | Nexp_neg of nexp (* For internal use. Not M as a dataconstructor is required *)
+ | Nexp_neg of nexp (* For internal use *)
and nexp =
| Nexp_aux of nexp_aux * l
diff --git a/language/l2.ml b/language/l2.ml
index dc96020d..d4423c54 100644
--- a/language/l2.ml
+++ b/language/l2.ml
@@ -45,8 +45,9 @@ nexp_aux = (* expression of kind Nat, for vector sizes and origins *)
| Nexp_constant of int (* constant *)
| Nexp_times of nexp * nexp (* product *)
| Nexp_sum of nexp * nexp (* sum *)
+ | Nexp_minus of nexp * nexp (* subtraction, error for nexp1 to be smaller than nexp2 *)
| Nexp_exp of nexp (* exponential *)
- | Nexp_neg of nexp (* For internal use. Not M as a dataconstructor is required *)
+ | Nexp_neg of nexp (* For internal use *)
and nexp =
Nexp_aux of nexp_aux * l
diff --git a/language/l2.ott b/language/l2.ott
index 77b2483b..59de79cd 100644
--- a/language/l2.ott
+++ b/language/l2.ott
@@ -166,8 +166,9 @@ nexp :: 'Nexp_' ::=
| num :: :: constant {{ com constant }}
| nexp1 * nexp2 :: :: times {{ com product }}
| nexp1 + nexp2 :: :: sum {{ com sum }}
+ | nexp1 - nexp2 :: :: minus {{ com subtraction, error for nexp1 to be smaller than nexp2 }}
| 2** nexp :: :: exp {{ com exponential }}
- | neg nexp :: :: neg {{ com For internal use. Not M as a dataconstructor is required }}
+ | neg nexp :: :: neg {{ com For internal use }}
| ( nexp ) :: S :: paren {{ ichlo [[nexp]] }}
order :: 'Ord_' ::=
diff --git a/language/l2_parse.ml b/language/l2_parse.ml
index 5aaf8086..ed594d3b 100644
--- a/language/l2_parse.ml
+++ b/language/l2_parse.ml
@@ -84,6 +84,7 @@ atyp_aux = (* expressions of all kinds, to be translated to types, nats, orders
| ATyp_constant of int (* constant *)
| ATyp_times of atyp * atyp (* product *)
| ATyp_sum of atyp * atyp (* sum *)
+ | ATyp_minus of atyp * atyp (* subtraction *)
| ATyp_exp of atyp (* exponential *)
| ATyp_neg of atyp (* Internal (but not M as I want a datatype constructor) negative nexp *)
| ATyp_inc (* increasing (little-endian) *)
diff --git a/language/l2_parse.ott b/language/l2_parse.ott
index 74522150..7126b9e0 100644
--- a/language/l2_parse.ott
+++ b/language/l2_parse.ott
@@ -168,6 +168,7 @@ atyp :: 'ATyp_' ::=
| num :: :: constant {{ com constant }}
| atyp1 * atyp2 :: :: times {{ com product }}
| atyp1 + atyp2 :: :: sum {{ com sum }}
+ | atyp1 - atyp2 :: :: minus {{ com subtraction }}
| 2** atyp :: :: exp {{ com exponential }}
| neg atyp :: :: neg {{ com Internal (but not M as I want a datatype constructor) negative nexp }}
| ( atyp ) :: S :: paren {{ icho [[atyp]] }}
diff --git a/language/l2_typ.ott b/language/l2_typ.ott
index 12baa059..3ffc5b2b 100644
--- a/language/l2_typ.ott
+++ b/language/l2_typ.ott
@@ -85,6 +85,7 @@ ne :: 'Ne_' ::=
| infinity :: :: inf
| ne1 * ne2 :: :: mult
| ne1 + ... + nen :: :: add
+ | ne1 - ne2 :: :: minus
| 2 ** ne :: :: exp
| ( - ne ) :: :: unary
| zero :: S :: zero
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 9b285032..8c613f36 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -180,16 +180,14 @@ and to_ast_nexp (k_env : kind Envmap.t) (n: Parse_ast.atyp) : Ast.nexp =
Nexp_aux(Nexp_sum(n1,n2),l)
| Parse_ast.ATyp_exp(t1) -> Nexp_aux(Nexp_exp(to_ast_nexp k_env t1),l)
| Parse_ast.ATyp_neg(t1) -> Nexp_aux(Nexp_neg(to_ast_nexp k_env t1),l)
- | Parse_ast.ATyp_tup(typs) ->
- let rec times_loop (typs : Parse_ast.atyp list) (one_ok : bool) : nexp =
- (match typs,one_ok with
- | [],_ | [_],false -> raise (Reporting_basic.err_unreachable l "to_ast_nexp has ATyp_tup with empty list or list with one element")
- | [t],true -> to_ast_nexp k_env t
- | (t1::typs),_ -> let n1 = to_ast_nexp k_env t1 in
- let n2 = times_loop typs true in
- (Nexp_aux((Nexp_times(n1,n2)),l))) (*TODO This needs just a portion of the l, think about adding a way to split*)
- in
- times_loop typs false
+ | Parse_ast.ATyp_times(t1,t2) ->
+ let n1 = to_ast_nexp k_env t1 in
+ let n2 = to_ast_nexp k_env t2 in
+ Nexp_aux(Nexp_times(n1,n2),l)
+ | Parse_ast.ATyp_minus(t1,t2) ->
+ let n1 = to_ast_nexp k_env t1 in
+ let n2 = to_ast_nexp k_env t2 in
+ Nexp_aux(Nexp_minus(n1,n2),l)
| _ -> typ_error l "Requred an item of kind Nat, encountered an illegal form for this kind" None None None)
and to_ast_order (k_env : kind Envmap.t) (def_ord : order) (o: Parse_ast.atyp) : Ast.order =
diff --git a/src/lem_interp/pretty_interp.ml b/src/lem_interp/pretty_interp.ml
index 2724ba9c..1ea6df3e 100644
--- a/src/lem_interp/pretty_interp.ml
+++ b/src/lem_interp/pretty_interp.ml
@@ -141,12 +141,13 @@ let doc_typ, doc_atomic_typ, doc_nexp =
and nexp ne = sum_typ ne
and sum_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_sum(n1,n2) -> doc_op plus (sum_typ n1) (star_typ n2)
+ | Nexp_minus(n1,n2) -> doc_op minus (sum_typ n1) (star_typ n2)
| _ -> star_typ ne
and star_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_times(n1,n2) -> doc_op star (star_typ n1) (exp_typ n2)
| _ -> exp_typ ne
and exp_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_exp n1 -> doc_unop (string "2**") (neg_typ n1)
+ | Nexp_exp n1 -> doc_unop (string "2**") (atomic_nexp_typ n1)
| _ -> neg_typ ne
and neg_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_neg n1 ->
@@ -158,7 +159,7 @@ let doc_typ, doc_atomic_typ, doc_nexp =
and atomic_nexp_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_var v -> doc_var v
| Nexp_constant i -> doc_int i
- | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ ->
+ | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ | Nexp_minus _ ->
group (parens (nexp ne))
(* expose doc_typ, doc_atomic_typ and doc_nexp *)
diff --git a/src/parser.mly b/src/parser.mly
index b6b7ecf3..2ae64887 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -393,29 +393,18 @@ app_num_typ:
| Num
{ tloc (ATyp_constant $1) }
-/* XXX this part of the parser makes absolutely no sense to me */
-star_typ_list:
- | app_num_typ
- { [$1] }
- | app_num_typ Star star_typ_list
- { $1::$3 }
-
star_typ:
- | star_typ_list
- { match $1 with
- | [] -> assert false
- | [t] -> t
- (* XXX why is ATyp_tup star-separated here, but comma-separated
- below? *)
- | ts -> tloc (ATyp_tup(ts)) }
+ | app_num_typ
+ { $1 }
+ | app_num_typ Star nexp_typ
+ { tloc (ATyp_times ($1, $3)) }
exp_typ:
| star_typ
{ $1 }
- | TwoStarStar nexp_typ
+ | TwoStarStar atomic_typ
{ tloc (ATyp_exp($2)) }
-/* XXX this is wrong - for instance, 2** 3 + 5 is parsed as 2** (3+5) */
nexp_typ:
| exp_typ
{ $1 }
@@ -427,6 +416,15 @@ nexp_typ:
{ tloc (ATyp_sum((tlocl (ATyp_constant $1) 1 1),$3)) }
| Lparen Num Plus nexp_typ Rparen
{ tloc (ATyp_sum((tlocl (ATyp_constant $2) 2 2),$4)) }
+ | atomic_typ Minus nexp_typ
+ { tloc (ATyp_minus($1,$3)) }
+ | Lparen atomic_typ Minus nexp_typ Rparen
+ { tloc (ATyp_minus($2,$4)) }
+ | Num Minus nexp_typ
+ { tloc (ATyp_minus((tlocl (ATyp_constant $1) 1 1),$3)) }
+ | Lparen Num Minus nexp_typ Rparen
+ { tloc (ATyp_minus((tlocl (ATyp_constant $2) 2 2),$4)) }
+
tup_typ_list:
| app_typ Comma app_typ
diff --git a/src/pretty_print.ml b/src/pretty_print.ml
index 8665d42d..9d9ed8a0 100644
--- a/src/pretty_print.ml
+++ b/src/pretty_print.ml
@@ -123,6 +123,7 @@ and pp_format_nexp_lem (Nexp_aux(n,l)) =
| Nexp_var(v) -> "(Nexp_var " ^ pp_format_var_lem v ^ ")"
| Nexp_constant(i) -> "(Nexp_constant " ^ (lemnum string_of_int i) ^ ")"
| Nexp_sum(n1,n2) -> "(Nexp_sum " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
+ | Nexp_minus(n1,n2) -> "(Nexp_minus " ^ (pp_format_nexp_lem n1)^ " " ^ (pp_format_nexp_lem n2) ^ ")"
| Nexp_times(n1,n2) -> "(Nexp_times " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
| Nexp_exp(n1) -> "(Nexp_exp " ^ (pp_format_nexp_lem n1) ^ ")"
| Nexp_neg(n1) -> "(Nexp_neg " ^ (pp_format_nexp_lem n1) ^ ")") ^ " " ^
@@ -255,6 +256,7 @@ and pp_format_n n =
| Nconst i -> "(Ne_const " ^ (lemnum string_of_int (int_of_big_int i)) ^ ")"
| Npos_inf -> "Ne_inf"
| Nadd(n1,n2) -> "(Ne_add [" ^ (pp_format_n n1) ^ "; " ^ (pp_format_n n2) ^ "])"
+ | Nsub(n1,n2) -> "(Ne_minus "^ (pp_format_n n1) ^ " " ^ (pp_format_n n2) ^ ")"
| Nmult(n1,n2) -> "(Ne_mult " ^ (pp_format_n n1) ^ " " ^ (pp_format_n n2) ^ ")"
| N2n(n,Some i) -> "(Ne_exp " ^ (pp_format_n n) ^ "(*" ^ string_of_big_int i ^ "*)" ^ ")"
| N2n(n,None) -> "(Ne_exp " ^ (pp_format_n n) ^ ")"
@@ -704,12 +706,13 @@ let doc_typ, doc_atomic_typ, doc_nexp =
and nexp ne = sum_typ ne
and sum_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_sum(n1,n2) -> doc_op plus (sum_typ n1) (star_typ n2)
+ | Nexp_minus(n1,n2) -> doc_op minus (sum_typ n1) (star_typ n2)
| _ -> star_typ ne
and star_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_times(n1,n2) -> doc_op star (star_typ n1) (exp_typ n2)
| _ -> exp_typ ne
and exp_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_exp n1 -> doc_unop (string "2**") (neg_typ n1)
+ | Nexp_exp n1 -> doc_unop (string "2**") (atomic_nexp_typ n1)
| _ -> neg_typ ne
and neg_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_neg n1 ->
@@ -721,7 +724,7 @@ let doc_typ, doc_atomic_typ, doc_nexp =
and atomic_nexp_typ ((Nexp_aux(n,_)) as ne) = match n with
| Nexp_var v -> doc_var v
| Nexp_constant i -> doc_int i
- | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ ->
+ | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ | Nexp_minus _->
group (parens (nexp ne))
(* expose doc_typ, doc_atomic_typ and doc_nexp *)
diff --git a/src/rewriter.ml b/src/rewriter.ml
index afcba19b..9335ea5d 100644
--- a/src/rewriter.ml
+++ b/src/rewriter.ml
@@ -21,6 +21,8 @@ let rec rewrite_nexp_to_exp program_vars l nexp =
(l, (tag_annot typ (External (Some "add")))))
| Nmult (n1,n2) -> E_aux (E_app_infix (rewrite n1,(Id_aux (Id "*",l)),rewrite n2),
(l, tag_annot typ (External (Some "multiply"))))
+ | Nsub (n1,n2) -> E_aux (E_app_infix (rewrite n1,(Id_aux (Id "-",l)),rewrite n2),
+ (l, tag_annot typ (External (Some "minus"))))
| N2n (n, _) -> E_aux (E_app_infix (E_aux (E_lit (L_aux (L_num 2,l)), (l, simple_annot (mk_atom_typ n_two))),
(Id_aux (Id "**",l)),
rewrite n), (l, tag_annot typ (External (Some "power"))))
diff --git a/src/type_check.ml b/src/type_check.ml
index 7ed4f19f..9723fd09 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -118,6 +118,7 @@ and anexp_to_nexp ((Nexp_aux(n,l)) : Ast.nexp) : nexp =
| Nexp_constant i -> {nexp=Nconst (big_int_of_int i)}
| Nexp_times(n1,n2) -> {nexp=Nmult(anexp_to_nexp n1,anexp_to_nexp n2)}
| Nexp_sum(n1,n2) -> {nexp=Nadd(anexp_to_nexp n1,anexp_to_nexp n2)}
+ | Nexp_minus(n1,n2) -> {nexp=Nsub(anexp_to_nexp n1,anexp_to_nexp n2)}
| Nexp_exp n -> {nexp=N2n(anexp_to_nexp n,None)}
| Nexp_neg n -> {nexp=Nneg(anexp_to_nexp n)}
and aeffect_to_effect ((Effect_aux(e,l)) : Ast.effect) : effect =
@@ -188,9 +189,9 @@ let into_register d_env (t : tannot) : tannot =
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,tp_env)) = envs in
- (*let _ = Printf.printf "checking pattern with expected type %s\n" (t_to_string expect_t) in*)
+ (*let _ = Printf.eprintf "checking pattern with expected type %s\n" (t_to_string expect_t) in*)
let expect_t,cs = get_abbrev d_env expect_t in
- (*let _ = Printf.printf "check pattern expect_t after abbrev %s\n" (t_to_string expect_t) in*)
+ (*let _ = Printf.eprintf "check pattern expect_t after abbrev %s\n" (t_to_string expect_t) in*)
let expect_actual = match expect_t.t with | Tabbrev(_,t) -> t | _ -> expect_t in
match p with
| P_lit (L_aux(lit,l')) ->
@@ -267,7 +268,7 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat)
| _ -> default)
| P_app(id,pats) ->
let i = id_to_string id in
- (*let _ = Printf.printf "checking constructor pattern %s\n" i in*)
+ let _ = Printf.eprintf "checking constructor pattern %s\n" i 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,bounds)) ->
@@ -577,8 +578,11 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
let cast_t = typ_subst tp_env cast_t in
let ct = {t = Toptions(cast_t,None)} in
let (e',u,t_env,cs,bounds,ef) = check_exp envs imp_param ct e in
+ let _ = Printf.eprintf "Type checking cast: cast_t is %s constraints after checking e are %s\n" (t_to_string cast_t) (constraints_to_string cs) in
let t',cs2,ef',e' = type_coerce (Expr l) d_env Require true false u e' cast_t in
+ let _ = Printf.eprintf "Type checking cast: after first coerce t' %s is and constraints are %s\n" (t_to_string t') (constraints_to_string cs2) in
let t',cs3,ef'',e'' = type_coerce (Expr l) d_env Guarantee false false cast_t e' expect_t in
+ let _ = Printf.eprintf "Type checking cast: after second coerce t' %s is and constraints are %s\n" (t_to_string t') (constraints_to_string cs3) in
(e'',t',t_env,cs_a@cs@cs2@cs3,bounds,union_effects ef' (union_effects ef'' ef))
| E_app(id,parms) ->
let i = id_to_string id in
@@ -605,7 +609,7 @@ 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 =
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 "implicit length or var required, no imp_param %s\n!" (n_to_string n) in
let internal_exp =
let implicit = {t= Tapp("implicit",[TA_nexp n])} in
let annot_i = Base(([],implicit),Emp_local,[],pure_e,b_env) in
@@ -613,8 +617,8 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
type_coerce (Expr l) d_env Guarantee false false ret
(E_aux (E_app(id, internal_exp::parms),(l,(Base(([],ret),tag,cs,ef,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 "and expected type is %s and return type is %s\n" (t_to_string expect_t) (t_to_string ret) in*)
+ 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 "and expected type is %s and return type is %s\n" (t_to_string expect_t) (t_to_string ret) in
let internal_exp =
let implicit_user = {t = Tapp("implicit",[TA_nexp ne])} in
let implicit = {t= Tapp("implicit",[TA_nexp n])} in
@@ -635,16 +639,16 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| 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,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 _ = 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,ef,_ = subst params t cs ef in
(match t.t with
| Tfn(arg,ret,imp,ef') ->
- (*let _ = Printf.eprintf "Checking funcation call of %s\n" i in
- let _ = Printf.eprintf "Substituted types and constraints are %s and %s\n" (t_to_string t) (constraints_to_string cs) in*)
+ let _ = Printf.eprintf "Checking funcation call of %s\n" i in
+ let _ = Printf.eprintf "Substituted types and constraints are %s and %s\n" (t_to_string t) (constraints_to_string cs) in
let parms,arg_t,cs_p,ef_p = check_parms arg parms in
- (*let _ = Printf.eprintf "Checked parms of %s\n" i in*)
+ let _ = Printf.eprintf "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.eprintf "Checked result of %s and constraints are %s\n" i (constraints_to_string cs_r) in*)
+ let _ = Printf.eprintf "Checked result of %s and constraints are %s\n" i (constraints_to_string cs_r) in
(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,_),overload_return,variants)) ->
@@ -1717,25 +1721,28 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
^ id_to_string id ^ " differs from other definitions of " ^ id')
| None -> Some(id_to_string id)) funcls None in
let in_env = Envmap.apply t_env id in
+ let typ_params = match in_env with
+ | Some(Base( (params,u),Spec,constraints,eft,_)) -> params
+ | _ -> [] in
let ret_t,param_t,tannot,t_param_env = match tannotopt with
| Typ_annot_opt_aux(Typ_annot_opt_some(typq,typ),l') ->
let (ids,_,constraints) = typq_to_params envs typq in
let t = typ_to_t false false typ in
- let t,constraints,_,t_param_env = subst ids t constraints pure_e in
+ let t,constraints,_,t_param_env = subst (if ids=[] then typ_params else ids) 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,nob),t_param_env in
let check t_env tp_env imp_param =
List.split
(List.map (fun (FCL_aux((FCL_Funcl(id,pat,exp)),(l,_))) ->
-(* let _ = Printf.eprintf "checking function %s : %s -> %s\n" (id_to_string id) (t_to_string param_t) (t_to_string ret_t) in*)
+ let _ = Printf.eprintf "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,b_env',t') = check_pattern (Env(d_env,t_env,b_env,tp_env)) Emp_local param_t pat in
let t', _ = type_consistent (Patt l) d_env Require 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',
merge_bounds b_env b_env',tp_env)) imp_param ret_t exp in
-(* let _ = Printf.eprintf "checked function %s : %s -> %s\n" (id_to_string id) (t_to_string param_t) (t_to_string ret_t) in
- let _ = Printf.eprintf "constraints were %s\n" (constraints_to_string (cs_p@cs_e)) in*)
+ let _ = Printf.eprintf "checked function %s : %s -> %s\n" (id_to_string id) (t_to_string param_t) (t_to_string ret_t) in
+ let _ = Printf.eprintf "constraints were %s\n" (constraints_to_string (cs_p@cs_e)) 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
let update_pattern var (FCL_aux ((FCL_Funcl(id,(P_aux(pat,t)),exp)),annot)) =
@@ -1747,11 +1754,11 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
in
match (in_env,tannot) with
| Some(Base( (params,u),Spec,constraints,eft,_)), Base( (p',t),_,c',eft',_) ->
- (*let _ = Printf.eprintf "Function %s is in env\n" id in*)
+ let _ = Printf.eprintf "Function %s is in env\n" id in
let u,constraints,eft,t_param_env_spec = subst params u constraints eft in
let t_param_cs = type_param_consistent l t_param_env_spec t_param_env in
let _,cs_decs = type_consistent (Specc l) d_env Require false t u in
- (*let _ = Printf.eprintf "valspec consistent with declared type for %s, %s ~< %s with %s derived constraints and %s stated and %s from environment consistency\n" id (t_to_string t) (t_to_string u) (constraints_to_string cs_decs) (constraints_to_string (constraints@c')) (constraints_to_string t_param_cs) in*)
+ let _ = Printf.eprintf "valspec consistent with declared type for %s, %s ~< %s with %s derived constraints and %s stated and %s from environment consistency\n" id (t_to_string t) (t_to_string u) (constraints_to_string cs_decs) (constraints_to_string (constraints@c')) (constraints_to_string t_param_cs) in
let imp_param = match u.t with
| Tfn(_,_,IP_user n,_) -> Some n
| _ -> None in
@@ -1760,14 +1767,14 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
let cs,ef = ((fun (cses,efses) ->
(List.concat cses),(List.fold_right union_effects efses pure_e)) (List.split cs_ef)) in
let cs' = resolve_constraints (cs@cs_decs@constraints@c'@t_param_cs) in
- (*let _ = Printf.eprintf "remaining constraints are: %s\n" (constraints_to_string cs') in*)
+ let _ = Printf.eprintf "remaining constraints are: %s\n" (constraints_to_string cs') in
let tannot = check_tannot l tannot imp_param cs' ef in
- (*let _ = Printf.eprintf "check_tannot ok for %s val type %s derived type %s \n" id (t_to_string u) (t_to_string t) in*)
+ let _ = Printf.eprintf "check_tannot ok for %s val type %s derived type %s \n" id (t_to_string u) (t_to_string t) in
let funcls = match imp_param with
| Some {nexp = Nvar i} -> List.map (update_pattern i) funcls
| _ -> funcls
in
- (*let _ = Printf.eprintf "done funcheck case 1\n" in*)
+ let _ = Printf.eprintf "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),b_env,tp_env)
| _ , _->
@@ -1775,9 +1782,9 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l,
let funcls,cs_ef = check t_env t_param_env None in
let cs,ef = ((fun (cses,efses) -> (List.concat cses),(List.fold_right union_effects efses pure_e)) (List.split cs_ef)) in
let cs' = resolve_constraints cs in
- (*let _ = Printf.eprintf "checking tannot for %s 2 remaining constraints are %s\n" id (constraints_to_string cs') in*)
+ let _ = Printf.eprintf "checking tannot for %s 2 remaining constraints are %s\n" id (constraints_to_string cs') in
let tannot = check_tannot l tannot None cs' ef in
- (*let _ = Printf.eprintf "done funcheck case2\n" in*)
+ let _ = Printf.eprintf "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)),b_env,tp_env)
diff --git a/src/type_internal.ml b/src/type_internal.ml
index 989460a8..0e309d82 100644
--- a/src/type_internal.ml
+++ b/src/type_internal.ml
@@ -44,13 +44,14 @@ and nexp_aux =
| Npos_inf
| Nneg_inf
| Nadd of nexp * nexp
+ | Nsub of nexp * nexp
| Nmult of nexp * nexp
| N2n of nexp * big_int option
| Npow of nexp * int (* nexp raised to the int *)
| Nneg of nexp (* Unary minus for representing new vector sizes after vector slicing *)
| 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; }
+and n_uvar = { nindex : int; mutable nsubst : nexp option; mutable nin : bool; mutable leave_var : bool}
and effect = { mutable effect : effect_aux }
and effect_aux =
| Evar of string
@@ -158,7 +159,11 @@ let rec t_to_string t =
match t.t with
| Tid i -> i
| Tvar i -> i
- | Tfn(t1,t2,_,e) -> (t_to_string t1) ^ " -> " ^ (t_to_string t2) ^ " effect " ^ e_to_string e
+ | Tfn(t1,t2,imp,e) ->
+ let implicit = match imp with
+ | IP_none -> ""
+ | IP_length n | IP_start n | IP_user n -> " with implicit parameter " ^ n_to_string n ^ " " in
+ (t_to_string t1) ^ " -> " ^ (t_to_string t2) ^ " effect " ^ e_to_string e ^ implicit
| Ttup(tups) -> "(" ^ string_of_list ", " t_to_string tups ^ ")"
| Tapp(i,args) -> i ^ "<" ^ string_of_list ", " targ_to_string args ^ ">"
| Tabbrev(ti,ta) -> (t_to_string ti) ^ " : " ^ (t_to_string ta)
@@ -178,6 +183,7 @@ and n_to_string n =
| Npos_inf -> "infinity"
| Nneg_inf -> "-infinity"
| Nadd(n1,n2) -> "("^ (n_to_string n1) ^ " + " ^ (n_to_string n2) ^")"
+ | Nsub(n1,n2) -> "("^ (n_to_string n1) ^ " - " ^ (n_to_string n2) ^ ")"
| Nmult(n1,n2) -> "(" ^ (n_to_string n1) ^ " * " ^ (n_to_string n2) ^ ")"
| N2n(n,None) -> "2**" ^ (n_to_string n)
| N2n(n,Some i) -> "2**" ^ (n_to_string n) ^ "(*" ^ (string_of_big_int i) ^ "*)"
@@ -338,6 +344,10 @@ let rec compare_nexps n1 n2 =
| a -> a)
| Nadd _ , _ -> -1
| _ , Nadd _ -> 1
+ | Nsub(n1,n12),Nsub(n2,n22) ->
+ (match compare_nexps n1 n2 with
+ | 0 -> compare_nexps n12 n22
+ | a -> a)
| Npow(n1,_),Npow(n2,_)-> compare_nexps n1 n2
| Npow _ , _ -> -1
| _ , Npow _ -> 1
@@ -363,7 +373,7 @@ let rec contains_const n =
| Nvar _ | Nuvar _ | Npow _ | N2n _ | Npos_inf | Nneg_inf -> false
| Nconst _ -> true
| Nneg n -> contains_const n
- | Nmult(n1,n2) | Nadd(n1,n2) -> (contains_const n1) || (contains_const n2)
+ | Nmult(n1,n2) | Nadd(n1,n2) | Nsub(n1,n2) -> (contains_const n1) || (contains_const n2)
let rec get_var n =
match n.nexp with
@@ -376,7 +386,7 @@ let rec get_all_nvar n =
match n.nexp with
| Nvar v -> [v]
| Nneg n | N2n(n,_) | Npow(n,_) -> get_all_nvar n
- | Nmult(n1,n2) | Nadd(n1,n2) -> (get_all_nvar n1)@(get_all_nvar n2)
+ | Nmult(n1,n2) | Nadd(n1,n2) | Nsub(n1,n2) -> (get_all_nvar n1)@(get_all_nvar n2)
| _ -> []
let get_factor n =
@@ -408,13 +418,14 @@ let increment_factor n i =
let negate n = {nexp = Nmult ({nexp = Nconst (big_int_of_int (-1))},n)}
let rec normalize_nexp n =
- (* let _ = Printf.printf "Working on normalizing %s\n" (n_to_string n) in *)
+ (*let _ = Printf.eprintf "Working on normalizing %s\n" (n_to_string n) in *)
match n.nexp with
| Nconst _ | Nvar _ | Nuvar _ | Npos_inf | Nneg_inf -> n
| Nneg n ->
let n',to_recur,add_neg = (match n.nexp with
| Nconst i -> {nexp = Nconst (mult_int_big_int (-1) i)},false,false
| Nadd(n1,n2) -> {nexp = Nadd(negate n1,negate n2)},true,false
+ | Nsub(n1,n2) -> {nexp = Nsub(n2,n1) },false,false
| Nneg n -> normalize_nexp n,false,false
| _ -> n,true,true) in
if to_recur
@@ -501,8 +512,33 @@ let rec normalize_nexp n =
| -1 -> { nexp = Nadd(n21', normalize_nexp { nexp = Nadd(n1',n22')})}
| 1 -> { nexp = Nadd(n1',n2') }
| _ -> let _ = Printf.eprintf "pattern didn't match unexpextedly here %s %s\n" (n_to_string n1') (n_to_string n2') in assert false)
- | _ -> let _ = Printf.eprintf "pattern didn't match here with no vars %s %s\n" (n_to_string n1') (n_to_string n2') in assert false)
+ | _ -> {nexp = Nadd (n1', n2')})
)
+ | Nsub(n1,n2) ->
+ let n1',n2' = normalize_nexp n1, normalize_nexp n2 in
+ (*let _ = Printf.eprintf "Normalizing subtraction of %s - %s \n" (n_to_string n1') (n_to_string n2') in*)
+ (match n1'.nexp,n2'.nexp with
+ | Nneg_inf, Npos_inf | Npos_inf, Nneg_inf -> {nexp = Ninexact }
+ | Npos_inf, _ | _,Nneg_inf -> { nexp = Npos_inf }
+ | Nneg_inf, _ | _,Npos_inf -> { nexp = Nneg_inf }
+ | Nconst i1, Nconst i2 | Nconst i1, N2n(_,Some i2) | N2n(_,Some i1), Nconst i2 ->
+ let _ = Printf.eprintf "constant subtraction of %s - %s gives %s" (Big_int.string_of_big_int i1) (Big_int.string_of_big_int i2) (Big_int.string_of_big_int (sub_big_int i1 i2)) in
+ {nexp = Nconst (sub_big_int i1 i2)}
+ | Nadd(n11,n12), Nconst _ -> {nexp = Nadd(n11,normalize_nexp {nexp = Nsub(n12,n2')})}
+ | Nconst _, Nadd(n21,n22) -> {nexp = Nadd(n21,normalize_nexp {nexp = Nsub(n22,n1')})}
+ | Nconst i, _ -> if (eq_big_int i zero) then negate n2' else {nexp = Nsub(n1',n2')}
+ | _, Nconst i -> if (eq_big_int i zero) then n1' else {nexp = Nsub(n1',n2')}
+ | Nvar _, Nuvar _ | Nvar _, N2n _ | Nuvar _, Npow _ -> {nexp = Nsub (n2',n1')}
+ | N2n(_,Some i1),N2n(_,Some i2) -> {nexp = Nconst (sub_big_int i1 i2)}
+ | N2n(n1,_), N2n(n2,_) ->
+ (match compare_nexps n1 n2 with
+ | 0 -> n_zero
+ | _ -> { nexp = Nsub (n1',n2')})
+ | Npow(n1,i1), Npow (n2,i2) ->
+ (match compare_nexps n1 n2, compare i1 i2 with
+ | 0,0 -> n_zero
+ | _ -> {nexp = Nsub (n1',n2')})
+ | _ -> {nexp = Nsub(n1',n2')})
| Nmult(n1,n2) ->
let n1',n2' = normalize_nexp n1, normalize_nexp n2 in
(match n1'.nexp,n2'.nexp with
@@ -617,9 +653,12 @@ let new_t _ =
let new_n _ =
let i = !n_count in
n_count := i + 1;
- let n = { nexp = Nuvar { nindex = i; nsubst = None ; nin = false}} in
+ let n = { nexp = Nuvar { nindex = i; nsubst = None ; nin = false ; leave_var = false}} in
nuvars := n::!nuvars;
n
+let leave_nuvar n = match n.nexp with
+ | Nuvar u -> u.leave_var <- true; n
+ | _ -> n
let new_o _ =
let i = !o_count in
o_count := i + 1;
@@ -752,23 +791,34 @@ let rec occurs_in_pending_subst n_box n : bool =
| _ -> occurs_in_nexp n_box n
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*)
+ 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
- | Nadd (nb1,nb2) | Nmult (nb1,nb2) -> occurs_in_nexp nb1 nuvar || occurs_in_nexp nb2 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 =
- match n.nexp with
+ let _ = Printf.eprintf "reduce_n_unifications %s\n" (n_to_string n) in
+ (match n.nexp with
| Nvar _ | Nconst _ | Npos_inf | Nneg_inf -> ()
| N2n(n1,_) | Npow(n1,_) | Nneg n1 -> reduce_n_unifications n1
- | Nadd(n1,n2) | Nmult(n1,n2) -> reduce_n_unifications n1; reduce_n_unifications n2
+ | 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); n.nexp <- nexp.nexp)
+ | 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 ()
+
+let rec leave_nu_as_var n =
+ match n.nexp with
+ | Nuvar nu ->
+ (match nu.nsubst 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*)
@@ -819,16 +869,16 @@ let equate_e (e_box : effect) (e : effect) : unit =
| _ ->
e_box.effect <- e.effect)
-let rec fresh_var i mkr bindings =
- let v = "'v" ^ (string_of_int i) in
+let fresh_var prefix i mkr bindings =
+ let v = "'" ^ prefix ^ (string_of_int i) in
match Envmap.apply bindings v with
- | Some _ -> fresh_var (i+1) mkr bindings
- | None -> mkr v
+ | Some _ -> mkr v false
+ | None -> mkr v true
let rec fresh_tvar bindings t =
match t.t with
| Tuvar { index = i;subst = None } ->
- fresh_var i (fun v -> equate_t t {t=Tvar v};Some (v,{k=K_Typ})) bindings
+ fresh_var "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';
@@ -838,10 +888,10 @@ let rec fresh_tvar bindings t =
None
| _ -> None
let rec fresh_nvar bindings n =
- (*let _ = Printf.printf "fresh_nvar for %s\n" (n_to_string n) in*)
+ let _ = Printf.eprintf "fresh_nvar for %s\n" (n_to_string n) in
match n.nexp with
| Nuvar { nindex = i;nsubst = None } ->
- fresh_var i (fun v -> n.nexp <- (Nvar v); Some(v,{k=K_Nat})) bindings
+ fresh_var "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 = Some({nexp=Nuvar _} as n')} ->
let kv = fresh_nvar bindings n' in
n.nexp <- n'.nexp;
@@ -853,7 +903,7 @@ let rec fresh_nvar bindings n =
let rec fresh_ovar bindings o =
match o.order with
| Ouvar { oindex = i;osubst = None } ->
- fresh_var i (fun v -> equate_o o {order = (Ovar v)}; Some(v,{k=K_Nat})) bindings
+ fresh_var "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';
@@ -865,7 +915,7 @@ let rec fresh_ovar bindings o =
let rec fresh_evar bindings e =
match e.effect with
| Euvar { eindex = i;esubst = None } ->
- fresh_var i (fun v -> equate_e e {effect = (Evar v)}; Some(v,{k=K_Nat})) bindings
+ fresh_var "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';
@@ -946,7 +996,7 @@ let mk_pure_imp arg ret var = {t = Tfn (arg,ret,IP_length {nexp = Nvar var},pure
let mk_nv v = {nexp = Nvar v}
let mk_add n1 n2 = {nexp = Nadd (n1,n2) }
-let mk_sub n1 n2 = {nexp = Nadd (n1, {nexp = Nneg n2})}
+let mk_sub n1 n2 = {nexp = Nsub (n1, n2)}
let mk_mult n1 n2 = {nexp = Nmult(n1,n2) }
let mk_range n1 n2 = {t=Tapp("range",[TA_nexp n1;TA_nexp n2])}
@@ -1322,7 +1372,7 @@ let initial_typ_env =
]));
("length", Base((["a",{k=K_Typ}]@(mk_nat_params["n";"m"])@(mk_ord_params["ord"]),
(mk_pure_fun (mk_vector {t=Tvar "a"} (Ovar "ord") (Nvar "n") (Nvar "m"))
- (mk_range (mk_nv "m") n_zero))),
+ (mk_range (mk_nv "m") (mk_nv "m")))),
External (Some "length"),[],pure_e,nob));
(* incorrect types for typechecking processed sail code; do we care? *)
("mask",Base(((mk_typ_params ["a"])@(mk_nat_params["n";"m";"o";"p"])@(mk_ord_params["ord"]),
@@ -1545,9 +1595,9 @@ let rec typ_subst s_env t =
and ip_subst s_env ip =
match ip with
| IP_none -> ip
- | IP_length n -> IP_length (n_subst s_env n)
- | IP_start n -> IP_start (n_subst s_env n)
- | IP_user n -> IP_user (n_subst s_env n)
+ | IP_length n -> IP_length (leave_nuvar (n_subst s_env n))
+ | IP_start n -> IP_start (leave_nuvar (n_subst s_env n))
+ | IP_user n -> IP_user (leave_nuvar (n_subst s_env n))
and ta_subst s_env ta =
match ta with
| TA_typ t -> TA_typ (typ_subst s_env t)
@@ -1556,15 +1606,17 @@ and ta_subst s_env ta =
| TA_ord o -> TA_ord (o_subst s_env o)
and n_subst s_env n =
match n.nexp with
- | Nvar i -> (match Envmap.apply s_env i with
- | Some(TA_nexp n1) -> n1
- | _ -> { nexp = Nvar i })
+ | Nvar i ->
+ (match Envmap.apply s_env i with
+ | Some(TA_nexp n1) -> n1
+ | _ -> { nexp = Nvar i })
| Nuvar _ -> new_n()
| Nconst _ | Npos_inf | Nneg_inf -> n
| N2n(n1,i) -> { nexp = N2n (n_subst s_env n1,i) }
| Npow(n1,i) -> { nexp = Npow (n_subst s_env n1,i) }
| Nneg n1 -> { nexp = Nneg (n_subst s_env n1) }
| Nadd(n1,n2) -> { nexp = Nadd(n_subst s_env n1,n_subst s_env n2) }
+ | Nsub(n1,n2) -> {nexp = Nsub(n_subst s_env n1,n_subst s_env n2) }
| Nmult(n1,n2) -> { nexp = Nmult(n_subst s_env n1,n_subst s_env n2) }
and o_subst s_env o =
match o.order with
@@ -1640,7 +1692,7 @@ let rec t_remove_unifications s_env t =
(match fresh_tvar s_env t with
| Some ks -> Envmap.insert s_env ks
| None -> s_env)
- | _ -> resolve_tsubst t; s_env)
+ | _ -> 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
@@ -1653,7 +1705,7 @@ and ta_remove_unifications s_env ta =
| TA_eft e -> (e_remove_unifications s_env e)
| TA_ord o -> (o_remove_unifications s_env o)
and n_remove_unifications s_env n =
- (*let _ = Printf.eprintf "n_remove_unifications %s\n" (n_to_string n) in*)
+ let _ = Printf.eprintf "n_remove_unifications %s\n" (n_to_string n) in
match n.nexp with
| Nvar _ | Nconst _ | Npos_inf | Nneg_inf -> s_env
| Nuvar nu ->
@@ -1662,13 +1714,13 @@ and n_remove_unifications s_env n =
| _ -> 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*)
+ 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)
| N2n(n1,_) | Npow(n1,_) | Nneg n1 -> (n_remove_unifications s_env n1)
- | Nadd(n1,n2) | Nmult(n1,n2) -> (n_remove_unifications (n_remove_unifications s_env n1) n2)
+ | 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 =
match o.order with
| Ouvar _ -> (match fresh_ovar s_env o with
@@ -1721,6 +1773,7 @@ and n_to_nexp n =
| Nneg_inf -> Nexp_constant min_int (* see above *)
| Nmult(n1,n2) -> Nexp_times(n_to_nexp n1,n_to_nexp n2)
| Nadd(n1,n2) -> Nexp_sum(n_to_nexp n1,n_to_nexp n2)
+ | Nsub(n1,n2) -> Nexp_minus(n_to_nexp n1,n_to_nexp n2)
| N2n(n,_) -> Nexp_exp (n_to_nexp n)
| Npow(n,1) -> let Nexp_aux(n',_) = n_to_nexp n in n'
| Npow(n,i) -> Nexp_times(n_to_nexp n,n_to_nexp{nexp = Npow(n,i-1)})
@@ -2137,13 +2190,13 @@ let rec type_coerce_internal co d_env enforce is_explicit widen t1 cs1 e t2 cs2
(match args2,args1 with
| [TA_nexp b1;TA_nexp r1;TA_ord {order = Oinc};TA_typ {t=Tid "bit"}],
[TA_nexp b2;TA_nexp r2;] ->
- let cs = [LtEq(co,Guarantee,r2,mk_sub {nexp=N2n(r1,None)} n_one)] in
+ let cs = [] (*[LtEq(co,Guarantee,r2,mk_sub {nexp=N2n(r1,None)} n_one)] (*This constraint failing should be a warning, but truncation is ok*)*) in
let tannot = (l,Base(([],t2),External None, cs,pure_e,nob)) in
(t2,cs,pure_e,E_aux(E_app((Id_aux(Id "to_vec_inc",l)),
[(E_aux(E_internal_exp(tannot), tannot));e]),tannot))
| [TA_nexp b1;TA_nexp r1;TA_ord {order = Odec};TA_typ {t=Tid "bit"}],
[TA_nexp b2;TA_nexp r2;] ->
- let cs = [LtEq(co,Guarantee,r2,mk_sub {nexp=N2n(r1,None)} n_one)] in
+ let cs = [] (* See above [LtEq(co,Guarantee,r2,mk_sub {nexp=N2n(r1,None)} n_one)]*) in
let tannot = (l,Base(([],t2),External None,cs,pure_e,nob)) in
(t2,cs,pure_e,E_aux(E_app((Id_aux(Id "to_vec_dec",l)),
[(E_aux(E_internal_exp(tannot), tannot)); e]),tannot))
@@ -2156,13 +2209,13 @@ let rec type_coerce_internal co d_env enforce is_explicit widen t1 cs1 e t2 cs2
(match args2,args1 with
| [TA_nexp b1;TA_nexp r1;TA_ord {order = Oinc};TA_typ {t=Tid "bit"}],
[TA_nexp b2] ->
- let cs = [LtEq(co,Guarantee,b2,mk_sub {nexp=N2n(r1,None)} n_one)] in
+ let cs = [](*[LtEq(co,Guarantee,b2,mk_sub {nexp=N2n(r1,None)} n_one)]*) in
let tannot = (l,Base(([],t2),External None, cs,pure_e,nob)) in
(t2,cs,pure_e,E_aux(E_app((Id_aux(Id "to_vec_inc",l)),
[(E_aux(E_internal_exp(tannot), tannot));e]),tannot))
| [TA_nexp b1;TA_nexp r1;TA_ord {order = Odec};TA_typ {t=Tid "bit"}],
[TA_nexp b2] ->
- let cs = [LtEq(co,Guarantee,b2,mk_sub {nexp=N2n(r1,None)} n_one)] in
+ let cs = [](*[LtEq(co,Guarantee,b2,mk_sub {nexp=N2n(r1,None)} n_one)]*) in
let tannot = (l,Base(([],t2),External None,cs,pure_e,nob)) in
(t2,cs,pure_e,E_aux(E_app((Id_aux(Id "to_vec_dec",l)),
[(E_aux(E_internal_exp(tannot), tannot)); e]),tannot))
@@ -2302,7 +2355,7 @@ let rec contains_var nu n =
match n.nexp with
| Nvar _ | Nuvar _ -> nexp_eq_check nu n
| Nconst _ | Npos_inf | Nneg_inf -> false
- | Nadd(n1,n2) | Nmult(n1,n2) -> contains_var nu n1 || contains_var nu n2
+ | Nadd(n1,n2) | Nsub(n1,n2) | Nmult(n1,n2) -> contains_var nu n1 || contains_var nu n2
| Nneg n | N2n(n,_) | Npow(n,_) -> contains_var nu n
let rec contains_in_vars in_env n =
@@ -2319,6 +2372,7 @@ let rec subst_nuvars nu nc n =
| Nuvar _ -> if nexp_eq_check nu n then nc else n
| Nmult(n1,n2) -> {nexp=Nmult(subst_nuvars nu nc n1,subst_nuvars nu nc n2)}
| Nadd(n1,n2) -> {nexp=Nadd(subst_nuvars nu nc n1,subst_nuvars nu nc n2)}
+ | Nsub(n1,n2) -> {nexp=Nsub(subst_nuvars nu nc n1,subst_nuvars nu nc n2)}
| Nneg n -> {nexp= Nneg (subst_nuvars nu nc n)}
| N2n(n,i) -> {nexp = N2n((subst_nuvars nu nc n),i)}
| Npow(n,i) -> {nexp = Npow((subst_nuvars nu nc n),i)}
@@ -2327,7 +2381,7 @@ let rec get_nuvars n =
match n.nexp with
| Nconst _ | Nvar _ | Npos_inf | Nneg_inf -> []
| Nuvar _ -> [n]
- | Nmult(n1,n2) | Nadd(n1,n2) -> (get_nuvars n1)@(get_nuvars n2)
+ | Nmult(n1,n2) | Nadd(n1,n2) | Nsub(n1,n2) -> (get_nuvars n1)@(get_nuvars n2)
| Nneg n | N2n(n,_) | Npow(n,_) -> get_nuvars n
let freshen n =
@@ -2337,13 +2391,43 @@ let freshen n =
(n,env_map)
+let rec equate_nuvars in_env cs =
+ let _ = Printf.eprintf "equate_nuvars\n" in
+ let equate = equate_nuvars in_env in
+ match cs with
+ | [] -> []
+ | (Eq(co,n1,n2) as c)::cs ->
+ (match (n1.nexp,n2.nexp) with
+ | 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
+ 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
+ else c::equate cs
+ | _ -> c::equate cs)
+ | CondCons(co,pats,exps):: cs ->
+ let pats' = equate pats in
+ let exps' = equate exps in
+ (match pats',exps' with
+ | [],[] -> equate cs
+ | _ -> CondCons(co,pats',exps')::(equate cs))
+ | BranchCons(co,branches)::cs ->
+ let b' = equate branches in
+ if [] = b'
+ then equate cs
+ else BranchCons(co,b')::(equate cs)
+ | x::cs -> x::(equate cs)
+
+
let rec simple_constraint_check in_env cs =
let check = simple_constraint_check in_env in
-(* let _ = Printf.eprintf "simple_constraint_check of %s\n" (constraints_to_string cs) in *)
+ let _ = Printf.eprintf "simple_constraint_check of %s\n" (constraints_to_string cs) in
match cs with
| [] -> []
| Eq(co,n1,n2)::cs ->
let eq_to_zero ok_to_set n1 n2 =
+ let _ = Printf.eprintf "eq_to_zero called with n1 %s and n2%s\n" (n_to_string n1) (n_to_string n2) in
let new_n = normalize_nexp (mk_sub n1 n2) in
(match new_n.nexp with
| Nconst i ->
@@ -2361,16 +2445,16 @@ let rec simple_constraint_check in_env cs =
| _ -> Some(Eq(co,n1,n2)))
| _ -> Some(Eq(co,n1,n2))) in
let check_eq ok_to_set n1 n2 =
- (*let _ = Printf.eprintf "eq check, about to normalize_nexp of %s, %s arising from %s \n" (n_to_string n1) (n_to_string n2) (co_to_string co) in *)
+ let _ = Printf.eprintf "eq check, about to normalize_nexp of %s, %s arising from %s \n" (n_to_string n1) (n_to_string n2) (co_to_string co) in
let n1',n2' = normalize_nexp n1,normalize_nexp n2 in
- (*let _ = Printf.eprintf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in *)
+ let _ = Printf.eprintf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in
(match n1'.nexp,n2'.nexp with
| Ninexact,nok | nok,Ninexact -> eq_error (get_c_loc co) ("Type constraint arising from here requires " ^ n_to_string {nexp = nok} ^ " to be equal to +inf + -inf")
| Npos_inf,Npos_inf | Nneg_inf, Nneg_inf -> None
| Nconst i1, Nconst i2 | Nconst i1,N2n(_,Some(i2)) | N2n(_,Some(i1)),Nconst(i2) ->
if eq_big_int i1 i2 then None else eq_error (get_c_loc co) ("Type constraint mismatch: constraint arising from here requires " ^ n_to_string n1 ^ " to equal " ^ n_to_string n2 )
| Nuvar u1, Nuvar u2 ->
- (*let _ = Printf.eprintf "setting two nuvars, %s and %s, it is ok_to_set %b\n" (n_to_string n1) (n_to_string n2) ok_to_set in*)
+ let _ = Printf.eprintf "setting two nuvars, %s and %s, it is ok_to_set %b\n" (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');
@@ -2378,15 +2462,21 @@ let rec simple_constraint_check in_env cs =
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
- if not(u.nin) && ok_to_set && not(occurs)
+ let leave = leave_nu_as_var 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
else Some (Eq(co,n1',n2'))
| Nuvar u, _ ->
+ let _ = Printf.eprintf "setting left nuvar\n" in
let occurs = occurs_in_nexp n2' n1' in
- if not(u.nin) && ok_to_set && not(occurs)
+ let leave = leave_nu_as_var 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
@@ -2404,9 +2494,9 @@ let rec simple_constraint_check in_env cs =
| Some(c) -> c::(check cs))
| _ -> (Eq(co,n1,n2)::(check cs)))
| GtEq(co,enforce,n1,n2)::cs ->
- (*let _ = Printf.eprintf ">= check, about to normalize_nexp of %s, %s\n" (n_to_string n1) (n_to_string 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
- (*let _ = Printf.printf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in*)
+ let _ = Printf.eprintf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in
(match n1'.nexp,n2'.nexp with
| Nconst i1, Nconst i2 | Nconst i1,N2n(_,Some(i2)) | N2n(_,Some(i1)),Nconst i2 ->
if ge_big_int i1 i2
@@ -2427,9 +2517,9 @@ 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)))
| LtEq(co,enforce,n1,n2)::cs ->
- (*let _ = Printf.eprintf "<= check, about to normalize_nexp of %s, %s\n" (n_to_string n1) (n_to_string 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
- (*let _ = Printf.eprintf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in *)
+ let _ = Printf.eprintf "finished evaled to %s, %s\n" (n_to_string n1') (n_to_string n2') in
(match n1'.nexp,n2'.nexp with
| Nconst i1, Nconst i2 | Nconst i1, N2n(_,Some(i2)) | N2n(_,Some(i1)),Nconst i2 ->
if le_big_int i1 i2
@@ -2473,13 +2563,14 @@ let resolve_constraints cs =
if not !do_resolve_constraints
then cs
else
- let rec fix len cs =
+ let rec fix checker len cs =
(*let _ = Printf.eprintf "Calling simple constraint check, fix check point is %i\n" len in *)
- let cs' = simple_constraint_check (in_constraint_env cs) cs in
+ let cs' = checker (in_constraint_env cs) cs in
let len' = constraint_size cs' in
- if len > len' then fix len' cs'
+ if len > len' then fix checker len' cs'
else cs' in
- let complex_constraints = fix (constraint_size cs) cs in
+ let nuvar_equated = fix equate_nuvars (constraint_size cs) cs in
+ let complex_constraints = fix simple_constraint_check (constraint_size nuvar_equated) nuvar_equated in
(*let _ = Printf.eprintf "Resolved as many constraints as possible, leaving %i\n" (constraint_size complex_constraints) in*)
complex_constraints
@@ -2490,11 +2581,11 @@ let check_tannot l annot imp_param constraints efs =
ignore(effects_eq (Specc l) efs e);
let s_env = (t_remove_unifications (Envmap.from_list params) t) in
let params = Envmap.to_list s_env in
- (*let _ = Printf.eprintf "parameters going to save are " 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*)
+ let _ = Printf.eprintf "\n" in
ignore (remove_internal_unifications s_env);
- (*let _ = Printf.printf "Checked tannot, t after removing uvars is %s\n" (t_to_string t) in *)
+ 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
diff --git a/src/type_internal.mli b/src/type_internal.mli
index f087f7f4..5d732406 100644
--- a/src/type_internal.mli
+++ b/src/type_internal.mli
@@ -48,6 +48,7 @@ and nexp_aux =
| Npos_inf (* Used to define nat and int types, does not arise from source otherwise *)
| Nneg_inf (* Used to define int type, does not arise from source otherwise *)
| Nadd of nexp * nexp
+ | Nsub of nexp * nexp
| Nmult of nexp * nexp
| N2n of nexp * big_int option (* Optionally contains the 2^n result for const n, for different constraint equations *)
| Npow of nexp * int (* Does not appear in source *)