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
25 readable writable attr _attr_sim
: Bool
26 readable writable attr _base_dir
: 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
31 readable writable attr _no_cc
: Bool
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
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
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
)
121 redef class MMGlobalProperty
122 # C symbol refering a method inocation
123 meth meth_call
: String
125 return "CALL_{intro.cname}"
128 # C symbol refering an attribure access
129 meth attr_access
: String
131 return "ATTR_{intro.cname}"
134 # C symbol refering the color of the global property
135 meth color_id
: String
137 return "COLOR_{intro.cname}"
142 redef class MMGlobalClass
143 # C symbol refering the identifier of the class
146 return "ID_{intro.name}"
149 # C symbol refering the color of the class (for subtype tests)
150 meth color_id
: String
152 return "COLOR_{intro.name}"
155 # C symbol refering the init table position of the class (for constructor linearization)
156 meth init_table_pos_id
: String
158 return "INIT_TABLE_POS_{intro.name}"
162 redef class MMLocalClass
163 # Cached primitive_info result
164 attr _primitive_info_cache
: PrimitiveInfo
166 # If primitive_info result cached?
167 attr _primitive_info_b
: Bool
169 # Return the primitive information of the class.
170 # Return null if the class is not primitive
171 # FIXME: Only here since there is no universal type yet
172 meth primitive_info
: PrimitiveInfo
174 if _primitive_info_b
== true then return _primitive_info_cache
176 var ctypes
= once primitive_ctypes
177 if ctypes
.has_key
(name
) then
178 _primitive_info_cache
= ctypes
[name
]
179 _primitive_info_b
= true
180 return _primitive_info_cache
182 var i
= ctypes
.iterator
185 if module.has_global_class_named
(n
) then
186 var c
= module.class_by_name
(n
)
188 _primitive_info_cache
= i
.item
189 _primitive_info_b
= true
190 return _primitive_info_cache
195 _primitive_info_b
= true
199 # Static information of primitive types
200 private meth primitive_ctypes
: HashMap[Symbol, PrimitiveInfo]
202 var res
= new HashMap[Symbol, PrimitiveInfo]
203 var pnames
= ["Int", "Char", "Bool", "Float", "NativeString", "NativeArray", "Pointer"]
204 var tagged
= [true, true, true, false, false, false, false]
205 var cnames
= ["int", "char", "int", "float", "char *", "val_t *", "void *"]
206 for i
in [0..pnames
.length
[ do
207 var n
= pnames
[i
].to_symbol
208 var pi
= new PrimitiveInfo
210 pi
.tagged
= tagged
[i
]
218 # Information about a primitive class
220 # The name of the class
221 readable writable attr _name
: Symbol
223 # Is the class tagged (aka not boxed)
224 readable writable attr _tagged
: Bool
226 # The corresponding c type for the primitive value
227 readable writable attr _cname
: String
233 # The corresponding c type
236 var pi
= local_class
.primitive_info
244 # The default c value for uninitialized types.
245 # Return "null" for non primitive types and something more specific for primitive types
246 meth default_cvalue
: String
248 var pi
= local_class
.primitive_info
249 if pi
!= null and pi
.tagged
then
250 return "TAG_{local_class.name}(({pi.cname})0)"
256 # Box (or tag) a primitive value
257 # Is identity if not primitive
258 meth boxtype
(s
: String): String
260 var pi
= local_class
.primitive_info
263 else if pi
.tagged
then
264 return "TAG_{local_class.name}({s})"
266 return "BOX_{local_class.name}({s})"
270 # Unbox (or untag) a primitive value
271 # Is identity if not primitive
272 meth unboxtype
(s
: String): String
274 var pi
= local_class
.primitive_info
277 else if pi
.tagged
then
278 return "UNTAG_{local_class.name}({s})"
280 return "UNBOX_{local_class.name}({s})"
285 redef class MMLocalProperty
286 # Cacher result of cname
287 attr _cname_cache
: String
289 # The mangled name of the method
292 if _cname_cache
== null then
293 _cname_cache
= cmangle
(concrete_property
.module.name
, concrete_property
.local_class
.name
, name
)
298 # C symbol refering the color of the super call of a super property
299 meth color_id_for_super
: String
301 return "COLOR_SUPER_{cname}"