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