Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file ast_exp_apply.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341(* Copyright (C) 2018 Hongbo Zhang, Authors of ReScript
*
* 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. *)openPpxlibopenAst_helpertypeexp=Parsetree.expressionletrecno_need_bound(exp:exp)=matchexp.pexp_descwith|Pexp_ident{txt=Lident_;_}->true|Pexp_constraint(e,_)->no_need_bounde|_->falseletocaml_obj_id="__ocaml_internal_obj"letbound(e:exp)(cb:exp->_)=ifno_need_boundethencbeelseletloc=e.pexp_locinExp.let_~locNonrecursive[Vb.mk~loc(Pat.var~loc{txt=ocaml_obj_id;loc})e](cb(Exp.ident~loc{txt=Lidentocaml_obj_id;loc}))letcheck_and_discard(args:(arg_label*Parsetree.expression)list)=List.map(fun(label,x)->Error.err_if_label~loc:x.pexp_loclabel;x)argstypeapp_pattern={op:string;loc:Location.t;(* locatoin is the location of whole expression #4451 *)args:Parsetree.expressionlist;}letsane_property_name_checklocs=ifString.containss'#'thenLocation.raise_errorf~loc"property name (%s) can not contain speical character #"sletview_as_app(fn:exp)(s:stringlist):app_patternoption=matchfn.pexp_descwith|Pexp_apply({pexp_desc=Pexp_ident{txt=Lidentop;_};_},args)whenList.memops->Some{op;loc=fn.pexp_loc;args=check_and_discardargs}|_->Noneletinner_ops=["##";"#@"]letinfix_ops=["|.";"#=";"##"]letrecexclude_with_val=letrecexclude(xs:'alist)(p:'a->bool):'alist=matchxswith|[]->[]|x::xs->ifpxthenexcludexspelsex::excludexspinfunlp->matchlwith|[]->None|a0::xs->(ifpa0thenSome(excludexsp)elsematchxswith|[]->None|a1::rest->(ifpa1thenSome(a0::excluderestp)elsematchexclude_with_valrestpwith|None->None|Somerest->Some(a0::a1::rest)))letapp_exp_mapper(e:exp)((self,super):Ast_traverse.map*(Parsetree.expression->Parsetree.expression))(fn:exp)(args:Ast_util.args):exp=(* - (f##paint) 1 2
- (f#@paint) 1 2
*)matchview_as_appfninner_opswith|Some{op;loc;args=[obj;{pexp_desc=Pexp_ident{txt=Lidentname;_};_}];}->{ewithpexp_desc=(ifop="##"thenAst_uncurry_apply.method_applylocselfobjnameargselseAst_uncurry_apply.property_applylocselfobjnameargs);}|Some{op;loc;_}->Location.raise_errorf~loc"%s expect f%sproperty arg0 arg2 form"opop|None->(matchview_as_appeinfix_opswith|Some{op="|.";args=[a_;f_];loc}->((*
a |. f
a |. f b c [@bs] --> f a b c [@bs]
a |. M.(f b c) --> M.f a M.b M.c
a |. (g |. b)
a |. M.Some
a |. `Variant
a |. (b |. f c [@bs])
*)leta=self#expressiona_inletf=self#expressionf_inmatchf.pexp_descwith|Pexp_variant(label,None)->{fwithpexp_desc=Pexp_variant(label,Somea);pexp_loc=e.pexp_loc;}|Pexp_construct(ctor,None)->{fwithpexp_desc=Pexp_construct(ctor,Somea);pexp_loc=e.pexp_loc;}|Pexp_apply(fn1,args)->Bs_ast_invariant.warn_discarded_unused_attributesfn1.pexp_attributes;{pexp_desc=Pexp_apply({fn1withpexp_attributes=fn1.pexp_attributes},(Nolabel,a)::args);pexp_loc=e.pexp_loc;pexp_loc_stack=e.pexp_loc_stack;pexp_attributes=e.pexp_attributes;}|_->(matchAst_open_cxt.destructf[]with|({pexp_desc=Pexp_tuplexs;pexp_attributes=tuple_attrs;_},wholes)->Ast_open_cxt.restore_exp(bounda(funbounded_obj_arg->{pexp_desc=Pexp_tuple(List.map(funfn->matchfn.pexp_descwith|Pexp_construct(ctor,None)->{fnwithpexp_desc=Pexp_construct(ctor,Somebounded_obj_arg);}|Pexp_apply(fn,args)->Bs_ast_invariant.warn_discarded_unused_attributesfn.pexp_attributes;{Parsetree.pexp_desc=Pexp_apply({fnwithpexp_attributes=[]},(Nolabel,bounded_obj_arg)::args);pexp_attributes=[];pexp_loc_stack=fn.pexp_loc_stack;pexp_loc=fn.pexp_loc;}|_->letloc=fn.pexp_locin[%expr[%efn][%ebounded_obj_arg]])xs);pexp_attributes=tuple_attrs;pexp_loc=f.pexp_loc;pexp_loc_stack=f.pexp_loc_stack;}))wholes|({pexp_desc=Pexp_apply(e,args);pexp_attributes;_},(_::_aswholes))->letfn=Ast_open_cxt.restore_expewholesinletargs=List.map(fun(lab,exp)->(lab,Ast_open_cxt.restore_expexpwholes))argsinBs_ast_invariant.warn_discarded_unused_attributespexp_attributes;{pexp_desc=Pexp_apply(fn,(Nolabel,a)::args);pexp_attributes;pexp_loc=loc;pexp_loc_stack=[];}|_->(match(exclude_with_valf_.pexp_attributesAst_attributes.is_bs,f_.pexp_desc)with|Someother_attributes,Pexp_apply(fn1,args)->(* a |. f b c [@bs]
Cannot process uncurried application early as the arity is wip *)letfn1=self#expressionfn1inletargs=args|>List.map(fun(l,e)->(l,self#expressione))inBs_ast_invariant.warn_discarded_unused_attributesfn1.pexp_attributes;{pexp_desc=Ast_uncurry_apply.uncurry_fn_applye.pexp_locselffn1((Nolabel,a)::args);pexp_loc=e.pexp_loc;pexp_loc_stack=e.pexp_loc_stack;pexp_attributes=e.pexp_attributes@other_attributes;}|_->Ast_helper.Exp.apply~loc~attrs:e.pexp_attributesf[(Nolabel,a)])))|Some{op="##";loc;args=[obj;rest]}->((* - obj##property
- obj#(method a b )
we should warn when we discard attributes
gpr#1063 foo##(bar##baz) we should rewrite (bar##baz)
first before pattern match.
currently the pattern match is written in a top down style.
Another corner case: f##(g a b [@bs])
*)matchrestwith|{pexp_desc=Pexp_apply({pexp_desc=Pexp_ident{txt=Lidentname;_};_},args);pexp_attributes=attrs;_;}->Bs_ast_invariant.warn_discarded_unused_attributesattrs;{ewithpexp_desc=Ast_uncurry_apply.method_applylocselfobjnameargs;}|{pexp_desc=(Pexp_ident{txt=Lidentname;_}|Pexp_constant(Pconst_string(name,_,None)));pexp_loc;_;}(* f##paint *)->sane_property_name_checkpexp_locname;{ewithpexp_desc=Ast_util.js_propertyloc(self#expressionobj)name;}|_->[%expr[%ocaml.error[%eExp.constant(Pconst_string("invalid ## syntax",loc,None))]]])(* we can not use [:=] for precedece cases
like {[i @@ x##length := 3 ]}
is parsed as {[ (i @@ x##length) := 3]}
since we allow user to create Js objects in OCaml, it can be of
ref type
{[
let u = object (self)
val x = ref 3
method setX x = self##x := 32
method getX () = !self##x
end
]}
*)|Some{op="#=";loc;args=[obj;arg]}->(matchview_as_appobj["##"]with|Some{args=[obj;{pexp_desc=(Pexp_ident{txt=Lidentname;_}|Pexp_constant(Pconst_string(name,_,None)));pexp_loc;_;};];_;}->sane_property_name_checkpexp_locname;Exp.constraint_~loc{ewithpexp_desc=Ast_uncurry_apply.method_applylocselfobj(name^Literals.setter_suffix)[(Nolabel,arg)];}[%type:unit]|_->assertfalse)|Some{op="|.";loc;_}->Location.raise_errorf~loc"invalid |. syntax, it can only be used as binary operator"|Some{op="##";loc;_}->Location.raise_errorf~loc"Js object ## expect syntax like obj##(paint (a,b)) "|Some{op;_}->Location.raise_errorf"invalid %s syntax"op|None->(matchexclude_with_vale.pexp_attributesAst_attributes.is_bswith|None->supere|Somepexp_attributes->{ewithpexp_desc=Ast_uncurry_apply.uncurry_fn_applye.pexp_locselffnargs;pexp_attributes;}))