tests: fix sav file for test_for_times
[nit.git] / src / native_interface / ni_metamodel.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2011 Alexis Laferrière <alexis.laf@xymus.net>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Information relevant to the native interface
18 module ni_metamodel
19
20 import compiling
21 import primitive_info
22 import utils
23
24 redef class MMType
25
26 # Friendly name used by frontier and custom code.
27 # It's mainly the nit class name or the primitive type when available.
28 fun friendly_extern_name: String
29 do
30 var pi = local_class.primitive_info
31 if is_nullable then
32 return "nullable_{local_class.name.to_s}"
33 else if pi == null then
34 return local_class.name.to_s
35 else
36 return pi.cname
37 end
38 end
39
40 fun mangled_name: String
41 do
42 var pi = local_class.primitive_info
43 if is_nullable then
44 return "nullable_{local_class.name.to_s}"
45 else
46 return local_class.name.to_s
47 end
48 end
49
50 # Return the expression to convert this type from its native version.
51 fun from_native( name : String ) : String
52 do
53 if ( local_class.primitive_info != null or local_class.global.is_extern ) and
54 not is_nullable then
55 return boxtype( name )
56 else
57 var getter = "{name}->ref.val"
58
59 return boxtype( getter )
60 end
61 end
62
63 # Return the expression to convert and assign this type to its
64 # friendly/native version.
65 fun assign_to_friendly( native_name, nit_name : String ) : String
66 do
67 if ( local_class.primitive_info != null or local_class.global.is_extern ) and
68 not is_nullable then
69 return "{native_name} = {unboxtype( nit_name )}"
70 else
71 return "{native_name}->ref.val = {unboxtype( nit_name )}"
72 end
73 end
74
75 # Return the expression to convert and assign this type to its
76 # generated C version, from friendly/native.
77 fun assign_from_friendly( nit_name, native_name : String ) : String
78 do
79 if ( local_class.primitive_info != null or local_class.global.is_extern ) and
80 not is_nullable then # int, float, point/void* ...
81 return "{nit_name} = {boxtype(native_name)}"
82 else
83 return "{nit_name} = {native_name}->ref.val"
84 end
85 end
86
87 fun uses_nitni_ref : Bool do return local_class.primitive_info == null or is_nullable
88
89 fun friendly_null_getter : String
90 do
91 return "null_{as_notnull.mangled_name}"
92 end
93
94 fun local_friendly_null_getter_from( m : MMModule ) : String
95 do
96 return "{m.to_s}_{friendly_null_getter}"
97 end
98 end
99
100 redef class MMMethod
101 # Local friendly name from a given module.
102 # Used to avoid conflits between modules.
103 fun local_friendly_name_from( m : MMModule, local_class : MMLocalClass ) : String
104 do
105 return "{m.to_s}_{friendly_extern_name(local_class)}"
106 end
107
108 fun friendly_super_cname : String
109 do
110 return "{friendly_extern_name(local_class)}___super"
111 end
112
113 fun local_friendly_super_name_from( m : MMModule ) : String
114 do
115 return "{m.to_s}_{friendly_super_cname}"
116 end
117
118 private fun friendly_cparams( local_class : MMLocalClass ) : List[ String ]
119 do
120 var params = new List[String]
121
122 if not global.is_init then
123 params.add( "{local_class.get_type.friendly_extern_name} recv" )
124 end
125
126 for p in signature.params do
127 params.add( "{p.mmtype.friendly_extern_name} {p.name}" )
128 end
129
130 return params
131 end
132
133 private fun csignature_with_suffix( suffix : String, local_class : MMLocalClass ) : String
134 do
135 var name = "{friendly_extern_name(local_class)}{suffix}"
136
137 return csignature_with_name( name, local_class )
138 end
139
140 private fun csignature_with_name( name : nullable String, local_class : MMLocalClass ) : String
141 do
142 var s = new Buffer
143
144 # return type
145 if signature.return_type != null then
146 s.append( "{signature.return_type.friendly_extern_name} " )
147 else if global.is_init then
148 s.append( "{local_class.get_type.friendly_extern_name} " )
149 else
150 s.append( "void " )
151 end
152
153 # function name
154 if name == null then
155 s.append( friendly_extern_name( local_class ) )
156 else
157 s.append( name )
158 end
159
160 # params
161 var params = friendly_cparams( local_class )
162
163 s.append( "( {params.join( ", " )} )" )
164
165 return s.to_s
166 end
167
168 fun friendly_csignature( local_class : MMLocalClass ) : String
169 do
170 return csignature_with_name( null, local_class )
171 end
172
173 fun frontier_csignature_from( m : MMModule, local_class : MMLocalClass ) : String
174 do
175 return csignature_with_name( local_friendly_name_from(m, local_class), local_class )
176 end
177
178 fun friendly_super_csignature : String
179 do
180 return csignature_with_suffix( "___super", local_class )
181 end
182
183 fun frontier_super_csignature_from( m : MMModule ) : String
184 do
185 return csignature_with_name( local_friendly_super_name_from(m), local_class )
186 end
187
188 fun impl_csignature : String
189 do
190 return csignature_with_suffix( "___impl", local_class )
191 end
192
193 # below is for frontier only
194 private fun cparams : List[ String ]
195 do
196 var params = new List[String]
197 if not global.is_init then params.add( "val_t recv" )
198 for p in signature.params do params.add( "val_t {p.name}" )
199 return params
200 end
201
202 fun out_csignature : String
203 do # boxed types
204 var s = new Buffer
205
206 # return type
207 if signature.return_type != null or global.is_init then
208 s.append( "val_t " )
209 else
210 s.append( "void " )
211 end
212
213 # function name
214 if global.is_init then
215 s.append( "NEW_{local_class}_{cname}" )
216 else
217 s.append( "{friendly_extern_name(local_class)}___out" )
218 end
219
220 # params
221 s.append( "( {cparams.join( ", " )} )" )
222
223 return s.to_s
224 end
225 end
226
227 redef class MMImportedCast
228
229 var in_name : String = "value"
230
231 fun as_friendly_extern_name : String do
232 if is_about_nullable_only then
233 if is_not_null_to_nullable then # to null
234 # nullable_Object Object_as_nullable( Object o )
235 return "{from.mangled_name}_as_nullable"
236 else if is_nullable_to_not_null then # from null
237 # Object Object_as_not_null( nullable_Object o )
238 return "{to.mangled_name}_as_not_null"
239 else
240 abort
241 end
242 else # inter types
243 # String Object_as_String( Object o )
244 return "{from.mangled_name}_as_{to.mangled_name}"
245 end
246 end
247
248 fun as_local_cname( m : MMModule ) : String do
249 return "{m.to_s}_{as_friendly_extern_name}"
250 end
251
252 fun as_local_csignature( m : MMModule ) : String
253 do
254 return "{to.friendly_extern_name} {as_local_cname( m )}( {from.friendly_extern_name} {in_name} )"
255 end
256
257 fun as_friendly_csignature : String
258 do
259 return "{to.friendly_extern_name} {as_friendly_extern_name}( {from.friendly_extern_name} {in_name} )"
260 end
261
262 fun is_a_friendly_extern_name : String do
263 if is_about_nullable_only then
264 if is_not_null_to_nullable then # to null
265 abort # would always be true
266 else if is_nullable_to_not_null then # from null
267 # Object_is_null( nullable_Object o )
268 # is opposite from others
269 return "{to.mangled_name}_is_null"
270 else
271 abort
272 end
273 else # inter types
274 # Object_is_a_String( Object o )
275 return "{from.mangled_name}_is_a_{to.mangled_name}"
276 end
277 end
278
279 fun is_a_local_cname( m : MMModule ) : String do
280 return "{m.to_s}_{is_a_friendly_extern_name}"
281 end
282
283 # Signature of function to check if an object of the "from" type is of
284 # the "to" type.
285 fun is_a_local_csignature( m : MMModule ) : String
286 do
287 return "int {is_a_local_cname( m )}( {from.friendly_extern_name} {in_name} )"
288 end
289
290 fun is_a_friendly_csignature : String
291 do
292 return "int {is_a_friendly_extern_name}( {from.friendly_extern_name} {in_name} )"
293 end
294
295 redef fun hash
296 do
297 return from.hash+to.hash
298 end
299 end