package codex
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
The Codex library for building static analysers based on abstract interpretation
Install
dune-project
Dependency
Authors
Maintainers
Sources
1.0-rc4.tar.gz
md5=bc7266a140c6886add673ede90e335d3
sha512=8da42c0ff2c1098c5f9cb2b5b43b306faf7ac93b8f5ae00c176918cee761f249ff45b29309f31a05bbcf6312304f86a0d5a000eb3f1094d3d3c2b9b4c7f5c386
doc/src/codex.fixpoint/fixpoint_wto.ml.html
Source file fixpoint_wto.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(**************************************************************************) (* This file is part of the Codex semantics library. *) (* *) (* Copyright (C) 2013-2025 *) (* CEA (Commissariat à l'énergie atomique et aux énergies *) (* alternatives) *) (* *) (* 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, version 2.1. *) (* *) (* It 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. *) (* *) (* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file LICENSE). *) (* *) (**************************************************************************) module Log = Tracelog.Make(struct let category = "Fixpoint.Fixpoint_Wto" end);; module type AbstractDomain = sig type state type transition type loop_id val copy: state -> state val join: state -> state -> state val fixpoint_step: loop_id:loop_id -> state -> state -> (state * bool) val transfer: transition -> state -> state option val pp: Format.formatter -> state -> unit val enter_loop: state -> (state * loop_id) val leave_loop: state -> state end module type Graph = sig type transition module ControlLocation:PatriciaTree.KEY val preds_with_transition: ControlLocation.t -> (ControlLocation.t * transition) list end module Make(G:Graph)(D:AbstractDomain with type transition = G.transition) = struct module CLMap = PatriciaTree.MakeMap(G.ControlLocation);; (* Compute the prestate for a node. *) let pre node map = let preds = G.preds_with_transition node in let prestates = preds |> List.filter_map(fun (pred,transition) -> match CLMap.find pred map with | exception Not_found -> None | state -> D.transfer transition state) in match prestates with | [] -> None | a::b -> let state = List.fold_left D.join a b in Some state let pp_opt fmt x = match x with | None -> Format.fprintf fmt "None" | Some v -> Format.fprintf fmt "Some %a" D.pp v let pp_map fmt map = Format.fprintf fmt "{ "; map |> CLMap.iter (fun key _value -> Format.fprintf fmt "%d " (G.ControlLocation.to_int key)); Format.fprintf fmt "} " ;; (* If node is a single node, update it in the map (remove the binding if the state is bottom. *) let update node value map = Log.debug (fun p -> p "Updating %d with %a %a" (G.ControlLocation.to_int node) pp_opt value pp_map map); match value with | None -> CLMap.remove node map | Some value -> CLMap.add node value map ;; let fixpoint_step ~loop_id previous next = match previous,next with | Some previous, Some next -> let state,bool = D.fixpoint_step ~loop_id previous next in Log.debug (fun p -> p "Fixpoint step@\n previous:@\n %a@\nnext:@\n %a@\nres:@\n%a" D.pp previous D.pp next D.pp state); Some state, bool | None, (Some _) -> next, false | None, None -> None, true | Some _, None -> assert false (* Should not happen if transfer functions are monotonous. *) let copy = Option.map D.copy (* Note: this assumes an initial map which is not changed after, i.e. we want the entry point to have no predecessor. TODO: check it. *) let rec fixpoint_component acc = function | Wto.Node n -> update n (pre n acc) acc | Wto.Component(head,part) -> (* We start over from save_acc everytime, otherwise we have spurious values when joining that come from the end of previous iterations. This strategy is described in [Lemerre, POPL 2023]. *) let save_acc = acc in let head_prestate = pre head acc in match head_prestate with | None -> acc (* Nothing to propagate on this component. *) | Some head_prestate -> begin let head_prestate, loop_id = D.enter_loop head_prestate in let rec loop head_prestate = let head_prestate_backup = copy head_prestate in let acc = update head head_prestate acc in let acc = fixpoint_partition acc part in let new_head_prestate = pre head acc in let newstate, fp_reached = fixpoint_step ~loop_id head_prestate_backup new_head_prestate in Log.debug (fun p -> p "Fixpoint reached: %b" fp_reached); if fp_reached then (* We found an invariant on head. Perform one last, possibly descending, iteration, to continue and to register alarms in the loop. Note that this also performs localized widening [amato_scozzari2013localizing_widening_narrowing]. *) let newstate = Option.map (fun st -> D.leave_loop st) newstate in let acc = update head newstate save_acc in fixpoint_partition acc part else loop newstate in loop (Some head_prestate) end and fixpoint_partition acc list = List.fold_left fixpoint_component acc list end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>