123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374openPrintfopenAtd_astopenAg_erroropenAg_mappingtypeo=Ag_ocaml.atd_ocaml_reprtypev=Ag_validate.validate_reprtypeov_mapping=(Ag_ocaml.atd_ocaml_repr,Ag_validate.validate_repr)Ag_mapping.mappingtypeob_def=(Ag_ocaml.atd_ocaml_repr,Ag_validate.validate_repr)Ag_mapping.def(*
Determine whether a type expression does not need validation.
1. Flatten.
For each type expression of interest, produce the list
of all type expressions on which it depends.
2. Read annotations.
If any of the type expressions has a validator annotation or if
on the type expressions is abstract, then the result is false.
*)letplocx=eprintf"%s\n"(string_of_loc(loc_of_type_exprx))letprints=eprintf"%s\n%!"sletget_defdefsname:type_exproption=trySome(Hashtbl.finddefsname)withNot_found->Noneletnovalx=letan=Atd_ast.annot_of_type_exprxinAg_validate.get_validatoran=NonemoduleH=Hashtbl.Make(structtypet=type_exprletequal=(==)lethash=Hashtbl.hashend)letfor_all_childrenfx0=letis_root=reftrueintryAtd_ast.fold(funx()->if!is_rootthen(is_root:=false;assert(x==x0);)elseifnot(fx)thenraiseExit)x0();truewithExit->false(*
Return if an expression is shallow, i.e. it does not require to call
a validation function other than the one possibly given
by an annotation <ocaml validator="..."> on this node.
Shallow:
int
int <ocaml validator="foo">
{ x : int } <ocaml validator="foo">
t (* where t is defined as: type t = int *)
Not shallow:
t (* where t is defined as: type t = int <ocaml validator="foo"> *)
{ x : int <ocaml validator="foo"> }
'a t
t (* where t is defined as: type t = abstract *)
*)letrecscan_expr(defs:(string,type_expr)Hashtbl.t)(visited:unitH.t)(results:boolH.t)(x:type_expr):bool=ifnot(H.memvisitedx)then(H.addvisitedx();tryH.findresultsxwithNot_found->name_is_shallowdefsvisitedresultsx&&for_all_children(funx->novalx&&scan_exprdefsvisitedresultsx)x)else(* neutral for the && operator *)trueandname_is_shallowdefsvisitedresultsx=matchxwith`Name(loc,(loc2,name,_),_)->(matchget_defdefsnamewithNone->(matchnamewith"unit"|"bool"|"int"|"float"|"string"->true|_->false)|Somex->novalx&&scan_exprdefsvisitedresultsx)|`Tvar(loc,_)->false|_->(* already verified in the call to scan_expr above *)trueletiterfx=Atd_ast.fold(funx()->fx)x()letscan_top_expr(defs:(string,type_expr)Hashtbl.t)(results:boolH.t)(x:type_expr):unit=(* Force-scan all sub-expressions *)iter(funx->ifnot(H.memresultsx)then(letb=scan_exprdefs(H.create10)resultsxin(tryletb0=H.findresultsxinassert(b0=b);withNot_found->());H.replaceresultsxb))xletmake_is_shallowdefs=letresults=H.create100inHashtbl.iter(funnamex->scan_top_exprdefsresultsx)defs;funx->tryH.findresultsxwithNot_found->assertfalse(*
Translation of the types into the ocaml/validate mapping.
*)letrecmapping_of_expr(is_shallow:type_expr->bool)(x0:type_expr):ov_mapping=letvan=Ag_validate.get_validatoraninletv2anx=(Ag_validate.get_validatoran,is_shallowx)inmatchx0with`Sum(loc,l,an)->letocaml_t=`Sum(Ag_ocaml.get_ocaml_suman)in`Sum(loc,Array.of_list(List.map(mapping_of_variantis_shallow)l),ocaml_t,v2anx0)|`Record(loc,l,an)->letocaml_t=`Record(Ag_ocaml.get_ocaml_recordan)inletocaml_field_prefix=Ag_ocaml.get_ocaml_field_prefixanin`Record(loc,Array.of_list(List.map(mapping_of_fieldis_shallowocaml_field_prefix)l),ocaml_t,v2anx0)|`Tuple(loc,l,an)->letocaml_t=`Tuplein`Tuple(loc,Array.of_list(List.map(mapping_of_cellis_shallow)l),ocaml_t,v2anx0)|`List(loc,x,an)->letocaml_t=`List(Ag_ocaml.get_ocaml_listan)in`List(loc,mapping_of_expris_shallowx,ocaml_t,v2anx0)|`Option(loc,x,an)->letocaml_t=`Optionin`Option(loc,mapping_of_expris_shallowx,ocaml_t,v2anx0)|`Nullable(loc,x,an)->letocaml_t=`Nullablein`Nullable(loc,mapping_of_expris_shallowx,ocaml_t,v2anx0)|`Shared(loc,x,an)->failwith"Sharing is not supported"|`Wrap(loc,x,an)->letw=Ag_ocaml.get_ocaml_wraplocaninletocaml_t=`Wrapwinletvalidator=matchwwithNone->v2anx0|Some_->van,truein`Wrap(loc,mapping_of_expris_shallowx,ocaml_t,validator)|`Name(loc,(loc2,s,l),an)->(matchswith"unit"->`Unit(loc,`Unit,(van,true))|"bool"->`Bool(loc,`Bool,(van,true))|"int"->leto=Ag_ocaml.get_ocaml_intanin`Int(loc,`Into,(van,true))|"float"->`Float(loc,`Float,(van,true))|"string"->`String(loc,`String,(van,true))|s->letvalidator=matchv2anx0withNone,true->None|x->Somexin`Name(loc,s,List.map(mapping_of_expris_shallow)l,None,validator))|`Tvar(loc,s)->`Tvar(loc,s)andmapping_of_cellis_shallow(loc,x,an)=letdefault=Ag_ocaml.get_ocaml_defaultaninletdoc=Ag_doc.get_doclocaninletocaml_t=`Cell{Ag_ocaml.ocaml_default=default;ocaml_fname="";ocaml_mutable=false;ocaml_fdoc=doc;}in{cel_loc=loc;cel_value=mapping_of_expris_shallowx;cel_arepr=ocaml_t;cel_brepr=(None,novalx&&is_shallowx)}andmapping_of_variantis_shallow=function`Variant(loc,(s,an),o)->letocaml_cons=Ag_ocaml.get_ocaml_conssaninletdoc=Ag_doc.get_doclocaninletocaml_t=`Variant{Ag_ocaml.ocaml_cons=ocaml_cons;ocaml_vdoc=doc;}inletarg,validate_t=matchowithNone->None,(None,true)|Somex->(Some(mapping_of_expris_shallowx),(None,novalx&&is_shallowx))in{var_loc=loc;var_cons=s;var_arg=arg;var_arepr=ocaml_t;var_brepr=validate_t;}|`Inherit_->assertfalseandmapping_of_fieldis_shallowocaml_field_prefix=function`Field(loc,(s,fk,an),x)->letfvalue=mapping_of_expris_shallowxinletocaml_default=matchfk,Ag_ocaml.get_ocaml_defaultanwith`Required,None->None|`Optional,None->Some"None"|(`Required|`Optional),Some_->errorloc"Superfluous default OCaml value"|`With_default,Somes->Somes|`With_default,None->(* will try to determine implicit default value later *)Noneinletocaml_fname=Ag_ocaml.get_ocaml_fname(ocaml_field_prefix^s)aninletocaml_mutable=Ag_ocaml.get_ocaml_mutableaninletdoc=Ag_doc.get_doclocanin{f_loc=loc;f_name=s;f_kind=fk;f_value=fvalue;f_arepr=`Field{Ag_ocaml.ocaml_default=ocaml_default;ocaml_fname=ocaml_fname;ocaml_mutable=ocaml_mutable;ocaml_fdoc=doc;};f_brepr=(None,novalx&&is_shallowx);}|`Inherit_->assertfalseletdef_of_atdis_shallow(loc,(name,param,an),x)=letocaml_predef=Ag_ocaml.get_ocaml_predef`Validateaninletdoc=Ag_doc.get_doclocaninleto=matchas_abstractxwithSome(loc2,an2)->(matchAg_ocaml.get_ocaml_module_and_t`ValidatenameanwithNone->None|Some(types_module,main_module,ext_name)->letargs=List.map(funs->`Tvar(loc,s))paraminSome(`External(loc,name,args,`External(types_module,main_module,ext_name),(Ag_validate.get_validatoran2,false))))|None->Some(mapping_of_expris_shallowx)in{def_loc=loc;def_name=name;def_param=param;def_value=o;def_arepr=`Def{Ag_ocaml.ocaml_predef=ocaml_predef;ocaml_ddoc=doc;};def_brepr=(None,false);}letfill_def_tbldefsl=List.iter(function`Type(loc,(name,param,an),x)->Hashtbl.adddefsnamex)lletinit_def_tbl()=Hashtbl.create100letmake_def_tbll=letdefs=init_def_tbl()infill_def_tbldefsl;defsletmake_def_tbl2l=letdefs=init_def_tbl()inList.iter(fun(is_rec,l)->fill_def_tbldefsl)l;defsletdefs_of_atd_module_genis_shallowl=List.map(function`Typedef->def_of_atdis_shallowdef)lletdefs_of_atd_modulel=letdefs=make_def_tbllinletis_shallow=make_is_shallowdefsindefs_of_atd_module_genis_shallowlletdefs_of_atd_modulesl=letdefs=make_def_tbl2linletis_shallow=make_is_shallowdefsinList.map(fun(is_rec,l)->(is_rec,defs_of_atd_module_genis_shallowl))l