123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175(* Yoann Padioleau
*
* Copyright (C) 2014 Facebook
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation, with the
* special exception on linking described in file license.txt.
*
* This library 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 file
* license.txt for more details.
*)openCommonmoduleE=Entity_code(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*
* For more information look at h_program-lang/prolog_code.pl
* and its many predicates.
*)(*****************************************************************************)(* Types *)(*****************************************************************************)(* mimics prolog_code.pl top comment *)typefact=|Atofentity*Common.filename(* readable path *)*int(* line *)|Kindofentity*Entity_code.entity_kind|Typeofentity*string(* could be more structured ... *)|Extendsofstring*string|Implementsofstring*string|Mixinsofstring*string|Privacyofentity*Entity_code.privacy(* direct use of entities, e.g. foo() *)|Callofentity*entity|UseDataofentity*entity*booloption(* read/write *)(* indirect uses of entities, e.g. xxx.f = &foo; *)|Specialofentity(* enclosing *)*entity(* ctx entity, e.g. function/field/global *)*entity(* the value *)*string(* field/function *)|Miscofstring(* todo? could use a record with
* namespace: string list;
* enclosing: string option;
* name: string
*)andentity=stringlist(* package/module/namespace/class/struct/type qualifier*)*string(* name *)(*****************************************************************************)(* IO *)(*****************************************************************************)(* todo: hmm need to escape x no? In OCaml toplevel values can have a quote
* in their name, like foo'', which will not work well with Prolog atoms.
*)(* http://pleac.sourceforge.net/pleac_ocaml/strings.html *)letescapecharliststr=letrx=Str.regexp("\\(["^charlist^"]\\)")inStr.global_replacerx"\\\\\\1"strletescape_quote_and_double_quotes=escape"'\""sletstring_of_entity(xs,x)=matchxswith|[]->spf"'%s'"(escape_quote_and_double_quotex)|xs->spf"('%s', '%s')"(Common.join"."xs)(escape_quote_and_double_quotex)(* Quite similar to database_code.string_of_id_kind, but with lowercase
* because of prolog atom convention. See also prolog_code.pl comment
* about kind/2.
*)letstring_of_entity_kind=function|E.Function->"function"|E.Constant->"constant"|E.Global->"global"|E.Macro->"macro"|E.Class->"class"|E.Type->"type"|E.Method->"method"|E.ClassConstant->"constant"|E.Field->"field"|E.Constructor->"constructor"|E.TopStmts->"stmtlist"|E.Other_->"idmisc"|E.Exception->"exception"|E.Module->"module"|E.Package->"package"|E.Prototype->"prototype"|E.GlobalExtern->"global_extern"|(E.MultiDirs|E.Dir|E.File)->raiseImpossibleletstring_of_factfact=lets=matchfactwith|Kind(entity,kind)->spf"kind(%s, %s)"(string_of_entityentity)(string_of_entity_kindkind)|At(entity,file,line)->spf"at(%s, '%s', %d)"(string_of_entityentity)fileline|Type(entity,str)->spf"type(%s, '%s')"(string_of_entityentity)(escape_quote_and_double_quotestr)|Extends(s1,s2)->spf"extends('%s', '%s')"s1s2|Mixins(s1,s2)->spf"mixins('%s', '%s')"s1s2|Implements(s1,s2)->spf"implements('%s', '%s')"s1s2|Privacy(entity,p)->letpredicate=matchpwith|E.Public->"is_public"|E.Private->"is_private"|E.Protected->"is_protected"inspf"%s(%s)"predicate(string_of_entityentity)(* less: depending on kind of e1 we could have 'method' or 'constructor'*)|Call(e1,e2)->spf"docall(%s, %s)"(string_of_entitye1)(string_of_entitye2)|UseData(e1,e2,b)->spf"use(%s, %s, %s)"(string_of_entitye1)(string_of_entitye2)(matchbwith|None->"na"|Sometrue->"write"|Somefalse->"read")|Special(e1,e2,e3,str)->spf"special(%s, %s, %s, '%s')"(string_of_entitye1)(string_of_entitye2)(string_of_entitye3)str|Miscs->sins^"."(*****************************************************************************)(* Helpers *)(*****************************************************************************)letentity_of_strs=letxs=Common.split"\\."sinmatchList.revxswith|[]->raiseImpossible|[x]->([],x)|x::xs->(List.revxs,x)