Intraprocedural static flow.

Introduced classes

class FlowContext

nitc :: FlowContext

A Node in the static flow graph.
private class FlowPhase

nitc :: FlowPhase

private class FlowVisitor

nitc :: FlowVisitor

The visitor that determine flowcontext for nodes

Redefined classes

redef class AAbortExpr

nitc :: flow $ AAbortExpr

An abort statement
redef class AAndExpr

nitc :: flow $ AAndExpr

A and expression
redef class AAssertExpr

nitc :: flow $ AAssertExpr

An assert statement
redef class ABlockExpr

nitc :: flow $ ABlockExpr

A sequence of AExpr (usually statements)
redef class ADoExpr

nitc :: flow $ ADoExpr

A do statement
redef class AEqExpr

nitc :: flow $ AEqExpr

A == expression
redef abstract class AEscapeExpr

nitc :: flow $ AEscapeExpr

A break or a continue
redef abstract class AExpr

nitc :: flow $ AExpr

Expression and statements
redef class AForExpr

nitc :: flow $ AForExpr

A for statement
redef class AIfExpr

nitc :: flow $ AIfExpr

A if statement
redef class AIfexprExpr

nitc :: flow $ AIfexprExpr

A if expression (ternary conditional). eg. if true then 1 else 0
redef class AImpliesExpr

nitc :: flow $ AImpliesExpr

A implies expression
redef class AIsaExpr

nitc :: flow $ AIsaExpr

A type-ckeck expression. eg x isa T
redef class ALoopExpr

nitc :: flow $ ALoopExpr

A loop statement
redef class ANeExpr

nitc :: flow $ ANeExpr

A != expression
redef abstract class ANode

nitc :: flow $ ANode

Root of the AST class-hierarchy
redef class ANotExpr

nitc :: flow $ ANotExpr

A not expression
redef class AOnceExpr

nitc :: flow $ AOnceExpr

A once expression. eg once x
redef class AOrElseExpr

nitc :: flow $ AOrElseExpr

A or else expression
redef class AOrExpr

nitc :: flow $ AOrExpr

A or expression
redef class AParExpr

nitc :: flow $ AParExpr

A simple parenthesis. eg (x)
redef abstract class APropdef

nitc :: flow $ APropdef

The definition of a property
redef abstract class AReassignFormExpr

nitc :: flow $ AReassignFormExpr

Whatever is a combined assignment. eg += something
redef class AReturnExpr

nitc :: flow $ AReturnExpr

A return statement. eg return x
redef class AVarAssignExpr

nitc :: flow $ AVarAssignExpr

A local variable simple assignment access
redef class AWhileExpr

nitc :: flow $ AWhileExpr

A while statement
redef class AWithExpr

nitc :: flow $ AWithExpr

A with statement
redef class ToolContext

nitc :: flow $ ToolContext

Global context for tools

All class definitions

redef class AAbortExpr

nitc :: flow $ AAbortExpr

An abort statement
redef class AAndExpr

nitc :: flow $ AAndExpr

A and expression
redef class AAssertExpr

nitc :: flow $ AAssertExpr

An assert statement
redef class ABlockExpr

nitc :: flow $ ABlockExpr

A sequence of AExpr (usually statements)
redef class ADoExpr

nitc :: flow $ ADoExpr

A do statement
redef class AEqExpr

nitc :: flow $ AEqExpr

A == expression
redef abstract class AEscapeExpr

nitc :: flow $ AEscapeExpr

A break or a continue
redef abstract class AExpr

nitc :: flow $ AExpr

Expression and statements
redef class AForExpr

nitc :: flow $ AForExpr

A for statement
redef class AIfExpr

nitc :: flow $ AIfExpr

A if statement
redef class AIfexprExpr

nitc :: flow $ AIfexprExpr

A if expression (ternary conditional). eg. if true then 1 else 0
redef class AImpliesExpr

nitc :: flow $ AImpliesExpr

A implies expression
redef class AIsaExpr

