diff --git a/compiler/obc/c/c.ml b/compiler/obc/c/c.ml index b679410..38cb78c 100644 --- a/compiler/obc/c/c.ml +++ b/compiler/obc/c/c.ml @@ -155,6 +155,10 @@ let cdecl_of_cfundef cfd = match cfd with | Cfundef cfd -> Cdecl_function (cfd.f_name, cfd.f_retty, cfd.f_args) | _ -> invalid_arg "cdecl_of_cfundef" +let cdef_name = function + | Cfundef cfd -> cfd.f_name + | Cvardef (name, _) -> name + (** A C file can be a source file, containing definitions, or a header file, containing declarations. *) type cfile = string * cfile_desc diff --git a/compiler/obc/c/cgen.ml b/compiler/obc/c/cgen.ml index 03cf0cd..b465a64 100644 --- a/compiler/obc/c/cgen.ml +++ b/compiler/obc/c/cgen.ml @@ -692,11 +692,11 @@ let step_fun_args n md pack_inputs = reset calls. A step function can have multiple return values, whereas C does not allow such functions. When it is the case, we declare a structure with a field by return value. *) -let fun_def_of_step_fun ?(async = false) n obj_env mem objs md = +let fun_def_of_step_fun n obj_env mem objs md = let fun_name = (cname_of_qn n) ^ "_step" in (* Its arguments, translating Obc types to C types and adding our internal memory structure. *) - let args = step_fun_args n md async in + let args = step_fun_args n md false in (* Out vars for function calls *) let out_vars = @@ -726,6 +726,53 @@ let fun_def_of_step_fun ?(async = false) n obj_env mem objs md = } } +let async_fun_def_of_step_fun n obj_env mem objs md copy_in_name + copy_out_name = + let fun_name = (cname_of_qn n) ^ "_async_step" in + (* Its arguments, translating Obc types to C types and adding our internal + memory structure. *) + let args = step_fun_args n md true in + + (* Out vars for function calls *) + let out_vars = + unique + (List.map (fun obj -> out_var_name_of_objn (cname_of_qn obj.o_class), + Cty_id (qn_append obj.o_class "_out")) + (List.filter (fun obj -> not (is_op obj.o_class)) objs)) in + + (* TODO(Arduino): Refactor with non-async version *) + (* The body *) + let mems = List.map cvar_of_vd (mem@md.m_outputs) in + let var_env = args @ mems @ out_vars in + let out_env = + List.fold_left + (fun out_env vd -> IdentSet.add vd.v_ident out_env) + IdentSet.empty + md.m_outputs + in + + let local_in = ("_local_in", Cty_id (qn_append n "_in")) in + let local_out = ("_local_out", Cty_id (qn_append n "_out")) in + + let copy_in = Cfun_call (copy_in_name, + [Caddrof (Cvar "_local_in"); Cvar "_in"]) in + + (* FIXME(Arduino): rename input & output variables *) + let body = cstm_of_act_list out_env var_env obj_env md.m_body in + + let copy_out = Cfun_call (copy_out_name, + [Cvar "_out"; Caddrof (Cvar "_local_out")]) in + + Cfundef { + C.f_name = fun_name; + f_retty = Cty_void; + f_args = args; + f_body = { + var_decls = local_in :: local_out :: out_vars; + block_body = (Csexpr copy_in) :: body @ [Csexpr copy_out] + } + } + (** [mem_decl_of_class_def cd] returns a declaration for a C structure holding internal variables and objects of the Obc class definition [cd]. *) let mem_decl_of_class_def cd = @@ -805,16 +852,22 @@ let cdefs_and_cdecls_of_class_def cd = (* TODO(Arduino): let the user choose the backend they want *) let copy_in_def = PosixBackend.gen_copy_func_in cd in let copy_out_def = PosixBackend.gen_copy_func_out cd in + let async_step_fun_def = async_fun_def_of_step_fun cd.cd_name + cd.cd_objs cd.cd_mems cd.cd_objs step_m (cdef_name copy_in_def) + (cdef_name copy_out_def) in (* C function for resetting our memory structure. *) let reset_fun_def = reset_fun_def_of_class_def cd in let res_fun_decl = cdecl_of_cfundef reset_fun_def in let step_fun_decl = cdecl_of_cfundef step_fun_def in + let async_step_fun_decl = cdecl_of_cfundef async_step_fun_def in let copy_in_decl = cdecl_of_cfundef copy_in_def in let copy_out_decl = cdecl_of_cfundef copy_out_def in let (decls, defs) = if is_stateful cd.cd_name then - ([res_fun_decl; step_fun_decl; copy_in_decl; copy_out_decl], - [reset_fun_def; step_fun_def; copy_in_def; copy_out_def]) + ([res_fun_decl; step_fun_decl; copy_in_decl; copy_out_decl; + async_step_fun_decl], + [reset_fun_def; step_fun_def; copy_in_def; copy_out_def; + async_step_fun_def]) else ([step_fun_decl], [step_fun_def]) in