package p4spectec
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
P4-SpecTec: A mechanization toolchain for the P4 Programming Language
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.1.2.tar.gz
md5=1a3bc0a385fe1ecf403c019f49aa6de6
sha512=5d20b5821f33e2a3a5419b208606f27c01511994c2b3b1e1cdf4c077056dfd0aa81682af0720e1060ee2bfb0341918fcc4c53159820205a2bc32b725e5c1a714
doc/src/p4spectec.backend_splice/splicer.ml.html
Source file splicer.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200open Lang open Error open Util.Source (* Splice key and values *) module type KEY = sig type t val to_string : t -> string val to_anchor : t -> string val parse : Source.t -> t list val compare : t -> t -> int end module type VALUE = sig type t val render : t list -> string end module type INIT = sig type key type value val init : El.spec -> Pl.spec -> (key * value) list end (* Splice lookups *) module type STORE = sig type key type value type t val cardinal : t -> int val add : key -> value -> t -> t val find_opt : t -> key -> value option val use : t -> key -> unit val used : t -> key -> bool val unused : t -> key list val empty : t val init : El.spec -> Pl.spec -> t end module Make_store (K : KEY) (V : VALUE) (I : INIT with type key = K.t and type value = V.t) : STORE with type key = K.t and type value = V.t = struct module M = Map.Make (K) type key = K.t type value = V.t type entry = { mutable used : bool; data : V.t } type t = entry M.t let cardinal (sto : t) : int = M.cardinal sto let add (key : K.t) (data : V.t) (sto : t) : t = M.add key { used = false; data } sto let find_opt (sto : t) (key : K.t) : V.t option = match M.find_opt key sto with Some entry -> Some entry.data | None -> None let use (sto : t) (key : K.t) : unit = let entry = M.find key sto in entry.used <- true let used (sto : t) (key : K.t) : bool = let entry = M.find key sto in entry.used let unused (sto : t) : K.t list = M.fold (fun key entry keys_unused -> if entry.used then keys_unused else key :: keys_unused) sto [] |> List.rev let empty : t = M.empty let init (spec_el : El.spec) (spec_pl : Pl.spec) : t = I.init spec_el spec_pl |> List.fold_left (fun sto (key, data) -> add key data sto) empty end (* Splice anchor *) let prefix_source = "ifdef::backend-html5[]\n" ^ ".Click to view the specification source\n[%collapsible]\n====\n" ^ "[source,watsup]\n----\n" let suffix_source = "\n----\n====\n\n[.empty]\n--\n\n\n--\n\n" ^ "endif::[]" let prefix_prose = "****\n" let suffix_prose = "\n****" module type ANCHOR = sig val name : string val prefix : string val suffix : string val header : bool end (* Splicer *) module type SPLICER = sig include ANCHOR type key type value val init : El.spec -> Pl.spec -> unit val splice : Source.t -> string val warn_unused : unit -> unit end module Make (K : KEY) (V : VALUE) (I : INIT with type key = K.t and type value = V.t) (A : ANCHOR) : SPLICER with type key = K.t and type value = V.t = struct include A type key = K.t type value = V.t (* Store *) module S = Make_store (K) (V) (I) let sto = ref S.empty let init (spec_el : El.spec) (spec_pl : Pl.spec) : unit = sto := S.init spec_el spec_pl (* Splicer functions *) let parse (source : Source.t) : K.t list = K.parse source let render (keys : K.t list) : string = let keys, values = keys |> List.filter_map (fun key -> let value_opt = S.find_opt !sto key in match value_opt with | Some value -> Some (key, value) | None -> warn no_region (Format.asprintf "%s splice key not found: %s" name (K.to_string key)); None) |> List.split in let headers = if header then (keys |> List.filter_map (fun key -> if not (S.used !sto key) then Some ("[[" ^ K.to_anchor key ^ "]]") else None) |> String.concat "\n") ^ "\n" else "" in List.iter (S.use !sto) keys; headers ^ prefix ^ V.render values ^ suffix let splice (source : Source.t) : string = let keys = parse source in render keys let warn_unused () : unit = let keys_unused = S.unused !sto in let count_unused = List.length keys_unused in let total = S.cardinal !sto in let percentage = if total = 0 then 0.0 else float_of_int count_unused /. float_of_int total *. 100.0 in Format.asprintf "unused %d %s splices out of %d (%.2f%%)" count_unused name total percentage |> warn no_region; let s = keys_unused |> List.mapi (fun idx key -> (idx, key)) |> List.fold_left (fun s (idx, key) -> let s = if idx mod 5 = 0 && idx > 0 then ( warn no_region ("\t" ^ s); "") else s in let s = s ^ K.to_string key in s ^ if idx mod 5 < 4 && idx < count_unused - 1 then ", " else "") "" in warn no_region ("\t" ^ s) end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>