123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505(*
* This file is part of Bolt.
* Copyright (C) 2009-2012 Xavier Clerc.
*
* Bolt 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.
*
* Bolt 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, see <http://www.gnu.org/licenses/>.
*)(* Definitions *)letmagic_trace="Paje trace\000(magic\001)"letmagic_kind="Paje kind\000(magic\001)"lett=magic_tracelet()=Utils.paje_t:=ttypeproperties=(string*string)listtypename=stringtypealias=stringtypecolor=float*float*floatletstring_of_color(r,g,b)=Printf.sprintf"%f %f %f"rgbtypefield_type=|Date(* | Int not used *)|Double(* | Hex not used *)|String|Colorletstring_of_field_type=function|Date->"date"(* | Int -> "int" not used *)|Double->"double"(* | Hex -> "hex" not used *)|String->"string"|Color->"color"typeevent={event_name:string;event_id:int;event_fields:(string*field_type)list;}(* The type of event definitions. *)letstring_of_eventev=letfield_def(nam,typ)=Printf.sprintf"%%\t%s\t%s"nam(string_of_field_typetyp)in((Printf.sprintf"%%EventDef\t%s\t%d"ev.event_nameev.event_id)::(List.mapfield_defev.event_fields))@["%EndEventDef"]letevent_def=letid=ref0infunnamel->incrid;{event_name=name;event_id=!id;event_fields=l;}letpredefined_events=[event_def"PajeDefineContainerType"["Name",String;"Type",String;"Alias",String];event_def"PajeDefineStateType"["Name",String;"Type",String;"Alias",String];event_def"PajeDefineEventType"["Name",String;"Type",String;"Alias",String];event_def"PajeDefineVariableType"["Name",String;"Type",String;"Color",Color;"Alias",String];event_def"PajeDefineLinkType"["Name",String;"Type",String;"StartContainerType",String;"EndContainerType",String;"Alias",String];event_def"PajeDefineEntityValue"["Name",String;"Type",String;"Color",Color;"Alias",String];event_def"PajeCreateContainer"["Time",Date;"Name",String;"Type",String;"Container",String;"Alias",String];event_def"PajeDestroyContainer"["Time",Date;"Name",String;"Type",String];event_def"PajeSetState"["Time",Date;"Type",String;"Container",String;"Value",String];event_def"PajePushState"["Time",Date;"Type",String;"Container",String;"Value",String];event_def"PajePopState"["Time",Date;"Type",String;"Container",String];event_def"PajeResetState"["Time",Date;"Type",String;"Container",String];event_def"PajeNewEvent"["Time",Date;"Type",String;"Container",String;"Value",String];event_def"PajeSetVariable"["Time",Date;"Type",String;"Container",String;"Value",Double];event_def"PajeAddVariable"["Time",Date;"Type",String;"Container",String;"Value",Double];event_def"PajeSubVariable"["Time",Date;"Type",String;"Container",String;"Value",Double];event_def"PajeStartLink"["Time",Date;"Type",String;"Container",String;"StartContainer",String;"Value",String;"Key",String];event_def"PajeEndLink"["Time",Date;"Type",String;"Container",String;"EndContainer",String;"Value",String;"Key",String]](* Predefined events: type definitions *)letdefine_container_type~name?(typ="0")?(alias=name)l=[magic_kind,"PajeDefineContainerType";"Name",name;"Type",typ;"Alias",alias]@lletdefine_state_type~name~typ?(alias=name)l=[magic_kind,"PajeDefineStateType";"Name",name;"Type",typ;"Alias",alias]@lletdefine_event_type~name~typ?(alias=name)l=[magic_kind,"PajeDefineEventType";"Name",name;"Type",typ;"Alias",alias]@lletdefine_variable_type~name~typ~color?(alias=name)l=[magic_kind,"PajeDefineVariableType";"Name",name;"Type",typ;"Color",string_of_colorcolor;"Alias",alias]@lletdefine_link_type~name~typ~start_container_type~end_container_type?(alias=name)l=[magic_kind,"PajeDefineLinkType";"Name",name;"Type",typ;"StartContainerType",start_container_type;"EndContainerType",end_container_type;"Alias",alias]@lletdefine_entity_value~name~typ~color?(alias=name)l=[magic_kind,"PajeDefineEntityValue";"Name",name;"Type",typ;"Color",string_of_colorcolor;"Alias",alias]@l(* Predefined events: trace recording *)letcreate_container~name~typ?(container="0")?(alias=name)l=[magic_kind,"PajeCreateContainer";"Name",name;"Alias",alias;"Type",typ;"Container",container]@lletdestroy_container~name~typl=[magic_kind,"PajeDestroyContainer";"Name",name;"Type",typ]@lletset_state~typ~container~valuel=[magic_kind,"PajeSetState";"Type",typ;"Container",container;"Value",value]@lletpush_state~typ~container~valuel=[magic_kind,"PajePushState";"Type",typ;"Container",container;"Value",value]@lletpop_state~typ~containerl=[magic_kind,"PajePopState";"Type",typ;"Container",container]@lletreset_state~typ~containerl=[magic_kind,"PajeResetState";"Type",typ;"Container",container]@lletnew_event~typ~container~valuel=[magic_kind,"PajeNewEvent";"Type",typ;"Container",container;"Value",value]@lletset_variable~typ~container~valuel=[magic_kind,"PajeSetVariable";"Type",typ;"Container",container;"Value",string_of_floatvalue]@lletadd_variable~typ~container~valuel=[magic_kind,"PajeAddVariable";"Type",typ;"Container",container;"Value",string_of_floatvalue]@lletsub_variable~typ~container~valuel=[magic_kind,"PajeSubVariable";"Type",typ;"Container",container;"Value",string_of_floatvalue]@lletstart_link~typ~container~start_container~value~keyl=[magic_kind,"PajeStartLink";"Type",typ;"Container",container;"StartContainer",start_container;"Value",value;"Key",key]@lletend_link~typ~container~end_container~value~keyl=[magic_kind,"PajeEndLink";"Type",typ;"Container",container;"EndContainer",end_container;"Value",value;"Key",key]@l(* Layout elements *)letextract_kindl=List.partition(fun(x,_)->x=magic_kind)lletrendere=letdefault=function|Date->string_of_float((floate.Event.relative)/.1000.)(* | Int -> "0" not used *)|Double->"0.0"(* | Hex -> "00" not used *)|String->"\"\""|Color->"1.0 1.0 1.0"inletmake_fieldsidfieldsproperties=letres=List.map(fun(nam,typ)->tryletres=List.assocnampropertiesiniftyp=StringthenPrintf.sprintf"%S"reselsereswithNot_found->defaulttyp)fieldsinletres=(string_of_intid)::resinString.concat" "resinife.Event.message=magic_tracethentryletkind,rest=extract_kinde.Event.propertiesinmatchkindwith|[_,kind]->letdef=List.find(funed->kind=ed.event_name)predefined_eventsinmake_fieldsdef.event_iddef.event_fieldsrest|_->""with_->""else""letheader=List.concat(List.mapstring_of_eventpredefined_events)letlayout=header,[],renderletlayout_noheader=[],[],renderlet()=List.iter(fun(x,y)->Layout.registerxy)["paje",layout;"paje_noheader",layout_noheader](* Functorial interface *)typetype_kind=Container|State|Event|Variable|Link|Entity_valueletstring_of_type_kind=function|Container->"container"|State->"state"|Event->"event"|Variable->"variable"|Link->"link"|Entity_value->"entity value"exceptionInvalid_typeoftype_kindlet()=Printexc.register_printer(function|Invalid_typetk->letmsg=Printf.sprintf"Invalid Pajé %s"(string_of_type_kindtk)inSomemsg|_->None)moduletypeDefinitions=sigvallogger:stringvallevel:Level.ttypecontainer_typevalcontainer_types:(container_type*name*(container_typeoption)*alias)listtypestate_typevalstate_types:(state_type*name*container_type*alias)listtypeevent_typevalevent_types:(event_type*name*container_type*alias)listtypevariable_typevalvariable_types:(variable_type*name*container_type*color*alias)listtypelink_typevallink_types:(link_type*name*container_type*container_type*container_type*alias)listtypeentity_value_typevalentity_value_types:(entity_value_type*name*container_type*color*alias)listendmoduletypeS=sigvalt:stringtypeproperties=(string*string)listtypename=stringtypealias=stringtypecolor=float*float*floattypecontainer_typetypestate_typetypeevent_typetypevariable_typetypelink_typetypeentity_value_typevalcreate_container:name:name->typ:container_type->?container:name->?alias:alias->properties->propertiesvaldestroy_container:name:name->typ:container_type->properties->propertiesvalset_state:typ:state_type->container:name->value:string->properties->propertiesvalpush_state:typ:state_type->container:name->value:string->properties->propertiesvalpop_state:typ:state_type->container:name->properties->propertiesvalreset_state:typ:state_type->container:name->properties->propertiesvalnew_event:typ:event_type->container:name->value:string->properties->propertiesvalset_variable:typ:variable_type->container:name->value:float->properties->propertiesvaladd_variable:typ:variable_type->container:name->value:float->properties->propertiesvalsub_variable:typ:variable_type->container:name->value:float->properties->propertiesvalstart_link:typ:link_type->container:name->start_container:name->value:string->key:string->properties->propertiesvalend_link:typ:link_type->container:name->end_container:name->value:string->key:string->properties->propertiesendmoduleMake(D:Definitions)=structlett=ttypeproperties=(string*string)listtypename=stringtypealias=stringtypecolor=float*float*floattypecontainer_type=D.container_typetypestate_type=D.state_typetypeevent_type=D.event_typetypevariable_type=D.variable_typetypelink_type=D.link_typetypeentity_value_type=D.entity_value_typeletmaketk=leth=Hashtbl.create17inletgx=tryHashtbl.findhxwithNot_found->raise(Invalid_typetk)inh,gletcontainers,get_container=makeContainerletstates,get_state=makeStateletevents,get_event=makeEventletvariables,get_variable=makeVariableletlinks,get_link=makeLinkletentity_values,_=makeEntity_valuelet()=(* containers *)List.iter(fun(x,name,parent,alias)->Hashtbl.addcontainersxname;lettyp=matchparentwith|Somex->(tryHashtbl.findcontainersxwith_->"0")|None->"0"inletproperties=define_container_type~name~typ~alias[]inLogger.logD.loggerD.level~propertiest)D.container_types;(* states *)List.iter(fun(x,name,typ,alias)->Hashtbl.addstatesxname;lettyp=get_containertypinletproperties=define_state_type~name~typ~alias[]inLogger.logD.loggerD.level~propertiest)D.state_types;(* events *)List.iter(fun(x,name,typ,alias)->Hashtbl.addeventsxname;lettyp=get_containertypinletproperties=define_event_type~name~typ~alias[]inLogger.logD.loggerD.level~propertiest)D.event_types;(* variables *)List.iter(fun(x,name,typ,color,alias)->Hashtbl.addvariablesxname;lettyp=get_containertypinletproperties=define_variable_type~name~typ~color~alias[]inLogger.logD.loggerD.level~propertiest)D.variable_types;(* links *)List.iter(fun(x,name,typ,start_container_type,end_container_type,alias)->Hashtbl.addlinksxname;lettyp=get_containertypinletstart_container_type=get_containerstart_container_typeinletend_container_type=get_containerend_container_typeinletproperties=define_link_type~name~typ~start_container_type~end_container_type~alias[]inLogger.logD.loggerD.level~propertiest)D.link_types;(* entity values *)List.iter(fun(x,name,typ,color,alias)->Hashtbl.addentity_valuesxname;lettyp=get_containertypinletproperties=define_entity_value~name~typ~color~alias[]inLogger.logD.loggerD.level~propertiest)D.entity_value_typesletcreate_container~name~typ?(container="0")?(alias=name)l=lettyp=get_containertypincreate_container~name~typ~container~aliaslletdestroy_container~name~typl=lettyp=get_containertypindestroy_container~name~typlletset_state~typ~container~valuel=lettyp=get_statetypinset_state~typ~container~valuelletpush_state~typ~container~valuel=lettyp=get_statetypinpush_state~typ~container~valuelletpop_state~typ~containerl=lettyp=get_statetypinpop_state~typ~containerlletreset_state~typ~containerl=lettyp=get_statetypinreset_state~typ~containerlletnew_event~typ~container~valuel=lettyp=get_eventtypinnew_event~typ~container~valuelletset_variable~typ~container~valuel=lettyp=get_variabletypinset_variable~typ~container~valuelletadd_variable~typ~container~valuel=lettyp=get_variabletypinadd_variable~typ~container~valuelletsub_variable~typ~container~valuel=lettyp=get_variabletypinsub_variable~typ~container~valuelletstart_link~typ~container~start_container~value~keyl=lettyp=get_linktypinstart_link~typ~container~start_container~value~keylletend_link~typ~container~end_container~value~keyl=lettyp=get_linktypinend_link~typ~container~end_container~value~keylend