Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / modelbuilder.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 module modelbuilder
18
19 import loader
20 import phase
21
22 private import more_collections
23
24 ###
25
26 redef class ToolContext
27 # Option --ignore-visibility
28 var opt_ignore_visibility = new OptionBool("Do not check, and produce errors, on visibility issues", "--ignore-visibility")
29
30 redef init
31 do
32 super
33 option_context.add_option(opt_ignore_visibility)
34 end
35
36 # Combine module to make a single one if required.
37 fun make_main_module(mmodules: Array[MModule]): MModule
38 do
39 assert not mmodules.is_empty
40 var mainmodule
41 # We need a main module, so we build it by importing all modules
42 mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name + "-m", new Location(mmodules.first.location.file, 0, 0, 0, 0))
43 mainmodule.is_fictive = true
44 mainmodule.first_real_mmodule = mmodules.first.first_real_mmodule
45 mainmodule.set_imported_mmodules(mmodules)
46 modelbuilder.apply_conditional_importations(mainmodule)
47 if mainmodule.in_importation.direct_greaters.length == 1 and mainmodule.in_importation.direct_greaters.first == mmodules.first then
48 # Drop the fictive module if not needed
49 mainmodule = mmodules.first
50 else
51 # Or else run phases on it
52 modelbuilder.run_phases
53 end
54 return mainmodule
55 end
56
57 # Run `process_mainmodule` on all phases
58 fun run_global_phases(mmodules: Array[MModule])
59 do
60 if not mmodules.is_empty then
61 var mainmodule = make_main_module(mmodules)
62 for phase in phases_list do
63 if phase.disabled then continue
64 phase.process_mainmodule(mainmodule, mmodules)
65 end
66 end
67
68 check_errors
69 errors_info
70 end
71 end
72
73 redef class Phase
74 # Specific action to execute on the whole program.
75 # Called by the `ToolContext::run_global_phases`.
76 #
77 # `mainmodule` is the main module of the program.
78 # It could be an implicit module (called like the first given_mmodules).
79 #
80 # `given_modules` is the list of explicitely requested modules.
81 # from the command-line for instance.
82 #
83 # REQUIRE: `not given_modules.is_empty`
84 # REQUIRE: `(given_modules.length == 1) == (mainmodule == given_modules.first)`
85 #
86 # @toimplement
87 fun process_mainmodule(mainmodule: MModule, given_mmodules: SequenceRead[MModule]) do end
88 end
89
90
91 redef class ModelBuilder
92 # Run phases on all loaded modules
93 fun run_phases
94 do
95 var mmodules = parsed_modules.to_a
96 model.mmodule_importation_hierarchy.sort(mmodules)
97 var nmodules = new Array[AModule]
98 for mm in mmodules do
99 if mm.is_fictive then continue
100 nmodules.add(mmodule2node(mm).as(not null))
101 end
102 toolcontext.run_phases(nmodules)
103
104 if toolcontext.opt_only_metamodel.value then
105 self.toolcontext.info("*** ONLY METAMODEL", 1)
106 toolcontext.quit
107 end
108 end
109
110 # Load module `filename` and add it as a conditional importation of `mmodule`.
111 #
112 # This means that current (and future) submodules of `module` will also import `filename`.
113 fun inject_module_subimportation(mmodule: MModule, filename: String)
114 do
115 var am = load_module(filename)
116 if am == null then return # forward error
117 var mm = am.mmodule
118 if mm == null then return # forward error
119 # Add the new module before the existing submodules in the hierarchy
120 for subm in mmodule.in_importation.direct_smallers do
121 subm.set_imported_mmodules([mm])
122 end
123 # Register the new module as a conditional_importations for future submodules
124 conditional_importations.add([mm, mmodule])
125 # Register the new amodule to be processed by `run_phases`
126 toolcontext.todo_nmodules.unshift am
127 end
128 end