summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lem_interp/interp.lem249
-rw-r--r--src/lem_interp/interp_inter_imp.lem366
-rw-r--r--src/lem_interp/interp_utilities.lem7
-rw-r--r--src/lem_interp/printing_functions.ml2
-rw-r--r--src/pretty_print.ml6
5 files changed, 360 insertions, 270 deletions
diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem
index 15584b60..aa7edf37 100644
--- a/src/lem_interp/interp.lem
+++ b/src/lem_interp/interp.lem
@@ -27,8 +27,8 @@ let ctor_annot typ = Just(typ,Tag_ctor,[],pure)
let enum_annot typ max = Just(typ,Tag_enum max,[],pure)
-let non_det_annot annot = match annot with
- | Just(t,_,cs,ef) -> Just(t,Tag_unknown,cs,ef)
+let non_det_annot annot maybe_id = match annot with
+ | Just(t,_,cs,ef) -> Just(t,Tag_unknown maybe_id,cs,ef)
| _ -> Nothing
end
@@ -187,15 +187,15 @@ end
(*Constant unit value, for use in interpreter *)
let unitv = V_lit (L_aux L_unit Unknown)
-(* Store for local memory of ref cells *)
-type lmem = LMem of nat * map nat value
+(* Store for local memory of ref cells, string stores the name of the function the memory is being created for*)
+type lmem = LMem of string * nat * map nat value * set nat
(* Environment for bindings *)
type env = map string value
(* Environment for lexical bindings, nat is a counter to build new unique variables when necessary *)
type lenv = LEnv of nat * env
-let emem = LMem 1 Map.empty
+let emem name = LMem name 1 Map.empty Set.empty
let eenv = LEnv 1 Map.empty
type sub_reg_map = map string index_range
@@ -368,15 +368,19 @@ 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 *)
-val update_mem : lmem -> nat -> value -> lmem
-let update_mem (LMem c m) loc value =
+val update_mem : bool -> lmem -> nat -> value -> lmem
+let update_mem track (LMem owner c m s) loc value =
let m' = Map.delete loc m in
let m' = Map.insert loc value m' in
- LMem c m'
+ let s' = if track then Set.insert loc s else s in
+ LMem owner c m' s'
+
+val clear_updates : lmem -> lmem
+let clear_updates (LMem owner c m _) = LMem owner c m Set.empty
(*Value helper functions*)
@@ -474,7 +478,8 @@ let rec merge_values v1 v2 =
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') ->
- if n = m then v1 else V_unknown (*Any change to locations in memory should be handled above this level*)
+ (*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') ->
@@ -510,6 +515,29 @@ let rec merge_values v1 v2 =
| (_, _) -> V_unknown
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 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
+ (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
+ (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
+ (fun i mem -> update_mem false mem i (merge_values (in_mem lmem1 i) (in_mem lmem2 i)))
+ diff_mem2 inters
+
let vector_length v = match (detaint v) with
| V_vector n inc vals -> List.length vals
| V_vector_sparse n m inc vals def -> m
@@ -658,15 +686,15 @@ let fupdate_vector_slice vec replace start stop =
end) in
binary_taint fupdate_vec_help vec replace
-val update_vector_slice : value -> value -> nat -> nat -> lmem -> lmem
-let update_vector_slice vector value start stop mem =
+val update_vector_slice : bool -> value -> value -> nat -> nat -> lmem -> lmem
+let update_vector_slice track vector value start stop mem =
match (detaint vector,detaint value) with
| ((V_boxref n t), v) ->
- update_mem 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 mem n v end)
+ | 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)) ->
let (V_vector m' _ vs') = slice_vector vector start stop in
@@ -674,7 +702,7 @@ let update_vector_slice vector value start stop mem =
match vbox with
| V_boxref n t ->
(if is_inc(dir) then i+1 else i-1,
- update_mem mem n (match List.lookup i vals with
+ update_mem track mem n (match List.lookup i vals with
| Nothing -> d
| Just v -> v end))
end) (m,mem) vs' in
@@ -682,7 +710,7 @@ let update_vector_slice vector value start stop mem =
| ((V_vector m _ vs),v) ->
let (V_vector m' _ vs') = slice_vector vector start stop in
List.foldr (fun vbox mem -> match vbox with
- | V_boxref n t -> update_mem mem n v end)
+ | V_boxref n t -> update_mem track mem n v end)
mem vs'
end
@@ -753,6 +781,26 @@ let get_stack_state stack =
| Thunk_frame exp top_level lenv lmem stack -> (lenv,lmem)
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 ->
+ (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)
+ | Thunk_frame e t_level env _ Top -> Thunk_frame e t_level env lmem Top
+ | Hole_frame id e t_level env mem s -> Hole_frame id e t_level env mem (update_stack_state s lmem)
+ | Thunk_frame e t_level env mem s -> Thunk_frame e t_level env mem (update_stack_state s lmem)
+end
+
+let rec clear_stack_state stack =
+ match stack with
+ | Top -> Top
+ | Hole_frame id e t_level env lmem Top -> Hole_frame id e t_level env (clear_updates lmem) Top
+ | Thunk_frame e t_level env lmem Top -> Thunk_frame e t_level env (clear_updates lmem) Top
+ | Hole_frame id e t_level env lmem s -> Hole_frame id e t_level env lmem (clear_stack_state s)
+ | Thunk_frame e t_level env lmem s -> Thunk_frame e t_level env lmem (clear_stack_state s)
+end
(*functions for converting in progress evaluation back into expression for building current continuation*)
let rec combine_typs ts =
@@ -942,10 +990,14 @@ let env_to_let mode (LEnv _ env) (E_aux e annot) taint_env =
(E_aux e annot))
annot, taint_env)
end
-(*
+
let fix_up_nondet typ branches annot =
- match typ with
- | T_id "unit" -> *)
+ match typ with
+ | T_id "unit" -> (branches, Nothing)
+ | T_abbrev _ (T_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
(* match_pattern returns a tuple of (pattern_matches? , pattern_passed_due_to_unknown?, env_of_pattern *)
val match_pattern : top_level -> pat tannot -> value -> bool * bool * lenv
@@ -1379,7 +1431,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| (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,_) ->
- interp_main mode t_level l_env lm (E_aux (E_block [thn;els]) (l,annot))
+ 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
| (_,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))))
@@ -1471,7 +1524,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
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
- interp_main mode t_level taint_env lm (E_aux (E_block lets) (l,annot))
+ 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) ->
@@ -1848,7 +1902,11 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| E_block exps -> interp_block mode t_level l_env l_env l_mem l annot exps
| E_nondet exps ->
(Action (Nondet exps tag)
- (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,(intern_annot annot))) t_level l_env l_mem Top),
+ (match tag with
+ | Tag_unknown (Just id) ->
+ Hole_frame redex_id (E_aux (E_id redex_id) (l,(intern_annot annot))) t_level l_env l_mem Top
+ | _ ->
+ Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l,(intern_annot annot))) t_level l_env l_mem Top end),
l_mem, l_env)
| E_app f args ->
(match (exp_list mode t_level
@@ -1868,8 +1926,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,_,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just v) exp t_level emem env))
+ 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 (E_aux (E_id redex_id) (l,(intern_annot annot)))
@@ -1878,7 +1936,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
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
- interp_main mode t_level taint_env lm (E_aux (E_block lets) (l,annot))
+ 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)
| Nothing ->
(Error l (String.stringAppend "Internal error: function with tag global unfound " name),lm,le) end)
@@ -1891,8 +1950,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,used_unknown,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just v) exp t_level emem env))
+ 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 (E_aux (E_id redex_id) (l,(intern_annot annot)))
@@ -1909,8 +1968,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,used_unknown,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just v) exp t_level emem env))
+ 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 ->
@@ -1977,8 +2036,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,used_unknown,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level emem env))
+ 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 stack ->
@@ -1994,8 +2053,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,used_unknown,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level emem env))
+ 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 stack -> (Hole_frame redex_id (E_aux (E_id redex_id) (l,annot))
@@ -2010,8 +2069,8 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
| [(env,used_unknown,exp)] ->
resolve_outcome
(if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just (V_tuple [lv;rv])) exp t_level emem env))
+ 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 stack -> (Hole_frame redex_id
@@ -2102,17 +2161,28 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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)), update_mem l_mem n (recenter_val t value), l_env),Nothing)
+ then ((Value (V_lit (L_aux L_unit l)),
+ update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing)
else ((Value v, l_mem, l_env),Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env)))
| V_unknown ->
if is_top_level then
- let (LMem c m) = l_mem in
- let l_mem = (LMem (c+1) m) in
- ((Value (V_lit (L_aux L_unit l)),
- update_mem l_mem c value, (add_to_env (id,(V_boxref c typ)) l_env)),Nothing)
+ if name = "0" then
+ ((Value (V_lit (L_aux L_unit l)), update_mem true l_mem 0 value, l_env), Nothing)
+ 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)),
+ update_mem mode.track_lmem l_mem c value,
+ (add_to_env (id,(V_boxref c typ)) l_env)),Nothing)
else ((Error l ("Unknown local id " ^ (get_id id)),l_mem,l_env),Nothing)
| v ->
- if is_top_level then ((Error l "Writes must be to reg values",l_mem,l_env),Nothing)
+ 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)
+ else
+ ((Error l ("Writes must be to reg values given " ^ (string_of_value v)),l_mem,l_env),
+ Nothing)
else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env)))
end
| Tag_global ->
@@ -2251,8 +2321,8 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
" on value " ^ (string_of_value new_vals)),l_mem,l_env),Nothing)
| [(env,used_unknown,exp)] ->
(match (if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just new_vals) exp t_level emem env)) with
+ 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)
| (Action action stack,lm,le) ->
(((update_stack (Action action stack)
@@ -2263,7 +2333,9 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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
- (interp_main mode t_level taint_env lm (E_aux (E_block lets) (l,annot)), Nothing)
+ 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)
end)
| Nothing ->
((Error l ("Internal error: function unfound " ^ name),lm,le),Nothing) end)
@@ -2280,8 +2352,8 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
" on value " ^ (string_of_value new_vals)),l_mem,l_env),Nothing)
| [(env,used_unknown,exp)] ->
(match (if mode.eager_eval
- then (interp_main mode t_level env emem exp)
- else (debug_out (Just name) (Just new_vals) exp t_level emem env)) with
+ 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)
| (Action action stack,lm,le) ->
(((update_stack (Action action stack)
@@ -2292,7 +2364,9 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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
- (interp_main mode t_level taint_env lm (E_aux (E_block lets) (l,annot)), Nothing)
+ 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)
end)
| Nothing ->
((Error l ("Internal error: function unfound " ^ name),lm,le),Nothing) end)
@@ -2307,14 +2381,16 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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)), update_mem l_mem n (recenter_val t value), l_env),Nothing)
- else ((Value v, l_mem, l_env),Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)))
+ then ((Value (V_lit (L_aux L_unit l)),
+ update_mem mode.track_lmem l_mem n (recenter_val t value), l_env),Nothing)
+ else ((Value v, l_mem, l_env),
+ Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)))
| V_unknown ->
if is_top_level
then begin
- let (LMem c m) = l_mem in
- let l_mem = (LMem (c+1) m) in
- ((Value (V_lit (L_aux L_unit l)), update_mem l_mem c value,
+ 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,
(add_to_env (id,(V_boxref c typ)) l_env)),Nothing)
end
else ((Error l ("Undefined id " ^ (get_id id)),l_mem,l_env),Nothing)
@@ -2331,13 +2407,16 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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))
+ (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)
else (request,Just (fun e env -> (LEXP_aux (LEXP_cast typc id) (l,annot), env)))
| _ ->
- ((Error l ("Internal error: writing to id not extern or empty " ^(get_id id)),l_mem,l_env),Nothing)
+ ((Error l ("Internal error: writing to id not extern or empty " ^(get_id id)),l_mem,l_env),
+ Nothing)
end
| LEXP_vector lexp exp ->
match (interp_main mode t_level l_env l_mem exp) with
@@ -2361,13 +2440,16 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
(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)), update_mem lm i new_vec, l_env), Nothing)
+ ((Value (V_lit (L_aux L_unit Unknown)),
+ update_mem mode.track_lmem lm i new_vec, l_env), 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)), update_mem lm i (taint new_vec r),l_env),Nothing)
+ ((Value (V_lit (L_aux L_unit Unknown)),
+ update_mem mode.track_lmem lm i (taint new_vec r),l_env),Nothing)
| ((V_vector _ _ _ as vec),false, Just lexp_builder) ->
((Value (access_vector vec n), lm, l_env), Just (next_builder lexp_builder))
- | (v,_,_) -> Assert_extra.failwith("no vector findable in set bit, found " ^ (string_of_value v))
+ | (v,_,_) ->
+ Assert_extra.failwith("no vector findable in set bit, found " ^ (string_of_value v))
end )
| V_vector inc m vs ->
(match (nth(),is_top_level,maybe_builder) with
@@ -2386,11 +2468,15 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
l_mem,l_env),
Just (next_builder lexp_builder))
| (V_boxref n t,true,_) ->
- ((Value (V_lit (L_aux L_unit Unknown)), update_mem lm n value, l_env),Nothing)
+ ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm n value, l_env),
+ Nothing)
| (V_unknown,true,_) -> ((Value (V_lit (L_aux L_unit Unknown)), lm, l_env),Nothing)
- | (v,true,_) -> ((Error l "Vector does not contain reg or register values",lm,l_env),Nothing)
- | ((V_boxref n t),false, Just lexp_builder) -> ((Value (in_mem lm n),lm, l_env),Just (next_builder lexp_builder))
- | (v,false, Just lexp_builder) -> ((Value v,lm,le), Just (next_builder lexp_builder)) end)
+ | (v,true,_) ->
+ ((Error l "Vector does not contain reg or register values",lm,l_env),Nothing)
+ | ((V_boxref n t),false, Just lexp_builder) ->
+ ((Value (in_mem lm n),lm, l_env),Just (next_builder lexp_builder))
+ | (v,false, Just lexp_builder) ->
+ ((Value v,lm,le), Just (next_builder lexp_builder)) end)
| V_vector_sparse n m inc vs d ->
(match (nth(),is_top_level,maybe_builder) with
| (V_register regform,true,_) ->
@@ -2407,13 +2493,15 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
l_mem,l_env),
Just (next_builder lexp_builder))
| (V_boxref n t,true,_) ->
- ((Value (V_lit (L_aux L_unit Unknown)), update_mem lm n value, l_env),Nothing)
- | (v,true,_) ->
- ((Error l ("Vector does not contain reg or register values " ^ (string_of_value v)),lm,l_env),
+ ((Value (V_lit (L_aux L_unit Unknown)), update_mem mode.track_lmem lm n value, l_env),
Nothing)
+ | (v,true,_) ->
+ ((Error l ("Vector does not contain reg or register values " ^ (string_of_value v)),
+ lm,l_env), Nothing)
| ((V_boxref n t),false, Just lexp_builder) ->
((Value (in_mem lm n),lm, l_env),Just (next_builder lexp_builder))
- | (v,false, Just lexp_builder) -> ((Value v,lm,le), Just (next_builder lexp_builder)) end)
+ | (v,false, Just lexp_builder) ->
+ ((Value v,lm,le), Just (next_builder lexp_builder)) end)
| v ->
((Error l ("Vector access to write of non-vector" ^ (string_of_value v)),lm,l_env),Nothing)
end)
@@ -2430,13 +2518,16 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
then (update_vector_start default_dir n 1 value)
else (access_vector value n))) s,lm,le),
Just (next_builder lexp_builder))
- | ((Write_mem id a Nothing value),true) -> ((Action (Write_mem id a (Just (n,n)) value) s,lm,le), Nothing)
+ | ((Write_mem id a Nothing value),true) ->
+ ((Action (Write_mem id a (Just (n,n)) value) s,lm,le), Nothing)
| ((Write_mem id a Nothing value),false) ->
((Action (Write_mem id a (Just (n,n)) value) s,lm,le), Just (next_builder lexp_builder))
| _ -> ((Action a s,lm,le), Just (next_builder lexp_builder)) end)
| e -> e end)
- | v -> ((Error l ("Vector access must be a number given " ^ (string_of_value v)),lm,le),Nothing) end)
- | (Action a s,lm,le) -> ((Action a s,lm,le), Just (fun e env -> (LEXP_aux (LEXP_vector lexp e) (l,annot), env)))
+ | v ->
+ ((Error l ("Vector access must be a number given " ^ (string_of_value v)),lm,le),Nothing) end)
+ | (Action a s,lm,le) ->
+ ((Action a s,lm,le), Just (fun e env -> (LEXP_aux (LEXP_vector lexp e) (l,annot), env)))
| e -> (e,Nothing) end
| LEXP_vector_range lexp exp1 exp2 ->
match (interp_main mode t_level l_env l_mem exp1) with
@@ -2460,16 +2551,19 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
| ((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)), update_vector_slice v value n1 n2 lm, l_env), Nothing)
+ ((Value (V_lit (L_aux L_unit Unknown)),
+ update_vector_slice mode.track_lmem v value n1 n2 lm, l_env), Nothing)
| (V_boxref _ _, true) ->
- ((Value (V_lit (L_aux L_unit Unknown)), update_vector_slice v value n1 n2 lm, l_env), Nothing)
+ ((Value (V_lit (L_aux L_unit Unknown)),
+ update_vector_slice mode.track_lmem v value n1 n2 lm, l_env), Nothing)
| (V_vector m inc vs,false) ->
((Value (slice_vector v n1 n2),lm,l_env), Just (next_builder lexp_builder))
| (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
- ((Value (V_vector start (if inc then IInc else IDec) (List.replicate size V_unknown)),lm,l_env),Nothing)
+ ((Value (V_vector start (if inc then IInc else IDec) (List.replicate size V_unknown)),
+ lm,l_env),Nothing)
| _ -> ((Error l "Vector required",lm,le),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
@@ -2501,7 +2595,8 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level (
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) -> ((Value (V_lit (L_aux L_unit l)), update_mem lm n value, l_env),Nothing)
+ | (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)
| (Just (V_boxref n t),false) -> ((Value (in_mem lm n),lm,l_env),next_builder)
| (Just v, true) -> ((Error l "Mutating a field access requires a reg type",lm,le),Nothing)
| (Just v,false) -> ((Value v,lm,l_env),next_builder)
@@ -2624,11 +2719,11 @@ let rec eval_toplevel_let handle_action tlevel env mem lbind =
let rec to_global_letbinds handle_action (Defs defs) t_level =
let (Env fdefs instrs default_dir lets regs ctors subregs aliases) = t_level in
match defs with
- | [] -> ((Value (V_lit (L_aux L_unit Unknown)), emem, eenv),t_level)
+ | [] -> ((Value (V_lit (L_aux L_unit Unknown)), (emem "global_letbinds"), eenv),t_level)
| def::defs ->
match def with
| DEF_val lbind ->
- match eval_toplevel_let handle_action t_level eenv emem lbind with
+ match eval_toplevel_let handle_action t_level eenv (emem "global_letbinds") lbind with
| Just le ->
to_global_letbinds handle_action (Defs defs)
(Env fdefs instrs default_dir (Map.(union) lets le) regs ctors subregs aliases)
@@ -2677,8 +2772,8 @@ let to_top_env external_functions defs =
let interp mode external_functions defs exp =
match (to_top_env external_functions defs) with
| (Nothing,t_level) ->
- interp_main mode t_level eenv emem exp
- | (Just o,_) -> (o,emem,eenv)
+ interp_main mode t_level eenv (emem "top level") exp
+ | (Just o,_) -> (o,(emem "top level error"),eenv)
end
let rec resume_with_env mode stack value =
@@ -2713,7 +2808,7 @@ let rec 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,eenv)
+ | (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) ->
interp_main mode t_level (add_to_env (id,value) env) mem exp
| (Hole_frame id exp t_level env mem Top,Nothing) ->
diff --git a/src/lem_interp/interp_inter_imp.lem b/src/lem_interp/interp_inter_imp.lem
index ed576d2d..88ce56e4 100644
--- a/src/lem_interp/interp_inter_imp.lem
+++ b/src/lem_interp/interp_inter_imp.lem
@@ -20,6 +20,9 @@ let make_interp_mode eager_eval tracking_values =
let make_mode eager_eval tracking_values endian =
<|internal_mode = make_interp_mode eager_eval tracking_values;
endian = endian|>;;
+let make_mode_exhaustive endian =
+ <| internal_mode = <| Interp.eager_eval = true; Interp.track_values = true; Interp.track_lmem = true|>;
+ endian = endian |>;;
let tracking_dependencies mode = mode.internal_mode.Interp.track_values
let make_eager_mode mode = <| mode with internal_mode = <|mode.internal_mode with Interp.eager_eval = true |> |>;;
let make_default_mode _ = <|internal_mode = make_interp_mode false false; endian = E_big_endian|>;;
@@ -228,57 +231,6 @@ let rec slice_reg_value v start stop =
(if inc then (stop - v.rv_start) else (v.rv_start - stop)) v.rv_bits);
rv_start = (if inc then start else ((stop - start) + 1)) |>
-(*
-let append_value left right =
- match (left,right) with
- | (Bitvector bools1 inc fst, Bitvector bools2 _ _) -> Bitvector (bools1++bools2) inc fst
- | (Bytevector bytes1, Bytevector bytes2) -> Bytevector (bytes1++bytes2)
- | ((Bitvector _ _ _ as bit),(Bytevector _ as byte)) ->
- (match (intern_value bit,intern_value byte) with
- | (Interp.V_vector a b bits1,Interp.V_vector _ _ bits2) ->
- (fst (extern_value (make_mode true false) false Nothing (Interp.V_vector a b (bits1++bits2))))
- | _ -> Unknown end)
- | ((Bytevector _ as byte),(Bitvector _ _ _ as bit)) ->
- (match (intern_value byte,intern_value bit) with
- | (Interp.V_vector a b bits1,Interp.V_vector _ _ bits2) ->
- (fst (extern_value (make_mode true false) true Nothing (Interp.V_vector a b (bits1++bits2))))
- | _ -> Unknown end)
- | _ -> Unknown
-end
-
-let add_to_address value num =
- match value with
- | Unknown -> Unknown
- | Bitvector _ _ _ ->
- fst(extern_value (make_mode true false) false Nothing
- (Interp_lib.arith_op_vec_range (+) Interp_lib.Unsigned 1
- (Interp.V_tuple [(intern_value value);Interp.V_lit (L_aux (L_num num) Interp_ast.Unknown)])))
- | Bytevector _ ->
- fst(extern_value (make_mode true false) true Nothing
- (Interp_lib.arith_op_vec_range (+) Interp_lib.Unsigned 1
- (Interp.V_tuple [(intern_value value);Interp.V_lit (L_aux (L_num num) Interp_ast.Unknown)])))
-end
-
-
-let coerce_Bytevector_of_Bitvector (v: value) : value =
- match v with
- | Bitvector bs b i -> Bytevector (to_bytes bs)
- | _ -> Assert_extra.failwith "coerce_Bytevector_of_Bitvector given non-Bitvector"
- end
-
-let coerce_Bitvector_of_Bytevector (v: value) : value =
- match v with
- | Bytevector ws -> Bitvector
- (List.concatMap
- (fun w ->
- List.reverse
- (boolListFrombitSeq 8 (bitSeqFromNat w)))
- ws)
- true
- 0
- | _ -> Assert_extra.failwith "coerce_Bitvector_of_Bitvector given non-Bytevector"
- end
-*)
let initial_instruction_state top_level main args =
let e_args = match args with
@@ -287,7 +239,7 @@ let initial_instruction_state top_level main args =
| args -> List.map fst (List.map (Interp.to_exp (make_interp_mode true false) Interp.eenv)
(List.map intern_reg_value args)) end in
Interp.Thunk_frame (E_aux (E_app (Id_aux (Id main) Interp_ast.Unknown) e_args) (Interp_ast.Unknown, Nothing))
- top_level Interp.eenv Interp.emem Interp.Top
+ top_level Interp.eenv (Interp.emem "istate top level") Interp.Top
let rec interp_to_value_helper arg err_str instr direction thunk =
@@ -375,7 +327,7 @@ let decode_to_istate top_level value =
mode
(Interp.Thunk_frame
(E_aux (E_app (Id_aux (Id "decode") Interp_ast.Unknown) [arg]) (Interp_ast.Unknown, Nothing))
- top_env Interp.eenv Interp.emem Interp.Top) Nothing) in
+ top_env Interp.eenv (Interp.emem "decode top level") Interp.Top) Nothing) in
match (instr_decoded,error) with
| (Just instr, _) ->
let instr_external = match instr with
@@ -400,14 +352,14 @@ let decode_to_istate top_level value =
(Interp.Thunk_frame
(E_aux (E_app (Id_aux (Id "supported_instructions") Interp_ast.Unknown) [arg])
(Interp_ast.Unknown, Nothing))
- top_env Interp.eenv Interp.emem Interp.Top) Nothing) in
+ top_env Interp.eenv (Interp.emem "decode second top level") Interp.Top) Nothing) in
match (instr_decoded,error) with
| (Just instr,_) ->
(*let (arg,_) = Interp.to_exp mode Interp.eenv instr in*)
Instr instr_external
(IState (Interp.Thunk_frame
(E_aux (E_app (Id_aux (Id "execute") Interp_ast.Unknown) [arg]) (Interp_ast.Unknown,Nothing))
- top_env Interp.eenv Interp.emem Interp.Top)
+ top_env Interp.eenv (Interp.emem "execute") Interp.Top)
top_level)
| (Nothing, Just err) -> Decode_error err
end
@@ -444,120 +396,125 @@ let instruction_to_istate (top_level:context) (((name, parms, _) as instr):instr
[(E_aux (E_app (Id_aux (Id name) Interp_ast.Unknown) (List.map get_value parms))
(Interp_ast.Unknown,Interp.ctor_annot (T_id "ast")) (*This type shouldn't be hard-coded*))])
(Interp_ast.Unknown,Nothing))
- top_env Interp.eenv Interp.emem Interp.Top)
+ top_env Interp.eenv (Interp.emem "execute") Interp.Top)
top_level)
let rec interp_to_outcome mode context thunk =
let (Context _ direction mem_reads mem_writes mem_write_eas mem_write_vals barriers spec_externs) = context in
let internal_direction = if direction = D_increasing then Interp.IInc else Interp.IDec in
match thunk () with
- | (Interp.Value _,lm,le) -> Done
- | (Interp.Error l msg,lm,le) -> Error msg
+ | (Interp.Value _,lm,le) -> (Done,lm)
+ | (Interp.Error l msg,lm,le) -> (Error msg,lm)
| (Interp.Action a next_state,lm,le) ->
- match a with
- | Interp.Read_reg reg_form slice ->
- Read_reg (extern_reg reg_form slice)
- (fun v ->
- let v = (intern_reg_value v) in
- let v = if mode.internal_mode.Interp.track_values then (Interp.V_track v (Set.fromList [reg_form])) else v in
- IState (Interp.add_answer_to_stack next_state v) context)
- | Interp.Write_reg reg_form slice value ->
- let reg_name = extern_reg reg_form slice in
- Write_reg reg_name (extern_reg_value reg_name value) (IState next_state context)
- | Interp.Read_mem (Id_aux (Id i) _) value slice ->
- match List.lookup i mem_reads with
- | (Just (MR read_k f)) ->
- let (location, length, tracking) = (f mode value) in
- if (List.length location) = 8
- then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
- | Just bs -> Just (integer_of_byte_list bs)
- | _ -> Nothing end in
- Read_mem read_k (Address_lifted location address_int) length tracking
- (fun v -> IState (Interp.add_answer_to_stack next_state (intern_mem_value mode direction v)) context)
- else Error ("Memory address on read is not 64 bits")
- | _ -> Error ("Memory " ^ i ^ " function with read kind not found")
- end
- | Interp.Write_mem (Id_aux (Id i) _) loc_val slice write_val ->
- match List.lookup i mem_writes with
- | (Just (MW write_k f return)) ->
- let (location, length, tracking) = (f mode loc_val) in
- let (value, v_tracking) = (extern_mem_value mode write_val) in
- if (List.length location) = 8
- then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
- | Just bs -> Just (integer_of_byte_list bs)
- | _ -> Nothing end in
- Write_mem write_k (Address_lifted location address_int)
- length tracking value v_tracking
- (fun b ->
- match return with
- | Nothing -> (IState (Interp.add_answer_to_stack next_state Interp.unitv) context)
- | Just return_bool -> return_bool (IState next_state context) b end)
- else Error "Memory address on write is not 64 bits"
- | _ -> Error ("Memory " ^ i ^ " function with write kind not found")
- end
- | Interp.Write_ea (Id_aux (Id i) _) loc_val ->
- match List.lookup i mem_write_eas with
- | (Just (MEA write_k f)) ->
- let (location, length, tracking) = (f mode loc_val) in
- if (List.length location) = 8
- then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
- | Just bs -> Just (integer_of_byte_list bs)
- | _ -> Nothing end in
- Write_ea write_k (Address_lifted location address_int) length tracking (IState next_state context)
- else Error "Memory address for write is not 64 bits"
- | _ -> Error ("Memory " ^ i ^ " function to signal impending write, not found") end
- | Interp.Write_memv (Id_aux (Id i) _) write_val ->
- match List.lookup i mem_write_vals with
- | (Just (MV return)) ->
- let (value, v_tracking) =
- match (Interp.detaint write_val) with
- | Interp.V_tuple[_;v] -> (extern_mem_value mode (Interp.retaint write_val v))
- | _ -> (extern_mem_value mode write_val) end in
- Write_memv value v_tracking
- (fun b ->
- match return with
- | Nothing -> (IState (Interp.add_answer_to_stack next_state Interp.unitv) context)
- | Just return_bool -> return_bool (IState next_state context) b end)
- | _ -> Error ("Memory " ^ i ^ " function with write value kind not found") end
- | Interp.Barrier (Id_aux (Id i) _) lval ->
- match List.lookup i barriers with
- | Just barrier ->
- Barrier barrier (IState next_state context)
- | _ -> Error ("Barrier " ^ i ^ " function not found") end
- | Interp.Footprint (Id_aux (Id i) _) lval ->
- Footprint (IState next_state context)
- | Interp.Nondet exps tag ->
- match tag with
- | Tag_unknown ->
- let possible_states = List.map (Interp.set_in_context next_state) exps in
- Analysis_non_det (List.map (fun i -> IState i context) possible_states) (IState next_state context)
- | _ ->
- let nondet_states = List.map (Interp.set_in_context next_state) exps in
- Nondet_choice (List.map (fun i -> IState i context) nondet_states) (IState next_state context) end
- | Interp.Call_extern i value ->
- match List.lookup i ((Interp_lib.library_functions internal_direction) ++ spec_externs) with
- | Nothing -> Error ("External function not available " ^ i)
- | Just f ->
- if (mode.internal_mode.Interp.eager_eval)
- then interp_to_outcome mode context (fun _ -> Interp.resume mode.internal_mode next_state (Just (f value)))
- else let new_v = f value in
- Internal (Just i)
+ (match a with
+ | Interp.Read_reg reg_form slice ->
+ (Read_reg (extern_reg reg_form slice)
+ (fun v ->
+ let v = (intern_reg_value v) in
+ let v = if mode.internal_mode.Interp.track_values then (Interp.V_track v (Set.fromList [reg_form])) else v in
+ IState (Interp.add_answer_to_stack next_state v) context), lm)
+ | Interp.Write_reg reg_form slice value ->
+ let reg_name = extern_reg reg_form slice in
+ (Write_reg reg_name (extern_reg_value reg_name value) (IState next_state context),lm)
+ | Interp.Read_mem (Id_aux (Id i) _) value slice ->
+ (match List.lookup i mem_reads with
+ | (Just (MR read_k f)) ->
+ let (location, length, tracking) = (f mode value) in
+ if (List.length location) = 8
+ then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
+ | Just bs -> Just (integer_of_byte_list bs)
+ | _ -> Nothing end in
+ Read_mem read_k (Address_lifted location address_int) length tracking
+ (fun v -> IState (Interp.add_answer_to_stack next_state (intern_mem_value mode direction v)) context)
+ else Error ("Memory address on read is not 64 bits")
+ | _ -> Error ("Memory " ^ i ^ " function with read kind not found")
+ end , lm)
+ | Interp.Write_mem (Id_aux (Id i) _) loc_val slice write_val ->
+ (match List.lookup i mem_writes with
+ | (Just (MW write_k f return)) ->
+ let (location, length, tracking) = (f mode loc_val) in
+ let (value, v_tracking) = (extern_mem_value mode write_val) in
+ if (List.length location) = 8
+ then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
+ | Just bs -> Just (integer_of_byte_list bs)
+ | _ -> Nothing end in
+ Write_mem write_k (Address_lifted location address_int)
+ length tracking value v_tracking
+ (fun b ->
+ match return with
+ | Nothing -> (IState (Interp.add_answer_to_stack next_state Interp.unitv) context)
+ | Just return_bool -> return_bool (IState next_state context) b end)
+ else Error "Memory address on write is not 64 bits"
+ | _ -> Error ("Memory " ^ i ^ " function with write kind not found")
+ end , lm)
+ | Interp.Write_ea (Id_aux (Id i) _) loc_val ->
+ (match List.lookup i mem_write_eas with
+ | (Just (MEA write_k f)) ->
+ let (location, length, tracking) = (f mode loc_val) in
+ if (List.length location) = 8
+ then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with
+ | Just bs -> Just (integer_of_byte_list bs)
+ | _ -> Nothing end in
+ Write_ea write_k (Address_lifted location address_int) length tracking (IState next_state context)
+ else Error "Memory address for write is not 64 bits"
+ | _ -> Error ("Memory " ^ i ^ " function to signal impending write, not found") end, lm)
+ | Interp.Write_memv (Id_aux (Id i) _) write_val ->
+ (match List.lookup i mem_write_vals with
+ | (Just (MV return)) ->
+ let (value, v_tracking) =
+ match (Interp.detaint write_val) with
+ | Interp.V_tuple[_;v] -> (extern_mem_value mode (Interp.retaint write_val v))
+ | _ -> (extern_mem_value mode write_val) end in
+ Write_memv value v_tracking
+ (fun b ->
+ match return with
+ | Nothing -> (IState (Interp.add_answer_to_stack next_state Interp.unitv) context)
+ | Just return_bool -> return_bool (IState next_state context) b end)
+ | _ -> Error ("Memory " ^ i ^ " function with write value kind not found") end, lm)
+ | Interp.Barrier (Id_aux (Id i) _) lval ->
+ (match List.lookup i barriers with
+ | Just barrier ->
+ Barrier barrier (IState next_state context)
+ | _ -> Error ("Barrier " ^ i ^ " function not found") end, lm)
+ | Interp.Footprint (Id_aux (Id i) _) lval ->
+ (Footprint (IState next_state context), lm)
+ | Interp.Nondet exps tag ->
+ (match tag with
+ | Tag_unknown _ ->
+ let possible_states = List.map (Interp.set_in_context next_state) exps in
+ let cleared_possibles = List.map Interp.clear_stack_state possible_states in
+ Analysis_non_det (List.map (fun i -> IState i context) cleared_possibles) (IState next_state context)
+ | _ ->
+ let nondet_states = List.map (Interp.set_in_context next_state) exps in
+ Nondet_choice (List.map (fun i -> IState i context) nondet_states) (IState next_state context) end, lm)
+ | Interp.Call_extern i value ->
+ (match List.lookup i ((Interp_lib.library_functions internal_direction) ++ spec_externs) with
+ | Nothing -> (Error ("External function not available " ^ i), lm)
+ | Just f ->
+ if (mode.internal_mode.Interp.eager_eval)
+ then interp_to_outcome mode context
+ (fun _ -> Interp.resume mode.internal_mode next_state (Just (f value)))
+ else let new_v = f value in
+ (Internal (Just i)
(Just (fun _ -> (Interp.string_of_value value) ^ "=>" ^ (Interp.string_of_value new_v)))
- (IState (Interp.add_answer_to_stack next_state new_v) context)
- end
- | Interp.Step l Nothing Nothing -> Internal Nothing Nothing (IState next_state context)
- | Interp.Step l (Just name) Nothing -> Internal (Just name) Nothing (IState next_state context)
- | Interp.Step l (Just name) (Just value) ->
- Internal (Just name) (Just (fun _ -> Interp.string_of_value value)) (IState next_state context)
- | Interp.Exit e ->
- Escape (match e with
- | E_aux (E_lit (L_aux L_unit _)) _ -> Nothing
- | _ -> Just (IState (Interp.set_in_context next_state e) context) end) (IState next_state context)
- end
- end
+ (IState (Interp.add_answer_to_stack next_state new_v) context), lm)
+ end)
+ | Interp.Step l Nothing Nothing -> (Internal Nothing Nothing (IState next_state context), lm)
+ | Interp.Step l (Just name) Nothing -> (Internal (Just name) Nothing (IState next_state context), lm)
+ | Interp.Step l (Just name) (Just value) ->
+ (Internal (Just name) (Just (fun _ -> Interp.string_of_value value)) (IState next_state context), lm)
+ | Interp.Exit e ->
+ (Escape (match e with
+ | E_aux (E_lit (L_aux L_unit _)) _ -> Nothing
+ | _ -> Just (IState (Interp.set_in_context next_state e) context) end) (IState next_state context),
+ (snd (Interp.get_stack_state next_state)))
+ end )
+ end
let interp mode (IState interp_state context) =
- interp_to_outcome mode context (fun _ -> Interp.resume mode.internal_mode interp_state Nothing)
+ match interp_to_outcome mode context (fun _ -> Interp.resume mode.internal_mode interp_state Nothing) with
+ | (o,_) -> o
+end
(*TODO: Only find some sub piece matches, need to look for field/slice sub pieces*)
(*TODO immediate: this will be impacted by need to change slicing *)
@@ -592,6 +549,7 @@ let reg_size = function
| Reg_f_slice i _ _ f _ (p1,p2) -> if p1 < p2 then p2-p1 +1 else p1-p2+1
end
+(*ie_loop returns a tuple of event list, and a tuple ofinternal interpreter memory, bool to indicate normal or exceptional termination*)
let rec ie_loop mode register_values (IState interp_state context) =
let (Context _ direction externs reads writes write_eas write_vals barriers) = context in
let unknown_reg size =
@@ -600,43 +558,73 @@ let rec ie_loop mode register_values (IState interp_state context) =
rv_start_internal = (if direction = D_increasing then 0 else (size-1));
rv_dir = direction |> in
let unknown_mem size = List.replicate size (Byte_lifted (List.replicate 8 Bitl_unknown)) in
- match interp mode (IState interp_state context) with
- | Done -> []
- | Error msg -> [E_error msg]
- | Escape Nothing i_state -> [E_escape]
+ match interp_to_outcome mode context (fun _ -> Interp.resume mode.internal_mode interp_state Nothing) with
+ | (Done,lm) -> ([],(lm,true))
+ | (Error msg,lm) -> ([E_error msg],(lm,false))
+ | (Escape Nothing i_state,lm) -> ([E_escape],(lm,false))
(*Do we want to record anything about the escape expression, which may be a function call*)
- | Escape _ i_state -> [E_escape]
- | Read_reg reg i_state_fun ->
- let v = match register_values with
+ | (Escape _ i_state,lm) -> ([E_escape],(lm,false))
+ | (Read_reg reg i_state_fun,_) ->
+ let v = (match register_values with
| Nothing -> unknown_reg (reg_size reg)
| Just(registers) -> match find_reg_name reg registers with
| Nothing -> unknown_reg (reg_size reg)
- | Just v -> v end end in
- (E_read_reg reg)::(ie_loop mode register_values (i_state_fun v))
- | Write_reg reg value i_state->
- (E_write_reg reg value)::(ie_loop mode register_values i_state)
- | Read_mem read_k loc length tracking i_state_fun ->
- (E_read_mem read_k loc length tracking)::
- (ie_loop mode register_values (i_state_fun (unknown_mem length)))
- | Write_mem write_k loc length tracking value v_tracking i_state_fun ->
- (E_write_mem write_k loc length tracking value v_tracking)::(ie_loop mode register_values (i_state_fun true))
- | Write_ea write_k loc length tracking i_state ->
- (E_write_ea write_k loc length tracking)::(ie_loop mode register_values i_state)
- | Write_memv value tracking i_state_fun ->
- (E_write_memv value tracking)::(ie_loop mode register_values (i_state_fun true))
- | Barrier barrier_k i_state ->
- (E_barrier barrier_k)::(ie_loop mode register_values i_state)
- | Footprint i_state ->
- E_footprint::(ie_loop mode register_values i_state)
- | Internal _ _ next -> (ie_loop mode register_values next)
- | Analysis_non_det possible_states i_state ->
- (*TODO: need to merge the stores from the stacks/results somehow (so probably need to have a different loop)*)
- (List.concat (List.map (ie_loop mode register_values) possible_states))++(ie_loop mode register_values i_state)
+ | Just v -> v end end) in
+ let (events,analysis_data) = ie_loop mode register_values (i_state_fun v) in
+ ((E_read_reg reg)::events,analysis_data)
+ | (Write_reg reg value i_state, _)->
+ let (events,analysis_data) = ie_loop mode register_values i_state in
+ ((E_write_reg reg value)::events,analysis_data)
+ | (Read_mem read_k loc length tracking i_state_fun, _) ->
+ let (events,analysis_data) = ie_loop mode register_values (i_state_fun (unknown_mem length)) in
+ ((E_read_mem read_k loc length tracking)::events,analysis_data)
+ | (Write_mem write_k loc length tracking value v_tracking i_state_fun, _) ->
+ let (events,analysis_data) = ie_loop mode register_values (i_state_fun true) in
+ let (events',analysis_data) = ie_loop mode register_values (i_state_fun false) in
+ (*TODO: consider if lm and lm should be distinct and merged*)
+ ((E_write_mem write_k loc length tracking value v_tracking)::(events++events'),analysis_data)
+ | (Write_ea write_k loc length tracking i_state, _) ->
+ let (events,analysis_data) = ie_loop mode register_values i_state in
+ ((E_write_ea write_k loc length tracking)::events,analysis_data)
+ | (Write_memv value tracking i_state_fun, _) ->
+ let (events,analysis_data) = ie_loop mode register_values (i_state_fun true) in
+ let (events',analysis_data) = ie_loop mode register_values (i_state_fun false) in
+ (*TODO: consider if lm and lm should be merged*)
+ ((E_write_memv value tracking)::(events++events'),analysis_data)
+ | (Barrier barrier_k i_state, _) ->
+ let (events,analysis_data) = ie_loop mode register_values i_state in
+ ((E_barrier barrier_k)::events,analysis_data)
+ | (Footprint i_state, _) ->
+ let (events,analysis_data) = ie_loop mode register_values i_state in
+ (E_footprint::events,analysis_data)
+ | (Internal _ _ next, _) -> (ie_loop mode register_values next)
+ | (Analysis_non_det possible_istates i_state,_) ->
+ if possible_istates = []
+ then ie_loop mode register_values i_state
+ else
+ let (possible_events,possible_states) = List.unzip(List.map (ie_loop mode register_values) possible_istates) in
+ let (unified_mem,update_mem) = List.foldr
+ (fun (lm,terminated_normally) (mem,update_mem) ->
+ if terminated_normally && update_mem
+ then (Interp.merge_lmems lm mem, true)
+ else if terminated_normally
+ then (lm, true)
+ else (mem, false))
+ (List_extra.head possible_states) (List_extra.tail possible_states) in
+ let updated_i_state =
+ if update_mem
+ then match i_state with
+ | (IState interp_state context) -> IState (Interp.update_stack_state interp_state unified_mem) context end
+ else i_state in
+ let (events,analysis_data) = ie_loop mode register_values updated_i_state in
+ ((List.concat possible_events)++events, analysis_data)
end ;;
let interp_exhaustive register_values i_state =
- let mode = make_mode true true E_big_endian in
- ie_loop mode register_values i_state
+ let mode = make_mode_exhaustive E_big_endian in
+ match ie_loop mode register_values i_state with
+ | (events,_) -> events
+end
let rec rr_ie_loop mode i_state =
let (IState _ (Context _ direction _ _ _ _ _ _)) = i_state in
diff --git a/src/lem_interp/interp_utilities.lem b/src/lem_interp/interp_utilities.lem
index 6d7cb9cf..d2a6b784 100644
--- a/src/lem_interp/interp_utilities.lem
+++ b/src/lem_interp/interp_utilities.lem
@@ -1,5 +1,6 @@
open import Interp_ast
open import Pervasives
+open import Show_extra
let rec power (a: integer) (b: integer) : integer =
if b <= 0
@@ -140,3 +141,9 @@ let rec get_index_range_size (BF_aux i _) = match i with
| BF_concat i j -> (get_index_range_size i) + (get_index_range_size j)
end
+let rec string_of_loc l = match l with
+ | Unknown -> "Unknown"
+ | Int s Nothing -> "Internal " ^ s
+ | Int s (Just l) -> "Internal " ^ s ^ " " ^ (string_of_loc l)
+ | Range file n1 n2 n3 n4 -> "File " ^ file ^ ": " ^ (show n1) ^ ": " ^ (show (n2:nat)) ^ ": " ^ (show (n3:nat)) ^ ": " ^ (show (n4:nat))
+end
diff --git a/src/lem_interp/printing_functions.ml b/src/lem_interp/printing_functions.ml
index 35cd4d59..0140a922 100644
--- a/src/lem_interp/printing_functions.ml
+++ b/src/lem_interp/printing_functions.ml
@@ -271,7 +271,7 @@ let reg_name_to_string = function
let dependencies_to_string dependencies = String.concat ", " (List.map reg_name_to_string dependencies)
-let rec val_to_string_internal ((Interp.LMem (_,memory)) as mem) = function
+let rec val_to_string_internal ((Interp.LMem (_,_,memory,_)) as mem) = function
| Interp.V_boxref(n, t) -> val_to_string_internal mem (Pmap.find n memory)
| Interp.V_lit (L_aux(l,_)) -> sprintf "%s" (lit_to_string l)
| Interp.V_tuple l ->
diff --git a/src/pretty_print.ml b/src/pretty_print.ml
index 182c1929..266e8141 100644
--- a/src/pretty_print.ml
+++ b/src/pretty_print.ml
@@ -65,14 +65,14 @@ let pp_format_var (Kid_aux(Var v,_)) = v
let rec pp_format_l_lem = function
| Parse_ast.Unknown -> "Unknown"
- | _ -> "Unknown"
-(* | Parse_ast.Int(s,None) -> "(Int \"" ^ s ^ "\" Nothing)"
+(* | _ -> "Unknown"*)
+ | Parse_ast.Int(s,None) -> "(Int \"" ^ s ^ "\" Nothing)"
| Parse_ast.Int(s,(Some l)) -> "(Int \"" ^ s ^ "\" (Just " ^ (pp_format_l_lem l) ^ "))"
| Parse_ast.Range(p1,p2) -> "(Range \"" ^ p1.Lexing.pos_fname ^ "\" " ^
(string_of_int p1.Lexing.pos_lnum) ^ " " ^
(string_of_int (p1.Lexing.pos_cnum - p1.Lexing.pos_bol)) ^ " " ^
(string_of_int p2.Lexing.pos_lnum) ^ " " ^
- (string_of_int (p2.Lexing.pos_cnum - p2.Lexing.pos_bol)) ^ ")"*)
+ (string_of_int (p2.Lexing.pos_cnum - p2.Lexing.pos_bol)) ^ ")"
let pp_lem_l ppf l = base ppf (pp_format_l_lem l)