diff options
| -rw-r--r-- | language/l2.ott | 85 | ||||
| -rw-r--r-- | src/Makefile | 3 | ||||
| -rw-r--r-- | src/lem_interp/interp.lem | 1504 | ||||
| -rw-r--r-- | src/lem_interp/interp_ast.lem | 747 | ||||
| -rw-r--r-- | src/lem_interp/interp_inter_imp.lem | 5 | ||||
| -rw-r--r-- | src/lem_interp/interp_utilities.lem | 11 | ||||
| -rw-r--r-- | src/lem_interp/pretty_interp.ml | 30 | ||||
| -rw-r--r-- | src/lem_interp/type_check.lem | 862 |
8 files changed, 790 insertions, 2457 deletions
diff --git a/language/l2.ott b/language/l2.ott index 8145de7a..6963d8bd 100644 --- a/language/l2.ott +++ b/language/l2.ott @@ -16,6 +16,7 @@ metavar num,numZero,numOne ::= metavar nat ::= {{ phantom }} + {{ ocaml int }} {{ lex numeric }} {{ lem nat }} @@ -31,7 +32,7 @@ metavar bin ::= {{ lex numeric }} {{ ocaml string }} {{ lem string }} - {{ com Bit vector literal, specified by C-style binary number }} + {{ com Bit vector literal, specified by C-style binary number }} metavar string ::= {{ phantom }} @@ -622,9 +623,85 @@ let rec disjoint_all sets = end }} - -grammar +grammar + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Interpreter specific things % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +optx :: '' ::= {{ phantom }} {{ lem maybe string }} {{ ocaml string option }} + | x :: :: optx_x + {{ lem (Just [[x]]) }} {{ ocaml (Some [[x]]) }} + | :: :: optx_none + {{ lem Nothing }} {{ ocaml None }} + +tag :: 'Tag_' ::= +{{ com Data indicating where the identifier arises and thus information necessary in compilation }} + | None :: :: empty + | Intro :: :: intro {{ com Denotes an assignment and lexp that introduces a binding }} + | Set :: :: set {{ com Denotes an expression that mutates a local variable }} + | Tuple :: :: tuple_assign {{ com Denotes an assignment with a tuple lexp }} + | Global :: :: global {{ com Globally let-bound or enumeration based value/variable }} + | Ctor :: :: ctor {{ com Data constructor from a type union }} + | Extern optx :: :: extern {{ com External function, specied only with a val statement }} + | Default :: :: default {{ com Type has come from default declaration, identifier may not be bound locally }} + | Spec :: :: spec + | Enum num :: :: enum + | Alias :: :: alias + | Unknown_path optx :: :: unknown {{ com Tag to distinguish an unknown path from a non-analysis non deterministic path}} + +embed +{{ lem + +type tannot = maybe (typ * tag * list unit * effect * effect) +}} + +embed +{{ ocaml + +(* Interpreter specific things are just set to unit here *) +type tannot = unit + +type reg_form_set = unit + +}} + +grammar +tannot :: '' ::= + {{ phantom }} + {{ ocaml unit }} + {{ lem tannot }} + +i_direction :: 'I' ::= + | IInc :: :: Inc + | IDec :: :: Dec + +ctor_kind :: 'C_' ::= + | C_Enum nat :: :: Enum + | C_Union :: :: Union + +reg_form :: 'Form_' ::= + | Reg id tannot i_direction :: :: Reg + | SubReg id reg_form index_range :: :: SubReg + +reg_form_set :: '' ::= {{ phantom }} {{ lem set reg_form }} + +alias_spec_tannot :: '' ::= {{ phantom }} {{ lem alias_spec tannot }} {{ ocaml tannot alias_spec }} + +value :: 'V_' ::= {{ com interpreter evaluated value }} + | Boxref nat typ :: :: boxref + | Lit lit :: :: lit + | Tuple ( value1 , ... , valuen ) :: :: tuple + | List ( value1 , ... , valuen ) :: :: list + | Vector nat i_direction ( value1 , ... , valuen ) :: :: vector + | Vector_sparse nat' nat'' i_direction ( nat1 value1 , ... , natn valuen ) value' :: :: vector_sparse + | Record typ ( id1 value1 , ... , idn valuen ) :: :: record + | V_ctor id typ ctor_kind value1 :: :: ctor + | Unknown :: :: unknown + | Register reg_form :: :: register + | Register_alias alias_spec_tannot tannot :: :: register_alias + | Track value reg_form_set :: :: track %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Expressions % @@ -772,7 +849,7 @@ exp :: 'E_' ::= | let lexp = exp in exp' :: I :: internal_let {{ com This is an internal node for compilation that demonstrates the scope of a local mutable variable }} | let pat = exp in exp' :: I :: internal_plet {{ com This is an internal node, used to distinguised some introduced lets during processing from original ones }} | return_int ( exp ) :: :: internal_return {{ com For internal use to embed into monad definition }} -% | value :: I :: internal_value {{ com For internal use in interpreter to wrap pre-evaluated values when returning an action }} + | value :: I :: internal_value {{ com For internal use in interpreter to wrap pre-evaluated values when returning an action }} | constraint n_constraint :: :: constraint %i_direction :: 'I' ::= diff --git a/src/Makefile b/src/Makefile index 68ad408f..eeaf9fba 100644 --- a/src/Makefile +++ b/src/Makefile @@ -52,6 +52,9 @@ full: sail lib power doc test ast.ml: ../language/l2.ott ott -sort false -generate_aux_rules true -o ast.ml -picky_multiple_parses true ../language/l2.ott +lem_interp2/interp_ast.lem: ../language/l2.ott + ott -sort false -generate_aux_rules true -o lem_interp2/interp_ast.lem -picky_multiple_parses true ../language/l2.ott + sail: ast.ml ocamlbuild sail.native diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem index 58874fa6..301849cd 100644 --- a/src/lem_interp/interp.lem +++ b/src/lem_interp/interp.lem @@ -98,7 +98,7 @@ end let rec {ocaml} string_of_value v = match v with | V_boxref nat t -> "$#" ^ (show nat) ^ "$" - | V_lit (L_aux lit _) -> + | V_lit (L_aux lit _) -> (match lit with | L_unit -> "()" | L_zero -> "0" @@ -112,9 +112,9 @@ let rec {ocaml} string_of_value v = match v with | L_string str-> "\"" ^ str ^ "\"" end) | V_tuple vals -> "(" ^ (list_to_string string_of_value "," vals) ^ ")" | V_list vals -> "[||" ^ (list_to_string string_of_value "," vals) ^ "||]" - | V_vector i inc vals -> + | V_vector i inc vals -> let default_format _ = "[" ^ (list_to_string string_of_value "," vals) ^ "]" in - let to_bin () = (*"("^show i ^") "^ *)"0b" ^ + let to_bin () = (*"("^show i ^") "^ *)"0b" ^ (List.foldr (fun v rst -> (match v with @@ -126,16 +126,16 @@ let rec {ocaml} string_of_value v = match v with match vals with | [] -> default_format () | v::vs -> - match v with + match v with | V_lit (L_aux L_zero _) -> to_bin() | V_lit (L_aux L_one _) -> to_bin() | _ -> default_format() end end - | V_vector_sparse start stop inc vals default -> + | V_vector_sparse start stop inc vals default -> "[" ^ (list_to_string (fun (i,v) -> (show i) ^ " = " ^ (string_of_value v)) "," vals) ^ "]:" ^ show start ^ "-" ^show stop ^ "(default of " ^ (string_of_value default) ^ ")" | V_record t vals -> "{" ^ (list_to_string (fun (id,v) -> (get_id id) ^ "=" ^ (string_of_value v)) ";" vals) ^ "}" - | V_ctor id t _ value -> (get_id id) ^ " " ^ string_of_value value + | V_ctor id t _ value -> (get_id id) ^ " " ^ string_of_value value | V_unknown -> "Unknown" | V_register r -> string_of_reg_form r | V_register_alias _ _ -> "register_as_alias" @@ -152,7 +152,7 @@ end val debug_print_value : value -> string let rec debug_print_value v = match v with | V_boxref n t -> "V_boxref " ^ (show n) ^ " t" - | V_lit (L_aux lit _) -> + | V_lit (L_aux lit _) -> "V_lit " ^ (match lit with | L_unit -> "L_unit" @@ -206,7 +206,7 @@ and value_eq strict left right = | (V_list l, V_list l') -> listEqualBy (value_eq strict) l l' | (V_vector n b l, V_vector m b' l') -> b = b' && listEqualBy (value_eq strict) l l' | (V_vector_sparse n o b l v, V_vector_sparse m p b' l' v') -> - n=m && o=p && b=b' && + n=m && o=p && b=b' && listEqualBy (fun (i,v) (i',v') -> i=i' && (value_eq strict v v')) l l' && value_eq strict v v' | (V_record t l, V_record t' l') -> t = t' && @@ -217,8 +217,8 @@ and value_eq strict left right = | (V_unknown,V_unknown) -> true | (V_unknown,_) -> if strict then false else true | (_,V_unknown) -> if strict then false else true - | (V_track v1 ts1, V_track v2 ts2) -> - if strict + | (V_track v1 ts1, V_track v2 ts2) -> + if strict then value_eq strict v1 v2 && ts1 = ts2 else value_eq strict v1 v2 | (V_track v _, v2) -> if strict then false else value_eq strict v v2 @@ -236,62 +236,52 @@ instance (Eq value) let (<>) = value_ineq end -let reg_start_pos reg = +let reg_start_pos reg = match reg with - | Form_Reg _ (Just(typ,_,_,_,_)) _ -> + | Form_Reg _ (Just(typ,_,_,_,_)) _ -> let start_from_vec targs = match targs with - | T_args [T_arg_nexp (Ne_const s);_;_;_] -> natFromInteger s - | T_args [T_arg_nexp _; T_arg_nexp (Ne_const s); T_arg_order Odec; _] -> (natFromInteger s) - 1 - | T_args [_; _; T_arg_order Oinc; _] -> 0 + | [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant s) _)) _;_;_;_] -> natFromInteger s + | [Typ_arg_aux (Typ_arg_nexp _) _; Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant s) _)) _; Typ_arg_aux (Typ_arg_order Odec) _; _] -> (natFromInteger s) - 1 + | [_; _; Typ_arg_aux (Typ_arg_order Oinc) _; _] -> 0 | _ -> Assert_extra.failwith "vector type not well formed" end in let start_from_reg targs = match targs with - | T_args [T_arg_typ (T_app "vector" targs)] -> start_from_vec targs - | T_args [T_arg_typ (T_abbrev _ (T_app "vector" targs))] -> start_from_vec targs + | [Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_app (Id_aux (Id "vector") _) targs) _)) _] -> start_from_vec targs | _ -> Assert_extra.failwith "register not of type vector" end in - let start_from_abbrev t = match t with - | T_app "vector" targs -> start_from_vec targs - | T_app "register" targs -> start_from_reg targs + match typ with + | Typ_aux (Typ_app id targs) _ -> + if get_id id = "vector" then start_from_vec targs + else if get_id id = "register" then start_from_reg targs + else Assert_extra.failwith "register abbrev not register or vector" | _ -> Assert_extra.failwith "register abbrev not register or vector" - end in - match typ with - | T_app "vector" targs -> start_from_vec targs - | T_app "register" targs -> start_from_reg targs - | T_abbrev _ t -> start_from_abbrev t - | _ -> Assert_extra.failwith "register type not vector, register, or abbrev" - end + end | _ -> Assert_extra.failwith "reg_start_pos found unexpected sub reg, or reg without a type" -end +end -let reg_size reg = +let reg_size reg = match reg with - | Form_Reg _ (Just(typ,_,_,_,_)) _ -> + | Form_Reg _ (Just(typ,_,_,_,_)) _ -> let end_from_vec targs = match targs with - | T_args [_;T_arg_nexp (Ne_const s);_;_] -> natFromInteger s + | [_;Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant s) _)) _;_;_] -> natFromInteger s | _ -> Assert_extra.failwith "register vector type not well formed" end in let end_from_reg targs = match targs with - | T_args [T_arg_typ (T_app "vector" targs)] -> end_from_vec targs - | T_args [T_arg_typ (T_abbrev _ (T_app "vector" targs))] -> end_from_vec targs - | _ -> Assert_extra.failwith "register does not contain vector" + | [Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_app (Id_aux (Id "vector") _) targs) _)) _] -> end_from_vec targs + | _ -> Assert_extra.failwith "register does not contain vector" end in - let end_from_abbrev t = match t with - | T_app "vector" targs -> end_from_vec targs - | T_app "register" targs -> end_from_reg targs - | _ -> Assert_extra.failwith "register abbrev is neither vector nor register" - end in - match typ with - | T_app "vector" targs -> end_from_vec targs - | T_app "register" targs -> end_from_reg targs - | T_abbrev _ t -> end_from_abbrev t - | _ -> Assert_extra.failwith "register type is none of vector, register, or abbrev" - end + match typ with + | Typ_aux (Typ_app id targs) _ -> + if get_id id = "vector" then end_from_vec targs + else if get_id id = "register" then end_from_reg targs + else Assert_extra.failwith "register type is none of vector, register, or abbrev" + | _ -> Assert_extra.failwith "register type is none of vector, register, or abbrev" + end | _ -> Assert_extra.failwith "reg_size given unexpected sub reg or reg without a type" -end +end (*Constant unit value, for use in interpreter *) -let unit_ty = T_id "unit" +let unit_ty = Typ_aux (Typ_id (Id_aux (Id "unit") Unknown)) Unknown let unitv = V_lit (L_aux L_unit Unknown) let unit_e = E_aux (E_lit (L_aux L_unit Unknown)) (Unknown, val_annot unit_ty) @@ -331,26 +321,26 @@ end type sub_reg_map = map string index_range -(*top_level is a tuple of +(*top_level is a tuple of (function definitions environment, all extracted instructions (where possible), default direction - letbound and enum values, - register values, - Typedef union constructors, + letbound and enum values, + register values, + Typedef union constructors, sub register mappings, and register aliases) *) -type top_level = +type top_level = | Env of map string (list (funcl tannot)) (*function definitions environment*) * list instruction_form (* extracted instructions (where extractable) *) * i_direction (*default direction*) * env (*letbound and enum values*) - * env (*register values*) + * env (*register values*) * map string typ (*typedef union constructors *) * map string sub_reg_map (*sub register mappings*) * map string (alias_spec tannot) (*register aliases*) * bool (* debug? *) -type action = +type action = | Read_reg of reg_form * maybe (nat * nat) | Write_reg of reg_form * maybe (nat * nat) * value | Read_mem of id * value * maybe (nat * nat) @@ -367,13 +357,13 @@ type action = | Return of value | Exit of (exp tannot) (* For the error case of a failed assert, carries up an optional error message*) - | Fail of value + | Fail of value (* For stepper, no action needed. String is function called, value is parameter where applicable *) - | Step of l * maybe string * maybe value + | Step of l * maybe string * maybe value (* Inverted call stack, where the frame with a Top stack waits for an action to resolve and all other frames for their inner stack *) -type stack = +type stack = | Top | Hole_frame of id * exp tannot * top_level * lenv * lmem * stack (* Stack frame waiting for a value *) | Thunk_frame of exp tannot * top_level * lenv * lmem * stack (* Paused stack frame *) @@ -383,7 +373,7 @@ type stack = type outcome = | Value of value | Action of action * stack - | Error of l * string + | Error of l * string let string_of_id id' = (match id' with @@ -501,7 +491,6 @@ let rec string_of_exp e' = | E_if cond thn els -> "(E_if " ^ (string_of_exp cond) ^ " ? " ^ (string_of_exp thn) ^ " : " ^ (string_of_exp els) ^ ")" | E_for id from to_ by order exp -> "(E_for " ^ string_of_id id ^ " " ^ string_of_exp from ^ " " ^ string_of_exp to_ ^ " " ^ string_of_exp by ^ " " ^ string_of_order order ^ " " ^ string_of_exp exp ^ ")" | E_vector exps -> "(E_vector [" ^ String.concat "; " (List.map string_of_exp exps) ^ "])" - | E_vector_indexed _ _ -> "(E_vector_indexed)" | E_vector_access exp1 exp2 -> "(E_vector_access " ^ string_of_exp exp1 ^ " " ^ string_of_exp exp2 ^ ")" | E_vector_subrange exp1 exp2 exp3 -> "(E_vector_subrange " ^ string_of_exp exp1 ^ " " ^ string_of_exp exp2 ^ " " ^ string_of_exp exp3 ^ ")" | E_vector_update _ _ _ -> "(E_vector_update)" @@ -585,7 +574,6 @@ let rec string_of_pat (P_aux pat _) = | P_app id pats -> "(P_app " ^ show id ^ " [" ^ String.concat "; " (List.map string_of_pat pats) ^ "])" | P_record _ _ -> "(P_record _ _)" | P_vector pats -> "(P_vector [" ^ String.concat "; " (List.map string_of_pat pats) ^ "])" - | P_vector_indexed _ -> "(P_vector_indexed _)" | P_vector_concat pats -> "(P_vector_concat [" ^ String.concat "; " (List.map string_of_pat pats) ^ "])" | P_tup pats -> "(P_tup [" ^ String.concat "; " (List.map string_of_pat pats) ^ "])" | P_list pats -> "(P_list [" ^ String.concat "; " (List.map string_of_pat pats) ^ "])" @@ -597,8 +585,7 @@ end let string_of_letbind (LB_aux lb _) = (match lb with - | LB_val_explicit ts pat exp -> "(LB_val_explicit " ^ (show ts) ^ " " ^ (show pat) ^ " " ^ (show exp) ^ ")" - | LB_val_implicit pat exp -> "(LB_val_implicit " ^ (show pat) ^ " " ^ (show exp) ^ ")" + | LB_val pat exp -> "(LB_val " ^ (show pat) ^ " " ^ (show exp) ^ ")" end) instance forall 'a. (Show letbind 'a) @@ -649,36 +636,36 @@ let rec to_fdefs (Defs defs) = | _ -> to_fdefs (Defs defs) end end val to_register_fields : defs tannot -> map string (map string index_range) -let rec to_register_fields (Defs defs) = +let rec to_register_fields (Defs defs) = match defs with | [ ] -> Map.empty - | def::defs -> - match def with + | def::defs -> + match def with | DEF_type (TD_aux (TD_register id n1 n2 indexes) l') -> - Map.insert (get_id id) + Map.insert (get_id id) (List.foldr (fun (a,b) imap -> Map.insert (get_id b) a imap) Map.empty indexes) (to_register_fields (Defs defs)) | _ -> to_register_fields (Defs defs) - end + end end val to_registers : i_direction -> defs tannot -> env -let rec to_registers dd (Defs defs) = +let rec to_registers dd (Defs defs) = match defs with | [ ] -> Map.empty - | def::defs -> - match def with - | DEF_reg_dec (DEC_aux (DEC_reg typ id) (l,tannot)) -> + | def::defs -> + match def with + | DEF_reg_dec (DEC_aux (DEC_reg typ id) (l,tannot)) -> let dir = match tannot with | Nothing -> dd | Just(t, _, _, _,_) -> dd (*TODO, lets pull the direction out properly*) end in Map.insert (get_id id) (V_register(Form_Reg id tannot dir)) (to_registers dd (Defs defs)) - | DEF_reg_dec (DEC_aux (DEC_alias id aspec) (l,tannot)) -> + | DEF_reg_dec (DEC_aux (DEC_alias id aspec) (l,tannot)) -> Map.insert (get_id id) (V_register_alias aspec tannot) (to_registers dd (Defs defs)) | _ -> to_registers dd (Defs defs) - end - end + end + end val to_aliases : defs tannot -> map string (alias_spec tannot) let rec to_aliases (Defs defs) = @@ -686,12 +673,12 @@ let rec to_aliases (Defs defs) = | [] -> Map.empty | def::defs -> match def with - | DEF_reg_dec (DEC_aux (DEC_alias id aspec) _) -> + | DEF_reg_dec (DEC_aux (DEC_alias id aspec) _) -> Map.insert (get_id id) aspec (to_aliases (Defs defs)) - | DEF_reg_dec (DEC_aux (DEC_typ_alias typ id aspec) _) -> + | DEF_reg_dec (DEC_aux (DEC_typ_alias typ id aspec) _) -> Map.insert (get_id id) aspec (to_aliases (Defs defs)) | _ -> to_aliases (Defs defs) - end + end end val to_data_constructors : defs tannot -> map string typ @@ -699,14 +686,14 @@ let rec to_data_constructors (Defs defs) = match defs with | [] -> (*Prime environment with built-in constructors*) - Map.insert "Some" (Typ_aux (Typ_var (Kid_aux (Var "a") Unknown)) Unknown) + Map.insert "Some" (Typ_aux (Typ_var (Kid_aux (Var "a") Unknown)) Unknown) (Map.insert "None" unit_t Map.empty) | def :: defs -> match def with | DEF_type (TD_aux t _)-> - match t with + match t with | TD_variant id _ tq tid_list _ -> - (List.foldr + (List.foldr (fun (Tu_aux t _) map -> match t with | (Tu_ty_id x y) -> Map.insert (get_id y) x map @@ -727,12 +714,12 @@ val in_lenv : lenv -> id -> value let in_lenv (LEnv _ env) id = match in_env env (get_id id) with | Nothing -> V_unknown - | Just v -> v + | Just v -> v end (*Prefer entries in the first when in conflict*) val union_env : lenv -> lenv -> lenv -let union_env (LEnv i1 env1) (LEnv i2 env2) = +let union_env (LEnv i1 env1) (LEnv i2 env2) = let l = if i1 < i2 then i2 else i1 in LEnv l (Map.(union) env2 env1) @@ -745,7 +732,7 @@ val add_to_env : (id * value) -> lenv -> lenv let add_to_env (id, entry) (LEnv i env) = (LEnv i (Map.insert (get_id id) entry env)) val in_mem : lmem -> nat -> value -let in_mem (LMem _ _ m _) n = +let in_mem (LMem _ _ m _) n = Map_extra.find n m (* Map.lookup n m *) @@ -762,9 +749,9 @@ let clear_updates (LMem owner c m _) = LMem owner c m Set.empty (*Value helper functions*) val is_lit_vector : lit -> bool -let is_lit_vector (L_aux l _) = +let is_lit_vector (L_aux l _) = match l with - | L_bin _ -> true + | L_bin _ -> true | L_hex _ -> true | _ -> false end @@ -774,9 +761,9 @@ let litV_to_vec (L_aux lit l) (dir: i_direction) = match lit with | L_hex s -> let to_v b = V_lit (L_aux b l) in - let hexes = List.map to_v - (List.concat - (List.map + let hexes = List.map to_v + (List.concat + (List.map (fun s -> match s with | #'0' -> [L_zero;L_zero;L_zero;L_zero] | #'1' -> [L_zero;L_zero;L_zero;L_one ] @@ -803,12 +790,12 @@ let litV_to_vec (L_aux lit l) (dir: i_direction) = | _ -> Assert_extra.failwith "Lexer did not restrict to valid hex" end) (String.toCharList s))) in V_vector (if is_inc(dir) then 0 else ((List.length hexes) - 1)) dir hexes - | L_bin s -> - let bits = List.map - (fun s -> match s with - | #'0' -> (V_lit (L_aux L_zero l)) + | L_bin s -> + let bits = List.map + (fun s -> match s with + | #'0' -> (V_lit (L_aux L_zero l)) | #'1' -> (V_lit (L_aux L_one l)) - | _ -> Assert_extra.failwith "Lexer did not restrict to valid bin" + | _ -> Assert_extra.failwith "Lexer did not restrict to valid bin" end) (String.toCharList s) in V_vector (if is_inc(dir) then 0 else ((List.length bits) -1)) dir bits | _ -> Assert_extra.failwith "litV predicate did not restrict to literal vectors" @@ -821,10 +808,10 @@ val list_length : forall 'a . list 'a -> integer let list_length l = integerFromNat (List.length l) val taint: value -> set reg_form -> value -let rec taint value regs = +let rec taint value regs = if Set.null regs then value - else match value with + else match value with | V_track value rs -> taint value (regs union rs) | V_tuple vals -> V_tuple (List.map (fun v -> taint v regs) vals) | _ -> V_track value regs @@ -832,13 +819,13 @@ end val retaint: value -> value -> value let retaint orig updated = - match orig with + match orig with | V_track _ rs -> taint updated rs | _ -> updated end -val detaint: value -> value -let rec detaint value = +val detaint: value -> value +let rec detaint value = match value with | V_track value _ -> detaint value | v -> v @@ -851,24 +838,24 @@ let rec binary_taint thunk = fun vall valr -> | (V_track vl rl,vr) -> taint (binary_taint thunk vl vr) rl | (vl,V_track vr rr) -> taint (binary_taint thunk vl vr) rr | (vl,vr) -> thunk vl vr -end +end -let rec merge_values v1 v2 = - if value_eq true v1 v2 - then v1 +let rec merge_values v1 v2 = + if value_eq true v1 v2 + then v1 else match (v1,v2) with | (V_lit l, V_lit l') -> if lit_eq l l' then v1 else V_unknown - | (V_boxref n t, V_boxref m t') -> + | (V_boxref n t, V_boxref m t') -> (*Changes to memory handled by merge_mem*) if n = m then v1 else V_unknown - | (V_tuple l, V_tuple l') -> - V_tuple (map2 merge_values l l') - | (V_list l, V_list l') -> - if (List.length l = List.length l') + | (V_tuple l, V_tuple l') -> + V_tuple (map2 merge_values l l') + | (V_list l, V_list l') -> + if (List.length l = List.length l') then V_list (map2 merge_values l l') else V_unknown - | (V_vector n b l, V_vector m b' l') -> - if b = b' && (List.length l = List.length l') + | (V_vector n b l, V_vector m b' l') -> + if b = b' && (List.length l = List.length l') then V_vector n b (map2 merge_values l l') else V_unknown | (V_vector_sparse n o b l v, V_vector_sparse m p b' l' v') -> @@ -877,45 +864,45 @@ let rec merge_values v1 v2 = else V_unknown | (V_record t l, V_record t' l') -> (*assumes canonical order for fields in a record*) - if t = t' && List.length l = length l' + if t = t' && List.length l = length l' then V_record t (map2 (fun (i,v1) (_,v2) -> (i, merge_values v1 v2)) l l') else V_unknown - | (V_ctor i t (C_Enum j) v, V_ctor i' t' (C_Enum j') v') -> + | (V_ctor i t (C_Enum j) v, V_ctor i' t' (C_Enum j') v') -> if i = i' then v1 else V_unknown | (V_ctor _ _ (C_Enum i) _,V_lit (L_aux (L_num j) _)) -> if i = (natFromInteger j) then v1 else V_unknown | (V_lit (L_aux (L_num j) _), V_ctor _ _ (C_Enum i) _) -> if i = (natFromInteger j) then v2 else V_unknown | (V_ctor i t ckind v, V_ctor i' t' _ v') -> - if t = t' && i = i' + if t = t' && i = i' then (V_ctor i t ckind (merge_values v v')) else V_unknown | (V_unknown,V_unknown) -> V_unknown - | (V_track v1 ts1, V_track v2 ts2) -> + | (V_track v1 ts1, V_track v2 ts2) -> taint (merge_values v1 v2) (ts1 union ts2) | (V_track v1 ts, v2) -> taint (merge_values v1 v2) ts | (v1,V_track v2 ts) -> taint (merge_values v1 v2) ts | (_, _) -> V_unknown -end +end val merge_lmems : lmem -> lmem -> lmem -let merge_lmems ((LMem owner1 c1 mem1 set1) as lmem1) ((LMem owner2 c2 mem2 set2) as lmem2) = +let merge_lmems ((LMem owner1 c1 mem1 set1) as lmem1) ((LMem owner2 c2 mem2 set2) as lmem2) = let diff1 = Set_extra.toList (set1 \ set2) in let diff2 = Set_extra.toList (set2 \ set1) in let inters = Set_extra.toList (set1 inter set2) in let c = max c1 c2 in let mem = LMem owner1 c (if c1 >= c2 then mem1 else mem2) Set.empty in - let diff_mem1 = - List.foldr - (fun i mem -> update_mem false mem i + let diff_mem1 = + List.foldr + (fun i mem -> update_mem false mem i (match Map.lookup i mem2 with | Nothing -> V_unknown | Just v -> merge_values (in_mem lmem1 i) v end)) mem diff1 in - let diff_mem2 = - List.foldr - (fun i mem -> update_mem false mem i + let diff_mem2 = + List.foldr + (fun i mem -> update_mem false mem i (match Map.lookup i mem1 with | Nothing -> V_unknown | Just v -> merge_values (in_mem lmem2 i) v end)) diff_mem1 diff2 in - List.foldr + List.foldr (fun i mem -> update_mem false mem i (merge_values (in_mem lmem1 i) (in_mem lmem2 i))) diff_mem2 inters @@ -929,7 +916,7 @@ end val access_vector : value -> nat -> value let access_vector v n = retaint v (match (detaint v) with - | V_unknown -> V_unknown + | V_unknown -> V_unknown | V_lit (L_aux L_undef _) -> v | V_lit (L_aux L_zero _) -> v | V_lit (L_aux L_one _ ) -> v @@ -938,7 +925,7 @@ let access_vector v n = | V_vector_sparse _ _ _ vs d -> match (List.lookup n vs) with | Nothing -> d - | Just v -> v end + | Just v -> v end | _ -> Assert_extra.failwith ("access_vector given unexpected " ^ string_of_value v) end ) @@ -946,16 +933,16 @@ val from_n_to_n :forall 'a. nat -> nat -> list 'a -> list 'a let from_n_to_n from to_ ls = take (to_ - from + 1) (drop from ls) val slice_sparse_list : (nat -> nat -> bool) -> (nat -> nat) -> list (nat * value) -> nat -> nat -> ((list (nat * value)) * bool) -let rec slice_sparse_list compare update_n vals n1 n2 = +let rec slice_sparse_list compare update_n vals n1 n2 = let sl = slice_sparse_list compare update_n in - if (n1 = n2) && (vals = []) + if (n1 = n2) && (vals = []) then ([],true) else if (n1=n2) then ([],false) else match vals with | [] -> ([],true) - | (i,v)::vals -> - if n1 = i + | (i,v)::vals -> + if n1 = i then let (rest,still_sparse) = (sl vals (update_n n1) n2) in ((i,v)::rest,still_sparse) else if (compare n1 i) then (sl vals (update_n n1) n2) @@ -966,12 +953,12 @@ val slice_vector : value -> nat -> nat -> value let slice_vector v n1 n2 = retaint v (match detaint v with | V_vector m dir vs -> - if is_inc(dir) + if is_inc(dir) then V_vector n1 dir (from_n_to_n (n1 - m) (n2 - m) vs) - else V_vector n1 dir (from_n_to_n (m - n1) (m - n2) vs) - | V_vector_sparse m n dir vs d -> - let (slice, still_sparse) = - if is_inc(dir) + else V_vector n1 dir (from_n_to_n (m - n1) (m - n2) vs) + | V_vector_sparse m n dir vs d -> + let (slice, still_sparse) = + if is_inc(dir) then slice_sparse_list (>) (fun i -> i + 1) vs n1 n2 else slice_sparse_list (<) (fun i -> i - 1) vs n1 n2 in if still_sparse && is_inc(dir) @@ -992,7 +979,7 @@ let rec update_field_list base updates = end val fupdate_record : value -> value -> value -let fupdate_record base updates = +let fupdate_record base updates = let fupdate_record_helper base updates = (match (base,updates) with | (V_record t bs,V_record _ us) -> V_record t (update_field_list bs (env_from_list us)) @@ -1017,7 +1004,7 @@ let fupdate_vec v n vexp = let tainted = binary_taint (fun v _ -> v) v vexp in retaint tainted (match detaint v with - | V_vector m dir vals -> + | V_vector m dir vals -> V_vector m dir (List.update vals (if is_inc(dir) then (n-m) else (m-n)) vexp) | V_vector_sparse m o dir vals d -> V_vector_sparse m o dir (fupdate_sparse (if is_inc(dir) then (>) else (<)) vals n vexp) d @@ -1029,7 +1016,7 @@ let rec replace_is ls vs base start stop = match (ls,vs) with | ([],_) -> [] | (ls,[]) -> ls - | (l::ls,v::vs) -> + | (l::ls,v::vs) -> if base >= start then if start >= stop then v::ls else v::(replace_is ls vs (base + 1) (start + 1) stop) @@ -1043,30 +1030,30 @@ let rec replace_sparse compare vals reps = | (vs,[]) -> vs | ((i1,v)::vs,(i2,r)::rs) -> if i1 = i2 then (i2,r)::(replace_sparse compare vs rs) - else if (compare i1 i2) + else if (compare i1 i2) then (i1,v)::(replace_sparse compare vs ((i2,r)::rs)) else (i2,r)::(replace_sparse compare ((i1,v)::vs) rs) end val fupdate_vector_slice : value -> value -> nat -> nat -> value let fupdate_vector_slice vec replace start stop = - let fupdate_vec_help vec replace = + let fupdate_vec_help vec replace = (match (vec,replace) with | (V_vector m dir vals,V_vector r_m dir' reps) -> - V_vector m dir - (replace_is vals + V_vector m dir + (replace_is vals (if dir=dir' then reps else (List.reverse reps)) 0 (if is_inc(dir) then (start-m) else (m-start)) (if is_inc(dir) then (stop-m) else (m-stop))) | (V_vector m dir vals, V_unknown) -> V_vector m dir - (replace_is vals + (replace_is vals (List.replicate (if is_inc(dir) then (stop-start) else (start-stop)) V_unknown) 0 (if is_inc(dir) then (start-m) else (m-start)) (if is_inc(dir) then (stop-m) else (m-stop))) | (V_vector_sparse m n dir vals d,V_vector _ _ reps) -> let (_,repsi) = List.foldl (fun (i,rs) r -> ((if is_inc(dir) then i+1 else i-1), (i,r)::rs)) (start,[]) reps in (V_vector_sparse m n dir (replace_sparse (if is_inc(dir) then (<) else (>)) vals (List.reverse repsi)) d) | (V_vector_sparse m n dir vals d, V_unknown) -> - let (_,repsi) = List.foldl (fun (i,rs) r -> ((if is_inc(dir) then i+1 else i-1), (i,r)::rs)) (start,[]) + let (_,repsi) = List.foldl (fun (i,rs) r -> ((if is_inc(dir) then i+1 else i-1), (i,r)::rs)) (start,[]) (List.replicate (if is_inc(dir) then (stop-start) else (start-stop)) V_unknown) in (V_vector_sparse m n dir (replace_sparse (if is_inc(dir) then (<) else (>)) vals (List.reverse repsi)) d) | (V_unknown,_) -> V_unknown @@ -1076,28 +1063,28 @@ let fupdate_vector_slice vec replace start stop = binary_taint fupdate_vec_help vec replace val update_vector_slice : bool -> value -> value -> nat -> nat -> lmem -> lmem -let update_vector_slice track vector value start stop mem = +let update_vector_slice track vector value start stop mem = match (detaint vector,detaint value) with | ((V_boxref n t), v) -> - update_mem track mem n (fupdate_vector_slice (in_mem mem n) (retaint value v) start stop) + update_mem track mem n (fupdate_vector_slice (in_mem mem n) (retaint value v) start stop) | ((V_vector m _ vs),(V_vector n _ vals)) -> let (V_vector m' _ vs') = slice_vector vector start stop in foldr2 (fun vbox v mem -> match vbox with | V_boxref n t -> update_mem track mem n v end) mem vs' vals - | ((V_vector m dir vs),(V_vector_sparse n o _ vals d)) -> + | ((V_vector m dir vs),(V_vector_sparse n o _ vals d)) -> let (m',vs') = match slice_vector vector start stop with | (V_vector m' _ vs') -> (m',vs') | _ -> Assert_extra.failwith "slice_vector did not return vector" end in let (_,mem) = foldr (fun vbox (i,mem) -> match vbox with - | V_boxref n t -> + | V_boxref n t -> (if is_inc(dir) then i+1 else i-1, update_mem track mem n (match List.lookup i vals with | Nothing -> d | Just v -> v end)) | _ -> Assert_extra.failwith "Internal error: update_vector_slice not of boxes" - end) (m,mem) vs' in + end) (m,mem) vs' in mem | ((V_vector m _ vs),v) -> let (m',vs') = match slice_vector vector start stop with @@ -1117,7 +1104,7 @@ let update_vector_start default_dir new_start expected_size v = | V_lit (L_aux L_zero _) -> V_vector new_start default_dir [v] | V_lit (L_aux L_one _) -> V_vector new_start default_dir [v] | V_vector m inc vs -> V_vector new_start inc vs (*Note, may need to shrink and check if still sparse *) - | V_vector_sparse m n dir vals d -> V_vector_sparse new_start n dir vals d + | V_vector_sparse m n dir vals d -> V_vector_sparse new_start n dir vals d | V_unknown -> V_vector new_start default_dir (List.replicate expected_size V_unknown) | V_lit (L_aux L_undef _) -> V_vector new_start default_dir (List.replicate expected_size v) | _ -> Assert_extra.failwith ("update_vector_start given unexpected " ^ string_of_value v) @@ -1135,9 +1122,9 @@ end let add_to_top_frame e_builder stack = match stack with | Top -> Top - | Hole_frame id e t_level env mem stack -> + | Hole_frame id e t_level env mem stack -> let (e',env') = (e_builder e env) in Hole_frame id e' t_level env' mem stack - | Thunk_frame e t_level env mem stack -> + | Thunk_frame e t_level env mem stack -> let (e',env') = (e_builder e env) in Thunk_frame e' t_level env' mem stack end @@ -1149,14 +1136,14 @@ let top_hole stack : bool = end let redex_id = id_of_string "0" -let mk_hole l annot t_level l_env l_mem = +let mk_hole l annot t_level l_env l_mem = Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem Top let mk_thunk l annot t_level l_env l_mem = Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,(intern_annot annot))) t_level l_env l_mem Top (*Converts a Hole_frame into a Thunk_frame, pushing to the top of the stack to insert the value at the innermost context *) val add_answer_to_stack : stack -> value -> stack -let rec add_answer_to_stack stack v = +let rec add_answer_to_stack stack v = match stack with | Top -> Top | Hole_frame id e t_level env mem Top -> Thunk_frame e t_level (add_to_env (id,v) env) mem Top @@ -1176,7 +1163,7 @@ let rec set_in_context stack e = | Thunk_frame _ _ _ _ s -> set_in_context s e end -let get_stack_state stack = +let get_stack_state stack = match stack with | Top -> Assert_extra.failwith "Top reached in extracting stack state" | Hole_frame id exp top_level lenv lmem stack -> (lenv,lmem) @@ -1186,7 +1173,7 @@ end let rec update_stack_state stack ((LMem name c mem _) as lmem) = match stack with | Top -> Top - | Hole_frame id oe t_level env (LMem _ _ _ s) Top -> + | Hole_frame id oe t_level env (LMem _ _ _ s) Top -> (match Map.lookup (0 : nat) mem with | Nothing -> Thunk_frame oe t_level (add_to_env (id,V_unknown) env) (LMem name c mem s) Top | Just v -> Thunk_frame oe t_level (add_to_env (id, v) env) (LMem name c (Map.delete (0 : nat) mem) s) Top end) @@ -1216,106 +1203,115 @@ end (*functions for converting in progress evaluation back into expression for building current continuation*) let rec combine_typs ts = match ts with - | [] -> T_var "fresh" + | [] -> mk_typ_var "fresh" | [t] -> t | t::ts -> let t' = combine_typs ts in - match (t,t') with - | (_,T_var _) -> t - | ((T_app "range" (T_args [T_arg_nexp (Ne_const bot1); T_arg_nexp (Ne_const top1)])), - (T_app "range" (T_args [T_arg_nexp (Ne_const bot2); T_arg_nexp (Ne_const top2)]))) -> + match (t,t') with + | (_,Typ_aux (Typ_var _) _) -> t + | ((Typ_aux (Typ_app (Id_aux (Id "range") _) + [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant bot1) _)) _; Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant top1) _)) _]) _), + (Typ_aux (Typ_app (Id_aux (Id "range") _) + [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant bot2) _)) _; Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant top2) _)) _]) _)) -> let (smallest,largest) = if bot1 <= bot2 then if top1 <= top2 then (bot1, top2) else (bot1, top1) else if top1 <= top2 then (bot2, top2) else (bot2, top1) in - T_app "range" (T_args [T_arg_nexp (Ne_const smallest); T_arg_nexp (Ne_const largest)]) - | ((T_app "atom" (T_args [T_arg_nexp (Ne_const a1);])), (T_app "atom" (T_args [T_arg_nexp (Ne_const a2);]))) -> + mk_typ_app "range" [Typ_arg_nexp (nconstant smallest); Typ_arg_nexp (nconstant largest)] + | ((Typ_aux (Typ_app (Id_aux (Id "atom") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant a1) _)) _]) _), + (Typ_aux (Typ_app (Id_aux (Id "atom") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant a2) _)) _]) _)) -> if a1 = a2 then t else let (smaller,larger) = if a1 < a2 then (a1,a2) else (a2,a1) in - T_app "range" (T_args [T_arg_nexp (Ne_const smaller); T_arg_nexp (Ne_const larger)]) - | (T_app "range" (T_args [T_arg_nexp (Ne_const bot); T_arg_nexp (Ne_const top)]), - T_app "atom" (T_args [T_arg_nexp (Ne_const a)])) -> + mk_typ_app "range" [Typ_arg_nexp (nconstant smaller); Typ_arg_nexp (nconstant larger)] + | (Typ_aux (Typ_app (Id_aux (Id "range") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant bot) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant top) _)) _]) _, + Typ_aux (Typ_app (Id_aux (Id "atom") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant a) _)) _]) _) -> if bot <= a && a <= top then t else if bot <= a && top <= a - then T_app "range" (T_args [T_arg_nexp (Ne_const bot); T_arg_nexp (Ne_const a)]) - else T_app "range" (T_args [T_arg_nexp (Ne_const a); T_arg_nexp (Ne_const top)]) - | (T_app "atom" (T_args [T_arg_nexp (Ne_const a)]), - T_app "range" (T_args [T_arg_nexp (Ne_const bot); T_arg_nexp (Ne_const top)])) -> + then mk_typ_app "range" [Typ_arg_nexp (nconstant bot); Typ_arg_nexp (nconstant a)] + else mk_typ_app "range" [Typ_arg_nexp (nconstant a); Typ_arg_nexp (nconstant top)] + | (Typ_aux (Typ_app (Id_aux (Id "atom") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant a) _)) _]) _, + Typ_aux (Typ_app (Id_aux (Id "range") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant bot) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant top) _)) _]) _) -> if bot <= a && a <= top then t else if bot <= a && top <= a - then T_app "range" (T_args [T_arg_nexp (Ne_const bot); T_arg_nexp (Ne_const a)]) - else T_app "range" (T_args [T_arg_nexp (Ne_const a); T_arg_nexp (Ne_const top)]) - | ((T_app "vector" (T_args [T_arg_nexp (Ne_const b1); T_arg_nexp (Ne_const r1); - T_arg_order (Ord_aux o1 _); T_arg_typ t1])), - (T_app "vector" (T_args [T_arg_nexp (Ne_const b2); T_arg_nexp (Ne_const r2); - T_arg_order (Ord_aux o2 _); T_arg_typ t2]))) -> - let t = combine_typs [t1;t2] in + then mk_typ_app "range" [Typ_arg_nexp (nconstant bot); Typ_arg_nexp (nconstant a)] + else mk_typ_app "range" [Typ_arg_nexp (nconstant a); Typ_arg_nexp (nconstant top)] + | (Typ_aux (Typ_app (Id_aux (Id "vector") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant b1) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant r1) _)) _; + Typ_arg_aux (Typ_arg_order (Ord_aux o1 _)) _; + Typ_arg_aux (Typ_arg_typ t1) _]) _, + Typ_aux (Typ_app (Id_aux (Id "vector") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant b2) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant r2) _)) _; + Typ_arg_aux (Typ_arg_order (Ord_aux o2 _)) _; + Typ_arg_aux (Typ_arg_typ t2) _]) _) -> + let t = combine_typs [t1;t2] in match (o1,o2) with | (Ord_inc,Ord_inc) -> let larger_start = if b1 < b2 then b2 else b1 in let smaller_rise = if r1 < r2 then r1 else r2 in - (T_app "vector" (T_args [T_arg_nexp (Ne_const larger_start); T_arg_nexp (Ne_const smaller_rise); - (T_arg_order (Ord_aux o1 Unknown)); T_arg_typ t])) + mk_typ_app "vector" [Typ_arg_nexp (nconstant larger_start); Typ_arg_nexp (nconstant smaller_rise); + Typ_arg_order (Ord_aux o1 Unknown); Typ_arg_typ t] | (Ord_dec,Ord_dec) -> let smaller_start = if b1 < b2 then b1 else b2 in let smaller_fall = if r1 < r2 then r2 else r2 in - (T_app "vector" (T_args [T_arg_nexp (Ne_const smaller_start); T_arg_nexp (Ne_const smaller_fall); - (T_arg_order (Ord_aux o1 Unknown)); T_arg_typ t])) - | _ -> T_var "fresh" - end + mk_typ_app "vector" [Typ_arg_nexp (nconstant smaller_start); Typ_arg_nexp (nconstant smaller_fall); + Typ_arg_order (Ord_aux o1 Unknown); Typ_arg_typ t] + | _ -> mk_typ_var "fresh" + end | _ -> t' - end + end end let reg_to_t r = match r with | Form_Reg _ (Just (t,_,_,_,_)) _ -> t - | _ -> T_var "fresh" + | _ -> mk_typ_var "fresh" end let rec val_typ v = match v with - | V_boxref n t -> T_app "reg" (T_args [T_arg_typ t]) + | V_boxref n t -> mk_typ_app "reg" [Typ_arg_typ t] | V_lit (L_aux lit _) -> match lit with - | L_unit -> T_id "unit" - | L_true -> T_id "bit" - | L_false -> T_id "bit" - | L_one -> T_id "bit" - | L_zero -> T_id "bit" - | L_string _ -> T_id "string" - | L_num n -> T_app "atom" (T_args [T_arg_nexp (Ne_const n);]) - | L_undef -> T_var "fresh" + | L_unit -> mk_typ_id "unit" + | L_true -> mk_typ_id "bit" + | L_false -> mk_typ_id "bit" + | L_one -> mk_typ_id "bit" + | L_zero -> mk_typ_id "bit" + | L_string _ -> mk_typ_id "string" + | L_num n -> mk_typ_app "atom" [Typ_arg_nexp (nconstant n)] + | L_undef -> mk_typ_var "fresh" | L_hex _ -> Assert_extra.failwith "literal hex not removed" | L_bin _ -> Assert_extra.failwith "literal bin not removed" - end - | V_tuple vals -> T_tup (List.map val_typ vals) - | V_vector n dir vals -> + end + | V_tuple vals -> mk_typ_tup (List.map val_typ vals) + | V_vector n dir vals -> let ts = List.map val_typ vals in let t = combine_typs ts in - T_app "vector" (T_args [T_arg_nexp (Ne_const (integerFromNat n)); T_arg_nexp (Ne_const (list_length vals)); - T_arg_order (Ord_aux (if is_inc(dir) then Ord_inc else Ord_dec) Unknown); - T_arg_typ t]) + mk_typ_app "vector" [Typ_arg_nexp (nconstant (integerFromNat n)); Typ_arg_nexp (nconstant (list_length vals)); + Typ_arg_order (Ord_aux (if is_inc dir then Ord_inc else Ord_dec) Unknown); + Typ_arg_typ t] | V_vector_sparse n m dir vals d -> let ts = List.map val_typ (d::(List.map snd vals)) in let t = combine_typs ts in - T_app "vector" (T_args [T_arg_nexp (Ne_const (integerFromNat n)); T_arg_nexp (Ne_const (integerFromNat m)); - T_arg_order (Ord_aux (if is_inc(dir) then Ord_inc else Ord_dec) Unknown); - T_arg_typ t]) + mk_typ_app "vector" [Typ_arg_nexp (nconstant (integerFromNat n)); Typ_arg_nexp (nconstant (integerFromNat m)); + Typ_arg_order (Ord_aux (if is_inc dir then Ord_inc else Ord_dec) Unknown); + Typ_arg_typ t] | V_record t ivals -> t - | V_list vals -> + | V_list vals -> let ts = List.map val_typ vals in let t = combine_typs ts in - T_app "list" (T_args [T_arg_typ t]) + mk_typ_app "list" [Typ_arg_typ t] | V_ctor id t _ vals -> t | V_register reg -> reg_to_t reg | V_track v _ -> val_typ v - | V_unknown -> T_var "fresh" (*consider carrying the type along*) - | V_register_alias _ _ -> T_var "fresh_alias" + | V_unknown -> mk_typ_var "fresh" + | V_register_alias _ _ -> mk_typ_var "fresh" end let rec to_exp mode env v : (exp tannot * lenv) = @@ -1324,37 +1320,36 @@ let rec to_exp mode env v : (exp tannot * lenv) = val env_to_let : interp_mode -> lenv -> (exp tannot) -> lenv -> ((exp tannot) * lenv) let rec env_to_let_help mode env taint_env = match env with | [] -> ([],taint_env) - | (i,v)::env -> + | (i,v)::env -> let t = (val_typ v) in let tan = (val_annot t) in let (e,taint_env) = to_exp mode taint_env v in let (rest,taint_env) = env_to_let_help mode env taint_env in ((((P_aux (P_id (id_of_string i)) (Unknown,tan)),e),t)::rest, taint_env) -end +end -let env_to_let mode (LEnv _ env) (E_aux e annot) taint_env = +let env_to_let mode (LEnv _ env) (E_aux e annot) taint_env = match env_to_let_help mode (Set_extra.toList (Map.toSet env)) taint_env with | ([],taint_env) -> (E_aux e annot,taint_env) | ([((p,e),t)],tain_env) -> - (E_aux (E_let (LB_aux (LB_val_implicit p e) (Unknown,(val_annot t))) e) annot,taint_env) + (E_aux (E_let (LB_aux (LB_val p e) (Unknown,(val_annot t))) e) annot,taint_env) | (pts,taint_env) -> let ts = List.map snd pts in let pes = List.map fst pts in let ps = List.map fst pes in let es = List.map snd pes in - let t = T_tup ts in + let t = mk_typ_tup ts in let tan = val_annot t in - (E_aux (E_let (LB_aux (LB_val_implicit (P_aux (P_tup ps) (Unknown,tan)) + (E_aux (E_let (LB_aux (LB_val (P_aux (P_tup ps) (Unknown,tan)) (E_aux (E_tuple es) (Unknown,tan))) (Unknown,tan)) (E_aux e annot)) annot, taint_env) -end +end -let fix_up_nondet typ branches annot = +let fix_up_nondet typ branches annot = match typ with - | T_id "unit" -> (branches, Nothing) - | T_abbrev _ (T_id "unit") -> (branches, Nothing) - | _ -> ((List.map + | Typ_aux (Typ_id (Id_aux (Id "unit") _)) _ -> (branches, Nothing) + | _ -> ((List.map (fun e -> E_aux (E_assign (LEXP_aux (LEXP_id redex_id) annot) e) annot) branches), Just "0") end @@ -1364,25 +1359,25 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = let (Env fdefs instrs default_dir lets regs ctors subregs aliases debug) = t_level in let (t,tag,cs) = match annot with | Just(t,tag,cs,e,_) -> (t,tag,cs) - | Nothing -> (T_var "fresh",Tag_empty,[]) end in + | Nothing -> (mk_typ_var "fresh",Tag_empty,[]) end in let value = detaint value_whole in let taint_pat v = binary_taint (fun v _ -> v) v value_whole in - match p with + match p with | P_lit(lit) -> if is_lit_vector lit then let (n, inc, bits) = match litV_to_vec lit default_dir with | V_vector n inc bits -> (n, inc, bits) - | _ -> Assert_extra.failwith "litV_to_vec failed" end in + | _ -> Assert_extra.failwith "litV_to_vec failed" end in match value with - | V_lit litv -> - if is_lit_vector litv then + | V_lit litv -> + if is_lit_vector litv then let (n', inc', bits') = match litV_to_vec litv default_dir with | V_vector n' inc' bits' -> (n', inc', bits') - | _ -> Assert_extra.failwith "litV_to_vec failed" end in + | _ -> Assert_extra.failwith "litV_to_vec failed" end in if n=n' && inc = inc' then (foldr2 (fun l r rest -> (l = r) && rest) true bits bits',false, eenv) else (false,false,eenv) else (false,false,eenv) - | V_vector n' inc' bits' -> + | V_vector n' inc' bits' -> (foldr2 (fun l r rest -> (l=r) && rest) true bits bits',false,eenv) | V_unknown -> (true,true,eenv) | _ -> (false,false,eenv) end @@ -1394,16 +1389,16 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = | _ -> (false,false,eenv) end | P_wild -> (true,false,eenv) - | P_as pat id -> + | P_as pat id -> let (matched_p,used_unknown,bounds) = match_pattern t_level pat value in if matched_p then (matched_p,used_unknown,(add_to_env (id,value_whole) bounds)) else (false,false,eenv) - | P_typ typ pat -> match_pattern t_level pat value_whole + | P_typ typ pat -> match_pattern t_level pat value_whole | P_id id -> (true, false, (LEnv 0 (Map.fromList [((get_id id),value_whole)]))) - | P_app (Id_aux id _) pats -> + | P_app (Id_aux id _) pats -> match value with - | V_ctor (Id_aux cid _) t ckind (V_tuple vals) -> + | V_ctor (Id_aux cid _) t ckind (V_tuple vals) -> if (id = cid && ((List.length pats) = (List.length vals))) then foldr2 (fun pat value (matched_p,used_unknown,bounds) -> @@ -1412,7 +1407,7 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = (matched_p, (used_unknown || used_unknown'), (union_env new_bounds bounds)) else (false,false,eenv)) (true,false,eenv) pats vals else (false,false,eenv) - | V_ctor (Id_aux cid _) t ckind (V_track (V_tuple vals) r) -> + | V_ctor (Id_aux cid _) t ckind (V_track (V_tuple vals) r) -> if (id = cid && ((List.length pats) = (List.length vals))) then foldr2 (fun pat value (matched_p,used_unknown,bounds) -> @@ -1430,10 +1425,10 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = | _ -> (false,false,eenv) end) else (false,false,eenv) | V_lit (L_aux (L_num i) _) -> - match tag with - | Tag_enum _ -> + match tag with + | Tag_enum _ -> match Map.lookup (get_id (Id_aux id Unknown)) lets with - | Just(V_ctor _ t (C_Enum j) _) -> + | Just(V_ctor _ t (C_Enum j) _) -> if i = (integerFromNat j) then (true,false,eenv) else (false,false,eenv) | _ -> (false,false,eenv) end @@ -1454,13 +1449,13 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = else (false,false,eenv)) (true,false,eenv) fpats | V_unknown -> (true,true,eenv) | _ -> (false,false,eenv) - end + end | P_vector pats -> match value with | V_vector n dir vals -> if ((List.length vals) = (List.length pats)) then foldr2 - (fun pat value (matched_p,used_unknown,bounds) -> + (fun pat value (matched_p,used_unknown,bounds) -> if matched_p then let (matched_p,used_unknown',new_bounds) = match_pattern t_level pat (taint_pat value) in (matched_p, (used_unknown||used_unknown'), (union_env new_bounds bounds)) @@ -1472,8 +1467,8 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = then let (_,matched_p,used_unknown,bounds) = foldr (fun pat (i,matched_p,used_unknown,bounds) -> - if matched_p - then let (matched_p,used_unknown',new_bounds) = + if matched_p + then let (matched_p,used_unknown',new_bounds) = match_pattern t_level pat (match List.lookup i vals with | Nothing -> d | Just v -> (taint_pat v) end) in @@ -1485,49 +1480,23 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = | V_unknown -> (true,true,eenv) | _ -> (false,false,eenv) end - | P_vector_indexed ipats -> - match value with - | V_vector n dir vals -> - let v_len = if is_inc(dir) then List.length vals + n else n - List.length vals in - List.foldr - (fun (i,pat) (matched_p,used_unknown,bounds) -> - let i = natFromInteger i in - if matched_p && i < v_len then - let (matched_p,used_unknown',new_bounds) = - match_pattern t_level pat (taint_pat (list_nth vals (if is_inc(dir) then i+n else i-n))) in - (matched_p,used_unknown||used_unknown',(union_env new_bounds bounds)) - else (false,false,eenv)) - (true,false,eenv) ipats - | V_vector_sparse n m dir vals d -> - List.foldr - (fun (i,pat) (matched_p,used_unknown,bounds) -> - let i = natFromInteger i in - if matched_p && i < m then - let (matched_p,used_unknown',new_bounds) = - match_pattern t_level pat (match List.lookup i vals with | Nothing -> d | Just v -> (taint_pat v) end) in - (matched_p,used_unknown||used_unknown',(union_env new_bounds bounds)) - else (false,false,eenv)) - (true,false,eenv) ipats - | V_unknown -> (true,true,eenv) - | _ -> (false,false, eenv) - end | P_vector_concat pats -> match value with | V_vector n dir vals -> let (matched_p,used_unknown,bounds,remaining_vals) = vec_concat_match_top t_level pats vals dir in - (*List.foldl + (*List.foldl (fun (matched_p,used_unknown,bounds,r_vals) (P_aux pat (l,Just(t,_,_,_))) -> let (matched_p,used_unknown',bounds',matcheds,r_vals) = vec_concat_match_plev t_level pat r_vals inc l t in (matched_p,(used_unknown || used_unknown'),(union_env bounds' bounds),r_vals)) (true,false,eenv,vals) pats in*) - if matched_p && ([] = remaining_vals) then (matched_p,used_unknown,bounds) else (false,false,eenv) + if matched_p && ([] = remaining_vals) then (matched_p,used_unknown,bounds) else (false,false,eenv) | V_unknown -> (true,true,eenv) - | _ -> (false,false, eenv) + | _ -> (false,false, eenv) end | P_tup(pats) -> - match value with + match value with | V_tuple(vals) -> if ((List.length pats)= (List.length vals)) - then foldr2 + then foldr2 (fun pat v (matched_p,used_unknown,bounds) -> if matched_p then let (matched_p,used_unknown',new_bounds) = match_pattern t_level pat (taint_pat v) in (matched_p,used_unknown ||used_unknown', (union_env new_bounds bounds)) @@ -1536,12 +1505,12 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = else (false,false,eenv) | V_unknown -> (true,true,eenv) | _ -> (false,false,eenv) - end + end | P_list(pats) -> - match value with + match value with | V_list(vals) -> if ((List.length pats)= (List.length vals)) - then foldr2 + then foldr2 (fun pat v (matched_p,used_unknown,bounds) -> if matched_p then let (matched_p,used_unknown',new_bounds) = match_pattern t_level pat (taint_pat v) in (matched_p,used_unknown|| used_unknown', (union_env new_bounds bounds)) @@ -1550,12 +1519,12 @@ let rec match_pattern t_level (P_aux p (_, annot)) value_whole = else (false,false,eenv) | V_unknown -> (true,true,eenv) | _ -> (false,false,eenv) end - end + end and vec_concat_match_top t_level pats r_vals dir : ((*matched_p*) bool * (*used_unknown*) bool * lenv * (list value)) = match pats with | [] -> (true,false,eenv,r_vals) - | [(P_aux p (l,Just(t,_,_,_,_)))] -> + | [(P_aux p (l,Just(t,_,_,_,_)))] -> let (matched_p,used_unknown,bounds,_,r_vals) = vec_concat_match_plev t_level p r_vals dir l true t in (matched_p,used_unknown,bounds,r_vals) | (P_aux p (l,Just(t,_,_,_,_)))::pats -> @@ -1571,8 +1540,8 @@ and vec_concat_match_plev t_level pat r_vals dir l last_pat t = match pat with | P_lit (L_aux (L_bin bin_string) l') -> let bin_chars = toCharList bin_string in - let binpats = List.map - (fun b -> P_aux (match b with + let binpats = List.map + (fun b -> P_aux (match b with | #'0' -> P_lit (L_aux L_zero l') | #'1' -> P_lit (L_aux L_one l') | _ -> Assert_extra.failwith "bin not 0 or 1" end) (l',Nothing)) bin_chars in @@ -1580,62 +1549,53 @@ and vec_concat_match_plev t_level pat r_vals dir l last_pat t = | P_vector pats -> vec_concat_match t_level pats r_vals | P_id id -> (match t with - | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp (Ne_const i);_;_]) -> + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [_;Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant i) _)) _;_;_]) _ -> let wilds = List.genlist (fun _ -> P_aux P_wild (l,Nothing)) (natFromInteger i) in let (matched_p,used_unknown,bounds,matcheds,r_vals) = vec_concat_match t_level wilds r_vals in - if matched_p - then (matched_p, used_unknown, + if matched_p + then (matched_p, used_unknown, (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length matcheds) - 1)) dir matcheds)) bounds), matcheds,r_vals) else (false,false,eenv,[],[]) - | T_abbrev _ (T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp (Ne_const i);_;_])) -> - let wilds = List.genlist (fun _ -> P_aux P_wild (l,Nothing)) (natFromInteger i) in - let (matched_p,used_unknown,bounds,matcheds,r_vals) = vec_concat_match t_level wilds r_vals in - if matched_p - then (matched_p, used_unknown, - (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length matcheds) - 1)) dir matcheds)) - bounds), - matcheds,r_vals) - else (false,false,eenv,[],[]) - | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp nc;_;_]) -> - if last_pat - then - (true,false, - (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length r_vals) - 1)) dir r_vals)) eenv), - r_vals,[]) - else (false,false,eenv,[],[]) (*TODO use some constraint bounds here*) - | _ -> - if last_pat - then - (true,false, - (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length r_vals) -1 )) dir r_vals)) eenv), - r_vals,[]) - else (false,false,eenv,[],[]) end) + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [_;Typ_arg_aux (Typ_arg_nexp nc) _;_;_]) _ -> + if last_pat + then + (true,false, + (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length r_vals) - 1)) dir r_vals)) eenv), + r_vals,[]) + else (false,false,eenv,[],[]) (*TODO use some constraint bounds here*) + | _ -> + if last_pat + then + (true,false, + (add_to_env (id,(V_vector (if is_inc(dir) then 0 else ((List.length r_vals) -1 )) dir r_vals)) eenv), + r_vals,[]) + else (false,false,eenv,[],[]) end) | P_wild -> (match t with - | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp (Ne_const i);_;_]) -> + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [_;Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant i) _)) _;_;_]) _ -> let wilds = List.genlist (fun _ -> P_aux P_wild (l,Nothing)) (natFromInteger i) in - vec_concat_match t_level wilds r_vals - | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp nc;_;_]) -> + vec_concat_match t_level wilds r_vals + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [_;Typ_arg_aux (Typ_arg_nexp nc) _;_;_]) _ -> if last_pat - then + then (true,false,eenv,r_vals,[]) else (false,false,eenv,[],[]) (*TODO use some constraint bounds here*) - | _ -> + | _ -> if last_pat - then + then (true,false,eenv,r_vals,[]) else (false,false,eenv,[],[]) end) - | P_as (P_aux pat (l',Just(t',_,_,_,_))) id -> + | P_as (P_aux pat (l',Just(t',_,_,_,_))) id -> let (matched_p, used_unknown, bounds,matcheds,r_vals) = vec_concat_match_plev t_level pat r_vals dir l last_pat t' in - if matched_p + if matched_p then (matched_p, used_unknown, (add_to_env (id,V_vector (if is_inc(dir) then 0 else (List.length matcheds)) dir matcheds) bounds), matcheds,r_vals) - else (false,false,eenv,[],[]) + else (false,false,eenv,[],[]) | P_typ _ (P_aux p (l',Just(t',_,_,_,_))) -> vec_concat_match_plev t_level p r_vals dir l last_pat t - | _ -> (false,false,eenv,[],[]) end + | _ -> (false,false,eenv,[],[]) end (*TODO Need to support indexed here, skipping intermediate numbers but consumming r_vals, and as *) and vec_concat_match t_level pats r_vals = @@ -1645,7 +1605,7 @@ and vec_concat_match t_level pats r_vals = | [] -> (false,false,eenv,[],[]) | r::r_vals -> let (matched_p,used_unknown,new_bounds) = match_pattern t_level pat r in - if matched_p then + if matched_p then let (matched_p,used_unknown',bounds,matcheds,r_vals) = vec_concat_match t_level pats r_vals in (matched_p, used_unknown||used_unknown',(union_env new_bounds bounds),r :: matcheds,r_vals) else (false,false,eenv,[],[]) end @@ -1670,7 +1630,7 @@ val find_case : top_level -> list (pexp tannot) -> value -> list (lenv * bool * let rec find_case t_level pexps value = match pexps with | [] -> [] - | (Pat_aux (Pat_exp p e) _)::pexps -> + | (Pat_aux (Pat_exp p e) _)::pexps -> let (is_matching,used_unknown,env) = match_pattern t_level p value in if (is_matching && used_unknown) then (env,used_unknown,e)::find_case t_level pexps value @@ -1731,10 +1691,10 @@ let update_stack o fn = match o with | _ -> o end -let debug_out fn value e tl lm le = +let debug_out fn value e tl lm le = (Action (Step (get_exp_l e) fn value) (Thunk_frame e tl le lm Top),lm,le) -let to_exps mode env vals = +let to_exps mode env vals = List.foldr (fun v (es,env) -> let (e,env') = to_exp mode env v in (e::es, union_env env' env)) ([],env) vals let get_num v = match v with @@ -1745,12 +1705,12 @@ let get_num v = match v with let rec __exp_list mode t_level build_e build_v l_env l_mem vals exps = match exps with | [ ] -> (Value (build_v vals), l_mem, l_env) - | e::exps -> + | e::exps -> resolve_outcome (interp_main mode t_level l_env l_mem e) (fun value lm le -> exp_list mode t_level build_e build_v l_env lm (vals++[value]) exps) - (fun a -> update_stack a (add_to_top_frame - (fun e env -> - let (es,env') = to_exps mode env vals in + (fun a -> update_stack a (add_to_top_frame + (fun e env -> + let (es,env') = to_exps mode env vals in let (e,env'') = build_e (es++(e::exps)) env' in (e,env'')))) end @@ -1763,62 +1723,62 @@ and exp_list mode t_level build_e build_v l_env l_mem vals exps = and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = let (Env fdefs instrs default_dir lets regs ctors subregs aliases debug) = t_level in - let (typ,tag,ncs,effect,reffect) = match annot with + let (typ,tag,ncs,effect,reffect) = match annot with | Nothing -> - (T_var "fresh_v", Tag_empty,[],(Effect_aux (Effect_set []) Unknown),(Effect_aux (Effect_set []) Unknown)) + (mk_typ_var "fresh_v", Tag_empty,[],(Effect_aux (Effect_set []) Unknown),(Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef,efr) -> (t,tag,ncs,ef,efr) end in match exp with | E_internal_value v -> (Value v, l_mem, l_env) - | E_lit lit -> - if is_lit_vector lit - then let is_inc = (match typ with - | T_app "vector" (T_args [_;_;T_arg_order (Ord_aux Ord_inc _);_]) -> IInc | _ -> IDec end) in - (Value (litV_to_vec lit is_inc),l_mem,l_env) + | E_lit lit -> + if is_lit_vector lit + then let is_inc = (match typ with + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [_;_;Typ_arg_aux (Typ_arg_order (Ord_aux Ord_inc _)) _;_]) _ -> IInc | _ -> IDec end) in + (Value (litV_to_vec lit is_inc),l_mem,l_env) else (Value (V_lit (match lit with | L_aux L_false loc -> L_aux L_zero loc | L_aux L_true loc -> L_aux L_one loc | _ -> lit end)), l_mem,l_env) | E_comment _ -> (Value unitv, l_mem,l_env) - | E_comment_struc _ -> (Value unitv, l_mem, l_env) - | E_cast ((Typ_aux typ _) as ctyp) exp -> + | E_comment_struc _ -> (Value unitv, l_mem, l_env) + | E_cast ((Typ_aux typ _) as ctyp) exp -> (*Cast is either a no-op, a signal to read a register, or a signal to change the start of a vector *) - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem exp) - (fun v lm le -> + (fun v lm le -> (* Potentially use cast to change vector start position *) let conditional_update_vstart () = match typ with | Typ_app (Id_aux (Id "vector") _) [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i) _)) _;_;_;_] -> let i = natFromInteger i in - match (detaint v) with + match (detaint v) with | V_vector start dir vs -> if start = i then (Value v,lm,le) else (Value (update_vector_start dir i 1 v),lm,le) | _ -> (Value v,lm,le) end | (Typ_var (Kid_aux (Var "length") _))-> - match (detaint v) with + match (detaint v) with | V_vector start dir vs -> let i = (List.length vs) - 1 in if start = i then (Value v,lm,le) else (Value (update_vector_start dir i 1 v),lm,le) | _ -> (Value v,lm,le) end | _ -> (Value v,lm,le) end in - (match (tag,detaint v) with + (match (tag,detaint v) with (*Cast is telling us to read a register*) | (Tag_extern _, V_register regform) -> (Action (Read_reg regform Nothing) (mk_hole l (val_annot (reg_to_t regform)) t_level le lm), lm,le) (*Cast is changing vector start position, potentially*) | (_,v) -> conditional_update_vstart () end)) (fun a -> update_stack a (add_to_top_frame (fun e env -> (E_aux (E_cast ctyp e) (l,annot), env)))) - | E_id id -> + | E_id id -> let name = get_id id in match tag with - | Tag_empty -> + | Tag_empty -> match in_lenv l_env id with | V_boxref n t -> (Value (in_mem l_mem n),l_mem,l_env) | value -> (Value value,l_mem,l_env) end | Tag_global -> match in_env lets name with | Just(value) -> (Value value, l_mem,l_env) - | Nothing -> + | Nothing -> (match in_env regs name with | Just(value) -> (Value value, l_mem,l_env) | Nothing -> (Error l ("Internal error: " ^ name ^ " unbound on Tag_global"),l_mem,l_env) end) end @@ -1826,28 +1786,28 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = match in_env lets name with | Just(value) -> (Value value,l_mem,l_env) | Nothing -> (Error l ("Internal error: " ^ name ^ " unbound on Tag_enum "), l_mem,l_env) - end + end | Tag_extern _ -> (* update with id here when it's never just "register" *) let regf = match in_lenv l_env id with (* Check for local treatment of a register as a value *) | V_register regform -> regform - | _ -> + | _ -> match in_env regs name with (* Register isn't a local value, so pull from global environment *) | Just(V_register regform) -> regform | _ -> Form_Reg id annot default_dir end end in (Action (Read_reg regf Nothing) (mk_hole l annot t_level l_env l_mem), l_mem, l_env) - | Tag_alias -> + | Tag_alias -> match in_env aliases name 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 + | _ -> + (Error l ("Internal error: tag " ^ (string_of_tag tag) ^ " expected empty,enum,alias,or extern for " ^ name), l_mem,l_env) end | E_if cond thn els -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem cond) - (fun value_whole lm le -> + (fun value_whole lm le -> let value = detaint value_whole in match (value,mode.eager_eval) with (*TODO remove booleans here when fully removed elsewhere *) @@ -1855,36 +1815,36 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | (V_lit(L_aux L_one _),false) -> debug_out Nothing Nothing thn t_level lm l_env | (V_vector _ _ [(V_lit(L_aux L_one _))],true) -> interp_main mode t_level l_env lm thn | (V_vector _ _ [(V_lit(L_aux L_one _))],false) -> debug_out Nothing Nothing thn t_level lm l_env - | (V_unknown,_) -> + | (V_unknown,_) -> let (branches,maybe_id) = fix_up_nondet typ [thn;els] (l,annot) in interp_main mode t_level l_env lm (E_aux (E_nondet branches) (l,non_det_annot annot maybe_id)) - | (_,true) -> interp_main mode t_level l_env lm els + | (_,true) -> interp_main mode t_level l_env lm els | (_,false) -> debug_out Nothing Nothing els t_level lm l_env end) (fun a -> update_stack a (add_to_top_frame (fun c env -> (E_aux (E_if c thn els) (l,annot), env)))) | E_for id from to_ by ((Ord_aux o _) as order) exp -> let is_inc = match o with | Ord_inc -> true | _ -> false end in - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem from) (fun from_val_whole lm le -> let from_val = detaint from_val_whole in let (from_e,env) = to_exp mode le from_val_whole in match from_val with - | V_lit(L_aux(L_num from_num) fl) -> - resolve_outcome + | V_lit(L_aux(L_num from_num) fl) -> + resolve_outcome (interp_main mode t_level env lm to_) (fun to_val_whole lm le -> let to_val = detaint to_val_whole in let (to_e,env) = to_exp mode le to_val_whole in match to_val with | V_lit(L_aux (L_num to_num) tl) -> - resolve_outcome + resolve_outcome (interp_main mode t_level env lm by) (fun by_val_whole lm le -> let by_val = detaint by_val_whole in let (by_e,env) = to_exp mode le by_val_whole in - match by_val with + match by_val with | V_lit (L_aux (L_num by_num) bl) -> - if ((is_inc && (from_num > to_num)) || (not(is_inc) && (from_num < to_num))) + if ((is_inc && (from_num > to_num)) || (not(is_inc) && (from_num < to_num))) then (Value(V_lit (L_aux L_unit l)),lm,le) else let (ftyp,ttyp,btyp) = (val_typ from_val,val_typ to_val,val_typ by_val) in @@ -1894,95 +1854,95 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | (V_lit _, V_lit _) -> ((E_aux (E_lit diff) augment_annot), env) | (V_track _ rs, V_lit _) -> to_exp mode env (taint (V_lit diff) rs) | (V_lit _, V_track _ rs) -> to_exp mode env (taint (V_lit diff) rs) - | (V_track _ r1, V_track _ r2) -> + | (V_track _ r1, V_track _ r2) -> (to_exp mode env (taint (V_lit diff) (r1 union r2))) | _ -> Assert_extra.failwith "For loop from and by values not range" end in - let e = + let e = (E_aux - (E_block - [(E_aux - (E_let - (LB_aux (LB_val_implicit (P_aux (P_id id) (fl,val_annot ftyp)) from_e) + (E_block + [(E_aux + (E_let + (LB_aux (LB_val (P_aux (P_id id) (fl,val_annot ftyp)) from_e) (Unknown,val_annot ftyp)) exp) (l,annot)); (E_aux (E_for id augment_e to_e by_e order exp) (l,annot))]) (l,annot)) in if mode.eager_eval - then interp_main mode t_level env lm e + then interp_main mode t_level env lm e else debug_out Nothing Nothing e t_level lm env - | V_unknown -> - let e = + | V_unknown -> + let e = (E_aux - (E_let - (LB_aux - (LB_val_implicit (P_aux (P_id id) (fl, val_annot (val_typ from_val))) from_e) + (E_let + (LB_aux + (LB_val (P_aux (P_id id) (fl, val_annot (val_typ from_val))) from_e) (fl, val_annot (val_typ from_val))) exp) (l,annot)) in interp_main mode t_level env lm e | _ -> (Error l "internal error: by must be a number",lm,le) end) - (fun a -> update_stack a + (fun a -> update_stack a (add_to_top_frame (fun b env -> (E_aux (E_for id from_e to_e b order exp) (l,annot), env)))) - | V_unknown -> + | V_unknown -> let e = (E_aux (E_let (LB_aux - (LB_val_implicit (P_aux (P_id id) (fl, val_annot (val_typ from_val))) from_e) + (LB_val (P_aux (P_id id) (fl, val_annot (val_typ from_val))) from_e) (fl, val_annot (val_typ from_val))) exp) (l,annot)) in interp_main mode t_level env lm e | _ -> (Error l "internal error: to must be a number",lm,env) end) - (fun a -> update_stack a - (add_to_top_frame (fun t env -> + (fun a -> update_stack a + (add_to_top_frame (fun t env -> (E_aux (E_for id from_e t by order exp) (l,annot), env)))) | V_unknown -> let e = (E_aux - (E_let (LB_aux (LB_val_implicit (P_aux (P_id id) (Unknown, val_annot (val_typ from_val))) from_e) + (E_let (LB_aux (LB_val (P_aux (P_id id) (Unknown, val_annot (val_typ from_val))) from_e) (Unknown, val_annot (val_typ from_val))) exp) (l,annot)) in interp_main mode t_level env lm e | _ -> (Error l "internal error: from must be a number",lm,le) end) (fun a -> update_stack a (add_to_top_frame (fun f env -> (E_aux (E_for id f to_ by order exp) (l,annot), env)))) | E_case exp pats -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem exp) (fun v lm le -> match find_case t_level pats v with | [] -> (Error l ("No matching patterns in case for value " ^ (string_of_value v)),lm,le) - | [(env,_,exp)] -> + | [(env,_,exp)] -> if mode.eager_eval then interp_main mode t_level (union_env env l_env) lm exp else debug_out Nothing Nothing exp t_level lm (union_env env l_env) | multi_matches -> - let (lets,taint_env) = - List.foldr (fun (env,_,exp) (rst,taint_env) -> + let (lets,taint_env) = + List.foldr (fun (env,_,exp) (rst,taint_env) -> let (e,t_e) = env_to_let mode env exp taint_env in (e::rst,t_e)) ([],l_env) multi_matches in let (branches,maybe_id) = fix_up_nondet typ lets (l,annot) in interp_main mode t_level taint_env lm (E_aux (E_nondet branches) (l,(non_det_annot annot maybe_id))) end) (fun a -> update_stack a (add_to_top_frame (fun e env -> (E_aux (E_case e pats) (l,annot), env)))) - | E_record(FES_aux (FES_Fexps fexps _) fes_annot) -> + | E_record(FES_aux (FES_Fexps fexps _) fes_annot) -> let (fields,exps) = List.unzip (List.map (fun (FE_aux (FE_Fexp id exp) _) -> (id,exp)) fexps) in - exp_list mode t_level - (fun es env' -> - ((E_aux - (E_record - (FES_aux (FES_Fexps + exp_list mode t_level + (fun es env' -> + ((E_aux + (E_record + (FES_aux (FES_Fexps (map2 (fun id exp -> (FE_aux (FE_Fexp id exp) (Unknown,Nothing))) fields es) false) fes_annot)) (l,annot)), env')) (fun vs -> (V_record typ (List.zip fields vs))) l_env l_mem [] exps | E_record_update exp (FES_aux (FES_Fexps fexps _) fes_annot) -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem exp) (fun rv lm le -> match rv with | V_record t fvs -> let (fields,exps) = List.unzip (List.map (fun (FE_aux (FE_Fexp id exp) _) -> (id,exp)) fexps) in - resolve_outcome - (exp_list mode t_level - (fun es env'-> + resolve_outcome + (exp_list mode t_level + (fun es env'-> let (e,env'') = (to_exp mode env' rv) in - ((E_aux (E_record_update e - (FES_aux (FES_Fexps + ((E_aux (E_record_update e + (FES_aux (FES_Fexps (map2 (fun id exp -> (FE_aux (FE_Fexp id exp) (Unknown,Nothing))) fields es) false) fes_annot)) (l,annot)), env'')) @@ -1991,38 +1951,37 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (fun a -> a) (*Due to exp_list this won't happen, but we want to functionaly update on Value *) | V_unknown -> (Value V_unknown, lm, le) | _ -> (Error l "internal error: record update requires record",lm,le) end) - (fun a -> update_stack a - (add_to_top_frame + (fun a -> update_stack a + (add_to_top_frame (fun e env -> (E_aux(E_record_update e (FES_aux(FES_Fexps fexps false) fes_annot)) (l,annot), env)))) | E_list(exps) -> exp_list mode t_level (fun exps env' -> (E_aux (E_list exps) (l,annot),env')) V_list l_env l_mem [] exps | E_cons hd tl -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem hd) - (fun hdv lm le -> + (fun hdv lm le -> resolve_outcome (interp_main mode t_level l_env lm tl) - (fun tlv lm le -> match detaint tlv with + (fun tlv lm le -> match detaint tlv with | V_list t -> (Value (retaint tlv (V_list (hdv::t))),lm,le) | V_unknown -> (Value (retaint tlv V_unknown),lm,le) | _ -> (Error l ("Internal error '::' of non-list value " ^ (string_of_value tlv)),lm,le) end) - (fun a -> update_stack a - (add_to_top_frame + (fun a -> update_stack a + (add_to_top_frame (fun t env -> let (hde,env') = to_exp mode env hdv in (E_aux (E_cons hde t) (l,annot),env'))))) (fun a -> update_stack a (add_to_top_frame (fun h env -> (E_aux (E_cons h tl) (l,annot), env)))) - | E_field exp id -> - resolve_outcome + | E_field exp id -> + resolve_outcome (interp_main mode t_level l_env l_mem exp) - (fun value_whole lm le -> - match detaint value_whole with - | V_record t fexps -> + (fun value_whole lm le -> + match detaint value_whole with + | V_record t fexps -> (match in_env (env_from_list fexps) (get_id id) with | Just v -> (Value (retaint value_whole v),lm,l_env) | Nothing -> (Error l "Internal_error: Field not found in record",lm,le) end) | V_register ((Form_Reg _ annot _) as reg_form) -> let id' = match annot with - | Just((T_id id'),_,_,_,_) -> id' - | Just((T_abbrev (T_id id') _),_,_,_,_) -> id' + | Just((Typ_aux (Typ_id (Id_aux (Id id') _)) _),_,_,_,_) -> id' | _ -> Assert_extra.failwith "annotation not well formed for field access" end in (match in_env subregs id' with @@ -2035,32 +1994,22 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | _ -> (Error l "Internal error: unrecognized read, no id",lm,le) end) | Nothing -> (Error l "Internal error: subregs indexes not found", lm, le) end) | V_unknown -> (Value (retaint value_whole V_unknown),lm,l_env) - | _ -> - (Error l ("Internal error: neither register nor record at field access " + | _ -> + (Error l ("Internal error: neither register nor record at field access " ^ (string_of_value value_whole)),lm,le) end) - (fun a -> + (fun a -> match (exp,a) with | (E_aux _ (l,Just(_,Tag_extern _,_,_,_)), - (Action (Read_reg ((Form_Reg _ (Just((T_id id'),_,_,_,_)) _) as regf) Nothing) s)) -> + (Action (Read_reg ((Form_Reg _ (Just((Typ_aux (Typ_id (Id_aux (Id id') _)) _),_,_,_,_)) _) as regf) Nothing) s)) -> match in_env subregs id' with | Just(indexes) -> (match in_env indexes (get_id id) with - | Just ir -> - (Action (Read_reg (Form_SubReg id regf ir) Nothing) s) - | _ -> Error l "Internal error, unrecognized read, no id" - end) - | Nothing -> Error l "Internal error, unrecognized read, no reg" end - | (E_aux _ (l,Just(_,Tag_extern _,_,_,_)), - (Action (Read_reg ((Form_Reg _ (Just((T_abbrev (T_id id') _),_,_,_,_)) _) as regf) Nothing) s))-> - match in_env subregs id' with - | Just(indexes) -> - match in_env indexes (get_id id) with - | Just ir -> + | Just ir -> (Action (Read_reg (Form_SubReg id regf ir) Nothing) s) | _ -> Error l "Internal error, unrecognized read, no id" - end + end) | Nothing -> Error l "Internal error, unrecognized read, no reg" end - | _ -> update_stack a (add_to_top_frame (fun e env -> (E_aux(E_field e id) (l,annot),env))) end) + | _ -> update_stack a (add_to_top_frame (fun e env -> (E_aux(E_field e id) (l,annot),env))) end) | E_vector_access vec i -> resolve_outcome (interp_main mode t_level l_env l_mem vec) @@ -2261,130 +2210,95 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (E_aux (E_vector_append e1_e e2') (l,annot), env'))))) (fun a -> update_stack a (add_to_top_frame (fun e1' env -> (E_aux (E_vector_append e1' e2) (l,annot), env)))) - | E_tuple(exps) -> + | E_tuple(exps) -> exp_list mode t_level (fun exps env' -> (E_aux (E_tuple exps) (l,annot), env')) V_tuple l_env l_mem [] exps | E_vector(exps) -> let (is_inc,dir) = (match typ with - | T_app "vector" (T_args [ _; _; T_arg_order (Ord_aux Ord_inc _); _]) -> (true,IInc) + | Typ_aux (Typ_app (Id_aux (Id "vector") _) [ _; _; Typ_arg_aux (Typ_arg_order (Ord_aux Ord_inc _)) _; _]) _ -> (true,IInc) | _ -> (false,IDec) end) in let base = (if is_inc then 0 else (List.length exps) - 1) in - exp_list mode t_level - (fun exps env' -> (E_aux (E_vector exps) (l,annot),env')) + exp_list mode t_level + (fun exps env' -> (E_aux (E_vector exps) (l,annot),env')) (fun vals -> V_vector base dir vals) l_env l_mem [] exps - | E_vector_indexed iexps (Def_val_aux default dannot) -> - let (indexes,exps) = List.unzip iexps in - let (dir,base,len) = (match typ with - | T_app "vector" (T_args [T_arg_nexp base;T_arg_nexp len; T_arg_order (Ord_aux Ord_inc _); _]) -> - (IInc,base,len) - | T_app "vector" (T_args [T_arg_nexp base;T_arg_nexp len; T_arg_order (Ord_aux _ _); _]) -> - (IDec,base,len) - | _ -> Assert_extra.failwith "Vector type not as expected for indexed vector" end) in - (match default with - | Def_val_empty -> - exp_list mode t_level - (fun es env' -> (E_aux (E_vector_indexed (map2 (fun i e -> (i,e)) indexes es) - (Def_val_aux default dannot)) (l,annot), env')) - (fun vals -> V_vector (if indexes=[] then 0 else (natFromInteger (List_extra.head indexes))) dir vals) - l_env l_mem [] exps - | Def_val_dec default_exp -> - let (b,len) = match (base,len) with - | (Ne_const b,Ne_const l) -> (natFromInteger b, natFromInteger l) - | _ -> Assert_extra.failwith "Vector start and end unset in vector with default value" end in - resolve_outcome - (interp_main mode t_level l_env l_mem default_exp) - (fun v lm le -> - exp_list mode t_level - (fun es env' -> - let (ev,env'') = to_exp mode env' v in - (E_aux (E_vector_indexed (map2 (fun i e -> (i,e)) indexes es) - (Def_val_aux (Def_val_dec ev) dannot)) - (l,annot), env'')) - (fun vs -> - (V_vector_sparse b len dir - (map2 (fun i v -> ((natFromInteger i),v)) indexes vs) v)) l_env l_mem [] exps) - (fun a -> - update_stack a - (add_to_top_frame (fun e env -> - (E_aux (E_vector_indexed iexps (Def_val_aux (Def_val_dec e) dannot)) (l,annot), env)))) end) | E_block exps -> interp_block mode t_level l_env l_env l_mem l annot exps | E_nondet exps -> - (Action (Nondet exps tag) + (Action (Nondet exps tag) (match tag with - | Tag_unknown (Just id) -> mk_hole l annot t_level l_env l_mem + | Tag_unknown (Just id) -> mk_hole l annot t_level l_env l_mem | _ -> mk_thunk l annot t_level l_env l_mem end), l_mem, l_env) | E_app f args -> - (match (exp_list mode t_level + (match (exp_list mode t_level (fun es env -> (E_aux (E_app f es) (l,annot),env)) - (fun vs -> match vs with | [] -> V_lit (L_aux L_unit l) | [v] -> v | vs -> V_tuple vs end) + (fun vs -> match vs with | [] -> V_lit (L_aux L_unit l) | [v] -> v | vs -> V_tuple vs end) l_env l_mem [] args) with - | (Value v,lm,le) -> - let name = get_id f in + | (Value v,lm,le) -> + let name = get_id f in (match tag with | Tag_global -> (match Map.lookup name fdefs with - | Just(funcls) -> + | Just(funcls) -> (match find_funcl t_level funcls v with - | [] -> + | [] -> (Error l ("No matching pattern for function " ^ name ^ " on value " ^ (string_of_value v)),l_mem,l_env) | [(env,_,exp)] -> - resolve_outcome - (if mode.eager_eval + resolve_outcome + (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) - else (debug_out (Just name) (Just v) exp t_level (emem name) env)) + else (debug_out (Just name) (Just v) exp t_level (emem name) env)) (fun ret lm le -> (Value ret, l_mem,l_env)) - (fun a -> update_stack a + (fun a -> update_stack a (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))) | multi_matches -> - let (lets,taint_env) = - List.foldr (fun (env,_,exp) (rst,taint_env) -> + let (lets,taint_env) = + List.foldr (fun (env,_,exp) (rst,taint_env) -> let (e,t_e) = env_to_let mode env exp taint_env in (e::rst,t_e)) ([],l_env) multi_matches in let (branches,maybe_id) = fix_up_nondet typ lets (l,annot) in let exp = E_aux (E_nondet branches) (l,(non_det_annot annot maybe_id)) in interp_main mode t_level taint_env lm exp end) - | Nothing -> + | Nothing -> (Error l ("Internal error: function with tag global unfound " ^ name),lm,le) end) - | Tag_empty -> + | Tag_empty -> (match Map.lookup name fdefs with - | Just(funcls) -> + | Just(funcls) -> (match find_funcl t_level funcls v with - | [] -> + | [] -> (Error l ("No matching pattern for function " ^ name ^ " on value " ^ (string_of_value v)),l_mem,l_env) - | [(env,used_unknown,exp)] -> - resolve_outcome - (if mode.eager_eval + | [(env,used_unknown,exp)] -> + resolve_outcome + (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) - else (debug_out (Just name) (Just v) exp t_level (emem name) env)) + else (debug_out (Just name) (Just v) exp t_level (emem name) env)) (fun ret lm le -> (Value ret, l_mem,l_env)) - (fun a -> update_stack a + (fun a -> update_stack a (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))) | _ -> (Error l ("Internal error: multiple pattern matches found for " ^ name), l_mem, l_env) end) - | Nothing -> + | Nothing -> (Error l ("Internal error: function with local tag unfound " ^ name),lm,le) end) - | Tag_spec -> + | Tag_spec -> (match Map.lookup name fdefs with - | Just(funcls) -> + | Just(funcls) -> (match find_funcl t_level funcls v with - | [] -> + | [] -> (Error l ("No matching pattern for function " ^ name ^ " on value " ^ (string_of_value v)),l_mem,l_env) - | [(env,used_unknown,exp)] -> - resolve_outcome - (if mode.eager_eval + | [(env,used_unknown,exp)] -> + resolve_outcome + (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) else (debug_out (Just name) (Just v) exp t_level (emem name) env)) (fun ret lm le -> (Value ret, l_mem,l_env)) - (fun a -> update_stack a - (fun stack -> - (Hole_frame redex_id + (fun a -> update_stack a + (fun stack -> + (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))) | _ -> (Error l ("Internal error: multiple pattern matches for " ^ name), l_mem, l_env) end) - | Nothing -> + | Nothing -> (Error l (String.stringAppend "Specified function must be defined before executing " name),lm,le) end) | Tag_ctor -> (match Map.lookup name ctors with @@ -2396,10 +2310,10 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = let name_ext = match opt_name with | Just s -> s | Nothing -> name end in let mk_hole_frame act = (Action act (mk_hole l annot t_level le lm), lm, le) in let mk_thunk_frame act = (Action act (mk_thunk l annot t_level le lm), lm, le) in - if has_rmem_effect effects - then mk_hole_frame (Read_mem (id_of_string name_ext) v Nothing) - else if has_rmemt_effect effects - then mk_hole_frame (Read_mem_tagged (id_of_string name_ext) v Nothing) + if has_rmem_effect effects + then mk_hole_frame (Read_mem (id_of_string name_ext) v Nothing) + else if has_rmemt_effect effects + then mk_hole_frame (Read_mem_tagged (id_of_string name_ext) v Nothing) else if has_barr_effect effects then mk_thunk_frame (Barrier (id_of_string name_ext) v) else if has_depend_effect effects @@ -2407,11 +2321,11 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = else if has_wmem_effect effects then let (wv,v) = match v with - | V_tuple [p;v] -> (v,p) + | V_tuple [p;v] -> (v,p) | V_tuple params_list -> let reved = List.reverse params_list in (List_extra.head reved,V_tuple (List.reverse (List_extra.tail reved))) - | _ -> Assert_extra.failwith ("Expected tuple found " ^ (string_of_value v)) end in + | _ -> Assert_extra.failwith ("Expected tuple found " ^ (string_of_value v)) end in mk_hole_frame (Write_mem (id_of_string name_ext) v Nothing wv) else if has_eamem_effect effects then mk_thunk_frame (Write_ea (id_of_string name_ext) v) @@ -2428,57 +2342,57 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = mk_hole_frame (Write_memv (id_of_string name_ext) v wv) else if has_wmvt_effect effects then match v with - | V_tuple [addr; size; tag; data] -> + | V_tuple [addr; size; tag; data] -> mk_hole_frame (Write_memv_tagged (id_of_string name_ext) (V_tuple([addr; size])) tag data) | _ -> Assert_extra.failwith("wmvt: expected tuple of four elements") end - else mk_hole_frame (Call_extern name_ext v) + else mk_hole_frame (Call_extern name_ext v) | _ -> (Error l (String.stringAppend "Tag not empty, spec, ctor, or extern on function call " name),lm,le) end) | out -> out end) - | E_app_infix lft op r -> + | E_app_infix lft op r -> let op = match op with | Id_aux (Id x) il -> Id_aux (DeIid x) il | _ -> op end in let name = get_id op in - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem lft) - (fun lv lm le -> - resolve_outcome + (fun lv lm le -> + resolve_outcome (interp_main mode t_level l_env lm r) - (fun rv lm le -> + (fun rv lm le -> match tag with | Tag_global -> (match Map.lookup name fdefs with | Nothing -> (Error l ("Internal error: no function def for " ^ name),lm,le) | Just (funcls) -> - (match find_funcl t_level funcls (V_tuple [lv;rv]) with + (match find_funcl t_level funcls (V_tuple [lv;rv]) with | [] -> (Error l ("No matching pattern for function " ^ name),lm,l_env) | [(env,used_unknown,exp)] -> - resolve_outcome + resolve_outcome (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) - else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level (emem name) env)) + else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level (emem name) env)) (fun ret lm le -> (Value ret,l_mem,l_env)) - (fun a -> update_stack a - (fun stack -> + (fun a -> update_stack a + (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))) | _ -> (Error l ("Internal error: multiple pattern matches for " ^ name),lm,le) end)end) - | Tag_empty -> + | Tag_empty -> (match Map.lookup name fdefs with | Nothing -> (Error l ("Internal error: no function def for " ^ name),lm,le) | Just (funcls) -> - (match find_funcl t_level funcls (V_tuple [lv;rv]) with + (match find_funcl t_level funcls (V_tuple [lv;rv]) with | [] -> (Error l ("No matching pattern for function " ^ name),lm,l_env) | [(env,used_unknown,exp)] -> - resolve_outcome + resolve_outcome (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) - else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level (emem name) env)) + else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level (emem name) env)) (fun ret lm le -> (Value ret,l_mem,l_env)) - (fun a -> update_stack a + (fun a -> update_stack a (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,annot)) t_level l_env l_mem stack))) | _ -> (Error l ("Internal error: multiple pattern matches for " ^ name),lm,le) @@ -2487,15 +2401,15 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (match Map.lookup name fdefs with | Nothing -> (Error l ("Internal error: No function definition found for " ^ name),lm,le) | Just (funcls) -> - (match find_funcl t_level funcls (V_tuple [lv;rv]) with + (match find_funcl t_level funcls (V_tuple [lv;rv]) with | [] -> (Error l ("No matching pattern for function " ^ name),lm,l_env) | [(env,used_unknown,exp)] -> - resolve_outcome - (if mode.eager_eval + resolve_outcome + (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level (emem name) env)) (fun ret lm le -> (Value ret,l_mem,l_env)) - (fun a -> update_stack a + (fun a -> update_stack a (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))) @@ -2503,12 +2417,12 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = end)end) | Tag_extern ext_name -> let ext_name = match ext_name with Just s -> s | Nothing -> name end in - (Action (Call_extern ext_name (V_tuple [lv;rv])) - (Hole_frame redex_id + (Action (Call_extern ext_name (V_tuple [lv;rv])) + (Hole_frame redex_id (E_aux (E_id redex_id) (l,intern_annot annot)) t_level le lm Top),lm,le) | _ -> (Error l "Internal error: unexpected tag for app_infix", l_mem, l_env) end) - (fun a -> update_stack a - (add_to_top_frame + (fun a -> update_stack a + (add_to_top_frame (fun r env -> let (el,env') = to_exp mode env lv in (E_aux (E_app_infix el op r) (l,annot), env'))))) (fun a -> update_stack a (add_to_top_frame (fun lft env -> (E_aux (E_app_infix lft op r) (l,annot), env)))) | E_exit exp -> @@ -2517,9 +2431,9 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = resolve_outcome (interp_main mode t_level l_env l_mem exp) (fun v lm le -> (Action (Return v) Top, l_mem, l_env)) - (fun a -> update_stack a (add_to_top_frame (fun e env -> (E_aux (E_return e) (l,annot), env)))) + (fun a -> update_stack a (add_to_top_frame (fun e env -> (E_aux (E_return e) (l,annot), env)))) | E_assert cond msg -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem msg) (fun v lm le -> resolve_outcome @@ -2530,43 +2444,43 @@ and __interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | V_lit (L_aux L_true _) -> (Value unitv,lm,l_env) | V_lit (L_aux L_zero _) -> (Action (Fail v) (mk_thunk l annot t_level l_env l_mem), lm,le) | V_lit (L_aux L_false _) -> (Action (Fail v) (mk_thunk l annot t_level l_env l_mem), lm,le) - | V_unknown -> + | V_unknown -> let (branches,maybe_id) = fix_up_nondet typ [unit_e; E_aux (E_assert (E_aux (E_lit (L_aux L_zero l)) - (l,val_annot (T_id "bit"))) msg) (l,annot)] + (l,val_annot (mk_typ_id "bit"))) msg) (l,annot)] (l,annot) in interp_main mode t_level l_env lm (E_aux (E_nondet branches) (l,non_det_annot annot maybe_id)) | _ -> (Error l ("assert given unexpected " ^ (string_of_value c)),l_mem,l_env) end)) (fun a -> update_stack a (add_to_top_frame (fun c env -> (E_aux (E_assert c msg) (l,annot), env))))) (fun a -> update_stack a (add_to_top_frame (fun m env -> (E_aux (E_assert cond m) (l,annot), env)))) - | E_let (lbind : letbind tannot) exp -> + | E_let (lbind : letbind tannot) exp -> match (interp_letbind mode t_level l_env l_mem lbind) with | ((Value v,lm,le),_) -> if mode.eager_eval then interp_main mode t_level le lm exp - else debug_out Nothing Nothing exp t_level lm le - | (((Action a s as o),lm,le),Just lbuild) -> + else debug_out Nothing Nothing exp t_level lm le + | (((Action a s as o),lm,le),Just lbuild) -> ((update_stack o (add_to_top_frame (fun e env -> (E_aux (E_let (lbuild e) exp) (l,annot), env)))),lm,le) | (e,_) -> e end | E_assign lexp exp -> - resolve_outcome + resolve_outcome (interp_main mode t_level l_env l_mem exp) - (fun v lm le -> + (fun v lm le -> (match create_write_message_or_update mode t_level v l_env lm true lexp with | (outcome,Nothing,_) -> outcome | (outcome,Just lexp_builder,Nothing) -> resolve_outcome outcome (fun v lm le -> (Value v,lm,le)) - (fun a -> + (fun a -> (match a with | (Action (Write_reg regf range value) stack) -> a | (Action (Write_mem id a_ range value) stack) -> a | (Action (Write_memv _ _ _) stack) -> a | (Action (Write_memv_tagged _ _ _ _) stack) -> a - | _ -> update_stack a (add_to_top_frame - (fun e env -> + | _ -> update_stack a (add_to_top_frame + (fun e env -> let (ev,env') = (to_exp mode env v) in let (lexp,env') = (lexp_builder e env') in (E_aux (E_assign lexp ev) (l,annot),env'))) end)) @@ -2593,17 +2507,17 @@ and interp_main mode t_level l_env l_mem exp = and __interp_block mode t_level init_env local_env local_mem l tannot exps = match exps with | [] -> (Value (V_lit (L_aux (L_unit) Unknown)), local_mem, init_env) - | [exp] -> + | [exp] -> if mode.eager_eval then interp_main mode t_level local_env local_mem exp else debug_out Nothing Nothing exp t_level local_mem local_env | exp:: exps -> resolve_outcome (interp_main mode t_level local_env local_mem exp) - (fun _ lm le -> + (fun _ lm le -> if mode.eager_eval then interp_block mode t_level init_env le lm l tannot exps else debug_out Nothing Nothing (E_aux (E_block exps) (l,tannot)) t_level lm le) - (fun a -> update_stack a + (fun a -> update_stack a (add_to_top_frame (fun e env-> (E_aux (E_block(e::exps)) (l,tannot), env)))) end @@ -2614,22 +2528,20 @@ and interp_block mode t_level init_env local_env local_mem l tannot exps = retval and __create_write_message_or_update mode t_level value l_env l_mem is_top_level - ((LEXP_aux lexp (l,annot)):lexp tannot) + ((LEXP_aux lexp (l,annot)):lexp tannot) : ((outcome * lmem * lenv) * maybe ((exp tannot) -> lenv -> ((lexp tannot) * lenv)) * maybe value) = let (Env fdefs instrs default_dir lets regs ctors subregs aliases debug) = t_level in - let (typ,tag,ncs,ef,efr) = match annot with - | Nothing -> (T_var "fresh_v", Tag_empty, [], + let (typ,tag,ncs,ef,efr) = match annot with + | Nothing -> (mk_typ_var "fresh_v", Tag_empty, [], (Effect_aux (Effect_set []) Unknown),(Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef,efr) -> (t,tag,ncs,ef,efr) end in - let recenter_val typ value = match typ with - | T_app "reg" (T_args [T_arg_typ - (T_app "vector" (T_args [T_arg_nexp (Ne_const start); T_arg_nexp (Ne_const size); _; _ ]))]) -> - update_vector_start default_dir (natFromInteger start) (natFromInteger size) value - | T_abbrev _ (T_app "vector" (T_args [T_arg_nexp (Ne_const start); T_arg_nexp (Ne_const size); _; _ ])) -> - update_vector_start default_dir (natFromInteger start) (natFromInteger size) value - | _ -> value end in + let recenter_val (Typ_aux typ _) value = match typ with + | Typ_app (Id_aux (Id "reg") _) [Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_app (Id_aux (Id "vector") _) + [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant start) _)) _; Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant size) _)) _;_;_]) _)) _] -> + update_vector_start default_dir (natFromInteger start) (natFromInteger size) value + | _ -> value end in match lexp with - | LEXP_id id -> + | LEXP_id id -> let name = get_id id in match tag with | Tag_intro -> @@ -2638,16 +2550,16 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level if is_top_level then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing, Nothing) - else + else let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing, Nothing) else ((Error l ("Unknown local id " ^ (get_id id)),l_mem,l_env),Nothing,Nothing) - | v -> - if is_top_level - then + | v -> + if is_top_level + then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing,Nothing) else @@ -2655,143 +2567,129 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level Nothing, Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env)), Nothing) end - | Tag_set -> + | Tag_set -> match detaint (in_lenv l_env id) with - | ((V_boxref n t) as v) -> - if is_top_level - then ((Value (V_lit (L_aux L_unit l)), + | ((V_boxref n t) as v) -> + if is_top_level + then ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing, Nothing) else ((Value v, l_mem, l_env),Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env)), Nothing) | V_unknown -> if is_top_level then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing, Nothing) - else + else let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing,Nothing) else ((Error l ("Unknown local id " ^ (get_id id)),l_mem,l_env),Nothing, Nothing) - | v -> - if is_top_level - then + | v -> + if is_top_level + then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing, Nothing) else ((Error l ("Writes must be to reg values given " ^ (string_of_value v)),l_mem,l_env), Nothing, Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env)), Nothing) - end - | Tag_empty -> + end + | Tag_empty -> match detaint (in_lenv l_env id) with - | ((V_boxref n t) as v) -> - if is_top_level - then ((Value (V_lit (L_aux L_unit l)), + | ((V_boxref n t) as v) -> + if is_top_level + then ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing, Nothing) else ((Value v, l_mem, l_env),Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env)), Nothing) | V_unknown -> if is_top_level then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing, Nothing) - else + else let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing, Nothing) else ((Error l ("Unknown local id " ^ (get_id id)),l_mem,l_env),Nothing,Nothing) - | v -> - if is_top_level - then + | v -> + if is_top_level + then if name = "0" then ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing, Nothing) else ((Error l ("Writes must be to reg values given " ^ (string_of_value v)),l_mem,l_env), Nothing, Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env)), Nothing) - end - | Tag_global -> + end + | Tag_global -> (match in_env lets name with - | Just v -> + | Just v -> if is_top_level then ((Error l "Writes must be to reg or registers",l_mem,l_env),Nothing,Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env)), Nothing) | Nothing -> - let regf = + let regf = match in_env regs name with (*pull the regform with the most specific type annotation from env *) | Just(V_register regform) -> regform | _ -> Assert_extra.failwith "Register not known in regenv" end in let start_pos = reg_start_pos regf in - let reg_size = reg_size regf in - let request = - (Action (Write_reg regf Nothing + let reg_size = reg_size regf in + let request = + (Action (Write_reg regf Nothing (if is_top_level then (update_vector_start default_dir start_pos reg_size value) else value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env) in - if is_top_level then (request,Nothing,Nothing) + if is_top_level then (request,Nothing,Nothing) else (request,Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env)), Nothing) end) | Tag_extern _ -> - let regf = + let regf = match in_env regs name with (*pull the regform with the most specific type annotation from env *) | Just(V_register regform) -> regform | _ -> Assert_extra.failwith "Register not known in regenv" end in let start_pos = reg_start_pos regf in let reg_size = reg_size regf in - let request = - (Action (Write_reg regf Nothing + let request = + (Action (Write_reg regf Nothing (if is_top_level then (update_vector_start default_dir start_pos reg_size value) else value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env) in - if is_top_level then (request,Nothing,Nothing) + if is_top_level then (request,Nothing,Nothing) else (request,Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env)),Nothing) - | Tag_alias -> - let request = + | Tag_alias -> + let request = (match in_env aliases name with - | Just (AL_aux aspec (l,_)) -> + | Just (AL_aux aspec (l,_)) -> (match aspec with - | AL_subreg (RI_aux (RI_id reg) (li, ((Just((T_id id),_,_,_,_)) as annot'))) subreg -> + | AL_subreg (RI_aux (RI_id reg) (li, ((Just((Typ_aux (Typ_id (Id_aux (Id id) _)) _),_,_,_,_)) as annot'))) subreg -> (match in_env subregs id with - | Just indexes -> + | Just indexes -> (match in_env indexes (get_id subreg) with - | Just ir -> - (Action - (Write_reg (Form_SubReg subreg (Form_Reg reg annot' default_dir) ir) Nothing + | Just ir -> + (Action + (Write_reg (Form_SubReg subreg (Form_Reg reg annot' default_dir) ir) Nothing (update_vector_start default_dir (get_first_index_range ir) (get_index_range_size ir) value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), l_mem, l_env) | _ -> (Error l "Internal error, alias spec has unknown field", l_mem, l_env) end) - | _ -> + | _ -> (Error l ("Internal error: alias spec has unknown register type " ^ id), l_mem, l_env) end) - | AL_subreg (RI_aux (RI_id reg) (li, ((Just((T_abbrev (T_id id) _),_,_,_,_)) as annot'))) subreg -> - (match in_env subregs id with - | Just indexes -> - (match in_env indexes (get_id subreg) with - | Just ir -> - (Action - (Write_reg (Form_SubReg subreg (Form_Reg reg annot' default_dir) ir) Nothing - (update_vector_start default_dir (get_first_index_range ir) - (get_index_range_size ir) value)) - (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) - t_level l_env l_mem Top), l_mem, l_env) - | _ -> (Error l "Internal error, alias spec has unknown field", l_mem, l_env) end) - | _ -> - (Error l ("Internal error: alias spec has unknown register type "^id), l_mem, l_env) end) | AL_bit (RI_aux (RI_id reg) (_,annot')) 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) _) -> + 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) _) -> let i = natFromInteger i in - (Action (Write_reg (Form_Reg reg annot' default_dir) (Just (i,i)) - (update_vector_start default_dir i 1 value)) + (Action (Write_reg (Form_Reg reg annot' default_dir) (Just (i,i)) + (update_vector_start default_dir i 1 value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), l_mem, l_env) | _ -> (Error l "Internal error: alias bit has non number", l_mem, l_env) end) (fun a -> a) - | AL_slice (RI_aux (RI_id reg) (_,annot')) start stop -> + | AL_slice (RI_aux (RI_id reg) (_,annot')) start stop -> resolve_outcome (interp_main mode t_level l_env l_mem start) - (fun v lm le -> - match detaint v with + (fun v lm le -> + match detaint v with | V_lit (L_aux (L_num start) _) -> (resolve_outcome (interp_main mode t_level l_env lm stop) (fun v le lm -> @@ -2799,7 +2697,7 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | V_lit (L_aux (L_num stop) _) -> let (start,stop) = (natFromInteger start,natFromInteger stop) in let size = if start < stop then stop - start +1 else start -stop +1 in - (Action (Write_reg (Form_Reg reg annot' default_dir) (Just (start,stop)) + (Action (Write_reg (Form_Reg reg annot' default_dir) (Just (start,stop)) (update_vector_start default_dir start size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), @@ -2808,23 +2706,24 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level (fun a -> a)) | _ -> (Error l "Alias slice has non number",l_mem,l_env) end) (fun a -> a) - | AL_concat (RI_aux (RI_id reg1) (l1,annot1)) (RI_aux (RI_id reg2) annot2) -> - let val_typ t = match t with - | T_app "register" (T_args [T_arg_typ t]) -> t - | T_abbrev _ (T_app "register" (T_args [T_arg_typ t])) -> t + | AL_concat (RI_aux (RI_id reg1) (l1,annot1)) (RI_aux (RI_id reg2) annot2) -> + let val_typ (Typ_aux t _) = match t with + | Typ_app (Id_aux (Id "register") _) [Typ_arg_aux (Typ_arg_typ t) _] -> t | _ -> Assert_extra.failwith "alias type ill formed" end in let (t1,t2) = match (annot1,annot2) with | (Just (t1,_,_,_,_), (_,(Just (t2,_,_,_,_)))) -> (val_typ t1,val_typ t2) | _ -> Assert_extra.failwith "type annotations ill formed" end in (match (t1,t2) with - | (T_app "vector" (T_args [T_arg_nexp (Ne_const b1); T_arg_nexp (Ne_const r1); _;_]), - T_app "vector" (T_args [T_arg_nexp (Ne_const b2); T_arg_nexp (Ne_const r2); _;_])) -> - (Action - (Write_reg (Form_Reg reg1 annot1 default_dir) Nothing + | (Typ_aux (Typ_app (Id_aux (Id "vector") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant b1) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant r1) _)) _; _;_]) _, + Typ_aux (Typ_app (Id_aux (Id "vector") _) [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant b2) _)) _; + Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant r2) _)) _; _;_]) _) -> + (Action + (Write_reg (Form_Reg reg1 annot1 default_dir) Nothing (slice_vector value (natFromInteger b1) (natFromInteger r1))) (Thunk_frame (E_aux (E_assign (LEXP_aux (LEXP_id reg2) annot2) - (fst (to_exp <| mode with track_values =false|> eenv + (fst (to_exp <| mode with track_values =false|> eenv (slice_vector value (natFromInteger (r1+1)) (natFromInteger r2))))) annot2) t_level l_env l_mem Top), l_mem,l_env) @@ -2832,182 +2731,182 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | _ -> (Error l "Internal error: alias spec ill formed", l_mem, l_env) end) | _ -> (Error l ("Internal error: alias not found for id " ^(get_id id)),l_mem,l_env) end) in (request,Nothing,Nothing) - | _ -> + | _ -> ((Error l ("Internal error: writing to id with tag other than extern, empty, or alias " ^ (get_id id)), l_mem,l_env),Nothing,Nothing) - end - | LEXP_memory id exps -> - match (exp_list mode t_level (fun exps env -> (E_aux (E_tuple exps) (Unknown,Nothing),env)) + end + | LEXP_memory id exps -> + match (exp_list mode t_level (fun exps env -> (E_aux (E_tuple exps) (Unknown,Nothing),env)) (fun vs -> match vs with | [] -> V_lit (L_aux L_unit Unknown) | [v] -> v | vs -> V_tuple vs end) l_env l_mem [] exps) with | (Value v,lm,le) -> (match tag with | Tag_extern _ -> - let request = + let request = let effects = (match ef with | Effect_aux(Effect_set es) _ -> es | _ -> [] end) in - let act = if has_wmem_effect effects then (Write_mem id v Nothing value) + let act = if has_wmem_effect effects then (Write_mem id v Nothing value) else if has_wmv_effect effects then (Write_memv id v value) else Assert_extra.failwith "LEXP_memory with neither wmem or wmv event" in - (Action act + (Action act (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env lm Top), lm,l_env) in - if is_top_level then (request,Nothing,Nothing) - else + if is_top_level then (request,Nothing,Nothing) + else (request, Just (fun e env-> let (parms,env) = (to_exps mode env (match v with | V_tuple vs -> vs | v -> [v] end)) in (LEXP_aux (LEXP_memory id parms) (l,annot), env)), Nothing) | Tag_global -> - let name = get_id id in + let name = get_id id in (match Map.lookup name fdefs with - | Just(funcls) -> - let new_vals = match v with + | Just(funcls) -> + let new_vals = match v with | V_tuple vs -> V_tuple (vs ++ [value]) | V_lit (L_aux L_unit _) -> V_tuple [v;value] (*hmmm may be wrong in some code*) | v -> V_tuple [v;value] end in (match find_funcl t_level funcls new_vals with | [] -> ((Error l ("No matching pattern for function " ^ name ^ " on value " ^ (string_of_value new_vals)),l_mem,l_env),Nothing, Nothing) - | [(env,used_unknown,exp)] -> - (match (if mode.eager_eval + | [(env,used_unknown,exp)] -> + (match (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) else (debug_out (Just name) (Just new_vals) exp t_level (emem name) env)) with | (Value ret, _,_) -> ((Value ret, l_mem,l_env),Nothing, Nothing) | (Action action stack,lm,le) -> - (((update_stack (Action action stack) + (((update_stack (Action action stack) (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))), l_mem,l_env), Nothing, Nothing) | (e,lm,le) -> ((e,lm,le),Nothing,Nothing) end) | multi_matches -> - let (lets,taint_env) = - List.foldr (fun (env,_,exp) (rst,taint_env) -> + let (lets,taint_env) = + List.foldr (fun (env,_,exp) (rst,taint_env) -> let (e,t_e) = env_to_let mode env exp taint_env in (e::rst,t_e)) ([],l_env) multi_matches in let (branches,maybe_id) = fix_up_nondet typ lets (l,annot) in (interp_main mode t_level taint_env lm (E_aux (E_nondet branches) (l,non_det_annot annot maybe_id)), Nothing, Nothing) end) - | Nothing -> + | Nothing -> ((Error l ("Internal error: function unfound " ^ name),lm,le),Nothing,Nothing) end) | Tag_spec -> - let name = get_id id in + let name = get_id id in (match Map.lookup name fdefs with - | Just(funcls) -> - let new_vals = match v with + | Just(funcls) -> + let new_vals = match v with | V_tuple vs -> V_tuple (vs ++ [value]) | V_lit (L_aux L_unit _) -> V_tuple [v;value] (*hmmm may be wrong in some code*) | v -> V_tuple [v;value] end in (match find_funcl t_level funcls new_vals with | [] -> ((Error l ("No matching pattern for function " ^ name ^ " on value " ^ (string_of_value new_vals)),l_mem,l_env),Nothing,Nothing) - | [(env,used_unknown,exp)] -> - (match (if mode.eager_eval + | [(env,used_unknown,exp)] -> + (match (if mode.eager_eval then (interp_main mode t_level env (emem name) exp) else (debug_out (Just name) (Just new_vals) exp t_level (emem name) env)) with | (Value ret, _,_) -> ((Value ret, l_mem,l_env),Nothing,Nothing) | (Action action stack,lm,le) -> - (((update_stack (Action action stack) + (((update_stack (Action action stack) (fun stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem stack))), l_mem,l_env), Nothing, Nothing) | (e,lm,le) -> ((e,lm,le),Nothing,Nothing) end) | multi_matches -> - let (lets,taint_env) = - List.foldr (fun (env,_,exp) (rst,taint_env) -> + let (lets,taint_env) = + List.foldr (fun (env,_,exp) (rst,taint_env) -> let (e,t_e) = env_to_let mode env exp taint_env in (e::rst,t_e)) ([],l_env) multi_matches in let (branches,maybe_id) = fix_up_nondet typ lets (l,annot) in (interp_main mode t_level taint_env lm (E_aux (E_nondet branches) (l,non_det_annot annot maybe_id)), Nothing,Nothing) end) - | Nothing -> + | Nothing -> ((Error l ("Internal error: function unfound " ^ name),lm,le),Nothing,Nothing) end) - | _ -> ((Error l "Internal error: unexpected tag for memory or register write", lm,le),Nothing,Nothing) + | _ -> ((Error l "Internal error: unexpected tag for memory or register write", lm,le),Nothing,Nothing) end) - | (Action a s,lm, le) -> + | (Action a s,lm, le) -> ((Action a s,lm,le), Just (fun (E_aux e _) env -> (match e with | E_tuple es -> (LEXP_aux (LEXP_memory id es) (l,annot), env) | _ -> Assert_extra.failwith "Lexp builder not well formed" end)), Nothing) | e -> (e,Nothing,Nothing) end - | LEXP_cast typc id -> + | LEXP_cast typc id -> let name = get_id id in match tag with | Tag_intro -> match detaint (in_lenv l_env id) with - | V_unknown -> - if is_top_level + | V_unknown -> + if is_top_level then begin let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing, Nothing) end else ((Error l ("LEXP:cast1: Undefined id " ^ (get_id id)),l_mem,l_env),Nothing, Nothing) - | v -> - if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing, Nothing) + | v -> + if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing, Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_cast typc id) (l,annot), env)), Nothing) end | Tag_set -> match detaint (in_lenv l_env id) with - | ((V_boxref n t) as v) -> - if is_top_level - then ((Value (V_lit (L_aux L_unit l)), + | ((V_boxref n t) as v) -> + if is_top_level + then ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing,Nothing) else ((Value v, l_mem, l_env), Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)), Nothing) - | V_unknown -> - if is_top_level + | V_unknown -> + if is_top_level then begin let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing,Nothing) end else ((Error l ("LEXP:cast2: Undefined id " ^ (get_id id)),l_mem,l_env),Nothing,Nothing) - | v -> - if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing,Nothing) + | v -> + if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing,Nothing) else ((Value v,l_mem,l_env), Just (fun e env -> (LEXP_aux(LEXP_cast typc id) (l,annot), env)),Nothing) - end + end | Tag_empty -> match detaint (in_lenv l_env id) with - | ((V_boxref n t) as v) -> - if is_top_level - then ((Value (V_lit (L_aux L_unit l)), + | ((V_boxref n t) as v) -> + if is_top_level + then ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing,Nothing) else ((Value v, l_mem, l_env), Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)), Nothing) - | V_unknown -> - if is_top_level + | V_unknown -> + if is_top_level then begin let (LMem owner c m s) = l_mem in let l_mem = (LMem owner (c+1) m s) in - ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, + ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing,Nothing) end else ((Error l ("LEXP:cast3: Undefined id " ^ (get_id id)),l_mem,l_env),Nothing,Nothing) - | v -> - if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing,Nothing) + | v -> + if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing,Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_cast typc id) (l,annot), env)),Nothing) - end + end | Tag_extern _ -> - let regf = + let regf = match in_env regs name with (*pull the regform with the most specific type annotation from env *) | Just(V_register regform) -> regform | _ -> Assert_extra.failwith "Register not known in regenv" end in let start_pos = reg_start_pos regf in let reg_size = reg_size regf in - let request = - (Action (Write_reg regf Nothing - (if is_top_level - then (update_vector_start default_dir start_pos reg_size value) - else value)) + let request = + (Action (Write_reg regf Nothing + (if is_top_level + then (update_vector_start default_dir start_pos reg_size value) + else value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env) in if is_top_level then (request,Nothing,Nothing) else (request,Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)),Nothing) - | _ -> + | _ -> ((Error l ("Internal error: writing to id not extern or empty " ^(get_id id)),l_mem,l_env), Nothing,Nothing) end @@ -3037,15 +2936,15 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | _ -> ((Error l "Internal error: Unexpected pattern match failure in LEXP_tup",l_mem,l_env),Nothing,Nothing) end) - end - | LEXP_vector lexp exp -> + end + | LEXP_vector lexp exp -> match (interp_main mode t_level l_env l_mem exp) with | (Value i,lm,le) -> - (match detaint i with + (match detaint i with | V_unknown -> ((Value i,lm,le),Nothing,Nothing) - | V_lit (L_aux (L_num n) ln) -> - let next_builder le_builder = - (fun e env -> + | V_lit (L_aux (L_num n) ln) -> + let next_builder le_builder = + (fun e env -> let (lexp,env) = le_builder e env in let (ie,env) = to_exp mode env i in (LEXP_aux (LEXP_vector lexp ie) (l,annot), env)) in @@ -3054,29 +2953,29 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | ((Value v_whole,lm,le),maybe_builder,maybe_value) -> let v = detaint v_whole in let nth _ = detaint (access_vector v n) in - (match v with + (match v with | V_unknown -> ((Value v_whole,lm,le),Nothing,Nothing) - | V_boxref i _ -> + | V_boxref i _ -> (match (in_mem lm i,is_top_level,maybe_builder) with | ((V_vector _ _ _ as vec),true,_) -> let new_vec = fupdate_vector_slice vec (V_vector 1 default_dir [value]) n n in - ((Value (V_lit (L_aux L_unit Unknown)), + ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm i new_vec, l_env), Nothing,Nothing) | ((V_track (V_vector _ _ _ as vec) r), true,_) -> let new_vec = fupdate_vector_slice vec (V_vector 1 default_dir [value]) n n in - ((Value (V_lit (L_aux L_unit Unknown)), + ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm i (taint new_vec r),l_env),Nothing,Nothing) | ((V_vector _ _ _ as vec),false, Just lexp_builder) -> ((Value (access_vector vec n), lm, l_env), Just (next_builder lexp_builder),Nothing) - | (v,_,_) -> + | (v,_,_) -> Assert_extra.failwith("no vector findable in set bit, found " ^ (string_of_value v)) end ) - | V_vector inc m vs -> + | V_vector inc m vs -> (match (nth(),is_top_level,maybe_builder) with | (V_register regform,true,_) -> let start_pos = reg_start_pos regform in let reg_size = reg_size regform in - ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) + ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env), @@ -3084,75 +2983,75 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | (V_register regform,false,Just lexp_builder) -> let start_pos = reg_start_pos regform in let reg_size = reg_size regform in - ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) + ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env), Just (next_builder lexp_builder),maybe_value) - | (V_boxref n t,true,_) -> + | (V_boxref n t,true,_) -> ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm n value, l_env), Nothing,Nothing) | (V_unknown,true,_) -> ((Value (V_lit (L_aux L_unit Unknown)), lm, l_env),Nothing,Nothing) - | (v,true,_) -> + | (v,true,_) -> ((Error l "Vector does not contain reg or register values",lm,l_env),Nothing,Nothing) - | ((V_boxref n t),false, Just lexp_builder) -> + | ((V_boxref n t),false, Just lexp_builder) -> ((Value (in_mem lm n),lm, l_env),Just (next_builder lexp_builder),Nothing) - | (v,false, Just lexp_builder) -> + | (v,false, Just lexp_builder) -> ((Value v,lm,le), Just (next_builder lexp_builder),Nothing) - | _ -> Assert_extra.failwith "Vector assignment logic incomplete" + | _ -> Assert_extra.failwith "Vector assignment logic incomplete" end) | V_vector_sparse n m inc vs d -> (match (nth(),is_top_level,maybe_builder) with | (V_register regform,true,_) -> - let start_pos = reg_start_pos regform in + let start_pos = reg_start_pos regform in let reg_size = reg_size regform in - ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) + ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env),Nothing,Nothing) | (V_register regform,false,Just lexp_builder) -> let start_pos = reg_start_pos regform in let reg_size = reg_size regform in - ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) + ((Action (Write_reg regform Nothing (update_vector_start default_dir start_pos reg_size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,intern_annot annot)) t_level l_env l_mem Top), l_mem,l_env), Just (next_builder lexp_builder),Nothing) - | (V_boxref n t,true,_) -> + | (V_boxref n t,true,_) -> ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm n value, l_env), Nothing,Nothing) - | (v,true,_) -> + | (v,true,_) -> ((Error l ("Vector does not contain reg or register values " ^ (string_of_value v)), lm,l_env), Nothing,Nothing) - | ((V_boxref n t),false, Just lexp_builder) -> + | ((V_boxref n t),false, Just lexp_builder) -> ((Value (in_mem lm n),lm, l_env),Just (next_builder lexp_builder),Nothing) - | (v,false, Just lexp_builder) -> + | (v,false, Just lexp_builder) -> ((Value v,lm,le), Just (next_builder lexp_builder), Nothing) | _ -> Assert_extra.failwith "Vector assignment logic incomplete" end) - | v -> + | v -> ((Error l ("Vector access to write of non-vector" ^ (string_of_value v)),lm,l_env),Nothing,Nothing) end) | ((Action a s,lm,le),Just lexp_builder,maybe_value) -> (match (a,is_top_level) with - | ((Write_reg regf Nothing value),true) -> - ((Action (Write_reg regf (Just (n,n)) - (if (vector_length value) = 1 + | ((Write_reg regf Nothing value),true) -> + ((Action (Write_reg regf (Just (n,n)) + (if (vector_length value) = 1 then (update_vector_start default_dir n 1 value) else (access_vector value n))) s, lm,le), Nothing, Nothing) - | ((Write_reg regf Nothing value),false) -> - ((Action (Write_reg regf (Just (n,n)) - (if (vector_length value) = 1 + | ((Write_reg regf Nothing value),false) -> + ((Action (Write_reg regf (Just (n,n)) + (if (vector_length value) = 1 then (update_vector_start default_dir n 1 value) else (access_vector value n))) s,lm,le), Just (next_builder lexp_builder), Nothing) - | ((Write_mem id a Nothing value),true) -> + | ((Write_mem id a Nothing value),true) -> ((Action (Write_mem id a (Just (n,n)) value) s,lm,le), Nothing, Nothing) - | ((Write_mem id a Nothing value),false) -> + | ((Write_mem id a Nothing value),false) -> ((Action (Write_mem id a (Just (n,n)) value) s,lm,le), Just (next_builder lexp_builder), Nothing) | _ -> ((Action a s,lm,le), Just (next_builder lexp_builder), Nothing) end) | e -> e end) - | v -> + | v -> ((Error l ("Vector access must be a number given " ^ (string_of_value v)),lm,le),Nothing,Nothing) end) - | (Action a s,lm,le) -> + | (Action a s,lm,le) -> ((Action a s,lm,le), Just (fun e env -> (LEXP_aux (LEXP_vector lexp e) (l,annot), env)), Nothing) | e -> (e,Nothing,Nothing) end | LEXP_vector_range lexp exp1 exp2 -> @@ -3166,8 +3065,8 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level (match detaint i2 with | V_unknown -> ((Value i2,lm,le),Nothing,Nothing) | V_lit (L_aux (L_num n2) ln2) -> - let next_builder le_builder = - (fun e env -> + let next_builder le_builder = + (fun e env -> let (e1,env) = to_exp mode env i1 in let (e2,env) = to_exp mode env i2 in let (lexp,env) = le_builder e env in @@ -3176,33 +3075,33 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level (match (create_write_message_or_update mode t_level value l_env lm false lexp) with | ((Value v,lm,le), Just lexp_builder,_) -> (match (detaint v,is_top_level) with - | (V_vector m inc vs,true) -> - ((Value (V_lit (L_aux L_unit Unknown)), + | (V_vector m inc vs,true) -> + ((Value (V_lit (L_aux L_unit Unknown)), update_vector_slice mode.track_lmem v value n1 n2 lm, l_env), Nothing, Nothing) - | (V_boxref _ _, true) -> - ((Value (V_lit (L_aux L_unit Unknown)), + | (V_boxref _ _, true) -> + ((Value (V_lit (L_aux L_unit Unknown)), update_vector_slice mode.track_lmem v value n1 n2 lm, l_env), Nothing, Nothing) | (V_vector m inc vs,false) -> ((Value (slice_vector v n1 n2),lm,l_env), Just (next_builder lexp_builder), Nothing) | (V_register regform,true) -> let start_pos = reg_start_pos regform in let reg_size = reg_size regform in - ((Action (Write_reg regform (Just (n1,n2)) (update_vector_start default_dir start_pos reg_size v)) + ((Action (Write_reg regform (Just (n1,n2)) (update_vector_start default_dir start_pos reg_size v)) (mk_thunk l annot t_level l_env l_mem), l_mem,l_env), Just (next_builder lexp_builder), Nothing) - | (V_unknown,_) -> + | (V_unknown,_) -> let inc = n1 < n2 in let start = if inc then n1 else (n2-1) in - let size = if inc then n2-n1 +1 else n1 -n2 +1 in + let size = if inc then n2-n1 +1 else n1 -n2 +1 in ((Value (V_vector start (if inc then IInc else IDec) (List.replicate size V_unknown)), lm,l_env),Nothing,Nothing) | _ -> ((Error l "Vector required",lm,le),Nothing,Nothing) end) | ((Action (Write_reg regf Nothing value) s, lm,le), Just lexp_builder,_) -> let len = (if n1 < n2 then n2 -n1 else n1 - n2) +1 in - ((Action - (Write_reg regf (Just (n1,n2)) - (if (vector_length value) <= len + ((Action + (Write_reg regf (Just (n1,n2)) + (if (vector_length value) <= len then (update_vector_start default_dir n1 len value) else (slice_vector value n1 n2))) s,lm,le), Just (next_builder lexp_builder), Nothing) @@ -3213,8 +3112,8 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | e -> e end) | _ -> ((Error l "Vector slice requires a number", lm, le),Nothing,Nothing) end) | (Action a s,lm,le) -> - ((Action a s,lm, le), - Just (fun e env -> + ((Action a s,lm, le), + Just (fun e env -> let (e1,env) = to_exp mode env i1 in (LEXP_aux (LEXP_vector_range lexp e1 e) (l,annot), env)), Nothing) | e -> (e,Nothing,Nothing) end) @@ -3225,53 +3124,39 @@ and __create_write_message_or_update mode t_level value l_env l_mem is_top_level | LEXP_field lexp id -> (match (create_write_message_or_update mode t_level value l_env l_mem false lexp) with | ((Value (V_record t fexps),lm,le),Just lexp_builder,_) -> - let next_builder = Just (fun e env -> let (lexp,env) = (lexp_builder e env) in + let next_builder = Just (fun e env -> let (lexp,env) = (lexp_builder e env) in (LEXP_aux (LEXP_field lexp id) (l,annot), env)) in match (in_env (env_from_list fexps) (get_id id),is_top_level) with - | (Just (V_boxref n t),true) -> + | (Just (V_boxref n t),true) -> ((Value (V_lit (L_aux L_unit l)), update_mem mode.track_lmem lm n value, l_env),Nothing,Nothing) | (Just (V_boxref n t),false) -> ((Value (in_mem lm n),lm,l_env),next_builder,Nothing) | (Just v, true) -> ((Error l "Mutating a field access requires a reg type",lm,le),Nothing,Nothing) | (Just v,false) -> ((Value v,lm,l_env),next_builder,Nothing) | (Nothing,_) -> ((Error l "Field not found in specified record",lm,le),Nothing,Nothing) end - | ((Action a s,lm,le), Just lexp_builder,_) -> - let next_builder = Just (fun e env -> let (lexp,env) = (lexp_builder e env) in + | ((Action a s,lm,le), Just lexp_builder,_) -> + let next_builder = Just (fun e env -> let (lexp,env) = (lexp_builder e env) in (LEXP_aux (LEXP_field lexp id) (l,annot), env)) in match a with | Read_reg _ _ -> ((Action a s,lm,le), next_builder, Nothing) | Read_mem _ _ _ -> ((Action a s,lm,le), next_builder, Nothing) | Read_mem_tagged _ _ _ -> ((Action a s,lm,le), next_builder, Nothing) | Call_extern _ _ -> ((Action a s,lm,le), next_builder, Nothing) - | Write_reg ((Form_Reg _ (Just(T_id id',_,_,_,_)) _) as regf) Nothing value -> - match in_env subregs id' with - | Just(indexes) -> - match in_env indexes (get_id id) with - | Just ir -> - ((Action - (Write_reg (Form_SubReg id regf ir) Nothing - (update_vector_start default_dir (get_first_index_range ir) - (get_index_range_size ir) value)) s, - lm,le), - (if is_top_level then Nothing else next_builder), Nothing) - | _ -> ((Error l "Internal error, unrecognized write, no field",lm,le),Nothing,Nothing) - end - | Nothing -> ((Error l "Internal error, unrecognized write, no subreges",lm,le),Nothing,Nothing) end - | Write_reg ((Form_Reg _ (Just((T_abbrev(T_id id') _),_,_,_,_)) _) as regf) Nothing value -> + | Write_reg ((Form_Reg _ (Just(Typ_aux (Typ_id (Id_aux (Id id') _)) _,_,_,_,_)) _) as regf) Nothing value -> match in_env subregs id' with | Just(indexes) -> match in_env indexes (get_id id) with - | Just ir -> - ((Action - (Write_reg (Form_SubReg id regf ir) Nothing + | Just ir -> + ((Action + (Write_reg (Form_SubReg id regf ir) Nothing (update_vector_start default_dir (get_first_index_range ir) (get_index_range_size ir) value)) s, - lm,le), + lm,le), (if is_top_level then Nothing else next_builder), Nothing) | _ -> ((Error l "Internal error, unrecognized write, no field",lm,le),Nothing,Nothing) - end + end | Nothing -> ((Error l "Internal error, unrecognized write, no subreges",lm,le),Nothing,Nothing) end | _ -> ((Error l "Internal error, unrecognized write, no matching action",lm,le),Nothing,Nothing) - end + end | e -> e end) end @@ -3283,21 +3168,13 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level l and __interp_letbind mode t_level l_env l_mem (LB_aux lbind (l,annot)) = match lbind with - | LB_val_explicit t pat exp -> + | LB_val pat exp -> match (interp_main mode t_level l_env l_mem exp) with | (Value v,lm,le) -> (match match_pattern t_level pat v with | (true,used_unknown,env) -> ((Value (V_lit (L_aux L_unit l)), lm, (union_env env l_env)),Nothing) | _ -> ((Error l "Pattern in letbind did not match value",lm,le),Nothing) end) - | (Action a s,lm,le) -> ((Action a s,lm,le),(Just (fun e ->(LB_aux (LB_val_explicit t pat e) (l,annot))))) - | e -> (e,Nothing) end - | LB_val_implicit pat exp -> - match (interp_main mode t_level l_env l_mem exp) with - | (Value v,lm,le) -> - (match match_pattern t_level pat v with - | (true,used_unknown,env) -> ((Value (V_lit (L_aux L_unit l)), lm, (union_env env l_env)),Nothing) - | _ -> ((Error l "Pattern in letbind did not match value",lm,le),Nothing) end) - | (Action a s,lm,le) -> ((Action a s,lm,le),(Just (fun e -> (LB_aux (LB_val_implicit pat e) (l,annot))))) + | (Action a s,lm,le) -> ((Action a s,lm,le),(Just (fun e -> (LB_aux (LB_val pat e) (l,annot))))) | e -> (e,Nothing) end end @@ -3312,15 +3189,14 @@ and __interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = let stack = Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem Top in let get_reg_typ_name typ = match typ with - | T_id i -> i - | T_abbrev (T_id i) _ -> i + | Typ_aux (Typ_id (Id_aux (Id i) _)) _ -> i | _ -> Assert_extra.failwith "Alias reg typ not well formed" end in match alspec with | AL_subreg (RI_aux (RI_id reg) (li,((Just (t,_,_,_,_)) as annot'))) subreg -> let reg_ti = get_reg_typ_name t in (match in_env subregs reg_ti with - | Just indexes -> + | Just indexes -> (match in_env indexes (get_id subreg) with | Just ir -> (Action (Read_reg (Form_SubReg subreg (Form_Reg reg annot' default_dir) ir) Nothing) stack, l_mem, l_env) @@ -3328,19 +3204,19 @@ and __interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = | _ -> (Error l (String.stringAppend "Internal error: alias spec has unknown register type " reg_ti), l_mem, l_env) end) | AL_bit (RI_aux (RI_id reg) (_,annot')) 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) _) -> + 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) _) -> let i = natFromInteger i in (Action (Read_reg (Form_Reg reg annot' default_dir) (Just (i,i))) stack, l_mem, l_env) | _ -> Assert_extra.failwith "alias bit did not reduce to number" end) (fun a -> a) (*Should not currently happen as type system enforces constants*) - | AL_slice (RI_aux (RI_id reg) (_,annot')) start stop -> + | AL_slice (RI_aux (RI_id reg) (_,annot')) start stop -> resolve_outcome (interp_main mode t_level l_env l_mem start) - (fun v lm le -> - match v with + (fun v lm le -> + match v with | V_lit (L_aux (L_num start) _) -> - (resolve_outcome + (resolve_outcome (interp_main mode t_level l_env lm stop) (fun v le lm -> (match v with @@ -3350,14 +3226,14 @@ and __interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = | _ -> Assert_extra.failwith ("Alias slice evaluted non-lit " ^ (string_of_value v)) end)) (fun a -> a)) - | _ -> Assert_extra.failwith ("Alias slice evaluated non-lit "^ string_of_value v) + | _ -> Assert_extra.failwith ("Alias slice evaluated non-lit "^ string_of_value v) end) (fun a -> a) (*Neither action function should occur, due to above*) - | AL_concat (RI_aux (RI_id reg1) (l1, annot1)) (RI_aux (RI_id reg2) annot2) -> + | AL_concat (RI_aux (RI_id reg1) (l1, annot1)) (RI_aux (RI_id reg2) annot2) -> (Action (Read_reg (Form_Reg reg1 annot1 default_dir) Nothing) (Hole_frame redex_id (E_aux (E_vector_append (E_aux (E_id redex_id) (l1, (intern_annot annot1))) - (E_aux (E_id reg2) annot2)) + (E_aux (E_id reg2) annot2)) (l,(intern_annot annot))) t_level l_env l_mem Top), l_mem,l_env) | _ -> Assert_extra.failwith "alias spec not well formed" end @@ -3368,10 +3244,10 @@ and interp_alias_read mode t_level l_env l_mem al = let _ = debug_fun_exit mode "interp_alias_read" retval in retval -let rec eval_toplevel_let handle_action tlevel env mem lbind = +let rec eval_toplevel_let handle_action tlevel env mem lbind = match interp_letbind <| eager_eval=true; track_values=false; track_lmem=false; debug=false; debug_indent="" |> tlevel env mem lbind with | ((Value v, lm, (LEnv _ le)),_) -> Just le - | ((Action a s,lm,le), Just le_builder) -> + | ((Action a s,lm,le), Just le_builder) -> (match handle_action (Action a s) with | Just value -> (match s with @@ -3389,30 +3265,30 @@ let rec to_global_letbinds handle_action (Defs defs) t_level = match def with | DEF_val lbind -> match eval_toplevel_let handle_action t_level eenv (emem "global_letbinds") lbind with - | Just le -> + | Just le -> to_global_letbinds handle_action - (Defs defs) + (Defs defs) (Env fdefs instrs default_dir (Map.(union) lets le) regs ctors subregs aliases debug) - | Nothing -> - to_global_letbinds handle_action (Defs defs) + | Nothing -> + to_global_letbinds handle_action (Defs defs) (Env fdefs instrs default_dir lets regs ctors subregs aliases debug) end | DEF_type (TD_aux tdef _) -> match tdef with - | TD_enum id ns ids _ -> - let typ = T_id (get_id id) in - let enum_vals = - Map.fromList - (snd + | TD_enum id ns ids _ -> + let typ = mk_typ_id (get_id id) in + let enum_vals = + Map.fromList + (snd (List.foldl (fun (c,rst) eid -> (1+c,(get_id eid,V_ctor eid typ (C_Enum c) unitv)::rst)) (0,[]) ids)) in - to_global_letbinds - handle_action (Defs defs) + to_global_letbinds + handle_action (Defs defs) (Env fdefs instrs default_dir (Map.(union) lets enum_vals) regs ctors subregs aliases debug) | _ -> to_global_letbinds handle_action (Defs defs) t_level end | _ -> to_global_letbinds handle_action (Defs defs) t_level end end -let rec extract_default_direction (Defs defs) = match defs with +let rec extract_default_direction (Defs defs) = match defs with | [] -> IInc (*When lack of a declared default, go for inc*) | def::defs -> match def with @@ -3423,11 +3299,11 @@ let rec extract_default_direction (Defs defs) = match defs with (*TODO Contemplate making execute environment variable instead of constant*) let to_top_env debug external_functions defs = let direction = (extract_default_direction defs) in - let t_level = Env (to_fdefs defs) - (extract_instructions "execute" defs) + let t_level = Env (to_fdefs defs) + (extract_instructions "execute" defs) direction - Map.empty (* empty letbind and enum values, call below will fill in any *) - (to_registers direction defs) + Map.empty (* empty letbind and enum values, call below will fill in any *) + (to_registers direction defs) (to_data_constructors defs) (to_register_fields defs) (to_aliases defs) debug in let (o,t_level) = to_global_letbinds (external_functions direction) defs t_level in match o with @@ -3437,9 +3313,9 @@ let to_top_env debug external_functions defs = let __interp mode external_functions defs exp = match (to_top_env mode.debug external_functions defs) with - | (Nothing,t_level) -> + | (Nothing,t_level) -> interp_main mode t_level eenv (emem "top level") exp - | (Just o,_) -> (o,(emem "top level error"),eenv) + | (Just o,_) -> (o,(emem "top level error"),eenv) end let interp mode external_functions defs exp = @@ -3451,15 +3327,15 @@ let interp mode external_functions defs exp = let rec __resume_with_env mode stack value = match (stack,value) with | (Top,_) -> (Error Unknown "Top hit without expression to evaluate in resume_with_env",eenv) - | (Hole_frame id exp t_level env mem Top,Just value) -> - match interp_main mode t_level (add_to_env (id,value) env) mem exp with | (o,_,e) -> (o,e) end + | (Hole_frame id exp t_level env mem Top,Just value) -> + match interp_main mode t_level (add_to_env (id,value) env) mem exp with | (o,_,e) -> (o,e) end | (Hole_frame id exp t_level env mem stack,Just value) -> match resume_with_env mode stack (Just value) with - | (Value v,e) -> - match interp_main mode t_level (add_to_env (id,v) env) mem exp with | (o,_,e) -> (o,e) end + | (Value v,e) -> + match interp_main mode t_level (add_to_env (id,v) env) mem exp with | (o,_,e) -> (o,e) end | (Action action stack,e) -> (Action action (Hole_frame id exp t_level env mem stack),e) | (Error l s,e) -> (Error l s,e) - end + end | (Hole_frame id exp t_level env mem stack, Nothing) -> match resume_with_env mode stack Nothing with | (Value v,e) -> @@ -3471,8 +3347,8 @@ let rec __resume_with_env mode stack value = match interp_main mode t_level env mem exp with | (o,_,e) -> (o,e) end | (Thunk_frame exp t_level env mem stack,value) -> match resume_with_env mode stack value with - | (Value v,e) -> - match interp_main mode t_level env mem exp with | (o,_,e) -> (o,e) end + | (Value v,e) -> + match interp_main mode t_level env mem exp with | (o,_,e) -> (o,e) end | (Action action stack,e) -> (Action action (Thunk_frame exp t_level env mem stack),e) | (Error l s,e) -> (Error l s,e) end @@ -3488,32 +3364,32 @@ and resume_with_env mode stack value = let rec __resume mode stack value = match (stack,value) with | (Top,_) -> (Error Unknown "Top hit without expression to evaluate in resume",(emem "top level error"),eenv) - | (Hole_frame id exp t_level env mem Top,Just value) -> + | (Hole_frame id exp t_level env mem Top,Just value) -> interp_main mode t_level (add_to_env (id,value) env) mem exp | (Hole_frame id exp t_level env mem Top,Nothing) -> (Error Unknown "Top hole frame hit wihtout a value in resume", mem, env) | (Hole_frame id exp t_level env mem stack,Just value) -> match resume mode stack (Just value) with - | (Value v,_,_) -> - interp_main mode t_level (add_to_env (id,v) env) mem exp + | (Value v,_,_) -> + interp_main mode t_level (add_to_env (id,v) env) mem exp | (Action action stack,lm,le) -> (Action action (Hole_frame id exp t_level env mem stack),lm,le) | (Error l s,lm,le) -> (Error l s,lm,le) - end + end | (Hole_frame id exp t_level env mem stack, Nothing) -> match resume mode stack Nothing with | (Value v,_,_) -> - interp_main mode t_level (add_to_env (id,v) env) mem exp + interp_main mode t_level (add_to_env (id,v) env) mem exp | (Action action stack,lm,le) -> (Action action (Hole_frame id exp t_level env mem stack),lm,le) | (Error l s,lm,le) -> (Error l s,lm,le) end | (Thunk_frame exp t_level env mem Top,_) -> - interp_main mode t_level env mem exp + interp_main mode t_level env mem exp | (Thunk_frame exp t_level env mem stack,value) -> match resume mode stack value with | (Value v,_,_) -> interp_main mode t_level env mem exp | (Action action stack,lm,le) -> (Action action (Thunk_frame exp t_level env mem stack), lm, le) | (Error l s,lm,le) -> (Error l s,lm,le) - end + end end and resume mode stack value = diff --git a/src/lem_interp/interp_ast.lem b/src/lem_interp/interp_ast.lem deleted file mode 100644 index 733d1a36..00000000 --- a/src/lem_interp/interp_ast.lem +++ /dev/null @@ -1,747 +0,0 @@ -(*========================================================================*) -(* Sail *) -(* *) -(* Copyright (c) 2013-2017 *) -(* Kathyrn Gray *) -(* Shaked Flur *) -(* Stephen Kell *) -(* Gabriel Kerneis *) -(* Robert Norton-Wright *) -(* Christopher Pulte *) -(* Peter Sewell *) -(* *) -(* All rights reserved. *) -(* *) -(* This software was developed by the University of Cambridge Computer *) -(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *) -(* (REMS) project, funded by EPSRC grant EP/K008528/1. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in *) -(* the documentation and/or other materials provided with the *) -(* distribution. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *) -(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *) -(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *) -(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *) -(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *) -(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *) -(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *) -(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *) -(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *) -(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *) -(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *) -(* SUCH DAMAGE. *) -(*========================================================================*) - -(* generated by Ott 0.25 from: l2.ott *) -open import Pervasives - -open import Pervasives -open import Pervasives_extra -open import Map -open import Maybe -open import Set_extra - -type l = - | Unknown - | Int of string * maybe l (*internal types, functions*) - | Range of string * nat * nat * nat * nat - | Generated of l (*location for a generated node, where l is the location of the closest original source*) - -type annot 'a = l * 'a - -val duplicates : forall 'a. list 'a -> list 'a - -val set_from_list : forall 'a. list 'a -> set 'a - -val subst : forall 'a. list 'a -> list 'a -> bool - - -type x = string (* identifier *) -type ix = string (* infix identifier *) - -type base_kind_aux = (* base kind *) - | BK_type (* kind of types *) - | BK_nat (* kind of natural number size expressions *) - | BK_order (* kind of vector order specifications *) - | BK_effect (* kind of effect sets *) - - -type kid_aux = (* kinded IDs: $Type$, $Nat$, $Order$, and $Effect$ variables *) - | Var of x - - -type id_aux = (* identifier *) - | Id of x - | DeIid of x (* remove infix status *) - - -type base_kind = - | BK_aux of base_kind_aux * l - - -type kid = - | Kid_aux of kid_aux * l - - -type id = - | Id_aux of id_aux * l - - -type kind_aux = (* kinds *) - | K_kind of list base_kind - - -type nexp_aux = (* numeric expression, of kind $Nat$ *) - | Nexp_id of id (* abbreviation identifier *) - | Nexp_var of kid (* variable *) - | Nexp_constant of integer (* constant *) - | Nexp_times of nexp * nexp (* product *) - | Nexp_sum of nexp * nexp (* sum *) - | Nexp_minus of nexp * nexp (* subtraction *) - | Nexp_exp of nexp (* exponential *) - | Nexp_neg of nexp (* for internal use only *) - -and nexp = - | Nexp_aux of nexp_aux * l - - -type kind = - | K_aux of kind_aux * l - - -type base_effect_aux = (* effect *) - | BE_rreg (* read register *) - | BE_wreg (* write register *) - | BE_rmem (* read memory *) - | BE_rmemt (* read memory and tag *) - | BE_wmem (* write memory *) - | BE_eamem (* signal effective address for writing memory *) - | BE_exmem (* determine if a store-exclusive (ARM) is going to succeed *) - | BE_wmv (* write memory, sending only value *) - | BE_wmvt (* write memory, sending only value and tag *) - | BE_barr (* memory barrier *) - | BE_depend (* dynamic footprint *) - | BE_undef (* undefined-instruction exception *) - | BE_unspec (* unspecified values *) - | BE_nondet (* nondeterminism, from $nondet$ *) - | BE_escape (* potential call of $exit$ *) - | BE_lset (* local mutation; not user-writable *) - | BE_lret (* local return; not user-writable *) - - -type base_effect = - | BE_aux of base_effect_aux * l - - -type order_aux = (* vector order specifications, of kind $Order$ *) - | Ord_var of kid (* variable *) - | Ord_inc (* increasing *) - | Ord_dec (* decreasing *) - - -type effect_aux = (* effect set, of kind $Effect$ *) - | Effect_var of kid - | Effect_set of list base_effect (* effect set *) - - -type order = - | Ord_aux of order_aux * l - - -type effect = - | Effect_aux of effect_aux * l - -let effect_union e1 e2 = - match (e1,e2) with - | ((Effect_aux (Effect_set els) _),(Effect_aux (Effect_set els2) l)) -> Effect_aux (Effect_set (els++els2)) l - end - - -type n_constraint_aux = (* constraint over kind $Nat$ *) - | NC_fixed of nexp * nexp - | NC_bounded_ge of nexp * nexp - | NC_bounded_le of nexp * nexp - | NC_nat_set_bounded of kid * list integer - - -type kinded_id_aux = (* optionally kind-annotated identifier *) - | KOpt_none of kid (* identifier *) - | KOpt_kind of kind * kid (* kind-annotated variable *) - - -type n_constraint = - | NC_aux of n_constraint_aux * l - - -type kinded_id = - | KOpt_aux of kinded_id_aux * l - - -type quant_item_aux = (* kinded identifier or $Nat$ constraint *) - | QI_id of kinded_id (* optionally kinded identifier *) - | QI_const of n_constraint (* $Nat$ constraint *) - - -type quant_item = - | QI_aux of quant_item_aux * l - - -type typquant_aux = (* type quantifiers and constraints *) - | TypQ_tq of list quant_item - | TypQ_no_forall (* empty *) - - -type typquant = - | TypQ_aux of typquant_aux * l - - -type typ_aux = (* type expressions, of kind $Type$ *) - | Typ_wild (* unspecified type *) - | Typ_id of id (* defined type *) - | Typ_var of kid (* type variable *) - | Typ_fn of typ * typ * effect (* Function (first-order only in user code) *) - | Typ_tup of list typ (* Tuple *) - | Typ_app of id * list typ_arg (* type constructor application *) - -and typ = - | Typ_aux of typ_aux * l - -and typ_arg_aux = (* type constructor arguments of all kinds *) - | Typ_arg_nexp of nexp - | Typ_arg_typ of typ - | Typ_arg_order of order - | Typ_arg_effect of effect - -and typ_arg = - | Typ_arg_aux of typ_arg_aux * l - - -type lit_aux = (* literal constant *) - | L_unit (* $() : unit$ *) - | L_zero (* $bitzero : bit$ *) - | L_one (* $bitone : bit$ *) - | L_true (* $true : bool$ *) - | L_false (* $false : bool$ *) - | L_num of integer (* natural number constant *) - | L_hex of string (* bit vector constant, C-style *) - | L_bin of string (* bit vector constant, C-style *) - | L_string of string (* string constant *) - | L_undef (* undefined-value constant *) - - -type index_range_aux = (* index specification, for bitfields in register types *) - | BF_single of integer (* single index *) - | BF_range of integer * integer (* index range *) - | BF_concat of index_range * index_range (* concatenation of index ranges *) - -and index_range = - | BF_aux of index_range_aux * l - - -type typschm_aux = (* type scheme *) - | TypSchm_ts of typquant * typ - - -type lit = - | L_aux of lit_aux * l - - -type typschm = - | TypSchm_aux of typschm_aux * l - - -type pat_aux 'a = (* pattern *) - | P_lit of lit (* literal constant pattern *) - | P_wild (* wildcard *) - | P_as of (pat 'a) * id (* named pattern *) - | P_typ of typ * (pat 'a) (* typed pattern *) - | P_id of id (* identifier *) - | P_app of id * list (pat 'a) (* union constructor pattern *) - | P_record of list (fpat 'a) * bool (* struct pattern *) - | P_vector of list (pat 'a) (* vector pattern *) - | P_vector_indexed of list (integer * (pat 'a)) (* vector pattern (with explicit indices) *) - | P_vector_concat of list (pat 'a) (* concatenated vector pattern *) - | P_tup of list (pat 'a) (* tuple pattern *) - | P_list of list (pat 'a) (* list pattern *) - -and pat 'a = - | P_aux of (pat_aux 'a) * annot 'a - -and fpat_aux 'a = (* field pattern *) - | FP_Fpat of id * (pat 'a) - -and fpat 'a = - | FP_aux of (fpat_aux 'a) * annot 'a - - -type name_scm_opt_aux = (* optional variable naming-scheme constraint *) - | Name_sect_none - | Name_sect_some of string - - -type type_union_aux = (* type union constructors *) - | Tu_id of id - | Tu_ty_id of typ * id - - -type name_scm_opt = - | Name_sect_aux of name_scm_opt_aux * l - - -type type_union = - | Tu_aux of type_union_aux * l - - -type kind_def_aux 'a = (* Definition body for elements of kind *) - | KD_nabbrev of kind * id * name_scm_opt * nexp (* $Nat$-expression abbreviation *) - | KD_abbrev of kind * id * name_scm_opt * typschm (* type abbreviation *) - | KD_record of kind * id * name_scm_opt * typquant * list (typ * id) * bool (* struct type definition *) - | KD_variant of kind * id * name_scm_opt * typquant * list type_union * bool (* union type definition *) - | KD_enum of kind * id * name_scm_opt * list id * bool (* enumeration type definition *) - | KD_register of kind * id * nexp * nexp * list (index_range * id) (* register mutable bitfield type definition *) - - -type type_def_aux 'a = (* type definition body *) - | TD_abbrev of id * name_scm_opt * typschm (* type abbreviation *) - | TD_record of id * name_scm_opt * typquant * list (typ * id) * bool (* struct type definition *) - | TD_variant of id * name_scm_opt * typquant * list type_union * bool (* tagged union type definition *) - | TD_enum of id * name_scm_opt * list id * bool (* enumeration type definition *) - | TD_register of id * nexp * nexp * list (index_range * id) (* register mutable bitfield type definition *) - - -type kind_def 'a = - | KD_aux of (kind_def_aux 'a) * annot 'a - - -type type_def 'a = - | TD_aux of (type_def_aux 'a) * annot 'a - - -let rec remove_one i l = - match l with - | [] -> [] - | i2::l2 -> if i2 = i then l2 else i2::(remove_one i l2) -end - -let rec remove_from l l2 = - match l2 with - | [] -> l - | i::l2' -> remove_from (remove_one i l) l2' -end - -let disjoint s1 s2 = Set.null (s1 inter s2) - -let rec disjoint_all sets = - match sets with - | [] -> true - | s1::[] -> true - | s1::s2::sets -> (disjoint s1 s2) && (disjoint_all (s2::sets)) -end - - -type ne = (* internal numeric expressions *) - | Ne_id of x - | Ne_var of x - | Ne_const of integer - | Ne_inf - | Ne_mult of ne * ne - | Ne_add of list ne - | Ne_minus of ne * ne - | Ne_exp of ne - | Ne_unary of ne - - -type t = (* Internal types *) - | T_id of x - | T_var of x - | T_fn of t * t * effect - | T_tup of list t - | T_app of x * t_args - | T_abbrev of t * t - -and t_arg = (* Argument to type constructors *) - | T_arg_typ of t - | T_arg_nexp of ne - | T_arg_effect of effect - | T_arg_order of order - -and t_args = (* Arguments to type constructors *) - | T_args of list t_arg - - -type k = (* Internal kinds *) - | Ki_typ - | Ki_nat - | Ki_ord - | Ki_efct - | Ki_ctor of list k * k - | Ki_infer (* Representing an unknown kind, inferred by context *) - - -type tid = (* A type identifier or type variable *) - | Tid_id of id - | Tid_var of kid - - -type kinf = (* Whether a kind is default or from a local binding *) - | Kinf_k of k - | Kinf_def of k - - -type nec = (* Numeric expression constraints *) - | Nec_lteq of ne * ne - | Nec_eq of ne * ne - | Nec_gteq of ne * ne - | Nec_in of x * list integer - | Nec_cond of list nec * list nec - | Nec_branch of list nec - - -type tag = (* Data indicating where the identifier arises and thus information necessary in compilation *) - | Tag_empty - | Tag_intro (* Denotes an assignment and lexp that introduces a binding *) - | Tag_set (* Denotes an expression that mutates a local variable *) - | Tag_tuple_assign (* Denotes an assignment with a tuple lexp *) - | Tag_global (* Globally let-bound or enumeration based value/variable *) - | Tag_ctor (* Data constructor from a type union *) - | Tag_extern of maybe string (* External function, specied only with a val statement *) - | Tag_default (* Type has come from default declaration, identifier may not be bound locally *) - | Tag_spec - | Tag_enum of integer - | Tag_alias - | Tag_unknown of maybe string (* Tag to distinguish an unknown path from a non-analysis non deterministic path *) - - -type tinf = (* Type variables, type, and constraints, bound to an identifier *) - | Tinf_typ of t - | Tinf_quant_typ of (map tid kinf) * list nec * tag * t - - -type conformsto = (* how much conformance does overloading need *) - | Conformsto_full - | Conformsto_parm - - -type widennum = - | Widennum_widen - | Widennum_dont - | Widennum_dontcare - - -type widenvec = - | Widenvec_widen - | Widenvec_dont - | Widenvec_dontcare - - -type widening = (* Should we widen vector start locations, should we widen atoms and ranges *) - | Widening_w of widennum * widenvec - - -type tinflist = (* In place so that a list of tinfs can be referred to without the dot form *) - | Tinfs_empty - | Tinfs_ls of list tinf - - type definition_env = - | DenvEmp - | Denv of (map tid kinf) * (map (list (id*t)) tinf) * (map t (list (nat*id))) - - -let blength (bit) = Ne_const 8 -let hlength (bit) = Ne_const 8 - - type env = - | EnvEmp - | Env of (map id tinf) * definition_env - - type inf = - | Iemp - | Inf of (list nec) * effect - - val denv_union : definition_env -> definition_env -> definition_env - let denv_union de1 de2 = - match (de1,de2) with - | (DenvEmp,de2) -> de2 - | (de1,DenvEmp) -> de1 - | ((Denv ke1 re1 ee1),(Denv ke2 re2 ee2)) -> - Denv (ke1 union ke2) (re1 union re2) (ee1 union ee2) - end - - val env_union : env -> env -> env - let env_union e1 e2 = - match (e1,e2) with - | (EnvEmp,e2) -> e2 - | (e1,EnvEmp) -> e1 - | ((Env te1 de1),(Env te2 de2)) -> - Env (te1 union te2) (denv_union de1 de2) - end - -let inf_union i1 i2 = - match (i1,i2) with - | (Iemp,i2) -> i2 - | (i1,Iemp) -> i1 - | (Inf n1 e1,Inf n2 e2) -> (Inf (n1++n2) (effect_union e1 e2)) - end - -let fresh_kid denv = Var "x" (*TODO When strings can be manipulated, this should actually build a fresh string*) - - - -type I = inf - - -type E = env - - -type tannot = maybe (t * tag * list nec * effect * effect) - - - -type i_direction = - | IInc - | IDec - - -type reg_id_aux 'a = - | RI_id of id - - -type reg_form = - | Form_Reg of id * tannot * i_direction - | Form_SubReg of id * reg_form * index_range - - -type ctor_kind = - | C_Enum of nat - | C_Union - - -type reg_id 'a = - | RI_aux of (reg_id_aux 'a) * annot 'a - - -type exp_aux 'a = (* expression *) - | E_block of list (exp 'a) (* sequential block *) - | E_nondet of list (exp 'a) (* nondeterministic block *) - | E_id of id (* identifier *) - | E_lit of lit (* literal constant *) - | E_cast of typ * (exp 'a) (* cast *) - | E_app of id * list (exp 'a) (* function application *) - | E_app_infix of (exp 'a) * id * (exp 'a) (* infix function application *) - | E_tuple of list (exp 'a) (* tuple *) - | E_if of (exp 'a) * (exp 'a) * (exp 'a) (* conditional *) - | E_for of id * (exp 'a) * (exp 'a) * (exp 'a) * order * (exp 'a) (* loop *) - | E_vector of list (exp 'a) (* vector (indexed from 0) *) - | E_vector_indexed of list (integer * (exp 'a)) * (opt_default 'a) (* vector (indexed consecutively) *) - | E_vector_access of (exp 'a) * (exp 'a) (* vector access *) - | E_vector_subrange of (exp 'a) * (exp 'a) * (exp 'a) (* subvector extraction *) - | E_vector_update of (exp 'a) * (exp 'a) * (exp 'a) (* vector functional update *) - | E_vector_update_subrange of (exp 'a) * (exp 'a) * (exp 'a) * (exp 'a) (* vector subrange update, with vector *) - | E_vector_append of (exp 'a) * (exp 'a) (* vector concatenation *) - | E_list of list (exp 'a) (* list *) - | E_cons of (exp 'a) * (exp 'a) (* cons *) - | E_record of (fexps 'a) (* struct *) - | E_record_update of (exp 'a) * (fexps 'a) (* functional update of struct *) - | E_field of (exp 'a) * id (* field projection from struct *) - | E_case of (exp 'a) * list (pexp 'a) (* pattern matching *) - | E_let of (letbind 'a) * (exp 'a) (* let expression *) - | E_assign of (lexp 'a) * (exp 'a) (* imperative assignment *) - | E_sizeof of nexp (* the value of nexp at run time *) - | E_return of (exp 'a) (* return (exp 'a) from current function *) - | E_exit of (exp 'a) (* halt all current execution *) - | E_assert of (exp 'a) * (exp 'a) (* halt with error (exp 'a) when not (exp 'a) *) - | E_internal_cast of annot 'a * (exp 'a) (* This is an internal cast, generated during type checking that will resolve into a syntactic cast after *) - | E_internal_exp of annot 'a (* This is an internal use for passing nexp information to library functions, postponed for constraint solving *) - | E_sizeof_internal of annot 'a (* For sizeof during type checking, to replace nexp with internal n *) - | E_internal_exp_user of annot 'a * annot 'a (* This is like the above but the user has specified an implicit parameter for the current function *) - | E_comment of string (* For generated unstructured comments *) - | E_comment_struc of (exp 'a) (* For generated structured comments *) - | E_internal_let of (lexp 'a) * (exp 'a) * (exp 'a) (* This is an internal node for compilation that demonstrates the scope of a local mutable variable *) - | E_internal_plet of (pat 'a) * (exp 'a) * (exp 'a) (* This is an internal node, used to distinguised some introduced lets during processing from original ones *) - | E_internal_return of (exp 'a) (* For internal use to embed into monad definition *) - | E_internal_value of value (* For internal use in interpreter to wrap pre-evaluated values when returning an action *) - -and exp 'a = - | E_aux of (exp_aux 'a) * annot 'a - -and value = (* interpreter evaluated value *) - | V_boxref of nat * t - | V_lit of lit - | V_tuple of list value - | V_list of list value - | V_vector of nat * i_direction * list value - | V_vector_sparse of nat * nat * i_direction * list (nat * value) * value - | V_record of t * list (id * value) - | V_ctor of id * t * ctor_kind * value - | V_unknown - | V_register of reg_form - | V_register_alias of alias_spec tannot * tannot - | V_track of value * set reg_form - -and lexp_aux 'a = (* lvalue expression *) - | LEXP_id of id (* identifier *) - | LEXP_memory of id * list (exp 'a) (* memory or register write via function call *) - | LEXP_cast of typ * id (* cast *) - | LEXP_tup of list (lexp 'a) (* multiple (non-memory) assignment *) - | LEXP_vector of (lexp 'a) * (exp 'a) (* vector element *) - | LEXP_vector_range of (lexp 'a) * (exp 'a) * (exp 'a) (* subvector *) - | LEXP_field of (lexp 'a) * id (* struct field *) - -and lexp 'a = - | LEXP_aux of (lexp_aux 'a) * annot 'a - -and fexp_aux 'a = (* field expression *) - | FE_Fexp of id * (exp 'a) - -and fexp 'a = - | FE_aux of (fexp_aux 'a) * annot 'a - -and fexps_aux 'a = (* field expression list *) - | FES_Fexps of list (fexp 'a) * bool - -and fexps 'a = - | FES_aux of (fexps_aux 'a) * annot 'a - -and opt_default_aux 'a = (* optional default value for indexed vector expressions *) - | Def_val_empty - | Def_val_dec of (exp 'a) - -and opt_default 'a = - | Def_val_aux of (opt_default_aux 'a) * annot 'a - -and pexp_aux 'a = (* pattern match *) - | Pat_exp of (pat 'a) * (exp 'a) - -and pexp 'a = - | Pat_aux of (pexp_aux 'a) * annot 'a - -and letbind_aux 'a = (* let binding *) - | LB_val_explicit of typschm * (pat 'a) * (exp 'a) (* let, explicit type ((pat 'a) must be total) *) - | LB_val_implicit of (pat 'a) * (exp 'a) (* let, implicit type ((pat 'a) must be total) *) - -and letbind 'a = - | LB_aux of (letbind_aux 'a) * annot 'a - -and alias_spec_aux 'a = (* register alias expression forms *) - | AL_subreg of (reg_id 'a) * id - | AL_bit of (reg_id 'a) * (exp 'a) - | AL_slice of (reg_id 'a) * (exp 'a) * (exp 'a) - | AL_concat of (reg_id 'a) * (reg_id 'a) - -and alias_spec 'a = - | AL_aux of (alias_spec_aux 'a) * annot 'a - - -type funcl_aux 'a = (* function clause *) - | FCL_Funcl of id * (pat 'a) * (exp 'a) - - -type rec_opt_aux = (* optional recursive annotation for functions *) - | Rec_nonrec (* non-recursive *) - | Rec_rec (* recursive *) - - -type tannot_opt_aux = (* optional type annotation for functions *) - | Typ_annot_opt_some of typquant * typ - - -type effect_opt_aux = (* optional effect annotation for functions *) - | Effect_opt_pure (* sugar for empty effect set *) - | Effect_opt_effect of effect - - -type funcl 'a = - | FCL_aux of (funcl_aux 'a) * annot 'a - - -type rec_opt = - | Rec_aux of rec_opt_aux * l - - -type tannot_opt = - | Typ_annot_opt_aux of tannot_opt_aux * l - - -type effect_opt = - | Effect_opt_aux of effect_opt_aux * l - - -type val_spec_aux 'a = (* value type specification *) - | VS_val_spec of typschm * id (* specify the type of an upcoming definition *) - | VS_extern_no_rename of typschm * id (* specify the type of an external function *) - | VS_extern_spec of typschm * id * string (* specify the type of a function from Lem *) - - -type fundef_aux 'a = (* function definition *) - | FD_function of rec_opt * tannot_opt * effect_opt * list (funcl 'a) - - -type scattered_def_aux 'a = (* scattered function and union type definitions *) - | SD_scattered_function of rec_opt * tannot_opt * effect_opt * id (* scattered function definition header *) - | SD_scattered_funcl of (funcl 'a) (* scattered function definition clause *) - | SD_scattered_variant of id * name_scm_opt * typquant (* scattered union definition header *) - | SD_scattered_unioncl of id * type_union (* scattered union definition member *) - | SD_scattered_end of id (* scattered definition end *) - - -type default_spec_aux 'a = (* default kinding or typing assumption *) - | DT_order of order - | DT_kind of base_kind * kid - | DT_typ of typschm * id - - -type dec_spec_aux 'a = (* register declarations *) - | DEC_reg of typ * id - | DEC_alias of id * (alias_spec 'a) - | DEC_typ_alias of typ * id * (alias_spec 'a) - - -type val_spec 'a = - | VS_aux of (val_spec_aux 'a) * annot 'a - - -type fundef 'a = - | FD_aux of (fundef_aux 'a) * annot 'a - - -type scattered_def 'a = - | SD_aux of (scattered_def_aux 'a) * annot 'a - - -type default_spec 'a = - | DT_aux of (default_spec_aux 'a) * l - - -type dec_spec 'a = - | DEC_aux of (dec_spec_aux 'a) * annot 'a - - -type dec_comm 'a = (* top-level generated comments *) - | DC_comm of string (* generated unstructured comment *) - | DC_comm_struct of (def 'a) (* generated structured comment *) - -and def 'a = (* top-level definition *) - | DEF_kind of (kind_def 'a) (* definition of named kind identifiers *) - | DEF_type of (type_def 'a) (* type definition *) - | DEF_fundef of (fundef 'a) (* function definition *) - | DEF_val of (letbind 'a) (* value definition *) - | DEF_spec of (val_spec 'a) (* top-level type constraint *) - | DEF_default of (default_spec 'a) (* default kind and type assumptions *) - | DEF_scattered of (scattered_def 'a) (* scattered function and type definition *) - | DEF_reg_dec of (dec_spec 'a) (* register declaration *) - | DEF_comm of (dec_comm 'a) (* generated comments *) - - -type defs 'a = (* definition sequence *) - | Defs of list (def 'a) - - - diff --git a/src/lem_interp/interp_inter_imp.lem b/src/lem_interp/interp_inter_imp.lem index fda9d5dd..68f82ccb 100644 --- a/src/lem_interp/interp_inter_imp.lem +++ b/src/lem_interp/interp_inter_imp.lem @@ -48,6 +48,7 @@ import Set_extra open import Pervasives open import Assert_extra open import Interp_ast +open import Interp_utilities open import Sail_impl_base open import Interp_interface @@ -501,7 +502,7 @@ let value_of_instruction_param direction (name,typ,v) = end in v let intern_instruction direction (name,parms) = - Interp_ast.V_ctor (Interp.id_of_string name) (T_id "ast") Interp_ast.C_Union + Interp_ast.V_ctor (Interp.id_of_string name) (mk_typ_id "ast") Interp_ast.C_Union (Interp_ast.V_tuple (List.map (value_of_instruction_param direction) parms)) let instruction_analysis top_level end_flag thunk_name regn_to_reg_details registers instruction = @@ -747,7 +748,7 @@ let instr_external_to_interp_value top_level instr = end in (*This type shouldn't be hard-coded*) Interp_ast.V_ctor (Interp_ast.Id_aux (Interp_ast.Id name) Interp_ast.Unknown) - (T_id "ast") Interp_ast.C_Union parmsV + (mk_typ_id "ast") Interp_ast.C_Union parmsV val instruction_to_istate : context -> instruction -> instruction_state let instruction_to_istate (top_level:context) (((name, parms) as instr):instruction) : instruction_state = diff --git a/src/lem_interp/interp_utilities.lem b/src/lem_interp/interp_utilities.lem index 4e8c1111..1878066f 100644 --- a/src/lem_interp/interp_utilities.lem +++ b/src/lem_interp/interp_utilities.lem @@ -52,15 +52,20 @@ let rec power (a: integer) (b: integer) : integer = let foldr2 f x l l' = List.foldr (Tuple.uncurry f) x (List.zip l l') let map2 f l l' = List.map (Tuple.uncurry f) (List.zip l l') -(*As in the type system, the first effect is local to the expression and the second is cummulative*) -type tannot = maybe (t * tag * list nec * effect * effect) - let get_exp_l (E_aux e (l,annot)) = l val pure : effect let pure = Effect_aux(Effect_set []) Unknown let unit_t = Typ_aux(Typ_app (Id_aux (Id "unit") Unknown) []) Unknown +let mk_typ_app str args = Typ_aux (Typ_app (Id_aux (Id str) Unknown) (List.map (fun aux -> Typ_arg_aux aux Unknown) args)) Unknown +let mk_typ_id str = Typ_aux (Typ_id (Id_aux (Id str) Unknown)) Unknown + +let mk_typ_var str = Typ_aux (Typ_var (Kid_aux (Var ("'" ^ str)) Unknown)) Unknown +let mk_typ_tup typs = Typ_aux (Typ_tup typs) Unknown + +let nconstant n = Nexp_aux (Nexp_constant n) Unknown + (* Workaround Lem's inability to scrap my (type classes) boilerplate. * Implementing only Eq, and only for literals - hopefully this will * be enough, but we should in principle implement ordering for everything in diff --git a/src/lem_interp/pretty_interp.ml b/src/lem_interp/pretty_interp.ml index 9f1ea3e3..950e1ac5 100644 --- a/src/lem_interp/pretty_interp.ml +++ b/src/lem_interp/pretty_interp.ml @@ -150,8 +150,7 @@ let doc_bkind (BK_aux(k,_)) = string (match k with | BK_type -> "Type" | BK_nat -> "Nat" - | BK_order -> "Order" - | BK_effect -> "Effect") + | BK_order -> "Order") let doc_op symb a b = infix 2 1 symb a b let doc_unop symb a = prefix 2 1 symb a @@ -233,7 +232,6 @@ let doc_typ, doc_atomic_typ, doc_nexp = and atomic_typ ((Typ_aux (t, _)) as ty) = match t with | Typ_id id -> doc_id id | Typ_var v -> doc_var v - | Typ_wild -> underscore | Typ_app _ | Typ_tup _ | Typ_fn _ -> (* exhaustiveness matters here to avoid infinite loops * if we add a new Typ constructor *) @@ -245,7 +243,6 @@ let doc_typ, doc_atomic_typ, doc_nexp = | Typ_arg_typ t -> app_typ t | Typ_arg_nexp n -> nexp n | Typ_arg_order o -> doc_ord o - | Typ_arg_effect e -> doc_effects e (* same trick to handle precedence of nexp *) and nexp ne = sum_typ ne @@ -277,10 +274,10 @@ let doc_typ, doc_atomic_typ, doc_nexp = in typ, atomic_typ, nexp let doc_nexp_constraint (NC_aux(nc,_)) = match nc with - | NC_fixed(n1,n2) -> doc_op equals (doc_nexp n1) (doc_nexp n2) + | NC_equal(n1,n2) -> doc_op equals (doc_nexp n1) (doc_nexp n2) | NC_bounded_ge(n1,n2) -> doc_op (string ">=") (doc_nexp n1) (doc_nexp n2) | NC_bounded_le(n1,n2) -> doc_op (string "<=") (doc_nexp n1) (doc_nexp n2) - | NC_nat_set_bounded(v,bounds) -> + | NC_set(v,bounds) -> doc_op (string "IN") (doc_var v) (braces (separate_map comma_sp doc_int bounds)) @@ -337,7 +334,6 @@ let doc_pat, doc_atomic_pat = | P_app(id,[]) -> doc_id id | P_record(fpats,_) -> braces (separate_map semi_sp fpat fpats) | P_vector pats -> brackets (separate_map comma_sp atomic_pat pats) - | P_vector_indexed ipats -> brackets (separate_map comma_sp npat ipats) | P_tup pats -> parens (separate_map comma_sp atomic_pat pats) | P_list pats -> squarebarbars (separate_map semi_sp atomic_pat pats) | P_app(_, _ :: _) | P_vector_concat _ -> @@ -493,13 +489,6 @@ let doc_exp, doc_let = | _ -> failwith "bit vector not just bit values") | _ -> failwith "bit vector not all lits") exps "")) else default_print ()) - | E_vector_indexed (iexps, (Def_val_aux(default,_))) -> - let default_string = - (match default with - | Def_val_empty -> string "" - | Def_val_dec e -> concat [semi; space; string "default"; equals; (exp env mem add_red show_hole_contents e)]) in - let iexp (i,e) = doc_op equals (doc_int i) (exp env mem add_red show_hole_contents e) in - brackets (concat [(separate_map comma iexp iexps);default_string]) | E_vector_update(v,e1,e2) -> brackets (doc_op (string "with") (exp env mem add_red show_hole_contents v) @@ -556,11 +545,7 @@ let doc_exp, doc_let = | _-> failwith "internal expression escaped" and let_exp env mem add_red show_hole_contents (LB_aux(lb,_)) = match lb with - | LB_val_explicit(ts,pat,e) -> - prefix 2 1 - (separate space [string "let"; doc_typscm_atomic ts; doc_atomic_pat pat; equals]) - (exp env mem add_red show_hole_contents e) - | LB_val_implicit(pat,e) -> + | LB_val(pat,e) -> prefix 2 1 (separate space [string "let"; doc_atomic_pat pat; equals]) (exp env mem add_red show_hole_contents e) @@ -603,13 +588,8 @@ let doc_default (DT_aux(df,_)) = match df with | DT_order o -> separate space [string "default"; string "Order"; doc_ord o] let doc_spec (VS_aux(v,_)) = match v with - | VS_val_spec(ts,id) -> + | VS_val_spec(ts,id, _, _) -> separate space [string "val"; doc_typscm ts; doc_id id] - | VS_extern_no_rename(ts,id) -> - separate space [string "val"; string "extern"; doc_typscm ts; doc_id id] - | VS_extern_spec(ts,id,s) -> - separate space [string "val"; string "extern"; doc_typscm ts; - doc_op equals (doc_id id) (dquotes (string s))] let doc_namescm (Name_sect_aux(ns,_)) = match ns with | Name_sect_none -> empty diff --git a/src/lem_interp/type_check.lem b/src/lem_interp/type_check.lem deleted file mode 100644 index 6c6cda1a..00000000 --- a/src/lem_interp/type_check.lem +++ /dev/null @@ -1,862 +0,0 @@ -(*========================================================================*) -(* Sail *) -(* *) -(* Copyright (c) 2013-2017 *) -(* Kathyrn Gray *) -(* Shaked Flur *) -(* Stephen Kell *) -(* Gabriel Kerneis *) -(* Robert Norton-Wright *) -(* Christopher Pulte *) -(* Peter Sewell *) -(* *) -(* All rights reserved. *) -(* *) -(* This software was developed by the University of Cambridge Computer *) -(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *) -(* (REMS) project, funded by EPSRC grant EP/K008528/1. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in *) -(* the documentation and/or other materials provided with the *) -(* distribution. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *) -(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *) -(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *) -(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *) -(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *) -(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *) -(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *) -(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *) -(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *) -(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *) -(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *) -(* SUCH DAMAGE. *) -(*========================================================================*) - -open import Pervasives -import Map -import Map_extra (* For 'find' instead of using lookup and maybe types, as we know it cannot fail *) -import Set_extra (* For 'to_list' because map only goes to set *) -import List_extra (* For 'nth' and 'head' where we know that they cannot fail *) -open import Show_extra (* for 'show' to convert nat to string) *) -open import String_extra (* for chr *) -import Assert_extra (*For failwith when partiality is known to be unreachable*) - -open import Sail_impl_base -open import Interp_ast -open import Interp_utilities -open import Instruction_extractor - -type tannot = Interp_ast.tannot - -(*Env of t counter, nexp counter, order counter, type env, order env, nexp env, nec env*) -type envs = | Env of nat * nat * nat * map string (t * nec) * map string order * map string ne * map string nec - -let union_envs (orig_envs : envs) (branch_envs : list envs) : envs = orig_envs - -let t_fresh envs = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - (T_var ("fresh_" ^ show t_count),(Env (t_count + 1) ne_count o_count t_env o_env ne_env nec_env)) -let nexp_fresh envs = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - (Ne_var ("fresh_" ^ show ne_count),(Env t_count (ne_count + 1) o_count t_env o_env ne_env nec_env)) -let ord_fresh envs = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - (Ord_aux (Ord_var (Kid_aux (Var ("fresh" ^ show o_count)) Unknown)) Unknown, - (Env t_count ne_count (o_count + 1) t_env o_env ne_env nec_env)) - -let get_nexp envs n = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Map.lookup n ne_env -let update_nexp envs n ne = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Env t_count ne_count o_count t_env o_env (Map.insert n ne ne_env) nec_env - -let get_typ envs t = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Map.lookup t t_env -let update_t envs t ty nec = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Env t_count ne_count o_count (Map.insert t (ty, nec) t_env) o_env ne_env nec_env - -let get_ord (envs : envs) (o :string) = - let (Env t_count ne_count o_count t_env (o_env : map string order) ne_env nec_env) = envs in - Map.lookup o o_env -let update_ord envs o ord = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Env t_count ne_count o_count t_env (Map.insert o ord o_env) ne_env nec_env - -let get_nec envs n = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Map.lookup nec_env n -let update_nec envs n nc = - let (Env t_count ne_count o_count t_env o_env ne_env nec_env) = envs in - Env t_count ne_count o_count t_env o_env ne_env (Map.insert n nc nec_env) - -let rec typ_to_t envs (Typ_aux typ _) = match typ with - | Typ_wild -> T_var "fresh" - | Typ_id id -> T_id (get_id id) - | Typ_var (Kid_aux (Var kid) _) -> T_var kid - | Typ_fn ptyp rtyp effect -> T_fn (typ_to_t envs ptyp) (typ_to_t envs rtyp) effect - | Typ_tup typs -> T_tup (List.map (typ_to_t envs) typs) - | Typ_app id typ_args -> T_app (get_id id) (T_args []) -end - -let rec pow_i (i:integer) (n:integer) : integer = - match (natFromInteger n) with - | 0 -> 1 - | n -> i * (pow_i i (integerFromNat (n-1))) -end -let two_pow = pow_i 2 - -let n_zero = Ne_const 0 -let n_one = Ne_const 1 -let n_two = Ne_const 2 - -val debug_print : string -> unit -declare ocaml target_rep function debug_print s = `Printf.eprintf` "%s" s - -type triple = Yes | No | Maybe -let triple_negate = function - | Yes -> No - | No -> Yes - | Maybe -> Maybe -end - - -(*Hand translated from Ocaml version*) - -let rec compare_nexps n1 n2 = - match (n1,n2) with - | (Ne_unary Ne_inf, Ne_unary Ne_inf) -> EQ - | (Ne_unary Ne_inf, _ ) -> LT - | (_ , Ne_unary Ne_inf) -> GT - | (Ne_const n1, Ne_const n2) -> compare n1 n2 - | (Ne_const _ , _ ) -> LT - | (_ , Ne_const _ ) -> GT - | (Ne_var i1 , Ne_var i2) -> compare i1 i2 - | (Ne_var _ , _ ) -> LT - | (_ , Ne_var _ ) -> GT - | (Ne_mult n0 n1, Ne_mult n2 n3) -> - (match compare_nexps n0 n2 with - | EQ -> compare_nexps n1 n3 - | a -> a end) - | (Ne_mult _ _ , _ ) -> LT - | (_ , Ne_mult _ _) -> GT - | (Ne_add[n1;n12],Ne_add [n2;n22]) -> - (match compare_nexps n1 n2 with - | EQ -> compare_nexps n12 n22 - | a -> a end) - | (Ne_add _ , _ ) -> LT - | (_ , Ne_add _ ) -> GT - | (Ne_minus n1 n12, Ne_minus n2 n22) -> - (match compare_nexps n1 n2 with - | EQ -> compare_nexps n12 n22 - | a -> a end) - | (Ne_minus _ _ , _ ) -> LT - | (_ , Ne_minus _ _ ) -> GT - | (Ne_exp n1, Ne_exp n2) -> compare_nexps n1 n2 - | (Ne_exp _ , _ ) -> LT - | (_ , Ne_exp _ ) -> GT - | (Ne_unary n1, Ne_unary n2) -> compare_nexps n1 n2 - | (Ne_unary _ , _ ) -> LT - | (_ , Ne_unary _ ) -> GT - | (Ne_inf, Ne_inf) -> EQ - | (Ne_inf, _ ) -> LT - | (_ , Ne_inf) -> GT -end - -let ~{ocaml} neLess b1 b2 = compare_nexps b1 b2 = LT -let ~{ocaml} neLessEq b1 b2 = compare_nexps b1 b2 <> GT -let ~{ocaml} neGreater b1 b2 = compare_nexps b1 b2 = GT -let ~{ocaml} neGreaterEq b1 b2 = compare_nexps b1 b2 <> LT - -let inline {ocaml} neLess = defaultLess -let inline {ocaml} neLessEq = defaultLessEq -let inline {ocaml} neGreater = defaultGreater -let inline {ocaml} neGreaterEq = defaultGreaterEq - -instance (Ord ne) - let compare = compare_nexps - let (<) = neLess - let (<=) = neLessEq - let (>) = neGreater - let (>=) = neGreaterEq -end - -let rec get_var n = match n with - | Ne_var _ -> Just n - | Ne_exp _ -> Just n - | Ne_unary n -> get_var n - | Ne_mult _ n1 -> get_var n1 - | _ -> Nothing -end - -let rec nexp_negative n = - match n with - | Ne_const i -> if i < 0 then Yes else No - | Ne_unary Ne_inf -> Yes - | Ne_inf -> No - | Ne_exp _ -> No - | Ne_var _ -> No - | Ne_mult n1 n2 -> (match (nexp_negative n1, nexp_negative n2) with - | (Yes,Yes) -> No - | (No, No) -> No - | (No, Yes) -> Yes - | (Yes, No) -> Yes - | _ -> Maybe end) - | Ne_add [n1;n2] -> (match (nexp_negative n1, nexp_negative n2) with - | (Yes,Yes) -> Yes - | (No, No) -> No - | _ -> Maybe end) - | _ -> Maybe -end - -let negate = function - | Ne_const i -> Ne_const ((0-1) * i) - | n -> Ne_mult (Ne_const (0-1)) n -end - -let increment_factor n i = - match n with - | Ne_var _ -> - (match i with - | Ne_const i -> - let ni = i + 1 in - if ni = 0 then n_zero else Ne_mult (Ne_const ni) n - | _ -> Ne_mult (Ne_add [i; n_one]) n end) - | Ne_exp _-> - (match i with - | Ne_const i -> - let ni = i + 1 in - if ni = 0 then n_zero else Ne_mult (Ne_const ni) n - | _ -> Ne_mult (Ne_add [i; n_one]) n end) - | Ne_mult n1 n2 -> - (match (n1,i) with - | (Ne_const i2,Ne_const i) -> - let ni = i + i2 in - if ni = 0 then n_zero else Ne_mult (Ne_const(i + i2)) n2 - | _ -> Ne_mult (Ne_add [n1; i]) n2 end) - | _ -> n - end - -let get_factor = function - | Ne_var _ -> n_one - | Ne_mult n1 _ -> n1 - | _ -> Assert_extra.failwith "get_factor argument not normalized" -end - -let rec normalize_n_rec recur_ok n = - match n with - | Ne_const _ -> n - | Ne_var _ -> n - | Ne_inf -> n - | Ne_unary n -> - let (n',to_recur,add_neg) = - (match n with - | Ne_const i -> (negate n,false,false) - | Ne_add [n1;n2] -> (Ne_add [negate n1; negate n2],true,false) - | Ne_minus n1 n2 -> (Ne_minus n2 n1,true,false) - | Ne_unary n -> (n,true,false) - | _ -> (n,true,true) end) in - if to_recur - then (let n' = normalize_n_rec true n' in - if add_neg - then negate n' - else n') - else n' - | Ne_exp n -> - let n' = normalize_n_rec true n in - (match n' with - | Ne_const i -> Ne_const (two_pow i) - | _ -> Ne_exp n' end) - | Ne_add [n1;n2] -> - let (n1',n2') = (normalize_n_rec true n1, normalize_n_rec true n2) in - (match (n1',n2', recur_ok) with - | (Ne_unary Ne_inf, Ne_inf,_) -> Assert_extra.failwith "Type inference should have failed" - | (Ne_inf, Ne_unary Ne_inf,_) -> Assert_extra.failwith "Type inference should have failed" - | (Ne_inf, _,_) -> Ne_inf - | (_, Ne_inf, _) -> Ne_inf - | (Ne_unary Ne_inf, _,_) -> Ne_unary Ne_inf - | (_, Ne_unary Ne_inf, _) -> Ne_unary Ne_inf - | (Ne_const i1, Ne_const i2,_) -> Ne_const (i1 + i2) - | (Ne_add [n11;n12], Ne_const i, true) -> - if (i = 0) - then n1' - else normalize_n_rec false (Ne_add [n11; (normalize_n_rec false (Ne_add [n12; n2']))]) - | (Ne_add [n11;n12], Ne_const i, false) -> - if i = 0 then n1' - else Ne_add [n11; (normalize_n_rec false (Ne_add [n12; n2']))] - | (Ne_const i, Ne_add[n21;n22], true) -> - if i = 0 then n2' - else normalize_n_rec false (Ne_add [n21; (normalize_n_rec false (Ne_add [n22; n1']))]) - | (Ne_const i, Ne_add [n21;n22], false) -> - if (i = 0) then n2' - else Ne_add [n21; (normalize_n_rec false (Ne_add [n22; n1']))] - | (Ne_const i, _,_) -> if i = 0 then n2' else Ne_add [n2'; n1'] - | (_, Ne_const i,_) -> if i = 0 then n1' else Ne_add [n1'; n2'] - | (Ne_add [n11;n12], Ne_add[n21;n22], true) -> - (match compare_nexps n11 n21 with - | GT -> normalize_n_rec false (Ne_add [n21; (normalize_n_rec false (Ne_add [n22; n1']))]) - | EQ -> - (match compare_nexps n12 n22 with - | GT -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_add [n12; n22])]) - | EQ -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_mult n_two n12)]) - | _ -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_add [n22; n12])]) end) - | _ -> normalize_n_rec false (Ne_add [n11; (normalize_n_rec false (Ne_add [n12; n2']))])end) - | (Ne_add[n11;n12], Ne_add[n21;n22], false) -> - (match compare_nexps n11 n21 with - | GT -> Ne_add [n21; (normalize_n_rec false (Ne_add [n22; n1']))] - | EQ -> - (match compare_nexps n12 n22 with - | GT -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_add [n12; n22])]) - | EQ -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_mult n_two n12)]) - | _ -> normalize_n_rec true (Ne_add [(Ne_mult n_two n11); (Ne_add [n22; n12])]) end) - | _ -> Ne_add [n11; (normalize_n_rec false (Ne_add [n12; n2']))] end) - | (Ne_exp n11, Ne_exp n21,_) -> - (match compare_nexps n11 n21 with - | GT -> Ne_add [n1'; n2'] - | EQ -> Ne_exp (normalize_n_rec true (Ne_add [n11; n_one])) - | _ -> Ne_add [ n2'; n1'] end) - | (Ne_exp n11,Ne_add[n21;n22],_) -> - (match n21 with - | Ne_exp n211 -> - (match compare_nexps n11 n211 with - | GT -> Ne_add [n21; (normalize_n_rec true (Ne_add [n11; n22]))] - | EQ -> Ne_add [(Ne_exp (normalize_n_rec true (Ne_add [n11; n_one]))); n22] - | _ -> Ne_add [n1'; n2'] end) - | _ -> Ne_add [n1'; n2'] end) - | (Ne_add [n11;n12],Ne_exp n21,_) -> - (match n11 with - | Ne_exp n111 -> - (match compare_nexps n111 n21 with - | GT -> Ne_add [n2'; n1'] - | EQ -> Ne_add [(Ne_exp (normalize_n_rec true (Ne_add [n111; n_one]))); n12] - | _ -> Ne_add [n11; (normalize_n_rec true (Ne_add [n2'; n12]))] end) - | _ -> Ne_add [n2'; n1'] end) - | _ -> - (match (get_var n1', get_var n2') with - | (Just nv1,Just nv2) -> - (match compare_nexps nv1 nv2 with - | GT -> Ne_add [n1'; n2'] - | EQ -> increment_factor n1' (get_factor n2') - | _ -> Ne_add [n2'; n1'] end) - | (Just (nv1),Nothing) -> Ne_add [n2'; n1'] - | (Nothing,Just(nv2)) -> Ne_add [n1'; n2'] - | _ -> (match (n1',n2') with - | (Ne_add[n11';n12'], _) -> - (match compare_nexps n11' n2' with - | GT -> Ne_add [n11'; (normalize_n_rec true (Ne_add [n12'; n2']))] - | EQ -> Assert_extra.failwith "Neither term has var but are the same?" - | _ -> Ne_add [n2';n1'] end) - | (_, Ne_add[n21';n22']) -> - (match compare_nexps n1' n21' with - | GT -> Ne_add [n1'; n2'] - | EQ -> Assert_extra.failwith "Unexpected equality" - | _ -> Ne_add [n21'; (normalize_n_rec true (Ne_add [n1'; n22']))] end) - | _ -> - (match compare_nexps n1' n2' with - | GT -> Ne_add [n1'; n2'] - | EQ -> normalize_n_rec true (Ne_mult n_two n1') - | _ -> Ne_add [n2'; n1'] end) end) end) end) - | Ne_minus n1 n2 -> - let (n1',n2') = (normalize_n_rec true n1, normalize_n_rec true n2) in - (match (n1',n2') with - | (Ne_unary Ne_inf, Ne_inf) -> Assert_extra.failwith "Type checker should have caught" - | (Ne_inf, Ne_unary Ne_inf) -> Assert_extra.failwith "Type checker should have caught" - | (Ne_inf, _) -> Ne_inf - | (_,Ne_unary Ne_inf) -> Ne_inf - | (Ne_unary Ne_inf, _) -> Ne_unary Ne_inf - | (_,Ne_inf) -> Ne_unary Ne_inf - | (Ne_const i1, Ne_const i2) -> Ne_const (i1 - i2) - | (Ne_const i, _) -> - if (i = 0) - then normalize_n_rec true (negate n2') - else normalize_n_rec true (Ne_add [(negate n2'); n1']) - | (_, Ne_const i) -> - if (i = 0) - then n1' - else normalize_n_rec true (Ne_add [n1'; (Ne_const ((0 - 1) * i))]) - | (_,_) -> - (match compare_nexps n1 n2 with - | EQ -> n_zero - | GT -> Ne_add [n1'; (negate n2')] - | _ -> Ne_add [(negate n2'); n1'] end) end) - | Ne_mult n1 n2 -> - let (n1',n2') = (normalize_n_rec true n1, normalize_n_rec true n2) in - (match (n1',n2') with - | (Ne_unary Ne_inf,Ne_unary Ne_inf) -> Ne_inf - | (Ne_inf, Ne_const i) -> if i = 0 then Ne_const 0 else Ne_inf - | (Ne_const i, Ne_inf) -> if i = 0 then Ne_const 0 else Ne_inf - | (Ne_unary Ne_inf, Ne_const i) -> - if i = 0 then Ne_const 0 - else if i < 0 then Ne_inf - else Ne_unary Ne_inf - | (Ne_const i, Ne_unary Ne_inf) -> - if i = 0 then Ne_const 0 - else if i < 0 then Ne_inf - else Ne_unary Ne_inf - | (Ne_unary Ne_inf, _) -> - (match nexp_negative n2 with - | Yes -> Ne_inf - | _ -> Ne_unary Ne_inf end) - | (_, Ne_unary Ne_inf) -> - (match nexp_negative n1 with - | Yes -> Ne_inf - | _ -> Ne_unary Ne_inf end) - | (Ne_inf, _) -> - (match nexp_negative n2 with - | Yes -> Ne_unary Ne_inf - | _ -> Ne_inf end) - | (_, Ne_inf) -> - (match nexp_negative n1 with - | Yes -> Ne_unary Ne_inf - | _ -> Ne_inf end) - | (Ne_const i1, Ne_const i2) -> Ne_const (i1 * i2) - | (Ne_const i1, Ne_exp n) -> - if i1 = 2 - then Ne_exp (normalize_n_rec true (Ne_add [n;n_one])) - else Ne_mult n1' n2' - | (Ne_exp n, Ne_const i1) -> - if i1 = 2 - then Ne_exp (normalize_n_rec true (Ne_add [n; n_one])) - else Ne_mult n2' n1' - | (Ne_mult _ _, Ne_var _) -> Ne_mult n1' n2' - | (Ne_exp n1, Ne_exp n2) -> Ne_exp (normalize_n_rec true (Ne_add [n1; n2])) - | (Ne_exp _, Ne_var _) -> Ne_mult n2' n1' - | (Ne_exp _, Ne_mult _ _) -> Ne_mult n2' n1' - | (Ne_var _, Ne_var _) -> - (match compare n1' n2' with - | EQ -> Ne_mult n1' n2' - | GT -> Ne_mult n1' n2' - | _ -> Ne_mult n2' n1' end) - | (Ne_const _, Ne_add [n21;n22]) -> - normalize_n_rec true (Ne_add [(Ne_mult n1' n21); (Ne_mult n1' n21)]) - | (Ne_var _,Ne_add [n21;n22]) -> - normalize_n_rec true (Ne_add [(Ne_mult n1' n21); (Ne_mult n1' n21)]) - | (Ne_exp _, Ne_add[n21;n22]) -> - normalize_n_rec true (Ne_add [(Ne_mult n1' n21); (Ne_mult n1' n21)]) - | (Ne_mult _ _, Ne_add[n21;n22]) -> - normalize_n_rec true (Ne_add [(Ne_mult n1' n21); (Ne_mult n1' n21)]) - | (Ne_add[n11;n12],Ne_const _) -> - normalize_n_rec true (Ne_add [(Ne_mult n11 n2'); (Ne_mult n12 n2')]) - | (Ne_add [n11;n12],Ne_var _) -> - normalize_n_rec true (Ne_add [(Ne_mult n11 n2'); (Ne_mult n12 n2')]) - | (Ne_add([n11;n12]), Ne_exp _) -> - normalize_n_rec true (Ne_add [(Ne_mult n11 n2'); (Ne_mult n12 n2')]) - | (Ne_add [n11;n12], Ne_mult _ _) -> - normalize_n_rec true (Ne_add [(Ne_mult n11 n2'); (Ne_mult n12 n2')]) - | (Ne_mult n11 n12 , Ne_const _) -> - normalize_n_rec false (Ne_mult (Ne_mult n11 n2') (Ne_mult n12 n2')) - | (Ne_const i1, _) -> - if (i1 = 0) then n1' - else if (i1 = 1) then n2' - else Ne_mult n1' n2' - | (_, Ne_const i1) -> - if (i1 = 0) then n2' - else if (i1 = 1) then n1' - else Ne_mult n2' n1' - | (Ne_add [n11;n12],Ne_add [n21;n22]) -> - normalize_n_rec true (Ne_add [(Ne_mult n11 n21); - (Ne_add [(Ne_mult n11 n22); - (Ne_add [(Ne_mult n12 n21); (Ne_mult n12 n22)])])]) - | (Ne_mult _ _, Ne_exp _) -> Ne_mult n1' n2' - | (Ne_var _, Ne_mult n1 n2) -> - (match (get_var n1, get_var n2) with - | (Just(nv1),Just(nv2)) -> - (match compare_nexps nv1 nv2 with - | EQ -> Ne_mult n1 (Ne_mult nv1 nv1) - | GT -> Ne_mult (normalize_n_rec true (Ne_mult n1 n1')) n2 - | _ -> Ne_mult n2' n1' end) - | _ -> Ne_mult (normalize_n_rec true (Ne_mult n1 n1')) n2 end) - | (Ne_var _, Ne_exp _) -> Ne_mult n2' n1' - | (Ne_mult _ _,Ne_mult n21 n22) -> Ne_mult (Ne_mult n21 n1') (Ne_mult n22 n1') - | _ -> Assert_extra.failwith "Normalize hit a case that should have been removed" end) -end - -let normalize_nexp = normalize_n_rec true - -let rec range_in_range envs (recur1,recur2,recur3,recur4) act_bot act_top exp_bot exp_top = - let (act_bot,act_top,exp_bot,exp_top) = - if recur1 && recur2 && recur3 && recur4 - then (normalize_nexp act_bot, normalize_nexp act_top, normalize_nexp exp_bot, normalize_nexp exp_top) - else (act_bot,act_top,exp_bot,exp_top) - in - match (act_bot,recur1,act_top,recur2,exp_bot,recur3,exp_top,recur4) with - | (Ne_var i, true, _,_, _,_, _,_) -> - (match get_nexp envs i with - | Just n -> range_in_range envs (false, recur2,recur3,recur4) n act_top exp_bot exp_top - | Nothing -> range_in_range envs (false,recur2,recur3,recur4) act_bot act_top exp_bot exp_top end) - | (_, _, Ne_var i, true, _, _, _, _) -> - (match get_nexp envs i with - | Just n -> range_in_range envs (recur1,false,recur3,recur4) act_bot n exp_bot exp_top - | Nothing -> range_in_range envs (recur1,false,recur3,recur4) act_bot act_top exp_bot exp_top end) - | (_,_,_,_,Ne_var i,true,_,_) -> - (match get_nexp envs i with - | Just n -> range_in_range envs (recur1,recur2,false,recur4) act_bot act_top n exp_top - | Nothing -> range_in_range envs (recur1,recur2,false,recur4) act_bot act_top exp_bot exp_top end) - | (_,_,_,_,_,_,Ne_var i,true) -> - (match get_nexp envs i with - | Just n -> range_in_range envs (recur1,recur2,recur3,false) act_bot act_top exp_bot n - | Nothing -> range_in_range envs (recur1,recur2,recur3,false) act_bot act_top exp_bot exp_top end) - | (Ne_const abi,_, Ne_const ati,_, Ne_const ebi,_, Ne_const ebt,_) -> - ebi <= abi && abi <= ebt && ati <= ebt - | (Ne_const abi,_, Ne_const ati,_, Ne_unary Ne_inf,_, Ne_inf,_) -> true - | (Ne_const abi,_, Ne_const ati,_, Ne_const ebi,_, Ne_inf,_) -> - ebi <= abi - | (Ne_const abi,_, Ne_const ati,_, Ne_unary Ne_inf,_, Ne_const ebt,_) -> - abi <= ebt && ati <= ebt - | (Ne_unary Ne_inf,_, Ne_inf,_, Ne_unary Ne_inf,_, Ne_inf,_) -> true -end - -let rec single_in_range envs act exp_bot exp_top = - let (act,exp_bot,exp_top) = (normalize_nexp act, normalize_nexp exp_bot, normalize_nexp exp_top) in - match (act,exp_bot,exp_top) with - | (Ne_const ai, Ne_const ebi, Ne_const eti) -> - ebi <= ai && ai <= eti - | (Ne_const _, Ne_unary Ne_inf, Ne_inf) -> true - | (Ne_const ai, Ne_const ebi, Ne_inf) -> ebi <= ai - | (Ne_const ai, Ne_unary Ne_inf, Ne_const eti) -> ai <= eti - end - -let make_new_range envs start length (Ord_aux order _) = - let is_inc = match order with - | Ord_inc -> true - | Ord_dec -> false - | Ord_var (Kid_aux (Var id) _) -> - (match get_ord envs id with - | Just (Ord_aux Ord_inc _) -> true - | Just (Ord_aux Ord_dec _) -> false - | _ -> true (* Default direction is inc *) end) end in - let length_n = match (normalize_nexp length) with - | Ne_var i -> (match get_nexp envs i with - | Just n -> n - | Nothing -> Assert_extra.failwith "Vector type has no length" end) - | n -> n end in - let start_n = match (normalize_nexp start) with - | Ne_var i -> (match get_nexp envs i with - | Just n -> n - | Nothing -> if is_inc then Ne_const 0 else (Ne_minus length_n n_one) end) - | n -> n end in - if is_inc - then T_app "range" (T_args [T_arg_nexp start;T_arg_nexp (Ne_minus (Ne_add [start;length]) n_one)]) - else T_app "range" (T_args [T_arg_nexp (Ne_add [(Ne_minus start_n length_n);n_one]); T_arg_nexp start]) - -let consistent_eff eff1 eff2 = true - -let rec consistent_typ envs (typ_actual :t) (typ_allowed : t) = - match (typ_actual,typ_allowed) with - | (T_abbrev ta _, T_abbrev tb _) -> consistent_typ envs ta tb - | (T_abbrev ta _, t) -> consistent_typ envs ta t - | (t, T_abbrev tb _) -> consistent_typ envs t tb - | (T_id x, T_id y) -> (x=y, envs) - | (T_fn act_parms act_ret act_eff, T_fn all_parms all_ret all_eff) -> - let (consistent,envs) = consistent_typ envs act_parms all_parms in - if consistent - then let (consistent,envs) = consistent_typ envs act_ret all_ret in - if consistent - then (consistent_eff act_eff all_eff, envs) - else (false,envs) - else (false,envs) - | (T_tup act_tups, T_tup all_tups) -> - if List.length act_tups = List.length all_tups - then consistent_typ_list envs act_tups all_tups - else (false,envs) - | (T_app "range" (T_args [T_arg_nexp low;T_arg_nexp high]), - T_app "range" (T_args [T_arg_nexp all_low;T_arg_nexp all_high])) -> - (range_in_range envs (true,true,true,true) low high all_low all_high,envs) - | (T_app "range" (T_args [T_arg_nexp low;T_arg_nexp high]), - T_app "atom" (T_args [T_arg_nexp all])) -> - (false,envs) - | (T_app "atom" (T_args [T_arg_nexp act]), T_app "range" (T_args [T_arg_nexp low; T_arg_nexp high])) -> - (single_in_range envs act low high,envs) - | (T_app "atom" (T_args [T_arg_nexp act]), T_app "atom" (T_args [T_arg_nexp all])) -> - (false,envs) - | (T_app "vector" (T_args [T_arg_nexp start; T_arg_nexp size; T_arg_order dir; T_arg_typ t]), - T_app "vector" (T_args [T_arg_nexp sta; T_arg_nexp sia ; T_arg_order da ; T_arg_typ ta])) -> - let (consistent,envs) = consistent_nexp envs start sta in - if consistent then - let (consistent,envs) = consistent_nexp envs size sia in - if consistent then - if dir = da - then consistent_typ envs t ta - else (false,envs) - else (false,envs) - else (false,envs) - | (T_app x (T_args args_act), T_app y (T_args args_all)) -> - if x = y && List.length args_act = List.length args_all - then consistent_typ_arg_list envs args_act args_all - else (false, envs) - | (T_var x, T_var y) -> (x = y,envs) - | _ -> (false,envs) -end - -and - consistent_nexp envs n_acc n_all = - let (n_acc,n_all) = (normalize_nexp n_acc,normalize_nexp n_all) in - match (n_acc,n_all) with - | (Ne_const iac, Ne_const ial) -> (iac = ial, envs) - | (Ne_exp nac, Ne_exp nal) -> consistent_nexp envs nac nal - | (_, Ne_inf) -> (true,envs) - | (Ne_var i, _) -> (true,envs) - | (_, Ne_var i) -> (true,envs) - | _ -> (true,envs) -end - -and consistent_typ_list envs t_accs t_alls = - match (t_accs,t_alls) with - | ([],[]) -> (true,envs) - | (t_acc::t_accs,t_all::t_alls) -> - let (consistent,envs) = consistent_typ envs t_acc t_all in - if consistent - then consistent_typ_list envs t_accs t_alls - else (false,envs) - | _ -> (false,envs) -end - -and consistent_typ_arg_list envs t_accs t_alls = - let arg_check t_acc t_all = - match (t_acc,t_all) with - | (T_arg_typ tacc,T_arg_typ tall) -> consistent_typ envs tacc tall - | (T_arg_nexp nacc,T_arg_nexp nall) -> consistent_nexp envs nacc nall - | (T_arg_order oacc, T_arg_order oall) -> (oacc=oall,envs) - | (T_arg_effect eacc, T_arg_effect eall) -> (consistent_eff eacc eall, envs) - end in - match (t_accs,t_alls) with - | ([],[]) -> (true,envs) - | (ta::tas,t::ts) -> - let (consistent,envs) = arg_check ta t in - if consistent - then consistent_typ_arg_list envs tas ts - else (false,envs) - | _ -> (false,envs) -end - -let mk_atom n = T_app "atom" (T_args [T_arg_nexp (Ne_const n)]) - -let check_lit envs typ (L_aux lit loc) = - match lit with - | L_num n -> consistent_typ envs (mk_atom n) typ - | L_zero -> consistent_typ envs (T_id "bit") typ - | L_one -> consistent_typ envs (T_id "bit") typ - | L_string _ -> consistent_typ envs (T_id "string") typ - | L_undef -> (true,envs) - | _ -> (false,envs) -end - -let rec check_exp envs ret_typ exp_typ (E_aux exp (l,annot)) = - let (typ,tag,ncs,effect,reffect) = match annot with - | Nothing -> - (T_var "fresh_v", Tag_empty,[],(Effect_aux (Effect_set []) Unknown),(Effect_aux (Effect_set []) Unknown)) - | Just(t, tag, ncs, ef,efr) -> (t,tag,ncs,ef,efr) end in - match exp with - | E_block exps -> check_block envs envs true ret_typ exp_typ exps - | E_nondet exps -> check_block envs envs false ret_typ exp_typ exps - | E_id id -> - (match get_typ envs (get_id id) with - | Just (t,necs) -> let (consistent,envs) = consistent_typ envs typ t in - if consistent - then consistent_typ envs typ exp_typ - else (false,envs) - | Nothing -> (false,envs) end) - | E_lit lit -> - let (consistent,envs) = check_lit envs exp_typ lit in - if consistent - then consistent_typ envs typ exp_typ - else (false,envs) - | E_cast typ exp -> - let t = typ_to_t envs typ in - let (consistent,envs) = check_exp envs ret_typ t exp in - if consistent - then consistent_typ envs t exp_typ - else (false,envs) - | E_app id exps -> (*Need to connect constraints for the function to new type variables in the parms and ret*) - (match get_typ envs (get_id id) with - | Just ((T_fn parms ret effects),necs) -> - (match (parms,exps) with - | (T_tup (_::_ as typs), (_::_ as exps)) -> - if List.length typs = List.length exps - then let (consistent,envs) = List.foldr (fun (exp,typ) (consistent,envs) -> - if consistent - then check_exp envs ret_typ typ exp - else (false,envs)) (true,envs) (List.zip exps typs) in - if consistent - then consistent_typ envs ret exp_typ - else (false,envs) - else (false,envs) - | (T_id "unit", []) -> - consistent_typ envs ret exp_typ - | (T_id "unit", [E_aux (E_lit (L_aux L_unit _)) _]) -> - consistent_typ envs ret exp_typ - | _ -> (false,envs) end) - | _ -> (false, envs) end) - | E_app_infix lexp id rexp -> - (match get_typ envs (get_id id) with - | Just ((T_fn parms ret effects),necs) -> - (match parms with - | T_tup [ltyp;rtyp] -> - let (consistent,envs) = check_exp envs ret_typ ltyp lexp in - if consistent then - let (consistent,envs) = check_exp envs ret_typ rtyp rexp in - if consistent - then consistent_typ envs ret exp_typ - else (false,envs) - else (false,envs) - | _ -> (false,envs) end) - | _ -> (false, envs) end) - | E_tuple exps -> - (match (typ,exp_typ) with - | (T_tup typs, T_tup e_typs) -> - if List.length typs = List.length e_typs && List.length exps = List.length typs - then - let typ_list = List.zip typs e_typs in - let exp_typs_list = List.zip exps typ_list in - List.foldr (fun (exp, (typ,e_typ)) (consistent,envs) -> - if consistent - then let (consistent,envs) = check_exp envs ret_typ e_typ exp in - consistent_typ envs typ e_typ - else (false,envs)) (true,envs) exp_typs_list - else (false,envs) - | _ -> (false,envs) end) - | E_if cond t_branch e_branch -> - let (consistent,envs) = check_exp envs ret_typ (T_id "bit") cond in - if consistent - then let (consistent,envs_t) = check_exp envs ret_typ exp_typ t_branch in - if consistent - then let (consistent,envs_e) = check_exp envs ret_typ exp_typ e_branch in - if consistent - then consistent_typ (union_envs envs [envs_t; envs_e]) typ exp_typ - else (false,envs) - else (false,envs) - else (false,envs) - | E_for id from to_ by ((Ord_aux o _) as order) exp -> (false,envs) - | E_vector exps -> - (match (typ,exp_typ) with - | (T_app "vector" (T_args [T_arg_nexp start; T_arg_nexp length; T_arg_order ord; T_arg_typ typ]), - T_app "vector" (T_args [T_arg_nexp strte; T_arg_nexp lenge; T_arg_order orde; T_arg_typ typ_e])) -> - let (consistent, envs) = consistent_nexp envs start strte in - if consistent then - let (consistent, envs) = consistent_nexp envs length lenge in - if consistent then - let (consistent,envs) = consistent_nexp envs (Ne_const (integerFromNat (List.length exps))) length in - if consistent then - List.foldr (fun exp (consistent,envs) -> - if consistent - then check_exp envs ret_typ exp_typ exp - else (false,envs)) (true,envs) exps - else (false,envs) - else (false,envs) - else (false,envs) - | _ -> (false,envs) end) - | E_vector_indexed iexps default -> (false,envs) - | E_vector_access vexp aexp -> - let (fresh_start,envs) = nexp_fresh envs in - let (fresh_length, envs) = nexp_fresh envs in - let (fresh_order, envs) = ord_fresh envs in - let (consistent,envs) = - check_exp envs ret_typ (T_app "vector" (T_args [T_arg_nexp fresh_start; T_arg_nexp fresh_length; - T_arg_order fresh_order; T_arg_typ typ])) vexp in - if consistent - then check_exp envs ret_typ (make_new_range envs fresh_start fresh_length fresh_order) aexp - else (false,envs) - | E_vector_subrange vexp sexp eexp -> - let (fresh_start,envs) = nexp_fresh envs in - let (fresh_length,envs) = nexp_fresh envs in - let (fresh_order, envs) = ord_fresh envs in - (match (typ,exp_typ) with - | (T_app "vector" (T_args [T_arg_nexp sstart; T_arg_nexp sleng; T_arg_order ord; T_arg_typ typ]), - T_app "vector" (T_args [T_arg_nexp sse; T_arg_nexp sle; T_arg_order oe; T_arg_typ exp_typ])) -> - let (consistent,envs) = - check_exp envs ret_typ (T_app "vector" (T_args [T_arg_nexp fresh_start; T_arg_nexp fresh_length; - T_arg_order fresh_order; T_arg_typ exp_typ])) vexp in - if consistent - then let range = make_new_range envs fresh_start fresh_length fresh_order in - let (consistent,envs) = check_exp envs ret_typ range sexp in - if consistent - then check_exp envs ret_typ range eexp (*TODO, make sure that the sub piece is build by the s and e terms*) - else (false,envs) - else (false,envs) - | _ -> (false,envs) end) - | E_vector_update vexp aexp nexp -> (false,envs) - | E_vector_update_subrange vexp sexp eexp nexp -> (false,envs) - | E_vector_append lexp rexp -> - (match (typ,exp_typ) with - | (T_app "vector" (T_args[T_arg_nexp start;T_arg_nexp length;T_arg_order dir;T_arg_typ t]), - T_app "vector" (T_args[T_arg_nexp ste; T_arg_nexp lee; T_arg_order dre; T_arg_typ te])) -> - let (startl,envs) = nexp_fresh envs in - let (lenl,envs) = nexp_fresh envs in - let (startr,envs) = nexp_fresh envs in - let (lenr,envs) = nexp_fresh envs in - let (consistent,envs) = - check_exp envs ret_typ (T_app "vector" (T_args [T_arg_nexp startl;T_arg_nexp lenl; - T_arg_order dir; T_arg_typ te])) lexp in - if consistent then - let (consistent,envs) = - check_exp envs ret_typ (T_app "vector" (T_args [T_arg_nexp startr;T_arg_nexp lenr; - T_arg_order dir; T_arg_typ te])) rexp in - if consistent then - let (consistent,envs) = consistent_typ envs typ exp_typ in - if consistent - then consistent_nexp envs (Ne_add [lenl; lenr]) lee - else (false,envs) - else (false,envs) - else (false,envs) - | _ -> (false,envs) end) - | E_list exps -> - (match (typ,exp_typ) with - | (T_app "list" (T_args [T_arg_typ t]),T_app "list" (T_args [T_arg_typ te])) -> - let (consistent,envs) = List.foldr (fun exp (consistent,envs) -> - if consistent - then check_exp envs ret_typ te exp - else (false,envs)) (true,envs) exps in - if consistent - then consistent_typ envs t te - else (false,envs) - | _ -> (false,envs) end) - | E_cons hexp texp -> - (match (typ,exp_typ) with - | (T_app "list" (T_args [T_arg_typ t]),T_app "list" (T_args [T_arg_typ te])) -> - let (consistent,envs) = check_exp envs ret_typ te hexp in - if consistent - then let (consistent,envs) = check_exp envs ret_typ exp_typ texp in - if consistent - then consistent_typ envs t te - else (false,envs) - else (false,envs) - | _ -> (false,envs) end) - | E_record fexps -> (false,envs) - | E_record_update rexp fexps -> (false,envs) - | E_field exp id -> (false,envs) - | E_case exp pexps -> (false,envs) - | E_let lbind exp -> (false,envs) - | E_assign lexp exp -> (false,envs) - | E_sizeof nexp -> (false,envs) - | E_exit exp -> let (fresh_t,envs) = t_fresh envs in check_exp envs ret_typ fresh_t exp - | E_return exp -> check_exp envs ret_typ ret_typ exp - | E_assert cond mesg -> - let (consistent,envs) = check_exp envs ret_typ (T_id "bit") cond in - if consistent then - let (consistent,envs) = check_exp envs ret_typ (T_app "option" (T_args[T_arg_typ (T_id "string")])) mesg in - if consistent - then consistent_typ envs (T_id "unit") exp_typ - else (false,envs) - else (false,envs) - | E_internal_cast tannot exp -> (false,envs) - | E_internal_exp tannot -> (false,envs) - | E_sizeof_internal tannot -> (false,envs) - | E_internal_exp_user tannot tannot2 -> (false,envs) - | E_comment msg -> (true,envs) - | E_comment_struc exp -> (true,envs) - | E_internal_let lexp exp inexp -> (false,envs) - | E_internal_plet pat exp inexp -> (false,envs) - | E_internal_return exp -> (false,envs) -end - -and check_block orig_envs envs carry_variables_forward ret_typ exp_typ exps = (false,orig_envs) |
