@@ -206,52 +206,80 @@ let print_value ppf v ty =
206206 Format. fprintf ppf " @]"
207207 end
208208
209+
210+ (* for a type [('a, 'b) foo] => [register_sampler "foo" f] where [f] must have
211+ type ['a sampler -> 'b sampler -> ('a, 'b) foo sampler].
212+ - find the sampler's type from its name and the cmi
213+ - lookup type [foo]
214+ - build the expected sampler type from the type params of [foo]
215+ - match with the sampler type
216+ *)
209217let register_sampler name f =
210- let sampler_name = " sample_" ^ name in
211- (* FIXME TODO: type-check the specified samplers ! *)
212- (* let sampled_ty_path, sampled_ty_decl =
213- * Env.find_type_by_name (Longident.Lident name) !Toploop.toplevel_env
214- * in
215- * let sampled_ty =
216- * match sampled_ty_decl.Types.type_manifest with
217- * | Some ty -> ty
218- * | None -> failwith "Type is not public for sampling"
219- * in
220- * let sampler_ty_computed =
221- * (\* The given sampler must be a function with one argument for every type param *\)
222- * let sampler ty = (\* ['a sampler] == [unit -> 'a] *\)
223- * Types.Tarrow (Asttypes.Nolabel, Predef.type_unit, ty, Types.Cok)
224- * in
225- * List.fold_right (fun typaram ty ->
226- * Types.Tarrow (Asttypes.Nolabel, Btype.newgenty (sampler typaram), Btype.newgenty ty, Types.Cok))
227- * sampled_ty_decl.Types.type_params
228- * (sampler sampled_ty)
229- * in *)
230- let sampler_ty(* _found *) =
231- Env. find_value
232- (Path. Pdot (Path. Pident (Ident. create_persistent " Test" ), sampler_name))
233- ! Toploop. toplevel_env
234- (* Requires [test.cmi] to be pre-loaded *)
235- (* FIXME: maybe don't require the cmi and skip this check when on the
236- browser.
237- ... unless the type of the sampler might somehow depend on the types
238- inferred from [Code], but that should definitely be forbidden! *)
218+ let open Types in
219+ let gen_sampler_type =
220+ Path. Pdot
221+ (Path. Pident (Ident. create_persistent " Test_lib" ),
222+ " sampler" )
239223 in
240- if true (* Ctype.moregeneral !Toploop.toplevel_env true
241- * (Btype.newgenty sampler_ty_found) sampler_ty_computed *)
242- then
243- (Toploop. toplevel_env :=
244- Env. add_value (Ident. create_local sampler_name) sampler_ty
245- ! Toploop. toplevel_env;
246- Toploop. setvalue sampler_name (Obj. repr f))
247- else
248- failwith " sampler has the wrong type !"
249-
224+ let lookup_env = ! Toploop. toplevel_env in
225+ let sampler_name = " sample_" ^ name in
226+ match
227+ let sampler_path =
228+ Path. Pdot (Path. Pident (Ident. create_persistent " Test" ),
229+ sampler_name)
230+ in
231+ try sampler_path, Env. find_value sampler_path lookup_env
232+ with Not_found ->
233+ Env. find_value_by_name (Longident. Lident sampler_name)
234+ lookup_env
235+ with
236+ | exception Not_found ->
237+ Format. ksprintf failwith " Bad sampler registration (function %s not found).@."
238+ sampler_name
239+ | _sampler_path , sampler_desc ->
240+ match
241+ Env. find_type_by_name (Longident. Lident name) lookup_env
242+ with
243+ | exception Not_found ->
244+ Format. eprintf " Warning: unrecognised sampler definition (type %s not found).@."
245+ name
246+ | sampled_ty_path , sampled_ty_decl ->
247+ let sampler_ty_expected =
248+ Ctype. begin_def() ;
249+ let ty_args =
250+ List. map (fun _ -> Ctype. newvar () ) sampled_ty_decl.type_params
251+ in
252+ let ty_target =
253+ Ctype. newty (Tconstr (sampled_ty_path, ty_args, ref Mnil ))
254+ in
255+ let fn_args =
256+ List. map (fun ty -> Ctype. newconstr gen_sampler_type [ty]) ty_args
257+ in
258+ let sampler_ty =
259+ List. fold_right (fun fn_arg ty ->
260+ Ctype. newty (Tarrow (Asttypes. Nolabel , fn_arg, ty, Cunknown )))
261+ fn_args (Ctype. newconstr gen_sampler_type [ty_target])
262+ in
263+ Ctype. end_def () ;
264+ Ctype. generalize sampler_ty;
265+ sampler_ty
266+ in
267+ (try
268+ Ctype. unify lookup_env
269+ sampler_ty_expected
270+ (Ctype. instance sampler_desc.val_type)
271+ with Ctype. Unify _ ->
272+ Format. ksprintf failwith " %s has a wrong type for a sampling function.@."
273+ sampler_name);
274+ Toploop. toplevel_env :=
275+ Env. add_value (Ident. create_local sampler_name) sampler_desc
276+ ! Toploop. toplevel_env;
277+ Toploop. setvalue sampler_name (Obj. repr f)
250278
251279let sample_value ty =
252280 let { Typedtree. ctyp_type = ty; _ } =
253281 Typetexp. transl_type_scheme ! Toploop. toplevel_env (Ty. obj ty) in
254- let lid = Format. asprintf " sample_%04X " (Random. int 0xFFFF ) in
282+ let lid = Format. asprintf " sample_%06X " (Random. int 0xFFFFFF ) in
255283 let phrase =
256284 let open Asttypes in
257285 let open Types in
0 commit comments