9c5cbc2ff97da6aab2799f7bb2faf201aa57d341
1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
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 # Services to generate extern class `in "Java"`
24 var file_out
: OFStream
25 fun code_warehouse
: CodeWarehouse do return once
new CodeWarehouse
27 init (file_name
: String)
29 file_out
= new OFStream.open
(file_name
)
32 fun gen_class_header
(full_class_name
: Array[String])
34 file_out
.write
("extern class Native{full_class_name.last} in \"Java\
" `\{ {full_class_name.join(".")} `\}")
35 file_out
.write
("\tsuper JavaObject\n\tredef type SELF: Native{full_class_name.last}\n\n")
38 fun gen_variable
(jid
: String, jtype
: JavaType)
40 file_out
.write
("\tvar {jid.to_snake_case}: {jtype.to_nit_type}\n")
43 fun gen_method
(jparam_list
: Array[JavaType], jreturn_type
: JavaType, jmethod_id
: String)
49 var nit_types
= new Array[NitType]
53 for i
in [0..jparam_list
.length
[ do
54 var jparam
= jparam_list
[i
]
55 var nit_type
= jparam
.to_nit_type
58 if not jparam
.is_collection
then cast
= jparam
.param_cast
60 nit_types
.add
(nit_type
)
61 nit_type
.arg_id
= "{nit_id}{nit_id_no}"
63 if i
== jparam_list
.length
- 1 then
64 java_params
+= "{cast}{nit_id}{nit_id_no}"
65 nit_params
+= "{nit_id}{nit_id_no}: {nit_type}"
67 java_params
+= "{cast}{nit_id}{nit_id_no}" + ", "
68 nit_params
+= "{nit_id}{nit_id_no}: {nit_type}, "
72 # Comment if one type is unknown
73 if not nit_type
.is_complete
then comment
= "#"
77 var method_id
= jmethod_id
.to_snake_case
78 var nit_signature
= new Array[String]
80 nit_signature
.add
"\tfun {method_id}"
82 if not jparam_list
.is_empty
then
83 nit_signature
.add
"({nit_params})"
86 var return_type
= null
88 if not jreturn_type
.is_void
then
89 return_type
= jreturn_type
.to_nit_type
90 if not return_type
.is_complete
then comment
= "#"
91 nit_signature
.add
": {return_type} "
94 file_out
.write
(comment
+ nit_signature
.join
(""))
96 var param_to_copy
= param_to_copy
(jparam_list
, nit_types
)
98 # Copy one parameter, the return value, one parameter and the return value or nothing
99 if return_type
!= null then
100 if return_type
.is_complete
and jreturn_type
.is_collection
then
101 if param_to_copy
!= null then
102 var rtype_couple
= new Couple[JavaType, NitType](jreturn_type
, return_type
)
103 file_out
.write
(code_warehouse
.param_return_copy
(rtype_couple
, param_to_copy
, jmethod_id
, java_params
))
105 file_out
.write
(code_warehouse
.return_type_copy
(jreturn_type
, return_type
, jmethod_id
, java_params
))
107 else if param_to_copy
!= null then
108 file_out
.write
(code_warehouse
.param_type_copy
(param_to_copy
.first
, param_to_copy
.second
, jmethod_id
, java_params
, true))
110 file_out
.write
(" in \"Java\
" `\{\n\t\t{comment}return {jreturn_type.return_cast} recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
112 else if jreturn_type
.is_void
then
113 if param_to_copy
!= null then
114 file_out
.write
(code_warehouse
.param_type_copy
(param_to_copy
.first
, param_to_copy
.second
, jmethod_id
, java_params
, false))
116 file_out
.write
(" in \"Java\
" `\{\n\t\t{comment}recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
119 file_out
.write
(" in \"Java\
" `\{\n\t\t{comment}recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
123 # Only one collection type parameter can be copied
124 # If there's none or more than one then `null` is returned
125 fun param_to_copy
(jtypes
: Array[JavaType], ntypes
: Array[NitType]): nullable Couple[JavaType, NitType]
129 for i
in [0..jtypes
.length
[ do
130 if jtypes
[i
].is_collection
and ntypes
[i
].is_complete
then
132 if counter
> 1 then return null
133 couple
= new Couple[JavaType, NitType](jtypes
[i
], ntypes
[i
])
141 # Contains raw code mostly used to copy collections
144 # Collection as return value
145 fun return_type_copy
(java_type
: JavaType, nit_type
: NitType, jmethod_id
, params_id
: String): String
147 var narray_id
= "nit_array"
148 var loop_
= create_loop
(java_type
, nit_type
, false, "java_array", narray_id
)
149 var imports
= create_imports
(nit_type
, false)
151 return """{{{imports}}} in "Java" `{
152 {{{java_type.to_s}}} java_array = recv.{{{jmethod_id}}}({{{params_id}}});
153 int {{{narray_id}}} = new_{{{nit_type.id}}}_of_{{{nit_type.generic_params.join("_")}}}();
157 return {{{narray_id}}};
162 # Collection as parameter
163 fun param_type_copy
(java_type
: JavaType, nit_type
: NitType, jmethod_id
, params_id
: String, has_return
: Bool): String
165 var narray_id
= "nit_array"
166 var jarray_id
= "java_array"
167 var loop_
= create_loop
(java_type
, nit_type
, true, jarray_id
, narray_id
)
168 var imports
= create_imports
(nit_type
, true)
169 var jtype
= java_type
.to_s
170 var jinstanciation
= create_array_instance
(java_type
, nit_type
, jarray_id
)
174 return_str
= "return "
177 params_id
= params_id
.replace
(nit_type
.arg_id
, jarray_id
)
179 return """{{{imports}}} in "Java" `{
181 int {{{narray_id}}} = new_{{{nit_type.id}}}_of_{{{nit_type.generic_params.join("_")}}}();
185 {{{return_str}}}recv.{{{jmethod_id}}}({{{params_id}}});
190 # One collection parameter and the return type will be copied
191 fun param_return_copy
(return_types
, param_types
: Couple[JavaType, NitType], jmethod_id
, params_id
: String): String
193 var narray_id
= "nit_array"
194 var narray_id2
= "nit_array2"
196 var r_jtype
= return_types
.first
197 var r_ntype
= return_types
.second
199 var p_jtype
= param_types
.first
200 var p_ntype
= param_types
.second
202 var r_loop
= create_loop
(r_jtype
, r_ntype
, false, "java_array", narray_id
)
203 var p_loop
= create_loop
(p_jtype
, p_ntype
, true, "java_array2", narray_id2
)
205 var imports
= new Array[String]
207 # Avoid import duplication
208 if p_ntype
.to_s
!= r_ntype
.to_s
then
209 imports
.add create_imports
(p_ntype
, true)
212 imports
.add create_imports
(r_ntype
, false)
214 params_id
= params_id
.replace
(p_ntype
.arg_id
, narray_id
)
216 var jinstanciation
= create_array_instance
(p_jtype
, p_ntype
, "java_array")
218 return """{{{imports.join(", ")}}} in "Java" `{
223 {{{r_jtype.to_s}}} java_array2 = recv.{{{jmethod_id}}}({{{params_id}}});
224 int {{{narray_id2}}} = new_{{{r_ntype.id}}}_of_{{{r_ntype.generic_params.join("_")}}}();
228 return {{{narray_id2}}};
233 private fun create_array_instance
(java_type
: JavaType, nit_type
: NitType, jarray_id
: String): String
235 var jtype
= java_type
.to_s
236 var instanciation
= ""
238 if java_type
.is_primitive_array
then
239 instanciation
= "{jtype} {jarray_id} = new {java_type.full_id}[Array_of_{nit_type.generic_params[0]}_length({nit_type.arg_id})];"
241 instanciation
= "{jtype} {jarray_id} = new {jtype}();"
247 private fun create_imports
(nit_type
: NitType, is_param
: Bool): String
250 var ntype
= nit_type
.to_s
251 var gen_type
= nit_type
.generic_params
.join
(", ")
254 if nit_type
.is_map
then
255 imports
= """import {{{ntype}}}, {{{ntype}}}.[]="""
257 imports
= """import {{{ntype}}}, {{{ntype}}}.add"""
259 else if nit_type
.id
== "Array" then
260 imports
= """import {{{ntype}}}.length, {{{ntype}}}.[]"""
261 else if nit_type
.is_map
then
262 imports
= """import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item, Iterator[{{{gen_type}}}].key"""
264 imports
= """import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item"""
270 private fun create_loop
(java_type
: JavaType, nit_type
: NitType, is_param
: Bool, jarray_id
, narray_id
: String): String
274 var gen_type
= nit_type
.generic_params
.join
("_")
277 if java_type
.is_primitive_array
then
278 loop_header
= "for(int i=0; i < {jarray_id}.length; ++i)"
279 loop_body
= """\t\t\t{{{jarray_id}}}[i] = {{{java_type.param_cast}}}Array_of_{{{gen_type}}}__index({{{nit_type.arg_id}}}, i);"""
280 else if nit_type
.id
== "Array" then
281 loop_header
= """int length = Array_of_{{{gen_type}}}_length({{{nit_type.arg_id}}});\n\t\tfor(int i=0; i < length; ++i)"""
282 loop_body
= """\t\t\t{{{jarray_id}}}.add({{{java_type.param_cast}}}Array_of_{{{gen_type}}}__index({{{narray_id}}}, i));"""
284 loop_header
= """int itr = {{{nit_type.id}}}_of_{{{gen_type}}}_iterator({{{nit_type.arg_id}}});\n\t\twhile(Iterator_of_{{{gen_type}}}_is_ok(itr)) {"""
285 if nit_type
.is_map
then
286 var key_cast
= java_type
.to_cast
(java_type
.generic_params
[0].id
, true)
287 var value_cast
= java_type
.to_cast
(java_type
.generic_params
[1].id
, true)
288 loop_body
= """\t\t\t{{{jarray_id}}}[{{{key_cast}}}iterator_of_{{{nit_type.id}}}_key(itr)] = {{{value_cast}}}iterator_of_{{{nit_type.id}}}_item(itr);\n\t\t\titerator_of_{{{gen_type}}}_next(itr);\n\t\t}"""
290 loop_body
= """\t\t\t{{{jarray_id}}}.add({{{java_type.param_cast}}}iterator_of_{{{nit_type.id}}}_item(itr));\n\t\t\titerator_of_{{{gen_type}}}_next(itr);\n\t\t}"""
294 if nit_type
.is_map
then
295 var key_cast
= java_type
.to_cast
(java_type
.generic_params
[0].id
, false)
296 var value_cast
= java_type
.to_cast
(java_type
.generic_params
[1].id
, false)
297 loop_header
= """for (java.util.Map.Entry<{{{java_type.generic_params[0]}}}, {{{java_type.generic_params[1]}}}> e: {{{jarray_id}}})"""
298 loop_body
= """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_{{{nit_type.generic_params[1]}}}__index_assign({{{narray_id}}}, {{{key_cast}}}e.getKey(), {{{value_cast}}}e.getValue()); """
299 else if java_type
.is_iterable
then
300 loop_header
= """for ({{{java_type.generic_params[0]}}} e: {{{jarray_id}}})"""
301 loop_body
= """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_add({{{narray_id}}}, {{{java_type.return_cast}}}e);"""
303 loop_header
= "for(int i=0; i < {jarray_id}.length; ++i)"
304 loop_body
= """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_add({{{narray_id}}}, {{{java_type.return_cast}}}{{{jarray_id}}}[i]);"""
308 return loop_header
+ "\n" + loop_body