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/dangling/multi.ml.html
Source file multi.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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280open Domain.Lib open Lang open Sl open Util.Source (* Dangling branch *) module Branch = struct (* Enclosing relation or function id *) type origin = id (* Status of a branch: if hit, record the paths that hit it with its likeliness; if missed, record the closest-missing paths; note that close-missing files must be well-formed and well-typed *) type status = Hit of bool * string list | Miss of string list (* Type *) type t = { origin : origin; status : status } (* Constructor *) let init (id : id) : t = { origin = id; status = Miss [] } (* Equivalence *) let eq (branch_a : t) (branch_b : t) : bool = branch_a.origin.it = branch_b.origin.it && branch_a.status = branch_b.status (* Printer *) let to_string (branch : t) : string = match branch.status with | Hit _ -> "H" ^ branch.origin.it | Miss _ -> "M" ^ branch.origin.it end (* Dangling coverage map: Note that its domain must be set-up initially, and no new dangling branch is added during the analysis *) module Cover = struct include MakeIIdEnv (Branch) (* Constructor *) let is_ignored (hints : hint list) : bool = Hints.Flag.init hints "testgen_ignore" let rec init_instr (cover : t) (id : id) (instr : instr) : t = let iid = instr.note.iid in match instr.it with | IfI (_, _, block_then, dangle) -> let cover = init_block cover id block_then in if dangle then let branch = Branch.init id in add iid branch cover else cover | HoldI (_, _, _, holdcase) -> ( match holdcase with | BothH (block_hold, block_nothold) -> let cover = init_block cover id block_hold in init_block cover id block_nothold | HoldH (block_hold, dangle) -> let cover = init_block cover id block_hold in if dangle then let branch = Branch.init id in add iid branch cover else cover | NotHoldH (block_nothold, dangle) -> let cover = init_block cover id block_nothold in if dangle then let branch = Branch.init id in add iid branch cover else cover) | CaseI (_, cases, dangle) -> let blocks = cases |> List.split |> snd in let cover = List.fold_left (fun cover block -> init_block cover id block) cover blocks in if dangle then let branch = Branch.init id in add iid branch cover else cover | GroupI (_, _, _, block_group) -> init_block cover id block_group | LetI (_, _, _, block) -> init_block cover id block | RuleI (_, _, _, _, block) -> init_block cover id block | _ -> cover and init_block (cover : t) (id : id) (block : block) : t = List.fold_left (fun cover instr -> init_instr cover id instr) cover block let init_tablerow (cover : t) (id : id) (tablerow : tablerow) : t = let _, _, block = tablerow in init_block cover id block let init_tablerows (cover : t) (id : id) (tablerows : tablerow list) : t = List.fold_left (fun cover tablerow -> init_tablerow cover id tablerow) cover tablerows let init_def (cover : t) (def : def) : t = match def.it with | RelD (id, _, _, block, elseblock_opt, hints) when not (is_ignored hints) -> ( let cover = init_block cover id block in match elseblock_opt with | Some elseblock -> init_block cover id elseblock | None -> cover) | FuncDecD (id, _, _, _, block, elseblock_opt, hints) when not (is_ignored hints) -> ( let cover = init_block cover id block in match elseblock_opt with | Some elseblock -> init_block cover id elseblock | None -> cover) | TableDecD (id, _, _, tablerows, hints) when not (is_ignored hints) -> init_tablerows cover id tablerows | _ -> cover let init_spec (spec : spec) : t = List.fold_left init_def empty spec (* Load from file *) let load_line (line : string) : iid * Branch.t = let data = String.split_on_char ' ' line in match data with | iid :: status :: origin :: paths -> let iid = int_of_string iid in let status = match status with | "Hit_likely" -> Branch.Hit (true, paths) | "Hit_unlikely" -> Branch.Hit (false, paths) | "Miss" -> if List.length paths == 1 && String.length (List.hd paths) < 2 then Branch.Miss [] else Branch.Miss paths | _ -> assert false in let origin = origin $ no_region in let branch = Branch.{ origin; status } in (iid, branch) | _ -> assert false let rec load_lines (cover : t) (ic : in_channel) : t = try let line = input_line ic in if String.starts_with ~prefix:"#" line then load_lines cover ic else let iid, branch = load_line line in let cover = add iid branch cover in load_lines cover ic with End_of_file -> cover let load_file (path : string) : t = open_in path |> load_lines empty end (* Dangling coverage *) type t = Cover.t (* Querying coverage *) let is_hit (cover : t) (iid : iid) : bool = let branch = Cover.find iid cover in match branch.status with Hit _ -> true | Miss _ -> false let is_miss (cover : t) (iid : iid) : bool = let branch = Cover.find iid cover in match branch.status with Hit _ -> false | Miss _ -> true let is_close_miss (cover : t) (iid : iid) : bool = let branch = Cover.find iid cover in match branch.status with | Hit _ -> false | Miss paths -> List.length paths > 0 (* Measuring coverage *) let measure_coverage (cover : t) : int * int * float = let total = Cover.cardinal cover in let hits = Cover.fold (fun _ (branch : Branch.t) (hits : int) -> match branch.status with Hit _ -> hits + 1 | Miss _ -> hits) cover 0 in let coverage = if total = 0 then 0. else float_of_int hits /. float_of_int total *. 100. in (total, hits, coverage) (* Extension from single coverage: A close-miss is added only if the program is well-typed and well-formed *) let extend (cover : t) (path_p4 : string) (wellformed : bool) (welltyped : bool) (cover_single : Single.t) : t = Cover.mapi (fun (iid : iid) (branch : Branch.t) -> let branch_single = Single.Cover.find iid cover_single in match branch.status with | Hit (likely, paths_p4) -> ( match branch_single.status with | Hit -> let likely = likely && not (wellformed && welltyped) in let paths_p4 = path_p4 :: paths_p4 in { branch with status = Hit (likely, paths_p4) } | _ -> branch) | Miss paths_p4 -> ( match branch_single.status with | Hit -> let likely = not (wellformed && welltyped) in let paths_p4 = [ path_p4 ] in { branch with status = Hit (likely, paths_p4) } | Miss (_ :: _) when wellformed && welltyped -> let paths_p4 = path_p4 :: paths_p4 in { branch with status = Miss paths_p4 } | Miss _ -> branch)) cover (* Logging *) let log ~(path_cov_opt : string option) (cover : t) : unit = let output oc_opt = match oc_opt with Some oc -> output_string oc | None -> print_string in let oc_opt = Option.map open_out path_cov_opt in (* Output overall coverage *) let total, hits, coverage = measure_coverage cover in Format.asprintf "# Overall Coverage: %d/%d (%.2f%%)\n" hits total coverage |> output oc_opt; (* Collect covers by origin *) let covers_origin = Cover.fold (fun (iid : iid) (branch : Branch.t) (covers_origin : t IdMap.t) -> let origin = branch.origin in let cover_origin = match IdMap.find_opt origin covers_origin with | Some cover_origin -> Cover.add iid branch cover_origin | None -> Cover.add iid branch Cover.empty in IdMap.add origin cover_origin covers_origin) cover IdMap.empty in IdMap.iter (fun origin cover_origin -> let total, hits, coverage = measure_coverage cover_origin in Format.asprintf "# Coverage for %s: %d/%d (%.2f%%)\n" origin.it hits total coverage |> output oc_opt; Cover.iter (fun (iid : iid) (branch : Branch.t) -> let origin = branch.origin in match branch.status with | Hit (likely, paths) -> let paths = String.concat " " paths in Format.asprintf "%d Hit_%s %s %s\n" iid (if likely then "likely" else "unlikely") origin.it paths |> output oc_opt | Miss [] -> Format.asprintf "%d Miss %s\n" iid origin.it |> output oc_opt | Miss paths -> let paths = String.concat " " paths in Format.asprintf "%d Miss %s %s\n" iid origin.it paths |> output oc_opt) cover_origin) covers_origin; Option.iter close_out oc_opt (* Constructor *) let init (spec : spec) : t = Cover.init_spec spec let load (path : string) : t = Cover.load_file path
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>