Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file api_web.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 Inria,
contributors: Emile Rolley <emile.rolley@tuta.io>, Louis Gesbert
<louis.gesbert@inria.fr>.
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)openCatala_utilsopenShared_astopenLcalcopenLcalc.AstopenLcalc.To_ocamlmoduleD=Dcalc.Ast(** Contains all format functions used to generating the [js_of_ocaml] wrapper
of the corresponding Catala program. *)moduleTo_jsoo=structletformat_struct_field_name_camel_case(ppf:Format.formatter)(v:StructField.t):unit=StructField.to_stringv|>String.to_camel_case|>String.uncapitalize_ascii|>avoid_keywords|>Format.pp_print_stringppf(* Supersedes [To_ocaml.format_struct_name], which can refer to enums from
other modules: here everything is flattened in the current namespace *)letformat_struct_nameppfname=StructName.to_stringname|>String.map(function'.'->'_'|c->c)|>String.to_snake_case|>avoid_keywords|>Format.pp_print_stringppf(* Supersedes [To_ocaml.format_enum_name], which can refer to enums from other
modules: here everything is flattened in the current namespace *)letformat_enum_nameppfname=EnumName.to_stringname|>String.map(function'.'->'_'|c->c)|>String.to_snake_case|>avoid_keywords|>Format.pp_print_stringppfletformat_tlit(fmt:Format.formatter)(l:typ_lit):unit=Print.base_typefmt(matchlwith|TUnit->"unit"|TInt->"int"|TRat|TMoney->"Js.number Js.t"|TDuration->"Runtime_jsoo.Runtime.duration Js.t"|TBool->"bool Js.t"|TDate->"Js.js_string Js.t")letrecformat_typ(fmt:Format.formatter)(typ:typ):unit=letformat_typ_with_parens(fmt:Format.formatter)(t:typ)=iftyp_needs_parenstthenFormat.fprintffmt"(%a)"format_typtelseFormat.fprintffmt"%a"format_typtinmatchMark.removetypwith|TLitl->Format.fprintffmt"%a"format_tlitl|TStructs->Format.fprintffmt"%a Js.t"format_struct_names|TTuple_->(* Tuples are encoded as an javascript polymorphic array. *)Format.fprintffmt"Js.Unsafe.any_js_array Js.t "|TOptiont->Format.fprintffmt"@[<hov 2>(%a)@] Js.opt"format_typ_with_parenst|TDefaultt->format_typfmtt|TEnume->Format.fprintffmt"%a Js.t"format_enum_namee|TArrayt1->Format.fprintffmt"@[%a@ Js.js_array Js.t@]"format_typ_with_parenst1|TAny->Format.fprintffmt"Js.Unsafe.any Js.t"|TArrow(t1,t2)->Format.fprintffmt"(@[<hov 2>unit, @ %a -> %a@]) Js.meth_callback"(Format.pp_print_list~pp_sep:(funfmt()->Format.pp_print_stringfmt" -> ")format_typ_with_parens)t1format_typ_with_parenst2|TClosureEnv->Format.fprintffmt"Js.Unsafe.any Js.t"letrecformat_to_jsfmttyp=matchMark.removetypwith|TLitTUnit->()|TLitTBool->Format.fprintffmt"Js.bool"|TLitTInt->Format.fprintffmt"integer_to_int"|TLitTRat->Format.fprintffmt"Js.number_of_float %@%@ decimal_to_float"|TLitTMoney->Format.fprintffmt"Js.number_of_float %@%@ money_to_float"|TLitTDuration->Format.fprintffmt"duration_to_js"|TLitTDate->Format.fprintffmt"date_to_js"|TEnumename->Format.fprintffmt"%a_to_js"format_enum_nameename|TStructsname->Format.fprintffmt"%a_to_js"format_struct_namesname|TArrayt->Format.fprintffmt"Js.array %@%@ Array.map (fun x -> %a x)"format_to_jst|TDefaultt->format_to_jsfmtt|TTupletl->letpp_sepfmt()=Format.fprintffmt",@ "inletelts=List.mapi(funit->i,t)tlinFormat.fprintffmt"(fun (%a) -> Js.array [|%a|])"(Format.pp_print_list~pp_sep(funfmt(i,_)->Format.fprintffmt"x%d"i))elts(Format.pp_print_list~pp_sep(funfmt(i,t)->Format.fprintffmt"%a x%d"format_to_jsti))elts|TOptiont->Format.fprintffmt"(function Eoption.ENone () -> Js.null | Eoption.ESome x -> Js.some \
(%a x))"format_to_jst|TAny->Format.fprintffmt"Js.Unsafe.inject"|TArrow_|TClosureEnv->()letrecformat_of_jsfmttyp=matchMark.removetypwith|TLitTUnit->()|TLitTBool->Format.fprintffmt"Js.to_bool"|TLitTInt->Format.fprintffmt"integer_of_int"|TLitTRat->Format.fprintffmt"decimal_of_float %@%@ Js.float_of_number"|TLitTMoney->Format.fprintffmt"money_of_decimal %@%@ decimal_of_float %@%@ Js.float_of_number"|TLitTDuration->Format.fprintffmt"duration_of_js"|TLitTDate->Format.fprintffmt"date_of_js"|TEnumename->Format.fprintffmt"%a_of_js"format_enum_nameename|TStructsname->Format.fprintffmt"%a_of_js"format_struct_namesname|TArrayt->Format.fprintffmt"Array.map (fun x -> %a x) %@%@ Js.to_array"format_of_jst|TDefaultt->format_of_jsfmtt|TTupletl->letpp_sepfmt()=Format.fprintffmt",@ "inletelts=List.mapi(funit->i,t)tlinFormat.fprintffmt"(fun t -> (%a))"(Format.pp_print_list~pp_sep(funfmt(i,t)->Format.fprintffmt"%a (Js.array_get t %d)"format_of_jsti))elts|TOptiont->Format.fprintffmt"(fun o -> Js.Opt.case o (fun () -> Eoption.ENone) (fun x -> \
Eoption.ESome (%a x)))"format_of_jst|TAny->Format.fprintffmt"Js.Unsafe.inject"|TArrow_|TClosureEnv->Format.fprintffmt""letformat_var_camel_case(fmt:Format.formatter)(v:'mVar.t):unit=letlowercase_name=Bindlib.name_ofv|>String.to_camel_case|>Re.Pcre.substitute~rex:(Re.Pcre.regexp"\\.")~subst:(fun_->"_dot_")|>String.uncapitalize_ascii|>avoid_keywordsinifList.memlowercase_name["handle_default";"handle_default_opt"]||String.begins_with_uppercase(Bindlib.name_ofv)thenFormat.fprintffmt"%s"lowercase_nameelseiflowercase_name="_"thenFormat.fprintffmt"%s"lowercase_nameelseFormat.fprintffmt"%s_"lowercase_nameletformat_ctx(type_ordering:Scopelang.Dependency.TVertex.tlist)(fmt:Format.formatter)(ctx:decl_ctx):unit=letformat_prop_or_methfmt(struct_field_type:typ)=matchMark.removestruct_field_typewith|TArrow_->Format.fprintffmt"Js.meth"|_->Format.fprintffmt"Js.readonly_prop"inletformat_struct_declfmt(struct_name,struct_fields)=(* if StructName.path struct_name <> [] then () else *)letfmt_struct_namefmt_=format_struct_namefmtstruct_nameinletfmt_module_struct_namefmt_=To_ocaml.format_to_module_namefmt(`Snamestruct_name)inletfmt_to_jsfmt_=Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt"@\n")(funfmt(struct_field,struct_field_type)->matchMark.removestruct_field_typewith|TArrow(t1,t2)->letargs_names=ListLabels.mapit1~f:(funi_->"function_input"^string_of_inti)inFormat.fprintffmt"@[<hov 2>method %a =@ Js.wrap_meth_callback@ "format_struct_field_name_camel_casestruct_field;Format.fprintffmt"@[<hv 2>(@,fun _ %a ->@ "(Format.pp_print_list(funfmt(arg_i,ti)->Format.fprintffmt"(%s: %a)"arg_iformat_typti))(List.combineargs_namest1);format_to_jsfmtt2;Format.pp_print_stringfmt" (";fmt_struct_namefmt();Format.pp_print_charfmt'.';format_struct_field_namefmt(None,struct_field);Format.pp_print_charfmt' ';Format.pp_print_list(funfmt(i,ti)->Format.fprintffmt"@[<hv 2>(%a@ %a)@]"format_of_jstiFormat.pp_print_stringi)fmt(List.combineargs_namest1);Format.fprintffmt"))@]@]"|_->Format.fprintffmt"@[<hov 2>val %a =@ %a %a.%a@]"format_struct_field_name_camel_casestruct_fieldformat_to_jsstruct_field_typefmt_struct_name()format_struct_field_name(None,struct_field))fmt(StructField.Map.bindingsstruct_fields)inletfmt_of_jsfmt_=Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt";@\n")(funfmt(struct_field,struct_field_type)->matchMark.removestruct_field_typewith|TArrow_->Format.fprintffmt"%a = failwith \"The function '%a' translation isn't yet \
supported...\""format_struct_field_name(None,struct_field)format_struct_field_name(None,struct_field)|_->Format.fprintffmt"@[<hv 2>%a =@ @[<hov 2>%a@ @[<hov>%a@,##.%a@]@]@]"format_struct_field_name(None,struct_field)format_of_jsstruct_field_typefmt_struct_name()format_struct_field_name_camel_casestruct_field)fmt(StructField.Map.bindingsstruct_fields)inletfmt_conv_funsfmt_=Format.fprintffmt"@[<hov 2>let %a_to_js@ (%a@ : %a.t)@ : %a Js.t =@ @[<hv 2>object%%js@\n\
%a@\n\
@]@]end@\n\
@[<hov 2>let %a_of_js@ @[<hov 2>(%a@ : %a Js.t)@] :@ %a.t =@ @[<hv \
2>{@,\
%a@]@\n\
}@]"fmt_struct_name()fmt_struct_name()fmt_module_struct_name()fmt_struct_name()fmt_to_js()fmt_struct_name()fmt_struct_name()fmt_struct_name()fmt_module_struct_name()fmt_of_js()inifStructField.Map.is_emptystruct_fieldsthenFormat.fprintffmt"class type %a =@ object end@\n\
let %a_to_js (_ : %a.t) : %a Js.t = object%%js end@\n\
let %a_of_js (_ : %a Js.t) : %a.t = ()"fmt_struct_name()fmt_struct_name()fmt_module_struct_name()fmt_struct_name()fmt_struct_name()fmt_struct_name()fmt_module_struct_name()elseFormat.fprintffmt"@[<hv 2>class type %a =@ @[<hov 2>object@ %a@]@,end@\n%a@]@\n"fmt_struct_name()(Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt"@\n")(funfmt(struct_field,struct_field_type)->Format.fprintffmt"@[<hov 2>method %a:@ %a %a@]"format_struct_field_name_camel_casestruct_fieldformat_typstruct_field_typeformat_prop_or_methstruct_field_type))(StructField.Map.bindingsstruct_fields)fmt_conv_funs()inletformat_enum_declfmt(enum_name,(enum_cons:typEnumConstructor.Map.t))=(* if EnumName.path enum_name <> [] then () else *)letfmt_enum_namefmt_=format_enum_namefmtenum_nameinletfmt_module_enum_namefmt()=To_ocaml.format_to_module_namefmt(`Enameenum_name)inletfmt_to_jsfmt_=Format.fprintffmt"%a"(Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt"@\n")(funfmt(cname,typ)->Format.fprintffmt"@[<v 2>@[<v 4>| %a arg -> object%%js@\n\
val kind = Js.string \"%a\"@\n\
val payload = Js.Unsafe.coerce (Js.Unsafe.inject (%a arg))@]@\n\
end@]"format_enum_cons_namecnameformat_enum_cons_namecnameformat_to_jstyp))(EnumConstructor.Map.bindingsenum_cons)inletfmt_of_jsfmt_=Format.fprintffmt"@[<hov 2>match@ %a##.kind@ |> Js.to_string@ with@]@\n\
@[<hv>%a@\n\
@[<hv 2>| cons ->@ @[<hov 2>failwith@ @[<hov 2>(Printf.sprintf@ \
\"Unexpected '%%s' kind for the enumeration '%a.t'\"@ cons)@]@]@]@]"fmt_enum_name()(Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt"@\n")(funfmt(cname,typ)->matchMark.removetypwith|TTuple_->Message.error~pos:(Mark.gettyp)"Tuples aren't yet supported in the conversion to JS..."|TLitTUnit->Format.fprintffmt"@[<hv 2>| \"%a\" ->@ %a.%a ()@]"format_enum_cons_namecnamefmt_module_enum_name()format_enum_cons_namecname|_->Format.fprintffmt"| \"%a\" ->@\n%a.%a (%a (Js.Unsafe.coerce %a##.payload))"format_enum_cons_namecnamefmt_module_enum_name()format_enum_cons_namecnameformat_of_jstypfmt_enum_name()))(EnumConstructor.Map.bindingsenum_cons)fmt_module_enum_name()inletfmt_conv_funsfmt_=Format.fprintffmt"@[<hov 2>let %a_to_js@ : %a.t -> %a Js.t@ = function@\n\
%a@]@\n\
@\n\
@[<hov 2>let %a_of_js@ @[<hov 2>(%a@ : %a Js.t)@]@ : %a.t =@ %a@]@\n"fmt_enum_name()fmt_module_enum_name()fmt_enum_name()fmt_to_js()fmt_enum_name()fmt_enum_name()fmt_enum_name()fmt_module_enum_name()fmt_of_js()inFormat.fprintffmt"@[<v 2>class type %a =@ @[<v 2>object@ @[<hov 2>method kind :@ \
Js.js_string Js.t Js.readonly_prop@\n\
@[<v 2>(** Expects one of:@\n\
%a *)@]@]@\n\
@\n\
@[<hov 2>method payload :@ Js.Unsafe.any Js.t Js.readonly_prop@]@]@\n\
end@]@\n\
@\n\
%a@\n"format_enum_nameenum_name(Format.pp_print_list~pp_sep:(funfmt()->Format.fprintffmt"@\n")(funfmt(enum_cons,_)->Format.fprintffmt"- \"%a\""format_enum_cons_nameenum_cons))(EnumConstructor.Map.bindingsenum_cons)fmt_conv_funs()inletis_in_type_orderings=List.exists(funstruct_or_enum->matchstruct_or_enumwith|Scopelang.Dependency.TVertex.Enum_->false|Scopelang.Dependency.TVertex.Structs'->s=s')type_orderinginletscope_structs=List.map(fun(s,_)->Scopelang.Dependency.TVertex.Structs)(StructName.Map.bindings(StructName.Map.filter(funs_->not(is_in_type_orderings))ctx.ctx_structs))inList.iter(funstruct_or_enum->matchstruct_or_enumwith|Scopelang.Dependency.TVertex.Structs->Format.fprintffmt"%a@\n"format_struct_decl(s,StructName.Map.findsctx.ctx_structs)|Scopelang.Dependency.TVertex.Enume->Format.fprintffmt"%a@\n"format_enum_decl(e,EnumName.Map.findectx.ctx_enums))(type_ordering@scope_structs)letfmt_input_struct_namefmt(scope_body:'aexprscope_body)=format_struct_namefmtscope_body.scope_body_input_structletfmt_output_struct_namefmt(scope_body:'aexprscope_body)=format_struct_namefmtscope_body.scope_body_output_structletformat_scopes_to_fun(_ctx:decl_ctx)(fmt:Format.formatter)(scopes:'ecode_item_list)=BoundList.iter~f:(funvarcode_item->matchcode_itemwith|Topdef_->()|ScopeDef(_name,body)->letfmt_fun_callfmt_=Format.fprintffmt"@[<hv>@[<hv 2>execute_or_throw_error@ (@[<hv 2>fun () ->@ %a@ \
|> %a_of_js@ |> %a@ |> %a_to_js@])@]@]"fmt_input_struct_namebodyfmt_input_struct_namebodyformat_varvarfmt_output_struct_namebodyinFormat.fprintffmt"@\n@\n@[<hov 2>let %a@ (%a : %a Js.t)@ : %a Js.t =@\n%a@]@\n"format_varvarfmt_input_struct_namebodyfmt_input_struct_namebodyfmt_output_struct_namebodyfmt_fun_call())scopesletformat_scopes_to_callbacks(_ctx:decl_ctx)(fmt:Format.formatter)(scopes:'ecode_item_list):unit=BoundList.iter~f:(funvarcode_item->matchcode_itemwith|Topdef_->()|ScopeDef(_name,body)->letfmt_meth_namefmt_=Format.fprintffmt"method %a : (%a Js.t -> %a Js.t) Js.callback"format_var_camel_casevarfmt_input_struct_namebodyfmt_output_struct_namebodyinFormat.fprintffmt"@,@[<hov 2>%a =@ Js.wrap_callback@ %a@]@,"fmt_meth_name()format_varvar)scopesletformat_program(fmt:Format.formatter)(module_name:stringoption)(prgm:'mLcalc.Ast.program)(type_ordering:Scopelang.Dependency.TVertex.tlist)=letfmt_lib_namefmt_=Format.fprintffmt"%sLib"(Option.fold~none:""~some:(funname->name|>String.split_on_char'_'|>List.mapString.capitalize_ascii|>String.concat"")module_name)inFormat.fprintffmt"(** This file has been generated by the Catala compiler, do not edit! *)@\n\
@\n\
open Runtime_ocaml.Runtime@\n\
open Runtime_jsoo.Runtime@\n\
open Js_of_ocaml@\n\
%s@\n\
@\n\
[@@@@@@ocaml.warning \"-4-26-27-32-41-42\"]@\n\
@\n\
(* Generated API *)@\n\
@\n\
%a@\n\
%a@\n\
@\n\
@[<v 2>let () =@ @[<hov 2> Js.export \"%a\"@\n\
@[<v 2>(object%%js@ %a@]@\n\
end)@]@]@?"(Option.fold~none:""~some:(funname->"open "^name)module_name)(format_ctxtype_ordering)prgm.decl_ctx(format_scopes_to_funprgm.decl_ctx)prgm.code_itemsfmt_lib_name()(format_scopes_to_callbacksprgm.decl_ctx)prgm.code_itemsendletrunincludesoutputoptimizecheck_invariantsavoid_exceptionsclosure_conversionmonomorphize_types_options=letoptions=Global.enforce_options~trace:true()inletprg,type_ordering=Driver.Passes.lcalcoptions~includes~optimize~check_invariants~avoid_exceptions~closure_conversion~typed:Expr.typed~monomorphize_typesinletjsoo_output_file,with_formatter=Driver.Commands.get_output_formatoptions~ext:"_api_web.ml"outputinwith_formatter(funfmt->Message.debug"Writing JSOO API code to %s..."(Option.value~default:"stdout"jsoo_output_file);letmodname=matchprg.module_namewith|Somem->ModuleName.to_stringm|None->String.capitalize_asciiFilename.(basename(remove_extension(Global.input_src_fileoptions.Global.input_src)))inTo_jsoo.format_programfmt(Somemodname)prgtype_ordering)letterm=letopenCmdliner.Terminconstrun$Cli.Flags.include_dirs$Cli.Flags.output$Cli.Flags.optimize$Cli.Flags.check_invariants$Cli.Flags.avoid_exceptions$Cli.Flags.closure_conversion$Cli.Flags.monomorphize_typeslet()=Driver.Plugin.register"api_web"term~doc:"Catala plugin for generating web APIs. It generates OCaml code before \
the associated [js_of_ocaml] wrapper."