@ -42,6 +42,8 @@ let template_args_of_template_spec_info = function
args
args
exception DoNotHandleJavaYet
let templated_name_of_class_name class_name =
let templated_name_of_class_name class_name =
let open Typ in
let open Typ in
match class_name with
match class_name with
@ -50,7 +52,7 @@ let templated_name_of_class_name class_name =
| CppClass ( qual_name , template_spec_info ) ->
| CppClass ( qual_name , template_spec_info ) ->
( qual_name , template_args_of_template_spec_info template_spec_info )
( qual_name , template_args_of_template_spec_info template_spec_info )
| JavaClass _ ->
| JavaClass _ ->
assert false
raise DoNotHandleJavaYet
(* * Little abstraction over arguments: currently actual args, we'll want formal args later *)
(* * Little abstraction over arguments: currently actual args, we'll want formal args later *)
@ -127,7 +129,8 @@ type ('arg_in, 'arg_out, 'f_in, 'f_out) arg_preparer =
type ( ' f_in , ' f_out , ' captured_types , ' markers ) func_arg =
type ( ' f_in , ' f_out , ' captured_types , ' markers ) func_arg =
{ eat_func_arg : ( ' f_in , ' f_out , ' captured_types ) on_args ; marker_static_checker : ' markers -> bool }
{ eat_func_arg : ( ' f_in , ' f_out , ' captured_types ) on_args ; marker_static_checker : ' markers -> bool }
type ' f matcher = Typ . Procname . t -> FuncArg . t list -> ' f option
type ' f matcher =
{ on_objc_cpp : objc_cpp -> FuncArg . t list -> ' f option ; on_c : c -> FuncArg . t list -> ' f option }
type ' f pre_result = DoesNotMatch | Matches of ' f | RetryWith of ' f matcher
type ' f pre_result = DoesNotMatch | Matches of ' f | RetryWith of ' f matcher
@ -135,15 +138,6 @@ let pre_bind_opt opt ~f = match opt with None -> DoesNotMatch | Some x -> f x
let pre_map_opt opt ~ f = match opt with None -> DoesNotMatch | Some x -> Matches ( f x )
let pre_map_opt opt ~ f = match opt with None -> DoesNotMatch | Some x -> Matches ( f x )
let pre_to_opt procname args = function
| DoesNotMatch ->
None
| Matches x ->
Some x
| RetryWith f ->
f procname args
type ( ' f_in , ' f_out , ' captured_types ) func_args_end =
type ( ' f_in , ' f_out , ' captured_types ) func_args_end =
on_args : ( ' f_in , ' f_out , ' captured_types ) on_args -> FuncArg . t list -> ' f_in * ' captured_types
on_args : ( ' f_in , ' f_out , ' captured_types ) on_args -> FuncArg . t list -> ' f_in * ' captured_types
-> ' f_out pre_result
-> ' f_out pre_result
@ -152,12 +146,11 @@ type ('f_in, 'f_out) all_args_matcher =
{ on_objc_cpp : ' f_in -> objc_cpp -> FuncArg . t list -> ' f_out pre_result
{ on_objc_cpp : ' f_in -> objc_cpp -> FuncArg . t list -> ' f_out pre_result
; on_c : ' f_in -> c -> FuncArg . t list -> ' f_out pre_result }
; on_c : ' f_in -> c -> FuncArg . t list -> ' f_out pre_result }
type ' f typ_matcher = Typ . name -> ' f option
type ' f typ_matcher = { on_templated_name : templated_ name -> ' f option }
(* they are actually just the same thing *)
type ' f dispatcher = Typ . Procname . t -> FuncArg . t list -> ' f option
type ' f dispatcher = ' f matcher
type ' f typ_dispatcher = ' f typ_matcher
type ' f typ_dispatcher = Typ . name -> ' f option
(* Combinators *)
(* Combinators *)
@ -551,21 +544,46 @@ module Procname = struct
let make_matcher : ( ' f_in , ' f_out ) all_args_matcher -> ' f_in -> ' f_out matcher =
let make_matcher : ( ' f_in , ' f_out ) all_args_matcher -> ' f_in -> ' f_out matcher =
fun m f ->
fun m f ->
let { on_c ; on_objc_cpp } : ( _ , _ ) all_args_matcher = m in
let { on_c ; on_objc_cpp } : ( _ , _ ) all_args_matcher = m in
let on_objc_cpp objc_cpp args =
match on_objc_cpp f objc_cpp args with
| DoesNotMatch ->
None
| Matches res ->
Some res
| RetryWith { on_objc_cpp } ->
on_objc_cpp objc_cpp args
in
let on_c c args =
match on_c f c args with
| DoesNotMatch ->
None
| Matches res ->
Some res
| RetryWith { on_c } ->
on_c c args
in
{ on_objc_cpp ; on_c }
(* * Simple implementation of a dispatcher, could be optimized later *)
let make_dispatcher : ' f matcher list -> ' f dispatcher =
fun matchers ->
let on_objc_cpp objc_cpp args =
List . find_map matchers ~ f : ( fun ( matcher : _ matcher ) -> matcher . on_objc_cpp objc_cpp args )
in
let on_c c args =
List . find_map matchers ~ f : ( fun ( matcher : _ matcher ) -> matcher . on_c c args )
in
fun procname args ->
fun procname args ->
match procname with
match procname with
| ObjC_Cpp objc_cpp ->
| ObjC_Cpp objc_cpp ->
on_objc_cpp f objc_cpp args | > pre_to_opt procname args
on_objc_cpp objc_cpp args
| C c ->
| C c ->
on_c f c args | > pre_to_opt procname args
on_c c args
| _ ->
| _ ->
None
None
(* * Simple implementation of a dispatcher, could be optimized later *)
let make_dispatcher : ' f matcher list -> ' f dispatcher =
fun matchers procname args -> List . find_map matchers ~ f : ( fun matcher -> matcher procname args )
(* Function args *)
(* Function args *)
let no_marker_checker _ markers = true
let no_marker_checker _ markers = true
@ -607,7 +625,7 @@ module Procname = struct
(* * Matches the type matched by the given path_matcher *)
(* * Matches the type matched by the given path_matcher *)
let match_typ : ( _ , _ , unit , unit , unit , non_empty ) path_matcher -> ( _ , _ ) one_arg_matcher =
let match_typ : ( _ , _ , unit , unit , unit , non_empty ) path_matcher -> ( _ , _ ) one_arg_matcher =
fun m ->
fun m ->
let { on_templated_name } = m in
let { on_templated_name } : ( _ , _ , unit , unit , unit , non_empty ) path_matcher = m in
let rec match_typ typ =
let rec match_typ typ =
match typ with
match typ with
| { Typ . desc = Tstruct name } ->
| { Typ . desc = Tstruct name } ->
@ -729,17 +747,24 @@ module Procname = struct
(* * Retries matching with another matcher *)
(* * Retries matching with another matcher *)
let args_end_retry : _ -> ( _ , _ , _ ) func_args_end = fun f ~ on_args : _ _ args _ f_capt -> RetryWith f
let args_end_retry : _ matcher -> ( _ , _ , _ ) func_args_end =
fun m ~ on_args : _ _ args _ f_capt -> RetryWith m
(* * Retries matching with another matcher if the function does not have the
(* * Retries matching with another matcher if the function does not have the
exact number / types of args * )
exact number / types of args * )
let exact_args_or_retry : ' f -> ( _ , _ , _ ) func_args_end =
let exact_args_or_retry : ' f matcher -> ( _ , _ , _ ) func_args_end =
fun f -> alternative_args_end no_args_left ( args_end_retry f )
fun m -> alternative_args_end no_args_left ( args_end_retry m )
let wrong_args_internal_error procname _ args =
let wrong_args_internal_error : _ matcher =
let on_procname procname =
Logging . ( die InternalError )
Logging . ( die InternalError )
" Unexpected number/types of arguments for %a " Typ . Procname . pp procname
" Unexpected number/types of arguments for %a " Typ . Procname . pp procname
in
let on_c c _ args = on_procname ( C c ) in
let on_objc_cpp objc_cpp _ args = on_procname ( ObjC_Cpp objc_cpp ) in
{ on_c ; on_objc_cpp }
let ( $! ) path_matcher () = args_begin path_matcher
let ( $! ) path_matcher () = args_begin path_matcher
@ -794,13 +819,21 @@ module TypName = struct
let make_matcher
let make_matcher
: ( ' f_in , ' f_out , _ , _ , _ , non_empty ) path_matcher -> ' f_in -> ' f_out typ_matcher =
: ( ' f_in , ' f_out , _ , _ , _ , non_empty ) path_matcher -> ' f_in -> ' f_out typ_matcher =
fun m f ->
fun m f ->
let { on_templated_name } = m in
let { on_templated_name } : ( ' f_in , ' f_out , _ , _ , _ , non_empty ) path_matcher = m in
function
let on_templated_name templated_name =
| name -> name | > templated_name_of_class_name | > on_templated_name f | > Option . map ~ f : fst
templated_name | > on_templated_name f | > Option . map ~ f : fst
in
{ on_templated_name }
let make_dispatcher : ' f typ_matcher list -> ' f typ_dispatcher =
let make_dispatcher : ' f typ_matcher list -> ' f typ_dispatcher =
fun matchers typname -> List . find_map matchers ~ f : ( fun matcher -> matcher typname )
fun matchers typname ->
match templated_name_of_class_name typname with
| exception DoNotHandleJavaYet ->
None
| templated_name ->
List . find_map matchers ~ f : ( fun ( matcher : _ typ_matcher ) ->
matcher . on_templated_name templated_name )
let ( & - -> ! ) path_matcher f = make_matcher path_matcher f
let ( & - -> ! ) path_matcher f = make_matcher path_matcher f