123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398openBaseopenPrintfopenPpxQtCfgopenGencppopenPpxlibopenPpxlib.Ast_builder.DefaultopenTypeReprletmake_coretyp~loctxt=Ast_helper.Typ.constr~loc{txt;loc}[]letcppobj_coretyploc=make_coretyp~loc(Lident"cppobj")letunit_coretyploc=make_coretyp~loc(Lident"unit")letint_coretyploc=make_coretyp~loc(Lident"int")letstring_coretyploc=make_coretyp~loc(Lident"string")letmake_store_func~loc~classname:structure_item=letpval_prim=[sprintf"caml_store_value_in_%s"classname]inletpval_type=[%type:tLablqml.cppobj->[%tptyp_object~loc[]Open]->[%tptyp_constr~loc{txt=Lident"unit";loc}[]]]inpstr_primitive~loc@@value_description~loc~name:(Located.mk~loc"store")~type_:pval_type~prim:pval_primletmake_stub_general~loc~types~name~stub_name=letrechelper=function|[]->assertfalse|[t]->t|txt::xs->[%type:[%ttxt]->[%thelperxs]]inlettype_=helpertypesinpstr_primitive~loc@@value_description~loc~name:(Located.mk~locname)~type_~prim:[stub_name]letmake_creator~loc~classname=pstr_primitive~loc@@value_description~loc~name:(Located.mk~loc@@sprintf"create_%s"classname)~type_:[%type:unit->'a]~prim:[sprintf"caml_create_%s"classname]letmake_stub_for_signal~classname~loc~typname:structure_item=pstr_primitive~loc@@value_description~loc~name:(Located.mk~loc@@sprintf"stub_%s"name)~type_:[%type:_Lablqml.cppobj->[%ttyp]->unit]~prim:[sprintf"caml_%s_%s_cppmeth_wrapper"classnamename]letmake_virt_meth~loc~namexs=letrechelper=function|[]->assertfalse|[t]->ptyp_constr~loc{txt=TypeRepr.ocaml_ast_of_typt;loc}[]|t::xs->[%type:[%tptyp_constr~loc(Located.mk~loc@@TypeRepr.ocaml_ast_of_typt)[]]->[%thelperxs]]inlettyp=helperxsinpcf_method~loc(Located.mkname~loc,Public,Cfk_virtualtyp)letmklocxloc=Located.mk~locxletmake_initializer~loc:class_field=pcf_initializer~loc[%exprstorecppobjself]letmake_handler_meth~loc:class_field=lete=[%exprcppobj]inpcf_method~loc(Located.mk"handler"~loc,Public,Cfk_concrete(Fresh,e))leteval_meth_typt=matchTypeRepr.eval_meth_typ_gentwith|Result.Okxs->List.map~f:sndxs|Error(msg,typ)->raise@@ErrorMsg(msg,typ)leteval_signal_typt=matchTypeRepr.eval_meth_typ_gentwith|Result.Okxs->xs|Error(msg,typ)->raise@@ErrorMsg(msg,typ)letcheck_meth_typ~loc_xs=let_=locin(* TODO: some checks like unit type should be at the end of list *)(* TODO: check that modelindexes are not used without QAbstractItemModel base *)trueletwrap_meth~classname(* ?(options = []) *)(({txt=methname;loc},_,kind)asm)=matchkindwith|Cfk_concrete_->raise@@ErrorMsg("Qt methods should be marked as virtual",loc)|Cfk_virtualtyp->letmeth_typ=eval_meth_typtypinifnot(check_meth_typ~locmeth_typ)thenraise@@ErrorMsg(sprintf"Method '%s' has wrong type"methname,loc);let()=ifPpxQtCfg.config.gencppthen(* let options =
if Options.is_itemmodel options then [ OItemModel ] else []
in *)Gencpp.gen_meth(*~options*)~classname~methname(meth_typ:>Arg.non_cppobjArg.tlist)in[pcf_method~locm](*
(* in 4.03 definition have changed from string to Ast_types.arg_label *)
let oldify_arg_label = function
| Nolabel -> ""
| Labelled s -> s
| Optional s -> s
;; *)moduleOfClass=structletrun~attributesloc(ci:class_declaration)=(* print_endline "wrap_class_type_decl on class type markend with `qtclass`"; *)letclassname=ci.pci_name.txtinletoptions=List.concat[(ifhas_attr"itemmodel"attributesthen[OItemModel]else[]);(ifhas_attr"instantiable"attributesthen[OInstantiable]else[]);]inifPpxQtCfg.config.gencppthenGencpp.open_files~options~classname;letclas_sig=matchci.pci_expr.pcl_descwith|Pcl_structures->s|_->raise@@ErrorMsg("Qt class signature should be structure of class",ci.pci_loc)inletfields:class_fieldlist=clas_sig.pcstr_fieldsinletheading=ref[[%stritypet];make_store_func~classname~loc]inletwrap_signal~options~classname(({txt=signalname;loc},_,kind)as_m)=let_=optionsinmatchkindwith|Cfk_concrete_->raise@@ErrorMsg("We can generate prop methods for virtuals only",loc)|Cfk_virtualcore_typ->(* stub which will be called by OCaml meth*)letexternal_stub=letopenAst_builder.Defaultinpstr_primitive~loc@@value_description~loc~name:(Located.mk~loc@@sprintf"stub_%s"signalname)~type_:[%type:tLablqml.cppobj->[%tcore_typ]]~prim:[sprintf"caml_%s_%s_emitter_wrapper"classnamesignalname]inGencpp.ref_append~set:headingexternal_stub;(* C++ stub *)lettypes=eval_signal_typcore_typinletargs,res=List.(drop_last_exntypes,last_exntypes)inifStdlib.(sndres<>TypeRepr.Arg.Unit)thenraise@@ErrorMsg("Result type for signal should be unit",loc);assert(Stdlib.(fstres=Nolabel));(* last argument always will be without a label, isn't it? *)ifList.exists~f:(fun(label,_)->Stdlib.(=)labelNolabel)argsthenraise@@ErrorMsg("All arguments should have a label",loc);ifconfig.gencppthenGencpp.gen_signal~classname~signalname@@List.map~f:(fun(l,x)->(l,(x:>Arg.non_cppobjArg.t)))args;(* OCaml meth *)lete=pexp_poly~loc(pexp_apply~loc(pexp_ident~loc(Located.mk~loc(Lident("stub_"^signalname))))[(Nolabel,[%exprself#handler])])Nonein[pcf_method~loc(Located.mk~loc("emit_"^signalname),Public,Cfk_concrete(Fresh,e));]inletwrap_prop~classname(loc,flag,kind)=letpropname=loc.txtinletloc=loc.locinmatchkindwith|Cfk_concrete_->raise@@ErrorMsg("We can generate prop methods for virtuals only",loc)|Cfk_virtualcore_typ->(matchtype_suits_propcore_typwith|Oktyp->ifconfig.gencppthenGencpp.gen_prop~classname~propnametyp;letsignal_name=Names.signal_of_proppropnameinref_append~set:heading(make_stub_for_signal~classname~loc~typ:core_typsignal_name);lete=pexp_poly~loc(pexp_apply~loc(pexp_ident~loc(Located.mk~loc@@lident("stub_"^signal_name)))[(Nolabel,[%exprself#handler])])Nonein[pcf_method~loc(Located.mk~loc("emit_"^signal_name),Public,Cfk_concrete(Fresh,e));pcf_method~loc(Located.mk~loc(Gencpp.Names.getter_of_proppropname),flag,Cfk_virtualAst_helper.Typ.(arrowNolabel(unit_coretyploc)core_typ));]|Errormsg->raise@@ErrorMsg(sprintf"Can't wrap property '%s': %s"propnamemsg,loc))inletwrap_field(f_desc:class_field):class_fieldlist=matchf_desc.pcf_descwith|Pcf_methodmwhenhas_attr"qtmeth"f_desc.pcf_attributes->wrap_meth~classnamem|Pcf_methodmwhenhas_attr"qtsignal"f_desc.pcf_attributes->wrap_signal~options~classnamem|Pcf_methodmwhenhas_attr"qtprop"f_desc.pcf_attributes->wrap_prop~classnamem|_->[]inletocaml_typ_of_typcppobj_param=letopenTypeRepr.Arginletrechelper=function|Cppobj->ptyp_constr~loc(Located.mk~loc@@Ldot(Lident"Lablqml","cppobj"))[cppobj_param]|QVariant->[%type:QVariant.t]|QModelIndex->[%type:QModelIndex.t]|Bool->[%type:bool]|Unit->[%type:unit]|QByteArray|QString->[%type:string]|Int->[%type:int]|QListx->ptyp_constr~loc(Located.mk~loc@@Lident"list")[helperx]inhelperinletitemmodel_meths=ifhas_attr"itemmodel"attributesthen(letf(methname,meth_typ,minfo)=(* printf "Generating itemmodel-specific meth: '%s'\n" methname; *)ifconfig.gencppthenGencpp.gen_meth~classname~methname~minfometh_typinifconfig.gencppthenList.iter~fGencpp.itemmodel_members;(* now add some OCaml code *)letf(name,stub_name,xs)=lettypes=List.mapxs~f:(ocaml_typ_of_typ[%type:t])inref_append~set:heading@@make_stub_general~loc~types~name:("stub_"^name)~stub_nameinList.iter(Gencpp.itemmodel_externals~classname)~f;let()=ifconfig.gencppthenGencpp.gen_itemmodel_stuff~classnameinletadd_role_stub=letname=Located.mk~loc"add_role"inletprim=[sprintf"caml_%s_%s_cppmeth_wrapper"classname"addRole"]inlettype_=[%type:'a->int->string->unit]inAst_builder.Default.pstr_primitive~loc@@Ast_builder.Default.value_description~loc~name~type_~priminref_appendadd_role_stub~set:heading;letemitters=List.map["dataChanged";"beginInsertRows";"endInsertRows";"beginRemoveRows";"endRemoveRows";]~f:(funname->lete=pexp_poly~loc(pexp_apply~loc(pexp_ident~loc@@Located.mk~loc@@Lident("stub_"^name))[(Nolabel,[%exprcppobj])])Noneinpcf_method~loc(mklocnameloc,Public,Cfk_concrete(Fresh,e)))inletvirtuals=[make_virt_meth[Arg.QModelIndex;Arg.QModelIndex]~loc~name:"parent";make_virt_meth[Arg.Int;Arg.Int;Arg.QModelIndex;Arg.QModelIndex]~loc~name:"index";make_virt_meth[Arg.QModelIndex;Arg.Int]~loc~name:"columnCount";make_virt_meth[Arg.QModelIndex;Arg.Int]~loc~name:"rowCount";make_virt_meth[Arg.QModelIndex;Arg.Bool]~loc~name:"hasChildren";make_virt_meth[Arg.QModelIndex;Arg.Int;Arg.QVariant]~loc~name:"data";]inemitters@virtuals)else[]inletnew_fields=List.concat_mapfields~f:wrap_field@itemmodel_methsinletnew_fields=make_initializer~loc::make_handler_meth~loc::new_fieldsinletnew_expr=letopenAst_builder.Defaultinpcl_fun~locNolabelNone[%pat?cppobj]@@pcl_structure~loc@@class_structure~self:[%pat?self]~fields:new_fieldsinletans=pstr_class~loc[{ciwithpci_expr=new_expr}]inletcreator=make_creator~loc~classnameinifconfig.gencppthenGencpp.close_files~options();!heading@[ans;creator]endlet()=Ppxlib.Driver.register_transformation~impl:(funss->letm=object(self)inheritAst_traverse.mapassupermethod!structuress=(* TODO: Maybe we don't need this *)List.concat@@List.map~f:self#do_structure_itemssmethoddo_structure_itemsi=letans=letopenAst_patterninparse(alt(pstr_module@@module_binding~name:(some__)~expr:(pmod_constraint(pmod_attributes__@@pmod_structure__)(pmty_signature__))|>pack3|>map2~f:(fun(name,attrs,stru)sign->matchfind_attr~name:"qml"attrswith|Some(PStr[{pstr_desc=Pstr_eval(e,_)}])->(matchMyparser.Testdemo.parse_singletonewith|None->raise(ErrorMsg("bad attribute",si.pstr_loc))|Someinfo->Generation2.wrap_module_decl~loc:si.pstr_locnamestrusigninfo)|Some_->raise(ErrorMsg(sprintf"bad attribute %s %d"__FILE____LINE__,si.pstr_loc))|None->[super#structure_itemsi]))(pstr_class(__^::nil)|>map1~f:(funcinfo->ifhas_attr"qtclass"cinfo.pci_attributesthenAst_helper.with_default_locsi.pstr_loc(fun()->OfClass.run~attributes:cinfo.pci_attributessi.pstr_loccinfo)else[super#structure_itemsi])))si.pstr_loc~on_error:(fun()->[super#structure_itemsi])siFun.idinansendinm#structuress)"ppx_qt"