123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482(*
* Copyright yutopp 2017 - .
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*)open!BasemoduleSf=Simple_term_formatmoduleZ=Aux.Z(* line number *)typeline_t=int[@@derivingsexp_of](* http://erlang.org/doc/apps/erts/absform.html *)typet=|AbstractCodeofform_tandform_t=|ModDeclofform_tlist|AttrExportof{line:line_t;function_arity_list:(string*int)list}|AttrExportTypeof{line:line_t;type_arity_list:(string*int)list}|AttrImportof{line:line_t;module_name:string;function_arity_list:(string*int)list}|AttrModof{line:line_t;module_name:string}|AttrFileof{line:line_t;file:string;file_line:line_t}|DeclFunof{line:line_t;function_name:string;arity:int;clauses:clause_tlist}|SpecFunof{line:line_t;module_name:stringoption;function_name:string;arity:int;specs:type_tlist}|Callbackof{line:line_t;function_name:string;arity:int;specs:type_tlist}|DeclRecordof{line:line_t;fields:record_field_tlist}|DeclTypeof{line:line_t;name:string;tvars:(line_t*string)list;ty:type_t}|DeclOpaqueTypeof{line:line_t;name:string;tvars:(line_t*string)list;ty:type_t}|AttrWildof{line:line_t;attribute:string;term:Sf.t}|FormEofandrecord_field_t=|RecordFieldof{line:line_t;line_field_name:line_t;field_name:string;ty:type_toption;default_expr:expr_toption}andliteral_t=|LitAtomof{line:line_t;atom:string}|LitCharof{line:line_t;uchar:Uchar.t}|LitFloatof{line:line_t;float:float}|LitIntegerof{line:line_t;integer:int}|LitBigIntof{line:line_t;bigint:Z.t}|LitStringof{line:line_t;str:chars}andchars=|Asciisofstring(* The char in the [Ascii s] is in 0-255 range chars and length is less than or equal to 65535.
See also http://erlang.org/doc/apps/erts/erl_ext_dist.html#string_ext *)|CharListofintlistandpattern_t=|PatBitstrof{line:line_t;elements:pattern_bin_element_tlist}|PatCompoundof{line:line_t;lhs:pattern_t;rhs:pattern_t}|PatConsof{line:line_t;head:pattern_t;tail:pattern_t}|PatNilof{line:line_t}|PatMapof{line:line_t;assocs:pattern_assoc_tlist}|PatBinOpof{line:line_t;op:string;lhs:pattern_t;rhs:pattern_t}|PatUnaryOpof{line:line_t;op:string;operand:pattern_t}|PatRecordFieldIndexof{line:line_t;name:string;line_field_name:line_t;field_name:string}|PatRecordof{line:line_t;name:string;record_fields:(line_t*atom_or_wildcard*pattern_t)list}|PatTupleof{line:line_t;pats:pattern_tlist}|PatUniversalof{line:line_t}|PatVarof{line:line_t;id:string}|PatLitof{lit:literal_t}andpattern_assoc_t=|PatAssocExactof{line:line_t;key:pattern_t;value:pattern_t}andpattern_bin_element_t=|PatBinElementof{pattern:pattern_t;size:expr_toption;tsl:(type_spec_tlist)option}andexpr_t=|ExprBodyof{exprs:expr_tlist}|ExprBitstrof{line:line_t;elements:expr_bin_element_tlist}|ExprBitstrComprehensionof{line:line_t;expr:expr_t;qualifiers:qualifier_tlist}|ExprBlockof{line:line_t;exprs:expr_tlist}|ExprCaseof{line:line_t;expr:expr_t;clauses:clause_tlist}|ExprCatchof{line:line_t;expr:expr_t}|ExprConsof{line:line_t;head:expr_t;tail:expr_t}|ExprNilof{line:line_t}|ExprListComprehensionof{line:line_t;expr:expr_t;qualifiers:qualifier_tlist}|ExprLocalFunRefof{line:line_t;function_name:string;arity:int}|ExprRemoteFunRefof{line:line_t;module_name:atom_or_var_t;function_name:atom_or_var_t;arity:integer_or_var_t}|ExprFunof{line:line_t;name:stringoption;clauses:clause_tlist}|ExprLocalCallof{line:line_t;function_expr:expr_t;args:expr_tlist}|ExprRemoteCallof{line:line_t;line_remote:line_t;module_expr:expr_t;function_expr:expr_t;args:expr_tlist}|ExprIfof{line:line_t;clauses:clause_tlist}(* `clauses` must be a list of if-clauses (ClsIf) *)|ExprMapCreationof{line:line_t;assocs:expr_assoc_tlist}|ExprMapUpdateof{line:line_t;map:expr_t;assocs:expr_assoc_tlist}|ExprMatchof{line:line_t;pattern:pattern_t;body:expr_t}|ExprBinOpof{line:line_t;op:string;lhs:expr_t;rhs:expr_t}|ExprUnaryOpof{line:line_t;op:string;operand:expr_t}|ExprReceiveof{line:line_t;clauses:clause_tlist}(* `clauses` must be a list of case-clauses (ClsCase) *)|ExprReceiveAfterof{line:line_t;clauses:clause_tlist;timeout:expr_t;body:expr_tlist}(* `clauses` must be a list of case-clauses (ClsCase) *)|ExprRecordof{line:line_t;name:string;record_fields:record_field_for_exprlist}|ExprRecordFieldAccessof{line:line_t;expr:expr_t;name:string;line_field_name:line_t;field_name:string}|ExprRecordFieldIndexof{line:line_t;name:string;line_field_name:line_t;field_name:string}|ExprRecordUpdateof{line:line_t;expr:expr_t;name:string;update_fields:record_field_for_exprlist}|ExprTupleof{line:line_t;elements:expr_tlist}|ExprTryof{line:line_t;exprs:expr_tlist;case_clauses:clause_tlist;catch_clauses:clause_tlist;after:expr_tlist}|ExprVarof{line:line_t;id:string}|ExprLitof{lit:literal_t}andexpr_assoc_t=|ExprAssocof{line:line_t;key:expr_t;value:expr_t}|ExprAssocExactof{line:line_t;key:expr_t;value:expr_t}andqualifier_t=|QualifierGeneratorof{line:line_t;pattern:pattern_t;expr:expr_t}|QualifierFilterof{filter:expr_t}|QualifierBitstrGeneratorof{line:line_t;pattern:pattern_t;expr:expr_t}andatom_or_var_t=|AtomVarAtomof{line:line_t;atom:string}|AtomVarVarof{line:line_t;id:string}andinteger_or_var_t=|IntegerVarIntegerof{line:line_t;integer:int}|IntegerVarVarof{line:line_t;id:string}andrecord_field_for_expr=|RecordFieldForExprof{line:line_t;line_name:line_t;name:string;value:expr_t}andtype_spec_t=|TypeSpecof{atom:string;value:intoption}andexpr_bin_element_t=|ExprBinElementof{expr:expr_t;size:expr_toption;tsl:(type_spec_tlist)option}andclause_t=|ClsCaseof{line:line_t;pattern:pattern_t;guard_sequence:guard_sequence_toption;body:expr_t}|ClsCatchof{line:line_t;line_cls:line_t;line_stacktrace:line_t;exception_class:atom_or_var_t;pattern:pattern_t;stacktrace:string;guard_sequence:guard_sequence_toption;body:expr_t}|ClsFunof{line:line_t;patterns:pattern_tlist;guard_sequence:guard_sequence_toption;body:expr_t}|ClsIfof{line:line_t;guard_sequence:guard_sequence_t;body:expr_t}(* guard_sequence must not be empty *)andguard_sequence_t=|GuardSeqof{guards:guard_tlist}andguard_t=|Guardof{guard_tests:guard_test_tlist}andguard_test_t=|GuardTestBitstrof{line:line_t;elements:guard_test_bin_element_tlist}|GuardTestConsof{line:line_t;head:guard_test_t;tail:guard_test_t}|GuardTestCallof{line:line_t;function_name:literal_t;args:guard_test_tlist}|GuardTestRemoteCallof{line:line_t;line_remote:line_t;line_module_name:line_t;module_name:string;(* `module_name` must be "erlang" *)line_function_name:line_t;function_name:string;args:guard_test_tlist}|GuardTestMapCreationof{line:line_t;assocs:guard_test_assoc_tlist}|GuardTestMapUpdateof{line:line_t;map:guard_test_t;assocs:guard_test_assoc_tlist}|GuardTestNilof{line:line_t}|GuardTestBinOpof{line:line_t;op:string;lhs:guard_test_t;rhs:guard_test_t}|GuardTestUnaryOpof{line:line_t;op:string;operand:guard_test_t}|GuardTestRecordof{line:line_t;name:string;record_fields:(line_t*atom_or_wildcard*guard_test_t)list}|GuardTestRecordFieldAccessof{line:line_t;record:guard_test_t;name:string;line_field_name:line_t;field_name:string}|GuardTestRecordFieldIndexof{line:line_t;name:string;line_field_name:line_t;field_name:string}|GuardTestTupleof{line:line_t;elements:guard_test_tlist}|GuardTestVarof{line:line_t;id:string}|GuardTestLitof{lit:literal_t}andguard_test_assoc_t=|GuardTestAssocof{line:line_t;key:guard_test_t;value:guard_test_t}|GuardTestAssocExactof{line:line_t;key:guard_test_t;value:guard_test_t}andatom_or_wildcard=(* atom or _ for the fields of a record creation in guard tests *)|AtomWildcardAtomof{line:line_t;atom:string}|AtomWildcardWildcardof{line:line_t}andguard_test_bin_element_t=|GuardTestBinElementof{guard_test:guard_test_t;size:guard_test_toption;tsl:(type_spec_tlist)option}andtype_t=|TyAnnof{line:line_t;annotation:type_t;tyvar:type_t}|TyBitstringof{line:line_t;m:type_t;n:type_t}|TyPredefof{line:line_t;name:string;args:type_tlist}|TyBinOpof{line:line_t;op:string;lhs:type_t;rhs:type_t}(* lhs and rhs must be an integer, char, binop or unaryop *)|TyUnaryOpof{line:line_t;op:string;operand:type_t}(* operand must be an integer, char, binop or unaryop *)|TyRangeof{line:line_t;low:type_t;high:type_t}(* low and high must be an integer, char, binop or unaryop *)|TyAnyMapof{line:line_t}|TyMapof{line:line_t;assocs:type_assoc_tlist}|TyVarof{line:line_t;id:string}|TyFunAnyof{line:line_t}|TyFunAnyArityof{line:line_t;line_any:line_t;ret:type_t}|TyContFunof{line:line_t;function_type:type_t;constraints:type_func_cont_t}|TyFunof{line:line_t;line_params:line_t;params:type_tlist;ret:type_t}|TyRecordof{line:line_t;line_name:line_t;name:string;field_types:record_field_type_tlist}|TyRemoteof{line:line_t;line_module_name:line_t;module_name:string;line_type_name:line_t;type_name:string;params:type_tlist}|TyAnyTupleof{line:line_t}|TyTupleof{line:line_t;elements:type_tlist}|TyUnionof{line:line_t;elements:type_tlist}|TyUserof{line:line_t;name:string;args:type_tlist}|TyLitof{lit:literal_t}andtype_assoc_t=|TyAssocof{line:line_t;key:type_t;value:type_t}|TyAssocExactof{line:line_t;key:type_t;value:type_t}andtype_func_cont_t=|TyContof{constraints:type_func_cont_tlist}|TyContRelof{line:line_t;constraint_kind:type_func_cont_t;lhs:type_t;rhs:type_t}|TyContIsSubTypeof{line:line_t}andrecord_field_type_t=|RecordFieldTypeof{line:line_t;line_name:line_t;name:string;ty:type_t}[@@derivingsexp_of]typeerr_t=Sf.tErr.t[@@derivingsexp_of]lettrack~locresult=Result.map_error~f:(Err.record_backtrace~loc:loc)result(* bitstring element type specifiers *)lettsl_of_sfsf=letopenResult.Let_syntaxinmatchsfwith|Sf.Listsf_tss->letts_of_sf=function|Sf.Atomatom->TypeSpec{atom;value=None}|>return|Sf.Tuple(2,[Sf.Atomatom;Sf.Integervalue])->TypeSpec{atom;value=Somevalue}|>return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of type specifier",sf))|>Result.failinsf_tss|>List.map~f:ts_of_sf|>Result.all|>track~loc:[%here]|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of type specifiers",sf))|>Result.fail(* bitstring element *)(* This function is used at bitstring constructor expression, pattern, and guard test. *)(* NOTE: This function cannot be contained in big mutual recursions started at `of_sf` without explicit type signature *)(* because type inference for polymorphic recursion is undecidable. *)(* ref: https://discuss.ocaml.org/t/value-restriction-and-mutually-recursive-functions/2432 *)letbin_element_of_sf~value_of_sf~size_of_sfsf=letopenResult.Let_syntaxinmatchsfwith|Sf.Tuple(5,[Sf.Atom"bin_element";Sf.Integerline;sf_value;sf_size;sf_tsl])->letdefault_orof_sf=function|Sf.Atom"default"->None|>return|sf->sf|>of_sf|>Result.map~f:(fune->Somee)|>track~loc:[%here]inlet%bindvalue=sf_value|>value_of_sf|>track~loc:[%here]inlet%bindsize=sf_size|>default_orsize_of_sf|>track~loc:[%here]inlet%bindtsl=sf_tsl|>default_ortsl_of_sf|>track~loc:[%here]in(value,size,tsl)|>return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of bin_element",sf))|>Result.fail(*
* Entry
*)letrecof_sfsf:(t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith|Sf.Tuple(2,[Sf.Atom"raw_abstract_v1";sf_forms])->let%bindforms=sf_forms|>form_of_sf|>track~loc:[%here]inAbstractCodeforms|>return(* is it suitable here? *)|Sf.Tuple(3,[Sf.Atom"debug_info_v1";Sf.Atom"erl_abstract_code";Sf.Tuple(2,[sf_forms;_options])])->let%bindforms=sf_forms|>form_of_sf|>track~loc:[%here]inAbstractCodeforms|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("root",sf))|>Result.fail(*
* 8.1 Module Declarations and Forms
*)andform_of_sfsf:(form_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* module declaration *)|Sf.Listsf_forms->let%bindforms=sf_forms|>List.map~f:form_of_sf|>Result.all|>track~loc:[%here]inModDeclforms|>return(* attribute -export *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"export";Sf.Listsf_function_arity_list])->let%bindfunction_arity_list=sf_function_arity_list|>List.map~f:name_and_arity_of_sf|>Result.all|>track~loc:[%here]inAttrExport{line;function_arity_list}|>return(* attribute -export_type *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"export_type";Sf.Listsf_type_arity_list])->let%bindtype_arity_list=sf_type_arity_list|>List.map~f:name_and_arity_of_sf|>Result.all|>track~loc:[%here]inAttrExportType{line;type_arity_list}|>return(* attribute -import *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"import";Sf.Tuple(2,[Sf.Atommodule_name;Sf.Listsf_function_arity_list])])->let%bindfunction_arity_list=sf_function_arity_list|>List.map~f:name_and_arity_of_sf|>Result.all|>track~loc:[%here]inAttrImport{line;module_name;function_arity_list}|>return(* attribute -module *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"module";Sf.Atommodule_name])->AttrMod{line;module_name}|>return(* attribute -file *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"file";Sf.Tuple(2,[Sf.Stringfile;Sf.Integerfile_line])])->AttrFile{line;file_line;file}|>return(* function declaration *)|Sf.Tuple(5,[Sf.Atom"function";Sf.Integerline;Sf.Atomfunction_name;Sf.Integerarity;Sf.Listsf_clauses])->let%bindclauses=sf_clauses|>List.map~f:(cls_of_sf~in_function:true)|>Result.all|>track~loc:[%here]inDeclFun{line;function_name;arity;clauses}|>return(* function specification *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"spec";Sf.Tuple(2,[Sf.Tuple(2,[Sf.Atomfunction_name;Sf.Integerarity]);Sf.Listsf_specs])])->let%bindspecs=sf_specs|>List.map~f:fun_type_of_sf|>Result.all|>track~loc:[%here]inletmodule_name=NoneinSpecFun{line;module_name;function_name;arity;specs}|>return(* function specification (callback attribute) *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"callback";Sf.Tuple(2,[Sf.Tuple(2,[Sf.Atomfunction_name;Sf.Integerarity]);Sf.Listsf_specs])])->let%bindspecs=sf_specs|>List.map~f:fun_type_of_sf|>Result.all|>track~loc:[%here]inCallback{line;function_name;arity;specs}|>return(* function specification(Mod) *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"spec";Sf.Tuple(2,[Sf.Tuple(3,[Sf.Atommodule_name;Sf.Atomfunction_name;Sf.Integerarity]);Sf.Listsf_specs])])->let%bindspecs=sf_specs|>List.map~f:fun_type_of_sf|>Result.all|>track~loc:[%here]inletmodule_name=Somemodule_nameinSpecFun{line;module_name;function_name;arity;specs}|>return(* record declaration *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"record";Sf.Tuple(2,[Sf.Atomname;Sf.Listsf_fields])])->let%bindfields=sf_fields|>List.map~f:record_field_of_sf|>Result.all|>track~loc:[%here]inDeclRecord{line;fields}|>return(* type declaration *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"type";Sf.Tuple(3,[Sf.Atomname;sf_ty;Sf.Listsf_tvars]);])->let%bindty=sf_ty|>type_of_sf|>track~loc:[%here]inlet%bindtvars=sf_tvars|>List.map~f:tvar_of_sf|>Result.all|>track~loc:[%here]inDeclType{line;name;tvars;ty}|>return(* opaque type declaration *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atom"opaque";Sf.Tuple(3,[Sf.Atomname;sf_ty;Sf.Listsf_tvars]);])->let%bindty=sf_ty|>type_of_sf|>track~loc:[%here]inlet%bindtvars=sf_tvars|>List.map~f:tvar_of_sf|>Result.all|>track~loc:[%here]inDeclOpaqueType{line;name;tvars;ty}|>return(* wild attribute *)|Sf.Tuple(4,[Sf.Atom"attribute";Sf.Integerline;Sf.Atomattribute;term])->AttrWild{line;attribute;term}|>return(* eof *)|Sf.Tuple(2,[Sf.Atom"eof";Sf.Integerline])->FormEof|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("form",sf))|>Result.failandname_and_arity_of_sfsf:((string*int),err_t)Result.t=matchsfwith|Sf.Tuple(2,[Sf.Atomname;Sf.Integerarity])->Ok(name,arity)|_->Err.create~loc:[%here](Err.Not_supported_absform("name_and_arity",sf))|>Result.failandrecord_field_of_sfsf:(record_field_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith|Sf.Tuple(3,[Sf.Atom"record_field";Sf.Integerline;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name]);])->RecordField{line;line_field_name;field_name;ty=None;default_expr=None}|>return|Sf.Tuple(4,[Sf.Atom"record_field";Sf.Integerline;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name]);sf_e])->let%binde=sf_e|>expr_of_sf|>track~loc:[%here]inRecordField{line;line_field_name;field_name;ty=None;default_expr=Somee}|>return|Sf.Tuple(3,[Sf.Atom"typed_record_field";Sf.Tuple(3,[Sf.Atom"record_field";Sf.Integerline;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])]);sf_t])->let%bindt=sf_t|>type_of_sf|>track~loc:[%here]inRecordField{line;line_field_name;field_name;ty=Somet;default_expr=None}|>return|Sf.Tuple(3,[Sf.Atom"typed_record_field";Sf.Tuple(4,[Sf.Atom"record_field";Sf.Integerline;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name]);sf_e]);sf_t])->let%binde=sf_e|>expr_of_sf|>track~loc:[%here]inlet%bindt=sf_t|>type_of_sf|>track~loc:[%here]inRecordField{line;line_field_name;field_name;ty=Somet;default_expr=Somee}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("record_field",sf))|>Result.failandtvar_of_sfsf:((line_t*string),err_t)Result.t=matchsfwith|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atomtvar])->Ok(line,tvar)|_->Err.create~loc:[%here](Err.Not_supported_absform("tvar",sf))|>Result.fail(*
* 8.2 Atomic Literals
*)andlit_of_sfsf:(literal_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith|Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline;Sf.Atomatom])->LitAtom{line;atom}|>return|Sf.Tuple(3,[Sf.Atom"char";Sf.Integerline;Sf.Integerc])->beginmatchUchar.of_scalarcwith|None->Err.create~loc:[%here](Err.Invalid_input("not a valid unicode scalar value",sf))|>Result.fail|Someuchar->LitChar{line;uchar}|>returnend|Sf.Tuple(3,[Sf.Atom"float";Sf.Integerline;Sf.Floatfloat])->LitFloat{line;float}|>return|Sf.Tuple(3,[Sf.Atom"integer";Sf.Integerline;Sf.Integerinteger])->LitInteger{line;integer}|>return|Sf.Tuple(3,[Sf.Atom"integer";Sf.Integerline;Sf.BigIntbigint])->LitBigInt{line;bigint}|>return|Sf.Tuple(3,[Sf.Atom"string";Sf.Integerline;Sf.Strings])->LitString{line;str=Asciiss}|>return|Sf.Tuple(3,[Sf.Atom"string";Sf.Integerline;Sf.Listsf_chars])->letf=function|Sf.Integerchar->returnchar|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of a string literal",sf))|>Result.failinlet%bindchars=sf_chars|>List.map~f|>Result.all|>track~loc:[%here]inLitString{line;str=CharListchars}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("lit",sf))|>Result.fail(*
* 8.3 Patterns
*)andpat_of_sfsf:(pattern_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* a bitstring pattern *)|Sf.Tuple(3,[Sf.Atom"bin";Sf.Integerline;Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:(bin_element_of_sf~value_of_sf:pat_of_sf~size_of_sf:expr_of_sf)|>Result.all|>Result.map~f:(List.map~f:(fun(pattern,size,tsl)->PatBinElement{pattern;size;tsl}))|>track~loc:[%here]inPatBitstr{line;elements}|>return(* a compound pattern *)|Sf.Tuple(4,[Sf.Atom"match";Sf.Integerline;sf_lhs;sf_rhs])->let%bindlhs=sf_lhs|>pat_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>pat_of_sf|>track~loc:[%here]inPatCompound{line;lhs;rhs}|>return(* a cons pattern *)|Sf.Tuple(4,[Sf.Atom"cons";Sf.Integerline;sf_head;sf_tail])->let%bindhead=sf_head|>pat_of_sf|>track~loc:[%here]inlet%bindtail=sf_tail|>pat_of_sf|>track~loc:[%here]inPatCons{line;head;tail}|>return(* a nil pattern *)|Sf.Tuple(2,[Sf.Atom"nil";Sf.Integerline])->PatNil{line}|>return(* a map pattern *)|Sf.Tuple(3,[Sf.Atom"map";Sf.Integerline;Sf.Listsf_assocs])->let%bindassocs=sf_assocs|>List.map~f:pat_assoc_of_sf|>Result.all|>track~loc:[%here]inPatMap{line;assocs}|>return(* a binary operator pattern *)|Sf.Tuple(5,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_lhs;sf_rhs])->let%bindlhs=sf_lhs|>pat_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>pat_of_sf|>track~loc:[%here]inPatBinOp{line;op;lhs;rhs}|>return(* a unary operator pattern *)|Sf.Tuple(4,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_operand])->let%bindoperand=sf_operand|>pat_of_sf|>track~loc:[%here]inPatUnaryOp{line;op;operand}|>return(* a record field index pattern : #user.name *)|Sf.Tuple(4,[Sf.Atom"record_index";Sf.Integerline;Sf.Atomname;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])])->PatRecordFieldIndex{line;name;line_field_name;field_name}|>return(* a record pattern : #user{name = "Taro", admin = true} *)|Sf.Tuple(4,[Sf.Atom"record";Sf.Integerline;Sf.Atomname;Sf.Listsf_record_fields])->letfield_of_sfsf=beginmatchsfwith|Sf.Tuple(4,[Sf.Atom"record_field";Sf.Integerline;sf_atom_or_wildcard;sf_pattern])->let%bindfield_name=atom_or_wildcard_of_sfsf_atom_or_wildcard|>track~loc:[%here]inlet%bindrhs=pat_of_sfsf_pattern|>track~loc:[%here]in(line,field_name,rhs)|>return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of a field of record pattern",sf))|>Result.failendinlet%bindrecord_fields=sf_record_fields|>List.map~f:field_of_sf|>Result.all|>track~loc:[%here]inPatRecord{line;name;record_fields}|>return(* a tuple pattern *)|Sf.Tuple(3,[Sf.Atom"tuple";Sf.Integerline;Sf.Listsf_pats])->let%bindpats=sf_pats|>List.map~f:pat_of_sf|>Result.all|>track~loc:[%here]inPatTuple{line;pats}|>return(* a variable pattern *)|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atom"_"])->PatUniversal{line}|>return(* a variable pattern *)|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atomid])->PatVar{line;id}|>return(* atomic literal *)|sf_lit->let%bindlit=sf_lit|>lit_of_sf|>track~loc:[%here]inPatLit{lit}|>returnandpat_assoc_of_sfsf:(pattern_assoc_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* an exact association *)|Sf.Tuple(4,[Sf.Atom"map_field_exact";Sf.Integerline;sf_key;sf_value])->let%bindkey=sf_key|>pat_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>pat_of_sf|>track~loc:[%here]inPatAssocExact{line;key;value}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("pat_assoc",sf))|>Result.fail(*
* 8.4 Expressions
*)andexpr_of_sfsf:(expr_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith|Sf.Listsf_exprs->let%bindexprs=sf_exprs|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprBody{exprs}|>return(* a bitstring constructor *)|Sf.Tuple(3,[Sf.Atom"bin";Sf.Integerline;Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:(bin_element_of_sf~value_of_sf:expr_of_sf~size_of_sf:expr_of_sf)|>Result.all|>Result.map~f:(List.map~f:(fun(expr,size,tsl)->ExprBinElement{expr;size;tsl}))|>track~loc:[%here]inExprBitstr{line;elements}|>return(* a bitstring comprehension *)|Sf.Tuple(4,[Sf.Atom"bc";Sf.Integerline;sf_expr;Sf.Listsf_qualifiers])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inlet%bindqualifiers=sf_qualifiers|>List.map~f:qualifier_of_sf|>Result.all|>track~loc:[%here]inExprBitstrComprehension{line;expr;qualifiers}|>return(* a block expression *)|Sf.Tuple(3,[Sf.Atom"block";Sf.Integerline;Sf.Listsf_exprs])->let%bindexprs=sf_exprs|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprBlock{line;exprs}|>return(* a case expression *)|Sf.Tuple(4,[Sf.Atom"case";Sf.Integerline;sf_expr;Sf.Listsf_clauses])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inlet%bindclauses=sf_clauses|>List.map~f:cls_of_sf|>Result.all|>track~loc:[%here]inExprCase{line;expr;clauses}|>return(* a catch expression *)|Sf.Tuple(3,[Sf.Atom"catch";Sf.Integerline;sf_expr])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inExprCatch{line;expr}|>return(* a cons expression *)|Sf.Tuple(4,[Sf.Atom"cons";Sf.Integerline;sf_head;sf_tail])->let%bindhead=sf_head|>expr_of_sf|>track~loc:[%here]inlet%bindtail=sf_tail|>expr_of_sf|>track~loc:[%here]inExprCons{line;head;tail}|>return(* a nil expression *)|Sf.Tuple(2,[Sf.Atom"nil";Sf.Integerline])->ExprNil{line}|>return(* a list comprehension *)|Sf.Tuple(4,[Sf.Atom"lc";Sf.Integerline;sf_expr;Sf.Listsf_qualifiers])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inlet%bindqualifiers=sf_qualifiers|>List.map~f:qualifier_of_sf|>Result.all|>track~loc:[%here]inExprListComprehension{line;expr;qualifiers}|>return(* a local function reference *)|Sf.Tuple(3,[Sf.Atom"fun";Sf.Integerline;Sf.Tuple(3,[Sf.Atom"function";Sf.Atomfunction_name;Sf.Integerarity])])->ExprLocalFunRef{line;function_name;arity}|>return(* a remote function reference *)|Sf.Tuple(3,[Sf.Atom"fun";Sf.Integerline;Sf.Tuple(4,[Sf.Atom"function";sf_module_name;sf_function_name;sf_arity])])->let%bindmodule_name=sf_module_name|>atom_or_var_of_sf|>track~loc:[%here]inlet%bindfunction_name=sf_function_name|>atom_or_var_of_sf|>track~loc:[%here]inlet%bindarity=sf_arity|>integer_or_var_of_sf|>track~loc:[%here]inExprRemoteFunRef{line;module_name;function_name;arity}|>return(* a function expression *)|Sf.Tuple(3,[Sf.Atom"fun";Sf.Integerline;Sf.Tuple(2,[Sf.Atom"clauses";Sf.Listsf_clauses])])->let%bindclauses=sf_clauses|>List.map~f:(cls_of_sf~in_function:true)|>Result.all|>track~loc:[%here]inExprFun{line;name=None;clauses}|>return(* a named function expression *)|Sf.Tuple(4,[Sf.Atom"named_fun";Sf.Integerline;Sf.Atomname;Sf.Listsf_clauses])->let%bindclauses=sf_clauses|>List.map~f:(cls_of_sf~in_function:true)|>Result.all|>track~loc:[%here]inExprFun{line;name=Somename;clauses}|>return(* a function call (remote) *)|Sf.Tuple(4,[Sf.Atom"call";Sf.Integerline;Sf.Tuple(4,[Sf.Atom"remote";Sf.Integerline_remote;sf_module_expr;sf_function_expr]);Sf.Listsf_args])->let%bindmodule_expr=sf_module_expr|>expr_of_sf|>track~loc:[%here]inlet%bindfunction_expr=sf_function_expr|>expr_of_sf|>track~loc:[%here]inlet%bindargs=sf_args|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprRemoteCall{line;line_remote;module_expr;function_expr;args}|>return(* a function call (local) *)|Sf.Tuple(4,[Sf.Atom"call";Sf.Integerline;sf_function_expr;Sf.Listsf_args])->let%bindfunction_expr=sf_function_expr|>expr_of_sf|>track~loc:[%here]inlet%bindargs=sf_args|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprLocalCall{line;function_expr;args}|>return(* an if expression *)|Sf.Tuple(3,[Sf.Atom"if";Sf.Integerline;Sf.Listsf_clauses])->let%bindclauses=sf_clauses|>List.map~f:(cls_of_sf~in_function:false)|>Result.all|>track~loc:[%here]inExprIf{line;clauses}|>return(* a map creation *)|Sf.Tuple(3,[Sf.Atom"map";Sf.Integerline;Sf.Listsf_assocs])->let%bindassocs=sf_assocs|>List.map~f:expr_assoc_of_sf|>Result.all|>track~loc:[%here]inExprMapCreation{line;assocs}|>return(* a map update *)|Sf.Tuple(4,[Sf.Atom"map";Sf.Integerline;sf_map;Sf.Listsf_assocs])->let%bindmap=sf_map|>expr_of_sf|>track~loc:[%here]inlet%bindassocs=sf_assocs|>List.map~f:expr_assoc_of_sf|>Result.all|>track~loc:[%here]inExprMapUpdate{line;map;assocs}|>return(* match operator expression *)|Sf.Tuple(4,[Sf.Atom"match";Sf.Integerline;sf_pattern;sf_body])->let%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inExprMatch{line;pattern;body}|>return(* an operator expression binary *)|Sf.Tuple(5,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_lhs;sf_rhs])->let%bindlhs=sf_lhs|>expr_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>expr_of_sf|>track~loc:[%here]inExprBinOp{line;op;lhs;rhs}|>return(* an operator expression unary *)|Sf.Tuple(4,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_operand])->let%bindoperand=sf_operand|>expr_of_sf|>track~loc:[%here]inExprUnaryOp{line;op;operand}|>return(* a receive expression *)|Sf.Tuple(3,[Sf.Atom"receive";Sf.Integerline;Sf.Listsf_clauses])->let%bindclauses=sf_clauses|>List.map~f:cls_of_sf|>Result.all|>track~loc:[%here]inExprReceive{line;clauses}|>return(* a receive-after expression *)|Sf.Tuple(5,[Sf.Atom"receive";Sf.Integerline;Sf.Listsf_clauses;sf_timeout;Sf.Listsf_body])->let%bindclauses=sf_clauses|>List.map~f:cls_of_sf|>Result.all|>track~loc:[%here]inlet%bindtimeout=sf_timeout|>expr_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprReceiveAfter{line;clauses;timeout;body}|>return(* a record creation : #user{name = "Taro", admin = true} *)|Sf.Tuple(4,[Sf.Atom"record";Sf.Integerline;Sf.Atomname;Sf.Listsf_record_fields])->let%bindrecord_fields=sf_record_fields|>List.map~f:record_field_for_expr_of_sf|>Result.all|>track~loc:[%here]inExprRecord{line;name;record_fields}|>return(* a record field access : U#user.name *)|Sf.Tuple(5,[Sf.Atom"record_field";Sf.Integerline;sf_expr;Sf.Atomname;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inExprRecordFieldAccess{line;expr;name;line_field_name;field_name}|>return(* a record field index : #user.name *)|Sf.Tuple(4,[Sf.Atom"record_index";Sf.Integerline;Sf.Atomname;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])])->ExprRecordFieldIndex{line;name;line_field_name;field_name}|>return(* a record update : U#user{admin = true} *)|Sf.Tuple(5,[Sf.Atom"record";Sf.Integerline;sf_expr;Sf.Atomname;Sf.Listsf_update_fields])->let%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inlet%bindupdate_fields=sf_update_fields|>List.map~f:record_field_for_expr_of_sf|>Result.all|>track~loc:[%here]inExprRecordUpdate{line;expr;name;update_fields}|>return(* a tuple skeleton *)|Sf.Tuple(3,[Sf.Atom"tuple";Sf.Integerline;Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprTuple{line;elements}|>return(* a try expression *)|Sf.Tuple(6,[Sf.Atom"try";Sf.Integerline;Sf.Listsf_exprs;Sf.Listsf_case_clauses;Sf.Listsf_catch_clauses;Sf.Listsf_after])->let%bindexprs=sf_exprs|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inlet%bindcase_clauses=sf_case_clauses|>List.map~f:cls_of_sf|>Result.all|>track~loc:[%here]inlet%bindcatch_clauses=sf_catch_clauses|>List.map~f:cls_of_sf|>Result.all|>track~loc:[%here]inlet%bindafter=sf_after|>List.map~f:expr_of_sf|>Result.all|>track~loc:[%here]inExprTry{line;exprs;case_clauses;catch_clauses;after}|>return(* a variable *)|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atomid])->ExprVar{line;id}|>return(* atomic literal *)|sf_lit->let%bindlit=sf_lit|>lit_of_sf|>track~loc:[%here]inExprLit{lit}|>returnandexpr_assoc_of_sfsf:(expr_assoc_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* an association *)|Sf.Tuple(4,[Sf.Atom"map_field_assoc";Sf.Integerline;sf_key;sf_value])->let%bindkey=sf_key|>expr_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>expr_of_sf|>track~loc:[%here]inExprAssoc{line;key;value}|>return(* an exact association *)|Sf.Tuple(4,[Sf.Atom"map_field_exact";Sf.Integerline;sf_key;sf_value])->let%bindkey=sf_key|>expr_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>expr_of_sf|>track~loc:[%here]inExprAssocExact{line;key;value}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("expr_assoc",sf))|>Result.failandqualifier_of_sfsf:(qualifier_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* generator qualifier *)|Sf.Tuple(4,[Sf.Atom"generate";Sf.Integerline;sf_pattern;sf_expr])->let%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inQualifierGenerator{line;pattern;expr}|>return(* bitstring generator qualifier *)|Sf.Tuple(4,[Sf.Atom"b_generate";Sf.Integerline;sf_pattern;sf_expr])->let%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindexpr=sf_expr|>expr_of_sf|>track~loc:[%here]inQualifierBitstrGenerator{line;pattern;expr}|>return(* filter qualifier *)|sf_filter->let%bindfilter=sf_filter|>expr_of_sf|>track~loc:[%here]inQualifierFilter{filter}|>returnandatom_or_var_of_sfsf:(atom_or_var_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* atom *)|(Sf.Tuple(3,[(Sf.Atom"atom");(Sf.Integerline);(Sf.Atomatom)]))->AtomVarAtom{line;atom}|>return(* variable *)|(Sf.Tuple(3,[(Sf.Atom"var");(Sf.Integerline);(Sf.Atomid)]))->AtomVarVar{line;id}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("atom_or_var",sf))|>Result.failandrecord_field_for_expr_of_sfsf=letopenResult.Let_syntaxinmatchrecord_field_of_sfsfwith|Ok(RecordField{line;line_field_name;field_name;ty=None;default_expr=Somevalue})->RecordFieldForExpr{line;line_name=line_field_name;name=field_name;value}|>return|Ok_->Err.create~loc:[%here](Err.Invalid_input("the field of a record expr must have an expression",sf))|>Result.fail|Errore->Errore|>track~loc:[%here]andinteger_or_var_of_sfsf=letopenResult.Let_syntaxinmatchsfwith(* integer *)|(Sf.Tuple(3,[(Sf.Atom"integer");(Sf.Integerline);(Sf.Integerinteger)]))->IntegerVarInteger{line;integer}|>return(* variable *)|(Sf.Tuple(3,[(Sf.Atom"var");(Sf.Integerline);(Sf.Atomid)]))->IntegerVarVar{line;id}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("integer_or_var",sf))|>Result.fail(*
* 8.5 Clauses
*)andcls_of_sf?(in_function=false)sf:(clause_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsf,in_functionwith(* catch clause P -> B or E:P -> B or E:P:S -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.List[Sf.Tuple(3,[Sf.Atom"tuple";Sf.Integerline_cls;Sf.List[sf_exception_class;sf_pattern;Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline_stacktrace;Sf.Atomstacktrace])]])];Sf.List[];sf_body]),false->let%bindexception_class=sf_exception_class|>atom_or_var_of_sf|>track~loc:[%here]inlet%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsCatch{line;line_cls;line_stacktrace;exception_class;pattern;stacktrace;guard_sequence=None;body}|>return(* catch clause P when Gs -> B or E:P when Gs -> B or E:P:S when Gs -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.List[Sf.Tuple(3,[Sf.Atom"tuple";Sf.Integerline_cls;Sf.List[sf_exception_class;sf_pattern;Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline_stacktrace;Sf.Atomstacktrace])]])];sf_guard_sequence;sf_body]),false->let%bindexception_class=sf_exception_class|>atom_or_var_of_sf|>track~loc:[%here]inlet%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindguard_sequence=sf_guard_sequence|>guard_sequence_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsCatch{line;line_cls;line_stacktrace;exception_class;pattern;stacktrace;guard_sequence=Someguard_sequence;body}|>return(* case clause P -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.List[sf_pattern];Sf.List[];sf_body]),false->let%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsCase{line;pattern;guard_sequence=None;body}|>return(* case clause P -> B when Gs *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.List[sf_pattern];sf_guard_sequence;sf_body]),false->let%bindpattern=sf_pattern|>pat_of_sf|>track~loc:[%here]inlet%bindguard_sequence=sf_guard_sequence|>guard_sequence_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsCase{line;pattern;guard_sequence=Someguard_sequence;body}|>return(* if clause Gs -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.List[];sf_guard_sequence;sf_body]),false->let%bindguard_sequence=sf_guard_sequence|>guard_sequence_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsIf{line;guard_sequence;body}|>return(* function clause ( Ps ) -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.Listsf_patterns;Sf.List[];sf_body]),true->let%bindpatterns=sf_patterns|>List.map~f:pat_of_sf|>Result.all|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsFun{line;patterns;guard_sequence=None;body}|>return(* function clause ( Ps ) when Gs -> B *)|Sf.Tuple(5,[Sf.Atom"clause";Sf.Integerline;Sf.Listsf_patterns;sf_guard_sequence;sf_body]),true->let%bindpatterns=sf_patterns|>List.map~f:pat_of_sf|>Result.all|>track~loc:[%here]inlet%bindguard_sequence=sf_guard_sequence|>guard_sequence_of_sf|>track~loc:[%here]inlet%bindbody=sf_body|>expr_of_sf|>track~loc:[%here]inClsFun{line;patterns;guard_sequence=Someguard_sequence;body}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("cls",sf))|>Result.fail(*
* 8.6 Guards
*)andguard_sequence_of_sfsf:(guard_sequence_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* empty or non-empty sequence *)|Sf.Listsf_guards->let%bindguards=sf_guards|>List.map~f:guard_of_sf|>Result.all|>track~loc:[%here]inGuardSeq{guards}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("guard_sequence",sf))|>Result.failandguard_of_sfsf:(guard_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* non-empty sequence *)|Sf.Listsf_guard_testswhenList.lengthsf_guard_tests>0->let%bindguard_tests=sf_guard_tests|>List.map~f:guard_test_of_sf|>Result.all|>track~loc:[%here]inGuard{guard_tests}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("guard",sf))|>Result.failandguard_test_of_sfsf:(guard_test_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* bitstring constructor *)|Sf.Tuple(3,[Sf.Atom"bin";Sf.Integerline;Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:(bin_element_of_sf~value_of_sf:guard_test_of_sf~size_of_sf:guard_test_of_sf)|>Result.all|>Result.map~f:(List.map~f:(fun(guard_test,size,tsl)->GuardTestBinElement{guard_test;size;tsl}))|>track~loc:[%here]inGuardTestBitstr{line;elements}|>return(* cons skeleton *)|Sf.Tuple(4,[Sf.Atom"cons";Sf.Integerline;sf_head;sf_tail])->let%bindhead=sf_head|>guard_test_of_sf|>track~loc:[%here]inlet%bindtail=sf_tail|>guard_test_of_sf|>track~loc:[%here]inGuardTestCons{line;head;tail}|>return(* remote function call *)|Sf.Tuple(4,[Sf.Atom"call";Sf.Integerline;Sf.Tuple(4,[Sf.Atom"remote";Sf.Integerline_remote;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_module_name;Sf.Atommodule_name]);Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_function_name;Sf.Atomfunction_name])]);Sf.Listsf_args])->let%bindargs=sf_args|>List.map~f:guard_test_of_sf|>Result.all|>track~loc:[%here]inGuardTestRemoteCall{line;line_remote;line_module_name;module_name;line_function_name;function_name;args}|>return(* function call *)|Sf.Tuple(4,[Sf.Atom"call";Sf.Integerline;sf_function_name;Sf.Listsf_args])->let%bindfunction_name=sf_function_name|>lit_of_sf|>track~loc:[%here]inlet%bindargs=sf_args|>List.map~f:guard_test_of_sf|>Result.all|>track~loc:[%here]inGuardTestCall{line;function_name;args}|>return(* a map creation *)|Sf.Tuple(3,[Sf.Atom"map";Sf.Integerline;Sf.Listsf_assocs])->let%bindassocs=sf_assocs|>List.map~f:guard_test_assoc_of_sf|>Result.all|>track~loc:[%here]inGuardTestMapCreation{line;assocs}|>return(* a map update *)|Sf.Tuple(4,[Sf.Atom"map";Sf.Integerline;sf_map;Sf.Listsf_assocs])->let%bindmap=sf_map|>guard_test_of_sf|>track~loc:[%here]inlet%bindassocs=sf_assocs|>List.map~f:guard_test_assoc_of_sf|>Result.all|>track~loc:[%here]inGuardTestMapUpdate{line;map;assocs}|>return(* nil *)|Sf.Tuple(2,[Sf.Atom"nil";Sf.Integerline])->GuardTestNil{line}|>return(* a binary operator *)|Sf.Tuple(5,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_lhs;sf_rhs])->let%bindlhs=sf_lhs|>guard_test_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>guard_test_of_sf|>track~loc:[%here]inGuardTestBinOp{line;op;lhs;rhs}|>return(* a unary operator *)|Sf.Tuple(4,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_operand])->let%bindoperand=sf_operand|>guard_test_of_sf|>track~loc:[%here]inGuardTestUnaryOp{line;op;operand}|>return(* a record creation : #user{name = "Taro", admin = true} *)|Sf.Tuple(4,[Sf.Atom"record";Sf.Integerline;Sf.Atomname;Sf.Listsf_record_fields])->letfield_of_sfsf=beginmatchsfwith|Sf.Tuple(4,[Sf.Atom"record_field";Sf.Integerline;sf_atom_or_wildcard;sf_guard_test])->let%bindfield_name=atom_or_wildcard_of_sfsf_atom_or_wildcard|>track~loc:[%here]inlet%bindrhs=guard_test_of_sfsf_guard_test|>track~loc:[%here]in(line,field_name,rhs)|>return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of record_field",sf))|>Result.failendinlet%bindrecord_fields=sf_record_fields|>List.map~f:field_of_sf|>Result.all|>track~loc:[%here]inGuardTestRecord{line;name;record_fields}|>return(* a record field access : U#user.name *)|Sf.Tuple(5,[Sf.Atom"record_field";Sf.Integerline;sf_record;Sf.Atomname;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])])->let%bindrecord=sf_record|>guard_test_of_sf|>track~loc:[%here]inGuardTestRecordFieldAccess{line;record;name;line_field_name;field_name}|>return(* a record field index : #user.name *)|Sf.Tuple(4,[Sf.Atom"record_index";Sf.Integerline;Sf.Atomname;Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_field_name;Sf.Atomfield_name])])->GuardTestRecordFieldIndex{line;name;line_field_name;field_name}|>return(* a tuple skeleton *)|Sf.Tuple(3,[Sf.Atom"tuple";Sf.Integerline;Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:guard_test_of_sf|>Result.all|>track~loc:[%here]inGuardTestTuple{line;elements}|>return(* variable pattern *)|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atomid])->GuardTestVar{line;id}|>return(* atomic literal *)|sf_lit->let%bindlit=sf_lit|>lit_of_sf|>track~loc:[%here]inGuardTestLit{lit}|>returnandguard_test_assoc_of_sfsf:(guard_test_assoc_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* an association *)|Sf.Tuple(4,[Sf.Atom"map_field_assoc";Sf.Integerline;sf_key;sf_value])->let%bindkey=sf_key|>guard_test_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>guard_test_of_sf|>track~loc:[%here]inGuardTestAssoc{line;key;value}|>return(* an exact association *)|Sf.Tuple(4,[Sf.Atom"map_field_exact";Sf.Integerline;sf_key;sf_value])->let%bindkey=sf_key|>guard_test_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>guard_test_of_sf|>track~loc:[%here]inGuardTestAssocExact{line;key;value}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("guard_test_assoc",sf))|>Result.failandatom_or_wildcard_of_sfsf=matchsfwith|Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline;Sf.Atomfield_name])->AtomWildcardAtom{line;atom=field_name}|>Result.return|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atom"_"])->AtomWildcardWildcard{line}|>Result.return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of atom_or_wildcard",sf))|>Result.fail(*
* 8.7 Types
*)andtype_of_sfsf:(type_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* annotated type *)|Sf.Tuple(3,[Sf.Atom"ann_type";Sf.Integerline;Sf.List[sf_annotation;sf_tyvar]])->let%bindannotation=sf_annotation|>type_of_sf|>track~loc:[%here]inlet%bindtyvar=sf_tyvar|>type_of_sf|>track~loc:[%here]inTyAnn{line;annotation;tyvar}|>return(* bitstring type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"binary";Sf.List[sf_m;sf_n]])->let%bindm=sf_m|>type_of_sf|>track~loc:[%here]inlet%bindn=sf_n|>type_of_sf|>track~loc:[%here]inTyBitstring{line;m;n}|>return(* fun type (any) *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"fun";Sf.List[]])->TyFunAny{line}|>return(* fun type (any arity) *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"fun";Sf.List[Sf.Tuple(3,[Sf.Atom"type";Sf.Integerline_any;Sf.Atom"any";]);sf_ret]])->let%bindret=sf_ret|>type_of_sf|>track~loc:[%here]inTyFunAnyArity{line;line_any;ret}|>return(* map type (any) *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"map";Sf.Atom"any"])->TyAnyMap{line}|>return(* map type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"map";Sf.Listsf_assocs])->let%bindassocs=sf_assocs|>List.map~f:type_assoc_of_sf|>Result.all|>track~loc:[%here]inTyMap{line;assocs}|>return(* operator type for a binary operator *)|Sf.Tuple(5,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_lhs;sf_rhs])->let%bindlhs=sf_lhs|>type_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>type_of_sf|>track~loc:[%here]inTyBinOp{line;lhs;op;rhs}|>return(* operator type for a unary operator *)|Sf.Tuple(4,[Sf.Atom"op";Sf.Integerline;Sf.Atomop;sf_operand])->let%bindoperand=sf_operand|>type_of_sf|>track~loc:[%here]inTyUnaryOp{line;op;operand}|>return(* range type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"range";Sf.List[sf_low;sf_high]])->let%bindlow=sf_low|>type_of_sf|>track~loc:[%here]inlet%bindhigh=sf_high|>type_of_sf|>track~loc:[%here]inTyRange{line;low;high}|>return(* record type : t(A) = #state{name :: A} *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"record";Sf.List(Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_name;Sf.Atomname])::sf_field_types)])->let%bindfield_types=sf_field_types|>List.map~f:record_field_type_of_sf|>Result.all|>track~loc:[%here]inTyRecord{line;line_name;name;field_types}|>return(* remote type : dict:dict(integer(), any()) *)|Sf.Tuple(3,[Sf.Atom"remote_type";Sf.Integerline;Sf.List[Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_module_name;Sf.Atommodule_name]);Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_type_name;Sf.Atomtype_name]);Sf.Listsf_params;]])->let%bindparams=sf_params|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inTyRemote{line;line_module_name;module_name;line_type_name;type_name;params}|>return(* tuple type (any) *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"tuple";Sf.Atom"any"])->TyAnyTuple{line}|>return(* tuple type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"tuple";Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inTyTuple{line;elements}|>return(* union type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"union";Sf.Listsf_elements])->let%bindelements=sf_elements|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inTyUnion{line;elements}|>return(* predefined (or built-in) type OR fun type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atomname;Sf.Listsf_args])->beginmatchfun_type_of_sfsfwith|Okfn->Okfn|_->let%bindargs=sf_args|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inTyPredef{line;name;args}|>returnend(* type variable *)|Sf.Tuple(3,[Sf.Atom"var";Sf.Integerline;Sf.Atomid])->TyVar{line;id}|>return(* user defined type *)|Sf.Tuple(4,[Sf.Atom"user_type";Sf.Integerline;Sf.Atomname;Sf.Listsf_args])->let%bindargs=sf_args|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inTyUser{line;name;args}|>return(* atomic literal *)|sf_lit->let%bindlit=sf_lit|>lit_of_sf|>track~loc:[%here]inTyLit{lit}|>returnandfun_type_of_sfsf:(type_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* constrained function type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"bounded_fun";Sf.List[sf_function_type;sf_constraints]])->let%bindfunction_type=sf_function_type|>type_of_sf|>track~loc:[%here]inlet%bindconstraints=sf_constraints|>type_fun_cont_of_sf|>track~loc:[%here]inTyContFun{line;function_type;constraints}|>return(* function type *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"fun";Sf.List[Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline_params;Sf.Atom"product";Sf.Listsf_params]);sf_ret]])->let%bindparams=sf_params|>List.map~f:type_of_sf|>Result.all|>track~loc:[%here]inlet%bindret=sf_ret|>type_of_sf|>track~loc:[%here]inTyFun{line;line_params;params;ret}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("fun_type",sf))|>Result.failandtype_fun_cont_of_sfsf:(type_func_cont_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith|Sf.Listsf_constraints->let%bindconstraints=sf_constraints|>List.map~f:type_fun_cont_of_sf|>Result.all|>track~loc:[%here]inTyCont{constraints}|>return|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"constraint";Sf.List[sf_constraint_kind;Sf.List[sf_lhs;sf_rhs]]])->let%bindconstraint_kind=sf_constraint_kind|>type_fun_cont_of_sf|>track~loc:[%here]inlet%bindlhs=sf_lhs|>type_of_sf|>track~loc:[%here]inlet%bindrhs=sf_rhs|>type_of_sf|>track~loc:[%here]inTyContRel{line;constraint_kind;lhs;rhs}|>return|Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline;Sf.Atom"is_subtype"])->TyContIsSubType{line}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("type_fun_cont",sf))|>Result.failandtype_assoc_of_sfsf:(type_assoc_t,err_t)Result.t=letopenResult.Let_syntaxinmatchsfwith(* an association *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"map_field_assoc";Sf.List[sf_key;sf_value]])->let%bindkey=sf_key|>type_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>type_of_sf|>track~loc:[%here]inTyAssoc{line;key;value}|>return(* an exact association *)|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"map_field_exact";Sf.List[sf_key;sf_value]])->let%bindkey=sf_key|>type_of_sf|>track~loc:[%here]inlet%bindvalue=sf_value|>type_of_sf|>track~loc:[%here]inTyAssocExact{line;key;value}|>return|_->Err.create~loc:[%here](Err.Not_supported_absform("type_assoc",sf))|>Result.failandrecord_field_type_of_sfsf=letopenResult.Let_syntaxinmatchsfwith|Sf.Tuple(4,[Sf.Atom"type";Sf.Integerline;Sf.Atom"field_type";Sf.List[Sf.Tuple(3,[Sf.Atom"atom";Sf.Integerline_name;Sf.Atomfield_name]);sf_ty;]])->let%bindty=sf_ty|>type_of_sf|>track~loc:[%here]inRecordFieldType{line;line_name;name=field_name;ty}|>return|_->Err.create~loc:[%here](Err.Invalid_input("invalid form of a record field type",sf))|>Result.fail(**)letof_etfetf:(t,err_t)Result.t=etf|>Sf.of_etf|>of_sf