nitc :: flow $ AIsaExpr

A type-ckeck expression. eg x isa T
redef class ALoopExpr

nitc :: flow $ ALoopExpr

A loop statement
redef class ANeExpr

nitc :: flow $ ANeExpr

A != expression
redef abstract class ANode

nitc :: flow $ ANode

Root of the AST class-hierarchy
redef class ANotExpr

nitc :: flow $ ANotExpr

A not expression
redef class AOnceExpr

nitc :: flow $ AOnceExpr

A once expression. eg once x
redef class AOrElseExpr

nitc :: flow $ AOrElseExpr

A or else expression
redef class AOrExpr

nitc :: flow $ AOrExpr

A or expression
redef class AParExpr

nitc :: flow $ AParExpr

A simple parenthesis. eg (x)
redef abstract class APropdef

nitc :: flow $ APropdef

The definition of a property
redef abstract class AReassignFormExpr

nitc :: flow $ AReassignFormExpr

Whatever is a combined assignment. eg += something
redef class AReturnExpr

nitc :: flow $ AReturnExpr

A return statement. eg return x
redef class AVarAssignExpr

nitc :: flow $ AVarAssignExpr

A local variable simple assignment access
redef class AWhileExpr

nitc :: flow $ AWhileExpr

A while statement
redef class AWithExpr

nitc :: flow $ AWithExpr

A with statement
class FlowContext

nitc $ FlowContext

A Node in the static flow graph.
private class FlowPhase

nitc $ FlowPhase

private class FlowVisitor

nitc $ FlowVisitor

The visitor that determine flowcontext for nodes
redef class ToolContext

nitc :: flow $ ToolContext

Global context for tools
package_diagram nitc::flow flow nitc::scope scope nitc::flow->nitc::scope nitc::modelbuilder modelbuilder nitc::scope->nitc::modelbuilder ...nitc::modelbuilder ... ...nitc::modelbuilder->nitc::modelbuilder nitc::local_var_init local_var_init nitc::local_var_init->nitc::flow nitc::typing typing nitc::typing->nitc::local_var_init nitc::typing... ... nitc::typing...->nitc::typing

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module console

console :: console

Defines some ANSI Terminal Control Escape Sequences.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module digraph

graph :: digraph

Implementation of directed graphs, also called digraphs.
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module ini

ini :: ini

Read and write INI configuration files
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module lexer

nitc :: lexer

Lexer and its tokens.
module lexer_work

nitc :: lexer_work

Internal algorithm and data structures for the Nit lexer
module list

core :: list

This module handle double linked lists
module loader

nitc :: loader

Loading of Nit source files
module location

nitc :: location

Nit source-file and locations in source-file
module math

core :: math

Mathematical operations
module mdoc

nitc :: mdoc

Documentation of model entities
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module mmodule

nitc :: mmodule

modules and module hierarchies in the metamodel
module model

nitc :: model

Classes, types and properties
module model_base

nitc :: model_base

The abstract concept of model and related common things
module modelbuilder_base

nitc :: modelbuilder_base

Load nit source files and build the associated model
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module mpackage

nitc :: mpackage

Modelisation of a Nit package
module native

core :: native

Native structures for text and bytes
module nitpm_shared

nitc :: nitpm_shared

Services related to the Nit package manager
module numeric

core :: numeric

Advanced services for Numeric types
module opts

opts :: opts

Management of options on the command line
module ordered_tree

ordered_tree :: ordered_tree

Manipulation and presentation of ordered trees.
module parser

nitc :: parser

Parser.
module parser_nodes

nitc :: parser_nodes

AST nodes of the Nit language
module parser_prod

nitc :: parser_prod

Production AST nodes full definition.
module parser_work

nitc :: parser_work

Internal algorithm and data structures for the Nit parser
module phase

nitc :: phase

Phases of the processing of nit programs
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module tables

nitc :: tables

Module that interfaces the parsing tables.
module template

template :: template

Basic template system
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module toolcontext

nitc :: toolcontext

