1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2009 Jean-Sebastien Gelinas <calestar@gmail.com>
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 # This package introduces an algorithm to find all methods reachable
18 # from at least one reachable initializer
19 package reachable_from_init_method_analysis_impl
21 import reachable_from_init_method_analysis
22 import reachable_method_analysis
25 readable var _program
: Program
26 readable var _context
: RFIMAContext = new RFIMAContext
33 program
.with_each_live_local_classes
!action
(c
) do
34 # For each reachable constructors for this class
35 for g
in c
.global_properties
do
37 if not p
.global
.is_init_for
(c
) then continue
39 if not program
.rma
.as(not null).is_method_reachable
(p
) then continue
40 if not c
.new_instance_iroutine
.has_key
(p
) then continue
41 var ir
= c
.new_instance_iroutine
[p
]
43 # Process this constructor
44 context
.reachable_from_init_iroutines
.add
(ir
)
45 (new RFIMAVisitor(context
, program
)).visit_iroutine
(ir
)
52 special ReachableFromInitMethodAnalysis
53 readable var _reachable_from_init_iroutines
: HashSet[IRoutine] = new HashSet[IRoutine]
55 redef fun is_iroutine_reachable_from_init
(ir
: nullable IRoutine): Bool do
56 return ir
!= null and reachable_from_init_iroutines
.has
(ir
)
59 redef fun is_method_reachable_from_init
(method
: MMMethod): Bool do
60 return is_iroutine_reachable_from_init
(method
.iroutine
)
66 readable var _context
: RFIMAContext
67 readable var _program
: Program
69 init (context
: RFIMAContext, p
: Program) do
74 fun process_call
(iroutine
: IRoutine) do
75 if context
.is_iroutine_reachable_from_init
(iroutine
) then return
76 context
.reachable_from_init_iroutines
.add
(iroutine
)
77 visit_iroutine
(iroutine
)
80 redef fun visit_icode
(ic
)
82 if ic
isa IStaticCall then
83 # FIXME: take only the last property on the redef. hierarchie
84 var ir
= ic
.property
.iroutine
85 if ir
!= null then process_call
(ir
)
86 else if ic
isa INew then
87 # FIXME: take only the last property on the redef. hierarchie
89 var cls
= t
.for_module
(program
.main_module
).local_class
90 var m
= cls
[ic
.property
.global
].as(MMMethod)
91 var r
= cls
.new_instance_iroutine
[m
]
93 else if ic
isa ISuper then
94 # Process possible calls
95 var method
= ic
.property
96 for greater
in method
.prhe
.greaters_and_self
do
97 if greater
isa MMMethod then
98 var ir
= greater
.iroutine
99 if ir
!= null then process_call
(ir
)
102 else if ic
isa ICall then
103 # Process possible calls
104 var method
= ic
.property
105 var ir
= method
.iroutine
106 if ir
!= null then process_call
(ir
)
107 for other
in method
.prhe
.smallers
do
108 if other
isa MMMethod then
110 if ir
!= null then process_call
(ir
)
113 else if ic
isa ICheckInstance then
115 var cls
= t
.for_module
(program
.main_module
).local_class
116 var ir
= cls
.checknew_iroutine
117 if ir
!= null then process_call
(ir
)
118 else if ic
isa IInitAttributes then
120 var cls
= t
.for_module
(program
.main_module
).local_class
121 var ir
= cls
.init_var_iroutine
122 if ir
!= null then process_call
(ir
)