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 primitive_info
20 #FIXME Split this module into 2: one in metamodel and one in compiling
24 redef class MMLocalClass
25 # extern type of extern classes
26 fun extern_c_type
: String is abstract
28 # Cached primitive_info result
29 var _primitive_info_cache
: nullable PrimitiveInfo = null
31 # If primitive_info result cached?
32 var _primitive_info_b
: Bool = false
34 # Return the primitive information of the class.
35 # Return null if the class is not primitive
36 fun primitive_info
: nullable PrimitiveInfo
38 if _primitive_info_b
== true then return _primitive_info_cache
40 var ctypes
= once primitive_ctypes
41 if ctypes
.has_key
(name
) then
42 _primitive_info_cache
= ctypes
[name
]
43 _primitive_info_b
= true
44 return _primitive_info_cache
46 if global
.is_extern
then
47 var pi
= new PrimitiveInfo( name
, false, extern_c_type
)
48 _primitive_info_cache
= pi
49 _primitive_info_b
= true
50 return _primitive_info_cache
52 var i
= ctypes
.iterator
55 if mmmodule
.has_global_class_named
(n
) then
56 var c
= mmmodule
.class_by_name
(n
)
58 _primitive_info_cache
= i
.item
59 _primitive_info_b
= true
60 return _primitive_info_cache
65 _primitive_info_b
= true
69 # Static information of primitive types
70 private fun primitive_ctypes
: HashMap[Symbol, PrimitiveInfo]
72 var res
= new HashMap[Symbol, PrimitiveInfo]
73 var pnames
= ["Int", "Char", "Bool", "Float", "NativeString", "Pointer"]
74 var tagged
= [true, true, true, false, false, false]
75 var cnames
= ["bigint", "char", "int", "float", "char *", "void *"]
76 for i
in [0..pnames
.length
[ do
77 var n
= pnames
[i
].to_symbol
78 var pi
= new PrimitiveInfo(n
, tagged
[i
], cnames
[i
])
85 # Information about a primitive class
87 # The name of the class
88 readable var _name
: Symbol
90 # Is the class tagged (aka not boxed)
91 readable var _tagged
: Bool
93 # The corresponding c type for the primitive value
94 readable var _cname
: String
96 private init(n
: Symbol, t
: Bool, c
: String)
105 # The corresponding c type
108 var pi
= local_class
.primitive_info
116 # Is the type tagged?
119 if is_nullable
then return false
120 var pi
= local_class
.primitive_info
121 return pi
!= null and pi
.tagged
124 # The default c value for uninitialized types.
125 # Return "null" for non primitive types and something more specific for primitive types
126 fun default_cvalue
: String
128 var pi
= local_class
.primitive_info
129 if pi
!= null and pi
.tagged
then
130 return "TAG_{local_class.name}(({pi.cname})0)"
136 # Box (or tag) a primitive value
137 # Is identity if not primitive
138 fun boxtype
(s
: String): String
140 var pi
= local_class
.primitive_info
141 if pi
== null or is_nullable
then
143 else if pi
.tagged
then
144 return "TAG_{local_class.name}({s})"
146 return "BOX_{local_class.name}({s})"
150 # Unbox (or untag) a primitive value
151 # Is identity if not primitive
152 fun unboxtype
(s
: String): String
154 var pi
= local_class
.primitive_info
155 if pi
== null or is_nullable
then
157 else if pi
.tagged
then
158 return "UNTAG_{local_class.name}({s})"
160 return "UNBOX_{local_class.name}({s})"
166 fun default_extern_name
: String
168 return "{friendly_extern_name(local_class)}___impl"
171 # Friendly name for this method. Is mainly the class name followed by the
172 # function name. It is prefixed with "new" for a constructor.
173 fun friendly_extern_name
( local_class
: MMLocalClass ) : String
175 if not global
.is_init
then
176 var native_fun_name
: String
177 var method_name
= name
.to_s
178 if method_name
== "+" then
179 native_fun_name
= "_plus" # add
180 else if method_name
== "-" then
181 native_fun_name
= "_minus" # sub
182 else if method_name
== "*" then
183 native_fun_name
= "_star" # multi
184 else if method_name
== "/" then
185 native_fun_name
= "_slash" # div
186 else if method_name
== "%" then
187 native_fun_name
= "_percent" # mod
188 else if method_name
== "[]" then
189 native_fun_name
= "_index" # brackets
190 else if method_name
== "[]=" then
191 native_fun_name
= "_index_assign" # brackets
192 else if method_name
== "==" then
193 native_fun_name
= "_equal" # eq
194 else if method_name
== "<" then
195 native_fun_name
= "_less" # lt
196 else if method_name
== ">" then
197 native_fun_name
= "_greater" # gt
198 else if method_name
== "<=" then
199 native_fun_name
= "_less_or_equal" # greater_or_equal
200 else if method_name
== ">=" then
201 native_fun_name
= "_ge" # smaller_or_equal
202 else if method_name
== "!=" then
203 native_fun_name
= "_not_equal" # bang
204 else if method_name
== ">>" then
205 native_fun_name
= "_right"
206 else if method_name
== "<<" then
207 native_fun_name
= "_left"
208 else if method_name
== "<=>" then
209 native_fun_name
= "_starship"
210 else if method_name
[ method_name
.length-1
] == '=' then
211 native_fun_name
= "{method_name.substring(0,method_name.length-1)}__assign"
213 native_fun_name
= method_name
216 return "{local_class.name}_{native_fun_name}"
218 if name
== once
"init".to_symbol
then
219 return "new_{local_class.name}"
221 return "new_{local_class.name}_{name}"