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 23-module(ic_union_java). 24 25-include("icforms.hrl"). 26-include("ic.hrl"). 27-include("ic_debug.hrl"). 28%%----------------------------------------------------------------- 29%% External exports 30%%----------------------------------------------------------------- 31-export([gen/3]). 32 33%%----------------------------------------------------------------- 34%% Internal exports 35%%----------------------------------------------------------------- 36-export([]). 37 38%%----------------------------------------------------------------- 39%% External functions 40%%----------------------------------------------------------------- 41 42%%----------------------------------------------------------------- 43%% Func: gen/3 44%%----------------------------------------------------------------- 45gen(G, N, X) when is_record(X, union) -> 46 47 %% Create a TK value if not existed 48 %% Should be integrated in fetchTk 49 %% instead 50 NewX = case ic_forms:get_tk(X) of 51 undefined -> 52 S = ic_genobj:tktab(G), 53 Tk = ictype:tk(G, S, N, X), 54 #union{ id = X#union.id, 55 type = X#union.type, 56 body = X#union.body, 57 tk = Tk }; 58 _Tk -> 59 X 60 end, 61 62 UnionName = ic_forms:get_java_id(NewX), 63 WiredUnionName = ic_forms:get_id2(NewX), 64 N2 = [UnionName ++ "Package"|N], 65 %%?PRINTDEBUG2("Recursive call over type ~p", 66 %% [[ic_forms:get_type(NewX)]]), 67 ic_jbe:gen(G, N, [ic_forms:get_type(NewX)]), 68 %%?PRINTDEBUG2("Recursive call over body: ~p", 69 %% [ic_forms:get_body(NewX)]), 70 ic_jbe:gen(G, N2, ic_forms:get_body(NewX)), 71 72 emit_union_class(G, N, NewX, UnionName), 73 emit_holder_class(G, N, NewX, UnionName), 74 emit_helper_class(G, N, NewX, UnionName, WiredUnionName); 75gen(_G, _N, _X) -> 76 ok. 77 78 79%%----------------------------------------------------------------- 80%% Internal functions 81%%----------------------------------------------------------------- 82 83%%----------------------------------------------------------------- 84%% Func: emit_union_class/4 85%%----------------------------------------------------------------- 86emit_union_class(G, N, X, UnionName) -> 87 {Fd, _} = ic_file:open_java_file(G, N, UnionName), 88 89 DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N], 90 ic_forms:get_type(X)), 91 92 MList = union_member_list(G, N, X, DiscrType), 93 94 ic_codegen:emit(Fd, "final public class ~s {\n",[UnionName]), 95 96 ic_codegen:emit(Fd, " // instance variables\n", []), 97 ic_codegen:emit(Fd, " private boolean _initialized;\n", []), 98 ic_codegen:emit(Fd, " private ~s _discriminator;\n", [DiscrType]), 99 ic_codegen:emit(Fd, " private java.lang.Object _value;\n", []), 100 101 {tk_union,_, _,DiscrTk, _, _} = ic_forms:get_tk(X), 102 103 DV = get_default_val(G, [UnionName |N], DiscrType, DiscrTk, MList), 104 105 case DV of 106 none -> %% all values in case 107 ok; 108 _ -> 109 ic_codegen:emit(Fd, " private ~s _default = ~s;\n", 110 [DiscrType, DV]) 111 end, 112 113 ic_codegen:nl(Fd), 114 ic_codegen:emit(Fd, " // constructors\n", []), 115 116 ic_codegen:emit(Fd, " public ~s() {\n", [UnionName]), 117 ic_codegen:emit(Fd, " _initialized = false;\n", []), 118 ic_codegen:emit(Fd, " _value = null;\n", []), 119 ic_codegen:emit(Fd, " }\n", []), 120 ic_codegen:nl(Fd), 121 122 ic_codegen:emit(Fd, " // discriminator access\n", []), 123 124 ic_codegen:emit(Fd, " public ~s discriminator() " 125 "throws java.lang.Exception {\n", [DiscrType]), 126 ic_codegen:emit(Fd, " if (!_initialized) {\n", []), 127 ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]), 128 ic_codegen:emit(Fd, " }\n", []), 129 ic_codegen:emit(Fd, " return _discriminator;\n", []), 130 ic_codegen:emit(Fd, " }\n", []), 131 ic_codegen:nl(Fd), 132 133 emit_union_members_functions(G, [UnionName ++ "Package"|N], X, 134 Fd, UnionName, DiscrType, MList, MList), 135 ic_codegen:nl(Fd), 136 137 ic_codegen:emit(Fd, "}\n", []), 138 file:close(Fd). 139 140%%----------------------------------------------------------------- 141%% Func: emit_holder_class/4 142%%----------------------------------------------------------------- 143emit_holder_class(G, N, _X, UnionName) -> 144 UName = string:concat(UnionName, "Holder"), 145 {Fd, _} = ic_file:open_java_file(G, N, UName), 146 147 ic_codegen:emit(Fd, "final public class ~sHolder {\n",[UnionName]), 148 149 ic_codegen:emit(Fd, " // instance variables\n"), 150 ic_codegen:emit(Fd, " public ~s value;\n", [UnionName]), 151 ic_codegen:nl(Fd), 152 153 ic_codegen:emit(Fd, " // constructors\n"), 154 ic_codegen:emit(Fd, " public ~sHolder() {}\n", [UnionName]), 155 ic_codegen:emit(Fd, " public ~sHolder(~s initial) {\n", 156 [UnionName, UnionName]), 157 ic_codegen:emit(Fd, " value = initial;\n"), 158 ic_codegen:emit(Fd, " }\n"), 159 ic_codegen:nl(Fd), 160 161 ic_codegen:emit(Fd, " // methods\n"), 162 163 ic_codegen:emit(Fd, " public void _marshal(~sOtpOutputStream out) throws java.lang.Exception {\n", 164 [?ERLANGPACKAGE]), 165 ic_codegen:emit(Fd, " ~sHelper.marshal(out, value);\n", [UnionName]), 166 ic_codegen:emit(Fd, " }\n\n"), 167 168 ic_codegen:emit(Fd, " public void _unmarshal(~sOtpInputStream in) throws java.lang.Exception {\n", 169 [?ERLANGPACKAGE]), 170 ic_codegen:emit(Fd, " value = ~sHelper.unmarshal(in);\n", [UnionName]), 171 ic_codegen:emit(Fd, " }\n\n"), 172 173 ic_codegen:emit(Fd, "}\n"), 174 file:close(Fd). 175 176 177%%----------------------------------------------------------------- 178%% Func: emit_helper_class/4 179%%----------------------------------------------------------------- 180emit_helper_class(G, N, X, UnionName, WiredUnionName) -> 181 UName = string:concat(UnionName, "Helper"), 182 {Fd, _} = ic_file:open_java_file(G, N, UName), 183 184 DiscrType = ic_java_type:getType(G, [ UnionName ++ "Package" |N], 185 ic_forms:get_type(X)), 186 187 ic_codegen:emit(Fd, "public class ~sHelper {\n",[UnionName]), 188 189 ic_codegen:emit(Fd, " // constructors\n", []), 190 ic_codegen:emit(Fd, " private ~sHelper() {}\n", [UnionName]), 191 ic_codegen:nl(Fd), 192 193 ic_codegen:emit(Fd, " // methods\n", []), 194 MList = union_member_list(G, N, X, DiscrType), 195 196 ic_codegen:emit(Fd, " public static void marshal(~sOtpOutputStream _out, ~s _value)\n", 197 [?ERLANGPACKAGE, UnionName]), 198 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 199 emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList), 200 ic_codegen:emit(Fd, " }\n\n"), 201 202 ic_codegen:emit(Fd, " public static ~s unmarshal(~sOtpInputStream _in)\n", 203 [UnionName, ?ERLANGPACKAGE]), 204 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 205 emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList), 206 ic_codegen:emit(Fd, " }\n\n"), 207 208 ic_codegen:emit(Fd, " public static String id() {\n"), 209 ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, X)]), 210 ic_codegen:emit(Fd, " }\n\n"), 211 212 ic_codegen:emit(Fd, " public static String name() {\n"), 213 ic_codegen:emit(Fd, " return ~p;\n",[UnionName]), 214 ic_codegen:emit(Fd, " }\n\n"), 215 216 ic_jbe:emit_type_function(G, N, X, Fd), 217 218 219 ic_codegen:emit(Fd, " public static void insert(~sAny _any, ~s _this)\n", 220 [?ICPACKAGE,UnionName]), 221 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 222 223 ic_codegen:emit(Fd, " ~sOtpOutputStream _os = \n",[?ERLANGPACKAGE]), 224 ic_codegen:emit(Fd, " new ~sOtpOutputStream();\n\n",[?ERLANGPACKAGE]), 225 226 ic_codegen:emit(Fd, " _any.type(type());\n"), 227 ic_codegen:emit(Fd, " marshal(_os, _this);\n"), 228 ic_codegen:emit(Fd, " _any.insert_Streamable(_os);\n"), 229 ic_codegen:emit(Fd, " }\n\n"), 230 231 ic_codegen:emit(Fd, " public static ~s extract(~sAny _any)\n", 232 [UnionName,?ICPACKAGE]), 233 ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"), 234 235 ic_codegen:emit(Fd, " return unmarshal(_any.extract_Streamable());\n"), 236 ic_codegen:emit(Fd, " }\n\n"), 237 238 ic_codegen:emit(Fd, " public static int discriminatorAsInt(~s _discriminator)\n", 239 [DiscrType]), 240 ic_codegen:emit(Fd, " throws java.lang.Exception {\n"), 241 emit_discriminator_as_int(G, N, ic_forms:get_type(X), Fd), 242 ic_codegen:emit(Fd, " }\n\n"), 243 244 ic_codegen:emit(Fd, "}\n"), 245 file:close(Fd). 246 247%%----------------------------------------------------------------- 248%% Func: emit_union_members_functions/7 249%%----------------------------------------------------------------- 250emit_union_members_functions(_, _, _, _, _, _, [], _) -> 251 ok; 252emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType, 253 [{Label, Case, TypeDef, Id, Ls} | MList], MListTot) -> 254 255 CaseId = Case#case_dcl.id, %% Maybe Array 256 CaseType = Case#case_dcl.type, %% Maybe Sequence 257 258 Type = if element(1,CaseId) == array -> 259 ic_java_type:getType(G, N, TypeDef) ++ 260 ic_java_type:getdim(CaseId#array.size); 261 true -> 262 ic_java_type:getType(G, N, TypeDef) 263 end, 264 265 HolderType = 266 if element(1,CaseId) == array -> 267 ic_java_type:getHolderType(G, N, CaseId); 268 true -> 269 if element(1,CaseType) == sequence -> 270 ic_util:to_dot(G,[Id|N]) ++"Holder"; 271 true -> 272 ic_java_type:getHolderType(G, N, TypeDef) 273 end 274 end, 275 276 %% 277 %% Set method 278 %% 279 ic_codegen:emit(Fd, " // ~s access and set functions\n",[Id]), 280 ic_codegen:emit(Fd, " public void ~s(~s value) " 281 "throws java.lang.Exception {\n", 282 [Id, Type]), 283 ic_codegen:emit(Fd, " _initialized = true;\n", []), 284 case Label of 285 "default" -> 286 ic_codegen:emit(Fd, " _discriminator = (~s) _default;\n", 287 [DiscrType]); 288 _ -> 289 case ic_java_type:isBasicType(G, N, ic_forms:get_type(X)) of 290 true -> 291 ic_codegen:emit(Fd, " _discriminator = (~s) " 292 "~s;\n", 293 [DiscrType, Label]); 294 _ -> 295 ic_codegen:emit(Fd, " _discriminator = (~s) " 296 "~s.~s;\n", 297 [DiscrType, DiscrType, Label]) 298 end 299 end, 300 ic_codegen:emit(Fd, " _value = new ~s(value);\n", 301 [HolderType]), 302 ic_codegen:emit(Fd, " }\n", []), 303 304 %% 305 %% Check this entry has more than one label and the generate an extra set method. 306 %% 307 case Ls of 308 [] -> 309 ok; 310 _ -> 311 ic_codegen:emit(Fd, " public void ~s(~s discriminator, ~s value) " 312 "throws java.lang.Exception {\n", 313 [Id, DiscrType, Type]), 314 ic_codegen:emit(Fd, " _initialized = true;\n", []), 315 ic_codegen:emit(Fd, " _discriminator = (~s) discriminator;\n", 316 [DiscrType]), 317 ic_codegen:emit(Fd, " _value = new ~s(value);\n", 318 [HolderType]), 319 ic_codegen:emit(Fd, " }\n", []) 320 end, 321 322 %% 323 %% Get method 324 %% 325 ic_codegen:emit(Fd, " public ~s ~s() throws java.lang.Exception {\n", 326 [Type, Id]), 327 ic_codegen:emit(Fd, " if (!_initialized) {\n", []), 328 ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]), 329 ic_codegen:emit(Fd, " }\n", []), 330 ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt" 331 "(discriminator())) {\n", 332 [UnionName]), 333 if 334 Label == "default" -> 335 ic_codegen:emit(Fd, " default:\n", []), 336 ic_codegen:emit(Fd, " break;\n", []), 337 emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, 338 MListTot), 339 ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", []); 340 true -> 341 ic_codegen:emit(Fd, " case ~s:\n", 342 [get_case_as_int(G, N, ic_forms:get_type(X), 343 DiscrType, Label)]), 344 ic_codegen:emit(Fd, " break;\n", []), 345 ic_codegen:emit(Fd, " default:\n", []), 346 ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", []) 347 end, 348 ic_codegen:emit(Fd, " }\n", []), 349 350 ic_codegen:emit(Fd, " return ((~s) _value).value;\n", 351 [HolderType]), 352 ic_codegen:emit(Fd, " }\n", []), 353 ic_codegen:nl(Fd), 354 emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType, MList, 355 MListTot). 356 357 358%%----------------------------------------------------------------- 359%% Func: emit_default_access_fun_switch_cases/6 360%%----------------------------------------------------------------- 361emit_default_access_fun_switch_cases(_G, _N, _X, _Fd, _DiscrType, []) -> 362 ok; 363emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, 364 [{"default", _, _, _, _} |MList]) -> 365 emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList); 366emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, 367 [{Label, _Case, _TypeDef, _Id, _} | MList]) -> 368 ic_codegen:emit(Fd, " case ~s:\n", 369 [get_case_as_int(G, N, ic_forms:get_type(X), 370 DiscrType, Label)]), 371 emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList). 372 373 374 375%%----------------------------------------------------------------- 376%% Func: emit_union_unmarshal_function/5 377%%----------------------------------------------------------------- 378emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) -> 379 DiscrTypeForm = ic_forms:get_type(X), 380 DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N], 381 DiscrTypeForm), 382 383 ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"), 384 385 ic_codegen:emit(Fd, " if ((_in.read_atom()).compareTo(~p) != 0)\n", 386 [ic_util:to_undersc([WiredUnionName|N])]), 387 ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n\n",[]), 388 389 ic_codegen:emit(Fd, " ~s _value = new ~s();\n", [UnionName, UnionName]), 390 391 %% Decode discriminator 392 case ic_java_type:isBasicType(G, N, DiscrTypeForm) of 393 true -> 394 ic_codegen:emit(Fd, " ~s _discriminator = _in~s;\n\n", 395 [DiscrType, 396 ic_java_type:unMarshalFun(G, N, X, DiscrTypeForm)]); 397 _ -> 398 ic_codegen:emit(Fd, " ~s _discriminator = ~s.unmarshal(_in);\n\n", 399 [DiscrType,ic_java_type:getUnmarshalType(G, N, X, DiscrTypeForm)]) 400 end, 401 402 ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt(_discriminator)) {\n", 403 [UnionName]), 404 405 emit_union_unmarshal_function_loop(G, [UnionName ++ "Package"|N], X, 406 Fd, DiscrType, MList), 407 408 ic_codegen:emit(Fd, " }\n\n"), 409 410 ic_codegen:emit(Fd, " return _value;\n"). 411 412%%----------------------------------------------------------------- 413%% Func: emit_union_unmarshal_function_loop/6 414%%----------------------------------------------------------------- 415emit_union_unmarshal_function_loop(_, _, _, _, _, []) -> 416 ok; 417emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType, 418 [{Label, Case, Type, Id, Ls} |MList]) -> 419 case Label of 420 "default" -> 421 ic_codegen:emit(Fd, " default:\n"); 422 _ -> 423 ic_codegen:emit(Fd, " case ~s:\n", 424 [get_case_as_int(G, N, ic_forms:get_type(X), 425 DiscrType, Label)]) 426 end, 427 428 gen_multiple_cases(G, N, X, Fd, DiscrType, Ls), 429 430 CaseId = Case#case_dcl.id, %% Maybe Array 431 CaseType = Case#case_dcl.type, %% Maybe Sequence 432 433 case element(1,CaseId) of 434 array -> 435 ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n", 436 [Id, 437 ic_java_type:getUnmarshalType(G, N, Case, CaseId)]); 438 439 _ -> 440 case element(1, CaseType) of 441 sequence -> 442 ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n", 443 [Id, 444 ic_java_type:getUnmarshalType(G, N, Case, CaseType)]); 445 _ -> 446 case ic_java_type:isBasicType(G, N, CaseType) of 447 true -> 448 ic_codegen:emit(Fd, " _value.~s(_in~s);\n", 449 [Id, 450 ic_java_type:unMarshalFun(G, N, X, Type)]); 451 false -> 452 ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n", 453 [Id, 454 ic_java_type:getUnmarshalType(G, N, X, Type)]) 455 end 456 end 457 end, 458 459 ic_codegen:emit(Fd, " break;\n", []), 460 emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType, MList). 461 462 463 464 465 466%%----------------------------------------------------------------- 467%% Func: emit_union_marshal_function/6 468%%----------------------------------------------------------------- 469emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) -> 470 471 DiscrTypeForm = ic_forms:get_type(X), 472 DiscrType = ic_java_type:getType(G, [UnionName ++ "Package" |N], 473 DiscrTypeForm), 474 475 ic_codegen:emit(Fd, " _out.write_tuple_head(3);\n"), 476 ic_codegen:emit(Fd, " _out.write_atom(~p);\n", 477 [ic_util:to_undersc([WiredUnionName|N])]), 478 479 case ic_java_type:isBasicType(G, N, DiscrTypeForm) of 480 true -> 481 ic_codegen:emit(Fd, " _out~s(_value.discriminator());\n\n", 482 [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)]); 483 false -> 484 ic_codegen:emit(Fd, " ~s(_out, _value.discriminator());\n\n", 485 [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)]) 486 end, 487 488 ic_codegen:emit(Fd, " switch(~sHelper.discriminatorAsInt(_value.discriminator())) {\n", 489 [UnionName]), 490 491 emit_union_marshal_function_loop(G, 492 [ UnionName ++ "Package"|N], 493 X, 494 Fd, 495 DiscrType, 496 MList), 497 498 ic_codegen:emit(Fd, " }\n\n", []). 499 500 501%%----------------------------------------------------------------- 502%% Func: emit_union_marshal_function_loop/ 503%%----------------------------------------------------------------- 504emit_union_marshal_function_loop(_, _, _, _, _, []) -> 505 ok; 506emit_union_marshal_function_loop(G, N, X, Fd, DiscrType, 507 [{Label, Case, Type, Id, Ls} |MList]) -> 508 case Label of 509 "default" -> 510 ic_codegen:emit(Fd, " default:\n", 511 []); 512 _ -> 513 ic_codegen:emit(Fd, " case ~s:\n", 514 [get_case_as_int(G, N, ic_forms:get_type(X), 515 DiscrType, Label)]) 516 end, 517 518 gen_multiple_cases(G, N, X, Fd, DiscrType, Ls), 519 520 521 CaseId = Case#case_dcl.id, %% Maybe Array 522 CaseType = Case#case_dcl.type, %% Maybe Sequence 523 524 case element(1,CaseId) of 525 array -> 526 ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n", 527 [ic_java_type:marshalFun(G, N, Case, CaseId), 528 Id]); 529 _ -> 530 case element(1, CaseType) of 531 sequence -> 532 ic_codegen:emit(Fd, " ~s.marshal(_out, _value.~s());\n", 533 [ic_util:to_dot(G,[Id|N]) ++ "Helper", 534 Id]); 535 _ -> 536 case ic_java_type:isBasicType(G, N, CaseType) of 537 true -> 538 ic_codegen:emit(Fd, " _out~s(_value.~s());\n", 539 [ic_java_type:marshalFun(G, N, X, Type), 540 Id]); 541 false -> 542 ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n", 543 [ic_java_type:marshalFun(G, N, X, Type), 544 Id]) 545 end 546 end 547 end, 548 549 ic_codegen:emit(Fd, " break;\n", []), 550 emit_union_marshal_function_loop(G, N, X, Fd, DiscrType, MList). 551 552 553 554gen_multiple_cases(_G, _N, _X, _Fd, _DiscrType, []) -> 555 ok; 556gen_multiple_cases(G, N, X, Fd, DiscrType, [Label |Ls]) -> 557 ic_codegen:emit(Fd, " case ~s:\n", 558 [get_case_as_int(G, N, ic_forms:get_type(X), 559 DiscrType, getLabel(DiscrType, Label))]), 560 gen_multiple_cases(G, N, X, Fd, DiscrType, Ls). 561 562 563%%----------------------------------------------------------------- 564%% Func: union_member_list/3 565%%----------------------------------------------------------------- 566union_member_list(G, N, X, DiscrType) -> 567 M = lists:map( 568 fun(Case) -> 569 {Label, LabelList} = case check_default(ic_forms:get_idlist(Case)) of 570 {{default, C}, List} -> 571 {{default, C}, List}; 572 {L, []} -> 573 {L, []}; 574 {_, [L |Ls]} -> 575 {L, Ls} 576 end, 577 578 CName = ic_forms:get_java_id(Case), 579 CId = Case#case_dcl.id, 580 CType = Case#case_dcl.type, 581 582 if element(1,CId) == array -> 583 N2 = [ic_forms:get_id2(X) ++ "Package" |N], 584 ic_array_java:gen(G, N2, Case, CId); 585 true -> 586 if element(1,Case#case_dcl.type) == sequence -> 587 N2 = [ic_forms:get_id2(X) ++ "Package" |N], 588 ic_sequence_java:gen(G, N2, CType, CName); 589 true -> 590 ok 591 end 592 end, 593 594 {getLabel(DiscrType, Label), 595 Case, 596 ic_forms:get_type(Case), 597 CName, 598 LabelList} 599 end, 600 ic_forms:get_body(X)), 601 lists:flatten(M). 602 603check_default([]) -> 604 {false, []}; 605check_default([{default, X} |Ls]) -> 606 {{default, X}, Ls}; 607check_default([L]) -> 608 {false, [L]}; 609check_default([L |Ls]) -> 610 {X, Y} = check_default(Ls), 611 {X, [L | Y]}. 612 613getLabel(_, {'<integer_literal>', _, N}) -> 614 N; 615getLabel(_, {'<character_literal>', _, N}) -> 616 "'" ++ N ++ "'"; 617getLabel(_, {'<wcharacter_literal>', _, N}) -> 618 "'" ++ N ++ "'"; 619getLabel(_, {'TRUE',_}) -> 620 "true"; 621getLabel(_, {'FALSE',_}) -> 622 "true"; 623getLabel(_, {default, _}) -> 624 "default"; 625getLabel(_DiscrType, X) -> %%DiscrType ++ "." ++ 626 ic_util:to_dot(ic_forms:get_id(X)). 627 628get_default_val(G, N, _, tk_short, MList) -> 629 integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 630get_default_val(G, N, _, tk_long, MList) -> 631 integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 632get_default_val(G, N, _, tk_ushort, MList) -> 633 integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 634get_default_val(G, N, _, tk_ulong, MList) -> 635 integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 636get_default_val(G, N, _, tk_char, MList) -> 637 char_default_val(G, N, $a, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 638get_default_val(G, N, _, tk_boolean, MList) -> 639 boolean_default_val(G, N, lists:map(fun({V, _, _, _, _}) -> V end, MList)); 640get_default_val(G, N, DiscrType, {tk_enum, _, _, Values}, MList) -> 641 enum_default_val(G, N, DiscrType, Values, MList). 642 643integer_default_val(G, N, Num, MList) -> 644 Num2 = integer_to_list(Num), 645 case lists:member(Num2, MList) of 646 true -> 647 integer_default_val(G, N, Num + 1, MList); 648 false -> 649 Num2 650 end. 651 652char_default_val(G, N, CharNum, MList) -> 653 Str = "'", 654 CharNum2 = Str ++ [CharNum | Str], 655 case lists:member(CharNum2, MList) of 656 true -> 657 char_default_val(G, N, CharNum + 1, MList); 658 false -> 659 CharNum2 660 end. 661 662boolean_default_val(G, N, MList) -> 663 if 664 length(MList) > 2 -> 665 ic_error:error(G, {plain_error_string, 666 lists:flatten( 667 io_lib:format("Default value found while all values have label on ~s", 668 [ic_util:to_colon(N)]))}), 669 none; 670 true -> 671 case MList of 672 ["true"] -> 673 "false"; 674 ["false"] -> 675 "true"; 676 ["default","true"] -> 677 "false"; 678 ["true","default"] -> 679 "false"; 680 ["default","false"] -> 681 "true"; 682 ["false","default"] -> 683 "true"; 684 _ -> 685 none 686 end 687 end. 688 689 690 691 692enum_default_val(G, N, DiscrType, Values, Mlist) -> 693 694 VLen = length(Values), 695 MLen = length(Mlist), 696 697 case MLen > VLen of 698 true -> 699 ic_error:error(G, {plain_error_string, 700 lists:flatten( 701 io_lib:format("Default value found while all values have label on ~s", 702 [ic_util:to_colon(N)]))}), 703 none; 704 false -> 705 enum_default_val_loop(G, N, DiscrType, Values, Mlist) 706 end. 707 708enum_default_val_loop(_G, _N, _, [], []) -> 709 none; 710enum_default_val_loop(_G, _N, DiscrType, [Value| _], []) -> 711 DiscrType ++ "." ++ Value; 712enum_default_val_loop(G, N, DiscrType, Values, [Case | MList]) when is_tuple(Case) -> 713 NewValues = lists:delete(element(1,Case), Values), 714 enum_default_val_loop(G, N, DiscrType, NewValues, MList). 715 716 717 718emit_discriminator_as_int(G, N, T, Fd) -> 719 case ictype:isBoolean(G,N,T) of 720 true -> 721 ic_codegen:emit(Fd, " if(_discriminator)\n", []), 722 ic_codegen:emit(Fd, " return 1;\n", []), 723 ic_codegen:emit(Fd, " else\n", []), 724 ic_codegen:emit(Fd, " return 0;\n", []); 725 false -> 726 case ictype:isEnum(G, N, T) of 727 true -> 728 ic_codegen:emit(Fd, " return _discriminator.value();\n", 729 []); 730 false -> 731 ic_codegen:emit(Fd, " return _discriminator;\n", []) 732 end 733 end. 734 735 736get_case_as_int(G, N, T, DiscrJavaTypeName, Label) -> 737 case ictype:isBoolean(G,N,T) of 738 true -> 739 case Label of 740 "true" -> 741 "1"; 742 "false" -> 743 "0" 744 end; 745 false -> 746 case ictype:isEnum(G, N, T) of 747 true -> 748 DiscrJavaTypeName ++ "._" ++ Label; 749 false -> 750 "(" ++ DiscrJavaTypeName ++ ") " ++ Label 751 end 752 end. 753 754 755 756