contrib/jwrapper: use declared upper bounds to set extern parameters types
[nit.git] / contrib / jwrapper / src / javap_visitor.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 # Copyright 2015 Alexis Laferrière <alexis.laf@xymus.net>
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17
18 # Uses a visitor to extract data from the javap output AST
19 # It sends the data to `code_generator` module
20 module javap_visitor
21
22 import javap_test_parser
23 import code_generator
24 import jtype_converter
25 intrude import model
26
27 # Visitor of the AST generated from javap output
28 class JavaVisitor
29 super Visitor
30
31 # Model of all the analyzed classes
32 var model: JavaModel
33
34 # Java class in construction
35 var java_class: JavaClass is noinit
36
37 redef fun visit(n) do n.accept_visitor(self)
38 end
39
40 redef class Node
41 private fun accept_visitor(v: JavaVisitor) do visit_children(v)
42 end
43
44 # ---
45 # Class Header
46
47 redef class Nclass_declaration
48 redef fun accept_visitor(v)
49 do
50 var jtype = n_full_class_name.to_java_type
51
52 v.java_class = new JavaClass(jtype)
53 v.model.add_class v.java_class
54
55 # Visit all properties
56 super
57 end
58 end
59
60 # Extends declaration in the class header
61 redef class Nextends_declaration
62 redef fun accept_visitor(v)
63 do
64 # TODO
65 end
66 end
67
68 # Implements declaration in the class header
69 redef class Nimplements_declaration
70 redef fun accept_visitor(v)
71 do
72 # TODO
73 end
74 end
75
76 # ---
77 # Properties
78
79 # Method declaration
80 redef class Nproperty_declaration_method
81 redef fun accept_visitor(v)
82 do
83 var is_static = false
84 var modifiers = n_modifier
85 if modifiers != null then is_static = modifiers.has_static
86
87 var id = n_identifier.text
88 var return_jtype = n_type.to_java_type
89
90 # Generic parameters
91 var n_params = n_generic_parameters
92 var generic_params
93 if n_params != null then
94 generic_params = n_params.n_parameters.to_a
95 else generic_params = new Array[JavaType]
96
97 # Collect parameters
98 var n_parameters = n_parameters
99 var params
100 if n_parameters != null then
101 params = n_parameters.to_a
102 else params = new Array[JavaType]
103
104 var method = new JavaMethod(is_static, return_jtype, params, generic_params)
105 v.java_class.methods[id].add method
106 end
107 end
108
109 # Constructor declaration
110 redef class Nproperty_declaration_constructor
111 redef fun accept_visitor(v)
112 do
113 # Collect parameters
114 var n_parameters = n_parameters
115 var params
116 if n_parameters != null then
117 params = n_parameters.to_a
118 else params = new Array[JavaType]
119
120 # Generic parameters
121 var n_params = n_generic_parameters
122 var generic_params
123 if n_params != null then
124 generic_params = n_params.n_parameters.to_a
125 else generic_params = new Array[JavaType]
126
127 var method = new JavaConstructor(params, generic_params)
128 v.java_class.constructors.add method
129 end
130 end
131
132 # Variable property declaration
133 redef class Nproperty_declaration_attribute
134 redef fun accept_visitor(v)
135 do
136 var id = n_identifier.text
137 var jtype = n_type.to_java_type
138
139 # Manually count the array depth as it is after the id
140 var brackets = n_brackets
141 if brackets != null then jtype.array_dimension += brackets.children.length
142
143 var is_static = false
144 var modifiers = n_modifier
145 if modifiers != null then is_static = modifiers.has_static
146
147 v.java_class.attributes[id] = new JavaAttribute(is_static, jtype)
148 end
149 end
150
151 # Static property declaration
152 redef class Nproperty_declaration_static
153 redef fun accept_visitor(v)
154 do
155 # TODO
156 end
157 end
158
159 # ---
160 # Services
161
162 redef class Ntype
163 private fun to_java_type: JavaType
164 do
165 var jtype = n_base_type.to_java_type
166
167 var brackets = n_brackets
168 if brackets != null then jtype.array_dimension += brackets.children.length
169
170 return jtype
171 end
172 end
173
174 redef class Nbase_type
175 private fun to_java_type: JavaType
176 do
177 # By default, everything is bound by object
178 var jtype = new JavaType
179 jtype.identifier.add_all(["java", "lang", "object"])
180 return jtype
181 end
182 end
183
184 redef class Nbase_type_class
185 redef fun to_java_type do return n_full_class_name.to_java_type
186 end
187
188 redef class Nbase_type_primitive
189 redef fun to_java_type
190 do
191 # All the concrete nodes under this production are tokens
192 for node in depth do
193 if not node isa NToken then continue
194
195 var jtype = new JavaType
196 jtype.identifier.add node.text
197 return jtype
198 end
199
200 abort
201 end
202 end
203
204 redef class Nbase_type_void
205 redef fun to_java_type
206 do
207 var jtype = new JavaType
208 jtype.is_void = true
209 return jtype
210 end
211 end
212
213 redef class Nbase_type_extends
214 redef fun to_java_type do return n_generic_identifier.to_java_type
215 end
216
217 redef class Nbase_type_super
218 redef fun to_java_type
219 do
220 var bounds = n_type_bound.to_a
221
222 # Java use more than one lower bound,
223 # it can't be translated statically to Nit,
224 # so we use the only the first one.
225 # This may cause problems on complex generic types,
226 # but these cases can be handled manually.
227 return bounds.first
228 end
229 end
230
231 redef class Ngeneric_identifier
232 private fun to_java_type: JavaType is abstract
233 end
234
235 redef class Ngeneric_identifier_class
236 redef fun to_java_type do return n_full_class_name.to_java_type
237 end
238
239 redef class Ngeneric_identifier_wildcard
240 redef fun to_java_type
241 do
242 var jtype = new JavaType
243 jtype.identifier.add_all(["java", "lang", "Object"])
244 return jtype
245 end
246 end
247
248 redef class Nfull_class_name
249 # All the identifiers composing this class name
250 private fun to_a: Array[String] is abstract
251
252 # Access `n_class_name` on both alternatives
253 private fun n_class_name_common: Nclass_name is abstract
254
255 private fun to_java_type: JavaType
256 do
257 var jtype = new JavaType
258 jtype.identifier = to_a
259
260 # Generic parameters
261 var n_params = n_class_name_common.n_generic_parameters
262 if n_params != null then jtype.generic_params = n_params.n_parameters.to_a
263
264 return jtype
265 end
266 end
267
268 redef class Nfull_class_name_head
269 redef fun n_class_name_common do return n_class_name
270
271 redef fun to_a do return [n_class_name.n_identifier.text]
272 end
273
274 redef class Nfull_class_name_tail
275 redef fun n_class_name_common do return n_class_name
276
277 redef fun to_a
278 do
279 var a = n_full_class_name.to_a
280 a.add n_class_name.n_identifier.text
281 return a
282 end
283 end
284
285 redef class Nparameters
286 # Get the types composing this list of parameters
287 #
288 # This is used both on methods signatures and type parameters.
289 private fun to_a: Array[JavaType] is abstract
290 end
291
292 redef class Nparameters_head
293 redef fun to_a do return [n_parameter.to_java_type]
294 end
295
296 redef class Nparameters_tail
297 redef fun to_a
298 do
299 var a = n_parameters.to_a
300 a.add n_parameter.to_java_type
301 return a
302 end
303 end
304
305 redef class Nparameter
306 private fun to_java_type: JavaType
307 do
308 var jtype = n_type.to_java_type
309
310 var dots = n_dots
311 if dots != null then jtype.is_vararg = true
312
313 return jtype
314 end
315 end
316
317 redef class Nodes
318 private fun has_static: Bool
319 do
320 for modifier in depth do
321 if modifier isa NToken and modifier.text == "static" then return true
322 end
323
324 return false
325 end
326 end
327
328 redef class Ntype_bound
329 # Get the types composing this bound
330 private fun to_a: Array[JavaType] is abstract
331 end
332
333 redef class Ntype_bound_head
334 redef fun to_a do return [n_full_class_name.to_java_type]
335 end
336
337 redef class Ntype_bound_tail
338 redef fun to_a
339 do
340 var a = n_type_bound.to_a
341 a.add n_full_class_name.to_java_type
342 return a
343 end
344 end