Common command-line tool infrastructure than handle options and error messages
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O
module version

nitc :: version

This file was generated by git-gen-version.sh

Parents

module scope

nitc :: scope

Identification and scoping of local variables and labels.

Children

module local_var_init

nitc :: local_var_init

Verify that local variables are initialized before their usage

Descendants

module a_star-m

a_star-m

module abstract_compiler

nitc :: abstract_compiler

Abstract compiler
module android

nitc :: android

Compile program for the Android platform
module android_annotations

nitc :: android_annotations

Additionnal annotations to gather metadata on Android projects
module api

nitc :: api

Components required to build a web server about the nit model.
module api_auth

nitc :: api_auth

module api_base

nitc :: api_base

Base classes used by nitweb.
module api_docdown

nitc :: api_docdown

Nitdoc specific Markdown format handling for Nitweb
module api_feedback

nitc :: api_feedback

Feedback related features
module api_light

nitc :: api_light

Highlight and collect messages from a piece of code
module api_model

nitc :: api_model

module app_annotations

nitc :: app_annotations

Annotations to gather metadata on app.nit projects
module astbuilder

nitc :: astbuilder

Instantiation and transformation of semantic nodes in the AST of expressions and statements
module auto_super_init

nitc :: auto_super_init

Computing of super-constructors that must be implicitly called at the begin of constructors.
module c

nitc :: c

Support for nesting C code within a Nit program using its FFI
module c_compiler_options

nitc :: c_compiler_options

Offers the annotations cflags and ldflags to specify
module code_gen

nitc :: code_gen

Main frontend phases plus code generation phases
module commands_docdown

nitc :: commands_docdown

Doc down related queries
module commands_http

nitc :: commands_http

Initialize commands from HTTP requests
module commands_parser

nitc :: commands_parser

A parser that create DocCommand from a string
module commands_usage

nitc :: commands_usage

Commands about how mentities are used
module compilation

nitc :: compilation

The compilation module of the VirtualMachine
module compiler

nitc :: compiler

Compilation to C
module compiler_ffi

nitc :: compiler_ffi

Full FFI support for the compiler
module compiler_serialization

nitc :: compiler_serialization

Serialization support for the compiler
module contracts

nitc :: contracts

Module to build contract
module cpp

nitc :: cpp

Supports the use of the C++ language through the FFI
module detect_covariance

nitc :: detect_covariance

Detect the static usage of covariance in the code.
module div_by_zero

nitc :: div_by_zero

Detection of divisions by zero in obvious cases
module dynamic_loading_ffi

nitc :: dynamic_loading_ffi

Execute FFI code by creating and loading shared libraries
module emscripten

nitc :: emscripten

Compile to JavaScript using the Emscripten SDK
module explain_assert

nitc :: explain_assert

Explain failed assert to the console by modifying the AST.
module extra_java_files

nitc :: extra_java_files

Intro the annotation extra_java_files to compile extra java files
module ffi

nitc :: ffi

Full FFI support, independent of the compiler
module ffi_base

nitc :: ffi_base

Tools and utilities for implement FFI with different languages
module frontend

nitc :: frontend

Collect and orchestration of main frontend phases
module global_compiler

nitc :: global_compiler

Global compilation of a Nit program
module header_dependency

nitc :: header_dependency

Tracks which modules has public header code that must be imported
module highlight

nitc :: highlight

Highlighting of Nit AST
module html_commands

nitc :: html_commands

Render commands results as HTML
module html_model

nitc :: html_model

Translate mentities to html blocks.
module htmlight

nitc :: htmlight

Highlighting of Nit AST with HTML
module i18n_phase

nitc :: i18n_phase

Basic support of internationalization through the generation of id-to-string tables
module interpreter

nitc :: interpreter

Interpretation of Nit programs
module ios

nitc :: ios

Compile programs for the iOS platform
module java

nitc :: java

FFI support for the Java language
module java_compiler

nitc :: java_compiler

Compile Nit code to Java code
module json_commands

