diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/initial_check.ml | 1 | ||||
| -rw-r--r-- | src/lem_interp/interp.lem | 14 | ||||
| -rw-r--r-- | src/lem_interp/interp_lib.lem | 20 | ||||
| -rw-r--r-- | src/parser.mly | 4 | ||||
| -rw-r--r-- | src/pretty_print.ml | 2 | ||||
| -rw-r--r-- | src/test/power.sail | 6 | ||||
| -rw-r--r-- | src/test/test3.sail | 2 | ||||
| -rw-r--r-- | src/type_check.ml | 180 | ||||
| -rw-r--r-- | src/type_internal.ml | 58 | ||||
| -rw-r--r-- | src/type_internal.mli | 5 |
10 files changed, 180 insertions, 112 deletions
diff --git a/src/initial_check.ml b/src/initial_check.ml index 95578d9f..0cd58e02 100644 --- a/src/initial_check.ml +++ b/src/initial_check.ml @@ -359,6 +359,7 @@ and to_ast_exp (k_env : kind Envmap.t) (Parse_ast.E_aux(exp,l) : Parse_ast.exp) | Parse_ast.E_vector_subrange(vex,exp1,exp2) -> E_vector_subrange(to_ast_exp k_env vex, to_ast_exp k_env exp1, to_ast_exp k_env exp2) | Parse_ast.E_vector_update(vex,exp1,exp2) -> E_vector_update(to_ast_exp k_env vex, to_ast_exp k_env exp1, to_ast_exp k_env exp2) | Parse_ast.E_vector_update_subrange(vex,e1,e2,e3) -> E_vector_update_subrange(to_ast_exp k_env vex, to_ast_exp k_env e1, to_ast_exp k_env e2, to_ast_exp k_env e3) + | Parse_ast.E_vector_append(e1,e2) -> E_vector_append(to_ast_exp k_env e1,to_ast_exp k_env e2) | Parse_ast.E_list(exps) -> E_list(List.map (to_ast_exp k_env) exps) | Parse_ast.E_cons(e1,e2) -> E_cons(to_ast_exp k_env e1, to_ast_exp k_env e2) | Parse_ast.E_record _ -> raise (Reporting_basic.err_unreachable l "parser generated an E_record") diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem index f0770d4e..2960f048 100644 --- a/src/lem_interp/interp.lem +++ b/src/lem_interp/interp.lem @@ -986,6 +986,20 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = update_stack a (add_to_top_frame (fun i2 -> E_aux (E_vector_update_subrange vec (to_exp vi1) i2 exp) (l,annot)))) | _ -> (Error l "vector update requires number",lm,le) end) (fun a -> update_stack a (add_to_top_frame (fun i1 -> E_aux (E_vector_update_subrange vec i1 i2 exp) (l,annot)))) + | E_vector_append e1 e2 -> + resolve_outcome (interp_main mode t_level l_env l_mem e1) + (fun v1 lm le -> + match v1 with + | V_vector m inc vals1 -> + (resolve_outcome (interp_main mode t_level l_env lm e2) + (fun v2 lm le -> + match v2 with + | V_vector _ _ vals2 -> (Value (V_vector m inc (vals1++vals2)) Tag_empty,lm,l_env) + | _ -> (Error l "vector concat requires vector",lm,le) end) + (fun a -> update_stack a (add_to_top_frame + (fun e -> E_aux (E_vector_append (to_exp v1) e) (l,annot))))) + | _ -> (Error l "vector concat requires vector",lm,le) end) + (fun a -> update_stack a (add_to_top_frame (fun e -> E_aux (E_vector_append e e2) (l,annot)))) | E_tuple(exps) -> exp_list mode t_level (fun exps -> E_aux (E_tuple exps) (l,annot)) V_tuple l_env l_mem [] exps | E_vector(exps) -> diff --git a/src/lem_interp/interp_lib.lem b/src/lem_interp/interp_lib.lem index 753de883..e994fdfe 100644 --- a/src/lem_interp/interp_lib.lem +++ b/src/lem_interp/interp_lib.lem @@ -39,6 +39,11 @@ let bitwise_not (V_vector idx inc v) = let apply x = bool_to_bit(not (bit_to_bool x)) in V_vector idx inc (List.map apply v) +let bitwise_not_bit (V_lit (L_aux l loc)) = match l with + | L_zero -> (V_lit (L_aux L_one loc)) + | L_one -> (V_lit (L_aux L_zero loc)) +end;; + let bitwise_binop op (V_tuple [V_vector idx inc v; V_vector idx' inc' v']) = (* typechecker ensures inc = inc', idx = idx' and length v = length v' *) let apply (x, y) = bool_to_bit(op (bit_to_bool x) (bit_to_bool y)) in @@ -74,14 +79,16 @@ let arith_op_vec op (V_tuple args) = match args with else to_vec_dec (List.length cs) n end ;; let arith_op_range_vec op (V_tuple args) = match args with - | [l1; (V_vector _ _ _ as l2)] -> - let l2 = (to_num true l2) in - arith_op op (V_tuple [l1;l2]) + | [n; (V_vector _ ord cs as l2)] -> + if ord + then arith_op_vec op (V_tuple [(to_vec_inc (List.length cs) n);l2]) + else arith_op_vec op (V_tuple [(to_vec_dec (List.length cs) n);l2]) end ;; let arith_op_vec_range op (V_tuple args) = match args with - | [(V_vector _ _ _ as l1);l2] -> - let l1 = (to_num true l1) in - arith_op op (V_tuple [l1;l2]) + | [(V_vector _ ord cs as l1);n] -> + if ord + then arith_op_vec op (V_tuple [l1;(to_vec_inc (List.length cs) n)]) + else arith_op_vec op (V_tuple [l1;(to_vec_dec (List.length cs) n)]) end ;; let compare_op op (V_tuple args) = match args with @@ -123,6 +130,7 @@ let function_map = [ ("to_vec_inc", to_vec_inc 64); ("to_vec_dec", to_vec_dec 64); ("bitwise_not", bitwise_not); + ("bitwise_not_bit", bitwise_not_bit); ("bitwise_and", bitwise_binop (&&)); ("bitwise_or", bitwise_binop (||)); ("bitwise_xor", bitwise_binop xor); diff --git a/src/parser.mly b/src/parser.mly index 75cdcf7d..aa088994 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -726,7 +726,7 @@ cons_exp: | shift_exp ColonColon cons_exp { eloc (E_cons($1,$3)) } | shift_exp Colon cons_exp - { eloc (E_app_infix($1,Id_aux(Id(":"), locn 2 2), $3)) } + { eloc (E_vector_append($1, $3)) } cons_right_atomic_exp: | shift_right_atomic_exp @@ -734,7 +734,7 @@ cons_right_atomic_exp: | shift_exp ColonColon cons_right_atomic_exp { eloc (E_cons($1,$3)) } | shift_exp Colon cons_right_atomic_exp - { eloc (E_app_infix($1,Id_aux(Id(":"), locn 2 2), $3)) } + { eloc (E_vector_append($1, $3)) } at_exp: | cons_exp diff --git a/src/pretty_print.ml b/src/pretty_print.ml index 3d8b0e91..7ade113c 100644 --- a/src/pretty_print.ml +++ b/src/pretty_print.ml @@ -348,6 +348,8 @@ and pp_lem_exp ppf (E_aux(e,(l,annot))) = fprintf ppf "@[<0>(E_aux (%a %a %a %a) (%a, %a))@]" kwd "E_vector_update" pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot | E_vector_update_subrange(v,e1,e2,e3) -> fprintf ppf "@[<0>(E_aux (%a %a %a %a %a) (%a, %a))@]" kwd "E_vector_update_subrange" pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_exp e3 pp_lem_l l pp_annot annot + | E_vector_append(v1,v2) -> + fprintf ppf "@[<0>(E_aux (E_vector_append %a %a) (%a, %a))@]" pp_lem_exp v1 pp_lem_exp v2 pp_lem_l l pp_annot annot | E_list(exps) -> fprintf ppf "@[<0>(E_aux (%a [%a]) (%a, %a))@]" kwd "E_list" (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot | E_cons(e1,e2) -> fprintf ppf "@[<0>(E_aux (%a %a %a) (%a, %a))@]" kwd "E_cons" pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot | E_record(FES_aux(FES_Fexps(fexps,_),_)) -> diff --git a/src/test/power.sail b/src/test/power.sail index 02b4555f..adcd0d9f 100644 --- a/src/test/power.sail +++ b/src/test/power.sail @@ -126,7 +126,7 @@ scattered function ast decode function clause execute ( LoadWordandZero ( D, RA, RT ) ) = { (bit[64]) EA := 0; (bit[64]) b := 0; { - if((bit) ( RA == 0 ) ) then b := 0 else b := (GPR[ RA ]) ; + if((bit) ( (nat) RA == 0 ) ) then b := 0 else b := (GPR[ RA ]) ; EA := ( b + ( exts ( D )) ) ; GPR[ RT ] := ( 0b00000000000000000000000000000000 : MEM( EA , 4 ) ) ; } } @@ -139,7 +139,7 @@ scattered function ast decode function clause execute ( StoreWord ( D, RA, RS ) ) = { (bit[64]) EA := 0; (bit[64]) b := 0; { - if((bit) ( RA == 0 ) ) then b := 0 else b := (GPR[ RA ]) ; + if((bit) ( (nat) RA == 0 ) ) then b := 0 else b := (GPR[ RA ]) ; EA := ( b + ( exts ( D )) ) ; MEM( EA , 4 ) := (( (GPR[ RS ]) )[ 32 .. 63 ]) ; } } @@ -165,7 +165,7 @@ scattered function ast decode function clause execute ( AddImmediate ( RA, RT, SI ) ) = { { - if((bit) ( RA == 0 ) ) then GPR[ RT ] := ( exts ( SI )) else GPR[ RT ] := ( (GPR[ RA ]) + ( exts ( SI )) ) ; + if((bit) ( (nat) RA == 0 ) ) then GPR[ RT ] := (bit[64]) ( exts ( SI )) else GPR[ RT ] := ( (GPR[ RA ]) + ( exts ( SI )) ) ; } } diff --git a/src/test/test3.sail b/src/test/test3.sail index 06086dd7..3a806f41 100644 --- a/src/test/test3.sail +++ b/src/test/test3.sail @@ -48,7 +48,7 @@ function nat main _ = { dummy_reg := (deinfix +)(5, 37); (* casts and external calls *) dummy_reg := 0b01 + 0b01; - dummy_reg2 := dummy_reg; (* cast from [|256|] to bit[8] *) + dummy_reg2 := 0b00000001; dummy_reg2 := dummy_reg2 + dummy_reg2; (* cast to nat for add call *) dummy_reg2; (* cast again and return 4 *) } diff --git a/src/type_check.ml b/src/type_check.ml index 073b36a7..5311b0b6 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -14,6 +14,11 @@ let id_to_string (Id_aux(id,l)) = | Id(s) -> s | DeIid(s) -> s +let get_e_typ (E_aux(_,(_,a))) = + match a with + | Base((_,t),_,_,_) -> t + | _ -> new_t () + let typ_error l msg = raise (Reporting_basic.err_typ l @@ -330,6 +335,8 @@ let rec check_pattern envs emp_tag expect_t (P_aux(p,(l,annot))) : ((tannot pat) let u,cs = List.fold_right (fun u (t,cs) -> let t',cs' = type_consistent (Patt l) d_env u t in t',cs@cs') ts (item_t,[]) in let t = {t = Tapp("list",[TA_typ u])} in (P_aux(P_list(pats'),(l,Base(([],t),Emp_local,cs,pure_e))), env,constraints@cs,t) + +let simp_exp e l t = E_aux(e,(l,Base(([],t),Emp_local,[],pure_e))) let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp * t * tannot emap * nexp_range list * effect) = let Env(d_env,t_env) = envs in @@ -345,14 +352,14 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let t,cs,ef = subst params t cs ef in (match t.t with | Tfn({t = Tid "unit"},t',ef) -> - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild (Base(([],{t=Tfn(unit_t,t',ef)}),Constructor,cs,ef))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild (Base(([],{t=Tfn(unit_t,t',ef)}),Constructor,cs,ef))) expect_t in (e',t',t_env,cs@cs',ef) | Tfn(t1,t',e) -> typ_error l ("Constructor " ^ i ^ " expects arguments of type " ^ (t_to_string t) ^ ", found none") | _ -> raise (Reporting_basic.err_unreachable l "Constructor tannot does not have function type")) | Some(Base((params,t),Enum,cs,ef)) -> let t',cs,_ = subst params t cs ef in - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild (Base(([],t'),Enum,cs,pure_e))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild (Base(([],t'),Enum,cs,pure_e))) expect_t in (e',t',t_env,cs@cs',pure_e) | Some(Base(tp,Default,cs,ef)) | Some(Base(tp,Spec,cs,ef)) -> typ_error l ("Identifier " ^ i ^ " must be defined, not just specified, before use") @@ -369,72 +376,74 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp | Tfn _,_ -> typ_error l ("Identifier " ^ (id_to_string id) ^ " is bound to a function and cannot be used as a value") | Tapp("register",[TA_typ(t')]),Tapp("register",[TA_typ(expect_t')]) -> let tannot = Base(([],t),Emp_local,cs,ef) in - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild tannot) expect_t' in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild tannot) expect_t' in (e',t,t_env,cs@cs',ef) | Tapp("register",[TA_typ(t')]),Tuvar _ -> let ef' = add_effect (BE_aux(BE_rreg,l)) ef in let tannot = Base(([],t),External (Some i),cs,ef') in - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild tannot) expect_actual in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild tannot) expect_actual in (e',t,t_env,cs@cs',ef) | Tapp("register",[TA_typ(t')]),_ -> let ef' = add_effect (BE_aux(BE_rreg,l)) ef in let tannot = Base(([],t),External (Some i),cs,ef') in - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild tannot) expect_actual in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild tannot) expect_actual in (e',t',t_env,cs@cs',ef) | Tapp("reg",[TA_typ(t')]),_ -> let tannot = Base(([],t),Emp_local,cs,pure_e) in - let t',cs',e' = type_coerce (Expr l) d_env t' (rebuild tannot) expect_actual in + let t',cs',e' = type_coerce (Expr l) d_env false t' (rebuild tannot) expect_actual in (e',t',t_env,cs@cs',pure_e) | _ -> - let t',cs',e' = type_coerce (Expr l) d_env t (rebuild (Base(([],t),tag,cs,pure_e))) expect_t in - (e',t,t_env,cs@cs',pure_e) + let t',cs',e' = type_coerce (Expr l) d_env false t (rebuild (Base(([],t),tag,cs,pure_e))) expect_t in + (e',t',t_env,cs@cs',pure_e) ) | Some NoTyp | Some Overload _ | None -> typ_error l ("Identifier " ^ (id_to_string id) ^ " is unbound")) | E_lit (L_aux(lit,l')) -> - let t,lit',effect = (match lit with - | L_unit -> unit_t,lit,pure_e + let e,cs,effect = (match lit with + | L_unit -> (rebuild (Base (([],unit_t), Emp_local,[],pure_e))),[],pure_e | L_zero -> (match expect_t.t with - | Tid "bool" -> bool_t,L_false,pure_e - | _ -> bit_t,lit,pure_e) + | Tid "bool" -> simp_exp (E_lit(L_aux(L_false,l'))) l bool_t,[],pure_e + | _ -> simp_exp e l bit_t,[],pure_e) | L_one -> (match expect_t.t with - | Tid "bool" -> bool_t,L_true,pure_e - | _ -> bit_t,lit,pure_e) - | L_true -> bool_t,lit,pure_e - | L_false -> bool_t,lit,pure_e + | Tid "bool" -> simp_exp (E_lit(L_aux(L_true,l'))) l bool_t,[],pure_e + | _ -> simp_exp e l bit_t,[],pure_e) + | L_true -> simp_exp e l bool_t,[],pure_e + | L_false -> simp_exp e l bool_t,[],pure_e | L_num i -> (match expect_t.t with | Tid "bit" -> - if i = 0 then bit_t,L_zero,pure_e - else - if i = 1 then bit_t,L_one,pure_e - else typ_error l "Expected bit, found a number that cannot be used as a bit" + if i = 0 then simp_exp (E_lit(L_aux(L_zero,l'))) l bit_t,[],pure_e + else if i = 1 then simp_exp (E_lit(L_aux(L_one,l'))) l bit_t,[],pure_e + else typ_error l ("Expected a bit, found " ^ string_of_int i) | Tid "bool" -> - if i = 0 then bool_t, L_false,pure_e - else - if i = 1 then bool_t,L_true,pure_e - else typ_error l "Expected bool, found a number that cannot be used as a bit and converted to bool" - | _ -> {t = Tapp("range", - [TA_nexp{nexp = Nconst (big_int_of_int i)};TA_nexp{nexp= Nconst zero};])},lit,pure_e) - | L_hex s -> {t = Tapp("vector", - [TA_nexp{nexp = Nconst zero}; - TA_nexp{nexp = Nconst (big_int_of_int ((String.length s)*4))}; - TA_ord{order = Oinc};TA_typ{t = Tid "bit"}])},lit,pure_e - | L_bin s -> {t = Tapp("vector", - [TA_nexp{nexp = Nconst zero}; - TA_nexp{nexp = Nconst (big_int_of_int (String.length s))}; - TA_ord{order = Oinc};TA_typ{t = Tid"bit"}])},lit,pure_e - | L_string s -> {t = Tid "string"},lit,pure_e - | L_undef -> new_t (),lit,{effect=Eset[BE_aux(BE_undef,l)]}) in - let t',cs',e' = - type_coerce (Expr l) d_env t (E_aux(E_lit(L_aux(lit',l')),(l,(Base(([],t),Emp_local,[],effect))))) expect_t in - (e',t',t_env,cs',effect) + if i = 0 then simp_exp (E_lit(L_aux(L_false,l'))) l bool_t,[],pure_e + else if i = 1 then simp_exp (E_lit(L_aux(L_true,l'))) l bool_t ,[],pure_e + else typ_error l ("Expected bool or a bit, found " ^ string_of_int i) + | Tapp ("vector",[TA_nexp base;TA_nexp rise;TA_ord o;(TA_typ {t=Tid "bit"})]) -> + let n = {nexp = Nconst (big_int_of_int i) } in + let t = {t=Tapp("range", [TA_nexp n;TA_nexp {nexp = Nconst zero};])} in + let cs = [LtEq(Expr l,n,{nexp = N2n(rise,None)})] in + let f = match o.order with | Oinc -> "to_vec_inc" | Odec -> "to_vec_dec" | _ -> "to_vec_inc" (*Change to follow a default?*) in + E_aux(E_app((Id_aux((Id f),l)),[simp_exp e l t]),(l,Base(([],expect_t),External (Some f),cs,pure_e))),cs,pure_e + | _ -> simp_exp e l {t = Tapp("range", [TA_nexp{nexp = Nconst (big_int_of_int i)};TA_nexp{nexp= Nconst zero};])},[],pure_e) + | L_hex s -> simp_exp e l {t = Tapp("vector", + [TA_nexp{nexp = Nconst zero}; + TA_nexp{nexp = Nconst (big_int_of_int ((String.length s)*4))}; + TA_ord{order = Oinc};TA_typ{t = Tid "bit"}])},[],pure_e + | L_bin s -> simp_exp e l {t = Tapp("vector", + [TA_nexp{nexp = Nconst zero}; + TA_nexp{nexp = Nconst (big_int_of_int (String.length s))}; + TA_ord{order = Oinc};TA_typ{t = Tid"bit"}])},[],pure_e + | L_string s -> simp_exp e l {t = Tid "string"},[],pure_e + | L_undef -> simp_exp e l (new_t ()),[],{effect=Eset[BE_aux(BE_undef,l)]}) in + let t',cs',e' = type_coerce (Expr l) d_env false (get_e_typ e) e expect_t in + (e',t',t_env,cs@cs',effect) | E_cast(typ,e) -> let t = typ_to_t typ in let (e',u,t_env,cs,ef) = check_exp envs (new_t ()) e in - let t',cs2,e' = type_coerce (Expr l) d_env u e' t in - let t',cs3,e'' = type_coerce (Expr l) d_env t e' expect_t in + let t',cs2,e' = type_coerce (Expr l) d_env true u e' t in + let t',cs3,e'' = type_coerce (Expr l) d_env false t e' expect_t in (e'',t',t_env,cs@cs2@cs3,ef) | E_app(id,parms) -> let i = id_to_string id in @@ -450,15 +459,15 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp (match parms with | [] -> let (p',cs') = type_consistent (Expr l) d_env unit_t arg in - let (ret_t,cs_r,e') = type_coerce (Expr l) d_env ret (rebuild (Base(([],ret),tag,cs@cs',ef))) expect_t in + let (ret_t,cs_r,e') = type_coerce (Expr l) d_env false ret (rebuild (Base(([],ret),tag,cs@cs',ef))) expect_t in (e',ret_t,t_env,cs@cs'@cs_r,ef) | [parm] -> let (parm',arg_t,t_env,cs',ef_p) = check_exp envs arg parm in - let (ret_t,cs_r',e') = type_coerce (Expr l) d_env ret (E_aux(E_app(id,[parm']),(l,(Base(([],ret),tag,cs,ef'))))) expect_t in + let (ret_t,cs_r',e') = type_coerce (Expr l) d_env false ret (E_aux(E_app(id,[parm']),(l,(Base(([],ret),tag,cs,ef'))))) expect_t in (e',ret_t,t_env,cs@cs'@cs_r',union_effects ef_p ef') | parms -> let ((E_aux(E_tuple parms',tannot')),arg_t,t_env,cs',ef_p) = check_exp envs arg (E_aux(E_tuple parms,(l,NoTyp))) in - let (ret_t,cs_r',e') = type_coerce (Expr l) d_env ret (E_aux(E_app(id, parms'),(l,(Base(([],ret),tag,cs,ef'))))) expect_t in + let (ret_t,cs_r',e') = type_coerce (Expr l) d_env false ret (E_aux(E_app(id, parms'),(l,(Base(([],ret),tag,cs,ef'))))) expect_t in (e',ret_t,t_env,cs@cs'@cs_r',union_effects ef_p ef')) | _ -> 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),variants)) -> @@ -485,14 +494,14 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let args',arg_cs' = (match args with | [parm] -> - let _,cs,parm' = type_coerce (Expr l) d_env arg_t parm arg in + let _,cs,parm' = type_coerce (Expr l) d_env false arg_t parm arg in [parm'],cs | parms -> let (_,cs,(E_aux(E_tuple parms',tannot'))) = - type_coerce (Expr l) d_env arg_t (E_aux(E_tuple parms,(l,NoTyp))) arg in + type_coerce (Expr l) d_env false arg_t (E_aux(E_tuple parms,(l,NoTyp))) arg in parms',cs) in let (ret_t,cs_r,e') = - type_coerce (Expr l) d_env ret (E_aux(E_app(id,args'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in + type_coerce (Expr l) d_env false ret (E_aux(E_app(id,args'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in (e',ret_t,t_env,cs_p@arg_cs@arg_cs'@cs_r,union_effects ef_p (union_effects arg_ef ef')) | _ -> assert false)) | _ -> typ_error l ("Unbound function " ^ i)) @@ -508,7 +517,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp (match t.t with | Tfn(arg,ret,ef) -> let (E_aux(E_tuple [lft';rht'],tannot'),arg_t,t_env,cs',ef') = check_exp envs arg (E_aux(E_tuple [lft;rht],(l,NoTyp))) in - let ret_t,cs_r',e' = type_coerce (Expr l) d_env ret (E_aux(E_app_infix(lft',op,rht'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in + let ret_t,cs_r',e' = type_coerce (Expr l) d_env false ret (E_aux(E_app_infix(lft',op,rht'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in (e',ret_t,t_env,cs@cs'@cs_r',union_effects ef ef') | _ -> 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),variants)) -> @@ -519,18 +528,19 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let (E_aux(E_tuple [lft';rht'],tannot'),arg_t,t_env,cs',ef') = check_exp envs arg (E_aux(E_tuple [lft;rht],(l,NoTyp))) in (lft',rht',arg_t,cs',ef') | _ -> typ_error l ("Expected a function or constructor, found identifier " ^ i ^ " bound to type " ^ (t_to_string t))) in + (*let _ = Printf.printf "Looking for overloaded function %s, generic type is %s, arg_t is %s\n" i (t_to_string t_p) (t_to_string arg_t) in*) (match (select_overload_variant d_env variants arg_t) with | NoTyp -> typ_error l ("No matching function found with name " ^ i ^ " that expects parameters " ^ (t_to_string arg_t)) | Base((params,t),tag,cs,ef) -> - (*let _ = Printf.eprintf "Selected an overloaded function for %s, variant with function type %s\n" i (t_to_string t) in*) + (*let _ = Printf.eprintf "Selected an overloaded function for %s, variant with function type %s for actual type %s\n" i (t_to_string t) (t_to_string arg_t) in*) (match t.t with | Tfn(arg,ret,ef') -> (match arg.t,arg_t.t with | Ttup([tlft;trght]),Ttup([tlft_t;trght_t]) -> - let (_,cs_lft,lft') = type_coerce (Expr l) d_env tlft_t lft' tlft in - let (_,cs_rght,rht') = type_coerce (Expr l) d_env trght_t rht' trght in + let (_,cs_lft,lft') = type_coerce (Expr l) d_env false tlft_t lft' tlft in + let (_,cs_rght,rht') = type_coerce (Expr l) d_env false trght_t rht' trght in let (ret_t,cs_r,e') = - type_coerce (Expr l) d_env ret (E_aux(E_app_infix(lft',op,rht'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in + type_coerce (Expr l) d_env false ret (E_aux(E_app_infix(lft',op,rht'),(l,(Base(([],ret),tag,cs,ef))))) expect_t in (e',ret_t,t_env,cs_p@arg_cs@cs_lft@cs_rght@cs@cs_r,union_effects ef_p (union_effects arg_ef ef')) |_ -> assert false) | _ -> assert false)) @@ -556,17 +566,29 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let (e',t,_,c,ef) = check_exp envs (new_t ()) e in ((e'::exps),(t::typs),c@consts,union_effects ef effect)) exps ([],[],[],pure_e) in let t = { t=Ttup typs } in - let t',cs',e' = type_coerce (Expr l) d_env t (E_aux(E_tuple(exps),(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t (E_aux(E_tuple(exps),(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,consts@cs',effect)) | E_if(cond,then_,else_) -> let (cond',_,_,c1,ef1) = check_exp envs bool_t cond in - let then',then_t,then_env,then_c,then_ef = check_exp envs expect_t then_ in - let else',else_t,else_env,else_c,else_ef = check_exp envs expect_t else_ in - let t_cs = CondCons((Expr l),c1,then_c) in - let e_cs = CondCons((Expr l),[],else_c) in - (E_aux(E_if(cond',then',else'),(l,Base(([],expect_t),Emp_local,[],pure_e))), - expect_t,Envmap.intersect_merge (tannot_merge (Expr l) d_env) then_env else_env,[t_cs;e_cs], - union_effects ef1 (union_effects then_ef else_ef)) + (match expect_t.t with + | Tuvar _ -> + let then',then_t,then_env,then_c,then_ef = check_exp envs (new_t ()) then_ in + let else',else_t,else_env,else_c,else_ef = check_exp envs (new_t ()) else_ in + let then_t',then_c' = type_consistent (Expr l) d_env then_t expect_t in + let else_t',else_c' = type_consistent (Expr l) d_env else_t then_t' in + let t_cs = CondCons((Expr l),c1,then_c@then_c') in + let e_cs = CondCons((Expr l),[],else_c@else_c') in + (E_aux(E_if(cond',then',else'),(l,Base(([],expect_t),Emp_local,[],pure_e))), + expect_t,Envmap.intersect_merge (tannot_merge (Expr l) d_env) then_env else_env,[t_cs;e_cs], + union_effects ef1 (union_effects then_ef else_ef)) + | _ -> + let then',then_t,then_env,then_c,then_ef = check_exp envs expect_t then_ in + let else',else_t,else_env,else_c,else_ef = check_exp envs expect_t else_ in + let t_cs = CondCons((Expr l),c1,then_c) in + let e_cs = CondCons((Expr l),[],else_c) in + (E_aux(E_if(cond',then',else'),(l,Base(([],expect_t),Emp_local,[],pure_e))), + expect_t,Envmap.intersect_merge (tannot_merge (Expr l) d_env) then_env else_env,[t_cs;e_cs], + union_effects ef1 (union_effects then_ef else_ef))) | E_for(id,from,to_,step,order,block) -> let fb,fr,tb,tr,sb,sr = new_n(),new_n(),new_n(),new_n(),new_n(),new_n() in let ft,tt,st = {t=Tapp("range",[TA_nexp fb;TA_nexp fr])}, @@ -595,7 +617,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp (fun (e,_,_,c,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect) (List.map (check_exp envs item_t) es) ([],[],pure_e)) in let t = {t = Tapp("vector",[TA_nexp({nexp=Nconst zero});TA_nexp({nexp=Nconst (big_int_of_int (List.length es))});TA_ord({order=Oinc});TA_typ item_t])} in - let t',cs',e' = type_coerce (Expr l) d_env t (E_aux(E_vector es,(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t (E_aux(E_vector es,(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,cs@cs',effect) | E_vector_indexed(eis,default) -> let item_t = match expect_t.t with @@ -614,7 +636,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp eis) ([],[],pure_e,first)) in let t = {t = Tapp("vector",[TA_nexp({nexp=Nconst (big_int_of_int first)});TA_nexp({nexp=Nconst (big_int_of_int (List.length eis))}); TA_ord({order= if is_increasing then Oinc else Odec});TA_typ item_t])} in - let t',cs',e' = type_coerce (Expr l) d_env t (E_aux(E_vector_indexed(es,default),(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t (E_aux(E_vector_indexed(es,default),(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,cs@cs',effect) | E_vector_access(vec,i) -> let base,rise,ord = new_n(),new_n(),new_o() in @@ -636,7 +658,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp | _ -> typ_error l "A vector must be either increasing or decreasing to access a single element" in (*let _ = Printf.eprintf "Type checking vector access. item_t is %s and expect_t is %s\n" (t_to_string item_t) (t_to_string expect_t) in*) - let t',cs',e'=type_coerce (Expr l) d_env item_t (E_aux(E_vector_access(vec',i'),(l,Base(([],item_t),Emp_local,[],pure_e)))) expect_t in + let t',cs',e'=type_coerce (Expr l) d_env false item_t (E_aux(E_vector_access(vec',i'),(l,Base(([],item_t),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,cs_loc@cs_i@cs@cs',union_effects ef ef_i) | E_vector_subrange(vec,i1,i2) -> let base,rise,ord = new_n(),new_n(),new_o() in @@ -666,7 +688,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp | _ -> typ_error l "A vector must be either increasing or decreasing to access a slice" in let nt = {t=Tapp("vector",[TA_nexp base_n;TA_nexp rise_n; TA_ord ord;TA_typ item_t])} in let (t,cs3,e') = - type_coerce (Expr l) d_env nt (E_aux(E_vector_subrange(vec',i1',i2'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in + type_coerce (Expr l) d_env false nt (E_aux(E_vector_subrange(vec',i1',i2'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc,(union_effects ef (union_effects ef_i1 ef_i2))) | E_vector_update(vec,i,e) -> let base,rise,ord = new_n(),new_n(),new_o() in @@ -689,7 +711,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp in let nt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise; TA_ord ord;TA_typ item_t])} in let (t,cs3,e') = - type_coerce (Expr l) d_env nt (E_aux(E_vector_update(vec',i',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in + type_coerce (Expr l) d_env false nt (E_aux(E_vector_update(vec',i',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in (e',t,t_env,cs3@cs@cs_i@cs_e@cs_loc,(union_effects ef (union_effects ef_i ef_e))) | E_vector_update_subrange(vec,i1,i2,e) -> let base,rise,ord = new_n(),new_n(),new_o() in @@ -723,8 +745,24 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp | _ -> typ_error l "A vector must be either increasing or decreasing to modify a slice" in let nt = {t=Tapp("vector",[TA_nexp base;TA_nexp rise; TA_ord ord;TA_typ item_t])} in let (t,cs3,e') = - type_coerce (Expr l) d_env nt (E_aux(E_vector_update_subrange(vec',i1',i2',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in + type_coerce (Expr l) d_env false nt (E_aux(E_vector_update_subrange(vec',i1',i2',e'),(l,Base(([],nt),Emp_local,cs_loc,pure_e)))) expect_t in (e',t,t_env,cs3@cs@cs_i1@cs_i2@cs_loc@cs_e,(union_effects ef (union_effects ef_i1 (union_effects ef_i2 ef_e)))) + | E_vector_append(v1,v2) -> + let item_t,ord = match expect_t.t with + | Tapp("vector",[_;_;TA_ord o;TA_typ i]) -> i,o + | Tapp("range",_) -> bit_t,new_o () + | _ -> new_t (),new_o () in + let base1,rise1 = new_n(), new_n() in + let base2,rise2 = new_n(),new_n() in + let (v1',t1',_,cs_1,ef_1) = check_exp envs {t=Tapp("vector",[TA_nexp base1;TA_nexp rise1;TA_ord ord;TA_typ item_t])} v1 in + let (v2',t2',_,cs_2,ef_2) = check_exp envs {t=Tapp("vector",[TA_nexp base2;TA_nexp rise2;TA_ord ord;TA_typ item_t])} v2 in + let ti = {t=Tapp("vector",[TA_nexp base1;TA_nexp {nexp = Nadd(rise1,rise2)};TA_ord ord; TA_typ item_t])} in + let cs_loc = match ord.order with + | Odec -> [GtEq((Expr l),base1,{nexp = Nadd(rise1,rise2)})] + | _ -> [] in + let (t,cs_c,e') = + type_coerce (Expr l) d_env false ti (E_aux(E_vector_append(v1',v2'),(l,Base(([],ti),Emp_local,cs_loc,pure_e)))) expect_t in + (e',t,t_env,cs_loc@cs_1@cs_2,(union_effects ef_1 ef_2)) | E_list(es) -> let item_t = match expect_t.t with | Tapp("list",[TA_typ i]) -> i @@ -733,7 +771,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp (List.fold_right (fun (e,_,_,c,ef) (es,cs,effect) -> (e::es),(c@cs),union_effects ef effect) (List.map (check_exp envs item_t) es) ([],[],pure_e)) in let t = {t = Tapp("list",[TA_typ item_t])} in - let t',cs',e' = type_coerce (Expr l) d_env t (E_aux(E_list es,(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in + let t',cs',e' = type_coerce (Expr l) d_env false t (E_aux(E_list es,(l,Base(([],t),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,cs@cs',effect) | E_cons(ls,i) -> let item_t = match expect_t.t with @@ -742,7 +780,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let lt = {t=Tapp("list",[TA_typ item_t])} in let (ls',t',_,cs,ef) = check_exp envs lt ls in let (i', ti, _,cs_i,ef_i) = check_exp envs item_t i in - let (t',cs',e') = type_coerce (Expr l) d_env lt (E_aux(E_cons(ls',i'),(l,Base(([],lt),Emp_local,[],pure_e)))) expect_t in + let (t',cs',e') = type_coerce (Expr l) d_env false lt (E_aux(E_cons(ls',i'),(l,Base(([],lt),Emp_local,[],pure_e)))) expect_t in (e',t',t_env,cs@cs'@cs_i,(union_effects ef ef_i)) | E_record(FES_aux(FES_Fexps(fexps,_),l')) -> let u,_ = get_abbrev d_env expect_t in @@ -848,7 +886,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp typ_error l ("Type " ^ i ^ " does not have a field " ^ fi) | Base((params,et),tag,cs,ef) -> let et,cs,ef = subst params et cs ef in - let (et',c',acc) = type_coerce (Expr l) d_env et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in + let (et',c',acc) = type_coerce (Expr l) d_env false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in (acc,et',t_env,cs@c',ef))) | Tid i -> (match lookup_record_typ i d_env.rec_env with @@ -860,7 +898,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp typ_error l ("Type " ^ i ^ " does not have a field " ^ fi) | Base((params,et),tag,cs,ef) -> let et,cs,ef = subst params et cs ef in - let (et',c',acc) = type_coerce (Expr l) d_env et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in + let (et',c',acc) = type_coerce (Expr l) d_env false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in (acc,et',t_env,cs@c',ef))) | Tuvar _ -> let fi = id_to_string id in @@ -873,7 +911,7 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp raise (Reporting_basic.err_unreachable l "lookup_possible_records returned a record that didn't include the field") | Base((params,et),tag,cs,ef) -> let et,cs,ef = subst params et cs ef in - let (et',c',acc) = type_coerce (Expr l) d_env et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in + let (et',c',acc) = type_coerce (Expr l) d_env false et (E_aux(E_field(e',id),(l,Base(([],et),tag,cs,ef)))) expect_t in (*TODO tHIS should be equate_t*) t'.t <- Tid i; (acc,et',t_env,cs@c',ef)) diff --git a/src/type_internal.ml b/src/type_internal.ml index c9a702e3..0c3efcab 100644 --- a/src/type_internal.ml +++ b/src/type_internal.ml @@ -759,15 +759,24 @@ let initial_typ_env = Base(((mk_nat_params ["n";"m";"o";"p"])@(mk_ord_params ["ord"]), (mk_pure_fun (mk_tup [mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m"); mk_range (mk_nv "o") (mk_nv "p")]) - (mk_range (mk_nv "o") (mk_add (mk_nv "p") {nexp = N2n (mk_nv "m",None)})))), + (mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")))), External (Some "add_vec_range"), [LtEq(Specc(Parse_ast.Int("+",None)),mk_add (mk_nv "o") (mk_nv "p"),{nexp=N2n (mk_nv "m",None)})],pure_e); Base(((mk_nat_params ["n";"m";"o";"p"])@(mk_ord_params ["ord"]), (mk_pure_fun (mk_tup [mk_range (mk_nv "o") (mk_nv "p"); mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m");]) - (mk_range (mk_nv "o") {nexp = N2n (mk_nv "m",None)}))), + (mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")))), External (Some "add_range_vec"), - [],pure_e); ])); + [LtEq(Specc(Parse_ast.Int("+",None)),mk_add (mk_nv "o") (mk_nv "p"),{nexp = N2n (mk_nv "m",None)})],pure_e); + Base(((mk_nat_params ["o";"p"]@(mk_ord_params["ord"])), + (mk_pure_fun (mk_tup [mk_vector bit_t (Ovar "ord") (Nvar "o") (Nvar "p"); bit_t]) + (mk_vector bit_t (Ovar "ord") (Nvar "o") (Nvar "p")))), + External (Some "add_vec_bit"), [], pure_e); + Base(((mk_nat_params ["o";"p"]@(mk_ord_params["ord"])), + (mk_pure_fun (mk_tup [bit_t; mk_vector bit_t (Ovar "ord") (Nvar "o") (Nvar "p")]) + (mk_vector bit_t (Ovar "ord") (Nvar "o") (Nvar "p")))), + External (Some "add_bit_vec"), [], pure_e); + ])); ("*",Base(((mk_nat_params ["n";"m";"o";"p"]), (mk_pure_fun (mk_tup [mk_range (mk_nv "n") (mk_nv "m"); mk_range (mk_nv "o") (mk_nv "p")]) (mk_range (mk_mult (mk_nv "n") (mk_nv "o")) (mk_mult (mk_nv "m") (mk_nv "p"))))), @@ -788,15 +797,15 @@ let initial_typ_env = Base(((mk_nat_params ["n";"m";"o";"p"])@(mk_ord_params ["ord"]), (mk_pure_fun (mk_tup [mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m"); mk_range (mk_nv "o") (mk_nv "p")]) - (mk_range (mk_nv "o") (mk_add (mk_nv "p") {nexp = N2n (mk_nv "m",None)})))), + (mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")))), External (Some "minus_vec_range"), [LtEq(Specc(Parse_ast.Int("-",None)),mk_add (mk_nv "o") (mk_nv "p"),{nexp=N2n (mk_nv "m",None)})],pure_e); Base(((mk_nat_params ["n";"m";"o";"p"])@(mk_ord_params ["ord"]), (mk_pure_fun (mk_tup [mk_range (mk_nv "o") (mk_nv "p"); mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m");]) - (mk_range (mk_nv "o") {nexp = N2n (mk_nv "m",None)}))), + (mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")))), External (Some "minus_range_vec"), - [],pure_e); ])); + [LtEq(Specc(Parse_ast.Int("-",None)),mk_add (mk_nv "o") (mk_nv "p"),{nexp=N2n (mk_nv "m",None)})],pure_e); ])); ("mod", Overload(Base(((mk_typ_params ["a";"b";"c"]), (mk_pure_fun (mk_tup [{t=Tvar "a"};{t=Tvar "b"}]) {t=Tvar "c"})), @@ -826,18 +835,13 @@ let initial_typ_env = mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")]) (mk_vector bit_t (Ovar "ord") (Nvar "n") (Nvar "m")))), External (Some "quot_vec"),[],pure_e)])); - (":",Base(((mk_nat_params["n";"m";"o";"p"]@(mk_ord_params["ord"])@(mk_typ_params ["a"])), - (mk_pure_fun (mk_tup [mk_vector {t=Tvar "a"} (Ovar "ord") (Nvar "n") (Nvar "m"); - mk_vector {t=Tvar "a"} (Ovar "ord") (Nvar "o") (Nvar "p")]) - (mk_vector {t=Tvar "a"} (Ovar "ord") (Nvar "n") (Nadd((mk_nv "m"), (mk_nv "p")))))), - External (Some "vec_concat"),[(*TODO:: This is incorrect when ord is dec, as then n >= m+p is needed *)],pure_e)); (* incorrect types, not pressing as the type checker puts in the correct types automatically on a first pass *) ("to_num_inc",Base(([("a",{k=K_Typ})],{t= Tfn ({t=Tvar "a"},nat_typ,pure_e)}),External None,[],pure_e)); ("to_num_dec",Base(([("a",{k=K_Typ})],{t= Tfn ({t=Tvar "a"},nat_typ,pure_e)}),External None,[],pure_e)); ("to_vec_inc",Base(([("a",{k=K_Typ})],{t= Tfn (nat_typ,{t=Tvar "a"},pure_e)}),External None,[],pure_e)); ("to_vec_dec",Base(([("a",{k=K_Typ})],{t= Tfn (nat_typ,{t=Tvar "a"},pure_e)}),External None,[],pure_e)); ("==", - Overload( Base((["a",{k=K_Typ}],{t= Tfn ({t=Ttup([{t=Tvar "a"};{t=Tvar "a"}])},bit_t,pure_e)}),External (Some "eq"),[],pure_e), + Overload( Base((mk_typ_params ["a";"b"],(mk_pure_fun (mk_tup [{t=Tvar "a"};{t=Tvar "b"}]) bit_t)),External (Some "eq"),[],pure_e), [Base(([("n",{k=K_Nat});("m",{k=K_Nat});("o",{k=K_Nat});("p",{k=K_Nat})], {t = Tfn({t=Ttup([mk_range (mk_nv "n") (mk_nv "m");mk_range (mk_nv "o") (mk_nv "p")])},bit_t,pure_e)}), External (Some "eq"), [Eq(Specc(Parse_ast.Int("==",None)), @@ -1211,23 +1215,23 @@ and type_arg_eq co d_env ta1 ta2 = and type_consistent co d_env t1 t2 = type_consistent_internal co d_env t1 [] t2 [] -let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = +let rec type_coerce_internal co d_env is_explicit t1 cs1 e t2 cs2 = let l = get_c_loc co in let t1,cs1' = get_abbrev d_env t1 in let t2,cs2' = get_abbrev d_env t2 in let cs1,cs2 = cs1@cs1',cs2@cs2' in let csp = cs1@cs2 in match t1.t,t2.t with - | Tabbrev(_,t1),Tabbrev(_,t2) -> type_coerce_internal co d_env t1 cs1 e t2 cs2 - | Tabbrev(_,t1),_ -> type_coerce_internal co d_env t1 cs1 e t2 cs2 - | _,Tabbrev(_,t2) -> type_coerce_internal co d_env t1 cs1 e t2 cs2 + | Tabbrev(_,t1),Tabbrev(_,t2) -> type_coerce_internal co d_env is_explicit t1 cs1 e t2 cs2 + | Tabbrev(_,t1),_ -> type_coerce_internal co d_env is_explicit t1 cs1 e t2 cs2 + | _,Tabbrev(_,t2) -> type_coerce_internal co d_env is_explicit t1 cs1 e t2 cs2 | Ttup t1s, Ttup t2s -> let tl1,tl2 = List.length t1s,List.length t2s in if tl1=tl2 then let ids = List.map (fun _ -> Id_aux(Id (new_id ()),l)) t1s in let vars = List.map2 (fun i t -> E_aux(E_id(i),(l,Base(([],t),Emp_local,[],pure_e)))) ids t1s in let (coerced_ts,cs,coerced_vars) = - List.fold_right2 (fun v (t1,t2) (ts,cs,es) -> let (t',c',e') = type_coerce co d_env t1 v t2 in + List.fold_right2 (fun v (t1,t2) (ts,cs,es) -> let (t',c',e') = type_coerce co d_env is_explicit t1 v t2 in ((t'::ts),c'@cs,(e'::es))) vars (List.combine t1s t2s) ([],[],[]) in if vars = coerced_vars then (t2,cs,e) @@ -1242,8 +1246,8 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = | Tapp(id1,args1),Tapp(id2,args2) -> if id1=id2 && (id1 <> "vector") then let t',cs' = type_consistent co d_env t1 t2 in (t',cs',e) - else (match id1,id2 with - | "vector","vector" -> + else (match id1,id2,is_explicit with + | "vector","vector",_ -> (match args1,args2 with | [TA_nexp b1;TA_nexp r1;TA_ord o1;TA_typ t1i], [TA_nexp b2;TA_nexp r2;TA_ord o2;TA_typ t2i] -> @@ -1258,7 +1262,7 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = let e' = E_aux(E_internal_cast ((l,(Base(([],t2),Emp_local,[],pure_e))),e),(l,tannot)) in (t2,cs@cs',e') | _ -> raise (Reporting_basic.err_unreachable l "vector is not properly kinded")) - | "vector","range" -> + | "vector","range",_ -> (match args1,args2 with | [TA_nexp b1;TA_nexp r1;TA_ord {order = Oinc};TA_typ {t=Tid "bit"}], [TA_nexp b2;TA_nexp r2;] -> @@ -1273,7 +1277,7 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = | [TA_nexp b1;TA_nexp r1;TA_ord o;TA_typ t],_ -> eq_error l "Cannot convert non-bit vector into an range" | _,_ -> raise (Reporting_basic.err_unreachable l "vector or range is not properly kinded")) - | "range","vector" -> + | "range","vector",true -> (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;] -> @@ -1288,17 +1292,17 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = | [TA_nexp b1;TA_nexp r1;TA_ord o;TA_typ t],_ -> eq_error l "Cannot convert an range into a non-bit vector" | _,_ -> raise (Reporting_basic.err_unreachable l "vector or range is not properly kinded")) - | "register",_ -> + | "register",_,_ -> (match args1 with | [TA_typ t] -> (*TODO Should this be an internal cast? Probably, make sure it doesn't interfere with the other internal cast and get removed *) (*let _ = Printf.printf "Adding cast to remove register read\n" in*) let new_e = E_aux(E_cast(t_to_typ unit_t,e),(l,Base(([],t),External None,[],(add_effect (BE_aux(BE_rreg, l)) pure_e)))) in - type_coerce co d_env t new_e t2 + type_coerce co d_env is_explicit t new_e t2 | _ -> raise (Reporting_basic.err_unreachable l "register is not properly kinded")) - | _,_ -> + | _,_,_ -> let t',cs' = type_consistent co d_env t1 t2 in (t',cs',e)) - | Tid("bit"),Tapp("vector",[TA_nexp {nexp=Nconst i};TA_nexp r1;TA_ord o;TA_typ {t=Tid "bit"}]) -> + (*| Tid("bit"),Tapp("vector",[TA_nexp {nexp=Nconst i};TA_nexp r1;TA_ord o;TA_typ {t=Tid "bit"}]) -> let cs = [Eq(co,r1,{nexp = Nconst one})] in (*WARNING: shrinking i to an int; should add a check*) let t2' = {t = Tapp("vector",[TA_nexp {nexp=Nconst i};TA_nexp {nexp=Nconst one};TA_ord o;TA_typ {t=Tid "bit"}])} in @@ -1307,7 +1311,7 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = let cs = [Eq(co,r1,{nexp = Nconst one})] in (t2,cs,E_aux((E_vector_access (e,(E_aux(E_lit(L_aux(L_num (int_of_big_int i),l)), (l,Base(([],{t=Tapp("range",[TA_nexp b1;TA_nexp {nexp=Nconst zero}])}),Emp_local,cs,pure_e)))))), - (l,Base(([],t2),Emp_local,cs,pure_e)))) + (l,Base(([],t2),Emp_local,cs,pure_e))))*) | Tid("bit"),Tapp("range",[TA_nexp b1;TA_nexp r1]) -> let t',cs'= type_consistent co d_env {t=Tapp("range",[TA_nexp{nexp=Nconst zero};TA_nexp{nexp=Nconst one}])} t2 in (t2,cs',E_aux(E_case (e,[Pat_aux(Pat_exp(P_aux(P_lit(L_aux(L_zero,l)),(l,Base(([],t1),Emp_local,[],pure_e))), @@ -1352,7 +1356,7 @@ let rec type_coerce_internal co d_env t1 cs1 e t2 cs2 = | None -> eq_error l ("Type mismatch: " ^ (t_to_string t1) ^ " , " ^ (t_to_string t2))) | _,_ -> let t',cs = type_consistent co d_env t1 t2 in (t',cs,e) -and type_coerce co d_env t1 e t2 = type_coerce_internal co d_env t1 [] e t2 [];; +and type_coerce co d_env is_explicit t1 e t2 = type_coerce_internal co d_env is_explicit t1 [] e t2 [];; let rec conforms_to_t spec actual = (*let _ = Printf.printf "conforms_to_t called with %s, %s\n" (t_to_string spec) (t_to_string actual) in*) diff --git a/src/type_internal.mli b/src/type_internal.mli index 30c0db15..2aff6db3 100644 --- a/src/type_internal.mli +++ b/src/type_internal.mli @@ -161,8 +161,9 @@ val nexp_eq : nexp -> nexp -> bool *) val type_consistent : constraint_origin -> def_envs -> t -> t -> t * nexp_range list -(* type_eq mutates to unify variables, and will raise an exception if the first type cannot be coerced into the second and is inconsistent *) -val type_coerce : constraint_origin -> def_envs -> t -> exp -> t -> t * nexp_range list * exp +(* type_eq mutates to unify variables, and will raise an exception if the first type cannot be coerced into the second and is inconsistent, + bool specifices whether this has arisen from an implicit or explicit type coercion request *) +val type_coerce : constraint_origin -> def_envs -> bool -> t -> exp -> t -> t * nexp_range list * exp (* Merge tannots when intersection or unioning two environments. In case of default types, defer to tannot on right *) val tannot_merge : constraint_origin -> def_envs -> tannot -> tannot -> tannot |
