ni_nitdoc: added fast copy past utility to signatures.
[nit.git] / src / program.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2009 Jean-Sebastien Gelinas <calestar@gmail.com>
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 # Common things to represent a Nit program/library
18 package program
19
20 import metamodel
21 import icode
22 private import primitive_info
23 import mmloader
24
25 redef class ToolContext
26 readable writable var _global: Bool = false
27 writable var _use_SFT_optimization: Bool = true
28
29 # We can say that we are using SFT optimization *only* when we are
30 # doing global compilation and we enabled the command line option
31 fun use_SFT_optimization: Bool do return global and _use_SFT_optimization
32 end
33
34 # Instances of this class represent a program/library that will
35 # be analyzed/compiled by nitc
36 class Program
37 # This is the ToolContext associated with this Program
38 # It contains (amongts other things) the command line options
39 readable var _tc: ToolContext
40
41 # This module is the 'main' module, the one where we find the 'main' method
42 readable var _main_module: MMModule
43
44 # This method is the entry point of this program
45 # There might be no entry point (if in fact we are compiling a library)
46 readable var _main_method: nullable MMMethod = null
47
48 # This is the class that contains the main method.
49 # Would be null if there is no main method
50 readable var _main_class: nullable MMLocalClass = null
51
52 # This method will ensure that all the metamodel is computed before we
53 # start using all the classes
54 private fun finish_processing_classes do
55 var classes = new Array[MMLocalClass]
56 for c in main_module.local_classes do
57 c.compute_super_classes
58 classes.add(c)
59 end
60
61 for c in classes do
62 c.compute_ancestors
63 end
64 end
65
66 fun compute_main_method do
67 # Check for the 'Sys' class
68 var sysname = once "Sys".to_symbol
69 if not main_module.has_global_class_named(sysname) then return
70 var sys = main_module.class_by_name(sysname)
71
72 # Check for 'Sys::main' method
73 var entryname = once "main".to_symbol
74 if not sys.has_global_property_by_name(entryname) then return
75
76 _main_method = sys.select_method(entryname)
77 _main_class = sys
78 end
79
80 # Generation of allocation function of this class
81 fun generate_allocation_iroutines
82 do
83 for c in main_module.local_classes do
84 if c.global.is_abstract or c.global.is_interface then continue
85 var pi = c.primitive_info
86 if pi == null then
87 do
88 # Generate INIT_ATTRIBUTES routine
89 var iself = new IRegister(c.get_type)
90 var iselfa = [iself]
91 var iroutine = new IRoutine(iselfa, null)
92 var icb = new ICodeBuilder(main_module, iroutine)
93
94 for sc in c.che.linear_extension.reversed do
95 for g in sc.global_properties do
96 if g.local_class != sc then continue
97 if not g.intro isa MMAttribute then continue
98 var p = c[g]
99 var t = p.signature.return_type
100 if p isa MMAttribute and t != null then
101 var ir = p.iroutine
102 if ir == null then continue
103 # FIXME: Not compatible with sep compilation
104 var e = icb.inline_routine(ir, iselfa, null).as(not null)
105 icb.stmt(new IAttrWrite(p, iself, e))
106 end
107 end
108 end
109
110 c.init_var_iroutine = iroutine
111 end
112 do
113 # Compile CHECKNAME
114 var iself = new IRegister(c.get_type)
115 var iselfa = [iself]
116 var iroutine = new IRoutine(iselfa, null)
117 var icb = new ICodeBuilder(main_module, iroutine)
118 for g in c.global_properties do
119 if not g.intro isa MMAttribute then continue
120 var p = c[g]
121 var t = p.signature.return_type
122 if p isa MMAttribute and t != null and not t.is_nullable then
123 icb.add_attr_check(p, iself)
124 end
125 end
126
127 c.checknew_iroutine = iroutine
128 end
129
130 for g in c.global_properties do
131 # FIXME skip invisible constructors
132 if not g.is_init_for(c) then continue
133 var p = c[g]
134 assert p isa MMMethod
135
136 var iself = new IRegister(c.get_type)
137 var iparams = new Array[IRegister]
138 for i in [0..p.signature.arity[ do iparams.add(new IRegister(p.signature[i]))
139 var iroutine = new IRoutine(iparams, iself)
140 iroutine.location = p.iroutine.location
141 var icb = new ICodeBuilder(main_module, iroutine)
142
143 var inew = new IAllocateInstance(c.get_type)
144 inew.result = iself
145 icb.stmt(inew)
146 var iargs = [iself]
147 iargs.add_all(iparams)
148
149 icb.stmt(new IInitAttributes(c.get_type, iself))
150 icb.stmt(new IStaticCall(p, iargs))
151 icb.stmt(new ICheckInstance(c.get_type, iself))
152
153 c.new_instance_iroutine[p] = iroutine
154 end
155 end
156 end
157 end
158
159 # This function will call the attached block for each IRoutines
160 # in this program
161 fun with_each_iroutines
162 !action(i: IRoutine, m: MMModule)
163 do
164 for m in main_module.mhe.greaters_and_self do
165 for c in m.local_classes do
166 var iroutine: nullable IRoutine = null
167
168 # Process methods and attributes initialization
169 for p in c.local_local_properties do
170 if p isa MMAttribute then
171 iroutine = p.iroutine
172 else if p isa MMMethod then
173 iroutine = p.iroutine
174 end
175 if iroutine == null then continue
176 action(iroutine, m)
177 end
178
179 # Process class-specific iroutines
180 iroutine = c.init_var_iroutine
181 if iroutine != null then
182 action(iroutine, m)
183 end
184 iroutine = c.checknew_iroutine
185 if iroutine != null then
186 action(iroutine, m)
187 end
188 for i in c.new_instance_iroutine.values do
189 action(i, m)
190 end
191 end
192 end
193 end
194
195 # This function will call the attached block for each MMMethods
196 # in this program
197 fun with_each_methods
198 !action(m: MMMethod)
199 do
200 for m in main_module.mhe.greaters_and_self do
201 for c in m.local_classes do
202 # Process methods and attributes initialization
203 for p in c.local_local_properties do
204 if p isa MMMethod then
205 action(p)
206 end
207 end
208 end
209 end
210 end
211
212 # This function will call the attached block for each live local classes
213 # in this program
214 fun with_each_live_local_classes
215 !action(m: MMLocalClass)
216 do
217 for c in main_module.local_classes do
218 action(c)
219 end
220 end
221
222 init(m: MMModule, toolcontext: ToolContext) do
223 _main_module = m
224 _tc = toolcontext
225 finish_processing_classes
226 end
227 end
228
229 redef class MMLocalClass
230 # IRoutine for the initialization of the default attributes (called by IInitAttributes)
231 readable writable var _init_var_iroutine: nullable IRoutine = null
232 # IRoutine to validate the instance after initialization (called by ICheckInstance)
233 readable writable var _checknew_iroutine: nullable IRoutine = null
234 # IRoutines to call to create a new valid instance (memory allocated, object initialized and validated)
235 # These iroutines will call: IAllocateInstance, IInitAttributes, some init function and ICheckInstance
236 # These routines will be called by INew
237 readable var _new_instance_iroutine: HashMap[MMMethod, IRoutine] = new HashMap[MMMethod, IRoutine]
238 end