nitc :: json_commands

Translate command results to json
module json_model

nitc :: json_model

Make model entities Serializable.
module light

nitc :: light

Light FFI support for the compiler
module light_only

nitc :: light_only

Compiler support for the light FFI only, detects unsupported usage of callbacks
module md_commands

nitc :: md_commands

Render commands results as Markdown
module memory_logger

nitc :: memory_logger

Extension to inject memory-tracing instrumentation in code generated by nitc.
module metrics

nitc :: metrics

Various statistics about Nit models and programs
module naive_interpreter

nitc :: naive_interpreter

Interpretation of a Nit program directly on the AST
module nit

nitc :: nit

A naive Nit interpreter
module nitc

nitc :: nitc

A Nit compiler
module nitcatalog

nitc :: nitcatalog

Basic catalog generator for Nit packages
module nitdoc

nitc :: nitdoc

Generator of static API documentation for the Nit language
module nith

nitc :: nith

A ligHt Nit compiler
module nitj

nitc :: nitj

Compile Nit into Java code runnable on the Java Virtual Machine.
module nitlight

nitc :: nitlight

Tool that produces highlighting for Nit programs
module nitmetrics

nitc :: nitmetrics

A program that collects various metrics on nit programs and libraries
module nitni

nitc :: nitni

Native interface related services (used underneath the FFI)
module nitni_callbacks

nitc :: nitni_callbacks

nitni services related to callbacks (used underneath the FFI)
module nitpackage

nitc :: nitpackage

Helpful features about packages
module nitpick

nitc :: nitpick

A program that collect potential style and code issues
module nitrestful

nitc :: nitrestful

Tool generating boilerplate code linking RESTful actions to Nit methods
module nitsaf

nitc :: nitsaf

Nit Static Analysis Framework client example.
module nitserial

nitc :: nitserial

Serialization support compiler, a tool to support deserialization of live generic types
module nitsmells

nitc :: nitsmells

module nituml

nitc :: nituml

UML generator in dot format.
module nitunit

nitc :: nitunit

Testing tool.
module nitvm

nitc :: nitvm

The Nit virtual machine launcher
module nitweb

nitc :: nitweb

Runs a webserver based on nitcorn that render things from model.
module nitx

nitc :: nitx

nitx, a command tool that displays useful data about Nit code
module nullables_metrics

nitc :: nullables_metrics

Statistics about the usage of nullables
module objc

nitc :: objc

FFI support for Objective-C
module on_demand_compiler

nitc :: on_demand_compiler

Compiles extern code within a module to a static library, as needed
module parallelization_phase

nitc :: parallelization_phase

Phase generating threads for functions annotated with threaded annotation
module pkgconfig

nitc :: pkgconfig

Offers the PkgconfigPhase to use the external program "pkg-config" in order
module rapid_type_analysis

nitc :: rapid_type_analysis

Rapid type analysis on the AST
module rta_metrics

nitc :: rta_metrics

Metrics from RTA
module semantize

nitc :: semantize

Process bodies of methods in regard with the model.
module separate_compiler

nitc :: separate_compiler

Separate compilation of a Nit program
module separate_erasure_compiler

nitc :: separate_erasure_compiler

Separate compilation of a Nit program with generic type erasure
module ssa

nitc :: ssa

Single-Static Assignment algorithm from an AST
module static

nitc :: static

Nitdoc generation framework
module static_base

nitc :: static_base

Base entities shared by all the nitdoc code
module static_cards

nitc :: static_cards

Cards templates for the static documentation
module static_html

nitc :: static_html

Render documentation pages as HTML
module static_index

nitc :: static_index

Manage indexing of Nit model for Nitdoc QuickSearch.
module static_structure

nitc :: static_structure

Composes the pages of the static documentation
module term

nitc :: term

module test_astbuilder

nitc :: test_astbuilder

Program used to test the clone method of the astbuilder tool
module test_highlight

nitc :: test_highlight

Program used to test the Nit highlighter
module test_model_visitor

