X-Git-Url: http://nitlanguage.org diff --git a/src/semantize/flow.nit b/src/semantize/flow.nit index 4717d9b..b0e833a 100644 --- a/src/semantize/flow.nit +++ b/src/semantize/flow.nit @@ -20,6 +20,7 @@ module flow import scope redef class ToolContext + # Run `APropdef::do_flow` on each propdef var flow_phase: Phase = new FlowPhase(self, [scope_phase]) end @@ -29,23 +30,21 @@ private class FlowPhase redef fun process_npropdef(npropdef) do npropdef.do_flow(toolcontext) end -# The visitor that derermine flowcontext for nodes +# The visitor that determine flowcontext for nodes private class FlowVisitor super Visitor - var current_flow_context: FlowContext + var current_flow_context = new FlowContext var toolcontext: ToolContext - init(toolcontext: ToolContext) + init do - self.toolcontext = toolcontext - current_flow_context = new FlowContext flows.add(current_flow_context) current_flow_context.is_start = true end - var first: nullable ANode + var first: nullable ANode = null redef fun visit(node) do @@ -74,12 +73,12 @@ private class FlowVisitor return node.after_flow_context.as(not null) end - var flows: Array[FlowContext] = new Array[FlowContext] + var flows = new Array[FlowContext] fun printflow do - var file = new OFStream.open("flow.dot") - file.write("digraph \{\n") + var file = new FileWriter.open("flow.dot") + file.write("digraph \{\nnode[shape=box];") for f in flows do var s = "" if f.node isa AExpr then @@ -87,13 +86,14 @@ private class FlowVisitor end file.write "F{f.object_id} [label=\"{f.object_id}\\n{f.node.location}\\n{f.node.class_name}\\n{f.name}{s}\"];\n" for p in f.previous do - file.write "F{p.object_id} -> F{f.object_id};\n" + s = "" + if f.when_true == p then s = "[label=TRUE, style=dotted]" + if f.when_false == p then s = "[label=FALSE, style=dotted]" + if f.when_true == p and f.when_false == p then s = "[label=TRUE_FALSE, style=dotted]" + file.write "F{p.object_id} -> F{f.object_id}{s};\n" end - if f.when_true != f then - file.write "F{f.object_id} -> F{f.when_true.object_id}[label=TRUE, style=dotted];\n" - end - if f.when_false != f then - file.write "F{f.object_id} -> F{f.when_false.object_id}[label=FALSE,style=dotted];\n" + for p in f.loops do + file.write "F{p.object_id} -> F{f.object_id}[label=LOOP, style=dashed, constraint=false];\n" end end file.write("\}\n") @@ -165,7 +165,7 @@ private class FlowVisitor fun merge_continues_to(before_loop: FlowContext, escapemark: nullable EscapeMark) do if escapemark == null then return - for b in escapemark.continues do + for b in escapemark.escapes do var before = b.before_flow_context if before == null then continue # Forward error before_loop.add_loop(before) @@ -175,7 +175,7 @@ private class FlowVisitor fun merge_breaks(escapemark: nullable EscapeMark) do if escapemark == null then return - for b in escapemark.breaks do + for b in escapemark.escapes do var before = b.before_flow_context if before == null then continue # Forward error self.make_merge_flow(self.current_flow_context, before) @@ -187,18 +187,18 @@ end # A same `FlowContext` can be shared by more than one `ANode`. class FlowContext # The reachable previous flow - var previous: Array[FlowContext] = new Array[FlowContext] + var previous = new Array[FlowContext] # Additional reachable flow that loop up to self. - # Loops apears in `loop`, `while`, `for`, and with `continue` - var loops: Array[FlowContext] = new Array[FlowContext] + # Loops appears in `loop`, `while`, `for`, and with `continue` + var loops = new Array[FlowContext] private var is_marked_unreachable: Bool = false # Is the flow dead? fun is_unreachable: Bool do - # Are we explicitely marked unreachable? + # Are we explicitly marked unreachable? if self.is_marked_unreachable then return true # Are we the starting flow context? @@ -209,17 +209,17 @@ class FlowContext return false end - # Flag to avoid repeaed errors + # Flag to avoid repeated errors var is_already_unreachable: Bool = false # Mark that self is the starting flow context. # Such a context is reachable even if there is no previous flow var is_start: Bool = false - # The node that introduce the flow (for debuging) + # The node that introduce the flow (for debugging) var node: nullable ANode = null - # Additional information for the flor (for debuging) + # Additional information for the flow (for debugging) var name: String = "" # The sub-flow to use if the associated expr is true @@ -319,22 +319,7 @@ redef class AReturnExpr end end -redef class AContinueExpr - # The flow just before it become unreachable - fun before_flow_context: nullable FlowContext - do - var after = self.after_flow_context - if after == null then return null - return after.previous.first - end - redef fun accept_flow_visitor(v) - do - super - v.make_unreachable_flow - end -end - -redef class ABreakExpr +redef class AEscapeExpr # The flow just before it become unreachable fun before_flow_context: nullable FlowContext do @@ -361,7 +346,7 @@ redef class ADoExpr redef fun accept_flow_visitor(v) do super - v.merge_breaks(self.escapemark) + v.merge_breaks(self.break_mark) end end @@ -411,10 +396,10 @@ redef class AWhileExpr var after_block = v.current_flow_context before_loop.add_loop(after_block) - v.merge_continues_to(after_block, self.escapemark) + v.merge_continues_to(before_loop, self.continue_mark) v.current_flow_context = after_expr.when_false - v.merge_breaks(self.escapemark) + v.merge_breaks(self.break_mark) end end @@ -428,10 +413,10 @@ redef class ALoopExpr var after_block = v.current_flow_context before_loop.add_loop(after_block) - v.merge_continues_to(after_block, self.escapemark) + v.merge_continues_to(before_loop, self.continue_mark) v.make_unreachable_flow - v.merge_breaks(self.escapemark) + v.merge_breaks(self.break_mark) end end @@ -447,10 +432,18 @@ redef class AForExpr var after_block = v.current_flow_context before_loop.add_loop(after_block) - v.merge_continues_to(after_block, self.escapemark) + v.merge_continues_to(before_loop, self.continue_mark) v.make_merge_flow(v.current_flow_context, before_loop) - v.merge_breaks(self.escapemark) + v.merge_breaks(self.break_mark) + end +end + +redef class AWithExpr + redef fun accept_flow_visitor(v) + do + super + v.merge_breaks(self.break_mark) end end @@ -553,7 +546,15 @@ redef class AIsaExpr end end -redef class AProxyExpr +redef class AParExpr + redef fun accept_flow_visitor(v) + do + var after_expr = v.visit_expr(self.n_expr) + v.current_flow_context = after_expr + end +end + +redef class AOnceExpr redef fun accept_flow_visitor(v) do var after_expr = v.visit_expr(self.n_expr)