Do not use CALL macro directly.
[nit.git] / src / compiling / compiling_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 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 # Common things for NIT compilation and C generation
18 package compiling_base
19
20 import syntax
21 private import utils
22
23 redef class ToolContext
24 readable writable attr _global: Bool = false
25 readable writable attr _attr_sim: Bool = false
26 readable writable attr _compdir: String
27 readable writable attr _clibdir: String
28 readable writable attr _bindir: String
29 readable writable attr _output_file: String
30 readable writable attr _boost: Bool = false
31 readable writable attr _no_cc: Bool = false
32 readable writable attr _ext_prefix: String
33 end
34
35 # Class used to generate files.
36 # Note that in fact it is not a visitor.
37 # Note also that this class is unefficient and poorly designed thus requires love.
38 class CompilerVisitor
39 # Add a line in the current declaration block
40 meth add_decl(s: String)
41 do
42 if _indent_level >= 8 then
43 _ctx.decls.add("\t\t" + s)
44 else
45 _ctx.decls.add(" " * _indent_level + s)
46 end
47 end
48
49 # Add a line in the current instr block
50 meth add_instr(s: String)
51 do
52 if _indent_level >= 8 then
53 _ctx.instrs.add("\t\t" + s)
54 else
55 _ctx.instrs.add(" " * _indent_level + s)
56 end
57 end
58
59 # Return a unique new number for the instance
60 meth new_number: Int
61 do
62 var res = _number_cpt
63 _number_cpt = res + 1
64 return res
65 end
66 # next number for new_number
67 attr _number_cpt: Int = 0
68
69 # Add an indent level.
70 # New decl and instr will be indented.
71 meth indent do _indent_level += 1
72
73 # Remove an indent level.
74 meth unindent
75 do
76 _indent_level -= 1
77 if _indent_level < 0 then _indent_level = 0
78 end
79
80 # Return a big string containing all decl and instr
81 redef meth to_s
82 do
83 var out = new Array[String]
84 out.append(_ctx.decls)
85 out.append(_ctx.instrs)
86 out.add("")
87 return out.join("\n")
88 end
89
90 # The current module processed
91 readable writable attr _module: MMSrcModule
92
93 # Where instr and decl are stored
94 readable writable attr _ctx: CContext = new CContext
95
96 # The current indent lever
97 readable writable attr _indent_level: Int = 0
98
99 # The current ToolContext
100 readable writable attr _tc: ToolContext
101
102 # Create a new CompilerVisitor based on a module
103 init(module: MMSrcModule) do _module = module
104 end
105
106 # Where instr and decl are stored for a module
107 # Note that this class is as badly designed as CompilerVisitor
108 class CContext
109 readable attr _decls: Array[String] = new Array[String]
110 readable attr _instrs: Array[String] = new Array[String]
111
112 meth append(c: CContext)
113 do
114 _instrs.append(c.decls)
115 _instrs.append(c.instrs)
116 end
117
118 meth merge(c: CContext)
119 do
120 _decls.append(c.decls)
121 _instrs.append(c.instrs)
122 end
123
124 init do end
125 end
126
127 redef class MMGlobalProperty
128 # C symbol refering a method inocation
129 meth meth_call: String
130 do
131 return "CALL_{intro.cname}"
132 end
133
134 # C symbol refering an attribure access
135 meth attr_access: String
136 do
137 return "ATTR_{intro.cname}"
138 end
139
140 # C symbol refering the color of the global property
141 meth color_id: String
142 do
143 return "COLOR_{intro.cname}"
144 end
145
146 end
147
148 redef class MMGlobalClass
149 # C symbol refering the identifier of the class
150 meth id_id: String
151 do
152 return "ID_{intro.name}"
153 end
154
155 # C symbol refering the color of the class (for subtype tests)
156 meth color_id: String
157 do
158 return "COLOR_{intro.name}"
159 end
160
161 # C symbol refering the init table position of the class (for constructor linearization)
162 meth init_table_pos_id: String
163 do
164 return "INIT_TABLE_POS_{intro.name}"
165 end
166 end
167
168 redef class MMLocalClass
169 # Cached primitive_info result
170 attr _primitive_info_cache: PrimitiveInfo
171
172 # If primitive_info result cached?
173 attr _primitive_info_b: Bool = false
174
175 # Return the primitive information of the class.
176 # Return null if the class is not primitive
177 # FIXME: Only here since there is no universal type yet
178 meth primitive_info: PrimitiveInfo
179 do
180 if _primitive_info_b == true then return _primitive_info_cache
181
182 var ctypes = once primitive_ctypes
183 if ctypes.has_key(name) then
184 _primitive_info_cache = ctypes[name]
185 _primitive_info_b = true
186 return _primitive_info_cache
187 end
188 var i = ctypes.iterator
189 while i.is_ok do
190 var n = i.key
191 if module.has_global_class_named(n) then
192 var c = module.class_by_name(n)
193 if cshe < c then
194 _primitive_info_cache = i.item
195 _primitive_info_b = true
196 return _primitive_info_cache
197 end
198 end
199 i.next
200 end
201 _primitive_info_b = true
202 return null
203 end
204
205 # Static information of primitive types
206 private meth primitive_ctypes: HashMap[Symbol, PrimitiveInfo]
207 do
208 var res = new HashMap[Symbol, PrimitiveInfo]
209 var pnames = ["Int", "Char", "Bool", "Float", "NativeString", "NativeArray", "Pointer"]
210 var tagged = [true, true, true, false, false, false, false]
211 var cnames = ["bigint", "char", "int", "float", "char *", "val_t *", "void *"]
212 for i in [0..pnames.length[ do
213 var n = pnames[i].to_symbol
214 var pi = new PrimitiveInfo
215 pi.name = n
216 pi.tagged = tagged[i]
217 pi.cname = cnames[i]
218 res[n] = pi
219 end
220 return res
221 end
222 end
223
224 # Information about a primitive class
225 class PrimitiveInfo
226 # The name of the class
227 readable writable attr _name: Symbol
228
229 # Is the class tagged (aka not boxed)
230 readable writable attr _tagged: Bool
231
232 # The corresponding c type for the primitive value
233 readable writable attr _cname: String
234
235 private init do end
236 end
237
238 redef class MMType
239 # The corresponding c type
240 meth cname: String
241 do
242 var pi = local_class.primitive_info
243 if pi == null then
244 return "val_t"
245 else
246 return pi.cname
247 end
248 end
249
250 # The default c value for uninitialized types.
251 # Return "null" for non primitive types and something more specific for primitive types
252 meth default_cvalue: String
253 do
254 var pi = local_class.primitive_info
255 if pi != null and pi.tagged then
256 return "TAG_{local_class.name}(({pi.cname})0)"
257 else
258 return "NIT_NULL"
259 end
260 end
261
262 # Box (or tag) a primitive value
263 # Is identity if not primitive
264 meth boxtype(s: String): String
265 do
266 var pi = local_class.primitive_info
267 if pi == null then
268 return s
269 else if pi.tagged then
270 return "TAG_{local_class.name}({s})"
271 else
272 return "BOX_{local_class.name}({s})"
273 end
274 end
275
276 # Unbox (or untag) a primitive value
277 # Is identity if not primitive
278 meth unboxtype(s: String): String
279 do
280 var pi = local_class.primitive_info
281 if pi == null then
282 return s
283 else if pi.tagged then
284 return "UNTAG_{local_class.name}({s})"
285 else
286 return "UNBOX_{local_class.name}({s})"
287 end
288 end
289 end
290
291 redef class MMLocalProperty
292 # Cacher result of cname
293 attr _cname_cache: String
294
295 # The mangled name of the method
296 meth cname: String
297 do
298 if _cname_cache == null then
299 _cname_cache = cmangle(module.name, local_class.name, name)
300 end
301 return _cname_cache
302 end
303
304 # C symbol refering the color of the super call of a super property
305 meth color_id_for_super: String
306 do
307 return "COLOR_SUPER_{cname}"
308 end
309
310 # C macro used to get the function for the call of a super property
311 meth super_meth_call: String
312 do
313 return "CALL_SUPER_{cname}"
314 end
315 end
316