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 # Cached primitive_info result
26 var _primitive_info_cache
: nullable PrimitiveInfo = null
28 # If primitive_info result cached?
29 var _primitive_info_b
: Bool = false
31 # Return the primitive information of the class.
32 # Return null if the class is not primitive
33 fun primitive_info
: nullable PrimitiveInfo
35 if _primitive_info_b
== true then return _primitive_info_cache
37 var ctypes
= once primitive_ctypes
38 if ctypes
.has_key
(name
) then
39 _primitive_info_cache
= ctypes
[name
]
40 _primitive_info_b
= true
41 return _primitive_info_cache
43 var i
= ctypes
.iterator
46 if mmmodule
.has_global_class_named
(n
) then
47 var c
= mmmodule
.class_by_name
(n
)
49 _primitive_info_cache
= i
.item
50 _primitive_info_b
= true
51 return _primitive_info_cache
56 _primitive_info_b
= true
60 # Static information of primitive types
61 private fun primitive_ctypes
: HashMap[Symbol, PrimitiveInfo]
63 var res
= new HashMap[Symbol, PrimitiveInfo]
64 var pnames
= ["Int", "Char", "Bool", "Float", "NativeString", "Pointer"]
65 var tagged
= [true, true, true, false, false, false]
66 var cnames
= ["bigint", "char", "int", "float", "char *", "void *"]
67 for i
in [0..pnames
.length
[ do
68 var n
= pnames
[i
].to_symbol
69 var pi
= new PrimitiveInfo(n
, tagged
[i
], cnames
[i
])
76 # Information about a primitive class
78 # The name of the class
79 readable var _name
: Symbol
81 # Is the class tagged (aka not boxed)
82 readable var _tagged
: Bool
84 # The corresponding c type for the primitive value
85 readable var _cname
: String
87 private init(n
: Symbol, t
: Bool, c
: String)
96 # The corresponding c type
99 var pi
= local_class
.primitive_info
107 # Is the type tagged?
110 if is_nullable
then return false
111 var pi
= local_class
.primitive_info
112 return pi
!= null and pi
.tagged
115 # The default c value for uninitialized types.
116 # Return "null" for non primitive types and something more specific for primitive types
117 fun default_cvalue
: String
119 var pi
= local_class
.primitive_info
120 if pi
!= null and pi
.tagged
then
121 return "TAG_{local_class.name}(({pi.cname})0)"
127 # Box (or tag) a primitive value
128 # Is identity if not primitive
129 fun boxtype
(s
: String): String
131 var pi
= local_class
.primitive_info
132 if pi
== null or is_nullable
then
134 else if pi
.tagged
then
135 return "TAG_{local_class.name}({s})"
137 return "BOX_{local_class.name}({s})"
141 # Unbox (or untag) a primitive value
142 # Is identity if not primitive
143 fun unboxtype
(s
: String): String
145 var pi
= local_class
.primitive_info
146 if pi
== null or is_nullable
then
148 else if pi
.tagged
then
149 return "UNTAG_{local_class.name}({s})"
151 return "UNBOX_{local_class.name}({s})"
157 fun default_extern_name
: String
159 return "{friendly_extern_name(local_class)}___impl"
162 # Friendly name for this method. Is mainly the class name followed by the
163 # function name. It is prefixed with "new" for a constructor.
164 fun friendly_extern_name
( local_class
: MMLocalClass ) : String
166 if not global
.is_init
then
167 var native_fun_name
: String
168 var method_name
= name
.to_s
169 if method_name
== "+" then
170 native_fun_name
= "_plus" # add
171 else if method_name
== "-" then
172 native_fun_name
= "_minus" # sub
173 else if method_name
== "*" then
174 native_fun_name
= "_star" # multi
175 else if method_name
== "/" then
176 native_fun_name
= "_slash" # div
177 else if method_name
== "%" then
178 native_fun_name
= "_percent" # mod
179 else if method_name
== "[]" then
180 native_fun_name
= "_index" # brackets
181 else if method_name
== "[]=" then
182 native_fun_name
= "_index_assign" # brackets
183 else if method_name
== "==" then
184 native_fun_name
= "_equal" # eq
185 else if method_name
== "<" then
186 native_fun_name
= "_less" # lt
187 else if method_name
== ">" then
188 native_fun_name
= "_greater" # gt
189 else if method_name
== "<=" then
190 native_fun_name
= "_less_or_equal" # greater_or_equal
191 else if method_name
== ">=" then
192 native_fun_name
= "_ge" # smaller_or_equal
193 else if method_name
== "!=" then
194 native_fun_name
= "_not_equal" # bang
195 else if method_name
== ">>" then
196 native_fun_name
= "_right"
197 else if method_name
== "<<" then
198 native_fun_name
= "_left"
199 else if method_name
== "<=>" then
200 native_fun_name
= "_starship"
201 else if method_name
[ method_name
.length-1
] == '=' then
202 native_fun_name
= "{method_name.substring(0,method_name.length-1)}__assign"
204 native_fun_name
= method_name
207 return "{local_class.name}_{native_fun_name}"
209 if name
== once
"init".to_symbol
then
210 return "new_{local_class.name}"
212 return "new_{local_class.name}_{name}"