syntax: merge control_flow.nit in typing.nit
[nit.git] / src / syntax / control_flow.nit
diff --git a/src/syntax/control_flow.nit b/src/syntax/control_flow.nit
deleted file mode 100644 (file)
index d13568e..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2008 Jean Privat <jean@pryen.org>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Analysis control flow in property bodies, statements and expressions
-package control_flow
-
-import syntax_base
-
-redef class MMSrcModule
-       # Walk trough the module and type statments and expressions
-       # Require than supermodules are processed
-       meth do_control_flow(tc: ToolContext)
-       do
-               var tv = new ControlFlowVisitor(tc, self)
-               tv.visit(node)
-       end
-end
-
-redef class Variable
-       # Is the variable must be set before being used ?
-       meth must_be_set: Bool do return false
-end
-
-redef class VarVariable
-       redef meth must_be_set do return true
-end
-
-
-
-# Control flow visitor
-# * Check reachability in methods
-# * Associate breaks and continues
-# * Check some other warning
-private class ControlFlowVisitor
-special AbsSyntaxVisitor
-       redef meth visit(n)
-       do
-               if n != null then n.accept_control_flow(self)
-       end
-
-       # Number of nested once
-       readable writable attr _once_count: Int = 0
-
-       # Current knowledge about variables types
-       readable writable attr _control_flow_ctx: ControlFlowContext
-
-       meth check_is_set(n: PNode, v: Variable)
-       do
-               if v.must_be_set and not control_flow_ctx.is_set(v) then
-                       error(n, "Error: variable '{v}' is possibly unset.")
-                       var cfc = control_flow_ctx
-                       while cfc != null do
-                               print("cfc: " + cfc.set_variables.join(" "))
-                               cfc = cfc.prev
-                       end
-               end
-       end
-
-       meth mark_is_set(v: Variable)
-       do
-               control_flow_ctx.set_variables.add(v)
-       end
-
-       init(tc, m) do super
-end
-
-private class ControlFlowContext
-       # Previous control flow context if any
-       readable attr _prev: ControlFlowContext
-
-       # Is a control flow break met? (return, break, continue)
-       readable writable attr _unreash: Bool = false
-
-       # Is a control flow already broken?
-       # Used to avoid repeating the same error message
-       readable writable attr _already_unreash: Bool = false
-
-       # Set of variable that are set (assigned)
-       readable attr _set_variables: HashSet[Variable] = new HashSet[Variable]
-
-       # Is a variable set?
-       meth is_set(v: Variable): Bool
-       do
-               return _set_variables.has(v) or (_prev != null and _prev.is_set(v))
-       end
-
-       meth sub: ControlFlowContext
-       do
-               return new ControlFlowContext.with_prev(self)
-       end
-
-       init
-       do 
-       end
-
-       init with_prev(p: ControlFlowContext)
-       do
-               _prev = p
-               _unreash = p.unreash
-               _already_unreash = p.already_unreash
-       end
-end
-
-###############################################################################
-
-redef class PNode
-       private meth accept_control_flow(v: ControlFlowVisitor) 
-       do
-               accept_abs_syntax_visitor(v)
-       end
-end
-
-redef class AMethPropdef
-       redef meth accept_control_flow(v)
-       do
-               v.control_flow_ctx = new ControlFlowContext
-               super
-       end
-end
-
-redef class AConcreteMethPropdef
-       redef meth accept_control_flow(v)
-       do
-               super
-               if v.control_flow_ctx.unreash == false and method.signature.return_type != null then
-                       v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
-               end
-       end
-end
-
-redef class AVardeclExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               if n_expr != null then v.mark_is_set(variable)
-       end
-end
-
-redef class ABlockExpr
-       redef meth accept_control_flow(v)
-       do
-               for e in n_expr do
-                       if v.control_flow_ctx.unreash and not v.control_flow_ctx.already_unreash then
-                               v.control_flow_ctx.already_unreash = true
-                               v.warning(e, "Warning: unreachable statement.")
-                       end
-                       v.visit(e)
-               end
-       end
-end
-
-redef class AReturnExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.control_flow_ctx.unreash = true
-       end
-end
-
-redef class ABreakExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.control_flow_ctx.unreash = true
-       end
-end
-redef class AContinueExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.control_flow_ctx.unreash = true
-       end
-end
-
-redef class AAbortExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.control_flow_ctx.unreash = true
-       end
-end
-
-redef class AClosureCallExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               if variable.closure.is_break then v.control_flow_ctx.unreash = true
-       end
-end
-
-redef class AIfExpr
-       redef meth accept_control_flow(v)
-       do
-               v.visit(n_expr)
-
-               var old_control_flow_ctx = v.control_flow_ctx
-               v.control_flow_ctx = v.control_flow_ctx.sub
-
-               v.visit(n_then)
-
-               if n_else == null then
-                       # Restore control flow ctx since the 'then" block is optional
-                       v.control_flow_ctx = old_control_flow_ctx
-               else
-                       # Remember what appens in the 'then'
-                       var then_control_flow_ctx = v.control_flow_ctx
-                       # Reset to execute the 'else'
-                       v.control_flow_ctx = old_control_flow_ctx.sub
-
-                       v.visit(n_else)
-
-                       # Merge then and else in the old control_flow
-                       old_control_flow_ctx.unreash = v.control_flow_ctx.unreash and then_control_flow_ctx.unreash
-
-                       if v.control_flow_ctx.unreash then v.control_flow_ctx = then_control_flow_ctx
-                       if then_control_flow_ctx.unreash then then_control_flow_ctx = v.control_flow_ctx
-                       for variable in v.control_flow_ctx.set_variables do
-                               if then_control_flow_ctx.is_set(variable) then
-                                       old_control_flow_ctx.set_variables.add(variable)
-                               end
-                       end
-                       v.control_flow_ctx = old_control_flow_ctx
-               end
-       end
-end
-
-class AControlableBlock
-special PExpr
-       redef meth accept_control_flow(v)
-       do
-               # Store old control flow values
-               var old_control_flow_ctx = v.control_flow_ctx
-               v.control_flow_ctx = v.control_flow_ctx.sub
-
-               super
-
-               # Check control flow if any
-               check_control_flow(v)
-
-               # Restore control flow value since all controlable blocks are optionnal
-               v.control_flow_ctx = old_control_flow_ctx
-       end
-
-       private meth check_control_flow(v: ControlFlowVisitor) do end
-end
-
-redef class AWhileExpr
-special AControlableBlock
-end
-
-redef class AForExpr
-special AControlableBlock
-end
-
-redef class AVarExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.check_is_set(self, variable)
-       end
-end
-
-redef class AVarAssignExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.mark_is_set(variable)
-       end
-end
-
-redef class AVarReassignExpr
-       redef meth accept_control_flow(v)
-       do
-               super
-               v.check_is_set(self, variable)
-               v.mark_is_set(variable)
-       end
-end
-
-redef class AClosureDecl
-       redef meth accept_control_flow(v)
-       do
-               if n_expr != null then
-                       var old_control_flow_ctx = v.control_flow_ctx
-                       v.control_flow_ctx = v.control_flow_ctx.sub
-
-                       super
-
-                       if v.control_flow_ctx.unreash == false then
-                               if variable.closure.signature.return_type != null then
-                                       v.error(self, "Control error: Reached end of block (a 'continue' with a value was expected).")
-                               else if variable.closure.is_break then
-                                       v.error(self, "Control error: Reached end of break block (an 'abort' was expected).")
-                               end
-                       end
-
-                       v.control_flow_ctx = old_control_flow_ctx
-               end
-       end
-end
-
-redef class AClosureDef
-special AControlableBlock
-       redef meth accept_control_flow(v)
-       do
-               for va in variables do v.mark_is_set(va)
-               super
-       end
-
-       redef meth check_control_flow(v)
-       do
-               if v.control_flow_ctx.unreash == false then
-                       if closure.signature.return_type != null then
-                               v.error(self, "Control error: Reached end of block (a 'continue' with a value was expected).")
-                       else if closure.is_break then
-                               v.error(self, "Control error: Reached end of break block (a 'break' was expected).")
-                       end
-               end
-       end
-end
-
-redef class AOnceExpr
-       redef meth accept_control_flow(v)
-       do
-               if v.once_count > 0 then
-                       v.warning(self, "Useless once in a once expression.")
-               end
-               v.once_count = v.once_count + 1
-
-               super
-
-               v.once_count = v.once_count - 1
-       end
-end
-