1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008-2009 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Analysis control flow and variable visibility in property bodies, statements and expressions
22 # Associate symbols to variable and variables to type
24 abstract class VariableContext
25 # Look for the variable from its name
26 # Return null if nothing found
27 meth
[](s
: Symbol): Variable
29 if _dico
.has_key
(s
) then
36 # Register a new variable with its name
43 meth mark_is_set
(v
: Variable)
48 meth check_is_set
(n
: PNode, v
: Variable)
50 if v
.must_be_set
and not is_set
(v
) then
51 _visitor
.error
(n
, "Error: variable '{v}' is possibly unset.")
54 print
" {x.node.locate}: {x._set_variables.join(", ")} ; {x._dico.join(", ")}"
56 if x0
isa SubVariableContext then
65 # The effective static type of a given variable
66 # May be different from the declaration static type
67 meth stype
(v
: Variable): MMType
72 # Variables by name (in the current context only)
73 attr _dico
: Map[Symbol, Variable]
75 # All variables in all contextes
76 attr _all_variables
: Set[Variable]
78 # Build a new VariableContext
79 meth sub
(node
: PNode): SubVariableContext
81 return new SubVariableContext.with_prev
(self, node
)
84 # Build a nested VariableContext with new variable information
85 meth sub_with
(node
: PNode, v
: Variable, t
: MMType): SubVariableContext
87 return new CastVariableContext.with_prev
(self, node
, v
, t
)
90 # The visitor of the context (used to display error)
91 attr _visitor
: AbsSyntaxVisitor
93 # The syntax node that introduced the context
94 readable attr _node
: PNode
96 init(visitor
: AbsSyntaxVisitor, node
: PNode)
100 _dico
= new HashMap[Symbol, Variable]
103 # Is a control flow break met? (return, break, continue)
104 readable writable attr _unreash
: Bool = false
106 # Is a control flow already broken?
107 # Used to avoid repeating the same error message
108 readable writable attr _already_unreash
: Bool = false
110 # Set of variable that are set (assigned)
111 readable attr _set_variables
: HashSet[Variable] = new HashSet[Variable]
114 meth is_set
(v
: Variable): Bool
116 return _set_variables
.has
(v
)
119 # Merge back one flow context information
120 meth merge
(ctx
: VariableContext)
124 if ctx
.already_unreash
then already_unreash
= true
127 for v
in _all_variables
do
128 if not is_set
(v
) and ctx
.is_set
(v
) then
134 # Merge back two alternative flow context informations
135 meth merge2
(ctx1
, ctx2
: VariableContext)
139 else if ctx2
.unreash
then
142 for v
in _all_variables
do
143 if not is_set
(v
) and ctx1
.is_set
(v
) and ctx2
.is_set
(v
) then
150 class RootVariableContext
151 special VariableContext
152 init(visitor
: AbsSyntaxVisitor, node
: PNode)
155 _all_variables
= new HashSet[Variable]
159 class SubVariableContext
160 special VariableContext
161 readable attr _prev
: VariableContext
165 if _dico
.has_key
(s
) then
177 init with_prev
(p
: VariableContext, node
: PNode)
179 init(p
._visitor
, node
)
181 _all_variables
= p
._all_variables
186 return _set_variables
.has
(v
) or _prev
.is_set
(v
)
190 class CastVariableContext
191 special SubVariableContext
192 attr _variable
: Variable
193 attr _var_type
: MMType
197 if _variable
== v
then
203 init with_prev
(p
: VariableContext, node
: PNode, v
: Variable, t
: MMType)
212 # Is the variable must be set before being used ?
213 meth must_be_set
: Bool do return false
216 redef class VarVariable
217 redef meth must_be_set
do return true