diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/initial_check.ml | 29 | ||||
| -rw-r--r-- | src/lem_interp/interp.lem | 79 | ||||
| -rw-r--r-- | src/lexer.mll | 2 | ||||
| -rw-r--r-- | src/parser.mly | 17 | ||||
| -rw-r--r-- | src/pretty_print.ml | 42 | ||||
| -rw-r--r-- | src/process_file.ml | 2 | ||||
| -rw-r--r-- | src/test/regbits.sail | 7 | ||||
| -rw-r--r-- | src/type_check.ml | 91 | ||||
| -rw-r--r-- | src/type_internal.ml | 6 | ||||
| -rw-r--r-- | src/type_internal.mli | 4 |
10 files changed, 254 insertions, 25 deletions
diff --git a/src/initial_check.ml b/src/initial_check.ml index b95bf279..d14fdc59 100644 --- a/src/initial_check.ml +++ b/src/initial_check.ml @@ -384,6 +384,7 @@ and to_ast_exp (k_env : kind Envmap.t) (Parse_ast.E_aux(exp,l) : Parse_ast.exp) | Parse_ast.E_case(exp,pexps) -> E_case(to_ast_exp k_env exp, List.map (to_ast_case k_env) pexps) | Parse_ast.E_let(leb,exp) -> E_let(to_ast_letbind k_env leb, to_ast_exp k_env exp) | Parse_ast.E_assign(lexp,exp) -> E_assign(to_ast_lexp k_env lexp, to_ast_exp k_env exp) + | Parse_ast.E_exit exp -> E_exit(to_ast_exp k_env exp) ), (l,NoTyp)) and to_ast_lexp (k_env : kind Envmap.t) (Parse_ast.E_aux(exp,l) : Parse_ast.exp) : tannot lexp = @@ -609,10 +610,30 @@ let rec def_in_progress (id : id) (partial_defs : (id * partial_def) list) : par | Id_aux(Id(n),_), Id_aux(Id(i),_) -> if (n = i) then Some(pd) else def_in_progress id defs | _,_ -> def_in_progress id defs) -let to_ast_dec (names,k_env,t_env) (Parse_ast.DEC_aux(Parse_ast.DEC_reg(typ,id),l)) = - let t = to_ast_typ k_env typ in - let id = to_ast_id id in - (DEC_aux(DEC_reg(t,id),(l,NoTyp))) +let to_ast_alias_spec k_env (Parse_ast.E_aux(e,le)) = + AL_aux( + (match e with + | Parse_ast.E_field(Parse_ast.E_aux(Parse_ast.E_id id,li), field) -> + AL_subreg(to_ast_id id,to_ast_id field) + | Parse_ast.E_vector_access(Parse_ast.E_aux(Parse_ast.E_id id,li),range) -> + AL_bit(to_ast_id id,to_ast_exp k_env range) + | Parse_ast.E_vector_subrange(Parse_ast.E_aux(Parse_ast.E_id id,li),base,stop) -> + AL_slice(to_ast_id id,to_ast_exp k_env base,to_ast_exp k_env stop) + | Parse_ast.E_vector_append(Parse_ast.E_aux(Parse_ast.E_id first,lf), + Parse_ast.E_aux(Parse_ast.E_id second,ls)) -> + AL_concat(to_ast_id first,to_ast_id second) + ), (le,NoTyp)) + +let to_ast_dec (names,k_env,t_env) (Parse_ast.DEC_aux(regdec,l)) = + DEC_aux( + (match regdec with + | Parse_ast.DEC_reg(typ,id) -> + DEC_reg(to_ast_typ k_env typ,to_ast_id id) + | Parse_ast.DEC_alias(id,e) -> + DEC_alias(to_ast_id id,to_ast_alias_spec k_env e) + | Parse_ast.DEC_typ_alias(typ,id,e) -> + DEC_typ_alias(to_ast_typ k_env typ,to_ast_id id,to_ast_alias_spec k_env e) + ),(l,NoTyp)) let to_ast_def (names, k_env, t_env) partial_defs def : def_progress envs_out * (id * partial_def) list = let envs = (names,k_env,t_env) in diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem index d4fcafb7..4a429423 100644 --- a/src/lem_interp/interp.lem +++ b/src/lem_interp/interp.lem @@ -116,7 +116,7 @@ type barrier_kind = | Barrier_plain (* ?? *) (*top_level is a tuple of (all definitions, letbound and enum values, register values, Typedef union constructors, and sub register mappings) *) -type top_level = Env of (defs tannot) * env * env * list (id * typ) * list (id * list (id * index_range)) +type top_level = Env of (defs tannot) * env * env * list (id * typ) * list (id * list (id * index_range)) * list (id * (alias_spec tannot)) type action = | Read_reg of reg_form * maybe (integer * integer) @@ -126,6 +126,7 @@ type action = | Barrier of id * value | Write_next_IA of value (* Perhaps not needed? *) | Nondet of list (exp tannot) + | Exit of (exp tannot) | Debug of l | Call_extern of string * value @@ -173,7 +174,19 @@ let rec to_registers (Defs defs) = | DEF_reg_dec (DEC_aux (DEC_reg typ id) (l,tannot)) -> (id, V_register(Reg id tannot)) :: (to_registers (Defs defs)) | _ -> to_registers (Defs defs) end - end + end + +val to_aliases : defs tannot -> list (id * (alias_spec tannot)) +let rec to_aliases (Defs defs) = + match defs with + | [] -> [] + | def::defs -> + match def with + | DEF_reg_dec (DEC_aux (DEC_alias id aspec) _) -> (id, aspec) :: (to_aliases (Defs defs)) + | DEF_reg_dec (DEC_aux (DEC_typ_alias typ id aspec) _) -> (id, aspec) :: (to_aliases (Defs defs)) + | _ -> to_aliases (Defs defs) + end + end val has_rmem_effect : list base_effect -> bool val has_barr_effect : list base_effect -> bool @@ -874,6 +887,7 @@ let rec find_case pexps value = val interp_main : interp_mode -> top_level -> env -> lmem -> (exp tannot) -> (outcome * lmem * env) val exp_list : interp_mode -> top_level -> (list (exp tannot) -> (exp tannot)) -> (list value -> value) -> env -> lmem -> list value -> list (exp tannot) -> (outcome * lmem * env) val interp_lbind : interp_mode -> top_level -> env -> lmem -> (letbind tannot) -> ((outcome * lmem * env) * (maybe ((exp tannot) -> (letbind tannot)))) +val interp_alias_read : interp_mode -> top_level -> env -> lmem -> (alias_spec tannot) -> (outcome * lmem * env) let resolve_outcome to_match value_thunk action_thunk = match to_match with @@ -897,7 +911,7 @@ let rec exp_list mode t_level build_e build_v l_env l_mem vals exps = end and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = - let (Env defs lets regs ctors subregs) = t_level in + let (Env defs lets regs ctors subregs aliases) = t_level in let (typ,tag,ncs,effect) = match annot with | Nothing -> (T_var "fresh_v", Tag_empty, [], (Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef) -> (t,tag,ncs,ef) end in @@ -962,6 +976,10 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (Hole_frame (Id_aux (Id "0") Unknown) (E_aux (E_id (Id_aux (Id "0") l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env) + | Tag_alias -> + match in_env aliases id with + | Just aspec -> interp_alias_read mode t_level l_env l_mem aspec + | _ -> (Error l ("Internal error: alias not found"), l_mem,l_env) end | _ -> (Error l (String.stringAppend "Internal error: tag other than empty,enum,or extern " name),l_mem,l_env) end | E_if cond thn els -> @@ -1500,7 +1518,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = end and create_write_message_or_update mode t_level value l_env l_mem is_top_level ((LEXP_aux lexp (l,annot)):lexp tannot) = - let (Env defs lets regs ctors subregs) = t_level in + let (Env defs lets regs ctors subregs aliases) = t_level in let (typ,tag,ncs,ef) = match annot with | Nothing -> (T_var "fresh_v", Tag_empty, [], (Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef) -> (t,tag,ncs,ef) end in @@ -1729,15 +1747,60 @@ and interp_letbind mode t_level l_env l_mem (LB_aux lbind (l,annot)) = | e -> (e,Nothing) end end +and interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = + let (Env defs lets regs ctors subregs aliases) = t_level in + let stack = Hole_frame (Id_aux (Id "0") Unknown) + (E_aux (E_id (Id_aux (Id "0") l)) (l,(intern_annot annot))) + t_level l_env l_mem Top in + match alspec with + | AL_subreg reg subreg -> + (match in_env regs reg with + | Just (V_register (Reg _ (Just((T_id id),_,_,_)))) -> + (match in_env subregs (Id_aux (Id id) Unknown) with + | Just indexes -> + (match in_env indexes subreg with + | Just ir -> (Action (Read_reg (SubReg subreg (Reg reg annot) ir) Nothing) stack, l_mem, l_env) + | _ -> (Error l "Internal error, alias spec has unknown field", l_mem, l_env) end) + | _ -> (Error l (String.stringAppend "Internal error: alias spec has unknown register type " id), l_mem, l_env) end) + | Just (V_register ((Reg _ (Just((T_abbrev (T_id id) _),_,_,_))) as rf)) -> + (match in_env subregs (Id_aux (Id id) Unknown) with + | Just indexes -> + (match in_env indexes subreg with + | Just ir -> (Action (Read_reg (SubReg subreg rf ir) Nothing) stack, l_mem, l_env) + | _ -> (Error l "Internal error, alias spec has unknown field", l_mem, l_env) end) + | _ -> (Error l (String.stringAppend "Internal error: alias spec has unknown register type " id), l_mem, l_env) end) + | _ -> (Error l (String.stringAppend "Internal error: alias spec has unknown register " (get_id reg)),l_mem,l_env) end) + | AL_bit reg e -> + resolve_outcome (interp_main mode t_level l_env l_mem e) + (fun v le lm -> match v with + | V_lit (L_aux (L_num i) _) -> + (Action (Read_reg (Reg reg annot) (Just (i,i))) stack, l_mem, l_env) end) + (fun a -> a) + | AL_slice reg start stop -> + resolve_outcome (interp_main mode t_level l_env l_mem start) + (fun v lm le -> + match v with + | V_lit (L_aux (L_num start) _) -> + (resolve_outcome (interp_main mode t_level l_env lm stop) + (fun v le lm -> + (match v with + | V_lit (L_aux (L_num stop) _) -> + (Action (Read_reg (Reg reg annot) (Just (start,stop))) stack, + l_mem, l_env) end)) + (fun a -> a)) end) + (fun a -> a) + | AL_concat reg1 reg2 -> (Error l "Unimplemented yet, alias spec concat", l_mem, l_env) +end + let rec to_global_letbinds (Defs defs) t_level = - let (Env defs' lets regs ctors subregs) = t_level in + let (Env defs' lets regs ctors subregs aliases) = t_level in match defs with | [] -> ((Value (V_lit (L_aux L_unit Unknown)) Tag_empty, emem, []),t_level) | def::defs -> match def with | DEF_val lbind -> match interp_letbind <|eager_eval=true|> t_level [] emem lbind with - | ((Value v tag,lm,le),_) -> to_global_letbinds (Defs defs) (Env defs' (lets++le) regs ctors subregs) + | ((Value v tag,lm,le),_) -> to_global_letbinds (Defs defs) (Env defs' (lets++le) regs ctors subregs aliases) | ((Action a s,lm,le),_) -> ((Error Unknown "Top level let may not access memory, registers or (for now) external functions", lm,le),t_level) | (e,_) -> (e,t_level) end @@ -1745,14 +1808,14 @@ let rec to_global_letbinds (Defs defs) t_level = match tdef with | TD_enum id ns ids _ -> let enum_vals = map (fun eid -> (eid,V_ctor eid (T_id (get_id id)) unitv)) ids in - to_global_letbinds (Defs defs) (Env defs' (lets++enum_vals) regs ctors subregs) + to_global_letbinds (Defs defs) (Env defs' (lets++enum_vals) regs ctors subregs aliases) | _ -> to_global_letbinds (Defs defs) t_level end | _ -> to_global_letbinds (Defs defs) t_level end end let to_top_env defs = - let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) (to_register_fields defs) in + let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) (to_register_fields defs) (to_aliases defs) in let (o,t_level) = to_global_letbinds defs t_level in match o with | (Value _ _,_,_) -> (Nothing,t_level) diff --git a/src/lexer.mll b/src/lexer.mll index b53577c5..f7cd1272 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -59,6 +59,7 @@ let kw_table = M.empty [ ("and", (fun _ -> And)); + ("alias", (fun _ -> Alias)); ("as", (fun _ -> As)); ("bitzero", (fun _ -> Bitzero)); ("bitone", (fun _ -> Bitone)); @@ -75,6 +76,7 @@ let kw_table = ("end", (fun _ -> End)); ("enumerate", (fun _ -> Enumerate)); ("else", (fun _ -> Else)); + ("exit", (fun _ -> Exit)); ("extern", (fun _ -> Extern)); ("false", (fun _ -> False)); ("forall", (fun _ -> Forall)); diff --git a/src/parser.mly b/src/parser.mly index aa6c853d..b36085a5 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -122,10 +122,12 @@ let make_vector_sugar typ typ1 = /*Terminals with no content*/ -%token And As Bitzero Bitone Bits By Case Clause Const Dec Default Deinfix Effect EFFECT End Enumerate Else Extern -%token False Forall Foreach Function_ If_ In IN Inc Let_ Member Nat Order Pure Rec Register +%token And Alias As Bitzero Bitone Bits By Case Clause Const Dec Default Deinfix Effect EFFECT End +%token Enumerate Else Exit Extern False Forall Foreach Function_ If_ In IN Inc Let_ Member Nat Order +%token Pure Rec Register Scattered Struct Switch Then True TwoStarStar Type TYPE Typedef +%token Undefined Union With Val %token Barr Rreg Wreg Rmem Wmem Undef Unspec Nondet -%token Scattered Struct Switch Then True TwoStarStar Type TYPE Typedef Undefined Union With Val + /* Avoid shift/reduce conflict - see right_atomic_exp rule */ %nonassoc Then @@ -541,9 +543,6 @@ atomic_exp: { eloc (E_cast($2,$4)) } | Lparen comma_exps Rparen { eloc (E_tuple($2)) } - /* XXX creates many conflicts - | Lcurly semi_exps Rcurly - { eloc (E_record($2)) } */ | Lcurly exp With semi_exps Rcurly { eloc (E_record_update($2,$4)) } | Lsquare Rsquare @@ -562,6 +561,8 @@ atomic_exp: { eloc (E_list($2)) } | Switch exp Lcurly case_exps Rcurly { eloc (E_case($2,$4)) } + | Exit atomic_exp + { eloc (E_exit $2) } field_exp: | atomic_exp @@ -1171,6 +1172,10 @@ def: { dloc (DEF_default($1)) } | Register atomic_typ id { dloc (DEF_reg_dec(DEC_aux(DEC_reg($2,$3),loc ()))) } + | Register Alias id Eq exp + { dloc (DEF_reg_dec(DEC_aux(DEC_alias($3,$5),loc ()))) } + | Register Alias atomic_typ id Eq exp + { dloc (DEF_reg_dec(DEC_aux(DEC_typ_alias($3,$4,$6), loc ()))) } | Scattered scattered_def { dloc (DEF_scattered $2) } | Function_ Clause funcl diff --git a/src/pretty_print.ml b/src/pretty_print.ml index 2a24dc3e..a537ff46 100644 --- a/src/pretty_print.ml +++ b/src/pretty_print.ml @@ -253,6 +253,7 @@ let pp_format_tag = function | Default -> "Tag_default" | Constructor -> "Tag_ctor" | Enum -> "Tag_enum" + | Alias -> "Tag_alias" | Spec -> "Tag_spec" let rec pp_format_nes nes = @@ -374,6 +375,7 @@ and pp_lem_exp ppf (E_aux(e,(l,annot))) = fprintf ppf "@[<0>(E_aux (%a %a [%a]) (%a, %a))@]" kwd "E_case" pp_lem_exp exp (list_pp pp_semi_lem_case pp_lem_case) pexps pp_lem_l l pp_annot annot | E_let(leb,exp) -> fprintf ppf "@[<0>(E_aux (%a %a %a) (%a, %a))@]" kwd "E_let" pp_lem_let leb pp_lem_exp exp pp_lem_l l pp_annot annot | E_assign(lexp,exp) -> fprintf ppf "@[<0>(E_aux (%a %a %a) (%a, %a))@]" kwd "E_assign" pp_lem_lexp lexp pp_lem_exp exp pp_lem_l l pp_annot annot + | E_exit exp -> fprintf ppf "@[<0>(E_aux (E_exit %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot | E_internal_exp (l, Base((_,t),_,_,_)) -> (match t.t with | Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) -> @@ -493,8 +495,25 @@ let pp_lem_fundef ppf (FD_aux(FD_function(r, typa, efa, fcls),(l,annot))) = kwd "FD_function" pp_lem_rec r pp_lem_tannot_opt typa pp_lem_effects_opt efa (list_pp pp_funcls pp_funcls) fcls pp_lem_l l pp_annot annot -let pp_lem_dec ppf (DEC_aux(DEC_reg(typ,id),(l,annot))) = - fprintf ppf "@[<0>(DEC_aux (DEC_reg %a %a) (%a,%a))@]" pp_lem_typ typ pp_lem_id id pp_lem_l l pp_annot annot +let pp_lem_aspec ppf (AL_aux(aspec,(l,annot))) = + match aspec with + | AL_subreg(reg,subreg) -> + fprintf ppf "@[<0>(AL_aux (AL_subreg %a %a) (%a,%a))@]" pp_lem_id reg pp_lem_id subreg pp_lem_l l pp_annot annot + | AL_bit(reg,ac) -> + fprintf ppf "@[<0>(AL_aux (AL_bit %a %a) (%a,%a))@]" pp_lem_id reg pp_lem_exp ac pp_lem_l l pp_annot annot + | AL_slice(reg,b,e) -> + fprintf ppf "@[<0>(AL_aux (AL_slice %a %a %a) (%a,%a))@]" pp_lem_id reg pp_lem_exp b pp_lem_exp e pp_lem_l l pp_annot annot + | AL_concat(f,s) -> + fprintf ppf "@[<0>(AL_aux (AL_concat %a %a) (%a,%a))@]" pp_lem_id f pp_lem_id s pp_lem_l l pp_annot annot + +let pp_lem_dec ppf (DEC_aux(reg,(l,annot))) = + match reg with + | DEC_reg(typ,id) -> + fprintf ppf "@[<0>(DEC_aux (DEC_reg %a %a) (%a,%a))@]" pp_lem_typ typ pp_lem_id id pp_lem_l l pp_annot annot + | DEC_alias(id,alias_spec) -> + fprintf ppf "@[<0>(DEC_aux (DEC_alias %a %a) (%a, %a))@]" pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot + | DEC_typ_alias(typ,id,alias_spec) -> + fprintf ppf "@[<0>(DEC_aux (DEC_typ_alias %a %a %a) (%a, %a))@]" pp_lem_typ typ pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot let pp_lem_def ppf d = match d with @@ -827,7 +846,7 @@ let doc_exp, doc_let = parens (separate_map comma exp exps) | E_record(FES_aux(FES_Fexps(fexps,_),_)) -> (* XXX E_record is not handled by parser currently - AAA I don't think the parser can handle E_record due to ambiguity with blocks; initial_check looks for blocks that are all field assignments and converts *) + AAA The parser can't handle E_record due to ambiguity with blocks; initial_check looks for blocks that are all field assignments and converts *) braces (separate_map semi_sp doc_fexp fexps) | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) -> braces (doc_op (string "with") (exp e) (separate_map semi_sp doc_fexp fexps)) @@ -849,6 +868,8 @@ let doc_exp, doc_let = let opening = separate space [string "switch"; exp e; lbrace] in let cases = separate_map (break 1) doc_case pexps in surround 2 1 opening cases rbrace + | E_exit e -> + separate space [string "exit"; exp e;] (* adding parens and loop for lower precedence *) | E_app (_, _)|E_vector_access (_, _)|E_vector_subrange (_, _, _) | E_cons (_, _)|E_field (_, _)|E_assign (_, _) @@ -1010,8 +1031,19 @@ let doc_fundef (FD_aux(FD_function(r, typa, efa, fcls),_)) = string "effect"; doc_effects_opt efa; clauses] -let doc_dec (DEC_aux(DEC_reg(typ,id),_)) = - separate space [string "register"; doc_atomic_typ typ; doc_id id] +let doc_alias (AL_aux (alspec,_)) = + match alspec with + | AL_subreg(id,subid) -> doc_id id ^^ dot ^^ doc_id subid + | AL_bit(id,ac) -> doc_id id ^^ brackets (doc_exp ac) + | AL_slice(id,b,e) -> doc_id id ^^ brackets (doc_op dotdot (doc_exp b) (doc_exp e)) + | AL_concat(f,s) -> doc_op colon (doc_id f) (doc_id s) + +let doc_dec (DEC_aux (reg,_)) = + match reg with + | DEC_reg(typ,id) -> separate space [string "register"; doc_atomic_typ typ; doc_id id] + | DEC_alias(id,alspec) -> separate space [string "register"; string "alias"; doc_id id; equals; doc_alias alspec] + | DEC_typ_alias(typ,id,alspec) -> + separate space [string "register"; string "alias"; doc_atomic_typ typ; doc_id id; equals; doc_alias alspec] let doc_scattered (SD_aux (sdef, _)) = match sdef with | SD_scattered_function (r, typa, efa, id) -> diff --git a/src/process_file.ml b/src/process_file.ml index 6d1729a5..98dd4db9 100644 --- a/src/process_file.ml +++ b/src/process_file.ml @@ -93,7 +93,7 @@ let convert_ast (defs : Parse_ast.defs) : (Type_internal.tannot Ast.defs * kind let check_ast (defs : Type_internal.tannot Ast.defs) (k : kind Envmap.t) : Type_internal.tannot Ast.defs = let d_env = { Type_internal.k_env = k; Type_internal.abbrevs = Type_internal.initial_abbrev_env; Type_internal.namesch = Envmap.empty; Type_internal.enum_env = Envmap.empty; - Type_internal.rec_env = []; } in + Type_internal.rec_env = []; Type_internal.alias_env = Envmap.empty} in Type_check.check (Type_check.Env (d_env, Type_internal.initial_typ_env)) defs let open_output_with_check file_name = diff --git a/src/test/regbits.sail b/src/test/regbits.sail index ed2a95e0..46343d67 100644 --- a/src/test/regbits.sail +++ b/src/test/regbits.sail @@ -8,12 +8,19 @@ register (xer) XER register (bit) query +register alias CA = XER.CA +register alias Fo = XER[35] +register alias foobar = XER[35..36] + function (bit[64]) main _ = { XER := 0b0101010101010101010101010101010101010101010101010101010101010010; f := XER; (bit[7]) foo := XER[57..63]; query := XER.SO; XER.SO := 0; + query := CA; + query := Fo; XER.FOOBAR := 0b11; + XER.FOOBAR := foobar; XER } diff --git a/src/type_check.ml b/src/type_check.ml index f8ec0642..e68337ab 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -28,6 +28,7 @@ let rec field_equivs fields fmaps = if (List.mem_assoc (id_to_string id) fmaps) then match (field_equivs fields fmaps) with | None -> None + | Some [] -> None | Some fs -> Some(((List.assoc (id_to_string id) fmaps),id,l,pat)::fs) else None @@ -1010,6 +1011,9 @@ let rec check_exp envs expect_t (E_aux(e,(l,annot)) : tannot exp) : (tannot exp let (exp',t'',_,cs',ef') = check_exp envs t' exp in let (t',c') = type_consistent (Expr l) d_env unit_t expect_t in (E_aux(E_assign(lexp',exp'),(l,(Base(([],unit_t),tag,[],ef)))),unit_t,t_env',cs@cs'@c',union_effects ef ef') + | E_exit e -> + let (e',t',_,_,_) = check_exp envs (new_t ()) e in + (E_aux (E_exit e',(l,(Base(([],expect_t),Emp_local,[],pure_e)))),expect_t,t_env,[],pure_e) | E_internal_cast _ | E_internal_exp _ -> raise (Reporting_basic.err_unreachable l "Internal expression passed back into type checker") and check_block orig_envs envs expect_t exps : ((tannot exp) list * tannot * tannot emap * nexp_range list * t * effect) = @@ -1426,6 +1430,84 @@ let check_fundef envs (FD_aux(FD_function(recopt,tannotopt,effectopt,funcls),(l, (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))) +let check_alias_spec envs alias (AL_aux(al,(l,annot))) e_typ = + let (Env(d_env,t_env)) = envs in + let check_reg (Id_aux(_,l) as id) : (string * typ * typ) = + let i = id_to_string id in + (match Envmap.apply t_env i with + | Some(Base(([],t), External (Some j), [], _)) -> + let t,_ = get_abbrev d_env t in + let t_actual,t_id = match t.t with + | Tabbrev(i,t) -> t,i + | _ -> t,t in + (match t_actual.t with + | Tapp("register",[TA_typ t']) -> + if i = j then (i,t_id,t') + else assert false + | _ -> typ_error l + ("register alias " ^ alias ^ " to " ^ i ^ " expected a register, found " ^ (t_to_string t))) + | _ -> typ_error l ("register alias " ^ alias ^ " to " ^ i ^ " exepcted a register.")) in + match al with + | AL_subreg(reg_a,subreg) -> + let (reg,reg_t,t) = check_reg reg_a in + (match reg_t.t with + | Tid i -> + (match lookup_record_typ i d_env.rec_env with + | None -> typ_error l ("Expected a register with bit fields, given " ^ i) + | Some(((i,rec_kind,fields) as r)) -> + let fi = id_to_string subreg in + (match lookup_field_type fi r with + | NoTyp -> typ_error l ("Type " ^ i ^ " does not have a field " ^ fi) + | Overload _ -> raise (Reporting_basic.err_unreachable l "Record given overload annot") + | Base(([],et),tag,cs,ef) -> + let tannot = Base(([],et),Alias,[],pure_e) in + let d_env = {d_env with alias_env = Envmap.insert (d_env.alias_env) (alias, (reg,tannot))} in + (AL_aux(AL_subreg(reg_a,subreg),(l,tannot)),tannot,d_env))) + | _ -> let _ = Printf.printf "%s\n" (t_to_string reg_t) in assert false) + | AL_bit(reg_a,bit) -> + let (reg,reg_t,t) = check_reg reg_a in + let (E_aux(bit,(le,eannot)),_,_,_,_) = check_exp envs (new_t ()) bit in + (match t.t with + | Tapp("vector",[TA_nexp base;TA_nexp len;TA_ord order;TA_typ item_t]) -> + match (base.nexp,len.nexp,order.order, bit) with + | (Nconst i,Nconst j,Oinc, E_lit (L_aux((L_num k), ll))) -> + if (int_of_big_int i) <= k && ((int_of_big_int i) + (int_of_big_int j)) >= k + then let tannot = Base(([],item_t),Alias,[],pure_e) in + let d_env = + {d_env with alias_env = Envmap.insert (d_env.alias_env) (alias, (reg,tannot))} in + (AL_aux(AL_bit(reg_a,(E_aux(bit,(le,eannot)))), (l,tannot)), tannot,d_env) + else typ_error ll ("Alias bit lookup must be in the range of the vector in the register") + | _ -> assert false) + | AL_slice(reg_a,sl1,sl2) -> + let (reg,reg_t,t) = check_reg reg_a in + let (E_aux(sl1,(le1,eannot1)),_,_,_,_) = check_exp envs (new_t ()) sl1 in + let (E_aux(sl2,(le2,eannot2)),_,_,_,_) = check_exp envs (new_t ()) sl2 in + (match t.t with + | Tapp("vector",[TA_nexp base;TA_nexp len;TA_ord order;TA_typ item_t]) -> + match (base.nexp,len.nexp,order.order, sl1,sl2) with + | (Nconst i,Nconst j,Oinc, E_lit (L_aux((L_num k), ll)),E_lit (L_aux((L_num k2), ll2))) -> + if (int_of_big_int i) <= k && ((int_of_big_int i) + (int_of_big_int j)) >= k2 && k < k2 + then let t = {t = Tapp("vector",[TA_nexp (int_to_nexp k);TA_nexp (int_to_nexp ((k2-k) +1)); + TA_ord order; TA_typ item_t])} in + let tannot = Base(([],t),Alias,[],pure_e) in + let d_env = + {d_env with alias_env = Envmap.insert (d_env.alias_env) (alias, (reg,tannot))} in + (AL_aux(AL_slice(reg_a,(E_aux(sl1,(le1,eannot1))),(E_aux(sl2,(le2,eannot2)))), + (l,tannot)), tannot,d_env) + else typ_error ll ("Alias slices must be in the range of the vector in the register") + | _ -> assert false) + | AL_concat(reg1_a,reg2_a) -> + let (reg1,reg_t,t1) = check_reg reg1_a in + let (reg2,reg_t,t2) = check_reg reg2_a in + (match (t1.t,t2.t) with + | (Tapp("vector",[TA_nexp b1;TA_nexp r; TA_ord {order = Oinc}; TA_typ item_t]), + Tapp("vector",[TA_nexp _ ;TA_nexp r2; TA_ord {order = Oinc}; TA_typ item_t2])) -> + let _ = type_consistent (Specc l) d_env item_t item_t2 in + let t = {t= Tapp("vector",[TA_nexp b1; TA_nexp {nexp = Nadd(r,r2)}; TA_ord {order = Oinc}; TA_typ item_t])} in + let tannot = Base(([],t),Alias,[],pure_e) in + let d_env = {d_env with alias_env = Envmap.insert (d_env.alias_env) (alias, (reg1,tannot))} in + (AL_aux (AL_concat(reg1_a,reg2_a), (l,tannot)), tannot, d_env)) + (*val check_def : envs -> tannot def -> (tannot def) envs_out*) let check_def envs def = let (Env(d_env,t_env)) = envs in @@ -1445,6 +1527,15 @@ let check_def envs def = let i = id_to_string id in let tannot = into_register d_env (Base(([],t),External (Some i),[],pure_e)) in (DEF_reg_dec(DEC_aux(DEC_reg(typ,id),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot)))) + | DEF_reg_dec(DEC_aux(DEC_alias(id,aspec), (l,annot))) -> + let i = id_to_string id in + let (aspec,tannot,d_env) = check_alias_spec envs i aspec None in + (DEF_reg_dec(DEC_aux(DEC_alias(id,aspec),(l,tannot))),(Env(d_env, Envmap.insert t_env (i,tannot)))) + | DEF_reg_dec(DEC_aux(DEC_typ_alias(typ,id,aspec),(l,tannot))) -> + let i = id_to_string id in + let t = typ_to_t typ in + let (aspec,tannot,d_env) = check_alias_spec envs i aspec (Some t) in + (DEF_reg_dec(DEC_aux(DEC_typ_alias(typ,id,aspec),(l,tannot))),(Env(d_env,Envmap.insert t_env (i,tannot)))) | DEF_scattered _ -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "Scattered given to type checker") diff --git a/src/type_internal.ml b/src/type_internal.ml index 08eddc3f..880d317a 100644 --- a/src/type_internal.ml +++ b/src/type_internal.ml @@ -74,6 +74,7 @@ type tag = | Default | Constructor | Enum + | Alias | Spec type constraint_origin = @@ -98,7 +99,6 @@ type tannot = | Base of (t_params * t) * tag * nexp_range list * effect | Overload of tannot * bool * tannot list (* First tannot is the most polymorphic version; the boolean indicates whether the overloaded functions can use the return type; the list includes all variants. All t to be Tfn *) -(*type tannot = ((t_params * t) * tag * nexp_range list * effect) option*) type 'a emap = 'a Envmap.t type rec_kind = Record | Register @@ -109,6 +109,7 @@ type def_envs = { namesch : tannot emap; enum_env : (string list) emap; rec_env : rec_env list; + alias_env : (string * tannot) emap; } type exp = tannot Ast.exp @@ -193,6 +194,7 @@ let tag_to_string = function | Default -> "Default" | Constructor -> "Constructor" | Enum -> "Enum" + | Alias -> "Alias" | Spec -> "Spec" let rec tannot_to_string = function @@ -496,6 +498,8 @@ let rec normalize_nexp n = | Nneg _,_ | _,Nneg _ -> let _ = Printf.printf "neg case still around %s\n" (n_to_string n) in assert false (* If things are normal, neg should be gone. *) ) +let int_to_nexp i = {nexp = Nconst (big_int_of_int i)} + let v_count = ref 0 let t_count = ref 0 let tuvars = ref [] diff --git a/src/type_internal.mli b/src/type_internal.mli index 7ddb082f..063ee088 100644 --- a/src/type_internal.mli +++ b/src/type_internal.mli @@ -70,6 +70,7 @@ type tag = | Default | Constructor | Enum + | Alias | Spec type constraint_origin = @@ -106,6 +107,7 @@ type def_envs = { namesch : tannot emap; enum_env : (string list) emap; rec_env : rec_env list; + alias_env : (string * tannot) emap; } type exp = tannot Ast.exp @@ -131,6 +133,8 @@ val t_to_string : t -> string val tannot_to_string : tannot -> string val t_to_typ : t -> Ast.typ +val int_to_nexp : int -> nexp + val reset_fresh : unit -> unit val new_t : unit -> t val new_n : unit -> nexp |
