123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315(*****************************************************************************)(* *)(* 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=letopenResult_syntaxinmatchannotwith|[]->return_unit|_::_->tzfail(Unexpected_annotationloc)(* Check that the predicate p holds on all s.[k] for k >= i *)letstring_iterpsi=letopenResult_syntaxinletlen=String.lengthsinletrecauxi=ifCompare.Int.(i>=len)thenreturn_unitelselet*()=ps.[i]inaux(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=letopenResult_syntaxinifis_allowed_charcthenreturn_unitelsetzfail(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=letopenResult_syntaxin(* 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->return@@wrapNone|Somes->(match(s:>string).[0]with|'a'..'z'|'A'..'Z'|'_'|'0'..'9'->(* check that all characters are valid*)let*()=string_iter(check_charloc)(s:>string)1inreturn@@wrap(Somes)|_->tzfail(Unexpected_annotationloc))inletlen=String.lengthsinifCompare.Int.(len=0||len>max_annot_length)thentzfail(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|_->tzfail(Unexpected_annotationloc)letparse_annotsloc?(allow_special_var=false)?(allow_special_field=false)l=letopenResult_syntaxinList.map_e(function|"@%"whenallow_special_var->return@@Var_annot_opt(SomeVar_annot)|"@%%"whenallow_special_var->return@@Var_annot_opt(SomeVar_annot)|"%@"whenallow_special_field->return@@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=letopenResult_syntaxintrylet_,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,[])linreturn(List.revrv,List.revrt,List.revrf)withExit->tzfail(Ungrouped_annotationsloc)letget_one_annotloc=letopenResult_syntaxinfunction|[]->return_none|[a]->returna|_->tzfail(Unexpected_annotationloc)letget_two_annotloc=letopenResult_syntaxinfunction|[]->return(None,None)|[a]->return(a,None)|[a;b]->return(a,b)|_->tzfail(Unexpected_annotationloc)letcheck_type_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotslocannotinclassify_annotlocannotsinlet*()=error_unexpected_annotlocvarsinlet*()=error_unexpected_annotlocfieldsinlet+(_a:type_annotoption)=get_one_annotloctypesin()letparse_field_annot:Script.location->string->Non_empty_string.toptiontzresult=letopenResult_syntaxinfunlocannot->ifCompare.Int.(String.lengthannot<=0)||Compare.Char.(annot.[0]<>'%')thenreturn_noneelselet+annot_opt=parse_annotlocannotinmatchannot_optwithField_annot_optannot_opt->annot_opt|_->Noneletis_field_annotloca=letopenResult_syntaxinlet+result=parse_field_annotlocainOption.is_someresultletextract_field_annot:Script.node->(Script.node*Non_empty_string.toption)tzresult=letopenResult_syntaxinfunction|Prim(loc,prim,args,annot)asexpr->letrecextract_firstacc=function|[]->return(expr,None)|s::rest->(let*str_opt=parse_field_annotlocsinmatchstr_optwith|None->extract_first(s::acc)rest|Some_assome_field_annot->letannot=List.rev_appendaccrestinreturn(Prim(loc,prim,args,annot),some_field_annot))inextract_first[]annot|expr->return(expr,None)lethas_field_annotnode=letopenResult_syntaxinlet+_node,result=extract_field_annotnodeinOption.is_someresultletremove_field_annotnode=letopenResult_syntaxinlet+node,_a=extract_field_annotnodeinnodeletextract_entrypoint_annotnode=letopenResult_syntaxinlet+node,field_annot_opt=extract_field_annotnodein(node,Option.bindfield_annot_opt(funfield_annot->Entrypoint.of_annot_lax_optfield_annot))letcheck_var_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotslocannotinclassify_annotlocannotsinlet*()=error_unexpected_annotloctypesinlet*()=error_unexpected_annotlocfieldsinlet+(_a:var_annotoption)=get_one_annotlocvarsin()letcheck_constr_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annots~allow_special_field:truelocannotinclassify_annotlocannotsinlet*(_v:var_annotoption)=get_one_annotlocvarsinlet*(_t:type_annotoption)=get_one_annotloctypesinlet+_f1,_f2=get_two_annotlocfieldsin()letcheck_two_var_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotslocannotinclassify_annotlocannotsinlet*()=error_unexpected_annotloctypesinlet*()=error_unexpected_annotlocfieldsinlet+_a1,_a2=get_two_annotlocvarsin()letcheck_destr_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotsloc~allow_special_var:trueannotinclassify_annotlocannotsinlet*()=error_unexpected_annotloctypesinlet*(_v:var_annotoption)=get_one_annotlocvarsinlet+(_f:field_annotoption)=get_one_annotlocfieldsin()letcheck_unpair_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotsloc~allow_special_var:trueannotinclassify_annotlocannotsinlet*()=error_unexpected_annotloctypesinlet*_vcar,_vcdr=get_two_annotlocvarsinlet+_f1,_f2=get_two_annotlocfieldsin()letparse_entrypoint_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotslocannotinclassify_annotlocannotsinlet*()=error_unexpected_annotloctypesinlet*f=get_one_annotlocfieldsinlet+(_v:var_annotoption)=get_one_annotlocvarsinfletparse_entrypoint_annot_strictlocannot=letopenResult_syntaxinlet*entrypoint_annot=parse_entrypoint_annotlocannotinmatchentrypoint_annotwith|None->OkEntrypoint.default|Some(Field_annota)->Entrypoint.of_annot_strict~localetparse_entrypoint_annot_laxlocannot=letopenResult_syntaxinlet*entrypoint_annot=parse_entrypoint_annotlocannotinmatchentrypoint_annotwith|None->OkEntrypoint.default|Some(Field_annotannot)->Entrypoint.of_annot_laxannotletcheck_var_type_annotlocannot=letopenResult_syntaxinlet*vars,types,fields=let*annots=parse_annotslocannotinclassify_annotlocannotsinlet*()=error_unexpected_annotlocfieldsinlet*(_v:var_annotoption)=get_one_annotlocvarsinlet+(_t:type_annotoption)=get_one_annotloctypesin()