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 _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
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.
39 # Add a line in the current declaration block
40 meth add_decl
(s
: String)
42 if _indent_level
>= 8 then
43 _ctx
.decls
.add
("\t\t" + s
)
45 _ctx
.decls
.add
(" " * _indent_level
+ s
)
49 # Add a line in the current instr block
50 meth add_instr
(s
: String)
52 if _indent_level
>= 8 then
53 _ctx
.instrs
.add
("\t\t" + s
)
55 _ctx
.instrs
.add
(" " * _indent_level
+ s
)
59 # Return a unique new number for the instance
66 # next number for new_number
67 attr _number_cpt
: Int = 0
69 # Add an indent level.
70 # New decl and instr will be indented.
71 meth indent
do _indent_level
+= 1
73 # Remove an indent level.
77 if _indent_level
< 0 then _indent_level
= 0
80 # Return a big string containing all decl and instr
83 var out
= new Array[String]
84 out
.append
(_ctx
.decls
)
85 out
.append
(_ctx
.instrs
)
90 # The current module processed
91 readable writable attr _module
: MMSrcModule
93 # Where instr and decl are stored
94 readable writable attr _ctx
: CContext = new CContext
96 # The current indent lever
97 readable writable attr _indent_level
: Int = 0
99 # The current ToolContext
100 readable writable attr _tc
: ToolContext
102 # Create a new CompilerVisitor based on a module
103 init(module: MMSrcModule) do _module
= module
106 # Where instr and decl are stored for a module
107 # Note that this class is as badly designed as CompilerVisitor
109 readable attr _decls
: Array[String] = new Array[String]
110 readable attr _instrs
: Array[String] = new Array[String]
112 meth append
(c
: CContext)
114 _instrs
.append
(c
.decls
)
115 _instrs
.append
(c
.instrs
)
118 meth merge
(c
: CContext)
120 _decls
.append
(c
.decls
)
121 _instrs
.append
(c
.instrs
)
127 redef class MMGlobalProperty
128 # C symbol refering a method inocation
129 meth meth_call
: String
131 return "CALL_{intro.cname}"
134 # C symbol refering an attribure access
135 meth attr_access
: String
137 return "ATTR_{intro.cname}"
140 # C symbol refering the color of the global property
141 meth color_id
: String
143 return "COLOR_{intro.cname}"
148 redef class MMGlobalClass
149 # C symbol refering the identifier of the class
152 return "ID_{intro.name}"
155 # C symbol refering the color of the class (for subtype tests)
156 meth color_id
: String
158 return "COLOR_{intro.name}"
161 # C symbol refering the init table position of the class (for constructor linearization)
162 meth init_table_pos_id
: String
164 return "INIT_TABLE_POS_{intro.name}"
168 redef class MMLocalClass
169 # Cached primitive_info result
170 attr _primitive_info_cache
: PrimitiveInfo
172 # If primitive_info result cached?
173 attr _primitive_info_b
: Bool = false
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
180 if _primitive_info_b
== true then return _primitive_info_cache
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
188 var i
= ctypes
.iterator
191 if module.has_global_class_named
(n
) then
192 var c
= module.class_by_name
(n
)
194 _primitive_info_cache
= i
.item
195 _primitive_info_b
= true
196 return _primitive_info_cache
201 _primitive_info_b
= true
205 # Static information of primitive types
206 private meth primitive_ctypes
: HashMap[Symbol, PrimitiveInfo]
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
216 pi
.tagged
= tagged
[i
]
224 # Information about a primitive class
226 # The name of the class
227 readable writable attr _name
: Symbol
229 # Is the class tagged (aka not boxed)
230 readable writable attr _tagged
: Bool
232 # The corresponding c type for the primitive value
233 readable writable attr _cname
: String
239 # The corresponding c type
242 var pi
= local_class
.primitive_info
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
254 var pi
= local_class
.primitive_info
255 if pi
!= null and pi
.tagged
then
256 return "TAG_{local_class.name}(({pi.cname})0)"
262 # Box (or tag) a primitive value
263 # Is identity if not primitive
264 meth boxtype
(s
: String): String
266 var pi
= local_class
.primitive_info
269 else if pi
.tagged
then
270 return "TAG_{local_class.name}({s})"
272 return "BOX_{local_class.name}({s})"
276 # Unbox (or untag) a primitive value
277 # Is identity if not primitive
278 meth unboxtype
(s
: String): String
280 var pi
= local_class
.primitive_info
283 else if pi
.tagged
then
284 return "UNTAG_{local_class.name}({s})"
286 return "UNBOX_{local_class.name}({s})"
291 redef class MMLocalProperty
292 # Cacher result of cname
293 attr _cname_cache
: String
295 # The mangled name of the method
298 if _cname_cache
== null then
299 _cname_cache
= cmangle
(module.name
, local_class
.name
, name
)
304 # C symbol refering the color of the super call of a super property
305 meth color_id_for_super
: String
307 return "COLOR_SUPER_{cname}"
310 # C macro used to get the function for the call of a super property
311 meth super_meth_call
: String
313 return "CALL_SUPER_{cname}"