summaryrefslogtreecommitdiff
path: root/src/lem_interp/interp.lem
diff options
context:
space:
mode:
Diffstat (limited to 'src/lem_interp/interp.lem')
-rw-r--r--src/lem_interp/interp.lem58
1 files changed, 46 insertions, 12 deletions
diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem
index ad22aa36..6bc4964d 100644
--- a/src/lem_interp/interp.lem
+++ b/src/lem_interp/interp.lem
@@ -118,6 +118,18 @@ type outcome =
(* interprets the exp sequentially in the presence of a set of top level definitions and returns a value or a memory request *)
val interp : defs tannot -> exp tannot -> outcome
+val to_register_fields : defs tannot -> list (id * list (id * index_range))
+let rec to_register_fields (Defs defs) =
+ match defs with
+ | [ ] -> [ ]
+ | (DEF_aux def (l,tannot))::defs ->
+ match def with
+ | DEF_type (TD_aux (TD_register id n1 n2 indexes) l') ->
+ (id,List.map (fun (a,b) -> (b,a)) indexes)::(to_register_fields (Defs defs))
+ | _ -> to_register_fields (Defs defs)
+ end
+ end
+
val to_registers : defs tannot -> env
let rec to_registers (Defs defs) =
match defs with
@@ -166,7 +178,7 @@ let rec to_data_constructors (Defs defs) =
| _ -> to_data_constructors (Defs defs) end
end
-val in_env : env -> id -> maybe value
+val in_env :forall 'a. (list (id * 'a)) -> id -> maybe 'a
let rec in_env env id =
match env with
| [] -> Nothing
@@ -574,8 +586,8 @@ let rec find_case pexps value =
end
(*top_level is a tuple of
- (all definitions, letbound and enum values, register values, and Typedef union constructors) *)
-type top_level = Env of (defs tannot) * env * env * list (id * typ)
+ (all definitions, letbound and enum values, register values, Typedef union constructors, and sub register mappings) *)
+type top_level = Env of (defs tannot) * env * env * list (id * typ) * list (id * list (id * index_range))
val interp_main : top_level -> env -> mem -> (exp tannot) -> (outcome * mem * env)
val exp_list : top_level -> (list (exp tannot) -> (exp tannot)) -> (list value -> value) -> env -> mem -> list value -> list (exp tannot) -> (outcome * mem * env)
@@ -607,7 +619,7 @@ let rec exp_list t_level build_e build_v l_env l_mem vals exps =
end
and interp_main t_level l_env l_mem (E_aux exp (l,annot)) =
- let (Env defs lets regs ctors) = t_level in
+ let (Env defs lets regs ctors subregs) = t_level in
let (typ,tag,ncs,effect) = match annot with
| Nothing -> (T_var (Kid_aux (Var "fresh_v") Unknown),
Tag_empty, [], (Effect_aux (Effect_set []) Unknown))
@@ -770,7 +782,19 @@ and interp_main t_level l_env l_mem (E_aux exp (l,annot)) =
| Nothing -> (Error l "Field not found in record",lm,le) end
| _ -> (Error l "Field access of vectors not implemented",lm,le)
end )
- (fun a -> update_stack a (add_to_top_frame (fun e -> E_aux(E_field e id) (l,annot))))
+ (fun a ->
+ match (exp,a) with
+ | (E_aux _ (l,Just(_,Tag_extern _,_,_)),
+ (Action (Read_reg ((Reg _ (Just((T_id id'),_,_,_))) as regf) Nothing) s)) ->
+ match in_env subregs id' with
+ | Just(indexes) ->
+ match in_env indexes id with
+ | Just ir ->
+ (Action (Read_reg (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
+ | _ -> update_stack a (add_to_top_frame (fun e -> E_aux(E_field e id) (l,annot))) end)
| E_vector_access vec i ->
(*Need to update to read one position of a register*)
resolve_outcome (interp_main t_level l_env l_mem i)
@@ -1012,7 +1036,7 @@ and interp_main t_level l_env l_mem (E_aux exp (l,annot)) =
end
and create_write_message_or_update t_level value l_env l_mem is_top_level ((LEXP_aux lexp (l,annot)):lexp tannot) =
- let (Env defs lets regs ctors) = t_level in
+ let (Env defs lets regs ctors subregs) = t_level in
let (typ,tag,ncs,ef) = match annot with
| Nothing -> (T_var (Kid_aux (Var "fresh_v") Unknown), Tag_empty, [], (Effect_aux (Effect_set []) Unknown))
| Just(t, tag, ncs, ef) -> (t,tag,ncs,ef) end in
@@ -1177,7 +1201,7 @@ and create_write_message_or_update t_level value l_env l_mem is_top_level ((LEXP
| (Just (V_boxref n t),true) -> ((Value (V_lit (L_aux L_unit l)) Tag_empty, update_mem lm n value, l_env),Nothing)
| (Just (V_boxref n t),false) ->
((Value (in_mem lm n) Tag_empty,lm,l_env),Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot)))
- | (Just v, true) -> ((Error l "Field access requires record",lm,le),Nothing)
+ | (Just v, true) -> ((Error l "Mutating a field access requires a reg type",lm,le),Nothing)
| (Just v,false) -> ((Value v Tag_empty,lm,l_env),Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot)))
| (Nothing,_) -> ((Error l "Field not found in specified record",lm,le),Nothing) end
| ((Action a s,lm,le), Just lexp_builder) ->
@@ -1185,7 +1209,17 @@ and create_write_message_or_update t_level value l_env l_mem is_top_level ((LEXP
| Read_reg _ _ -> ((Action a s,lm,le), Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot)))
| Read_mem _ _ _ -> ((Action a s,lm,le), Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot)))
| Call_extern _ _ -> ((Action a s,lm,le), Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot)))
- | _ -> ((Error l "Unimplemented feature, writing to a field in a register or memory",lm,le),Nothing)
+ | Write_reg ((Reg id' t') as regf) Nothing value ->
+ match in_env subregs id' with
+ | Just(indexes) ->
+ match in_env indexes id with
+ | Just ir ->
+ ((Action (Write_reg (SubReg id regf ir) Nothing value) s,lm,le),
+ (if is_top_level then Nothing else Just (fun e -> LEXP_aux (LEXP_field (lexp_builder e) id) (l,annot))))
+ | _ -> ((Error l "Internal error, unrecognized write",lm,le),Nothing)
+ end
+ | Nothing -> ((Error l "Internal error, unrecognized write",lm,le),Nothing) end
+ | _ -> ((Error l "Internal error, unrecognized write",lm,le),Nothing)
end
| e -> e end)
end
@@ -1212,14 +1246,14 @@ end
(*Beef up to pick up enums as well*)
let rec to_global_letbinds (Defs defs) t_level =
- let (Env defs' lets regs ctors) = t_level in
+ let (Env defs' lets regs ctors subregs) = t_level in
match defs with
| [] -> ((Value (V_lit (L_aux L_unit Unknown)) Tag_empty, emem, []),t_level)
| (DEF_aux def (l,_))::defs ->
match def with
| DEF_val lbind ->
match interp_letbind t_level [] emem lbind with
- | ((Value v tag,lm,le),_) -> to_global_letbinds (Defs defs) (Env defs' (lets++le) regs ctors)
+ | ((Value v tag,lm,le),_) -> to_global_letbinds (Defs defs) (Env defs' (lets++le) regs ctors subregs)
| ((Action a s,lm,le),_) ->
((Error l "Top level let may not access memory, registers or (for now) external functions", lm,le),t_level)
| (e,_) -> (e,t_level) end
@@ -1229,7 +1263,7 @@ let rec to_global_letbinds (Defs defs) t_level =
let interp defs exp =
- let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) in
+ let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) (to_register_fields defs) in
let (o,t_level) = to_global_letbinds defs t_level in
match o with
| (Value _ _,_,_) ->
@@ -1254,7 +1288,7 @@ let rec resume_main t_level stack value =
end
let resume defs stack value =
- let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) in
+ let t_level = Env defs [] (to_registers defs) (to_data_constructors defs) (to_register_fields defs) in
let (o,t_level) = to_global_letbinds defs t_level in
match o with
| (Value _ _,_,_) ->