Definitions and notations a. Let π be a set of all reset contexts over the program's variables. b. Denote πΊ to be a graph where each vertex is a context from π. Each context can be expressed as a set of variables, so for ease of expressiveness, instead of using πΊππ to represent a graph directed edge from context π to context π, it is also possible to reference for instance πΊ{1,3},{1,3,4} - this indicates the directed edge from context {π1 , π3 } to context {π1 , π2 , π3 }. c. Alternatively, the notation (π, π) will denote the edge from context π to context π. d. The ⋅ operator (compositional) works on a context graph πΊ in the following manner: ′ For every 2 edges πΊπ,π and πΊπ′,π′ in πΊ and πΊ′, respectively, where π = π′ , the result graph πΊ′′ will hold an edge ′′ πΊπ,π′ such that: ′′ ′ πΊπ,π′ = πΊπ,π ⋅ πΊπ′,π′ e. Each edge holds a dependency set, and the compositional operator ⋅ works as defined for dependency sets. ′′ ′ i.e. – the πΊπ,π′ dependency set will be the composition the dependency sets of πΊπ,π and πΊπ′,π′ in this order. e. The β operator works on graphs edge-wise, such that provided the edge π → π exists on both joined graphs: πβπ‘ π π‘ π→π π→π π→π ′′ ′ πΊπ,π = πΊπ,π β πΊπ,π = {π → π | π → π ∈ πΊ ′ π,π βπ → π ∈ πΊπ,π } β { | ∈ πΊ ′ π,π ∨ ∈ πΊπ,π } π→π π→π π→π if only one of the graphs holds the edge π → π, the result graph will hold this exact edge. If none of the graphs holds the edge π → π, then this edge will be missing from the result graph. f. For a context π, we define the symbols: πΜπ₯,π¦ = π β {π₯} ∪ { π₯ |ππ π¦ ∈ π} πΜπ₯,π¦,π§ = π β {π₯} ∪ { π₯ |ππ π¦ ∈ πβ π§ ∈ π} πΜπ₯,π¦,π§ = π β {π₯} ∪ { π₯ |ππ π¦ ∈ π ∨ π§ ∈ π} Algorithm (ML-like, at parts): fun analyse(Core.Cmd c, preContexts : Context list) : G = case c of Core.Seq(c1,c2) => let val g = analyse(c1, preContexts); val g' = analyse(c2, targetContexts1(g)); in g β g' end; | Core.Choice(c1,c2) => analyse(c1, preContexts) β analyse(c2, preContexts) 1 | Core.Skip => doAssignment(1,Core.Var 1, preContexts) | Core.Asgn(i, e) => doAssignment(i, e, preContexts) | Core.Loop(i, c) => doLoop(i, c, preContexts); targetContexts(πΊ) = the set { t | (π , π‘) ∈ πΊ } , ordered into a list. fun doAssignment (x : int, Core.Expr e, preContexts : Context list) : G = let fun doAssignmentInternal (x : int, Core.Expr e, PC : Context list) : G = case e of Core.Zero => 1 π′ π€βπππ ∀π∈PC : π′π,π∪{π₯} = {π → π | π ∉ π ∧ π ≠ π₯} 1 1 | Core.Var y => π′ π€βπππ ∀π∈PC : π′π,πΜπ₯,π¦ = {π¦ → π₯ | π¦ ∉ π} ∪ { π → π | π ∉ π ∧ π ≠ π₯} | Core.times(Core.Var y, Core.Var z) => 1 2 π′ π€βπππ ∀π∈PC : π′π,πΜπ₯,π¦,π§ = {π → π | π ∉ π ∧ π ≠ π₯} ∪ {π‘ → π₯ | π‘ ∈ {π¦, π§} ∧ π¦, π§ ∉ π } | Core.plus(Core.Var y , Core.Var z) => 1 1 1 1+ π′ π€βπππ ∀π∈PC : π′π,πΜπ₯,π¦,π§ = {π → π | π ≠ π₯ ∧ π ∉ π} ∪ {π¦ → π₯|π¦ ∉ π ∧ π§ ∈ π} ∪ {π§ → π₯|π§ ∉ π ∧ π¦ ∈ π} ∪ {π‘ → π₯|π‘ ∈ {π¦, π§} ∧ π¦, π§ ∉ π}; val PC = if (preContexts = []) then !allContexts2 else preContexts; val π′ = doAssignmentInternal(x,e,PC); in π′′ π€βπππ π′′π,π π→π ={ ′ | π → π′ π, π ′ ∉ π ∧ π1 π, π ′ ∉ π π2 ∧ (π ≠ π ′ ∨ π ≠ π ′ ) ∧ π → π ∈ π′π,π ∧ π → π ∈ π′π,π ∧ π1 , π2 β 1 } β π′π,π end; 2 allContexts is a "global" Context list which includes all contexts except for the full context (which holds all program variables). fun doLoop(Core.Var x, c : Core.Cmd, preContexts : Context list) : G = doLoopClosure(x, doMIterations(analyse(c, preContexts) ) ); fun lfp(F, g) = let val fm = (F g); in if (fg = g) then g else lfp F fg end; fun doLoopClosure(x : int, g : G) : G = π′ π€βπππ ∀ππ ,π1 ,π2 : ((π0 , π1 ) ∈ π ∧ (π1 , π2 ) ∈ π) → (π′ π ,π = ππ0 ,π1 β πΏπΆπ₯ (ππ1 ,π1 ) β ππ1 ,π2 ) ; π 2 fun doMIterations(g : G) : G = let val g' = ref g; in lfp (doSingleIteration g') g end fun doSingleIteration (ref g) g' : G->G = (g := !g β g β g'; !g)