nitc :: test_model_visitor

Example of model_visitor
module test_neo

nitc :: test_neo

Test for neo model saving and loading.
module test_test_phase

nitc :: test_test_phase

Example of simple module that aims to do some specific work on nit programs.
module transform

nitc :: transform

Thansformations that simplify the AST of expressions
module typing

nitc :: typing

Intraprocedural resolution of static types and OO-services
module variables_numbering

nitc :: variables_numbering

Handle all numbering operations related to local variables in the Nit virtual machine
module virtual_machine

nitc :: virtual_machine

Implementation of the Nit virtual machine
module vm

nitc :: vm

Entry point of all vm components
module vm_optimizations

nitc :: vm_optimizations

Optimization of the nitvm
module xcode_templates

nitc :: xcode_templates

Templates and other services to create XCode projects
# Intraprocedural static flow.
module flow

import scope

redef class ToolContext
	# Run `APropdef::do_flow` on each propdef
	var flow_phase: Phase = new FlowPhase(self, [scope_phase])
end

private class FlowPhase
	super Phase

	redef fun process_npropdef(npropdef) do npropdef.do_flow(toolcontext)
end

# The visitor that determine flowcontext for nodes
private class FlowVisitor
	super Visitor

	var current_flow_context = new FlowContext

	var toolcontext: ToolContext

	init
	do
		flows.add(current_flow_context)
		current_flow_context.is_start = true
	end

	var first: nullable ANode = null

	redef fun visit(node)
	do
		if first == null then first = node

		if current_flow_context.node == null then current_flow_context.node = node
		node.accept_flow_visitor(self)
		if node isa AExpr then
			var flow = self.current_flow_context
			node.after_flow_context = flow
			# Force the creation of a specific merge after the analysis of the node.
			if flow.when_true != flow or flow.when_false != flow then
				self.make_sub_flow
				self.current_flow_context.name = "AUTOSUB"
			end
		end

		if first == node then
			#self.printflow
		end
	end

	fun visit_expr(node: AExpr): FlowContext
	do
		self.enter_visit(node)
		return node.after_flow_context.as(not null)
	end

	var flows = new Array[FlowContext]

	fun printflow
	do
		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
				s = "\\nmain={f.node.as(AExpr).after_flow_context.object_id}"
			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
				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
			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")
		file.close
	end


	fun make_sub_flow: FlowContext
	do
		var flow = new FlowContext
		flows.add(flow)
		flow.node = current_node
		flow.add_previous(self.current_flow_context)
		self.current_flow_context = flow
		return flow
	end

	fun make_merge_flow(flow1, flow2: FlowContext): FlowContext
	do
		var flow = new FlowContext
		flows.add(flow)
		flow.node = current_node
		flow.add_previous(flow1)
		flow.add_previous(flow2)
		self.current_flow_context = flow
		return flow
	end

	fun make_true_false_flow(true_flow, false_flow: FlowContext): FlowContext
	do
		var flow = new FlowContext
		flows.add(flow)
		flow.node = current_node
		flow.add_previous(true_flow)
		flow.add_previous(false_flow)
		flow.when_true = true_flow
		flow.when_false = false_flow
		self.current_flow_context = flow
		return flow
	end

	fun make_sub_true_false_flow: FlowContext
	do
		var orig_flow = self.current_flow_context
		var true_flow = new FlowContext
		flows.add(true_flow)
		true_flow.node = current_node
		true_flow.add_previous(orig_flow)
		true_flow.name = "TRUE"
		var false_flow = new FlowContext
		flows.add(false_flow)
		false_flow.node = current_node
		false_flow.add_previous(orig_flow)
		false_flow.name = "FALSE"
		return make_true_false_flow(true_flow, false_flow)
	end

	fun make_unreachable_flow: FlowContext
	do
		var flow = new FlowContext
		flows.add(flow)
		flow.node = current_node
		flow.add_previous(self.current_flow_context)
		flow.is_marked_unreachable = true
		self.current_flow_context = flow
		return flow
	end

	fun merge_continues_to(before_loop: FlowContext, escapemark: nullable EscapeMark)
	do
		if escapemark == null then return
		for b in escapemark.escapes do
			var before = b.before_flow_context
			if before == null then continue # Forward error
			before_loop.add_loop(before)
		end
	end

	fun merge_breaks(escapemark: nullable EscapeMark)
	do
		if escapemark == null then return
		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)
		end
	end
