8ce2ef8f8380cc6b965e7d4c178954a255f03c56
[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_types.to_a
95 else generic_params = new Array[JavaType]
96
97 # Collect parameters
98 var n_types = n_types
99 var params
100 if n_types != null then
101 params = n_types.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_types = n_types
115 var params
116 if n_types != null then
117 params = n_types.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_types.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 var dots = n_dots
171 if dots != null then jtype.is_vararg = true
172
173 return jtype
174 end
175 end
176
177 redef class Nbase_type
178 private fun to_java_type: JavaType
179 do
180 # By default, everything is bound by object
181 var jtype = new JavaType
182 jtype.identifier.add_all(["java", "lang", "object"])
183 return jtype
184 end
185 end
186
187 redef class Nbase_type_class
188 redef fun to_java_type do return n_full_class_name.to_java_type
189 end
190
191 redef class Nbase_type_primitive
192 redef fun to_java_type
193 do
194 # All the concrete nodes under this production are tokens
195 for node in depth do
196 if not node isa NToken then continue
197
198 var jtype = new JavaType
199 jtype.identifier.add node.text
200 return jtype
201 end
202
203 abort
204 end
205 end
206
207 redef class Nbase_type_void
208 redef fun to_java_type
209 do
210 var jtype = new JavaType
211 jtype.is_void = true
212 return jtype
213 end
214 end
215
216 redef class Nbase_type_extends
217 redef fun to_java_type do return n_generic_identifier.to_java_type
218 end
219
220 redef class Nbase_type_super
221 redef fun to_java_type
222 do
223 var bounds = n_type_bound.to_a
224
225 # Java use more than one lower bound,
226 # it can't be translated statically to Nit,
227 # so we use the only the first one.
228 # This may cause problems on complex generic types,
229 # but these cases can be handled manually.
230 return bounds.first
231 end
232 end
233
234 redef class Ngeneric_identifier
235 private fun to_java_type: JavaType is abstract
236 end
237
238 redef class Ngeneric_identifier_class
239 redef fun to_java_type do return n_full_class_name.to_java_type
240 end
241
242 redef class Ngeneric_identifier_wildcard
243 redef fun to_java_type
244 do
245 var jtype = new JavaType
246 jtype.identifier.add_all(["java", "lang", "Object"])
247 return jtype
248 end
249 end
250
251 redef class Nfull_class_name
252 # All the identifiers composing this class name
253 private fun to_a: Array[String] is abstract
254
255 # Access `n_class_name` on both alternatives
256 private fun n_class_name_common: Nclass_name is abstract
257
258 private fun to_java_type: JavaType
259 do
260 var jtype = new JavaType
261 jtype.identifier = to_a
262
263 # Generic parameters
264 var n_params = n_class_name_common.n_generic_parameters
265 if n_params != null then jtype.generic_params = n_params.n_types.to_a
266
267 return jtype
268 end
269 end
270
271 redef class Nfull_class_name_head
272 redef fun n_class_name_common do return n_class_name
273
274 redef fun to_a do return [n_class_name.n_identifier.text]
275 end
276
277 redef class Nfull_class_name_tail
278 redef fun n_class_name_common do return n_class_name
279
280 redef fun to_a
281 do
282 var a = n_full_class_name.to_a
283 a.add n_class_name.n_identifier.text
284 return a
285 end
286 end
287
288 redef class Ntypes
289 # Get the types composing this list of parameters
290 #
291 # This is used both on methods signatures and type parameters.
292 private fun to_a: Array[JavaType] is abstract
293 end
294
295 redef class Ntypes_head
296 redef fun to_a do return [n_type.to_java_type]
297 end
298
299 redef class Ntypes_tail
300 redef fun to_a
301 do
302 var a = n_types.to_a
303 a.add n_type.to_java_type
304 return a
305 end
306 end
307
308 redef class Nodes
309 private fun has_static: Bool
310 do
311 for modifier in depth do
312 if modifier isa NToken and modifier.text == "static" then return true
313 end
314
315 return false
316 end
317 end
318
319 redef class Ntype_bound
320 # Get the types composing this bound
321 private fun to_a: Array[JavaType] is abstract
322 end
323
324 redef class Ntype_bound_head
325 redef fun to_a do return [n_full_class_name.to_java_type]
326 end
327
328 redef class Ntype_bound_tail
329 redef fun to_a
330 do
331 var a = n_type_bound.to_a
332 a.add n_full_class_name.to_java_type
333 return a
334 end
335 end