let rec translate_field e1 id typ =
match e1.expr_t with
CTTexpPtrDeref(e2) ->
CTTMlvPtr(translate e2), [id, typ]
| CTTexpVar(id2) ->
CTTMlvVar(id2, e1.expr_type), [id, typ]
| CTTexpInvoke(e2, args) ->
CTTMlvInvoke(translate_invoke_lhs e2, List.map translate args, e1.expr_type), [id, typ]
| CTTexpField(e2, id2) ->
let l, r = translate_field e2 id2 e1.expr_type in
l, (r @ [id, typ])
| _ -> failwith "invalid LHS for . operator"
and translate (e : expr) : mexpr =
let body : mexpr_desc = match e.expr_t with
CTTexpComma(e1,e2) -> CTTMexpComma(translate e1, translate e2)
| CTTexpConditional(e1,e2,e3) -> CTTMexpConditional(translate e1, translate e2, translate e3)
| CTTexpBinExpr(binop,e1,e2) -> CTTMexpBinExpr(binop, translate e1, translate e2)
| CTTexpCoerce(t,e1) -> CTTMexpCoerce(t, translate e1)
| CTTexpUnaryExpr(u,e1) -> CTTMexpUnaryExpr(u, translate e1)
| CTTexpInvoke(e1,args) -> CTTMexpInvoke(translate_invoke_lhs e1, List.map translate args)
| CTTexpConstant(c) -> CTTMexpConstant(c)
| CTTexpAddress(e) -> translate_address e
| CTTexpPtrDeref(e) -> CTTMexpRead(CTTMlvPtr (translate e),[])
| CTTexpAssign(e1,e2) -> translate_assign e1 (translate e2) None
| CTTexpBinAssign(binop,e1,tcast,e2) -> translate_assign e1 (translate e2) (Some (binop, tcast))
| CTTexpField(e1,id) ->
let l,r = translate_field e1 id e.expr_type in
CTTMexpRead(l,r)
| CTTexpVar(id) -> begin
match e.expr_type.ct_ty with
Tarray(_) ->
CTTMexpAddress(CTTMlvVar(id, e.expr_type), [])
| _ ->
CTTMexpRead(CTTMlvVar(id, e.expr_type), [])
end
in
{ mexpr_type = e.expr_type; mexpr_t = body }
and translate_address e =
match e.expr_t with
CTTexpPtrDeref(e) -> (translate e).mexpr_t
| CTTexpVar(id) -> CTTMexpAddress(CTTMlvVar(id, e.expr_type), [])
| CTTexpField(e1,id) ->
let l, r = translate_field e1 id e1.expr_type in
CTTMexpAddress(l,r)
| _ -> raise (TypeError_typed(e,"not an lvalue"))
and translate_invoke_lhs e1 =
match e1.expr_t with
CTTexpPtrDeref(e) -> CTTMlvPtr(translate e)
| CTTexpVar(id) -> CTTMlvVar(id, e1.expr_type)
| CTTexpField _ -> assert false
| _ -> assert false
and translate_assign e1 rhs binop =
match e1.expr_t with
CTTexpPtrDeref(e) -> CTTMexpWrite(CTTMlvPtr(translate e), [], binop, rhs)
| CTTexpVar(id) -> CTTMexpWrite(CTTMlvVar(id, e1.expr_type), [], binop, rhs)
| CTTexpField(e1,id) ->
let l, r = translate_field e1 id e1.expr_type in
CTTMexpWrite(l,r, binop, rhs)
| _ -> raise (TypeError_typed(e1,"not an lvalue"))