end

# A Node in the static flow graph.
# A same `FlowContext` can be shared by more than one `ANode`.
class FlowContext
	# The reachable previous flow
	var previous = new Array[FlowContext]

	# Additional reachable flow that loop up to self.
	# 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 explicitly marked unreachable?
		if self.is_marked_unreachable then return true

		# Are we the starting flow context?
		if is_start then return false

		# De we have a reachable previous?
		if previous.length == 0 then return true
		return false
	end

	# 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 debugging)
	var node: nullable ANode = null

	# Additional information for the flow (for debugging)
	var name: String = ""

	# The sub-flow to use if the associated expr is true
	var when_true: FlowContext = self

	# The sub-flow to use if the associated expr is true
	var when_false: FlowContext = self

	# Add a previous flow (iff it is reachable)
	private fun add_previous(flow: FlowContext)
	do
		if not flow.is_unreachable and not previous.has(flow) then
			previous.add(flow)
		end
	end

	# Add a previous loop flow (iff it is reachable)
	private fun add_loop(flow: FlowContext)
	do
		if not flow.is_unreachable and not previous.has(flow) then
			loops.add(flow)
		end
	end

end

redef class ANode
	private fun accept_flow_visitor(v: FlowVisitor)
	do
		self.visit_all(v)
	end
end

redef class APropdef
	# The entry point of the whole flow analysis
	fun do_flow(toolcontext: ToolContext)
	do
		var v = new FlowVisitor(toolcontext)
		v.enter_visit(self)
	end


	# The starting flow
	var before_flow_context: nullable FlowContext is noautoinit

	# The ending flow
	var after_flow_context: nullable FlowContext is noautoinit

	redef fun accept_flow_visitor(v)
	do
		self.before_flow_context = v.current_flow_context
		super
		self.after_flow_context = v.current_flow_context
	end
end

redef class AExpr
	# The flow after the full evaluation of the expression/statement
	var after_flow_context: nullable FlowContext
end

redef class AVarAssignExpr
	redef fun accept_flow_visitor(v)
	do
		super
		self.after_flow_context = v.make_sub_flow
	end
end

redef class AReassignFormExpr
	redef fun accept_flow_visitor(v)
	do
		super
		self.after_flow_context = v.make_sub_flow
	end
end

redef class ABlockExpr
	redef fun accept_flow_visitor(v)
	do
		for e in n_expr do
			if not v.current_flow_context.is_unreachable then
				v.enter_visit(e)
			else if not v.current_flow_context.is_already_unreachable then
				v.current_flow_context.is_already_unreachable = true
				v.toolcontext.error(e.hot_location, "Error: unreachable statement.")
			end
		end
	end
end

redef class AReturnExpr
	redef fun accept_flow_visitor(v)
	do
		super
		v.make_unreachable_flow
	end
end

redef class AEscapeExpr
	# 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 AAbortExpr
	redef fun accept_flow_visitor(v)
	do
		super
		v.make_unreachable_flow
	end
end

redef class ADoExpr
	redef fun accept_flow_visitor(v)
	do
		# FlowContext before the block
		var before_block = v.make_sub_flow

		# Visit the bloc, then merge the breaks
		v.enter_visit(self.n_block)
		v.merge_breaks(self.break_mark)
		var after_block =  v.current_flow_context

		# Visit the catch if there is one
		if self.n_catch != null then
			var before_catch = v.make_sub_flow
			v.make_merge_flow(before_block, after_block)
			v.enter_visit(self.n_catch)
			var after_catch = v.current_flow_context
			v.make_merge_flow(before_catch, after_catch)
		end
	end
