phase: use a better name on output
[nit.git] / src / phase.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Phases of the processing of nit programs
16 module phase
17
18 import toolcontext
19 import parser
20 import poset
21
22 redef class ToolContext
23 # The various registered phases to performs
24 # The order in the poset is the dependance of phases
25 #
26 # While you can directly modify the poset (nodes and edges),
27 # it is often simpler to use the constructor in `Phase`
28 var phases = new POSet[Phase]
29
30 fun phases_list: Sequence[Phase]
31 do
32 var phases = self.phases.to_a
33 self.phases.sort(phases)
34 return phases
35 end
36
37 # Run all registered phases on a set of modules
38 fun run_phases(nmodules: Collection[AModule])
39 do
40 var time0 = get_time
41 self.info("*** SEMANTIC ANALYSIS ***", 1)
42 #phases.show_dot
43
44 var phases = phases_list
45
46 for phase in phases do
47 self.info(" registered phases: {phase}", 2)
48 end
49
50 for nmodule in nmodules do
51 self.info("Semantic analysis module {nmodule.location.file.filename}", 2)
52 for phase in phases do
53 self.info(" phase: {phase}", 3)
54 assert phase.toolcontext == self
55 var errcount = self.error_count
56 phase.process_nmodule(nmodule)
57 if errcount != self.error_count then
58 self.check_errors
59 break
60 end
61 errcount = self.error_count
62 for nclassdef in nmodule.n_classdefs do
63 self.info(" phase: {phase} for {nclassdef.location}", 3)
64 assert phase.toolcontext == self
65 phase.process_nclassdef(nclassdef)
66 for npropdef in nclassdef.n_propdefs do
67 assert phase.toolcontext == self
68 phase.process_npropdef(npropdef)
69 end
70 end
71 if errcount != self.error_count then
72 self.check_errors
73 break
74 end
75 var v = new AnnotationPhaseVisitor(phase)
76 v.enter_visit(nmodule)
77 if errcount != self.error_count then
78 self.check_errors
79 break
80 end
81 end
82 self.check_errors
83 end
84
85 var time1 = get_time
86 self.info("*** END SEMANTIC ANALYSIS: {time1-time0} ***", 2)
87 end
88 end
89
90 private class AnnotationPhaseVisitor
91 super Visitor
92
93 var phase: Phase
94
95 init(phase: Phase) do self.phase = phase
96
97 redef fun visit(n)
98 do
99 n.visit_all(self)
100 if n isa AAnnotation then phase.process_annotated_node(n.parent.parent.as(not null), n)
101 end
102 end
103
104 # Abstraction of steps in the analysis/processing of Nit programs
105 # Specific phases should implements one of the `process_*` method
106 abstract class Phase
107 # The toolcontext instance attached to the phase
108 var toolcontext: ToolContext
109
110 # The dependence relation of the phase with the other phases
111 var in_hierarchy: POSetElement[Phase]
112
113 # Initialize and register a phase to the toolcontext
114 init(toolcontext: ToolContext, depends: nullable Collection[Phase])
115 do
116 self.toolcontext = toolcontext
117 in_hierarchy = toolcontext.phases.add_node(self)
118 if depends != null then
119 for d in depends do
120 toolcontext.phases.add_edge(self, d)
121 end
122 end
123 end
124
125 # By default, the name is the lowercased prefix of the classname
126 redef fun to_s do return class_name.strip_extension("Phase").to_lower
127
128 # Specific actions to execute on the whole tree of a module
129 # @toimplement
130 fun process_nmodule(nmodule: AModule) do end
131
132 # Specific actions to execute on the tree of a class definition
133 # Note that the order of the visit is the one of the file
134 # @toimplement
135 fun process_nclassdef(nclassdef: AClassdef) do end
136
137 # Specific actions to execute on the tree of a property
138 # Note that the order of the visit is the one of the file
139 # @toimplement
140 fun process_npropdef(npropdef: APropdef) do end
141
142 # Specific actions to execute on annotated nodes
143 # Note that the order of the visit is the one of the file
144 # @toimplement
145 fun process_annotated_node(node: ANode, nat: AAnnotation) do end
146 end