123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2019-2022 Nomadic Labs, <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openAlpha_contextopenMichelineopenScript_tc_errorstypevar_annot=Var_annottypetype_annot=Type_annottypefield_annot=Field_annotofNon_empty_string.t[@@ocaml.unboxed]leterror_unexpected_annotlocannot=matchannotwith|[]->Result.return_unit|_::_->error(Unexpected_annotationloc)(* Check that the predicate p holds on all s.[k] for k >= i *)letstring_iterpsi=letlen=String.lengthsinletrecauxi=ifCompare.Int.(i>=len)thenResult.return_unitelseps.[i]>>?fun()->aux(i+1)inauxiletis_allowed_char=function|'a'..'z'|'A'..'Z'|'_'|'.'|'%'|'@'|'0'..'9'->true|_->false(* Valid annotation characters as defined by the allowed_annot_char function from lib_micheline/micheline_parser *)letcheck_charlocc=ifis_allowed_charcthenResult.return_unitelseerror(Unexpected_annotationloc)(* This constant is defined in lib_micheline/micheline_parser which is not available in the environment. *)letmax_annot_length=255typeannot_opt=|Field_annot_optofNon_empty_string.toption|Type_annot_optoftype_annotoption|Var_annot_optofvar_annotoptionletat=Non_empty_string.of_string_exn"@"letparse_annotlocs=(* allow empty annotations as wildcards but otherwise only accept
annotations that start with [a-zA-Z_] *)letsub_or_wildcardwraps=matchNon_empty_string.of_stringswith|None->ok@@wrapNone|Somes->(match(s:>string).[0]with|'a'..'z'|'A'..'Z'|'_'|'0'..'9'->(* check that all characters are valid*)string_iter(check_charloc)(s:>string)1>>?fun()->ok@@wrap(Somes)|_->error(Unexpected_annotationloc))inletlen=String.lengthsinifCompare.Int.(len=0||len>max_annot_length)thenerror(Unexpected_annotationloc)elseletrest=String.subs1(len-1)inmatchs.[0]with|':'->sub_or_wildcard(funa->Type_annot_opt(Option.map(fun(_:Non_empty_string.t)->Type_annot)a))rest|'@'->sub_or_wildcard(funa->Var_annot_opt(Option.map(fun(_:Non_empty_string.t)->Var_annot)a))rest|'%'->sub_or_wildcard(funa->Field_annot_opta)rest|_->error(Unexpected_annotationloc)letparse_annotsloc?(allow_special_var=false)?(allow_special_field=false)l=List.map_e(function|"@%"whenallow_special_var->ok@@Var_annot_opt(SomeVar_annot)|"@%%"whenallow_special_var->ok@@Var_annot_opt(SomeVar_annot)|"%@"whenallow_special_field->ok@@Field_annot_opt(Someat)|s->parse_annotlocs)lletopt_field_of_field_opt=function|None->None|Somea->Some(Field_annota)letclassify_annotlocl:(var_annotoptionlist*type_annotoptionlist*field_annotoptionlist)tzresult=trylet_,rv,_,rt,_,rf=List.fold_left(fun(in_v,rv,in_t,rt,in_f,rf)a->match(a,in_v,rv,in_t,rt,in_f,rf)with|Var_annot_opta,true,_,_,_,_,_|Var_annot_opta,false,[],_,_,_,_->(true,a::rv,false,rt,false,rf)|Type_annot_opta,_,_,true,_,_,_|Type_annot_opta,_,_,false,[],_,_->(false,rv,true,a::rt,false,rf)|Field_annot_opta,_,_,_,_,true,_|Field_annot_opta,_,_,_,_,false,[]->(false,rv,false,rt,true,opt_field_of_field_opta::rf)|_->raiseExit)(false,[],false,[],false,[])linok(List.revrv,List.revrt,List.revrf)withExit->error(Ungrouped_annotationsloc)letget_one_annotloc=function|[]->Result.return_none|[a]->oka|_->error(Unexpected_annotationloc)letget_two_annotloc=function|[]->ok(None,None)|[a]->ok(a,None)|[a;b]->ok(a,b)|_->error(Unexpected_annotationloc)letcheck_type_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotlocvars>>?fun()->error_unexpected_annotlocfields>>?fun()->get_one_annotloctypes>|?fun(_a:type_annotoption)->()letcheck_composed_type_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotlocvars>>?fun()->get_one_annotloctypes>>?fun(_t:type_annotoption)->get_two_annotlocfields>|?fun(_f1,_f2)->()letparse_field_annot:Script.location->string->Non_empty_string.toptiontzresult=funlocannot->ifCompare.Int.(String.lengthannot<=0)||Compare.Char.(annot.[0]<>'%')thenResult.return_noneelseparse_annotlocannot>|?function|Field_annot_optannot_opt->annot_opt|_->Noneletis_field_annotloca=parse_field_annotloca>|?Option.is_someletextract_field_annot:Script.node->(Script.node*Non_empty_string.toption)tzresult=function|Prim(loc,prim,args,annot)asexpr->letrecextract_firstacc=function|[]->ok(expr,None)|s::rest->(parse_field_annotlocs>>?function|None->extract_first(s::acc)rest|Some_assome_field_annot->letannot=List.rev_appendaccrestinok(Prim(loc,prim,args,annot),some_field_annot))inextract_first[]annot|expr->ok(expr,None)lethas_field_annotnode=extract_field_annotnode>|?function|_node,Some_->true|_node,None->falseletremove_field_annotnode=extract_field_annotnode>|?fun(node,_a)->nodeletextract_entrypoint_annotnode=extract_field_annotnode>|?fun(node,field_annot_opt)->(node,Option.bindfield_annot_opt(funfield_annot->Entrypoint.of_annot_lax_optfield_annot))letcheck_var_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotloctypes>>?fun()->error_unexpected_annotlocfields>>?fun()->get_one_annotlocvars>|?fun(_a:var_annotoption)->()letcheck_constr_annotlocannot=parse_annots~allow_special_field:truelocannot>>?classify_annotloc>>?fun(vars,types,fields)->get_one_annotlocvars>>?fun(_v:var_annotoption)->get_one_annotloctypes>>?fun(_t:type_annotoption)->get_two_annotlocfields>|?fun(_f1,_f2)->()letcheck_two_var_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotloctypes>>?fun()->error_unexpected_annotlocfields>>?fun()->get_two_annotlocvars>|?fun(_a1,_a2)->()letcheck_destr_annotlocannot=parse_annotsloc~allow_special_var:trueannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotloctypes>>?fun()->get_one_annotlocvars>>?fun(_v:var_annotoption)->get_one_annotlocfields>|?fun(_f:field_annotoption)->()letcheck_unpair_annotlocannot=parse_annotsloc~allow_special_var:trueannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotloctypes>>?fun()->get_two_annotlocvars>>?fun(_vcar,_vcdr)->get_two_annotlocfields>|?fun(_f1,_f2)->()letparse_entrypoint_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotloctypes>>?fun()->get_one_annotlocfields>>?funf->get_one_annotlocvars>|?fun(_v:var_annotoption)->fletparse_entrypoint_annot_strictlocannot=parse_entrypoint_annotlocannot>>?function|None->OkEntrypoint.default|Some(Field_annota)->Entrypoint.of_annot_strict~localetparse_entrypoint_annot_laxlocannot=parse_entrypoint_annotlocannot>>?function|None->OkEntrypoint.default|Some(Field_annotannot)->Entrypoint.of_annot_laxannotletcheck_var_type_annotlocannot=parse_annotslocannot>>?classify_annotloc>>?fun(vars,types,fields)->error_unexpected_annotlocfields>>?fun()->get_one_annotlocvars>>?fun(_v:var_annotoption)->get_one_annotloctypes>|?fun(_t:type_annotoption)->()