diff --git a/Pystan/config/__pycache__/constant_propagation.cpython-313.pyc b/Pystan/config/__pycache__/constant_propagation.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51feff5f9764833e4c0f2ab14143279abe81d367 Binary files /dev/null and b/Pystan/config/__pycache__/constant_propagation.cpython-313.pyc differ diff --git a/Pystan/config/constant_propagation.py b/Pystan/config/constant_propagation.py index a530c34071106acc53ced1ee96915ab2cb9deb93..37cb8ce757715dfa5bdb9e17ff45b6419edde794 100644 --- a/Pystan/config/constant_propagation.py +++ b/Pystan/config/constant_propagation.py @@ -85,23 +85,62 @@ class Constant_propagation(Transfer[state]): def __init__(self,instr): self.variables = variables_of_instr(instr) def bottom(self) -> state: - ... + return None def init_state(self) -> state: - ... - def join(self,s1:state,s2:state) -> state: - ... + return {var: abstract_value(None) for var in self.variables} + def join(self, s1: state, s2: state) -> state: + if s1 is None: + return s2 + if s2 is None: + return s1 + result = {} + for var in self.variables: + v1 = s1.get(var, abstract_value(None)) + v2 = s2.get(var, abstract_value(None)) + if v1.value == v2.value: + result[var] = v1 + else: + result[var] = abstract_value(None) + return result + + def included(self, s1: state, s2: state) -> bool: + if s1 is None: + return True + if s2 is None: + return False + return all( + s2.get(var, abstract_value(None)).value in {s1.get(var, abstract_value(None)).value, None} + for var in self.variables + ) - def included(self,s1: state,s2: state) -> bool: - ... + def tr_skip(self, s: state) -> state: + return s - def tr_skip(self,s: state) -> state: - ... + def tr_set(self, s: state, v: str, e: ArithExpr) -> state: + if s is None: + return None + new_env = s.copy() + new_env[v] = eval_aexp(s, e) or abstract_value(None) + return new_env + + def tr_test(self, s: state, c: BoolExpr) -> state: + if s is None: + return None + + res = eval_bexp(s, c) + if res is None: + return None + if res.value is False: + return None - def tr_set(self,s: state,v: str,e: ArithExpr) -> state: - ... + if isinstance(c, BEEq) and isinstance(c.left_expr, AEVar) and isinstance(c.right_expr, AECst): + var = c.left_expr.var + val = c.right_expr.value + new_env = s.copy() + new_env[var] = abstract_value(val) + return new_env - def tr_test(self,s: state,c: BoolExpr) -> state: - ... + return s - def tr_err(self,s: state,e: Expr) -> state: - ... + def tr_err(self, s: state, e: Expr) -> state: + return None diff --git a/Pystan/config/example_iteration.py b/Pystan/config/example_iteration.py index 3a9a71bb66f797cb0a6ac81b285ed1c2a8da2f75..02020a10831764a33e4eb677a52ce67afa4c706c 100644 --- a/Pystan/config/example_iteration.py +++ b/Pystan/config/example_iteration.py @@ -50,3 +50,5 @@ res = fixpoint_iteration(NoInfo(),cfg) unreachable = [node for node, state in res.items() if state == frozenset()] for node in unreachable: print(f"{node} is unreachable") + +# Les noeuds inaccessibles sont ceux qui sont gardés par une condition toujours fausse.