123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition to the permissions granted to you by the LGPL, you may combine
* or link a "work that uses the Library" with a publicly distributed version
* of this file to produce a combined library or application, then distribute
* that combined work under the terms of your choosing, with no requirement
* to comply with the obligations normally placed on you by section 4 of the
* LGPL version 3 (or the corresponding section of a later version of the LGPL
* should you choose to use a later version).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)openPpxlibtypeattr=Parsetree.attributetypet=attrlisttype('a,'b)st={get:'aoption;set:'boption}letassert_bool_lit(e:Parsetree.expression)=matche.pexp_descwith|Pexp_construct({txt=Lident"true";_},None)->true|Pexp_construct({txt=Lident"false";_},None)->false|_->Location.raise_errorf~loc:e.pexp_loc"expect `true` or `false` in this field"letwarn_if_bs~loctxt=matchtxtwith|"bs"->Bs_ast_invariant.warn~locDeprecated_uncurry_attribute|other->ifString.starts_with~prefix:"bs."otherthenBs_ast_invariant.warn~locDeprecated_attribute_namespaceletprocess_method_attributes_rev(attrs:t)=letexceptionLocalofstringintryletret=List.fold_left(fun(st,acc)({attr_name={txt;loc};attr_payload=payload;_}asattr)->warn_if_bs~loctxt;matchtxtwith|"mel.get"|"bs.get"|"get"(* @bs.get{null; undefined}*)->letresult=matchAst_payload.ident_or_record_as_configpayloadwith|Errors->raise(Locals)|Okconfig->List.fold_left(fun(null,undefined)({txt;loc},opt_expr)->matchtxtwith|"null"->((matchopt_exprwith|None->true|Somee->assert_bool_lite),undefined)|"undefined"->(null,matchopt_exprwith|None->true|Somee->assert_bool_lite)|"nullable"->(matchopt_exprwith|None->(true,true)|Somee->letv=assert_bool_litein(v,v))|_->Error.err~locUnsupported_predicates)(false,false)configin({stwithget=Someresult},acc)|"mel.set"|"bs.set"|"set"->letresult=matchAst_payload.ident_or_record_as_configpayloadwith|Errors->raise(Locals)|Okconfig->List.fold_left(fun_st({txt;loc},opt_expr)->(*FIXME*)iftxt="no_get"thenmatchopt_exprwith|None->`No_get|Somee->ifassert_bool_litethen`No_getelse`GetelseError.err~locUnsupported_predicates)`Getconfigin(* properties -- void
[@@set{only}]
*)({stwithset=Someresult},acc)|_->(st,attr::acc))({get=None;set=None},[])attrsinOkretwithLocals->Errorstypeattr_kind=|Nothing|Meth_callbackofattr|Uncurryofattr|Methodofattrletprocess_attributes_rev(attrs:t):attr_kind*t=List.fold_left(fun(st,acc)({attr_name={txt;loc};_}asattr)->warn_if_bs~loctxt;match(txt,st)with|("u"|"bs"),(Nothing|Uncurry_)->(Uncurryattr,acc)(* TODO: warn unused/duplicated attribute *)|("mel.this"|"bs.this"|"this"),(Nothing|Meth_callback_)->(Meth_callbackattr,acc)|("mel.meth"|"bs.meth"|"meth"),(Nothing|Method_)->(Methodattr,acc)|("u"|"bs"|"mel.this"|"bs.this"|"this"),_->Error.err~locConflict_u_mel_this_mel_meth|_,_->(st,attr::acc))(Nothing,[])attrsletprocess_pexp_fun_attributes_rev(attrs:t)=List.fold_left(fun(st,acc)({attr_name={txt;loc};_}asattr)->warn_if_bs~loctxt;matchtxtwith|"mel.open"|"bs.open"->(true,acc)|_->(st,attr::acc))(false,[])attrsletprocess_bs(attrs:t)=List.fold_left(fun(st,acc)({attr_name={txt;loc};_}asattr)->warn_if_bs~loctxt;match(txt,st)with|("u"|"bs"),_->(true,acc)|_,_->(st,attr::acc))(false,[])attrsletis_bs(attr:attr)=matchattrwith|{attr_name={Location.txt="u"|"bs";_};_}->true|_->falseletbs_get:attr={attr_name={txt="mel.get";loc=Location.none};attr_payload=Parsetree.PStr[];attr_loc=Location.none;}letbs_get_index:attr={attr_name={txt="mel.get_index";loc=Location.none};attr_payload=Parsetree.PStr[];attr_loc=Location.none;}letbs_get_arity:attr={attr_name={txt="internal.arity";loc=Location.none};attr_payload=PStr[{pstr_desc=Pstr_eval({pexp_loc=Location.none;pexp_loc_stack=[];pexp_attributes=[];pexp_desc=Pexp_constant(Pconst_integer(string_of_int1,None));},[]);pstr_loc=Location.none;};];attr_loc=Location.none;}letbs_set:attr={attr_name={txt="mel.set";loc=Location.none};attr_payload=PStr[];attr_loc=Location.none;}letinternal_expansive:attr={attr_name={txt="internal.expansive";loc=Location.none};attr_payload=PStr[];attr_loc=Location.none;}letbs_return_undefined:attr={attr_name={txt="mel.return";loc=Location.none};attr_payload=PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_ident{txt=Lident"undefined_to_opt";loc=Location.none};pexp_loc=Location.none;pexp_loc_stack=[];pexp_attributes=[];},[]);pstr_loc=Location.none;};];attr_loc=Location.none;}typeas_const_payload=Intofint|Strofstring|Js_literal_strofstringletiter_process_bs_string_or_int_as(attrs:Parsetree.attributes)=letst=refNoneinList.iter(fun({attr_name={txt;loc};attr_payload=payload;_}asattr)->matchtxtwith|"mel.as"|"bs.as"|"as"->if!st=Nonethen(Bs_ast_invariant.mark_used_bs_attributeattr;matchAst_payload.is_single_intpayloadwith|None->(matchpayloadwith|PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant(Pconst_string(s,_,((None|Some"json")asdec)));pexp_loc;_;},_);_;};]->ifdec=Nonethenst:=Some(Strs)else((matchClassify_function.classify~check:(pexp_loc,Bs_flow_ast_utils.flow_deli_offsetdec)swith|Js_literal_->()|_->Location.raise_errorf~loc:pexp_loc"an object literal expected");st:=Some(Js_literal_strs))|_->Error.err~locExpect_int_or_string_or_json_literal)|Somev->st:=Some(Intv))elseError.err~locDuplicated_mel_as|_->())attrs;!st(* duplicated @uncurry @string not allowed,
it is worse in @uncurry since it will introduce
inconsistency in arity
*)letiter_process_bs_string_int_unwrap_uncurry(attrs:t)=letst=ref`Nothinginletassignv({attr_name={loc;_};_}asattr:attr)=if!st=`Nothingthen(Bs_ast_invariant.mark_used_bs_attributeattr;st:=v)elseError.err~locConflict_attributesinList.iter(fun({attr_name={txt;loc};attr_payload=payload;_}asattr)->warn_if_bs~loctxt;matchtxtwith|"mel.string"|"bs.string"|"string"->assign`Stringattr|"mel.int"|"bs.int"|"int"->assign`Intattr|"mel.ignore"|"bs.ignore"|"ignore"->assign`Ignoreattr|"mel.unwrap"|"bs.unwrap"|"unwrap"->assign`Unwrapattr|"mel.uncurry"|"bs.uncurry"|"uncurry"->assign(`Uncurry(Ast_payload.is_single_intpayload))attr|_->())attrs;!stletiter_process_bs_string_as(attrs:t):stringoption=letst=refNoneinList.iter(fun({attr_name={txt;loc};attr_payload=payload;_}asattr)->matchtxtwith|"mel.as"|"bs.as"|"as"->if!st=Nonethen(matchAst_payload.is_single_stringpayloadwith|None->Error.err~locExpect_string_literal|Some(v,_dec)->Bs_ast_invariant.mark_used_bs_attributeattr;st:=Somev)elseError.err~locDuplicated_mel_as|_->())attrs;!stletexternal_attrs=[|"get";"set";"get_index";"return";"obj";"val";"module";"scope";"variadic";"send";"new";"set_index";Literals.gentype_import;|]letfirst_char_special(x:string)=matchString.unsafe_getx0with|'#'|'?'|'%'->true|_->(* XXX(anmonteiro): Upstream considers "builtin" attributes ones that
start with `?`. We keep the original terminology of `caml_` (and,
incidentally, `nativeint_`). *)String.starts_withx~prefix:"caml_"||String.starts_withx~prefix:"nativeint_"letfirst_marshal_char(x:string)=x<>""&&String.unsafe_getx0='\132'letprims_to_be_encoded(attrs:stringlist)=matchattrswith|[]->assertfalse(* normal val declaration *)|x::_whenfirst_char_specialx->false|_::x::_whenfirst_marshal_charx->false|_->true(**
[@@inline]
let a = 3
[@@inline]
let a : 3
They are not considered externals, they are part of the language
*)letrs_externals(attrs:t)pval_prim=match(attrs,pval_prim)with|_,[]->false(* This is val *)|[],_->(* No attributes found *)prims_to_be_encodedpval_prim|_,_->List.exists(fun{attr_name={txt;loc=_};_}->String.starts_withtxt~prefix:"bs."||String.starts_withtxt~prefix:"mel."||Array.exists(fun(x:string)->txt=x)external_attrs)attrs||prims_to_be_encodedpval_primletiter_process_bs_int_as(attrs:t)=letst=refNoneinList.iter(fun({attr_name={txt;loc};attr_payload=payload;_}asattr)->warn_if_bs~loctxt;matchtxtwith|"mel.as"|"bs.as"|"as"->if!st=Nonethen(matchAst_payload.is_single_intpayloadwith|None->Error.err~locExpect_int_literal|Some_asv->Bs_ast_invariant.mark_used_bs_attributeattr;st:=v)elseError.err~locDuplicated_mel_as|_->())attrs;!stlethas_bs_optional(attrs:t):bool=List.exists(fun({attr_name={txt;loc};_}asattr)->warn_if_bs~loctxt;matchtxtwith|"mel.optional"|"bs.optional"|"optional"->Bs_ast_invariant.mark_used_bs_attributeattr;true|_->false)attrsletis_inline:attr->bool=fun{attr_name={txt;loc};_}->warn_if_bs~loctxt;txt="mel.inline"||txt="bs.inline"||txt="inline"lethas_inline_payload(attrs:t)=List.find_optis_inlineattrsletis_mel_as:attr->bool=fun{attr_name={txt;loc};_}->warn_if_bs~loctxt;txt="mel.as"||txt="bs.as"||txt="as"lethas_mel_as_payload(attrs:t)=List.find_optis_mel_asattrs(* We disable warning 61 in Melange externals since they're substantially
different from OCaml externals. This warning doesn't make sense for a JS
runtime *)letunboxable_type_in_prim_decl:Parsetree.attribute=letopenAst_helperin{attr_name={txt="ocaml.warning";loc=Location.none};attr_payload=PStr[Str.eval(Exp.constant(Pconst_string("-unboxable-type-in-prim-decl",Location.none,None)));];attr_loc=Location.none;}