1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. All Rights Reserved. 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%% %CopyrightEnd% 19%% 20%% 21 22-module(ic_array_java). 23 24-export([gen/4]). 25 26-include("ic.hrl"). 27-include("icforms.hrl"). 28 29 30gen(G, N, X, Array) when is_record(X, member) -> 31 ArrayName = ic_forms:get_java_id(Array), 32 ArrayElement = ic_forms:get_type(X), 33 emit_holder_class(G, N, X, Array, ArrayName, ArrayElement), 34 emit_helper_class(G, N, X, Array, ArrayName, ArrayElement); 35gen(G, N, X, Array) when is_record(X, case_dcl) -> 36 ArrayName = ic_forms:get_java_id(Array), 37 ArrayElement = ic_forms:get_type(X), 38 emit_holder_class(G, N, X, Array, ArrayName, ArrayElement), 39 emit_helper_class(G, N, X, Array, ArrayName, ArrayElement); 40gen(G, N, X, Array) -> 41 ArrayName = ic_forms:get_java_id(Array), 42 ArrayElement = ic_forms:get_body(X), 43 emit_holder_class(G, N, X, Array, ArrayName, ArrayElement), 44 emit_helper_class(G, N, X, Array, ArrayName, ArrayElement). 45 46 47 48%%----------------------------------------------------------------- 49%% Func: emit_holder_class/4 50%%----------------------------------------------------------------- 51emit_holder_class(G, N, _X, Array, ArrayName, ArrayElement) -> 52 SName = string:concat(ArrayName, "Holder"), 53 {Fd, _}= ic_file:open_java_file(G, N, SName), 54 55 ArrayElementName = ic_java_type:getType(G, N, ArrayElement), 56 EmptyDim = arrayEmptyDim(Array), 57 58 ic_codegen:emit(Fd, "final public class ~sHolder {\n",[ArrayName]), 59 60 ic_codegen:emit(Fd, " // instance variables\n", []), 61 ic_codegen:emit(Fd, " public ~s~s value;\n\n", 62 [ArrayElementName,EmptyDim]), 63 64 ic_codegen:emit(Fd, " // constructors\n", []), 65 ic_codegen:emit(Fd, " public ~sHolder() {}\n", [ArrayName]), 66 ic_codegen:emit(Fd, " public ~sHolder(~s~s initial) {\n", 67 [ArrayName,ArrayElementName,EmptyDim]), 68 ic_codegen:emit(Fd, " value = initial;\n", []), 69 ic_codegen:emit(Fd, " }\n", []), 70 ic_codegen:nl(Fd), 71 72 ic_codegen:emit(Fd, " // methods\n", []), 73 74 ic_codegen:emit(Fd, " public void _marshal(~sOtpOutputStream out)\n", [?ERLANGPACKAGE]), 75 ic_codegen:emit(Fd, " throws java.lang.Exception {\n"), 76 ic_codegen:emit(Fd, " ~sHelper.marshal(out, value);\n", [ArrayName]), 77 ic_codegen:emit(Fd, " }\n"), 78 ic_codegen:nl(Fd), 79 ic_codegen:emit(Fd, " public void _unmarshal(~sOtpInputStream in)\n", [?ERLANGPACKAGE]), 80 ic_codegen:emit(Fd, " throws java.lang.Exception {\n"), 81 ic_codegen:emit(Fd, " value = ~sHelper.unmarshal(in);\n", [ArrayName]), 82 ic_codegen:emit(Fd, " }\n", []), 83 ic_codegen:nl(Fd), 84 85 ic_codegen:emit(Fd, "}\n", []), 86 file:close(Fd). 87 88 89%%----------------------------------------------------------------- 90%% Func: emit_helper_class/4 91%%----------------------------------------------------------------- 92emit_helper_class(G, N, X, Array, ArrayName, ArrayElement) -> 93 SName = string:concat(ArrayName, "Helper"), 94 {Fd, _}= ic_file:open_java_file(G, N, SName), 95 96 ArrayElementName = ic_java_type:getType(G, N, ArrayElement), 97 EmptyDim = arrayEmptyDim(Array), 98% Dim = arrayDim(G,N,Array), 99 100 ic_codegen:emit(Fd, "public class ~sHelper {\n",[ArrayName]), 101 102 ic_codegen:emit(Fd, " // constructors\n"), 103 ic_codegen:emit(Fd, " private ~sHelper() {}\n\n", [ArrayName]), 104 105 ic_codegen:emit(Fd, " // methods\n"), 106 107 ic_codegen:emit(Fd, " public static void marshal(~sOtpOutputStream _out, ~s~s _value)\n", 108 [?ERLANGPACKAGE,ArrayElementName,EmptyDim]), 109 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 110 emit_array_marshal_loop(G,N,X,Array,ArrayElement,Fd), 111 ic_codegen:emit(Fd, " }\n"), 112 ic_codegen:nl(Fd), 113 ic_codegen:emit(Fd, " public static ~s~s unmarshal(~sOtpInputStream _in)\n", 114 [ArrayElementName,EmptyDim,?ERLANGPACKAGE]), 115 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 116 ic_codegen:emit(Fd, " ~s~s _value = new ~s;\n\n", 117 [ArrayElementName,EmptyDim,ic_java_type:getFullType(G, N, X, Array)]), 118 emit_array_unmarshal_loop(G,N,X,Array,ArrayElement,Fd), 119 ic_codegen:emit(Fd, " return _value;\n"), 120 ic_codegen:emit(Fd, " }\n\n"), 121 122 ic_codegen:emit(Fd, " public static String id() {\n", []), 123 ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, Array)]), 124 ic_codegen:emit(Fd, " }\n\n"), 125 126 ic_codegen:emit(Fd, " public static String name() {\n", []), 127 ic_codegen:emit(Fd, " return ~p;\n",[ArrayName]), 128 ic_codegen:emit(Fd, " }\n\n"), 129 130 ic_jbe:emit_type_function(G, N, X, Fd), 131 132 ic_codegen:emit(Fd, " public static void insert(~sAny _any, ~s~s _this)\n", 133 [?ICPACKAGE,ArrayElementName,EmptyDim]), 134 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 135 136 ic_codegen:emit(Fd, " ~sOtpOutputStream _os = \n",[?ERLANGPACKAGE]), 137 ic_codegen:emit(Fd, " new ~sOtpOutputStream();\n\n",[?ERLANGPACKAGE]), 138 139 ic_codegen:emit(Fd, " _any.type(type());\n"), 140 ic_codegen:emit(Fd, " marshal(_os, _this);\n"), 141 ic_codegen:emit(Fd, " _any.insert_Streamable(_os);\n"), 142 ic_codegen:emit(Fd, " }\n\n"), 143 144 ic_codegen:emit(Fd, " public static ~s~s extract(~sAny _any)\n", 145 [ArrayElementName,EmptyDim,?ICPACKAGE]), 146 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 147 148 ic_codegen:emit(Fd, " return unmarshal(_any.extract_Streamable());\n"), 149 ic_codegen:emit(Fd, " }\n\n"), 150 151 ic_codegen:emit(Fd, "}\n"), 152 file:close(Fd). 153 154 155 156 157emit_array_marshal_loop(G,N,X,Array,AEl,Fd) -> 158 DimList = mk_array_dim_list(G,N,Array), 159 emit_array_marshal_loop_1(G,N,X,Array,AEl,DimList,0,Fd). 160 161 162emit_array_marshal_loop_1(G,N,X,Array,AEl,[D],C,Fd) -> 163 164 DimList = mk_array_dim_list(G,N,Array), 165 166 ic_codegen:emit(Fd, " _out.write_tuple_head(~s);\n\n",[D]), 167 168 ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++)\n",[C,C,D,C]), 169 170 case ic_java_type:isBasicType(G, N, AEl) of 171 true -> 172 ic_codegen:emit(Fd, " _out~s(_value", 173 [ic_java_type:marshalFun(G, N, X, AEl)]); 174 false -> 175 ic_codegen:emit(Fd, " ~s(_out, _value", 176 [ic_java_type:marshalFun(G, N, X, AEl)]) 177 end, 178 179 emit_array_dimensions(DimList,0,Fd), 180 181 ic_codegen:emit(Fd, ");\n\n"); 182 183emit_array_marshal_loop_1(G,N,X,Array,AEl,[D|Ds],C,Fd) -> 184% DimList = mk_array_dim_list(G,N,Array), 185 186 ic_codegen:emit(Fd, " _out.write_tuple_head(~s);\n\n",[D]), 187 188 ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++) {\n",[C,C,D,C]), 189 190 emit_array_marshal_loop_1(G,N,X,Array,AEl,Ds,C+1,Fd), 191 192 ic_codegen:emit(Fd, " }\n\n"). 193 194 195 196 197 198emit_array_unmarshal_loop(G,N,X,Array,AEl,Fd) -> 199 DimList = mk_array_dim_list(G,N,Array), 200 case length(DimList) > 0 of 201 true -> 202 ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"), 203 204 ic_codegen:emit(Fd, " for(int _tmp0 = 0; _tmp0 < ~s; _tmp0++) {\n\n",[hd(DimList)]), 205 emit_array_unmarshal_loop_1(G,N,X,Array,AEl,tl(DimList),1,Fd), 206 ic_codegen:emit(Fd, " }\n\n"); 207 false -> 208 emit_array_unmarshal_loop_1(G,N,X,Array,AEl,DimList,0,Fd) 209 end. 210 211emit_array_unmarshal_loop_1(G,N,X,_Array,AEl,[],1,Fd) -> %% One dimensional array 212 case ic_java_type:isBasicType(G, N, AEl) of 213 true -> 214 ic_codegen:emit(Fd, " _value[_tmp0] = _in~s;\n", 215 [ic_java_type:unMarshalFun(G, N, X, AEl)]); 216 false -> 217 ic_codegen:emit(Fd, " _value[_tmp0] = ~s.unmarshal(_in);\n\n", 218 [ic_java_type:getUnmarshalType(G, N, X, AEl)]) 219 end; 220emit_array_unmarshal_loop_1(G,N,X,Array,AEl,[],_C,Fd) -> 221 DimList = mk_array_dim_list(G,N,Array), 222 ic_codegen:emit(Fd, " _value"), 223 emit_array_dimensions(DimList,0,Fd), 224 case ic_java_type:isBasicType(G,N,AEl) of 225 true -> 226 ic_codegen:emit(Fd, " = _in~s;\n", 227 [ic_java_type:unMarshalFun(G, N, X, AEl)]); 228 false -> 229 ic_codegen:emit(Fd, " = ~s.unmarshal(_in);\n", 230 [ic_java_type:getUnmarshalType(G, N, X, AEl)]) 231 end; 232emit_array_unmarshal_loop_1(G,N,X,Array,AEl,[D|Ds],C,Fd) -> 233 ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"), 234 235 ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++) {\n\n",[C,C,D,C]), 236 emit_array_unmarshal_loop_1(G,N,X,Array,AEl,Ds,C+1,Fd), 237 ic_codegen:emit(Fd, " }\n"). 238 239 240 241 242 243%%--------------------------------------------------- 244%% Utilities 245%%--------------------------------------------------- 246 247mk_array_dim_list(G,N,Array) -> 248 mk_array_dim_list2(G,N,Array#array.size). 249 250 251mk_array_dim_list2(_G,_N,[]) -> 252 []; 253 254mk_array_dim_list2(G,N,[D |Ds]) when is_record(D,scoped_id) -> 255 {FSN, _, _, _} = ic_symtab:get_full_scoped_name(G, N, D), 256 [ ic_util:to_dot(G,FSN) | mk_array_dim_list2(G,N,Ds)]; 257 258mk_array_dim_list2(G,N,[D |Ds]) -> 259 [ic_util:eval_java(G,N,D) | mk_array_dim_list2(G,N,Ds)]. 260 261 262 263%% Array dimension string 264%arrayDim(G,N,X) -> 265% arrayDim2(G,N,X#array.size). 266 267%arrayDim2(_G,_N,[]) -> 268% ""; 269%arrayDim2(G,N,[D|Ds]) when record(D,scoped_id) -> 270% {FSN, _, _, _} = ic_symtab:get_full_scoped_name(G, N, D), 271% "[" ++ ic_util:to_dot(G,FSN) ++ "]" ++ arrayDim2(G,N,Ds); 272%arrayDim2(G,N,[D|Ds]) -> 273% "[" ++ ic_util:eval_java(G,N,D) ++ "]" ++ arrayDim2(G,N,Ds). 274 275 276%% Array Empty dimension string 277arrayEmptyDim(X) -> 278 arrayEmptyDim2(X#array.size). 279 280arrayEmptyDim2([_D]) -> 281 "[]"; 282arrayEmptyDim2([_D |Ds]) -> 283 "[]" ++ arrayEmptyDim2(Ds). 284 285 286emit_array_dimensions([_D],C,Fd) -> 287 ic_codegen:emit(Fd, "[_tmp~p]",[C]); 288emit_array_dimensions([_D|Ds],C,Fd) -> 289 ic_codegen:emit(Fd, "[_tmp~p]",[C]), 290 emit_array_dimensions(Ds,C+1,Fd). 291 292 293 294 295 296 297