1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Common things for NIT compilation and C generation
18 package compiling_base
23 redef class ToolContext
24 readable writable attr _global
: Bool = false
25 readable writable attr _compdir
: String
26 readable writable attr _clibdir
: String
27 readable writable attr _bindir
: String
28 readable writable attr _output_file
: String
29 readable writable attr _boost
: Bool = false
30 readable writable attr _no_cc
: Bool = false
31 readable writable attr _ext_prefix
: String
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.
38 # Add a line in the current declaration block
39 meth add_decl
(s
: String)
41 if _indent_level
>= 8 then
42 _ctx
.decls
.add
("\t\t" + s
)
44 _ctx
.decls
.add
(" " * _indent_level
+ s
)
48 # Add a line in the current instr block
49 meth add_instr
(s
: String)
51 if _indent_level
>= 8 then
52 _ctx
.instrs
.add
("\t\t" + s
)
54 _ctx
.instrs
.add
(" " * _indent_level
+ s
)
58 # Return a unique new number for the instance
65 # next number for new_number
66 attr _number_cpt
: Int = 0
68 # Add an indent level.
69 # New decl and instr will be indented.
70 meth indent
do _indent_level
+= 1
72 # Remove an indent level.
76 if _indent_level
< 0 then _indent_level
= 0
79 # Return a big string containing all decl and instr
82 var out
= new Array[String]
83 out
.append
(_ctx
.decls
)
84 out
.append
(_ctx
.instrs
)
89 # The current module processed
90 readable writable attr _module
: MMSrcModule
92 # Where instr and decl are stored
93 readable writable attr _ctx
: CContext = new CContext
95 # The current indent lever
96 readable writable attr _indent_level
: Int = 0
98 # The current ToolContext
99 readable writable attr _tc
: ToolContext
101 # Create a new CompilerVisitor based on a module
102 init(module: MMSrcModule) do _module
= module
105 # Where instr and decl are stored for a module
106 # Note that this class is as badly designed as CompilerVisitor
108 readable attr _decls
: Array[String] = new Array[String]
109 readable attr _instrs
: Array[String] = new Array[String]
111 meth append
(c
: CContext)
113 _instrs
.append
(c
.decls
)
114 _instrs
.append
(c
.instrs
)
117 meth merge
(c
: CContext)
119 _decls
.append
(c
.decls
)
120 _instrs
.append
(c
.instrs
)
126 redef class MMGlobalProperty
127 # C symbol refering a method inocation
128 meth meth_call
: String
130 return "CALL_{intro.cname}"
133 # C symbol refering an attribure access
134 meth attr_access
: String
136 return "ATTR_{intro.cname}"
139 # C symbol refering the color of the global property
140 meth color_id
: String
142 return "COLOR_{intro.cname}"
147 redef class MMGlobalClass
148 # C symbol refering the identifier of the class
151 return "ID_{intro.name}"
154 # C symbol refering the color of the class (for subtype tests)
155 meth color_id
: String
157 return "COLOR_{intro.name}"
160 # C symbol refering the init table position of the class (for constructor linearization)
161 meth init_table_pos_id
: String
163 return "INIT_TABLE_POS_{intro.name}"
167 redef class MMLocalClass
168 # Cached primitive_info result
169 attr _primitive_info_cache
: PrimitiveInfo
171 # If primitive_info result cached?
172 attr _primitive_info_b
: Bool = false
174 # Return the primitive information of the class.
175 # Return null if the class is not primitive
176 # FIXME: Only here since there is no universal type yet
177 meth primitive_info
: PrimitiveInfo
179 if _primitive_info_b
== true then return _primitive_info_cache
181 var ctypes
= once primitive_ctypes
182 if ctypes
.has_key
(name
) then
183 _primitive_info_cache
= ctypes
[name
]
184 _primitive_info_b
= true
185 return _primitive_info_cache
187 var i
= ctypes
.iterator
190 if module.has_global_class_named
(n
) then
191 var c
= module.class_by_name
(n
)
193 _primitive_info_cache
= i
.item
194 _primitive_info_b
= true
195 return _primitive_info_cache
200 _primitive_info_b
= true
204 # Static information of primitive types
205 private meth primitive_ctypes
: HashMap[Symbol, PrimitiveInfo]
207 var res
= new HashMap[Symbol, PrimitiveInfo]
208 var pnames
= ["Int", "Char", "Bool", "Float", "NativeString", "NativeArray", "Pointer"]
209 var tagged
= [true, true, true, false, false, false, false]
210 var cnames
= ["bigint", "char", "int", "float", "char *", "val_t *", "void *"]
211 for i
in [0..pnames
.length
[ do
212 var n
= pnames
[i
].to_symbol
213 var pi
= new PrimitiveInfo
215 pi
.tagged
= tagged
[i
]
223 # Information about a primitive class
225 # The name of the class
226 readable writable attr _name
: Symbol
228 # Is the class tagged (aka not boxed)
229 readable writable attr _tagged
: Bool
231 # The corresponding c type for the primitive value
232 readable writable attr _cname
: String
238 # The corresponding c type
241 var pi
= local_class
.primitive_info
249 # The default c value for uninitialized types.
250 # Return "null" for non primitive types and something more specific for primitive types
251 meth default_cvalue
: String
253 var pi
= local_class
.primitive_info
254 if pi
!= null and pi
.tagged
then
255 return "TAG_{local_class.name}(({pi.cname})0)"
261 # Box (or tag) a primitive value
262 # Is identity if not primitive
263 meth boxtype
(s
: String): String
265 var pi
= local_class
.primitive_info
268 else if pi
.tagged
then
269 return "TAG_{local_class.name}({s})"
271 return "BOX_{local_class.name}({s})"
275 # Unbox (or untag) a primitive value
276 # Is identity if not primitive
277 meth unboxtype
(s
: String): String
279 var pi
= local_class
.primitive_info
282 else if pi
.tagged
then
283 return "UNTAG_{local_class.name}({s})"
285 return "UNBOX_{local_class.name}({s})"
290 redef class MMLocalProperty
291 # Cacher result of cname
292 attr _cname_cache
: String
294 # The mangled name of the method
297 if _cname_cache
== null then
298 _cname_cache
= cmangle
(module.name
, local_class
.name
, name
)
303 # C symbol refering the color of the super call of a super property
304 meth color_id_for_super
: String
306 return "COLOR_SUPER_{cname}"
309 # C macro used to get the function for the call of a super property
310 meth super_meth_call
: String
312 return "CALL_SUPER_{cname}"