Skip to content

Commit a38af3a

Browse files
authored
adds bap primus-lisp-documentation (#1306)
Much like the old `bap --primus-lisp-documentation` this command prints the Primus Lisp documentation in the .org format. But it doesn't require a file as it is possible to specify the target using the `--target` command line option. Since `primus-lisp-documentation` is a separate command, it is not necessary to specify a bogus file name and there are more options to control the output. First of all, it is now possible to specify the system (using `--system`), so that now it is possible to get the documentation for symbolic primtives and functions. It is also possible to set the package name (using `--package`) and request the documentation for the Primus Lisp Semantics subsystem (with `--semantics`). Therefore, to get the documentation for thumb semantics (functions and primitives), use ``` bap primus-lisp-documentation --semantics --package=thumb ``` The list of packages, along with their documentation is also available in the `bap primus-lisp-documentation`
1 parent 850f24b commit a38af3a

14 files changed

+189
-53
lines changed

lib/bap_primus/bap_primus.mli

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3671,7 +3671,7 @@ text ::= ?any atom that is not recognized as a <word>?
36713671
end
36723672

36733673
module Category : Element
3674-
module Name : Element
3674+
module Name = Knowledge.Name
36753675
module Descr : Element
36763676

36773677

@@ -3988,6 +3988,13 @@ text ::= ?any atom that is not recognized as a <word>?
39883988
?types:Type.signature ->
39893989
?docs:string ->
39903990
?package:string -> string -> unit
3991+
3992+
3993+
(** [documentation unit] documentation for [unit]'s lisp source.
3994+
3995+
Typechecks and loads the unit lisp source and generates
3996+
its documentation. *)
3997+
val documentation : Theory.Unit.t -> Doc.index KB.t
39913998
end
39923999

39934000

lib/bap_primus/bap_primus_lisp.ml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -855,31 +855,44 @@ module Doc = struct
855855
Map.to_alist
856856

857857
let describe prog item =
858-
Lisp.Program.get prog item |> List.map ~f:(fun x ->
859-
let name = Name.create (Lisp.Def.name x) in
860-
let info = Info.create ~desc:(Lisp.Def.docs x) name in
861-
name,Info.desc info) |> normalize
858+
Lisp.Program.fold prog item ~init:[] ~f:(fun ~package def defs ->
859+
let name = Name.create ~package (Lisp.Def.name def) in
860+
let info = Info.create ~desc:(Lisp.Def.docs def) name in
861+
(name,Info.desc info) :: defs) |> normalize
862862

863-
let index p = Lisp.Program.Items.[
863+
let describe_packages prog =
864+
Lisp.Program.packages prog |>
865+
List.map ~f:(fun (n,d) -> KB.Name.create n, d)
866+
867+
let remove_empty = List.filter ~f:(function (_,[]) -> false | _ -> true)
868+
869+
let create_index p = remove_empty@@Lisp.Program.Items.[
870+
"Packages", describe_packages p;
864871
"Macros", describe p macro;
865872
"Substitutions", describe p subst;
866873
"Constants", describe p const;
867874
"Functions", describe p func;
868875
"Methods", describe p meth;
869876
"Parameters", describe p para;
870877
"Primitives", describe p primitive;
878+
"Primitives", describe p semantics;
871879
"Signals", describe p signal;
872880
]
873881

874882
module Make(Machine : Machine) = struct
875883
open Machine.Syntax
876884
let generate_index : index Machine.t =
877885
Machine.Local.get state >>| fun s ->
878-
index s.program
886+
create_index s.program
879887
end
880888
end
881889

882890
let primitive = lisp_primitive
883-
module Semantics = Bap_primus_lisp_semantics
891+
module Semantics = struct
892+
include Bap_primus_lisp_semantics
893+
let documentation unit =
894+
KB.Syntax.(typed_program unit >>| Doc.create_index)
895+
end
896+
884897
module Unit = Semantics.Unit
885898
module Attribute = Lisp.Attribute

lib/bap_primus/bap_primus_lisp.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Doc : sig
2222
end
2323

2424
module Category : Element
25-
module Name : Element
25+
module Name = KB.Name
2626
module Descr : Element
2727
type index = (Category.t * (Name.t * Descr.t) list) list
2828

@@ -155,6 +155,7 @@ module Semantics : sig
155155
?types:Type.signature ->
156156
?docs:string -> ?package:string -> string -> unit
157157

158+
val documentation : Theory.Unit.t -> Doc.index KB.t
158159
end
159160

160161
module Unit : sig

lib/bap_primus/bap_primus_lisp_parse.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ let is_quoted s =
6868
let is_symbol s =
6969
String.length s > 1 && Char.(s.[0] = '\'')
7070

71-
let unqoute s =
71+
let unquote s =
7272
if is_quoted s
7373
then String.sub ~pos:1 ~len:(String.length s - 2) s
7474
else s
@@ -107,7 +107,7 @@ module Parse = struct
107107
| Ok var -> var
108108

109109
let fmt prog fmt tree =
110-
let fmt = unqoute fmt in
110+
let fmt = unquote fmt in
111111
let fail err off =
112112
let pos =
113113
Loc.nth_char (loc (Program.sources prog) [tree]) (off+1) in
@@ -355,8 +355,8 @@ module Parse = struct
355355
List.fold ~init:prog trees ~f:(fun prog -> function
356356
| {data=List ({data=Atom ":use"} :: packages)} ->
357357
use_package ~package:name prog packages
358-
| {data=List ({data=Atom ":documentation"} :: _)} ->
359-
prog
358+
| {data=List [{data=Atom ":documentation"}; {data=Atom docs}]} ->
359+
Program.update_package_documentation prog name (unquote docs)
360360
| s -> fail (Bad_def Defpkg) s)
361361

362362
let toplevels = String.Set.of_list [

lib/bap_primus/bap_primus_lisp_program.ml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type t = {
3636
sources : Source.t;
3737
exports : Set.M(String).t Map.M(String).t;
3838
library : package Map.M(String).t;
39+
pkgdocs : string Map.M(String).t;
3940
} [@@deriving fields]
4041

4142
type program = t
@@ -61,6 +62,7 @@ let empty = {
6162
package = default_package;
6263
exports = Map.empty (module String);
6364
library = Map.empty (module String);
65+
pkgdocs = Map.empty (module String);
6466
}
6567

6668
let with_package program package = {program with package}
@@ -146,6 +148,16 @@ let merge_packages p1 p2 = {
146148
places = p1.places ++ p2.places;
147149
}
148150

151+
let update_package_documentation prog package docs = {
152+
prog with pkgdocs = Map.set prog.pkgdocs package docs;
153+
}
154+
155+
let packages {library; pkgdocs} =
156+
Map.keys library |>
157+
List.map ~f:(fun pkg -> pkg, match Map.find pkgdocs pkg with
158+
| None -> ""
159+
| Some docs -> docs)
160+
149161
let use_package program ?(target=program.package) from =
150162
let program = {
151163
program with
@@ -169,6 +181,14 @@ let equal p1 p2 =
169181

170182
let is_empty p = Map.is_empty p.library
171183

184+
let merge_pkgdocs =
185+
Map.merge ~f:(fun ~key:_ -> function
186+
| `Left docs | `Right docs -> Some docs
187+
| `Both ("","") -> Some ""
188+
| `Both (d,"")
189+
| `Both ("",d) -> Some d
190+
| `Both (d1,_) -> Some d1)
191+
172192
let merge_libraries l1 l2 =
173193
Map.merge_skewed l1 l2 ~combine:(fun ~key:_ -> merge_packages)
174194

@@ -181,14 +201,14 @@ let reexport program =
181201

182202
let merge p1 p2 = reexport {
183203
p1 with
204+
pkgdocs = merge_pkgdocs p1.pkgdocs p2.pkgdocs;
184205
sources = p2.sources;
185206
context = Lisp.Context.merge p1.context p2.context;
186207
library = merge_libraries p1.library p2.library;
187208
exports = Map.merge_skewed p1.exports p2.exports
188209
~combine:(fun ~key:_ -> Set.union)
189210
}
190211

191-
192212
type full_access = [`Read | `Set_and_create ]
193213
type 'a item =
194214
(full_access, package, 'a Def.t list) Fieldslib.Field.t_with_perm
@@ -1537,7 +1557,7 @@ the inferred type of the method:@\n%a"
15371557
| No_unification (x,t1,y,t2) ->
15381558
fprintf ppf "
15391559
Type error: expected %a got %a. Details follow, the expression:
1540-
%ahas type %a, but it is expected to have type %a after its unification
1560+
%a has type %a, but it is expected to have type %a after its unification
15411561
with the expression:@\n%a@\n"
15421562
pp_val t1 pp_val t2
15431563
pp_exp (sources,x) pp_val t1 pp_val t2 pp_exp (sources,y)

lib/bap_primus/bap_primus_lisp_program.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ val with_package : t -> string -> t
2828
val reset_package : t -> t
2929
val use_package : t -> ?target:string -> string -> t
3030
val in_package : string -> t -> (t -> 'a) -> 'a
31-
31+
val packages : t -> (string * string) list
32+
val update_package_documentation : t -> string -> string -> t
3233
val is_applicable : t -> 'a Def.t -> bool
3334

3435
module Items : sig

lib/bap_primus/bap_primus_lisp_semantics.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,6 @@ let static_slot =
160160
~equal:Bitvec.equal
161161
~inspect:(fun x -> Sexp.Atom (Bitvec.to_string x))
162162

163-
164-
165-
166163
let update_value r f =
167164
let v = KB.Value.get Theory.Semantics.value r in
168165
KB.Value.put Theory.Semantics.value r (f v)
@@ -645,6 +642,12 @@ let obtain_typed_program unit =
645642
program
646643
| errs -> KB.fail (Illtyped_program errs)
647644

645+
646+
let typed_program unit =
647+
let open KB.Syntax in
648+
obtain_typed_program unit >>| fun {prog} -> prog
649+
650+
648651
let provide_semantics ?(stdout=Format.std_formatter) () =
649652
let open KB.Syntax in
650653
KB.Rule.(begin

lib/bap_primus/bap_primus_lisp_semantics.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ val symbol : (Theory.Value.cls, String.t option) KB.slot
1515
val static : (Theory.Value.cls, Bitvec.t option) KB.slot
1616
val enable : ?stdout:Format.formatter -> unit -> unit
1717

18+
val typed_program : Theory.Unit.t -> program KB.t
19+
1820
val declare :
1921
?types:(Theory.Target.t -> Bap_primus_lisp_type.signature) ->
2022
?docs:string ->

lib/knowledge/bap_knowledge.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3071,7 +3071,8 @@ module Knowledge = struct
30713071
module Make() = struct
30723072
type t = Name.t [@@deriving bin_io, sexp]
30733073

3074-
let elements = Hash_set.create (module Name)
3074+
let unknown = Name.of_string ":unknown"
3075+
let elements = Hash_set.of_list (module Name) [unknown]
30753076
let declare ?package name =
30763077
let name = Name.create ?package name in
30773078
if Hash_set.mem elements name
@@ -3089,7 +3090,6 @@ module Knowledge = struct
30893090
name
30903091

30913092
let name x = x
3092-
let unknown = Name.of_string ":unknown"
30933093
let is_unknown = Name.equal unknown
30943094
let hash = Name.hash
30953095
let members () = Hash_set.to_list elements

oasis/primus-lisp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Library primus_lisp_library_plugin
1616
Primus_lisp_ieee754,
1717
Primus_lisp_io,
1818
Primus_lisp_show,
19-
Primus_lisp_run
19+
Primus_lisp_run,
20+
Primus_lisp_documentation
2021
XMETADescription: install and load Primus lisp libraries
2122
DataFiles: lisp/*.lisp ($datadir/bap/primus/lisp),
2223
site-lisp/*.lisp ($datadir/bap/primus/site-lisp),

0 commit comments

Comments
 (0)