end

redef class AIfExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_true
		v.enter_visit(self.n_then)
		var after_then = v.current_flow_context

		v.current_flow_context = after_expr.when_false
		v.enter_visit(self.n_else)
		var after_else = v.current_flow_context

		v.make_merge_flow(after_then, after_else)
	end
end

redef class AIfexprExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_true
		v.enter_visit(self.n_then)
		var after_then = v.current_flow_context

		v.current_flow_context = after_expr.when_false
		v.enter_visit(self.n_else)
		var after_else = v.current_flow_context

		v.make_merge_flow(after_then, after_else)
	end
end

redef class AWhileExpr
	redef fun accept_flow_visitor(v)
	do
		var before_loop = v.make_sub_flow

		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_true
		v.enter_visit(self.n_block)
		var after_block = v.current_flow_context

		before_loop.add_loop(after_block)
		v.merge_continues_to(before_loop, self.continue_mark)

		v.current_flow_context = after_expr.when_false
		v.merge_breaks(self.break_mark)
	end
end

redef class ALoopExpr
	redef fun accept_flow_visitor(v)
	do
		var before_loop = v.make_sub_flow

		v.enter_visit(self.n_block)

		var after_block = v.current_flow_context

		before_loop.add_loop(after_block)
		v.merge_continues_to(before_loop, self.continue_mark)

		v.make_unreachable_flow
		v.merge_breaks(self.break_mark)
	end
end

redef class AForExpr
	redef fun accept_flow_visitor(v)
	do
		for g in n_groups do
			v.enter_visit(g.n_expr)
		end

		var before_loop = v.make_sub_flow

		v.enter_visit(self.n_block)

		var after_block = v.current_flow_context

		before_loop.add_loop(after_block)
		v.merge_continues_to(before_loop, self.continue_mark)

		v.make_merge_flow(v.current_flow_context, before_loop)
		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

redef class AAssertExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_false
		v.enter_visit(n_else)
		# the after context of n_else is a dead end, so we do not care

		v.current_flow_context = after_expr.when_true
	end
end

redef class AOrExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_false
		var after_expr2 = v.visit_expr(self.n_expr2)

		var merge_true = v.make_merge_flow(after_expr.when_true, after_expr2.when_true)
		merge_true.name = "OR TRUE"

		v.make_true_false_flow(merge_true, after_expr2.when_false)
	end
end

redef class AImpliesExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_true
		var after_expr2 = v.visit_expr(self.n_expr2)

		var merge_true = v.make_merge_flow(after_expr.when_false, after_expr2.when_true)
		merge_true.name = "OR TRUE"

		v.make_true_false_flow(merge_true, after_expr2.when_false)
	end
end

redef class AAndExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.current_flow_context = after_expr.when_true
		var after_expr2 = v.visit_expr(self.n_expr2)

		var merge_false = v.make_merge_flow(after_expr.when_false, after_expr2.when_false)
		merge_false.name = "AND FALSE"

		v.make_true_false_flow(after_expr2.when_true, merge_false)
	end
end

redef class ANotExpr
	redef fun accept_flow_visitor(v)
	do
		var after_expr = v.visit_expr(self.n_expr)

		v.make_true_false_flow(after_expr.when_false, after_expr.when_true)
	end
end

redef class AOrElseExpr
	redef fun accept_flow_visitor(v)
	do
		super
	end
end

redef class AEqExpr
	redef fun accept_flow_visitor(v)
	do
		super
		v.make_sub_true_false_flow
	end
end


redef class ANeExpr
	redef fun accept_flow_visitor(v)
	do
		super
		v.make_sub_true_false_flow
	end
end

redef class AIsaExpr
	redef fun accept_flow_visitor(v)
	do
		super
		v.make_sub_true_false_flow
	end
end

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)
		v.current_flow_context = after_expr
	end
end
src/semantize/flow.nit:17,1--579,3