X-Git-Url: http://nitlanguage.org diff --git a/src/saf/saf_base.nit b/src/saf/saf_base.nit index 806b711..fcc409e 100644 --- a/src/saf/saf_base.nit +++ b/src/saf/saf_base.nit @@ -56,6 +56,13 @@ abstract class StaticAnalysis # implementation of this method is the responsability the subclass. fun new_initial_flow: FLOW is abstract + # Initial flow set to use within methods. + # + # Returns `new_initial_flow` by default. + # Redefine this method to inject things in the inset like parameters from + # the signature. + fun new_initial_method_flow(v: AMethPropdef): FLOW do return new_initial_flow + # The merge operation on sets for confluence. # # Depends on the analysis performed. @@ -131,3 +138,109 @@ redef class ANode v.outsets[self] = v.current_outset end end + +redef class AIfExpr + + # Merge flow on if .. else constructs. + redef fun accept_forward_analysis(v) do + v.enter_visit(n_expr) + var inset = v.current_inset + var outset = v.current_outset + + if n_then != null then v.enter_visit(n_then) + var then_outset = v.current_outset + + v.current_inset = inset + v.current_outset = outset + + if n_else != null then + v.enter_visit(n_else) + outset = v.merge(then_outset, v.current_outset) + else + outset = v.merge(then_outset, v.current_inset) + end + v.current_inset = inset + v.current_outset = outset + end +end + +# Represent all kind of `do .. end` blocks. +# +# Used to factorize implementations across do blocks, whiles, fors and loops. +# +# This factorization makes sense since all these contructs can be flow managed +# through contine and breack statements. +# +# TODO move this up in the module hierarchy +interface ADoBlockHelper + # Lookup fix point for this loop. + fun loop_fix_point(v: StaticAnalysis, node: ANode) do + var inset = v.current_inset.clone + var last: nullable FlowSet = null + while v.current_outset != last do + v.enter_visit(node) + v.current_inset = v.merge(inset, v.current_outset) + v.current_outset = v.current_inset.clone + last = v.current_outset.clone + end + v.current_inset = inset + v.current_outset = v.merge(inset, v.current_outset) + end + + # Factorize loop forward analysis. + fun accept_loop_forward_analysis(v: StaticAnalysis) do + var n_block = loop_block + if not n_block == null then loop_fix_point(v, n_block) + end + + # The block contained by this loop. + fun loop_block: nullable ANode is abstract +end + +redef class ADoExpr + super ADoBlockHelper + + redef fun loop_block do return self.n_block + redef fun accept_forward_analysis(v) do accept_loop_forward_analysis(v) +end + +redef class ALoopExpr + super ADoBlockHelper + + redef fun loop_block do return self.n_block + redef fun accept_forward_analysis(v) do accept_loop_forward_analysis(v) +end + +redef class AWhileExpr + super ADoBlockHelper + + redef fun loop_block do return self.n_block + + redef fun accept_forward_analysis(v) do + v.enter_visit(n_expr) + accept_loop_forward_analysis(v) + end +end + +redef class AForExpr + super ADoBlockHelper + + redef fun loop_block do return self.n_block + + redef fun accept_forward_analysis(v) do + for n_group in n_groups do + v.enter_visit(n_group.n_expr) + end + accept_loop_forward_analysis(v) + end +end + +redef class AMethPropdef + redef fun accept_forward_analysis(v) do + v.current_inset = v.new_initial_method_flow(self) + v.current_outset = v.current_inset.clone + v.insets[self] = v.current_inset + visit_all(v) + v.outsets[self] = v.current_outset + end +end